]> granicus.if.org Git - nethack/commitdiff
misplacement
authornhmall <nhmall@nethack.org>
Sun, 18 Mar 2018 14:11:51 +0000 (10:11 -0400)
committernhmall <nhmall@nethack.org>
Sun, 18 Mar 2018 14:11:51 +0000 (10:11 -0400)
objnam.c [deleted file]

diff --git a/objnam.c b/objnam.c
deleted file mode 100644 (file)
index ecb5de3..0000000
--- a/objnam.c
+++ /dev/null
@@ -1,4062 +0,0 @@
-/* NetHack 3.6 objnam.c        $NHDT-Date: 1521377345 2018/03/18 12:49:05 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.194 $ */
-/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
-/* NetHack may be freely redistributed.  See license for details. */
-
-#include "hack.h"
-
-/* "an uncursed greased partly eaten guardian naga hatchling [corpse]" */
-#define PREFIX 80 /* (56) */
-#define SCHAR_LIM 127
-#define NUMOBUF 12
-
-STATIC_DCL char *FDECL(strprepend, (char *, const char *));
-STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
-STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (char *, CHAR_P));
-STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
-STATIC_DCL char *NDECL(nextobuf);
-STATIC_DCL void FDECL(releaseobuf, (char *));
-STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
-STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
-STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned));
-STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
-                                           const char *const *));
-STATIC_DCL char *FDECL(singplur_compound, (char *));
-STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
-STATIC_DCL boolean FDECL(badman, (const char *, BOOLEAN_P));
-
-struct Jitem {
-    int item;
-    const char *name;
-};
-
-#define BSTRCMPI(base, ptr, str) ((ptr) < base || strcmpi((ptr), str))
-#define BSTRNCMPI(base, ptr, str, num) \
-    ((ptr) < base || strncmpi((ptr), str, num))
-#define Strcasecpy(dst, src) (void) strcasecpy(dst, src)
-
-/* true for gems/rocks that should have " stone" appended to their names */
-#define GemStone(typ)                                                  \
-    (typ == FLINT                                                      \
-     || (objects[typ].oc_material == GEMSTONE                          \
-         && (typ != DILITHIUM_CRYSTAL && typ != RUBY && typ != DIAMOND \
-             && typ != SAPPHIRE && typ != BLACK_OPAL && typ != EMERALD \
-             && typ != OPAL)))
-
-STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "wakizashi" },
-                                             { BROADSWORD, "ninja-to" },
-                                             { FLAIL, "nunchaku" },
-                                             { GLAIVE, "naginata" },
-                                             { LOCK_PICK, "osaku" },
-                                             { WOODEN_HARP, "koto" },
-                                             { KNIFE, "shito" },
-                                             { PLATE_MAIL, "tanko" },
-                                             { HELMET, "kabuto" },
-                                             { LEATHER_GLOVES, "yugake" },
-                                             { FOOD_RATION, "gunyoki" },
-                                             { POT_BOOZE, "sake" },
-                                             { 0, "" } };
-
-STATIC_DCL const char *FDECL(Japanese_item_name, (int i));
-
-STATIC_OVL char *
-strprepend(s, pref)
-register char *s;
-register const char *pref;
-{
-    register int i = (int) strlen(pref);
-
-    if (i > PREFIX) {
-        impossible("PREFIX too short (for %d).", i);
-        return s;
-    }
-    s -= i;
-    (void) strncpy(s, pref, i); /* do not copy trailing 0 */
-    return s;
-}
-
-/* manage a pool of BUFSZ buffers, so callers don't have to */
-static char NEARDATA obufs[NUMOBUF][BUFSZ];
-static int obufidx = 0;
-
-STATIC_OVL char *
-nextobuf()
-{
-    obufidx = (obufidx + 1) % NUMOBUF;
-    return obufs[obufidx];
-}
-
-/* put the most recently allocated buffer back if possible */
-STATIC_OVL void
-releaseobuf(bufp)
-char *bufp;
-{
-    /* caller may not know whether bufp is the most recently allocated
-       buffer; if it isn't, do nothing; note that because of the somewhat
-       obscure PREFIX handling for object name formatting by xname(),
-       the pointer our caller has and is passing to us might be into the
-       middle of an obuf rather than the address returned by nextobuf() */
-    if (bufp >= obufs[obufidx]
-        && bufp < obufs[obufidx] + sizeof obufs[obufidx]) /* obufs[][BUFSZ] */
-        obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
-}
-
-char *
-obj_typename(otyp)
-register int otyp;
-{
-    char *buf = nextobuf();
-    struct objclass *ocl = &objects[otyp];
-    const char *actualn = OBJ_NAME(*ocl);
-    const char *dn = OBJ_DESCR(*ocl);
-    const char *un = ocl->oc_uname;
-    int nn = ocl->oc_name_known;
-
-    if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
-        actualn = Japanese_item_name(otyp);
-    switch (ocl->oc_class) {
-    case COIN_CLASS:
-        Strcpy(buf, "coin");
-        break;
-    case POTION_CLASS:
-        Strcpy(buf, "potion");
-        break;
-    case SCROLL_CLASS:
-        Strcpy(buf, "scroll");
-        break;
-    case WAND_CLASS:
-        Strcpy(buf, "wand");
-        break;
-    case SPBOOK_CLASS:
-        if (otyp != SPE_NOVEL) {
-            Strcpy(buf, "spellbook");
-        } else {
-            Strcpy(buf, !nn ? "book" : "novel");
-            nn = 0;
-        }
-        break;
-    case RING_CLASS:
-        Strcpy(buf, "ring");
-        break;
-    case AMULET_CLASS:
-        if (nn)
-            Strcpy(buf, actualn);
-        else
-            Strcpy(buf, "amulet");
-        if (un)
-            Sprintf(eos(buf), " called %s", un);
-        if (dn)
-            Sprintf(eos(buf), " (%s)", dn);
-        return buf;
-    default:
-        if (nn) {
-            Strcpy(buf, actualn);
-            if (GemStone(otyp))
-                Strcat(buf, " stone");
-            if (un)
-                Sprintf(eos(buf), " called %s", un);
-            if (dn)
-                Sprintf(eos(buf), " (%s)", dn);
-        } else {
-            Strcpy(buf, dn ? dn : actualn);
-            if (ocl->oc_class == GEM_CLASS)
-                Strcat(buf,
-                       (ocl->oc_material == MINERAL) ? " stone" : " gem");
-            if (un)
-                Sprintf(eos(buf), " called %s", un);
-        }
-        return buf;
-    }
-    /* here for ring/scroll/potion/wand */
-    if (nn) {
-        if (ocl->oc_unique)
-            Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
-        else
-            Sprintf(eos(buf), " of %s", actualn);
-    }
-    if (un)
-        Sprintf(eos(buf), " called %s", un);
-    if (dn)
-        Sprintf(eos(buf), " (%s)", dn);
-    return buf;
-}
-
-/* less verbose result than obj_typename(); either the actual name
-   or the description (but not both); user-assigned name is ignored */
-char *
-simple_typename(otyp)
-int otyp;
-{
-    char *bufp, *pp, *save_uname = objects[otyp].oc_uname;
-
-    objects[otyp].oc_uname = 0; /* suppress any name given by user */
-    bufp = obj_typename(otyp);
-    objects[otyp].oc_uname = save_uname;
-    if ((pp = strstri(bufp, " (")) != 0)
-        *pp = '\0'; /* strip the appended description */
-    return bufp;
-}
-
-boolean
-obj_is_pname(obj)
-struct obj *obj;
-{
-    if (!obj->oartifact || !has_oname(obj))
-        return FALSE;
-    if (!program_state.gameover && !iflags.override_ID) {
-        if (not_fully_identified(obj))
-            return FALSE;
-    }
-    return TRUE;
-}
-
-/* used by distant_name() to pass extra information to xname_flags();
-   it would be much cleaner if this were a parameter, but that would
-   require all of the xname() and doname() calls to be modified */
-static int distantname = 0;
-
-/* Give the name of an object seen at a distance.  Unlike xname/doname,
- * we don't want to set dknown if it's not set already.
- */
-char *
-distant_name(obj, func)
-struct obj *obj;
-char *FDECL((*func), (OBJ_P));
-{
-    char *str;
-
-    /* 3.6.1: this used to save Blind, set it, make the call, then restore
-     * the saved value; but the Eyes of the Overworld override blindness
-     * and let characters wearing them get dknown set for distant items.
-     *
-     * TODO? if the hero is wearing those Eyes, figure out whether the
-     * object is within X-ray radius and only treat it as distant when
-     * beyond that radius.  Logic is iffy but result might be interesting.
-     */
-    ++distantname;
-    str = (*func)(obj);
-    --distantname;
-    return str;
-}
-
-/* convert player specified fruit name into corresponding fruit juice name
-   ("slice of pizza" -> "pizza juice" rather than "slice of pizza juice") */
-char *
-fruitname(juice)
-boolean juice; /* whether or not to append " juice" to the name */
-{
-    char *buf = nextobuf();
-    const char *fruit_nam = strstri(pl_fruit, " of ");
-
-    if (fruit_nam)
-        fruit_nam += 4; /* skip past " of " */
-    else
-        fruit_nam = pl_fruit; /* use it as is */
-
-    Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
-    return buf;
-}
-
-/* look up a named fruit by index (1..127) */
-struct fruit *
-fruit_from_indx(indx)
-int indx;
-{
-    struct fruit *f;
-
-    for (f = ffruit; f; f = f->nextf)
-        if (f->fid == indx)
-            break;
-    return f;
-}
-
-/* look up a named fruit by name */
-struct fruit *
-fruit_from_name(fname, exact, highest_fid)
-const char *fname;
-boolean exact; /* False => prefix or exact match, True = exact match only */
-int *highest_fid; /* optional output; only valid if 'fname' isn't found */
-{
-    struct fruit *f, *tentativef;
-    char *altfname;
-    unsigned k;
-    /*
-     * note: named fruits are case-senstive...
-     */
-
-    if (highest_fid)
-        *highest_fid = 0;
-    /* first try for an exact match */
-    for (f = ffruit; f; f = f->nextf)
-        if (!strcmp(f->fname, fname))
-            return f;
-        else if (highest_fid && f->fid > *highest_fid)
-            *highest_fid = f->fid;
-
-    /* didn't match as-is; if caller is willing to accept a prefix
-       match, try to find one; we want to find the longest prefix that
-       matches, not the first */
-    if (!exact) {
-        tentativef = 0;
-        for (f = ffruit; f; f = f->nextf) {
-            k = strlen(f->fname);
-            if (!strncmp(f->fname, fname, k)
-                && (!fname[k] || fname[k] == ' ')
-                && (!tentativef || k > strlen(tentativef->fname)))
-                tentativef = f;
-        }
-        f = tentativef;
-    }
-    /* if we still don't have a match, try singularizing the target;
-       for exact match, that's trivial, but for prefix, it's hard */
-    if (!f) {
-        altfname = makesingular(fname);
-        for (f = ffruit; f; f = f->nextf) {
-            if (!strcmp(f->fname, altfname))
-                break;
-        }
-        releaseobuf(altfname);
-    }
-    if (!f && !exact) {
-        char fnamebuf[BUFSZ], *p;
-        unsigned fname_k = strlen(fname); /* length of assumed plural fname */
-
-        tentativef = 0;
-        for (f = ffruit; f; f = f->nextf) {
-            k = strlen(f->fname);
-            /* reload fnamebuf[] each iteration in case it gets modified;
-               there's no need to recalculate fname_k */
-            Strcpy(fnamebuf, fname);
-            /* bug? if singular of fname is longer than plural,
-               failing the 'fname_k > k' test could skip a viable
-               candidate; unfortunately, we can't singularize until
-               after stripping off trailing stuff and we can't get
-               accurate fname_k until fname has been singularized;
-               compromise and use 'fname_k >= k' instead of '>',
-               accepting 1 char length discrepancy without risking
-               false match (I hope...) */
-            if (fname_k >= k && (p = index(&fnamebuf[k], ' ')) != 0) {
-                *p = '\0'; /* truncate at 1st space past length of f->fname */
-                altfname = makesingular(fnamebuf);
-                k = strlen(altfname); /* actually revised 'fname_k' */
-                if (!strcmp(f->fname, altfname)
-                    && (!tentativef || k > strlen(tentativef->fname)))
-                    tentativef = f;
-                releaseobuf(altfname); /* avoid churning through all obufs */
-            }
-        }
-        f = tentativef;
-    }
-    return f;
-}
-
-/* sort the named-fruit linked list by fruit index number */
-void
-reorder_fruit(forward)
-boolean forward;
-{
-    struct fruit *f, *allfr[1 + 127];
-    int i, j, k = SIZE(allfr);
-
-    for (i = 0; i < k; ++i)
-        allfr[i] = (struct fruit *) 0;
-    for (f = ffruit; f; f = f->nextf) {
-        /* without sanity checking, this would reduce to 'allfr[f->fid]=f' */
-        j = f->fid;
-        if (j < 1 || j >= k) {
-            impossible("reorder_fruit: fruit index (%d) out of range", j);
-            return; /* don't sort after all; should never happen... */
-        } else if (allfr[j]) {
-            impossible("reorder_fruit: duplicate fruit index (%d)", j);
-            return;
-        }
-        allfr[j] = f;
-    }
-    ffruit = 0; /* reset linked list; we're rebuilding it from scratch */
-    /* slot [0] will always be empty; must start 'i' at 1 to avoid
-       [k - i] being out of bounds during first iteration */
-    for (i = 1; i < k; ++i) {
-        /* for forward ordering, go through indices from high to low;
-           for backward ordering, go from low to high */
-        j = forward ? (k - i) : i;
-        if (allfr[j]) {
-            allfr[j]->nextf = ffruit;
-            ffruit = allfr[j];
-        }
-    }
-}
-
-char *
-xname(obj)
-struct obj *obj;
-{
-    return xname_flags(obj, CXN_NORMAL);
-}
-
-char *
-xname_flags(obj, cxn_flags)
-register struct obj *obj;
-unsigned cxn_flags; /* bitmask of CXN_xxx values */
-{
-    register char *buf;
-    register int typ = obj->otyp;
-    register struct objclass *ocl = &objects[typ];
-    int nn = ocl->oc_name_known, omndx = obj->corpsenm;
-    const char *actualn = OBJ_NAME(*ocl);
-    const char *dn = OBJ_DESCR(*ocl) ? OBJ_DESCR(*ocl) : actualn;
-    const char *un = ocl->oc_uname;
-    boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
-    boolean known, dknown, bknown;
-
-    buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
-    if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
-        actualn = Japanese_item_name(typ);
-
-    buf[0] = '\0';
-    /*
-     * clean up known when it's tied to oc_name_known, eg after AD_DRIN
-     * This is only required for unique objects since the article
-     * printed for the object is tied to the combination of the two
-     * and printing the wrong article gives away information.
-     */
-    if (!nn && ocl->oc_uses_known && ocl->oc_unique)
-        obj->known = 0;
-    if (!Blind && !distantname)
-        obj->dknown = TRUE;
-    if (Role_if(PM_PRIEST))
-        obj->bknown = TRUE;
-
-    if (iflags.override_ID) {
-        known = dknown = bknown = TRUE;
-        nn = 1;
-    } else {
-        known = obj->known;
-        dknown = obj->dknown;
-        bknown = obj->bknown;
-    }
-
-    if (obj_is_pname(obj))
-        goto nameit;
-    switch (obj->oclass) {
-    case AMULET_CLASS:
-        if (!dknown)
-            Strcpy(buf, "amulet");
-        else if (typ == AMULET_OF_YENDOR || typ == FAKE_AMULET_OF_YENDOR)
-            /* each must be identified individually */
-            Strcpy(buf, known ? actualn : dn);
-        else if (nn)
-            Strcpy(buf, actualn);
-        else if (un)
-            Sprintf(buf, "amulet called %s", un);
-        else
-            Sprintf(buf, "%s amulet", dn);
-        break;
-    case WEAPON_CLASS:
-        if (is_poisonable(obj) && obj->opoisoned)
-            Strcpy(buf, "poisoned ");
-    case VENOM_CLASS:
-    case TOOL_CLASS:
-        if (typ == LENSES)
-            Strcpy(buf, "pair of ");
-        else if (is_wet_towel(obj))
-            Strcpy(buf, (obj->spe < 3) ? "moist " : "wet ");
-
-        if (!dknown)
-            Strcat(buf, dn);
-        else if (nn)
-            Strcat(buf, actualn);
-        else if (un) {
-            Strcat(buf, dn);
-            Strcat(buf, " called ");
-            Strcat(buf, un);
-        } else
-            Strcat(buf, dn);
-        /* If we use an() here we'd have to remember never to use */
-        /* it whenever calling doname() or xname(). */
-        if (typ == FIGURINE && omndx != NON_PM) {
-            Sprintf(eos(buf), " of a%s %s",
-                    index(vowels, *mons[omndx].mname) ? "n" : "",
-                    mons[omndx].mname);
-        } else if (is_wet_towel(obj)) {
-            if (wizard)
-                Sprintf(eos(buf), " (%d)", obj->spe);
-        }
-        break;
-    case ARMOR_CLASS:
-        /* depends on order of the dragon scales objects */
-        if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
-            Sprintf(buf, "set of %s", actualn);
-            break;
-        }
-        if (is_boots(obj) || is_gloves(obj))
-            Strcpy(buf, "pair of ");
-
-        if (obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
-            && !dknown) {
-            Strcpy(buf, "shield");
-            break;
-        }
-        if (obj->otyp == SHIELD_OF_REFLECTION && !dknown) {
-            Strcpy(buf, "smooth shield");
-            break;
-        }
-
-        if (nn)
-            Strcat(buf, actualn);
-        else if (un) {
-            if (is_boots(obj))
-                Strcat(buf, "boots");
-            else if (is_gloves(obj))
-                Strcat(buf, "gloves");
-            else if (is_cloak(obj))
-                Strcpy(buf, "cloak");
-            else if (is_helmet(obj))
-                Strcpy(buf, "helmet");
-            else if (is_shield(obj))
-                Strcpy(buf, "shield");
-            else
-                Strcpy(buf, "armor");
-            Strcat(buf, " called ");
-            Strcat(buf, un);
-        } else
-            Strcat(buf, dn);
-        break;
-    case FOOD_CLASS:
-        if (typ == SLIME_MOLD) {
-            struct fruit *f = fruit_from_indx(obj->spe);
-
-            if (!f) {
-                impossible("Bad fruit #%d?", obj->spe);
-                Strcpy(buf, "fruit");
-            } else {
-                Strcpy(buf, f->fname);
-                if (pluralize) {
-                    /* ick; already pluralized fruit names
-                       are allowed--we want to try to avoid
-                       adding a redundant plural suffix */
-                    Strcpy(buf, makeplural(makesingular(buf)));
-                    pluralize = FALSE;
-                }
-            }
-            break;
-        }
-        if (obj->globby) {
-            Sprintf(buf, "%s%s",
-                    (obj->owt <= 100)
-                       ? "small "
-                       : (obj->owt > 500)
-                          ? "very large "
-                          : (obj->owt > 300)
-                             ? "large "
-                             : "",
-                    actualn);
-            break;
-        }
-
-        Strcpy(buf, actualn);
-        if (typ == TIN && known)
-            tin_details(obj, omndx, buf);
-        break;
-    case COIN_CLASS:
-    case CHAIN_CLASS:
-        Strcpy(buf, actualn);
-        break;
-    case ROCK_CLASS:
-        if (typ == STATUE && omndx != NON_PM)
-            Sprintf(buf, "%s%s of %s%s",
-                    (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
-                       ? "historic "
-                       : "",
-                    actualn,
-                    type_is_pname(&mons[omndx])
-                       ? ""
-                       : the_unique_pm(&mons[omndx])
-                          ? "the "
-                          : index(vowels, *mons[omndx].mname)
-                             ? "an "
-                             : "a ",
-                    mons[omndx].mname);
-        else
-            Strcpy(buf, actualn);
-        break;
-    case BALL_CLASS:
-        Sprintf(buf, "%sheavy iron ball",
-                (obj->owt > ocl->oc_weight) ? "very " : "");
-        break;
-    case POTION_CLASS:
-        if (dknown && obj->odiluted)
-            Strcpy(buf, "diluted ");
-        if (nn || un || !dknown) {
-            Strcat(buf, "potion");
-            if (!dknown)
-                break;
-            if (nn) {
-                Strcat(buf, " of ");
-                if (typ == POT_WATER && bknown
-                    && (obj->blessed || obj->cursed)) {
-                    Strcat(buf, obj->blessed ? "holy " : "unholy ");
-                }
-                Strcat(buf, actualn);
-            } else {
-                Strcat(buf, " called ");
-                Strcat(buf, un);
-            }
-        } else {
-            Strcat(buf, dn);
-            Strcat(buf, " potion");
-        }
-        break;
-    case SCROLL_CLASS:
-        Strcpy(buf, "scroll");
-        if (!dknown)
-            break;
-        if (nn) {
-            Strcat(buf, " of ");
-            Strcat(buf, actualn);
-        } else if (un) {
-            Strcat(buf, " called ");
-            Strcat(buf, un);
-        } else if (ocl->oc_magic) {
-            Strcat(buf, " labeled ");
-            Strcat(buf, dn);
-        } else {
-            Strcpy(buf, dn);
-            Strcat(buf, " scroll");
-        }
-        break;
-    case WAND_CLASS:
-        if (!dknown)
-            Strcpy(buf, "wand");
-        else if (nn)
-            Sprintf(buf, "wand of %s", actualn);
-        else if (un)
-            Sprintf(buf, "wand called %s", un);
-        else
-            Sprintf(buf, "%s wand", dn);
-        break;
-    case SPBOOK_CLASS:
-        if (typ == SPE_NOVEL) { /* 3.6 tribute */
-            if (!dknown)
-                Strcpy(buf, "book");
-            else if (nn)
-                Strcpy(buf, actualn);
-            else if (un)
-                Sprintf(buf, "novel called %s", un);
-            else
-                Sprintf(buf, "%s book", dn);
-            break;
-            /* end of tribute */
-        } else if (!dknown) {
-            Strcpy(buf, "spellbook");
-        } else if (nn) {
-            if (typ != SPE_BOOK_OF_THE_DEAD)
-                Strcpy(buf, "spellbook of ");
-            Strcat(buf, actualn);
-        } else if (un) {
-            Sprintf(buf, "spellbook called %s", un);
-        } else
-            Sprintf(buf, "%s spellbook", dn);
-        break;
-    case RING_CLASS:
-        if (!dknown)
-            Strcpy(buf, "ring");
-        else if (nn)
-            Sprintf(buf, "ring of %s", actualn);
-        else if (un)
-            Sprintf(buf, "ring called %s", un);
-        else
-            Sprintf(buf, "%s ring", dn);
-        break;
-    case GEM_CLASS: {
-        const char *rock = (ocl->oc_material == MINERAL) ? "stone" : "gem";
-
-        if (!dknown) {
-            Strcpy(buf, rock);
-        } else if (!nn) {
-            if (un)
-                Sprintf(buf, "%s called %s", rock, un);
-            else
-                Sprintf(buf, "%s %s", dn, rock);
-        } else {
-            Strcpy(buf, actualn);
-            if (GemStone(typ))
-                Strcat(buf, " stone");
-        }
-        break;
-    }
-    default:
-        Sprintf(buf, "glorkum %d %d %d", obj->oclass, typ, obj->spe);
-    }
-    if (pluralize)
-        Strcpy(buf, makeplural(buf));
-
-    if (obj->otyp == T_SHIRT && program_state.gameover) {
-        char tmpbuf[BUFSZ];
-
-        Sprintf(eos(buf), " with text \"%s\"", tshirt_text(obj, tmpbuf));
-    }
-
-    if (has_oname(obj) && dknown) {
-        Strcat(buf, " named ");
-    nameit:
-        Strcat(buf, ONAME(obj));
-    }
-
-    if (!strncmpi(buf, "the ", 4))
-        buf += 4;
-    return buf;
-}
-
-/* similar to simple_typename but minimal_xname operates on a particular
-   object rather than its general type; it formats the most basic info:
-     potion                     -- if description not known
-     brown potion               -- if oc_name_known not set
-     potion of object detection -- if discovered
- */
-STATIC_OVL char *
-minimal_xname(obj)
-struct obj *obj;
-{
-    char *bufp;
-    struct obj bareobj;
-    struct objclass saveobcls;
-    int otyp = obj->otyp;
-
-    /* suppress user-supplied name */
-    saveobcls.oc_uname = objects[otyp].oc_uname;
-    objects[otyp].oc_uname = 0;
-    /* suppress actual name if object's description is unknown */
-    saveobcls.oc_name_known = objects[otyp].oc_name_known;
-    if (!obj->dknown)
-        objects[otyp].oc_name_known = 0;
-
-    /* caveat: this makes a lot of assumptions about which fields
-       are required in order for xname() to yield a sensible result */
-    bareobj = zeroobj;
-    bareobj.otyp = otyp;
-    bareobj.oclass = obj->oclass;
-    bareobj.dknown = obj->dknown;
-    /* suppress known except for amulets (needed for fakes and real A-of-Y) */
-    bareobj.known = (obj->oclass == AMULET_CLASS)
-                        ? obj->known
-                        /* default is "on" for types which don't use it */
-                        : !objects[otyp].oc_uses_known;
-    bareobj.quan = 1L;         /* don't want plural */
-    bareobj.corpsenm = NON_PM; /* suppress statue and figurine details */
-    /* but suppressing fruit details leads to "bad fruit #0"
-       [perhaps we should force "slime mold" rather than use xname?] */
-    if (obj->otyp == SLIME_MOLD)
-        bareobj.spe = obj->spe;
-
-    bufp = distant_name(&bareobj, xname); /* xname(&bareobj) */
-    if (!strncmp(bufp, "uncursed ", 9))
-        bufp += 9; /* Role_if(PM_PRIEST) */
-
-    objects[otyp].oc_uname = saveobcls.oc_uname;
-    objects[otyp].oc_name_known = saveobcls.oc_name_known;
-    return bufp;
-}
-
-/* xname() output augmented for multishot missile feedback */
-char *
-mshot_xname(obj)
-struct obj *obj;
-{
-    char tmpbuf[BUFSZ];
-    char *onm = xname(obj);
-
-    if (m_shot.n > 1 && m_shot.o == obj->otyp) {
-        /* "the Nth arrow"; value will eventually be passed to an() or
-           The(), both of which correctly handle this "the " prefix */
-        Sprintf(tmpbuf, "the %d%s ", m_shot.i, ordin(m_shot.i));
-        onm = strprepend(onm, tmpbuf);
-    }
-    return onm;
-}
-
-/* used for naming "the unique_item" instead of "a unique_item" */
-boolean
-the_unique_obj(obj)
-struct obj *obj;
-{
-    boolean known = (obj->known || iflags.override_ID);
-
-    if (!obj->dknown && !iflags.override_ID)
-        return FALSE;
-    else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !known)
-        return TRUE; /* lie */
-    else
-        return (boolean) (objects[obj->otyp].oc_unique
-                          && (known || obj->otyp == AMULET_OF_YENDOR));
-}
-
-/* should monster type be prefixed with "the"? (mostly used for corpses) */
-boolean
-the_unique_pm(ptr)
-struct permonst *ptr;
-{
-    boolean uniq;
-
-    /* even though monsters with personal names are unique, we want to
-       describe them as "Name" rather than "the Name" */
-    if (type_is_pname(ptr))
-        return FALSE;
-
-    uniq = (ptr->geno & G_UNIQ) ? TRUE : FALSE;
-    /* high priest is unique if it includes "of <deity>", otherwise not
-       (caller needs to handle the 1st possibility; we assume the 2nd);
-       worm tail should be irrelevant but is included for completeness */
-    if (ptr == &mons[PM_HIGH_PRIEST] || ptr == &mons[PM_LONG_WORM_TAIL])
-        uniq = FALSE;
-    /* Wizard no longer needs this; he's flagged as unique these days */
-    if (ptr == &mons[PM_WIZARD_OF_YENDOR])
-        uniq = TRUE;
-    return uniq;
-}
-
-STATIC_OVL void
-add_erosion_words(obj, prefix)
-struct obj *obj;
-char *prefix;
-{
-    boolean iscrys = (obj->otyp == CRYSKNIFE);
-    boolean rknown;
-
-    rknown = (iflags.override_ID == 0) ? obj->rknown : TRUE;
-
-    if (!is_damageable(obj) && !iscrys)
-        return;
-
-    /* The only cases where any of these bits do double duty are for
-     * rotted food and diluted potions, which are all not is_damageable().
-     */
-    if (obj->oeroded && !iscrys) {
-        switch (obj->oeroded) {
-        case 2:
-            Strcat(prefix, "very ");
-            break;
-        case 3:
-            Strcat(prefix, "thoroughly ");
-            break;
-        }
-        Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
-    }
-    if (obj->oeroded2 && !iscrys) {
-        switch (obj->oeroded2) {
-        case 2:
-            Strcat(prefix, "very ");
-            break;
-        case 3:
-            Strcat(prefix, "thoroughly ");
-            break;
-        }
-        Strcat(prefix, is_corrodeable(obj) ? "corroded " : "rotted ");
-    }
-    if (rknown && obj->oerodeproof)
-        Strcat(prefix, iscrys
-                          ? "fixed "
-                          : is_rustprone(obj)
-                             ? "rustproof "
-                             : is_corrodeable(obj)
-                                ? "corrodeproof " /* "stainless"? */
-                                : is_flammable(obj)
-                                   ? "fireproof "
-                                   : "");
-}
-
-/* used to prevent rust on items where rust makes no difference */
-boolean
-erosion_matters(obj)
-struct obj *obj;
-{
-    switch (obj->oclass) {
-    case TOOL_CLASS:
-        /* it's possible for a rusty weptool to be polymorphed into some
-           non-weptool iron tool, in which case the rust implicitly goes
-           away, but it's also possible for it to be polymorphed into a
-           non-iron tool, in which case rust also implicitly goes away,
-           so there's no particular reason to try to handle the first
-           instance differently [this comment belongs in poly_obj()...] */
-        return is_weptool(obj) ? TRUE : FALSE;
-    case WEAPON_CLASS:
-    case ARMOR_CLASS:
-    case BALL_CLASS:
-    case CHAIN_CLASS:
-        return TRUE;
-    default:
-        break;
-    }
-    return FALSE;
-}
-
-#define DONAME_WITH_PRICE 1
-#define DONAME_VAGUE_QUAN 2
-
-STATIC_OVL char *
-doname_base(obj, doname_flags)
-struct obj *obj;
-unsigned doname_flags;
-{
-    boolean ispoisoned = FALSE,
-            with_price = (doname_flags & DONAME_WITH_PRICE) != 0,
-            vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0;
-    boolean known, dknown, cknown, bknown, lknown;
-    int omndx = obj->corpsenm;
-    char prefix[PREFIX];
-    char tmpbuf[PREFIX + 1]; /* for when we have to add something at
-                                the start of prefix instead of the
-                                end (Strcat is used on the end) */
-    register char *bp = xname(obj);
-
-    if (iflags.override_ID) {
-        known = dknown = cknown = bknown = lknown = TRUE;
-    } else {
-        known = obj->known;
-        dknown = obj->dknown;
-        cknown = obj->cknown;
-        bknown = obj->bknown;
-        lknown = obj->lknown;
-    }
-
-    /* When using xname, we want "poisoned arrow", and when using
-     * doname, we want "poisoned +0 arrow".  This kludge is about the only
-     * way to do it, at least until someone overhauls xname() and doname(),
-     * combining both into one function taking a parameter.
-     */
-    /* must check opoisoned--someone can have a weirdly-named fruit */
-    if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
-        bp += 9;
-        ispoisoned = TRUE;
-    }
-
-    if (obj->quan != 1L) {
-        if (dknown || !vague_quan)
-            Sprintf(prefix, "%ld ", obj->quan);
-        else
-            Strcpy(prefix, "some ");
-    } 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;
-        Strcpy(prefix, "the ");
-    } else {
-        Strcpy(prefix, "a ");
-    }
-
-    /* "empty" goes at the beginning, but item count goes at the end */
-    if (cknown
-        /* bag of tricks: include "empty" prefix if it's known to
-           be empty but its precise number of charges isn't known
-           (when that is known, suffix of "(n:0)" will be appended,
-           making the prefix be redundant; note that 'known' flag
-           isn't set when emptiness gets discovered because then
-           charging magic would yield known number of new charges) */
-        && ((obj->otyp == BAG_OF_TRICKS)
-             ? (obj->spe == 0 && !obj->known)
-             /* not bag of tricks: empty if container which has no contents */
-             : ((Is_container(obj) || obj->otyp == STATUE)
-                && !Has_contents(obj))))
-        Strcat(prefix, "empty ");
-
-    if (bknown && obj->oclass != COIN_CLASS
-        && (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
-            || (!obj->cursed && !obj->blessed))) {
-        /* allow 'blessed clear potion' if we don't know it's holy water;
-         * always allow "uncursed potion of water"
-         */
-        if (obj->cursed)
-            Strcat(prefix, "cursed ");
-        else if (obj->blessed)
-            Strcat(prefix, "blessed ");
-        else if (!iflags.implicit_uncursed
-            /* For most items with charges or +/-, if you know how many
-             * charges are left or what the +/- is, then you must have
-             * totally identified the item, so "uncursed" is unnecessary,
-             * because an identified object not described as "blessed" or
-             * "cursed" must be uncursed.
-             *
-             * If the charges or +/- is not known, "uncursed" must be
-             * printed to avoid ambiguity between an item whose curse
-             * status is unknown, and an item known to be uncursed.
-             */
-                 || ((!known || !objects[obj->otyp].oc_charged
-                      || obj->oclass == ARMOR_CLASS
-                      || obj->oclass == RING_CLASS)
-#ifdef MAIL
-                     && obj->otyp != SCR_MAIL
-#endif
-                     && obj->otyp != FAKE_AMULET_OF_YENDOR
-                     && obj->otyp != AMULET_OF_YENDOR
-                     && !Role_if(PM_PRIEST)))
-            Strcat(prefix, "uncursed ");
-    }
-
-    if (lknown && Is_box(obj)) {
-        if (obj->obroken)
-            /* 3.6.0 used an "unlockable" prefix here but that could be
-               misunderstood to mean "capable of being unlocked" rather
-               than the intended "not capable of being locked" */
-            Strcat(bp, " with a broken lock");
-        else if (obj->olocked)
-            Strcat(prefix, "locked ");
-        else
-            Strcat(prefix, "unlocked ");
-    }
-
-    if (obj->greased)
-        Strcat(prefix, "greased ");
-
-    if (cknown && Has_contents(obj)) {
-        /* we count the number of separate stacks, which corresponds
-           to the number of inventory slots needed to be able to take
-           everything out if no merges occur */
-        long itemcount = count_contents(obj, FALSE, FALSE, TRUE);
-
-        Sprintf(eos(bp), " containing %ld item%s", itemcount,
-                plur(itemcount));
-    }
-
-    switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
-    case AMULET_CLASS:
-        if (obj->owornmask & W_AMUL)
-            Strcat(bp, " (being worn)");
-        break;
-    case ARMOR_CLASS:
-        if (obj->owornmask & W_ARMOR)
-            Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
-                                      : " (being worn)");
-        /*FALLTHRU*/
-    case WEAPON_CLASS:
-        if (ispoisoned)
-            Strcat(prefix, "poisoned ");
-        add_erosion_words(obj, prefix);
-        if (known) {
-            Strcat(prefix, sitoa(obj->spe));
-            Strcat(prefix, " ");
-        }
-        break;
-    case TOOL_CLASS:
-        if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
-            Strcat(bp, " (being worn)");
-            break;
-        }
-        if (obj->otyp == LEASH && obj->leashmon != 0) {
-            struct monst *mlsh = find_mid(obj->leashmon, FM_FMON);
-
-            if (!mlsh) {
-                impossible("leashed monster not on this level");
-                obj->leashmon = 0;
-            } else {
-                Sprintf(eos(bp), " (attached to %s)",
-                        a_monnam(mlsh));
-            }
-            break;
-        }
-        if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
-            if (!obj->spe)
-                Strcpy(tmpbuf, "no");
-            else
-                Sprintf(tmpbuf, "%d", obj->spe);
-            Sprintf(eos(bp), " (%s candle%s%s)", tmpbuf, plur(obj->spe),
-                    !obj->lamplit ? " attached" : ", lit");
-            break;
-        } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
-                   || obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
-            if (Is_candle(obj)
-                && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
-                Strcat(prefix, "partly used ");
-            if (obj->lamplit)
-                Strcat(bp, " (lit)");
-            break;
-        }
-        if (objects[obj->otyp].oc_charged)
-            goto charges;
-        break;
-    case WAND_CLASS:
-    charges:
-        if (known)
-            Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
-        break;
-    case POTION_CLASS:
-        if (obj->otyp == POT_OIL && obj->lamplit)
-            Strcat(bp, " (lit)");
-        break;
-    case RING_CLASS:
-    ring:
-        if (obj->owornmask & W_RINGR)
-            Strcat(bp, " (on right ");
-        if (obj->owornmask & W_RINGL)
-            Strcat(bp, " (on left ");
-        if (obj->owornmask & W_RING) {
-            Strcat(bp, body_part(HAND));
-            Strcat(bp, ")");
-        }
-        if (known && objects[obj->otyp].oc_charged) {
-            Strcat(prefix, sitoa(obj->spe));
-            Strcat(prefix, " ");
-        }
-        break;
-    case FOOD_CLASS:
-        if (obj->oeaten)
-            Strcat(prefix, "partly eaten ");
-        if (obj->otyp == CORPSE) {
-            /* (quan == 1) => want corpse_xname() to supply article,
-               (quan != 1) => already have count or "some" as prefix;
-               "corpse" is already in the buffer returned by xname() */
-            unsigned cxarg = (((obj->quan != 1L) ? 0 : CXN_ARTICLE)
-                              | CXN_NOCORPSE);
-            char *cxstr = corpse_xname(obj, prefix, cxarg);
-
-            Sprintf(prefix, "%s ", cxstr);
-            /* avoid having doname(corpse) consume an extra obuf */
-            releaseobuf(cxstr);
-        } else if (obj->otyp == EGG) {
-#if 0 /* corpses don't tell if they're stale either */
-            if (known && stale_egg(obj))
-                Strcat(prefix, "stale ");
-#endif
-            if (omndx >= LOW_PM
-                && (known || (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
-                Strcat(prefix, mons[omndx].mname);
-                Strcat(prefix, " ");
-                if (obj->spe)
-                    Strcat(bp, " (laid by you)");
-            }
-        }
-        if (obj->otyp == MEAT_RING)
-            goto ring;
-        break;
-    case BALL_CLASS:
-    case CHAIN_CLASS:
-        add_erosion_words(obj, prefix);
-        if (obj->owornmask & W_BALL)
-            Strcat(bp, " (chained to you)");
-        break;
-    }
-
-    if ((obj->owornmask & W_WEP) && !mrg_to_wielded) {
-        if (obj->quan != 1L) {
-            Strcat(bp, " (wielded)");
-        } else {
-            const char *hand_s = body_part(HAND);
-
-            if (bimanual(obj))
-                hand_s = makeplural(hand_s);
-            Sprintf(eos(bp), " (weapon in %s)", hand_s);
-
-            if (warn_obj_cnt && obj == uwep && (EWarn_of_mon & W_WEP) != 0L) {
-                /* presumably can be felt when blind */
-                Strcat(bp, " (glowing");
-                if (!Blind)
-                    Sprintf(eos(bp), " %s", glow_color(obj->oartifact));
-                Strcat(bp, ")");
-            }
-        }
-    }
-    if (obj->owornmask & W_SWAPWEP) {
-        if (u.twoweap)
-            Sprintf(eos(bp), " (wielded in other %s)", body_part(HAND));
-        else
-            Strcat(bp, " (alternate weapon; not wielded)");
-    }
-    if (obj->owornmask & W_QUIVER) {
-        switch (obj->oclass) {
-        case WEAPON_CLASS:
-            if (is_ammo(obj)) {
-                if (objects[obj->otyp].oc_skill == -P_BOW) {
-                    /* Ammo for a bow */
-                    Strcat(bp, " (in quiver)");
-                    break;
-                } else {
-                    /* Ammo not for a bow */
-                    Strcat(bp, " (in quiver pouch)");
-                    break;
-                }
-            } else {
-                /* Weapons not considered ammo */
-                Strcat(bp, " (at the ready)");
-                break;
-            }
-        /* Small things and ammo not for a bow */
-        case RING_CLASS:
-        case AMULET_CLASS:
-        case WAND_CLASS:
-        case COIN_CLASS:
-        case GEM_CLASS:
-            Strcat(bp, " (in quiver pouch)");
-            break;
-        default: /* odd things */
-            Strcat(bp, " (at the ready)");
-        }
-    }
-    if (!iflags.suppress_price && is_unpaid(obj)) {
-        long quotedprice = unpaid_cost(obj, TRUE);
-
-        Sprintf(eos(bp), " (%s, %ld %s)",
-                obj->unpaid ? "unpaid" : "contents",
-                quotedprice, currency(quotedprice));
-    } else if (with_price) {
-        long price = get_cost_of_shop_item(obj);
-
-        if (price > 0)
-            Sprintf(eos(bp), " (%ld %s)", price, currency(price));
-    }
-    if (!strncmp(prefix, "a ", 2)
-        && index(vowels, *(prefix + 2) ? *(prefix + 2) : *bp)
-        && (*(prefix + 2)
-            || (strncmp(bp, "uranium", 7) && strncmp(bp, "unicorn", 7)
-                && strncmp(bp, "eucalyptus", 10)))) {
-        Strcpy(tmpbuf, prefix);
-        Strcpy(prefix, "an ");
-        Strcpy(prefix + 3, tmpbuf + 2);
-    }
-
-    /* show weight for items (debug tourist info)
-     * aum is stolen from Crawl's "Arbitrary Unit of Measure" */
-    if (wizard && iflags.wizweight) {
-        Sprintf(eos(bp), " (%d aum)", obj->owt);
-    }
-    bp = strprepend(bp, prefix);
-    return bp;
-}
-
-char *
-doname(obj)
-struct obj *obj;
-{
-    return doname_base(obj, (unsigned) 0);
-}
-
-/* Name of object including price. */
-char *
-doname_with_price(obj)
-struct obj *obj;
-{
-    return doname_base(obj, DONAME_WITH_PRICE);
-}
-
-/* "some" instead of precise quantity if obj->dknown not set */
-char *
-doname_vague_quan(obj)
-struct obj *obj;
-{
-    /* Used by farlook.
-     * If it hasn't been seen up close and quantity is more than one,
-     * use "some" instead of the quantity: "some gold pieces" rather
-     * than "25 gold pieces".  This is suboptimal, to put it mildly,
-     * because lookhere and pickup report the precise amount.
-     * Picking the item up while blind also shows the precise amount
-     * for inventory display, then dropping it while still blind leaves
-     * obj->dknown unset so the count reverts to "some" for farlook.
-     *
-     * TODO: add obj->qknown flag for 'quantity known' on stackable
-     * items; it could overlay obj->cknown since no containers stack.
-     */
-    return doname_base(obj, DONAME_VAGUE_QUAN);
-}
-
-/* used from invent.c */
-boolean
-not_fully_identified(otmp)
-struct obj *otmp;
-{
-    /* gold doesn't have any interesting attributes [yet?] */
-    if (otmp->oclass == COIN_CLASS)
-        return FALSE; /* always fully ID'd */
-    /* check fundamental ID hallmarks first */
-    if (!otmp->known || !otmp->dknown
-#ifdef MAIL
-        || (!otmp->bknown && otmp->otyp != SCR_MAIL)
-#else
-        || !otmp->bknown
-#endif
-        || !objects[otmp->otyp].oc_name_known)
-        return TRUE;
-    if ((!otmp->cknown && (Is_container(otmp) || otmp->otyp == STATUE))
-        || (!otmp->lknown && Is_box(otmp)))
-        return TRUE;
-    if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
-        return TRUE;
-    /* otmp->rknown is the only item of interest if we reach here */
-    /*
-     *  Note:  if a revision ever allows scrolls to become fireproof or
-     *  rings to become shockproof, this checking will need to be revised.
-     *  `rknown' ID only matters if xname() will provide the info about it.
-     */
-    if (otmp->rknown
-        || (otmp->oclass != ARMOR_CLASS && otmp->oclass != WEAPON_CLASS
-            && !is_weptool(otmp)            /* (redundant) */
-            && otmp->oclass != BALL_CLASS)) /* (useless) */
-        return FALSE;
-    else /* lack of `rknown' only matters for vulnerable objects */
-        return (boolean) (is_rustprone(otmp) || is_corrodeable(otmp)
-                          || is_flammable(otmp));
-}
-
-/* format a corpse name (xname() omits monster type; doname() calls us);
-   eatcorpse() also uses us for death reason when eating tainted glob */
-char *
-corpse_xname(otmp, adjective, cxn_flags)
-struct obj *otmp;
-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,
-        glob = (otmp->otyp != CORPSE && otmp->globby);
-    const char *mname;
-
-    if (glob) {
-        mname = OBJ_NAME(objects[otmp->otyp]); /* "glob of <monster>" */
-    } else 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.] */
-    } 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])) {
-            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;
-        }
-    }
-    if (no_prefix)
-        the_prefix = any_prefix = FALSE;
-    else if (the_prefix)
-        any_prefix = FALSE; /* mutually exclusive */
-
-    *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 (glob) {
-        ; /* omit_corpse doesn't apply; quantity is always 1 */
-    } else if (!omit_corpse) {
-        Strcat(nambuf, " corpse");
-        /* makeplural(nambuf) => append "s" to "corpse" */
-        if (otmp->quan > 1L && !ignore_quan) {
-            Strcat(nambuf, "s");
-            any_prefix = FALSE; /* avoid "a newt corpses" */
-        }
-    }
-
-    /* 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 doesn't include monster type for "corpse"; cxname does */
-char *
-cxname(obj)
-struct obj *obj;
-{
-    if (obj->otyp == CORPSE)
-        return corpse_xname(obj, (const char *) 0, CXN_NORMAL);
-    return xname(obj);
-}
-
-/* like cxname, but ignores quantity */
-char *
-cxname_singular(obj)
-struct obj *obj;
-{
-    if (obj->otyp == CORPSE)
-        return corpse_xname(obj, (const char *) 0, CXN_SINGULAR);
-    return xname_flags(obj, CXN_SINGULAR);
-}
-
-/* treat an object as fully ID'd when it might be used as reason for death */
-char *
-killer_xname(obj)
-struct obj *obj;
-{
-    struct obj save_obj;
-    unsigned save_ocknown;
-    char *buf, *save_ocuname, *save_oname = (char *) 0;
-
-    /* bypass object twiddling for artifacts */
-    if (obj->oartifact)
-        return bare_artifactname(obj);
-
-    /* remember original settings for core of the object;
-       oextra structs other than oname don't matter here--since they
-       aren't modified they don't need to be saved and restored */
-    save_obj = *obj;
-    if (has_oname(obj))
-        save_oname = ONAME(obj);
-
-    /* killer name should be more specific than general xname; however, exact
-       info like blessed/cursed and rustproof makes things be too verbose */
-    obj->known = obj->dknown = 1;
-    obj->bknown = obj->rknown = obj->greased = 0;
-    /* if character is a priest[ess], bknown will get toggled back on */
-    if (obj->otyp != POT_WATER)
-        obj->blessed = obj->cursed = 0;
-    else
-        obj->bknown = 1; /* describe holy/unholy water as such */
-    /* "killed by poisoned <obj>" would be misleading when poison is
-       not the cause of death and "poisoned by poisoned <obj>" would
-       be redundant when it is, so suppress "poisoned" prefix */
-    obj->opoisoned = 0;
-    /* strip user-supplied name; artifacts keep theirs */
-    if (!obj->oartifact && save_oname)
-        ONAME(obj) = (char *) 0;
-    /* temporarily identify the type of object */
-    save_ocknown = objects[obj->otyp].oc_name_known;
-    objects[obj->otyp].oc_name_known = 1;
-    save_ocuname = objects[obj->otyp].oc_uname;
-    objects[obj->otyp].oc_uname = 0; /* avoid "foo called bar" */
-
-    /* format the object */
-    if (obj->otyp == CORPSE) {
-        buf = nextobuf();
-        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
-           those can be used to fake other objects and dungeon features */
-        buf = nextobuf();
-        Sprintf(buf, "deadly slime mold%s", plur(obj->quan));
-    } else {
-        buf = xname(obj);
-    }
-    /* apply an article if appropriate; caller should always use KILLED_BY */
-    if (obj->quan == 1L && !strstri(buf, "'s ") && !strstri(buf, "s' "))
-        buf = (obj_is_pname(obj) || the_unique_obj(obj)) ? the(buf) : an(buf);
-
-    objects[obj->otyp].oc_name_known = save_ocknown;
-    objects[obj->otyp].oc_uname = save_ocuname;
-    *obj = save_obj; /* restore object's core settings */
-    if (!obj->oartifact && save_oname)
-        ONAME(obj) = save_oname;
-
-    return buf;
-}
-
-/* xname,doname,&c with long results reformatted to omit some stuff */
-char *
-short_oname(obj, func, altfunc, lenlimit)
-struct obj *obj;
-char *FDECL((*func), (OBJ_P)),    /* main formatting routine */
-     *FDECL((*altfunc), (OBJ_P)); /* alternate for shortest result */
-unsigned lenlimit;
-{
-    struct obj save_obj;
-    char unamebuf[12], onamebuf[12], *save_oname, *save_uname, *outbuf;
-
-    outbuf = (*func)(obj);
-    if ((unsigned) strlen(outbuf) <= lenlimit)
-        return outbuf;
-
-    /* shorten called string to fairly small amount */
-    save_uname = objects[obj->otyp].oc_uname;
-    if (save_uname && strlen(save_uname) >= sizeof unamebuf) {
-        (void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
-        Strcpy(unamebuf + sizeof unamebuf - 4, "...");
-        objects[obj->otyp].oc_uname = unamebuf;
-        releaseobuf(outbuf);
-        outbuf = (*func)(obj);
-        objects[obj->otyp].oc_uname = save_uname; /* restore called string */
-        if ((unsigned) strlen(outbuf) <= lenlimit)
-            return outbuf;
-    }
-
-    /* shorten named string to fairly small amount */
-    save_oname = has_oname(obj) ? ONAME(obj) : 0;
-    if (save_oname && strlen(save_oname) >= sizeof onamebuf) {
-        (void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
-        Strcpy(onamebuf + sizeof onamebuf - 4, "...");
-        ONAME(obj) = onamebuf;
-        releaseobuf(outbuf);
-        outbuf = (*func)(obj);
-        ONAME(obj) = save_oname; /* restore named string */
-        if ((unsigned) strlen(outbuf) <= lenlimit)
-            return outbuf;
-    }
-
-    /* shorten both called and named strings;
-       unamebuf and onamebuf have both already been populated */
-    if (save_uname && strlen(save_uname) >= sizeof unamebuf && save_oname
-        && strlen(save_oname) >= sizeof onamebuf) {
-        objects[obj->otyp].oc_uname = unamebuf;
-        ONAME(obj) = onamebuf;
-        releaseobuf(outbuf);
-        outbuf = (*func)(obj);
-        if ((unsigned) strlen(outbuf) <= lenlimit) {
-            objects[obj->otyp].oc_uname = save_uname;
-            ONAME(obj) = save_oname;
-            return outbuf;
-        }
-    }
-
-    /* still long; strip several name-lengthening attributes;
-       called and named strings are still in truncated form */
-    save_obj = *obj;
-    obj->bknown = obj->rknown = obj->greased = 0;
-    obj->oeroded = obj->oeroded2 = 0;
-    releaseobuf(outbuf);
-    outbuf = (*func)(obj);
-    if (altfunc && (unsigned) strlen(outbuf) > lenlimit) {
-        /* still long; use the alternate function (usually one of
-           the jackets around minimal_xname()) */
-        releaseobuf(outbuf);
-        outbuf = (*altfunc)(obj);
-    }
-    /* restore the object */
-    *obj = save_obj;
-    if (save_oname)
-        ONAME(obj) = save_oname;
-    if (save_uname)
-        objects[obj->otyp].oc_uname = save_uname;
-
-    /* use whatever we've got, whether it's too long or not */
-    return outbuf;
-}
-
-/*
- * Used if only one of a collection of objects is named (e.g. in eat.c).
- */
-const char *
-singular(otmp, func)
-register struct obj *otmp;
-char *FDECL((*func), (OBJ_P));
-{
-    long savequan;
-    char *nam;
-
-    /* using xname for corpses does not give the monster type */
-    if (otmp->otyp == CORPSE && func == xname)
-        func = cxname;
-
-    savequan = otmp->quan;
-    otmp->quan = 1L;
-    nam = (*func)(otmp);
-    otmp->quan = savequan;
-    return nam;
-}
-
-char *
-an(str)
-register const char *str;
-{
-    char *buf = nextobuf();
-
-    buf[0] = '\0';
-
-    if (strncmpi(str, "the ", 4) && strcmp(str, "molten lava")
-        && strcmp(str, "iron bars") && strcmp(str, "ice")) {
-        if (index(vowels, *str) && strncmp(str, "one-", 4)
-            && strncmp(str, "useful", 6) && strncmp(str, "unicorn", 7)
-            && strncmp(str, "uranium", 7) && strncmp(str, "eucalyptus", 10))
-            Strcpy(buf, "an ");
-        else
-            Strcpy(buf, "a ");
-    }
-
-    Strcat(buf, str);
-    return buf;
-}
-
-char *
-An(str)
-const char *str;
-{
-    char *tmp = an(str);
-
-    *tmp = highc(*tmp);
-    return tmp;
-}
-
-/*
- * Prepend "the" if necessary; assumes str is a subject derived from xname.
- * Use type_is_pname() for monster names, not the().  the() is idempotent.
- */
-char *
-the(str)
-const char *str;
-{
-    char *buf = nextobuf();
-    boolean insert_the = FALSE;
-
-    if (!strncmpi(str, "the ", 4)) {
-        buf[0] = lowc(*str);
-        Strcpy(&buf[1], str + 1);
-        return buf;
-    } else if (*str < 'A' || *str > 'Z'
-               /* treat named fruit as not a proper name, even if player
-                  has assigned a capitalized proper name as his/her fruit */
-               || fruit_from_name(str, TRUE, (int *) 0)) {
-        /* not a proper name, needs an article */
-        insert_the = TRUE;
-    } else {
-        /* Probably a proper name, might not need an article */
-        register char *tmp, *named, *called;
-        int l;
-
-        /* some objects have capitalized adjectives in their names */
-        if (((tmp = rindex(str, ' ')) != 0 || (tmp = rindex(str, '-')) != 0)
-            && (tmp[1] < 'A' || tmp[1] > 'Z')) {
-            insert_the = TRUE;
-        } else if (tmp && index(str, ' ') < tmp) { /* has spaces */
-            /* it needs an article if the name contains "of" */
-            tmp = strstri(str, " of ");
-            named = strstri(str, " named ");
-            called = strstri(str, " called ");
-            if (called && (!named || called < named))
-                named = called;
-
-            if (tmp && (!named || tmp < named)) /* found an "of" */
-                insert_the = TRUE;
-            /* stupid special case: lacks "of" but needs "the" */
-            else if (!named && (l = strlen(str)) >= 31
-                     && !strcmp(&str[l - 31],
-                                "Platinum Yendorian Express Card"))
-                insert_the = TRUE;
-        }
-    }
-    if (insert_the)
-        Strcpy(buf, "the ");
-    else
-        buf[0] = '\0';
-    Strcat(buf, str);
-
-    return buf;
-}
-
-char *
-The(str)
-const char *str;
-{
-    char *tmp = the(str);
-
-    *tmp = highc(*tmp);
-    return tmp;
-}
-
-/* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */
-char *
-aobjnam(otmp, verb)
-struct obj *otmp;
-const char *verb;
-{
-    char prefix[PREFIX];
-    char *bp = cxname(otmp);
-
-    if (otmp->quan != 1L) {
-        Sprintf(prefix, "%ld ", otmp->quan);
-        bp = strprepend(bp, prefix);
-    }
-    if (verb) {
-        Strcat(bp, " ");
-        Strcat(bp, otense(otmp, verb));
-    }
-    return bp;
-}
-
-/* combine yname and aobjnam eg "your count cxname(otmp)" */
-char *
-yobjnam(obj, verb)
-struct obj *obj;
-const char *verb;
-{
-    char *s = aobjnam(obj, verb);
-
-    /* leave off "your" for most of your artifacts, but prepend
-     * "your" for unique objects and "foo of bar" quest artifacts */
-    if (!carried(obj) || !obj_is_pname(obj)
-        || obj->oartifact >= ART_ORB_OF_DETECTION) {
-        char *outbuf = shk_your(nextobuf(), obj);
-        int space_left = BUFSZ - 1 - strlen(outbuf);
-
-        s = strncat(outbuf, s, space_left);
-    }
-    return s;
-}
-
-/* combine Yname2 and aobjnam eg "Your count cxname(otmp)" */
-char *
-Yobjnam2(obj, verb)
-struct obj *obj;
-const char *verb;
-{
-    register char *s = yobjnam(obj, verb);
-
-    *s = highc(*s);
-    return s;
-}
-
-/* like aobjnam, but prepend "The", not count, and use xname */
-char *
-Tobjnam(otmp, verb)
-struct obj *otmp;
-const char *verb;
-{
-    char *bp = The(xname(otmp));
-
-    if (verb) {
-        Strcat(bp, " ");
-        Strcat(bp, otense(otmp, verb));
-    }
-    return bp;
-}
-
-/* capitalized variant of doname() */
-char *
-Doname2(obj)
-struct obj *obj;
-{
-    char *s = doname(obj);
-
-    *s = highc(*s);
-    return s;
-}
-
-/* returns "[your ]xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
-char *
-yname(obj)
-struct obj *obj;
-{
-    char *s = cxname(obj);
-
-    /* leave off "your" for most of your artifacts, but prepend
-     * "your" for unique objects and "foo of bar" quest artifacts */
-    if (!carried(obj) || !obj_is_pname(obj)
-        || obj->oartifact >= ART_ORB_OF_DETECTION) {
-        char *outbuf = shk_your(nextobuf(), obj);
-        int space_left = BUFSZ - 1 - strlen(outbuf);
-
-        s = strncat(outbuf, s, space_left);
-    }
-
-    return s;
-}
-
-/* capitalized variant of yname() */
-char *
-Yname2(obj)
-struct obj *obj;
-{
-    char *s = yname(obj);
-
-    *s = highc(*s);
-    return s;
-}
-
-/* returns "your minimal_xname(obj)"
- * or "Foobar's minimal_xname(obj)"
- * or "the minimal_xname(obj)"
- */
-char *
-ysimple_name(obj)
-struct obj *obj;
-{
-    char *outbuf = nextobuf();
-    char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
-    int space_left = BUFSZ - 1 - strlen(s);
-
-    return strncat(s, minimal_xname(obj), space_left);
-}
-
-/* capitalized variant of ysimple_name() */
-char *
-Ysimple_name2(obj)
-struct obj *obj;
-{
-    char *s = ysimple_name(obj);
-
-    *s = highc(*s);
-    return s;
-}
-
-/* "scroll" or "scrolls" */
-char *
-simpleonames(obj)
-struct obj *obj;
-{
-    char *simpleoname = minimal_xname(obj);
-
-    if (obj->quan != 1L)
-        simpleoname = makeplural(simpleoname);
-    return simpleoname;
-}
-
-/* "a scroll" or "scrolls"; "a silver bell" or "the Bell of Opening" */
-char *
-ansimpleoname(obj)
-struct obj *obj;
-{
-    char *simpleoname = simpleonames(obj);
-    int otyp = obj->otyp;
-
-    /* prefix with "the" if a unique item, or a fake one imitating same,
-       has been formatted with its actual name (we let typename() handle
-       any `known' and `dknown' checking necessary) */
-    if (otyp == FAKE_AMULET_OF_YENDOR)
-        otyp = AMULET_OF_YENDOR;
-    if (objects[otyp].oc_unique
-        && !strcmp(simpleoname, OBJ_NAME(objects[otyp])))
-        return the(simpleoname);
-
-    /* simpleoname is singular if quan==1, plural otherwise */
-    if (obj->quan == 1L)
-        simpleoname = an(simpleoname);
-    return simpleoname;
-}
-
-/* "the scroll" or "the scrolls" */
-char *
-thesimpleoname(obj)
-struct obj *obj;
-{
-    char *simpleoname = simpleonames(obj);
-
-    return the(simpleoname);
-}
-
-/* artifact's name without any object type or known/dknown/&c feedback */
-char *
-bare_artifactname(obj)
-struct obj *obj;
-{
-    char *outbuf;
-
-    if (obj->oartifact) {
-        outbuf = nextobuf();
-        Strcpy(outbuf, artiname(obj->oartifact));
-        if (!strncmp(outbuf, "The ", 4))
-            outbuf[0] = lowc(outbuf[0]);
-    } else {
-        outbuf = xname(obj);
-    }
-    return outbuf;
-}
-
-static const char *wrp[] = {
-    "wand",   "ring",      "potion",     "scroll", "gem",
-    "amulet", "spellbook", "spell book",
-    /* for non-specific wishes */
-    "weapon", "armor",     "tool",       "food",   "comestible",
-};
-static const char wrpsym[] = { WAND_CLASS,   RING_CLASS,   POTION_CLASS,
-                               SCROLL_CLASS, GEM_CLASS,    AMULET_CLASS,
-                               SPBOOK_CLASS, SPBOOK_CLASS, WEAPON_CLASS,
-                               ARMOR_CLASS,  TOOL_CLASS,   FOOD_CLASS,
-                               FOOD_CLASS };
-
-/* return form of the verb (input plural) if xname(otmp) were the subject */
-char *
-otense(otmp, verb)
-struct obj *otmp;
-const char *verb;
-{
-    char *buf;
-
-    /*
-     * verb is given in plural (without trailing s).  Return as input
-     * if the result of xname(otmp) would be plural.  Don't bother
-     * recomputing xname(otmp) at this time.
-     */
-    if (!is_plural(otmp))
-        return vtense((char *) 0, verb);
-
-    buf = nextobuf();
-    Strcpy(buf, verb);
-    return buf;
-}
-
-/* various singular words that vtense would otherwise categorize as plural;
-   also used by makesingular() to catch some special cases */
-static const char *const special_subjs[] = {
-    "erinys",  "manes", /* this one is ambiguous */
-    "Cyclops", "Hippocrates",     "Pelias",    "aklys",
-    "amnesia", "detect monsters", "paralysis", "shape changers",
-    "nemesis", 0
-    /* note: "detect monsters" and "shape changers" are normally
-       caught via "<something>(s) of <whatever>", but they can be
-       wished for using the shorter form, so we include them here
-       to accommodate usage by makesingular during wishing */
-};
-
-/* return form of the verb (input plural) for present tense 3rd person subj */
-char *
-vtense(subj, verb)
-register const char *subj;
-register const char *verb;
-{
-    char *buf = nextobuf(), *bspot;
-    int len, ltmp;
-    const char *sp, *spot;
-    const char *const *spec;
-
-    /*
-     * verb is given in plural (without trailing s).  Return as input
-     * if subj appears to be plural.  Add special cases as necessary.
-     * Many hard cases can already be handled by using otense() instead.
-     * If this gets much bigger, consider decomposing makeplural.
-     * Note: monster names are not expected here (except before corpse).
-     *
-     * Special case: allow null sobj to get the singular 3rd person
-     * present tense form so we don't duplicate this code elsewhere.
-     */
-    if (subj) {
-        if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
-            goto sing;
-        spot = (const char *) 0;
-        for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
-            if (!strncmpi(sp, " of ", 4) || !strncmpi(sp, " from ", 6)
-                || !strncmpi(sp, " called ", 8) || !strncmpi(sp, " named ", 7)
-                || !strncmpi(sp, " labeled ", 9)) {
-                if (sp != subj)
-                    spot = sp - 1;
-                break;
-            }
-        }
-        len = (int) strlen(subj);
-        if (!spot)
-            spot = subj + len - 1;
-
-        /*
-         * plural: anything that ends in 's', but not '*us' or '*ss'.
-         * Guess at a few other special cases that makeplural creates.
-         */
-        if ((lowc(*spot) == 's' && spot != subj
-             && !index("us", lowc(*(spot - 1))))
-            || !BSTRNCMPI(subj, spot - 3, "eeth", 4)
-            || !BSTRNCMPI(subj, spot - 3, "feet", 4)
-            || !BSTRNCMPI(subj, spot - 1, "ia", 2)
-            || !BSTRNCMPI(subj, spot - 1, "ae", 2)) {
-            /* check for special cases to avoid false matches */
-            len = (int) (spot - subj) + 1;
-            for (spec = special_subjs; *spec; spec++) {
-                ltmp = strlen(*spec);
-                if (len == ltmp && !strncmpi(*spec, subj, len))
-                    goto sing;
-                /* also check for <prefix><space><special_subj>
-                   to catch things like "the invisible erinys" */
-                if (len > ltmp && *(spot - ltmp) == ' '
-                    && !strncmpi(*spec, spot - ltmp + 1, ltmp))
-                    goto sing;
-            }
-
-            return strcpy(buf, verb);
-        }
-        /*
-         * 3rd person plural doesn't end in telltale 's';
-         * 2nd person singular behaves as if plural.
-         */
-        if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
-            return strcpy(buf, verb);
-    }
-
-sing:
-    Strcpy(buf, verb);
-    len = (int) strlen(buf);
-    bspot = buf + len - 1;
-
-    if (!strcmpi(buf, "are")) {
-        Strcasecpy(buf, "is");
-    } else if (!strcmpi(buf, "have")) {
-        Strcasecpy(bspot - 1, "s");
-    } else if (index("zxs", lowc(*bspot))
-               || (len >= 2 && lowc(*bspot) == 'h'
-                   && index("cs", lowc(*(bspot - 1))))
-               || (len == 2 && lowc(*bspot) == 'o')) {
-        /* Ends in z, x, s, ch, sh; add an "es" */
-        Strcasecpy(bspot + 1, "es");
-    } else if (lowc(*bspot) == 'y' && !index(vowels, lowc(*(bspot - 1)))) {
-        /* like "y" case in makeplural */
-        Strcasecpy(bspot, "ies");
-    } else {
-        Strcasecpy(bspot + 1, "s");
-    }
-
-    return buf;
-}
-
-struct sing_plur {
-    const char *sing, *plur;
-};
-
-/* word pairs that don't fit into formula-based transformations;
-   also some suffices which have very few--often one--matches or
-   which aren't systematically reversible (knives, staves) */
-static struct sing_plur one_off[] = {
-    { "child",
-      "children" },      /* (for wise guys who give their food funny names) */
-    { "cubus", "cubi" }, /* in-/suc-cubus */
-    { "culus", "culi" }, /* homunculus */
-    { "djinni", "djinn" },
-    { "erinys", "erinyes" },
-    { "foot", "feet" },
-    { "fungus", "fungi" },
-    { "goose", "geese" },
-    { "knife", "knives" },
-    { "labrum", "labra" }, /* candelabrum */
-    { "louse", "lice" },
-    { "mouse", "mice" },
-    { "mumak", "mumakil" },
-    { "nemesis", "nemeses" },
-    { "ovum", "ova" },
-    { "ox", "oxen" },
-    { "passerby", "passersby" },
-    { "rtex", "rtices" }, /* vortex */
-    { "serum", "sera" },
-    { "staff", "staves" },
-    { "tooth", "teeth" },
-    { 0, 0 }
-};
-
-static const char *const as_is[] = {
-    /* makesingular() leaves these plural due to how they're used */
-    "boots",   "shoes",     "gloves",    "lenses",   "scales",
-    "eyes",    "gauntlets", "iron bars",
-    /* both singular and plural are spelled the same */
-    "bison",   "deer",      "elk",       "fish",      "fowl",
-    "tuna",    "yaki",      "-hai",      "krill",     "manes",
-    "moose",   "ninja",     "sheep",     "ronin",     "roshi",
-    "shito",   "tengu",     "ki-rin",    "Nazgul",    "gunyoki",
-    "piranha", "samurai",   "shuriken", 0,
-    /* Note:  "fish" and "piranha" are collective plurals, suitable
-       for "wiped out all <foo>".  For "3 <foo>", they should be
-       "fishes" and "piranhas" instead.  We settle for collective
-       variant instead of attempting to support both. */
-};
-
-/* singularize/pluralize decisions common to both makesingular & makeplural */
-STATIC_OVL boolean
-singplur_lookup(basestr, endstring, to_plural, alt_as_is)
-char *basestr, *endstring;    /* base string, pointer to eos(string) */
-boolean to_plural;            /* true => makeplural, false => makesingular */
-const char *const *alt_as_is; /* another set like as_is[] */
-{
-    const struct sing_plur *sp;
-    const char *same, *other, *const *as;
-    int al;
-
-    for (as = as_is; *as; ++as) {
-        al = (int) strlen(*as);
-        if (!BSTRCMPI(basestr, endstring - al, *as))
-            return TRUE;
-    }
-    if (alt_as_is) {
-        for (as = alt_as_is; *as; ++as) {
-            al = (int) strlen(*as);
-            if (!BSTRCMPI(basestr, endstring - al, *as))
-                return TRUE;
-        }
-    }
-
-    /* avoid false hit on one_off[].plur == "lice" or .sing == "goose";
-       if more of these turn up, one_off[] entries will need to flagged
-       as to which are whole words and which are matchable as suffices
-       then matching in the loop below will end up becoming more complex */
-    if (!strcmpi(basestr, "slice")
-        || !strcmpi(basestr, "mongoose")) {
-        if (to_plural)
-            Strcasecpy(endstring, "s");
-        return TRUE;
-    }
-    /* skip "ox" -> "oxen" entry when pluralizing "<something>ox"
-       unless it is muskox */
-    if (to_plural && strlen(basestr) > 2 && !strcmpi(endstring - 2, "ox")
-        && strcmpi(endstring - 6, "muskox")) {
-        /* "fox" -> "foxes" */
-        Strcasecpy(endstring, "es");
-        return TRUE;
-    }
-    if (to_plural) {
-        if (!strcmpi(endstring - 3, "man")
-            && badman(basestr, to_plural)) {
-            Strcasecpy(endstring, "s");
-            return TRUE;
-        }
-    } else {
-        if (!strcmpi(endstring - 3, "men")
-            && badman(basestr, to_plural))
-            return TRUE;
-    }
-    for (sp = one_off; sp->sing; sp++) {
-        /* check whether endstring already matches */
-        same = to_plural ? sp->plur : sp->sing;
-        al = (int) strlen(same);
-        if (!BSTRCMPI(basestr, endstring - al, same))
-            return TRUE; /* use as-is */
-        /* check whether it matches the inverse; if so, transform it */
-        other = to_plural ? sp->sing : sp->plur;
-        al = (int) strlen(other);
-        if (!BSTRCMPI(basestr, endstring - al, other)) {
-            Strcasecpy(endstring - al, same);
-            return TRUE; /* one_off[] transformation */
-        }
-    }
-    return FALSE;
-}
-
-/* searches for common compounds, ex. lump of royal jelly */
-STATIC_OVL char *
-singplur_compound(str)
-char *str;
-{
-    /* if new entries are added, be sure to keep compound_start[] in sync */
-    static const char *const compounds[] =
-        {
-          " of ",     " labeled ", " called ",
-          " named ",  " above", /* lurkers above */
-          " versus ", " from ",    " in ",
-          " on ",     " a la ",    " with", /* " with "? */
-          " de ",     " d'",       " du ",
-          "-in-",     "-at-",      0
-        }, /* list of first characters for all compounds[] entries */
-        compound_start[] = " -";
-
-    const char *const *cmpd;
-    char *p;
-
-    for (p = str; *p; ++p) {
-        /* substring starting at p can only match if *p is found
-           within compound_start[] */
-        if (!index(compound_start, *p))
-            continue;
-
-        /* check current substring against all words in the compound[] list */
-        for (cmpd = compounds; *cmpd; ++cmpd)
-            if (!strncmpi(p, *cmpd, (int) strlen(*cmpd)))
-                return p;
-    }
-    /* wasn't recognized as a compound phrase */
-    return 0;
-}
-
-/* Plural routine; once upon a time it may have been chiefly used for
- * user-defined fruits, but it is now used extensively throughout the
- * program.
- *
- * For fruit, we have to try to account for everything reasonable the
- * player has; something unreasonable can still break the code.
- * However, it's still a lot more accurate than "just add an 's' at the
- * end", which Rogue uses...
- *
- * Also used for plural monster names ("Wiped out all homunculi." or the
- * vanquished monsters list) and body parts.  A lot of unique monsters have
- * names which get mangled by makeplural and/or makesingular.  They're not
- * genocidable, and vanquished-mon handling does its own special casing
- * (for uniques who've been revived and re-killed), so we don't bother
- * trying to get those right here.
- *
- * Also misused by muse.c to convert 1st person present verbs to 2nd person.
- * 3.6.0: made case-insensitive.
- */
-char *
-makeplural(oldstr)
-const char *oldstr;
-{
-    register char *spot;
-    char lo_c, *str = nextobuf();
-    const char *excess = (char *) 0;
-    int len;
-
-    if (oldstr)
-        while (*oldstr == ' ')
-            oldstr++;
-    if (!oldstr || !*oldstr) {
-        impossible("plural of null?");
-        Strcpy(str, "s");
-        return str;
-    }
-    Strcpy(str, oldstr);
-
-    /*
-     * Skip changing "pair of" to "pairs of".  According to Webster, usual
-     * English usage is use pairs for humans, e.g. 3 pairs of dancers,
-     * and pair for objects and non-humans, e.g. 3 pair of boots.  We don't
-     * refer to pairs of humans in this game so just skip to the bottom.
-     */
-    if (!strncmpi(str, "pair of ", 8))
-        goto bottom;
-
-    /* look for "foo of bar" so that we can focus on "foo" */
-    if ((spot = singplur_compound(str)) != 0) {
-        excess = oldstr + (int) (spot - str);
-        *spot = '\0';
-    } else
-        spot = eos(str);
-
-    spot--;
-    while (spot > str && *spot == ' ')
-        spot--; /* Strip blanks from end */
-    *(spot + 1) = '\0';
-    /* Now spot is the last character of the string */
-
-    len = strlen(str);
-
-    /* Single letters */
-    if (len == 1 || !letter(*spot)) {
-        Strcpy(spot + 1, "'s");
-        goto bottom;
-    }
-
-    /* dispense with some words which don't need pluralization */
-    {
-        static const char *const already_plural[] = {
-            "ae",  /* algae, larvae, &c */
-            "matzot", 0,
-        };
-
-        /* spot+1: synch up with makesingular's usage */
-        if (singplur_lookup(str, spot + 1, TRUE, already_plural))
-            goto bottom;
-
-        /* more of same, but not suitable for blanket loop checking */
-        if ((len == 2 && !strcmpi(str, "ya"))
-            || (len >= 3 && !strcmpi(spot - 2, " ya")))
-            goto bottom;
-    }
-
-    /* man/men ("Wiped out all cavemen.") */
-    if (len >= 3 && !strcmpi(spot - 2, "man")
-        /* exclude shamans and humans etc */
-        && !badman(str, TRUE)) {
-        Strcasecpy(spot - 1, "en");
-        goto bottom;
-    }
-    if (lowc(*spot) == 'f') { /* (staff handled via one_off[]) */
-        lo_c = lowc(*(spot - 1));
-        if (len >= 3 && !strcmpi(spot - 2, "erf")) {
-            /* avoid "nerf" -> "nerves", "serf" -> "serves" */
-            ; /* fall through to default (append 's') */
-        } else if (index("lr", lo_c) || index(vowels, lo_c)) {
-            /* [aeioulr]f to [aeioulr]ves */
-            Strcasecpy(spot, "ves");
-            goto bottom;
-        }
-    }
-    /* ium/ia (mycelia, baluchitheria) */
-    if (len >= 3 && !strcmpi(spot - 2, "ium")) {
-        Strcasecpy(spot - 2, "ia");
-        goto bottom;
-    }
-    /* algae, larvae, hyphae (another fungus part) */
-    if ((len >= 4 && !strcmpi(spot - 3, "alga"))
-        || (len >= 5
-            && (!strcmpi(spot - 4, "hypha") || !strcmpi(spot - 4, "larva")))
-        || (len >= 6 && !strcmpi(spot - 5, "amoeba"))
-        || (len >= 8 && (!strcmpi(spot - 7, "vertebra")))) {
-        /* a to ae */
-        Strcasecpy(spot + 1, "e");
-        goto bottom;
-    }
-    /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
-    if (len > 3 && !strcmpi(spot - 1, "us")
-        && !((len >= 5 && !strcmpi(spot - 4, "lotus"))
-             || (len >= 6 && !strcmpi(spot - 5, "wumpus")))) {
-        Strcasecpy(spot - 1, "i");
-        goto bottom;
-    }
-    /* sis/ses (nemesis) */
-    if (len >= 3 && !strcmpi(spot - 2, "sis")) {
-        Strcasecpy(spot - 1, "es");
-        goto bottom;
-    }
-    /* matzoh/matzot, possible food name */
-    if (len >= 6
-        && (!strcmpi(spot - 5, "matzoh") || !strcmpi(spot - 5, "matzah"))) {
-        Strcasecpy(spot - 1, "ot"); /* oh/ah -> ot */
-        goto bottom;
-    }
-    if (len >= 5
-        && (!strcmpi(spot - 4, "matzo") || !strcmpi(spot - 4, "matza"))) {
-        Strcasecpy(spot, "ot"); /* o/a -> ot */
-        goto bottom;
-    }
-
-    /* note: -eau/-eaux (gateau, bordeau...) */
-    /* note: ox/oxen, VAX/VAXen, goose/geese */
-
-    lo_c = lowc(*spot);
-
-    /* Ends in z, x, s, ch, sh; add an "es" */
-    if (index("zxs", lo_c)
-        || (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot - 1))))
-        /* Kludge to get "tomatoes" and "potatoes" right */
-        || (len >= 4 && !strcmpi(spot - 2, "ato"))
-        || (len >= 5 && !strcmpi(spot - 4, "dingo"))) {
-        Strcasecpy(spot + 1, "es"); /* append es */
-        goto bottom;
-    }
-    /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
-    if (lo_c == 'y' && !index(vowels, lowc(*(spot - 1)))) {
-        Strcasecpy(spot, "ies"); /* y -> ies */
-        goto bottom;
-    }
-    /* Default: append an 's' */
-    Strcasecpy(spot + 1, "s");
-
-bottom:
-    if (excess)
-        Strcat(str, excess);
-    return str;
-}
-
-/*
- * Singularize a string the user typed in; this helps reduce the complexity
- * of readobjnam, and is also used in pager.c to singularize the string
- * for which help is sought.
- *
- * "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)?
- * Its inclusion in as_is[]/special_subj[] makes it get treated as the former.
- *
- * A lot of unique monsters have names ending in s; plural, or singular
- * from plural, doesn't make much sense for them so we don't bother trying.
- * 3.6.0: made case-insensitive.
- */
-char *
-makesingular(oldstr)
-const char *oldstr;
-{
-    register char *p, *bp;
-    const char *excess = 0;
-    char *str = nextobuf();
-
-    if (oldstr)
-        while (*oldstr == ' ')
-            oldstr++;
-    if (!oldstr || !*oldstr) {
-        impossible("singular of null?");
-        str[0] = '\0';
-        return str;
-    }
-
-    bp = strcpy(str, oldstr);
-
-    /* check for "foo of bar" so that we can focus on "foo" */
-    if ((p = singplur_compound(bp)) != 0) {
-        excess = oldstr + (int) (p - bp);
-        *p = '\0';
-    } else
-        p = eos(bp);
-
-    /* dispense with some words which don't need singularization */
-    if (singplur_lookup(bp, p, FALSE, special_subjs))
-        goto bottom;
-
-    /* remove -s or -es (boxes) or -ies (rubies) */
-    if (p >= bp + 1 && lowc(p[-1]) == 's') {
-        if (p >= bp + 2 && lowc(p[-2]) == 'e') {
-            if (p >= bp + 3 && lowc(p[-3]) == 'i') { /* "ies" */
-                if (!BSTRCMPI(bp, p - 7, "cookies")
-                    || !BSTRCMPI(bp, p - 4, "pies")
-                    || !BSTRCMPI(bp, p - 5, "mbies") /* zombie */
-                    || !BSTRCMPI(bp, p - 5, "yries")) /* valkyrie */
-                    goto mins;
-                Strcasecpy(p - 3, "y"); /* ies -> y */
-                goto bottom;
-            }
-            /* wolves, but f to ves isn't fully reversible */
-            if (p - 4 >= bp && (index("lr", lowc(*(p - 4)))
-                                || index(vowels, lowc(*(p - 4))))
-                && !BSTRCMPI(bp, p - 3, "ves")) {
-                if (!BSTRCMPI(bp, p - 6, "cloves")
-                    || !BSTRCMPI(bp, p - 6, "nerves"))
-                    goto mins;
-                Strcasecpy(p - 3, "f"); /* ves -> f */
-                goto bottom;
-            }
-            /* note: nurses, axes but boxes, wumpuses */
-            if (!BSTRCMPI(bp, p - 4, "eses")
-                || !BSTRCMPI(bp, p - 4, "oxes") /* boxes, foxes */
-                || !BSTRCMPI(bp, p - 4, "nxes") /* lynxes */
-                || !BSTRCMPI(bp, p - 4, "ches")
-                || !BSTRCMPI(bp, p - 4, "uses") /* lotuses */
-                || !BSTRCMPI(bp, p - 4, "sses") /* priestesses */
-                || !BSTRCMPI(bp, p - 5, "atoes") /* tomatoes */
-                || !BSTRCMPI(bp, p - 7, "dingoes")
-                || !BSTRCMPI(bp, p - 7, "Aleaxes")) {
-                *(p - 2) = '\0'; /* drop es */
-                goto bottom;
-            } /* else fall through to mins */
-
-            /* ends in 's' but not 'es' */
-        } else if (!BSTRCMPI(bp, p - 2, "us")) { /* lotus, fungus... */
-            if (BSTRCMPI(bp, p - 6, "tengus") /* but not these... */
-                && BSTRCMPI(bp, p - 7, "hezrous"))
-                goto bottom;
-        } else if (!BSTRCMPI(bp, p - 2, "ss")
-                   || !BSTRCMPI(bp, p - 5, " lens")
-                   || (p - 4 == bp && !strcmpi(p - 4, "lens"))) {
-            goto bottom;
-        }
-    mins:
-        *(p - 1) = '\0'; /* drop s */
-
-    } else { /* input doesn't end in 's' */
-
-        if (!BSTRCMPI(bp, p - 3, "men")
-            && !badman(bp, FALSE)) {
-            Strcasecpy(p - 2, "an");
-            goto bottom;
-        }
-        /* matzot -> matzo, algae -> alga */
-        if (!BSTRCMPI(bp, p - 6, "matzot") || !BSTRCMPI(bp, p - 2, "ae")) {
-            *(p - 1) = '\0'; /* drop t/e */
-            goto bottom;
-        }
-        /* balactheria -> balactherium */
-        if (p - 4 >= bp && !strcmpi(p - 2, "ia")
-            && index("lr", lowc(*(p - 3))) && lowc(*(p - 4)) == 'e') {
-            Strcasecpy(p - 1, "um"); /* a -> um */
-        }
-
-        /* here we cannot find the plural suffix */
-    }
-
-bottom:
-    /* if we stripped off a suffix (" of bar" from "foo of bar"),
-       put it back now [strcat() isn't actually 100% safe here...] */
-    if (excess)
-        Strcat(bp, excess);
-
-    return bp;
-}
-
-boolean
-badman(basestr, to_plural)
-const char *basestr;
-boolean to_plural;            /* true => makeplural, false => makesingular */
-{
-    int i, al;
-    char *endstr, *spot;
-    /* these are all the prefixes for *man that don't have a *men plural */
-    const char *no_men[] = {
-        "albu", "antihu", "anti", "ata", "auto", "bildungsro", "cai",
-        "cay", "ceru", "corner", "decu", "des", "dura", "fir",
-        "glass", "hanu", "het", "infrahu", "inhu", "land",
-        "meat", "nonhu", "otto", "out", "prehu", "protohu",
-        "subhu", "superhu", "talis", "unhu", "sha",
-        "hu", "un", "le", "re", "so", "to", "at", "a",
-    };
-    /* these are all the prefixes for *men that don't have a *man singular */
-    const char *no_man[] = {
-        "abdo", "acu", "agno", "ceru", "cogno", "cycla", "fleh", "grava",
-        "hegu", "preno", "sonar", "dai", "exa", "fla", "sta", "teg", "tegu",
-        "vela", "da", "hy", "lu", "no", "nu", "ra", "ru", "se", "vi", "ya",
-        "o", "a",
-    };
-
-    if (!basestr || strlen(basestr) < 4)
-        return FALSE;
-
-    endstr = eos((char *)basestr);
-
-    if (to_plural) {
-        for (i = 0; i < SIZE(no_men); i++) {
-            al = (int) strlen(no_men[i]);
-            spot = endstr - (al + 3);
-            if (!BSTRNCMPI(basestr, spot, no_men[i], al)
-                && (spot == basestr || *(spot - 1) == ' '))
-                return TRUE;
-        }
-    } else {
-        for (i = 0; i < SIZE(no_man); i++) {
-            al = (int) strlen(no_man[i]);
-            spot = endstr - (al + 3);
-            if (!BSTRNCMPI(basestr, spot, no_man[i], al)
-                && (spot == basestr || *(spot - 1) == ' '))
-                return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-/* compare user string against object name string using fuzzy matching */
-STATIC_OVL boolean
-wishymatch(u_str, o_str, retry_inverted)
-const char *u_str;      /* from user, so might be variant spelling */
-const char *o_str;      /* from objects[], so is in canonical form */
-boolean retry_inverted; /* optional extra "of" handling */
-{
-    static NEARDATA const char detect_SP[] = "detect ",
-                               SP_detection[] = " detection";
-    char *p, buf[BUFSZ];
-
-    /* ignore spaces & hyphens and upper/lower case when comparing */
-    if (fuzzymatch(u_str, o_str, " -", TRUE))
-        return TRUE;
-
-    if (retry_inverted) {
-        const char *u_of, *o_of;
-
-        /* when just one of the strings is in the form "foo of bar",
-           convert it into "bar foo" and perform another comparison */
-        u_of = strstri(u_str, " of ");
-        o_of = strstri(o_str, " of ");
-        if (u_of && !o_of) {
-            Strcpy(buf, u_of + 4);
-            p = eos(strcat(buf, " "));
-            while (u_str < u_of)
-                *p++ = *u_str++;
-            *p = '\0';
-            return fuzzymatch(buf, o_str, " -", TRUE);
-        } else if (o_of && !u_of) {
-            Strcpy(buf, o_of + 4);
-            p = eos(strcat(buf, " "));
-            while (o_str < o_of)
-                *p++ = *o_str++;
-            *p = '\0';
-            return fuzzymatch(u_str, buf, " -", TRUE);
-        }
-    }
-
-    /* [note: if something like "elven speed boots" ever gets added, these
-       special cases should be changed to call wishymatch() recursively in
-       order to get the "of" inversion handling] */
-    if (!strncmp(o_str, "dwarvish ", 9)) {
-        if (!strncmpi(u_str, "dwarven ", 8))
-            return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
-    } else if (!strncmp(o_str, "elven ", 6)) {
-        if (!strncmpi(u_str, "elvish ", 7))
-            return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
-        else if (!strncmpi(u_str, "elfin ", 6))
-            return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
-    } else if (!strncmp(o_str, detect_SP, sizeof detect_SP - 1)) {
-        /* check for "detect <foo>" vs "<foo> detection" */
-        if ((p = strstri(u_str, SP_detection)) != 0
-            && !*(p + sizeof SP_detection - 1)) {
-            /* convert "<foo> detection" into "detect <foo>" */
-            *p = '\0';
-            Strcat(strcpy(buf, detect_SP), u_str);
-            /* "detect monster" -> "detect monsters" */
-            if (!strcmpi(u_str, "monster"))
-                Strcat(buf, "s");
-            *p = ' ';
-            return fuzzymatch(buf, o_str, " -", TRUE);
-        }
-    } else if (strstri(o_str, SP_detection)) {
-        /* and the inverse, "<foo> detection" vs "detect <foo>" */
-        if (!strncmpi(u_str, detect_SP, sizeof detect_SP - 1)) {
-            /* convert "detect <foo>s" into "<foo> detection" */
-            p = makesingular(u_str + sizeof detect_SP - 1);
-            Strcat(strcpy(buf, p), SP_detection);
-            /* caller may be looping through objects[], so avoid
-               churning through all the obufs */
-            releaseobuf(p);
-            return fuzzymatch(buf, o_str, " -", TRUE);
-        }
-    } else if (strstri(o_str, "ability")) {
-        /* when presented with "foo of bar", makesingular() used to
-           singularize both foo & bar, but now only does so for foo */
-        /* catch "{potion(s),ring} of {gain,restore,sustain} abilities" */
-        if ((p = strstri(u_str, "abilities")) != 0
-            && !*(p + sizeof "abilities" - 1)) {
-            (void) strncpy(buf, u_str, (unsigned) (p - u_str));
-            Strcpy(buf + (p - u_str), "ability");
-            return fuzzymatch(buf, o_str, " -", TRUE);
-        }
-    } else if (!strcmp(o_str, "aluminum")) {
-        /* this special case doesn't really fit anywhere else... */
-        /* (note that " wand" will have been stripped off by now) */
-        if (!strcmpi(u_str, "aluminium"))
-            return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
-    }
-
-    return FALSE;
-}
-
-struct o_range {
-    const char *name, oclass;
-    int f_o_range, l_o_range;
-};
-
-/* wishable subranges of objects */
-STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
-    { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
-    { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
-    { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
-    { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
-    { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
-    { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
-    { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
-    { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
-    { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
-    { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
-    { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
-    { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
-    { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
-    { "dragon scales", ARMOR_CLASS, GRAY_DRAGON_SCALES,
-      YELLOW_DRAGON_SCALES },
-    { "dragon scale mail", ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL,
-      YELLOW_DRAGON_SCALE_MAIL },
-    { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
-    { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
-    { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
-    { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
-};
-
-/* alternate spellings; if the difference is only the presence or
-   absence of spaces and/or hyphens (such as "pickaxe" vs "pick axe"
-   vs "pick-axe") then there is no need for inclusion in this list;
-   likewise for ``"of" inversions'' ("boots of speed" vs "speed boots") */
-struct alt_spellings {
-    const char *sp;
-    int ob;
-} spellings[] = {
-    { "pickax", PICK_AXE },
-    { "whip", BULLWHIP },
-    { "saber", SILVER_SABER },
-    { "silver sabre", SILVER_SABER },
-    { "smooth shield", SHIELD_OF_REFLECTION },
-    { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
-    { "grey dragon scales", GRAY_DRAGON_SCALES },
-    { "iron ball", HEAVY_IRON_BALL },
-    { "lantern", BRASS_LANTERN },
-    { "mattock", DWARVISH_MATTOCK },
-    { "amulet of poison resistance", AMULET_VERSUS_POISON },
-    { "potion of sleep", POT_SLEEPING },
-    { "stone", ROCK },
-    { "camera", EXPENSIVE_CAMERA },
-    { "tee shirt", T_SHIRT },
-    { "can", TIN },
-    { "can opener", TIN_OPENER },
-    { "kelp", KELP_FROND },
-    { "eucalyptus", EUCALYPTUS_LEAF },
-    { "royal jelly", LUMP_OF_ROYAL_JELLY },
-    { "lembas", LEMBAS_WAFER },
-    { "marker", MAGIC_MARKER },
-    { "hook", GRAPPLING_HOOK },
-    { "grappling iron", GRAPPLING_HOOK },
-    { "grapnel", GRAPPLING_HOOK },
-    { "grapple", GRAPPLING_HOOK },
-    { "protection from shape shifters", RIN_PROTECTION_FROM_SHAPE_CHAN },
-    /* normally we wouldn't have to worry about unnecessary <space>, but
-       " stone" will get stripped off, preventing a wishymatch; that actually
-       lets "flint stone" be a match, so we also accept bogus "flintstone" */
-    { "luck stone", LUCKSTONE },
-    { "load stone", LOADSTONE },
-    { "touch stone", TOUCHSTONE },
-    { "flintstone", FLINT },
-    { (const char *) 0, 0 },
-};
-
-STATIC_OVL short
-rnd_otyp_by_wpnskill(skill)
-schar skill;
-{
-    int i, n = 0;
-    short otyp = STRANGE_OBJECT;
-    for (i = bases[WEAPON_CLASS];
-         i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
-        if (objects[i].oc_skill == skill) {
-            n++;
-            otyp = i;
-        }
-    if (n > 0) {
-        n = rn2(n);
-        for (i = bases[WEAPON_CLASS];
-             i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
-            if (objects[i].oc_skill == skill)
-                if (--n < 0)
-                    return i;
-    }
-    return otyp;
-}
-
-STATIC_OVL short
-rnd_otyp_by_namedesc(name, oclass)
-char *name;
-char oclass;
-{
-    int i, n = 0;
-    short validobjs[NUM_OBJECTS];
-    register const char *zn;
-    long maxprob = 0;
-
-    if (!name)
-        return STRANGE_OBJECT;
-
-    memset((genericptr_t) validobjs, 0, sizeof(validobjs));
-
-    for (i = oclass ? bases[(int)oclass] : STRANGE_OBJECT + 1;
-         i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
-         ++i) {
-        /* don't match extra descriptions (w/o real name) */
-        if ((zn = OBJ_NAME(objects[i])) == 0)
-            continue;
-        if (wishymatch(name, zn, TRUE)
-            || ((zn = OBJ_DESCR(objects[i])) != 0
-                && wishymatch(name, zn, FALSE))
-            || ((zn = objects[i].oc_uname) != 0
-                && wishymatch(name, zn, FALSE))) {
-            validobjs[n++] = (short) i;
-            maxprob += (objects[i].oc_prob + 1);
-        }
-    }
-
-    if (n > 0 && maxprob) {
-        long prob = rn2(maxprob);
-
-        i = 0;
-        while (i < n - 1
-               && (prob -= (objects[validobjs[i]].oc_prob + 1)) >= 0)
-            i++;
-        return validobjs[i];
-    }
-    return STRANGE_OBJECT;
-}
-
-/*
- * Return something wished for.  Specifying a null pointer for
- * the user request string results in a random object.  Otherwise,
- * if asking explicitly for "nothing" (or "nil") return no_wish;
- * if not an object return &zeroobj; if an error (no matching object),
- * return null.
- */
-struct obj *
-readobjnam(bp, no_wish)
-register char *bp;
-struct obj *no_wish;
-{
-    register char *p;
-    register int i;
-    register struct obj *otmp;
-    int cnt, spe, spesgn, typ, very, rechrg;
-    int blessed, uncursed, iscursed, ispoisoned, isgreased;
-    int eroded, eroded2, erodeproof;
-    int halfeaten, mntmp, contents;
-    int islit, unlabeled, ishistoric, isdiluted, trapped;
-    int tmp, tinv, tvariety;
-    int wetness, gsize = 0;
-    struct fruit *f;
-    int ftype = context.current_fruit;
-    char fruitbuf[BUFSZ];
-    /* Fruits may not mess up the ability to wish for real objects (since
-     * you can leave a fruit in a bones file and it will be added to
-     * another person's game), so they must be checked for last, after
-     * stripping all the possible prefixes and seeing if there's a real
-     * name in there.  So we have to save the full original name.  However,
-     * it's still possible to do things like "uncursed burnt Alaska",
-     * or worse yet, "2 burned 5 course meals", so we need to loop to
-     * strip off the prefixes again, this time stripping only the ones
-     * possible on food.
-     * We could get even more detailed so as to allow food names with
-     * prefixes that _are_ possible on food, so you could wish for
-     * "2 3 alarm chilis".  Currently this isn't allowed; options.c
-     * automatically sticks 'candied' in front of such names.
-     */
-    char oclass;
-    char *un, *dn, *actualn, *origbp = bp;
-    const char *name = 0;
-
-    cnt = spe = spesgn = typ = very = rechrg = blessed = uncursed = iscursed =
-        ispoisoned = isgreased = eroded = eroded2 = erodeproof = halfeaten =
-            islit = unlabeled = ishistoric = isdiluted = trapped = 0;
-    tvariety = RANDOM_TIN;
-    mntmp = NON_PM;
-#define UNDEFINED 0
-#define EMPTY 1
-#define SPINACH 2
-    contents = UNDEFINED;
-    oclass = 0;
-    actualn = dn = un = 0;
-    wetness = 0;
-
-    if (!bp)
-        goto any;
-    /* first, remove extra whitespace they may have typed */
-    (void) mungspaces(bp);
-    /* allow wishing for "nothing" to preserve wishless conduct...
-       [now requires "wand of nothing" if that's what was really wanted] */
-    if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil")
-        || !strcmpi(bp, "none"))
-        return no_wish;
-    /* save the [nearly] unmodified choice string */
-    Strcpy(fruitbuf, bp);
-
-    for (;;) {
-        register int l;
-
-        if (!bp || !*bp)
-            goto any;
-        if (!strncmpi(bp, "an ", l = 3) || !strncmpi(bp, "a ", l = 2)) {
-            cnt = 1;
-        } else if (!strncmpi(bp, "the ", l = 4)) {
-            ; /* just increment `bp' by `l' below */
-        } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
-            cnt = atoi(bp);
-            while (digit(*bp))
-                bp++;
-            while (*bp == ' ')
-                bp++;
-            l = 0;
-        } else if (*bp == '+' || *bp == '-') {
-            spesgn = (*bp++ == '+') ? 1 : -1;
-            spe = atoi(bp);
-            while (digit(*bp))
-                bp++;
-            while (*bp == ' ')
-                bp++;
-            l = 0;
-        } else if (!strncmpi(bp, "blessed ", l = 8)
-                   || !strncmpi(bp, "holy ", l = 5)) {
-            blessed = 1;
-        } else if (!strncmpi(bp, "moist ", l = 6)
-                   || !strncmpi(bp, "wet ", l = 4)) {
-            if (!strncmpi(bp, "wet ", 4))
-                wetness = rn2(3) + 3;
-            else
-                wetness = rnd(2);
-        } else if (!strncmpi(bp, "cursed ", l = 7)
-                   || !strncmpi(bp, "unholy ", l = 7)) {
-            iscursed = 1;
-        } else if (!strncmpi(bp, "uncursed ", l = 9)) {
-            uncursed = 1;
-        } else if (!strncmpi(bp, "rustproof ", l = 10)
-                   || !strncmpi(bp, "erodeproof ", l = 11)
-                   || !strncmpi(bp, "corrodeproof ", l = 13)
-                   || !strncmpi(bp, "fixed ", l = 6)
-                   || !strncmpi(bp, "fireproof ", l = 10)
-                   || !strncmpi(bp, "rotproof ", l = 9)) {
-            erodeproof = 1;
-        } else if (!strncmpi(bp, "lit ", l = 4)
-                   || !strncmpi(bp, "burning ", l = 8)) {
-            islit = 1;
-        } else if (!strncmpi(bp, "unlit ", l = 6)
-                   || !strncmpi(bp, "extinguished ", l = 13)) {
-            islit = 0;
-            /* "unlabeled" and "blank" are synonymous */
-        } else if (!strncmpi(bp, "unlabeled ", l = 10)
-                   || !strncmpi(bp, "unlabelled ", l = 11)
-                   || !strncmpi(bp, "blank ", l = 6)) {
-            unlabeled = 1;
-        } else if (!strncmpi(bp, "poisoned ", l = 9)) {
-            ispoisoned = 1;
-            /* "trapped" recognized but not honored outside wizard mode */
-        } else if (!strncmpi(bp, "trapped ", l = 8)) {
-            trapped = 0; /* undo any previous "untrapped" */
-            if (wizard)
-                trapped = 1;
-        } else if (!strncmpi(bp, "untrapped ", l = 10)) {
-            trapped = 2; /* not trapped */
-        } else if (!strncmpi(bp, "greased ", l = 8)) {
-            isgreased = 1;
-        } else if (!strncmpi(bp, "very ", l = 5)) {
-            /* very rusted very heavy iron ball */
-            very = 1;
-        } else if (!strncmpi(bp, "thoroughly ", l = 11)) {
-            very = 2;
-        } else if (!strncmpi(bp, "rusty ", l = 6)
-                   || !strncmpi(bp, "rusted ", l = 7)
-                   || !strncmpi(bp, "burnt ", l = 6)
-                   || !strncmpi(bp, "burned ", l = 7)) {
-            eroded = 1 + very;
-            very = 0;
-        } else if (!strncmpi(bp, "corroded ", l = 9)
-                   || !strncmpi(bp, "rotted ", l = 7)) {
-            eroded2 = 1 + very;
-            very = 0;
-        } else if (!strncmpi(bp, "partly eaten ", l = 13)
-                   || !strncmpi(bp, "partially eaten ", l = 16)) {
-            halfeaten = 1;
-        } else if (!strncmpi(bp, "historic ", l = 9)) {
-            ishistoric = 1;
-        } else if (!strncmpi(bp, "diluted ", l = 8)) {
-            isdiluted = 1;
-        } else if (!strncmpi(bp, "empty ", l = 6)) {
-            contents = EMPTY;
-        } else if (!strncmpi(bp, "small ", l = 6)) { /* glob sizes */
-            gsize = 1;
-        } else if (!strncmpi(bp, "medium ", l = 7)) {
-            /* xname() doesn't display "medium" but without this
-               there'd be no way to ask for the intermediate size */
-            gsize = 2;
-        } else if (!strncmpi(bp, "large ", l = 6)) {
-            /* "very large " had "very " peeled off on previous iteration */
-            gsize = (very != 1) ? 3 : 4;
-        } else
-            break;
-        bp += l;
-    }
-    if (!cnt)
-        cnt = 1; /* %% what with "gems" etc. ? */
-    if (strlen(bp) > 1 && (p = rindex(bp, '(')) != 0) {
-        boolean keeptrailingchars = TRUE;
-
-        p[(p > bp && p[-1] == ' ') ? -1 : 0] = '\0'; /*terminate bp */
-        ++p; /* advance past '(' */
-        if (!strncmpi(p, "lit)", 4)) {
-            islit = 1;
-            p += 4 - 1; /* point at ')' */
-        } else {
-            spe = atoi(p);
-            while (digit(*p))
-                p++;
-            if (*p == ':') {
-                p++;
-                rechrg = spe;
-                spe = atoi(p);
-                while (digit(*p))
-                    p++;
-            }
-            if (*p != ')') {
-                spe = rechrg = 0;
-                /* mis-matched parentheses; rest of string will be ignored
-                 * [probably we should restore everything back to '('
-                 * instead since it might be part of "named ..."]
-                 */
-                keeptrailingchars = FALSE;
-            } else {
-                spesgn = 1;
-            }
-        }
-        if (keeptrailingchars) {
-            char *pp = eos(bp);
-
-            /* 'pp' points at 'pb's terminating '\0',
-               'p' points at ')' and will be incremented past it */
-            do {
-                *pp++ = *++p;
-            } while (*p);
-        }
-    }
-    /*
-     * otmp->spe is type schar, so we don't want spe to be any bigger or
-     * smaller.  Also, spe should always be positive --some cheaters may
-     * try to confuse atoi().
-     */
-    if (spe < 0) {
-        spesgn = -1; /* cheaters get what they deserve */
-        spe = abs(spe);
-    }
-    if (spe > SCHAR_LIM)
-        spe = SCHAR_LIM;
-    if (rechrg < 0 || rechrg > 7)
-        rechrg = 7; /* recharge_limit */
-
-    /* now we have the actual name, as delivered by xname, say
-     *  green potions called whisky
-     *  scrolls labeled "QWERTY"
-     *  egg
-     *  fortune cookies
-     *  very heavy iron ball named hoei
-     *  wand of wishing
-     *  elven cloak
-     */
-    if ((p = strstri(bp, " named ")) != 0) {
-        *p = 0;
-        name = p + 7;
-    }
-    if ((p = strstri(bp, " called ")) != 0) {
-        *p = 0;
-        un = p + 8;
-        /* "helmet called telepathy" is not "helmet" (a specific type)
-         * "shield called reflection" is not "shield" (a general type)
-         */
-        for (i = 0; i < SIZE(o_ranges); i++)
-            if (!strcmpi(bp, o_ranges[i].name)) {
-                oclass = o_ranges[i].oclass;
-                goto srch;
-            }
-    }
-    if ((p = strstri(bp, " labeled ")) != 0) {
-        *p = 0;
-        dn = p + 9;
-    } else if ((p = strstri(bp, " labelled ")) != 0) {
-        *p = 0;
-        dn = p + 10;
-    }
-    if ((p = strstri(bp, " of spinach")) != 0) {
-        *p = 0;
-        contents = SPINACH;
-    }
-
-    /*
-     * Skip over "pair of ", "pairs of", "set of" and "sets of".
-     *
-     * Accept "3 pair of boots" as well as "3 pairs of boots".  It is
-     * valid English either way.  See makeplural() for more on pair/pairs.
-     *
-     * We should only double count if the object in question is not
-     * referred to as a "pair of".  E.g. We should double if the player
-     * types "pair of spears", but not if the player types "pair of
-     * lenses".  Luckily (?) all objects that are referred to as pairs
-     * -- boots, gloves, and lenses -- are also not mergable, so cnt is
-     * ignored anyway.
-     */
-    if (!strncmpi(bp, "pair of ", 8)) {
-        bp += 8;
-        cnt *= 2;
-    } else if (!strncmpi(bp, "pairs of ", 9)) {
-        bp += 9;
-        if (cnt > 1)
-            cnt *= 2;
-    } else if (!strncmpi(bp, "set of ", 7)) {
-        bp += 7;
-    } else if (!strncmpi(bp, "sets of ", 8)) {
-        bp += 8;
-    }
-
-    /* intercept pudding globs here; they're a valid wish target,
-     * but we need them to not get treated like a corpse.
-     *
-     * also don't let player wish for multiple globs.
-     */
-    if ((p = strstri(bp, "glob of ")) != 0
-        || (p = strstri(bp, "globs of ")) != 0) {
-        int globoffset = (*(p + 4) == 's') ? 9 : 8;
-
-        if ((mntmp = name_to_mon(p + globoffset)) >= PM_GRAY_OOZE
-            && mntmp <= PM_BLACK_PUDDING) {
-            mntmp = NON_PM; /* lie to ourselves */
-            cnt = 0;        /* force only one */
-        }
-    } else {
-        /*
-         * Find corpse type using "of" (figurine of an orc, tin of orc meat)
-         * Don't check if it's a wand or spellbook.
-         * (avoid "wand/finger of death" confusion).
-         */
-        if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
-            && !strstri(bp, "finger ")) {
-            if ((p = strstri(bp, "tin of ")) != 0) {
-                if (!strcmpi(p + 7, "spinach")) {
-                    contents = SPINACH;
-                    mntmp = NON_PM;
-                } else {
-                    tmp = tin_variety_txt(p + 7, &tinv);
-                    tvariety = tinv;
-                    mntmp = name_to_mon(p + 7 + tmp);
-                }
-                typ = TIN;
-                goto typfnd;
-            } else if ((p = strstri(bp, " of ")) != 0
-                       && (mntmp = name_to_mon(p + 4)) >= LOW_PM)
-                *p = 0;
-        }
-    }
-    /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
-    if (strncmpi(bp, "samurai sword", 13)  /* not the "samurai" monster! */
-        && strncmpi(bp, "wizard lock", 11) /* not the "wizard" monster! */
-        && strncmpi(bp, "ninja-to", 8)     /* not the "ninja" rank */
-        && strncmpi(bp, "master key", 10)  /* not the "master" rank */
-        && strncmpi(bp, "magenta", 7)) {   /* not the "mage" rank */
-        if (mntmp < LOW_PM && strlen(bp) > 2
-            && (mntmp = name_to_mon(bp)) >= LOW_PM) {
-            int mntmptoo, mntmplen; /* double check for rank title */
-            char *obp = bp;
-
-            mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
-            bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname)
-                                      : mntmplen;
-            if (*bp == ' ') {
-                bp++;
-            } else if (!strncmpi(bp, "s ", 2)) {
-                bp += 2;
-            } else if (!strncmpi(bp, "es ", 3)) {
-                bp += 3;
-            } else if (!*bp && !actualn && !dn && !un && !oclass) {
-                /* no referent; they don't really mean a monster type */
-                bp = obp;
-                mntmp = NON_PM;
-            }
-        }
-    }
-
-    /* first change to singular if necessary */
-    if (*bp) {
-        char *sng = makesingular(bp);
-        if (strcmp(bp, sng)) {
-            if (cnt == 1)
-                cnt = 2;
-            Strcpy(bp, sng);
-        }
-    }
-
-    /* Alternate spellings (pick-ax, silver sabre, &c) */
-    {
-        struct alt_spellings *as = spellings;
-
-        while (as->sp) {
-            if (fuzzymatch(bp, as->sp, " -", TRUE)) {
-                typ = as->ob;
-                goto typfnd;
-            }
-            as++;
-        }
-        /* can't use spellings list for this one due to shuffling */
-        if (!strncmpi(bp, "grey spell", 10))
-            *(bp + 2) = 'a';
-
-        if ((p = strstri(bp, "armour")) != 0) {
-            /* skip past "armo", then copy remainder beyond "u" */
-            p += 4;
-            while ((*p = *(p + 1)) != '\0')
-                ++p; /* self terminating */
-        }
-    }
-
-    /* dragon scales - assumes order of dragons */
-    if (!strcmpi(bp, "scales") && mntmp >= PM_GRAY_DRAGON
-        && mntmp <= PM_YELLOW_DRAGON) {
-        typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
-        mntmp = NON_PM; /* no monster */
-        goto typfnd;
-    }
-
-    p = eos(bp);
-    if (!BSTRCMPI(bp, p - 10, "holy water")) {
-        typ = POT_WATER;
-        if ((p - bp) >= 12 && *(p - 12) == 'u')
-            iscursed = 1; /* unholy water */
-        else
-            blessed = 1;
-        goto typfnd;
-    }
-    if (unlabeled && !BSTRCMPI(bp, p - 6, "scroll")) {
-        typ = SCR_BLANK_PAPER;
-        goto typfnd;
-    }
-    if (unlabeled && !BSTRCMPI(bp, p - 9, "spellbook")) {
-        typ = SPE_BLANK_PAPER;
-        goto typfnd;
-    }
-    /*
-     * NOTE: Gold pieces are handled as objects nowadays, and therefore
-     * this section should probably be reconsidered as well as the entire
-     * gold/money concept.  Maybe we want to add other monetary units as
-     * well in the future. (TH)
-     */
-    if (!BSTRCMPI(bp, p - 10, "gold piece")
-        || !BSTRCMPI(bp, p - 7, "zorkmid")
-        || !strcmpi(bp, "gold") || !strcmpi(bp, "money")
-        || !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
-        if (cnt > 5000 && !wizard)
-            cnt = 5000;
-        else if (cnt < 1)
-            cnt = 1;
-        otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
-        otmp->quan = (long) cnt;
-        otmp->owt = weight(otmp);
-        context.botl = 1;
-        return otmp;
-    }
-
-    /* check for single character object class code ("/" for wand, &c) */
-    if (strlen(bp) == 1 && (i = def_char_to_objclass(*bp)) < MAXOCLASSES
-        && i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) {
-        oclass = i;
-        goto any;
-    }
-
-    /* Search for class names: XXXXX potion, scroll of XXXXX.  Avoid */
-    /* false hits on, e.g., rings for "ring mail". */
-    if (strncmpi(bp, "enchant ", 8)
-        && strncmpi(bp, "destroy ", 8)
-        && strncmpi(bp, "detect food", 11)
-        && strncmpi(bp, "food detection", 14)
-        && strncmpi(bp, "ring mail", 9)
-        && strncmpi(bp, "studded leather armor", 21)
-        && strncmpi(bp, "leather armor", 13)
-        && strncmpi(bp, "tooled horn", 11)
-        && strncmpi(bp, "food ration", 11)
-        && strncmpi(bp, "meat ring", 9))
-        for (i = 0; i < (int) (sizeof wrpsym); i++) {
-            register int j = strlen(wrp[i]);
-
-            if (!strncmpi(bp, wrp[i], j)) {
-                oclass = wrpsym[i];
-                if (oclass != AMULET_CLASS) {
-                    bp += j;
-                    if (!strncmpi(bp, " of ", 4))
-                        actualn = bp + 4;
-                    /* else if(*bp) ?? */
-                } else
-                    actualn = bp;
-                goto srch;
-            }
-            if (!BSTRCMPI(bp, p - j, wrp[i])) {
-                oclass = wrpsym[i];
-                p -= j;
-                *p = 0;
-                if (p > bp && p[-1] == ' ')
-                    p[-1] = 0;
-                actualn = dn = bp;
-                goto srch;
-            }
-        }
-
-    /* Wishing in wizard mode can create traps and furniture.
-     * Part I:  distinguish between trap and object for the two
-     * types of traps which have corresponding objects:  bear trap
-     * and land mine.  "beartrap" (object) and "bear trap" (trap)
-     * have a difference in spelling which we used to exploit by
-     * adding a special case in wishymatch(), but "land mine" is
-     * spelled the same either way so needs different handing.
-     * Since we need something else for land mine, we've dropped
-     * the bear trap hack so that both are handled exactly the
-     * same.  To get an armed trap instead of a disarmed object,
-     * the player can prefix either the object name or the trap
-     * name with "trapped " (which ordinarily applies to chests
-     * and tins), or append something--anything at all except for
-     * " object", but " trap" is suggested--to either the trap
-     * name or the object name.
-     */
-    if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) {
-        boolean beartrap = (lowc(*bp) == 'b');
-        char *zp = bp + 4; /* skip "bear"/"land" */
-
-        if (*zp == ' ')
-            ++zp; /* embedded space is optional */
-        if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) {
-            zp += 4;
-            if (trapped == 2 || !strcmpi(zp, " object")) {
-                /* "untrapped <foo>" or "<foo> object" */
-                typ = beartrap ? BEARTRAP : LAND_MINE;
-                goto typfnd;
-            } else if (trapped == 1 || *zp != '\0') {
-                /* "trapped <foo>" or "<foo> trap" (actually "<foo>*") */
-                int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE);
-
-                /* use canonical trap spelling, skip object matching */
-                Strcpy(bp, defsyms[idx].explanation);
-                goto wiztrap;
-            }
-            /* [no prefix or suffix; we're going to end up matching
-               the object name and getting a disarmed trap object] */
-        }
-    }
-
-retry:
-    /* "grey stone" check must be before general "stone" */
-    for (i = 0; i < SIZE(o_ranges); i++)
-        if (!strcmpi(bp, o_ranges[i].name)) {
-            typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
-            goto typfnd;
-        }
-
-    if (!BSTRCMPI(bp, p - 6, " stone") || !BSTRCMPI(bp, p - 4, " gem")) {
-        p[!strcmpi(p - 4, " gem") ? -4 : -6] = '\0';
-        oclass = GEM_CLASS;
-        dn = actualn = bp;
-        goto srch;
-    } else if (!strcmpi(bp, "looking glass")) {
-        ; /* avoid false hit on "* glass" */
-    } else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
-        register char *g = bp;
-        if (strstri(g, "broken"))
-            return (struct obj *) 0;
-        if (!strncmpi(g, "worthless ", 10))
-            g += 10;
-        if (!strncmpi(g, "piece of ", 9))
-            g += 9;
-        if (!strncmpi(g, "colored ", 8))
-            g += 8;
-        else if (!strncmpi(g, "coloured ", 9))
-            g += 9;
-        if (!strcmpi(g, "glass")) { /* choose random color */
-            /* 9 different kinds */
-            typ = LAST_GEM + rnd(9);
-            if (objects[typ].oc_class == GEM_CLASS)
-                goto typfnd;
-            else
-                typ = 0; /* somebody changed objects[]? punt */
-        } else { /* try to construct canonical form */
-            char tbuf[BUFSZ];
-
-            Strcpy(tbuf, "worthless piece of ");
-            Strcat(tbuf, g); /* assume it starts with the color */
-            Strcpy(bp, tbuf);
-        }
-    }
-
-    actualn = bp;
-    if (!dn)
-        dn = actualn; /* ex. "skull cap" */
-srch:
-    /* check real names of gems first */
-    if (!oclass && actualn) {
-        for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
-            register const char *zn;
-
-            if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) {
-                typ = i;
-                goto typfnd;
-            }
-        }
-        /* "tin of foo" would be caught above, but plain "tin" has
-           a random chance of yielding "tin wand" unless we do this */
-        if (!strcmpi(actualn, "tin")) {
-            typ = TIN;
-            goto typfnd;
-        }
-    }
-
-    if (((typ = rnd_otyp_by_namedesc(actualn, oclass)) != STRANGE_OBJECT)
-        || ((typ = rnd_otyp_by_namedesc(dn, oclass)) != STRANGE_OBJECT)
-        || ((typ = rnd_otyp_by_namedesc(un, oclass)) != STRANGE_OBJECT)
-        || ((typ = rnd_otyp_by_namedesc(origbp, oclass)) != STRANGE_OBJECT))
-        goto typfnd;
-    typ = 0;
-
-    if (actualn) {
-        struct Jitem *j = Japanese_items;
-
-        while (j->item) {
-            if (actualn && !strcmpi(actualn, j->name)) {
-                typ = j->item;
-                goto typfnd;
-            }
-            j++;
-        }
-    }
-    /* if we've stripped off "armor" and failed to match anything
-       in objects[], append "mail" and try again to catch misnamed
-       requests like "plate armor" and "yellow dragon scale armor" */
-    if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) {
-        /* modifying bp's string is ok; we're about to resort
-           to random armor if this also fails to match anything */
-        Strcat(bp, " mail");
-        goto retry;
-    }
-    if (!strcmpi(bp, "spinach")) {
-        contents = SPINACH;
-        typ = TIN;
-        goto typfnd;
-    }
-    /* Note: not strcmpi.  2 fruits, one capital, one not, are possible.
-       Also not strncmp.  We used to ignore trailing text with it, but
-       that resulted in "grapefruit" matching "grape" if the latter came
-       earlier than the former in the fruit list. */
-    {
-        char *fp;
-        int l, cntf;
-        int blessedf, iscursedf, uncursedf, halfeatenf;
-
-        blessedf = iscursedf = uncursedf = halfeatenf = 0;
-        cntf = 0;
-
-        fp = fruitbuf;
-        for (;;) {
-            if (!fp || !*fp)
-                break;
-            if (!strncmpi(fp, "an ", l = 3) || !strncmpi(fp, "a ", l = 2)) {
-                cntf = 1;
-            } else if (!cntf && digit(*fp)) {
-                cntf = atoi(fp);
-                while (digit(*fp))
-                    fp++;
-                while (*fp == ' ')
-                    fp++;
-                l = 0;
-            } else if (!strncmpi(fp, "blessed ", l = 8)) {
-                blessedf = 1;
-            } else if (!strncmpi(fp, "cursed ", l = 7)) {
-                iscursedf = 1;
-            } else if (!strncmpi(fp, "uncursed ", l = 9)) {
-                uncursedf = 1;
-            } else if (!strncmpi(fp, "partly eaten ", l = 13)
-                       || !strncmpi(fp, "partially eaten ", l = 16)) {
-                halfeatenf = 1;
-            } else
-                break;
-            fp += l;
-        }
-
-        for (f = ffruit; f; f = f->nextf) {
-            /* match type: 0=none, 1=exact, 2=singular, 3=plural */
-            int ftyp = 0;
-
-            if (!strcmp(fp, f->fname))
-                ftyp = 1;
-            else if (!strcmp(fp, makesingular(f->fname)))
-                ftyp = 2;
-            else if (!strcmp(fp, makeplural(f->fname)))
-                ftyp = 3;
-            if (ftyp) {
-                typ = SLIME_MOLD;
-                blessed = blessedf;
-                iscursed = iscursedf;
-                uncursed = uncursedf;
-                halfeaten = halfeatenf;
-                /* adjust count if user explicitly asked for
-                   singular amount (can't happen unless fruit
-                   has been given an already pluralized name)
-                   or for plural amount */
-                if (ftyp == 2 && !cntf)
-                    cntf = 1;
-                else if (ftyp == 3 && !cntf)
-                    cntf = 2;
-                cnt = cntf;
-                ftype = f->fid;
-                goto typfnd;
-            }
-        }
-    }
-
-    if (!oclass && actualn) {
-        short objtyp;
-
-        /* Perhaps it's an artifact specified by name, not type */
-        name = artifact_name(actualn, &objtyp);
-        if (name) {
-            typ = objtyp;
-            goto typfnd;
-        }
-    }
-/* Let wizards wish for traps and furniture.
- * Must come after objects check so wizards can still wish for
- * trap objects like beartraps.
- * Disallow such topology tweaks for WIZKIT startup wishes.
- */
-wiztrap:
-    if (wizard && !program_state.wizkit_wishing) {
-        struct rm *lev;
-        int trap, x = u.ux, y = u.uy;
-
-        for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
-            struct trap *t;
-            const char *tname;
-
-            tname = defsyms[trap_to_defsym(trap)].explanation;
-            if (strncmpi(tname, bp, strlen(tname)))
-                continue;
-            /* found it; avoid stupid mistakes */
-            if ((trap == TRAPDOOR || trap == HOLE) && !Can_fall_thru(&u.uz))
-                trap = ROCKTRAP;
-            if ((t = maketrap(x, y, trap)) != 0) {
-                trap = t->ttyp;
-                tname = defsyms[trap_to_defsym(trap)].explanation;
-                pline("%s%s.", An(tname),
-                      (trap != MAGIC_PORTAL) ? "" : " to nowhere");
-            } else
-                pline("Creation of %s failed.", an(tname));
-            return &zeroobj;
-        }
-
-        /* furniture and terrain */
-        lev = &levl[x][y];
-        p = eos(bp);
-        if (!BSTRCMPI(bp, p - 8, "fountain")) {
-            lev->typ = FOUNTAIN;
-            level.flags.nfountains++;
-            if (!strncmpi(bp, "magic ", 6))
-                lev->blessedftn = 1;
-            pline("A %sfountain.", lev->blessedftn ? "magic " : "");
-            newsym(x, y);
-            return &zeroobj;
-        }
-        if (!BSTRCMPI(bp, p - 6, "throne")) {
-            lev->typ = THRONE;
-            pline("A throne.");
-            newsym(x, y);
-            return &zeroobj;
-        }
-        if (!BSTRCMPI(bp, p - 4, "sink")) {
-            lev->typ = SINK;
-            level.flags.nsinks++;
-            pline("A sink.");
-            newsym(x, y);
-            return &zeroobj;
-        }
-        /* ("water" matches "potion of water" rather than terrain) */
-        if (!BSTRCMPI(bp, p - 4, "pool") || !BSTRCMPI(bp, p - 4, "moat")) {
-            lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT;
-            del_engr_at(x, y);
-            pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
-            /* Must manually make kelp! */
-            water_damage_chain(level.objects[x][y], TRUE);
-            newsym(x, y);
-            return &zeroobj;
-        }
-        if (!BSTRCMPI(bp, p - 4, "lava")) { /* also matches "molten lava" */
-            lev->typ = LAVAPOOL;
-            del_engr_at(x, y);
-            pline("A pool of molten lava.");
-            if (!(Levitation || Flying))
-                (void) lava_effects();
-            newsym(x, y);
-            return &zeroobj;
-        }
-
-        if (!BSTRCMPI(bp, p - 5, "altar")) {
-            aligntyp al;
-
-            lev->typ = ALTAR;
-            if (!strncmpi(bp, "chaotic ", 8))
-                al = A_CHAOTIC;
-            else if (!strncmpi(bp, "neutral ", 8))
-                al = A_NEUTRAL;
-            else if (!strncmpi(bp, "lawful ", 7))
-                al = A_LAWFUL;
-            else if (!strncmpi(bp, "unaligned ", 10))
-                al = A_NONE;
-            else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
-                al = (!rn2(6)) ? A_NONE : rn2((int) A_LAWFUL + 2) - 1;
-            lev->altarmask = Align2amask(al);
-            pline("%s altar.", An(align_str(al)));
-            newsym(x, y);
-            return &zeroobj;
-        }
-
-        if (!BSTRCMPI(bp, p - 5, "grave")
-            || !BSTRCMPI(bp, p - 9, "headstone")) {
-            make_grave(x, y, (char *) 0);
-            pline("%s.", IS_GRAVE(lev->typ) ? "A grave"
-                                            : "Can't place a grave here");
-            newsym(x, y);
-            return &zeroobj;
-        }
-
-        if (!BSTRCMPI(bp, p - 4, "tree")) {
-            lev->typ = TREE;
-            pline("A tree.");
-            newsym(x, y);
-            block_point(x, y);
-            return &zeroobj;
-        }
-
-        if (!BSTRCMPI(bp, p - 4, "bars")) {
-            lev->typ = IRONBARS;
-            pline("Iron bars.");
-            newsym(x, y);
-            return &zeroobj;
-        }
-    }
-
-    if (!oclass && !typ) {
-        if (!strncmpi(bp, "polearm", 7)) {
-            typ = rnd_otyp_by_wpnskill(P_POLEARMS);
-            goto typfnd;
-        } else if (!strncmpi(bp, "hammer", 6)) {
-            typ = rnd_otyp_by_wpnskill(P_HAMMER);
-            goto typfnd;
-        }
-    }
-
-    if (!oclass)
-        return ((struct obj *) 0);
-any:
-    if (!oclass)
-        oclass = wrpsym[rn2((int) sizeof(wrpsym))];
-typfnd:
-    if (typ)
-        oclass = objects[typ].oc_class;
-
-    /* handle some objects that are only allowed in wizard mode */
-    if (typ && !wizard) {
-        switch (typ) {
-        case AMULET_OF_YENDOR:
-            typ = FAKE_AMULET_OF_YENDOR;
-            break;
-        case CANDELABRUM_OF_INVOCATION:
-            typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
-            break;
-        case BELL_OF_OPENING:
-            typ = BELL;
-            break;
-        case SPE_BOOK_OF_THE_DEAD:
-            typ = SPE_BLANK_PAPER;
-            break;
-        case MAGIC_LAMP:
-            typ = OIL_LAMP;
-            break;
-        default:
-            /* catch any other non-wishable objects (venom) */
-            if (objects[typ].oc_nowish)
-                return (struct obj *) 0;
-            break;
-        }
-    }
-
-    /*
-     * Create the object, then fine-tune it.
-     */
-    otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE);
-    typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */
-
-    if (islit && (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN
-                  || Is_candle(otmp) || typ == POT_OIL)) {
-        place_object(otmp, u.ux, u.uy); /* make it viable light source */
-        begin_burn(otmp, FALSE);
-        obj_extract_self(otmp); /* now release it for caller's use */
-    }
-
-    /* if player specified a reasonable count, maybe honor it */
-    if (cnt > 0 && objects[typ].oc_merge
-        && (wizard || cnt < rnd(6) || (cnt <= 7 && Is_candle(otmp))
-            || (cnt <= 20 && ((oclass == WEAPON_CLASS && is_ammo(otmp))
-                              || typ == ROCK || is_missile(otmp)))))
-        otmp->quan = (long) cnt;
-
-    if (oclass == VENOM_CLASS)
-        otmp->spe = 1;
-
-    if (spesgn == 0) {
-        spe = otmp->spe;
-    } else if (wizard) {
-        ; /* no alteration to spe */
-    } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS
-               || is_weptool(otmp)
-               || (oclass == RING_CLASS && objects[typ].oc_charged)) {
-        if (spe > rnd(5) && spe > otmp->spe)
-            spe = 0;
-        if (spe > 2 && Luck < 0)
-            spesgn = -1;
-    } else {
-        if (oclass == WAND_CLASS) {
-            if (spe > 1 && spesgn == -1)
-                spe = 1;
-        } else {
-            if (spe > 0 && spesgn == -1)
-                spe = 0;
-        }
-        if (spe > otmp->spe)
-            spe = otmp->spe;
-    }
-
-    if (spesgn == -1)
-        spe = -spe;
-
-    /* set otmp->spe.  This may, or may not, use spe... */
-    switch (typ) {
-    case TIN:
-        if (contents == EMPTY) {
-            otmp->corpsenm = NON_PM;
-            otmp->spe = 0;
-        } else if (contents == SPINACH) {
-            otmp->corpsenm = NON_PM;
-            otmp->spe = 1;
-        }
-        break;
-    case TOWEL:
-        if (wetness)
-            otmp->spe = wetness;
-        break;
-    case SLIME_MOLD:
-        otmp->spe = ftype;
-    /* Fall through */
-    case SKELETON_KEY:
-    case CHEST:
-    case LARGE_BOX:
-    case HEAVY_IRON_BALL:
-    case IRON_CHAIN:
-    case STATUE:
-        /* otmp->cobj already done in mksobj() */
-        break;
-#ifdef MAIL
-    case SCR_MAIL:
-        /* 0: delivered in-game via external event (or randomly for fake mail);
-           1: from bones or wishing; 2: written with marker */
-        otmp->spe = 1;
-        break;
-#endif
-    case WAN_WISHING:
-        if (!wizard) {
-            otmp->spe = (rn2(10) ? -1 : 0);
-            break;
-        }
-    /* fall through, if wizard */
-    default:
-        otmp->spe = spe;
-    }
-
-    /* set otmp->corpsenm or dragon scale [mail] */
-    if (mntmp >= LOW_PM) {
-        if (mntmp == PM_LONG_WORM_TAIL)
-            mntmp = PM_LONG_WORM;
-
-        switch (typ) {
-        case TIN:
-            otmp->spe = 0; /* No spinach */
-            if (dead_species(mntmp, FALSE)) {
-                otmp->corpsenm = NON_PM; /* it's empty */
-            } else if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
-                       && !(mvitals[mntmp].mvflags & G_NOCORPSE)
-                       && mons[mntmp].cnutrit != 0) {
-                otmp->corpsenm = mntmp;
-            }
-            break;
-        case CORPSE:
-            if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
-                && !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
-                if (mons[mntmp].msound == MS_GUARDIAN)
-                    mntmp = genus(mntmp, 1);
-                set_corpsenm(otmp, mntmp);
-            }
-            break;
-        case EGG:
-            mntmp = can_be_hatched(mntmp);
-            /* this also sets hatch timer if appropriate */
-            set_corpsenm(otmp, mntmp);
-            break;
-        case FIGURINE:
-            if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
-#ifdef MAIL
-                && mntmp != PM_MAIL_DAEMON
-#endif
-                )
-                otmp->corpsenm = mntmp;
-            break;
-        case STATUE:
-            otmp->corpsenm = mntmp;
-            if (Has_contents(otmp) && verysmall(&mons[mntmp]))
-                delete_contents(otmp); /* no spellbook */
-            otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
-            break;
-        case SCALE_MAIL:
-            /* Dragon mail - depends on the order of objects & dragons. */
-            if (mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON)
-                otmp->otyp = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
-            break;
-        }
-    }
-
-    /* set blessed/cursed -- setting the fields directly is safe
-     * since weight() is called below and addinv() will take care
-     * of luck */
-    if (iscursed) {
-        curse(otmp);
-    } else if (uncursed) {
-        otmp->blessed = 0;
-        otmp->cursed = (Luck < 0 && !wizard);
-    } else if (blessed) {
-        otmp->blessed = (Luck >= 0 || wizard);
-        otmp->cursed = (Luck < 0 && !wizard);
-    } else if (spesgn < 0) {
-        curse(otmp);
-    }
-
-    /* set eroded and erodeproof */
-    if (erosion_matters(otmp)) {
-        if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
-            otmp->oeroded = eroded;
-        if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
-            otmp->oeroded2 = eroded2;
-        /*
-         * 3.6.1: earlier versions included `&& !eroded && !eroded2' here,
-         * but damageproof combined with damaged is feasible (eroded
-         * armor modified by confused reading of cursed destroy armor)
-         * so don't prevent player from wishing for such a combination.
-         */
-        if (erodeproof && (is_damageable(otmp) || otmp->otyp == CRYSKNIFE))
-            otmp->oerodeproof = (Luck >= 0 || wizard);
-    }
-
-    /* set otmp->recharged */
-    if (oclass == WAND_CLASS) {
-        /* prevent wishing abuse */
-        if (otmp->otyp == WAN_WISHING && !wizard)
-            rechrg = 1;
-        otmp->recharged = (unsigned) rechrg;
-    }
-
-    /* set poisoned */
-    if (ispoisoned) {
-        if (is_poisonable(otmp))
-            otmp->opoisoned = (Luck >= 0);
-        else if (oclass == FOOD_CLASS)
-            /* try to taint by making it as old as possible */
-            otmp->age = 1L;
-    }
-    /* and [un]trapped */
-    if (trapped) {
-        if (Is_box(otmp) || typ == TIN)
-            otmp->otrapped = (trapped == 1);
-    }
-
-    if (isgreased)
-        otmp->greased = 1;
-
-    if (isdiluted && otmp->oclass == POTION_CLASS && otmp->otyp != POT_WATER)
-        otmp->odiluted = 1;
-
-    /* set tin variety */
-    if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard))
-        set_tin_variety(otmp, tvariety);
-
-    if (name) {
-        const char *aname;
-        short objtyp;
-
-        /* an artifact name might need capitalization fixing */
-        aname = artifact_name(name, &objtyp);
-        if (aname && objtyp == otmp->otyp)
-            name = aname;
-
-        /* 3.6 tribute - fix up novel */
-        if (otmp->otyp == SPE_NOVEL) {
-            const char *novelname;
-
-            novelname = lookup_novel(name, &otmp->novelidx);
-            if (novelname)
-                name = novelname;
-        }
-
-        otmp = oname(otmp, name);
-        /* name==aname => wished for artifact (otmp->oartifact => got it) */
-        if (otmp->oartifact || name == aname) {
-            otmp->quan = 1L;
-            u.uconduct.wisharti++; /* KMH, conduct */
-        }
-    }
-
-    /* more wishing abuse: don't allow wishing for certain artifacts */
-    /* and make them pay; charge them for the wish anyway! */
-    if ((is_quest_artifact(otmp)
-         || (otmp->oartifact && rn2(nartifact_exist()) > 1)) && !wizard) {
-        artifact_exists(otmp, safe_oname(otmp), FALSE);
-        obfree(otmp, (struct obj *) 0);
-        otmp = &zeroobj;
-        pline("For a moment, you feel %s in your %s, but it disappears!",
-              something, makeplural(body_part(HAND)));
-    }
-
-    if (halfeaten && otmp->oclass == FOOD_CLASS) {
-        if (otmp->otyp == CORPSE)
-            otmp->oeaten = mons[otmp->corpsenm].cnutrit;
-        else
-            otmp->oeaten = objects[otmp->otyp].oc_nutrition;
-        /* (do this adjustment before setting up object's weight) */
-        consume_oeaten(otmp, 1);
-    }
-    otmp->owt = weight(otmp);
-    if (very && otmp->otyp == HEAVY_IRON_BALL)
-        otmp->owt += IRON_BALL_W_INCR;
-    else if (gsize > 1 && otmp->globby)
-        /* 0: unspecified => small; 1: small => keep default owt of 20;
-           2: medium => 120; 3: large => 320; 4: very large => 520 */
-        otmp->owt += 100 + (gsize - 2) * 200;
-
-    return otmp;
-}
-
-int
-rnd_class(first, last)
-int first, last;
-{
-    int i, x, sum = 0;
-
-    if (first == last)
-        return first;
-    for (i = first; i <= last; i++)
-        sum += objects[i].oc_prob;
-    if (!sum) /* all zero */
-        return first + rn2(last - first + 1);
-    x = rnd(sum);
-    for (i = first; i <= last; i++)
-        if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
-            return i;
-    return 0;
-}
-
-STATIC_OVL const char *
-Japanese_item_name(i)
-int i;
-{
-    struct Jitem *j = Japanese_items;
-
-    while (j->item) {
-        if (i == j->item)
-            return j->name;
-        j++;
-    }
-    return (const char *) 0;
-}
-
-const char *
-suit_simple_name(suit)
-struct obj *suit;
-{
-    const char *suitnm, *esuitp;
-
-    if (Is_dragon_mail(suit))
-        return "dragon mail"; /* <color> dragon scale mail */
-    else if (Is_dragon_scales(suit))
-        return "dragon scales";
-    suitnm = OBJ_NAME(objects[suit->otyp]);
-    esuitp = eos((char *) suitnm);
-    if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
-        return "mail"; /* most suits fall into this category */
-    else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
-        return "jacket"; /* leather jacket */
-    /* suit is lame but armor is ambiguous and body armor is absurd */
-    return "suit";
-}
-
-const char *
-cloak_simple_name(cloak)
-struct obj *cloak;
-{
-    if (cloak) {
-        switch (cloak->otyp) {
-        case ROBE:
-            return "robe";
-        case MUMMY_WRAPPING:
-            return "wrapping";
-        case ALCHEMY_SMOCK:
-            return (objects[cloak->otyp].oc_name_known && cloak->dknown)
-                       ? "smock"
-                       : "apron";
-        default:
-            break;
-        }
-    }
-    return "cloak";
-}
-
-/* helm vs hat for messages */
-const char *
-helm_simple_name(helmet)
-struct obj *helmet;
-{
-    /*
-     *  There is some wiggle room here; the result has been chosen
-     *  for consistency with the "protected by hard helmet" messages
-     *  given for various bonks on the head:  headgear that provides
-     *  such protection is a "helm", that which doesn't is a "hat".
-     *
-     *      elven leather helm / leather hat    -> hat
-     *      dwarvish iron helm / hard hat       -> helm
-     *  The rest are completely straightforward:
-     *      fedora, cornuthaum, dunce cap       -> hat
-     *      all other types of helmets          -> helm
-     */
-    return (helmet && !is_metallic(helmet)) ? "hat" : "helm";
-}
-
-const char *
-mimic_obj_name(mtmp)
-struct monst *mtmp;
-{
-    if (mtmp->m_ap_type == M_AP_OBJECT) {
-        if (mtmp->mappearance == GOLD_PIECE)
-            return "gold";
-        if (mtmp->mappearance != STRANGE_OBJECT)
-            return simple_typename(mtmp->mappearance);
-    }
-    return "whatcha-may-callit";
-}
-
-/*
- * Construct a query prompt string, based around an object name, which is
- * guaranteed to fit within [QBUFSZ].  Takes an optional prefix, three
- * choices for filling in the middle (two object formatting functions and a
- * last resort literal which should be very short), and an optional suffix.
- */
-char *
-safe_qbuf(qbuf, qprefix, qsuffix, obj, func, altfunc, lastR)
-char *qbuf; /* output buffer */
-const char *qprefix, *qsuffix;
-struct obj *obj;
-char *FDECL((*func), (OBJ_P)), *FDECL((*altfunc), (OBJ_P));
-const char *lastR;
-{
-    char *bufp, *endp;
-    /* convert size_t (or int for ancient systems) to ordinary unsigned */
-    unsigned len, lenlimit,
-        len_qpfx = (unsigned) (qprefix ? strlen(qprefix) : 0),
-        len_qsfx = (unsigned) (qsuffix ? strlen(qsuffix) : 0),
-        len_lastR = (unsigned) strlen(lastR);
-
-    lenlimit = QBUFSZ - 1;
-    endp = qbuf + lenlimit;
-    /* sanity check, aimed mainly at paniclog (it's conceivable for
-       the result of short_oname() to be shorter than the length of
-       the last resort string, but we ignore that possibility here) */
-    if (len_qpfx > lenlimit)
-        impossible("safe_qbuf: prefix too long (%u characters).", len_qpfx);
-    else if (len_qpfx + len_qsfx > lenlimit)
-        impossible("safe_qbuf: suffix too long (%u + %u characters).",
-                   len_qpfx, len_qsfx);
-    else if (len_qpfx + len_lastR + len_qsfx > lenlimit)
-        impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
-                   len_qpfx, len_lastR, len_qsfx);
-
-    /* the output buffer might be the same as the prefix if caller
-       has already partially filled it */
-    if (qbuf == qprefix) {
-        /* prefix is already in the buffer */
-        *endp = '\0';
-    } else if (qprefix) {
-        /* put prefix into the buffer */
-        (void) strncpy(qbuf, qprefix, lenlimit);
-        *endp = '\0';
-    } else {
-        /* no prefix; output buffer starts out empty */
-        qbuf[0] = '\0';
-    }
-    len = (unsigned) strlen(qbuf);
-
-    if (len + len_lastR + len_qsfx > lenlimit) {
-        /* too long; skip formatting, last resort output is truncated */
-        if (len < lenlimit) {
-            (void) strncpy(&qbuf[len], lastR, lenlimit - len);
-            *endp = '\0';
-            len = (unsigned) strlen(qbuf);
-            if (qsuffix && len < lenlimit) {
-                (void) strncpy(&qbuf[len], qsuffix, lenlimit - len);
-                *endp = '\0';
-                /* len = (unsigned) strlen(qbuf); */
-            }
-        }
-    } else {
-        /* suffix and last resort are guaranteed to fit */
-        len += len_qsfx; /* include the pending suffix */
-        /* format the object */
-        bufp = short_oname(obj, func, altfunc, lenlimit - len);
-        if (len + strlen(bufp) <= lenlimit)
-            Strcat(qbuf, bufp); /* formatted name fits */
-        else
-            Strcat(qbuf, lastR); /* use last resort */
-        releaseobuf(bufp);
-
-        if (qsuffix)
-            Strcat(qbuf, qsuffix);
-    }
-    /* assert( strlen(qbuf) < QBUFSZ ); */
-    return qbuf;
-}
-
-/*objnam.c*/