From e2d694ed32959c7d3f8a36e03948fa64cb922532 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 10 Jun 2022 11:35:07 -0700 Subject: [PATCH] fix github issue #769 - revive panic 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 | 5 ++++- src/eat.c | 28 +++++++++++++++++++++++++++- src/zap.c | 6 +++++- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index bc9481d83..3a3bbb69f 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -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 diff --git a/src/eat.c b/src/eat.c index b812219ab..60e3d11db 100644 --- 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 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 diff --git a/src/zap.c b/src/zap.c index f713fb7c0..52a0558e2 100644 --- 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) { -- 2.50.1