]> granicus.if.org Git - nethack/commitdiff
fix bullwhip-induced panic
authorPatR <rankin@nethack.org>
Wed, 16 Jun 2021 01:42:30 +0000 (18:42 -0700)
committerPatR <rankin@nethack.org>
Wed, 16 Jun 2021 01:42:30 +0000 (18:42 -0700)
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).

doc/fixes37.0
src/apply.c

index a17c28c470df4282c335c808d3e92be4653a00bf..569d577268d7c04768b35debd3ac50911cd3abdf 100644 (file)
@@ -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
index 4a149cc3f66d7b7fa5ea73b0c1104da0ea6e6c4c..c39d02b0fa58b25a551e4a6d281e9169914ac903 100644 (file)
@@ -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);