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

View File

@@ -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)));

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. */
/* 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

View File

@@ -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 ? '!' : '.');

View File

@@ -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)

View File

@@ -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",

View File

@@ -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);
}
}

View File

@@ -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)) {

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. */
/* 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)) :

View File

@@ -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

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. */
/* 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)

View File

@@ -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;
/* 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... */
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";
}
Sprintf(kbuf, fmt, cbuf);
instapetrify(kbuf);
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 */

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. */
/* 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;

View File

@@ -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) {