From: nethack.rankin Date: Fri, 30 Dec 2005 06:08:20 +0000 (+0000) Subject: corpse_xname overhaul (trunk only) X-Git-Tag: MOVE2GIT~1174 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=40dd6072330db729d0969672d74874e3fa861a1c;p=nethack corpse_xname overhaul (trunk only) Extend the capabilities of corpse_xname() so that various callers can be simplified. It can how handle an article prefix, effectively turning it into corpse_doname() (not quite; still need doname() to see a count when quantity is more than one, or to see bless/curse state). It can also handle inclusion of adjectives like "partly eaten" or "bite-covered". For unique monsters those come out in the form the Chromatic Dragon's partly eaten corpse instead of the old partly eaten Chromatic Dragon corpse [so wishing probably needs to be taught about potentially finding a monster name before assorted adjectives such as blessed; also, name_to_mon() needs to learn how to cope with the possessive suffix]. A sizeable chunk of this patch deals with consolidating some of the redundant "petrified by a cockatrice corpse" handling. It may be possible to consolidate all remaining instances together since they're quite similar, but I didn't think about that until just now and I want to get this patch over with. --- diff --git a/include/extern.h b/include/extern.h index 2ec40316e..ff9d4a4ef 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1428,7 +1428,7 @@ E boolean FDECL(the_unique_obj, (struct obj *)); E boolean FDECL(the_unique_pm, (struct permonst *)); E char *FDECL(doname, (struct obj *)); E boolean FDECL(not_fully_identified, (struct obj *)); -E char *FDECL(corpse_xname, (struct obj *,BOOLEAN_P)); +E char *FDECL(corpse_xname, (struct obj *,const char *,unsigned)); E char *FDECL(cxname, (struct obj *)); E char *FDECL(killer_xname, (struct obj *)); E const char *FDECL(singular, (struct obj *,char *(*)(OBJ_P))); diff --git a/include/hack.h b/include/hack.h index d6600798f..1ae17d998 100644 --- a/include/hack.h +++ b/include/hack.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)hack.h 3.5 2005/03/28 */ +/* SCCS Id: @(#)hack.h 3.5 2005/12/10 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -76,6 +76,15 @@ #define COST_BITE 13 /* start eating food */ #define COST_OPEN 14 /* open tin */ +/* bitmask flags for corpse_xname(); + PFX_THE takes precedence over ARTICLE, NO_PFX takes precedence over both */ +#define CXN_NORMAL 0 /* no special handling */ +#define CXN_SINGULAR 1 /* override quantity if greather than 1 */ +#define CXN_NO_PFX 2 /* suppress "the" from "the Unique Monst */ +#define CXN_PFX_THE 4 /* prefix with "the " (unless pname) */ +#define CXN_ARTICLE 8 /* include a/an/the prefix */ +#define CXN_NOCORPSE 16 /* suppress " corpse" suffix */ + /* * This is the way the game ends. If these are rearranged, the arrays * in end.c and topten.c will need to be changed. Some parts of the diff --git a/src/dig.c b/src/dig.c index 08a2a5001..c3d26e5d9 100644 --- a/src/dig.c +++ b/src/dig.c @@ -1538,7 +1538,8 @@ long timeout; /* unused */ y = obj->oy; } else if (in_invent) { if (flags.verbose) { - char *cname = corpse_xname(obj, FALSE); + char *cname = corpse_xname(obj, (const char *)0, CXN_NO_PFX); + Your("%s%s %s away%c", obj == uwep ? "wielded " : nul, cname, otense(obj, "rot"), obj == uwep ? '!' : '.'); diff --git a/src/do.c b/src/do.c index 4986b1747..02206ffa7 100644 --- a/src/do.c +++ b/src/do.c @@ -1486,28 +1486,29 @@ struct obj *corpse; struct monst *mtmp, *mcarry; boolean is_uwep, chewed; xchar where; - char *cname, cname_buf[BUFSZ]; + char cname[BUFSZ]; struct obj *container = (struct obj *)0; int container_where = 0; where = corpse->where; - is_uwep = corpse == uwep; - cname = eos(strcpy(cname_buf, "bite-covered ")); - Strcpy(cname, corpse_xname(corpse, TRUE)); + is_uwep = (corpse == uwep); + chewed = (corpse->oeaten != 0); + Strcpy(cname, corpse_xname(corpse, + chewed ? "bite-covered" : (const char *)0, + CXN_SINGULAR)); mcarry = (where == OBJ_MINVENT) ? corpse->ocarry : 0; if (where == OBJ_CONTAINED) { - struct monst *mtmp2 = (struct monst *)0; + struct monst *mtmp2; + container = corpse->ocontainer; - mtmp2 = get_container_location(container, &container_where, (int *)0); + mtmp2 = get_container_location(container, &container_where, (int *)0); /* container_where is the outermost container's location even if nested */ if (container_where == OBJ_MINVENT && mtmp2) mcarry = mtmp2; } mtmp = revive(corpse, FALSE); /* corpse is gone if successful */ if (mtmp) { - chewed = (mtmp->mhp < mtmp->mhpmax); - if (chewed) cname = cname_buf; /* include "bite-covered" prefix */ switch (where) { case OBJ_INVENT: if (is_uwep) diff --git a/src/do_wear.c b/src/do_wear.c index eff0abea3..d7de101f9 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -422,7 +422,7 @@ boolean voluntary; /* taking gloves off on purpose? */ if (touch_petrifies(&mons[obj->corpsenm]) && !Stone_resistance) { You("now wield %s in your bare %s.", - the(corpse_xname(obj, TRUE)), + corpse_xname(obj, (const char *)0, CXN_ARTICLE), makeplural(body_part(HAND))); Sprintf(kbuf, "%s gloves while wielding %s", voluntary ? "removing" : "losing", diff --git a/src/dokick.c b/src/dokick.c index 6c86d60e0..c76c871f2 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -432,16 +432,20 @@ xchar x, y; return(1); } - if(kickobj->otyp == CORPSE && touch_petrifies(&mons[kickobj->corpsenm]) - && !Stone_resistance && !uarmf) { - You("kick the %s with your bare %s.", - corpse_xname(kickobj, TRUE), makeplural(body_part(FOOT))); - if (!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) { + if (!uarmf && kickobj->otyp == CORPSE && + touch_petrifies(&mons[kickobj->corpsenm]) && + !Stone_resistance) { + You("kick %s with your bare %s.", + corpse_xname(kickobj, (const char *)0, CXN_PFX_THE), + makeplural(body_part(FOOT))); + if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) { + ; /* hero has been transformed but kick continues */ + } else { You("turn to stone..."); killer.format = KILLED_BY; - /* KMH -- otmp should be kickobj */ - Sprintf(killer.name, "kicking %s without boots", - an(corpse_xname(kickobj, TRUE))); + /* normalize body shape here; foot, not body_part(FOOT) */ + Sprintf(killer.name, "kicking %s barefoot", + killer_xname(kickobj)); done(STONING); } } diff --git a/src/dothrow.c b/src/dothrow.c index 024201022..038822327 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -91,11 +91,16 @@ int shotlimit; return(0); } u_wipe_engr(2); - if (!uarmg && !Stone_resistance && (obj->otyp == CORPSE && - touch_petrifies(&mons[obj->corpsenm]))) { - You("throw the %s corpse with your bare %s.", - mons[obj->corpsenm].mname, body_part(HAND)); - Sprintf(killer.name, "%s corpse", an(mons[obj->corpsenm].mname)); + if (!uarmg && obj->otyp == CORPSE && + touch_petrifies(&mons[obj->corpsenm]) && + !Stone_resistance) { + You("throw %s with your bare %s.", + corpse_xname(obj, (const char *)0, CXN_PFX_THE), + /* throwing with one hand, but pluralize since the + expression "with your bare hands" sounds better */ + makeplural(body_part(HAND))); + Sprintf(killer.name, "throwing %s bare-handed", + killer_xname(obj)); instapetrify(killer.name); } if (welded(obj)) { diff --git a/src/eat.c b/src/eat.c index 064c9aedc..a48d767c9 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)eat.c 3.5 2005/09/27 */ +/* SCCS Id: @(#)eat.c 3.5 2005/12/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -163,7 +163,7 @@ eatmdone() /* called after mimicing is over */ return 0; } -/* ``[the(] singular(food, xname) [)]'' with awareness of unique monsters */ +/* ``[the(] singular(food, xname) [)]'' */ STATIC_OVL const char * food_xname(food, the_pfx) struct obj *food; @@ -172,18 +172,17 @@ boolean the_pfx; const char *result; int mnum = food->corpsenm; - if (food->otyp == CORPSE && (mons[mnum].geno & G_UNIQ)) { - /* grab xname()'s modifiable return buffer for our own use */ - char *bufp = xname(food); - Sprintf(bufp, "%s%s corpse", - (the_pfx && !type_is_pname(&mons[mnum])) ? "the " : "", - s_suffix(mons[mnum].mname)); - result = bufp; + if (food->otyp == CORPSE) { + result = corpse_xname(food, (const char *)0, + CXN_SINGULAR | (the_pfx ? CXN_PFX_THE : 0)); + /* not strictly needed since pname values are capitalized + and the() is a no-op for them */ + if (type_is_pname(&mons[food->corpsenm])) the_pfx = FALSE; } else { /* the ordinary case */ result = singular(food, xname); - if (the_pfx) result = the(result); } + if (the_pfx) result = the(result); return result; } @@ -227,17 +226,8 @@ choke(food) /* To a full belly all food is bad. (It.) */ if (food->oclass == COIN_CLASS) { Strcpy(killer.name, "very rich meal"); } else { - Strcpy(killer.name, food_xname(food, FALSE)); - if (food->otyp == CORPSE && - (mons[food->corpsenm].geno & G_UNIQ)) { - if (!type_is_pname(&mons[food->corpsenm])) - Strcpy(killer.name, the(killer.name)); - killer.format = KILLED_BY; - } else if (obj_is_pname(food)) { - killer.format = KILLED_BY; - if (food->oartifact >= ART_ORB_OF_DETECTION) - Strcpy(killer.name, the(killer.name)); - } + killer.format = KILLED_BY; + Strcpy(killer.name, killer_xname(food)); } } else { You("choke over it."); @@ -1269,8 +1259,8 @@ opentin() /* called during each move whilst opening a tin */ what = rndmonnam(); } else { what = mons[mnum].mname; - if (mons[mnum].geno & G_UNIQ) - which = type_is_pname(&mons[mnum]) ? 1 : 2; + if (the_unique_pm(&mons[mnum])) which = 2; + else if (type_is_pname(&mons[mnum])) which = 1; } if (which == 0) what = makeplural(what); @@ -1463,7 +1453,6 @@ eatcorpse(otmp) /* called when a corpse is selected as food */ { int tp = 0, mnum = otmp->corpsenm; long rotted = 0L; - boolean uniq = !!(mons[mnum].geno & G_UNIQ); int retcode = 0; boolean stoneable = (flesh_petrifies(&mons[mnum]) && !Stone_resistance && @@ -1490,20 +1479,15 @@ eatcorpse(otmp) /* called when a corpse is selected as food */ if (Sick_resistance) { pline("It doesn't seem at all sickening, though..."); } else { - char buf[BUFSZ]; long sick_time; sick_time = (long) rn1(10, 10); /* make sure new ill doesn't result in improvement */ if (Sick && (sick_time > Sick)) sick_time = (Sick > 1L) ? Sick - 1L : 1L; - if (!uniq) - Sprintf(buf, "rotted %s", corpse_xname(otmp,TRUE)); - else - Sprintf(buf, "%s%s rotted corpse", - !type_is_pname(&mons[mnum]) ? "the " : "", - s_suffix(mons[mnum].mname)); - make_sick(sick_time, buf, TRUE, SICK_VOMITABLE); + make_sick(sick_time, + corpse_xname(otmp, "rotted", CXN_NORMAL), + TRUE, SICK_VOMITABLE); } if (carried(otmp)) useup(otmp); else useupf(otmp, 1L); @@ -1552,7 +1536,8 @@ eatcorpse(otmp) /* called when a corpse is selected as food */ pline("This tastes just like chicken!"); } else { pline("%s%s %s!", - !uniq ? "This " : !type_is_pname(&mons[mnum]) ? "The " : "", + type_is_pname(&mons[mnum]) ? "" : + the_unique_pm(&mons[mnum]) ? "The " : "This ", food_xname(otmp, FALSE), (vegan(&mons[mnum]) ? (!carnivorous(youmonst.data) && herbivorous(youmonst.data)) : diff --git a/src/objnam.c b/src/objnam.c index 0fa55a9b5..caede5d1a 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -592,6 +592,10 @@ register struct obj *obj; if(obj->quan != 1L) Sprintf(prefix, "%ld ", obj->quan); + else if (obj->otyp == CORPSE) + /* skip article prefix for corpses [else corpse_xname() + would have to be taught how to strip it off again] */ + *prefix = '\0'; else if (obj_is_pname(obj) || the_unique_obj(obj)) { if (!strncmpi(bp, "the ", 4)) bp += 4; @@ -750,16 +754,9 @@ ring: if (obj->oeaten) Strcat(prefix, "partly eaten "); if (obj->otyp == CORPSE) { - if (the_unique_pm(&mons[omndx]) || - type_is_pname(&mons[omndx])) { - Sprintf(prefix, "%s%s ", - the_unique_pm(&mons[omndx]) ? "the " : "", - s_suffix(mons[omndx].mname)); - if (obj->oeaten) Strcat(prefix, "partly eaten "); - } else { - Strcat(prefix, mons[omndx].mname); - Strcat(prefix, " "); - } + Sprintf(prefix, "%s ", + corpse_xname(obj, prefix, + CXN_ARTICLE|CXN_NOCORPSE)); } else if (obj->otyp == EGG) { #if 0 /* corpses don't tell if they're stale either */ if (obj->known && stale_egg(obj)) @@ -868,41 +865,92 @@ register struct obj *otmp; } char * -corpse_xname(otmp, ignore_oquan) +corpse_xname(otmp, adjective, cxn_flags) struct obj *otmp; -boolean ignore_oquan; /* to force singular */ +const char *adjective; +unsigned cxn_flags; /* bitmask of CXN_xxx values */ { char *nambuf = nextobuf(); int omndx = otmp->corpsenm; + boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0, + /* suppress "the" from "the unique monster corpse" */ + no_prefix = (cxn_flags & CXN_NO_PFX) != 0, + /* include "the" for "the woodchuck corpse */ + the_prefix = (cxn_flags & CXN_PFX_THE) != 0, + /* include "an" for "an ogre corpse */ + any_prefix = (cxn_flags & CXN_ARTICLE) != 0, + /* leave off suffix (do_name() appends "corpse" itself) */ + omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0, + possessive = FALSE; const char *mname; - if (omndx == NON_PM) return strcpy(nambuf, "thing"); /* paranoia */ - + if (omndx == NON_PM) { /* paranoia */ + mname = "thing"; /* [Possible enhancement: check whether corpse has monster traits attached in order to use priestname() for priests and minions.] */ - if (omndx == PM_ALIGNED_PRIEST) { + } else if (omndx == PM_ALIGNED_PRIEST) { /* avoid "aligned priest"; it just exposes internal details */ mname = "priest"; } else { mname = mons[omndx].mname; - if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) + if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) { mname = s_suffix(mname); + possessive = TRUE; + /* don't precede personal name like "Medusa" with an article */ + if (type_is_pname(&mons[omndx])) + no_prefix = TRUE; + /* always precede non-personal unique monster name like + "Oracle" with "the" unless explicitly overridden */ + else if (the_unique_pm(&mons[omndx]) && !no_prefix) + the_prefix = TRUE; + } } - Sprintf(nambuf, "%s corpse", mname); + if (no_prefix) the_prefix = any_prefix = FALSE; + else if (the_prefix) any_prefix = FALSE; /* mutually exclusive */ - if (ignore_oquan || otmp->quan < 2) - return nambuf; - else - return makeplural(nambuf); + *nambuf = '\0'; + /* can't use the() the way we use an() below because any capitalized + Name causes it to assume a personal name and return Name as-is; + that's usually the behavior wanted, but here we need to force "the" + to precede capitalized unique monsters (pnames are handled above) */ + if (the_prefix) Strcat(nambuf, "the "); + + if (!adjective || !*adjective) { + /* normal case: newt corpse */ + Strcat(nambuf, mname); + } else { + /* adjective positioning depends upon format of monster name */ + if (possessive) /* Medusa's cursed partly eaten corpse */ + Sprintf(eos(nambuf), "%s %s", mname, adjective); + else /* cursed partly eaten troll corpse */ + Sprintf(eos(nambuf), "%s %s", adjective, mname); + /* in case adjective has a trailing space, squeeze it out */ + mungspaces(nambuf); + /* doname() might include a count in the adjective argument; + if so, don't prepend an article */ + if (digit(*adjective)) any_prefix = FALSE; + } + + if (!omit_corpse) { + Strcat(nambuf, " corpse"); + /* makeplural(nambuf) => append "s" to "corpse" */ + if (otmp->quan > 1L && !ignore_quan) Strcat(nambuf, "s"); + } + + /* it's safe to overwrite our nambuf after an() has copied + its old value into another buffer */ + if (any_prefix) Strcpy(nambuf, an(nambuf)); + + return nambuf; } -/* xname, unless it's a corpse, then corpse_xname(obj, FALSE) */ +/* xname doesn't include monster type for "corpse"; cxname does */ char * cxname(obj) struct obj *obj; { if (obj->otyp == CORPSE) - return corpse_xname(obj, FALSE); + return corpse_xname(obj, (const char *)0, CXN_NORMAL); return xname(obj); } @@ -941,10 +989,7 @@ struct obj *obj; /* format the object */ if (obj->otyp == CORPSE) { buf = nextobuf(); - Sprintf(buf, "%s%s", - /* can't use the(); capitalized name blocks its article */ - the_unique_pm(&mons[obj->corpsenm]) ? "the " : "", - corpse_xname(obj, FALSE)); + Strcpy(buf, corpse_xname(obj, (const char *)0, CXN_NORMAL)); } else if (obj->otyp == SLIME_MOLD) { /* concession to "most unique deaths competition" in the annual devnull tournament, suppress player supplied fruit names because diff --git a/src/pickup.c b/src/pickup.c index 08b131245..049ad7383 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pickup.c 3.5 2005/11/02 */ +/* SCCS Id: @(#)pickup.c 3.5 2005/12/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -16,6 +16,7 @@ STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *, STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *, const char *,struct obj *,BOOLEAN_P,int *)); #endif +STATIC_DCL boolean FDECL(fatal_corpse_mistake, (struct obj *,BOOLEAN_P)); STATIC_DCL void FDECL(check_here, (BOOLEAN_P)); STATIC_DCL boolean FDECL(n_or_more, (struct obj *)); STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *)); @@ -262,6 +263,27 @@ ask_again: return TRUE; } +/* check whether hero is bare-handedly touching a cockatrice corpse */ +STATIC_OVL boolean +fatal_corpse_mistake(obj, remotely) +struct obj *obj; +boolean remotely; +{ + if (uarmg || remotely || obj->otyp != CORPSE || + !touch_petrifies(&mons[obj->corpsenm]) || Stone_resistance) + return FALSE; + + if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) { + display_nhwindow(WIN_MESSAGE, FALSE); /* --More-- */ + return FALSE; + } + + pline("Touching %s is a fatal mistake.", + corpse_xname(obj, (const char *)0, CXN_SINGULAR|CXN_ARTICLE)); + instapetrify(killer_xname(obj)); + return TRUE; +} + /* look at the objects at our location, unless there are too many of them */ STATIC_OVL void check_here(picked_some) @@ -1307,18 +1329,8 @@ boolean telekinesis; /* not picking it up directly by hand */ return 1; #endif } else if (obj->otyp == CORPSE) { - if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg - && !Stone_resistance && !telekinesis) { - if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) - display_nhwindow(WIN_MESSAGE, FALSE); - else { - char kbuf[BUFSZ]; - - Strcpy(kbuf, an(corpse_xname(obj, TRUE))); - pline("Touching %s is a fatal mistake.", kbuf); - instapetrify(kbuf); - return -1; - } + if (fatal_corpse_mistake(obj, telekinesis)) { + return -1; } else if (is_rider(&mons[obj->corpsenm])) { pline("At your %s, the corpse suddenly moves...", telekinesis ? "attempted acquisition" : "touch"); @@ -1823,21 +1835,7 @@ register struct obj *obj; if (uquiver) return 0; /* unwielded, died, rewielded */ } - if (obj->otyp == CORPSE) { - if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg - && !Stone_resistance) { - if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) - display_nhwindow(WIN_MESSAGE, FALSE); - else { - char kbuf[BUFSZ]; - - Strcpy(kbuf, an(corpse_xname(obj, TRUE))); - pline("Touching %s is a fatal mistake.", kbuf); - instapetrify(kbuf); - return -1; - } - } - } + if (fatal_corpse_mistake(obj, FALSE)) return -1; /* boxes, boulders, and big statues can't fit into any container */ if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER || @@ -1946,21 +1944,7 @@ register struct obj *obj; if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0; - if (obj->otyp == CORPSE) { - if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg - && !Stone_resistance) { - if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) - display_nhwindow(WIN_MESSAGE, FALSE); - else { - char kbuf[BUFSZ]; - - Strcpy(kbuf, an(corpse_xname(obj, TRUE))); - pline("Touching %s is a fatal mistake.", kbuf); - instapetrify(kbuf); - return -1; - } - } - } + if (fatal_corpse_mistake(obj, FALSE)) return -1; count = obj->quan; if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0) diff --git a/src/uhitm.c b/src/uhitm.c index feb78cd55..a237e6668 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -753,13 +753,12 @@ int thrown; #endif case CORPSE: /* fixed by polder@cs.vu.nl */ if (touch_petrifies(&mons[obj->corpsenm])) { - static const char withwhat[] = "corpse"; tmp = 1; hittxt = TRUE; - You("hit %s with %s %s.", mon_nam(mon), - obj->dknown ? the(mons[obj->corpsenm].mname) : - an(mons[obj->corpsenm].mname), - (obj->quan > 1L) ? makeplural(withwhat) : withwhat); + You("hit %s with %s.", mon_nam(mon), + corpse_xname(obj, (const char *)0, + obj->dknown ? CXN_PFX_THE : CXN_ARTICLE)); + obj->dknown = 1; if (!munstone(mon, TRUE)) minstapetrify(mon, TRUE); if (resists_ston(mon)) break; @@ -1215,28 +1214,20 @@ STATIC_OVL boolean theft_petrifies(otmp) struct obj *otmp; { - const char *fmt; - char *p, cbuf[BUFSZ], kbuf[BUFSZ]; - if (uarmg || otmp->otyp != CORPSE || - !touch_petrifies(&mons[otmp->corpsenm])) return FALSE; + !touch_petrifies(&mons[otmp->corpsenm]) || Stone_resistance) + return FALSE; - /* stealing this corpse is fatal... */ - Strcpy(cbuf, cxname(otmp)); /* "cockatrice corpse" */ - fmt = "a stolen %s"; - if (otmp->quan > 1L) { - /* stack of multiple cockatrice corpses; no article for plural */ - fmt += 2; /* skip "a ", leaving "stolen %s" */ - } else if ((p = strstri(cbuf, "'s corpse")) != 0 || - (p = strstri(cbuf, "s' corpse")) != 0) { - /* in case a unique monster with petrifying touch and - a personal name ever gets introduced: we want to use - "Foo's stolen corpse" instead of "a stolen Foo's corpse" */ - *(p + 2) = '\0'; /* chop " corpse" off of cbuf */ - fmt = "%s stolen corpse"; + /* no poly_when_stoned() critter has theft capability */ +#if 0 + if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) { + display_nhwindow(WIN_MESSAGE, FALSE); /* --More-- */ + return TRUE; } - Sprintf(kbuf, fmt, cbuf); - instapetrify(kbuf); +#endif + + /* stealing this corpse is fatal... */ + instapetrify(corpse_xname(otmp, "stolen", CXN_ARTICLE)); /* apparently wasn't fatal after all... */ return TRUE; } @@ -1246,12 +1237,6 @@ struct obj *otmp; * * If the target is wearing body armor, take all of its possesions; * otherwise, take one object. [Is this really the behavior we want?] - * - * This routine implicitly assumes that there is no way to be able to - * resist petfication (ie, be polymorphed into a xorn or golem) at the - * same time as being able to steal (poly'd into nymph or succubus). - * If that ever changes, the check for touching a cockatrice corpse - * will need to be smarter about whether to break out of the theft loop. */ STATIC_OVL void steal_it(mdef, mattk) @@ -1801,7 +1786,7 @@ register struct attack *mattk; /* engulfing a cockatrice or digesting a Rider or Medusa */ fatal_gulp = (touch_petrifies(pd) && !Stone_resistance) || (mattk->adtyp == AD_DGST && (is_rider(pd) || - ((pd == &mons[PM_MEDUSA]) && !Stone_resistance))); + (pd == &mons[PM_MEDUSA] && !Stone_resistance))); if ((mattk->adtyp == AD_DGST && !Slow_digestion) || fatal_gulp) { /* KMH, conduct */ diff --git a/src/wield.c b/src/wield.c index 05d695083..9a45a76b5 100644 --- a/src/wield.c +++ b/src/wield.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wield.c 3.5 2005/04/15 */ +/* SCCS Id: @(#)wield.c 3.5 2005/12/26 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -50,6 +50,7 @@ */ +STATIC_DCL boolean FDECL(cant_wield_corpse, (struct obj *)); STATIC_DCL int FDECL(ready_weapon, (struct obj *)); /* used by will_weld() */ @@ -112,6 +113,25 @@ register struct obj *obj; update_inventory(); } +STATIC_OVL boolean +cant_wield_corpse(obj) +struct obj *obj; +{ + char kbuf[BUFSZ]; + + if (uarmg || obj->otyp != CORPSE || + !touch_petrifies(&mons[obj->corpsenm]) || Stone_resistance) + return FALSE; + + /* Prevent wielding cockatrice when not wearing gloves --KAA */ + You("wield %s in your bare %s.", + corpse_xname(obj, (const char *)0, CXN_PFX_THE), + makeplural(body_part(HAND))); + Sprintf(kbuf, "wielding %s bare-handed", killer_xname(obj)); + instapetrify(kbuf); + return TRUE; +} + STATIC_OVL int ready_weapon(wep) struct obj *wep; @@ -127,15 +147,9 @@ struct obj *wep; res++; } else You("are already empty %s.", body_part(HANDED)); - } else if (!uarmg && !Stone_resistance && wep->otyp == CORPSE - && touch_petrifies(&mons[wep->corpsenm])) { - /* Prevent wielding cockatrice when not wearing gloves --KAA */ - char kbuf[BUFSZ]; - - You("wield the %s corpse in your bare %s.", - mons[wep->corpsenm].mname, makeplural(body_part(HAND))); - Sprintf(kbuf, "%s corpse", an(mons[wep->corpsenm].mname)); - instapetrify(kbuf); + } else if (wep->otyp == CORPSE && cant_wield_corpse(wep)) { + /* hero must have been life-saved to get here; use a turn */ + res++; /* corpse won't be wielded */ } else if (uarms && bimanual(wep)) You("cannot wield a two-handed %s while wearing a shield.", is_sword(wep) ? "sword" : @@ -497,14 +511,9 @@ can_twoweapon() else if (uswapwep->oartifact) pline("%s being held second to another weapon!", Yobjnam2(uswapwep, "resist")); - else if (!uarmg && !Stone_resistance && (uswapwep->otyp == CORPSE && - touch_petrifies(&mons[uswapwep->corpsenm]))) { - char kbuf[BUFSZ]; - - You("wield the %s corpse with your bare %s.", - mons[uswapwep->corpsenm].mname, body_part(HAND)); - Sprintf(kbuf, "%s corpse", an(mons[uswapwep->corpsenm].mname)); - instapetrify(kbuf); + else if (uswapwep->otyp == CORPSE && cant_wield_corpse(uswapwep)) { + /* [Note: NOT_WEAPON() check prevents ever getting here...] */ + ; /* must be life-saved to reach here; return FALSE */ } else if (Glib || uswapwep->cursed) { if (!Glib) uswapwep->bknown = TRUE; diff --git a/src/zap.c b/src/zap.c index 822e7cbc8..7b8f9f535 100644 --- a/src/zap.c +++ b/src/zap.c @@ -786,7 +786,9 @@ struct monst *mon; revive_egg(otmp); if (otmp->otyp != CORPSE) continue; /* save the name; the object is liable to go away */ - if (youseeit) Strcpy(corpse, corpse_xname(otmp, TRUE)); + if (youseeit) + Strcpy(corpse, + corpse_xname(otmp, (const char *)0, CXN_SINGULAR)); /* for a merged group, only one is revived; should this be fixed? */ if ((mtmp2 = revive(otmp, !context.mon_moving)) != 0) {