From 95a6c458bc9bbc2b76d6700f1f2269b4eb4f811e Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 5 Dec 2018 01:45:16 -0800 Subject: [PATCH] fix #H6292 - green slime & genocide Report suggested that if hero is turning into green slime, genociding green slime should cure it. I went another direction: if life-saved while dying due to turning into green slime, you survive polymorphed into green slime form. If green slimes have been genocided (probably after becoming infected with slime or hero wouldn't have faced any slimes to cause infection, but that could be from eating a glob of green slime created prior to genocide, or from #wizintrinsic), you'll immediately die again, this time from genocide. --- doc/fixes36.2 | 1 + src/end.c | 16 +++++++++---- src/timeout.c | 66 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 4073cef20..f87856d44 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -242,6 +242,7 @@ level change after being interruped locking or unlocking a container might access freed memory if a restore attempt failed and a new game was started instead, it would use stale context from old game if restoration got far enough to load that +if hero survives turning into slime (life-saving), survive as a green slime Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/end.c b/src/end.c index a433acc07..cbc312598 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 end.c $NHDT-Date: 1542798619 2018/11/21 11:10:19 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.152 $ */ +/* NetHack 3.6 end.c $NHDT-Date: 1544003110 2018/12/05 09:45:10 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.156 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1184,7 +1184,12 @@ int how; u.ugrave_arise = (NON_PM - 2); /* leave no corpse */ else if (how == STONING) u.ugrave_arise = (NON_PM - 1); /* statue instead of corpse */ - else if (how == TURNED_SLIME) + else if (how == TURNED_SLIME + /* it's possible to turn into slime even though green slimes + have been genocided: genocide could occur after hero is + already infected or hero could eat a glob of one created + before genocide; don't try to arise as one if they're gone */ + && !(mvitals[PM_GREEN_SLIME].mvflags & G_GENOD)) u.ugrave_arise = PM_GREEN_SLIME; if (how == QUIT) { @@ -1310,11 +1315,14 @@ int how; } } - if (u.ugrave_arise >= LOW_PM && u.ugrave_arise != PM_GREEN_SLIME) { + if (u.ugrave_arise >= LOW_PM) { /* give this feedback even if bones aren't going to be created, so that its presence or absence doesn't tip off the player to new bones or their lack; it might be a lie if makemon fails */ - Your("body rises from the dead as %s...", + Your("%s as %s...", + (u.ugrave_arise != PM_GREEN_SLIME) + ? "body rises from the dead" + : "revenant persists", an(mons[u.ugrave_arise].mname)); display_nhwindow(WIN_MESSAGE, FALSE); } diff --git a/src/timeout.c b/src/timeout.c index 110aa03ad..e4347c5b3 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 timeout.c $NHDT-Date: 1541902953 2018/11/11 02:22:33 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.84 $ */ +/* NetHack 3.6 timeout.c $NHDT-Date: 1544003111 2018/12/05 09:45:11 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.87 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -11,6 +11,7 @@ STATIC_DCL void NDECL(vomiting_dialogue); STATIC_DCL void NDECL(choke_dialogue); STATIC_DCL void NDECL(levitation_dialogue); STATIC_DCL void NDECL(slime_dialogue); +STATIC_DCL void FDECL(slimed_to_death, (struct kinfo *)); STATIC_DCL void NDECL(slip_or_trip); STATIC_DCL void FDECL(see_lamp_flicker, (struct obj *, const char *)); STATIC_DCL void FDECL(lantern_message, (struct obj *)); @@ -357,6 +358,57 @@ burn_away_slime() } } +/* countdown timer for turning into green slime has run out; kill our hero */ +STATIC_OVL void +slimed_to_death(kptr) +struct kinfo *kptr; +{ + /* redundant: polymon() cures sliming when polying into green slime */ + if (Upolyd && youmonst.data == &mons[PM_GREEN_SLIME]) { + dealloc_killer(kptr); + return; + } + /* more sure killer reason is set up */ + if (kptr && kptr->name[0]) { + killer.format = kptr->format; + Strcpy(killer.name, kptr->name); + } else { + killer.format = NO_KILLER_PREFIX; + Strcpy(killer.name, "turned into green slime"); + } + dealloc_killer(kptr); + /* involuntarily break "never changed form" conduct */ + u.uconduct.polyselfs++; + done(TURNED_SLIME); + + /* life-saved; even so, hero still has turned into green slime; + player may have genocided green slimes after being infected */ + if ((mvitals[PM_GREEN_SLIME].mvflags & G_GENOD) != 0) { + killer.format = KILLED_BY; + Strcpy(killer.name, "slimicide"); + /* immediately follows "OK, so you don't die." */ + pline("Yes, you do. Green slime has been genocided..."); + done(GENOCIDED); + /* could be life-saved again (only in explore or wizard mode) + but green slimes are gone; just stay in current form */ + + /* not geno'd; survive as a green slime */ + } else { + /* this part of polyself() isn't in polymon(); + we assume that green slimes don't emit light */ + if (emits_light(youmonst.data)) + del_light_source(LS_MONSTER, monst_to_any(&youmonst)); + /* undo the 'involuntarily break "never changed form"' + increment so that this change isn't counted twice */ + u.uconduct.polyselfs--; + /* can't be Unchanging even if life-saving wasn't due to amulet; + hero infected with slime wouldn't have turned into green slime + to get here if Unchanging */ + (void) polymon(PM_GREEN_SLIME); + } + return; +} + /* Intrinsic Passes_walls is temporary when your god is trying to fix all troubles and then TROUBLE_STUCK_IN_WALL calls safe_teleds() but it can't find anywhere to place you. If that happens you get a small @@ -469,17 +521,7 @@ nh_timeout() done(STONING); break; case SLIMED: - if (kptr && kptr->name[0]) { - killer.format = kptr->format; - Strcpy(killer.name, kptr->name); - } else { - killer.format = NO_KILLER_PREFIX; - Strcpy(killer.name, "turned into green slime"); - } - dealloc_killer(kptr); - /* involuntarily break "never changed form" conduct */ - u.uconduct.polyselfs++; - done(TURNED_SLIME); + slimed_to_death(kptr); /* done(TURNED_SLIME) */ break; case VOMITING: make_vomiting(0L, TRUE); -- 2.40.0