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.
This commit is contained in:
nethack.rankin
2005-12-30 06:08:20 +00:00
parent bd3a5466dd
commit 40dd607233
13 changed files with 208 additions and 178 deletions
+1 -1
View File
@@ -1428,7 +1428,7 @@ E boolean FDECL(the_unique_obj, (struct obj *));
E boolean FDECL(the_unique_pm, (struct permonst *)); E boolean FDECL(the_unique_pm, (struct permonst *));
E char *FDECL(doname, (struct obj *)); E char *FDECL(doname, (struct obj *));
E boolean FDECL(not_fully_identified, (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(cxname, (struct obj *));
E char *FDECL(killer_xname, (struct obj *)); E char *FDECL(killer_xname, (struct obj *));
E const char *FDECL(singular, (struct obj *,char *(*)(OBJ_P))); E const char *FDECL(singular, (struct obj *,char *(*)(OBJ_P)));
+10 -1
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -76,6 +76,15 @@
#define COST_BITE 13 /* start eating food */ #define COST_BITE 13 /* start eating food */
#define COST_OPEN 14 /* open tin */ #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 * 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 * in end.c and topten.c will need to be changed. Some parts of the
+2 -1
View File
@@ -1538,7 +1538,8 @@ long timeout; /* unused */
y = obj->oy; y = obj->oy;
} else if (in_invent) { } else if (in_invent) {
if (flags.verbose) { 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", Your("%s%s %s away%c",
obj == uwep ? "wielded " : nul, cname, obj == uwep ? "wielded " : nul, cname,
otense(obj, "rot"), obj == uwep ? '!' : '.'); otense(obj, "rot"), obj == uwep ? '!' : '.');
+9 -8
View File
@@ -1486,28 +1486,29 @@ struct obj *corpse;
struct monst *mtmp, *mcarry; struct monst *mtmp, *mcarry;
boolean is_uwep, chewed; boolean is_uwep, chewed;
xchar where; xchar where;
char *cname, cname_buf[BUFSZ]; char cname[BUFSZ];
struct obj *container = (struct obj *)0; struct obj *container = (struct obj *)0;
int container_where = 0; int container_where = 0;
where = corpse->where; where = corpse->where;
is_uwep = corpse == uwep; is_uwep = (corpse == uwep);
cname = eos(strcpy(cname_buf, "bite-covered ")); chewed = (corpse->oeaten != 0);
Strcpy(cname, corpse_xname(corpse, TRUE)); Strcpy(cname, corpse_xname(corpse,
chewed ? "bite-covered" : (const char *)0,
CXN_SINGULAR));
mcarry = (where == OBJ_MINVENT) ? corpse->ocarry : 0; mcarry = (where == OBJ_MINVENT) ? corpse->ocarry : 0;
if (where == OBJ_CONTAINED) { if (where == OBJ_CONTAINED) {
struct monst *mtmp2 = (struct monst *)0; struct monst *mtmp2;
container = corpse->ocontainer; 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 */ /* container_where is the outermost container's location even if nested */
if (container_where == OBJ_MINVENT && mtmp2) mcarry = mtmp2; if (container_where == OBJ_MINVENT && mtmp2) mcarry = mtmp2;
} }
mtmp = revive(corpse, FALSE); /* corpse is gone if successful */ mtmp = revive(corpse, FALSE); /* corpse is gone if successful */
if (mtmp) { if (mtmp) {
chewed = (mtmp->mhp < mtmp->mhpmax);
if (chewed) cname = cname_buf; /* include "bite-covered" prefix */
switch (where) { switch (where) {
case OBJ_INVENT: case OBJ_INVENT:
if (is_uwep) if (is_uwep)
+1 -1
View File
@@ -422,7 +422,7 @@ boolean voluntary; /* taking gloves off on purpose? */
if (touch_petrifies(&mons[obj->corpsenm]) && !Stone_resistance) { if (touch_petrifies(&mons[obj->corpsenm]) && !Stone_resistance) {
You("now wield %s in your bare %s.", 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))); makeplural(body_part(HAND)));
Sprintf(kbuf, "%s gloves while wielding %s", Sprintf(kbuf, "%s gloves while wielding %s",
voluntary ? "removing" : "losing", voluntary ? "removing" : "losing",
+12 -8
View File
@@ -432,16 +432,20 @@ xchar x, y;
return(1); return(1);
} }
if(kickobj->otyp == CORPSE && touch_petrifies(&mons[kickobj->corpsenm]) if (!uarmf && kickobj->otyp == CORPSE &&
&& !Stone_resistance && !uarmf) { touch_petrifies(&mons[kickobj->corpsenm]) &&
You("kick the %s with your bare %s.", !Stone_resistance) {
corpse_xname(kickobj, TRUE), makeplural(body_part(FOOT))); You("kick %s with your bare %s.",
if (!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) { 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..."); You("turn to stone...");
killer.format = KILLED_BY; killer.format = KILLED_BY;
/* KMH -- otmp should be kickobj */ /* normalize body shape here; foot, not body_part(FOOT) */
Sprintf(killer.name, "kicking %s without boots", Sprintf(killer.name, "kicking %s barefoot",
an(corpse_xname(kickobj, TRUE))); killer_xname(kickobj));
done(STONING); done(STONING);
} }
} }
+10 -5
View File
@@ -91,11 +91,16 @@ int shotlimit;
return(0); return(0);
} }
u_wipe_engr(2); u_wipe_engr(2);
if (!uarmg && !Stone_resistance && (obj->otyp == CORPSE && if (!uarmg && obj->otyp == CORPSE &&
touch_petrifies(&mons[obj->corpsenm]))) { touch_petrifies(&mons[obj->corpsenm]) &&
You("throw the %s corpse with your bare %s.", !Stone_resistance) {
mons[obj->corpsenm].mname, body_part(HAND)); You("throw %s with your bare %s.",
Sprintf(killer.name, "%s corpse", an(mons[obj->corpsenm].mname)); 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); instapetrify(killer.name);
} }
if (welded(obj)) { if (welded(obj)) {
+18 -33
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -163,7 +163,7 @@ eatmdone() /* called after mimicing is over */
return 0; return 0;
} }
/* ``[the(] singular(food, xname) [)]'' with awareness of unique monsters */ /* ``[the(] singular(food, xname) [)]'' */
STATIC_OVL const char * STATIC_OVL const char *
food_xname(food, the_pfx) food_xname(food, the_pfx)
struct obj *food; struct obj *food;
@@ -172,18 +172,17 @@ boolean the_pfx;
const char *result; const char *result;
int mnum = food->corpsenm; int mnum = food->corpsenm;
if (food->otyp == CORPSE && (mons[mnum].geno & G_UNIQ)) { if (food->otyp == CORPSE) {
/* grab xname()'s modifiable return buffer for our own use */ result = corpse_xname(food, (const char *)0,
char *bufp = xname(food); CXN_SINGULAR | (the_pfx ? CXN_PFX_THE : 0));
Sprintf(bufp, "%s%s corpse", /* not strictly needed since pname values are capitalized
(the_pfx && !type_is_pname(&mons[mnum])) ? "the " : "", and the() is a no-op for them */
s_suffix(mons[mnum].mname)); if (type_is_pname(&mons[food->corpsenm])) the_pfx = FALSE;
result = bufp;
} else { } else {
/* the ordinary case */ /* the ordinary case */
result = singular(food, xname); result = singular(food, xname);
if (the_pfx) result = the(result);
} }
if (the_pfx) result = the(result);
return result; return result;
} }
@@ -227,17 +226,8 @@ choke(food) /* To a full belly all food is bad. (It.) */
if (food->oclass == COIN_CLASS) { if (food->oclass == COIN_CLASS) {
Strcpy(killer.name, "very rich meal"); Strcpy(killer.name, "very rich meal");
} else { } else {
Strcpy(killer.name, food_xname(food, FALSE)); killer.format = KILLED_BY;
if (food->otyp == CORPSE && Strcpy(killer.name, killer_xname(food));
(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));
}
} }
} else { } else {
You("choke over it."); You("choke over it.");
@@ -1269,8 +1259,8 @@ opentin() /* called during each move whilst opening a tin */
what = rndmonnam(); what = rndmonnam();
} else { } else {
what = mons[mnum].mname; what = mons[mnum].mname;
if (mons[mnum].geno & G_UNIQ) if (the_unique_pm(&mons[mnum])) which = 2;
which = type_is_pname(&mons[mnum]) ? 1 : 2; else if (type_is_pname(&mons[mnum])) which = 1;
} }
if (which == 0) what = makeplural(what); 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; int tp = 0, mnum = otmp->corpsenm;
long rotted = 0L; long rotted = 0L;
boolean uniq = !!(mons[mnum].geno & G_UNIQ);
int retcode = 0; int retcode = 0;
boolean stoneable = (flesh_petrifies(&mons[mnum]) && boolean stoneable = (flesh_petrifies(&mons[mnum]) &&
!Stone_resistance && !Stone_resistance &&
@@ -1490,20 +1479,15 @@ eatcorpse(otmp) /* called when a corpse is selected as food */
if (Sick_resistance) { if (Sick_resistance) {
pline("It doesn't seem at all sickening, though..."); pline("It doesn't seem at all sickening, though...");
} else { } else {
char buf[BUFSZ];
long sick_time; long sick_time;
sick_time = (long) rn1(10, 10); sick_time = (long) rn1(10, 10);
/* make sure new ill doesn't result in improvement */ /* make sure new ill doesn't result in improvement */
if (Sick && (sick_time > Sick)) if (Sick && (sick_time > Sick))
sick_time = (Sick > 1L) ? Sick - 1L : 1L; sick_time = (Sick > 1L) ? Sick - 1L : 1L;
if (!uniq) make_sick(sick_time,
Sprintf(buf, "rotted %s", corpse_xname(otmp,TRUE)); corpse_xname(otmp, "rotted", CXN_NORMAL),
else TRUE, SICK_VOMITABLE);
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);
} }
if (carried(otmp)) useup(otmp); if (carried(otmp)) useup(otmp);
else useupf(otmp, 1L); else useupf(otmp, 1L);
@@ -1552,7 +1536,8 @@ eatcorpse(otmp) /* called when a corpse is selected as food */
pline("This tastes just like chicken!"); pline("This tastes just like chicken!");
} else { } else {
pline("%s%s %s!", 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), food_xname(otmp, FALSE),
(vegan(&mons[mnum]) ? (vegan(&mons[mnum]) ?
(!carnivorous(youmonst.data) && herbivorous(youmonst.data)) : (!carnivorous(youmonst.data) && herbivorous(youmonst.data)) :
+72 -27
View File
@@ -592,6 +592,10 @@ register struct obj *obj;
if(obj->quan != 1L) if(obj->quan != 1L)
Sprintf(prefix, "%ld ", obj->quan); 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)) { else if (obj_is_pname(obj) || the_unique_obj(obj)) {
if (!strncmpi(bp, "the ", 4)) if (!strncmpi(bp, "the ", 4))
bp += 4; bp += 4;
@@ -750,16 +754,9 @@ ring:
if (obj->oeaten) if (obj->oeaten)
Strcat(prefix, "partly eaten "); Strcat(prefix, "partly eaten ");
if (obj->otyp == CORPSE) { if (obj->otyp == CORPSE) {
if (the_unique_pm(&mons[omndx]) || Sprintf(prefix, "%s ",
type_is_pname(&mons[omndx])) { corpse_xname(obj, prefix,
Sprintf(prefix, "%s%s ", CXN_ARTICLE|CXN_NOCORPSE));
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, " ");
}
} else if (obj->otyp == EGG) { } else if (obj->otyp == EGG) {
#if 0 /* corpses don't tell if they're stale either */ #if 0 /* corpses don't tell if they're stale either */
if (obj->known && stale_egg(obj)) if (obj->known && stale_egg(obj))
@@ -868,41 +865,92 @@ register struct obj *otmp;
} }
char * char *
corpse_xname(otmp, ignore_oquan) corpse_xname(otmp, adjective, cxn_flags)
struct obj *otmp; struct obj *otmp;
boolean ignore_oquan; /* to force singular */ const char *adjective;
unsigned cxn_flags; /* bitmask of CXN_xxx values */
{ {
char *nambuf = nextobuf(); char *nambuf = nextobuf();
int omndx = otmp->corpsenm; 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; 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 /* [Possible enhancement: check whether corpse has monster traits
attached in order to use priestname() for priests and minions.] */ 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 */ /* avoid "aligned priest"; it just exposes internal details */
mname = "priest"; mname = "priest";
} else { } else {
mname = mons[omndx].mname; 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); 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) *nambuf = '\0';
return nambuf; /* can't use the() the way we use an() below because any capitalized
else Name causes it to assume a personal name and return Name as-is;
return makeplural(nambuf); 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 * char *
cxname(obj) cxname(obj)
struct obj *obj; struct obj *obj;
{ {
if (obj->otyp == CORPSE) if (obj->otyp == CORPSE)
return corpse_xname(obj, FALSE); return corpse_xname(obj, (const char *)0, CXN_NORMAL);
return xname(obj); return xname(obj);
} }
@@ -941,10 +989,7 @@ struct obj *obj;
/* format the object */ /* format the object */
if (obj->otyp == CORPSE) { if (obj->otyp == CORPSE) {
buf = nextobuf(); buf = nextobuf();
Sprintf(buf, "%s%s", Strcpy(buf, corpse_xname(obj, (const char *)0, CXN_NORMAL));
/* can't use the(); capitalized name blocks its article */
the_unique_pm(&mons[obj->corpsenm]) ? "the " : "",
corpse_xname(obj, FALSE));
} else if (obj->otyp == SLIME_MOLD) { } else if (obj->otyp == SLIME_MOLD) {
/* concession to "most unique deaths competition" in the annual /* concession to "most unique deaths competition" in the annual
devnull tournament, suppress player supplied fruit names because devnull tournament, suppress player supplied fruit names because
+27 -43
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* 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 *, STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
const char *,struct obj *,BOOLEAN_P,int *)); const char *,struct obj *,BOOLEAN_P,int *));
#endif #endif
STATIC_DCL boolean FDECL(fatal_corpse_mistake, (struct obj *,BOOLEAN_P));
STATIC_DCL void FDECL(check_here, (BOOLEAN_P)); STATIC_DCL void FDECL(check_here, (BOOLEAN_P));
STATIC_DCL boolean FDECL(n_or_more, (struct obj *)); STATIC_DCL boolean FDECL(n_or_more, (struct obj *));
STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *)); STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *));
@@ -262,6 +263,27 @@ ask_again:
return TRUE; 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 */ /* look at the objects at our location, unless there are too many of them */
STATIC_OVL void STATIC_OVL void
check_here(picked_some) check_here(picked_some)
@@ -1307,18 +1329,8 @@ boolean telekinesis; /* not picking it up directly by hand */
return 1; return 1;
#endif #endif
} else if (obj->otyp == CORPSE) { } else if (obj->otyp == CORPSE) {
if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg if (fatal_corpse_mistake(obj, telekinesis)) {
&& !Stone_resistance && !telekinesis) { return -1;
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;
}
} else if (is_rider(&mons[obj->corpsenm])) { } else if (is_rider(&mons[obj->corpsenm])) {
pline("At your %s, the corpse suddenly moves...", pline("At your %s, the corpse suddenly moves...",
telekinesis ? "attempted acquisition" : "touch"); telekinesis ? "attempted acquisition" : "touch");
@@ -1823,21 +1835,7 @@ register struct obj *obj;
if (uquiver) return 0; /* unwielded, died, rewielded */ if (uquiver) return 0; /* unwielded, died, rewielded */
} }
if (obj->otyp == CORPSE) { if (fatal_corpse_mistake(obj, FALSE)) return -1;
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;
}
}
}
/* boxes, boulders, and big statues can't fit into any container */ /* boxes, boulders, and big statues can't fit into any container */
if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER || 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->oartifact && !touch_artifact(obj,&youmonst)) return 0;
if (obj->otyp == CORPSE) { if (fatal_corpse_mistake(obj, FALSE)) return -1;
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;
}
}
}
count = obj->quan; count = obj->quan;
if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0) if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0)
+16 -31
View File
@@ -753,13 +753,12 @@ int thrown;
#endif #endif
case CORPSE: /* fixed by polder@cs.vu.nl */ case CORPSE: /* fixed by polder@cs.vu.nl */
if (touch_petrifies(&mons[obj->corpsenm])) { if (touch_petrifies(&mons[obj->corpsenm])) {
static const char withwhat[] = "corpse";
tmp = 1; tmp = 1;
hittxt = TRUE; hittxt = TRUE;
You("hit %s with %s %s.", mon_nam(mon), You("hit %s with %s.", mon_nam(mon),
obj->dknown ? the(mons[obj->corpsenm].mname) : corpse_xname(obj, (const char *)0,
an(mons[obj->corpsenm].mname), obj->dknown ? CXN_PFX_THE : CXN_ARTICLE));
(obj->quan > 1L) ? makeplural(withwhat) : withwhat); obj->dknown = 1;
if (!munstone(mon, TRUE)) if (!munstone(mon, TRUE))
minstapetrify(mon, TRUE); minstapetrify(mon, TRUE);
if (resists_ston(mon)) break; if (resists_ston(mon)) break;
@@ -1215,28 +1214,20 @@ STATIC_OVL boolean
theft_petrifies(otmp) theft_petrifies(otmp)
struct obj *otmp; struct obj *otmp;
{ {
const char *fmt;
char *p, cbuf[BUFSZ], kbuf[BUFSZ];
if (uarmg || otmp->otyp != CORPSE || if (uarmg || otmp->otyp != CORPSE ||
!touch_petrifies(&mons[otmp->corpsenm])) return FALSE; !touch_petrifies(&mons[otmp->corpsenm]) || Stone_resistance)
return FALSE;
/* 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;
}
#endif
/* stealing this corpse is fatal... */ /* stealing this corpse is fatal... */
Strcpy(cbuf, cxname(otmp)); /* "cockatrice corpse" */ instapetrify(corpse_xname(otmp, "stolen", CXN_ARTICLE));
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";
}
Sprintf(kbuf, fmt, cbuf);
instapetrify(kbuf);
/* apparently wasn't fatal after all... */ /* apparently wasn't fatal after all... */
return TRUE; return TRUE;
} }
@@ -1246,12 +1237,6 @@ struct obj *otmp;
* *
* If the target is wearing body armor, take all of its possesions; * If the target is wearing body armor, take all of its possesions;
* otherwise, take one object. [Is this really the behavior we want?] * 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 STATIC_OVL void
steal_it(mdef, mattk) steal_it(mdef, mattk)
@@ -1801,7 +1786,7 @@ register struct attack *mattk;
/* engulfing a cockatrice or digesting a Rider or Medusa */ /* engulfing a cockatrice or digesting a Rider or Medusa */
fatal_gulp = (touch_petrifies(pd) && !Stone_resistance) || fatal_gulp = (touch_petrifies(pd) && !Stone_resistance) ||
(mattk->adtyp == AD_DGST && (is_rider(pd) || (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) { if ((mattk->adtyp == AD_DGST && !Slow_digestion) || fatal_gulp) {
/* KMH, conduct */ /* KMH, conduct */
+27 -18
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* 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 *)); STATIC_DCL int FDECL(ready_weapon, (struct obj *));
/* used by will_weld() */ /* used by will_weld() */
@@ -112,6 +113,25 @@ register struct obj *obj;
update_inventory(); 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 STATIC_OVL int
ready_weapon(wep) ready_weapon(wep)
struct obj *wep; struct obj *wep;
@@ -127,15 +147,9 @@ struct obj *wep;
res++; res++;
} else } else
You("are already empty %s.", body_part(HANDED)); You("are already empty %s.", body_part(HANDED));
} else if (!uarmg && !Stone_resistance && wep->otyp == CORPSE } else if (wep->otyp == CORPSE && cant_wield_corpse(wep)) {
&& touch_petrifies(&mons[wep->corpsenm])) { /* hero must have been life-saved to get here; use a turn */
/* Prevent wielding cockatrice when not wearing gloves --KAA */ res++; /* corpse won't be wielded */
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 (uarms && bimanual(wep)) } else if (uarms && bimanual(wep))
You("cannot wield a two-handed %s while wearing a shield.", You("cannot wield a two-handed %s while wearing a shield.",
is_sword(wep) ? "sword" : is_sword(wep) ? "sword" :
@@ -497,14 +511,9 @@ can_twoweapon()
else if (uswapwep->oartifact) else if (uswapwep->oartifact)
pline("%s being held second to another weapon!", pline("%s being held second to another weapon!",
Yobjnam2(uswapwep, "resist")); Yobjnam2(uswapwep, "resist"));
else if (!uarmg && !Stone_resistance && (uswapwep->otyp == CORPSE && else if (uswapwep->otyp == CORPSE && cant_wield_corpse(uswapwep)) {
touch_petrifies(&mons[uswapwep->corpsenm]))) { /* [Note: NOT_WEAPON() check prevents ever getting here...] */
char kbuf[BUFSZ]; ; /* must be life-saved to reach here; return FALSE */
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 (Glib || uswapwep->cursed) { } else if (Glib || uswapwep->cursed) {
if (!Glib) if (!Glib)
uswapwep->bknown = TRUE; uswapwep->bknown = TRUE;
+3 -1
View File
@@ -786,7 +786,9 @@ struct monst *mon;
revive_egg(otmp); revive_egg(otmp);
if (otmp->otyp != CORPSE) continue; if (otmp->otyp != CORPSE) continue;
/* save the name; the object is liable to go away */ /* 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? */ /* for a merged group, only one is revived; should this be fixed? */
if ((mtmp2 = revive(otmp, !context.mon_moving)) != 0) { if ((mtmp2 = revive(otmp, !context.mon_moving)) != 0) {