From 3e19858edd380a4ad6d7dc2cefc456af9eee840f Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 30 Sep 2018 01:06:59 -0700 Subject: [PATCH 01/12] fix #H6925 - being trapped vs Levitation/Flying Make being trapped in/on/over floor block Levitation and Flying, the way that being inside solid rock already does, and the way levitating blocks flight. Blocked levitation still provides enhanced carrying capacity since magic is attempting to make the hero's body be bouyant. I think that that is appropriate but am not completely convinced. One thing that almost certainly needs fixing is digging a hole when trapped in the floor or tethered to a buried iron ball, where the first part of digactualhole() releases the hero from being trapped. If being released re-enables blocked levitation, the further stages of digging might not make sense in some circumstances. I recently realized that being held by a grabbing monster is similar to being trapped so should also interfere with levitation and flying. Nothing here attempts to address that. Save files change, but in a compatible fashion unless trapped at the time of saving. If someone saves while trapped prior to this patch, then applies it and restores, the game will behave as if the patch wasn't in place--until escape from trap is achieved. (Not verified.) --- doc/fixes36.2 | 5 ++ include/extern.h | 2 + include/youprop.h | 7 ++ src/apply.c | 4 +- src/ball.c | 14 +-- src/cmd.c | 39 ++++++-- src/dig.c | 17 ++-- src/do.c | 4 +- src/do_wear.c | 14 +-- src/eat.c | 8 +- src/end.c | 2 +- src/hack.c | 40 ++++++--- src/mhitu.c | 2 +- src/mklev.c | 2 +- src/music.c | 45 ++++++---- src/polyself.c | 40 ++++++--- src/pray.c | 2 +- src/teleport.c | 2 +- src/trap.c | 225 +++++++++++++++++++++++++++++++++------------- src/zap.c | 5 +- 20 files changed, 330 insertions(+), 149 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 25fd65dc4..9c108add6 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -152,6 +152,11 @@ fix missing space in "would flyif you weren't levitating" a wand of polymorph lost its magical ability for the turn just because the player using it to engrave happened to be blind, which didn't make a much sense +floating eye is classified as a flyer but flying is blocked while levitating, + so don't set intrinsic flying if hero is polymorphed into one +being trapped (bear trap, web, molten or solidified lava, chained to buried + iron ball) blocks both levitation and flight (note: being stuck in a + pit ends when either of those starts so doesn't apply) Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 345442345..e73c931a6 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2438,6 +2438,8 @@ E struct monst *FDECL(animate_statue, (struct obj *, XCHAR_P, XCHAR_P, int, int *)); E struct monst *FDECL(activate_statue_trap, (struct trap *, XCHAR_P, XCHAR_P, BOOLEAN_P)); +E void FDECL(set_utrap, (unsigned, unsigned)); +E void FDECL(reset_utrap, (BOOLEAN_P)); E void FDECL(dotrap, (struct trap *, unsigned)); E void FDECL(seetrap, (struct trap *)); E void FDECL(feeltrap, (struct trap *)); diff --git a/include/youprop.h b/include/youprop.h index d71ec8b5c..c0eb10eef 100644 --- a/include/youprop.h +++ b/include/youprop.h @@ -209,8 +209,12 @@ #define ETeleport_control u.uprops[TELEPORT_CONTROL].extrinsic #define Teleport_control (HTeleport_control || ETeleport_control) +/* HLevitation has I_SPECIAL set if levitating due to blessed potion + which allows player to use the '>' command to end levitation early */ #define HLevitation u.uprops[LEVITATION].intrinsic #define ELevitation u.uprops[LEVITATION].extrinsic +/* BLevitation has I_SPECIAL set if trapped in the floor, + FROMOUTSIDE set if inside solid rock (or in water on Plane of Water) */ #define BLevitation u.uprops[LEVITATION].blocked #define Levitation ((HLevitation || ELevitation) && !BLevitation) /* Can't touch surface, can't go under water; overrides all others */ @@ -219,8 +223,11 @@ && (HLevitation & ~(I_SPECIAL | TIMEOUT)) == 0L \ && (ELevitation & ~W_ARTI) == 0L) +/* Flying is overridden by Levitation */ #define HFlying u.uprops[FLYING].intrinsic #define EFlying u.uprops[FLYING].extrinsic +/* BFlying has I_SPECIAL set if levitating or trapped in the floor or both, + FROMOUTSIDE set if inside solid rock (or in water on Plane of Water) */ #define BFlying u.uprops[FLYING].blocked #define Flying \ ((HFlying || EFlying || (u.usteed && is_flyer(u.usteed->data))) \ diff --git a/src/apply.c b/src/apply.c index 0fa842636..5a7ba6d19 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1752,7 +1752,7 @@ int magic; /* 0=Physical, otherwise skill level */ break; case TT_LAVA: You("pull yourself above the %s!", hliquid("lava")); - u.utrap = 0; + reset_utrap(TRUE); return 1; case TT_BURIEDBALL: case TT_INFLOOR: @@ -2738,7 +2738,7 @@ struct obj *obj; if (!mtmp || enexto(&cc, rx, ry, youmonst.data)) { You("yank yourself out of the pit!"); teleds(cc.x, cc.y, TRUE); - u.utrap = 0; + reset_utrap(TRUE); vision_full_recalc = 1; } } else { diff --git a/src/ball.c b/src/ball.c index 762de85f8..3ac723866 100644 --- a/src/ball.c +++ b/src/ball.c @@ -703,11 +703,12 @@ xchar x, y; } if (x != u.ux || y != u.uy) { + static const char *pullmsg = "The ball pulls you out of the %s!"; struct trap *t; - const char *pullmsg = "The ball pulls you out of the %s!"; + long side; - if (u.utrap && u.utraptype != TT_INFLOOR - && u.utraptype != TT_BURIEDBALL) { + if (u.utrap + && u.utraptype != TT_INFLOOR && u.utraptype != TT_BURIEDBALL) { switch (u.utraptype) { case TT_PIT: pline(pullmsg, "pit"); @@ -720,8 +721,8 @@ xchar x, y; case TT_LAVA: pline(pullmsg, hliquid("lava")); break; - case TT_BEARTRAP: { - register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE; + case TT_BEARTRAP: + side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE; pline(pullmsg, "bear trap"); set_wounded_legs(side, rn1(1000, 500)); if (!u.usteed) { @@ -734,8 +735,7 @@ xchar x, y; } break; } - } - u.utrap = 0; + reset_utrap(TRUE); fill_pit(u.ux, u.uy); } diff --git a/src/cmd.c b/src/cmd.c index 54054f3c3..34d3ee19a 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -803,6 +803,7 @@ wiz_makemap(VOID_ARGS) ballrelease(FALSE); unplacebc(); } + reset_utrap(FALSE); /* also done by safe_teleds() for new level */ check_special_room(TRUE); dmonsfree(); savelev(-1, ledger_no(&u.uz), FREE_SAVE); @@ -2458,9 +2459,19 @@ int final; long save_BLev = BLevitation; BLevitation = 0L; - if (Levitation) - enl_msg(You_, "would levitate", "would have levitated", - if_surroundings_permitted, ""); + if (Levitation) { + /* either trapped in the floor or inside solid rock + (or both if chained to buried iron ball and have + moved one step into solid rock somehow) */ + boolean trapped = (save_BLev & I_SPECIAL) != 0L, + terrain = (save_BLev & FROMOUTSIDE) != 0L; + + Sprintf(buf, "%s%s%s", + trapped ? " if not trapped" : "", + (trapped && terrain) ? " and" : "", + terrain ? if_surroundings_permitted : ""); + enl_msg(You_, "would levitate", "would have levitated", buf, ""); + } BLevitation = save_BLev; } /* actively flying handled earlier as a status condition */ @@ -2468,15 +2479,27 @@ int final; long save_BFly = BFlying; BFlying = 0L; - if (Flying) + if (Flying) { enl_msg(You_, "would fly", "would have flown", + /* wording quibble: for past tense, "hadn't been" + would sound better than "weren't" (and + "had permitted" better than "permitted"), but + "weren't" and "permitted" are adequate so the + extra complexity to handle that isn't worth it */ Levitation ? " if you weren't levitating" - : (save_BFly == FROMOUTSIDE) - ? if_surroundings_permitted - /* both surroundings and [latent] levitation */ - : " if circumstances permitted", + : (save_BFly == I_SPECIAL) + /* this is an oversimpliction; being trapped + might also be blocking levitation so flight + would still be blocked after escaping trap */ + ? " if you weren't trapped" + : (save_BFly == FROMOUTSIDE) + ? if_surroundings_permitted + /* two or more of levitation, surroundings, + and being trapped in the floor */ + : " if circumstances permitted", ""); + } BFlying = save_BFly; } /* actively walking on water handled earlier as a status condition */ diff --git a/src/dig.c b/src/dig.c index a89b354be..1cdaee380 100644 --- a/src/dig.c +++ b/src/dig.c @@ -339,8 +339,8 @@ dig(VOID_ARGS) } else { You("destroy the bear trap with %s.", yobjnam(uwep, (const char *) 0)); - u.utrap = 0; /* release from trap */ deltrap(ttmp); + reset_utrap(TRUE); /* release from trap, maybe Lev or Fly */ } /* we haven't made any progress toward a pit yet */ context.digging.effort = 0; @@ -557,7 +557,7 @@ int ttyp; if (u.utraptype == TT_BURIEDBALL) buried_ball_to_punishment(); else if (u.utraptype == TT_INFLOOR) - u.utrap = 0; + reset_utrap(FALSE); } /* these furniture checks were in dighole(), but wand @@ -619,11 +619,10 @@ int ttyp; if (at_u) { if (!wont_fall) { - u.utrap = rn1(4, 2); - u.utraptype = TT_PIT; + set_utrap(rn1(4, 2), TT_PIT); vision_full_recalc = 1; /* vision limits change */ } else - u.utrap = 0; + reset_utrap(TRUE); if (oldobjs != newobjs) /* something unearthed */ (void) pickup(1); /* detects pit */ } else if (mtmp) { @@ -1103,7 +1102,7 @@ struct obj *obj; pline("You clear some debris from between the pits."); } } else if (u.utrap && u.utraptype == TT_PIT - && (trap_with_u = t_at(u.ux, u.uy))) { + && (trap_with_u = t_at(u.ux, u.uy)) != 0) { You("swing %s, but the rubble has no place to go.", yobjnam(obj, (char *) 0)); } else { @@ -1775,8 +1774,7 @@ buried_ball_to_punishment() (void) stop_timer(RUST_METAL, obj_to_any(ball)); #endif punish(ball); /* use ball as flag for unearthed buried ball */ - u.utrap = 0; - u.utraptype = 0; + reset_utrap(FALSE); del_engr_at(cc.x, cc.y); newsym(cc.x, cc.y); } @@ -1800,8 +1798,7 @@ buried_ball_to_freedom() #endif place_object(ball, cc.x, cc.y); stackobj(ball); - u.utrap = 0; - u.utraptype = 0; + reset_utrap(TRUE); del_engr_at(cc.x, cc.y); newsym(cc.x, cc.y); } diff --git a/src/do.c b/src/do.c index 81bbb6235..db67a34d9 100644 --- a/src/do.c +++ b/src/do.c @@ -171,7 +171,7 @@ const char *verb; "squished under a boulder", NO_KILLER_PREFIX); return FALSE; /* player remains trapped */ } else - u.utrap = 0; + reset_utrap(TRUE); } } if (*verb) { @@ -1239,7 +1239,7 @@ boolean at_stairs, falling, portal; check_special_room(TRUE); /* probably was a trap door */ if (Punished) unplacebc(); - u.utrap = 0; /* needed in level_tele */ + reset_utrap(FALSE); /* needed in level_tele */ fill_pit(u.ux, u.uy); u.ustuck = 0; /* idem */ u.uinwater = 0; diff --git a/src/do_wear.c b/src/do_wear.c index 269370e81..7ab53a79e 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -185,10 +185,11 @@ Boots_on(VOID_ARGS) incr_itimeout(&HFumbling, rnd(20)); break; case LEVITATION_BOOTS: - if (!oldprop && !HLevitation && !BLevitation) { + if (!oldprop && !HLevitation && !(BLevitation & FROMOUTSIDE)) { makeknown(uarmf->otyp); float_up(); - spoteffects(FALSE); + if (Levitation) + spoteffects(FALSE); /* for sink effect */ } else { float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */ } @@ -238,7 +239,7 @@ Boots_off(VOID_ARGS) HFumbling = EFumbling = 0; break; case LEVITATION_BOOTS: - if (!oldprop && !HLevitation && !BLevitation + if (!oldprop && !HLevitation && !(BLevitation & FROMOUTSIDE) && !context.takeoff.cancelled_don) { (void) float_down(0L, 0L); makeknown(otyp); @@ -902,10 +903,11 @@ register struct obj *obj; } break; case RIN_LEVITATION: - if (!oldprop && !HLevitation && !BLevitation) { + if (!oldprop && !HLevitation && !(BLevitation & FROMOUTSIDE)) { float_up(); learnring(obj, TRUE); - spoteffects(FALSE); /* for sinks */ + if (Levitation) + spoteffects(FALSE); /* for sinks */ } else { float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */ } @@ -1016,7 +1018,7 @@ boolean gone; } break; case RIN_LEVITATION: - if (!BLevitation) { + if (!(BLevitation & FROMOUTSIDE)) { (void) float_down(0L, 0L); if (!Levitation) learnring(obj, TRUE); diff --git a/src/eat.c b/src/eat.c index 895cdf2a6..3e74d435f 100644 --- a/src/eat.c +++ b/src/eat.c @@ -3088,15 +3088,17 @@ int corpsecheck; /* 0, no check, 1, corpses, 2, tinnable corpses */ struct trap *ttmp = t_at(u.ux, u.uy); if (ttmp && ttmp->tseen && ttmp->ttyp == BEAR_TRAP) { + boolean u_in_beartrap = (u.utrap && u.utraptype == TT_BEARTRAP); + /* If not already stuck in the trap, perhaps there should be a chance to becoming trapped? Probably not, because then the trap would just get eaten on the _next_ turn... */ Sprintf(qbuf, "There is a bear trap here (%s); eat it?", - (u.utrap && u.utraptype == TT_BEARTRAP) ? "holding you" - : "armed"); + u_in_beartrap ? "holding you" : "armed"); if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') { - u.utrap = u.utraptype = 0; deltrap(ttmp); + if (u_in_beartrap) + reset_utrap(TRUE); return mksobj(BEARTRAP, TRUE, FALSE); } else if (c == 'q') { return (struct obj *) 0; diff --git a/src/end.c b/src/end.c index fd5d73db9..7b10d2c0e 100644 --- a/src/end.c +++ b/src/end.c @@ -870,7 +870,7 @@ int how; else multi = -1; if (u.utrap && u.utraptype == TT_LAVA) - u.utrap = 0; + reset_utrap(FALSE); context.botl = 1; u.ugrave_arise = NON_PM; HUnchanging = 0L; diff --git a/src/hack.c b/src/hack.c index 1a83ae3d9..44351f4d7 100644 --- a/src/hack.c +++ b/src/hack.c @@ -539,11 +539,17 @@ dosinkfall() int dmg; boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS), innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L), - ufall = (!innate_lev && !(HFlying || EFlying)); /* BFlying */ + /* to handle being chained to buried iron ball, trying to + levitate but being blocked, then moving onto adjacent sink; + no need to worry about being blocked by terrain because we + couldn't be over a sink at the same time */ + blockd_lev = (BLevitation == I_SPECIAL), + ufall = (!innate_lev && !blockd_lev + && !(HFlying || EFlying)); /* BFlying */ if (!ufall) { - You(innate_lev ? "wobble unsteadily for a moment." - : "gain control of your flight."); + You((innate_lev || blockd_lev) ? "wobble unsteadily for a moment." + : "gain control of your flight."); } else { long save_ELev = ELevitation, save_HLev = HLevitation; @@ -1179,6 +1185,10 @@ struct trap *desttrap; /* nonnull if another trap at */ if (!u.utrap) return TRUE; /* sanity check */ + /* + * Note: caller should call reset_utrap() when we set u.utrap to 0. + */ + switch (u.utraptype) { case TT_BEARTRAP: if (flags.verbose) { @@ -1203,7 +1213,6 @@ struct trap *desttrap; /* nonnull if another trap at */ break; case TT_WEB: if (uwep && uwep->oartifact == ART_STING) { - u.utrap = 0; pline("Sting cuts through the web!"); break; /* escape trap but don't move */ } @@ -1656,7 +1665,12 @@ domove() return; if (u.utrap) { - if (!trapmove(x, y, trap)) + boolean moved = trapmove(x, y, trap); + + if (!u.utrap) + reset_utrap(TRUE); /* might resume levitation or flight */ + /* might not have escaped, or did escape but remain in same spot */ + if (!moved) return; } @@ -1927,13 +1941,15 @@ switch_terrain() || (Is_waterlevel(&u.uz) && lev->typ == WATER)); if (blocklev) { - /* called from spoteffects(), skip float_down() */ + /* called from spoteffects(), stop levitating but skip float_down() */ if (Levitation) You_cant("levitate in here."); BLevitation |= FROMOUTSIDE; } else if (BLevitation) { BLevitation &= ~FROMOUTSIDE; - if (Levitation) + /* we're probably levitating now; if not, we must be chained + to a buried iron ball so get float_up() feedback for that */ + if (Levitation || BLevitation) float_up(); } /* the same terrain that blocks levitation also blocks flight */ @@ -2058,7 +2074,7 @@ boolean pick; spotterrain = levl[u.ux][u.uy].typ; spotloc.x = u.ux, spotloc.y = u.uy; - /* moving onto different terrain might cause Levitation to toggle */ + /* moving onto different terrain might cause Lev or Fly to toggle */ if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0)) switch_terrain(); @@ -2890,7 +2906,7 @@ boolean k_format; int weight_cap() { - long carrcap, save_ELev = ELevitation; + long carrcap, save_ELev = ELevitation, save_BLev = BLevitation; /* boots take multiple turns to wear but any properties they confer are enabled at the start rather than the end; that @@ -2900,6 +2916,9 @@ weight_cap() ELevitation &= ~W_ARMF; float_vs_flight(); /* in case Levitation is blocking Flying */ } + /* levitation is blocked by being trapped in the floor, but it still + functions enough in that situation to enhance carrying capacity */ + BLevitation &= ~I_SPECIAL; carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50; if (Upolyd) { @@ -2930,8 +2949,9 @@ weight_cap() carrcap = 0; } - if (ELevitation != save_ELev) { + if (ELevitation != save_ELev || BLevitation != save_BLev) { ELevitation = save_ELev; + BLevitation = save_BLev; float_vs_flight(); } diff --git a/src/mhitu.c b/src/mhitu.c index 7ae3ff103..f3fecbd92 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1774,7 +1774,7 @@ struct attack *mattk; if (u.utrap) { You("are released from the %s!", u.utraptype == TT_WEB ? "web" : "trap"); - u.utrap = 0; + reset_utrap(FALSE); } i = number_leashed(); diff --git a/src/mklev.c b/src/mklev.c index aecba88fa..11067b931 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -1683,9 +1683,9 @@ mkinvokearea() /* any trap hero is stuck in will be going away now */ if (u.utrap) { - u.utrap = 0; if (u.utraptype == TT_BURIEDBALL) buried_ball_to_punishment(); + reset_utrap(FALSE); } mkinvpos(xmin, ymin, 0); /* middle, before placing stairs */ diff --git a/src/music.c b/src/music.c index cb63bde90..b2dee2cad 100644 --- a/src/music.c +++ b/src/music.c @@ -254,14 +254,10 @@ int force; start_y = u.uy - (force * 2); end_x = u.ux + (force * 2); end_y = u.uy + (force * 2); - if (start_x < 1) - start_x = 1; - if (start_y < 1) - start_y = 1; - if (end_x >= COLNO) - end_x = COLNO - 1; - if (end_y >= ROWNO) - end_y = ROWNO - 1; + start_x = max(start_x, 1); + start_y = max(start_y, 0); + end_x = min(end_x, COLNO - 1); + end_y = min(end_y, ROWNO - 1); for (x = start_x; x <= end_x; x++) for (y = start_y; y <= end_y; y++) { if ((mtmp = m_at(x, y)) != 0) { @@ -311,6 +307,11 @@ int force; break; /* no pit if portal at that location */ chasm->tseen = 1; + /* TODO: + * This ought to be split into a separate routine to + * reduce indentation and the consequent line-wraps. + */ + levl[x][y].doormask = 0; /* * Let liquid flow into the newly created chasm. @@ -328,8 +329,8 @@ int force; if ((otmp = sobj_at(BOULDER, x, y)) != 0) { if (cansee(x, y)) pline("KADOOM! The boulder falls into a chasm%s!", - ((x == u.ux) && (y == u.uy)) ? " below you" - : ""); + (x == u.ux && y == u.uy) ? " below you" + : ""); if (mtmp) mtmp->mtrapped = 0; obj_extract_self(otmp); @@ -343,6 +344,7 @@ int force; if (!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) { boolean m_already_trapped = mtmp->mtrapped; + mtmp->mtrapped = 1; if (!m_already_trapped) { /* suppress messages */ if (cansee(x, y)) @@ -375,6 +377,16 @@ int force; } } } else if (x == u.ux && y == u.uy) { + if (u.utrap && u.utraptype == TT_BURIEDBALL) { + /* Note: the chain should break if a pit gets + created at the buried ball's location, which + is not necessarily here. But if we don't do + things this way, entering the new pit below + will override current trap anyway, but too + late to get Lev and Fly handling. */ + Your("chain breaks!"); + reset_utrap(TRUE); + } if (Levitation || Flying || is_clinger(youmonst.data)) { if (!tu_pit) { /* no pit here previously */ @@ -384,10 +396,9 @@ int force; } else if (!tu_pit || !u.utrap || (u.utrap && u.utraptype != TT_PIT)) { /* no pit here previously, or you were - not in it even it there was */ + not in it even if there was */ You("fall into a chasm!"); - u.utrap = rn1(6, 2); - u.utraptype = TT_PIT; + set_utrap(rn1(6, 2), TT_PIT); losehp(Maybe_Half_Phys(rnd(6)), "fell into a chasm", NO_KILLER_PREFIX); selftouch("Falling, you"); @@ -396,9 +407,9 @@ int force; ((Fumbling && !rn2(5)) || (!rnl(Role_if(PM_ARCHEOLOGIST) ? 3 : 9)) || ((ACURR(A_DEX) > 7) && rn2(5))); + You("are jostled around violently!"); - u.utrap = rn1(6, 2); - u.utraptype = TT_PIT; /* superfluous */ + set_utrap(rn1(6, 2), TT_PIT); losehp(Maybe_Half_Phys(rnd(keepfooting ? 2 : 4)), "hurt in a chasm", NO_KILLER_PREFIX); if (keepfooting) @@ -605,8 +616,8 @@ struct obj *instr; You("beat a deafening row!"); incr_itimeout(&HDeaf, rn1(20, 30)); exercise(A_WIS, FALSE); - } else - You("%s %s.", + } else + You("%s %s.", rn2(2) ? "butcher" : rn2(2) ? "manage" : "pull off", an(beats[rn2(SIZE(beats))])); awaken_monsters(u.ulevel * (mundane ? 5 : 40)); diff --git a/src/polyself.c b/src/polyself.c index c7f9c538d..a3bea6a24 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -86,7 +86,10 @@ set_uasmon() PROPSET(TELEPORT, can_teleport(mdat)); PROPSET(TELEPORT_CONTROL, control_teleport(mdat)); PROPSET(LEVITATION, is_floater(mdat)); - PROPSET(FLYING, is_flyer(mdat)); + /* floating eye is the only 'floater'; it is also flagged as a 'flyer'; + suppress flying for it so that enlightenment doesn't confusingly + show latent flight capability always blocked by levitation */ + PROPSET(FLYING, (is_flyer(mdat) && !is_floater(mdat))); PROPSET(SWIMMING, is_swimmer(mdat)); /* [don't touch MAGICAL_BREATHING here; both Amphibious and Breathless key off of it but include different monster forms...] */ @@ -116,12 +119,21 @@ set_uasmon() void float_vs_flight() { - /* floating overrides flight; normally float_up() and float_down() - handle this, but sometimes they're skipped */ - if (HLevitation || ELevitation) + boolean stuck_in_floor = (u.utrap && u.utraptype != TT_PIT); + + /* floating overrides flight; so does being trapped in the floor */ + if ((HLevitation || ELevitation) + || ((HFlying || EFlying) && stuck_in_floor)) BFlying |= I_SPECIAL; else BFlying &= ~I_SPECIAL; + /* being trapped on the ground (bear trap, web, molten lava survived + with fire resistance, former lava solidified via cold, tethered + to a buried iron ball) overrides floating--the floor is reachable */ + if ((HLevitation || ELevitation) && stuck_in_floor) + BLevitation |= I_SPECIAL; + else + BLevitation &= ~I_SPECIAL; context.botl = TRUE; } @@ -207,8 +219,8 @@ const char *fmt, *arg; if (u.twoweap && !could_twoweap(youmonst.data)) untwoweapon(); - if (u.utraptype == TT_PIT && u.utrap) { - u.utrap = rn1(6, 2); /* time to escape resets */ + if (u.utrap && u.utraptype == TT_PIT) { + set_utrap(rn1(6, 2), TT_PIT); /* time to escape resets */ } if (was_blind && !Blind) { /* reverting from eyeless */ Blinded = 1L; @@ -725,8 +737,8 @@ int mntmp; drop_weapon(1); (void) hideunder(&youmonst); - if (u.utraptype == TT_PIT && u.utrap) { - u.utrap = rn1(6, 2); /* time to escape resets */ + if (u.utrap && u.utraptype == TT_PIT) { + set_utrap(rn1(6, 2), TT_PIT); /* time to escape resets */ } if (was_blind && !Blind) { /* previous form was eyeless */ Blinded = 1L; @@ -794,17 +806,17 @@ int mntmp; spoteffects(TRUE); if (Passes_walls && u.utrap && (u.utraptype == TT_INFLOOR || u.utraptype == TT_BURIEDBALL)) { - u.utrap = 0; - if (u.utraptype == TT_INFLOOR) + if (u.utraptype == TT_INFLOOR) { pline_The("rock seems to no longer trap you."); - else { + } else { pline_The("buried ball is no longer bound to you."); buried_ball_to_freedom(); } + reset_utrap(TRUE); } else if (likes_lava(youmonst.data) && u.utrap && u.utraptype == TT_LAVA) { - u.utrap = 0; pline_The("%s now feels soothing.", hliquid("lava")); + reset_utrap(TRUE); } if (amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data)) { @@ -823,11 +835,11 @@ int mntmp; You("are no longer stuck in the %s.", u.utraptype == TT_WEB ? "web" : "bear trap"); /* probably should burn webs too if PM_FIRE_ELEMENTAL */ - u.utrap = 0; + reset_utrap(TRUE); } if (webmaker(youmonst.data) && u.utrap && u.utraptype == TT_WEB) { You("orient yourself on the web."); - u.utrap = 0; + reset_utrap(TRUE); } check_strangling(TRUE); /* maybe start strangling */ diff --git a/src/pray.c b/src/pray.c index 5d0d456fc..bd8a3604e 100644 --- a/src/pray.c +++ b/src/pray.c @@ -355,7 +355,7 @@ int trouble; You("are back on solid ground."); /* teleport should always succeed, but if not, just untrap them */ if (!safe_teleds(FALSE)) - u.utrap = 0; + reset_utrap(TRUE); break; case TROUBLE_STARVING: /* temporarily lost strength recovery now handled by init_uhunger() */ diff --git a/src/teleport.c b/src/teleport.c index 615292d5d..a1adfd95d 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -289,7 +289,7 @@ boolean allow_drag; } } } - u.utrap = 0; + reset_utrap(FALSE); u.ustuck = 0; u.ux0 = u.ux; u.uy0 = u.uy; diff --git a/src/trap.c b/src/trap.c index 056570906..85d8c1a2e 100644 --- a/src/trap.c +++ b/src/trap.c @@ -805,10 +805,12 @@ struct trap *trap; { boolean isyou = (mtmp == &youmonst); struct permonst *mptr = mtmp->data; + if (amorphous(mptr) || is_whirly(mptr) || flaming(mptr) || unsolid(mptr) || mptr == &mons[PM_GELATINOUS_CUBE]) { xchar x = trap->tx; xchar y = trap->ty; + if (flaming(mptr) || acidic(mptr)) { if (domsg) { if (isyou) @@ -825,9 +827,9 @@ struct trap *trap; return TRUE; } if (domsg) { - if (isyou) + if (isyou) { You("flow through %s spider web.", a_your[trap->madeby_u]); - else { + } else { pline("%s flows through %s spider web.", Monnam(mtmp), a_your[trap->madeby_u]); seetrap(trap); @@ -853,6 +855,37 @@ struct trap *trap; return otmp; } +void +set_utrap(tim, typ) +unsigned tim, typ; +{ + u.utrap = tim; + /* FIXME: + * utraptype==0 is bear trap rather than 'none'; we probably ought + * to change that but can't do so until save file compatability is + * able to be broken. + */ + u.utraptype = tim ? typ : 0; + + float_vs_flight(); /* maybe block Lev and/or Fly */ +} + +void +reset_utrap(msg) +boolean msg; +{ + boolean was_Lev = (Levitation != 0), was_Fly = (Flying != 0); + + set_utrap(0, 0); + + if (msg) { + if (!was_Lev && Levitation) + float_up(); + if (!was_Fly && Flying) + You("can fly."); + } +} + void dotrap(trap, trflags) register struct trap *trap; @@ -1042,13 +1075,12 @@ unsigned trflags; A_Your[trap->madeby_u]); break; } - u.utrap = rn1(4, 4); - u.utraptype = TT_BEARTRAP; + set_utrap((unsigned) rn1(4, 4), TT_BEARTRAP); if (u.usteed) { pline("%s bear trap closes on %s %s!", A_Your[trap->madeby_u], s_suffix(mon_nam(u.usteed)), mbodypart(u.usteed, FOOT)); if (thitm(0, u.usteed, (struct obj *) 0, dmg, FALSE)) - u.utrap = 0; /* steed died, hero not trapped */ + reset_utrap(TRUE); /* steed died, hero not trapped */ } else { pline("%s bear trap closes on your %s!", A_Your[trap->madeby_u], body_part(FOOT)); @@ -1191,8 +1223,12 @@ unsigned trflags; } else You("%s %s!", conj_pit ? "step" : "land", predicament); } - u.utrap = rn1(6, 2); - u.utraptype = TT_PIT; + /* FIXME: + * if hero gets killed here, setting u.utrap in advance will + * show "you were trapped in a pit" during disclosure's display + * of enlightenment, but hero is dying *before* becoming trapped. + */ + set_utrap((unsigned) rn1(6, 2), TT_PIT); if (!steedintrap(trap, (struct obj *) 0)) { if (ttype == SPIKED_PIT) { oldumort = u.umortality; @@ -1286,11 +1322,13 @@ unsigned trflags; } You("%s %s spider web!", verbbuf, a_your[trap->madeby_u]); } - u.utraptype = TT_WEB; + + /* time will be adjusted below */ + set_utrap(1, TT_WEB); /* Time stuck in the web depends on your/steed strength. */ { - register int str = ACURR(A_STR); + int tim, str = ACURR(A_STR); /* If mounted, the steed gets trapped. Use mintrap * to do all the work. If mtrapped is set as a result, @@ -1312,32 +1350,34 @@ unsigned trflags; if (strongmonst(u.usteed->data)) str = 17; } else { + reset_utrap(FALSE); break; } webmsgok = FALSE; /* mintrap printed the messages */ } if (str <= 3) - u.utrap = rn1(6, 6); + tim = rn1(6, 6); else if (str < 6) - u.utrap = rn1(6, 4); + tim = rn1(6, 4); else if (str < 9) - u.utrap = rn1(4, 4); + tim = rn1(4, 4); else if (str < 12) - u.utrap = rn1(4, 2); + tim = rn1(4, 2); else if (str < 15) - u.utrap = rn1(2, 2); + tim = rn1(2, 2); else if (str < 18) - u.utrap = rnd(2); + tim = rnd(2); else if (str < 69) - u.utrap = 1; + tim = 1; else { - u.utrap = 0; + tim = 0; if (webmsgok) You("tear through %s web!", a_your[trap->madeby_u]); deltrap(trap); newsym(u.ux, u.uy); /* get rid of trap symbol */ } + set_utrap((unsigned) tim, TT_WEB); } break; @@ -2767,16 +2807,34 @@ float_up() context.botl = TRUE; if (u.utrap) { if (u.utraptype == TT_PIT) { - u.utrap = 0; + reset_utrap(FALSE); You("float up, out of the pit!"); vision_full_recalc = 1; /* vision limits change */ fill_pit(u.ux, u.uy); - } else if (u.utraptype == TT_INFLOOR) { + } else if (u.utraptype == TT_LAVA /* molten lava */ + || u.utraptype == TT_INFLOOR) { /* solidified lava */ Your("body pulls upward, but your %s are still stuck.", makeplural(body_part(LEG))); - } else { - You("float up, only your %s is still stuck.", body_part(LEG)); + } else if (u.utraptype == TT_BURIEDBALL) { /* tethered */ + coord cc; + + cc.x = u.ux, cc.y = u.uy; + /* caveat: this finds the first buried iron ball within + one step of the specified location, not necessarily the + buried [former] uball at the original anchor point */ + (void) buried_ball(&cc); + /* being chained to the floor blocks levitation from floating + above that floor but not from enhancing carrying capacity */ + You("feel lighter, but your %s is still chained to the %s.", + body_part(LEG), + IS_ROOM(levl[cc.x][cc.y].typ) ? "floor" : "ground"); + } else if (u.utraptype == WEB) { + You("float up slightly, but you are still stuck in the web."); + } else { /* bear trap */ + You("float up slightly, but your %s is still stuck.", + body_part(LEG)); } + /* when still trapped, float_vs_flight() below will block levitation */ #if 0 } else if (Is_waterlevel(&u.uz)) { pline("It feels as though you've lost some weight."); @@ -2795,8 +2853,7 @@ float_up() } else { You("start to float in the air!"); } - if (u.usteed && !is_floater(u.usteed->data) - && !is_flyer(u.usteed->data)) { + if (u.usteed && !is_floater(u.usteed->data) && !is_flyer(u.usteed->data)) { if (Lev_at_will) { pline("%s magically floats up!", Monnam(u.usteed)); } else { @@ -2806,7 +2863,7 @@ float_up() } if (Flying) You("are no longer able to control your flight."); - BFlying |= I_SPECIAL; + float_vs_flight(); /* set BFlying, also BLevitation if still trapped */ /* levitation gives maximum carrying capacity, so encumbrance state might be reduced */ (void) encumber_msg(); @@ -2841,16 +2898,29 @@ long hmask, emask; /* might cancel timeout */ if (Levitation) return 0; /* maybe another ring/potion/boots */ if (BLevitation) { - /* Levitation is blocked, so hero is not actually floating - hence shouldn't have float_down effects and feedback */ - float_vs_flight(); /* before nomul() rather than after */ + /* if blocked by terrain, we haven't actually been levitating so + we don't give any end-of-levitation feedback or side-effects, + but if blocking is solely due to being trapped in/on floor, + do give some feedback but skip other float_down() effects */ + boolean trapped = (BLevitation == I_SPECIAL); + + float_vs_flight(); + if (trapped && u.utrap) /* u.utrap => paranoia */ + You("are no longer trying to float up from the %s.", + (u.utraptype == TT_BEARTRAP) ? "trap's jaws" + : (u.utraptype == TT_WEB) ? "web" + : (u.utraptype == TT_BURIEDBALL) ? "chain" + : (u.utraptype == TT_LAVA) ? "lava" + : "ground"); /* TT_INFLOOR */ + (void) encumber_msg(); /* carrying capacity might have changed */ return 0; } context.botl = TRUE; nomul(0); /* stop running or resting */ if (BFlying) { /* controlled flight no longer overridden by levitation */ - BFlying &= ~I_SPECIAL; + float_vs_flight(); /* clears BFlying & I_SPECIAL + * unless hero is stuck in floor */ if (Flying) { You("have stopped levitating and are now flying."); (void) encumber_msg(); /* carrying capacity might have changed */ @@ -2981,7 +3051,7 @@ climb_pit() if (Passes_walls) { /* marked as trapped so they can pick things up */ You("ascend from the pit."); - u.utrap = 0; + reset_utrap(FALSE); fill_pit(u.ux, u.uy); vision_full_recalc = 1; /* vision limits change */ } else if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) { @@ -2993,10 +3063,11 @@ climb_pit() /* eg fell in pit, then poly'd to a flying monster; or used '>' to deliberately enter it */ You("%s from the pit.", Flying ? "fly" : "climb"); - u.utrap = 0; + reset_utrap(FALSE); fill_pit(u.ux, u.uy); vision_full_recalc = 1; /* vision limits change */ } else if (!(--u.utrap)) { + reset_utrap(FALSE); You("%s to the edge of the pit.", (Sokoban && Levitation) ? "struggle against the air currents and float" @@ -3887,7 +3958,7 @@ boolean bury_it; } newsym(ttmp->tx, ttmp->ty); if (u.utrap && ttmp->tx == u.ux && ttmp->ty == u.uy) - u.utrap = 0; + reset_utrap(TRUE); deltrap(ttmp); } @@ -4506,51 +4577,80 @@ struct monst *mon; boolean *noticed; /* set to true iff hero notices the effect; */ { /* otherwise left with its previous value intact */ struct trap *t; - char buf[BUFSZ]; - const char *trapdescr, *which; + char buf[BUFSZ], whichbuf[20]; + const char *trapdescr = 0, *which = 0; boolean ishero = (mon == &youmonst); if (!mon) return FALSE; if (mon == u.usteed) ishero = TRUE; - t = t_at(ishero ? u.ux : mon->mx, ishero ? u.uy : mon->my); - /* if no trap here or it's not a holding trap, we're done */ - if (!t || (t->ttyp != BEAR_TRAP && t->ttyp != WEB)) - return FALSE; - trapdescr = defsyms[trap_to_defsym(t->ttyp)].explanation; - which = t->tseen ? the_your[t->madeby_u] - : index(vowels, *trapdescr) ? "an" : "a"; + t = t_at(ishero ? u.ux : mon->mx, ishero ? u.uy : mon->my); + + if (ishero && u.utrap) { /* all u.utraptype values are holding traps */ + which = ""; + switch (u.utraptype) { + case TT_LAVA: + trapdescr = "molten lava"; + break; + case TT_INFLOOR: + /* solidified lava, so not "floor" even if within a room */ + trapdescr = "ground"; + break; + case TT_BURIEDBALL: + trapdescr = "your anchor"; + break; + case TT_BEARTRAP: + case TT_PIT: + case TT_WEB: + trapdescr = 0; /* use defsyms[].explanation */ + break; + default: + /* lint suppression in case 't' is unexpectedly Null + or u.utraptype has new value we don't know about yet */ + trapdescr = "trap"; + break; + } + } else { + /* if no trap here or it's not a holding trap, we're done */ + if (!t || (t->ttyp != BEAR_TRAP && t->ttyp != WEB)) + return FALSE; + } + + if (!trapdescr) + trapdescr = defsyms[trap_to_defsym(t->ttyp)].explanation; + if (!which) + which = t->tseen ? the_your[t->madeby_u] + : index(vowels, *trapdescr) ? "an" : "a"; + if (*which) + which = strcat(strcpy(whichbuf, which), " "); if (ishero) { if (!u.utrap) return FALSE; - u.utrap = 0; /* released regardless of type */ *noticed = TRUE; - /* give message only if trap was the expected type */ - if (u.utraptype == TT_BEARTRAP || u.utraptype == TT_WEB) { - if (u.usteed) - Sprintf(buf, "%s is", noit_Monnam(u.usteed)); - else - Strcpy(buf, "You are"); - pline("%s released from %s %s.", buf, which, trapdescr); - } + if (u.usteed) + Sprintf(buf, "%s is", noit_Monnam(u.usteed)); + else + Strcpy(buf, "You are"); + pline("%s released from %s%s.", buf, which, trapdescr); + reset_utrap(TRUE); } else { if (!mon->mtrapped) return FALSE; mon->mtrapped = 0; if (canspotmon(mon)) { *noticed = TRUE; - pline("%s is released from %s %s.", Monnam(mon), which, + pline("%s is released from %s%s.", Monnam(mon), which, trapdescr); } else if (cansee(t->tx, t->ty) && t->tseen) { *noticed = TRUE; if (t->ttyp == WEB) - pline("%s is released from %s %s.", Something, which, + pline("%s is released from %s%s.", Something, which, trapdescr); else /* BEAR_TRAP */ - pline("%s %s opens.", upstart(strcpy(buf, which)), trapdescr); + pline("%s%s opens.", upstart(strcpy(buf, which)), trapdescr); } /* might pacify monster if adjacent */ if (rn2(2) && distu(mon->mx, mon->my) <= 2) @@ -5002,8 +5102,8 @@ register struct trap *ttmp; register struct monst *mtmp; if (ttmp->tx == u.ux && ttmp->ty == u.uy) { - u.utrap = 0; - u.utraptype = 0; + if (u.utraptype != TT_BURIEDBALL) + reset_utrap(TRUE); } else if ((mtmp = m_at(ttmp->tx, ttmp->ty)) != 0) { mtmp->mtrapped = 0; } @@ -5211,12 +5311,11 @@ lava_effects() boil_away = !Fire_resistance; /* if not fire resistant, sink_into_lava() will quickly be fatal; hero needs to escape immediately */ - u.utrap = rn1(4, 4) + ((boil_away ? 2 : rn1(4, 12)) << 8); - u.utraptype = TT_LAVA; + set_utrap((unsigned) (rn1(4, 4) + ((boil_away ? 2 : rn1(4, 12)) << 8)), + TT_LAVA); You("sink into the %s%s!", hliquid("lava"), - !boil_away - ? ", but it only burns slightly" - : " and are about to be immolated"); + !boil_away ? ", but it only burns slightly" + : " and are about to be immolated"); if (u.uhp > 1) losehp(!boil_away ? 1 : (u.uhp / 2), lava_killer, KILLED_BY); /* lava damage */ @@ -5238,7 +5337,7 @@ sink_into_lava() if (!u.utrap || u.utraptype != TT_LAVA) { ; /* do nothing; this shouldn't happen */ } else if (!is_lava(u.ux, u.uy)) { - u.utrap = 0; /* this shouldn't happen either */ + reset_utrap(FALSE); /* this shouldn't happen either */ } else if (!u.uinvulnerable) { /* ordinarily we'd have to be fire resistant to survive long enough to become stuck in lava, but it can happen without @@ -5255,8 +5354,10 @@ sink_into_lava() burn_away_slime(); /* add insult to injury? */ done(DISSOLVED); /* can only get here via life-saving; try to get away from lava */ - u.utrap = 0; - (void) safe_teleds(TRUE); + reset_utrap(TRUE); + /* levitation or flight have become unblocked, otherwise Tport */ + if (!Levitation && !Flying) + (void) safe_teleds(TRUE); } else if (!u.umoved) { /* can't fully turn into slime while in lava, but might not have it be burned away until you've come awfully close */ diff --git a/src/zap.c b/src/zap.c index 7a5ab3416..5781d8789 100644 --- a/src/zap.c +++ b/src/zap.c @@ -4431,11 +4431,10 @@ short exploding_wand_typ; vision_full_recalc = 1; } else if (u.utrap && u.utraptype == TT_LAVA) { if (Passes_walls) { - u.utrap = 0; You("pass through the now-solid rock."); + reset_utrap(TRUE); } else { - u.utrap = rn1(50, 20); - u.utraptype = TT_INFLOOR; + set_utrap(rn1(50, 20), TT_INFLOOR); You("are firmly stuck in the cooling rock."); } } From 317f0b56fac77a1b6d5b837222dd30f242fe16f9 Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 30 Sep 2018 02:11:32 -0700 Subject: [PATCH 02/12] tile.c formatting Modify win/share/tilemap.c so that generated source file src/tile.c uses similar formatting to the other sources. Mainly, avoid tabs and use 4 columns indentation instead of 8 columns in the short routine near the end. tilemap.c still treats STATUES_LOOK_LIKE_MONSTERS as conditional. The main sources made that unconditional prior to release of 3.6.0. --- win/share/tilemap.c | 91 +++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/win/share/tilemap.c b/win/share/tilemap.c index 46b1056e2..e2ec90e40 100644 --- a/win/share/tilemap.c +++ b/win/share/tilemap.c @@ -3,13 +3,15 @@ /* NetHack may be freely redistributed. See license for details. */ /* - * This source file is compiled twice: - * once without TILETEXT defined to make tilemap.{o,obj}, - * then again with it defined to produce tiletxt.{o,obj}. + * This source file is compiled twice: + * once without TILETEXT defined to make tilemap.{o,obj}, + * then again with it defined to produce tiletxt.{o,obj}. */ #include "hack.h" +#define Fprintf (void) fprintf + const char *FDECL(tilename, (int, int)); void NDECL(init_tilemap); void FDECL(process_substitutions, (FILE *)); @@ -40,7 +42,7 @@ struct conditionals { int sequence, predecessor; const char *name; } conditionals[] = { -#ifndef CHARON /* not supported yet */ +#ifndef CHARON /* not supported */ { MON_GLYPH, PM_HELL_HOUND, "Cerberus" }, #endif /* commented out in monst.c at present */ @@ -68,7 +70,8 @@ struct conditionals { * don't know what a slime mold should look like when renamed anyway */ #ifndef MAIL - { OBJ_GLYPH, SCR_STINKING_CLOUD + EXTRA_SCROLL_DESCR_COUNT, "stamped / mail" }, + { OBJ_GLYPH, SCR_STINKING_CLOUD + EXTRA_SCROLL_DESCR_COUNT, + "stamped / mail" }, #endif { 0, 0, 0 } }; @@ -394,19 +397,20 @@ init_tilemap() #endif } -const char *prolog[] = { "", "", "void", "substitute_tiles(plev)", - "d_level *plev;", "{", "\tint i;", "" }; +const char *prolog[] = { "", "void", "substitute_tiles(plev)", + "d_level *plev;", "{", " int i;", "" }; -const char *epilog[] = { "}" }; +const char *epilog[] = { " return;", "}" }; /* write out the substitutions in an easily-used form. */ void process_substitutions(ofp) FILE *ofp; { + static const char Dent[] = " "; /* 4 space indentation */ int i, j, k, span, start; - fprintf(ofp, "\n\n"); + Fprintf(ofp, "\n"); j = 0; /* unnecessary */ span = -1; @@ -415,16 +419,16 @@ FILE *ofp; || substitutes[i].last_glyph != substitutes[j].last_glyph) { j = i; span++; - fprintf(ofp, "short std_tiles%d[] = { ", span); + Fprintf(ofp, "short std_tiles%d[] = { ", span); for (k = substitutes[i].first_glyph; k < substitutes[i].last_glyph; k++) - fprintf(ofp, "%d, ", tilemap[k]); - fprintf(ofp, "%d };\n", tilemap[substitutes[i].last_glyph]); + Fprintf(ofp, "%d, ", tilemap[k]); + Fprintf(ofp, "%d };\n", tilemap[substitutes[i].last_glyph]); } } for (i = 0; i < SIZE(prolog); i++) { - fprintf(ofp, "%s\n", prolog[i]); + Fprintf(ofp, "%s\n", prolog[i]); } j = -1; span = -1; @@ -433,43 +437,41 @@ FILE *ofp; if (i == 0 || substitutes[i].first_glyph != substitutes[j].first_glyph || substitutes[i].last_glyph != substitutes[j].last_glyph) { if (i != 0) { /* finish previous span */ - fprintf(ofp, "\t} else {\n"); - fprintf(ofp, "\t\tfor (i = %d; i <= %d; i++)\n", - substitutes[j].first_glyph, - substitutes[j].last_glyph); - fprintf(ofp, "\t\t\tglyph2tile[i] = std_tiles%d[i - %d];\n", - span, substitutes[j].first_glyph); - fprintf(ofp, "\t}\n\n"); + Fprintf(ofp, "%s} else {\n", Dent); + Fprintf(ofp, "%s%sfor (i = %d; i <= %d; i++)\n", Dent, Dent, + substitutes[j].first_glyph, substitutes[j].last_glyph); + Fprintf(ofp, "%s%s%sglyph2tile[i] = std_tiles%d[i - %d];\n", + Dent, Dent, Dent, span, substitutes[j].first_glyph); + Fprintf(ofp, "%s}\n\n", Dent); } j = i; span++; } - if (i != j) - fprintf(ofp, "\t} else "); - fprintf(ofp, "\tif (%s) {\n", substitutes[i].level_test); - fprintf(ofp, "\t\tfor (i = %d; i <= %d; i++)\n", + Fprintf(ofp, "%s%sif (%s) {\n", Dent, (i == j) ? "" : "} else ", + substitutes[i].level_test); + Fprintf(ofp, "%s%sfor (i = %d; i <= %d; i++)\n", Dent, Dent, substitutes[i].first_glyph, substitutes[i].last_glyph); - fprintf(ofp, "\t\t\tglyph2tile[i] = %d + i - %d;\n", start, - substitutes[i].first_glyph); + Fprintf(ofp, "%s%s%sglyph2tile[i] = %d + i - %d;\n", + Dent, Dent, Dent, start, substitutes[i].first_glyph); start += substitutes[i].last_glyph - substitutes[i].first_glyph + 1; } /* finish last span */ - fprintf(ofp, "\t} else {\n"); - fprintf(ofp, "\t\tfor (i = %d; i <= %d; i++)\n", + Fprintf(ofp, "%s} else {\n", Dent); + Fprintf(ofp, "%s%sfor (i = %d; i <= %d; i++)\n", Dent, Dent, substitutes[j].first_glyph, substitutes[j].last_glyph); - fprintf(ofp, "\t\t\tglyph2tile[i] = std_tiles%d[i - %d];\n", span, - substitutes[j].first_glyph); - fprintf(ofp, "\t}\n\n"); + Fprintf(ofp, "%s%s%sglyph2tile[i] = std_tiles%d[i - %d];\n", + Dent, Dent, Dent, span, substitutes[j].first_glyph); + Fprintf(ofp, "%s}\n", Dent); for (i = 0; i < SIZE(epilog); i++) { - fprintf(ofp, "%s\n", epilog[i]); + Fprintf(ofp, "%s\n", epilog[i]); } lastothtile = start - 1; #ifdef STATUES_LOOK_LIKE_MONSTERS start = laststatuetile + 1; #endif - fprintf(ofp, "\nint total_tiles_used = %d;\n", start); + Fprintf(ofp, "\nint total_tiles_used = %d;\n", start); } int @@ -489,27 +491,27 @@ main() perror(filename); exit(EXIT_FAILURE); } - fprintf(ofp, + Fprintf(ofp, "/* This file is automatically generated. Do not edit. */\n"); - fprintf(ofp, "\n#include \"hack.h\"\n\n"); - fprintf(ofp, "short glyph2tile[MAX_GLYPH] = {\n"); + Fprintf(ofp, "\n#include \"hack.h\"\n"); + Fprintf(ofp, "\nshort glyph2tile[MAX_GLYPH] = {\n"); for (i = 0; i < MAX_GLYPH; i++) { - fprintf(ofp, "%2d,%c", tilemap[i], (i % 12) ? ' ' : '\n'); + Fprintf(ofp, "%2d,%c", tilemap[i], (i % 12) ? ' ' : '\n'); } - fprintf(ofp, "%s};\n", (i % 12) ? "\n" : ""); + Fprintf(ofp, "\n};\n"); process_substitutions(ofp); - fprintf(ofp, "\n#define MAXMONTILE %d\n", lastmontile); - fprintf(ofp, "#define MAXOBJTILE %d\n", lastobjtile); - fprintf(ofp, "#define MAXOTHTILE %d\n", lastothtile); + Fprintf(ofp, "\n#define MAXMONTILE %d\n", lastmontile); + Fprintf(ofp, "#define MAXOBJTILE %d\n", lastobjtile); + Fprintf(ofp, "#define MAXOTHTILE %d\n", lastothtile); #ifdef STATUES_LOOK_LIKE_MONSTERS - fprintf(ofp, "/* #define MAXSTATUETILE %d */\n", laststatuetile); + Fprintf(ofp, "/* #define MAXSTATUETILE %d */\n", laststatuetile); #endif - fprintf(ofp, "\n/*tile.c*/\n"); + Fprintf(ofp, "\n/*tile.c*/\n"); - fclose(ofp); + (void) fclose(ofp); exit(EXIT_SUCCESS); /*NOTREACHED*/ return 0; @@ -634,3 +636,4 @@ const char *encountered, *expected; return FALSE; } +/*tilemap.c*/ From 85aef136d59a303d0ac42c645403ecd56f68c53c Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 30 Sep 2018 08:45:49 -0400 Subject: [PATCH 03/12] comment typo in music.c --- src/music.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/music.c b/src/music.c index b2dee2cad..b9e159e75 100644 --- a/src/music.c +++ b/src/music.c @@ -598,7 +598,7 @@ struct obj *instr; exercise(A_DEX, TRUE); break; case DRUM_OF_EARTHQUAKE: /* create several pits */ - /* a drum of earthquake does cause not cause deafness + /* a drum of earthquake does not cause deafness while still magically functional, nor afterwards when it invokes the LEATHER_DRUM case instead and mundane is flagged */ From d9ecc425662edf3558a6519d10515b290f1749a0 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 30 Sep 2018 10:01:43 -0400 Subject: [PATCH 04/12] a couple of steed Flying messages --- src/polyself.c | 6 +++++- src/steed.c | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/polyself.c b/src/polyself.c index a3bea6a24..e136d1898 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1030,6 +1030,8 @@ int alone; void rehumanize() { + boolean was_flying = (Flying != 0); + /* You can't revert back while unchanging */ if (Unchanging) { if (u.mh < 1) { @@ -1060,7 +1062,9 @@ rehumanize() context.botl = 1; vision_full_recalc = 1; (void) encumber_msg(); - + if (was_flying && !Flying && u.usteed) + You("and %s return gently to the %s.", + mon_nam(u.usteed), surface(u.ux, u.uy)); retouch_equipment(2); if (!uarmg) selftouch(no_longer_petrify_resistant); diff --git a/src/steed.c b/src/steed.c index aa2beb300..1abdb867c 100644 --- a/src/steed.c +++ b/src/steed.c @@ -335,6 +335,8 @@ boolean force; /* Quietly force this animal */ /* Must have Lev_at_will at this point */ pline("%s magically floats up!", Monnam(mtmp)); You("mount %s.", mon_nam(mtmp)); + if (Flying) + You("and %s take flight together.", mon_nam(mtmp)); } /* setuwep handles polearms differently when you're mounted */ if (uwep && is_pole(uwep)) From 053880c149858fafd4016e786ae576284dec0f5f Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 30 Sep 2018 16:37:32 -0700 Subject: [PATCH 05/12] untrap downwards while over trap Force trap to activate during failed untrap attempt if done while already at the trap's location, to match the recent change in behavior when failed attempt occurs while adjacent to the trap. Most noticeable while flying over bear traps, but affects all failed untrap attempts. --- include/hack.h | 1 + src/hack.c | 2 +- src/trap.c | 8 +++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/hack.h b/include/hack.h index 555a08818..5785b8590 100644 --- a/include/hack.h +++ b/include/hack.h @@ -333,6 +333,7 @@ typedef struct sortloot_item Loot; #define RECURSIVETRAP 0x08 /* trap changed into another type this same turn */ #define TOOKPLUNGE 0x10 /* used '>' to enter pit below you */ #define VIASITTING 0x20 /* #sit while at trap location (affects message) */ +#define FAILEDUNTRAP 0x40 /* trap activated by failed untrap attempt */ /* Flags to control test_move in hack.c */ #define DO_MOVE 0 /* really doing the move */ diff --git a/src/hack.c b/src/hack.c index 44351f4d7..29261a968 100644 --- a/src/hack.c +++ b/src/hack.c @@ -2058,7 +2058,7 @@ boolean pick; struct monst *mtmp; struct trap *trap = t_at(u.ux, u.uy); - int trapflag = iflags.failing_untrap ? FORCETRAP : 0; + int trapflag = iflags.failing_untrap ? FAILEDUNTRAP : 0; /* prevent recursion from affecting the hero all over again [hero poly'd to iron golem enters water here, drown() inflicts diff --git a/src/trap.c b/src/trap.c index 85d8c1a2e..957e0f63c 100644 --- a/src/trap.c +++ b/src/trap.c @@ -894,7 +894,8 @@ unsigned trflags; register int ttype = trap->ttyp; struct obj *otmp; boolean already_seen = trap->tseen, - forcetrap = (trflags & FORCETRAP) != 0, + forcetrap = ((trflags & FORCETRAP) != 0 + || (trflags & FAILEDUNTRAP) != 0), webmsgok = (trflags & NOWEBMSG) == 0, forcebungle = (trflags & FORCEBUNGLE) != 0, plunged = (trflags & TOOKPLUNGE) != 0, @@ -3989,7 +3990,7 @@ struct trap *ttmp; there are objects covering this trap */ ttmp->tseen = 0; /* hack for check_here() */ /* trigger the trap */ - iflags.failing_untrap++; /* spoteffects() -> dotrap(,FORCETRAP) */ + iflags.failing_untrap++; /* spoteffects() -> dotrap(,FAILEDUNTRAP) */ spoteffects(TRUE); /* pickup() + dotrap() */ iflags.failing_untrap--; /* this should no longer be necessary; before the failing_untrap @@ -4074,7 +4075,8 @@ boolean force_failure; pline("%s remains entangled.", Monnam(mtmp)); } } else if (under_u) { - dotrap(ttmp, 0); + /* [don't need the iflags.failing_untrap hack here] */ + dotrap(ttmp, FAILEDUNTRAP); } else { move_into_trap(ttmp); } From 1110786ec20e28ea8805ccabcfc876ca46486181 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 1 Oct 2018 15:08:33 -0700 Subject: [PATCH 06/12] change default for 'autodescribe' to 'on' This was discussed two years ago then nothing happened. Make autodescribe for feedback when moving the cursor to pick something default to on instead of off. --- doc/Guidebook.mn | 3 ++- doc/Guidebook.tex | 4 ++-- doc/fixes36.2 | 1 + src/options.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 1802eca98..72963a6bb 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -2601,7 +2601,8 @@ exclude that alignment from being picked randomly. Cannot be set with the `O' command. Persistent. .lp autodescribe Automatically describe the terrain under cursor when asked to get a location -on the map. The +on the map (default true). +The .op whatis_coord option controls whether the description includes map coordinates. .lp autodig diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 7a118abb6..98533d091 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -3038,8 +3038,8 @@ Cannot be set with the `{\tt O}' command. Persistent. %.lp \item[\ib{autodescribe}] Automatically describe the terrain under cursor when asked to get a location -on the map. The -{\it whatis\verb+_+coord\/} +on the map (default true). +The {\it whatis\verb+_+coord\/} option controls whether the description includes map coordinates. %.lp \item[\ib{autodig}] diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 9c108add6..8baf780cc 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -157,6 +157,7 @@ floating eye is classified as a flyer but flying is blocked while levitating, being trapped (bear trap, web, molten or solidified lava, chained to buried iron ball) blocks both levitation and flight (note: being stuck in a pit ends when either of those starts so doesn't apply) +change default value for the 'autodescribe' option to 'on' Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/options.c b/src/options.c index 9829874e8..e337b4c36 100644 --- a/src/options.c +++ b/src/options.c @@ -78,7 +78,7 @@ static struct Bool_Opt { #else { "asksavedisk", (boolean *) 0, FALSE, SET_IN_FILE }, #endif - { "autodescribe", &iflags.autodescribe, FALSE, SET_IN_GAME }, + { "autodescribe", &iflags.autodescribe, TRUE, SET_IN_GAME }, { "autodig", &flags.autodig, FALSE, SET_IN_GAME }, { "autoopen", &flags.autoopen, TRUE, SET_IN_GAME }, { "autopickup", &flags.pickup, TRUE, SET_IN_GAME }, From 14bef9a02d93ec9d62992316276b14c65af8d649 Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 2 Oct 2018 16:53:22 -0700 Subject: [PATCH 07/12] formatting cleanup src/*.c Remove trailing spaces, and remove tabs from the files that had trailing spaces. Also, rndorcname() was using a random value to terminate a loop and was recalculating a new one each iteration. --- src/allmain.c | 58 +++++++++++++++++++++++++-------------------------- src/botl.c | 4 ++-- src/do_name.c | 21 ++++++++----------- src/dog.c | 2 +- src/dokick.c | 2 +- src/dothrow.c | 2 +- src/engrave.c | 2 +- src/files.c | 31 ++++++++++++++------------- src/invent.c | 2 +- src/makemon.c | 4 ++-- src/mhitm.c | 4 ++-- src/mkmaze.c | 3 +-- src/mon.c | 2 +- src/monmove.c | 10 ++++----- src/pager.c | 6 +++--- src/version.c | 2 +- 16 files changed, 75 insertions(+), 80 deletions(-) diff --git a/src/allmain.c b/src/allmain.c index 2c1364d75..d0b2c5302 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -793,44 +793,42 @@ enum earlyarg e_arg; userea = &argv[i][1]; } match = match_optname(userea, earlyopts[idx].name, - earlyopts[idx].minlength, earlyopts[idx].valallowed); + earlyopts[idx].minlength, + earlyopts[idx].valallowed); if (match) break; } if (match) { - const char *extended_opt = index(userea,':'); + const char *extended_opt = index(userea, ':'); if (!extended_opt) extended_opt = index(userea, '='); switch(e_arg) { - case ARG_DEBUG: - if (extended_opt) { - extended_opt++; - debug_fields(extended_opt); - } - return 1; - break; - case ARG_VERSION: { - boolean insert_into_pastebuf = FALSE; - - if (extended_opt) { - extended_opt++; - if (match_optname(extended_opt, "paste", - 5, FALSE)) { - insert_into_pastebuf = TRUE; - } else { - raw_printf( - "-%sversion can only be extended with -%sversion:paste.\n", - dashdash, dashdash); - return TRUE; - } - } - early_version_info(insert_into_pastebuf); - return 2; - break; + case ARG_DEBUG: + if (extended_opt) { + extended_opt++; + debug_fields(extended_opt); } - default: - break; + return 1; + case ARG_VERSION: { + boolean insert_into_pastebuf = FALSE; + + if (extended_opt) { + extended_opt++; + if (match_optname(extended_opt, "paste", 5, FALSE)) { + insert_into_pastebuf = TRUE; + } else { + raw_printf( + "-%sversion can only be extended with -%sversion:paste.\n", + dashdash, dashdash); + return TRUE; + } + } + early_version_info(insert_into_pastebuf); + return 2; + } + default: + break; } }; return FALSE; @@ -843,7 +841,7 @@ enum earlyarg e_arg; * are documented is right here. No gameplay is altered. * * test - test whether this parser is working - * ttystatus - TTY: + * ttystatus - TTY: * immediateflips - WIN32: turn off display performance * optimization so that display output * can be debugged without buffering. diff --git a/src/botl.c b/src/botl.c index 721ad2316..fde46e2fb 100644 --- a/src/botl.c +++ b/src/botl.c @@ -799,7 +799,7 @@ boolean *valsetlist; * all of the fields when context.botlx is set. The tty port in * particular has a problem if that isn't done, since the core sets * context.botlx when a menu or text display obliterates the status - * line. + * line. * * For those situations, to trigger the full update of every field * whether changed or not, call status_update() with BL_RESET. @@ -817,7 +817,7 @@ boolean *valsetlist; else if ((windowprocs.wincap2 & WC2_FLUSH_STATUS) != 0L) status_update(BL_FLUSH, (genericptr_t) 0, 0, 0, NO_COLOR, &cond_hilites[0]); - + context.botl = context.botlx = 0; update_all = FALSE; } diff --git a/src/do_name.c b/src/do_name.c index b6decaa86..aa688765a 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -175,7 +175,7 @@ const char *goal; } /* disgusting hack; the alternate selection characters work for any getpos call, but only matter for dowhatis (and doquickwhatis) */ - doing_what_is = (goal == what_is_an_unknown_object); + doing_what_is = (goal == what_is_an_unknown_object); if (doing_what_is) { Sprintf(kbuf, "'%s' or '%s' or '%s' or '%s'", visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]), @@ -2071,20 +2071,17 @@ char * rndorcname(s) char *s; { - int i; - const char *v[] = {"a", "ai", "og", "u"}; - const char *snd[] = {"gor", "gris", "un", "bane", "ruk", - "oth","ul", "z", "thos","akh","hai"}; - int vstart = rn2(2); - + static const char *v[] = { "a", "ai", "og", "u" }; + static const char *snd[] = { "gor", "gris", "un", "bane", "ruk", + "oth","ul", "z", "thos","akh","hai" }; + int i, iend = rn1(2, 3), vstart = rn2(2); + if (s) { *s = '\0'; - for (i = 0; i < rn2(2) + 3; ++i) { + for (i = 0; i < iend; ++i) { vstart = 1 - vstart; /* 0 -> 1, 1 -> 0 */ - if (!rn2(30) && i > 0) - (void) strcat(s, "-"); - (void) sprintf(eos(s), "%s", vstart ? v[rn2(SIZE(v))] : - snd[rn2(SIZE(snd))]); + Sprintf(eos(s), "%s%s", (i > 0 && !rn2(30)) ? "-" : "", + vstart ? v[rn2(SIZE(v))] : snd[rn2(SIZE(snd))]); } } return s; diff --git a/src/dog.c b/src/dog.c index 1dc4018b9..e5767103a 100644 --- a/src/dog.c +++ b/src/dog.c @@ -412,7 +412,7 @@ boolean with_you; if (migrating_objs) deliver_obj_to_mon(mtmp, 0, DF_ALL); } - + if (xlocale && wander) { /* monster moved a bit; pick a nearby location */ /* mnearto() deals w/stone, et al */ diff --git a/src/dokick.c b/src/dokick.c index 99858a62f..1bea20ab6 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -1694,7 +1694,7 @@ unsigned long deliverflags; where = (int) (otmp->owornmask & 0x7fffL); /* destination code */ if ((where & MIGR_TO_SPECIES) == 0) continue; - + if ((mtmp->data->mflags2 & otmp->corpsenm) != 0) { obj_extract_self(otmp); otmp->owornmask = 0L; diff --git a/src/dothrow.c b/src/dothrow.c index 5a559ae4e..8dd71a8f2 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1292,7 +1292,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ if ((obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)) || tethered_weapon) { if (rn2(100)) { - if (tethered_weapon) + if (tethered_weapon) tmp_at(DISP_END, BACKTRACK); else sho_obj_return_to_u(obj); /* display its flight */ diff --git a/src/engrave.c b/src/engrave.c index abd531abf..39c4005be 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -690,7 +690,7 @@ doengrave() xcrypt(blengr(), buf); } dengr = TRUE; - } + } break; case WAN_NOTHING: case WAN_UNDEAD_TURNING: diff --git a/src/files.c b/src/files.c index c122c3794..77ff211c8 100644 --- a/src/files.c +++ b/src/files.c @@ -666,7 +666,7 @@ void really_close() { int fd; - + if (lftrack.init) { fd = lftrack.fd; @@ -2156,24 +2156,27 @@ char sep; return (char *) 0; while (*str) { - if (*str == sep) nsep++; - str++; + if (*str == sep) + nsep++; + str++; } csep = rn2(nsep); str = begin; while ((csep > 0) && *str) { - str++; - if (*str == sep) csep--; + str++; + if (*str == sep) + csep--; } if (*str) { - if (*str == sep) str++; - begin = str; - while (*str && *str != sep) { - str++; - len++; - } - *str = '\0'; - if (len) + if (*str == sep) + str++; + begin = str; + while (*str && *str != sep) { + str++; + len++; + } + *str = '\0'; + if (len) return begin; } return (char *) 0; @@ -3582,7 +3585,7 @@ const char *reason; /* explanation */ void testinglog(filenm, type, reason) const char *filenm; /* ad hoc file name */ -const char *type; +const char *type; const char *reason; /* explanation */ { FILE *lfile; diff --git a/src/invent.c b/src/invent.c index 84e6367df..34b784475 100644 --- a/src/invent.c +++ b/src/invent.c @@ -2592,7 +2592,7 @@ long *out_cnt; int unid_cnt; char prompt[QBUFSZ]; - unid_cnt = count_unidentified(invent); + unid_cnt = count_unidentified(invent); Sprintf(prompt, "Debug Identify"); /* 'title' rather than 'prompt' */ if (unid_cnt) Sprintf(eos(prompt), diff --git a/src/makemon.c b/src/makemon.c index ee87d332e..a589d65b7 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1391,8 +1391,8 @@ int mmflags; } if (allow_minvent && migrating_objs) - deliver_obj_to_mon(mtmp, 1, DF_NONE); /* in case there's waiting items */ - + deliver_obj_to_mon(mtmp, 1, DF_NONE); /* in case of waiting items */ + if (!in_mklev) newsym(mtmp->mx, mtmp->my); /* make sure the mon shows up */ diff --git a/src/mhitm.c b/src/mhitm.c index dfff12b26..ba322a8ca 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -782,13 +782,13 @@ struct attack *mattk; /* Kill off aggressor if it didn't die. */ if (!(result & MM_AGR_DIED)) { - boolean was_leashed = (magr->mleashed); + boolean was_leashed = (magr->mleashed != 0); mondead(magr); if (!DEADMONSTER(magr)) return result; /* life saved */ result |= MM_AGR_DIED; - + /* mondead() -> m_detach() -> m_unleash() always suppresses the m_unleash() slack message, so deliver it here instead */ if (was_leashed) diff --git a/src/mkmaze.c b/src/mkmaze.c index be6fcfd7f..1c2aca8da 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -801,11 +801,10 @@ stolen_booty(VOID_ARGS) mtyp = rn2((PM_ORC_SHAMAN - PM_ORC) + 1) + PM_ORC; mtmp = makemon(&mons[mtyp], 0, 0, MM_NONAME); if (mtmp) { - shiny_orc_stuff(mtmp); + shiny_orc_stuff(mtmp); migrate_orc(mtmp, 0UL); } } - ransacked = 0; } diff --git a/src/mon.c b/src/mon.c index 72f3df1a6..49ab5ac6a 100644 --- a/src/mon.c +++ b/src/mon.c @@ -462,7 +462,7 @@ unsigned corpseflags; * underneath it, you could be told the corpse type of a * monster that you never knew was there without this. * The code in hitmu() substitutes the word "something" - * if the corpses obj->dknown is 0. + * if the corpse's obj->dknown is 0. */ if (Blind && !sensemon(mtmp)) obj->dknown = 0; diff --git a/src/monmove.c b/src/monmove.c index fc32ebfb8..5694a31b8 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -255,14 +255,12 @@ struct monst *mon; } } -#define flees_light(mon) ((mon)->data == &mons[PM_GREMLIN] && \ - (uwep && artifact_light(uwep) && uwep->lamplit)) - +#define flees_light(mon) ((mon)->data == &mons[PM_GREMLIN] \ + && (uwep && artifact_light(uwep) && uwep->lamplit)) /* we could include this in the above macro, but probably overkill/overhead */ -/* (!((which_armor((mon), W_ARMC) != 0) && ((which_armor((mon), W_ARMH) != 0))) && */ +/* && (!(which_armor((mon), W_ARMC) != 0 */ +/* && which_armor((mon), W_ARMH) != 0)) */ - - /* monster begins fleeing for the specified time, 0 means untimed flee * if first, only adds fleetime if monster isn't already fleeing * if fleemsg, prints a message about new flight, otherwise, caller should */ diff --git a/src/pager.c b/src/pager.c index 4515ea8e8..c1824d2f8 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1390,7 +1390,7 @@ boolean without_asking; } display_nhwindow(datawin, FALSE); destroy_nhwindow(datawin), datawin = WIN_ERR; - } + } } } @@ -1470,7 +1470,7 @@ doidtrap() commands: basic letters vs digits, 'g' vs 'G' for '5', phone keypad vs normal layout of digits, and QWERTZ keyboard swap between y/Y/^Y/M-y/M-Y/M-^Y and z/Z/^Z/M-z/M-Z/M-^Z.) - + The interpretor understands '&#' for comment, '&? option' for 'if' (also '&? !option' @@ -1481,7 +1481,7 @@ doidtrap() '&:' for 'else' (also '&: #comment'; 0 or 1 instance for a given 'if'), and '&.' for 'endif' (also '&. #comment'; required for each 'if'). - + The option handling is a bit of a mess, with no generality for which options to deal with and only a comma separated list of integer values for the '=value' part. number_pad is the only diff --git a/src/version.c b/src/version.c index 5055e8df6..9b3763841 100644 --- a/src/version.c +++ b/src/version.c @@ -57,7 +57,7 @@ char *buf; Sprintf(eos(buf), " ("); #if defined(RUNTIME_PORT_ID) - tmp = get_port_id(tmpbuf); + tmp = get_port_id(tmpbuf); if (tmp) Sprintf(eos(buf), "%s%s", c++ ? "," : "", tmp); #endif From 39074d29fc157c8eb02c17417a449819d91c7a0b Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 4 Oct 2018 21:49:16 -0400 Subject: [PATCH 08/12] ensure tmp_at() structures are initialized for all code paths when swallowed --- doc/fixes36.2 | 2 ++ src/dothrow.c | 42 ++++++++++++++++++------------------------ 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 8baf780cc..a8258b5e5 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -169,6 +169,8 @@ sortloot segfaulted when filtering a subset of items (seen with 'A' command) orctown: prevent Bad fruit #0 and some minor tuning make long extended commands list be more navigable simplify #wizidentify; don't rely on having bold menu entries +a code path wasn't initializing necessary tmp_at() structures for DISP_TETHER + when you were swallowed tty: turn off an optimization that is the suspected cause of Windows reported partial status lines following level changes tty: ensure that current status fields are always copied to prior status diff --git a/src/dothrow.c b/src/dothrow.c index 8dd71a8f2..81487a5b6 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -571,7 +571,7 @@ int x, y; int ox, oy, *range = (int *) arg; struct obj *obj; struct monst *mon; - boolean may_pass = TRUE, via_jumping, stopping_short; + boolean may_pass = TRUE; struct trap *ttmp; int dmg = 0; @@ -583,8 +583,6 @@ int x, y; } else if (*range == 0) { return FALSE; /* previous step wants to stop now */ } - via_jumping = (EWwalking & I_SPECIAL) != 0L; - stopping_short = (via_jumping && *range < 2); if (!Passes_walls || !(may_pass = may_passwall(x, y))) { boolean odoor_diag = (IS_DOOR(levl[x][y].typ) @@ -664,8 +662,12 @@ int x, y; mon->mundetected = 0; /* wakeup() will handle mimic */ mnam = a_monnam(mon); /* after unhiding */ - pronoun = noit_mhim(mon); + pronoun = mhim(mon); if (!strcmp(mnam, "it")) { + /* mhim() uses pronoun_gender() which forces neuter if monster + can't be seen; we want him/her for humanoid sensed by touch */ + if (!strcmp(pronoun, "it") && humanoid(mon->data)) + pronoun = genders[mon->female].him; mnam = !strcmp(pronoun, "it") ? "something" : "someone"; } if (!glyph_is_monster(glyph) && !glyph_is_invisible(glyph)) @@ -708,17 +710,12 @@ int x, y; vision_recalc(1); /* update for new position */ flush_screen(1); - if (is_pool(x, y) && !u.uinwater) { - if ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) - || !(Levitation || Flying || Wwalking)) { - multi = 0; /* can move, so drown() allows crawling out of water */ - (void) drown(); - return FALSE; - } else if (!Is_waterlevel(&u.uz) && !stopping_short) { - Norep("You move over %s.", an(is_moat(x, y) ? "moat" : "pool")); - } - } else if (is_lava(x, y) && !stopping_short) { - Norep("You move over some lava."); + if (is_pool(x, y) && !u.uinwater + && ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) + || !(Levitation || Flying || Wwalking))) { + multi = 0; /* can move, so drown() allows crawling out of water */ + (void) drown(); + return FALSE; } /* FIXME: @@ -730,9 +727,7 @@ int x, y; * ones that we have not yet tested. */ if ((ttmp = t_at(x, y)) != 0) { - if (stopping_short) { - ; /* see the comment above hurtle_jump() */ - } else if (ttmp->ttyp == MAGIC_PORTAL) { + if (ttmp->ttyp == MAGIC_PORTAL) { dotrap(ttmp, 0); return FALSE; } else if (ttmp->ttyp == VIBRATING_SQUARE) { @@ -740,12 +735,11 @@ int x, y; dotrap(ttmp, 0); /* doesn't print messages */ } else if (ttmp->ttyp == FIRE_TRAP) { dotrap(ttmp, 0); - } else if ((is_pit(ttmp->ttyp) || is_hole(ttmp->ttyp)) + } else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT + || ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR) && Sokoban) { - /* air currents overcome the recoil in Sokoban; - when jumping, caller performs last step and enters trap */ - if (!via_jumping) - dotrap(ttmp, 0); + /* Air currents overcome the recoil */ + dotrap(ttmp, 0); *range = 0; return TRUE; } else { @@ -1292,7 +1286,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ if ((obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)) || tethered_weapon) { if (rn2(100)) { - if (tethered_weapon) + if (tethered_weapon) tmp_at(DISP_END, BACKTRACK); else sho_obj_return_to_u(obj); /* display its flight */ From 2eb8436db2b8a7123857f386a89003aed18c71d4 Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 4 Oct 2018 21:55:01 -0400 Subject: [PATCH 09/12] fix up a bad commit --- src/dothrow.c | 62 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/src/dothrow.c b/src/dothrow.c index 81487a5b6..877740193 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -571,7 +571,7 @@ int x, y; int ox, oy, *range = (int *) arg; struct obj *obj; struct monst *mon; - boolean may_pass = TRUE; + boolean may_pass = TRUE, via_jumping, stopping_short; struct trap *ttmp; int dmg = 0; @@ -583,6 +583,8 @@ int x, y; } else if (*range == 0) { return FALSE; /* previous step wants to stop now */ } + via_jumping = (EWwalking & I_SPECIAL) != 0L; + stopping_short = (via_jumping && *range < 2); if (!Passes_walls || !(may_pass = may_passwall(x, y))) { boolean odoor_diag = (IS_DOOR(levl[x][y].typ) @@ -662,12 +664,8 @@ int x, y; mon->mundetected = 0; /* wakeup() will handle mimic */ mnam = a_monnam(mon); /* after unhiding */ - pronoun = mhim(mon); + pronoun = noit_mhim(mon); if (!strcmp(mnam, "it")) { - /* mhim() uses pronoun_gender() which forces neuter if monster - can't be seen; we want him/her for humanoid sensed by touch */ - if (!strcmp(pronoun, "it") && humanoid(mon->data)) - pronoun = genders[mon->female].him; mnam = !strcmp(pronoun, "it") ? "something" : "someone"; } if (!glyph_is_monster(glyph) && !glyph_is_invisible(glyph)) @@ -710,12 +708,17 @@ int x, y; vision_recalc(1); /* update for new position */ flush_screen(1); - if (is_pool(x, y) && !u.uinwater - && ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) - || !(Levitation || Flying || Wwalking))) { - multi = 0; /* can move, so drown() allows crawling out of water */ - (void) drown(); - return FALSE; + if (is_pool(x, y) && !u.uinwater) { + if ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) + || !(Levitation || Flying || Wwalking)) { + multi = 0; /* can move, so drown() allows crawling out of water */ + (void) drown(); + return FALSE; + } else if (!Is_waterlevel(&u.uz) && !stopping_short) { + Norep("You move over %s.", an(is_moat(x, y) ? "moat" : "pool")); + } + } else if (is_lava(x, y) && !stopping_short) { + Norep("You move over some lava."); } /* FIXME: @@ -727,7 +730,9 @@ int x, y; * ones that we have not yet tested. */ if ((ttmp = t_at(x, y)) != 0) { - if (ttmp->ttyp == MAGIC_PORTAL) { + if (stopping_short) { + ; /* see the comment above hurtle_jump() */ + } else if (ttmp->ttyp == MAGIC_PORTAL) { dotrap(ttmp, 0); return FALSE; } else if (ttmp->ttyp == VIBRATING_SQUARE) { @@ -735,11 +740,12 @@ int x, y; dotrap(ttmp, 0); /* doesn't print messages */ } else if (ttmp->ttyp == FIRE_TRAP) { dotrap(ttmp, 0); - } else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT - || ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR) + } else if ((is_pit(ttmp->ttyp) || is_hole(ttmp->ttyp)) && Sokoban) { - /* Air currents overcome the recoil */ - dotrap(ttmp, 0); + /* air currents overcome the recoil in Sokoban; + when jumping, caller performs last step and enters trap */ + if (!via_jumping) + dotrap(ttmp, 0); *range = 0; return TRUE; } else { @@ -1128,6 +1134,8 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ mon = u.ustuck; bhitpos.x = mon->mx; bhitpos.y = mon->my; + if (tethered_weapon) + tmp_at(DISP_TETHER, obj_to_glyph(obj)); } else if (u.dz) { if (u.dz < 0 /* Mjollnir must we wielded to be thrown--caller verifies this; @@ -1274,19 +1282,27 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ /* missile has already been handled */ if (tethered_weapon) tmp_at(DISP_END, 0); } else if (u.uswallow) { - if (tethered_weapon) + if (tethered_weapon) { tmp_at(DISP_END, 0); - /* ball is not picked up by monster */ - if (obj != uball) - (void) mpickobj(u.ustuck, obj); - thrownobj = (struct obj *) 0; + pline("%s returns to your hand!", The(xname(thrownobj))); + thrownobj = addinv(thrownobj); + (void) encumber_msg(); + if (thrownobj->owornmask & W_QUIVER) /* in case addinv() autoquivered */ + setuqwep((struct obj *) 0); + setuwep(thrownobj); + } else { + /* ball is not picked up by monster */ + if (obj != uball) + (void) mpickobj(u.ustuck, obj); + thrownobj = (struct obj *) 0; + } } else { /* Mjollnir must we wielded to be thrown--caller verifies this; aklys must we wielded as primary to return when thrown */ if ((obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)) || tethered_weapon) { if (rn2(100)) { - if (tethered_weapon) + if (tethered_weapon) tmp_at(DISP_END, BACKTRACK); else sho_obj_return_to_u(obj); /* display its flight */ From 67c80b2e4b33beaa7a6d630df47636c851948a75 Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 4 Oct 2018 22:00:08 -0400 Subject: [PATCH 10/12] Revert "fix up a bad commit" This reverts commit 2eb8436db2b8a7123857f386a89003aed18c71d4. --- src/dothrow.c | 62 +++++++++++++++++++-------------------------------- 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/src/dothrow.c b/src/dothrow.c index 877740193..81487a5b6 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -571,7 +571,7 @@ int x, y; int ox, oy, *range = (int *) arg; struct obj *obj; struct monst *mon; - boolean may_pass = TRUE, via_jumping, stopping_short; + boolean may_pass = TRUE; struct trap *ttmp; int dmg = 0; @@ -583,8 +583,6 @@ int x, y; } else if (*range == 0) { return FALSE; /* previous step wants to stop now */ } - via_jumping = (EWwalking & I_SPECIAL) != 0L; - stopping_short = (via_jumping && *range < 2); if (!Passes_walls || !(may_pass = may_passwall(x, y))) { boolean odoor_diag = (IS_DOOR(levl[x][y].typ) @@ -664,8 +662,12 @@ int x, y; mon->mundetected = 0; /* wakeup() will handle mimic */ mnam = a_monnam(mon); /* after unhiding */ - pronoun = noit_mhim(mon); + pronoun = mhim(mon); if (!strcmp(mnam, "it")) { + /* mhim() uses pronoun_gender() which forces neuter if monster + can't be seen; we want him/her for humanoid sensed by touch */ + if (!strcmp(pronoun, "it") && humanoid(mon->data)) + pronoun = genders[mon->female].him; mnam = !strcmp(pronoun, "it") ? "something" : "someone"; } if (!glyph_is_monster(glyph) && !glyph_is_invisible(glyph)) @@ -708,17 +710,12 @@ int x, y; vision_recalc(1); /* update for new position */ flush_screen(1); - if (is_pool(x, y) && !u.uinwater) { - if ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) - || !(Levitation || Flying || Wwalking)) { - multi = 0; /* can move, so drown() allows crawling out of water */ - (void) drown(); - return FALSE; - } else if (!Is_waterlevel(&u.uz) && !stopping_short) { - Norep("You move over %s.", an(is_moat(x, y) ? "moat" : "pool")); - } - } else if (is_lava(x, y) && !stopping_short) { - Norep("You move over some lava."); + if (is_pool(x, y) && !u.uinwater + && ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) + || !(Levitation || Flying || Wwalking))) { + multi = 0; /* can move, so drown() allows crawling out of water */ + (void) drown(); + return FALSE; } /* FIXME: @@ -730,9 +727,7 @@ int x, y; * ones that we have not yet tested. */ if ((ttmp = t_at(x, y)) != 0) { - if (stopping_short) { - ; /* see the comment above hurtle_jump() */ - } else if (ttmp->ttyp == MAGIC_PORTAL) { + if (ttmp->ttyp == MAGIC_PORTAL) { dotrap(ttmp, 0); return FALSE; } else if (ttmp->ttyp == VIBRATING_SQUARE) { @@ -740,12 +735,11 @@ int x, y; dotrap(ttmp, 0); /* doesn't print messages */ } else if (ttmp->ttyp == FIRE_TRAP) { dotrap(ttmp, 0); - } else if ((is_pit(ttmp->ttyp) || is_hole(ttmp->ttyp)) + } else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT + || ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR) && Sokoban) { - /* air currents overcome the recoil in Sokoban; - when jumping, caller performs last step and enters trap */ - if (!via_jumping) - dotrap(ttmp, 0); + /* Air currents overcome the recoil */ + dotrap(ttmp, 0); *range = 0; return TRUE; } else { @@ -1134,8 +1128,6 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ mon = u.ustuck; bhitpos.x = mon->mx; bhitpos.y = mon->my; - if (tethered_weapon) - tmp_at(DISP_TETHER, obj_to_glyph(obj)); } else if (u.dz) { if (u.dz < 0 /* Mjollnir must we wielded to be thrown--caller verifies this; @@ -1282,27 +1274,19 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ /* missile has already been handled */ if (tethered_weapon) tmp_at(DISP_END, 0); } else if (u.uswallow) { - if (tethered_weapon) { + if (tethered_weapon) tmp_at(DISP_END, 0); - pline("%s returns to your hand!", The(xname(thrownobj))); - thrownobj = addinv(thrownobj); - (void) encumber_msg(); - if (thrownobj->owornmask & W_QUIVER) /* in case addinv() autoquivered */ - setuqwep((struct obj *) 0); - setuwep(thrownobj); - } else { - /* ball is not picked up by monster */ - if (obj != uball) - (void) mpickobj(u.ustuck, obj); - thrownobj = (struct obj *) 0; - } + /* ball is not picked up by monster */ + if (obj != uball) + (void) mpickobj(u.ustuck, obj); + thrownobj = (struct obj *) 0; } else { /* Mjollnir must we wielded to be thrown--caller verifies this; aklys must we wielded as primary to return when thrown */ if ((obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)) || tethered_weapon) { if (rn2(100)) { - if (tethered_weapon) + if (tethered_weapon) tmp_at(DISP_END, BACKTRACK); else sho_obj_return_to_u(obj); /* display its flight */ From 8ce1f88f533304689e4ae3c73c1f970a5c7017fa Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 4 Oct 2018 22:00:51 -0400 Subject: [PATCH 11/12] Revert "ensure tmp_at() structures are initialized for all code paths when swallowed" This reverts commit 39074d29fc157c8eb02c17417a449819d91c7a0b. Bad commit of do_throw --- doc/fixes36.2 | 2 -- src/dothrow.c | 42 ++++++++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index a8258b5e5..8baf780cc 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -169,8 +169,6 @@ sortloot segfaulted when filtering a subset of items (seen with 'A' command) orctown: prevent Bad fruit #0 and some minor tuning make long extended commands list be more navigable simplify #wizidentify; don't rely on having bold menu entries -a code path wasn't initializing necessary tmp_at() structures for DISP_TETHER - when you were swallowed tty: turn off an optimization that is the suspected cause of Windows reported partial status lines following level changes tty: ensure that current status fields are always copied to prior status diff --git a/src/dothrow.c b/src/dothrow.c index 81487a5b6..8dd71a8f2 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -571,7 +571,7 @@ int x, y; int ox, oy, *range = (int *) arg; struct obj *obj; struct monst *mon; - boolean may_pass = TRUE; + boolean may_pass = TRUE, via_jumping, stopping_short; struct trap *ttmp; int dmg = 0; @@ -583,6 +583,8 @@ int x, y; } else if (*range == 0) { return FALSE; /* previous step wants to stop now */ } + via_jumping = (EWwalking & I_SPECIAL) != 0L; + stopping_short = (via_jumping && *range < 2); if (!Passes_walls || !(may_pass = may_passwall(x, y))) { boolean odoor_diag = (IS_DOOR(levl[x][y].typ) @@ -662,12 +664,8 @@ int x, y; mon->mundetected = 0; /* wakeup() will handle mimic */ mnam = a_monnam(mon); /* after unhiding */ - pronoun = mhim(mon); + pronoun = noit_mhim(mon); if (!strcmp(mnam, "it")) { - /* mhim() uses pronoun_gender() which forces neuter if monster - can't be seen; we want him/her for humanoid sensed by touch */ - if (!strcmp(pronoun, "it") && humanoid(mon->data)) - pronoun = genders[mon->female].him; mnam = !strcmp(pronoun, "it") ? "something" : "someone"; } if (!glyph_is_monster(glyph) && !glyph_is_invisible(glyph)) @@ -710,12 +708,17 @@ int x, y; vision_recalc(1); /* update for new position */ flush_screen(1); - if (is_pool(x, y) && !u.uinwater - && ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) - || !(Levitation || Flying || Wwalking))) { - multi = 0; /* can move, so drown() allows crawling out of water */ - (void) drown(); - return FALSE; + if (is_pool(x, y) && !u.uinwater) { + if ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) + || !(Levitation || Flying || Wwalking)) { + multi = 0; /* can move, so drown() allows crawling out of water */ + (void) drown(); + return FALSE; + } else if (!Is_waterlevel(&u.uz) && !stopping_short) { + Norep("You move over %s.", an(is_moat(x, y) ? "moat" : "pool")); + } + } else if (is_lava(x, y) && !stopping_short) { + Norep("You move over some lava."); } /* FIXME: @@ -727,7 +730,9 @@ int x, y; * ones that we have not yet tested. */ if ((ttmp = t_at(x, y)) != 0) { - if (ttmp->ttyp == MAGIC_PORTAL) { + if (stopping_short) { + ; /* see the comment above hurtle_jump() */ + } else if (ttmp->ttyp == MAGIC_PORTAL) { dotrap(ttmp, 0); return FALSE; } else if (ttmp->ttyp == VIBRATING_SQUARE) { @@ -735,11 +740,12 @@ int x, y; dotrap(ttmp, 0); /* doesn't print messages */ } else if (ttmp->ttyp == FIRE_TRAP) { dotrap(ttmp, 0); - } else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT - || ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR) + } else if ((is_pit(ttmp->ttyp) || is_hole(ttmp->ttyp)) && Sokoban) { - /* Air currents overcome the recoil */ - dotrap(ttmp, 0); + /* air currents overcome the recoil in Sokoban; + when jumping, caller performs last step and enters trap */ + if (!via_jumping) + dotrap(ttmp, 0); *range = 0; return TRUE; } else { @@ -1286,7 +1292,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ if ((obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)) || tethered_weapon) { if (rn2(100)) { - if (tethered_weapon) + if (tethered_weapon) tmp_at(DISP_END, BACKTRACK); else sho_obj_return_to_u(obj); /* display its flight */ From c6a5ec1ab63d6f30635012abb8970ad6890e7b2d Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 4 Oct 2018 22:02:28 -0400 Subject: [PATCH 12/12] ensure tmp_at() structures are initialized for all code paths when swallowed --- doc/fixes36.2 | 1 + src/dothrow.c | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 8baf780cc..d458496a1 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -169,6 +169,7 @@ sortloot segfaulted when filtering a subset of items (seen with 'A' command) orctown: prevent Bad fruit #0 and some minor tuning make long extended commands list be more navigable simplify #wizidentify; don't rely on having bold menu entries +ensure tmp_at() structures are initialized for all code paths when swallowed tty: turn off an optimization that is the suspected cause of Windows reported partial status lines following level changes tty: ensure that current status fields are always copied to prior status diff --git a/src/dothrow.c b/src/dothrow.c index 8dd71a8f2..877740193 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1134,6 +1134,8 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ mon = u.ustuck; bhitpos.x = mon->mx; bhitpos.y = mon->my; + if (tethered_weapon) + tmp_at(DISP_TETHER, obj_to_glyph(obj)); } else if (u.dz) { if (u.dz < 0 /* Mjollnir must we wielded to be thrown--caller verifies this; @@ -1280,12 +1282,20 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ /* missile has already been handled */ if (tethered_weapon) tmp_at(DISP_END, 0); } else if (u.uswallow) { - if (tethered_weapon) + if (tethered_weapon) { tmp_at(DISP_END, 0); - /* ball is not picked up by monster */ - if (obj != uball) - (void) mpickobj(u.ustuck, obj); - thrownobj = (struct obj *) 0; + pline("%s returns to your hand!", The(xname(thrownobj))); + thrownobj = addinv(thrownobj); + (void) encumber_msg(); + if (thrownobj->owornmask & W_QUIVER) /* in case addinv() autoquivered */ + setuqwep((struct obj *) 0); + setuwep(thrownobj); + } else { + /* ball is not picked up by monster */ + if (obj != uball) + (void) mpickobj(u.ustuck, obj); + thrownobj = (struct obj *) 0; + } } else { /* Mjollnir must we wielded to be thrown--caller verifies this; aklys must we wielded as primary to return when thrown */