1 /* NetHack 3.6 objnam.c $NHDT-Date: 1521507553 2018/03/20 00:59:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.199 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2011. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2018 */
9 /* JNetHack may be freely redistributed. See license for details. */
13 /* "an uncursed greased partly eaten guardian naga hatchling [corpse]" */
15 #define PREFIX 80 /* (56) */
17 /*
\81u
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\96û
\82Ì
\93h
\82ç
\82ê
\82½
\90H
\82×
\82©
\82¯
\82Ì
\83N
\83\8d\83}
\83e
\83B
\83b
\83N
\81E
\83h
\83\89\83S
\83\93(
\82Ì
\8e\80\91Ì)
\81v*/
23 STATIC_DCL char *FDECL(strprepend, (char *, const char *));
24 STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
25 STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (char *, CHAR_P));
26 STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
27 STATIC_DCL char *NDECL(nextobuf);
28 STATIC_DCL void FDECL(releaseobuf, (char *));
29 STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
30 STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
31 STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned));
32 STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
33 const char *const *));
34 STATIC_DCL char *FDECL(singplur_compound, (char *));
35 STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
36 STATIC_DCL boolean FDECL(badman, (const char *, BOOLEAN_P));
38 static char *FDECL(substitute, (char *, char *, char *));
39 static char *FDECL(transpose, (char *buf,char *));
40 static char *FDECL(delete, (char *, char *str));
41 static int FDECL(digit_8, (int));
42 static int FDECL(atoi_8, (const char *));
50 #define BSTRCMPI(base, ptr, str) ((ptr) < base || strcmpi((ptr), str))
51 #define BSTRNCMPI(base, ptr, str, num) \
52 ((ptr) < base || strncmpi((ptr), str, num))
53 #define Strcasecpy(dst, src) (void) strcasecpy(dst, src)
55 /* true for gems/rocks that should have " stone" appended to their names */
56 #define GemStone(typ) \
58 || (objects[typ].oc_material == GEMSTONE \
59 && (typ != DILITHIUM_CRYSTAL && typ != RUBY && typ != DIAMOND \
60 && typ != SAPPHIRE && typ != BLACK_OPAL && typ != EMERALD \
64 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "wakizashi" },
65 { BROADSWORD, "ninja-to" },
66 { FLAIL, "nunchaku" },
67 { GLAIVE, "naginata" },
68 { LOCK_PICK, "osaku" },
69 { WOODEN_HARP, "koto" },
71 { PLATE_MAIL, "tanko" },
73 { LEATHER_GLOVES, "yugake" },
74 { FOOD_RATION, "gunyoki" },
75 { POT_BOOZE, "sake" },
78 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "
\98e
\8d·
\82µ" },
79 { BROADSWORD, "
\94E
\8eÒ
\93\81" },
80 { FLAIL, "
\83k
\83\93\83`
\83\83\83N" },
81 { GLAIVE, "
\82È
\82¬
\82È
\82½" },
82 { LOCK_PICK, "
\82¨
\82³
\82" },
83 { WOODEN_HARP, "
\8bÕ" },
84 { KNIFE, "
\8eh
\93\81" },
85 { PLATE_MAIL, "
\92Z
\8db" },
87 { LEATHER_GLOVES, "
\8b|
\8c\9c" },
88 { FOOD_RATION, "
\8aÛ
\96ò" },
89 { POT_BOOZE, "
\8eð" },
93 STATIC_DCL const char *FDECL(Japanese_item_name, (int i));
98 register const char *pref;
100 register int i = (int) strlen(pref);
103 impossible("PREFIX too short (for %d).", i);
107 (void) strncpy(s, pref, i); /* do not copy trailing 0 */
111 /* manage a pool of BUFSZ buffers, so callers don't have to */
112 static char NEARDATA obufs[NUMOBUF][BUFSZ];
113 static int obufidx = 0;
118 obufidx = (obufidx + 1) % NUMOBUF;
119 return obufs[obufidx];
122 /* put the most recently allocated buffer back if possible */
127 /* caller may not know whether bufp is the most recently allocated
128 buffer; if it isn't, do nothing; note that because of the somewhat
129 obscure PREFIX handling for object name formatting by xname(),
130 the pointer our caller has and is passing to us might be into the
131 middle of an obuf rather than the address returned by nextobuf() */
132 if (bufp >= obufs[obufidx]
133 && bufp < obufs[obufidx] + sizeof obufs[obufidx]) /* obufs[][BUFSZ] */
134 obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
141 char *buf = nextobuf();
142 struct objclass *ocl = &objects[otyp];
143 const char *actualn = OBJ_NAME(*ocl);
144 const char *dn = OBJ_DESCR(*ocl);
145 const char *un = ocl->oc_uname;
146 int nn = ocl->oc_name_known;
148 if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
149 actualn = Japanese_item_name(otyp);
152 Sprintf(buf, "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é", un);
154 switch (ocl->oc_class) {
159 Strcat(buf, "
\8bà
\89Ý");
163 Strcpy(buf, "potion");
169 Strcpy(buf, "scroll");
171 Strcat(buf, "
\8aª
\95¨");
180 if (otyp != SPE_NOVEL) {
182 Strcpy(buf, "spellbook");
184 Strcat(buf, "
\96\82\96@
\8f\91");
187 Strcpy(buf, !nn ? "book" : "novel");
189 Strcpy(buf, !nn ? "
\96{" : "
\8f¬
\90à");
197 Strcat(buf, "
\8ew
\97Ö");
202 Strcpy(buf, actualn);
204 Strcpy(buf, "amulet");
206 Sprintf(eos(buf), " called %s", un);
208 Sprintf(eos(buf), " (%s)", dn);
212 Strcat(buf, actualn);
214 Strcat(buf, "
\96\82\8f\9c\82¯");
220 Strcat(buf, actualn);
222 Strcat(buf, "
\95ó
\90Î");
228 Strcpy(buf, actualn);
230 Strcat(buf, " stone");
232 Sprintf(eos(buf), " called %s", un);
234 Sprintf(eos(buf), " (%s)", dn);
236 Strcat(buf, actualn);
240 Strcpy(buf, dn ? dn : actualn);
241 if (ocl->oc_class == GEM_CLASS)
243 (ocl->oc_material == MINERAL) ? " stone" : " gem");
245 Sprintf(eos(buf), " called %s", un);
247 Strcat(buf, dn ? dn : actualn);
256 /* here for ring/scroll/potion/wand */
260 Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
262 Sprintf(eos(buf), " of %s", actualn);
264 Strcpy(buf, actualn);
269 Sprintf(eos(buf), " called %s", un);
273 Sprintf(eos(buf), " (%s)", dn);
275 Sprintf(eos(buf), "(%s)", dn);
280 /* less verbose result than obj_typename(); either the actual name
281 or the description (but not both); user-assigned name is ignored */
283 simple_typename(otyp)
286 char *bufp, *pp, *save_uname = objects[otyp].oc_uname;
288 objects[otyp].oc_uname = 0; /* suppress any name given by user */
289 bufp = obj_typename(otyp);
290 objects[otyp].oc_uname = save_uname;
291 if ((pp = strstri(bufp, " (")) != 0)
292 *pp = '\0'; /* strip the appended description */
300 if (!obj->oartifact || !has_oname(obj))
302 if (!program_state.gameover && !iflags.override_ID) {
303 if (not_fully_identified(obj))
309 /* used by distant_name() to pass extra information to xname_flags();
310 it would be much cleaner if this were a parameter, but that would
311 require all of the xname() and doname() calls to be modified */
312 static int distantname = 0;
314 /* Give the name of an object seen at a distance. Unlike xname/doname,
315 * we don't want to set dknown if it's not set already.
318 distant_name(obj, func)
320 char *FDECL((*func), (OBJ_P));
324 /* 3.6.1: this used to save Blind, set it, make the call, then restore
325 * the saved value; but the Eyes of the Overworld override blindness
326 * and let characters wearing them get dknown set for distant items.
328 * TODO? if the hero is wearing those Eyes, figure out whether the
329 * object is within X-ray radius and only treat it as distant when
330 * beyond that radius. Logic is iffy but result might be interesting.
338 /* convert player specified fruit name into corresponding fruit juice name
339 ("slice of pizza" -> "pizza juice" rather than "slice of pizza juice") */
342 boolean juice; /* whether or not to append " juice" to the name */
344 #if 1 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\82»
\82±
\82Ü
\82Å
\82µ
\82È
\82¢*/
345 char *buf = nextobuf();
346 Sprintf(buf, "%s%s", pl_fruit, juice ? "
\83W
\83\85\81[
\83X" : "");
349 char *buf = nextobuf();
350 const char *fruit_nam = strstri(pl_fruit, " of ");
353 fruit_nam += 4; /* skip past " of " */
355 fruit_nam = pl_fruit; /* use it as is */
357 Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
362 /* look up a named fruit by index (1..127) */
364 fruit_from_indx(indx)
369 for (f = ffruit; f; f = f->nextf)
375 /* look up a named fruit by name */
377 fruit_from_name(fname, exact, highest_fid)
379 boolean exact; /* False => prefix or exact match, True = exact match only */
380 int *highest_fid; /* optional output; only valid if 'fname' isn't found */
382 struct fruit *f, *tentativef;
386 * note: named fruits are case-senstive...
391 /* first try for an exact match */
392 for (f = ffruit; f; f = f->nextf)
393 if (!strcmp(f->fname, fname))
395 else if (highest_fid && f->fid > *highest_fid)
396 *highest_fid = f->fid;
398 /* didn't match as-is; if caller is willing to accept a prefix
399 match, try to find one; we want to find the longest prefix that
400 matches, not the first */
403 for (f = ffruit; f; f = f->nextf) {
404 k = strlen(f->fname);
405 if (!strncmp(f->fname, fname, k)
406 && (!fname[k] || fname[k] == ' ')
407 && (!tentativef || k > strlen(tentativef->fname)))
412 /* if we still don't have a match, try singularizing the target;
413 for exact match, that's trivial, but for prefix, it's hard */
415 altfname = makesingular(fname);
416 for (f = ffruit; f; f = f->nextf) {
417 if (!strcmp(f->fname, altfname))
420 releaseobuf(altfname);
423 char fnamebuf[BUFSZ], *p;
424 unsigned fname_k = strlen(fname); /* length of assumed plural fname */
427 for (f = ffruit; f; f = f->nextf) {
428 k = strlen(f->fname);
429 /* reload fnamebuf[] each iteration in case it gets modified;
430 there's no need to recalculate fname_k */
431 Strcpy(fnamebuf, fname);
432 /* bug? if singular of fname is longer than plural,
433 failing the 'fname_k > k' test could skip a viable
434 candidate; unfortunately, we can't singularize until
435 after stripping off trailing stuff and we can't get
436 accurate fname_k until fname has been singularized;
437 compromise and use 'fname_k >= k' instead of '>',
438 accepting 1 char length discrepancy without risking
439 false match (I hope...) */
440 if (fname_k >= k && (p = index(&fnamebuf[k], ' ')) != 0) {
441 *p = '\0'; /* truncate at 1st space past length of f->fname */
442 altfname = makesingular(fnamebuf);
443 k = strlen(altfname); /* actually revised 'fname_k' */
444 if (!strcmp(f->fname, altfname)
445 && (!tentativef || k > strlen(tentativef->fname)))
447 releaseobuf(altfname); /* avoid churning through all obufs */
455 /* sort the named-fruit linked list by fruit index number */
457 reorder_fruit(forward)
460 struct fruit *f, *allfr[1 + 127];
461 int i, j, k = SIZE(allfr);
463 for (i = 0; i < k; ++i)
464 allfr[i] = (struct fruit *) 0;
465 for (f = ffruit; f; f = f->nextf) {
466 /* without sanity checking, this would reduce to 'allfr[f->fid]=f' */
468 if (j < 1 || j >= k) {
469 impossible("reorder_fruit: fruit index (%d) out of range", j);
470 return; /* don't sort after all; should never happen... */
471 } else if (allfr[j]) {
472 impossible("reorder_fruit: duplicate fruit index (%d)", j);
477 ffruit = 0; /* reset linked list; we're rebuilding it from scratch */
478 /* slot [0] will always be empty; must start 'i' at 1 to avoid
479 [k - i] being out of bounds during first iteration */
480 for (i = 1; i < k; ++i) {
481 /* for forward ordering, go through indices from high to low;
482 for backward ordering, go from low to high */
483 j = forward ? (k - i) : i;
485 allfr[j]->nextf = ffruit;
495 return xname_flags(obj, CXN_NORMAL);
499 xname_flags(obj, cxn_flags)
500 register struct obj *obj;
501 unsigned cxn_flags; /* bitmask of CXN_xxx values */
504 register int typ = obj->otyp;
505 register struct objclass *ocl = &objects[typ];
506 int nn = ocl->oc_name_known, omndx = obj->corpsenm;
507 const char *actualn = OBJ_NAME(*ocl);
508 const char *dn = OBJ_DESCR(*ocl) ? OBJ_DESCR(*ocl) : actualn;
509 const char *un = ocl->oc_uname;
510 boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
511 boolean known, dknown, bknown;
513 buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
514 if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
515 actualn = Japanese_item_name(typ);
519 * clean up known when it's tied to oc_name_known, eg after AD_DRIN
520 * This is only required for unique objects since the article
521 * printed for the object is tied to the combination of the two
522 * and printing the wrong article gives away information.
524 if (!nn && ocl->oc_uses_known && ocl->oc_unique)
526 if (!Blind && !distantname)
528 if (Role_if(PM_PRIEST))
531 if (iflags.override_ID) {
532 known = dknown = bknown = TRUE;
536 dknown = obj->dknown;
537 bknown = obj->bknown;
540 if (obj_is_pname(obj))
545 Strcat(buf, ONAME(obj));
550 if (has_oname(obj) && dknown) {
551 Strcat(buf, ONAME(obj));
552 Strcat(buf, "
\82Æ
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½");
555 switch (obj->oclass) {
559 Strcpy(buf, "amulet");
561 Strcat(buf, "
\96\82\8f\9c\82¯");
562 else if (typ == AMULET_OF_YENDOR || typ == FAKE_AMULET_OF_YENDOR)
563 /* each must be identified individually */
564 Strcpy(buf, known ? actualn : dn);
566 Strcpy(buf, actualn);
569 Sprintf(buf, "amulet called %s", un);
571 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96\82\8f\9c\82¯", un);
574 Sprintf(buf, "%s amulet", dn);
576 Sprintf(eos(buf), "%s", dn);
579 if (is_poisonable(obj) && obj->opoisoned)
581 Strcpy(buf, "poisoned ");
583 Strcpy(buf, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
589 Sprintf(eos(buf), "%s
\82Ì", mons[obj->corpsenm].mname);
593 Strcpy(buf, "pair of ");
595 Strcpy(buf, "
\88ê
\91Î
\82Ì");
596 else if (is_wet_towel(obj))
598 Strcpy(buf, (obj->spe < 3) ? "moist " : "wet ");
600 Strcpy(buf, (obj->spe < 3) ? "
\8e¼
\82Á
\82½" : "
\94G
\82ê
\82½");
605 Strcat(buf, actualn);
609 Strcat(buf, " called ");
613 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é");
618 #if 0 /*JP*/ /*
\82±
\82ê
\82Í
\8cê
\8f\87\82Ì
\8aÖ
\8cW
\82©
\82ç
\8fã
\82Ì
\95û
\82Å
\92è
\8b`*/
619 /* If we use an() here we'd have to remember never to use */
620 /* it whenever calling doname() or xname(). */
621 if (typ == FIGURINE && omndx != NON_PM) {
622 Sprintf(eos(buf), " of a%s %s",
623 index(vowels, *mons[omndx].mname) ? "n" : "",
625 } else if (is_wet_towel(obj)) {
627 if (is_wet_towel(obj)) {
630 Sprintf(eos(buf), " (%d)", obj->spe);
634 /* depends on order of the dragon scales objects */
635 if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
637 Sprintf(buf, "set of %s", actualn);
639 Sprintf(buf, "%s
\88ê
\8e®", actualn);
642 if (is_boots(obj) || is_gloves(obj))
644 Strcpy(buf, "pair of ");
646 Strcat(buf,"
\88ê
\91Î
\82Ì");
648 if (obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
651 Strcpy(buf, "shield");
653 Strcat(buf, "
\8f\82");
656 if (obj->otyp == SHIELD_OF_REFLECTION && !dknown) {
658 Strcpy(buf, "smooth shield");
660 Strcat(buf, "
\82·
\82×
\82·
\82×
\82µ
\82½
\8f\82");
665 Strcat(buf, actualn);
669 Strcat(buf, "boots");
670 else if (is_gloves(obj))
671 Strcat(buf, "gloves");
672 else if (is_cloak(obj))
673 Strcpy(buf, "cloak");
674 else if (is_helmet(obj))
675 Strcpy(buf, "helmet");
676 else if (is_shield(obj))
677 Strcpy(buf, "shield");
679 Strcpy(buf, "armor");
680 Strcat(buf, " called ");
686 else if (is_gloves(obj))
688 else if (is_cloak(obj))
689 p = "
\83N
\83\8d\81[
\83N";
690 else if (is_helmet(obj))
692 else if (is_shield(obj))
696 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", un, p);
702 if (typ == SLIME_MOLD) {
703 struct fruit *f = fruit_from_indx(obj->spe);
706 impossible("Bad fruit #%d?", obj->spe);
707 Strcpy(buf, "fruit");
709 Strcpy(buf, f->fname);
711 /* ick; already pluralized fruit names
712 are allowed--we want to try to avoid
713 adding a redundant plural suffix */
714 Strcpy(buf, makeplural(makesingular(buf)));
731 ? "
\82Æ
\82Ä
\82à
\91å
\82«
\82¢"
743 Strcpy(buf, actualn);
744 if (typ == TIN && known)
745 tin_details(obj, omndx, buf);
747 if (typ == TIN && known)
748 /*JP
\81u
\81`
\82Ì
\93÷
\82Ì
\81v*/
749 tin_details(obj, omndx, buf);
750 Strcat(buf, actualn);
756 Strcpy(buf, actualn);
758 Strcat(buf, actualn);
762 if (typ == STATUE && omndx != NON_PM)
764 Sprintf(buf, "%s%s of %s%s",
765 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
769 type_is_pname(&mons[omndx])
771 : the_unique_pm(&mons[omndx])
773 : index(vowels, *mons[omndx].mname)
778 Sprintf(eos(buf), "%s%s
\82Ì%s",
779 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
782 mons[obj->corpsenm].mname, actualn);
786 Strcpy(buf, actualn);
788 Strcat(buf, actualn);
793 Sprintf(buf, "%sheavy iron ball",
794 (obj->owt > ocl->oc_weight) ? "very " : "");
796 Sprintf(eos(buf), "%s
\8fd
\82¢
\93S
\8b\85",
797 (obj->owt > ocl->oc_weight) ? "
\82Æ
\82Ä
\82à" : "");
801 if (dknown && obj->odiluted)
803 Strcpy(buf, "diluted ");
805 Strcat(buf, "
\94\96\82Ü
\82Á
\82½");
806 if (nn || un || !dknown) {
808 Strcat(buf, "potion");
821 if (typ == POT_WATER && bknown
822 && (obj->blessed || obj->cursed)) {
824 Strcat(buf, obj->blessed ? "holy " : "unholy ");
826 Strcat(buf, obj->blessed ? "
\90¹" : "
\95s
\8fò
\82È");
828 Strcat(buf, actualn);
831 Strcat(buf, " called ");
835 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96ò");
840 #if 0 /*JP*//*
\95s
\8am
\92è
\96¼
\82É
\81u
\96ò
\81v
\82Í
\95t
\82¢
\82Ä
\82¢
\82é*/
841 Strcat(buf, " potion");
847 Strcpy(buf, "scroll");
852 Strcat(buf,"
\8aª
\95¨");
860 Strcat(buf, actualn);
863 Strcat(buf, " called ");
867 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8aª
\95¨");
869 } else if (ocl->oc_magic) {
871 Strcat(buf, " labeled ");
877 Strcat(buf, " scroll");
891 Sprintf(buf, "wand of %s", actualn);
893 Strcat(buf, actualn);
896 Sprintf(buf, "wand called %s", un);
898 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8fñ", un);
901 Sprintf(buf, "%s wand", dn);
906 if (typ == SPE_NOVEL) { /* 3.6 tribute */
913 Strcpy(buf, actualn);
916 Sprintf(buf, "novel called %s", un);
918 Sprintf(buf, "%s
\82Æ
\82¢
\82¤
\8f¬
\90à", un);
921 Sprintf(buf, "%s book", dn);
923 Sprintf(buf, "%s
\96{", dn);
926 } else if (!dknown) {
928 Strcpy(buf, "spellbook");
930 Strcat(buf, "
\96\82\96@
\8f\91");
933 if (typ != SPE_BOOK_OF_THE_DEAD)
934 Strcpy(buf, "spellbook of ");
936 Strcat(buf, actualn);
939 Sprintf(buf, "spellbook called %s", un);
941 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96\82\96@
\8f\91", un);
944 Sprintf(buf, "%s spellbook", dn);
946 Sprintf(eos(buf), "%s", dn);
953 Strcat(buf, "
\8ew
\97Ö");
956 Sprintf(buf, "ring of %s", actualn);
958 Strcat(buf, actualn);
961 Sprintf(buf, "ring called %s", un);
963 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8ew
\97Ö", un);
966 Sprintf(buf, "%s ring", dn);
972 const char *rock = (ocl->oc_material == MINERAL) ? "stone" : "gem";
974 const char *rock = (ocl->oc_material == MINERAL) ? "
\90Î" : "
\95ó
\90Î";
985 Sprintf(buf, "%s called %s", rock, un);
987 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", un, rock);
990 Sprintf(buf, "%s %s", dn, rock);
994 Strcpy(buf, actualn);
997 Strcat(buf, " stone");
1003 Sprintf(buf, "glorkum %d %d %d", obj->oclass, typ, obj->spe);
1007 Strcpy(buf, makeplural(buf));
1010 if (obj->otyp == T_SHIRT && program_state.gameover) {
1014 Sprintf(eos(buf), " with text \"%s\"", tshirt_text(obj, tmpbuf));
1016 Sprintf(eos(buf), "(
\81u%s
\81v
\82Æ
\8f\91\82¢
\82Ä
\82 \82é)", tshirt_text(obj, tmpbuf));
1020 if (has_oname(obj) && dknown) {
1021 Strcat(buf, " named ");
1023 Strcat(buf, ONAME(obj));
1026 if (!strncmpi(buf, "the ", 4))
1034 /* similar to simple_typename but minimal_xname operates on a particular
1035 object rather than its general type; it formats the most basic info:
1036 potion -- if description not known
1037 brown potion -- if oc_name_known not set
1038 potion of object detection -- if discovered
1046 struct objclass saveobcls;
1047 int otyp = obj->otyp;
1049 /* suppress user-supplied name */
1050 saveobcls.oc_uname = objects[otyp].oc_uname;
1051 objects[otyp].oc_uname = 0;
1052 /* suppress actual name if object's description is unknown */
1053 saveobcls.oc_name_known = objects[otyp].oc_name_known;
1055 objects[otyp].oc_name_known = 0;
1057 /* caveat: this makes a lot of assumptions about which fields
1058 are required in order for xname() to yield a sensible result */
1060 bareobj.otyp = otyp;
1061 bareobj.oclass = obj->oclass;
1062 bareobj.dknown = obj->dknown;
1063 /* suppress known except for amulets (needed for fakes and real A-of-Y) */
1064 bareobj.known = (obj->oclass == AMULET_CLASS)
1066 /* default is "on" for types which don't use it */
1067 : !objects[otyp].oc_uses_known;
1068 bareobj.quan = 1L; /* don't want plural */
1069 bareobj.corpsenm = NON_PM; /* suppress statue and figurine details */
1070 /* but suppressing fruit details leads to "bad fruit #0"
1071 [perhaps we should force "slime mold" rather than use xname?] */
1072 if (obj->otyp == SLIME_MOLD)
1073 bareobj.spe = obj->spe;
1075 bufp = distant_name(&bareobj, xname); /* xname(&bareobj) */
1077 if (!strncmp(bufp, "uncursed ", 9))
1078 bufp += 9; /* Role_if(PM_PRIEST) */
1080 if (!strncmp(bufp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢", 14))
1081 bufp += 14; /* Role_if(PM_PRIEST) */
1084 objects[otyp].oc_uname = saveobcls.oc_uname;
1085 objects[otyp].oc_name_known = saveobcls.oc_name_known;
1089 /* xname() output augmented for multishot missile feedback */
1095 char *onm = xname(obj);
1097 if (m_shot.n > 1 && m_shot.o == obj->otyp) {
1098 /* "the Nth arrow"; value will eventually be passed to an() or
1099 The(), both of which correctly handle this "the " prefix */
1101 Sprintf(tmpbuf, "the %d%s ", m_shot.i, ordin(m_shot.i));
1103 Sprintf(tmpbuf, "%d%s
\96Ú
\82Ì", m_shot.i, numeral(obj));
1104 onm = strprepend(onm, tmpbuf);
1109 /* used for naming "the unique_item" instead of "a unique_item" */
1115 boolean known = (obj->known || iflags.override_ID);
1117 if (!obj->dknown && !iflags.override_ID)
1119 else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !known)
1120 return TRUE; /* lie */
1122 return (boolean) (objects[obj->otyp].oc_unique
1123 && (known || obj->otyp == AMULET_OF_YENDOR));
1129 /* should monster type be prefixed with "the"? (mostly used for corpses) */
1132 struct permonst *ptr;
1136 /* even though monsters with personal names are unique, we want to
1137 describe them as "Name" rather than "the Name" */
1138 if (type_is_pname(ptr))
1141 uniq = (ptr->geno & G_UNIQ) ? TRUE : FALSE;
1142 /* high priest is unique if it includes "of <deity>", otherwise not
1143 (caller needs to handle the 1st possibility; we assume the 2nd);
1144 worm tail should be irrelevant but is included for completeness */
1145 if (ptr == &mons[PM_HIGH_PRIEST] || ptr == &mons[PM_LONG_WORM_TAIL])
1147 /* Wizard no longer needs this; he's flagged as unique these days */
1148 if (ptr == &mons[PM_WIZARD_OF_YENDOR])
1154 add_erosion_words(obj, prefix)
1158 boolean iscrys = (obj->otyp == CRYSKNIFE);
1161 rknown = (iflags.override_ID == 0) ? obj->rknown : TRUE;
1163 if (!is_damageable(obj) && !iscrys)
1166 /* The only cases where any of these bits do double duty are for
1167 * rotted food and diluted potions, which are all not is_damageable().
1169 if (obj->oeroded && !iscrys) {
1170 switch (obj->oeroded) {
1173 Strcat(prefix, "very ");
1175 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1179 Strcat(prefix, "thoroughly ");
1181 Strcat(prefix, "
\82©
\82È
\82è");
1185 Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
1187 Strcat(prefix, is_rustprone(obj) ? "
\8eK
\82Ñ
\82½" : "
\8f\9d\82Â
\82¢
\82½");
1189 if (obj->oeroded2 && !iscrys) {
1190 switch (obj->oeroded2) {
1193 Strcat(prefix, "very ");
1195 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1199 Strcat(prefix, "thoroughly ");
1201 Strcat(prefix, "
\82©
\82È
\82è");
1205 Strcat(prefix, is_corrodeable(obj) ? "corroded " : "rotted ");
1207 Strcat(prefix, is_corrodeable(obj) ? "
\95\85\90H
\82µ
\82½" : "
\95\85\82Á
\82½");
1209 if (rknown && obj->oerodeproof)
1210 Strcat(prefix, iscrys
1214 ? "
\88À
\92è
\82µ
\82½"
1219 ? "
\8eK
\82Ñ
\82È
\82¢"
1220 : is_corrodeable(obj)
1222 ? "corrodeproof " /* "stainless"? */
1224 ? "
\95\85\90H
\82µ
\82È
\82¢" /* "stainless"? */
1230 ? "
\94R
\82¦
\82È
\82¢"
1234 /* used to prevent rust on items where rust makes no difference */
1236 erosion_matters(obj)
1239 switch (obj->oclass) {
1241 /* it's possible for a rusty weptool to be polymorphed into some
1242 non-weptool iron tool, in which case the rust implicitly goes
1243 away, but it's also possible for it to be polymorphed into a
1244 non-iron tool, in which case rust also implicitly goes away,
1245 so there's no particular reason to try to handle the first
1246 instance differently [this comment belongs in poly_obj()...] */
1247 return is_weptool(obj) ? TRUE : FALSE;
1259 #define DONAME_WITH_PRICE 1
1260 #define DONAME_VAGUE_QUAN 2
1263 doname_base(obj, doname_flags)
1265 unsigned doname_flags;
1267 boolean ispoisoned = FALSE,
1268 with_price = (doname_flags & DONAME_WITH_PRICE) != 0,
1269 vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0;
1270 boolean known, dknown, cknown, bknown, lknown;
1271 int omndx = obj->corpsenm;
1272 char prefix[PREFIX];
1274 char tmpbuf[PREFIX + 1]; /* for when we have to add something at
1275 the start of prefix instead of the
1276 end (Strcat is used on the end) */
1278 register char *bp = xname(obj);
1279 #if 1 /*JP*//*
\8f\87\8f\98\93ü
\82ê
\91Ö
\82¦
\82É
\8eg
\82¤*/
1280 char preprefix[PREFIX];
1283 if (iflags.override_ID) {
1284 known = dknown = cknown = bknown = lknown = TRUE;
1287 dknown = obj->dknown;
1288 cknown = obj->cknown;
1289 bknown = obj->bknown;
1290 lknown = obj->lknown;
1293 /* When using xname, we want "poisoned arrow", and when using
1294 * doname, we want "poisoned +0 arrow". This kludge is about the only
1295 * way to do it, at least until someone overhauls xname() and doname(),
1296 * combining both into one function taking a parameter.
1298 /* must check opoisoned--someone can have a weirdly-named fruit */
1300 if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
1305 if (!strncmp(bp, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½", 12) && obj->opoisoned) {
1312 *
\81u
\8eq
\94L
\82Ì
\82½
\82Ü
\82Æ
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½
\8e\80\91Ì
\81v
\82æ
\82è
\81u
\82½
\82Ü
\82Æ
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½
\8eq
\94L
\82Ì
\8e\80\91Ì
\81v
1313 *
\82Ì
\82Ù
\82¤
\82ª
\8e©
\91R
\82Å
\82 \82é
\81D
1317 preprefix[0] = '\0';
1318 if((tp = strstri(bp, "
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½")) != NULL){
1319 tp += 12; /*
\81u
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½
\81v*/
1320 strncpy(preprefix, bp, tp - bp);
1321 preprefix[tp - bp] = '\0';
1328 if (obj->quan != 1L) {
1329 if (dknown || !vague_quan)
1331 Sprintf(prefix, "%ld ", obj->quan);
1332 #else /*
\93ú
\96{
\8cê
\82Æ
\82µ
\82Ä
\82Í
\90\94\8e\8c\82ª
\82È
\82¢
\82Ì
\82Í
\95s
\8e©
\91R */
1333 Sprintf(prefix, "%ld%s
\82Ì", obj->quan, numeral(obj));
1337 Strcpy(prefix, "some ");
1339 Strcpy(prefix, "
\82¢
\82
\82Â
\82©
\82Ì");
1340 } else if (obj->otyp == CORPSE) {
1341 /* skip article prefix for corpses [else corpse_xname()
1342 would have to be taught how to strip it off again] */
1344 #if 0 /*JP*/ /*
\8a¥
\8e\8c\82Í
\95s
\97v */
1345 } else if (obj_is_pname(obj) || the_unique_obj(obj)) {
1346 if (!strncmpi(bp, "the ", 4))
1348 Strcpy(prefix, "the ");
1350 Strcpy(prefix, "a ");
1351 #else /*prefix
\82Ì
\8f\89\8aú
\89»*/
1357 /* "empty" goes at the beginning, but item count goes at the end */
1359 /* bag of tricks: include "empty" prefix if it's known to
1360 be empty but its precise number of charges isn't known
1361 (when that is known, suffix of "(n:0)" will be appended,
1362 making the prefix be redundant; note that 'known' flag
1363 isn't set when emptiness gets discovered because then
1364 charging magic would yield known number of new charges) */
1365 && ((obj->otyp == BAG_OF_TRICKS)
1366 ? (obj->spe == 0 && !obj->known)
1367 /* not bag of tricks: empty if container which has no contents */
1368 : ((Is_container(obj) || obj->otyp == STATUE)
1369 && !Has_contents(obj))))
1371 Strcat(prefix, "empty ");
1373 Strcat(prefix, "
\8bó
\82Ì");
1375 if (bknown && obj->oclass != COIN_CLASS
1376 && (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
1377 || (!obj->cursed && !obj->blessed))) {
1378 /* allow 'blessed clear potion' if we don't know it's holy water;
1379 * always allow "uncursed potion of water"
1383 Strcat(prefix, "cursed ");
1385 Strcat(prefix, "
\8eô
\82í
\82ê
\82½");
1386 else if (obj->blessed)
1388 Strcat(prefix, "blessed ");
1390 Strcat(prefix, "
\8fj
\95\9f\82³
\82ê
\82½");
1391 else if (!iflags.implicit_uncursed
1392 /* For most items with charges or +/-, if you know how many
1393 * charges are left or what the +/- is, then you must have
1394 * totally identified the item, so "uncursed" is unnecessary,
1395 * because an identified object not described as "blessed" or
1396 * "cursed" must be uncursed.
1398 * If the charges or +/- is not known, "uncursed" must be
1399 * printed to avoid ambiguity between an item whose curse
1400 * status is unknown, and an item known to be uncursed.
1402 || ((!known || !objects[obj->otyp].oc_charged
1403 || obj->oclass == ARMOR_CLASS
1404 || obj->oclass == RING_CLASS)
1406 && obj->otyp != SCR_MAIL
1408 && obj->otyp != FAKE_AMULET_OF_YENDOR
1409 && obj->otyp != AMULET_OF_YENDOR
1410 && !Role_if(PM_PRIEST)))
1412 Strcat(prefix, "uncursed ");
1414 Strcat(prefix, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢");
1417 if (lknown && Is_box(obj)) {
1419 /* 3.6.0 used "unlockable" here but that could be misunderstood
1420 to mean "capable of being unlocked" rather than the intended
1421 "not capable of being locked" */
1423 Strcat(prefix, "broken ");
1425 Strcat(prefix, "
\8c®
\82Ì
\89ó
\82ê
\82½");
1426 else if (obj->olocked)
1428 Strcat(prefix, "locked ");
1430 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82½");
1433 Strcat(prefix, "unlocked ");
1435 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82Ä
\82¢
\82È
\82¢");
1440 Strcat(prefix, "greased ");
1442 Strcat(prefix, "
\96û
\82Ì
\93h
\82ç
\82ê
\82½");
1444 if (cknown && Has_contents(obj)) {
1445 /* we count the number of separate stacks, which corresponds
1446 to the number of inventory slots needed to be able to take
1447 everything out if no merges occur */
1448 long itemcount = count_contents(obj, FALSE, FALSE, TRUE);
1451 Sprintf(eos(bp), " containing %ld item%s", itemcount,
1454 Sprintf(eos(bp), "(%ld
\8cÂ
\93ü
\82Á
\82Ä
\82¢
\82é)", itemcount);
1458 switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
1460 if (obj->owornmask & W_AMUL)
1462 Strcat(bp, " (being worn)");
1464 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1467 if (obj->owornmask & W_ARMOR)
1469 Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
1471 Strcat(bp, (obj == uskin) ? "(
\94§
\82É
\96\84\82ß
\82±
\82Ü
\82ê
\82Ä
\82¢
\82é)"
1475 : "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1480 Strcat(prefix, "poisoned ");
1482 Strcat(prefix, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
1483 add_erosion_words(obj, prefix);
1485 Strcat(prefix, sitoa(obj->spe));
1486 Strcat(prefix, " ");
1490 if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
1492 Strcat(bp, " (being worn)");
1494 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1497 if (obj->otyp == LEASH && obj->leashmon != 0) {
1498 struct monst *mlsh = find_mid(obj->leashmon, FM_FMON);
1501 impossible("leashed monster not on this level");
1505 Sprintf(eos(bp), " (attached to %s)",
1508 Sprintf(eos(bp), " (%s
\82É
\8c\8b\82Ñ
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é)",
1514 if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
1517 Strcpy(tmpbuf, "no");
1519 Sprintf(tmpbuf, "%d", obj->spe);
1520 Sprintf(eos(bp), " (%s candle%s%s)", tmpbuf, plur(obj->spe),
1521 !obj->lamplit ? " attached" : ", lit");
1524 Sprintf(eos(bp), "(
\88ê
\96{
\82à
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82È
\82¢)");
1527 Sprintf(eos(bp), "(%d
\96{
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é)", obj->spe);
1529 Sprintf(eos(bp), "(%d
\96{
\8cõ
\82Á
\82Ä
\82¢
\82é)", obj->spe);
1533 } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
1534 || obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
1536 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
1538 Strcat(prefix, "partly used ");
1540 Strcat(prefix, "
\8eg
\82¢
\82³
\82µ
\82Ì");
1543 Strcat(bp, " (lit)");
1545 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1548 if (objects[obj->otyp].oc_charged)
1555 Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
1557 Sprintf(eos(bp), "(%d:%d)", (int) obj->recharged, obj->spe);
1560 if (obj->otyp == POT_OIL && obj->lamplit)
1562 Strcat(bp, " (lit)");
1564 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1568 if (obj->owornmask & W_RINGR)
1570 Strcat(bp, " (on right ");
1572 Strcat(bp, "(
\89E");
1573 if (obj->owornmask & W_RINGL)
1575 Strcat(bp, " (on left ");
1577 Strcat(bp, "(
\8d¶");
1578 if (obj->owornmask & W_RING) {
1579 Strcat(bp, body_part(HAND));
1582 if (known && objects[obj->otyp].oc_charged) {
1584 Strcat(prefix, " ");
1586 Strcat(prefix, sitoa(obj->spe));
1587 Strcat(prefix, " ");
1593 Strcat(prefix, "partly eaten ");
1595 Strcat(prefix, "
\90H
\82×
\82©
\82¯
\82Ì");
1596 if (obj->otyp == CORPSE) {
1597 /* (quan == 1) => want corpse_xname() to supply article,
1598 (quan != 1) => already have count or "some" as prefix;
1599 "corpse" is already in the buffer returned by xname() */
1600 unsigned cxarg = (((obj->quan != 1L) ? 0 : CXN_ARTICLE)
1602 char *cxstr = corpse_xname(obj, prefix, cxarg);
1605 Sprintf(prefix, "%s ", cxstr);
1607 Sprintf(prefix, "%s
\82Ì", cxstr);
1609 /* avoid having doname(corpse) consume an extra obuf */
1611 } else if (obj->otyp == EGG) {
1612 #if 0 /* corpses don't tell if they're stale either */
1613 if (known && stale_egg(obj))
1614 Strcat(prefix, "stale ");
1617 && (known || (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
1619 Strcat(prefix, mons[omndx].mname);
1620 Strcat(prefix, " ");
1622 Strcat(prefix, mons[omndx].mname);
1623 Strcat(prefix, "
\82Ì");
1627 Strcat(bp, " (laid by you)");
1629 Strcat(bp, "(
\82 \82È
\82½
\82ª
\8eY
\82ñ
\82¾)");
1632 if (obj->otyp == MEAT_RING)
1637 add_erosion_words(obj, prefix);
1638 if (obj->owornmask & W_BALL)
1640 Strcat(bp, " (chained to you)");
1642 Strcat(bp, "(
\82 \82È
\82½
\82É
\8cq
\82ª
\82ê
\82Ä
\82¢
\82é)");
1646 if ((obj->owornmask & W_WEP) && !mrg_to_wielded) {
1647 if (obj->quan != 1L) {
1649 Strcat(bp, " (wielded)");
1651 Strcat(bp, "(
\91\95\94õ
\82µ
\82Ä
\82¢
\82é)");
1653 const char *hand_s = body_part(HAND);
1656 hand_s = makeplural(hand_s);
1658 Sprintf(eos(bp), " (weapon in %s)", hand_s);
1660 Sprintf(eos(bp), "(%s
\82É
\82µ
\82Ä
\82¢
\82é)", hand_s);
1662 if (warn_obj_cnt && obj == uwep && (EWarn_of_mon & W_WEP) != 0L) {
1663 /* presumably can be felt when blind */
1665 Strcat(bp, " (glowing");
1667 Sprintf(eos(bp), " %s", glow_color(obj->oartifact));
1671 Strcat(bp, " (
\94M
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82é)");
1673 Sprintf(eos(bp), " (%s
\8bP
\82¢
\82Ä
\82¢
\82é)",
1674 glow_color(obj->oartifact));
1679 if (obj->owornmask & W_SWAPWEP) {
1682 Sprintf(eos(bp), " (wielded in other %s)", body_part(HAND));
1684 Sprintf(eos(bp), "(
\8d¶%s
\82É
\82µ
\82Ä
\82¢
\82é)", body_part(HAND));
1687 Strcat(bp, " (alternate weapon; not wielded)");
1689 Strcat(bp, "(
\97\
\94õ
\82Ì
\95\90\8aí;
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢)");
1691 if (obj->owornmask & W_QUIVER) {
1692 switch (obj->oclass) {
1695 if (objects[obj->otyp].oc_skill == -P_BOW) {
1696 /* Ammo for a bow */
1698 Strcat(bp, " (in quiver)");
1700 Strcat(bp, "(
\96î
\93\9b\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1703 /* Ammo not for a bow */
1705 Strcat(bp, " (in quiver pouch)");
1707 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1711 /* Weapons not considered ammo */
1713 Strcat(bp, " (at the ready)");
1715 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1718 /* Small things and ammo not for a bow */
1725 Strcat(bp, " (in quiver pouch)");
1727 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1729 default: /* odd things */
1731 Strcat(bp, " (at the ready)");
1733 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1736 if (!iflags.suppress_price && is_unpaid(obj)) {
1737 long quotedprice = unpaid_cost(obj, TRUE);
1740 Sprintf(eos(bp), " (%s, %ld %s)",
1741 obj->unpaid ? "unpaid" : "contents",
1742 quotedprice, currency(quotedprice));
1744 Sprintf(eos(bp), " (%s, %ld%s)",
1745 obj->unpaid ? "
\96¢
\95¥
\82¢" : "
\92\86\90g",
1746 quotedprice, currency(quotedprice));
1748 } else if (with_price) {
1749 long price = get_cost_of_shop_item(obj);
1752 Sprintf(eos(bp), " (%ld %s)", price, currency(price));
1754 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
1755 if (!strncmp(prefix, "a ", 2)
1756 && index(vowels, *(prefix + 2) ? *(prefix + 2) : *bp)
1758 || (strncmp(bp, "uranium", 7) && strncmp(bp, "unicorn", 7)
1759 && strncmp(bp, "eucalyptus", 10)))) {
1760 Strcpy(tmpbuf, prefix);
1761 Strcpy(prefix, "an ");
1762 Strcpy(prefix + 3, tmpbuf + 2);
1766 /* show weight for items (debug tourist info)
1767 * aum is stolen from Crawl's "Arbitrary Unit of Measure" */
1768 if (wizard && iflags.wizweight) {
1769 Sprintf(eos(bp), " (%d aum)", obj->owt);
1772 bp = strprepend(bp, prefix);
1773 #else /*JP:
\81u
\96¼
\95t
\82¯
\82ç
\82ê
\82½
\81v
\82ð
\96ß
\82·*/
1774 Strcat(preprefix, prefix);
1775 bp = strprepend(bp, preprefix);
1784 return doname_base(obj, (unsigned) 0);
1787 /* Name of object including price. */
1789 doname_with_price(obj)
1792 return doname_base(obj, DONAME_WITH_PRICE);
1795 /* "some" instead of precise quantity if obj->dknown not set */
1797 doname_vague_quan(obj)
1801 * If it hasn't been seen up close and quantity is more than one,
1802 * use "some" instead of the quantity: "some gold pieces" rather
1803 * than "25 gold pieces". This is suboptimal, to put it mildly,
1804 * because lookhere and pickup report the precise amount.
1805 * Picking the item up while blind also shows the precise amount
1806 * for inventory display, then dropping it while still blind leaves
1807 * obj->dknown unset so the count reverts to "some" for farlook.
1809 * TODO: add obj->qknown flag for 'quantity known' on stackable
1810 * items; it could overlay obj->cknown since no containers stack.
1812 return doname_base(obj, DONAME_VAGUE_QUAN);
1815 /* used from invent.c */
1817 not_fully_identified(otmp)
1820 /* gold doesn't have any interesting attributes [yet?] */
1821 if (otmp->oclass == COIN_CLASS)
1822 return FALSE; /* always fully ID'd */
1823 /* check fundamental ID hallmarks first */
1824 if (!otmp->known || !otmp->dknown
1826 || (!otmp->bknown && otmp->otyp != SCR_MAIL)
1830 || !objects[otmp->otyp].oc_name_known)
1832 if ((!otmp->cknown && (Is_container(otmp) || otmp->otyp == STATUE))
1833 || (!otmp->lknown && Is_box(otmp)))
1835 if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
1837 /* otmp->rknown is the only item of interest if we reach here */
1839 * Note: if a revision ever allows scrolls to become fireproof or
1840 * rings to become shockproof, this checking will need to be revised.
1841 * `rknown' ID only matters if xname() will provide the info about it.
1844 || (otmp->oclass != ARMOR_CLASS && otmp->oclass != WEAPON_CLASS
1845 && !is_weptool(otmp) /* (redundant) */
1846 && otmp->oclass != BALL_CLASS)) /* (useless) */
1848 else /* lack of `rknown' only matters for vulnerable objects */
1849 return (boolean) (is_rustprone(otmp) || is_corrodeable(otmp)
1850 || is_flammable(otmp));
1853 /* format a corpse name (xname() omits monster type; doname() calls us);
1854 eatcorpse() also uses us for death reason when eating tainted glob */
1856 corpse_xname(otmp, adjective, cxn_flags)
1858 const char *adjective;
1859 unsigned cxn_flags; /* bitmask of CXN_xxx values */
1861 char *nambuf = nextobuf();
1862 int omndx = otmp->corpsenm;
1863 boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0,
1864 /* suppress "the" from "the unique monster corpse" */
1865 no_prefix = (cxn_flags & CXN_NO_PFX) != 0,
1866 /* include "the" for "the woodchuck corpse */
1867 the_prefix = (cxn_flags & CXN_PFX_THE) != 0,
1868 /* include "an" for "an ogre corpse */
1869 any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
1870 /* leave off suffix (do_name() appends "corpse" itself) */
1871 omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
1873 glob = (otmp->otyp != CORPSE && otmp->globby);
1877 mname = OBJ_NAME(objects[otmp->otyp]); /* "glob of <monster>" */
1878 } else if (omndx == NON_PM) { /* paranoia */
1883 /* [Possible enhancement: check whether corpse has monster traits
1884 attached in order to use priestname() for priests and minions.] */
1885 } else if (omndx == PM_ALIGNED_PRIEST) {
1886 /* avoid "aligned priest"; it just exposes internal details */
1892 mname = mons[omndx].mname;
1893 if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) {
1894 mname = s_suffix(mname);
1896 /* don't precede personal name like "Medusa" with an article */
1897 if (type_is_pname(&mons[omndx]))
1899 /* always precede non-personal unique monster name like
1900 "Oracle" with "the" unless explicitly overridden */
1901 else if (the_unique_pm(&mons[omndx]) && !no_prefix)
1906 the_prefix = any_prefix = FALSE;
1907 else if (the_prefix)
1908 any_prefix = FALSE; /* mutually exclusive */
1911 /* can't use the() the way we use an() below because any capitalized
1912 Name causes it to assume a personal name and return Name as-is;
1913 that's usually the behavior wanted, but here we need to force "the"
1914 to precede capitalized unique monsters (pnames are handled above) */
1915 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
1917 Strcat(nambuf, "the ");
1920 if (!adjective || !*adjective) {
1921 /* normal case: newt corpse */
1922 Strcat(nambuf, mname);
1924 /* adjective positioning depends upon format of monster name */
1925 if (possessive) /* Medusa's cursed partly eaten corpse */
1927 Sprintf(eos(nambuf), "%s %s", mname, adjective);
1929 Sprintf(eos(nambuf), "%s%s", mname, adjective);
1930 else /* cursed partly eaten troll corpse */
1932 Sprintf(eos(nambuf), "%s %s", adjective, mname);
1934 Sprintf(eos(nambuf), "%s%s", adjective, mname);
1935 /* in case adjective has a trailing space, squeeze it out */
1937 /* doname() might include a count in the adjective argument;
1938 if so, don't prepend an article */
1939 if (digit(*adjective))
1944 ; /* omit_corpse doesn't apply; quantity is always 1 */
1945 } else if (!omit_corpse) {
1947 Strcat(nambuf, " corpse");
1948 /* makeplural(nambuf) => append "s" to "corpse" */
1949 if (otmp->quan > 1L && !ignore_quan) {
1950 Strcat(nambuf, "s");
1951 any_prefix = FALSE; /* avoid "a newt corpses" */
1954 Strcat(nambuf, "
\82Ì
\8e\80\91Ì");
1958 /* it's safe to overwrite our nambuf after an() has copied
1959 its old value into another buffer */
1961 Strcpy(nambuf, an(nambuf));
1966 /* xname doesn't include monster type for "corpse"; cxname does */
1971 if (obj->otyp == CORPSE)
1972 return corpse_xname(obj, (const char *) 0, CXN_NORMAL);
1976 /* like cxname, but ignores quantity */
1978 cxname_singular(obj)
1981 if (obj->otyp == CORPSE)
1982 return corpse_xname(obj, (const char *) 0, CXN_SINGULAR);
1983 return xname_flags(obj, CXN_SINGULAR);
1986 /* treat an object as fully ID'd when it might be used as reason for death */
1991 struct obj save_obj;
1992 unsigned save_ocknown;
1993 char *buf, *save_ocuname, *save_oname = (char *) 0;
1995 /* bypass object twiddling for artifacts */
1997 return bare_artifactname(obj);
1999 /* remember original settings for core of the object;
2000 oextra structs other than oname don't matter here--since they
2001 aren't modified they don't need to be saved and restored */
2004 save_oname = ONAME(obj);
2006 /* killer name should be more specific than general xname; however, exact
2007 info like blessed/cursed and rustproof makes things be too verbose */
2008 obj->known = obj->dknown = 1;
2009 obj->bknown = obj->rknown = obj->greased = 0;
2010 /* if character is a priest[ess], bknown will get toggled back on */
2011 if (obj->otyp != POT_WATER)
2012 obj->blessed = obj->cursed = 0;
2014 obj->bknown = 1; /* describe holy/unholy water as such */
2015 /* "killed by poisoned <obj>" would be misleading when poison is
2016 not the cause of death and "poisoned by poisoned <obj>" would
2017 be redundant when it is, so suppress "poisoned" prefix */
2019 /* strip user-supplied name; artifacts keep theirs */
2020 if (!obj->oartifact && save_oname)
2021 ONAME(obj) = (char *) 0;
2022 /* temporarily identify the type of object */
2023 save_ocknown = objects[obj->otyp].oc_name_known;
2024 objects[obj->otyp].oc_name_known = 1;
2025 save_ocuname = objects[obj->otyp].oc_uname;
2026 objects[obj->otyp].oc_uname = 0; /* avoid "foo called bar" */
2028 /* format the object */
2029 if (obj->otyp == CORPSE) {
2031 Strcpy(buf, corpse_xname(obj, (const char *) 0, CXN_NORMAL));
2032 } else if (obj->otyp == SLIME_MOLD) {
2033 /* concession to "most unique deaths competition" in the annual
2034 devnull tournament, suppress player supplied fruit names because
2035 those can be used to fake other objects and dungeon features */
2038 Sprintf(buf, "deadly slime mold%s", plur(obj->quan));
2040 Strcpy(buf, "
\8aë
\8c¯
\82È
\82Ë
\82Î
\82Ë
\82Î
\83J
\83r");
2044 /* apply an article if appropriate; caller should always use KILLED_BY */
2045 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
2046 if (obj->quan == 1L && !strstri(buf, "'s ") && !strstri(buf, "s' "))
2047 buf = (obj_is_pname(obj) || the_unique_obj(obj)) ? the(buf) : an(buf);
2050 objects[obj->otyp].oc_name_known = save_ocknown;
2051 objects[obj->otyp].oc_uname = save_ocuname;
2052 *obj = save_obj; /* restore object's core settings */
2053 if (!obj->oartifact && save_oname)
2054 ONAME(obj) = save_oname;
2059 /* xname,doname,&c with long results reformatted to omit some stuff */
2061 short_oname(obj, func, altfunc, lenlimit)
2063 char *FDECL((*func), (OBJ_P)), /* main formatting routine */
2064 *FDECL((*altfunc), (OBJ_P)); /* alternate for shortest result */
2067 struct obj save_obj;
2068 char unamebuf[12], onamebuf[12], *save_oname, *save_uname, *outbuf;
2070 outbuf = (*func)(obj);
2071 if ((unsigned) strlen(outbuf) <= lenlimit)
2074 /* shorten called string to fairly small amount */
2075 save_uname = objects[obj->otyp].oc_uname;
2076 if (save_uname && strlen(save_uname) >= sizeof unamebuf) {
2077 (void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
2078 Strcpy(unamebuf + sizeof unamebuf - 4, "...");
2079 objects[obj->otyp].oc_uname = unamebuf;
2080 releaseobuf(outbuf);
2081 outbuf = (*func)(obj);
2082 objects[obj->otyp].oc_uname = save_uname; /* restore called string */
2083 if ((unsigned) strlen(outbuf) <= lenlimit)
2087 /* shorten named string to fairly small amount */
2088 save_oname = has_oname(obj) ? ONAME(obj) : 0;
2089 if (save_oname && strlen(save_oname) >= sizeof onamebuf) {
2090 (void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
2091 Strcpy(onamebuf + sizeof onamebuf - 4, "...");
2092 ONAME(obj) = onamebuf;
2093 releaseobuf(outbuf);
2094 outbuf = (*func)(obj);
2095 ONAME(obj) = save_oname; /* restore named string */
2096 if ((unsigned) strlen(outbuf) <= lenlimit)
2100 /* shorten both called and named strings;
2101 unamebuf and onamebuf have both already been populated */
2102 if (save_uname && strlen(save_uname) >= sizeof unamebuf && save_oname
2103 && strlen(save_oname) >= sizeof onamebuf) {
2104 objects[obj->otyp].oc_uname = unamebuf;
2105 ONAME(obj) = onamebuf;
2106 releaseobuf(outbuf);
2107 outbuf = (*func)(obj);
2108 if ((unsigned) strlen(outbuf) <= lenlimit) {
2109 objects[obj->otyp].oc_uname = save_uname;
2110 ONAME(obj) = save_oname;
2115 /* still long; strip several name-lengthening attributes;
2116 called and named strings are still in truncated form */
2118 obj->bknown = obj->rknown = obj->greased = 0;
2119 obj->oeroded = obj->oeroded2 = 0;
2120 releaseobuf(outbuf);
2121 outbuf = (*func)(obj);
2122 if (altfunc && (unsigned) strlen(outbuf) > lenlimit) {
2123 /* still long; use the alternate function (usually one of
2124 the jackets around minimal_xname()) */
2125 releaseobuf(outbuf);
2126 outbuf = (*altfunc)(obj);
2128 /* restore the object */
2131 ONAME(obj) = save_oname;
2133 objects[obj->otyp].oc_uname = save_uname;
2135 /* use whatever we've got, whether it's too long or not */
2140 * Used if only one of a collection of objects is named (e.g. in eat.c).
2143 singular(otmp, func)
2144 register struct obj *otmp;
2145 char *FDECL((*func), (OBJ_P));
2150 /* using xname for corpses does not give the monster type */
2151 if (otmp->otyp == CORPSE && func == xname)
2154 savequan = otmp->quan;
2156 nam = (*func)(otmp);
2157 otmp->quan = savequan;
2163 register const char *str;
2165 char *buf = nextobuf();
2167 #if 0 /*JP*//*
\95s
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2170 if (strncmpi(str, "the ", 4) && strcmp(str, "molten lava")
2171 && strcmp(str, "iron bars") && strcmp(str, "ice")) {
2172 if (index(vowels, *str) && strncmp(str, "one-", 4)
2173 && strncmp(str, "useful", 6) && strncmp(str, "unicorn", 7)
2174 && strncmp(str, "uranium", 7) && strncmp(str, "eucalyptus", 10))
2181 #else /*
\92P
\82É
\83R
\83s
\81[*/
2191 char *tmp = an(str);
2193 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
2200 * Prepend "the" if necessary; assumes str is a subject derived from xname.
2201 * Use type_is_pname() for monster names, not the(). the() is idempotent.
2207 char *buf = nextobuf();
2208 #if 0 /*JP*//*
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2209 boolean insert_the = FALSE;
2211 if (!strncmpi(str, "the ", 4)) {
2212 buf[0] = lowc(*str);
2213 Strcpy(&buf[1], str + 1);
2215 } else if (*str < 'A' || *str > 'Z'
2216 /* treat named fruit as not a proper name, even if player
2217 has assigned a capitalized proper name as his/her fruit */
2218 || fruit_from_name(str, TRUE, (int *) 0)) {
2219 /* not a proper name, needs an article */
2222 /* Probably a proper name, might not need an article */
2223 register char *tmp, *named, *called;
2226 /* some objects have capitalized adjectives in their names */
2227 if (((tmp = rindex(str, ' ')) != 0 || (tmp = rindex(str, '-')) != 0)
2228 && (tmp[1] < 'A' || tmp[1] > 'Z')) {
2230 } else if (tmp && index(str, ' ') < tmp) { /* has spaces */
2231 /* it needs an article if the name contains "of" */
2232 tmp = strstri(str, " of ");
2233 named = strstri(str, " named ");
2234 called = strstri(str, " called ");
2235 if (called && (!named || called < named))
2238 if (tmp && (!named || tmp < named)) /* found an "of" */
2240 /* stupid special case: lacks "of" but needs "the" */
2241 else if (!named && (l = strlen(str)) >= 31
2242 && !strcmp(&str[l - 31],
2243 "Platinum Yendorian Express Card"))
2248 Strcpy(buf, "the ");
2253 #else /*
\92P
\82É
\83R
\83s
\81[*/
2263 char *tmp = the(str);
2265 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
2274 register struct obj *otmp;
2275 register const char *verb;
2281 /* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */
2287 char prefix[PREFIX];
2288 char *bp = cxname(otmp);
2290 if (otmp->quan != 1L) {
2291 Sprintf(prefix, "%ld ", otmp->quan);
2292 bp = strprepend(bp, prefix);
2296 Strcat(bp, otense(otmp, verb));
2302 /* combine yname and aobjnam eg "your count cxname(otmp)" */
2308 char *s = aobjnam(obj, verb);
2310 /* leave off "your" for most of your artifacts, but prepend
2311 * "your" for unique objects and "foo of bar" quest artifacts */
2312 if (!carried(obj) || !obj_is_pname(obj)
2313 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2314 char *outbuf = shk_your(nextobuf(), obj);
2315 int space_left = BUFSZ - 1 - strlen(outbuf);
2317 s = strncat(outbuf, s, space_left);
2322 /* combine Yname2 and aobjnam eg "Your count cxname(otmp)" */
2328 register char *s = yobjnam(obj, verb);
2336 /* like aobjnam, but prepend "The", not count, and use xname */
2342 char *bp = The(xname(otmp));
2344 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2347 Strcat(bp, otense(otmp, verb));
2353 /* capitalized variant of doname() */
2358 char *s = doname(obj);
2364 /* returns "[your ]xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
2369 char *s = cxname(obj);
2371 /* leave off "your" for most of your artifacts, but prepend
2372 * "your" for unique objects and "foo of bar" quest artifacts */
2373 if (!carried(obj) || !obj_is_pname(obj)
2374 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2375 char *outbuf = shk_your(nextobuf(), obj);
2376 int space_left = BUFSZ - 1 - strlen(outbuf);
2378 s = strncat(outbuf, s, space_left);
2384 /* capitalized variant of yname() */
2389 char *s = yname(obj);
2397 /* returns "your minimal_xname(obj)"
2398 * or "Foobar's minimal_xname(obj)"
2399 * or "the minimal_xname(obj)"
2405 char *outbuf = nextobuf();
2406 char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
2408 int space_left = BUFSZ - 1 - strlen(s);
2410 return strncat(s, minimal_xname(obj), space_left);
2412 int space_left = BUFSZ - strlen(s);
2414 return strncat(s, minimal_xname(obj), space_left);
2418 /* capitalized variant of ysimple_name() */
2423 char *s = ysimple_name(obj);
2431 /* "scroll" or "scrolls" */
2436 char *simpleoname = minimal_xname(obj);
2438 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2439 if (obj->quan != 1L)
2440 simpleoname = makeplural(simpleoname);
2445 /* "a scroll" or "scrolls"; "a silver bell" or "the Bell of Opening" */
2450 char *simpleoname = simpleonames(obj);
2451 int otyp = obj->otyp;
2453 /* prefix with "the" if a unique item, or a fake one imitating same,
2454 has been formatted with its actual name (we let typename() handle
2455 any `known' and `dknown' checking necessary) */
2456 if (otyp == FAKE_AMULET_OF_YENDOR)
2457 otyp = AMULET_OF_YENDOR;
2458 if (objects[otyp].oc_unique
2459 && !strcmp(simpleoname, OBJ_NAME(objects[otyp])))
2460 return the(simpleoname);
2462 /* simpleoname is singular if quan==1, plural otherwise */
2463 if (obj->quan == 1L)
2464 simpleoname = an(simpleoname);
2468 /* "the scroll" or "the scrolls" */
2473 char *simpleoname = simpleonames(obj);
2475 return the(simpleoname);
2478 /* artifact's name without any object type or known/dknown/&c feedback */
2480 bare_artifactname(obj)
2485 if (obj->oartifact) {
2486 outbuf = nextobuf();
2487 Strcpy(outbuf, artiname(obj->oartifact));
2489 if (!strncmp(outbuf, "The ", 4))
2490 outbuf[0] = lowc(outbuf[0]);
2493 outbuf = xname(obj);
2498 static const char *wrp[] = {
2499 "wand", "ring", "potion", "scroll", "gem",
2500 "amulet", "spellbook", "spell book",
2501 /* for non-specific wishes */
2502 "weapon", "armor", "tool", "food", "comestible",
2504 static const char wrpsym[] = { WAND_CLASS, RING_CLASS, POTION_CLASS,
2505 SCROLL_CLASS, GEM_CLASS, AMULET_CLASS,
2506 SPBOOK_CLASS, SPBOOK_CLASS, WEAPON_CLASS,
2507 ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
2510 /* return form of the verb (input plural) if xname(otmp) were the subject */
2519 * verb is given in plural (without trailing s). Return as input
2520 * if the result of xname(otmp) would be plural. Don't bother
2521 * recomputing xname(otmp) at this time.
2523 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2524 if (!is_plural(otmp))
2525 return vtense((char *) 0, verb);
2533 /* various singular words that vtense would otherwise categorize as plural;
2534 also used by makesingular() to catch some special cases */
2535 static const char *const special_subjs[] = {
2536 "erinys", "manes", /* this one is ambiguous */
2537 "Cyclops", "Hippocrates", "Pelias", "aklys",
2538 "amnesia", "detect monsters", "paralysis", "shape changers",
2540 /* note: "detect monsters" and "shape changers" are normally
2541 caught via "<something>(s) of <whatever>", but they can be
2542 wished for using the shorter form, so we include them here
2543 to accommodate usage by makesingular during wishing */
2546 /* return form of the verb (input plural) for present tense 3rd person subj */
2549 register const char *subj;
2550 register const char *verb;
2552 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2553 char *buf = nextobuf(), *bspot;
2555 const char *sp, *spot;
2556 const char *const *spec;
2559 * verb is given in plural (without trailing s). Return as input
2560 * if subj appears to be plural. Add special cases as necessary.
2561 * Many hard cases can already be handled by using otense() instead.
2562 * If this gets much bigger, consider decomposing makeplural.
2563 * Note: monster names are not expected here (except before corpse).
2565 * Special case: allow null sobj to get the singular 3rd person
2566 * present tense form so we don't duplicate this code elsewhere.
2569 if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
2571 spot = (const char *) 0;
2572 for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
2573 if (!strncmpi(sp, " of ", 4) || !strncmpi(sp, " from ", 6)
2574 || !strncmpi(sp, " called ", 8) || !strncmpi(sp, " named ", 7)
2575 || !strncmpi(sp, " labeled ", 9)) {
2581 len = (int) strlen(subj);
2583 spot = subj + len - 1;
2586 * plural: anything that ends in 's', but not '*us' or '*ss'.
2587 * Guess at a few other special cases that makeplural creates.
2589 if ((lowc(*spot) == 's' && spot != subj
2590 && !index("us", lowc(*(spot - 1))))
2591 || !BSTRNCMPI(subj, spot - 3, "eeth", 4)
2592 || !BSTRNCMPI(subj, spot - 3, "feet", 4)
2593 || !BSTRNCMPI(subj, spot - 1, "ia", 2)
2594 || !BSTRNCMPI(subj, spot - 1, "ae", 2)) {
2595 /* check for special cases to avoid false matches */
2596 len = (int) (spot - subj) + 1;
2597 for (spec = special_subjs; *spec; spec++) {
2598 ltmp = strlen(*spec);
2599 if (len == ltmp && !strncmpi(*spec, subj, len))
2601 /* also check for <prefix><space><special_subj>
2602 to catch things like "the invisible erinys" */
2603 if (len > ltmp && *(spot - ltmp) == ' '
2604 && !strncmpi(*spec, spot - ltmp + 1, ltmp))
2608 return strcpy(buf, verb);
2611 * 3rd person plural doesn't end in telltale 's';
2612 * 2nd person singular behaves as if plural.
2614 if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
2615 return strcpy(buf, verb);
2620 len = (int) strlen(buf);
2621 bspot = buf + len - 1;
2623 if (!strcmpi(buf, "are")) {
2624 Strcasecpy(buf, "is");
2625 } else if (!strcmpi(buf, "have")) {
2626 Strcasecpy(bspot - 1, "s");
2627 } else if (index("zxs", lowc(*bspot))
2628 || (len >= 2 && lowc(*bspot) == 'h'
2629 && index("cs", lowc(*(bspot - 1))))
2630 || (len == 2 && lowc(*bspot) == 'o')) {
2631 /* Ends in z, x, s, ch, sh; add an "es" */
2632 Strcasecpy(bspot + 1, "es");
2633 } else if (lowc(*bspot) == 'y' && !index(vowels, lowc(*(bspot - 1)))) {
2634 /* like "y" case in makeplural */
2635 Strcasecpy(bspot, "ies");
2637 Strcasecpy(bspot + 1, "s");
2640 #else /*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
2650 const char *sing, *plur;
2653 /* word pairs that don't fit into formula-based transformations;
2654 also some suffices which have very few--often one--matches or
2655 which aren't systematically reversible (knives, staves) */
2656 static struct sing_plur one_off[] = {
2658 "children" }, /* (for wise guys who give their food funny names) */
2659 { "cubus", "cubi" }, /* in-/suc-cubus */
2660 { "culus", "culi" }, /* homunculus */
2661 { "djinni", "djinn" },
2662 { "erinys", "erinyes" },
2664 { "fungus", "fungi" },
2665 { "goose", "geese" },
2666 { "knife", "knives" },
2667 { "labrum", "labra" }, /* candelabrum */
2668 { "louse", "lice" },
2669 { "mouse", "mice" },
2670 { "mumak", "mumakil" },
2671 { "nemesis", "nemeses" },
2674 { "passerby", "passersby" },
2675 { "rtex", "rtices" }, /* vortex */
2676 { "serum", "sera" },
2677 { "staff", "staves" },
2678 { "tooth", "teeth" },
2682 static const char *const as_is[] = {
2683 /* makesingular() leaves these plural due to how they're used */
2684 "boots", "shoes", "gloves", "lenses", "scales",
2685 "eyes", "gauntlets", "iron bars",
2686 /* both singular and plural are spelled the same */
2687 "bison", "deer", "elk", "fish", "fowl",
2688 "tuna", "yaki", "-hai", "krill", "manes",
2689 "moose", "ninja", "sheep", "ronin", "roshi",
2690 "shito", "tengu", "ki-rin", "Nazgul", "gunyoki",
2691 "piranha", "samurai", "shuriken", 0,
2692 /* Note: "fish" and "piranha" are collective plurals, suitable
2693 for "wiped out all <foo>". For "3 <foo>", they should be
2694 "fishes" and "piranhas" instead. We settle for collective
2695 variant instead of attempting to support both. */
2698 /* singularize/pluralize decisions common to both makesingular & makeplural */
2700 singplur_lookup(basestr, endstring, to_plural, alt_as_is)
2701 char *basestr, *endstring; /* base string, pointer to eos(string) */
2702 boolean to_plural; /* true => makeplural, false => makesingular */
2703 const char *const *alt_as_is; /* another set like as_is[] */
2705 const struct sing_plur *sp;
2706 const char *same, *other, *const *as;
2709 for (as = as_is; *as; ++as) {
2710 al = (int) strlen(*as);
2711 if (!BSTRCMPI(basestr, endstring - al, *as))
2715 for (as = alt_as_is; *as; ++as) {
2716 al = (int) strlen(*as);
2717 if (!BSTRCMPI(basestr, endstring - al, *as))
2722 /* avoid false hit on one_off[].plur == "lice" or .sing == "goose";
2723 if more of these turn up, one_off[] entries will need to flagged
2724 as to which are whole words and which are matchable as suffices
2725 then matching in the loop below will end up becoming more complex */
2726 if (!strcmpi(basestr, "slice")
2727 || !strcmpi(basestr, "mongoose")) {
2729 Strcasecpy(endstring, "s");
2732 /* skip "ox" -> "oxen" entry when pluralizing "<something>ox"
2733 unless it is muskox */
2734 if (to_plural && strlen(basestr) > 2 && !strcmpi(endstring - 2, "ox")
2735 && strcmpi(endstring - 6, "muskox")) {
2736 /* "fox" -> "foxes" */
2737 Strcasecpy(endstring, "es");
2741 if (!strcmpi(endstring - 3, "man")
2742 && badman(basestr, to_plural)) {
2743 Strcasecpy(endstring, "s");
2747 if (!strcmpi(endstring - 3, "men")
2748 && badman(basestr, to_plural))
2751 for (sp = one_off; sp->sing; sp++) {
2752 /* check whether endstring already matches */
2753 same = to_plural ? sp->plur : sp->sing;
2754 al = (int) strlen(same);
2755 if (!BSTRCMPI(basestr, endstring - al, same))
2756 return TRUE; /* use as-is */
2757 /* check whether it matches the inverse; if so, transform it */
2758 other = to_plural ? sp->sing : sp->plur;
2759 al = (int) strlen(other);
2760 if (!BSTRCMPI(basestr, endstring - al, other)) {
2761 Strcasecpy(endstring - al, same);
2762 return TRUE; /* one_off[] transformation */
2768 /* searches for common compounds, ex. lump of royal jelly */
2770 singplur_compound(str)
2773 /* if new entries are added, be sure to keep compound_start[] in sync */
2774 static const char *const compounds[] =
2776 " of ", " labeled ", " called ",
2777 " named ", " above", /* lurkers above */
2778 " versus ", " from ", " in ",
2779 " on ", " a la ", " with", /* " with "? */
2780 " de ", " d'", " du ",
2782 }, /* list of first characters for all compounds[] entries */
2783 compound_start[] = " -";
2785 const char *const *cmpd;
2788 for (p = str; *p; ++p) {
2789 /* substring starting at p can only match if *p is found
2790 within compound_start[] */
2791 if (!index(compound_start, *p))
2794 /* check current substring against all words in the compound[] list */
2795 for (cmpd = compounds; *cmpd; ++cmpd)
2796 if (!strncmpi(p, *cmpd, (int) strlen(*cmpd)))
2799 /* wasn't recognized as a compound phrase */
2803 /* Plural routine; once upon a time it may have been chiefly used for
2804 * user-defined fruits, but it is now used extensively throughout the
2807 * For fruit, we have to try to account for everything reasonable the
2808 * player has; something unreasonable can still break the code.
2809 * However, it's still a lot more accurate than "just add an 's' at the
2810 * end", which Rogue uses...
2812 * Also used for plural monster names ("Wiped out all homunculi." or the
2813 * vanquished monsters list) and body parts. A lot of unique monsters have
2814 * names which get mangled by makeplural and/or makesingular. They're not
2815 * genocidable, and vanquished-mon handling does its own special casing
2816 * (for uniques who've been revived and re-killed), so we don't bother
2817 * trying to get those right here.
2819 * Also misused by muse.c to convert 1st person present verbs to 2nd person.
2820 * 3.6.0: made case-insensitive.
2826 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2827 register char *spot;
2828 char lo_c, *str = nextobuf();
2829 const char *excess = (char *) 0;
2833 while (*oldstr == ' ')
2835 if (!oldstr || !*oldstr) {
2836 impossible("plural of null?");
2840 Strcpy(str, oldstr);
2843 * Skip changing "pair of" to "pairs of". According to Webster, usual
2844 * English usage is use pairs for humans, e.g. 3 pairs of dancers,
2845 * and pair for objects and non-humans, e.g. 3 pair of boots. We don't
2846 * refer to pairs of humans in this game so just skip to the bottom.
2848 if (!strncmpi(str, "pair of ", 8))
2851 /* look for "foo of bar" so that we can focus on "foo" */
2852 if ((spot = singplur_compound(str)) != 0) {
2853 excess = oldstr + (int) (spot - str);
2859 while (spot > str && *spot == ' ')
2860 spot--; /* Strip blanks from end */
2862 /* Now spot is the last character of the string */
2866 /* Single letters */
2867 if (len == 1 || !letter(*spot)) {
2868 Strcpy(spot + 1, "'s");
2872 /* dispense with some words which don't need pluralization */
2874 static const char *const already_plural[] = {
2875 "ae", /* algae, larvae, &c */
2879 /* spot+1: synch up with makesingular's usage */
2880 if (singplur_lookup(str, spot + 1, TRUE, already_plural))
2883 /* more of same, but not suitable for blanket loop checking */
2884 if ((len == 2 && !strcmpi(str, "ya"))
2885 || (len >= 3 && !strcmpi(spot - 2, " ya")))
2889 /* man/men ("Wiped out all cavemen.") */
2890 if (len >= 3 && !strcmpi(spot - 2, "man")
2891 /* exclude shamans and humans etc */
2892 && !badman(str, TRUE)) {
2893 Strcasecpy(spot - 1, "en");
2896 if (lowc(*spot) == 'f') { /* (staff handled via one_off[]) */
2897 lo_c = lowc(*(spot - 1));
2898 if (len >= 3 && !strcmpi(spot - 2, "erf")) {
2899 /* avoid "nerf" -> "nerves", "serf" -> "serves" */
2900 ; /* fall through to default (append 's') */
2901 } else if (index("lr", lo_c) || index(vowels, lo_c)) {
2902 /* [aeioulr]f to [aeioulr]ves */
2903 Strcasecpy(spot, "ves");
2907 /* ium/ia (mycelia, baluchitheria) */
2908 if (len >= 3 && !strcmpi(spot - 2, "ium")) {
2909 Strcasecpy(spot - 2, "ia");
2912 /* algae, larvae, hyphae (another fungus part) */
2913 if ((len >= 4 && !strcmpi(spot - 3, "alga"))
2915 && (!strcmpi(spot - 4, "hypha") || !strcmpi(spot - 4, "larva")))
2916 || (len >= 6 && !strcmpi(spot - 5, "amoeba"))
2917 || (len >= 8 && (!strcmpi(spot - 7, "vertebra")))) {
2919 Strcasecpy(spot + 1, "e");
2922 /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
2923 if (len > 3 && !strcmpi(spot - 1, "us")
2924 && !((len >= 5 && !strcmpi(spot - 4, "lotus"))
2925 || (len >= 6 && !strcmpi(spot - 5, "wumpus")))) {
2926 Strcasecpy(spot - 1, "i");
2929 /* sis/ses (nemesis) */
2930 if (len >= 3 && !strcmpi(spot - 2, "sis")) {
2931 Strcasecpy(spot - 1, "es");
2934 /* matzoh/matzot, possible food name */
2936 && (!strcmpi(spot - 5, "matzoh") || !strcmpi(spot - 5, "matzah"))) {
2937 Strcasecpy(spot - 1, "ot"); /* oh/ah -> ot */
2941 && (!strcmpi(spot - 4, "matzo") || !strcmpi(spot - 4, "matza"))) {
2942 Strcasecpy(spot, "ot"); /* o/a -> ot */
2946 /* note: -eau/-eaux (gateau, bordeau...) */
2947 /* note: ox/oxen, VAX/VAXen, goose/geese */
2951 /* Ends in z, x, s, ch, sh; add an "es" */
2952 if (index("zxs", lo_c)
2953 || (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot - 1))))
2954 /* Kludge to get "tomatoes" and "potatoes" right */
2955 || (len >= 4 && !strcmpi(spot - 2, "ato"))
2956 || (len >= 5 && !strcmpi(spot - 4, "dingo"))) {
2957 Strcasecpy(spot + 1, "es"); /* append es */
2960 /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
2961 if (lo_c == 'y' && !index(vowels, lowc(*(spot - 1)))) {
2962 Strcasecpy(spot, "ies"); /* y -> ies */
2965 /* Default: append an 's' */
2966 Strcasecpy(spot + 1, "s");
2970 Strcat(str, excess);
2971 #else /*JP*//*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
2972 char *str = nextobuf();
2973 Strcpy(str, oldstr);
2979 * Singularize a string the user typed in; this helps reduce the complexity
2980 * of readobjnam, and is also used in pager.c to singularize the string
2981 * for which help is sought.
2983 * "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)?
2984 * Its inclusion in as_is[]/special_subj[] makes it get treated as the former.
2986 * A lot of unique monsters have names ending in s; plural, or singular
2987 * from plural, doesn't make much sense for them so we don't bother trying.
2988 * 3.6.0: made case-insensitive.
2991 makesingular(oldstr)
2994 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2995 register char *p, *bp;
2996 const char *excess = 0;
2997 char *str = nextobuf();
3000 while (*oldstr == ' ')
3002 if (!oldstr || !*oldstr) {
3003 impossible("singular of null?");
3008 bp = strcpy(str, oldstr);
3010 /* check for "foo of bar" so that we can focus on "foo" */
3011 if ((p = singplur_compound(bp)) != 0) {
3012 excess = oldstr + (int) (p - bp);
3017 /* dispense with some words which don't need singularization */
3018 if (singplur_lookup(bp, p, FALSE, special_subjs))
3021 /* remove -s or -es (boxes) or -ies (rubies) */
3022 if (p >= bp + 1 && lowc(p[-1]) == 's') {
3023 if (p >= bp + 2 && lowc(p[-2]) == 'e') {
3024 if (p >= bp + 3 && lowc(p[-3]) == 'i') { /* "ies" */
3025 if (!BSTRCMPI(bp, p - 7, "cookies")
3026 || !BSTRCMPI(bp, p - 4, "pies")
3027 || !BSTRCMPI(bp, p - 5, "mbies") /* zombie */
3028 || !BSTRCMPI(bp, p - 5, "yries")) /* valkyrie */
3030 Strcasecpy(p - 3, "y"); /* ies -> y */
3033 /* wolves, but f to ves isn't fully reversible */
3034 if (p - 4 >= bp && (index("lr", lowc(*(p - 4)))
3035 || index(vowels, lowc(*(p - 4))))
3036 && !BSTRCMPI(bp, p - 3, "ves")) {
3037 if (!BSTRCMPI(bp, p - 6, "cloves")
3038 || !BSTRCMPI(bp, p - 6, "nerves"))
3040 Strcasecpy(p - 3, "f"); /* ves -> f */
3043 /* note: nurses, axes but boxes, wumpuses */
3044 if (!BSTRCMPI(bp, p - 4, "eses")
3045 || !BSTRCMPI(bp, p - 4, "oxes") /* boxes, foxes */
3046 || !BSTRCMPI(bp, p - 4, "nxes") /* lynxes */
3047 || !BSTRCMPI(bp, p - 4, "ches")
3048 || !BSTRCMPI(bp, p - 4, "uses") /* lotuses */
3049 || !BSTRCMPI(bp, p - 4, "sses") /* priestesses */
3050 || !BSTRCMPI(bp, p - 5, "atoes") /* tomatoes */
3051 || !BSTRCMPI(bp, p - 7, "dingoes")
3052 || !BSTRCMPI(bp, p - 7, "Aleaxes")) {
3053 *(p - 2) = '\0'; /* drop es */
3055 } /* else fall through to mins */
3057 /* ends in 's' but not 'es' */
3058 } else if (!BSTRCMPI(bp, p - 2, "us")) { /* lotus, fungus... */
3059 if (BSTRCMPI(bp, p - 6, "tengus") /* but not these... */
3060 && BSTRCMPI(bp, p - 7, "hezrous"))
3062 } else if (!BSTRCMPI(bp, p - 2, "ss")
3063 || !BSTRCMPI(bp, p - 5, " lens")
3064 || (p - 4 == bp && !strcmpi(p - 4, "lens"))) {
3068 *(p - 1) = '\0'; /* drop s */
3070 } else { /* input doesn't end in 's' */
3072 if (!BSTRCMPI(bp, p - 3, "men")
3073 && !badman(bp, FALSE)) {
3074 Strcasecpy(p - 2, "an");
3077 /* matzot -> matzo, algae -> alga */
3078 if (!BSTRCMPI(bp, p - 6, "matzot") || !BSTRCMPI(bp, p - 2, "ae")) {
3079 *(p - 1) = '\0'; /* drop t/e */
3082 /* balactheria -> balactherium */
3083 if (p - 4 >= bp && !strcmpi(p - 2, "ia")
3084 && index("lr", lowc(*(p - 3))) && lowc(*(p - 4)) == 'e') {
3085 Strcasecpy(p - 1, "um"); /* a -> um */
3088 /* here we cannot find the plural suffix */
3092 /* if we stripped off a suffix (" of bar" from "foo of bar"),
3093 put it back now [strcat() isn't actually 100% safe here...] */
3098 #else /*JP*//*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
3099 char *str = nextobuf();
3100 Strcpy(str, oldstr);
3106 badman(basestr, to_plural)
3107 const char *basestr;
3108 boolean to_plural; /* true => makeplural, false => makesingular */
3111 char *endstr, *spot;
3112 /* these are all the prefixes for *man that don't have a *men plural */
3113 const char *no_men[] = {
3114 "albu", "antihu", "anti", "ata", "auto", "bildungsro", "cai", "cay",
3115 "ceru", "corner", "decu", "des", "dura", "fir", "hanu", "het",
3116 "infrahu", "inhu", "nonhu", "otto", "out", "prehu", "protohu",
3117 "subhu", "superhu", "talis", "unhu", "sha",
3118 "hu", "un", "le", "re", "so", "to", "at", "a",
3120 /* these are all the prefixes for *men that don't have a *man singular */
3121 const char *no_man[] = {
3122 "abdo", "acu", "agno", "ceru", "cogno", "cycla", "fleh", "grava",
3123 "hegu", "preno", "sonar", "speci", "dai", "exa", "fla", "sta", "teg",
3124 "tegu", "vela", "da", "hy", "lu", "no", "nu", "ra", "ru", "se", "vi", "ya",
3128 if (!basestr || strlen(basestr) < 4)
3131 endstr = eos((char *)basestr);
3134 for (i = 0; i < SIZE(no_men); i++) {
3135 al = (int) strlen(no_men[i]);
3136 spot = endstr - (al + 3);
3137 if (!BSTRNCMPI(basestr, spot, no_men[i], al)
3138 && (spot == basestr || *(spot - 1) == ' '))
3142 for (i = 0; i < SIZE(no_man); i++) {
3143 al = (int) strlen(no_man[i]);
3144 spot = endstr - (al + 3);
3145 if (!BSTRNCMPI(basestr, spot, no_man[i], al)
3146 && (spot == basestr || *(spot - 1) == ' '))
3153 /* compare user string against object name string using fuzzy matching */
3155 wishymatch(u_str, o_str, retry_inverted)
3156 const char *u_str; /* from user, so might be variant spelling */
3157 const char *o_str; /* from objects[], so is in canonical form */
3158 boolean retry_inverted; /* optional extra "of" handling */
3160 static NEARDATA const char detect_SP[] = "detect ",
3161 SP_detection[] = " detection";
3162 char *p, buf[BUFSZ];
3164 /* ignore spaces & hyphens and upper/lower case when comparing */
3165 if (fuzzymatch(u_str, o_str, " -", TRUE))
3168 if (retry_inverted) {
3169 const char *u_of, *o_of;
3171 /* when just one of the strings is in the form "foo of bar",
3172 convert it into "bar foo" and perform another comparison */
3173 u_of = strstri(u_str, " of ");
3174 o_of = strstri(o_str, " of ");
3175 if (u_of && !o_of) {
3176 Strcpy(buf, u_of + 4);
3177 p = eos(strcat(buf, " "));
3178 while (u_str < u_of)
3181 return fuzzymatch(buf, o_str, " -", TRUE);
3182 } else if (o_of && !u_of) {
3183 Strcpy(buf, o_of + 4);
3184 p = eos(strcat(buf, " "));
3185 while (o_str < o_of)
3188 return fuzzymatch(u_str, buf, " -", TRUE);
3192 /* [note: if something like "elven speed boots" ever gets added, these
3193 special cases should be changed to call wishymatch() recursively in
3194 order to get the "of" inversion handling] */
3195 if (!strncmp(o_str, "dwarvish ", 9)) {
3196 if (!strncmpi(u_str, "dwarven ", 8))
3197 return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
3198 } else if (!strncmp(o_str, "elven ", 6)) {
3199 if (!strncmpi(u_str, "elvish ", 7))
3200 return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
3201 else if (!strncmpi(u_str, "elfin ", 6))
3202 return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
3203 } else if (!strncmp(o_str, detect_SP, sizeof detect_SP - 1)) {
3204 /* check for "detect <foo>" vs "<foo> detection" */
3205 if ((p = strstri(u_str, SP_detection)) != 0
3206 && !*(p + sizeof SP_detection - 1)) {
3207 /* convert "<foo> detection" into "detect <foo>" */
3209 Strcat(strcpy(buf, detect_SP), u_str);
3210 /* "detect monster" -> "detect monsters" */
3211 if (!strcmpi(u_str, "monster"))
3214 return fuzzymatch(buf, o_str, " -", TRUE);
3216 } else if (strstri(o_str, SP_detection)) {
3217 /* and the inverse, "<foo> detection" vs "detect <foo>" */
3218 if (!strncmpi(u_str, detect_SP, sizeof detect_SP - 1)) {
3219 /* convert "detect <foo>s" into "<foo> detection" */
3220 p = makesingular(u_str + sizeof detect_SP - 1);
3221 Strcat(strcpy(buf, p), SP_detection);
3222 /* caller may be looping through objects[], so avoid
3223 churning through all the obufs */
3225 return fuzzymatch(buf, o_str, " -", TRUE);
3227 } else if (strstri(o_str, "ability")) {
3228 /* when presented with "foo of bar", makesingular() used to
3229 singularize both foo & bar, but now only does so for foo */
3230 /* catch "{potion(s),ring} of {gain,restore,sustain} abilities" */
3231 if ((p = strstri(u_str, "abilities")) != 0
3232 && !*(p + sizeof "abilities" - 1)) {
3233 (void) strncpy(buf, u_str, (unsigned) (p - u_str));
3234 Strcpy(buf + (p - u_str), "ability");
3235 return fuzzymatch(buf, o_str, " -", TRUE);
3237 } else if (!strcmp(o_str, "aluminum")) {
3238 /* this special case doesn't really fit anywhere else... */
3239 /* (note that " wand" will have been stripped off by now) */
3240 if (!strcmpi(u_str, "aluminium"))
3241 return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
3248 const char *name, oclass;
3249 int f_o_range, l_o_range;
3252 /* wishable subranges of objects */
3253 STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
3254 { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
3255 { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
3256 { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
3257 { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
3258 { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
3259 { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
3260 { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
3261 { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3262 { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3263 { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
3264 { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
3265 { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
3266 { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
3267 { "dragon scales", ARMOR_CLASS, GRAY_DRAGON_SCALES,
3268 YELLOW_DRAGON_SCALES },
3269 { "dragon scale mail", ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL,
3270 YELLOW_DRAGON_SCALE_MAIL },
3271 { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
3272 { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
3273 { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
3274 { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
3278 #if 0 /*JP*//*not used*/
3279 /* alternate spellings; if the difference is only the presence or
3280 absence of spaces and/or hyphens (such as "pickaxe" vs "pick axe"
3281 vs "pick-axe") then there is no need for inclusion in this list;
3282 likewise for ``"of" inversions'' ("boots of speed" vs "speed boots") */
3283 struct alt_spellings {
3287 { "pickax", PICK_AXE },
3288 { "whip", BULLWHIP },
3289 { "saber", SILVER_SABER },
3290 { "silver sabre", SILVER_SABER },
3291 { "smooth shield", SHIELD_OF_REFLECTION },
3292 { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
3293 { "grey dragon scales", GRAY_DRAGON_SCALES },
3294 { "iron ball", HEAVY_IRON_BALL },
3295 { "lantern", BRASS_LANTERN },
3296 { "mattock", DWARVISH_MATTOCK },
3297 { "amulet of poison resistance", AMULET_VERSUS_POISON },
3298 { "potion of sleep", POT_SLEEPING },
3300 { "camera", EXPENSIVE_CAMERA },
3301 { "tee shirt", T_SHIRT },
3303 { "can opener", TIN_OPENER },
3304 { "kelp", KELP_FROND },
3305 { "eucalyptus", EUCALYPTUS_LEAF },
3306 { "royal jelly", LUMP_OF_ROYAL_JELLY },
3307 { "lembas", LEMBAS_WAFER },
3308 { "marker", MAGIC_MARKER },
3309 { "hook", GRAPPLING_HOOK },
3310 { "grappling iron", GRAPPLING_HOOK },
3311 { "grapnel", GRAPPLING_HOOK },
3312 { "grapple", GRAPPLING_HOOK },
3313 { "protection from shape shifters", RIN_PROTECTION_FROM_SHAPE_CHAN },
3314 /* if we ever add other sizes, move this to o_ranges[] with "bag" */
3315 { "box", LARGE_BOX },
3316 /* normally we wouldn't have to worry about unnecessary <space>, but
3317 " stone" will get stripped off, preventing a wishymatch; that actually
3318 lets "flint stone" be a match, so we also accept bogus "flintstone" */
3319 { "luck stone", LUCKSTONE },
3320 { "load stone", LOADSTONE },
3321 { "touch stone", TOUCHSTONE },
3322 { "flintstone", FLINT },
3323 { (const char *) 0, 0 },
3328 rnd_otyp_by_wpnskill(skill)
3332 short otyp = STRANGE_OBJECT;
3333 for (i = bases[WEAPON_CLASS];
3334 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3335 if (objects[i].oc_skill == skill) {
3341 for (i = bases[WEAPON_CLASS];
3342 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3343 if (objects[i].oc_skill == skill)
3351 rnd_otyp_by_namedesc(name, oclass)
3356 short validobjs[NUM_OBJECTS];
3357 register const char *zn;
3361 return STRANGE_OBJECT;
3363 memset((genericptr_t) validobjs, 0, sizeof(validobjs));
3365 for (i = oclass ? bases[(int)oclass] : STRANGE_OBJECT + 1;
3366 i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
3368 /* don't match extra descriptions (w/o real name) */
3369 if ((zn = OBJ_NAME(objects[i])) == 0)
3373 *
\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É
3374 *
\82È
\82ç
\82È
\82¢
\82æ
\82¤
\82É
\82·
\82é
\81B
3375 *
\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
3377 if (i == FAKE_AMULET_OF_YENDOR)
3380 if (wishymatch(name, zn, TRUE)
3381 || ((zn = OBJ_DESCR(objects[i])) != 0
3382 && wishymatch(name, zn, FALSE))
3383 || ((zn = objects[i].oc_uname) != 0
3384 && wishymatch(name, zn, FALSE))) {
3385 validobjs[n++] = (short) i;
3386 maxprob += (objects[i].oc_prob + 1);
3390 if (n > 0 && maxprob) {
3391 long prob = rn2(maxprob);
3395 && (prob -= (objects[validobjs[i]].oc_prob + 1)) >= 0)
3397 return validobjs[i];
3399 return STRANGE_OBJECT;
3403 * Return something wished for. Specifying a null pointer for
3404 * the user request string results in a random object. Otherwise,
3405 * if asking explicitly for "nothing" (or "nil") return no_wish;
3406 * if not an object return &zeroobj; if an error (no matching object),
3411 readobjnam(bp, no_wish)
3413 struct obj *no_wish;
3417 register struct obj *otmp;
3418 int cnt, spe, spesgn, typ, very, rechrg;
3419 int blessed, uncursed, iscursed, ispoisoned, isgreased;
3420 int eroded, eroded2, erodeproof, locked, unlocked, broken;
3421 int halfeaten, mntmp, contents;
3422 int islit, unlabeled, ishistoric, isdiluted, trapped;
3424 int tmp, tinv, tvariety;
3428 int wetness, gsize = 0;
3430 int ftype = context.current_fruit;
3431 char fruitbuf[BUFSZ];
3432 /* Fruits may not mess up the ability to wish for real objects (since
3433 * you can leave a fruit in a bones file and it will be added to
3434 * another person's game), so they must be checked for last, after
3435 * stripping all the possible prefixes and seeing if there's a real
3436 * name in there. So we have to save the full original name. However,
3437 * it's still possible to do things like "uncursed burnt Alaska",
3438 * or worse yet, "2 burned 5 course meals", so we need to loop to
3439 * strip off the prefixes again, this time stripping only the ones
3441 * We could get even more detailed so as to allow food names with
3442 * prefixes that _are_ possible on food, so you could wish for
3443 * "2 3 alarm chilis". Currently this isn't allowed; options.c
3444 * automatically sticks 'candied' in front of such names.
3447 char *un, *dn, *actualn, *origbp = bp;
3448 const char *name = 0;
3450 cnt = spe = spesgn = typ = 0;
3451 very = rechrg = blessed = uncursed = iscursed = ispoisoned =
3452 isgreased = eroded = eroded2 = erodeproof = halfeaten =
3453 islit = unlabeled = ishistoric = isdiluted = trapped =
3454 locked = unlocked = broken = 0;
3455 tvariety = RANDOM_TIN;
3460 contents = UNDEFINED;
3462 actualn = dn = un = 0;
3467 /* first, remove extra whitespace they may have typed */
3468 (void) mungspaces(bp);
3469 /* allow wishing for "nothing" to preserve wishless conduct...
3470 [now requires "wand of nothing" if that's what was really wanted] */
3472 if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil")
3473 || !strcmpi(bp, "none"))
3475 if (!strcmpi(bp, "
\82È
\82µ") || !strcmpi(bp, "
\96³
\82µ"))
3478 /* save the [nearly] unmodified choice string */
3479 Strcpy(fruitbuf, bp);
3486 if (!strncmpi(bp, "an ", l = 3) || !strncmpi(bp, "a ", l = 2)) {
3488 } else if (!strncmpi(bp, "the ", l = 4)) {
3489 ; /* just increment `bp' by `l' below */
3490 } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
3497 } else if (*bp == '+' || *bp == '-') {
3498 spesgn = (*bp++ == '+') ? 1 : -1;
3506 } else if (!strncmpi(bp, "blessed ", l = 8)
3507 || !strncmpi(bp, "holy ", l = 5)) {
3509 } else if (!strncmpi(bp, "
\8fj
\95\9f\82³
\82ê
\82½", l = 10)) {
3513 } else if (!strncmpi(bp, "moist ", l = 6)
3514 || !strncmpi(bp, "wet ", l = 4)) {
3516 } else if (!strncmpi(bp, "
\8e¼
\82Á
\82½", l = 6)
3517 || !strncmpi(bp, "
\94G
\82ê
\82½", l = 6)) {
3520 if (!strncmpi(bp, "wet ", 4))
3522 if (!strncmpi(bp, "
\94G
\82ê
\82½", 4))
3524 wetness = rn2(3) + 3;
3528 } else if (!strncmpi(bp, "cursed ", l = 7)
3529 || !strncmpi(bp, "unholy ", l = 7)) {
3531 } else if (!strncmpi(bp, "
\8eô
\82í
\82ê
\82½", l = 8)) {
3535 } else if (!strncmpi(bp, "uncursed ", l = 9)) {
3537 } else if (!strncmpi(bp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢", l = 9)) {
3541 } else if (!strncmpi(bp, "rustproof ", l = 10)
3542 || !strncmpi(bp, "erodeproof ", l = 11)
3543 || !strncmpi(bp, "corrodeproof ", l = 13)
3544 || !strncmpi(bp, "fixed ", l = 6)
3545 || !strncmpi(bp, "fireproof ", l = 10)
3546 || !strncmpi(bp, "rotproof ", l = 9)) {
3548 } else if (!strncmpi(bp, "
\8eK
\82Ñ
\82È
\82¢", l = 8)
3549 || !strncmpi(bp, "
\95\85\90H
\82µ
\82È
\82¢", l = 10)
3550 || !strncmpi(bp, "
\88À
\92è
\82µ
\82½", l = 8)
3551 || !strncmpi(bp, "
\94R
\82¦
\82È
\82¢", l = 8)) {
3554 } else if (!strncmpi(bp, "lit ", l = 4)
3555 || !strncmpi(bp, "burning ", l = 8)) {
3557 } else if (!strncmpi(bp, "unlit ", l = 6)
3558 || !strncmpi(bp, "extinguished ", l = 13)) {
3560 /* "unlabeled" and "blank" are synonymous */
3561 } else if (!strncmpi(bp, "unlabeled ", l = 10)
3562 || !strncmpi(bp, "unlabelled ", l = 11)
3563 || !strncmpi(bp, "blank ", l = 6)) {
3565 } else if (!strncmpi(bp, "poisoned ", l = 9)) {
3567 /* "trapped" recognized but not honored outside wizard mode */
3568 } else if (!strncmpi(bp, "trapped ", l = 8)) {
3569 trapped = 0; /* undo any previous "untrapped" */
3572 } else if (!strncmpi(bp, "untrapped ", l = 10)) {
3573 trapped = 2; /* not trapped */
3574 /* locked, unlocked, broken: box/chest lock states */
3575 } else if (!strncmpi(bp, "locked ", l = 7)) {
3576 locked = 1, unlocked = broken = 0;
3577 } else if (!strncmpi(bp, "unlocked ", l = 9)) {
3578 unlocked = 1, locked = broken = 0;
3579 } else if (!strncmpi(bp, "broken ", l = 7)) {
3580 broken = 1, locked = unlocked = 0;
3581 } else if (!strncmpi(bp, "greased ", l = 8)) {
3583 } else if (!strncmpi(bp, "very ", l = 5)) {
3584 /* very rusted very heavy iron ball */
3586 } else if (!strncmpi(bp, "thoroughly ", l = 11)) {
3588 } else if (!strncmpi(bp, "rusty ", l = 6)
3589 || !strncmpi(bp, "rusted ", l = 7)
3590 || !strncmpi(bp, "burnt ", l = 6)
3591 || !strncmpi(bp, "burned ", l = 7)) {
3594 } else if (!strncmpi(bp, "corroded ", l = 9)
3595 || !strncmpi(bp, "rotted ", l = 7)) {
3598 } else if (!strncmpi(bp, "partly eaten ", l = 13)
3599 || !strncmpi(bp, "partially eaten ", l = 16)) {
3601 } else if (!strncmpi(bp, "historic ", l = 9)) {
3603 } else if (!strncmpi(bp, "diluted ", l = 8)) {
3605 } else if (!strncmpi(bp, "empty ", l = 6)) {
3607 } else if (!strncmpi(bp, "small ", l = 6)) { /* glob sizes */
3609 } else if (!strncmpi(bp, "medium ", l = 7)) {
3610 /* xname() doesn't display "medium" but without this
3611 there'd be no way to ask for the intermediate size */
3613 } else if (!strncmpi(bp, "large ", l = 6)) {
3614 /* "very large " had "very " peeled off on previous iteration */
3615 gsize = (very != 1) ? 3 : 4;
3621 cnt = 1; /* %% what with "gems" etc. ? */
3622 if (strlen(bp) > 1 && (p = rindex(bp, '(')) != 0) {
3623 boolean keeptrailingchars = TRUE;
3625 p[(p > bp && p[-1] == ' ') ? -1 : 0] = '\0'; /*terminate bp */
3626 ++p; /* advance past '(' */
3627 if (!strncmpi(p, "lit)", 4)) {
3629 p += 4 - 1; /* point at ')' */
3643 /* mis-matched parentheses; rest of string will be ignored
3644 * [probably we should restore everything back to '('
3645 * instead since it might be part of "named ..."]
3647 keeptrailingchars = FALSE;
3652 if (keeptrailingchars) {
3655 /* 'pp' points at 'pb's terminating '\0',
3656 'p' points at ')' and will be incremented past it */
3663 * otmp->spe is type schar, so we don't want spe to be any bigger or
3664 * smaller. Also, spe should always be positive --some cheaters may
3665 * try to confuse atoi().
3668 spesgn = -1; /* cheaters get what they deserve */
3671 if (spe > SCHAR_LIM)
3673 if (rechrg < 0 || rechrg > 7)
3674 rechrg = 7; /* recharge_limit */
3676 /* now we have the actual name, as delivered by xname, say
3677 * green potions called whisky
3678 * scrolls labeled "QWERTY"
3681 * very heavy iron ball named hoei
3685 if ((p = strstri(bp, " named ")) != 0) {
3689 if ((p = strstri(bp, " called ")) != 0) {
3692 /* "helmet called telepathy" is not "helmet" (a specific type)
3693 * "shield called reflection" is not "shield" (a general type)
3695 for (i = 0; i < SIZE(o_ranges); i++)
3696 if (!strcmpi(bp, o_ranges[i].name)) {
3697 oclass = o_ranges[i].oclass;
3701 if ((p = strstri(bp, " labeled ")) != 0) {
3704 } else if ((p = strstri(bp, " labelled ")) != 0) {
3708 if ((p = strstri(bp, " of spinach")) != 0) {
3713 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8f\88\97\9d\82µ
\82È
\82¢*/
3715 * Skip over "pair of ", "pairs of", "set of" and "sets of".
3717 * Accept "3 pair of boots" as well as "3 pairs of boots". It is
3718 * valid English either way. See makeplural() for more on pair/pairs.
3720 * We should only double count if the object in question is not
3721 * referred to as a "pair of". E.g. We should double if the player
3722 * types "pair of spears", but not if the player types "pair of
3723 * lenses". Luckily (?) all objects that are referred to as pairs
3724 * -- boots, gloves, and lenses -- are also not mergable, so cnt is
3727 if (!strncmpi(bp, "pair of ", 8)) {
3730 } else if (!strncmpi(bp, "pairs of ", 9)) {
3734 } else if (!strncmpi(bp, "set of ", 7)) {
3736 } else if (!strncmpi(bp, "sets of ", 8)) {
3742 /* intercept pudding globs here; they're a valid wish target,
3743 * but we need them to not get treated like a corpse.
3745 * also don't let player wish for multiple globs.
3747 if ((p = strstri(bp, "glob of ")) != 0
3748 || (p = strstri(bp, "globs of ")) != 0) {
3749 int globoffset = (*(p + 4) == 's') ? 9 : 8;
3751 if ((mntmp = name_to_mon(p + globoffset)) >= PM_GRAY_OOZE
3752 && mntmp <= PM_BLACK_PUDDING) {
3753 mntmp = NON_PM; /* lie to ourselves */
3754 cnt = 0; /* force only one */
3758 * Find corpse type using "of" (figurine of an orc, tin of orc meat)
3759 * Don't check if it's a wand or spellbook.
3760 * (avoid "wand/finger of death" confusion).
3762 if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
3763 && !strstri(bp, "finger ")) {
3764 if ((p = strstri(bp, "tin of ")) != 0) {
3765 if (!strcmpi(p + 7, "spinach")) {
3769 tmp = tin_variety_txt(p + 7, &tinv);
3771 mntmp = name_to_mon(p + 7 + tmp);
3775 } else if ((p = strstri(bp, " of ")) != 0
3776 && (mntmp = name_to_mon(p + 4)) >= LOW_PM)
3780 /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
3781 if (strncmpi(bp, "samurai sword", 13) /* not the "samurai" monster! */
3782 && strncmpi(bp, "wizard lock", 11) /* not the "wizard" monster! */
3783 && strncmpi(bp, "ninja-to", 8) /* not the "ninja" rank */
3784 && strncmpi(bp, "master key", 10) /* not the "master" rank */
3785 && strncmpi(bp, "magenta", 7)) { /* not the "mage" rank */
3786 if (mntmp < LOW_PM && strlen(bp) > 2
3787 && (mntmp = name_to_mon(bp)) >= LOW_PM) {
3788 int mntmptoo, mntmplen; /* double check for rank title */
3791 mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
3792 bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname)
3796 } else if (!strncmpi(bp, "s ", 2)) {
3798 } else if (!strncmpi(bp, "es ", 3)) {
3800 } else if (!*bp && !actualn && !dn && !un && !oclass) {
3801 /* no referent; they don't really mean a monster type */
3807 #else /*JP:
\81u(
\89ö
\95¨
\96¼)
\82Ì(
\83A
\83C
\83e
\83\80)
\81v
\91Î
\89\9e */
3809 if ((mntmp = name_to_mon(bp)) >= LOW_PM) {
3810 const char *mp = mons[mntmp].mname;
3811 bp = strstri(bp, mp) + strlen(mp) + 2;
3816 #if 0 /*JP*//*
\92P
\90\94\89»
\82Í
\82µ
\82È
\82¢*/
3817 /* first change to singular if necessary */
3819 char *sng = makesingular(bp);
3820 if (strcmp(bp, sng)) {
3828 #if 0 /*JP*//*
\83X
\83y
\83\8b\97h
\82ê
\8f\88\97\9d\82Í
\82µ
\82È
\82¢*/
3829 /* Alternate spellings (pick-ax, silver sabre, &c) */
3831 struct alt_spellings *as = spellings;
3834 if (fuzzymatch(bp, as->sp, " -", TRUE)) {
3840 /* can't use spellings list for this one due to shuffling */
3841 if (!strncmpi(bp, "grey spell", 10))
3844 if ((p = strstri(bp, "armour")) != 0) {
3845 /* skip past "armo", then copy remainder beyond "u" */
3847 while ((*p = *(p + 1)) != '\0')
3848 ++p; /* self terminating */
3854 /* dragon scales - assumes order of dragons */
3855 if (!strcmpi(bp, "scales") && mntmp >= PM_GRAY_DRAGON
3856 && mntmp <= PM_YELLOW_DRAGON) {
3857 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
3858 mntmp = NON_PM; /* no monster */
3862 /*JP:
\81u
\97Ø
\8aZ
\81v
\82ð
\90æ
\82É
\8f\88\97\9d\82µ
\82Ä
\82¨
\82 */
3863 if (!strcmpi(bp, "
\97Ø
\8aZ") && mntmp >= PM_GRAY_DRAGON
3864 && mntmp <= PM_YELLOW_DRAGON) {
3865 typ = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
3866 mntmp = NON_PM; /* no monster */
3870 if (!strcmpi(bp, "
\97Ø") && mntmp >= PM_GRAY_DRAGON
3871 && mntmp <= PM_YELLOW_DRAGON) {
3872 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
3873 mntmp = NON_PM; /* no monster */
3880 if (!BSTRCMPI(bp, p - 10, "holy water")) {
3882 if ((p - bp) >= 12 && *(p - 12) == 'u')
3883 iscursed = 1; /* unholy water */
3888 #else /*JP:
\90¹
\90\85\82Æ
\95s
\8fò
\82È
\90\85\82ð
\95Ê
\82É
\94»
\92è*/
3889 if (!BSTRCMPI(bp, p - 4, "
\90¹
\90\85")) {
3894 if (!BSTRCMPI(bp, p - 4, "
\95s
\8fò
\82È
\90\85")) {
3901 if (unlabeled && !BSTRCMPI(bp, p - 6, "scroll")) {
3903 if (unlabeled && !BSTRCMPI(bp, p - 4, "
\8aª
\95¨")) {
3905 typ = SCR_BLANK_PAPER;
3909 if (unlabeled && !BSTRCMPI(bp, p - 9, "spellbook")) {
3911 if (unlabeled && !BSTRCMPI(bp, p - 6, "
\96\82\96@
\8f\91")) {
3913 typ = SPE_BLANK_PAPER;
3917 * NOTE: Gold pieces are handled as objects nowadays, and therefore
3918 * this section should probably be reconsidered as well as the entire
3919 * gold/money concept. Maybe we want to add other monetary units as
3920 * well in the future. (TH)
3923 if (!BSTRCMPI(bp, p - 10, "gold piece")
3924 || !BSTRCMPI(bp, p - 7, "zorkmid")
3925 || !strcmpi(bp, "gold") || !strcmpi(bp, "money")
3926 || !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
3928 if (!BSTRCMPI(bp, p - 4, "
\8bà
\89Ý") || !BSTRCMPI(bp, p - 8, "
\83S
\81[
\83\8b\83h")
3929 || *bp == GOLD_SYM) {
3931 if (cnt > 5000 && !wizard)
3935 otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
3936 otmp->quan = (long) cnt;
3937 otmp->owt = weight(otmp);
3942 /* check for single character object class code ("/" for wand, &c) */
3943 if (strlen(bp) == 1 && (i = def_char_to_objclass(*bp)) < MAXOCLASSES
3944 && i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) {
3951 \89p
\8cê
\82È
\82ç XXXXX potion
\82Í
\95s
\8am
\92è
\96¼
\81Apotion of XXXXX
\82Í
\8am
\92è
\96¼
\82Æ
\82¢
\82¤
3952 \8bæ
\95Ê
\82ª
\95t
\82
\82ª
\81A
\93ú
\96{
\8cê
\82Å
\82Í
\82Ç
\82¿
\82ç
\82à
\81uXXXXX
\82Ì
\96ò
\81v
\82È
\82Ì
\82Å
\82±
\82±
\82Å
\82Í
\94»
\95Ê
\82µ
\82È
\82¢
3954 /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */
3955 /* false hits on, e.g., rings for "ring mail". */
3956 if (strncmpi(bp, "enchant ", 8)
3957 && strncmpi(bp, "destroy ", 8)
3958 && strncmpi(bp, "detect food", 11)
3959 && strncmpi(bp, "food detection", 14)
3960 && strncmpi(bp, "ring mail", 9)
3961 && strncmpi(bp, "studded leather armor", 21)
3962 && strncmpi(bp, "leather armor", 13)
3963 && strncmpi(bp, "tooled horn", 11)
3964 && strncmpi(bp, "food ration", 11)
3965 && strncmpi(bp, "meat ring", 9))
3966 for (i = 0; i < (int) (sizeof wrpsym); i++) {
3967 register int j = strlen(wrp[i]);
3969 if (!strncmpi(bp, wrp[i], j)) {
3971 if (oclass != AMULET_CLASS) {
3973 if (!strncmpi(bp, " of ", 4))
3975 /* else if(*bp) ?? */
3980 if (!BSTRCMPI(bp, p - j, wrp[i])) {
3984 if (p > bp && p[-1] == ' ')
3992 /* Wishing in wizard mode can create traps and furniture.
3993 * Part I: distinguish between trap and object for the two
3994 * types of traps which have corresponding objects: bear trap
3995 * and land mine. "beartrap" (object) and "bear trap" (trap)
3996 * have a difference in spelling which we used to exploit by
3997 * adding a special case in wishymatch(), but "land mine" is
3998 * spelled the same either way so needs different handing.
3999 * Since we need something else for land mine, we've dropped
4000 * the bear trap hack so that both are handled exactly the
4001 * same. To get an armed trap instead of a disarmed object,
4002 * the player can prefix either the object name or the trap
4003 * name with "trapped " (which ordinarily applies to chests
4004 * and tins), or append something--anything at all except for
4005 * " object", but " trap" is suggested--to either the trap
4006 * name or the object name.
4008 if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) {
4009 boolean beartrap = (lowc(*bp) == 'b');
4010 char *zp = bp + 4; /* skip "bear"/"land" */
4013 ++zp; /* embedded space is optional */
4014 if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) {
4016 if (trapped == 2 || !strcmpi(zp, " object")) {
4017 /* "untrapped <foo>" or "<foo> object" */
4018 typ = beartrap ? BEARTRAP : LAND_MINE;
4020 } else if (trapped == 1 || *zp != '\0') {
4021 /* "trapped <foo>" or "<foo> trap" (actually "<foo>*") */
4022 int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE);
4024 /* use canonical trap spelling, skip object matching */
4025 Strcpy(bp, defsyms[idx].explanation);
4028 /* [no prefix or suffix; we're going to end up matching
4029 the object name and getting a disarmed trap object] */
4034 /* "grey stone" check must be before general "stone" */
4035 for (i = 0; i < SIZE(o_ranges); i++)
4036 if (!strcmpi(bp, o_ranges[i].name)) {
4037 typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
4041 if (!BSTRCMPI(bp, p - 6, " stone") || !BSTRCMPI(bp, p - 4, " gem")) {
4042 p[!strcmpi(p - 4, " gem") ? -4 : -6] = '\0';
4046 } else if (!strcmpi(bp, "looking glass")) {
4047 ; /* avoid false hit on "* glass" */
4048 } else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
4049 register char *g = bp;
4051 /* treat "broken glass" as a non-existent item; since "broken" is
4052 also a chest/box prefix it might have been stripped off above */
4053 if (broken || strstri(g, "broken"))
4054 return (struct obj *) 0;
4055 if (!strncmpi(g, "worthless ", 10))
4057 if (!strncmpi(g, "piece of ", 9))
4059 if (!strncmpi(g, "colored ", 8))
4061 else if (!strncmpi(g, "coloured ", 9))
4063 if (!strcmpi(g, "glass")) { /* choose random color */
4064 /* 9 different kinds */
4065 typ = LAST_GEM + rnd(9);
4066 if (objects[typ].oc_class == GEM_CLASS)
4069 typ = 0; /* somebody changed objects[]? punt */
4070 } else { /* try to construct canonical form */
4073 Strcpy(tbuf, "worthless piece of ");
4074 Strcat(tbuf, g); /* assume it starts with the color */
4081 dn = actualn; /* ex. "skull cap" */
4083 /* check real names of gems first */
4084 if (!oclass && actualn) {
4085 for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
4086 register const char *zn;
4088 if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) {
4093 /* "tin of foo" would be caught above, but plain "tin" has
4094 a random chance of yielding "tin wand" unless we do this */
4095 if (!strcmpi(actualn, "tin")) {
4101 if (((typ = rnd_otyp_by_namedesc(actualn, oclass)) != STRANGE_OBJECT)
4102 || ((typ = rnd_otyp_by_namedesc(dn, oclass)) != STRANGE_OBJECT)
4103 || ((typ = rnd_otyp_by_namedesc(un, oclass)) != STRANGE_OBJECT)
4104 || ((typ = rnd_otyp_by_namedesc(origbp, oclass)) != STRANGE_OBJECT))
4109 struct Jitem *j = Japanese_items;
4112 if (actualn && !strcmpi(actualn, j->name)) {
4119 /* if we've stripped off "armor" and failed to match anything
4120 in objects[], append "mail" and try again to catch misnamed
4121 requests like "plate armor" and "yellow dragon scale armor" */
4122 if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) {
4123 /* modifying bp's string is ok; we're about to resort
4124 to random armor if this also fails to match anything */
4125 Strcat(bp, " mail");
4129 if (!strcmpi(bp, "spinach")) {
4131 if (!strcmp(bp, "
\83z
\83E
\83\8c\83\93\91\90")) {
4137 /* Note: not strcmpi. 2 fruits, one capital, one not, are possible.
4138 Also not strncmp. We used to ignore trailing text with it, but
4139 that resulted in "grapefruit" matching "grape" if the latter came
4140 earlier than the former in the fruit list. */
4144 int blessedf, iscursedf, uncursedf, halfeatenf;
4146 blessedf = iscursedf = uncursedf = halfeatenf = 0;
4153 if (!strncmpi(fp, "an ", l = 3) || !strncmpi(fp, "a ", l = 2)) {
4155 } else if (!cntf && digit(*fp)) {
4162 } else if (!strncmpi(fp, "blessed ", l = 8)) {
4164 } else if (!strncmpi(fp, "cursed ", l = 7)) {
4166 } else if (!strncmpi(fp, "uncursed ", l = 9)) {
4168 } else if (!strncmpi(fp, "partly eaten ", l = 13)
4169 || !strncmpi(fp, "partially eaten ", l = 16)) {
4176 for (f = ffruit; f; f = f->nextf) {
4177 /* match type: 0=none, 1=exact, 2=singular, 3=plural */
4180 if (!strcmp(fp, f->fname))
4182 else if (!strcmp(fp, makesingular(f->fname)))
4184 else if (!strcmp(fp, makeplural(f->fname)))
4189 iscursed = iscursedf;
4190 uncursed = uncursedf;
4191 halfeaten = halfeatenf;
4192 /* adjust count if user explicitly asked for
4193 singular amount (can't happen unless fruit
4194 has been given an already pluralized name)
4195 or for plural amount */
4196 if (ftyp == 2 && !cntf)
4198 else if (ftyp == 3 && !cntf)
4207 if (!oclass && actualn) {
4210 /* Perhaps it's an artifact specified by name, not type */
4211 name = artifact_name(actualn, &objtyp);
4217 /* Let wizards wish for traps and furniture.
4218 * Must come after objects check so wizards can still wish for
4219 * trap objects like beartraps.
4220 * Disallow such topology tweaks for WIZKIT startup wishes.
4223 if (wizard && !program_state.wizkit_wishing) {
4225 int trap, x = u.ux, y = u.uy;
4227 for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
4231 tname = defsyms[trap_to_defsym(trap)].explanation;
4232 if (strncmpi(tname, bp, strlen(tname)))
4234 /* found it; avoid stupid mistakes */
4235 if ((trap == TRAPDOOR || trap == HOLE) && !Can_fall_thru(&u.uz))
4237 if ((t = maketrap(x, y, trap)) != 0) {
4239 tname = defsyms[trap_to_defsym(trap)].explanation;
4240 pline("%s%s.", An(tname),
4241 (trap != MAGIC_PORTAL) ? "" : " to nowhere");
4243 pline("Creation of %s failed.", an(tname));
4247 /* furniture and terrain */
4250 if (!BSTRCMPI(bp, p - 8, "fountain")) {
4251 lev->typ = FOUNTAIN;
4252 level.flags.nfountains++;
4253 if (!strncmpi(bp, "magic ", 6))
4254 lev->blessedftn = 1;
4255 pline("A %sfountain.", lev->blessedftn ? "magic " : "");
4259 if (!BSTRCMPI(bp, p - 6, "throne")) {
4265 if (!BSTRCMPI(bp, p - 4, "sink")) {
4267 level.flags.nsinks++;
4272 /* ("water" matches "potion of water" rather than terrain) */
4273 if (!BSTRCMPI(bp, p - 4, "pool") || !BSTRCMPI(bp, p - 4, "moat")) {
4274 lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT;
4276 pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
4277 /* Must manually make kelp! */
4278 water_damage_chain(level.objects[x][y], TRUE);
4282 if (!BSTRCMPI(bp, p - 4, "lava")) { /* also matches "molten lava" */
4283 lev->typ = LAVAPOOL;
4285 pline("A pool of molten lava.");
4286 if (!(Levitation || Flying))
4287 (void) lava_effects();
4292 if (!BSTRCMPI(bp, p - 5, "altar")) {
4296 if (!strncmpi(bp, "chaotic ", 8))
4298 else if (!strncmpi(bp, "neutral ", 8))
4300 else if (!strncmpi(bp, "lawful ", 7))
4302 else if (!strncmpi(bp, "unaligned ", 10))
4304 else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
4305 al = (!rn2(6)) ? A_NONE : rn2((int) A_LAWFUL + 2) - 1;
4306 lev->altarmask = Align2amask(al);
4307 pline("%s altar.", An(align_str(al)));
4312 if (!BSTRCMPI(bp, p - 5, "grave")
4313 || !BSTRCMPI(bp, p - 9, "headstone")) {
4314 make_grave(x, y, (char *) 0);
4315 pline("%s.", IS_GRAVE(lev->typ) ? "A grave"
4316 : "Can't place a grave here");
4321 if (!BSTRCMPI(bp, p - 4, "tree")) {
4329 if (!BSTRCMPI(bp, p - 4, "bars")) {
4330 lev->typ = IRONBARS;
4331 pline("Iron bars.");
4337 if (!oclass && !typ) {
4338 if (!strncmpi(bp, "polearm", 7)) {
4339 typ = rnd_otyp_by_wpnskill(P_POLEARMS);
4341 } else if (!strncmpi(bp, "hammer", 6)) {
4342 typ = rnd_otyp_by_wpnskill(P_HAMMER);
4348 return ((struct obj *) 0);
4351 oclass = wrpsym[rn2((int) sizeof(wrpsym))];
4354 oclass = objects[typ].oc_class;
4356 /* handle some objects that are only allowed in wizard mode */
4357 if (typ && !wizard) {
4359 case AMULET_OF_YENDOR:
4360 typ = FAKE_AMULET_OF_YENDOR;
4362 case CANDELABRUM_OF_INVOCATION:
4363 typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
4365 case BELL_OF_OPENING:
4368 case SPE_BOOK_OF_THE_DEAD:
4369 typ = SPE_BLANK_PAPER;
4375 /* catch any other non-wishable objects (venom) */
4376 if (objects[typ].oc_nowish)
4377 return (struct obj *) 0;
4383 * Create the object, then fine-tune it.
4385 otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE);
4386 typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */
4388 if (islit && (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN
4389 || Is_candle(otmp) || typ == POT_OIL)) {
4390 place_object(otmp, u.ux, u.uy); /* make it viable light source */
4391 begin_burn(otmp, FALSE);
4392 obj_extract_self(otmp); /* now release it for caller's use */
4395 /* if player specified a reasonable count, maybe honor it */
4396 if (cnt > 0 && objects[typ].oc_merge
4397 && (wizard || cnt < rnd(6) || (cnt <= 7 && Is_candle(otmp))
4398 || (cnt <= 20 && ((oclass == WEAPON_CLASS && is_ammo(otmp))
4399 || typ == ROCK || is_missile(otmp)))))
4400 otmp->quan = (long) cnt;
4402 if (oclass == VENOM_CLASS)
4407 } else if (wizard) {
4408 ; /* no alteration to spe */
4409 } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS
4411 || (oclass == RING_CLASS && objects[typ].oc_charged)) {
4412 if (spe > rnd(5) && spe > otmp->spe)
4414 if (spe > 2 && Luck < 0)
4417 if (oclass == WAND_CLASS) {
4418 if (spe > 1 && spesgn == -1)
4421 if (spe > 0 && spesgn == -1)
4424 if (spe > otmp->spe)
4431 /* set otmp->spe. This may, or may not, use spe... */
4434 if (contents == EMPTY) {
4435 otmp->corpsenm = NON_PM;
4437 } else if (contents == SPINACH) {
4438 otmp->corpsenm = NON_PM;
4444 otmp->spe = wetness;
4452 case HEAVY_IRON_BALL:
4455 /* otmp->cobj already done in mksobj() */
4459 /* 0: delivered in-game via external event (or randomly for fake mail);
4460 1: from bones or wishing; 2: written with marker */
4466 otmp->spe = (rn2(10) ? -1 : 0);
4474 /* set otmp->corpsenm or dragon scale [mail] */
4475 if (mntmp >= LOW_PM) {
4476 if (mntmp == PM_LONG_WORM_TAIL)
4477 mntmp = PM_LONG_WORM;
4481 otmp->spe = 0; /* No spinach */
4482 if (dead_species(mntmp, FALSE)) {
4483 otmp->corpsenm = NON_PM; /* it's empty */
4484 } else if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4485 && !(mvitals[mntmp].mvflags & G_NOCORPSE)
4486 && mons[mntmp].cnutrit != 0) {
4487 otmp->corpsenm = mntmp;
4491 if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4492 && !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
4493 if (mons[mntmp].msound == MS_GUARDIAN)
4494 mntmp = genus(mntmp, 1);
4495 set_corpsenm(otmp, mntmp);
4499 mntmp = can_be_hatched(mntmp);
4500 /* this also sets hatch timer if appropriate */
4501 set_corpsenm(otmp, mntmp);
4504 if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
4506 && mntmp != PM_MAIL_DAEMON
4509 otmp->corpsenm = mntmp;
4512 otmp->corpsenm = mntmp;
4513 if (Has_contents(otmp) && verysmall(&mons[mntmp]))
4514 delete_contents(otmp); /* no spellbook */
4515 otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
4518 /* Dragon mail - depends on the order of objects & dragons. */
4519 if (mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON)
4520 otmp->otyp = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4525 /* set blessed/cursed -- setting the fields directly is safe
4526 * since weight() is called below and addinv() will take care
4530 } else if (uncursed) {
4532 otmp->cursed = (Luck < 0 && !wizard);
4533 } else if (blessed) {
4534 otmp->blessed = (Luck >= 0 || wizard);
4535 otmp->cursed = (Luck < 0 && !wizard);
4536 } else if (spesgn < 0) {
4540 /* set eroded and erodeproof */
4541 if (erosion_matters(otmp)) {
4542 if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
4543 otmp->oeroded = eroded;
4544 if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
4545 otmp->oeroded2 = eroded2;
4547 * 3.6.1: earlier versions included `&& !eroded && !eroded2' here,
4548 * but damageproof combined with damaged is feasible (eroded
4549 * armor modified by confused reading of cursed destroy armor)
4550 * so don't prevent player from wishing for such a combination.
4552 if (erodeproof && (is_damageable(otmp) || otmp->otyp == CRYSKNIFE))
4553 otmp->oerodeproof = (Luck >= 0 || wizard);
4556 /* set otmp->recharged */
4557 if (oclass == WAND_CLASS) {
4558 /* prevent wishing abuse */
4559 if (otmp->otyp == WAN_WISHING && !wizard)
4561 otmp->recharged = (unsigned) rechrg;
4566 if (is_poisonable(otmp))
4567 otmp->opoisoned = (Luck >= 0);
4568 else if (oclass == FOOD_CLASS)
4569 /* try to taint by making it as old as possible */
4572 /* and [un]trapped */
4574 if (Is_box(otmp) || typ == TIN)
4575 otmp->otrapped = (trapped == 1);
4577 /* empty for containers rather than for tins */
4578 if (contents == EMPTY) {
4579 if (otmp->otyp == BAG_OF_TRICKS || otmp->otyp == HORN_OF_PLENTY) {
4582 } else if (Has_contents(otmp)) {
4583 /* this assumes that artifacts can't be randomly generated
4584 inside containers */
4585 delete_contents(otmp);
4586 otmp->owt = weight(otmp);
4589 /* set locked/unlocked/broken */
4592 otmp->olocked = 1, otmp->obroken = 0;
4593 } else if (unlocked) {
4594 otmp->olocked = 0, otmp->obroken = 0;
4595 } else if (broken) {
4596 otmp->olocked = 0, otmp->obroken = 1;
4603 if (isdiluted && otmp->oclass == POTION_CLASS && otmp->otyp != POT_WATER)
4606 /* set tin variety */
4607 if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard))
4608 set_tin_variety(otmp, tvariety);
4614 /* an artifact name might need capitalization fixing */
4615 aname = artifact_name(name, &objtyp);
4616 if (aname && objtyp == otmp->otyp)
4619 /* 3.6 tribute - fix up novel */
4620 if (otmp->otyp == SPE_NOVEL) {
4621 const char *novelname;
4623 novelname = lookup_novel(name, &otmp->novelidx);
4628 otmp = oname(otmp, name);
4629 /* name==aname => wished for artifact (otmp->oartifact => got it) */
4630 if (otmp->oartifact || name == aname) {
4632 u.uconduct.wisharti++; /* KMH, conduct */
4636 /* more wishing abuse: don't allow wishing for certain artifacts */
4637 /* and make them pay; charge them for the wish anyway! */
4638 if ((is_quest_artifact(otmp)
4639 || (otmp->oartifact && rn2(nartifact_exist()) > 1)) && !wizard) {
4640 artifact_exists(otmp, safe_oname(otmp), FALSE);
4641 obfree(otmp, (struct obj *) 0);
4644 pline("For a moment, you feel %s in your %s, but it disappears!",
4646 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",
4647 something, makeplural(body_part(HAND)));
4650 if (halfeaten && otmp->oclass == FOOD_CLASS) {
4651 if (otmp->otyp == CORPSE)
4652 otmp->oeaten = mons[otmp->corpsenm].cnutrit;
4654 otmp->oeaten = objects[otmp->otyp].oc_nutrition;
4655 /* (do this adjustment before setting up object's weight) */
4656 consume_oeaten(otmp, 1);
4658 otmp->owt = weight(otmp);
4659 if (very && otmp->otyp == HEAVY_IRON_BALL)
4660 otmp->owt += IRON_BALL_W_INCR;
4661 else if (gsize > 1 && otmp->globby)
4662 /* 0: unspecified => small; 1: small => keep default owt of 20;
4663 2: medium => 120; 3: large => 320; 4: very large => 520 */
4664 otmp->owt += 100 + (gsize - 2) * 200;
4670 rnd_class(first, last)
4677 for (i = first; i <= last; i++)
4678 sum += objects[i].oc_prob;
4679 if (!sum) /* all zero */
4680 return first + rn2(last - first + 1);
4682 for (i = first; i <= last; i++)
4683 if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
4688 STATIC_OVL const char *
4689 Japanese_item_name(i)
4692 struct Jitem *j = Japanese_items;
4699 return (const char *) 0;
4703 suit_simple_name(suit)
4706 const char *suitnm, *esuitp;
4708 if (Is_dragon_mail(suit))
4710 return "dragon mail"; /* <color> dragon scale mail */
4712 return "
\97Ø
\8aZ"; /* <color> dragon scale mail */
4714 else if (Is_dragon_scales(suit))
4716 return "dragon scales";
4719 suitnm = OBJ_NAME(objects[suit->otyp]);
4720 esuitp = eos((char *) suitnm);
4722 if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
4723 return "mail"; /* most suits fall into this category */
4725 if (strlen(suitnm) > 2 && !strcmp(esuitp - 2, "
\8aZ"))
4726 return "
\8aZ"; /* most suits fall into this category */
4729 else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
4730 return "jacket"; /* leather jacket */
4732 /* suit is lame but armor is ambiguous and body armor is absurd */
4740 cloak_simple_name(cloak)
4744 switch (cloak->otyp) {
4749 return "
\83\8d\81[
\83u";
4750 case MUMMY_WRAPPING:
4756 return (objects[cloak->otyp].oc_name_known && cloak->dknown)
4760 ? "
\83X
\83\82\83b
\83N"
4764 : "
\83G
\83v
\83\8d\83\93";
4772 return "
\83N
\83\8d\81[
\83N";
4775 /* helm vs hat for messages */
4777 helm_simple_name(helmet)
4781 * There is some wiggle room here; the result has been chosen
4782 * for consistency with the "protected by hard helmet" messages
4783 * given for various bonks on the head: headgear that provides
4784 * such protection is a "helm", that which doesn't is a "hat".
4786 * elven leather helm / leather hat -> hat
4787 * dwarvish iron helm / hard hat -> helm
4788 * The rest are completely straightforward:
4789 * fedora, cornuthaum, dunce cap -> hat
4790 * all other types of helmets -> helm
4793 return (helmet && !is_metallic(helmet)) ? "hat" : "helm";
4795 return (helmet && !is_metallic(helmet)) ? "
\96X
\8eq" : "
\8a\95";
4799 mimic_obj_name(mtmp)
4802 if (mtmp->m_ap_type == M_AP_OBJECT) {
4803 if (mtmp->mappearance == GOLD_PIECE)
4808 if (mtmp->mappearance != STRANGE_OBJECT)
4809 return simple_typename(mtmp->mappearance);
4812 return "whatcha-may-callit";
4814 return "
\89½
\82Æ
\82©
\82¢
\82¤
\82à
\82Ì";
4818 * Construct a query prompt string, based around an object name, which is
4819 * guaranteed to fit within [QBUFSZ]. Takes an optional prefix, three
4820 * choices for filling in the middle (two object formatting functions and a
4821 * last resort literal which should be very short), and an optional suffix.
4824 safe_qbuf(qbuf, qprefix, qsuffix, obj, func, altfunc, lastR)
4825 char *qbuf; /* output buffer */
4826 const char *qprefix, *qsuffix;
4828 char *FDECL((*func), (OBJ_P)), *FDECL((*altfunc), (OBJ_P));
4832 /* convert size_t (or int for ancient systems) to ordinary unsigned */
4833 unsigned len, lenlimit,
4834 len_qpfx = (unsigned) (qprefix ? strlen(qprefix) : 0),
4835 len_qsfx = (unsigned) (qsuffix ? strlen(qsuffix) : 0),
4836 len_lastR = (unsigned) strlen(lastR);
4838 lenlimit = QBUFSZ - 1;
4839 endp = qbuf + lenlimit;
4840 /* sanity check, aimed mainly at paniclog (it's conceivable for
4841 the result of short_oname() to be shorter than the length of
4842 the last resort string, but we ignore that possibility here) */
4843 if (len_qpfx > lenlimit)
4844 impossible("safe_qbuf: prefix too long (%u characters).", len_qpfx);
4845 else if (len_qpfx + len_qsfx > lenlimit)
4846 impossible("safe_qbuf: suffix too long (%u + %u characters).",
4847 len_qpfx, len_qsfx);
4848 else if (len_qpfx + len_lastR + len_qsfx > lenlimit)
4849 impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
4850 len_qpfx, len_lastR, len_qsfx);
4852 /* the output buffer might be the same as the prefix if caller
4853 has already partially filled it */
4854 if (qbuf == qprefix) {
4855 /* prefix is already in the buffer */
4857 } else if (qprefix) {
4858 /* put prefix into the buffer */
4859 (void) strncpy(qbuf, qprefix, lenlimit);
4862 /* no prefix; output buffer starts out empty */
4865 len = (unsigned) strlen(qbuf);
4867 if (len + len_lastR + len_qsfx > lenlimit) {
4868 /* too long; skip formatting, last resort output is truncated */
4869 if (len < lenlimit) {
4870 (void) strncpy(&qbuf[len], lastR, lenlimit - len);
4872 len = (unsigned) strlen(qbuf);
4873 if (qsuffix && len < lenlimit) {
4874 (void) strncpy(&qbuf[len], qsuffix, lenlimit - len);
4876 /* len = (unsigned) strlen(qbuf); */
4880 /* suffix and last resort are guaranteed to fit */
4881 len += len_qsfx; /* include the pending suffix */
4882 /* format the object */
4883 bufp = short_oname(obj, func, altfunc, lenlimit - len);
4884 if (len + strlen(bufp) <= lenlimit)
4885 Strcat(qbuf, bufp); /* formatted name fits */
4887 Strcat(qbuf, lastR); /* use last resort */
4891 Strcat(qbuf, qsuffix);
4893 /* assert( strlen(qbuf) < QBUFSZ ); */