From 128ed0f0beee6034d9f15daf3896f01ffd33b362 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Tue, 6 Feb 2007 04:35:50 +0000 Subject: [PATCH] fix #Q117 - vomiting by rodents & more From a bug report: you could vomit when polymorphed into a rat but real life rats can't/don't vomit. The latter was confirmed by and . While testing a fix for this, I discovered a couple of other problems. Healing magic which cured sickness failed to heal Vomiting (potion or spell; unicorn horn deals with them separately). Enlightenment failed to report Vomiting (it's not shown on the status line). Most significant was that vomiting_dialogue() called vomit() twice (also make_confused() and make_stunned() three times for every once intended). It was dividing the remaining turns by 3 and then using that value to decide what to do, but only message display took into account that the same divided value would occur on 3 consecutive turns (or just 2 for the final countdown to 0, because dialog routine gets called before timed-property decrement). --- doc/fixes34.4 | 4 ++++ include/extern.h | 1 + src/cmd.c | 3 ++- src/eat.c | 9 +++++++-- src/mondata.c | 15 ++++++++++++++- src/potion.c | 9 ++++++--- src/timeout.c | 38 +++++++++++++++++++++++--------------- 7 files changed, 57 insertions(+), 22 deletions(-) diff --git a/doc/fixes34.4 b/doc/fixes34.4 index 56813781e..b35687bcc 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -303,6 +303,10 @@ a magic portal could be rendered inactive for the hero if a successful hangup save took place during level change; leaving the level by any means other than triggering the portal would reactivate it hero wasn't allowed to affix candles to the candelabrum while underwater +non-unicorn horn healing magic which cures sickness now also cures vomiting +vomiting/nauseated state is included in enlightenment feedback +vomiting countdown actually triggered the final vomit code twice +rats aren't capable of vomiting Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 9a5703eba..b4cd47610 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1316,6 +1316,7 @@ E boolean FDECL(can_track, (struct permonst *)); E boolean FDECL(breakarm, (struct permonst *)); E boolean FDECL(sliparm, (struct permonst *)); E boolean FDECL(sticks, (struct permonst *)); +E boolean FDECL(cantvomit, (struct permonst *)); E int FDECL(num_horns, (struct permonst *)); /* E boolean FDECL(canseemon, (struct monst *)); */ E struct attack *FDECL(dmgtype_fromattack, (struct permonst *,int,int)); diff --git a/src/cmd.c b/src/cmd.c index e5fcd0a3e..2e76f1c4d 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)cmd.c 3.5 2007/01/12 */ +/* SCCS Id: @(#)cmd.c 3.5 2007/02/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1105,6 +1105,7 @@ int final; /* 0 => still in progress; 1 => over, survived; 2 => dead */ if (Stoned) you_are("turning to stone",""); if (Slimed) you_are("turning into slime",""); if (Strangled) you_are((u.uburied) ? "buried" : "being strangled",""); + if (Vomiting) you_are("nauseated",""); if (Glib) { Sprintf(buf, "slippery %s", makeplural(body_part(FINGER))); you_have(buf,""); diff --git a/src/eat.c b/src/eat.c index 1e5299106..3cef6fc7a 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)eat.c 3.5 2007/01/24 */ +/* SCCS Id: @(#)eat.c 3.5 2007/02/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2853,7 +2853,12 @@ floorfood(verb,corpsecheck) /* get food from floor or pack */ void vomit() /* A good idea from David Neves */ { - make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE); + if (cantvomit(youmonst.data)) + /* doesn't cure food poisoning; message assumes that we aren't + dealing with some esoteric body_part() */ + Your("jaw gapes convulsively."); + else + make_sick(0L, (char *)0, TRUE, SICK_VOMITABLE); nomul(-2); nomovemsg = You_can_move_again; } diff --git a/src/mondata.c b/src/mondata.c index e4d34d9ba..479c86817 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mondata.c 3.5 2006/11/24 */ +/* SCCS Id: @(#)mondata.c 3.5 2007/02/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -335,6 +335,19 @@ sticks(ptr) /* creature sticks other creatures it hits */ attacktype(ptr,AT_HUGS))); } +boolean +cantvomit(ptr) +struct permonst *ptr; +{ + /* rats and mice are incapable of vomitting; + which other creatures have the same limitation? */ + if (ptr->mlet == S_RODENT && + ptr != &mons[PM_ROCK_MOLE] && + ptr != &mons[PM_WOODCHUCK]) + return TRUE; + return FALSE; +} + /* number of horns this type of monster has on its head */ int num_horns(ptr) diff --git a/src/potion.c b/src/potion.c index 06b184940..f00b36270 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)potion.c 3.5 2006/11/29 */ +/* SCCS Id: @(#)potion.c 3.5 2007/02/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -988,8 +988,11 @@ healup(nhp, nxtra, curesick, cureblind) if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra); } } - if(cureblind) make_blinded(0L,TRUE); - if(curesick) make_sick(0L, (char *) 0, TRUE, SICK_ALL); + if (cureblind) make_blinded(0L, TRUE); + if (curesick) { + make_vomiting(0L, TRUE); + make_sick(0L, (char *)0, TRUE, SICK_ALL); + } context.botl = 1; return; } diff --git a/src/timeout.c b/src/timeout.c index 0a73ad204..56f03e5a6 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)timeout.c 3.5 2006/07/08 */ +/* SCCS Id: @(#)timeout.c 3.5 2007/02/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -64,27 +64,35 @@ static NEARDATA const char * const vomiting_texts[] = { STATIC_OVL void vomiting_dialogue() { - register long i = (Vomiting & TIMEOUT) / 3L; + const char *txt = 0; + long v = (Vomiting & TIMEOUT); - if ((((Vomiting & TIMEOUT) % 3L) == 2) && (i >= 0) - && (i < SIZE(vomiting_texts))) - You(vomiting_texts[SIZE(vomiting_texts) - i - 1]); - - switch ((int) i) { - case 0: - stop_occupation(); - morehungry(20); - vomit(); - break; - case 2: + /* note: nhtimeout() hasn't decremented timed properties for the + current turn yet, so we use Vomiting-1 here */ + switch ((int)(v - 1L)) { + case 14: txt = vomiting_texts[0]; break; + case 11: txt = vomiting_texts[1]; break; + case 6: make_stunned(HStun + d(2,4), FALSE); if (!Popeye(VOMITING)) stop_occupation(); - /* fall through */ - case 3: + /*FALLTHRU*/ + case 9: make_confused(HConfusion + d(2,4), FALSE); if (multi > 0) nomul(0); break; + case 8: txt = vomiting_texts[2]; break; + case 5: txt = vomiting_texts[3]; break; + case 2: txt = vomiting_texts[4]; + if (cantvomit(youmonst.data)) txt = "gag uncontrolably."; + break; + case 0: + stop_occupation(); + if (!cantvomit(youmonst.data)) morehungry(20); + vomit(); + break; + default: break; } + if (txt) You("%s", txt); exercise(A_CON, FALSE); }