From 858e9ce00d3fda6fbee3263972591d742ea7e861 Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 28 Oct 2018 16:03:42 -0700 Subject: [PATCH] fix github issue #148 - life-save while swallowed Life-saving was setting u.uswldtim to 0, presumably intending that to stop the hero from being digested, but it actually resulted in being totally digested on the swallower's next turn if the death being short-circuited wasn't digestion. Change life-saving to make swallower or grabber release the hero instead of tinkering with u.uswldtim. In addition to rescuing the hero from digestion, it prevents an eel which has just drowned the hero (who has survived drowning via life-saving) from pulling him/her back into the water on its next turn. It will need to make another successful grab to do that now. While testing, I noticed that if I was polymorphed and wearing an amulet of unchanging, life-saving didn't restore my HP-as-a-monster and due to the recent change to force that to 0 when the hero dies, I died again immediately after my life was saved. So this bug was latent in the past and became noticeable in the last couple of days. --- doc/fixes36.2 | 2 ++ src/end.c | 36 +++++++++++++++++++++++++++--------- src/mhitu.c | 10 ++++++++-- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index fa28f3768..fce3cb275 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -191,6 +191,7 @@ 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 trapped-vs-levitation/flying change broke Sting releasing hero from web +life-saving while poly'd and Unchanging wasn't restoring u.mh (HP as monster) 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 @@ -274,6 +275,7 @@ make mine town "orctown" variation a multiple level feature of the mines replace #monpolycontrol command with monpolycontrol boolean option replace #wizdebug_traveldisplay command with travel_debug boolean option rename #wizdebug_bury command to #wizbury +life-saving now makes swallower or grabber release hero Code Cleanup and Reorganization diff --git a/src/end.c b/src/end.c index 2d9c754c7..c423fbcde 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 end.c $NHDT-Date: 1539804880 2018/10/17 19:34:40 $ $NHDT-Branch: keni-makedefsm $:$NHDT-Revision: 1.146 $ */ +/* NetHack 3.6 end.c $NHDT-Date: 1540767809 2018/10/28 23:03:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.148 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -851,7 +851,8 @@ int how; if (u.uhpmax < uhpmin) u.uhpmax = uhpmin; u.uhp = u.uhpmax; - u.uswldtim = 0; + if (Upolyd) /* Unchanging, or death which bypasses losing hit points */ + u.mh = u.mhmax; if (u.uhunger < 500) { u.uhunger = 500; newuhs(FALSE); @@ -877,6 +878,16 @@ int how; curs_on_u(); if (!context.mon_moving) endmultishot(FALSE); + if (u.uswallow) { + /* might drop hero onto a trap that kills her all over again */ + expels(u.ustuck, u.ustuck->data, TRUE); + } else if (u.ustuck) { + if (Upolyd && sticks(youmonst.data)) + You("release %s.", mon_nam(u.ustuck)); + else + pline("%s releases you.", Monnam(u.ustuck)); + unstuck(u.ustuck); + } } /* @@ -1006,13 +1017,16 @@ void done(how) int how; { + boolean survive = FALSE; + if (how == TRICKED) { if (killer.name[0]) { paniclog("trickery", killer.name); - killer.name[0] = 0; + killer.name[0] = '\0'; } if (wizard) { You("are a very tricky wizard, it seems."); + killer.format = KILLED_BY_AN; /* reset to 0 */ return; } } @@ -1064,20 +1078,24 @@ int how; if (how == GENOCIDED) { pline("Unfortunately you are still genocided..."); } else { - killer.name[0] = 0; - killer.format = 0; - return; + survive = TRUE; } } - if ((wizard || discover) && (how <= GENOCIDED) + /* explore and wizard modes offer player the option to keep playing */ + if (!survive && (wizard || discover) && how <= GENOCIDED && !paranoid_query(ParanoidDie, "Die?")) { pline("OK, so you don't %s.", (how == CHOKING) ? "choke" : "die"); savelife(how); - killer.name[0] = 0; - killer.format = 0; + survive = TRUE; + } + + if (survive) { + killer.name[0] = '\0'; + killer.format = KILLED_BY_AN; /* reset to 0 */ return; } really_done(how); + /*NOTREACHED*/ } /* separated from done() in order to specify the __noreturn__ attribute */ diff --git a/src/mhitu.c b/src/mhitu.c index f3fecbd92..85293d57b 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mhitu.c $NHDT-Date: 1513297347 2017/12/15 00:22:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.149 $ */ +/* NetHack 3.6 mhitu.c $NHDT-Date: 1540767817 2018/10/28 23:03:37 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.159 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1956,11 +1956,17 @@ struct attack *mattk; if (tmp) stop_occupation(); - if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) { + if (!u.uswallow) { + ; /* life-saving has already expelled swallowed hero */ + } else if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) { pline("%s very hurriedly %s you!", Monnam(mtmp), is_animal(mtmp->data) ? "regurgitates" : "expels"); expels(mtmp, mtmp->data, FALSE); } else if (!u.uswldtim || youmonst.data->msize >= MZ_HUGE) { + /* 3.6.2: u.uswldtim used to be set to 0 by life-saving but it + expels now so the !u.uswldtim case is no longer possible; + however, polymorphing into a huge form while already + swallowed is still possible */ You("get %s!", is_animal(mtmp->data) ? "regurgitated" : "expelled"); if (flags.verbose && (is_animal(mtmp->data)