From 191db348ec907a72babd848bc615947734c77635 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Tue, 1 Feb 2005 03:46:31 +0000 Subject: [PATCH] stop occupation during problem countdown A user recently complained that he started an activity such as searching and specified a repeat count, right after getting--and not realizing the significance of--the first message in the countdown sequence for turning into stone. He suggested that subsequent messages interrupt multi-turn activity so that the player has a chance to do something to prevent imminent death. This implements that, with the added wrinkle that it won't interrupt if the activity is something that might save the character's life: attempting to eat a tin that is either sure to help (if ID'd as food that cures stoning) or a desparate gamble (if unID'd). Some hooks for similar behavior for other conditions like turning into slime are included, although no tins can help for anything other than petrification so far. Shouldn't fatal illness have an end-is-near countdown too? --- doc/fixes34.4 | 1 + include/extern.h | 1 + src/eat.c | 38 ++++++++++++++++++++++++++++++++++++++ src/timeout.c | 28 +++++++++++++++++++++++----- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/doc/fixes34.4 b/doc/fixes34.4 index 30eae3532..e898b22eb 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -82,6 +82,7 @@ adding more candles than required to total 7 to a candelabrum which give correct message when a spellcasting monster summons other monsters correct experience calculation for monsters that cause nonphysical damage monsters evading a kick on noteleport levels would cause a "teleports" message +interrupt current activity during certain stages of petrification or vomiting Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index d42b34ae8..6ca4c6092 100644 --- a/include/extern.h +++ b/include/extern.h @@ -570,6 +570,7 @@ E void FDECL(consume_oeaten, (struct obj *,int)); E boolean FDECL(maybe_finished_meal, (BOOLEAN_P)); E void FDECL(set_tin_variety, (struct obj *,int)); E int FDECL(tin_variety_txt, (char *,int *)); +E boolean FDECL(Popeye, (int)); /* ### end.c ### */ diff --git a/src/eat.c b/src/eat.c index 9790ba900..a4a6c583b 100644 --- a/src/eat.c +++ b/src/eat.c @@ -2652,4 +2652,42 @@ boolean stopping; return 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 + effects there take place on first bite rather than at end of occupation. + [Popeye the Sailor gets out of trouble by eating tins of spinach. :-] */ +boolean +Popeye(threat) +int threat; +{ + struct obj *otin; + int mndx; + + if (occupation != opentin) return FALSE; + otin = context.tin.tin; + /* make sure hero still has access to tin */ + if (!carried(otin) && !obj_here(otin, u.ux, u.uy)) return FALSE; + /* unknown tin is assumed to be helpful */ + if (!otin->known) return TRUE; + /* known tin is helpful if it will stop life-threatening problem */ + mndx = otin->corpsenm; + switch (threat) { + /* note: not used; hunger code bypasses stop_occupation() when eating */ + case HUNGER: + return (mndx != NON_PM || otin->spe == 1); + /* flesh from lizards and acidic critters stops petrification */ + case STONED: + return (mndx >= LOW_PM && (mndx == PM_LIZARD || acidic(&mons[mndx]))); + /* no tins can cure these (yet?) */ + case SLIMED: + case SICK: + case VOMITING: + break; + default: + break; + } + return FALSE; +} + /*eat.c*/ diff --git a/src/timeout.c b/src/timeout.c index a458ca7d3..24434a78d 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)timeout.c 3.5 2003/11/18 */ +/* SCCS Id: @(#)timeout.c 3.5 2005/01/31 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -30,10 +30,24 @@ stoned_dialogue() if (i > 0L && i <= SIZE(stoned_texts)) pline(stoned_texts[SIZE(stoned_texts) - i]); - if (i == 5L) + switch ((int) i) { + case 5: /* slowing down */ HFast = 0L; - if (i == 3L) - nomul(-3); + if (multi > 0) nomul(0); + break; + case 4: /* limbs stiffening */ + /* just one move left to save oneself so quit fiddling around; + don't stop attempt to eat tin--might be lizard or acidic */ + if (!Popeye(STONED)) stop_occupation(); + if (multi > 0) nomul(0); + break; + case 3: /* limbs turned to stone */ + stop_occupation(); + nomul(-3); /* can't move anymore */ + break; + default: + break; + } exercise(A_DEX, FALSE); } @@ -59,12 +73,16 @@ vomiting_dialogue() case 0: vomit(); morehungry(20); + stop_occupation(); + if (multi > 0) nomul(0); break; case 2: make_stunned(HStun + d(2,4), FALSE); + if (!Popeye(VOMITING)) stop_occupation(); /* fall through */ case 3: make_confused(HConfusion + d(2,4), FALSE); + if (multi > 0) nomul(0); break; } exercise(A_CON, FALSE); @@ -134,7 +152,7 @@ slime_dialogue() } if (i == 3L) { /* limbs becoming oozy */ HFast = 0L; /* lose intrinsic speed */ - stop_occupation(); + if (!Popeye(SLIMED)) stop_occupation(); if (multi > 0) nomul(0); } exercise(A_DEX, FALSE);