prayer fix for being in poison gas cloud region

Like stuck-in-wall, there might not be any place to move the hero
in order to escape a poison gas cloud.  That could result in "fix
all troubles" becoming stuck in a loop.  3.6.something fixed the
stuck-in-wall case by temporarily conferring Passes_walls.  Fix the
in-poison-region case by temporarily conferring Magical_breathing.

Not adequately tested...

I don't think that this fixes "#K4252: NH 3.7 Prayer Bug" where the
game hung during a couple out of scores of prayers.  I didn't see
any other fix-trouble cases that seemed likely to remain unfixed
and end up with repair attempts retrying.
This commit is contained in:
PatR
2024-09-25 01:01:17 -07:00
parent da8ba281a4
commit 2471306112
3 changed files with 69 additions and 9 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 timeout.c $NHDT-Date: 1723580900 2024/08/13 20:28:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.190 $ */
/* NetHack 3.7 timeout.c $NHDT-Date: 1727251273 2024/09/25 08:01:13 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.193 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -56,6 +56,8 @@ static const struct propname {
/* timed pass-walls is a potential prayer result if surrounded by stone
with nowhere to be safely teleported to */
{ PASSES_WALLS, "pass thru walls" },
/* likewise for magical breathing vs poison gas regions */
{ MAGICAL_BREATHING, "magical breathing" },
/* timed fire resistance and water walking are possible in explore mode
(as well as in wizard mode) after life-saving in lava if it fails to
teleport the hero to safety and player declines to die */
@@ -92,7 +94,6 @@ static const struct propname {
{ TELEPORT_CONTROL, "teleport control" },
{ FLYING, "flying" },
{ SWIMMING, "swimming" },
{ MAGICAL_BREATHING, "magical breathing" },
{ SLOW_DIGESTION, "slow digestion" },
{ HALF_SPDAM, "half spell damage" },
{ HALF_PHDAM, "half physical damage" },
@@ -534,7 +535,33 @@ phaze_dialogue(void)
return;
if (((HPasses_walls & TIMEOUT) % 2L) && i > 0L && i <= SIZE(phaze_texts))
pline1(phaze_texts[SIZE(phaze_texts) - i]);
pline("%s", phaze_texts[SIZE(phaze_texts) - i]);
}
/* Similar to Passes_walls, if prayer tries to save hero from a poison
gas region but can't, (HMagical_breathing & TIMEOUT) will be set to
a small value. Unlike Passes_walls, there's no joke message. */
static NEARDATA const char *const region_texts[] = {
"You seem to have some trouble breathing.",
"The air here seems foul.",
};
staticfn void
region_dialogue(void)
{
boolean breathless, in_poison_gas_cloud;
long r = (HMagical_breathing & TIMEOUT), i = r / 2L;
/* might have poly'd into non-breather or moved out of gas cloud */
HMagical_breathing &= ~TIMEOUT;
breathless = breathless(&mons[u.umonnum]);
in_poison_gas_cloud = region_danger();
HMagical_breathing |= r;
if (breathless || !in_poison_gas_cloud)
return;
if ((r % 2L) && i > 0L && i <= SIZE(region_texts))
pline("%s", region_texts[SIZE(region_texts) - i]);
}
/* when a status timeout is fatal, keep the status line indicator shown
@@ -600,6 +627,8 @@ nh_timeout(void)
levitation_dialogue();
if (HPasses_walls & TIMEOUT)
phaze_dialogue();
if (HMagical_breathing & TIMEOUT)
region_dialogue();
if (HSleepy & TIMEOUT)
sleep_dialogue();
if (u.mtimedone && !--u.mtimedone) {
@@ -844,6 +873,13 @@ nh_timeout(void)
!Upolyd ? "normal" : "unusual");
}
break;
case MAGICAL_BREATHING:
if (!Breathless) {
if (region_danger())
You("cough%s",
Poison_resistance ? "." : " and spit blood!");
}
break;
case STRANGLED:
svk.killer.format = KILLED_BY;
Strcpy(svk.killer.name,