-/* NetHack 3.6 objnam.c $NHDT-Date: 1447490776 2015/11/14 08:46:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.154 $ */
+/* NetHack 3.6 objnam.c $NHDT-Date: 1583315888 2020/03/04 09:58:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.293 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2022 */
/* JNetHack may be freely redistributed. See license for details. */
#include "hack.h"
#define NUMOBUF 12
STATIC_DCL char *FDECL(strprepend, (char *, const char *));
+#if 0 /*JP*/
STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
+#endif
+STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (const char *, CHAR_P, int));
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 boolean
-FDECL(singplur_lookup, (char *, char *, BOOLEAN_P, const char *const *));
+STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned));
+STATIC_DCL char *FDECL(just_an, (char *str, const char *));
+#if 0 /*JP*/
+STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
+ const char *const *));
STATIC_DCL char *FDECL(singplur_compound, (char *));
+#endif
STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
-#if 1 /*JP*/
-static char *FDECL(substitute, (char *, char *, char *));
-static char *FDECL(transpose, (char *buf,char *));
-static char *FDECL(delete, (char *, char *str));
-static int FDECL(digit_8, (int));
-static int FDECL(atoi_8, (const char *));
+#if 0 /*JP*/
+STATIC_DCL boolean FDECL(badman, (const char *, BOOLEAN_P));
#endif
+STATIC_DCL char *FDECL(globwt, (struct obj *, char *, boolean *));
struct Jitem {
int item;
#define BSTRNCMPI(base, ptr, str, num) \
((ptr) < base || strncmpi((ptr), str, num))
#define Strcasecpy(dst, src) (void) strcasecpy(dst, src)
+#if 1 /*JP*/
+#define STRNCMPEX(x, y) strncmp(x, y, l = strlen(y))
+#endif
/* true for gems/rocks that should have " stone" appended to their names */
#define GemStone(typ) \
&& typ != SAPPHIRE && typ != BLACK_OPAL && typ != EMERALD \
&& typ != OPAL)))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "wakizashi" },
{ BROADSWORD, "ninja-to" },
{ FLAIL, "nunchaku" },
register int i = (int) strlen(pref);
if (i > PREFIX) {
- impossible("PREFIX too short (for %d).%s//%s", i, s, pref);
+ impossible("PREFIX too short (for %d).", i);
return s;
}
s -= i;
char *bufp;
{
/* caller may not know whether bufp is the most recently allocated
- buffer; if it isn't, do nothing */
- if (bufp == obufs[obufidx])
+ 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;
}
register int otyp;
{
char *buf = nextobuf();
- register struct objclass *ocl = &objects[otyp];
- register const char *actualn = OBJ_NAME(*ocl);
- register const char *dn = OBJ_DESCR(*ocl);
- register const char *un = ocl->oc_uname;
- register int nn = ocl->oc_name_known;
+ 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);
Strcat(buf, "\8fñ");
break;
case SPBOOK_CLASS:
+ if (otyp != SPE_NOVEL) {
+/*JP
+ Strcpy(buf, "spellbook");
+*/
+ Strcat(buf, "\96\82\96@\8f\91");
+ } else {
/*JP
- Strcpy(buf, "spellbook");
+ Strcpy(buf, !nn ? "book" : "novel");
*/
- Strcat(buf, "\96\82\96@\8f\91");
+ Strcpy(buf, !nn ? "\96{" : "\8f¬\90à");
+ nn = 0;
+ }
break;
case RING_CLASS:
/*JP
return bufp;
}
+/* typename for debugging feedback where data involved might be suspect */
+char *
+safe_typename(otyp)
+int otyp;
+{
+ unsigned save_nameknown;
+ char *res = 0;
+
+ if (otyp < STRANGE_OBJECT || otyp >= NUM_OBJECTS
+ || !OBJ_NAME(objects[otyp])) {
+ res = nextobuf();
+ Sprintf(res, "glorkum[%d]", otyp);
+ } else {
+ /* force it to be treated as fully discovered */
+ save_nameknown = objects[otyp].oc_name_known;
+ objects[otyp].oc_name_known = 1;
+ res = simple_typename(otyp);
+ objects[otyp].oc_name_known = save_nameknown;
+ }
+ return res;
+}
+
boolean
obj_is_pname(obj)
struct obj *obj;
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. The kludge used is
- * to temporarily set Blind so that xname() skips the dknown setting. This
- * assumes that we don't want to do this too often; if this function becomes
- * frequently used, it'd probably be better to pass a parameter to xname()
- * or doname() instead.
+ * we don't want to set dknown if it's not set already.
*/
char *
distant_name(obj, func)
{
char *str;
- long save_Blinded = Blinded;
- Blinded = 1;
+ /* 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);
- Blinded = save_Blinded;
+ --distantname;
return str;
}
fruitname(juice)
boolean juice; /* whether or not to append " juice" to the name */
{
-#if 1 /*JP*//*\93ú\96{\8cê\82Å\82Í\82»\82±\82Ü\82Å\82µ\82È\82¢*/
- char *buf = nextobuf();
- Sprintf(buf, "%s%s", pl_fruit, juice ? "\83W\83\85\81[\83X" : "");
- return buf;
-#else
+#if 0 /*JP*/
char *buf = nextobuf();
const char *fruit_nam = strstri(pl_fruit, " of ");
Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
return buf;
+#else
+ /*\93ú\96{\8cê\82Å\82Í\82»\82±\82Ü\82Å\82µ\82È\82¢*/
+ char *buf = nextobuf();
+ Sprintf(buf, "%s%s", pl_fruit, juice ? "\83W\83\85\81[\83X" : "");
+ return buf;
#endif
}
+/* 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 *
+STATIC_OVL char *
xname_flags(obj, cxn_flags)
register struct obj *obj;
unsigned cxn_flags; /* bitmask of CXN_xxx values */
buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
actualn = Japanese_item_name(typ);
+ /* As of 3.6.2: this used to be part of 'dn's initialization, but it
+ needs to come after possibly overriding 'actualn' */
+ if (!dn)
+ dn = actualn;
buf[0] = '\0';
/*
*/
if (!nn && ocl->oc_uses_known && ocl->oc_unique)
obj->known = 0;
- if (!Blind)
- obj->dknown = TRUE;
+ if (!Blind && !distantname)
+ obj->dknown = 1;
if (Role_if(PM_PRIEST))
- obj->bknown = TRUE;
+ obj->bknown = 1; /* actively avoid set_bknown();
+ * we mustn't call update_inventory() now because
+ * it would call xname() (via doname()) recursively
+ * and could end up clobbering all the obufs... */
if (iflags.override_ID) {
known = dknown = bknown = TRUE;
Strcpy(buf, "poisoned ");
*/
Strcpy(buf, "\93Å\82Ì\93h\82ç\82ê\82½");
+ /*FALLTHRU*/
case VENOM_CLASS:
case TOOL_CLASS:
#if 1 /*JP*/
Strcpy(buf, (obj->spe < 3) ? "\8e¼\82Á\82½" : "\94G\82ê\82½");
if (!dknown)
- Strcat(buf, dn ? dn : actualn);
+ Strcat(buf, dn);
else if (nn)
Strcat(buf, actualn);
else if (un) {
#if 0 /*JP*/
- Strcat(buf, dn ? dn : actualn);
+ Strcat(buf, dn);
Strcat(buf, " called ");
Strcat(buf, un);
#else
Strcat(buf, un);
Strcat(buf, "\82Æ\8cÄ\82Î\82ê\82é");
- Strcat(buf, dn ? dn : actualn);
+ Strcat(buf, dn);
#endif
} else
- Strcat(buf, dn ? dn : actualn);
+ Strcat(buf, dn);
+
#if 0 /*JP*/ /*\82±\82ê\82Í\8cê\8f\87\82Ì\8aÖ\8cW\82©\82ç\8fã\82Ì\95û\82Å\92è\8b`*/
- /* 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" : "",
+ char anbuf[10]; /* [4] would be enough: 'a','n',' ','\0' */
+
+ Sprintf(eos(buf), " of %s%s",
+ just_an(anbuf, mons[omndx].mname),
mons[omndx].mname);
} else if (is_wet_towel(obj)) {
#else
break;
}
- if (nn)
+ if (nn) {
Strcat(buf, actualn);
- else if (un) {
+ } else if (un) {
#if 0 /*JP*/
if (is_boots(obj))
Strcat(buf, "boots");
Strcat(buf, " called ");
Strcat(buf, un);
#else
- char *p;
+ const char *p;
if (is_boots(obj))
p = "\8cC";
else if (is_gloves(obj))
break;
case FOOD_CLASS:
if (typ == SLIME_MOLD) {
- register struct fruit *f;
+ struct fruit *f = fruit_from_indx(obj->spe);
- for (f = ffruit; f; f = f->nextf) {
- if (f->fid == obj->spe) {
- Strcpy(buf, f->fname);
- break;
- }
- }
if (!f) {
impossible("Bad fruit #%d?", obj->spe);
Strcpy(buf, "fruit");
- } else 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;
+ } 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 (Is_pudding(obj)) {
+ if (obj->globby) {
Sprintf(buf, "%s%s",
- (obj->owt < 100)
+ (obj->owt <= 100)
/*JP
? "small "
*/
#endif
break;
case ROCK_CLASS:
- if (typ == STATUE && omndx != NON_PM)
+ if (typ == STATUE && omndx != NON_PM) {
#if 0 /*JP*/
+ char anbuf[10];
+
Sprintf(buf, "%s%s of %s%s",
(Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
? "historic "
? ""
: the_unique_pm(&mons[omndx])
? "the "
- : index(vowels, *mons[omndx].mname)
- ? "an "
- : "a ",
+ : just_an(anbuf, mons[omndx].mname),
mons[omndx].mname);
#else
Sprintf(eos(buf), "%s%s\82Ì%s",
: "",
mons[obj->corpsenm].mname, actualn);
#endif
- else
+ } else
#if 0 /*JP*/
Strcpy(buf, actualn);
#else
case SPBOOK_CLASS:
if (typ == SPE_NOVEL) { /* 3.6 tribute */
if (!dknown)
+/*JP
Strcpy(buf, "book");
+*/
+ Strcpy(buf, "\96{");
else if (nn)
Strcpy(buf, actualn);
else if (un)
+/*JP
Sprintf(buf, "novel called %s", un);
+*/
+ Sprintf(buf, "%s\82Æ\82¢\82¤\8f¬\90à", un);
else
+/*JP
Sprintf(buf, "%s book", dn);
+*/
+ Sprintf(buf, "%s\96{", dn);
break;
/* end of tribute */
} else if (!dknown) {
#if 0 /*JP*/
if (has_oname(obj) && dknown) {
Strcat(buf, " named ");
- nameit:
+ nameit:
Strcat(buf, ONAME(obj));
}
brown potion -- if oc_name_known not set
potion of object detection -- if discovered
*/
-static char *
+STATIC_OVL char *
minimal_xname(obj)
struct obj *obj;
{
struct obj bareobj;
struct objclass saveobcls;
int otyp = obj->otyp;
+#if 1 /*JP*/
+ int l = 0;
+#endif
/* suppress user-supplied name */
saveobcls.oc_uname = objects[otyp].oc_uname;
if (!strncmp(bufp, "uncursed ", 9))
bufp += 9; /* Role_if(PM_PRIEST) */
#else
- if (!strncmp(bufp, "\8eô\82í\82ê\82Ä\82¢\82È\82¢", 14))
- bufp += 14; /* Role_if(PM_PRIEST) */
+ if (!STRNCMPEX(bufp, "\8eô\82í\82ê\82Ä\82¢\82È\82¢"))
+ bufp += l; /* Role_if(PM_PRIEST) */
#endif
objects[otyp].oc_uname = saveobcls.oc_uname;
Strcat(prefix, is_corrodeable(obj) ? "\95\85\90H\82µ\82½" : "\95\85\82Á\82½");
}
if (rknown && obj->oerodeproof)
+#if 0 /*JP:T*/
Strcat(prefix, iscrys
-/*JP
? "fixed "
-*/
- ? "\88À\92è\82µ\82½"
: is_rustprone(obj)
-/*JP
? "rustproof "
-*/
- ? "\8eK\82Ñ\82È\82¢"
: is_corrodeable(obj)
-#if 0 /*JP*/
? "corrodeproof " /* "stainless"? */
+ : is_flammable(obj)
+ ? "fireproof "
+ : "");
#else
+ Strcat(prefix, iscrys
+ ? "\88À\92è\82µ\82½"
+ : is_rustprone(obj)
+ ? "\8eK\82Ñ\82È\82¢"
+ : is_corrodeable(obj)
? "\95\85\90H\82µ\82È\82¢" /* "stainless"? */
-#endif
: is_flammable(obj)
-/*JP
- ? "fireproof "
-*/
? "\94R\82¦\82È\82¢"
: "");
+#endif
}
-static char *
-doname_base(obj, with_price)
-register struct obj *obj;
-boolean with_price;
+/* 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;
- boolean known, cknown, bknown, lknown;
+ boolean ispoisoned = FALSE,
+ with_price = (doname_flags & DONAME_WITH_PRICE) != 0,
+ vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0,
+ weightshown = FALSE;
+ boolean known, dknown, cknown, bknown, lknown;
int omndx = obj->corpsenm;
- char prefix[PREFIX];
+ char prefix[PREFIX], globbuf[QBUFSZ];
+#if 0 /*JP*/
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) */
+#endif
register char *bp = xname(obj);
-#if 1 /*JP*//*\8f\87\8f\98\93ü\82ê\91Ö\82¦\82É\8eg\82¤*/
- char preprefix[PREFIX];
+#if 1 /*JP*/
+ char preprefix[PREFIX]; /*\8f\87\8f\98\93ü\82ê\91Ö\82¦\82É\8eg\82¤*/
+ int l = 0;
#endif
if (iflags.override_ID) {
- known = cknown = bknown = lknown = TRUE;
+ known = dknown = cknown = bknown = lknown = TRUE;
} else {
known = obj->known;
+ dknown = obj->dknown;
cknown = obj->cknown;
bknown = obj->bknown;
lknown = obj->lknown;
* combining both into one function taking a parameter.
*/
/* must check opoisoned--someone can have a weirdly-named fruit */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
bp += 9;
ispoisoned = TRUE;
}
#else
- if (!strncmp(bp, "\93Å\82Ì\93h\82ç\82ê\82½", 12) && obj->opoisoned) {
- bp += 12;
+ if (!STRNCMPEX(bp, "\93Å\82Ì\93h\82ç\82ê\82½") && obj->opoisoned) {
+ bp += l;
ispoisoned = TRUE;
}
#endif
#endif
if (obj->quan != 1L) {
+ if (dknown || !vague_quan)
#if 0 /*JP*/
- Sprintf(prefix, "%ld ", obj->quan);
+ Sprintf(prefix, "%ld ", obj->quan);
#else /* \93ú\96{\8cê\82Æ\82µ\82Ä\82Í\90\94\8e\8c\82ª\82È\82¢\82Ì\82Í\95s\8e©\91R */
- Sprintf(prefix, "%ld%s\82Ì", obj->quan, numeral(obj));
+ Sprintf(prefix, "%ld%s\82Ì", obj->quan, numeral(obj));
#endif
+ else
+/*JP
+ Strcpy(prefix, "some ");
+*/
+ Strcpy(prefix, "\82¢\82\82Â\82©\82Ì");
} else if (obj->otyp == CORPSE) {
/* skip article prefix for corpses [else corpse_xname()
would have to be taught how to strip it off again] */
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->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)))
+ : ((Is_container(obj) || obj->otyp == STATUE)
+ && !Has_contents(obj))))
/*JP
Strcat(prefix, "empty ");
*/
if (lknown && Is_box(obj)) {
if (obj->obroken)
+ /* 3.6.0 used "unlockable" here but that could be misunderstood
+ to mean "capable of being unlocked" rather than the intended
+ "not capable of being locked" */
/*JP
- Strcat(prefix, "unlockable ");
+ Strcat(prefix, "broken ");
*/
Strcat(prefix, "\8c®\82Ì\89ó\82ê\82½");
else if (obj->olocked)
Strcat(prefix, "\96û\82Ì\93h\82ç\82ê\82½");
if (cknown && Has_contents(obj)) {
- /* we count all objects (obj->quantity); perhaps we should
- count separate stacks instead (or even introduce a user
- preference option to choose between the two alternatives)
- since it's somewhat odd so see "containing 1002 items"
- when there are 2 scrolls plus 1000 gold pieces */
- long itemcount = count_contents(obj, FALSE, FALSE, TRUE);
+ /* 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, FALSE);
#if 0 /*JP*/
Sprintf(eos(bp), " containing %ld item%s", itemcount,
#endif
}
- switch (obj->oclass) {
+ switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
case AMULET_CLASS:
if (obj->owornmask & W_AMUL)
/*JP
*/
Strcat(bp, "(\90g\82É\82Â\82¯\82Ä\82¢\82é)");
break;
+ case ARMOR_CLASS:
+ if (obj->owornmask & W_ARMOR) {
+/*JP
+ Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
+*/
+ Strcat(bp, (obj == uskin) ? "(\94§\82É\96\84\82ß\82±\82Ü\82ê\82Ä\82¢\82é)"
+ /* in case of perm_invent update while Wear/Takeoff
+ is in progress; check doffing() before donning()
+ because donning() returns True for both cases */
+/*JP
+ : doffing(obj) ? " (being doffed)"
+*/
+ : doffing(obj) ? " (\90g\82É\82Â\82¯\82Ä\82¢\82é\93r\92\86)"
+/*JP
+ : donning(obj) ? " (being donned)"
+*/
+ : donning(obj) ? " (\92E\82¢\82Å\82¢\82é\93r\92\86)"
+/*JP
+ : " (being worn)");
+*/
+ : "(\90g\82É\82Â\82¯\82Ä\82¢\82é)");
+ /* slippery fingers is an intrinsic condition of the hero
+ rather than extrinsic condition of objects, but gloves
+ are described as slippery when hero has slippery fingers */
+ if (obj == uarmg && Glib) /* just appended "(something)",
+ * change to "(something; slippery)" */
+/*JP
+ Strcpy(rindex(bp, ')'), "; slippery)");
+*/
+ Strcpy(rindex(bp, ')'), "; \82Ê\82é\82Ê\82é)");
+ }
+ /*FALLTHRU*/
case WEAPON_CLASS:
if (ispoisoned)
/*JP
Strcat(prefix, "poisoned ");
*/
Strcat(prefix, "\93Å\82Ì\93h\82ç\82ê\82½");
- plus:
add_erosion_words(obj, prefix);
if (known) {
Strcat(prefix, sitoa(obj->spe));
Strcat(prefix, " ");
}
break;
- case ARMOR_CLASS:
- if (obj->owornmask & W_ARMOR)
-/*JP
- Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
-*/
- Strcat(bp, (obj == uskin) ? "(\94§\82É\96\84\82ß\82±\82Ü\82ê\82Ä\82¢\82é)"
-/*JP
- : " (being worn)");
-*/
- : "(\90g\82É\82Â\82¯\82Ä\82¢\82é)");
- goto plus;
case TOOL_CLASS:
- /* weptools already get this done when we go to the +n code */
- if (!is_weptool(obj))
- add_erosion_words(obj, prefix);
- if (obj->owornmask & (W_TOOL /* blindfold */ | W_SADDLE)) {
+ if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
/*JP
Strcat(bp, " (being worn)");
*/
break;
}
if (obj->otyp == LEASH && obj->leashmon != 0) {
-/*JP
- Strcat(bp, " (in use)");
-*/
- Strcat(bp, "(\8c\8b\82Ñ\82Â\82¯\82Ä\82¢\82é)");
+ struct monst *mlsh = find_mid(obj->leashmon, FM_FMON);
+
+ if (!mlsh) {
+ impossible("leashed monster not on this level");
+ obj->leashmon = 0;
+ } else {
+#if 0 /*JP:T*/
+ Sprintf(eos(bp), " (attached to %s)",
+ noit_mon_nam(mlsh));
+#else
+ Sprintf(eos(bp), " (%s\82É\8c\8b\82Ñ\82Â\82¯\82ç\82ê\82Ä\82¢\82é)",
+ noit_mon_nam(mlsh));
+#endif
+ }
break;
}
- if (is_weptool(obj))
- goto plus;
if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
#if 0 /*JP*/
if (!obj->spe)
goto charges;
break;
case WAND_CLASS:
- add_erosion_words(obj, prefix);
- charges:
+ charges:
if (known)
/*JP
Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
Strcat(bp, "(\8cõ\82Á\82Ä\82¢\82é)");
break;
case RING_CLASS:
- add_erosion_words(obj, prefix);
- ring:
+ ring:
if (obj->owornmask & W_RINGR)
/*JP
Strcat(bp, " (on right ");
*/
Strcat(prefix, "\90H\82×\82©\82¯\82Ì");
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);
+
#if 0 /*JP*/
- Sprintf(prefix, "%s ",
- corpse_xname(obj, prefix, CXN_ARTICLE | CXN_NOCORPSE));
+ Sprintf(prefix, "%s ", cxstr);
#else
- Sprintf(prefix, "%s\82Ì",
- corpse_xname(obj, prefix, CXN_ARTICLE | CXN_NOCORPSE));
+ Sprintf(prefix, "%s\82Ì", cxstr);
#endif
+ /* 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))
#endif
if (omndx >= LOW_PM
&& (known || (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Strcat(prefix, mons[omndx].mname);
Strcat(prefix, " ");
#else
if (bimanual(obj))
hand_s = makeplural(hand_s);
-/*JP
- Sprintf(eos(bp), " (weapon in %s)", hand_s);
-*/
+ /* note: Sting's glow message, if added, will insert text
+ in front of "(weapon in hand)"'s closing paren */
+#if 0 /*JP*/
+ Sprintf(eos(bp), " (%sweapon in %s)",
+ (obj->otyp == AKLYS) ? "tethered " : "", hand_s);
+#else /*\83A\83L\83\8a\83X\82ð\93Á\95Ê\88µ\82¢\82µ\82È\82¢*/
Sprintf(eos(bp), "(%s\82É\82µ\82Ä\82¢\82é)", hand_s);
+#endif
if (warn_obj_cnt && obj == uwep && (EWarn_of_mon & W_WEP) != 0L) {
- /* presumably can be felt when blind */
+ if (!Blind) /* we know bp[] ends with ')'; overwrite that */
#if 0 /*JP*/
- Strcat(bp, " (glowing");
- if (!Blind)
- Sprintf(eos(bp), " %s", glow_color(obj->oartifact));
- Strcat(bp, ")");
-#else
- if (Blind)
- Strcat(bp, " (\94M\82ð\8e\9d\82Á\82Ä\82¢\82é)");
- else
- Sprintf(eos(bp), " (%s\8bP\82¢\82Ä\82¢\82é)",
+ Sprintf(eos(bp) - 1, ", %s %s)",
+ glow_verb(warn_obj_cnt, TRUE),
glow_color(obj->oartifact));
+#else
+ Sprintf(eos(bp) - 1, ", %s%s\82¢\82é)",
+ glow_color(obj->oartifact),
+ jconj(glow_verb(warn_obj_cnt, TRUE), "\82Ä"));
#endif
}
}
Strcat(bp, "(\8f\80\94õ\82µ\82Ä\82¢\82é)");
}
}
- if (!iflags.suppress_price && is_unpaid(obj)) {
+ /* treat 'restoring' like suppress_price because shopkeeper and
+ bill might not be available yet while restore is in progress
+ (objects won't normally be formatted during that time, but if
+ 'perm_invent' is enabled then they might be) */
+ if (iflags.suppress_price || restoring) {
+ ; /* don't attempt to obtain any stop pricing, even if 'with_price' */
+ } else if (is_unpaid(obj)) { /* in inventory or in container in invent */
long quotedprice = unpaid_cost(obj, TRUE);
- Sprintf(eos(bp), " (%s, %ld %s)",
+#if 0 /*JP:T*/
+ Sprintf(eos(bp), " (%s, %s%ld %s)",
obj->unpaid ? "unpaid" : "contents",
+ globwt(obj, globbuf, &weightshown),
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));
+#else
+ Sprintf(eos(bp), " (%s, %s%ld%s)",
+ obj->unpaid ? "\96¢\95¥\82¢" : "\92\86\90g",
+ globwt(obj, globbuf, &weightshown),
+ quotedprice, currency(quotedprice));
+#endif
+ } else if (with_price) { /* on floor or in container on floor */
+ int nochrg = 0;
+ long price = get_cost_of_shop_item(obj, &nochrg);
+
+ if (price > 0L)
+#if 0 /*JP:T*/
+ Sprintf(eos(bp), " (%s, %s%ld %s)",
+ nochrg ? "contents" : "for sale",
+ globwt(obj, globbuf, &weightshown),
+ price, currency(price));
+#else
+ Sprintf(eos(bp), " (%s, %s%ld%s)",
+ nochrg ? "\92\86\90g" : "\8f¤\95i",
+ globwt(obj, globbuf, &weightshown),
+ price, currency(price));
+#endif
+ else if (nochrg > 0)
+#if 0 /*JP:T*/
+ Sprintf(eos(bp), " (%sno charge)",
+ globwt(obj, globbuf, &weightshown));
+#else
+ Sprintf(eos(bp), " (%s\96³\97¿)",
+ globwt(obj, globbuf, &weightshown));
+#endif
}
#if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\95s\97v*/
- 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);
+ if (!strncmp(prefix, "a ", 2)) {
+ /* save current prefix, without "a "; might be empty */
+ Strcpy(tmpbuf, prefix + 2);
+ /* set prefix[] to "", "a ", or "an " */
+ (void) just_an(prefix, *tmpbuf ? tmpbuf : bp);
+ /* append remainder of original prefix */
+ Strcat(prefix, tmpbuf);
}
#endif
- /* show weight for items (debug tourist info)
- * aum is stolen from Crawl's "Arbitrary Unit of Measure" */
- if (wizard) {
- Sprintf(eos(bp), " (%d aum)", obj->owt);
+ /* show weight for items (debug tourist info);
+ "aum" is stolen from Crawl's "Arbitrary Unit of Measure" */
+ if (wizard && iflags.wizweight) {
+ /* wizard mode user has asked to see object weights;
+ globs with shop pricing attached already include it */
+ if (!weightshown)
+ Sprintf(eos(bp), " (%u aum)", obj->owt);
}
#if 0 /*JP*/
bp = strprepend(bp, prefix);
char *
doname(obj)
-register struct obj *obj;
+struct obj *obj;
{
- return doname_base(obj, FALSE);
+ return doname_base(obj, (unsigned) 0);
}
/* Name of object including price. */
char *
doname_with_price(obj)
-register struct obj *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;
{
- return doname_base(obj, TRUE);
+ /* 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)
-register struct obj *otmp;
+struct obj *otmp;
{
/* gold doesn't have any interesting attributes [yet?] */
if (otmp->oclass == COIN_CLASS)
|| 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();
+ /* some callers [aobjnam()] rely on prefix area that xname() sets aside */
+ char *nambuf = nextobuf() + PREFIX;
int omndx = otmp->corpsenm;
+#if 0 /*JP*/
boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0,
/* suppress "the" from "the unique monster corpse" */
+#else
+ boolean
+#endif
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;
+ omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
+ possessive = FALSE,
+ glob = (otmp->otyp != CORPSE && otmp->globby);
const char *mname;
- if (omndx == NON_PM) { /* paranoia */
+ if (glob) {
+ mname = OBJ_NAME(objects[otmp->otyp]); /* "glob of <monster>" */
+ } else if (omndx == NON_PM) { /* paranoia */
/*JP
mname = "thing";
*/
any_prefix = FALSE;
}
- if (!omit_corpse) {
+ if (glob) {
+ ; /* omit_corpse doesn't apply; quantity is always 1 */
+ } else if (!omit_corpse) {
#if 0 /*JP*/
Strcat(nambuf, " corpse");
/* makeplural(nambuf) => append "s" to "corpse" */
/* format the object */
if (obj->otyp == CORPSE) {
- buf = nextobuf();
- Strcpy(buf, corpse_xname(obj, (const char *) 0, CXN_NORMAL));
+ 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
return nam;
}
+/* pick "", "a ", or "an " as article for 'str'; used by an() and doname() */
+STATIC_OVL char *
+just_an(outbuf, str)
+char *outbuf;
+const char *str;
+{
+#if 0 /*JP*//*\95s\92è\8a¥\8e\8c\82Í\95s\97v*/
+ char c0;
+
+ *outbuf = '\0';
+ c0 = lowc(*str);
+ if (!str[1]) {
+ /* single letter; might be used for named fruit */
+ Strcpy(outbuf, index("aefhilmnosx", c0) ? "an " : "a ");
+ } else if (!strncmpi(str, "the ", 4) || !strcmpi(str, "molten lava")
+ || !strcmpi(str, "iron bars") || !strcmpi(str, "ice")) {
+ ; /* no article */
+ } else {
+ if ((index(vowels, c0) && strncmpi(str, "one-", 4)
+ && strncmpi(str, "eucalyptus", 10) && strncmpi(str, "unicorn", 7)
+ && strncmpi(str, "uranium", 7) && strncmpi(str, "useful", 6))
+ || (index("x", c0) && !index(vowels, lowc(str[1]))))
+ Strcpy(outbuf, "an ");
+ else
+ Strcpy(outbuf, "a ");
+ }
+#else
+ *outbuf = '\0';
+#endif
+ return outbuf;
+}
+
char *
an(str)
-register const char *str;
+const char *str;
{
char *buf = nextobuf();
-#if 0 /*JP*//*\95s\92è\8a¥\8e\8c\82Í\95s\97v*/
- 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 ");
+ if (!str || !*str) {
+ impossible("Alphabet soup: 'an(%s)'.", str ? "\"\"" : "<null>");
+ return strcpy(buf, "an []");
}
-
- Strcat(buf, str);
-#else /*\92P\82É\83R\83s\81[*/
- Strcpy(buf, str);
-#endif
- return buf;
+ (void) just_an(buf, str);
+ return strcat(buf, str);
}
char *
#if 0 /*JP*//*\92è\8a¥\8e\8c\82Í\95s\97v*/
boolean insert_the = FALSE;
+ if (!str || !*str) {
+ impossible("Alphabet soup: 'the(%s)'.", str ? "\"\"" : "<null>");
+ return strcpy(buf, "the []");
+ }
if (!strncmpi(str, "the ", 4)) {
buf[0] = lowc(*str);
Strcpy(&buf[1], str + 1);
return buf;
- } else if (*str < 'A' || *str > 'Z') {
+ } 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 {
return s;
}
+#if 0 /* stalled-out work in progress */
+/* Doname2() for itemized buying of 'obj' from a shop */
+char *
+payDoname(obj)
+struct obj *obj;
+{
+ static const char and_contents[] = " and its contents";
+ char *p = doname(obj);
+
+ if (Is_container(obj) && !obj->cknown) {
+ if (obj->unpaid) {
+ if ((int) strlen(p) + sizeof and_contents - 1 < BUFSZ - PREFIX)
+ Strcat(p, and_contents);
+ *p = highc(*p);
+ } else {
+ p = strprepend(p, "Contents of ");
+ }
+ } else {
+ *p = highc(*p);
+ }
+ return p;
+}
+#endif /*0*/
+
/* returns "[your ]xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
char *
yname(obj)
return outbuf;
}
+#if 0 /*JP*/
static const char *wrp[] = {
"wand", "ring", "potion", "scroll", "gem",
"amulet", "spellbook", "spell book",
/* for non-specific wishes */
"weapon", "armor", "tool", "food", "comestible",
};
+#endif
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 };
+#if 0 /*JP*//*\93ú\96{\8cê\82É\82Í\8eO\92P\8c»\82Ìs\82Í\82È\82¢*/
/* return form of the verb (input plural) if xname(otmp) were the subject */
char *
otense(otmp, verb)
* if the result of xname(otmp) would be plural. Don't bother
* recomputing xname(otmp) at this time.
*/
-#if 0 /*JP*//*\93ú\96{\8cê\82É\82Í\8eO\92P\8c»\82Ìs\82Í\82È\82¢*/
if (!is_plural(otmp))
return vtense((char *) 0, verb);
-#endif /*JP*/
buf = nextobuf();
Strcpy(buf, verb);
register const char *subj;
register const char *verb;
{
-#if 0 /*JP*//*\93ú\96{\8cê\82É\82Í\8eO\92P\8c»\82Ìs\82Í\82È\82¢*/
char *buf = nextobuf(), *bspot;
int len, ltmp;
const char *sp, *spot;
return strcpy(buf, verb);
}
-sing:
+ sing:
Strcpy(buf, verb);
len = (int) strlen(buf);
bspot = buf + len - 1;
Strcasecpy(bspot + 1, "s");
}
-#else
- char *buf;
-
- buf = nextobuf();
- Strcpy(buf, verb);
-#endif /*JP*/
return buf;
}
+#endif
+#if 0 /*JP*/
struct sing_plur {
const char *sing, *plur;
};
{ "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 */
- { "tooth", "teeth" },
+ { "serum", "sera" },
{ "staff", "staves" },
+ { "tooth", "teeth" },
{ 0, 0 }
};
"boots", "shoes", "gloves", "lenses", "scales",
"eyes", "gauntlets", "iron bars",
/* both singular and plural are spelled the same */
- "deer", "fish", "tuna", "yaki", "-hai",
- "krill", "manes", "ninja", "sheep", "ronin",
- "roshi", "shito", "tengu", "ki-rin", "Nazgul",
- "gunyoki", "piranha", "samurai", "shuriken", 0,
+ "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
- */
+/* 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) */
const struct sing_plur *sp;
const char *same, *other, *const *as;
int al;
+ int baselen = strlen(basestr);
for (as = as_is; *as; ++as) {
al = (int) strlen(*as);
}
}
+ /* Leave "craft" as a suffix as-is (aircraft, hovercraft);
+ "craft" itself is (arguably) not included in our likely context */
+ if ((baselen > 5) && (!BSTRCMPI(basestr, endstring - 5, "craft")))
+ 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 && baselen > 2 && !strcmpi(endstring - 2, "ox")
+ && !(baselen > 5 && !strcmpi(endstring - 6, "muskox"))) {
+ /* "fox" -> "foxes" */
+ Strcasecpy(endstring, "es");
+ return TRUE;
+ }
+ if (to_plural) {
+ if (baselen > 2 && !strcmpi(endstring - 3, "man")
+ && badman(basestr, to_plural)) {
+ Strcasecpy(endstring, "s");
+ return TRUE;
+ }
+ } else {
+ if (baselen > 2 && !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;
/* wasn't recognized as a compound phrase */
return 0;
}
+#endif
-/* Plural routine; chiefly used for user-defined fruits. 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...
+/* 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
spot--;
while (spot > str && *spot == ' ')
spot--; /* Strip blanks from end */
- *(spot + 1) = 0;
+ *(spot + 1) = '\0';
/* Now spot is the last character of the string */
len = strlen(str);
{
static const char *const already_plural[] = {
"ae", /* algae, larvae, &c */
- "men", /* also catches women, watchmen */
"matzot", 0,
};
/* man/men ("Wiped out all cavemen.") */
if (len >= 3 && !strcmpi(spot - 2, "man")
- /* exclude shamans and humans */
- && (len < 6 || strcmpi(spot - 5, "shaman"))
- && (len < 5 || strcmpi(spot - 4, "human"))) {
+ /* exclude shamans and humans etc */
+ && !badman(str, TRUE)) {
Strcasecpy(spot - 1, "en");
goto bottom;
}
lo_c = lowc(*spot);
+ /* codex/spadix/neocortex and the like */
+ if (len >= 5
+ && (!strcmpi(spot - 2, "dex")
+ ||!strcmpi(spot - 2, "dix")
+ ||!strcmpi(spot - 2, "tex"))
+ /* indices would have been ok too, but stick with indexes */
+ && (strcmpi(spot - 4,"index") != 0)) {
+ Strcasecpy(spot - 1, "ices"); /* ex|ix -> ices */
+ goto bottom;
+ }
/* 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))))
+ || (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot - 1)))
+ /* 21st century k-sound */
+ && !(len >= 4 &&
+ ((lowc(*(spot - 2)) == 'e'
+ && index("mt", lowc(*(spot - 3)))) ||
+ (lowc(*(spot - 2)) == 'o'
+ && index("lp", lowc(*(spot - 3)))))))
/* Kludge to get "tomatoes" and "potatoes" right */
|| (len >= 4 && !strcmpi(spot - 2, "ato"))
|| (len >= 5 && !strcmpi(spot - 4, "dingo"))) {
/* Default: append an 's' */
Strcasecpy(spot + 1, "s");
-bottom:
+ bottom:
if (excess)
Strcat(str, excess);
-#else /*JP*/
+#else /*JP*//*\90V\82µ\82¢\83o\83b\83t\83@\82Í\95K\97v*/
char *str = nextobuf();
Strcpy(str, oldstr);
#endif
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 - 4, "pies")
+ /* avoid false match for "harpies" */
+ && (p - 4 == bp || p[-5] == ' '))
+ /* alternate djinni/djinn spelling; not really needed */
+ || (!BSTRCMPI(bp, p - 6, "genies")
+ /* avoid false match for "progenies" */
+ && (p - 6 == bp || p[-7] == ' '))
|| !BSTRCMPI(bp, p - 5, "mbies") /* zombie */
|| !BSTRCMPI(bp, p - 5, "yries")) /* valkyrie */
goto mins;
|| (p - 4 == bp && !strcmpi(p - 4, "lens"))) {
goto bottom;
}
- mins:
+ mins:
*(p - 1) = '\0'; /* drop s */
} else { /* input doesn't end in 's' */
- if (!BSTRCMPI(bp, p - 3, "men")) {
+ if (!BSTRCMPI(bp, p - 3, "men")
+ && !badman(bp, FALSE)) {
Strcasecpy(p - 2, "an");
goto bottom;
}
/* here we cannot find the plural suffix */
}
-bottom:
+ 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;
-#else /*JP*/
+#else /*JP*//*\90V\82µ\82¢\83o\83b\83t\83@\82Í\95K\97v*/
char *str = nextobuf();
Strcpy(str, oldstr);
return str;
#endif
}
+#if 0 /*JP*/
+STATIC_OVL boolean
+badman(basestr, to_plural)
+const char *basestr;
+boolean to_plural; /* true => makeplural, false => makesingular */
+{
+ /* these are all the prefixes for *man that don't have a *men plural */
+ static const char *no_men[] = {
+ "albu", "antihu", "anti", "ata", "auto", "bildungsro", "cai", "cay",
+ "ceru", "corner", "decu", "des", "dura", "fir", "hanu", "het",
+ "infrahu", "inhu", "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 */
+ static const char *no_man[] = {
+ "abdo", "acu", "agno", "ceru", "cogno", "cycla", "fleh", "grava",
+ "hegu", "preno", "sonar", "speci", "dai", "exa", "fla", "sta", "teg",
+ "tegu", "vela", "da", "hy", "lu", "no", "nu", "ra", "ru", "se", "vi",
+ "ya", "o", "a",
+ };
+ int i, al;
+ const char *endstr, *spot;
+
+ 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;
+}
+#endif
+
/* compare user string against object name string using fuzzy matching */
STATIC_OVL boolean
wishymatch(u_str, o_str, retry_inverted)
int f_o_range, l_o_range;
};
+#if 0 /*JP*//*\95\94\95ª\93I\82È\83W\83\83\83\93\83\8b\8ew\92è\82Å\82Ì\8aè\82¢\97p\81B\93ú\96{\8cê\82Å\82Í\82Æ\82è\82 \82¦\82¸\82µ\82È\82¢*/
/* wishable subranges of objects */
STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
{ "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
{ "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
{ "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
};
+#endif
#if 0 /*JP*//*not used*/
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 {
+static const struct alt_spellings {
const char *sp;
int ob;
} spellings[] = {
{ "eucalyptus", EUCALYPTUS_LEAF },
{ "royal jelly", LUMP_OF_ROYAL_JELLY },
{ "lembas", LEMBAS_WAFER },
+ { "cookie", FORTUNE_COOKIE },
+ { "pie", CREAM_PIE },
{ "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 },
+ /* if we ever add other sizes, move this to o_ranges[] with "bag" */
+ { "box", LARGE_BOX },
/* 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" */
{ "flintstone", FLINT },
{ (const char *) 0, 0 },
};
-#endif
-short
+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) {
}
return otyp;
}
+#endif
+
+STATIC_OVL short
+rnd_otyp_by_namedesc(name, oclass, xtra_prob)
+const char *name;
+char oclass;
+int xtra_prob; /* to force 0% random generation items to also be considered */
+{
+ int i, n = 0;
+ short validobjs[NUM_OBJECTS];
+ register const char *zn;
+ int prob, maxprob = 0;
+
+ if (!name || !*name)
+ return STRANGE_OBJECT;
+
+ memset((genericptr_t) validobjs, 0, sizeof validobjs);
+
+ /* FIXME:
+ * When this spans classes (the !oclass case), the item
+ * probabilities are not very useful because they don't take
+ * the class generation probability into account. [If 10%
+ * of spellbooks were blank and 1% of scrolls were blank,
+ * "blank" would have 10/11 chance to yield a book even though
+ * scrolls are supposed to be much more common than books.]
+ */
+ 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 1 /*JP*/
+ /*
+ * \81u\83C\83F\83\93\83_\81[\82Ì\96\82\8f\9c\82¯\81v\82ð\8aè\82Á\82½\82Æ\82«\82É\82±\82±\82Å\82Í\8bU\95¨\82É
+ * \82È\82ç\82È\82¢\82æ\82¤\82É\82·\82é\81B
+ * \94ñ\83E\83B\83U\81[\83h\83\82\81[\83h\82Å\82Ì\93ü\82ê\91Ö\82¦\8f\88\97\9d\82Í\8cã\82É\82 \82é\81B
+ */
+ if (i == FAKE_AMULET_OF_YENDOR)
+ continue;
+#endif
+ 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 + xtra_prob);
+ }
+ }
+
+ if (n > 0 && maxprob) {
+ prob = rn2(maxprob);
+ for (i = 0; i < n - 1; i++)
+ if ((prob -= (objects[validobjs[i]].oc_prob + xtra_prob)) < 0)
+ break;
+ return validobjs[i];
+ }
+ return STRANGE_OBJECT;
+}
+
+int
+shiny_obj(oclass)
+char oclass;
+{
+ return (int) rnd_otyp_by_namedesc("shiny", oclass, 0);
+}
/*
* Return something wished for. Specifying a null pointer for
register struct obj *otmp;
int cnt, spe, spesgn, typ, very, rechrg;
int blessed, uncursed, iscursed, ispoisoned, isgreased;
- int eroded, eroded2, erodeproof;
+ int eroded, eroded2, erodeproof, locked, unlocked, broken;
int halfeaten, mntmp, contents;
int islit, unlabeled, ishistoric, isdiluted, trapped;
+#if 0 /*JP*/
int tmp, tinv, tvariety;
- int wetness;
+#else
+ int tvariety;
+#endif
+ int wetness, gsize = 0;
struct fruit *f;
int ftype = context.current_fruit;
+#if 0 /*JP*/
+ char fruitbuf[BUFSZ], globbuf[BUFSZ];
+#else
char fruitbuf[BUFSZ];
-#if 1 /*JP*/
- char buf[BUFSZ];
- char pfx[BUFSZ];
#endif
/* 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
* automatically sticks 'candied' in front of such names.
*/
char oclass;
- char *un, *dn, *actualn;
+ 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;
+ cnt = spe = spesgn = typ = 0;
+ very = rechrg = blessed = uncursed = iscursed = ispoisoned =
+ isgreased = eroded = eroded2 = erodeproof = halfeaten =
+ islit = unlabeled = ishistoric = isdiluted = trapped =
+ locked = unlocked = broken = 0;
tvariety = RANDOM_TIN;
mntmp = NON_PM;
#define UNDEFINED 0
while (*bp == ' ')
bp++;
l = 0;
+#if 1 /*JP*//* \8cã\82É\90\94\8e\8c\82ª\82 \82é\82Æ\82«\82Í\8dí\8f\9c */
+ if(!STRNCMPEX(bp, "\8dû\82Ì") ||
+ !STRNCMPEX(bp, "\96{\82Ì") ||
+ !STRNCMPEX(bp, "\92\85\82Ì") ||
+ !STRNCMPEX(bp, "\8cÂ\82Ì") ||
+ !STRNCMPEX(bp, "\96\87\82Ì") ||
+ !STRNCMPEX(bp, "\82Â\82Ì") ||
+ !STRNCMPEX(bp, "\82Ì"))
+ ;
+ else
+ l = 0;
+#endif
} else if (*bp == '+' || *bp == '-') {
spesgn = (*bp++ == '+') ? 1 : -1;
spe = atoi(bp);
while (*bp == ' ')
bp++;
l = 0;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "blessed ", l = 8)
|| !strncmpi(bp, "holy ", l = 5)) {
#else
- } else if (!strncmpi(bp, "\8fj\95\9f\82³\82ê\82½", l = 10)) {
+ } else if (!STRNCMPEX(bp, "\8fj\95\9f\82³\82ê\82½")) {
#endif
blessed = 1;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "moist ", l = 6)
|| !strncmpi(bp, "wet ", l = 4)) {
#else
- } else if (!strncmpi(bp, "\8e¼\82Á\82½", l = 6)
- || !strncmpi(bp, "\94G\82ê\82½", l = 6)) {
+ } else if (!STRNCMPEX(bp, "\8e¼\82Á\82½")
+ || !STRNCMPEX(bp, "\94G\82ê\82½")) {
#endif
-#if 0 /*JP*/
+#if 0 /*JP:T*/
if (!strncmpi(bp, "wet ", 4))
#else
- if (!strncmpi(bp, "\94G\82ê\82½", 4))
+ if (!STRNCMP2(bp, "\94G\82ê\82½"))
#endif
wetness = rn2(3) + 3;
else
wetness = rnd(2);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "cursed ", l = 7)
|| !strncmpi(bp, "unholy ", l = 7)) {
#else
- } else if (!strncmpi(bp, "\8eô\82í\82ê\82½", l = 8)) {
+ } else if (!STRNCMPEX(bp, "\8eô\82í\82ê\82½")) {
#endif
iscursed = 1;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "uncursed ", l = 9)) {
#else
- } else if (!strncmpi(bp, "\8eô\82í\82ê\82Ä\82¢\82È\82¢", l = 9)) {
+ } else if (!STRNCMPEX(bp, "\8eô\82í\82ê\82Ä\82¢\82È\82¢")) {
#endif
uncursed = 1;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "rustproof ", l = 10)
|| !strncmpi(bp, "erodeproof ", l = 11)
|| !strncmpi(bp, "corrodeproof ", l = 13)
|| !strncmpi(bp, "fireproof ", l = 10)
|| !strncmpi(bp, "rotproof ", l = 9)) {
#else
- } else if (!strncmpi(bp, "\8eK\82Ñ\82È\82¢", l = 8)
- || !strncmpi(bp, "\95\85\90H\82µ\82È\82¢", l = 10)
- || !strncmpi(bp, "\88À\92è\82µ\82½", l = 8)
- || !strncmpi(bp, "\94R\82¦\82È\82¢", l = 8)) {
+ } else if (!STRNCMPEX(bp, "\8eK\82Ñ\82È\82¢")
+ || !STRNCMPEX(bp, "\95\85\90H\82µ\82È\82¢")
+ || !STRNCMPEX(bp, "\88À\92è\82µ\82½")
+ || !STRNCMPEX(bp, "\94R\82¦\82È\82¢")) {
#endif
erodeproof = 1;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "lit ", l = 4)
|| !strncmpi(bp, "burning ", l = 8)) {
+#else
+ } else if (!STRNCMPEX(bp, "\8cõ\82Á\82Ä\82¢\82é")
+ || !STRNCMPEX(bp, "\94R\82¦\82Ä\82¢\82é")) {
+#endif
islit = 1;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "unlit ", l = 6)
|| !strncmpi(bp, "extinguished ", l = 13)) {
+#else
+ } else if (!STRNCMPEX(bp, "\8fÁ\82¦\82Ä\82¢\82é")) {
+#endif
islit = 0;
/* "unlabeled" and "blank" are synonymous */
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "unlabeled ", l = 10)
|| !strncmpi(bp, "unlabelled ", l = 11)
|| !strncmpi(bp, "blank ", l = 6)) {
+#else
+ } else if (!STRNCMPEX(bp, "\83\89\83x\83\8b\82Ì\82È\82¢")
+ || !STRNCMPEX(bp, "\90^\82Á\94\92\82È")) {
+#endif
unlabeled = 1;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "poisoned ", l = 9)) {
+#else
+ } else if (!STRNCMPEX(bp, "\93Å\82Ì\93h\82ç\82ê\82½")) {
+#endif
ispoisoned = 1;
/* "trapped" recognized but not honored outside wizard mode */
} else if (!strncmpi(bp, "trapped ", l = 8)) {
trapped = 1;
} else if (!strncmpi(bp, "untrapped ", l = 10)) {
trapped = 2; /* not trapped */
+ /* locked, unlocked, broken: box/chest lock states */
+#if 0 /*JP:T*/
+ } else if (!strncmpi(bp, "locked ", l = 7)) {
+#else
+ } else if (!STRNCMPEX(bp, "\8c®\82Ì\8a|\82©\82Á\82½")) {
+#endif
+ locked = 1, unlocked = broken = 0;
+#if 0 /*JP:T*/
+ } else if (!strncmpi(bp, "unlocked ", l = 9)) {
+#else
+ } else if (!STRNCMPEX(bp, "\8c®\82Ì\8a|\82©\82Á\82Ä\82¢\82È\82¢")) {
+#endif
+ unlocked = 1, locked = broken = 0;
+#if 0 /*JP:T*/
+ } else if (!strncmpi(bp, "broken ", l = 7)) {
+#else
+ } else if (!STRNCMPEX(bp, "\8c®\82Ì\89ó\82ê\82½")) {
+#endif
+ broken = 1, locked = unlocked = 0;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "greased ", l = 8)) {
+#else
+ } else if (!STRNCMPEX(bp, "\96û\82Ì\93h\82ç\82ê\82½")
+ || !STRNCMPEX(bp, "\8e\89\82Ì\93h\82ç\82ê\82½")) {
+#endif
isgreased = 1;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "very ", l = 5)) {
+#else
+ } else if (!STRNCMPEX(bp, "\82Æ\82Ä\82à")) {
+#endif
/* very rusted very heavy iron ball */
very = 1;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "thoroughly ", l = 11)) {
+#else
+ } else if (!STRNCMPEX(bp, "\82©\82È\82è")) {
+#endif
very = 2;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "rusty ", l = 6)
|| !strncmpi(bp, "rusted ", l = 7)
|| !strncmpi(bp, "burnt ", l = 6)
|| !strncmpi(bp, "burned ", l = 7)) {
+#else
+ } else if (!STRNCMPEX(bp, "\8eK\82Ñ\82½")
+ || !STRNCMPEX(bp, "\94R\82¦\82½")) {
+#endif
eroded = 1 + very;
very = 0;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "corroded ", l = 9)
|| !strncmpi(bp, "rotted ", l = 7)) {
+#else
+ } else if (!STRNCMPEX(bp, "\95\85\90H\82µ\82½")
+ || !STRNCMPEX(bp, "\95\85\82Á\82½")) {
+#endif
eroded2 = 1 + very;
very = 0;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "partly eaten ", l = 13)
|| !strncmpi(bp, "partially eaten ", l = 16)) {
+#else
+ } else if (!STRNCMPEX(bp, "\90H\82×\82©\82¯\82Ì")) {
+#endif
halfeaten = 1;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "historic ", l = 9)) {
+#else
+ } else if (!STRNCMPEX(bp, "\97ð\8ej\93I\82È")) {
+#endif
ishistoric = 1;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "diluted ", l = 8)) {
+#else
+ } else if (!STRNCMPEX(bp, "\94\96\82Ü\82Á\82½")) {
+#endif
isdiluted = 1;
+#if 0 /*JP:T*/
} else if (!strncmpi(bp, "empty ", l = 6)) {
+#else
+ } else if (!STRNCMPEX(bp, "\8bó\82Á\82Û\82Ì")) {
+#endif
contents = EMPTY;
+#if 0 /*JP:T*/
+ } else if (!strncmpi(bp, "small ", l = 6)) { /* glob sizes */
+#else
+ } else if (!STRNCMPEX(bp, "\8f¬\82³\82¢")) { /* glob sizes */
+#endif
+ /* "small" might be part of monster name (mimic, if wishing
+ for its corpse) rather than prefix for glob size; when
+ used for globs, it might be either "small glob of <foo>" or
+ "small <foo> glob" and user might add 's' even though plural
+ doesn't accomplish anything because globs don't stack */
+ if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
+ break;
+ gsize = 1;
+#if 0 /*JP:T*/
+ } else if (!strncmpi(bp, "medium ", l = 7)) {
+#else
+ } else if (!STRNCMPEX(bp, "\92\86\82\82ç\82¢\82Ì")) {
+#endif
+ /* xname() doesn't display "medium" but without this
+ there'd be no way to ask for the intermediate size
+ ("glob" without size prefix yields smallest one) */
+ gsize = 2;
+#if 0 /*JP:T*/
+ } else if (!strncmpi(bp, "large ", l = 6)) {
+#else
+ } else if (!STRNCMPEX(bp, "\91å\82«\82¢")) {
+#endif
+ /* "large" might be part of monster name (dog, cat, koboold,
+ mimic) or object name (box, round shield) rather than
+ prefix for glob size */
+ if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
+ break;
+ /* "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. ? */
+ cnt = 1; /* will be changed to 2 if makesingular() changes string */
if (strlen(bp) > 1 && (p = rindex(bp, '(')) != 0) {
boolean keeptrailingchars = TRUE;
if ((p = strstri(bp, " called ")) != 0) {
*p = 0;
un = p + 8;
+#if 0 /*JP*//*\83^\83C\83v\95Ê\82Í\82Æ\82è\82 \82¦\82¸\82µ\82È\82¢*/
/* "helmet called telepathy" is not "helmet" (a specific type)
* "shield called reflection" is not "shield" (a general type)
*/
oclass = o_ranges[i].oclass;
goto srch;
}
+#endif
}
if ((p = strstri(bp, " labeled ")) != 0) {
*p = 0;
#if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\8f\88\97\9d\82µ\82È\82¢*/
/*
- 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.
- */
+ * 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 (cnt > 1 && !strncmpi(bp, "pairs of ", 9)) {
+ } else if (!strncmpi(bp, "pairs of ", 9)) {
bp += 9;
- cnt *= 2;
+ if (cnt > 1)
+ cnt *= 2;
} else if (!strncmpi(bp, "set of ", 7)) {
bp += 7;
} else if (!strncmpi(bp, "sets of ", 8)) {
}
#endif
-#if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\8f\88\97\9d\82µ\82È\82¢*/
+#if 0 /*JP*/
/* 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
+ i = (int) strlen(bp);
+ p = (char *) 0;
+ /* check for "glob", "<foo> glob", and "glob of <foo>" */
+ if (!strcmpi(bp, "glob") || !BSTRCMPI(bp, bp + i - 5, " glob")
+ || !strcmpi(bp, "globs") || !BSTRCMPI(bp, bp + i - 6, " globs")
+ || (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 */
- }
+ mntmp = name_to_mon(!p ? bp : (strstri(p, " of ") + 4));
+ /* if we didn't recognize monster type, pick a valid one at random */
+ if (mntmp == NON_PM)
+ mntmp = rn1(PM_BLACK_PUDDING - PM_GRAY_OOZE, PM_GRAY_OOZE);
+ /* construct canonical spelling in case name_to_mon() recognized a
+ variant (grey ooze) or player used inverted syntax (<foo> glob);
+ if player has given a valid monster type but not valid glob type,
+ object name lookup won't find it and wish attempt will fail */
+ Sprintf(globbuf, "glob of %s", mons[mntmp].mname);
+ bp = globbuf;
+ mntmp = NON_PM; /* not useful for "glob of <foo>" object lookup */
+ cnt = 0; /* globs don't stack */
+ oclass = FOOD_CLASS;
+ actualn = bp, dn = 0;
+ goto srch;
} else {
/*
* Find corpse type using "of" (figurine of an orc, tin of orc meat)
*/
if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
&& !strstri(bp, "finger ")) {
- if (((p = strstri(bp, "tin of ")) != 0)
- && (tmp = tin_variety_txt(p + 7, &tinv))
- && (mntmp = name_to_mon(p + 7 + tmp)) >= LOW_PM) {
- *(p + 3) = 0;
- tvariety = tinv;
+ 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;
}
}
-#endif
/* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
- if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */
- if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */
- if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */
- if (strncmpi(bp, "master key",
- 10)) /* not the "master" rank */
- if (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)
+ 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;
- }
- }
+ 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;
+ }
+ }
+ }
+#else
+ {
+ /*JP \81u(\89ö\95¨\96¼)\82Ì\89ò\81v\82Í\8cÂ\81X\82ÉID\82ª\82 \82é\82Ì\82Å\95Ê\88µ\82¢ */
+ int l = strlen(bp);
+ int l2 = strlen("\82Ì\89ò");
+ if (l > 4 && strncmp(bp + l - l2, "\82Ì\89ò", l2) == 0) {
+ if ((mntmp = name_to_mon(bp)) >= PM_GRAY_OOZE
+ && mntmp <= PM_BLACK_PUDDING) {
+ mntmp = NON_PM; /* lie to ourselves */
+ cnt = 0; /* force only one */
+ }
+ } else {
+ /*JP:\81u(\89ö\95¨\96¼)\82Ì(\83A\83C\83e\83\80)\81v\91Î\89\9e */
+ if ((mntmp = name_to_mon(bp)) >= LOW_PM) {
+ const char *mp = mons[mntmp].mname;
+ bp = strstri(bp, mp) + strlen(mp) + 2;
+ }
+ }
+ }
+#endif
#if 0 /*JP*//*\92P\90\94\89»\82Í\82µ\82È\82¢*/
/* first change to singular if necessary */
if (*bp) {
char *sng = makesingular(bp);
+
if (strcmp(bp, sng)) {
if (cnt == 1)
cnt = 2;
#if 0 /*JP*//*\83X\83y\83\8b\97h\82ê\8f\88\97\9d\82Í\82µ\82È\82¢*/
/* Alternate spellings (pick-ax, silver sabre, &c) */
{
- struct alt_spellings *as = spellings;
+ const struct alt_spellings *as = spellings;
while (as->sp) {
if (fuzzymatch(bp, as->sp, " -", TRUE)) {
}
#endif
+#if 0 /*JP*/
/* dragon scales - assumes order of dragons */
if (!strcmpi(bp, "scales") && mntmp >= PM_GRAY_DRAGON
&& mntmp <= PM_YELLOW_DRAGON) {
mntmp = NON_PM; /* no monster */
goto typfnd;
}
+#else
+ /*JP: \81u\97Ø\8aZ\81v\82ð\90æ\82É\8f\88\97\9d\82µ\82Ä\82¨\82 */
+ if (!strcmpi(bp, "\97Ø\8aZ") && mntmp >= PM_GRAY_DRAGON
+ && mntmp <= PM_YELLOW_DRAGON) {
+ typ = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
+ mntmp = NON_PM; /* no monster */
+ goto typfnd;
+ }
+
+ if (!strcmpi(bp, "\97Ø") && mntmp >= PM_GRAY_DRAGON
+ && mntmp <= PM_YELLOW_DRAGON) {
+ typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
+ mntmp = NON_PM; /* no monster */
+ goto typfnd;
+ }
+#endif
p = eos(bp);
#if 0 /*JP*/
#else /*JP:\90¹\90\85\82Æ\95s\8fò\82È\90\85\82ð\95Ê\82É\94»\92è*/
if (!BSTRCMPI(bp, p - 4, "\90¹\90\85")) {
typ = POT_WATER;
- blessed = 1;
+ blessed = 1;
goto typfnd;
}
- if (!BSTRCMPI(bp, p - 4, "\95s\8fò\82È\90\85")) {
+ if (!BSTRCMPI(bp, p - 8, "\95s\8fò\82È\90\85")) {
typ = POT_WATER;
- iscursed = 1;
+ iscursed = 1;
goto typfnd;
}
#endif
typ = SPE_BLANK_PAPER;
goto typfnd;
}
+ /* specific food rather than color of gem/potion/spellbook[/scales] */
+ if (!BSTRCMPI(bp, p - 6, "orange") && mntmp == NON_PM) {
+ typ = ORANGE;
+ goto typfnd;
+ }
/*
* NOTE: Gold pieces are handled as objects nowadays, and therefore
* this section should probably be reconsidered as well as the entire
* well in the future. (TH)
*/
#if 0 /*JP*/
- if (!BSTRCMPI(bp, p - 10, "gold piece") || !BSTRCMPI(bp, p - 7, "zorkmid")
+ if (!BSTRCMPI(bp, p - 10, "gold piece")
+ || !BSTRCMPI(bp, p - 7, "zorkmid")
|| !strcmpi(bp, "gold") || !strcmpi(bp, "money")
|| !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
#else
*/
/* 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)
+ 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, "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, "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]);
+
+ /* check for "<class> [ of ] something" */
if (!strncmpi(bp, wrp[i], j)) {
oclass = wrpsym[i];
if (oclass != AMULET_CLASS) {
actualn = bp;
goto srch;
}
+ /* check for "something <class>" */
if (!BSTRCMPI(bp, p - j, wrp[i])) {
oclass = wrpsym[i];
- p -= j;
- *p = 0;
- if (p > bp && p[-1] == ' ')
- p[-1] = 0;
+ /* for "foo amulet", leave the class name so that
+ wishymatch() can do "of inversion" to try matching
+ "amulet of foo"; other classes don't include their
+ class name in their full object names (where
+ "potion of healing" is just "healing", for instance) */
+ if (oclass != AMULET_CLASS) {
+ p -= j;
+ *p = '\0';
+ if (p > bp && p[-1] == ' ')
+ p[-1] = '\0';
+ } else {
+ /* amulet without "of"; convoluted wording but better a
+ special case that's handled than one that's missing */
+ if (!strncmpi(bp, "versus poison ", 14)) {
+ typ = AMULET_VERSUS_POISON;
+ goto typfnd;
+ }
+ }
actualn = dn = bp;
goto srch;
}
}
}
-retry:
+#if 0 /*JP*//* mail/armor\8aÖ\98A\82Å\82Ì\82Ý\8eg\82¤\83\89\83x\83\8b */
+ retry:
+#endif
+#if 0 /*JP*//* \83^\83C\83v\95Ê\82Í\82Æ\82è\82 \82¦\82¸\82µ\82È\82¢ */
/* "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;
}
+#endif
+#if 0 /*JP*//* \90Î\82Ì\93Á\95Ê\8f\88\97\9d\82Í\95s\97v */
if (!BSTRCMPI(bp, p - 6, " stone") || !BSTRCMPI(bp, p - 4, " gem")) {
p[!strcmpi(p - 4, " gem") ? -4 : -6] = '\0';
oclass = GEM_CLASS;
; /* avoid false hit on "* glass" */
} else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
register char *g = bp;
- if (strstri(g, "broken"))
+
+ /* treat "broken glass" as a non-existent item; since "broken" is
+ also a chest/box prefix it might have been stripped off above */
+ if (broken || strstri(g, "broken"))
return (struct obj *) 0;
if (!strncmpi(g, "worthless ", 10))
g += 10;
Strcpy(bp, tbuf);
}
}
+#endif
actualn = bp;
if (!dn)
dn = actualn; /* ex. "skull cap" */
-srch:
+#if 0 /*JP*/
+ srch:
+#endif
/* 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])) && !strcmpi(actualn, zn)) {
+ if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) {
typ = i;
goto typfnd;
}
}
- }
- i = oclass ? bases[(int) oclass] : 1;
- while (i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)) {
- register const char *zn;
-
- if (actualn && (zn = OBJ_NAME(objects[i])) != 0
- && wishymatch(actualn, zn, TRUE)) {
- typ = i;
- goto typfnd;
- }
-#if 0 /*JP*/
- if (dn && (zn = OBJ_DESCR(objects[i])) != 0
- && wishymatch(dn, zn, FALSE)) {
-#else /*JP
- * \81u\83C\83F\83\93\83_\81[\82Ì\96\82\8f\9c\82¯\81v\82ð\8aè\82Á\82½\82Æ\82«\82É\82±\82±\82Å\82Í\8bU\95¨\82É
- * \82È\82ç\82È\82¢\82æ\82¤\82É\82·\82é\81B
- * \94ñ\83E\83B\83U\81[\83h\83\82\81[\83h\82Å\82Ì\93ü\82ê\91Ö\82¦\8f\88\97\9d\82Í\8cã\82É\82 \82é\81B
- */
- if (i != FAKE_AMULET_OF_YENDOR &&
- dn && (zn = OBJ_DESCR(objects[i])) != 0
- && wishymatch(dn, zn, FALSE)) {
-#endif
- /* don't match extra descriptions (w/o real name) */
- if (!OBJ_NAME(objects[i]))
- return (struct obj *) 0;
- typ = i;
- goto typfnd;
- }
- if (un && (zn = objects[i].oc_uname) != 0
- && wishymatch(un, zn, FALSE)) {
- typ = i;
+#if 0 /*JP*//* \93ú\96{\8cê\82Í"tin"\82ð\96ó\82µ\95ª\82¯\82Ä\82¢\82é\82Ì\82Å\95s\97v */
+ /* "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;
}
- i++;
+#endif
}
+
+ if (((typ = rnd_otyp_by_namedesc(actualn, oclass, 1)) != STRANGE_OBJECT)
+ || ((typ = rnd_otyp_by_namedesc(dn, oclass, 1)) != STRANGE_OBJECT)
+ || ((typ = rnd_otyp_by_namedesc(un, oclass, 1)) != STRANGE_OBJECT)
+ || ((typ = rnd_otyp_by_namedesc(origbp, oclass, 1)) != STRANGE_OBJECT))
+ goto typfnd;
+ typ = 0;
+
if (actualn) {
struct Jitem *j = Japanese_items;
j++;
}
}
+#if 0 /*JP*//* mail/armor\82Ì\95\\8bL\97h\82ê\83`\83F\83b\83N\82Í\95s\97v */
/* 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" */
Strcat(bp, " mail");
goto retry;
}
+#endif
#if 0 /*JP*/
if (!strcmpi(bp, "spinach")) {
#else
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:
+
+ /*
+ * 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;
+ boolean madeterrain = FALSE;
int trap, x = u.ux, y = u.uy;
for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
if (strncmpi(tname, bp, strlen(tname)))
continue;
/* found it; avoid stupid mistakes */
- if ((trap == TRAPDOOR || trap == HOLE) && !Can_fall_thru(&u.uz))
+ if (is_hole(trap) && !Can_fall_thru(&u.uz))
trap = ROCKTRAP;
if ((t = maketrap(x, y, trap)) != 0) {
trap = t->ttyp;
(trap != MAGIC_PORTAL) ? "" : " to nowhere");
} else
pline("Creation of %s failed.", an(tname));
- return &zeroobj;
+ return (struct obj *) &zeroobj;
}
- /* furniture and terrain */
+ /* furniture and terrain (use at your own risk; can clobber stairs
+ or place furniture on existing traps which shouldn't be allowed) */
lev = &levl[x][y];
p = eos(bp);
if (!BSTRCMPI(bp, p - 8, "fountain")) {
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")) {
+ madeterrain = TRUE;
+ } else if (!BSTRCMPI(bp, p - 6, "throne")) {
lev->typ = THRONE;
pline("A throne.");
- newsym(x, y);
- return &zeroobj;
- }
- if (!BSTRCMPI(bp, p - 4, "sink")) {
+ madeterrain = TRUE;
+ } else if (!BSTRCMPI(bp, p - 4, "sink")) {
lev->typ = SINK;
level.flags.nsinks++;
pline("A sink.");
- newsym(x, y);
- return &zeroobj;
- }
+ madeterrain = TRUE;
+
/* ("water" matches "potion of water" rather than terrain) */
- if (!BSTRCMPI(bp, p - 4, "pool") || !BSTRCMPI(bp, p - 4, "moat")) {
+ } else 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" */
+ madeterrain = TRUE;
+
+ /* also matches "molten lava" */
+ } else if (!BSTRCMPI(bp, p - 4, "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")) {
+ pooleffects(FALSE);
+ madeterrain = TRUE;
+ } else if (!BSTRCMPI(bp, p - 5, "altar")) {
aligntyp al;
lev->typ = ALTAR;
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;
+ 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")) {
+ madeterrain = TRUE;
+ } else 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")) {
+ madeterrain = TRUE;
+ } else 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")) {
+ madeterrain = TRUE;
+ } else if (!BSTRCMPI(bp, p - 4, "bars")) {
lev->typ = IRONBARS;
pline("Iron bars.");
- newsym(x, y);
- return &zeroobj;
+ madeterrain = TRUE;
}
- }
+ if (madeterrain) {
+ feel_newsym(x, y); /* map the spot where the wish occurred */
+ /* hero started at <x,y> but might not be there anymore (create
+ lava, decline to die, and get teleported away to safety) */
+ if (u.uinwater && !is_pool(u.ux, u.uy)) {
+ u.uinwater = 0; /* leave the water */
+ docrt();
+ vision_full_recalc = 1;
+ } else if (u.utrap && u.utraptype == TT_LAVA
+ && !is_lava(u.ux, u.uy)) {
+ reset_utrap(FALSE);
+ }
+ /* cast 'const' away; caller won't modify this */
+ return (struct obj *) &zeroobj;
+ }
+ } /* end of wizard mode traps and terrain */
+
+#if 0 /*JP*//* \83^\83C\83v\95Ê\82Í\82Æ\82è\82 \82¦\82¸\82µ\82È\82¢ */
if (!oclass && !typ) {
if (!strncmpi(bp, "polearm", 7)) {
typ = rnd_otyp_by_wpnskill(P_POLEARMS);
goto typfnd;
}
}
+#endif
if (!oclass)
return ((struct obj *) 0);
-any:
+ any:
if (!oclass)
- oclass = wrpsym[rn2((int) sizeof(wrpsym))];
-typfnd:
+ oclass = wrpsym[rn2((int) sizeof wrpsym)];
+ typfnd:
if (typ)
oclass = objects[typ].oc_class;
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
otmp->spe = (rn2(10) ? -1 : 0);
break;
}
- /* fall through, if wizard */
+ /*FALLTHRU*/
default:
otmp->spe = spe;
}
otmp->spe = 0; /* No spinach */
if (dead_species(mntmp, FALSE)) {
otmp->corpsenm = NON_PM; /* it's empty */
- } else if (!(mons[mntmp].geno & G_UNIQ)
+ } 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)
+ 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
)
otmp->corpsenm = mntmp;
break;
- case EGG:
- mntmp = can_be_hatched(mntmp);
- /* this also sets hatch timer if appropriate */
- set_corpsenm(otmp, mntmp);
- break;
case STATUE:
otmp->corpsenm = mntmp;
if (Has_contents(otmp) && verysmall(&mons[mntmp]))
curse(otmp);
}
- /* set eroded */
- if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) {
+ /* 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;
-
- /* set erodeproof */
- if (erodeproof && !eroded && !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);
}
if (Is_box(otmp) || typ == TIN)
otmp->otrapped = (trapped == 1);
}
+ /* empty for containers rather than for tins */
+ if (contents == EMPTY) {
+ if (otmp->otyp == BAG_OF_TRICKS || otmp->otyp == HORN_OF_PLENTY) {
+ if (otmp->spe > 0)
+ otmp->spe = 0;
+ } else if (Has_contents(otmp)) {
+ /* this assumes that artifacts can't be randomly generated
+ inside containers */
+ delete_contents(otmp);
+ otmp->owt = weight(otmp);
+ }
+ }
+ /* set locked/unlocked/broken */
+ if (Is_box(otmp)) {
+ if (locked) {
+ otmp->olocked = 1, otmp->obroken = 0;
+ } else if (unlocked) {
+ otmp->olocked = 0, otmp->obroken = 0;
+ } else if (broken) {
+ otmp->olocked = 0, otmp->obroken = 1;
+ }
+ }
if (isgreased)
otmp->greased = 1;
if (aname && objtyp == otmp->otyp)
name = aname;
- /* 3.6.0 tribute - fix up novel */
+ /* 3.6 tribute - fix up novel */
if (otmp->otyp == SPE_NOVEL) {
const char *novelname;
}
otmp = oname(otmp, name);
- if (otmp->oartifact) {
+ /* name==aname => wished for artifact (otmp->oartifact => got it) */
+ if (otmp->oartifact || name == aname) {
otmp->quan = 1L;
u.uconduct.wisharti++; /* KMH, conduct */
}
|| (otmp->oartifact && rn2(nartifact_exist()) > 1)) && !wizard) {
artifact_exists(otmp, safe_oname(otmp), FALSE);
obfree(otmp, (struct obj *) 0);
- otmp = &zeroobj;
+ otmp = (struct obj *) &zeroobj;
/*JP
pline("For a moment, you feel %s in your %s, but it disappears!",
*/
pline("\88ê\8fu%s\82ª%s\82Ì\92\86\82É\82 \82é\82æ\82¤\82È\8a´\82¶\82ª\82µ\82½\82ª\81C\82·\82®\82É\8fÁ\82¦\82³\82Á\82½\81I",
something, makeplural(body_part(HAND)));
+ return otmp;
}
if (halfeaten && otmp->oclass == FOOD_CLASS) {
}
otmp->owt = weight(otmp);
if (very && otmp->otyp == HEAVY_IRON_BALL)
- otmp->owt += 160;
+ 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;
}
{
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 */
+ if (suit) {
+ if (Is_dragon_mail(suit))
+#if 0 /*JP:T*/
+ return "dragon mail"; /* <color> dragon scale mail */
+#else
+ return "\97Ø\8aZ"; /* <color> dragon scale mail */
+#endif
+ else if (Is_dragon_scales(suit))
+/*JP
+ return "dragon scales";
+*/
+ return "\97Ø";
+ suitnm = OBJ_NAME(objects[suit->otyp]);
+ esuitp = eos((char *) suitnm);
+#if 0 /*JP:T*/
+ if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
+ return "mail"; /* most suits fall into this category */
+#else
+ if (strlen(suitnm) > 2 && !strcmp(esuitp - 2, "\8aZ"))
+ return "\8aZ"; /* most suits fall into this category */
+#endif
+#if 0 /*JP*/
+ else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
+ return "jacket"; /* leather jacket */
+#endif
+ }
+ /* "suit" is lame but "armor" is ambiguous and "body armor" is absurd */
+/*JP
return "suit";
+*/
+ return "\95\9e";
}
const char *
return (helmet && !is_metallic(helmet)) ? "\96X\8eq" : "\8a\95";
}
+/* gloves vs gauntlets; depends upon discovery state */
+const char *
+gloves_simple_name(gloves)
+struct obj *gloves;
+{
+/*JP
+ static const char gauntlets[] = "gauntlets";
+*/
+ static const char gauntlets[] = "\8f¬\8eè";
+
+ if (gloves && gloves->dknown) {
+ int otyp = gloves->otyp;
+ struct objclass *ocl = &objects[otyp];
+ const char *actualn = OBJ_NAME(*ocl),
+ *descrpn = OBJ_DESCR(*ocl);
+
+ if (strstri(objects[otyp].oc_name_known ? actualn : descrpn,
+ gauntlets))
+ return gauntlets;
+ }
+/*JP
+ return "gloves";
+*/
+ return "\8eè\91Ü";
+}
+
const char *
mimic_obj_name(mtmp)
struct monst *mtmp;
{
- if (mtmp->m_ap_type == M_AP_OBJECT
- && mtmp->mappearance != STRANGE_OBJECT) {
- int idx = objects[mtmp->mappearance].oc_descr_idx;
+ if (M_AP_TYPE(mtmp) == M_AP_OBJECT) {
if (mtmp->mappearance == GOLD_PIECE)
/*JP
return "gold";
*/
return "\8bà\89Ý";
- return obj_descr[idx].oc_name;
+ if (mtmp->mappearance != STRANGE_OBJECT)
+ return simple_typename(mtmp->mappearance);
}
/*JP
return "whatcha-may-callit";
return qbuf;
}
+STATIC_OVL char *
+globwt(otmp, buf, weightformatted_p)
+struct obj *otmp;
+char *buf;
+boolean *weightformatted_p;
+{
+ *buf = '\0';
+ if (otmp->globby) {
+ Sprintf(buf, "%u aum, ", otmp->owt);
+ *weightformatted_p = TRUE;
+ } else {
+ *weightformatted_p = FALSE;
+ }
+ return buf;
+}
+
/*objnam.c*/