From: PatR Date: Wed, 16 Jun 2021 01:42:30 +0000 (-0700) Subject: fix bullwhip-induced panic X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f6e60c75168f4e50ea45cb39fd6816ee149b4a09;p=nethack fix bullwhip-induced panic While testing some corpse/statue name manipulation changes I managed to trigger a panic during end-of-game cleanup. Using a bullwhip to snatch a wielded cockatrice corpse from a monster's inventory into the hero's inventory and being turned to stone due to lack of gloves took the corpse out of the monster's inventory but didn't place it anywhere. If no life-saving took place, it led to an "obj_is_local" panic during timer cleanup when freeing the level. This patch includes some of the stuff I've been testing rather than just the fix for the panic (which is the very last bit of the diff). --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index a17c28c47..569d57726 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.568 $ $NHDT-Date: 1623282330 2021/06/09 23:45:30 $ +NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.571 $ $NHDT-Date: 1623807747 2021/06/16 01:42:27 $ General Fixes and Modified Features ----------------------------------- @@ -542,6 +542,9 @@ change attendant (healer quest) monster from lawful to neutral quit is not longer bound to M-q change default value of autopickup to off and color to on resurrected corpse of mon could end up with different gender from original mon +using a bullwhip to snatch a wielded cockatrice corpse from a monster when not + wearing gloves and without life-saving could trigger "obj_is_local" + panic during final cleanup Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/apply.c b/src/apply.c index 4a149cc3f..c39d02b0f 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 apply.c $NHDT-Date: 1621387861 2021/05/19 01:31:01 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.344 $ */ +/* NetHack 3.7 apply.c $NHDT-Date: 1623807747 2021/06/16 01:42:27 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.345 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -271,7 +271,7 @@ its_dead(int rx, int ry, int *resp) humanoid(mptr) ? "person" : "creature"); what = buf; } else { - what = pmname(mptr, NEUTRAL); + what = obj_pmname(statue); if (!type_is_pname(mptr)) what = The(what); } @@ -1920,6 +1920,7 @@ static void use_tinning_kit(struct obj *obj) { struct obj *corpse, *can; + struct permonst *mptr; /* This takes only 1 move. If this is to be changed to take many * moves, we've got to deal with decaying corpses... @@ -1934,29 +1935,28 @@ use_tinning_kit(struct obj *obj) You("cannot tin %s which is partly eaten.", something); return; } - if (touch_petrifies(&mons[corpse->corpsenm]) && !Stone_resistance - && !uarmg) { + mptr = &mons[corpse->corpsenm]; + if (touch_petrifies(mptr) && !Stone_resistance && !uarmg) { char kbuf[BUFSZ]; + const char *corpse_name = an(cxname(corpse)); - if (poly_when_stoned(g.youmonst.data)) - You("tin %s without wearing gloves.", - an(mons[corpse->corpsenm].pmnames[NEUTRAL])); - else { + if (poly_when_stoned(g.youmonst.data)) { + You("tin %s without wearing gloves.", corpse_name); + } else { pline("Tinning %s without wearing gloves is a fatal mistake...", - an(mons[corpse->corpsenm].pmnames[NEUTRAL])); - Sprintf(kbuf, "trying to tin %s without gloves", - an(mons[corpse->corpsenm].pmnames[NEUTRAL])); + corpse_name); + Sprintf(kbuf, "trying to tin %s without gloves", corpse_name); } instapetrify(kbuf); } - if (is_rider(&mons[corpse->corpsenm])) { + if (is_rider(mptr)) { if (revive_corpse(corpse)) verbalize("Yes... But War does not preserve its enemies..."); else pline_The("corpse evades your grasp."); return; } - if (mons[corpse->corpsenm].cnutrit == 0) { + if (mptr->cnutrit == 0) { pline("That's too insubstantial to tin."); return; } @@ -2141,7 +2141,7 @@ fig_transform(anything *arg, long timeout) char monnambuf[BUFSZ], carriedby[BUFSZ]; if (!figurine) { - debugpline0("null figurine in fig_transform()"); + impossible("null figurine in fig_transform()"); return; } silent = (timeout != g.monstermoves); /* happened while away */ @@ -2908,10 +2908,18 @@ use_whip(struct obj *obj) && polymon(PM_STONE_GOLEM))) { char kbuf[BUFSZ]; - Sprintf(kbuf, "%s corpse", - an(mons[otmp->corpsenm].pmnames[NEUTRAL])); + Strcpy(kbuf, (otmp->quan == 1L) ? an(onambuf) + : onambuf); pline("Snatching %s is a fatal mistake.", kbuf); + /* corpse probably has a rot timer but is now + OBJ_FREE; end of game cleanup will panic if + it isn't part of current level; plus it would + be missing from bones, so put it on the floor */ + place_object(otmp, u.ux, u.uy); /* but don't stack */ + instapetrify(kbuf); + /* life-saved; free the corpse again */ + obj_extract_self(otmp); } (void) hold_another_object(otmp, "You drop %s!", doname(otmp), (const char *) 0);