]> granicus.if.org Git - nethack/commitdiff
fix github issue #769 - revive panic
authorPatR <rankin@nethack.org>
Fri, 10 Jun 2022 18:35:07 +0000 (11:35 -0700)
committerPatR <rankin@nethack.org>
Fri, 10 Jun 2022 18:35:07 +0000 (11:35 -0700)
Issue #769, reported by k2 and diagnosed by entrez:  eating a troll
corpse that revives on the last turn of the meal was using up the
corpse while the revival was in progress (unless the hero couldn't
observe the resulting monster), leading to a panic when trying to
use it up at the end of revival.  Brought on by a recent change to
interrupt an occupied hero who can observe a hostile monster being
created nearby.

The fix isn't perfect.  If revival fails because there's no place
to put the revived troll, the meal will be interrupted with one bite
left instead of finishing.  If that happens, the interruption will
include a "you stop eating" message, just with no explanation why.
The partly eaten--almost completely eaten--corpse will remain.

Closes #769

doc/fixes3-7-0.txt
src/eat.c
src/zap.c

index bc9481d83188128c21276f506ea8c86208e19a64..3a3bbb69f7cbbe477f2157e8a3ae402a67f062d2 100644 (file)
@@ -1,4 +1,4 @@
-HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.941 $ $NHDT-Date: 1654717838 2022/06/08 19:50:38 $
+HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.945 $ $NHDT-Date: 1654886097 2022/06/10 18:34:57 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -1244,6 +1244,9 @@ items flagged as just-picked-up were unflagged if you stepped on other items
 activating a magic portal still gave "you feel dizzy for a moment, but the
        sensation passes" after portal traversal was changed to make the hero
        be stunned for a few turns
+after the fix for zombie reviving near hero (which now interrupts hero's
+       occupation), could get "revive panic" when eating a troll corpse if
+       it revived on the same turn that eating the corpse would finish
 
 curses: 'msg_window' option wasn't functional for curses unless the binary
        also included tty support
index b812219ab60c656f318b10b73c89678f7dbe6e30..60e3d11db9a102561817c6579dff29ae27c9bb33 100644 (file)
--- a/src/eat.c
+++ b/src/eat.c
@@ -1,4 +1,4 @@
-/* NetHack 3.7 eat.c   $NHDT-Date: 1653506421 2022/05/25 19:20:21 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.278 $ */
+/* NetHack 3.7 eat.c   $NHDT-Date: 1654886097 2022/06/10 18:34:57 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.281 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -3709,6 +3709,32 @@ maybe_finished_meal(boolean stopping)
     return FALSE;
 }
 
+/* called by revive(); sort of the opposite of maybe_finished_meal() */
+void
+cant_finish_meal(struct obj *corpse)
+{
+    /*
+     * When a corpse gets resurrected, the makemon() for that might
+     * call stop_occupation().  If that happens, prevent it from using
+     * up the corpse via maybe_finished_meal() when there's not enough
+     * left for another bite.  revive() needs continued access to the
+     * corpse and will delete it when done.
+     */
+    if (g.occupation == eatfood && g.context.victual.piece == corpse) {
+        /* normally performed by done_eating() */
+        g.context.victual.piece = (struct obj *) 0;
+        g.context.victual.o_id = 0;
+        g.context.victual.fullwarn = g.context.victual.eating =
+            g.context.victual.doreset = FALSE;
+
+        if (!corpse->oeaten)
+            corpse->oeaten = 1; /* [see consume_oeaten()] */
+        g.occupation = donull; /* any non-Null other than eatfood() */
+        stop_occupation();
+        newuhs(FALSE);
+    }
+}
+
 /* Tin of <something> to the rescue?  Decide whether current occupation
    is an attempt to eat a tin of something capable of saving hero's life.
    We don't care about consumption of non-tinned food here because special
index f713fb7c0405878e9432f7a4674ffcbe8b499072..52a0558e2c0492fc2e7bf6d945cbfc98d21a2eb1 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -1,4 +1,4 @@
-/* NetHack 3.7 zap.c   $NHDT-Date: 1654881021 2022/06/10 17:10:21 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.425 $ */
+/* NetHack 3.7 zap.c   $NHDT-Date: 1654886101 2022/06/10 18:35:01 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.426 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2013. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -804,6 +804,10 @@ revive(struct obj *corpse, boolean by_hero)
         impossible("Attempting to revive %s?", xname(corpse));
         return (struct monst *) 0;
     }
+    /* if this corpse is being eaten, stop doing that; this should be done
+       after makemon() succeeds and skipped if it fails, but waiting until
+       we know the result for that would be too late */
+    cant_finish_meal(corpse);
 
     x = y = 0;
     if (corpse->where != OBJ_CONTAINED) {