1 /* NetHack 3.6 objnam.c $NHDT-Date: 1583315888 2020/03/04 09:58:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.293 $ */
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-2022 */
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 *));
25 STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
27 STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (const char *, CHAR_P, int));
28 STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
29 STATIC_DCL char *NDECL(nextobuf);
30 STATIC_DCL void FDECL(releaseobuf, (char *));
31 STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
32 STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
33 STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned));
34 STATIC_DCL char *FDECL(just_an, (char *str, const char *));
36 STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
37 const char *const *));
38 STATIC_DCL char *FDECL(singplur_compound, (char *));
40 STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
42 STATIC_DCL boolean FDECL(badman, (const char *, BOOLEAN_P));
44 STATIC_DCL char *FDECL(globwt, (struct obj *, char *, boolean *));
51 #define BSTRCMPI(base, ptr, str) ((ptr) < base || strcmpi((ptr), str))
52 #define BSTRNCMPI(base, ptr, str, num) \
53 ((ptr) < base || strncmpi((ptr), str, num))
54 #define Strcasecpy(dst, src) (void) strcasecpy(dst, src)
56 #define STRNCMPEX(x, y) strncmp(x, y, l = strlen(y))
59 /* true for gems/rocks that should have " stone" appended to their names */
60 #define GemStone(typ) \
62 || (objects[typ].oc_material == GEMSTONE \
63 && (typ != DILITHIUM_CRYSTAL && typ != RUBY && typ != DIAMOND \
64 && typ != SAPPHIRE && typ != BLACK_OPAL && typ != EMERALD \
68 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "wakizashi" },
69 { BROADSWORD, "ninja-to" },
70 { FLAIL, "nunchaku" },
71 { GLAIVE, "naginata" },
72 { LOCK_PICK, "osaku" },
73 { WOODEN_HARP, "koto" },
75 { PLATE_MAIL, "tanko" },
77 { LEATHER_GLOVES, "yugake" },
78 { FOOD_RATION, "gunyoki" },
79 { POT_BOOZE, "sake" },
82 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "
\98e
\8d·
\82µ" },
83 { BROADSWORD, "
\94E
\8eÒ
\93\81" },
84 { FLAIL, "
\83k
\83\93\83`
\83\83\83N" },
85 { GLAIVE, "
\82È
\82¬
\82È
\82½" },
86 { LOCK_PICK, "
\82¨
\82³
\82" },
87 { WOODEN_HARP, "
\8bÕ" },
88 { KNIFE, "
\8eh
\93\81" },
89 { PLATE_MAIL, "
\92Z
\8db" },
91 { LEATHER_GLOVES, "
\8b|
\8c\9c" },
92 { FOOD_RATION, "
\8aÛ
\96ò" },
93 { POT_BOOZE, "
\8eð" },
97 STATIC_DCL const char *FDECL(Japanese_item_name, (int i));
102 register const char *pref;
104 register int i = (int) strlen(pref);
107 impossible("PREFIX too short (for %d).", i);
111 (void) strncpy(s, pref, i); /* do not copy trailing 0 */
115 /* manage a pool of BUFSZ buffers, so callers don't have to */
116 static char NEARDATA obufs[NUMOBUF][BUFSZ];
117 static int obufidx = 0;
122 obufidx = (obufidx + 1) % NUMOBUF;
123 return obufs[obufidx];
126 /* put the most recently allocated buffer back if possible */
131 /* caller may not know whether bufp is the most recently allocated
132 buffer; if it isn't, do nothing; note that because of the somewhat
133 obscure PREFIX handling for object name formatting by xname(),
134 the pointer our caller has and is passing to us might be into the
135 middle of an obuf rather than the address returned by nextobuf() */
136 if (bufp >= obufs[obufidx]
137 && bufp < obufs[obufidx] + sizeof obufs[obufidx]) /* obufs[][BUFSZ] */
138 obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
145 char *buf = nextobuf();
146 struct objclass *ocl = &objects[otyp];
147 const char *actualn = OBJ_NAME(*ocl);
148 const char *dn = OBJ_DESCR(*ocl);
149 const char *un = ocl->oc_uname;
150 int nn = ocl->oc_name_known;
152 if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
153 actualn = Japanese_item_name(otyp);
156 Sprintf(buf, "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é", un);
158 switch (ocl->oc_class) {
163 Strcat(buf, "
\8bà
\89Ý");
167 Strcpy(buf, "potion");
173 Strcpy(buf, "scroll");
175 Strcat(buf, "
\8aª
\95¨");
184 if (otyp != SPE_NOVEL) {
186 Strcpy(buf, "spellbook");
188 Strcat(buf, "
\96\82\96@
\8f\91");
191 Strcpy(buf, !nn ? "book" : "novel");
193 Strcpy(buf, !nn ? "
\96{" : "
\8f¬
\90à");
201 Strcat(buf, "
\8ew
\97Ö");
206 Strcpy(buf, actualn);
208 Strcpy(buf, "amulet");
210 Sprintf(eos(buf), " called %s", un);
212 Sprintf(eos(buf), " (%s)", dn);
216 Strcat(buf, actualn);
218 Strcat(buf, "
\96\82\8f\9c\82¯");
224 Strcat(buf, actualn);
226 Strcat(buf, "
\95ó
\90Î");
232 Strcpy(buf, actualn);
234 Strcat(buf, " stone");
236 Sprintf(eos(buf), " called %s", un);
238 Sprintf(eos(buf), " (%s)", dn);
240 Strcat(buf, actualn);
244 Strcpy(buf, dn ? dn : actualn);
245 if (ocl->oc_class == GEM_CLASS)
247 (ocl->oc_material == MINERAL) ? " stone" : " gem");
249 Sprintf(eos(buf), " called %s", un);
251 Strcat(buf, dn ? dn : actualn);
260 /* here for ring/scroll/potion/wand */
264 Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
266 Sprintf(eos(buf), " of %s", actualn);
268 Strcpy(buf, actualn);
273 Sprintf(eos(buf), " called %s", un);
277 Sprintf(eos(buf), " (%s)", dn);
279 Sprintf(eos(buf), "(%s)", dn);
284 /* less verbose result than obj_typename(); either the actual name
285 or the description (but not both); user-assigned name is ignored */
287 simple_typename(otyp)
290 char *bufp, *pp, *save_uname = objects[otyp].oc_uname;
292 objects[otyp].oc_uname = 0; /* suppress any name given by user */
293 bufp = obj_typename(otyp);
294 objects[otyp].oc_uname = save_uname;
295 if ((pp = strstri(bufp, " (")) != 0)
296 *pp = '\0'; /* strip the appended description */
300 /* typename for debugging feedback where data involved might be suspect */
305 unsigned save_nameknown;
308 if (otyp < STRANGE_OBJECT || otyp >= NUM_OBJECTS
309 || !OBJ_NAME(objects[otyp])) {
311 Sprintf(res, "glorkum[%d]", otyp);
313 /* force it to be treated as fully discovered */
314 save_nameknown = objects[otyp].oc_name_known;
315 objects[otyp].oc_name_known = 1;
316 res = simple_typename(otyp);
317 objects[otyp].oc_name_known = save_nameknown;
326 if (!obj->oartifact || !has_oname(obj))
328 if (!program_state.gameover && !iflags.override_ID) {
329 if (not_fully_identified(obj))
335 /* used by distant_name() to pass extra information to xname_flags();
336 it would be much cleaner if this were a parameter, but that would
337 require all of the xname() and doname() calls to be modified */
338 static int distantname = 0;
340 /* Give the name of an object seen at a distance. Unlike xname/doname,
341 * we don't want to set dknown if it's not set already.
344 distant_name(obj, func)
346 char *FDECL((*func), (OBJ_P));
350 /* 3.6.1: this used to save Blind, set it, make the call, then restore
351 * the saved value; but the Eyes of the Overworld override blindness
352 * and let characters wearing them get dknown set for distant items.
354 * TODO? if the hero is wearing those Eyes, figure out whether the
355 * object is within X-ray radius and only treat it as distant when
356 * beyond that radius. Logic is iffy but result might be interesting.
364 /* convert player specified fruit name into corresponding fruit juice name
365 ("slice of pizza" -> "pizza juice" rather than "slice of pizza juice") */
368 boolean juice; /* whether or not to append " juice" to the name */
371 char *buf = nextobuf();
372 const char *fruit_nam = strstri(pl_fruit, " of ");
375 fruit_nam += 4; /* skip past " of " */
377 fruit_nam = pl_fruit; /* use it as is */
379 Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
382 /*
\93ú
\96{
\8cê
\82Å
\82Í
\82»
\82±
\82Ü
\82Å
\82µ
\82È
\82¢*/
383 char *buf = nextobuf();
384 Sprintf(buf, "%s%s", pl_fruit, juice ? "
\83W
\83\85\81[
\83X" : "");
389 /* look up a named fruit by index (1..127) */
391 fruit_from_indx(indx)
396 for (f = ffruit; f; f = f->nextf)
402 /* look up a named fruit by name */
404 fruit_from_name(fname, exact, highest_fid)
406 boolean exact; /* False => prefix or exact match, True = exact match only */
407 int *highest_fid; /* optional output; only valid if 'fname' isn't found */
409 struct fruit *f, *tentativef;
413 * note: named fruits are case-senstive...
418 /* first try for an exact match */
419 for (f = ffruit; f; f = f->nextf)
420 if (!strcmp(f->fname, fname))
422 else if (highest_fid && f->fid > *highest_fid)
423 *highest_fid = f->fid;
425 /* didn't match as-is; if caller is willing to accept a prefix
426 match, try to find one; we want to find the longest prefix that
427 matches, not the first */
430 for (f = ffruit; f; f = f->nextf) {
431 k = strlen(f->fname);
432 if (!strncmp(f->fname, fname, k)
433 && (!fname[k] || fname[k] == ' ')
434 && (!tentativef || k > strlen(tentativef->fname)))
439 /* if we still don't have a match, try singularizing the target;
440 for exact match, that's trivial, but for prefix, it's hard */
442 altfname = makesingular(fname);
443 for (f = ffruit; f; f = f->nextf) {
444 if (!strcmp(f->fname, altfname))
447 releaseobuf(altfname);
450 char fnamebuf[BUFSZ], *p;
451 unsigned fname_k = strlen(fname); /* length of assumed plural fname */
454 for (f = ffruit; f; f = f->nextf) {
455 k = strlen(f->fname);
456 /* reload fnamebuf[] each iteration in case it gets modified;
457 there's no need to recalculate fname_k */
458 Strcpy(fnamebuf, fname);
459 /* bug? if singular of fname is longer than plural,
460 failing the 'fname_k > k' test could skip a viable
461 candidate; unfortunately, we can't singularize until
462 after stripping off trailing stuff and we can't get
463 accurate fname_k until fname has been singularized;
464 compromise and use 'fname_k >= k' instead of '>',
465 accepting 1 char length discrepancy without risking
466 false match (I hope...) */
467 if (fname_k >= k && (p = index(&fnamebuf[k], ' ')) != 0) {
468 *p = '\0'; /* truncate at 1st space past length of f->fname */
469 altfname = makesingular(fnamebuf);
470 k = strlen(altfname); /* actually revised 'fname_k' */
471 if (!strcmp(f->fname, altfname)
472 && (!tentativef || k > strlen(tentativef->fname)))
474 releaseobuf(altfname); /* avoid churning through all obufs */
482 /* sort the named-fruit linked list by fruit index number */
484 reorder_fruit(forward)
487 struct fruit *f, *allfr[1 + 127];
488 int i, j, k = SIZE(allfr);
490 for (i = 0; i < k; ++i)
491 allfr[i] = (struct fruit *) 0;
492 for (f = ffruit; f; f = f->nextf) {
493 /* without sanity checking, this would reduce to 'allfr[f->fid]=f' */
495 if (j < 1 || j >= k) {
496 impossible("reorder_fruit: fruit index (%d) out of range", j);
497 return; /* don't sort after all; should never happen... */
498 } else if (allfr[j]) {
499 impossible("reorder_fruit: duplicate fruit index (%d)", j);
504 ffruit = 0; /* reset linked list; we're rebuilding it from scratch */
505 /* slot [0] will always be empty; must start 'i' at 1 to avoid
506 [k - i] being out of bounds during first iteration */
507 for (i = 1; i < k; ++i) {
508 /* for forward ordering, go through indices from high to low;
509 for backward ordering, go from low to high */
510 j = forward ? (k - i) : i;
512 allfr[j]->nextf = ffruit;
522 return xname_flags(obj, CXN_NORMAL);
526 xname_flags(obj, cxn_flags)
527 register struct obj *obj;
528 unsigned cxn_flags; /* bitmask of CXN_xxx values */
531 register int typ = obj->otyp;
532 register struct objclass *ocl = &objects[typ];
533 int nn = ocl->oc_name_known, omndx = obj->corpsenm;
534 const char *actualn = OBJ_NAME(*ocl);
535 const char *dn = OBJ_DESCR(*ocl);
536 const char *un = ocl->oc_uname;
537 boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
538 boolean known, dknown, bknown;
540 buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
541 if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
542 actualn = Japanese_item_name(typ);
543 /* As of 3.6.2: this used to be part of 'dn's initialization, but it
544 needs to come after possibly overriding 'actualn' */
550 * clean up known when it's tied to oc_name_known, eg after AD_DRIN
551 * This is only required for unique objects since the article
552 * printed for the object is tied to the combination of the two
553 * and printing the wrong article gives away information.
555 if (!nn && ocl->oc_uses_known && ocl->oc_unique)
557 if (!Blind && !distantname)
559 if (Role_if(PM_PRIEST))
560 obj->bknown = 1; /* actively avoid set_bknown();
561 * we mustn't call update_inventory() now because
562 * it would call xname() (via doname()) recursively
563 * and could end up clobbering all the obufs... */
565 if (iflags.override_ID) {
566 known = dknown = bknown = TRUE;
570 dknown = obj->dknown;
571 bknown = obj->bknown;
574 if (obj_is_pname(obj))
579 Strcat(buf, ONAME(obj));
584 if (has_oname(obj) && dknown) {
585 Strcat(buf, ONAME(obj));
586 Strcat(buf, "
\82Æ
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½");
589 switch (obj->oclass) {
593 Strcpy(buf, "amulet");
595 Strcat(buf, "
\96\82\8f\9c\82¯");
596 else if (typ == AMULET_OF_YENDOR || typ == FAKE_AMULET_OF_YENDOR)
597 /* each must be identified individually */
598 Strcpy(buf, known ? actualn : dn);
600 Strcpy(buf, actualn);
603 Sprintf(buf, "amulet called %s", un);
605 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96\82\8f\9c\82¯", un);
608 Sprintf(buf, "%s amulet", dn);
610 Sprintf(eos(buf), "%s", dn);
613 if (is_poisonable(obj) && obj->opoisoned)
615 Strcpy(buf, "poisoned ");
617 Strcpy(buf, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
623 Sprintf(eos(buf), "%s
\82Ì", mons[obj->corpsenm].mname);
627 Strcpy(buf, "pair of ");
629 Strcpy(buf, "
\88ê
\91Î
\82Ì");
630 else if (is_wet_towel(obj))
632 Strcpy(buf, (obj->spe < 3) ? "moist " : "wet ");
634 Strcpy(buf, (obj->spe < 3) ? "
\8e¼
\82Á
\82½" : "
\94G
\82ê
\82½");
639 Strcat(buf, actualn);
643 Strcat(buf, " called ");
647 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é");
653 #if 0 /*JP*/ /*
\82±
\82ê
\82Í
\8cê
\8f\87\82Ì
\8aÖ
\8cW
\82©
\82ç
\8fã
\82Ì
\95û
\82Å
\92è
\8b`*/
654 if (typ == FIGURINE && omndx != NON_PM) {
655 char anbuf[10]; /* [4] would be enough: 'a','n',' ','\0' */
657 Sprintf(eos(buf), " of %s%s",
658 just_an(anbuf, mons[omndx].mname),
660 } else if (is_wet_towel(obj)) {
662 if (is_wet_towel(obj)) {
665 Sprintf(eos(buf), " (%d)", obj->spe);
669 /* depends on order of the dragon scales objects */
670 if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
672 Sprintf(buf, "set of %s", actualn);
674 Sprintf(buf, "%s
\88ê
\8e®", actualn);
677 if (is_boots(obj) || is_gloves(obj))
679 Strcpy(buf, "pair of ");
681 Strcat(buf,"
\88ê
\91Î
\82Ì");
683 if (obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
686 Strcpy(buf, "shield");
688 Strcat(buf, "
\8f\82");
691 if (obj->otyp == SHIELD_OF_REFLECTION && !dknown) {
693 Strcpy(buf, "smooth shield");
695 Strcat(buf, "
\82·
\82×
\82·
\82×
\82µ
\82½
\8f\82");
700 Strcat(buf, actualn);
704 Strcat(buf, "boots");
705 else if (is_gloves(obj))
706 Strcat(buf, "gloves");
707 else if (is_cloak(obj))
708 Strcpy(buf, "cloak");
709 else if (is_helmet(obj))
710 Strcpy(buf, "helmet");
711 else if (is_shield(obj))
712 Strcpy(buf, "shield");
714 Strcpy(buf, "armor");
715 Strcat(buf, " called ");
721 else if (is_gloves(obj))
723 else if (is_cloak(obj))
724 p = "
\83N
\83\8d\81[
\83N";
725 else if (is_helmet(obj))
727 else if (is_shield(obj))
731 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", un, p);
737 if (typ == SLIME_MOLD) {
738 struct fruit *f = fruit_from_indx(obj->spe);
741 impossible("Bad fruit #%d?", obj->spe);
742 Strcpy(buf, "fruit");
744 Strcpy(buf, f->fname);
746 /* ick; already pluralized fruit names
747 are allowed--we want to try to avoid
748 adding a redundant plural suffix */
749 Strcpy(buf, makeplural(makesingular(buf)));
766 ? "
\82Æ
\82Ä
\82à
\91å
\82«
\82¢"
778 Strcpy(buf, actualn);
779 if (typ == TIN && known)
780 tin_details(obj, omndx, buf);
782 if (typ == TIN && known)
783 /*JP
\81u
\81`
\82Ì
\93÷
\82Ì
\81v*/
784 tin_details(obj, omndx, buf);
785 Strcat(buf, actualn);
791 Strcpy(buf, actualn);
793 Strcat(buf, actualn);
797 if (typ == STATUE && omndx != NON_PM) {
801 Sprintf(buf, "%s%s of %s%s",
802 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
806 type_is_pname(&mons[omndx])
808 : the_unique_pm(&mons[omndx])
810 : just_an(anbuf, mons[omndx].mname),
813 Sprintf(eos(buf), "%s%s
\82Ì%s",
814 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
817 mons[obj->corpsenm].mname, actualn);
821 Strcpy(buf, actualn);
823 Strcat(buf, actualn);
828 Sprintf(buf, "%sheavy iron ball",
829 (obj->owt > ocl->oc_weight) ? "very " : "");
831 Sprintf(eos(buf), "%s
\8fd
\82¢
\93S
\8b\85",
832 (obj->owt > ocl->oc_weight) ? "
\82Æ
\82Ä
\82à" : "");
836 if (dknown && obj->odiluted)
838 Strcpy(buf, "diluted ");
840 Strcat(buf, "
\94\96\82Ü
\82Á
\82½");
841 if (nn || un || !dknown) {
843 Strcat(buf, "potion");
856 if (typ == POT_WATER && bknown
857 && (obj->blessed || obj->cursed)) {
859 Strcat(buf, obj->blessed ? "holy " : "unholy ");
861 Strcat(buf, obj->blessed ? "
\90¹" : "
\95s
\8fò
\82È");
863 Strcat(buf, actualn);
866 Strcat(buf, " called ");
870 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96ò");
875 #if 0 /*JP*//*
\95s
\8am
\92è
\96¼
\82É
\81u
\96ò
\81v
\82Í
\95t
\82¢
\82Ä
\82¢
\82é*/
876 Strcat(buf, " potion");
882 Strcpy(buf, "scroll");
887 Strcat(buf,"
\8aª
\95¨");
895 Strcat(buf, actualn);
898 Strcat(buf, " called ");
902 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8aª
\95¨");
904 } else if (ocl->oc_magic) {
906 Strcat(buf, " labeled ");
912 Strcat(buf, " scroll");
926 Sprintf(buf, "wand of %s", actualn);
928 Strcat(buf, actualn);
931 Sprintf(buf, "wand called %s", un);
933 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8fñ", un);
936 Sprintf(buf, "%s wand", dn);
941 if (typ == SPE_NOVEL) { /* 3.6 tribute */
948 Strcpy(buf, actualn);
951 Sprintf(buf, "novel called %s", un);
953 Sprintf(buf, "%s
\82Æ
\82¢
\82¤
\8f¬
\90à", un);
956 Sprintf(buf, "%s book", dn);
958 Sprintf(buf, "%s
\96{", dn);
961 } else if (!dknown) {
963 Strcpy(buf, "spellbook");
965 Strcat(buf, "
\96\82\96@
\8f\91");
968 if (typ != SPE_BOOK_OF_THE_DEAD)
969 Strcpy(buf, "spellbook of ");
971 Strcat(buf, actualn);
974 Sprintf(buf, "spellbook called %s", un);
976 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96\82\96@
\8f\91", un);
979 Sprintf(buf, "%s spellbook", dn);
981 Sprintf(eos(buf), "%s", dn);
988 Strcat(buf, "
\8ew
\97Ö");
991 Sprintf(buf, "ring of %s", actualn);
993 Strcat(buf, actualn);
996 Sprintf(buf, "ring called %s", un);
998 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8ew
\97Ö", un);
1001 Sprintf(buf, "%s ring", dn);
1007 const char *rock = (ocl->oc_material == MINERAL) ? "stone" : "gem";
1009 const char *rock = (ocl->oc_material == MINERAL) ? "
\90Î" : "
\95ó
\90Î";
1020 Sprintf(buf, "%s called %s", rock, un);
1022 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", un, rock);
1025 Sprintf(buf, "%s %s", dn, rock);
1029 Strcpy(buf, actualn);
1032 Strcat(buf, " stone");
1038 Sprintf(buf, "glorkum %d %d %d", obj->oclass, typ, obj->spe);
1042 Strcpy(buf, makeplural(buf));
1045 if (obj->otyp == T_SHIRT && program_state.gameover) {
1049 Sprintf(eos(buf), " with text \"%s\"", tshirt_text(obj, tmpbuf));
1051 Sprintf(eos(buf), "(
\81u%s
\81v
\82Æ
\8f\91\82¢
\82Ä
\82 \82é)", tshirt_text(obj, tmpbuf));
1055 if (has_oname(obj) && dknown) {
1056 Strcat(buf, " named ");
1058 Strcat(buf, ONAME(obj));
1061 if (!strncmpi(buf, "the ", 4))
1069 /* similar to simple_typename but minimal_xname operates on a particular
1070 object rather than its general type; it formats the most basic info:
1071 potion -- if description not known
1072 brown potion -- if oc_name_known not set
1073 potion of object detection -- if discovered
1081 struct objclass saveobcls;
1082 int otyp = obj->otyp;
1087 /* suppress user-supplied name */
1088 saveobcls.oc_uname = objects[otyp].oc_uname;
1089 objects[otyp].oc_uname = 0;
1090 /* suppress actual name if object's description is unknown */
1091 saveobcls.oc_name_known = objects[otyp].oc_name_known;
1093 objects[otyp].oc_name_known = 0;
1095 /* caveat: this makes a lot of assumptions about which fields
1096 are required in order for xname() to yield a sensible result */
1098 bareobj.otyp = otyp;
1099 bareobj.oclass = obj->oclass;
1100 bareobj.dknown = obj->dknown;
1101 /* suppress known except for amulets (needed for fakes and real A-of-Y) */
1102 bareobj.known = (obj->oclass == AMULET_CLASS)
1104 /* default is "on" for types which don't use it */
1105 : !objects[otyp].oc_uses_known;
1106 bareobj.quan = 1L; /* don't want plural */
1107 bareobj.corpsenm = NON_PM; /* suppress statue and figurine details */
1108 /* but suppressing fruit details leads to "bad fruit #0"
1109 [perhaps we should force "slime mold" rather than use xname?] */
1110 if (obj->otyp == SLIME_MOLD)
1111 bareobj.spe = obj->spe;
1113 bufp = distant_name(&bareobj, xname); /* xname(&bareobj) */
1115 if (!strncmp(bufp, "uncursed ", 9))
1116 bufp += 9; /* Role_if(PM_PRIEST) */
1118 if (!STRNCMPEX(bufp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢"))
1119 bufp += l; /* Role_if(PM_PRIEST) */
1122 objects[otyp].oc_uname = saveobcls.oc_uname;
1123 objects[otyp].oc_name_known = saveobcls.oc_name_known;
1127 /* xname() output augmented for multishot missile feedback */
1133 char *onm = xname(obj);
1135 if (m_shot.n > 1 && m_shot.o == obj->otyp) {
1136 /* "the Nth arrow"; value will eventually be passed to an() or
1137 The(), both of which correctly handle this "the " prefix */
1139 Sprintf(tmpbuf, "the %d%s ", m_shot.i, ordin(m_shot.i));
1141 Sprintf(tmpbuf, "%d%s
\96Ú
\82Ì", m_shot.i, numeral(obj));
1142 onm = strprepend(onm, tmpbuf);
1147 /* used for naming "the unique_item" instead of "a unique_item" */
1153 boolean known = (obj->known || iflags.override_ID);
1155 if (!obj->dknown && !iflags.override_ID)
1157 else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !known)
1158 return TRUE; /* lie */
1160 return (boolean) (objects[obj->otyp].oc_unique
1161 && (known || obj->otyp == AMULET_OF_YENDOR));
1167 /* should monster type be prefixed with "the"? (mostly used for corpses) */
1170 struct permonst *ptr;
1174 /* even though monsters with personal names are unique, we want to
1175 describe them as "Name" rather than "the Name" */
1176 if (type_is_pname(ptr))
1179 uniq = (ptr->geno & G_UNIQ) ? TRUE : FALSE;
1180 /* high priest is unique if it includes "of <deity>", otherwise not
1181 (caller needs to handle the 1st possibility; we assume the 2nd);
1182 worm tail should be irrelevant but is included for completeness */
1183 if (ptr == &mons[PM_HIGH_PRIEST] || ptr == &mons[PM_LONG_WORM_TAIL])
1185 /* Wizard no longer needs this; he's flagged as unique these days */
1186 if (ptr == &mons[PM_WIZARD_OF_YENDOR])
1192 add_erosion_words(obj, prefix)
1196 boolean iscrys = (obj->otyp == CRYSKNIFE);
1199 rknown = (iflags.override_ID == 0) ? obj->rknown : TRUE;
1201 if (!is_damageable(obj) && !iscrys)
1204 /* The only cases where any of these bits do double duty are for
1205 * rotted food and diluted potions, which are all not is_damageable().
1207 if (obj->oeroded && !iscrys) {
1208 switch (obj->oeroded) {
1211 Strcat(prefix, "very ");
1213 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1217 Strcat(prefix, "thoroughly ");
1219 Strcat(prefix, "
\82©
\82È
\82è");
1223 Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
1225 Strcat(prefix, is_rustprone(obj) ? "
\8eK
\82Ñ
\82½" : "
\8f\9d\82Â
\82¢
\82½");
1227 if (obj->oeroded2 && !iscrys) {
1228 switch (obj->oeroded2) {
1231 Strcat(prefix, "very ");
1233 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1237 Strcat(prefix, "thoroughly ");
1239 Strcat(prefix, "
\82©
\82È
\82è");
1243 Strcat(prefix, is_corrodeable(obj) ? "corroded " : "rotted ");
1245 Strcat(prefix, is_corrodeable(obj) ? "
\95\85\90H
\82µ
\82½" : "
\95\85\82Á
\82½");
1247 if (rknown && obj->oerodeproof)
1249 Strcat(prefix, iscrys
1253 : is_corrodeable(obj)
1254 ? "corrodeproof " /* "stainless"? */
1259 Strcat(prefix, iscrys
1260 ? "
\88À
\92è
\82µ
\82½"
1262 ? "
\8eK
\82Ñ
\82È
\82¢"
1263 : is_corrodeable(obj)
1264 ? "
\95\85\90H
\82µ
\82È
\82¢" /* "stainless"? */
1266 ? "
\94R
\82¦
\82È
\82¢"
1271 /* used to prevent rust on items where rust makes no difference */
1273 erosion_matters(obj)
1276 switch (obj->oclass) {
1278 /* it's possible for a rusty weptool to be polymorphed into some
1279 non-weptool iron tool, in which case the rust implicitly goes
1280 away, but it's also possible for it to be polymorphed into a
1281 non-iron tool, in which case rust also implicitly goes away,
1282 so there's no particular reason to try to handle the first
1283 instance differently [this comment belongs in poly_obj()...] */
1284 return is_weptool(obj) ? TRUE : FALSE;
1296 #define DONAME_WITH_PRICE 1
1297 #define DONAME_VAGUE_QUAN 2
1300 doname_base(obj, doname_flags)
1302 unsigned doname_flags;
1304 boolean ispoisoned = FALSE,
1305 with_price = (doname_flags & DONAME_WITH_PRICE) != 0,
1306 vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0,
1307 weightshown = FALSE;
1308 boolean known, dknown, cknown, bknown, lknown;
1309 int omndx = obj->corpsenm;
1310 char prefix[PREFIX], globbuf[QBUFSZ];
1312 char tmpbuf[PREFIX + 1]; /* for when we have to add something at
1313 the start of prefix instead of the
1314 end (Strcat is used on the end) */
1316 register char *bp = xname(obj);
1318 char preprefix[PREFIX]; /*
\8f\87\8f\98\93ü
\82ê
\91Ö
\82¦
\82É
\8eg
\82¤*/
1322 if (iflags.override_ID) {
1323 known = dknown = cknown = bknown = lknown = TRUE;
1326 dknown = obj->dknown;
1327 cknown = obj->cknown;
1328 bknown = obj->bknown;
1329 lknown = obj->lknown;
1332 /* When using xname, we want "poisoned arrow", and when using
1333 * doname, we want "poisoned +0 arrow". This kludge is about the only
1334 * way to do it, at least until someone overhauls xname() and doname(),
1335 * combining both into one function taking a parameter.
1337 /* must check opoisoned--someone can have a weirdly-named fruit */
1339 if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
1344 if (!STRNCMPEX(bp, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½") && obj->opoisoned) {
1351 *
\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
1352 *
\82Ì
\82Ù
\82¤
\82ª
\8e©
\91R
\82Å
\82 \82é
\81D
1356 preprefix[0] = '\0';
1357 if((tp = strstri(bp, "
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½")) != NULL){
1358 tp += 12; /*
\81u
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½
\81v*/
1359 strncpy(preprefix, bp, tp - bp);
1360 preprefix[tp - bp] = '\0';
1367 if (obj->quan != 1L) {
1368 if (dknown || !vague_quan)
1370 Sprintf(prefix, "%ld ", obj->quan);
1371 #else /*
\93ú
\96{
\8cê
\82Æ
\82µ
\82Ä
\82Í
\90\94\8e\8c\82ª
\82È
\82¢
\82Ì
\82Í
\95s
\8e©
\91R */
1372 Sprintf(prefix, "%ld%s
\82Ì", obj->quan, numeral(obj));
1376 Strcpy(prefix, "some ");
1378 Strcpy(prefix, "
\82¢
\82
\82Â
\82©
\82Ì");
1379 } else if (obj->otyp == CORPSE) {
1380 /* skip article prefix for corpses [else corpse_xname()
1381 would have to be taught how to strip it off again] */
1383 #if 0 /*JP*/ /*
\8a¥
\8e\8c\82Í
\95s
\97v */
1384 } else if (obj_is_pname(obj) || the_unique_obj(obj)) {
1385 if (!strncmpi(bp, "the ", 4))
1387 Strcpy(prefix, "the ");
1389 Strcpy(prefix, "a ");
1390 #else /*prefix
\82Ì
\8f\89\8aú
\89»*/
1396 /* "empty" goes at the beginning, but item count goes at the end */
1398 /* bag of tricks: include "empty" prefix if it's known to
1399 be empty but its precise number of charges isn't known
1400 (when that is known, suffix of "(n:0)" will be appended,
1401 making the prefix be redundant; note that 'known' flag
1402 isn't set when emptiness gets discovered because then
1403 charging magic would yield known number of new charges) */
1404 && ((obj->otyp == BAG_OF_TRICKS)
1405 ? (obj->spe == 0 && !obj->known)
1406 /* not bag of tricks: empty if container which has no contents */
1407 : ((Is_container(obj) || obj->otyp == STATUE)
1408 && !Has_contents(obj))))
1410 Strcat(prefix, "empty ");
1412 Strcat(prefix, "
\8bó
\82Ì");
1414 if (bknown && obj->oclass != COIN_CLASS
1415 && (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
1416 || (!obj->cursed && !obj->blessed))) {
1417 /* allow 'blessed clear potion' if we don't know it's holy water;
1418 * always allow "uncursed potion of water"
1422 Strcat(prefix, "cursed ");
1424 Strcat(prefix, "
\8eô
\82í
\82ê
\82½");
1425 else if (obj->blessed)
1427 Strcat(prefix, "blessed ");
1429 Strcat(prefix, "
\8fj
\95\9f\82³
\82ê
\82½");
1430 else if (!iflags.implicit_uncursed
1431 /* For most items with charges or +/-, if you know how many
1432 * charges are left or what the +/- is, then you must have
1433 * totally identified the item, so "uncursed" is unnecessary,
1434 * because an identified object not described as "blessed" or
1435 * "cursed" must be uncursed.
1437 * If the charges or +/- is not known, "uncursed" must be
1438 * printed to avoid ambiguity between an item whose curse
1439 * status is unknown, and an item known to be uncursed.
1441 || ((!known || !objects[obj->otyp].oc_charged
1442 || obj->oclass == ARMOR_CLASS
1443 || obj->oclass == RING_CLASS)
1445 && obj->otyp != SCR_MAIL
1447 && obj->otyp != FAKE_AMULET_OF_YENDOR
1448 && obj->otyp != AMULET_OF_YENDOR
1449 && !Role_if(PM_PRIEST)))
1451 Strcat(prefix, "uncursed ");
1453 Strcat(prefix, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢");
1456 if (lknown && Is_box(obj)) {
1458 /* 3.6.0 used "unlockable" here but that could be misunderstood
1459 to mean "capable of being unlocked" rather than the intended
1460 "not capable of being locked" */
1462 Strcat(prefix, "broken ");
1464 Strcat(prefix, "
\8c®
\82Ì
\89ó
\82ê
\82½");
1465 else if (obj->olocked)
1467 Strcat(prefix, "locked ");
1469 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82½");
1472 Strcat(prefix, "unlocked ");
1474 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82Ä
\82¢
\82È
\82¢");
1479 Strcat(prefix, "greased ");
1481 Strcat(prefix, "
\96û
\82Ì
\93h
\82ç
\82ê
\82½");
1483 if (cknown && Has_contents(obj)) {
1484 /* we count the number of separate stacks, which corresponds
1485 to the number of inventory slots needed to be able to take
1486 everything out if no merges occur */
1487 long itemcount = count_contents(obj, FALSE, FALSE, TRUE, FALSE);
1490 Sprintf(eos(bp), " containing %ld item%s", itemcount,
1493 Sprintf(eos(bp), "(%ld
\8cÂ
\93ü
\82Á
\82Ä
\82¢
\82é)", itemcount);
1497 switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
1499 if (obj->owornmask & W_AMUL)
1501 Strcat(bp, " (being worn)");
1503 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1506 if (obj->owornmask & W_ARMOR) {
1508 Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
1510 Strcat(bp, (obj == uskin) ? "(
\94§
\82É
\96\84\82ß
\82±
\82Ü
\82ê
\82Ä
\82¢
\82é)"
1511 /* in case of perm_invent update while Wear/Takeoff
1512 is in progress; check doffing() before donning()
1513 because donning() returns True for both cases */
1515 : doffing(obj) ? " (being doffed)"
1517 : doffing(obj) ? " (
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é
\93r
\92\86)"
1519 : donning(obj) ? " (being donned)"
1521 : donning(obj) ? " (
\92E
\82¢
\82Å
\82¢
\82é
\93r
\92\86)"
1525 : "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1526 /* slippery fingers is an intrinsic condition of the hero
1527 rather than extrinsic condition of objects, but gloves
1528 are described as slippery when hero has slippery fingers */
1529 if (obj == uarmg && Glib) /* just appended "(something)",
1530 * change to "(something; slippery)" */
1532 Strcpy(rindex(bp, ')'), "; slippery)");
1534 Strcpy(rindex(bp, ')'), ";
\82Ê
\82é
\82Ê
\82é)");
1540 Strcat(prefix, "poisoned ");
1542 Strcat(prefix, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
1543 add_erosion_words(obj, prefix);
1545 Strcat(prefix, sitoa(obj->spe));
1546 Strcat(prefix, " ");
1550 if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
1552 Strcat(bp, " (being worn)");
1554 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1557 if (obj->otyp == LEASH && obj->leashmon != 0) {
1558 struct monst *mlsh = find_mid(obj->leashmon, FM_FMON);
1561 impossible("leashed monster not on this level");
1565 Sprintf(eos(bp), " (attached to %s)",
1566 noit_mon_nam(mlsh));
1568 Sprintf(eos(bp), " (%s
\82É
\8c\8b\82Ñ
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é)",
1569 noit_mon_nam(mlsh));
1574 if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
1577 Strcpy(tmpbuf, "no");
1579 Sprintf(tmpbuf, "%d", obj->spe);
1580 Sprintf(eos(bp), " (%s candle%s%s)", tmpbuf, plur(obj->spe),
1581 !obj->lamplit ? " attached" : ", lit");
1584 Sprintf(eos(bp), "(
\88ê
\96{
\82à
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82È
\82¢)");
1587 Sprintf(eos(bp), "(%d
\96{
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é)", obj->spe);
1589 Sprintf(eos(bp), "(%d
\96{
\8cõ
\82Á
\82Ä
\82¢
\82é)", obj->spe);
1593 } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
1594 || obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
1596 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
1598 Strcat(prefix, "partly used ");
1600 Strcat(prefix, "
\8eg
\82¢
\82³
\82µ
\82Ì");
1603 Strcat(bp, " (lit)");
1605 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1608 if (objects[obj->otyp].oc_charged)
1615 Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
1617 Sprintf(eos(bp), "(%d:%d)", (int) obj->recharged, obj->spe);
1620 if (obj->otyp == POT_OIL && obj->lamplit)
1622 Strcat(bp, " (lit)");
1624 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1628 if (obj->owornmask & W_RINGR)
1630 Strcat(bp, " (on right ");
1632 Strcat(bp, "(
\89E");
1633 if (obj->owornmask & W_RINGL)
1635 Strcat(bp, " (on left ");
1637 Strcat(bp, "(
\8d¶");
1638 if (obj->owornmask & W_RING) {
1639 Strcat(bp, body_part(HAND));
1642 if (known && objects[obj->otyp].oc_charged) {
1644 Strcat(prefix, " ");
1646 Strcat(prefix, sitoa(obj->spe));
1647 Strcat(prefix, " ");
1653 Strcat(prefix, "partly eaten ");
1655 Strcat(prefix, "
\90H
\82×
\82©
\82¯
\82Ì");
1656 if (obj->otyp == CORPSE) {
1657 /* (quan == 1) => want corpse_xname() to supply article,
1658 (quan != 1) => already have count or "some" as prefix;
1659 "corpse" is already in the buffer returned by xname() */
1660 unsigned cxarg = (((obj->quan != 1L) ? 0 : CXN_ARTICLE)
1662 char *cxstr = corpse_xname(obj, prefix, cxarg);
1665 Sprintf(prefix, "%s ", cxstr);
1667 Sprintf(prefix, "%s
\82Ì", cxstr);
1669 /* avoid having doname(corpse) consume an extra obuf */
1671 } else if (obj->otyp == EGG) {
1672 #if 0 /* corpses don't tell if they're stale either */
1673 if (known && stale_egg(obj))
1674 Strcat(prefix, "stale ");
1677 && (known || (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
1679 Strcat(prefix, mons[omndx].mname);
1680 Strcat(prefix, " ");
1682 Strcat(prefix, mons[omndx].mname);
1683 Strcat(prefix, "
\82Ì");
1687 Strcat(bp, " (laid by you)");
1689 Strcat(bp, "(
\82 \82È
\82½
\82ª
\8eY
\82ñ
\82¾)");
1692 if (obj->otyp == MEAT_RING)
1697 add_erosion_words(obj, prefix);
1698 if (obj->owornmask & W_BALL)
1700 Strcat(bp, " (chained to you)");
1702 Strcat(bp, "(
\82 \82È
\82½
\82É
\8cq
\82ª
\82ê
\82Ä
\82¢
\82é)");
1706 if ((obj->owornmask & W_WEP) && !mrg_to_wielded) {
1707 if (obj->quan != 1L) {
1709 Strcat(bp, " (wielded)");
1711 Strcat(bp, "(
\91\95\94õ
\82µ
\82Ä
\82¢
\82é)");
1713 const char *hand_s = body_part(HAND);
1716 hand_s = makeplural(hand_s);
1717 /* note: Sting's glow message, if added, will insert text
1718 in front of "(weapon in hand)"'s closing paren */
1720 Sprintf(eos(bp), " (%sweapon in %s)",
1721 (obj->otyp == AKLYS) ? "tethered " : "", hand_s);
1722 #else /*
\83A
\83L
\83\8a\83X
\82ð
\93Á
\95Ê
\88µ
\82¢
\82µ
\82È
\82¢*/
1723 Sprintf(eos(bp), "(%s
\82É
\82µ
\82Ä
\82¢
\82é)", hand_s);
1726 if (warn_obj_cnt && obj == uwep && (EWarn_of_mon & W_WEP) != 0L) {
1727 if (!Blind) /* we know bp[] ends with ')'; overwrite that */
1729 Sprintf(eos(bp) - 1, ", %s %s)",
1730 glow_verb(warn_obj_cnt, TRUE),
1731 glow_color(obj->oartifact));
1733 Sprintf(eos(bp) - 1, ", %s%s
\82¢
\82é)",
1734 glow_color(obj->oartifact),
1735 jconj(glow_verb(warn_obj_cnt, TRUE), "
\82Ä"));
1740 if (obj->owornmask & W_SWAPWEP) {
1743 Sprintf(eos(bp), " (wielded in other %s)", body_part(HAND));
1745 Sprintf(eos(bp), "(
\8d¶%s
\82É
\82µ
\82Ä
\82¢
\82é)", body_part(HAND));
1748 Strcat(bp, " (alternate weapon; not wielded)");
1750 Strcat(bp, "(
\97\
\94õ
\82Ì
\95\90\8aí;
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢)");
1752 if (obj->owornmask & W_QUIVER) {
1753 switch (obj->oclass) {
1756 if (objects[obj->otyp].oc_skill == -P_BOW) {
1757 /* Ammo for a bow */
1759 Strcat(bp, " (in quiver)");
1761 Strcat(bp, "(
\96î
\93\9b\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1764 /* Ammo not for a bow */
1766 Strcat(bp, " (in quiver pouch)");
1768 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1772 /* Weapons not considered ammo */
1774 Strcat(bp, " (at the ready)");
1776 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1779 /* Small things and ammo not for a bow */
1786 Strcat(bp, " (in quiver pouch)");
1788 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1790 default: /* odd things */
1792 Strcat(bp, " (at the ready)");
1794 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1797 /* treat 'restoring' like suppress_price because shopkeeper and
1798 bill might not be available yet while restore is in progress
1799 (objects won't normally be formatted during that time, but if
1800 'perm_invent' is enabled then they might be) */
1801 if (iflags.suppress_price || restoring) {
1802 ; /* don't attempt to obtain any stop pricing, even if 'with_price' */
1803 } else if (is_unpaid(obj)) { /* in inventory or in container in invent */
1804 long quotedprice = unpaid_cost(obj, TRUE);
1807 Sprintf(eos(bp), " (%s, %s%ld %s)",
1808 obj->unpaid ? "unpaid" : "contents",
1809 globwt(obj, globbuf, &weightshown),
1810 quotedprice, currency(quotedprice));
1812 Sprintf(eos(bp), " (%s, %s%ld%s)",
1813 obj->unpaid ? "
\96¢
\95¥
\82¢" : "
\92\86\90g",
1814 globwt(obj, globbuf, &weightshown),
1815 quotedprice, currency(quotedprice));
1817 } else if (with_price) { /* on floor or in container on floor */
1819 long price = get_cost_of_shop_item(obj, &nochrg);
1823 Sprintf(eos(bp), " (%s, %s%ld %s)",
1824 nochrg ? "contents" : "for sale",
1825 globwt(obj, globbuf, &weightshown),
1826 price, currency(price));
1828 Sprintf(eos(bp), " (%s, %s%ld%s)",
1829 nochrg ? "
\92\86\90g" : "
\8f¤
\95i",
1830 globwt(obj, globbuf, &weightshown),
1831 price, currency(price));
1833 else if (nochrg > 0)
1835 Sprintf(eos(bp), " (%sno charge)",
1836 globwt(obj, globbuf, &weightshown));
1838 Sprintf(eos(bp), " (%s
\96³
\97¿)",
1839 globwt(obj, globbuf, &weightshown));
1842 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
1843 if (!strncmp(prefix, "a ", 2)) {
1844 /* save current prefix, without "a "; might be empty */
1845 Strcpy(tmpbuf, prefix + 2);
1846 /* set prefix[] to "", "a ", or "an " */
1847 (void) just_an(prefix, *tmpbuf ? tmpbuf : bp);
1848 /* append remainder of original prefix */
1849 Strcat(prefix, tmpbuf);
1853 /* show weight for items (debug tourist info);
1854 "aum" is stolen from Crawl's "Arbitrary Unit of Measure" */
1855 if (wizard && iflags.wizweight) {
1856 /* wizard mode user has asked to see object weights;
1857 globs with shop pricing attached already include it */
1859 Sprintf(eos(bp), " (%u aum)", obj->owt);
1862 bp = strprepend(bp, prefix);
1863 #else /*JP:
\81u
\96¼
\95t
\82¯
\82ç
\82ê
\82½
\81v
\82ð
\96ß
\82·*/
1864 Strcat(preprefix, prefix);
1865 bp = strprepend(bp, preprefix);
1874 return doname_base(obj, (unsigned) 0);
1877 /* Name of object including price. */
1879 doname_with_price(obj)
1882 return doname_base(obj, DONAME_WITH_PRICE);
1885 /* "some" instead of precise quantity if obj->dknown not set */
1887 doname_vague_quan(obj)
1891 * If it hasn't been seen up close and quantity is more than one,
1892 * use "some" instead of the quantity: "some gold pieces" rather
1893 * than "25 gold pieces". This is suboptimal, to put it mildly,
1894 * because lookhere and pickup report the precise amount.
1895 * Picking the item up while blind also shows the precise amount
1896 * for inventory display, then dropping it while still blind leaves
1897 * obj->dknown unset so the count reverts to "some" for farlook.
1899 * TODO: add obj->qknown flag for 'quantity known' on stackable
1900 * items; it could overlay obj->cknown since no containers stack.
1902 return doname_base(obj, DONAME_VAGUE_QUAN);
1905 /* used from invent.c */
1907 not_fully_identified(otmp)
1910 /* gold doesn't have any interesting attributes [yet?] */
1911 if (otmp->oclass == COIN_CLASS)
1912 return FALSE; /* always fully ID'd */
1913 /* check fundamental ID hallmarks first */
1914 if (!otmp->known || !otmp->dknown
1916 || (!otmp->bknown && otmp->otyp != SCR_MAIL)
1920 || !objects[otmp->otyp].oc_name_known)
1922 if ((!otmp->cknown && (Is_container(otmp) || otmp->otyp == STATUE))
1923 || (!otmp->lknown && Is_box(otmp)))
1925 if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
1927 /* otmp->rknown is the only item of interest if we reach here */
1929 * Note: if a revision ever allows scrolls to become fireproof or
1930 * rings to become shockproof, this checking will need to be revised.
1931 * `rknown' ID only matters if xname() will provide the info about it.
1934 || (otmp->oclass != ARMOR_CLASS && otmp->oclass != WEAPON_CLASS
1935 && !is_weptool(otmp) /* (redundant) */
1936 && otmp->oclass != BALL_CLASS)) /* (useless) */
1938 else /* lack of `rknown' only matters for vulnerable objects */
1939 return (boolean) (is_rustprone(otmp) || is_corrodeable(otmp)
1940 || is_flammable(otmp));
1943 /* format a corpse name (xname() omits monster type; doname() calls us);
1944 eatcorpse() also uses us for death reason when eating tainted glob */
1946 corpse_xname(otmp, adjective, cxn_flags)
1948 const char *adjective;
1949 unsigned cxn_flags; /* bitmask of CXN_xxx values */
1951 /* some callers [aobjnam()] rely on prefix area that xname() sets aside */
1952 char *nambuf = nextobuf() + PREFIX;
1953 int omndx = otmp->corpsenm;
1955 boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0,
1956 /* suppress "the" from "the unique monster corpse" */
1960 no_prefix = (cxn_flags & CXN_NO_PFX) != 0,
1961 /* include "the" for "the woodchuck corpse */
1962 the_prefix = (cxn_flags & CXN_PFX_THE) != 0,
1963 /* include "an" for "an ogre corpse */
1964 any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
1965 /* leave off suffix (do_name() appends "corpse" itself) */
1966 omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
1968 glob = (otmp->otyp != CORPSE && otmp->globby);
1972 mname = OBJ_NAME(objects[otmp->otyp]); /* "glob of <monster>" */
1973 } else if (omndx == NON_PM) { /* paranoia */
1978 /* [Possible enhancement: check whether corpse has monster traits
1979 attached in order to use priestname() for priests and minions.] */
1980 } else if (omndx == PM_ALIGNED_PRIEST) {
1981 /* avoid "aligned priest"; it just exposes internal details */
1987 mname = mons[omndx].mname;
1988 if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) {
1989 mname = s_suffix(mname);
1991 /* don't precede personal name like "Medusa" with an article */
1992 if (type_is_pname(&mons[omndx]))
1994 /* always precede non-personal unique monster name like
1995 "Oracle" with "the" unless explicitly overridden */
1996 else if (the_unique_pm(&mons[omndx]) && !no_prefix)
2001 the_prefix = any_prefix = FALSE;
2002 else if (the_prefix)
2003 any_prefix = FALSE; /* mutually exclusive */
2006 /* can't use the() the way we use an() below because any capitalized
2007 Name causes it to assume a personal name and return Name as-is;
2008 that's usually the behavior wanted, but here we need to force "the"
2009 to precede capitalized unique monsters (pnames are handled above) */
2010 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2012 Strcat(nambuf, "the ");
2015 if (!adjective || !*adjective) {
2016 /* normal case: newt corpse */
2017 Strcat(nambuf, mname);
2019 /* adjective positioning depends upon format of monster name */
2020 if (possessive) /* Medusa's cursed partly eaten corpse */
2022 Sprintf(eos(nambuf), "%s %s", mname, adjective);
2024 Sprintf(eos(nambuf), "%s%s", mname, adjective);
2025 else /* cursed partly eaten troll corpse */
2027 Sprintf(eos(nambuf), "%s %s", adjective, mname);
2029 Sprintf(eos(nambuf), "%s%s", adjective, mname);
2030 /* in case adjective has a trailing space, squeeze it out */
2032 /* doname() might include a count in the adjective argument;
2033 if so, don't prepend an article */
2034 if (digit(*adjective))
2039 ; /* omit_corpse doesn't apply; quantity is always 1 */
2040 } else if (!omit_corpse) {
2042 Strcat(nambuf, " corpse");
2043 /* makeplural(nambuf) => append "s" to "corpse" */
2044 if (otmp->quan > 1L && !ignore_quan) {
2045 Strcat(nambuf, "s");
2046 any_prefix = FALSE; /* avoid "a newt corpses" */
2049 Strcat(nambuf, "
\82Ì
\8e\80\91Ì");
2053 /* it's safe to overwrite our nambuf after an() has copied
2054 its old value into another buffer */
2056 Strcpy(nambuf, an(nambuf));
2061 /* xname doesn't include monster type for "corpse"; cxname does */
2066 if (obj->otyp == CORPSE)
2067 return corpse_xname(obj, (const char *) 0, CXN_NORMAL);
2071 /* like cxname, but ignores quantity */
2073 cxname_singular(obj)
2076 if (obj->otyp == CORPSE)
2077 return corpse_xname(obj, (const char *) 0, CXN_SINGULAR);
2078 return xname_flags(obj, CXN_SINGULAR);
2081 /* treat an object as fully ID'd when it might be used as reason for death */
2086 struct obj save_obj;
2087 unsigned save_ocknown;
2088 char *buf, *save_ocuname, *save_oname = (char *) 0;
2090 /* bypass object twiddling for artifacts */
2092 return bare_artifactname(obj);
2094 /* remember original settings for core of the object;
2095 oextra structs other than oname don't matter here--since they
2096 aren't modified they don't need to be saved and restored */
2099 save_oname = ONAME(obj);
2101 /* killer name should be more specific than general xname; however, exact
2102 info like blessed/cursed and rustproof makes things be too verbose */
2103 obj->known = obj->dknown = 1;
2104 obj->bknown = obj->rknown = obj->greased = 0;
2105 /* if character is a priest[ess], bknown will get toggled back on */
2106 if (obj->otyp != POT_WATER)
2107 obj->blessed = obj->cursed = 0;
2109 obj->bknown = 1; /* describe holy/unholy water as such */
2110 /* "killed by poisoned <obj>" would be misleading when poison is
2111 not the cause of death and "poisoned by poisoned <obj>" would
2112 be redundant when it is, so suppress "poisoned" prefix */
2114 /* strip user-supplied name; artifacts keep theirs */
2115 if (!obj->oartifact && save_oname)
2116 ONAME(obj) = (char *) 0;
2117 /* temporarily identify the type of object */
2118 save_ocknown = objects[obj->otyp].oc_name_known;
2119 objects[obj->otyp].oc_name_known = 1;
2120 save_ocuname = objects[obj->otyp].oc_uname;
2121 objects[obj->otyp].oc_uname = 0; /* avoid "foo called bar" */
2123 /* format the object */
2124 if (obj->otyp == CORPSE) {
2125 buf = corpse_xname(obj, (const char *) 0, CXN_NORMAL);
2126 } else if (obj->otyp == SLIME_MOLD) {
2127 /* concession to "most unique deaths competition" in the annual
2128 devnull tournament, suppress player supplied fruit names because
2129 those can be used to fake other objects and dungeon features */
2132 Sprintf(buf, "deadly slime mold%s", plur(obj->quan));
2134 Strcpy(buf, "
\8aë
\8c¯
\82È
\82Ë
\82Î
\82Ë
\82Î
\83J
\83r");
2138 /* apply an article if appropriate; caller should always use KILLED_BY */
2139 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
2140 if (obj->quan == 1L && !strstri(buf, "'s ") && !strstri(buf, "s' "))
2141 buf = (obj_is_pname(obj) || the_unique_obj(obj)) ? the(buf) : an(buf);
2144 objects[obj->otyp].oc_name_known = save_ocknown;
2145 objects[obj->otyp].oc_uname = save_ocuname;
2146 *obj = save_obj; /* restore object's core settings */
2147 if (!obj->oartifact && save_oname)
2148 ONAME(obj) = save_oname;
2153 /* xname,doname,&c with long results reformatted to omit some stuff */
2155 short_oname(obj, func, altfunc, lenlimit)
2157 char *FDECL((*func), (OBJ_P)), /* main formatting routine */
2158 *FDECL((*altfunc), (OBJ_P)); /* alternate for shortest result */
2161 struct obj save_obj;
2162 char unamebuf[12], onamebuf[12], *save_oname, *save_uname, *outbuf;
2164 outbuf = (*func)(obj);
2165 if ((unsigned) strlen(outbuf) <= lenlimit)
2168 /* shorten called string to fairly small amount */
2169 save_uname = objects[obj->otyp].oc_uname;
2170 if (save_uname && strlen(save_uname) >= sizeof unamebuf) {
2171 (void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
2172 Strcpy(unamebuf + sizeof unamebuf - 4, "...");
2173 objects[obj->otyp].oc_uname = unamebuf;
2174 releaseobuf(outbuf);
2175 outbuf = (*func)(obj);
2176 objects[obj->otyp].oc_uname = save_uname; /* restore called string */
2177 if ((unsigned) strlen(outbuf) <= lenlimit)
2181 /* shorten named string to fairly small amount */
2182 save_oname = has_oname(obj) ? ONAME(obj) : 0;
2183 if (save_oname && strlen(save_oname) >= sizeof onamebuf) {
2184 (void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
2185 Strcpy(onamebuf + sizeof onamebuf - 4, "...");
2186 ONAME(obj) = onamebuf;
2187 releaseobuf(outbuf);
2188 outbuf = (*func)(obj);
2189 ONAME(obj) = save_oname; /* restore named string */
2190 if ((unsigned) strlen(outbuf) <= lenlimit)
2194 /* shorten both called and named strings;
2195 unamebuf and onamebuf have both already been populated */
2196 if (save_uname && strlen(save_uname) >= sizeof unamebuf && save_oname
2197 && strlen(save_oname) >= sizeof onamebuf) {
2198 objects[obj->otyp].oc_uname = unamebuf;
2199 ONAME(obj) = onamebuf;
2200 releaseobuf(outbuf);
2201 outbuf = (*func)(obj);
2202 if ((unsigned) strlen(outbuf) <= lenlimit) {
2203 objects[obj->otyp].oc_uname = save_uname;
2204 ONAME(obj) = save_oname;
2209 /* still long; strip several name-lengthening attributes;
2210 called and named strings are still in truncated form */
2212 obj->bknown = obj->rknown = obj->greased = 0;
2213 obj->oeroded = obj->oeroded2 = 0;
2214 releaseobuf(outbuf);
2215 outbuf = (*func)(obj);
2216 if (altfunc && (unsigned) strlen(outbuf) > lenlimit) {
2217 /* still long; use the alternate function (usually one of
2218 the jackets around minimal_xname()) */
2219 releaseobuf(outbuf);
2220 outbuf = (*altfunc)(obj);
2222 /* restore the object */
2225 ONAME(obj) = save_oname;
2227 objects[obj->otyp].oc_uname = save_uname;
2229 /* use whatever we've got, whether it's too long or not */
2234 * Used if only one of a collection of objects is named (e.g. in eat.c).
2237 singular(otmp, func)
2238 register struct obj *otmp;
2239 char *FDECL((*func), (OBJ_P));
2244 /* using xname for corpses does not give the monster type */
2245 if (otmp->otyp == CORPSE && func == xname)
2248 savequan = otmp->quan;
2250 nam = (*func)(otmp);
2251 otmp->quan = savequan;
2255 /* pick "", "a ", or "an " as article for 'str'; used by an() and doname() */
2257 just_an(outbuf, str)
2261 #if 0 /*JP*//*
\95s
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2267 /* single letter; might be used for named fruit */
2268 Strcpy(outbuf, index("aefhilmnosx", c0) ? "an " : "a ");
2269 } else if (!strncmpi(str, "the ", 4) || !strcmpi(str, "molten lava")
2270 || !strcmpi(str, "iron bars") || !strcmpi(str, "ice")) {
2273 if ((index(vowels, c0) && strncmpi(str, "one-", 4)
2274 && strncmpi(str, "eucalyptus", 10) && strncmpi(str, "unicorn", 7)
2275 && strncmpi(str, "uranium", 7) && strncmpi(str, "useful", 6))
2276 || (index("x", c0) && !index(vowels, lowc(str[1]))))
2277 Strcpy(outbuf, "an ");
2279 Strcpy(outbuf, "a ");
2291 char *buf = nextobuf();
2293 if (!str || !*str) {
2294 impossible("Alphabet soup: 'an(%s)'.", str ? "\"\"" : "<null>");
2295 return strcpy(buf, "an []");
2297 (void) just_an(buf, str);
2298 return strcat(buf, str);
2305 char *tmp = an(str);
2307 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
2314 * Prepend "the" if necessary; assumes str is a subject derived from xname.
2315 * Use type_is_pname() for monster names, not the(). the() is idempotent.
2321 char *buf = nextobuf();
2322 #if 0 /*JP*//*
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2323 boolean insert_the = FALSE;
2325 if (!str || !*str) {
2326 impossible("Alphabet soup: 'the(%s)'.", str ? "\"\"" : "<null>");
2327 return strcpy(buf, "the []");
2329 if (!strncmpi(str, "the ", 4)) {
2330 buf[0] = lowc(*str);
2331 Strcpy(&buf[1], str + 1);
2333 } else if (*str < 'A' || *str > 'Z'
2334 /* treat named fruit as not a proper name, even if player
2335 has assigned a capitalized proper name as his/her fruit */
2336 || fruit_from_name(str, TRUE, (int *) 0)) {
2337 /* not a proper name, needs an article */
2340 /* Probably a proper name, might not need an article */
2341 register char *tmp, *named, *called;
2344 /* some objects have capitalized adjectives in their names */
2345 if (((tmp = rindex(str, ' ')) != 0 || (tmp = rindex(str, '-')) != 0)
2346 && (tmp[1] < 'A' || tmp[1] > 'Z')) {
2348 } else if (tmp && index(str, ' ') < tmp) { /* has spaces */
2349 /* it needs an article if the name contains "of" */
2350 tmp = strstri(str, " of ");
2351 named = strstri(str, " named ");
2352 called = strstri(str, " called ");
2353 if (called && (!named || called < named))
2356 if (tmp && (!named || tmp < named)) /* found an "of" */
2358 /* stupid special case: lacks "of" but needs "the" */
2359 else if (!named && (l = strlen(str)) >= 31
2360 && !strcmp(&str[l - 31],
2361 "Platinum Yendorian Express Card"))
2366 Strcpy(buf, "the ");
2371 #else /*
\92P
\82É
\83R
\83s
\81[*/
2381 char *tmp = the(str);
2383 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
2392 register struct obj *otmp;
2393 register const char *verb;
2399 /* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */
2405 char prefix[PREFIX];
2406 char *bp = cxname(otmp);
2408 if (otmp->quan != 1L) {
2409 Sprintf(prefix, "%ld ", otmp->quan);
2410 bp = strprepend(bp, prefix);
2414 Strcat(bp, otense(otmp, verb));
2420 /* combine yname and aobjnam eg "your count cxname(otmp)" */
2426 char *s = aobjnam(obj, verb);
2428 /* leave off "your" for most of your artifacts, but prepend
2429 * "your" for unique objects and "foo of bar" quest artifacts */
2430 if (!carried(obj) || !obj_is_pname(obj)
2431 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2432 char *outbuf = shk_your(nextobuf(), obj);
2433 int space_left = BUFSZ - 1 - strlen(outbuf);
2435 s = strncat(outbuf, s, space_left);
2440 /* combine Yname2 and aobjnam eg "Your count cxname(otmp)" */
2446 register char *s = yobjnam(obj, verb);
2454 /* like aobjnam, but prepend "The", not count, and use xname */
2460 char *bp = The(xname(otmp));
2462 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2465 Strcat(bp, otense(otmp, verb));
2471 /* capitalized variant of doname() */
2476 char *s = doname(obj);
2482 #if 0 /* stalled-out work in progress */
2483 /* Doname2() for itemized buying of 'obj' from a shop */
2488 static const char and_contents[] = " and its contents";
2489 char *p = doname(obj);
2491 if (Is_container(obj) && !obj->cknown) {
2493 if ((int) strlen(p) + sizeof and_contents - 1 < BUFSZ - PREFIX)
2494 Strcat(p, and_contents);
2497 p = strprepend(p, "Contents of ");
2506 /* returns "[your ]xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
2511 char *s = cxname(obj);
2513 /* leave off "your" for most of your artifacts, but prepend
2514 * "your" for unique objects and "foo of bar" quest artifacts */
2515 if (!carried(obj) || !obj_is_pname(obj)
2516 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2517 char *outbuf = shk_your(nextobuf(), obj);
2518 int space_left = BUFSZ - 1 - strlen(outbuf);
2520 s = strncat(outbuf, s, space_left);
2526 /* capitalized variant of yname() */
2531 char *s = yname(obj);
2539 /* returns "your minimal_xname(obj)"
2540 * or "Foobar's minimal_xname(obj)"
2541 * or "the minimal_xname(obj)"
2547 char *outbuf = nextobuf();
2548 char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
2550 int space_left = BUFSZ - 1 - strlen(s);
2552 return strncat(s, minimal_xname(obj), space_left);
2554 int space_left = BUFSZ - strlen(s);
2556 return strncat(s, minimal_xname(obj), space_left);
2560 /* capitalized variant of ysimple_name() */
2565 char *s = ysimple_name(obj);
2573 /* "scroll" or "scrolls" */
2578 char *simpleoname = minimal_xname(obj);
2580 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2581 if (obj->quan != 1L)
2582 simpleoname = makeplural(simpleoname);
2587 /* "a scroll" or "scrolls"; "a silver bell" or "the Bell of Opening" */
2592 char *simpleoname = simpleonames(obj);
2593 int otyp = obj->otyp;
2595 /* prefix with "the" if a unique item, or a fake one imitating same,
2596 has been formatted with its actual name (we let typename() handle
2597 any `known' and `dknown' checking necessary) */
2598 if (otyp == FAKE_AMULET_OF_YENDOR)
2599 otyp = AMULET_OF_YENDOR;
2600 if (objects[otyp].oc_unique
2601 && !strcmp(simpleoname, OBJ_NAME(objects[otyp])))
2602 return the(simpleoname);
2604 /* simpleoname is singular if quan==1, plural otherwise */
2605 if (obj->quan == 1L)
2606 simpleoname = an(simpleoname);
2610 /* "the scroll" or "the scrolls" */
2615 char *simpleoname = simpleonames(obj);
2617 return the(simpleoname);
2620 /* artifact's name without any object type or known/dknown/&c feedback */
2622 bare_artifactname(obj)
2627 if (obj->oartifact) {
2628 outbuf = nextobuf();
2629 Strcpy(outbuf, artiname(obj->oartifact));
2631 if (!strncmp(outbuf, "The ", 4))
2632 outbuf[0] = lowc(outbuf[0]);
2635 outbuf = xname(obj);
2641 static const char *wrp[] = {
2642 "wand", "ring", "potion", "scroll", "gem",
2643 "amulet", "spellbook", "spell book",
2644 /* for non-specific wishes */
2645 "weapon", "armor", "tool", "food", "comestible",
2648 static const char wrpsym[] = { WAND_CLASS, RING_CLASS, POTION_CLASS,
2649 SCROLL_CLASS, GEM_CLASS, AMULET_CLASS,
2650 SPBOOK_CLASS, SPBOOK_CLASS, WEAPON_CLASS,
2651 ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
2654 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2655 /* return form of the verb (input plural) if xname(otmp) were the subject */
2664 * verb is given in plural (without trailing s). Return as input
2665 * if the result of xname(otmp) would be plural. Don't bother
2666 * recomputing xname(otmp) at this time.
2668 if (!is_plural(otmp))
2669 return vtense((char *) 0, verb);
2676 /* various singular words that vtense would otherwise categorize as plural;
2677 also used by makesingular() to catch some special cases */
2678 static const char *const special_subjs[] = {
2679 "erinys", "manes", /* this one is ambiguous */
2680 "Cyclops", "Hippocrates", "Pelias", "aklys",
2681 "amnesia", "detect monsters", "paralysis", "shape changers",
2683 /* note: "detect monsters" and "shape changers" are normally
2684 caught via "<something>(s) of <whatever>", but they can be
2685 wished for using the shorter form, so we include them here
2686 to accommodate usage by makesingular during wishing */
2689 /* return form of the verb (input plural) for present tense 3rd person subj */
2692 register const char *subj;
2693 register const char *verb;
2695 char *buf = nextobuf(), *bspot;
2697 const char *sp, *spot;
2698 const char *const *spec;
2701 * verb is given in plural (without trailing s). Return as input
2702 * if subj appears to be plural. Add special cases as necessary.
2703 * Many hard cases can already be handled by using otense() instead.
2704 * If this gets much bigger, consider decomposing makeplural.
2705 * Note: monster names are not expected here (except before corpse).
2707 * Special case: allow null sobj to get the singular 3rd person
2708 * present tense form so we don't duplicate this code elsewhere.
2711 if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
2713 spot = (const char *) 0;
2714 for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
2715 if (!strncmpi(sp, " of ", 4) || !strncmpi(sp, " from ", 6)
2716 || !strncmpi(sp, " called ", 8) || !strncmpi(sp, " named ", 7)
2717 || !strncmpi(sp, " labeled ", 9)) {
2723 len = (int) strlen(subj);
2725 spot = subj + len - 1;
2728 * plural: anything that ends in 's', but not '*us' or '*ss'.
2729 * Guess at a few other special cases that makeplural creates.
2731 if ((lowc(*spot) == 's' && spot != subj
2732 && !index("us", lowc(*(spot - 1))))
2733 || !BSTRNCMPI(subj, spot - 3, "eeth", 4)
2734 || !BSTRNCMPI(subj, spot - 3, "feet", 4)
2735 || !BSTRNCMPI(subj, spot - 1, "ia", 2)
2736 || !BSTRNCMPI(subj, spot - 1, "ae", 2)) {
2737 /* check for special cases to avoid false matches */
2738 len = (int) (spot - subj) + 1;
2739 for (spec = special_subjs; *spec; spec++) {
2740 ltmp = strlen(*spec);
2741 if (len == ltmp && !strncmpi(*spec, subj, len))
2743 /* also check for <prefix><space><special_subj>
2744 to catch things like "the invisible erinys" */
2745 if (len > ltmp && *(spot - ltmp) == ' '
2746 && !strncmpi(*spec, spot - ltmp + 1, ltmp))
2750 return strcpy(buf, verb);
2753 * 3rd person plural doesn't end in telltale 's';
2754 * 2nd person singular behaves as if plural.
2756 if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
2757 return strcpy(buf, verb);
2762 len = (int) strlen(buf);
2763 bspot = buf + len - 1;
2765 if (!strcmpi(buf, "are")) {
2766 Strcasecpy(buf, "is");
2767 } else if (!strcmpi(buf, "have")) {
2768 Strcasecpy(bspot - 1, "s");
2769 } else if (index("zxs", lowc(*bspot))
2770 || (len >= 2 && lowc(*bspot) == 'h'
2771 && index("cs", lowc(*(bspot - 1))))
2772 || (len == 2 && lowc(*bspot) == 'o')) {
2773 /* Ends in z, x, s, ch, sh; add an "es" */
2774 Strcasecpy(bspot + 1, "es");
2775 } else if (lowc(*bspot) == 'y' && !index(vowels, lowc(*(bspot - 1)))) {
2776 /* like "y" case in makeplural */
2777 Strcasecpy(bspot, "ies");
2779 Strcasecpy(bspot + 1, "s");
2788 const char *sing, *plur;
2791 /* word pairs that don't fit into formula-based transformations;
2792 also some suffices which have very few--often one--matches or
2793 which aren't systematically reversible (knives, staves) */
2794 static struct sing_plur one_off[] = {
2796 "children" }, /* (for wise guys who give their food funny names) */
2797 { "cubus", "cubi" }, /* in-/suc-cubus */
2798 { "culus", "culi" }, /* homunculus */
2799 { "djinni", "djinn" },
2800 { "erinys", "erinyes" },
2802 { "fungus", "fungi" },
2803 { "goose", "geese" },
2804 { "knife", "knives" },
2805 { "labrum", "labra" }, /* candelabrum */
2806 { "louse", "lice" },
2807 { "mouse", "mice" },
2808 { "mumak", "mumakil" },
2809 { "nemesis", "nemeses" },
2812 { "passerby", "passersby" },
2813 { "rtex", "rtices" }, /* vortex */
2814 { "serum", "sera" },
2815 { "staff", "staves" },
2816 { "tooth", "teeth" },
2820 static const char *const as_is[] = {
2821 /* makesingular() leaves these plural due to how they're used */
2822 "boots", "shoes", "gloves", "lenses", "scales",
2823 "eyes", "gauntlets", "iron bars",
2824 /* both singular and plural are spelled the same */
2825 "bison", "deer", "elk", "fish", "fowl",
2826 "tuna", "yaki", "-hai", "krill", "manes",
2827 "moose", "ninja", "sheep", "ronin", "roshi",
2828 "shito", "tengu", "ki-rin", "Nazgul", "gunyoki",
2829 "piranha", "samurai", "shuriken", 0,
2830 /* Note: "fish" and "piranha" are collective plurals, suitable
2831 for "wiped out all <foo>". For "3 <foo>", they should be
2832 "fishes" and "piranhas" instead. We settle for collective
2833 variant instead of attempting to support both. */
2836 /* singularize/pluralize decisions common to both makesingular & makeplural */
2838 singplur_lookup(basestr, endstring, to_plural, alt_as_is)
2839 char *basestr, *endstring; /* base string, pointer to eos(string) */
2840 boolean to_plural; /* true => makeplural, false => makesingular */
2841 const char *const *alt_as_is; /* another set like as_is[] */
2843 const struct sing_plur *sp;
2844 const char *same, *other, *const *as;
2846 int baselen = strlen(basestr);
2848 for (as = as_is; *as; ++as) {
2849 al = (int) strlen(*as);
2850 if (!BSTRCMPI(basestr, endstring - al, *as))
2854 for (as = alt_as_is; *as; ++as) {
2855 al = (int) strlen(*as);
2856 if (!BSTRCMPI(basestr, endstring - al, *as))
2861 /* Leave "craft" as a suffix as-is (aircraft, hovercraft);
2862 "craft" itself is (arguably) not included in our likely context */
2863 if ((baselen > 5) && (!BSTRCMPI(basestr, endstring - 5, "craft")))
2865 /* avoid false hit on one_off[].plur == "lice" or .sing == "goose";
2866 if more of these turn up, one_off[] entries will need to flagged
2867 as to which are whole words and which are matchable as suffices
2868 then matching in the loop below will end up becoming more complex */
2869 if (!strcmpi(basestr, "slice")
2870 || !strcmpi(basestr, "mongoose")) {
2872 Strcasecpy(endstring, "s");
2875 /* skip "ox" -> "oxen" entry when pluralizing "<something>ox"
2876 unless it is muskox */
2877 if (to_plural && baselen > 2 && !strcmpi(endstring - 2, "ox")
2878 && !(baselen > 5 && !strcmpi(endstring - 6, "muskox"))) {
2879 /* "fox" -> "foxes" */
2880 Strcasecpy(endstring, "es");
2884 if (baselen > 2 && !strcmpi(endstring - 3, "man")
2885 && badman(basestr, to_plural)) {
2886 Strcasecpy(endstring, "s");
2890 if (baselen > 2 && !strcmpi(endstring - 3, "men")
2891 && badman(basestr, to_plural))
2894 for (sp = one_off; sp->sing; sp++) {
2895 /* check whether endstring already matches */
2896 same = to_plural ? sp->plur : sp->sing;
2897 al = (int) strlen(same);
2898 if (!BSTRCMPI(basestr, endstring - al, same))
2899 return TRUE; /* use as-is */
2900 /* check whether it matches the inverse; if so, transform it */
2901 other = to_plural ? sp->sing : sp->plur;
2902 al = (int) strlen(other);
2903 if (!BSTRCMPI(basestr, endstring - al, other)) {
2904 Strcasecpy(endstring - al, same);
2905 return TRUE; /* one_off[] transformation */
2911 /* searches for common compounds, ex. lump of royal jelly */
2913 singplur_compound(str)
2916 /* if new entries are added, be sure to keep compound_start[] in sync */
2917 static const char *const compounds[] =
2919 " of ", " labeled ", " called ",
2920 " named ", " above", /* lurkers above */
2921 " versus ", " from ", " in ",
2922 " on ", " a la ", " with", /* " with "? */
2923 " de ", " d'", " du ",
2925 }, /* list of first characters for all compounds[] entries */
2926 compound_start[] = " -";
2928 const char *const *cmpd;
2931 for (p = str; *p; ++p) {
2932 /* substring starting at p can only match if *p is found
2933 within compound_start[] */
2934 if (!index(compound_start, *p))
2937 /* check current substring against all words in the compound[] list */
2938 for (cmpd = compounds; *cmpd; ++cmpd)
2939 if (!strncmpi(p, *cmpd, (int) strlen(*cmpd)))
2942 /* wasn't recognized as a compound phrase */
2947 /* Plural routine; once upon a time it may have been chiefly used for
2948 * user-defined fruits, but it is now used extensively throughout the
2951 * For fruit, we have to try to account for everything reasonable the
2952 * player has; something unreasonable can still break the code.
2953 * However, it's still a lot more accurate than "just add an 's' at the
2954 * end", which Rogue uses...
2956 * Also used for plural monster names ("Wiped out all homunculi." or the
2957 * vanquished monsters list) and body parts. A lot of unique monsters have
2958 * names which get mangled by makeplural and/or makesingular. They're not
2959 * genocidable, and vanquished-mon handling does its own special casing
2960 * (for uniques who've been revived and re-killed), so we don't bother
2961 * trying to get those right here.
2963 * Also misused by muse.c to convert 1st person present verbs to 2nd person.
2964 * 3.6.0: made case-insensitive.
2970 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2971 register char *spot;
2972 char lo_c, *str = nextobuf();
2973 const char *excess = (char *) 0;
2977 while (*oldstr == ' ')
2979 if (!oldstr || !*oldstr) {
2980 impossible("plural of null?");
2984 Strcpy(str, oldstr);
2987 * Skip changing "pair of" to "pairs of". According to Webster, usual
2988 * English usage is use pairs for humans, e.g. 3 pairs of dancers,
2989 * and pair for objects and non-humans, e.g. 3 pair of boots. We don't
2990 * refer to pairs of humans in this game so just skip to the bottom.
2992 if (!strncmpi(str, "pair of ", 8))
2995 /* look for "foo of bar" so that we can focus on "foo" */
2996 if ((spot = singplur_compound(str)) != 0) {
2997 excess = oldstr + (int) (spot - str);
3003 while (spot > str && *spot == ' ')
3004 spot--; /* Strip blanks from end */
3006 /* Now spot is the last character of the string */
3010 /* Single letters */
3011 if (len == 1 || !letter(*spot)) {
3012 Strcpy(spot + 1, "'s");
3016 /* dispense with some words which don't need pluralization */
3018 static const char *const already_plural[] = {
3019 "ae", /* algae, larvae, &c */
3023 /* spot+1: synch up with makesingular's usage */
3024 if (singplur_lookup(str, spot + 1, TRUE, already_plural))
3027 /* more of same, but not suitable for blanket loop checking */
3028 if ((len == 2 && !strcmpi(str, "ya"))
3029 || (len >= 3 && !strcmpi(spot - 2, " ya")))
3033 /* man/men ("Wiped out all cavemen.") */
3034 if (len >= 3 && !strcmpi(spot - 2, "man")
3035 /* exclude shamans and humans etc */
3036 && !badman(str, TRUE)) {
3037 Strcasecpy(spot - 1, "en");
3040 if (lowc(*spot) == 'f') { /* (staff handled via one_off[]) */
3041 lo_c = lowc(*(spot - 1));
3042 if (len >= 3 && !strcmpi(spot - 2, "erf")) {
3043 /* avoid "nerf" -> "nerves", "serf" -> "serves" */
3044 ; /* fall through to default (append 's') */
3045 } else if (index("lr", lo_c) || index(vowels, lo_c)) {
3046 /* [aeioulr]f to [aeioulr]ves */
3047 Strcasecpy(spot, "ves");
3051 /* ium/ia (mycelia, baluchitheria) */
3052 if (len >= 3 && !strcmpi(spot - 2, "ium")) {
3053 Strcasecpy(spot - 2, "ia");
3056 /* algae, larvae, hyphae (another fungus part) */
3057 if ((len >= 4 && !strcmpi(spot - 3, "alga"))
3059 && (!strcmpi(spot - 4, "hypha") || !strcmpi(spot - 4, "larva")))
3060 || (len >= 6 && !strcmpi(spot - 5, "amoeba"))
3061 || (len >= 8 && (!strcmpi(spot - 7, "vertebra")))) {
3063 Strcasecpy(spot + 1, "e");
3066 /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
3067 if (len > 3 && !strcmpi(spot - 1, "us")
3068 && !((len >= 5 && !strcmpi(spot - 4, "lotus"))
3069 || (len >= 6 && !strcmpi(spot - 5, "wumpus")))) {
3070 Strcasecpy(spot - 1, "i");
3073 /* sis/ses (nemesis) */
3074 if (len >= 3 && !strcmpi(spot - 2, "sis")) {
3075 Strcasecpy(spot - 1, "es");
3078 /* matzoh/matzot, possible food name */
3080 && (!strcmpi(spot - 5, "matzoh") || !strcmpi(spot - 5, "matzah"))) {
3081 Strcasecpy(spot - 1, "ot"); /* oh/ah -> ot */
3085 && (!strcmpi(spot - 4, "matzo") || !strcmpi(spot - 4, "matza"))) {
3086 Strcasecpy(spot, "ot"); /* o/a -> ot */
3090 /* note: -eau/-eaux (gateau, bordeau...) */
3091 /* note: ox/oxen, VAX/VAXen, goose/geese */
3095 /* codex/spadix/neocortex and the like */
3097 && (!strcmpi(spot - 2, "dex")
3098 ||!strcmpi(spot - 2, "dix")
3099 ||!strcmpi(spot - 2, "tex"))
3100 /* indices would have been ok too, but stick with indexes */
3101 && (strcmpi(spot - 4,"index") != 0)) {
3102 Strcasecpy(spot - 1, "ices"); /* ex|ix -> ices */
3105 /* Ends in z, x, s, ch, sh; add an "es" */
3106 if (index("zxs", lo_c)
3107 || (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot - 1)))
3108 /* 21st century k-sound */
3110 ((lowc(*(spot - 2)) == 'e'
3111 && index("mt", lowc(*(spot - 3)))) ||
3112 (lowc(*(spot - 2)) == 'o'
3113 && index("lp", lowc(*(spot - 3)))))))
3114 /* Kludge to get "tomatoes" and "potatoes" right */
3115 || (len >= 4 && !strcmpi(spot - 2, "ato"))
3116 || (len >= 5 && !strcmpi(spot - 4, "dingo"))) {
3117 Strcasecpy(spot + 1, "es"); /* append es */
3120 /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
3121 if (lo_c == 'y' && !index(vowels, lowc(*(spot - 1)))) {
3122 Strcasecpy(spot, "ies"); /* y -> ies */
3125 /* Default: append an 's' */
3126 Strcasecpy(spot + 1, "s");
3130 Strcat(str, excess);
3131 #else /*JP*//*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
3132 char *str = nextobuf();
3133 Strcpy(str, oldstr);
3139 * Singularize a string the user typed in; this helps reduce the complexity
3140 * of readobjnam, and is also used in pager.c to singularize the string
3141 * for which help is sought.
3143 * "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)?
3144 * Its inclusion in as_is[]/special_subj[] makes it get treated as the former.
3146 * A lot of unique monsters have names ending in s; plural, or singular
3147 * from plural, doesn't make much sense for them so we don't bother trying.
3148 * 3.6.0: made case-insensitive.
3151 makesingular(oldstr)
3154 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
3155 register char *p, *bp;
3156 const char *excess = 0;
3157 char *str = nextobuf();
3160 while (*oldstr == ' ')
3162 if (!oldstr || !*oldstr) {
3163 impossible("singular of null?");
3168 bp = strcpy(str, oldstr);
3170 /* check for "foo of bar" so that we can focus on "foo" */
3171 if ((p = singplur_compound(bp)) != 0) {
3172 excess = oldstr + (int) (p - bp);
3177 /* dispense with some words which don't need singularization */
3178 if (singplur_lookup(bp, p, FALSE, special_subjs))
3181 /* remove -s or -es (boxes) or -ies (rubies) */
3182 if (p >= bp + 1 && lowc(p[-1]) == 's') {
3183 if (p >= bp + 2 && lowc(p[-2]) == 'e') {
3184 if (p >= bp + 3 && lowc(p[-3]) == 'i') { /* "ies" */
3185 if (!BSTRCMPI(bp, p - 7, "cookies")
3186 || (!BSTRCMPI(bp, p - 4, "pies")
3187 /* avoid false match for "harpies" */
3188 && (p - 4 == bp || p[-5] == ' '))
3189 /* alternate djinni/djinn spelling; not really needed */
3190 || (!BSTRCMPI(bp, p - 6, "genies")
3191 /* avoid false match for "progenies" */
3192 && (p - 6 == bp || p[-7] == ' '))
3193 || !BSTRCMPI(bp, p - 5, "mbies") /* zombie */
3194 || !BSTRCMPI(bp, p - 5, "yries")) /* valkyrie */
3196 Strcasecpy(p - 3, "y"); /* ies -> y */
3199 /* wolves, but f to ves isn't fully reversible */
3200 if (p - 4 >= bp && (index("lr", lowc(*(p - 4)))
3201 || index(vowels, lowc(*(p - 4))))
3202 && !BSTRCMPI(bp, p - 3, "ves")) {
3203 if (!BSTRCMPI(bp, p - 6, "cloves")
3204 || !BSTRCMPI(bp, p - 6, "nerves"))
3206 Strcasecpy(p - 3, "f"); /* ves -> f */
3209 /* note: nurses, axes but boxes, wumpuses */
3210 if (!BSTRCMPI(bp, p - 4, "eses")
3211 || !BSTRCMPI(bp, p - 4, "oxes") /* boxes, foxes */
3212 || !BSTRCMPI(bp, p - 4, "nxes") /* lynxes */
3213 || !BSTRCMPI(bp, p - 4, "ches")
3214 || !BSTRCMPI(bp, p - 4, "uses") /* lotuses */
3215 || !BSTRCMPI(bp, p - 4, "sses") /* priestesses */
3216 || !BSTRCMPI(bp, p - 5, "atoes") /* tomatoes */
3217 || !BSTRCMPI(bp, p - 7, "dingoes")
3218 || !BSTRCMPI(bp, p - 7, "Aleaxes")) {
3219 *(p - 2) = '\0'; /* drop es */
3221 } /* else fall through to mins */
3223 /* ends in 's' but not 'es' */
3224 } else if (!BSTRCMPI(bp, p - 2, "us")) { /* lotus, fungus... */
3225 if (BSTRCMPI(bp, p - 6, "tengus") /* but not these... */
3226 && BSTRCMPI(bp, p - 7, "hezrous"))
3228 } else if (!BSTRCMPI(bp, p - 2, "ss")
3229 || !BSTRCMPI(bp, p - 5, " lens")
3230 || (p - 4 == bp && !strcmpi(p - 4, "lens"))) {
3234 *(p - 1) = '\0'; /* drop s */
3236 } else { /* input doesn't end in 's' */
3238 if (!BSTRCMPI(bp, p - 3, "men")
3239 && !badman(bp, FALSE)) {
3240 Strcasecpy(p - 2, "an");
3243 /* matzot -> matzo, algae -> alga */
3244 if (!BSTRCMPI(bp, p - 6, "matzot") || !BSTRCMPI(bp, p - 2, "ae")) {
3245 *(p - 1) = '\0'; /* drop t/e */
3248 /* balactheria -> balactherium */
3249 if (p - 4 >= bp && !strcmpi(p - 2, "ia")
3250 && index("lr", lowc(*(p - 3))) && lowc(*(p - 4)) == 'e') {
3251 Strcasecpy(p - 1, "um"); /* a -> um */
3254 /* here we cannot find the plural suffix */
3258 /* if we stripped off a suffix (" of bar" from "foo of bar"),
3259 put it back now [strcat() isn't actually 100% safe here...] */
3264 #else /*JP*//*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
3265 char *str = nextobuf();
3266 Strcpy(str, oldstr);
3273 badman(basestr, to_plural)
3274 const char *basestr;
3275 boolean to_plural; /* true => makeplural, false => makesingular */
3277 /* these are all the prefixes for *man that don't have a *men plural */
3278 static const char *no_men[] = {
3279 "albu", "antihu", "anti", "ata", "auto", "bildungsro", "cai", "cay",
3280 "ceru", "corner", "decu", "des", "dura", "fir", "hanu", "het",
3281 "infrahu", "inhu", "nonhu", "otto", "out", "prehu", "protohu",
3282 "subhu", "superhu", "talis", "unhu", "sha",
3283 "hu", "un", "le", "re", "so", "to", "at", "a",
3285 /* these are all the prefixes for *men that don't have a *man singular */
3286 static const char *no_man[] = {
3287 "abdo", "acu", "agno", "ceru", "cogno", "cycla", "fleh", "grava",
3288 "hegu", "preno", "sonar", "speci", "dai", "exa", "fla", "sta", "teg",
3289 "tegu", "vela", "da", "hy", "lu", "no", "nu", "ra", "ru", "se", "vi",
3293 const char *endstr, *spot;
3295 if (!basestr || strlen(basestr) < 4)
3298 endstr = eos((char *) basestr);
3301 for (i = 0; i < SIZE(no_men); i++) {
3302 al = (int) strlen(no_men[i]);
3303 spot = endstr - (al + 3);
3304 if (!BSTRNCMPI(basestr, spot, no_men[i], al)
3305 && (spot == basestr || *(spot - 1) == ' '))
3309 for (i = 0; i < SIZE(no_man); i++) {
3310 al = (int) strlen(no_man[i]);
3311 spot = endstr - (al + 3);
3312 if (!BSTRNCMPI(basestr, spot, no_man[i], al)
3313 && (spot == basestr || *(spot - 1) == ' '))
3321 /* compare user string against object name string using fuzzy matching */
3323 wishymatch(u_str, o_str, retry_inverted)
3324 const char *u_str; /* from user, so might be variant spelling */
3325 const char *o_str; /* from objects[], so is in canonical form */
3326 boolean retry_inverted; /* optional extra "of" handling */
3328 static NEARDATA const char detect_SP[] = "detect ",
3329 SP_detection[] = " detection";
3330 char *p, buf[BUFSZ];
3332 /* ignore spaces & hyphens and upper/lower case when comparing */
3333 if (fuzzymatch(u_str, o_str, " -", TRUE))
3336 if (retry_inverted) {
3337 const char *u_of, *o_of;
3339 /* when just one of the strings is in the form "foo of bar",
3340 convert it into "bar foo" and perform another comparison */
3341 u_of = strstri(u_str, " of ");
3342 o_of = strstri(o_str, " of ");
3343 if (u_of && !o_of) {
3344 Strcpy(buf, u_of + 4);
3345 p = eos(strcat(buf, " "));
3346 while (u_str < u_of)
3349 return fuzzymatch(buf, o_str, " -", TRUE);
3350 } else if (o_of && !u_of) {
3351 Strcpy(buf, o_of + 4);
3352 p = eos(strcat(buf, " "));
3353 while (o_str < o_of)
3356 return fuzzymatch(u_str, buf, " -", TRUE);
3360 /* [note: if something like "elven speed boots" ever gets added, these
3361 special cases should be changed to call wishymatch() recursively in
3362 order to get the "of" inversion handling] */
3363 if (!strncmp(o_str, "dwarvish ", 9)) {
3364 if (!strncmpi(u_str, "dwarven ", 8))
3365 return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
3366 } else if (!strncmp(o_str, "elven ", 6)) {
3367 if (!strncmpi(u_str, "elvish ", 7))
3368 return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
3369 else if (!strncmpi(u_str, "elfin ", 6))
3370 return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
3371 } else if (!strncmp(o_str, detect_SP, sizeof detect_SP - 1)) {
3372 /* check for "detect <foo>" vs "<foo> detection" */
3373 if ((p = strstri(u_str, SP_detection)) != 0
3374 && !*(p + sizeof SP_detection - 1)) {
3375 /* convert "<foo> detection" into "detect <foo>" */
3377 Strcat(strcpy(buf, detect_SP), u_str);
3378 /* "detect monster" -> "detect monsters" */
3379 if (!strcmpi(u_str, "monster"))
3382 return fuzzymatch(buf, o_str, " -", TRUE);
3384 } else if (strstri(o_str, SP_detection)) {
3385 /* and the inverse, "<foo> detection" vs "detect <foo>" */
3386 if (!strncmpi(u_str, detect_SP, sizeof detect_SP - 1)) {
3387 /* convert "detect <foo>s" into "<foo> detection" */
3388 p = makesingular(u_str + sizeof detect_SP - 1);
3389 Strcat(strcpy(buf, p), SP_detection);
3390 /* caller may be looping through objects[], so avoid
3391 churning through all the obufs */
3393 return fuzzymatch(buf, o_str, " -", TRUE);
3395 } else if (strstri(o_str, "ability")) {
3396 /* when presented with "foo of bar", makesingular() used to
3397 singularize both foo & bar, but now only does so for foo */
3398 /* catch "{potion(s),ring} of {gain,restore,sustain} abilities" */
3399 if ((p = strstri(u_str, "abilities")) != 0
3400 && !*(p + sizeof "abilities" - 1)) {
3401 (void) strncpy(buf, u_str, (unsigned) (p - u_str));
3402 Strcpy(buf + (p - u_str), "ability");
3403 return fuzzymatch(buf, o_str, " -", TRUE);
3405 } else if (!strcmp(o_str, "aluminum")) {
3406 /* this special case doesn't really fit anywhere else... */
3407 /* (note that " wand" will have been stripped off by now) */
3408 if (!strcmpi(u_str, "aluminium"))
3409 return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
3416 const char *name, oclass;
3417 int f_o_range, l_o_range;
3420 #if 0 /*JP*//*
\95\94\95ª
\93I
\82È
\83W
\83\83\83\93\83\8b\8ew
\92è
\82Å
\82Ì
\8aè
\82¢
\97p
\81B
\93ú
\96{
\8cê
\82Å
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢*/
3421 /* wishable subranges of objects */
3422 STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
3423 { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
3424 { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
3425 { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
3426 { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
3427 { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
3428 { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
3429 { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
3430 { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3431 { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3432 { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
3433 { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
3434 { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
3435 { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
3436 { "dragon scales", ARMOR_CLASS, GRAY_DRAGON_SCALES,
3437 YELLOW_DRAGON_SCALES },
3438 { "dragon scale mail", ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL,
3439 YELLOW_DRAGON_SCALE_MAIL },
3440 { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
3441 { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
3442 { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
3443 { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
3448 #if 0 /*JP*//*not used*/
3449 /* alternate spellings; if the difference is only the presence or
3450 absence of spaces and/or hyphens (such as "pickaxe" vs "pick axe"
3451 vs "pick-axe") then there is no need for inclusion in this list;
3452 likewise for ``"of" inversions'' ("boots of speed" vs "speed boots") */
3453 static const struct alt_spellings {
3457 { "pickax", PICK_AXE },
3458 { "whip", BULLWHIP },
3459 { "saber", SILVER_SABER },
3460 { "silver sabre", SILVER_SABER },
3461 { "smooth shield", SHIELD_OF_REFLECTION },
3462 { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
3463 { "grey dragon scales", GRAY_DRAGON_SCALES },
3464 { "iron ball", HEAVY_IRON_BALL },
3465 { "lantern", BRASS_LANTERN },
3466 { "mattock", DWARVISH_MATTOCK },
3467 { "amulet of poison resistance", AMULET_VERSUS_POISON },
3468 { "potion of sleep", POT_SLEEPING },
3470 { "camera", EXPENSIVE_CAMERA },
3471 { "tee shirt", T_SHIRT },
3473 { "can opener", TIN_OPENER },
3474 { "kelp", KELP_FROND },
3475 { "eucalyptus", EUCALYPTUS_LEAF },
3476 { "royal jelly", LUMP_OF_ROYAL_JELLY },
3477 { "lembas", LEMBAS_WAFER },
3478 { "cookie", FORTUNE_COOKIE },
3479 { "pie", CREAM_PIE },
3480 { "marker", MAGIC_MARKER },
3481 { "hook", GRAPPLING_HOOK },
3482 { "grappling iron", GRAPPLING_HOOK },
3483 { "grapnel", GRAPPLING_HOOK },
3484 { "grapple", GRAPPLING_HOOK },
3485 { "protection from shape shifters", RIN_PROTECTION_FROM_SHAPE_CHAN },
3486 /* if we ever add other sizes, move this to o_ranges[] with "bag" */
3487 { "box", LARGE_BOX },
3488 /* normally we wouldn't have to worry about unnecessary <space>, but
3489 " stone" will get stripped off, preventing a wishymatch; that actually
3490 lets "flint stone" be a match, so we also accept bogus "flintstone" */
3491 { "luck stone", LUCKSTONE },
3492 { "load stone", LOADSTONE },
3493 { "touch stone", TOUCHSTONE },
3494 { "flintstone", FLINT },
3495 { (const char *) 0, 0 },
3499 rnd_otyp_by_wpnskill(skill)
3503 short otyp = STRANGE_OBJECT;
3505 for (i = bases[WEAPON_CLASS];
3506 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3507 if (objects[i].oc_skill == skill) {
3513 for (i = bases[WEAPON_CLASS];
3514 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3515 if (objects[i].oc_skill == skill)
3524 rnd_otyp_by_namedesc(name, oclass, xtra_prob)
3527 int xtra_prob; /* to force 0% random generation items to also be considered */
3530 short validobjs[NUM_OBJECTS];
3531 register const char *zn;
3532 int prob, maxprob = 0;
3534 if (!name || !*name)
3535 return STRANGE_OBJECT;
3537 memset((genericptr_t) validobjs, 0, sizeof validobjs);
3540 * When this spans classes (the !oclass case), the item
3541 * probabilities are not very useful because they don't take
3542 * the class generation probability into account. [If 10%
3543 * of spellbooks were blank and 1% of scrolls were blank,
3544 * "blank" would have 10/11 chance to yield a book even though
3545 * scrolls are supposed to be much more common than books.]
3547 for (i = oclass ? bases[(int) oclass] : STRANGE_OBJECT + 1;
3548 i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
3550 /* don't match extra descriptions (w/o real name) */
3551 if ((zn = OBJ_NAME(objects[i])) == 0)
3555 *
\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É
3556 *
\82È
\82ç
\82È
\82¢
\82æ
\82¤
\82É
\82·
\82é
\81B
3557 *
\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
3559 if (i == FAKE_AMULET_OF_YENDOR)
3562 if (wishymatch(name, zn, TRUE)
3563 || ((zn = OBJ_DESCR(objects[i])) != 0
3564 && wishymatch(name, zn, FALSE))
3565 || ((zn = objects[i].oc_uname) != 0
3566 && wishymatch(name, zn, FALSE))) {
3567 validobjs[n++] = (short) i;
3568 maxprob += (objects[i].oc_prob + xtra_prob);
3572 if (n > 0 && maxprob) {
3573 prob = rn2(maxprob);
3574 for (i = 0; i < n - 1; i++)
3575 if ((prob -= (objects[validobjs[i]].oc_prob + xtra_prob)) < 0)
3577 return validobjs[i];
3579 return STRANGE_OBJECT;
3586 return (int) rnd_otyp_by_namedesc("shiny", oclass, 0);
3590 * Return something wished for. Specifying a null pointer for
3591 * the user request string results in a random object. Otherwise,
3592 * if asking explicitly for "nothing" (or "nil") return no_wish;
3593 * if not an object return &zeroobj; if an error (no matching object),
3598 readobjnam(bp, no_wish)
3600 struct obj *no_wish;
3604 register struct obj *otmp;
3605 int cnt, spe, spesgn, typ, very, rechrg;
3606 int blessed, uncursed, iscursed, ispoisoned, isgreased;
3607 int eroded, eroded2, erodeproof, locked, unlocked, broken;
3608 int halfeaten, mntmp, contents;
3609 int islit, unlabeled, ishistoric, isdiluted, trapped;
3611 int tmp, tinv, tvariety;
3615 int wetness, gsize = 0;
3617 int ftype = context.current_fruit;
3619 char fruitbuf[BUFSZ], globbuf[BUFSZ];
3621 char fruitbuf[BUFSZ];
3623 /* Fruits may not mess up the ability to wish for real objects (since
3624 * you can leave a fruit in a bones file and it will be added to
3625 * another person's game), so they must be checked for last, after
3626 * stripping all the possible prefixes and seeing if there's a real
3627 * name in there. So we have to save the full original name. However,
3628 * it's still possible to do things like "uncursed burnt Alaska",
3629 * or worse yet, "2 burned 5 course meals", so we need to loop to
3630 * strip off the prefixes again, this time stripping only the ones
3632 * We could get even more detailed so as to allow food names with
3633 * prefixes that _are_ possible on food, so you could wish for
3634 * "2 3 alarm chilis". Currently this isn't allowed; options.c
3635 * automatically sticks 'candied' in front of such names.
3638 char *un, *dn, *actualn, *origbp = bp;
3639 const char *name = 0;
3641 cnt = spe = spesgn = typ = 0;
3642 very = rechrg = blessed = uncursed = iscursed = ispoisoned =
3643 isgreased = eroded = eroded2 = erodeproof = halfeaten =
3644 islit = unlabeled = ishistoric = isdiluted = trapped =
3645 locked = unlocked = broken = 0;
3646 tvariety = RANDOM_TIN;
3651 contents = UNDEFINED;
3653 actualn = dn = un = 0;
3658 /* first, remove extra whitespace they may have typed */
3659 (void) mungspaces(bp);
3660 /* allow wishing for "nothing" to preserve wishless conduct...
3661 [now requires "wand of nothing" if that's what was really wanted] */
3663 if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil")
3664 || !strcmpi(bp, "none"))
3666 if (!strcmpi(bp, "
\82È
\82µ") || !strcmpi(bp, "
\96³
\82µ"))
3669 /* save the [nearly] unmodified choice string */
3670 Strcpy(fruitbuf, bp);
3677 if (!strncmpi(bp, "an ", l = 3) || !strncmpi(bp, "a ", l = 2)) {
3679 } else if (!strncmpi(bp, "the ", l = 4)) {
3680 ; /* just increment `bp' by `l' below */
3681 } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
3688 #if 1 /*JP*//*
\8cã
\82É
\90\94\8e\8c\82ª
\82 \82é
\82Æ
\82«
\82Í
\8dí
\8f\9c */
3689 if(!STRNCMPEX(bp, "
\8dû
\82Ì") ||
3690 !STRNCMPEX(bp, "
\96{
\82Ì") ||
3691 !STRNCMPEX(bp, "
\92\85\82Ì") ||
3692 !STRNCMPEX(bp, "
\8cÂ
\82Ì") ||
3693 !STRNCMPEX(bp, "
\96\87\82Ì") ||
3694 !STRNCMPEX(bp, "
\82Â
\82Ì") ||
3695 !STRNCMPEX(bp, "
\82Ì"))
3700 } else if (*bp == '+' || *bp == '-') {
3701 spesgn = (*bp++ == '+') ? 1 : -1;
3709 } else if (!strncmpi(bp, "blessed ", l = 8)
3710 || !strncmpi(bp, "holy ", l = 5)) {
3712 } else if (!STRNCMPEX(bp, "
\8fj
\95\9f\82³
\82ê
\82½")) {
3716 } else if (!strncmpi(bp, "moist ", l = 6)
3717 || !strncmpi(bp, "wet ", l = 4)) {
3719 } else if (!STRNCMPEX(bp, "
\8e¼
\82Á
\82½")
3720 || !STRNCMPEX(bp, "
\94G
\82ê
\82½")) {
3723 if (!strncmpi(bp, "wet ", 4))
3725 if (!STRNCMP2(bp, "
\94G
\82ê
\82½"))
3727 wetness = rn2(3) + 3;
3731 } else if (!strncmpi(bp, "cursed ", l = 7)
3732 || !strncmpi(bp, "unholy ", l = 7)) {
3734 } else if (!STRNCMPEX(bp, "
\8eô
\82í
\82ê
\82½")) {
3738 } else if (!strncmpi(bp, "uncursed ", l = 9)) {
3740 } else if (!STRNCMPEX(bp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢")) {
3744 } else if (!strncmpi(bp, "rustproof ", l = 10)
3745 || !strncmpi(bp, "erodeproof ", l = 11)
3746 || !strncmpi(bp, "corrodeproof ", l = 13)
3747 || !strncmpi(bp, "fixed ", l = 6)
3748 || !strncmpi(bp, "fireproof ", l = 10)
3749 || !strncmpi(bp, "rotproof ", l = 9)) {
3751 } else if (!STRNCMPEX(bp, "
\8eK
\82Ñ
\82È
\82¢")
3752 || !STRNCMPEX(bp, "
\95\85\90H
\82µ
\82È
\82¢")
3753 || !STRNCMPEX(bp, "
\88À
\92è
\82µ
\82½")
3754 || !STRNCMPEX(bp, "
\94R
\82¦
\82È
\82¢")) {
3758 } else if (!strncmpi(bp, "lit ", l = 4)
3759 || !strncmpi(bp, "burning ", l = 8)) {
3761 } else if (!STRNCMPEX(bp, "
\8cõ
\82Á
\82Ä
\82¢
\82é")
3762 || !STRNCMPEX(bp, "
\94R
\82¦
\82Ä
\82¢
\82é")) {
3766 } else if (!strncmpi(bp, "unlit ", l = 6)
3767 || !strncmpi(bp, "extinguished ", l = 13)) {
3769 } else if (!STRNCMPEX(bp, "
\8fÁ
\82¦
\82Ä
\82¢
\82é")) {
3772 /* "unlabeled" and "blank" are synonymous */
3774 } else if (!strncmpi(bp, "unlabeled ", l = 10)
3775 || !strncmpi(bp, "unlabelled ", l = 11)
3776 || !strncmpi(bp, "blank ", l = 6)) {
3778 } else if (!STRNCMPEX(bp, "
\83\89\83x
\83\8b\82Ì
\82È
\82¢")
3779 || !STRNCMPEX(bp, "
\90^
\82Á
\94\92\82È")) {
3783 } else if (!strncmpi(bp, "poisoned ", l = 9)) {
3785 } else if (!STRNCMPEX(bp, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½")) {
3788 /* "trapped" recognized but not honored outside wizard mode */
3789 } else if (!strncmpi(bp, "trapped ", l = 8)) {
3790 trapped = 0; /* undo any previous "untrapped" */
3793 } else if (!strncmpi(bp, "untrapped ", l = 10)) {
3794 trapped = 2; /* not trapped */
3795 /* locked, unlocked, broken: box/chest lock states */
3797 } else if (!strncmpi(bp, "locked ", l = 7)) {
3799 } else if (!STRNCMPEX(bp, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82½")) {
3801 locked = 1, unlocked = broken = 0;
3803 } else if (!strncmpi(bp, "unlocked ", l = 9)) {
3805 } else if (!STRNCMPEX(bp, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82Ä
\82¢
\82È
\82¢")) {
3807 unlocked = 1, locked = broken = 0;
3809 } else if (!strncmpi(bp, "broken ", l = 7)) {
3811 } else if (!STRNCMPEX(bp, "
\8c®
\82Ì
\89ó
\82ê
\82½")) {
3813 broken = 1, locked = unlocked = 0;
3815 } else if (!strncmpi(bp, "greased ", l = 8)) {
3817 } else if (!STRNCMPEX(bp, "
\96û
\82Ì
\93h
\82ç
\82ê
\82½")
3818 || !STRNCMPEX(bp, "
\8e\89\82Ì
\93h
\82ç
\82ê
\82½")) {
3822 } else if (!strncmpi(bp, "very ", l = 5)) {
3824 } else if (!STRNCMPEX(bp, "
\82Æ
\82Ä
\82à")) {
3826 /* very rusted very heavy iron ball */
3829 } else if (!strncmpi(bp, "thoroughly ", l = 11)) {
3831 } else if (!STRNCMPEX(bp, "
\82©
\82È
\82è")) {
3835 } else if (!strncmpi(bp, "rusty ", l = 6)
3836 || !strncmpi(bp, "rusted ", l = 7)
3837 || !strncmpi(bp, "burnt ", l = 6)
3838 || !strncmpi(bp, "burned ", l = 7)) {
3840 } else if (!STRNCMPEX(bp, "
\8eK
\82Ñ
\82½")
3841 || !STRNCMPEX(bp, "
\94R
\82¦
\82½")) {
3846 } else if (!strncmpi(bp, "corroded ", l = 9)
3847 || !strncmpi(bp, "rotted ", l = 7)) {
3849 } else if (!STRNCMPEX(bp, "
\95\85\90H
\82µ
\82½")
3850 || !STRNCMPEX(bp, "
\95\85\82Á
\82½")) {
3855 } else if (!strncmpi(bp, "partly eaten ", l = 13)
3856 || !strncmpi(bp, "partially eaten ", l = 16)) {
3858 } else if (!STRNCMPEX(bp, "
\90H
\82×
\82©
\82¯
\82Ì")) {
3862 } else if (!strncmpi(bp, "historic ", l = 9)) {
3864 } else if (!STRNCMPEX(bp, "
\97ð
\8ej
\93I
\82È")) {
3868 } else if (!strncmpi(bp, "diluted ", l = 8)) {
3870 } else if (!STRNCMPEX(bp, "
\94\96\82Ü
\82Á
\82½")) {
3874 } else if (!strncmpi(bp, "empty ", l = 6)) {
3876 } else if (!STRNCMPEX(bp, "
\8bó
\82Á
\82Û
\82Ì")) {
3880 } else if (!strncmpi(bp, "small ", l = 6)) { /* glob sizes */
3882 } else if (!STRNCMPEX(bp, "
\8f¬
\82³
\82¢")) { /* glob sizes */
3884 /* "small" might be part of monster name (mimic, if wishing
3885 for its corpse) rather than prefix for glob size; when
3886 used for globs, it might be either "small glob of <foo>" or
3887 "small <foo> glob" and user might add 's' even though plural
3888 doesn't accomplish anything because globs don't stack */
3889 if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
3893 } else if (!strncmpi(bp, "medium ", l = 7)) {
3895 } else if (!STRNCMPEX(bp, "
\92\86\82
\82ç
\82¢
\82Ì")) {
3897 /* xname() doesn't display "medium" but without this
3898 there'd be no way to ask for the intermediate size
3899 ("glob" without size prefix yields smallest one) */
3902 } else if (!strncmpi(bp, "large ", l = 6)) {
3904 } else if (!STRNCMPEX(bp, "
\91å
\82«
\82¢")) {
3906 /* "large" might be part of monster name (dog, cat, koboold,
3907 mimic) or object name (box, round shield) rather than
3908 prefix for glob size */
3909 if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
3911 /* "very large " had "very " peeled off on previous iteration */
3912 gsize = (very != 1) ? 3 : 4;
3918 cnt = 1; /* will be changed to 2 if makesingular() changes string */
3919 if (strlen(bp) > 1 && (p = rindex(bp, '(')) != 0) {
3920 boolean keeptrailingchars = TRUE;
3922 p[(p > bp && p[-1] == ' ') ? -1 : 0] = '\0'; /*terminate bp */
3923 ++p; /* advance past '(' */
3924 if (!strncmpi(p, "lit)", 4)) {
3926 p += 4 - 1; /* point at ')' */
3940 /* mis-matched parentheses; rest of string will be ignored
3941 * [probably we should restore everything back to '('
3942 * instead since it might be part of "named ..."]
3944 keeptrailingchars = FALSE;
3949 if (keeptrailingchars) {
3952 /* 'pp' points at 'pb's terminating '\0',
3953 'p' points at ')' and will be incremented past it */
3960 * otmp->spe is type schar, so we don't want spe to be any bigger or
3961 * smaller. Also, spe should always be positive --some cheaters may
3962 * try to confuse atoi().
3965 spesgn = -1; /* cheaters get what they deserve */
3968 if (spe > SCHAR_LIM)
3970 if (rechrg < 0 || rechrg > 7)
3971 rechrg = 7; /* recharge_limit */
3973 /* now we have the actual name, as delivered by xname, say
3974 * green potions called whisky
3975 * scrolls labeled "QWERTY"
3978 * very heavy iron ball named hoei
3982 if ((p = strstri(bp, " named ")) != 0) {
3986 if ((p = strstri(bp, " called ")) != 0) {
3989 #if 0 /*JP*//*
\83^
\83C
\83v
\95Ê
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢*/
3990 /* "helmet called telepathy" is not "helmet" (a specific type)
3991 * "shield called reflection" is not "shield" (a general type)
3993 for (i = 0; i < SIZE(o_ranges); i++)
3994 if (!strcmpi(bp, o_ranges[i].name)) {
3995 oclass = o_ranges[i].oclass;
4000 if ((p = strstri(bp, " labeled ")) != 0) {
4003 } else if ((p = strstri(bp, " labelled ")) != 0) {
4007 if ((p = strstri(bp, " of spinach")) != 0) {
4012 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8f\88\97\9d\82µ
\82È
\82¢*/
4014 * Skip over "pair of ", "pairs of", "set of" and "sets of".
4016 * Accept "3 pair of boots" as well as "3 pairs of boots". It is
4017 * valid English either way. See makeplural() for more on pair/pairs.
4019 * We should only double count if the object in question is not
4020 * referred to as a "pair of". E.g. We should double if the player
4021 * types "pair of spears", but not if the player types "pair of
4022 * lenses". Luckily (?) all objects that are referred to as pairs
4023 * -- boots, gloves, and lenses -- are also not mergable, so cnt is
4026 if (!strncmpi(bp, "pair of ", 8)) {
4029 } else if (!strncmpi(bp, "pairs of ", 9)) {
4033 } else if (!strncmpi(bp, "set of ", 7)) {
4035 } else if (!strncmpi(bp, "sets of ", 8)) {
4041 /* intercept pudding globs here; they're a valid wish target,
4042 * but we need them to not get treated like a corpse.
4044 * also don't let player wish for multiple globs.
4046 i = (int) strlen(bp);
4048 /* check for "glob", "<foo> glob", and "glob of <foo>" */
4049 if (!strcmpi(bp, "glob") || !BSTRCMPI(bp, bp + i - 5, " glob")
4050 || !strcmpi(bp, "globs") || !BSTRCMPI(bp, bp + i - 6, " globs")
4051 || (p = strstri(bp, "glob of ")) != 0
4052 || (p = strstri(bp, "globs of ")) != 0) {
4053 mntmp = name_to_mon(!p ? bp : (strstri(p, " of ") + 4));
4054 /* if we didn't recognize monster type, pick a valid one at random */
4055 if (mntmp == NON_PM)
4056 mntmp = rn1(PM_BLACK_PUDDING - PM_GRAY_OOZE, PM_GRAY_OOZE);
4057 /* construct canonical spelling in case name_to_mon() recognized a
4058 variant (grey ooze) or player used inverted syntax (<foo> glob);
4059 if player has given a valid monster type but not valid glob type,
4060 object name lookup won't find it and wish attempt will fail */
4061 Sprintf(globbuf, "glob of %s", mons[mntmp].mname);
4063 mntmp = NON_PM; /* not useful for "glob of <foo>" object lookup */
4064 cnt = 0; /* globs don't stack */
4065 oclass = FOOD_CLASS;
4066 actualn = bp, dn = 0;
4070 * Find corpse type using "of" (figurine of an orc, tin of orc meat)
4071 * Don't check if it's a wand or spellbook.
4072 * (avoid "wand/finger of death" confusion).
4074 if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
4075 && !strstri(bp, "finger ")) {
4076 if ((p = strstri(bp, "tin of ")) != 0) {
4077 if (!strcmpi(p + 7, "spinach")) {
4081 tmp = tin_variety_txt(p + 7, &tinv);
4083 mntmp = name_to_mon(p + 7 + tmp);
4087 } else if ((p = strstri(bp, " of ")) != 0
4088 && (mntmp = name_to_mon(p + 4)) >= LOW_PM)
4092 /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
4093 if (strncmpi(bp, "samurai sword", 13) /* not the "samurai" monster! */
4094 && strncmpi(bp, "wizard lock", 11) /* not the "wizard" monster! */
4095 && strncmpi(bp, "ninja-to", 8) /* not the "ninja" rank */
4096 && strncmpi(bp, "master key", 10) /* not the "master" rank */
4097 && strncmpi(bp, "magenta", 7)) { /* not the "mage" rank */
4098 if (mntmp < LOW_PM && strlen(bp) > 2
4099 && (mntmp = name_to_mon(bp)) >= LOW_PM) {
4100 int mntmptoo, mntmplen; /* double check for rank title */
4103 mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
4104 bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname)
4108 } else if (!strncmpi(bp, "s ", 2)) {
4110 } else if (!strncmpi(bp, "es ", 3)) {
4112 } else if (!*bp && !actualn && !dn && !un && !oclass) {
4113 /* no referent; they don't really mean a monster type */
4121 /*JP
\81u(
\89ö
\95¨
\96¼)
\82Ì
\89ò
\81v
\82Í
\8cÂ
\81X
\82ÉID
\82ª
\82 \82é
\82Ì
\82Å
\95Ê
\88µ
\82¢ */
4123 int l2 = strlen("
\82Ì
\89ò");
4124 if (l > 4 && strncmp(bp + l - l2, "
\82Ì
\89ò", l2) == 0) {
4125 if ((mntmp = name_to_mon(bp)) >= PM_GRAY_OOZE
4126 && mntmp <= PM_BLACK_PUDDING) {
4127 mntmp = NON_PM; /* lie to ourselves */
4128 cnt = 0; /* force only one */
4131 /*JP:
\81u(
\89ö
\95¨
\96¼)
\82Ì(
\83A
\83C
\83e
\83\80)
\81v
\91Î
\89\9e */
4132 if ((mntmp = name_to_mon(bp)) >= LOW_PM) {
4133 const char *mp = mons[mntmp].mname;
4134 bp = strstri(bp, mp) + strlen(mp) + 2;
4140 #if 0 /*JP*//*
\92P
\90\94\89»
\82Í
\82µ
\82È
\82¢*/
4141 /* first change to singular if necessary */
4143 char *sng = makesingular(bp);
4145 if (strcmp(bp, sng)) {
4153 #if 0 /*JP*//*
\83X
\83y
\83\8b\97h
\82ê
\8f\88\97\9d\82Í
\82µ
\82È
\82¢*/
4154 /* Alternate spellings (pick-ax, silver sabre, &c) */
4156 const struct alt_spellings *as = spellings;
4159 if (fuzzymatch(bp, as->sp, " -", TRUE)) {
4165 /* can't use spellings list for this one due to shuffling */
4166 if (!strncmpi(bp, "grey spell", 10))
4169 if ((p = strstri(bp, "armour")) != 0) {
4170 /* skip past "armo", then copy remainder beyond "u" */
4172 while ((*p = *(p + 1)) != '\0')
4173 ++p; /* self terminating */
4179 /* dragon scales - assumes order of dragons */
4180 if (!strcmpi(bp, "scales") && mntmp >= PM_GRAY_DRAGON
4181 && mntmp <= PM_YELLOW_DRAGON) {
4182 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
4183 mntmp = NON_PM; /* no monster */
4187 /*JP:
\81u
\97Ø
\8aZ
\81v
\82ð
\90æ
\82É
\8f\88\97\9d\82µ
\82Ä
\82¨
\82 */
4188 if (!strcmpi(bp, "
\97Ø
\8aZ") && mntmp >= PM_GRAY_DRAGON
4189 && mntmp <= PM_YELLOW_DRAGON) {
4190 typ = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4191 mntmp = NON_PM; /* no monster */
4195 if (!strcmpi(bp, "
\97Ø") && mntmp >= PM_GRAY_DRAGON
4196 && mntmp <= PM_YELLOW_DRAGON) {
4197 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
4198 mntmp = NON_PM; /* no monster */
4205 if (!BSTRCMPI(bp, p - 10, "holy water")) {
4207 if ((p - bp) >= 12 && *(p - 12) == 'u')
4208 iscursed = 1; /* unholy water */
4213 #else /*JP:
\90¹
\90\85\82Æ
\95s
\8fò
\82È
\90\85\82ð
\95Ê
\82É
\94»
\92è*/
4214 if (!BSTRCMPI(bp, p - 4, "
\90¹
\90\85")) {
4219 if (!BSTRCMPI(bp, p - 8, "
\95s
\8fò
\82È
\90\85")) {
4226 if (unlabeled && !BSTRCMPI(bp, p - 6, "scroll")) {
4228 if (unlabeled && !BSTRCMPI(bp, p - 4, "
\8aª
\95¨")) {
4230 typ = SCR_BLANK_PAPER;
4234 if (unlabeled && !BSTRCMPI(bp, p - 9, "spellbook")) {
4236 if (unlabeled && !BSTRCMPI(bp, p - 6, "
\96\82\96@
\8f\91")) {
4238 typ = SPE_BLANK_PAPER;
4241 /* specific food rather than color of gem/potion/spellbook[/scales] */
4242 if (!BSTRCMPI(bp, p - 6, "orange") && mntmp == NON_PM) {
4247 * NOTE: Gold pieces are handled as objects nowadays, and therefore
4248 * this section should probably be reconsidered as well as the entire
4249 * gold/money concept. Maybe we want to add other monetary units as
4250 * well in the future. (TH)
4253 if (!BSTRCMPI(bp, p - 10, "gold piece")
4254 || !BSTRCMPI(bp, p - 7, "zorkmid")
4255 || !strcmpi(bp, "gold") || !strcmpi(bp, "money")
4256 || !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
4258 if (!BSTRCMPI(bp, p - 4, "
\8bà
\89Ý") || !BSTRCMPI(bp, p - 8, "
\83S
\81[
\83\8b\83h")
4259 || *bp == GOLD_SYM) {
4261 if (cnt > 5000 && !wizard)
4265 otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
4266 otmp->quan = (long) cnt;
4267 otmp->owt = weight(otmp);
4272 /* check for single character object class code ("/" for wand, &c) */
4273 if (strlen(bp) == 1 && (i = def_char_to_objclass(*bp)) < MAXOCLASSES
4274 && i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) {
4281 \89p
\8cê
\82È
\82ç XXXXX potion
\82Í
\95s
\8am
\92è
\96¼
\81Apotion of XXXXX
\82Í
\8am
\92è
\96¼
\82Æ
\82¢
\82¤
4282 \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¢
4284 /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */
4285 /* false hits on, e.g., rings for "ring mail". */
4286 if (strncmpi(bp, "enchant ", 8)
4287 && strncmpi(bp, "destroy ", 8)
4288 && strncmpi(bp, "detect food", 11)
4289 && strncmpi(bp, "food detection", 14)
4290 && strncmpi(bp, "ring mail", 9)
4291 && strncmpi(bp, "studded leather armor", 21)
4292 && strncmpi(bp, "leather armor", 13)
4293 && strncmpi(bp, "tooled horn", 11)
4294 && strncmpi(bp, "food ration", 11)
4295 && strncmpi(bp, "meat ring", 9))
4296 for (i = 0; i < (int) (sizeof wrpsym); i++) {
4297 register int j = strlen(wrp[i]);
4299 /* check for "<class> [ of ] something" */
4300 if (!strncmpi(bp, wrp[i], j)) {
4302 if (oclass != AMULET_CLASS) {
4304 if (!strncmpi(bp, " of ", 4))
4306 /* else if(*bp) ?? */
4311 /* check for "something <class>" */
4312 if (!BSTRCMPI(bp, p - j, wrp[i])) {
4314 /* for "foo amulet", leave the class name so that
4315 wishymatch() can do "of inversion" to try matching
4316 "amulet of foo"; other classes don't include their
4317 class name in their full object names (where
4318 "potion of healing" is just "healing", for instance) */
4319 if (oclass != AMULET_CLASS) {
4322 if (p > bp && p[-1] == ' ')
4325 /* amulet without "of"; convoluted wording but better a
4326 special case that's handled than one that's missing */
4327 if (!strncmpi(bp, "versus poison ", 14)) {
4328 typ = AMULET_VERSUS_POISON;
4338 /* Wishing in wizard mode can create traps and furniture.
4339 * Part I: distinguish between trap and object for the two
4340 * types of traps which have corresponding objects: bear trap
4341 * and land mine. "beartrap" (object) and "bear trap" (trap)
4342 * have a difference in spelling which we used to exploit by
4343 * adding a special case in wishymatch(), but "land mine" is
4344 * spelled the same either way so needs different handing.
4345 * Since we need something else for land mine, we've dropped
4346 * the bear trap hack so that both are handled exactly the
4347 * same. To get an armed trap instead of a disarmed object,
4348 * the player can prefix either the object name or the trap
4349 * name with "trapped " (which ordinarily applies to chests
4350 * and tins), or append something--anything at all except for
4351 * " object", but " trap" is suggested--to either the trap
4352 * name or the object name.
4354 if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) {
4355 boolean beartrap = (lowc(*bp) == 'b');
4356 char *zp = bp + 4; /* skip "bear"/"land" */
4359 ++zp; /* embedded space is optional */
4360 if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) {
4362 if (trapped == 2 || !strcmpi(zp, " object")) {
4363 /* "untrapped <foo>" or "<foo> object" */
4364 typ = beartrap ? BEARTRAP : LAND_MINE;
4366 } else if (trapped == 1 || *zp != '\0') {
4367 /* "trapped <foo>" or "<foo> trap" (actually "<foo>*") */
4368 int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE);
4370 /* use canonical trap spelling, skip object matching */
4371 Strcpy(bp, defsyms[idx].explanation);
4374 /* [no prefix or suffix; we're going to end up matching
4375 the object name and getting a disarmed trap object] */
4379 #if 0 /*JP*//* mail/armor
\8aÖ
\98A
\82Å
\82Ì
\82Ý
\8eg
\82¤
\83\89\83x
\83\8b */
4382 #if 0 /*JP*//*
\83^
\83C
\83v
\95Ê
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢ */
4383 /* "grey stone" check must be before general "stone" */
4384 for (i = 0; i < SIZE(o_ranges); i++)
4385 if (!strcmpi(bp, o_ranges[i].name)) {
4386 typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
4391 #if 0 /*JP*//*
\90Î
\82Ì
\93Á
\95Ê
\8f\88\97\9d\82Í
\95s
\97v */
4392 if (!BSTRCMPI(bp, p - 6, " stone") || !BSTRCMPI(bp, p - 4, " gem")) {
4393 p[!strcmpi(p - 4, " gem") ? -4 : -6] = '\0';
4397 } else if (!strcmpi(bp, "looking glass")) {
4398 ; /* avoid false hit on "* glass" */
4399 } else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
4400 register char *g = bp;
4402 /* treat "broken glass" as a non-existent item; since "broken" is
4403 also a chest/box prefix it might have been stripped off above */
4404 if (broken || strstri(g, "broken"))
4405 return (struct obj *) 0;
4406 if (!strncmpi(g, "worthless ", 10))
4408 if (!strncmpi(g, "piece of ", 9))
4410 if (!strncmpi(g, "colored ", 8))
4412 else if (!strncmpi(g, "coloured ", 9))
4414 if (!strcmpi(g, "glass")) { /* choose random color */
4415 /* 9 different kinds */
4416 typ = LAST_GEM + rnd(9);
4417 if (objects[typ].oc_class == GEM_CLASS)
4420 typ = 0; /* somebody changed objects[]? punt */
4421 } else { /* try to construct canonical form */
4424 Strcpy(tbuf, "worthless piece of ");
4425 Strcat(tbuf, g); /* assume it starts with the color */
4433 dn = actualn; /* ex. "skull cap" */
4437 /* check real names of gems first */
4438 if (!oclass && actualn) {
4439 for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
4440 register const char *zn;
4442 if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) {
4447 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í"tin"
\82ð
\96ó
\82µ
\95ª
\82¯
\82Ä
\82¢
\82é
\82Ì
\82Å
\95s
\97v */
4448 /* "tin of foo" would be caught above, but plain "tin" has
4449 a random chance of yielding "tin wand" unless we do this */
4450 if (!strcmpi(actualn, "tin")) {
4457 if (((typ = rnd_otyp_by_namedesc(actualn, oclass, 1)) != STRANGE_OBJECT)
4458 || ((typ = rnd_otyp_by_namedesc(dn, oclass, 1)) != STRANGE_OBJECT)
4459 || ((typ = rnd_otyp_by_namedesc(un, oclass, 1)) != STRANGE_OBJECT)
4460 || ((typ = rnd_otyp_by_namedesc(origbp, oclass, 1)) != STRANGE_OBJECT))
4465 struct Jitem *j = Japanese_items;
4468 if (actualn && !strcmpi(actualn, j->name)) {
4475 #if 0 /*JP*//* mail/armor
\82Ì
\95\
\8bL
\97h
\82ê
\83`
\83F
\83b
\83N
\82Í
\95s
\97v */
4476 /* if we've stripped off "armor" and failed to match anything
4477 in objects[], append "mail" and try again to catch misnamed
4478 requests like "plate armor" and "yellow dragon scale armor" */
4479 if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) {
4480 /* modifying bp's string is ok; we're about to resort
4481 to random armor if this also fails to match anything */
4482 Strcat(bp, " mail");
4487 if (!strcmpi(bp, "spinach")) {
4489 if (!strcmp(bp, "
\83z
\83E
\83\8c\83\93\91\90")) {
4495 /* Note: not strcmpi. 2 fruits, one capital, one not, are possible.
4496 Also not strncmp. We used to ignore trailing text with it, but
4497 that resulted in "grapefruit" matching "grape" if the latter came
4498 earlier than the former in the fruit list. */
4502 int blessedf, iscursedf, uncursedf, halfeatenf;
4504 blessedf = iscursedf = uncursedf = halfeatenf = 0;
4511 if (!strncmpi(fp, "an ", l = 3) || !strncmpi(fp, "a ", l = 2)) {
4513 } else if (!cntf && digit(*fp)) {
4520 } else if (!strncmpi(fp, "blessed ", l = 8)) {
4522 } else if (!strncmpi(fp, "cursed ", l = 7)) {
4524 } else if (!strncmpi(fp, "uncursed ", l = 9)) {
4526 } else if (!strncmpi(fp, "partly eaten ", l = 13)
4527 || !strncmpi(fp, "partially eaten ", l = 16)) {
4534 for (f = ffruit; f; f = f->nextf) {
4535 /* match type: 0=none, 1=exact, 2=singular, 3=plural */
4538 if (!strcmp(fp, f->fname))
4540 else if (!strcmp(fp, makesingular(f->fname)))
4542 else if (!strcmp(fp, makeplural(f->fname)))
4547 iscursed = iscursedf;
4548 uncursed = uncursedf;
4549 halfeaten = halfeatenf;
4550 /* adjust count if user explicitly asked for
4551 singular amount (can't happen unless fruit
4552 has been given an already pluralized name)
4553 or for plural amount */
4554 if (ftyp == 2 && !cntf)
4556 else if (ftyp == 3 && !cntf)
4565 if (!oclass && actualn) {
4568 /* Perhaps it's an artifact specified by name, not type */
4569 name = artifact_name(actualn, &objtyp);
4577 * Let wizards wish for traps and furniture.
4578 * Must come after objects check so wizards can still wish for
4579 * trap objects like beartraps.
4580 * Disallow such topology tweaks for WIZKIT startup wishes.
4583 if (wizard && !program_state.wizkit_wishing) {
4585 boolean madeterrain = FALSE;
4586 int trap, x = u.ux, y = u.uy;
4588 for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
4592 tname = defsyms[trap_to_defsym(trap)].explanation;
4593 if (strncmpi(tname, bp, strlen(tname)))
4595 /* found it; avoid stupid mistakes */
4596 if (is_hole(trap) && !Can_fall_thru(&u.uz))
4598 if ((t = maketrap(x, y, trap)) != 0) {
4600 tname = defsyms[trap_to_defsym(trap)].explanation;
4601 pline("%s%s.", An(tname),
4602 (trap != MAGIC_PORTAL) ? "" : " to nowhere");
4604 pline("Creation of %s failed.", an(tname));
4605 return (struct obj *) &zeroobj;
4608 /* furniture and terrain (use at your own risk; can clobber stairs
4609 or place furniture on existing traps which shouldn't be allowed) */
4612 if (!BSTRCMPI(bp, p - 8, "fountain")) {
4613 lev->typ = FOUNTAIN;
4614 level.flags.nfountains++;
4615 if (!strncmpi(bp, "magic ", 6))
4616 lev->blessedftn = 1;
4617 pline("A %sfountain.", lev->blessedftn ? "magic " : "");
4619 } else if (!BSTRCMPI(bp, p - 6, "throne")) {
4623 } else if (!BSTRCMPI(bp, p - 4, "sink")) {
4625 level.flags.nsinks++;
4629 /* ("water" matches "potion of water" rather than terrain) */
4630 } else if (!BSTRCMPI(bp, p - 4, "pool")
4631 || !BSTRCMPI(bp, p - 4, "moat")) {
4632 lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT;
4634 pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
4635 /* Must manually make kelp! */
4636 water_damage_chain(level.objects[x][y], TRUE);
4639 /* also matches "molten lava" */
4640 } else if (!BSTRCMPI(bp, p - 4, "lava")) {
4641 lev->typ = LAVAPOOL;
4643 pline("A pool of molten lava.");
4644 if (!(Levitation || Flying))
4647 } else if (!BSTRCMPI(bp, p - 5, "altar")) {
4651 if (!strncmpi(bp, "chaotic ", 8))
4653 else if (!strncmpi(bp, "neutral ", 8))
4655 else if (!strncmpi(bp, "lawful ", 7))
4657 else if (!strncmpi(bp, "unaligned ", 10))
4659 else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
4660 al = !rn2(6) ? A_NONE : (rn2((int) A_LAWFUL + 2) - 1);
4661 lev->altarmask = Align2amask(al);
4662 pline("%s altar.", An(align_str(al)));
4664 } else if (!BSTRCMPI(bp, p - 5, "grave")
4665 || !BSTRCMPI(bp, p - 9, "headstone")) {
4666 make_grave(x, y, (char *) 0);
4667 pline("%s.", IS_GRAVE(lev->typ) ? "A grave"
4668 : "Can't place a grave here");
4670 } else if (!BSTRCMPI(bp, p - 4, "tree")) {
4675 } else if (!BSTRCMPI(bp, p - 4, "bars")) {
4676 lev->typ = IRONBARS;
4677 pline("Iron bars.");
4682 feel_newsym(x, y); /* map the spot where the wish occurred */
4683 /* hero started at <x,y> but might not be there anymore (create
4684 lava, decline to die, and get teleported away to safety) */
4685 if (u.uinwater && !is_pool(u.ux, u.uy)) {
4686 u.uinwater = 0; /* leave the water */
4688 vision_full_recalc = 1;
4689 } else if (u.utrap && u.utraptype == TT_LAVA
4690 && !is_lava(u.ux, u.uy)) {
4693 /* cast 'const' away; caller won't modify this */
4694 return (struct obj *) &zeroobj;
4696 } /* end of wizard mode traps and terrain */
4698 #if 0 /*JP*//*
\83^
\83C
\83v
\95Ê
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢ */
4699 if (!oclass && !typ) {
4700 if (!strncmpi(bp, "polearm", 7)) {
4701 typ = rnd_otyp_by_wpnskill(P_POLEARMS);
4703 } else if (!strncmpi(bp, "hammer", 6)) {
4704 typ = rnd_otyp_by_wpnskill(P_HAMMER);
4711 return ((struct obj *) 0);
4714 oclass = wrpsym[rn2((int) sizeof wrpsym)];
4717 oclass = objects[typ].oc_class;
4719 /* handle some objects that are only allowed in wizard mode */
4720 if (typ && !wizard) {
4722 case AMULET_OF_YENDOR:
4723 typ = FAKE_AMULET_OF_YENDOR;
4725 case CANDELABRUM_OF_INVOCATION:
4726 typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
4728 case BELL_OF_OPENING:
4731 case SPE_BOOK_OF_THE_DEAD:
4732 typ = SPE_BLANK_PAPER;
4738 /* catch any other non-wishable objects (venom) */
4739 if (objects[typ].oc_nowish)
4740 return (struct obj *) 0;
4746 * Create the object, then fine-tune it.
4748 otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE);
4749 typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */
4751 if (islit && (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN
4752 || Is_candle(otmp) || typ == POT_OIL)) {
4753 place_object(otmp, u.ux, u.uy); /* make it viable light source */
4754 begin_burn(otmp, FALSE);
4755 obj_extract_self(otmp); /* now release it for caller's use */
4758 /* if player specified a reasonable count, maybe honor it */
4759 if (cnt > 0 && objects[typ].oc_merge
4760 && (wizard || cnt < rnd(6) || (cnt <= 7 && Is_candle(otmp))
4761 || (cnt <= 20 && ((oclass == WEAPON_CLASS && is_ammo(otmp))
4762 || typ == ROCK || is_missile(otmp)))))
4763 otmp->quan = (long) cnt;
4765 if (oclass == VENOM_CLASS)
4770 } else if (wizard) {
4771 ; /* no alteration to spe */
4772 } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS
4774 || (oclass == RING_CLASS && objects[typ].oc_charged)) {
4775 if (spe > rnd(5) && spe > otmp->spe)
4777 if (spe > 2 && Luck < 0)
4780 if (oclass == WAND_CLASS) {
4781 if (spe > 1 && spesgn == -1)
4784 if (spe > 0 && spesgn == -1)
4787 if (spe > otmp->spe)
4794 /* set otmp->spe. This may, or may not, use spe... */
4797 if (contents == EMPTY) {
4798 otmp->corpsenm = NON_PM;
4800 } else if (contents == SPINACH) {
4801 otmp->corpsenm = NON_PM;
4807 otmp->spe = wetness;
4815 case HEAVY_IRON_BALL:
4818 /* otmp->cobj already done in mksobj() */
4822 /* 0: delivered in-game via external event (or randomly for fake mail);
4823 1: from bones or wishing; 2: written with marker */
4829 otmp->spe = (rn2(10) ? -1 : 0);
4837 /* set otmp->corpsenm or dragon scale [mail] */
4838 if (mntmp >= LOW_PM) {
4839 if (mntmp == PM_LONG_WORM_TAIL)
4840 mntmp = PM_LONG_WORM;
4844 otmp->spe = 0; /* No spinach */
4845 if (dead_species(mntmp, FALSE)) {
4846 otmp->corpsenm = NON_PM; /* it's empty */
4847 } else if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4848 && !(mvitals[mntmp].mvflags & G_NOCORPSE)
4849 && mons[mntmp].cnutrit != 0) {
4850 otmp->corpsenm = mntmp;
4854 if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4855 && !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
4856 if (mons[mntmp].msound == MS_GUARDIAN)
4857 mntmp = genus(mntmp, 1);
4858 set_corpsenm(otmp, mntmp);
4862 mntmp = can_be_hatched(mntmp);
4863 /* this also sets hatch timer if appropriate */
4864 set_corpsenm(otmp, mntmp);
4867 if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
4869 && mntmp != PM_MAIL_DAEMON
4872 otmp->corpsenm = mntmp;
4875 otmp->corpsenm = mntmp;
4876 if (Has_contents(otmp) && verysmall(&mons[mntmp]))
4877 delete_contents(otmp); /* no spellbook */
4878 otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
4881 /* Dragon mail - depends on the order of objects & dragons. */
4882 if (mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON)
4883 otmp->otyp = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4888 /* set blessed/cursed -- setting the fields directly is safe
4889 * since weight() is called below and addinv() will take care
4893 } else if (uncursed) {
4895 otmp->cursed = (Luck < 0 && !wizard);
4896 } else if (blessed) {
4897 otmp->blessed = (Luck >= 0 || wizard);
4898 otmp->cursed = (Luck < 0 && !wizard);
4899 } else if (spesgn < 0) {
4903 /* set eroded and erodeproof */
4904 if (erosion_matters(otmp)) {
4905 if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
4906 otmp->oeroded = eroded;
4907 if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
4908 otmp->oeroded2 = eroded2;
4910 * 3.6.1: earlier versions included `&& !eroded && !eroded2' here,
4911 * but damageproof combined with damaged is feasible (eroded
4912 * armor modified by confused reading of cursed destroy armor)
4913 * so don't prevent player from wishing for such a combination.
4915 if (erodeproof && (is_damageable(otmp) || otmp->otyp == CRYSKNIFE))
4916 otmp->oerodeproof = (Luck >= 0 || wizard);
4919 /* set otmp->recharged */
4920 if (oclass == WAND_CLASS) {
4921 /* prevent wishing abuse */
4922 if (otmp->otyp == WAN_WISHING && !wizard)
4924 otmp->recharged = (unsigned) rechrg;
4929 if (is_poisonable(otmp))
4930 otmp->opoisoned = (Luck >= 0);
4931 else if (oclass == FOOD_CLASS)
4932 /* try to taint by making it as old as possible */
4935 /* and [un]trapped */
4937 if (Is_box(otmp) || typ == TIN)
4938 otmp->otrapped = (trapped == 1);
4940 /* empty for containers rather than for tins */
4941 if (contents == EMPTY) {
4942 if (otmp->otyp == BAG_OF_TRICKS || otmp->otyp == HORN_OF_PLENTY) {
4945 } else if (Has_contents(otmp)) {
4946 /* this assumes that artifacts can't be randomly generated
4947 inside containers */
4948 delete_contents(otmp);
4949 otmp->owt = weight(otmp);
4952 /* set locked/unlocked/broken */
4955 otmp->olocked = 1, otmp->obroken = 0;
4956 } else if (unlocked) {
4957 otmp->olocked = 0, otmp->obroken = 0;
4958 } else if (broken) {
4959 otmp->olocked = 0, otmp->obroken = 1;
4966 if (isdiluted && otmp->oclass == POTION_CLASS && otmp->otyp != POT_WATER)
4969 /* set tin variety */
4970 if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard))
4971 set_tin_variety(otmp, tvariety);
4977 /* an artifact name might need capitalization fixing */
4978 aname = artifact_name(name, &objtyp);
4979 if (aname && objtyp == otmp->otyp)
4982 /* 3.6 tribute - fix up novel */
4983 if (otmp->otyp == SPE_NOVEL) {
4984 const char *novelname;
4986 novelname = lookup_novel(name, &otmp->novelidx);
4991 otmp = oname(otmp, name);
4992 /* name==aname => wished for artifact (otmp->oartifact => got it) */
4993 if (otmp->oartifact || name == aname) {
4995 u.uconduct.wisharti++; /* KMH, conduct */
4999 /* more wishing abuse: don't allow wishing for certain artifacts */
5000 /* and make them pay; charge them for the wish anyway! */
5001 if ((is_quest_artifact(otmp)
5002 || (otmp->oartifact && rn2(nartifact_exist()) > 1)) && !wizard) {
5003 artifact_exists(otmp, safe_oname(otmp), FALSE);
5004 obfree(otmp, (struct obj *) 0);
5005 otmp = (struct obj *) &zeroobj;
5007 pline("For a moment, you feel %s in your %s, but it disappears!",
5009 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",
5010 something, makeplural(body_part(HAND)));
5014 if (halfeaten && otmp->oclass == FOOD_CLASS) {
5015 if (otmp->otyp == CORPSE)
5016 otmp->oeaten = mons[otmp->corpsenm].cnutrit;
5018 otmp->oeaten = objects[otmp->otyp].oc_nutrition;
5019 /* (do this adjustment before setting up object's weight) */
5020 consume_oeaten(otmp, 1);
5022 otmp->owt = weight(otmp);
5023 if (very && otmp->otyp == HEAVY_IRON_BALL)
5024 otmp->owt += IRON_BALL_W_INCR;
5025 else if (gsize > 1 && otmp->globby)
5026 /* 0: unspecified => small; 1: small => keep default owt of 20;
5027 2: medium => 120; 3: large => 320; 4: very large => 520 */
5028 otmp->owt += 100 + (gsize - 2) * 200;
5034 rnd_class(first, last)
5041 for (i = first; i <= last; i++)
5042 sum += objects[i].oc_prob;
5043 if (!sum) /* all zero */
5044 return first + rn2(last - first + 1);
5046 for (i = first; i <= last; i++)
5047 if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
5052 STATIC_OVL const char *
5053 Japanese_item_name(i)
5056 struct Jitem *j = Japanese_items;
5063 return (const char *) 0;
5067 suit_simple_name(suit)
5070 const char *suitnm, *esuitp;
5073 if (Is_dragon_mail(suit))
5075 return "dragon mail"; /* <color> dragon scale mail */
5077 return "
\97Ø
\8aZ"; /* <color> dragon scale mail */
5079 else if (Is_dragon_scales(suit))
5081 return "dragon scales";
5084 suitnm = OBJ_NAME(objects[suit->otyp]);
5085 esuitp = eos((char *) suitnm);
5087 if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
5088 return "mail"; /* most suits fall into this category */
5090 if (strlen(suitnm) > 2 && !strcmp(esuitp - 2, "
\8aZ"))
5091 return "
\8aZ"; /* most suits fall into this category */
5094 else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
5095 return "jacket"; /* leather jacket */
5098 /* "suit" is lame but "armor" is ambiguous and "body armor" is absurd */
5106 cloak_simple_name(cloak)
5110 switch (cloak->otyp) {
5115 return "
\83\8d\81[
\83u";
5116 case MUMMY_WRAPPING:
5122 return (objects[cloak->otyp].oc_name_known && cloak->dknown)
5126 ? "
\83X
\83\82\83b
\83N"
5130 : "
\83G
\83v
\83\8d\83\93";
5138 return "
\83N
\83\8d\81[
\83N";
5141 /* helm vs hat for messages */
5143 helm_simple_name(helmet)
5147 * There is some wiggle room here; the result has been chosen
5148 * for consistency with the "protected by hard helmet" messages
5149 * given for various bonks on the head: headgear that provides
5150 * such protection is a "helm", that which doesn't is a "hat".
5152 * elven leather helm / leather hat -> hat
5153 * dwarvish iron helm / hard hat -> helm
5154 * The rest are completely straightforward:
5155 * fedora, cornuthaum, dunce cap -> hat
5156 * all other types of helmets -> helm
5159 return (helmet && !is_metallic(helmet)) ? "hat" : "helm";
5161 return (helmet && !is_metallic(helmet)) ? "
\96X
\8eq" : "
\8a\95";
5164 /* gloves vs gauntlets; depends upon discovery state */
5166 gloves_simple_name(gloves)
5170 static const char gauntlets[] = "gauntlets";
5172 static const char gauntlets[] = "
\8f¬
\8eè";
5174 if (gloves && gloves->dknown) {
5175 int otyp = gloves->otyp;
5176 struct objclass *ocl = &objects[otyp];
5177 const char *actualn = OBJ_NAME(*ocl),
5178 *descrpn = OBJ_DESCR(*ocl);
5180 if (strstri(objects[otyp].oc_name_known ? actualn : descrpn,
5191 mimic_obj_name(mtmp)
5194 if (M_AP_TYPE(mtmp) == M_AP_OBJECT) {
5195 if (mtmp->mappearance == GOLD_PIECE)
5200 if (mtmp->mappearance != STRANGE_OBJECT)
5201 return simple_typename(mtmp->mappearance);
5204 return "whatcha-may-callit";
5206 return "
\89½
\82Æ
\82©
\82¢
\82¤
\82à
\82Ì";
5210 * Construct a query prompt string, based around an object name, which is
5211 * guaranteed to fit within [QBUFSZ]. Takes an optional prefix, three
5212 * choices for filling in the middle (two object formatting functions and a
5213 * last resort literal which should be very short), and an optional suffix.
5216 safe_qbuf(qbuf, qprefix, qsuffix, obj, func, altfunc, lastR)
5217 char *qbuf; /* output buffer */
5218 const char *qprefix, *qsuffix;
5220 char *FDECL((*func), (OBJ_P)), *FDECL((*altfunc), (OBJ_P));
5224 /* convert size_t (or int for ancient systems) to ordinary unsigned */
5225 unsigned len, lenlimit,
5226 len_qpfx = (unsigned) (qprefix ? strlen(qprefix) : 0),
5227 len_qsfx = (unsigned) (qsuffix ? strlen(qsuffix) : 0),
5228 len_lastR = (unsigned) strlen(lastR);
5230 lenlimit = QBUFSZ - 1;
5231 endp = qbuf + lenlimit;
5232 /* sanity check, aimed mainly at paniclog (it's conceivable for
5233 the result of short_oname() to be shorter than the length of
5234 the last resort string, but we ignore that possibility here) */
5235 if (len_qpfx > lenlimit)
5236 impossible("safe_qbuf: prefix too long (%u characters).", len_qpfx);
5237 else if (len_qpfx + len_qsfx > lenlimit)
5238 impossible("safe_qbuf: suffix too long (%u + %u characters).",
5239 len_qpfx, len_qsfx);
5240 else if (len_qpfx + len_lastR + len_qsfx > lenlimit)
5241 impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
5242 len_qpfx, len_lastR, len_qsfx);
5244 /* the output buffer might be the same as the prefix if caller
5245 has already partially filled it */
5246 if (qbuf == qprefix) {
5247 /* prefix is already in the buffer */
5249 } else if (qprefix) {
5250 /* put prefix into the buffer */
5251 (void) strncpy(qbuf, qprefix, lenlimit);
5254 /* no prefix; output buffer starts out empty */
5257 len = (unsigned) strlen(qbuf);
5259 if (len + len_lastR + len_qsfx > lenlimit) {
5260 /* too long; skip formatting, last resort output is truncated */
5261 if (len < lenlimit) {
5262 (void) strncpy(&qbuf[len], lastR, lenlimit - len);
5264 len = (unsigned) strlen(qbuf);
5265 if (qsuffix && len < lenlimit) {
5266 (void) strncpy(&qbuf[len], qsuffix, lenlimit - len);
5268 /* len = (unsigned) strlen(qbuf); */
5272 /* suffix and last resort are guaranteed to fit */
5273 len += len_qsfx; /* include the pending suffix */
5274 /* format the object */
5275 bufp = short_oname(obj, func, altfunc, lenlimit - len);
5276 if (len + strlen(bufp) <= lenlimit)
5277 Strcat(qbuf, bufp); /* formatted name fits */
5279 Strcat(qbuf, lastR); /* use last resort */
5283 Strcat(qbuf, qsuffix);
5285 /* assert( strlen(qbuf) < QBUFSZ ); */
5290 globwt(otmp, buf, weightformatted_p)
5293 boolean *weightformatted_p;
5297 Sprintf(buf, "%u aum, ", otmp->owt);
5298 *weightformatted_p = TRUE;
5300 *weightformatted_p = FALSE;