From 29f21b488cdaec8d397a0b8fc8b02b984d400faf Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Thu, 20 Nov 2003 04:54:39 +0000 Subject: [PATCH] stethoscope use on corpses & statues (trunk only) Prompted by the report that it was possible to check a corpse at an adjacent spot while levitating: substantially revamp the handling of applying a stethoscope to corpses and/or statues. Aside from the missing reachability check, the old code suffered from grammar problems when multiple corpses were present and it didn't try to figure out the gender of the monster who left the corpse. This now lets non-healers check corpses and statues at any time (previously that only worked for them while hallucinating). For healers it gives some new feedback: when listening to a corpse, they'll be given a hint if it (actually any corpse in the pile at that location) is going to revive, and when listening to a statue they'll be given a hint if it contains any items. The existing hint when a statue is actually a trap is still only given to healers. --- doc/fixes34.3 | 1 + doc/fixes35.0 | 1 + src/apply.c | 126 ++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 103 insertions(+), 25 deletions(-) diff --git a/doc/fixes34.3 b/doc/fixes34.3 index d512ca23c..ac8898e91 100644 --- a/doc/fixes34.3 +++ b/doc/fixes34.3 @@ -92,6 +92,7 @@ silver items such as wands avoided all the silver checks in hmon_hitmon() resuming an interrupted 'A' command could cause crash if pending worn item(s) were stolen or destroyed when you're asleep you shouldn't "notice" monsters that have become undetected +must be able to reach floor in order to use stethoscope on corpse or statue Platform- and/or Interface-Specific Fixes diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 985e30a9c..eec9d25dd 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -50,6 +50,7 @@ healers notice when a wand of undead turning revives a monster so the update display if bestowed a spellbook while unable to see invisible self use small pool of static buffers for mon_nam() and Monnam() Acknowledge Schroedinger's cat at end of game +grammar fixes for applying stethoscope to corpses and statues Platform- and/or Interface-Specific Fixes diff --git a/src/apply.c b/src/apply.c index 95f5b2468..2e95d1d0f 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)apply.c 3.4 2003/10/21 */ +/* SCCS Id: @(#)apply.c 3.4 2003/11/18 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -163,34 +163,110 @@ STATIC_OVL boolean its_dead(rx, ry, resp) int rx, ry, *resp; { - struct obj *otmp; - struct trap *ttmp; + char buf[BUFSZ]; + boolean more_corpses; + struct permonst *mptr; + struct obj *corpse = sobj_at(CORPSE, rx, ry), + *statue = sobj_at(STATUE, rx, ry); - /* additional stethoscope messages from jyoung@apanix.apana.org.au */ - if (Hallucination && sobj_at(CORPSE, rx, ry)) { - /* (a corpse doesn't retain the monster's sex, - so we're forced to use generic pronoun here) */ - You_hear("a voice say, \"It's dead, Jim.\""); - *resp = 1; - return TRUE; - } else if (Role_if(PM_HEALER) && ((otmp = sobj_at(CORPSE, rx, ry)) != 0 || - (otmp = sobj_at(STATUE, rx, ry)) != 0)) { - /* possibly should check uppermost {corpse,statue} in the pile - if both types are present, but it's not worth the effort */ - if (vobj_at(rx, ry)->otyp == STATUE) otmp = vobj_at(rx, ry); - if (otmp->otyp == CORPSE) { - You("determine that %s unfortunate being is dead.", - (rx == u.ux && ry == u.uy) ? "this" : "that"); + if (!can_reach_floor()) { /* levitation or unskilled riding */ + corpse = 0; /* can't reach corpse on floor */ + /* you can't reach tiny statues (even though you can fight + tiny monsters while levitating--consistency, what's that?) */ + while (statue && mons[statue->corpsenm].msize == MZ_TINY) + statue = nxtobj(statue, STATUE, TRUE); + } + /* when both corpse and statue are present, pick the uppermost one */ + if (corpse && statue) { + if (nxtobj(statue, CORPSE, TRUE) == corpse) + corpse = 0; /* corpse follows statue; ignore it */ + else + statue = 0; /* corpse precedes statue; ignore statue */ + } + more_corpses = (corpse && nxtobj(corpse, CORPSE, TRUE)); + + /* additional stethoscope messages from jyoung@apanix.apana.org.au */ + if (!corpse && !statue) { + ; /* nothing to do */ + + } else if (Hallucination) { + if (!corpse) { + /* it's a statue */ + Strcpy(buf, "You're both stoned"); + } else if (corpse->quan == 1L && !more_corpses) { + int gndr = 2; /* neuter: "it" */ + struct monst *mtmp = get_mtraits(corpse, FALSE); + + /* (most corpses don't retain the monster's sex, so + we're usually forced to use generic pronoun here) */ + if (mtmp) { + mptr = &mons[mtmp->mnum]; + /* can't use mhe() here; it calls pronoun_gender() which + expects monster to be on the map (visibility check) */ + if ((humanoid(mptr) || (mptr->geno & G_UNIQ) || + type_is_pname(mptr)) && !is_neuter(mptr)) + gndr = (int)mtmp->female; } else { - ttmp = t_at(rx, ry); - pline("%s appears to be in %s health for a statue.", - The(mons[otmp->corpsenm].mname), - (ttmp && ttmp->ttyp == STATUE_TRAP) ? - "extraordinary" : "excellent"); + mptr = &mons[corpse->corpsenm]; + if (is_female(mptr)) gndr = 1; + else if (is_male(mptr)) gndr = 0; } - return TRUE; + Sprintf(buf, "%s's dead", genders[gndr].he); /* "he"/"she"/"it" */ + buf[0] = highc(buf[0]); + } else { /* plural */ + Strcpy(buf, "They're dead"); } - return FALSE; + /* variations on "He's dead, Jim." (Star Trek's Dr McCoy) */ + You_hear("a voice say, \"%s, Jim.\"", buf); + *resp = 1; + return TRUE; + + } else if (corpse) { + boolean here = (rx == u.ux && ry == u.uy), + one = (corpse->quan == 1L && !more_corpses), + reviver = FALSE; + + if (Role_if(PM_HEALER)) { + /* ok to reset `corpse' here; we're done with it */ + do { + if (obj_has_timer(corpse, REVIVE_MON)) + reviver = TRUE; + else + corpse = nxtobj(corpse, CORPSE, TRUE); + } while (corpse && !reviver); + } + You("determine that %s unfortunate being%s %s%s dead.", + one ? (here ? "this" : "that") : (here ? "these" : "those"), + one ? "" : "s", one ? "is" : "are", + reviver ? " mostly" : ""); + return TRUE; + + } else { /* statue */ + const char *what, *how; + + mptr = &mons[statue->corpsenm]; + if (Blind) { /* ignore statue->dknown; it'll always be set */ + Sprintf(buf, "%s %s", + (rx == u.ux && ry == u.uy) ? "This" : "That", + humanoid(mptr) ? "person" : "creature"); + what = buf; + } else { + what = mptr->mname; + if (!type_is_pname(mptr)) what = The(what); + } + how = "fine"; + if (Role_if(PM_HEALER)) { + struct trap *ttmp = t_at(rx, ry); + + if (ttmp && ttmp->ttyp == STATUE_TRAP) how = "extraordinary"; + else if (Has_contents(statue)) how = "remarkable"; + } + + pline("%s is in %s health for a statue.", what, how); + return TRUE; + + } + return FALSE; /* no corpse or statue */ } static const char hollow_str[] = "a hollow sound. This must be a secret %s!";