]> granicus.if.org Git - nethack/commitdiff
corpse_xname overhaul (trunk only)
authornethack.rankin <nethack.rankin>
Fri, 30 Dec 2005 06:08:20 +0000 (06:08 +0000)
committernethack.rankin <nethack.rankin>
Fri, 30 Dec 2005 06:08:20 +0000 (06:08 +0000)
     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.

13 files changed:
include/extern.h
include/hack.h
src/dig.c
src/do.c
src/do_wear.c
src/dokick.c
src/dothrow.c
src/eat.c
src/objnam.c
src/pickup.c
src/uhitm.c
src/wield.c
src/zap.c

index 2ec40316e649411d7bd35d94416f39deca5d9952..ff9d4a4effcf39f11714ba0765038cc75d5b3126 100644 (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)));
index d6600798fe770e15808ed8823687ded69643c581..1ae17d998f699ff045314efc3b094876920a766b 100644 (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. */
 
 #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
index 08a2a5001d4f6ade48637f07dbd18c58fc7fce95..c3d26e5d99468f632870769904ae9c82c6abcf82 100644 (file)
--- 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 ? '!' : '.');
index 4986b1747d71243b0b341931dd5b248409bcd145..02206ffa7dc2f7a7fe56591348db84d4955fbb02 100644 (file)
--- 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)
index eff0abea33e5752a53e71430e318d9372be2fec6..d7de101f99c34e0a0180e73759d7db49a8d8a259 100644 (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",
index 6c86d60e09082ff8a22f439c9b0ddfb382be4600..c76c871f2c0d7d6dea31de761206b3deb6f86498 100644 (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);
            }
        }
index 0242010228bce5f79612f6e2b0042f4dd657e263..038822327a1c08c53cdde996eb29dd9a09e91a04 100644 (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)) {
index 064c9aedc1502b370fd0fb5f9e986cb85889bb55..a48d767c99ee39b1526c635cf7936baa15285c48 100644 (file)
--- 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)) :
index 0fa55a9b5f785bc97017c32fe7c650791c85f52e..caede5d1a30c494795c62824d887ec7776201c7c 100644 (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
index 08b131245a2a2cd85fc112854973200272c1e26c..049ad7383eec8b6fb5145dc957b298452af8f763 100644 (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)
index feb78cd55f4838df7dc62d97ec7e7e9ef0fb613b..a237e6668de9380c0045240ad6f385826ca919e5 100644 (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;
 
-    /* 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 */
index 05d695083c88533a6baef9f994d44f6ae09cb52c..9a45a76b5bb1918233f710f86fc68024c2c142d4 100644 (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;
index 822e7cbc8c85b307ad1a49d922b6214b0a6e9142..7b8f9f5358e90ce37e0728b518804adde6afb7a5 100644 (file)
--- 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) {