1 /* NetHack 3.6 objnam.c $NHDT-Date: 1551138256 2019/02/25 23:44:16 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.235 $ */
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-2019 */
9 /* JNetHack may be freely redistributed. See license for details. */
13 /* "an uncursed greased partly eaten guardian naga hatchling [corpse]" */
15 #define PREFIX 80 /* (56) */
17 /*
\81u
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\96û
\82Ì
\93h
\82ç
\82ê
\82½
\90H
\82×
\82©
\82¯
\82Ì
\83N
\83\8d\83}
\83e
\83B
\83b
\83N
\81E
\83h
\83\89\83S
\83\93(
\82Ì
\8e\80\91Ì)
\81v*/
23 STATIC_DCL char *FDECL(strprepend, (char *, const char *));
24 STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
25 STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (const char *, CHAR_P, int));
26 STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
27 STATIC_DCL char *NDECL(nextobuf);
28 STATIC_DCL void FDECL(releaseobuf, (char *));
29 STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
30 STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
31 STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned));
32 STATIC_DCL char *FDECL(just_an, (char *str, const char *));
34 STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
35 const char *const *));
37 STATIC_DCL char *FDECL(singplur_compound, (char *));
38 STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
40 STATIC_DCL boolean FDECL(badman, (const char *, BOOLEAN_P));
48 #define BSTRCMPI(base, ptr, str) ((ptr) < base || strcmpi((ptr), str))
49 #define BSTRNCMPI(base, ptr, str, num) \
50 ((ptr) < base || strncmpi((ptr), str, num))
51 #define Strcasecpy(dst, src) (void) strcasecpy(dst, src)
53 /* true for gems/rocks that should have " stone" appended to their names */
54 #define GemStone(typ) \
56 || (objects[typ].oc_material == GEMSTONE \
57 && (typ != DILITHIUM_CRYSTAL && typ != RUBY && typ != DIAMOND \
58 && typ != SAPPHIRE && typ != BLACK_OPAL && typ != EMERALD \
62 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "wakizashi" },
63 { BROADSWORD, "ninja-to" },
64 { FLAIL, "nunchaku" },
65 { GLAIVE, "naginata" },
66 { LOCK_PICK, "osaku" },
67 { WOODEN_HARP, "koto" },
69 { PLATE_MAIL, "tanko" },
71 { LEATHER_GLOVES, "yugake" },
72 { FOOD_RATION, "gunyoki" },
73 { POT_BOOZE, "sake" },
76 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "
\98e
\8d·
\82µ" },
77 { BROADSWORD, "
\94E
\8eÒ
\93\81" },
78 { FLAIL, "
\83k
\83\93\83`
\83\83\83N" },
79 { GLAIVE, "
\82È
\82¬
\82È
\82½" },
80 { LOCK_PICK, "
\82¨
\82³
\82" },
81 { WOODEN_HARP, "
\8bÕ" },
82 { KNIFE, "
\8eh
\93\81" },
83 { PLATE_MAIL, "
\92Z
\8db" },
85 { LEATHER_GLOVES, "
\8b|
\8c\9c" },
86 { FOOD_RATION, "
\8aÛ
\96ò" },
87 { POT_BOOZE, "
\8eð" },
91 STATIC_DCL const char *FDECL(Japanese_item_name, (int i));
96 register const char *pref;
98 register int i = (int) strlen(pref);
101 impossible("PREFIX too short (for %d).", i);
105 (void) strncpy(s, pref, i); /* do not copy trailing 0 */
109 /* manage a pool of BUFSZ buffers, so callers don't have to */
110 static char NEARDATA obufs[NUMOBUF][BUFSZ];
111 static int obufidx = 0;
116 obufidx = (obufidx + 1) % NUMOBUF;
117 return obufs[obufidx];
120 /* put the most recently allocated buffer back if possible */
125 /* caller may not know whether bufp is the most recently allocated
126 buffer; if it isn't, do nothing; note that because of the somewhat
127 obscure PREFIX handling for object name formatting by xname(),
128 the pointer our caller has and is passing to us might be into the
129 middle of an obuf rather than the address returned by nextobuf() */
130 if (bufp >= obufs[obufidx]
131 && bufp < obufs[obufidx] + sizeof obufs[obufidx]) /* obufs[][BUFSZ] */
132 obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
139 char *buf = nextobuf();
140 struct objclass *ocl = &objects[otyp];
141 const char *actualn = OBJ_NAME(*ocl);
142 const char *dn = OBJ_DESCR(*ocl);
143 const char *un = ocl->oc_uname;
144 int nn = ocl->oc_name_known;
146 if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
147 actualn = Japanese_item_name(otyp);
150 Sprintf(buf, "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é", un);
152 switch (ocl->oc_class) {
157 Strcat(buf, "
\8bà
\89Ý");
161 Strcpy(buf, "potion");
167 Strcpy(buf, "scroll");
169 Strcat(buf, "
\8aª
\95¨");
178 if (otyp != SPE_NOVEL) {
180 Strcpy(buf, "spellbook");
182 Strcat(buf, "
\96\82\96@
\8f\91");
185 Strcpy(buf, !nn ? "book" : "novel");
187 Strcpy(buf, !nn ? "
\96{" : "
\8f¬
\90à");
195 Strcat(buf, "
\8ew
\97Ö");
200 Strcpy(buf, actualn);
202 Strcpy(buf, "amulet");
204 Sprintf(eos(buf), " called %s", un);
206 Sprintf(eos(buf), " (%s)", dn);
210 Strcat(buf, actualn);
212 Strcat(buf, "
\96\82\8f\9c\82¯");
218 Strcat(buf, actualn);
220 Strcat(buf, "
\95ó
\90Î");
226 Strcpy(buf, actualn);
228 Strcat(buf, " stone");
230 Sprintf(eos(buf), " called %s", un);
232 Sprintf(eos(buf), " (%s)", dn);
234 Strcat(buf, actualn);
238 Strcpy(buf, dn ? dn : actualn);
239 if (ocl->oc_class == GEM_CLASS)
241 (ocl->oc_material == MINERAL) ? " stone" : " gem");
243 Sprintf(eos(buf), " called %s", un);
245 Strcat(buf, dn ? dn : actualn);
254 /* here for ring/scroll/potion/wand */
258 Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
260 Sprintf(eos(buf), " of %s", actualn);
262 Strcpy(buf, actualn);
267 Sprintf(eos(buf), " called %s", un);
271 Sprintf(eos(buf), " (%s)", dn);
273 Sprintf(eos(buf), "(%s)", dn);
278 /* less verbose result than obj_typename(); either the actual name
279 or the description (but not both); user-assigned name is ignored */
281 simple_typename(otyp)
284 char *bufp, *pp, *save_uname = objects[otyp].oc_uname;
286 objects[otyp].oc_uname = 0; /* suppress any name given by user */
287 bufp = obj_typename(otyp);
288 objects[otyp].oc_uname = save_uname;
289 if ((pp = strstri(bufp, " (")) != 0)
290 *pp = '\0'; /* strip the appended description */
298 if (!obj->oartifact || !has_oname(obj))
300 if (!program_state.gameover && !iflags.override_ID) {
301 if (not_fully_identified(obj))
307 /* used by distant_name() to pass extra information to xname_flags();
308 it would be much cleaner if this were a parameter, but that would
309 require all of the xname() and doname() calls to be modified */
310 static int distantname = 0;
312 /* Give the name of an object seen at a distance. Unlike xname/doname,
313 * we don't want to set dknown if it's not set already.
316 distant_name(obj, func)
318 char *FDECL((*func), (OBJ_P));
322 /* 3.6.1: this used to save Blind, set it, make the call, then restore
323 * the saved value; but the Eyes of the Overworld override blindness
324 * and let characters wearing them get dknown set for distant items.
326 * TODO? if the hero is wearing those Eyes, figure out whether the
327 * object is within X-ray radius and only treat it as distant when
328 * beyond that radius. Logic is iffy but result might be interesting.
336 /* convert player specified fruit name into corresponding fruit juice name
337 ("slice of pizza" -> "pizza juice" rather than "slice of pizza juice") */
340 boolean juice; /* whether or not to append " juice" to the name */
342 #if 1 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\82»
\82±
\82Ü
\82Å
\82µ
\82È
\82¢*/
343 char *buf = nextobuf();
344 Sprintf(buf, "%s%s", pl_fruit, juice ? "
\83W
\83\85\81[
\83X" : "");
347 char *buf = nextobuf();
348 const char *fruit_nam = strstri(pl_fruit, " of ");
351 fruit_nam += 4; /* skip past " of " */
353 fruit_nam = pl_fruit; /* use it as is */
355 Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
360 /* look up a named fruit by index (1..127) */
362 fruit_from_indx(indx)
367 for (f = ffruit; f; f = f->nextf)
373 /* look up a named fruit by name */
375 fruit_from_name(fname, exact, highest_fid)
377 boolean exact; /* False => prefix or exact match, True = exact match only */
378 int *highest_fid; /* optional output; only valid if 'fname' isn't found */
380 struct fruit *f, *tentativef;
384 * note: named fruits are case-senstive...
389 /* first try for an exact match */
390 for (f = ffruit; f; f = f->nextf)
391 if (!strcmp(f->fname, fname))
393 else if (highest_fid && f->fid > *highest_fid)
394 *highest_fid = f->fid;
396 /* didn't match as-is; if caller is willing to accept a prefix
397 match, try to find one; we want to find the longest prefix that
398 matches, not the first */
401 for (f = ffruit; f; f = f->nextf) {
402 k = strlen(f->fname);
403 if (!strncmp(f->fname, fname, k)
404 && (!fname[k] || fname[k] == ' ')
405 && (!tentativef || k > strlen(tentativef->fname)))
410 /* if we still don't have a match, try singularizing the target;
411 for exact match, that's trivial, but for prefix, it's hard */
413 altfname = makesingular(fname);
414 for (f = ffruit; f; f = f->nextf) {
415 if (!strcmp(f->fname, altfname))
418 releaseobuf(altfname);
421 char fnamebuf[BUFSZ], *p;
422 unsigned fname_k = strlen(fname); /* length of assumed plural fname */
425 for (f = ffruit; f; f = f->nextf) {
426 k = strlen(f->fname);
427 /* reload fnamebuf[] each iteration in case it gets modified;
428 there's no need to recalculate fname_k */
429 Strcpy(fnamebuf, fname);
430 /* bug? if singular of fname is longer than plural,
431 failing the 'fname_k > k' test could skip a viable
432 candidate; unfortunately, we can't singularize until
433 after stripping off trailing stuff and we can't get
434 accurate fname_k until fname has been singularized;
435 compromise and use 'fname_k >= k' instead of '>',
436 accepting 1 char length discrepancy without risking
437 false match (I hope...) */
438 if (fname_k >= k && (p = index(&fnamebuf[k], ' ')) != 0) {
439 *p = '\0'; /* truncate at 1st space past length of f->fname */
440 altfname = makesingular(fnamebuf);
441 k = strlen(altfname); /* actually revised 'fname_k' */
442 if (!strcmp(f->fname, altfname)
443 && (!tentativef || k > strlen(tentativef->fname)))
445 releaseobuf(altfname); /* avoid churning through all obufs */
453 /* sort the named-fruit linked list by fruit index number */
455 reorder_fruit(forward)
458 struct fruit *f, *allfr[1 + 127];
459 int i, j, k = SIZE(allfr);
461 for (i = 0; i < k; ++i)
462 allfr[i] = (struct fruit *) 0;
463 for (f = ffruit; f; f = f->nextf) {
464 /* without sanity checking, this would reduce to 'allfr[f->fid]=f' */
466 if (j < 1 || j >= k) {
467 impossible("reorder_fruit: fruit index (%d) out of range", j);
468 return; /* don't sort after all; should never happen... */
469 } else if (allfr[j]) {
470 impossible("reorder_fruit: duplicate fruit index (%d)", j);
475 ffruit = 0; /* reset linked list; we're rebuilding it from scratch */
476 /* slot [0] will always be empty; must start 'i' at 1 to avoid
477 [k - i] being out of bounds during first iteration */
478 for (i = 1; i < k; ++i) {
479 /* for forward ordering, go through indices from high to low;
480 for backward ordering, go from low to high */
481 j = forward ? (k - i) : i;
483 allfr[j]->nextf = ffruit;
493 return xname_flags(obj, CXN_NORMAL);
497 xname_flags(obj, cxn_flags)
498 register struct obj *obj;
499 unsigned cxn_flags; /* bitmask of CXN_xxx values */
502 register int typ = obj->otyp;
503 register struct objclass *ocl = &objects[typ];
504 int nn = ocl->oc_name_known, omndx = obj->corpsenm;
505 const char *actualn = OBJ_NAME(*ocl);
506 const char *dn = OBJ_DESCR(*ocl);
507 const char *un = ocl->oc_uname;
508 boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
509 boolean known, dknown, bknown;
511 buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
512 if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
513 actualn = Japanese_item_name(typ);
514 /* 3.6.2: this used to be part of 'dn's initialization, but it
515 needs to come after possibly overriding 'actualn' */
521 * clean up known when it's tied to oc_name_known, eg after AD_DRIN
522 * This is only required for unique objects since the article
523 * printed for the object is tied to the combination of the two
524 * and printing the wrong article gives away information.
526 if (!nn && ocl->oc_uses_known && ocl->oc_unique)
528 if (!Blind && !distantname)
530 if (Role_if(PM_PRIEST))
533 if (iflags.override_ID) {
534 known = dknown = bknown = TRUE;
538 dknown = obj->dknown;
539 bknown = obj->bknown;
542 if (obj_is_pname(obj))
547 Strcat(buf, ONAME(obj));
552 if (has_oname(obj) && dknown) {
553 Strcat(buf, ONAME(obj));
554 Strcat(buf, "
\82Æ
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½");
557 switch (obj->oclass) {
561 Strcpy(buf, "amulet");
563 Strcat(buf, "
\96\82\8f\9c\82¯");
564 else if (typ == AMULET_OF_YENDOR || typ == FAKE_AMULET_OF_YENDOR)
565 /* each must be identified individually */
566 Strcpy(buf, known ? actualn : dn);
568 Strcpy(buf, actualn);
571 Sprintf(buf, "amulet called %s", un);
573 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96\82\8f\9c\82¯", un);
576 Sprintf(buf, "%s amulet", dn);
578 Sprintf(eos(buf), "%s", dn);
581 if (is_poisonable(obj) && obj->opoisoned)
583 Strcpy(buf, "poisoned ");
585 Strcpy(buf, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
591 Sprintf(eos(buf), "%s
\82Ì", mons[obj->corpsenm].mname);
595 Strcpy(buf, "pair of ");
597 Strcpy(buf, "
\88ê
\91Î
\82Ì");
598 else if (is_wet_towel(obj))
600 Strcpy(buf, (obj->spe < 3) ? "moist " : "wet ");
602 Strcpy(buf, (obj->spe < 3) ? "
\8e¼
\82Á
\82½" : "
\94G
\82ê
\82½");
607 Strcat(buf, actualn);
611 Strcat(buf, " called ");
615 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é");
621 #if 0 /*JP*/ /*
\82±
\82ê
\82Í
\8cê
\8f\87\82Ì
\8aÖ
\8cW
\82©
\82ç
\8fã
\82Ì
\95û
\82Å
\92è
\8b`*/
622 if (typ == FIGURINE && omndx != NON_PM) {
623 char anbuf[10]; /* [4] would be enough: 'a','n',' ','\0' */
625 Sprintf(eos(buf), " of %s%s",
626 just_an(anbuf, mons[omndx].mname),
628 } else if (is_wet_towel(obj)) {
630 if (is_wet_towel(obj)) {
633 Sprintf(eos(buf), " (%d)", obj->spe);
637 /* depends on order of the dragon scales objects */
638 if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
640 Sprintf(buf, "set of %s", actualn);
642 Sprintf(buf, "%s
\88ê
\8e®", actualn);
645 if (is_boots(obj) || is_gloves(obj))
647 Strcpy(buf, "pair of ");
649 Strcat(buf,"
\88ê
\91Î
\82Ì");
651 if (obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
654 Strcpy(buf, "shield");
656 Strcat(buf, "
\8f\82");
659 if (obj->otyp == SHIELD_OF_REFLECTION && !dknown) {
661 Strcpy(buf, "smooth shield");
663 Strcat(buf, "
\82·
\82×
\82·
\82×
\82µ
\82½
\8f\82");
668 Strcat(buf, actualn);
672 Strcat(buf, "boots");
673 else if (is_gloves(obj))
674 Strcat(buf, "gloves");
675 else if (is_cloak(obj))
676 Strcpy(buf, "cloak");
677 else if (is_helmet(obj))
678 Strcpy(buf, "helmet");
679 else if (is_shield(obj))
680 Strcpy(buf, "shield");
682 Strcpy(buf, "armor");
683 Strcat(buf, " called ");
689 else if (is_gloves(obj))
691 else if (is_cloak(obj))
692 p = "
\83N
\83\8d\81[
\83N";
693 else if (is_helmet(obj))
695 else if (is_shield(obj))
699 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", un, p);
705 if (typ == SLIME_MOLD) {
706 struct fruit *f = fruit_from_indx(obj->spe);
709 impossible("Bad fruit #%d?", obj->spe);
710 Strcpy(buf, "fruit");
712 Strcpy(buf, f->fname);
714 /* ick; already pluralized fruit names
715 are allowed--we want to try to avoid
716 adding a redundant plural suffix */
717 Strcpy(buf, makeplural(makesingular(buf)));
734 ? "
\82Æ
\82Ä
\82à
\91å
\82«
\82¢"
746 Strcpy(buf, actualn);
747 if (typ == TIN && known)
748 tin_details(obj, omndx, buf);
750 if (typ == TIN && known)
751 /*JP
\81u
\81`
\82Ì
\93÷
\82Ì
\81v*/
752 tin_details(obj, omndx, buf);
753 Strcat(buf, actualn);
759 Strcpy(buf, actualn);
761 Strcat(buf, actualn);
765 if (typ == STATUE && omndx != NON_PM) {
769 Sprintf(buf, "%s%s of %s%s",
770 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
774 type_is_pname(&mons[omndx])
776 : the_unique_pm(&mons[omndx])
778 : just_an(anbuf, mons[omndx].mname),
781 Sprintf(eos(buf), "%s%s
\82Ì%s",
782 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
785 mons[obj->corpsenm].mname, actualn);
789 Strcpy(buf, actualn);
791 Strcat(buf, actualn);
796 Sprintf(buf, "%sheavy iron ball",
797 (obj->owt > ocl->oc_weight) ? "very " : "");
799 Sprintf(eos(buf), "%s
\8fd
\82¢
\93S
\8b\85",
800 (obj->owt > ocl->oc_weight) ? "
\82Æ
\82Ä
\82à" : "");
804 if (dknown && obj->odiluted)
806 Strcpy(buf, "diluted ");
808 Strcat(buf, "
\94\96\82Ü
\82Á
\82½");
809 if (nn || un || !dknown) {
811 Strcat(buf, "potion");
824 if (typ == POT_WATER && bknown
825 && (obj->blessed || obj->cursed)) {
827 Strcat(buf, obj->blessed ? "holy " : "unholy ");
829 Strcat(buf, obj->blessed ? "
\90¹" : "
\95s
\8fò
\82È");
831 Strcat(buf, actualn);
834 Strcat(buf, " called ");
838 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96ò");
843 #if 0 /*JP*//*
\95s
\8am
\92è
\96¼
\82É
\81u
\96ò
\81v
\82Í
\95t
\82¢
\82Ä
\82¢
\82é*/
844 Strcat(buf, " potion");
850 Strcpy(buf, "scroll");
855 Strcat(buf,"
\8aª
\95¨");
863 Strcat(buf, actualn);
866 Strcat(buf, " called ");
870 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8aª
\95¨");
872 } else if (ocl->oc_magic) {
874 Strcat(buf, " labeled ");
880 Strcat(buf, " scroll");
894 Sprintf(buf, "wand of %s", actualn);
896 Strcat(buf, actualn);
899 Sprintf(buf, "wand called %s", un);
901 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8fñ", un);
904 Sprintf(buf, "%s wand", dn);
909 if (typ == SPE_NOVEL) { /* 3.6 tribute */
916 Strcpy(buf, actualn);
919 Sprintf(buf, "novel called %s", un);
921 Sprintf(buf, "%s
\82Æ
\82¢
\82¤
\8f¬
\90à", un);
924 Sprintf(buf, "%s book", dn);
926 Sprintf(buf, "%s
\96{", dn);
929 } else if (!dknown) {
931 Strcpy(buf, "spellbook");
933 Strcat(buf, "
\96\82\96@
\8f\91");
936 if (typ != SPE_BOOK_OF_THE_DEAD)
937 Strcpy(buf, "spellbook of ");
939 Strcat(buf, actualn);
942 Sprintf(buf, "spellbook called %s", un);
944 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96\82\96@
\8f\91", un);
947 Sprintf(buf, "%s spellbook", dn);
949 Sprintf(eos(buf), "%s", dn);
956 Strcat(buf, "
\8ew
\97Ö");
959 Sprintf(buf, "ring of %s", actualn);
961 Strcat(buf, actualn);
964 Sprintf(buf, "ring called %s", un);
966 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8ew
\97Ö", un);
969 Sprintf(buf, "%s ring", dn);
975 const char *rock = (ocl->oc_material == MINERAL) ? "stone" : "gem";
977 const char *rock = (ocl->oc_material == MINERAL) ? "
\90Î" : "
\95ó
\90Î";
988 Sprintf(buf, "%s called %s", rock, un);
990 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", un, rock);
993 Sprintf(buf, "%s %s", dn, rock);
997 Strcpy(buf, actualn);
1000 Strcat(buf, " stone");
1006 Sprintf(buf, "glorkum %d %d %d", obj->oclass, typ, obj->spe);
1010 Strcpy(buf, makeplural(buf));
1013 if (obj->otyp == T_SHIRT && program_state.gameover) {
1017 Sprintf(eos(buf), " with text \"%s\"", tshirt_text(obj, tmpbuf));
1019 Sprintf(eos(buf), "(
\81u%s
\81v
\82Æ
\8f\91\82¢
\82Ä
\82 \82é)", tshirt_text(obj, tmpbuf));
1023 if (has_oname(obj) && dknown) {
1024 Strcat(buf, " named ");
1026 Strcat(buf, ONAME(obj));
1029 if (!strncmpi(buf, "the ", 4))
1037 /* similar to simple_typename but minimal_xname operates on a particular
1038 object rather than its general type; it formats the most basic info:
1039 potion -- if description not known
1040 brown potion -- if oc_name_known not set
1041 potion of object detection -- if discovered
1049 struct objclass saveobcls;
1050 int otyp = obj->otyp;
1052 /* suppress user-supplied name */
1053 saveobcls.oc_uname = objects[otyp].oc_uname;
1054 objects[otyp].oc_uname = 0;
1055 /* suppress actual name if object's description is unknown */
1056 saveobcls.oc_name_known = objects[otyp].oc_name_known;
1058 objects[otyp].oc_name_known = 0;
1060 /* caveat: this makes a lot of assumptions about which fields
1061 are required in order for xname() to yield a sensible result */
1063 bareobj.otyp = otyp;
1064 bareobj.oclass = obj->oclass;
1065 bareobj.dknown = obj->dknown;
1066 /* suppress known except for amulets (needed for fakes and real A-of-Y) */
1067 bareobj.known = (obj->oclass == AMULET_CLASS)
1069 /* default is "on" for types which don't use it */
1070 : !objects[otyp].oc_uses_known;
1071 bareobj.quan = 1L; /* don't want plural */
1072 bareobj.corpsenm = NON_PM; /* suppress statue and figurine details */
1073 /* but suppressing fruit details leads to "bad fruit #0"
1074 [perhaps we should force "slime mold" rather than use xname?] */
1075 if (obj->otyp == SLIME_MOLD)
1076 bareobj.spe = obj->spe;
1078 bufp = distant_name(&bareobj, xname); /* xname(&bareobj) */
1080 if (!strncmp(bufp, "uncursed ", 9))
1081 bufp += 9; /* Role_if(PM_PRIEST) */
1083 if (!strncmp(bufp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢", 14))
1084 bufp += 14; /* Role_if(PM_PRIEST) */
1087 objects[otyp].oc_uname = saveobcls.oc_uname;
1088 objects[otyp].oc_name_known = saveobcls.oc_name_known;
1092 /* xname() output augmented for multishot missile feedback */
1098 char *onm = xname(obj);
1100 if (m_shot.n > 1 && m_shot.o == obj->otyp) {
1101 /* "the Nth arrow"; value will eventually be passed to an() or
1102 The(), both of which correctly handle this "the " prefix */
1104 Sprintf(tmpbuf, "the %d%s ", m_shot.i, ordin(m_shot.i));
1106 Sprintf(tmpbuf, "%d%s
\96Ú
\82Ì", m_shot.i, numeral(obj));
1107 onm = strprepend(onm, tmpbuf);
1112 /* used for naming "the unique_item" instead of "a unique_item" */
1118 boolean known = (obj->known || iflags.override_ID);
1120 if (!obj->dknown && !iflags.override_ID)
1122 else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !known)
1123 return TRUE; /* lie */
1125 return (boolean) (objects[obj->otyp].oc_unique
1126 && (known || obj->otyp == AMULET_OF_YENDOR));
1132 /* should monster type be prefixed with "the"? (mostly used for corpses) */
1135 struct permonst *ptr;
1139 /* even though monsters with personal names are unique, we want to
1140 describe them as "Name" rather than "the Name" */
1141 if (type_is_pname(ptr))
1144 uniq = (ptr->geno & G_UNIQ) ? TRUE : FALSE;
1145 /* high priest is unique if it includes "of <deity>", otherwise not
1146 (caller needs to handle the 1st possibility; we assume the 2nd);
1147 worm tail should be irrelevant but is included for completeness */
1148 if (ptr == &mons[PM_HIGH_PRIEST] || ptr == &mons[PM_LONG_WORM_TAIL])
1150 /* Wizard no longer needs this; he's flagged as unique these days */
1151 if (ptr == &mons[PM_WIZARD_OF_YENDOR])
1157 add_erosion_words(obj, prefix)
1161 boolean iscrys = (obj->otyp == CRYSKNIFE);
1164 rknown = (iflags.override_ID == 0) ? obj->rknown : TRUE;
1166 if (!is_damageable(obj) && !iscrys)
1169 /* The only cases where any of these bits do double duty are for
1170 * rotted food and diluted potions, which are all not is_damageable().
1172 if (obj->oeroded && !iscrys) {
1173 switch (obj->oeroded) {
1176 Strcat(prefix, "very ");
1178 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1182 Strcat(prefix, "thoroughly ");
1184 Strcat(prefix, "
\82©
\82È
\82è");
1188 Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
1190 Strcat(prefix, is_rustprone(obj) ? "
\8eK
\82Ñ
\82½" : "
\8f\9d\82Â
\82¢
\82½");
1192 if (obj->oeroded2 && !iscrys) {
1193 switch (obj->oeroded2) {
1196 Strcat(prefix, "very ");
1198 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1202 Strcat(prefix, "thoroughly ");
1204 Strcat(prefix, "
\82©
\82È
\82è");
1208 Strcat(prefix, is_corrodeable(obj) ? "corroded " : "rotted ");
1210 Strcat(prefix, is_corrodeable(obj) ? "
\95\85\90H
\82µ
\82½" : "
\95\85\82Á
\82½");
1212 if (rknown && obj->oerodeproof)
1214 Strcat(prefix, iscrys
1218 : is_corrodeable(obj)
1219 ? "
\95\85\90H
\82µ
\82È
\82¢" /* "stainless"? */
1224 Strcat(prefix, iscrys
1225 ? "
\88À
\92è
\82µ
\82½"
1227 ? "
\8eK
\82Ñ
\82È
\82¢"
1228 : is_corrodeable(obj)
1229 ? "
\95\85\90H
\82µ
\82È
\82¢" /* "stainless"? */
1231 ? "
\94R
\82¦
\82È
\82¢"
1236 /* used to prevent rust on items where rust makes no difference */
1238 erosion_matters(obj)
1241 switch (obj->oclass) {
1243 /* it's possible for a rusty weptool to be polymorphed into some
1244 non-weptool iron tool, in which case the rust implicitly goes
1245 away, but it's also possible for it to be polymorphed into a
1246 non-iron tool, in which case rust also implicitly goes away,
1247 so there's no particular reason to try to handle the first
1248 instance differently [this comment belongs in poly_obj()...] */
1249 return is_weptool(obj) ? TRUE : FALSE;
1261 #define DONAME_WITH_PRICE 1
1262 #define DONAME_VAGUE_QUAN 2
1265 doname_base(obj, doname_flags)
1267 unsigned doname_flags;
1269 boolean ispoisoned = FALSE,
1270 with_price = (doname_flags & DONAME_WITH_PRICE) != 0,
1271 vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0;
1272 boolean known, dknown, cknown, bknown, lknown;
1273 int omndx = obj->corpsenm;
1274 char prefix[PREFIX];
1276 char tmpbuf[PREFIX + 1]; /* for when we have to add something at
1277 the start of prefix instead of the
1278 end (Strcat is used on the end) */
1280 register char *bp = xname(obj);
1281 #if 1 /*JP*//*
\8f\87\8f\98\93ü
\82ê
\91Ö
\82¦
\82É
\8eg
\82¤*/
1282 char preprefix[PREFIX];
1285 if (iflags.override_ID) {
1286 known = dknown = cknown = bknown = lknown = TRUE;
1289 dknown = obj->dknown;
1290 cknown = obj->cknown;
1291 bknown = obj->bknown;
1292 lknown = obj->lknown;
1295 /* When using xname, we want "poisoned arrow", and when using
1296 * doname, we want "poisoned +0 arrow". This kludge is about the only
1297 * way to do it, at least until someone overhauls xname() and doname(),
1298 * combining both into one function taking a parameter.
1300 /* must check opoisoned--someone can have a weirdly-named fruit */
1302 if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
1307 if (!strncmp(bp, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½", 12) && obj->opoisoned) {
1314 *
\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
1315 *
\82Ì
\82Ù
\82¤
\82ª
\8e©
\91R
\82Å
\82 \82é
\81D
1319 preprefix[0] = '\0';
1320 if((tp = strstri(bp, "
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½")) != NULL){
1321 tp += 12; /*
\81u
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½
\81v*/
1322 strncpy(preprefix, bp, tp - bp);
1323 preprefix[tp - bp] = '\0';
1330 if (obj->quan != 1L) {
1331 if (dknown || !vague_quan)
1333 Sprintf(prefix, "%ld ", obj->quan);
1334 #else /*
\93ú
\96{
\8cê
\82Æ
\82µ
\82Ä
\82Í
\90\94\8e\8c\82ª
\82È
\82¢
\82Ì
\82Í
\95s
\8e©
\91R */
1335 Sprintf(prefix, "%ld%s
\82Ì", obj->quan, numeral(obj));
1339 Strcpy(prefix, "some ");
1341 Strcpy(prefix, "
\82¢
\82
\82Â
\82©
\82Ì");
1342 } else if (obj->otyp == CORPSE) {
1343 /* skip article prefix for corpses [else corpse_xname()
1344 would have to be taught how to strip it off again] */
1346 #if 0 /*JP*/ /*
\8a¥
\8e\8c\82Í
\95s
\97v */
1347 } else if (obj_is_pname(obj) || the_unique_obj(obj)) {
1348 if (!strncmpi(bp, "the ", 4))
1350 Strcpy(prefix, "the ");
1352 Strcpy(prefix, "a ");
1353 #else /*prefix
\82Ì
\8f\89\8aú
\89»*/
1359 /* "empty" goes at the beginning, but item count goes at the end */
1361 /* bag of tricks: include "empty" prefix if it's known to
1362 be empty but its precise number of charges isn't known
1363 (when that is known, suffix of "(n:0)" will be appended,
1364 making the prefix be redundant; note that 'known' flag
1365 isn't set when emptiness gets discovered because then
1366 charging magic would yield known number of new charges) */
1367 && ((obj->otyp == BAG_OF_TRICKS)
1368 ? (obj->spe == 0 && !obj->known)
1369 /* not bag of tricks: empty if container which has no contents */
1370 : ((Is_container(obj) || obj->otyp == STATUE)
1371 && !Has_contents(obj))))
1373 Strcat(prefix, "empty ");
1375 Strcat(prefix, "
\8bó
\82Ì");
1377 if (bknown && obj->oclass != COIN_CLASS
1378 && (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
1379 || (!obj->cursed && !obj->blessed))) {
1380 /* allow 'blessed clear potion' if we don't know it's holy water;
1381 * always allow "uncursed potion of water"
1385 Strcat(prefix, "cursed ");
1387 Strcat(prefix, "
\8eô
\82í
\82ê
\82½");
1388 else if (obj->blessed)
1390 Strcat(prefix, "blessed ");
1392 Strcat(prefix, "
\8fj
\95\9f\82³
\82ê
\82½");
1393 else if (!iflags.implicit_uncursed
1394 /* For most items with charges or +/-, if you know how many
1395 * charges are left or what the +/- is, then you must have
1396 * totally identified the item, so "uncursed" is unnecessary,
1397 * because an identified object not described as "blessed" or
1398 * "cursed" must be uncursed.
1400 * If the charges or +/- is not known, "uncursed" must be
1401 * printed to avoid ambiguity between an item whose curse
1402 * status is unknown, and an item known to be uncursed.
1404 || ((!known || !objects[obj->otyp].oc_charged
1405 || obj->oclass == ARMOR_CLASS
1406 || obj->oclass == RING_CLASS)
1408 && obj->otyp != SCR_MAIL
1410 && obj->otyp != FAKE_AMULET_OF_YENDOR
1411 && obj->otyp != AMULET_OF_YENDOR
1412 && !Role_if(PM_PRIEST)))
1414 Strcat(prefix, "uncursed ");
1416 Strcat(prefix, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢");
1419 if (lknown && Is_box(obj)) {
1421 /* 3.6.0 used "unlockable" here but that could be misunderstood
1422 to mean "capable of being unlocked" rather than the intended
1423 "not capable of being locked" */
1425 Strcat(prefix, "broken ");
1427 Strcat(prefix, "
\8c®
\82Ì
\89ó
\82ê
\82½");
1428 else if (obj->olocked)
1430 Strcat(prefix, "locked ");
1432 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82½");
1435 Strcat(prefix, "unlocked ");
1437 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82Ä
\82¢
\82È
\82¢");
1442 Strcat(prefix, "greased ");
1444 Strcat(prefix, "
\96û
\82Ì
\93h
\82ç
\82ê
\82½");
1446 if (cknown && Has_contents(obj)) {
1447 /* we count the number of separate stacks, which corresponds
1448 to the number of inventory slots needed to be able to take
1449 everything out if no merges occur */
1450 long itemcount = count_contents(obj, FALSE, FALSE, TRUE);
1453 Sprintf(eos(bp), " containing %ld item%s", itemcount,
1456 Sprintf(eos(bp), "(%ld
\8cÂ
\93ü
\82Á
\82Ä
\82¢
\82é)", itemcount);
1460 switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
1462 if (obj->owornmask & W_AMUL)
1464 Strcat(bp, " (being worn)");
1466 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1469 if (obj->owornmask & W_ARMOR)
1471 Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
1473 Strcat(bp, (obj == uskin) ? "(
\94§
\82É
\96\84\82ß
\82±
\82Ü
\82ê
\82Ä
\82¢
\82é)"
1474 /* in case of perm_invent update while Wear/Takeoff
1475 is in progress; check doffing() before donning()
1476 because donning() returns True for both cases */
1477 : doffing(obj) ? " (being doffed)"
1478 : donning(obj) ? " (being donned)"
1482 : "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1487 Strcat(prefix, "poisoned ");
1489 Strcat(prefix, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
1490 add_erosion_words(obj, prefix);
1492 Strcat(prefix, sitoa(obj->spe));
1493 Strcat(prefix, " ");
1497 if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
1499 Strcat(bp, " (being worn)");
1501 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1504 if (obj->otyp == LEASH && obj->leashmon != 0) {
1505 struct monst *mlsh = find_mid(obj->leashmon, FM_FMON);
1508 impossible("leashed monster not on this level");
1512 Sprintf(eos(bp), " (attached to %s)",
1513 noit_mon_nam(mlsh));
1515 Sprintf(eos(bp), " (%s
\82É
\8c\8b\82Ñ
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é)",
1516 noit_mon_nam(mlsh));
1521 if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
1524 Strcpy(tmpbuf, "no");
1526 Sprintf(tmpbuf, "%d", obj->spe);
1527 Sprintf(eos(bp), " (%s candle%s%s)", tmpbuf, plur(obj->spe),
1528 !obj->lamplit ? " attached" : ", lit");
1531 Sprintf(eos(bp), "(
\88ê
\96{
\82à
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82È
\82¢)");
1534 Sprintf(eos(bp), "(%d
\96{
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é)", obj->spe);
1536 Sprintf(eos(bp), "(%d
\96{
\8cõ
\82Á
\82Ä
\82¢
\82é)", obj->spe);
1540 } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
1541 || obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
1543 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
1545 Strcat(prefix, "partly used ");
1547 Strcat(prefix, "
\8eg
\82¢
\82³
\82µ
\82Ì");
1550 Strcat(bp, " (lit)");
1552 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1555 if (objects[obj->otyp].oc_charged)
1562 Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
1564 Sprintf(eos(bp), "(%d:%d)", (int) obj->recharged, obj->spe);
1567 if (obj->otyp == POT_OIL && obj->lamplit)
1569 Strcat(bp, " (lit)");
1571 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1575 if (obj->owornmask & W_RINGR)
1577 Strcat(bp, " (on right ");
1579 Strcat(bp, "(
\89E");
1580 if (obj->owornmask & W_RINGL)
1582 Strcat(bp, " (on left ");
1584 Strcat(bp, "(
\8d¶");
1585 if (obj->owornmask & W_RING) {
1586 Strcat(bp, body_part(HAND));
1589 if (known && objects[obj->otyp].oc_charged) {
1591 Strcat(prefix, " ");
1593 Strcat(prefix, sitoa(obj->spe));
1594 Strcat(prefix, " ");
1600 Strcat(prefix, "partly eaten ");
1602 Strcat(prefix, "
\90H
\82×
\82©
\82¯
\82Ì");
1603 if (obj->otyp == CORPSE) {
1604 /* (quan == 1) => want corpse_xname() to supply article,
1605 (quan != 1) => already have count or "some" as prefix;
1606 "corpse" is already in the buffer returned by xname() */
1607 unsigned cxarg = (((obj->quan != 1L) ? 0 : CXN_ARTICLE)
1609 char *cxstr = corpse_xname(obj, prefix, cxarg);
1612 Sprintf(prefix, "%s ", cxstr);
1614 Sprintf(prefix, "%s
\82Ì", cxstr);
1616 /* avoid having doname(corpse) consume an extra obuf */
1618 } else if (obj->otyp == EGG) {
1619 #if 0 /* corpses don't tell if they're stale either */
1620 if (known && stale_egg(obj))
1621 Strcat(prefix, "stale ");
1624 && (known || (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
1626 Strcat(prefix, mons[omndx].mname);
1627 Strcat(prefix, " ");
1629 Strcat(prefix, mons[omndx].mname);
1630 Strcat(prefix, "
\82Ì");
1634 Strcat(bp, " (laid by you)");
1636 Strcat(bp, "(
\82 \82È
\82½
\82ª
\8eY
\82ñ
\82¾)");
1639 if (obj->otyp == MEAT_RING)
1644 add_erosion_words(obj, prefix);
1645 if (obj->owornmask & W_BALL)
1647 Strcat(bp, " (chained to you)");
1649 Strcat(bp, "(
\82 \82È
\82½
\82É
\8cq
\82ª
\82ê
\82Ä
\82¢
\82é)");
1653 if ((obj->owornmask & W_WEP) && !mrg_to_wielded) {
1654 if (obj->quan != 1L) {
1656 Strcat(bp, " (wielded)");
1658 Strcat(bp, "(
\91\95\94õ
\82µ
\82Ä
\82¢
\82é)");
1660 const char *hand_s = body_part(HAND);
1663 hand_s = makeplural(hand_s);
1664 /* note: Sting's glow message, if added, will insert text
1665 in front of "(weapon in hand)"'s closing paren */
1667 Sprintf(eos(bp), " (%sweapon in %s)",
1668 (obj->otyp == AKLYS) ? "tethered " : "", hand_s);
1669 #else /*
\83A
\83L
\83\8a\83X
\82ð
\93Á
\95Ê
\88µ
\82¢
\82µ
\82È
\82¢*/
1670 Sprintf(eos(bp), "(%s
\82É
\82µ
\82Ä
\82¢
\82é)", hand_s);
1673 if (warn_obj_cnt && obj == uwep && (EWarn_of_mon & W_WEP) != 0L) {
1674 if (!Blind) /* we know bp[] ends with ')'; overwrite that */
1676 Sprintf(eos(bp) - 1, ", %s %s)",
1677 glow_verb(warn_obj_cnt, TRUE),
1678 glow_color(obj->oartifact));
1680 Sprintf(eos(bp) - 1, ", %s%s
\82¢
\82é)",
1681 jconj_adj(glow_color(obj->oartifact)),
1682 jconj(glow_verb(warn_obj_cnt, TRUE), "
\82Ä"));
1687 if (obj->owornmask & W_SWAPWEP) {
1690 Sprintf(eos(bp), " (wielded in other %s)", body_part(HAND));
1692 Sprintf(eos(bp), "(
\8d¶%s
\82É
\82µ
\82Ä
\82¢
\82é)", body_part(HAND));
1695 Strcat(bp, " (alternate weapon; not wielded)");
1697 Strcat(bp, "(
\97\
\94õ
\82Ì
\95\90\8aí;
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢)");
1699 if (obj->owornmask & W_QUIVER) {
1700 switch (obj->oclass) {
1703 if (objects[obj->otyp].oc_skill == -P_BOW) {
1704 /* Ammo for a bow */
1706 Strcat(bp, " (in quiver)");
1708 Strcat(bp, "(
\96î
\93\9b\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1711 /* Ammo not for a bow */
1713 Strcat(bp, " (in quiver pouch)");
1715 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1719 /* Weapons not considered ammo */
1721 Strcat(bp, " (at the ready)");
1723 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1726 /* Small things and ammo not for a bow */
1733 Strcat(bp, " (in quiver pouch)");
1735 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1737 default: /* odd things */
1739 Strcat(bp, " (at the ready)");
1741 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1744 /* treat 'restoring' like suppress_price because shopkeeper and
1745 bill might not be available yet while restore is in progress */
1746 if (iflags.suppress_price || restoring) {
1747 ; /* don't attempt to obtain any stop pricing, even if 'with_price' */
1748 } else if (is_unpaid(obj)) { /* in inventory or in container in invent */
1749 long quotedprice = unpaid_cost(obj, TRUE);
1752 Sprintf(eos(bp), " (%s, %ld %s)",
1753 obj->unpaid ? "unpaid" : "contents",
1754 quotedprice, currency(quotedprice));
1756 Sprintf(eos(bp), " (%s, %ld%s)",
1757 obj->unpaid ? "
\96¢
\95¥
\82¢" : "
\92\86\90g",
1758 quotedprice, currency(quotedprice));
1760 } else if (with_price) { /* on floor or in container on floor */
1762 long price = get_cost_of_shop_item(obj, &nochrg);
1765 Sprintf(eos(bp), " (%s, %ld %s)",
1766 nochrg ? "contents" : "for sale",
1767 price, currency(price));
1768 else if (nochrg > 0)
1769 Strcat(bp, " (no charge)");
1771 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
1772 if (!strncmp(prefix, "a ", 2)) {
1773 /* save current prefix, without "a "; might be empty */
1774 Strcpy(tmpbuf, prefix + 2);
1775 /* set prefix[] to "", "a ", or "an " */
1776 (void) just_an(prefix, *tmpbuf ? tmpbuf : bp);
1777 /* append remainder of original prefix */
1778 Strcat(prefix, tmpbuf);
1782 /* show weight for items (debug tourist info)
1783 * aum is stolen from Crawl's "Arbitrary Unit of Measure" */
1784 if (wizard && iflags.wizweight) {
1785 Sprintf(eos(bp), " (%d aum)", obj->owt);
1788 bp = strprepend(bp, prefix);
1789 #else /*JP:
\81u
\96¼
\95t
\82¯
\82ç
\82ê
\82½
\81v
\82ð
\96ß
\82·*/
1790 Strcat(preprefix, prefix);
1791 bp = strprepend(bp, preprefix);
1800 return doname_base(obj, (unsigned) 0);
1803 /* Name of object including price. */
1805 doname_with_price(obj)
1808 return doname_base(obj, DONAME_WITH_PRICE);
1811 /* "some" instead of precise quantity if obj->dknown not set */
1813 doname_vague_quan(obj)
1817 * If it hasn't been seen up close and quantity is more than one,
1818 * use "some" instead of the quantity: "some gold pieces" rather
1819 * than "25 gold pieces". This is suboptimal, to put it mildly,
1820 * because lookhere and pickup report the precise amount.
1821 * Picking the item up while blind also shows the precise amount
1822 * for inventory display, then dropping it while still blind leaves
1823 * obj->dknown unset so the count reverts to "some" for farlook.
1825 * TODO: add obj->qknown flag for 'quantity known' on stackable
1826 * items; it could overlay obj->cknown since no containers stack.
1828 return doname_base(obj, DONAME_VAGUE_QUAN);
1831 /* used from invent.c */
1833 not_fully_identified(otmp)
1836 /* gold doesn't have any interesting attributes [yet?] */
1837 if (otmp->oclass == COIN_CLASS)
1838 return FALSE; /* always fully ID'd */
1839 /* check fundamental ID hallmarks first */
1840 if (!otmp->known || !otmp->dknown
1842 || (!otmp->bknown && otmp->otyp != SCR_MAIL)
1846 || !objects[otmp->otyp].oc_name_known)
1848 if ((!otmp->cknown && (Is_container(otmp) || otmp->otyp == STATUE))
1849 || (!otmp->lknown && Is_box(otmp)))
1851 if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
1853 /* otmp->rknown is the only item of interest if we reach here */
1855 * Note: if a revision ever allows scrolls to become fireproof or
1856 * rings to become shockproof, this checking will need to be revised.
1857 * `rknown' ID only matters if xname() will provide the info about it.
1860 || (otmp->oclass != ARMOR_CLASS && otmp->oclass != WEAPON_CLASS
1861 && !is_weptool(otmp) /* (redundant) */
1862 && otmp->oclass != BALL_CLASS)) /* (useless) */
1864 else /* lack of `rknown' only matters for vulnerable objects */
1865 return (boolean) (is_rustprone(otmp) || is_corrodeable(otmp)
1866 || is_flammable(otmp));
1869 /* format a corpse name (xname() omits monster type; doname() calls us);
1870 eatcorpse() also uses us for death reason when eating tainted glob */
1872 corpse_xname(otmp, adjective, cxn_flags)
1874 const char *adjective;
1875 unsigned cxn_flags; /* bitmask of CXN_xxx values */
1877 char *nambuf = nextobuf();
1878 int omndx = otmp->corpsenm;
1880 boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0,
1881 /* suppress "the" from "the unique monster corpse" */
1885 no_prefix = (cxn_flags & CXN_NO_PFX) != 0,
1886 /* include "the" for "the woodchuck corpse */
1887 the_prefix = (cxn_flags & CXN_PFX_THE) != 0,
1888 /* include "an" for "an ogre corpse */
1889 any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
1890 /* leave off suffix (do_name() appends "corpse" itself) */
1891 omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
1893 glob = (otmp->otyp != CORPSE && otmp->globby);
1897 mname = OBJ_NAME(objects[otmp->otyp]); /* "glob of <monster>" */
1898 } else if (omndx == NON_PM) { /* paranoia */
1903 /* [Possible enhancement: check whether corpse has monster traits
1904 attached in order to use priestname() for priests and minions.] */
1905 } else if (omndx == PM_ALIGNED_PRIEST) {
1906 /* avoid "aligned priest"; it just exposes internal details */
1912 mname = mons[omndx].mname;
1913 if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) {
1914 mname = s_suffix(mname);
1916 /* don't precede personal name like "Medusa" with an article */
1917 if (type_is_pname(&mons[omndx]))
1919 /* always precede non-personal unique monster name like
1920 "Oracle" with "the" unless explicitly overridden */
1921 else if (the_unique_pm(&mons[omndx]) && !no_prefix)
1926 the_prefix = any_prefix = FALSE;
1927 else if (the_prefix)
1928 any_prefix = FALSE; /* mutually exclusive */
1931 /* can't use the() the way we use an() below because any capitalized
1932 Name causes it to assume a personal name and return Name as-is;
1933 that's usually the behavior wanted, but here we need to force "the"
1934 to precede capitalized unique monsters (pnames are handled above) */
1935 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
1937 Strcat(nambuf, "the ");
1940 if (!adjective || !*adjective) {
1941 /* normal case: newt corpse */
1942 Strcat(nambuf, mname);
1944 /* adjective positioning depends upon format of monster name */
1945 if (possessive) /* Medusa's cursed partly eaten corpse */
1947 Sprintf(eos(nambuf), "%s %s", mname, adjective);
1949 Sprintf(eos(nambuf), "%s%s", mname, adjective);
1950 else /* cursed partly eaten troll corpse */
1952 Sprintf(eos(nambuf), "%s %s", adjective, mname);
1954 Sprintf(eos(nambuf), "%s%s", adjective, mname);
1955 /* in case adjective has a trailing space, squeeze it out */
1957 /* doname() might include a count in the adjective argument;
1958 if so, don't prepend an article */
1959 if (digit(*adjective))
1964 ; /* omit_corpse doesn't apply; quantity is always 1 */
1965 } else if (!omit_corpse) {
1967 Strcat(nambuf, " corpse");
1968 /* makeplural(nambuf) => append "s" to "corpse" */
1969 if (otmp->quan > 1L && !ignore_quan) {
1970 Strcat(nambuf, "s");
1971 any_prefix = FALSE; /* avoid "a newt corpses" */
1974 Strcat(nambuf, "
\82Ì
\8e\80\91Ì");
1978 /* it's safe to overwrite our nambuf after an() has copied
1979 its old value into another buffer */
1981 Strcpy(nambuf, an(nambuf));
1986 /* xname doesn't include monster type for "corpse"; cxname does */
1991 if (obj->otyp == CORPSE)
1992 return corpse_xname(obj, (const char *) 0, CXN_NORMAL);
1996 /* like cxname, but ignores quantity */
1998 cxname_singular(obj)
2001 if (obj->otyp == CORPSE)
2002 return corpse_xname(obj, (const char *) 0, CXN_SINGULAR);
2003 return xname_flags(obj, CXN_SINGULAR);
2006 /* treat an object as fully ID'd when it might be used as reason for death */
2011 struct obj save_obj;
2012 unsigned save_ocknown;
2013 char *buf, *save_ocuname, *save_oname = (char *) 0;
2015 /* bypass object twiddling for artifacts */
2017 return bare_artifactname(obj);
2019 /* remember original settings for core of the object;
2020 oextra structs other than oname don't matter here--since they
2021 aren't modified they don't need to be saved and restored */
2024 save_oname = ONAME(obj);
2026 /* killer name should be more specific than general xname; however, exact
2027 info like blessed/cursed and rustproof makes things be too verbose */
2028 obj->known = obj->dknown = 1;
2029 obj->bknown = obj->rknown = obj->greased = 0;
2030 /* if character is a priest[ess], bknown will get toggled back on */
2031 if (obj->otyp != POT_WATER)
2032 obj->blessed = obj->cursed = 0;
2034 obj->bknown = 1; /* describe holy/unholy water as such */
2035 /* "killed by poisoned <obj>" would be misleading when poison is
2036 not the cause of death and "poisoned by poisoned <obj>" would
2037 be redundant when it is, so suppress "poisoned" prefix */
2039 /* strip user-supplied name; artifacts keep theirs */
2040 if (!obj->oartifact && save_oname)
2041 ONAME(obj) = (char *) 0;
2042 /* temporarily identify the type of object */
2043 save_ocknown = objects[obj->otyp].oc_name_known;
2044 objects[obj->otyp].oc_name_known = 1;
2045 save_ocuname = objects[obj->otyp].oc_uname;
2046 objects[obj->otyp].oc_uname = 0; /* avoid "foo called bar" */
2048 /* format the object */
2049 if (obj->otyp == CORPSE) {
2051 Strcpy(buf, corpse_xname(obj, (const char *) 0, CXN_NORMAL));
2052 } else if (obj->otyp == SLIME_MOLD) {
2053 /* concession to "most unique deaths competition" in the annual
2054 devnull tournament, suppress player supplied fruit names because
2055 those can be used to fake other objects and dungeon features */
2058 Sprintf(buf, "deadly slime mold%s", plur(obj->quan));
2060 Strcpy(buf, "
\8aë
\8c¯
\82È
\82Ë
\82Î
\82Ë
\82Î
\83J
\83r");
2064 /* apply an article if appropriate; caller should always use KILLED_BY */
2065 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
2066 if (obj->quan == 1L && !strstri(buf, "'s ") && !strstri(buf, "s' "))
2067 buf = (obj_is_pname(obj) || the_unique_obj(obj)) ? the(buf) : an(buf);
2070 objects[obj->otyp].oc_name_known = save_ocknown;
2071 objects[obj->otyp].oc_uname = save_ocuname;
2072 *obj = save_obj; /* restore object's core settings */
2073 if (!obj->oartifact && save_oname)
2074 ONAME(obj) = save_oname;
2079 /* xname,doname,&c with long results reformatted to omit some stuff */
2081 short_oname(obj, func, altfunc, lenlimit)
2083 char *FDECL((*func), (OBJ_P)), /* main formatting routine */
2084 *FDECL((*altfunc), (OBJ_P)); /* alternate for shortest result */
2087 struct obj save_obj;
2088 char unamebuf[12], onamebuf[12], *save_oname, *save_uname, *outbuf;
2090 outbuf = (*func)(obj);
2091 if ((unsigned) strlen(outbuf) <= lenlimit)
2094 /* shorten called string to fairly small amount */
2095 save_uname = objects[obj->otyp].oc_uname;
2096 if (save_uname && strlen(save_uname) >= sizeof unamebuf) {
2097 (void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
2098 Strcpy(unamebuf + sizeof unamebuf - 4, "...");
2099 objects[obj->otyp].oc_uname = unamebuf;
2100 releaseobuf(outbuf);
2101 outbuf = (*func)(obj);
2102 objects[obj->otyp].oc_uname = save_uname; /* restore called string */
2103 if ((unsigned) strlen(outbuf) <= lenlimit)
2107 /* shorten named string to fairly small amount */
2108 save_oname = has_oname(obj) ? ONAME(obj) : 0;
2109 if (save_oname && strlen(save_oname) >= sizeof onamebuf) {
2110 (void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
2111 Strcpy(onamebuf + sizeof onamebuf - 4, "...");
2112 ONAME(obj) = onamebuf;
2113 releaseobuf(outbuf);
2114 outbuf = (*func)(obj);
2115 ONAME(obj) = save_oname; /* restore named string */
2116 if ((unsigned) strlen(outbuf) <= lenlimit)
2120 /* shorten both called and named strings;
2121 unamebuf and onamebuf have both already been populated */
2122 if (save_uname && strlen(save_uname) >= sizeof unamebuf && save_oname
2123 && strlen(save_oname) >= sizeof onamebuf) {
2124 objects[obj->otyp].oc_uname = unamebuf;
2125 ONAME(obj) = onamebuf;
2126 releaseobuf(outbuf);
2127 outbuf = (*func)(obj);
2128 if ((unsigned) strlen(outbuf) <= lenlimit) {
2129 objects[obj->otyp].oc_uname = save_uname;
2130 ONAME(obj) = save_oname;
2135 /* still long; strip several name-lengthening attributes;
2136 called and named strings are still in truncated form */
2138 obj->bknown = obj->rknown = obj->greased = 0;
2139 obj->oeroded = obj->oeroded2 = 0;
2140 releaseobuf(outbuf);
2141 outbuf = (*func)(obj);
2142 if (altfunc && (unsigned) strlen(outbuf) > lenlimit) {
2143 /* still long; use the alternate function (usually one of
2144 the jackets around minimal_xname()) */
2145 releaseobuf(outbuf);
2146 outbuf = (*altfunc)(obj);
2148 /* restore the object */
2151 ONAME(obj) = save_oname;
2153 objects[obj->otyp].oc_uname = save_uname;
2155 /* use whatever we've got, whether it's too long or not */
2160 * Used if only one of a collection of objects is named (e.g. in eat.c).
2163 singular(otmp, func)
2164 register struct obj *otmp;
2165 char *FDECL((*func), (OBJ_P));
2170 /* using xname for corpses does not give the monster type */
2171 if (otmp->otyp == CORPSE && func == xname)
2174 savequan = otmp->quan;
2176 nam = (*func)(otmp);
2177 otmp->quan = savequan;
2181 /* pick "", "a ", or "an " as article for 'str'; used by an() and doname() */
2183 just_an(outbuf, str)
2187 #if 0 /*JP*//*
\95s
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2193 /* single letter; might be used for named fruit */
2194 Strcpy(outbuf, index("aefhilmnosx", c0) ? "an " : "a ");
2195 } else if (!strncmpi(str, "the ", 4) || !strcmpi(str, "molten lava")
2196 || !strcmpi(str, "iron bars") || !strcmpi(str, "ice")) {
2199 if ((index(vowels, c0) && strncmpi(str, "one-", 4)
2200 && strncmpi(str, "eucalyptus", 10) && strncmpi(str, "unicorn", 7)
2201 && strncmpi(str, "uranium", 7) && strncmpi(str, "useful", 6))
2202 || (index("x", c0) && !index(vowels, lowc(str[1]))))
2203 Strcpy(outbuf, "an ");
2205 Strcpy(outbuf, "a ");
2217 char *buf = nextobuf();
2219 if (!str || !*str) {
2220 impossible("Alphabet soup: 'an(%s)'.", str ? "\"\"" : "<null>");
2221 return strcpy(buf, "an []");
2223 (void) just_an(buf, str);
2224 return strcat(buf, str);
2231 char *tmp = an(str);
2233 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
2240 * Prepend "the" if necessary; assumes str is a subject derived from xname.
2241 * Use type_is_pname() for monster names, not the(). the() is idempotent.
2247 char *buf = nextobuf();
2248 #if 0 /*JP*//*
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2249 boolean insert_the = FALSE;
2251 if (!str || !*str) {
2252 impossible("Alphabet soup: 'the(%s)'.", str ? "\"\"" : "<null>");
2253 return strcpy(buf, "the []");
2255 if (!strncmpi(str, "the ", 4)) {
2256 buf[0] = lowc(*str);
2257 Strcpy(&buf[1], str + 1);
2259 } else if (*str < 'A' || *str > 'Z'
2260 /* treat named fruit as not a proper name, even if player
2261 has assigned a capitalized proper name as his/her fruit */
2262 || fruit_from_name(str, TRUE, (int *) 0)) {
2263 /* not a proper name, needs an article */
2266 /* Probably a proper name, might not need an article */
2267 register char *tmp, *named, *called;
2270 /* some objects have capitalized adjectives in their names */
2271 if (((tmp = rindex(str, ' ')) != 0 || (tmp = rindex(str, '-')) != 0)
2272 && (tmp[1] < 'A' || tmp[1] > 'Z')) {
2274 } else if (tmp && index(str, ' ') < tmp) { /* has spaces */
2275 /* it needs an article if the name contains "of" */
2276 tmp = strstri(str, " of ");
2277 named = strstri(str, " named ");
2278 called = strstri(str, " called ");
2279 if (called && (!named || called < named))
2282 if (tmp && (!named || tmp < named)) /* found an "of" */
2284 /* stupid special case: lacks "of" but needs "the" */
2285 else if (!named && (l = strlen(str)) >= 31
2286 && !strcmp(&str[l - 31],
2287 "Platinum Yendorian Express Card"))
2292 Strcpy(buf, "the ");
2297 #else /*
\92P
\82É
\83R
\83s
\81[*/
2307 char *tmp = the(str);
2309 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
2318 register struct obj *otmp;
2319 register const char *verb;
2325 /* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */
2331 char prefix[PREFIX];
2332 char *bp = cxname(otmp);
2334 if (otmp->quan != 1L) {
2335 Sprintf(prefix, "%ld ", otmp->quan);
2336 bp = strprepend(bp, prefix);
2340 Strcat(bp, otense(otmp, verb));
2346 /* combine yname and aobjnam eg "your count cxname(otmp)" */
2352 char *s = aobjnam(obj, verb);
2354 /* leave off "your" for most of your artifacts, but prepend
2355 * "your" for unique objects and "foo of bar" quest artifacts */
2356 if (!carried(obj) || !obj_is_pname(obj)
2357 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2358 char *outbuf = shk_your(nextobuf(), obj);
2359 int space_left = BUFSZ - 1 - strlen(outbuf);
2361 s = strncat(outbuf, s, space_left);
2366 /* combine Yname2 and aobjnam eg "Your count cxname(otmp)" */
2372 register char *s = yobjnam(obj, verb);
2380 /* like aobjnam, but prepend "The", not count, and use xname */
2386 char *bp = The(xname(otmp));
2388 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2391 Strcat(bp, otense(otmp, verb));
2397 /* capitalized variant of doname() */
2402 char *s = doname(obj);
2408 /* returns "[your ]xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
2413 char *s = cxname(obj);
2415 /* leave off "your" for most of your artifacts, but prepend
2416 * "your" for unique objects and "foo of bar" quest artifacts */
2417 if (!carried(obj) || !obj_is_pname(obj)
2418 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2419 char *outbuf = shk_your(nextobuf(), obj);
2420 int space_left = BUFSZ - 1 - strlen(outbuf);
2422 s = strncat(outbuf, s, space_left);
2428 /* capitalized variant of yname() */
2433 char *s = yname(obj);
2441 /* returns "your minimal_xname(obj)"
2442 * or "Foobar's minimal_xname(obj)"
2443 * or "the minimal_xname(obj)"
2449 char *outbuf = nextobuf();
2450 char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
2452 int space_left = BUFSZ - 1 - strlen(s);
2454 return strncat(s, minimal_xname(obj), space_left);
2456 int space_left = BUFSZ - strlen(s);
2458 return strncat(s, minimal_xname(obj), space_left);
2462 /* capitalized variant of ysimple_name() */
2467 char *s = ysimple_name(obj);
2475 /* "scroll" or "scrolls" */
2480 char *simpleoname = minimal_xname(obj);
2482 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2483 if (obj->quan != 1L)
2484 simpleoname = makeplural(simpleoname);
2489 /* "a scroll" or "scrolls"; "a silver bell" or "the Bell of Opening" */
2494 char *simpleoname = simpleonames(obj);
2495 int otyp = obj->otyp;
2497 /* prefix with "the" if a unique item, or a fake one imitating same,
2498 has been formatted with its actual name (we let typename() handle
2499 any `known' and `dknown' checking necessary) */
2500 if (otyp == FAKE_AMULET_OF_YENDOR)
2501 otyp = AMULET_OF_YENDOR;
2502 if (objects[otyp].oc_unique
2503 && !strcmp(simpleoname, OBJ_NAME(objects[otyp])))
2504 return the(simpleoname);
2506 /* simpleoname is singular if quan==1, plural otherwise */
2507 if (obj->quan == 1L)
2508 simpleoname = an(simpleoname);
2512 /* "the scroll" or "the scrolls" */
2517 char *simpleoname = simpleonames(obj);
2519 return the(simpleoname);
2522 /* artifact's name without any object type or known/dknown/&c feedback */
2524 bare_artifactname(obj)
2529 if (obj->oartifact) {
2530 outbuf = nextobuf();
2531 Strcpy(outbuf, artiname(obj->oartifact));
2533 if (!strncmp(outbuf, "The ", 4))
2534 outbuf[0] = lowc(outbuf[0]);
2537 outbuf = xname(obj);
2543 static const char *wrp[] = {
2544 "wand", "ring", "potion", "scroll", "gem",
2545 "amulet", "spellbook", "spell book",
2546 /* for non-specific wishes */
2547 "weapon", "armor", "tool", "food", "comestible",
2550 static const char wrpsym[] = { WAND_CLASS, RING_CLASS, POTION_CLASS,
2551 SCROLL_CLASS, GEM_CLASS, AMULET_CLASS,
2552 SPBOOK_CLASS, SPBOOK_CLASS, WEAPON_CLASS,
2553 ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
2556 /* return form of the verb (input plural) if xname(otmp) were the subject */
2565 * verb is given in plural (without trailing s). Return as input
2566 * if the result of xname(otmp) would be plural. Don't bother
2567 * recomputing xname(otmp) at this time.
2569 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2570 if (!is_plural(otmp))
2571 return vtense((char *) 0, verb);
2579 /* various singular words that vtense would otherwise categorize as plural;
2580 also used by makesingular() to catch some special cases */
2581 static const char *const special_subjs[] = {
2582 "erinys", "manes", /* this one is ambiguous */
2583 "Cyclops", "Hippocrates", "Pelias", "aklys",
2584 "amnesia", "detect monsters", "paralysis", "shape changers",
2586 /* note: "detect monsters" and "shape changers" are normally
2587 caught via "<something>(s) of <whatever>", but they can be
2588 wished for using the shorter form, so we include them here
2589 to accommodate usage by makesingular during wishing */
2592 /* return form of the verb (input plural) for present tense 3rd person subj */
2595 register const char *subj;
2596 register const char *verb;
2598 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2599 char *buf = nextobuf(), *bspot;
2601 const char *sp, *spot;
2602 const char *const *spec;
2605 * verb is given in plural (without trailing s). Return as input
2606 * if subj appears to be plural. Add special cases as necessary.
2607 * Many hard cases can already be handled by using otense() instead.
2608 * If this gets much bigger, consider decomposing makeplural.
2609 * Note: monster names are not expected here (except before corpse).
2611 * Special case: allow null sobj to get the singular 3rd person
2612 * present tense form so we don't duplicate this code elsewhere.
2615 if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
2617 spot = (const char *) 0;
2618 for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
2619 if (!strncmpi(sp, " of ", 4) || !strncmpi(sp, " from ", 6)
2620 || !strncmpi(sp, " called ", 8) || !strncmpi(sp, " named ", 7)
2621 || !strncmpi(sp, " labeled ", 9)) {
2627 len = (int) strlen(subj);
2629 spot = subj + len - 1;
2632 * plural: anything that ends in 's', but not '*us' or '*ss'.
2633 * Guess at a few other special cases that makeplural creates.
2635 if ((lowc(*spot) == 's' && spot != subj
2636 && !index("us", lowc(*(spot - 1))))
2637 || !BSTRNCMPI(subj, spot - 3, "eeth", 4)
2638 || !BSTRNCMPI(subj, spot - 3, "feet", 4)
2639 || !BSTRNCMPI(subj, spot - 1, "ia", 2)
2640 || !BSTRNCMPI(subj, spot - 1, "ae", 2)) {
2641 /* check for special cases to avoid false matches */
2642 len = (int) (spot - subj) + 1;
2643 for (spec = special_subjs; *spec; spec++) {
2644 ltmp = strlen(*spec);
2645 if (len == ltmp && !strncmpi(*spec, subj, len))
2647 /* also check for <prefix><space><special_subj>
2648 to catch things like "the invisible erinys" */
2649 if (len > ltmp && *(spot - ltmp) == ' '
2650 && !strncmpi(*spec, spot - ltmp + 1, ltmp))
2654 return strcpy(buf, verb);
2657 * 3rd person plural doesn't end in telltale 's';
2658 * 2nd person singular behaves as if plural.
2660 if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
2661 return strcpy(buf, verb);
2666 len = (int) strlen(buf);
2667 bspot = buf + len - 1;
2669 if (!strcmpi(buf, "are")) {
2670 Strcasecpy(buf, "is");
2671 } else if (!strcmpi(buf, "have")) {
2672 Strcasecpy(bspot - 1, "s");
2673 } else if (index("zxs", lowc(*bspot))
2674 || (len >= 2 && lowc(*bspot) == 'h'
2675 && index("cs", lowc(*(bspot - 1))))
2676 || (len == 2 && lowc(*bspot) == 'o')) {
2677 /* Ends in z, x, s, ch, sh; add an "es" */
2678 Strcasecpy(bspot + 1, "es");
2679 } else if (lowc(*bspot) == 'y' && !index(vowels, lowc(*(bspot - 1)))) {
2680 /* like "y" case in makeplural */
2681 Strcasecpy(bspot, "ies");
2683 Strcasecpy(bspot + 1, "s");
2686 #else /*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
2697 const char *sing, *plur;
2700 /* word pairs that don't fit into formula-based transformations;
2701 also some suffices which have very few--often one--matches or
2702 which aren't systematically reversible (knives, staves) */
2703 static struct sing_plur one_off[] = {
2705 "children" }, /* (for wise guys who give their food funny names) */
2706 { "cubus", "cubi" }, /* in-/suc-cubus */
2707 { "culus", "culi" }, /* homunculus */
2708 { "djinni", "djinn" },
2709 { "erinys", "erinyes" },
2711 { "fungus", "fungi" },
2712 { "goose", "geese" },
2713 { "knife", "knives" },
2714 { "labrum", "labra" }, /* candelabrum */
2715 { "louse", "lice" },
2716 { "mouse", "mice" },
2717 { "mumak", "mumakil" },
2718 { "nemesis", "nemeses" },
2721 { "passerby", "passersby" },
2722 { "rtex", "rtices" }, /* vortex */
2723 { "serum", "sera" },
2724 { "staff", "staves" },
2725 { "tooth", "teeth" },
2729 static const char *const as_is[] = {
2730 /* makesingular() leaves these plural due to how they're used */
2731 "boots", "shoes", "gloves", "lenses", "scales",
2732 "eyes", "gauntlets", "iron bars",
2733 /* both singular and plural are spelled the same */
2734 "bison", "deer", "elk", "fish", "fowl",
2735 "tuna", "yaki", "-hai", "krill", "manes",
2736 "moose", "ninja", "sheep", "ronin", "roshi",
2737 "shito", "tengu", "ki-rin", "Nazgul", "gunyoki",
2738 "piranha", "samurai", "shuriken", 0,
2739 /* Note: "fish" and "piranha" are collective plurals, suitable
2740 for "wiped out all <foo>". For "3 <foo>", they should be
2741 "fishes" and "piranhas" instead. We settle for collective
2742 variant instead of attempting to support both. */
2745 /* singularize/pluralize decisions common to both makesingular & makeplural */
2747 singplur_lookup(basestr, endstring, to_plural, alt_as_is)
2748 char *basestr, *endstring; /* base string, pointer to eos(string) */
2749 boolean to_plural; /* true => makeplural, false => makesingular */
2750 const char *const *alt_as_is; /* another set like as_is[] */
2752 const struct sing_plur *sp;
2753 const char *same, *other, *const *as;
2755 int baselen = strlen(basestr);
2757 for (as = as_is; *as; ++as) {
2758 al = (int) strlen(*as);
2759 if (!BSTRCMPI(basestr, endstring - al, *as))
2763 for (as = alt_as_is; *as; ++as) {
2764 al = (int) strlen(*as);
2765 if (!BSTRCMPI(basestr, endstring - al, *as))
2770 /* avoid false hit on one_off[].plur == "lice" or .sing == "goose";
2771 if more of these turn up, one_off[] entries will need to flagged
2772 as to which are whole words and which are matchable as suffices
2773 then matching in the loop below will end up becoming more complex */
2774 if (!strcmpi(basestr, "slice")
2775 || !strcmpi(basestr, "mongoose")) {
2777 Strcasecpy(endstring, "s");
2780 /* skip "ox" -> "oxen" entry when pluralizing "<something>ox"
2781 unless it is muskox */
2782 if (to_plural && baselen > 2 && !strcmpi(endstring - 2, "ox")
2783 && !(baselen > 5 && !strcmpi(endstring - 6, "muskox"))) {
2784 /* "fox" -> "foxes" */
2785 Strcasecpy(endstring, "es");
2789 if (baselen > 2 && !strcmpi(endstring - 3, "man")
2790 && badman(basestr, to_plural)) {
2791 Strcasecpy(endstring, "s");
2795 if (baselen > 2 && !strcmpi(endstring - 3, "men")
2796 && badman(basestr, to_plural))
2799 for (sp = one_off; sp->sing; sp++) {
2800 /* check whether endstring already matches */
2801 same = to_plural ? sp->plur : sp->sing;
2802 al = (int) strlen(same);
2803 if (!BSTRCMPI(basestr, endstring - al, same))
2804 return TRUE; /* use as-is */
2805 /* check whether it matches the inverse; if so, transform it */
2806 other = to_plural ? sp->sing : sp->plur;
2807 al = (int) strlen(other);
2808 if (!BSTRCMPI(basestr, endstring - al, other)) {
2809 Strcasecpy(endstring - al, same);
2810 return TRUE; /* one_off[] transformation */
2816 /* searches for common compounds, ex. lump of royal jelly */
2818 singplur_compound(str)
2821 /* if new entries are added, be sure to keep compound_start[] in sync */
2822 static const char *const compounds[] =
2824 " of ", " labeled ", " called ",
2825 " named ", " above", /* lurkers above */
2826 " versus ", " from ", " in ",
2827 " on ", " a la ", " with", /* " with "? */
2828 " de ", " d'", " du ",
2830 }, /* list of first characters for all compounds[] entries */
2831 compound_start[] = " -";
2833 const char *const *cmpd;
2836 for (p = str; *p; ++p) {
2837 /* substring starting at p can only match if *p is found
2838 within compound_start[] */
2839 if (!index(compound_start, *p))
2842 /* check current substring against all words in the compound[] list */
2843 for (cmpd = compounds; *cmpd; ++cmpd)
2844 if (!strncmpi(p, *cmpd, (int) strlen(*cmpd)))
2847 /* wasn't recognized as a compound phrase */
2852 /* Plural routine; once upon a time it may have been chiefly used for
2853 * user-defined fruits, but it is now used extensively throughout the
2856 * For fruit, we have to try to account for everything reasonable the
2857 * player has; something unreasonable can still break the code.
2858 * However, it's still a lot more accurate than "just add an 's' at the
2859 * end", which Rogue uses...
2861 * Also used for plural monster names ("Wiped out all homunculi." or the
2862 * vanquished monsters list) and body parts. A lot of unique monsters have
2863 * names which get mangled by makeplural and/or makesingular. They're not
2864 * genocidable, and vanquished-mon handling does its own special casing
2865 * (for uniques who've been revived and re-killed), so we don't bother
2866 * trying to get those right here.
2868 * Also misused by muse.c to convert 1st person present verbs to 2nd person.
2869 * 3.6.0: made case-insensitive.
2875 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2876 register char *spot;
2877 char lo_c, *str = nextobuf();
2878 const char *excess = (char *) 0;
2882 while (*oldstr == ' ')
2884 if (!oldstr || !*oldstr) {
2885 impossible("plural of null?");
2889 Strcpy(str, oldstr);
2892 * Skip changing "pair of" to "pairs of". According to Webster, usual
2893 * English usage is use pairs for humans, e.g. 3 pairs of dancers,
2894 * and pair for objects and non-humans, e.g. 3 pair of boots. We don't
2895 * refer to pairs of humans in this game so just skip to the bottom.
2897 if (!strncmpi(str, "pair of ", 8))
2900 /* look for "foo of bar" so that we can focus on "foo" */
2901 if ((spot = singplur_compound(str)) != 0) {
2902 excess = oldstr + (int) (spot - str);
2908 while (spot > str && *spot == ' ')
2909 spot--; /* Strip blanks from end */
2911 /* Now spot is the last character of the string */
2915 /* Single letters */
2916 if (len == 1 || !letter(*spot)) {
2917 Strcpy(spot + 1, "'s");
2921 /* dispense with some words which don't need pluralization */
2923 static const char *const already_plural[] = {
2924 "ae", /* algae, larvae, &c */
2928 /* spot+1: synch up with makesingular's usage */
2929 if (singplur_lookup(str, spot + 1, TRUE, already_plural))
2932 /* more of same, but not suitable for blanket loop checking */
2933 if ((len == 2 && !strcmpi(str, "ya"))
2934 || (len >= 3 && !strcmpi(spot - 2, " ya")))
2938 /* man/men ("Wiped out all cavemen.") */
2939 if (len >= 3 && !strcmpi(spot - 2, "man")
2940 /* exclude shamans and humans etc */
2941 && !badman(str, TRUE)) {
2942 Strcasecpy(spot - 1, "en");
2945 if (lowc(*spot) == 'f') { /* (staff handled via one_off[]) */
2946 lo_c = lowc(*(spot - 1));
2947 if (len >= 3 && !strcmpi(spot - 2, "erf")) {
2948 /* avoid "nerf" -> "nerves", "serf" -> "serves" */
2949 ; /* fall through to default (append 's') */
2950 } else if (index("lr", lo_c) || index(vowels, lo_c)) {
2951 /* [aeioulr]f to [aeioulr]ves */
2952 Strcasecpy(spot, "ves");
2956 /* ium/ia (mycelia, baluchitheria) */
2957 if (len >= 3 && !strcmpi(spot - 2, "ium")) {
2958 Strcasecpy(spot - 2, "ia");
2961 /* algae, larvae, hyphae (another fungus part) */
2962 if ((len >= 4 && !strcmpi(spot - 3, "alga"))
2964 && (!strcmpi(spot - 4, "hypha") || !strcmpi(spot - 4, "larva")))
2965 || (len >= 6 && !strcmpi(spot - 5, "amoeba"))
2966 || (len >= 8 && (!strcmpi(spot - 7, "vertebra")))) {
2968 Strcasecpy(spot + 1, "e");
2971 /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
2972 if (len > 3 && !strcmpi(spot - 1, "us")
2973 && !((len >= 5 && !strcmpi(spot - 4, "lotus"))
2974 || (len >= 6 && !strcmpi(spot - 5, "wumpus")))) {
2975 Strcasecpy(spot - 1, "i");
2978 /* sis/ses (nemesis) */
2979 if (len >= 3 && !strcmpi(spot - 2, "sis")) {
2980 Strcasecpy(spot - 1, "es");
2983 /* matzoh/matzot, possible food name */
2985 && (!strcmpi(spot - 5, "matzoh") || !strcmpi(spot - 5, "matzah"))) {
2986 Strcasecpy(spot - 1, "ot"); /* oh/ah -> ot */
2990 && (!strcmpi(spot - 4, "matzo") || !strcmpi(spot - 4, "matza"))) {
2991 Strcasecpy(spot, "ot"); /* o/a -> ot */
2995 /* note: -eau/-eaux (gateau, bordeau...) */
2996 /* note: ox/oxen, VAX/VAXen, goose/geese */
3000 /* Ends in z, x, s, ch, sh; add an "es" */
3001 if (index("zxs", lo_c)
3002 || (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot - 1))))
3003 /* Kludge to get "tomatoes" and "potatoes" right */
3004 || (len >= 4 && !strcmpi(spot - 2, "ato"))
3005 || (len >= 5 && !strcmpi(spot - 4, "dingo"))) {
3006 Strcasecpy(spot + 1, "es"); /* append es */
3009 /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
3010 if (lo_c == 'y' && !index(vowels, lowc(*(spot - 1)))) {
3011 Strcasecpy(spot, "ies"); /* y -> ies */
3014 /* Default: append an 's' */
3015 Strcasecpy(spot + 1, "s");
3019 Strcat(str, excess);
3020 #else /*JP*//*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
3021 char *str = nextobuf();
3022 Strcpy(str, oldstr);
3028 * Singularize a string the user typed in; this helps reduce the complexity
3029 * of readobjnam, and is also used in pager.c to singularize the string
3030 * for which help is sought.
3032 * "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)?
3033 * Its inclusion in as_is[]/special_subj[] makes it get treated as the former.
3035 * A lot of unique monsters have names ending in s; plural, or singular
3036 * from plural, doesn't make much sense for them so we don't bother trying.
3037 * 3.6.0: made case-insensitive.
3040 makesingular(oldstr)
3043 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
3044 register char *p, *bp;
3045 const char *excess = 0;
3046 char *str = nextobuf();
3049 while (*oldstr == ' ')
3051 if (!oldstr || !*oldstr) {
3052 impossible("singular of null?");
3057 bp = strcpy(str, oldstr);
3059 /* check for "foo of bar" so that we can focus on "foo" */
3060 if ((p = singplur_compound(bp)) != 0) {
3061 excess = oldstr + (int) (p - bp);
3066 /* dispense with some words which don't need singularization */
3067 if (singplur_lookup(bp, p, FALSE, special_subjs))
3070 /* remove -s or -es (boxes) or -ies (rubies) */
3071 if (p >= bp + 1 && lowc(p[-1]) == 's') {
3072 if (p >= bp + 2 && lowc(p[-2]) == 'e') {
3073 if (p >= bp + 3 && lowc(p[-3]) == 'i') { /* "ies" */
3074 if (!BSTRCMPI(bp, p - 7, "cookies")
3075 || (!BSTRCMPI(bp, p - 4, "pies")
3076 /* avoid false match for "harpies" */
3077 && (p - 4 == bp || p[-5] == ' '))
3078 /* alternate djinni/djinn spelling; not really needed */
3079 || (!BSTRCMPI(bp, p - 6, "genies")
3080 /* avoid false match for "progenies" */
3081 && (p - 6 == bp || p[-7] == ' '))
3082 || !BSTRCMPI(bp, p - 5, "mbies") /* zombie */
3083 || !BSTRCMPI(bp, p - 5, "yries")) /* valkyrie */
3085 Strcasecpy(p - 3, "y"); /* ies -> y */
3088 /* wolves, but f to ves isn't fully reversible */
3089 if (p - 4 >= bp && (index("lr", lowc(*(p - 4)))
3090 || index(vowels, lowc(*(p - 4))))
3091 && !BSTRCMPI(bp, p - 3, "ves")) {
3092 if (!BSTRCMPI(bp, p - 6, "cloves")
3093 || !BSTRCMPI(bp, p - 6, "nerves"))
3095 Strcasecpy(p - 3, "f"); /* ves -> f */
3098 /* note: nurses, axes but boxes, wumpuses */
3099 if (!BSTRCMPI(bp, p - 4, "eses")
3100 || !BSTRCMPI(bp, p - 4, "oxes") /* boxes, foxes */
3101 || !BSTRCMPI(bp, p - 4, "nxes") /* lynxes */
3102 || !BSTRCMPI(bp, p - 4, "ches")
3103 || !BSTRCMPI(bp, p - 4, "uses") /* lotuses */
3104 || !BSTRCMPI(bp, p - 4, "sses") /* priestesses */
3105 || !BSTRCMPI(bp, p - 5, "atoes") /* tomatoes */
3106 || !BSTRCMPI(bp, p - 7, "dingoes")
3107 || !BSTRCMPI(bp, p - 7, "Aleaxes")) {
3108 *(p - 2) = '\0'; /* drop es */
3110 } /* else fall through to mins */
3112 /* ends in 's' but not 'es' */
3113 } else if (!BSTRCMPI(bp, p - 2, "us")) { /* lotus, fungus... */
3114 if (BSTRCMPI(bp, p - 6, "tengus") /* but not these... */
3115 && BSTRCMPI(bp, p - 7, "hezrous"))
3117 } else if (!BSTRCMPI(bp, p - 2, "ss")
3118 || !BSTRCMPI(bp, p - 5, " lens")
3119 || (p - 4 == bp && !strcmpi(p - 4, "lens"))) {
3123 *(p - 1) = '\0'; /* drop s */
3125 } else { /* input doesn't end in 's' */
3127 if (!BSTRCMPI(bp, p - 3, "men")
3128 && !badman(bp, FALSE)) {
3129 Strcasecpy(p - 2, "an");
3132 /* matzot -> matzo, algae -> alga */
3133 if (!BSTRCMPI(bp, p - 6, "matzot") || !BSTRCMPI(bp, p - 2, "ae")) {
3134 *(p - 1) = '\0'; /* drop t/e */
3137 /* balactheria -> balactherium */
3138 if (p - 4 >= bp && !strcmpi(p - 2, "ia")
3139 && index("lr", lowc(*(p - 3))) && lowc(*(p - 4)) == 'e') {
3140 Strcasecpy(p - 1, "um"); /* a -> um */
3143 /* here we cannot find the plural suffix */
3147 /* if we stripped off a suffix (" of bar" from "foo of bar"),
3148 put it back now [strcat() isn't actually 100% safe here...] */
3153 #else /*JP*//*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
3154 char *str = nextobuf();
3155 Strcpy(str, oldstr);
3162 badman(basestr, to_plural)
3163 const char *basestr;
3164 boolean to_plural; /* true => makeplural, false => makesingular */
3166 /* these are all the prefixes for *man that don't have a *men plural */
3167 static const char *no_men[] = {
3168 "albu", "antihu", "anti", "ata", "auto", "bildungsro", "cai", "cay",
3169 "ceru", "corner", "decu", "des", "dura", "fir", "hanu", "het",
3170 "infrahu", "inhu", "nonhu", "otto", "out", "prehu", "protohu",
3171 "subhu", "superhu", "talis", "unhu", "sha",
3172 "hu", "un", "le", "re", "so", "to", "at", "a",
3174 /* these are all the prefixes for *men that don't have a *man singular */
3175 static const char *no_man[] = {
3176 "abdo", "acu", "agno", "ceru", "cogno", "cycla", "fleh", "grava",
3177 "hegu", "preno", "sonar", "speci", "dai", "exa", "fla", "sta", "teg",
3178 "tegu", "vela", "da", "hy", "lu", "no", "nu", "ra", "ru", "se", "vi",
3182 const char *endstr, *spot;
3184 if (!basestr || strlen(basestr) < 4)
3187 endstr = eos((char *) basestr);
3190 for (i = 0; i < SIZE(no_men); i++) {
3191 al = (int) strlen(no_men[i]);
3192 spot = endstr - (al + 3);
3193 if (!BSTRNCMPI(basestr, spot, no_men[i], al)
3194 && (spot == basestr || *(spot - 1) == ' '))
3198 for (i = 0; i < SIZE(no_man); i++) {
3199 al = (int) strlen(no_man[i]);
3200 spot = endstr - (al + 3);
3201 if (!BSTRNCMPI(basestr, spot, no_man[i], al)
3202 && (spot == basestr || *(spot - 1) == ' '))
3210 /* compare user string against object name string using fuzzy matching */
3212 wishymatch(u_str, o_str, retry_inverted)
3213 const char *u_str; /* from user, so might be variant spelling */
3214 const char *o_str; /* from objects[], so is in canonical form */
3215 boolean retry_inverted; /* optional extra "of" handling */
3217 static NEARDATA const char detect_SP[] = "detect ",
3218 SP_detection[] = " detection";
3219 char *p, buf[BUFSZ];
3221 /* ignore spaces & hyphens and upper/lower case when comparing */
3222 if (fuzzymatch(u_str, o_str, " -", TRUE))
3225 if (retry_inverted) {
3226 const char *u_of, *o_of;
3228 /* when just one of the strings is in the form "foo of bar",
3229 convert it into "bar foo" and perform another comparison */
3230 u_of = strstri(u_str, " of ");
3231 o_of = strstri(o_str, " of ");
3232 if (u_of && !o_of) {
3233 Strcpy(buf, u_of + 4);
3234 p = eos(strcat(buf, " "));
3235 while (u_str < u_of)
3238 return fuzzymatch(buf, o_str, " -", TRUE);
3239 } else if (o_of && !u_of) {
3240 Strcpy(buf, o_of + 4);
3241 p = eos(strcat(buf, " "));
3242 while (o_str < o_of)
3245 return fuzzymatch(u_str, buf, " -", TRUE);
3249 /* [note: if something like "elven speed boots" ever gets added, these
3250 special cases should be changed to call wishymatch() recursively in
3251 order to get the "of" inversion handling] */
3252 if (!strncmp(o_str, "dwarvish ", 9)) {
3253 if (!strncmpi(u_str, "dwarven ", 8))
3254 return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
3255 } else if (!strncmp(o_str, "elven ", 6)) {
3256 if (!strncmpi(u_str, "elvish ", 7))
3257 return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
3258 else if (!strncmpi(u_str, "elfin ", 6))
3259 return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
3260 } else if (!strncmp(o_str, detect_SP, sizeof detect_SP - 1)) {
3261 /* check for "detect <foo>" vs "<foo> detection" */
3262 if ((p = strstri(u_str, SP_detection)) != 0
3263 && !*(p + sizeof SP_detection - 1)) {
3264 /* convert "<foo> detection" into "detect <foo>" */
3266 Strcat(strcpy(buf, detect_SP), u_str);
3267 /* "detect monster" -> "detect monsters" */
3268 if (!strcmpi(u_str, "monster"))
3271 return fuzzymatch(buf, o_str, " -", TRUE);
3273 } else if (strstri(o_str, SP_detection)) {
3274 /* and the inverse, "<foo> detection" vs "detect <foo>" */
3275 if (!strncmpi(u_str, detect_SP, sizeof detect_SP - 1)) {
3276 /* convert "detect <foo>s" into "<foo> detection" */
3277 p = makesingular(u_str + sizeof detect_SP - 1);
3278 Strcat(strcpy(buf, p), SP_detection);
3279 /* caller may be looping through objects[], so avoid
3280 churning through all the obufs */
3282 return fuzzymatch(buf, o_str, " -", TRUE);
3284 } else if (strstri(o_str, "ability")) {
3285 /* when presented with "foo of bar", makesingular() used to
3286 singularize both foo & bar, but now only does so for foo */
3287 /* catch "{potion(s),ring} of {gain,restore,sustain} abilities" */
3288 if ((p = strstri(u_str, "abilities")) != 0
3289 && !*(p + sizeof "abilities" - 1)) {
3290 (void) strncpy(buf, u_str, (unsigned) (p - u_str));
3291 Strcpy(buf + (p - u_str), "ability");
3292 return fuzzymatch(buf, o_str, " -", TRUE);
3294 } else if (!strcmp(o_str, "aluminum")) {
3295 /* this special case doesn't really fit anywhere else... */
3296 /* (note that " wand" will have been stripped off by now) */
3297 if (!strcmpi(u_str, "aluminium"))
3298 return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
3305 const char *name, oclass;
3306 int f_o_range, l_o_range;
3309 #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¢*/
3310 /* wishable subranges of objects */
3311 STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
3312 { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
3313 { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
3314 { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
3315 { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
3316 { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
3317 { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
3318 { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
3319 { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3320 { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3321 { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
3322 { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
3323 { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
3324 { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
3325 { "dragon scales", ARMOR_CLASS, GRAY_DRAGON_SCALES,
3326 YELLOW_DRAGON_SCALES },
3327 { "dragon scale mail", ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL,
3328 YELLOW_DRAGON_SCALE_MAIL },
3329 { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
3330 { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
3331 { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
3332 { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
3337 #if 0 /*JP*//*not used*/
3338 /* alternate spellings; if the difference is only the presence or
3339 absence of spaces and/or hyphens (such as "pickaxe" vs "pick axe"
3340 vs "pick-axe") then there is no need for inclusion in this list;
3341 likewise for ``"of" inversions'' ("boots of speed" vs "speed boots") */
3342 static const struct alt_spellings {
3346 { "pickax", PICK_AXE },
3347 { "whip", BULLWHIP },
3348 { "saber", SILVER_SABER },
3349 { "silver sabre", SILVER_SABER },
3350 { "smooth shield", SHIELD_OF_REFLECTION },
3351 { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
3352 { "grey dragon scales", GRAY_DRAGON_SCALES },
3353 { "iron ball", HEAVY_IRON_BALL },
3354 { "lantern", BRASS_LANTERN },
3355 { "mattock", DWARVISH_MATTOCK },
3356 { "amulet of poison resistance", AMULET_VERSUS_POISON },
3357 { "potion of sleep", POT_SLEEPING },
3359 { "camera", EXPENSIVE_CAMERA },
3360 { "tee shirt", T_SHIRT },
3362 { "can opener", TIN_OPENER },
3363 { "kelp", KELP_FROND },
3364 { "eucalyptus", EUCALYPTUS_LEAF },
3365 { "royal jelly", LUMP_OF_ROYAL_JELLY },
3366 { "lembas", LEMBAS_WAFER },
3367 { "cookie", FORTUNE_COOKIE },
3368 { "pie", CREAM_PIE },
3369 { "marker", MAGIC_MARKER },
3370 { "hook", GRAPPLING_HOOK },
3371 { "grappling iron", GRAPPLING_HOOK },
3372 { "grapnel", GRAPPLING_HOOK },
3373 { "grapple", GRAPPLING_HOOK },
3374 { "protection from shape shifters", RIN_PROTECTION_FROM_SHAPE_CHAN },
3375 /* if we ever add other sizes, move this to o_ranges[] with "bag" */
3376 { "box", LARGE_BOX },
3377 /* normally we wouldn't have to worry about unnecessary <space>, but
3378 " stone" will get stripped off, preventing a wishymatch; that actually
3379 lets "flint stone" be a match, so we also accept bogus "flintstone" */
3380 { "luck stone", LUCKSTONE },
3381 { "load stone", LOADSTONE },
3382 { "touch stone", TOUCHSTONE },
3383 { "flintstone", FLINT },
3384 { (const char *) 0, 0 },
3389 rnd_otyp_by_wpnskill(skill)
3393 short otyp = STRANGE_OBJECT;
3395 for (i = bases[WEAPON_CLASS];
3396 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3397 if (objects[i].oc_skill == skill) {
3403 for (i = bases[WEAPON_CLASS];
3404 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3405 if (objects[i].oc_skill == skill)
3413 rnd_otyp_by_namedesc(name, oclass, xtra_prob)
3416 int xtra_prob; /* to force 0% random generation items to also be considered */
3419 short validobjs[NUM_OBJECTS];
3420 register const char *zn;
3421 int prob, maxprob = 0;
3423 if (!name || !*name)
3424 return STRANGE_OBJECT;
3426 memset((genericptr_t) validobjs, 0, sizeof validobjs);
3429 * When this spans classes (the !oclass case), the item
3430 * probabilities are not very useful because they don't take
3431 * the class generation probability into account. [If 10%
3432 * of spellbooks were blank and 1% of scrolls were blank,
3433 * "blank" would have 10/11 chance to yield a blook even though
3434 * scrolls are supposed to be much more common than books.]
3436 for (i = oclass ? bases[(int) oclass] : STRANGE_OBJECT + 1;
3437 i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
3439 /* don't match extra descriptions (w/o real name) */
3440 if ((zn = OBJ_NAME(objects[i])) == 0)
3444 *
\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É
3445 *
\82È
\82ç
\82È
\82¢
\82æ
\82¤
\82É
\82·
\82é
\81B
3446 *
\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
3448 if (i == FAKE_AMULET_OF_YENDOR)
3451 if (wishymatch(name, zn, TRUE)
3452 || ((zn = OBJ_DESCR(objects[i])) != 0
3453 && wishymatch(name, zn, FALSE))
3454 || ((zn = objects[i].oc_uname) != 0
3455 && wishymatch(name, zn, FALSE))) {
3456 validobjs[n++] = (short) i;
3457 maxprob += (objects[i].oc_prob + xtra_prob);
3461 if (n > 0 && maxprob) {
3462 prob = rn2(maxprob);
3463 for (i = 0; i < n - 1; i++)
3464 if ((prob -= (objects[validobjs[i]].oc_prob + xtra_prob)) < 0)
3466 return validobjs[i];
3468 return STRANGE_OBJECT;
3475 return (int) rnd_otyp_by_namedesc("shiny", oclass, 0);
3479 * Return something wished for. Specifying a null pointer for
3480 * the user request string results in a random object. Otherwise,
3481 * if asking explicitly for "nothing" (or "nil") return no_wish;
3482 * if not an object return &zeroobj; if an error (no matching object),
3487 readobjnam(bp, no_wish)
3489 struct obj *no_wish;
3493 register struct obj *otmp;
3494 int cnt, spe, spesgn, typ, very, rechrg;
3495 int blessed, uncursed, iscursed, ispoisoned, isgreased;
3496 int eroded, eroded2, erodeproof, locked, unlocked, broken;
3497 int halfeaten, mntmp, contents;
3498 int islit, unlabeled, ishistoric, isdiluted, trapped;
3500 int tmp, tinv, tvariety;
3504 int wetness, gsize = 0;
3506 int ftype = context.current_fruit;
3508 char fruitbuf[BUFSZ], globbuf[BUFSZ];
3510 char fruitbuf[BUFSZ];
3512 /* Fruits may not mess up the ability to wish for real objects (since
3513 * you can leave a fruit in a bones file and it will be added to
3514 * another person's game), so they must be checked for last, after
3515 * stripping all the possible prefixes and seeing if there's a real
3516 * name in there. So we have to save the full original name. However,
3517 * it's still possible to do things like "uncursed burnt Alaska",
3518 * or worse yet, "2 burned 5 course meals", so we need to loop to
3519 * strip off the prefixes again, this time stripping only the ones
3521 * We could get even more detailed so as to allow food names with
3522 * prefixes that _are_ possible on food, so you could wish for
3523 * "2 3 alarm chilis". Currently this isn't allowed; options.c
3524 * automatically sticks 'candied' in front of such names.
3527 char *un, *dn, *actualn, *origbp = bp;
3528 const char *name = 0;
3530 cnt = spe = spesgn = typ = 0;
3531 very = rechrg = blessed = uncursed = iscursed = ispoisoned =
3532 isgreased = eroded = eroded2 = erodeproof = halfeaten =
3533 islit = unlabeled = ishistoric = isdiluted = trapped =
3534 locked = unlocked = broken = 0;
3535 tvariety = RANDOM_TIN;
3540 contents = UNDEFINED;
3542 actualn = dn = un = 0;
3547 /* first, remove extra whitespace they may have typed */
3548 (void) mungspaces(bp);
3549 /* allow wishing for "nothing" to preserve wishless conduct...
3550 [now requires "wand of nothing" if that's what was really wanted] */
3552 if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil")
3553 || !strcmpi(bp, "none"))
3555 if (!strcmpi(bp, "
\82È
\82µ") || !strcmpi(bp, "
\96³
\82µ"))
3558 /* save the [nearly] unmodified choice string */
3559 Strcpy(fruitbuf, bp);
3566 if (!strncmpi(bp, "an ", l = 3) || !strncmpi(bp, "a ", l = 2)) {
3568 } else if (!strncmpi(bp, "the ", l = 4)) {
3569 ; /* just increment `bp' by `l' below */
3570 } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
3577 #if 1 /*JP*//*
\8cã
\82É
\90\94\8e\8c\82ª
\82 \82é
\82Æ
\82«
\82Í
\8dí
\8f\9c */
3578 if(!strncmp(bp, "
\8dû
\82Ì", l = 4) ||
3579 !strncmp(bp, "
\96{
\82Ì", l = 4) ||
3580 !strncmp(bp, "
\92\85\82Ì", l = 4) ||
3581 !strncmp(bp, "
\8cÂ
\82Ì", l = 4) ||
3582 !strncmp(bp, "
\96\87\82Ì", l = 4) ||
3583 !strncmp(bp, "
\82Â
\82Ì", l = 4) ||
3584 !strncmp(bp, "
\82Ì", l = 2))
3589 } else if (*bp == '+' || *bp == '-') {
3590 spesgn = (*bp++ == '+') ? 1 : -1;
3598 } else if (!strncmpi(bp, "blessed ", l = 8)
3599 || !strncmpi(bp, "holy ", l = 5)) {
3601 } else if (!strncmpi(bp, "
\8fj
\95\9f\82³
\82ê
\82½", l = 10)) {
3605 } else if (!strncmpi(bp, "moist ", l = 6)
3606 || !strncmpi(bp, "wet ", l = 4)) {
3608 } else if (!strncmpi(bp, "
\8e¼
\82Á
\82½", l = 6)
3609 || !strncmpi(bp, "
\94G
\82ê
\82½", l = 6)) {
3612 if (!strncmpi(bp, "wet ", 4))
3614 if (!strncmpi(bp, "
\94G
\82ê
\82½", 6))
3616 wetness = rn2(3) + 3;
3620 } else if (!strncmpi(bp, "cursed ", l = 7)
3621 || !strncmpi(bp, "unholy ", l = 7)) {
3623 } else if (!strncmpi(bp, "
\8eô
\82í
\82ê
\82½", l = 8)) {
3627 } else if (!strncmpi(bp, "uncursed ", l = 9)) {
3629 } else if (!strncmpi(bp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢", l = 14)) {
3633 } else if (!strncmpi(bp, "rustproof ", l = 10)
3634 || !strncmpi(bp, "erodeproof ", l = 11)
3635 || !strncmpi(bp, "corrodeproof ", l = 13)
3636 || !strncmpi(bp, "fixed ", l = 6)
3637 || !strncmpi(bp, "fireproof ", l = 10)
3638 || !strncmpi(bp, "rotproof ", l = 9)) {
3640 } else if (!strncmpi(bp, "
\8eK
\82Ñ
\82È
\82¢", l = 8)
3641 || !strncmpi(bp, "
\95\85\90H
\82µ
\82È
\82¢", l = 10)
3642 || !strncmpi(bp, "
\88À
\92è
\82µ
\82½", l = 8)
3643 || !strncmpi(bp, "
\94R
\82¦
\82È
\82¢", l = 8)) {
3647 } else if (!strncmpi(bp, "lit ", l = 4)
3648 || !strncmpi(bp, "burning ", l = 8)) {
3650 } else if (!strncmpi(bp, "
\8cõ
\82Á
\82Ä
\82¢
\82é", l = 10)
3651 || !strncmpi(bp, "
\94R
\82¦
\82Ä
\82¢
\82é", l = 10)) {
3655 } else if (!strncmpi(bp, "unlit ", l = 6)
3656 || !strncmpi(bp, "extinguished ", l = 13)) {
3658 } else if (!strncmpi(bp, "
\8fÁ
\82¦
\82Ä
\82¢
\82é", l = 10)) {
3661 /* "unlabeled" and "blank" are synonymous */
3663 } else if (!strncmpi(bp, "unlabeled ", l = 10)
3664 || !strncmpi(bp, "unlabelled ", l = 11)
3665 || !strncmpi(bp, "blank ", l = 6)) {
3667 } else if (!strncmpi(bp, "
\83\89\83x
\83\8b\82Ì
\82È
\82¢", l = 12)
3668 || !strncmpi(bp, "
\90^
\82Á
\94\92\82È", l = 8)) {
3672 } else if (!strncmpi(bp, "poisoned ", l = 9)) {
3674 } else if (!strncmpi(bp, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½", l = 12)) {
3677 /* "trapped" recognized but not honored outside wizard mode */
3678 } else if (!strncmpi(bp, "trapped ", l = 8)) {
3679 trapped = 0; /* undo any previous "untrapped" */
3682 } else if (!strncmpi(bp, "untrapped ", l = 10)) {
3683 trapped = 2; /* not trapped */
3684 /* locked, unlocked, broken: box/chest lock states */
3686 } else if (!strncmpi(bp, "locked ", l = 7)) {
3688 } else if (!strncmpi(bp, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82½", l = 12)) {
3690 locked = 1, unlocked = broken = 0;
3692 } else if (!strncmpi(bp, "unlocked ", l = 9)) {
3694 } else if (!strncmpi(bp, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82Ä
\82¢
\82È
\82¢", l = 18)) {
3696 unlocked = 1, locked = broken = 0;
3698 } else if (!strncmpi(bp, "broken ", l = 7)) {
3700 } else if (!strncmpi(bp, "
\8c®
\82Ì
\89ó
\82ê
\82½", l = 10)) {
3702 broken = 1, locked = unlocked = 0;
3704 } else if (!strncmpi(bp, "greased ", l = 8)) {
3706 } else if (!strncmpi(bp, "
\96û
\82Ì
\93h
\82ç
\82ê
\82½", l = 12)
3707 || !strncmpi(bp, "
\8e\89\82Ì
\93h
\82ç
\82ê
\82½", l = 12)) {
3711 } else if (!strncmpi(bp, "very ", l = 5)) {
3713 } else if (!strncmpi(bp, "
\82Æ
\82Ä
\82à", l = 6)) {
3715 /* very rusted very heavy iron ball */
3718 } else if (!strncmpi(bp, "thoroughly ", l = 11)) {
3720 } else if (!strncmpi(bp, "
\82©
\82È
\82è", l = 6)) {
3724 } else if (!strncmpi(bp, "rusty ", l = 6)
3725 || !strncmpi(bp, "rusted ", l = 7)
3726 || !strncmpi(bp, "burnt ", l = 6)
3727 || !strncmpi(bp, "burned ", l = 7)) {
3729 } else if (!strncmpi(bp, "
\8eK
\82Ñ
\82½", l = 6)
3730 || !strncmpi(bp, "
\94R
\82¦
\82½", l = 6)) {
3735 } else if (!strncmpi(bp, "corroded ", l = 9)
3736 || !strncmpi(bp, "rotted ", l = 7)) {
3738 } else if (!strncmpi(bp, "
\95\85\90H
\82µ
\82½", l = 8)
3739 || !strncmpi(bp, "
\95\85\82Á
\82½", l = 6)) {
3744 } else if (!strncmpi(bp, "partly eaten ", l = 13)
3745 || !strncmpi(bp, "partially eaten ", l = 16)) {
3747 } else if (!strncmpi(bp, "
\90H
\82×
\82©
\82¯
\82Ì", l = 10)) {
3751 } else if (!strncmpi(bp, "historic ", l = 9)) {
3753 } else if (!strncmpi(bp, "
\97ð
\8ej
\93I
\82È", l = 8)) {
3757 } else if (!strncmpi(bp, "diluted ", l = 8)) {
3759 } else if (!strncmpi(bp, "
\94\96\82Ü
\82Á
\82½", l = 8)) {
3763 } else if (!strncmpi(bp, "empty ", l = 6)) {
3765 } else if (!strncmpi(bp, "
\8bó
\82Á
\82Û
\82Ì", l = 8)) {
3769 } else if (!strncmpi(bp, "small ", l = 6)) { /* glob sizes */
3771 } else if (!strncmpi(bp, "
\8f¬
\82³
\82¢", l = 6)) { /* glob sizes */
3773 /* "small" might be part of monster name (mimic, if wishing
3774 for its corpse) rather than prefix for glob size; when
3775 used for globs, it might be either "small glob of <foo>" or
3776 "small <foo> glob" and user might add 's' even though plural
3777 doesn't accomplish anything because globs don't stack */
3778 if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
3782 } else if (!strncmpi(bp, "medium ", l = 7)) {
3784 } else if (!strncmpi(bp, "
\92\86\82
\82ç
\82¢
\82Ì", l = 10)) {
3786 /* xname() doesn't display "medium" but without this
3787 there'd be no way to ask for the intermediate size
3788 ("glob" without size prefix yields smallest one) */
3791 } else if (!strncmpi(bp, "large ", l = 6)) {
3793 } else if (!strncmpi(bp, "
\91å
\82«
\82¢", l = 6)) {
3795 /* "large" might be part of monster name (dog, cat, koboold,
3796 mimic) or object name (box, round shield) rather than
3797 prefix for glob size */
3798 if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
3800 /* "very large " had "very " peeled off on previous iteration */
3801 gsize = (very != 1) ? 3 : 4;
3807 cnt = 1; /* will be changed to 2 if makesingular() changes string */
3808 if (strlen(bp) > 1 && (p = rindex(bp, '(')) != 0) {
3809 boolean keeptrailingchars = TRUE;
3811 p[(p > bp && p[-1] == ' ') ? -1 : 0] = '\0'; /*terminate bp */
3812 ++p; /* advance past '(' */
3813 if (!strncmpi(p, "lit)", 4)) {
3815 p += 4 - 1; /* point at ')' */
3829 /* mis-matched parentheses; rest of string will be ignored
3830 * [probably we should restore everything back to '('
3831 * instead since it might be part of "named ..."]
3833 keeptrailingchars = FALSE;
3838 if (keeptrailingchars) {
3841 /* 'pp' points at 'pb's terminating '\0',
3842 'p' points at ')' and will be incremented past it */
3849 * otmp->spe is type schar, so we don't want spe to be any bigger or
3850 * smaller. Also, spe should always be positive --some cheaters may
3851 * try to confuse atoi().
3854 spesgn = -1; /* cheaters get what they deserve */
3857 if (spe > SCHAR_LIM)
3859 if (rechrg < 0 || rechrg > 7)
3860 rechrg = 7; /* recharge_limit */
3862 /* now we have the actual name, as delivered by xname, say
3863 * green potions called whisky
3864 * scrolls labeled "QWERTY"
3867 * very heavy iron ball named hoei
3871 if ((p = strstri(bp, " named ")) != 0) {
3875 if ((p = strstri(bp, " called ")) != 0) {
3878 #if 0 /*JP*//*
\83^
\83C
\83v
\95Ê
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢*/
3879 /* "helmet called telepathy" is not "helmet" (a specific type)
3880 * "shield called reflection" is not "shield" (a general type)
3882 for (i = 0; i < SIZE(o_ranges); i++)
3883 if (!strcmpi(bp, o_ranges[i].name)) {
3884 oclass = o_ranges[i].oclass;
3889 if ((p = strstri(bp, " labeled ")) != 0) {
3892 } else if ((p = strstri(bp, " labelled ")) != 0) {
3896 if ((p = strstri(bp, " of spinach")) != 0) {
3901 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8f\88\97\9d\82µ
\82È
\82¢*/
3903 * Skip over "pair of ", "pairs of", "set of" and "sets of".
3905 * Accept "3 pair of boots" as well as "3 pairs of boots". It is
3906 * valid English either way. See makeplural() for more on pair/pairs.
3908 * We should only double count if the object in question is not
3909 * referred to as a "pair of". E.g. We should double if the player
3910 * types "pair of spears", but not if the player types "pair of
3911 * lenses". Luckily (?) all objects that are referred to as pairs
3912 * -- boots, gloves, and lenses -- are also not mergable, so cnt is
3915 if (!strncmpi(bp, "pair of ", 8)) {
3918 } else if (!strncmpi(bp, "pairs of ", 9)) {
3922 } else if (!strncmpi(bp, "set of ", 7)) {
3924 } else if (!strncmpi(bp, "sets of ", 8)) {
3930 /* intercept pudding globs here; they're a valid wish target,
3931 * but we need them to not get treated like a corpse.
3933 * also don't let player wish for multiple globs.
3935 i = (int) strlen(bp);
3937 /* check for "glob", "<foo> glob", and "glob of <foo>" */
3938 if (!strcmpi(bp, "glob") || !BSTRCMPI(bp, bp + i - 5, " glob")
3939 || !strcmpi(bp, "globs") || !BSTRCMPI(bp, bp + i - 6, " globs")
3940 || (p = strstri(bp, "glob of ")) != 0
3941 || (p = strstri(bp, "globs of ")) != 0) {
3942 mntmp = name_to_mon(!p ? bp : (strstri(p, " of ") + 4));
3943 /* if we didn't recognize monster type, pick a valid one at random */
3944 if (mntmp == NON_PM)
3945 mntmp = rn1(PM_BLACK_PUDDING - PM_GRAY_OOZE, PM_GRAY_OOZE);
3946 /* construct canonical spelling in case name_to_mon() recognized a
3947 variant (grey ooze) or player used inverted syntax (<foo> glob);
3948 if player has given a valid monster type but not valid glob type,
3949 object name lookup won't find it and wish attempt will fail */
3950 Sprintf(globbuf, "glob of %s", mons[mntmp].mname);
3952 mntmp = NON_PM; /* not useful for "glob of <foo>" object lookup */
3953 cnt = 0; /* globs don't stack */
3954 oclass = FOOD_CLASS;
3955 actualn = bp, dn = 0;
3959 * Find corpse type using "of" (figurine of an orc, tin of orc meat)
3960 * Don't check if it's a wand or spellbook.
3961 * (avoid "wand/finger of death" confusion).
3963 if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
3964 && !strstri(bp, "finger ")) {
3965 if ((p = strstri(bp, "tin of ")) != 0) {
3966 if (!strcmpi(p + 7, "spinach")) {
3970 tmp = tin_variety_txt(p + 7, &tinv);
3972 mntmp = name_to_mon(p + 7 + tmp);
3976 } else if ((p = strstri(bp, " of ")) != 0
3977 && (mntmp = name_to_mon(p + 4)) >= LOW_PM)
3981 /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
3982 if (strncmpi(bp, "samurai sword", 13) /* not the "samurai" monster! */
3983 && strncmpi(bp, "wizard lock", 11) /* not the "wizard" monster! */
3984 && strncmpi(bp, "ninja-to", 8) /* not the "ninja" rank */
3985 && strncmpi(bp, "master key", 10) /* not the "master" rank */
3986 && strncmpi(bp, "magenta", 7)) { /* not the "mage" rank */
3987 if (mntmp < LOW_PM && strlen(bp) > 2
3988 && (mntmp = name_to_mon(bp)) >= LOW_PM) {
3989 int mntmptoo, mntmplen; /* double check for rank title */
3992 mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
3993 bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname)
3997 } else if (!strncmpi(bp, "s ", 2)) {
3999 } else if (!strncmpi(bp, "es ", 3)) {
4001 } else if (!*bp && !actualn && !dn && !un && !oclass) {
4002 /* no referent; they don't really mean a monster type */
4010 /*JP
\81u(
\89ö
\95¨
\96¼)
\82Ì
\89ò
\81v
\82Í
\8cÂ
\81X
\82ÉID
\82ª
\82 \82é
\82Ì
\82Å
\95Ê
\88µ
\82¢ */
4012 if (l > 4 && strncmp(bp + l - 4, "
\82Ì
\89ò", 4) == 0) {
4013 if ((mntmp = name_to_mon(bp)) >= PM_GRAY_OOZE
4014 && mntmp <= PM_BLACK_PUDDING) {
4015 mntmp = NON_PM; /* lie to ourselves */
4016 cnt = 0; /* force only one */
4019 /*JP:
\81u(
\89ö
\95¨
\96¼)
\82Ì(
\83A
\83C
\83e
\83\80)
\81v
\91Î
\89\9e */
4020 if ((mntmp = name_to_mon(bp)) >= LOW_PM) {
4021 const char *mp = mons[mntmp].mname;
4022 bp = strstri(bp, mp) + strlen(mp) + 2;
4028 #if 0 /*JP*//*
\92P
\90\94\89»
\82Í
\82µ
\82È
\82¢*/
4029 /* first change to singular if necessary */
4031 char *sng = makesingular(bp);
4033 if (strcmp(bp, sng)) {
4041 #if 0 /*JP*//*
\83X
\83y
\83\8b\97h
\82ê
\8f\88\97\9d\82Í
\82µ
\82È
\82¢*/
4042 /* Alternate spellings (pick-ax, silver sabre, &c) */
4044 const struct alt_spellings *as = spellings;
4047 if (fuzzymatch(bp, as->sp, " -", TRUE)) {
4053 /* can't use spellings list for this one due to shuffling */
4054 if (!strncmpi(bp, "grey spell", 10))
4057 if ((p = strstri(bp, "armour")) != 0) {
4058 /* skip past "armo", then copy remainder beyond "u" */
4060 while ((*p = *(p + 1)) != '\0')
4061 ++p; /* self terminating */
4067 /* dragon scales - assumes order of dragons */
4068 if (!strcmpi(bp, "scales") && mntmp >= PM_GRAY_DRAGON
4069 && mntmp <= PM_YELLOW_DRAGON) {
4070 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
4071 mntmp = NON_PM; /* no monster */
4075 /*JP:
\81u
\97Ø
\8aZ
\81v
\82ð
\90æ
\82É
\8f\88\97\9d\82µ
\82Ä
\82¨
\82 */
4076 if (!strcmpi(bp, "
\97Ø
\8aZ") && mntmp >= PM_GRAY_DRAGON
4077 && mntmp <= PM_YELLOW_DRAGON) {
4078 typ = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4079 mntmp = NON_PM; /* no monster */
4083 if (!strcmpi(bp, "
\97Ø") && mntmp >= PM_GRAY_DRAGON
4084 && mntmp <= PM_YELLOW_DRAGON) {
4085 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
4086 mntmp = NON_PM; /* no monster */
4093 if (!BSTRCMPI(bp, p - 10, "holy water")) {
4095 if ((p - bp) >= 12 && *(p - 12) == 'u')
4096 iscursed = 1; /* unholy water */
4101 #else /*JP:
\90¹
\90\85\82Æ
\95s
\8fò
\82È
\90\85\82ð
\95Ê
\82É
\94»
\92è*/
4102 if (!BSTRCMPI(bp, p - 4, "
\90¹
\90\85")) {
4107 if (!BSTRCMPI(bp, p - 8, "
\95s
\8fò
\82È
\90\85")) {
4114 if (unlabeled && !BSTRCMPI(bp, p - 6, "scroll")) {
4116 if (unlabeled && !BSTRCMPI(bp, p - 4, "
\8aª
\95¨")) {
4118 typ = SCR_BLANK_PAPER;
4122 if (unlabeled && !BSTRCMPI(bp, p - 9, "spellbook")) {
4124 if (unlabeled && !BSTRCMPI(bp, p - 6, "
\96\82\96@
\8f\91")) {
4126 typ = SPE_BLANK_PAPER;
4129 /* specific food rather than color of gem/potion/spellbook[/scales] */
4130 if (!BSTRCMPI(bp, p - 6, "orange") && mntmp == NON_PM) {
4135 * NOTE: Gold pieces are handled as objects nowadays, and therefore
4136 * this section should probably be reconsidered as well as the entire
4137 * gold/money concept. Maybe we want to add other monetary units as
4138 * well in the future. (TH)
4141 if (!BSTRCMPI(bp, p - 10, "gold piece")
4142 || !BSTRCMPI(bp, p - 7, "zorkmid")
4143 || !strcmpi(bp, "gold") || !strcmpi(bp, "money")
4144 || !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
4146 if (!BSTRCMPI(bp, p - 4, "
\8bà
\89Ý") || !BSTRCMPI(bp, p - 8, "
\83S
\81[
\83\8b\83h")
4147 || *bp == GOLD_SYM) {
4149 if (cnt > 5000 && !wizard)
4153 otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
4154 otmp->quan = (long) cnt;
4155 otmp->owt = weight(otmp);
4160 /* check for single character object class code ("/" for wand, &c) */
4161 if (strlen(bp) == 1 && (i = def_char_to_objclass(*bp)) < MAXOCLASSES
4162 && i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) {
4169 \89p
\8cê
\82È
\82ç XXXXX potion
\82Í
\95s
\8am
\92è
\96¼
\81Apotion of XXXXX
\82Í
\8am
\92è
\96¼
\82Æ
\82¢
\82¤
4170 \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¢
4172 /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */
4173 /* false hits on, e.g., rings for "ring mail". */
4174 if (strncmpi(bp, "enchant ", 8)
4175 && strncmpi(bp, "destroy ", 8)
4176 && strncmpi(bp, "detect food", 11)
4177 && strncmpi(bp, "food detection", 14)
4178 && strncmpi(bp, "ring mail", 9)
4179 && strncmpi(bp, "studded leather armor", 21)
4180 && strncmpi(bp, "leather armor", 13)
4181 && strncmpi(bp, "tooled horn", 11)
4182 && strncmpi(bp, "food ration", 11)
4183 && strncmpi(bp, "meat ring", 9))
4184 for (i = 0; i < (int) (sizeof wrpsym); i++) {
4185 register int j = strlen(wrp[i]);
4187 if (!strncmpi(bp, wrp[i], j)) {
4189 if (oclass != AMULET_CLASS) {
4191 if (!strncmpi(bp, " of ", 4))
4193 /* else if(*bp) ?? */
4198 if (!BSTRCMPI(bp, p - j, wrp[i])) {
4202 if (p > bp && p[-1] == ' ')
4210 /* Wishing in wizard mode can create traps and furniture.
4211 * Part I: distinguish between trap and object for the two
4212 * types of traps which have corresponding objects: bear trap
4213 * and land mine. "beartrap" (object) and "bear trap" (trap)
4214 * have a difference in spelling which we used to exploit by
4215 * adding a special case in wishymatch(), but "land mine" is
4216 * spelled the same either way so needs different handing.
4217 * Since we need something else for land mine, we've dropped
4218 * the bear trap hack so that both are handled exactly the
4219 * same. To get an armed trap instead of a disarmed object,
4220 * the player can prefix either the object name or the trap
4221 * name with "trapped " (which ordinarily applies to chests
4222 * and tins), or append something--anything at all except for
4223 * " object", but " trap" is suggested--to either the trap
4224 * name or the object name.
4226 if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) {
4227 boolean beartrap = (lowc(*bp) == 'b');
4228 char *zp = bp + 4; /* skip "bear"/"land" */
4231 ++zp; /* embedded space is optional */
4232 if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) {
4234 if (trapped == 2 || !strcmpi(zp, " object")) {
4235 /* "untrapped <foo>" or "<foo> object" */
4236 typ = beartrap ? BEARTRAP : LAND_MINE;
4238 } else if (trapped == 1 || *zp != '\0') {
4239 /* "trapped <foo>" or "<foo> trap" (actually "<foo>*") */
4240 int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE);
4242 /* use canonical trap spelling, skip object matching */
4243 Strcpy(bp, defsyms[idx].explanation);
4246 /* [no prefix or suffix; we're going to end up matching
4247 the object name and getting a disarmed trap object] */
4251 #if 0 /*JP*//* mail/armor
\8aÖ
\98A
\82Å
\82Ì
\82Ý
\8eg
\82¤
\83\89\83x
\83\8b */
4254 #if 0 /*JP*//*
\83^
\83C
\83v
\95Ê
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢ */
4255 /* "grey stone" check must be before general "stone" */
4256 for (i = 0; i < SIZE(o_ranges); i++)
4257 if (!strcmpi(bp, o_ranges[i].name)) {
4258 typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
4263 #if 0 /*JP*//*
\90Î
\82Ì
\93Á
\95Ê
\8f\88\97\9d\82Í
\95s
\97v */
4264 if (!BSTRCMPI(bp, p - 6, " stone") || !BSTRCMPI(bp, p - 4, " gem")) {
4265 p[!strcmpi(p - 4, " gem") ? -4 : -6] = '\0';
4269 } else if (!strcmpi(bp, "looking glass")) {
4270 ; /* avoid false hit on "* glass" */
4271 } else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
4272 register char *g = bp;
4274 /* treat "broken glass" as a non-existent item; since "broken" is
4275 also a chest/box prefix it might have been stripped off above */
4276 if (broken || strstri(g, "broken"))
4277 return (struct obj *) 0;
4278 if (!strncmpi(g, "worthless ", 10))
4280 if (!strncmpi(g, "piece of ", 9))
4282 if (!strncmpi(g, "colored ", 8))
4284 else if (!strncmpi(g, "coloured ", 9))
4286 if (!strcmpi(g, "glass")) { /* choose random color */
4287 /* 9 different kinds */
4288 typ = LAST_GEM + rnd(9);
4289 if (objects[typ].oc_class == GEM_CLASS)
4292 typ = 0; /* somebody changed objects[]? punt */
4293 } else { /* try to construct canonical form */
4296 Strcpy(tbuf, "worthless piece of ");
4297 Strcat(tbuf, g); /* assume it starts with the color */
4305 dn = actualn; /* ex. "skull cap" */
4309 /* check real names of gems first */
4310 if (!oclass && actualn) {
4311 for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
4312 register const char *zn;
4314 if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) {
4319 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í"tin"
\82ð
\96ó
\82µ
\95ª
\82¯
\82Ä
\82¢
\82é
\82Ì
\82Å
\95s
\97v */
4320 /* "tin of foo" would be caught above, but plain "tin" has
4321 a random chance of yielding "tin wand" unless we do this */
4322 if (!strcmpi(actualn, "tin")) {
4329 if (((typ = rnd_otyp_by_namedesc(actualn, oclass, 1)) != STRANGE_OBJECT)
4330 || ((typ = rnd_otyp_by_namedesc(dn, oclass, 1)) != STRANGE_OBJECT)
4331 || ((typ = rnd_otyp_by_namedesc(un, oclass, 1)) != STRANGE_OBJECT)
4332 || ((typ = rnd_otyp_by_namedesc(origbp, oclass, 1)) != STRANGE_OBJECT))
4337 struct Jitem *j = Japanese_items;
4340 if (actualn && !strcmpi(actualn, j->name)) {
4347 #if 0 /*JP*//* mail/armor
\82Ì
\95\
\8bL
\97h
\82ê
\83`
\83F
\83b
\83N
\82Í
\95s
\97v */
4348 /* if we've stripped off "armor" and failed to match anything
4349 in objects[], append "mail" and try again to catch misnamed
4350 requests like "plate armor" and "yellow dragon scale armor" */
4351 if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) {
4352 /* modifying bp's string is ok; we're about to resort
4353 to random armor if this also fails to match anything */
4354 Strcat(bp, " mail");
4359 if (!strcmpi(bp, "spinach")) {
4361 if (!strcmp(bp, "
\83z
\83E
\83\8c\83\93\91\90")) {
4367 /* Note: not strcmpi. 2 fruits, one capital, one not, are possible.
4368 Also not strncmp. We used to ignore trailing text with it, but
4369 that resulted in "grapefruit" matching "grape" if the latter came
4370 earlier than the former in the fruit list. */
4374 int blessedf, iscursedf, uncursedf, halfeatenf;
4376 blessedf = iscursedf = uncursedf = halfeatenf = 0;
4383 if (!strncmpi(fp, "an ", l = 3) || !strncmpi(fp, "a ", l = 2)) {
4385 } else if (!cntf && digit(*fp)) {
4392 } else if (!strncmpi(fp, "blessed ", l = 8)) {
4394 } else if (!strncmpi(fp, "cursed ", l = 7)) {
4396 } else if (!strncmpi(fp, "uncursed ", l = 9)) {
4398 } else if (!strncmpi(fp, "partly eaten ", l = 13)
4399 || !strncmpi(fp, "partially eaten ", l = 16)) {
4406 for (f = ffruit; f; f = f->nextf) {
4407 /* match type: 0=none, 1=exact, 2=singular, 3=plural */
4410 if (!strcmp(fp, f->fname))
4412 else if (!strcmp(fp, makesingular(f->fname)))
4414 else if (!strcmp(fp, makeplural(f->fname)))
4419 iscursed = iscursedf;
4420 uncursed = uncursedf;
4421 halfeaten = halfeatenf;
4422 /* adjust count if user explicitly asked for
4423 singular amount (can't happen unless fruit
4424 has been given an already pluralized name)
4425 or for plural amount */
4426 if (ftyp == 2 && !cntf)
4428 else if (ftyp == 3 && !cntf)
4437 if (!oclass && actualn) {
4440 /* Perhaps it's an artifact specified by name, not type */
4441 name = artifact_name(actualn, &objtyp);
4447 /* Let wizards wish for traps and furniture.
4448 * Must come after objects check so wizards can still wish for
4449 * trap objects like beartraps.
4450 * Disallow such topology tweaks for WIZKIT startup wishes.
4453 if (wizard && !program_state.wizkit_wishing) {
4455 int trap, x = u.ux, y = u.uy;
4457 for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
4461 tname = defsyms[trap_to_defsym(trap)].explanation;
4462 if (strncmpi(tname, bp, strlen(tname)))
4464 /* found it; avoid stupid mistakes */
4465 if (is_hole(trap) && !Can_fall_thru(&u.uz))
4467 if ((t = maketrap(x, y, trap)) != 0) {
4469 tname = defsyms[trap_to_defsym(trap)].explanation;
4470 pline("%s%s.", An(tname),
4471 (trap != MAGIC_PORTAL) ? "" : " to nowhere");
4473 pline("Creation of %s failed.", an(tname));
4474 return (struct obj *) &zeroobj;
4477 /* furniture and terrain */
4480 if (!BSTRCMPI(bp, p - 8, "fountain")) {
4481 lev->typ = FOUNTAIN;
4482 level.flags.nfountains++;
4483 if (!strncmpi(bp, "magic ", 6))
4484 lev->blessedftn = 1;
4485 pline("A %sfountain.", lev->blessedftn ? "magic " : "");
4487 return (struct obj *) &zeroobj;
4489 if (!BSTRCMPI(bp, p - 6, "throne")) {
4493 return (struct obj *) &zeroobj;
4495 if (!BSTRCMPI(bp, p - 4, "sink")) {
4497 level.flags.nsinks++;
4500 return (struct obj *) &zeroobj;
4502 /* ("water" matches "potion of water" rather than terrain) */
4503 if (!BSTRCMPI(bp, p - 4, "pool") || !BSTRCMPI(bp, p - 4, "moat")) {
4504 lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT;
4506 pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
4507 /* Must manually make kelp! */
4508 water_damage_chain(level.objects[x][y], TRUE);
4510 return (struct obj *) &zeroobj;
4512 if (!BSTRCMPI(bp, p - 4, "lava")) { /* also matches "molten lava" */
4513 lev->typ = LAVAPOOL;
4515 pline("A pool of molten lava.");
4516 if (!(Levitation || Flying))
4517 (void) lava_effects();
4519 return (struct obj *) &zeroobj;
4522 if (!BSTRCMPI(bp, p - 5, "altar")) {
4526 if (!strncmpi(bp, "chaotic ", 8))
4528 else if (!strncmpi(bp, "neutral ", 8))
4530 else if (!strncmpi(bp, "lawful ", 7))
4532 else if (!strncmpi(bp, "unaligned ", 10))
4534 else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
4535 al = (!rn2(6)) ? A_NONE : rn2((int) A_LAWFUL + 2) - 1;
4536 lev->altarmask = Align2amask(al);
4537 pline("%s altar.", An(align_str(al)));
4539 return (struct obj *) &zeroobj;
4542 if (!BSTRCMPI(bp, p - 5, "grave")
4543 || !BSTRCMPI(bp, p - 9, "headstone")) {
4544 make_grave(x, y, (char *) 0);
4545 pline("%s.", IS_GRAVE(lev->typ) ? "A grave"
4546 : "Can't place a grave here");
4548 return (struct obj *) &zeroobj;
4551 if (!BSTRCMPI(bp, p - 4, "tree")) {
4556 return (struct obj *) &zeroobj;
4559 if (!BSTRCMPI(bp, p - 4, "bars")) {
4560 lev->typ = IRONBARS;
4561 pline("Iron bars.");
4563 return (struct obj *) &zeroobj;
4567 #if 0 /*JP*//*
\83^
\83C
\83v
\95Ê
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢ */
4568 if (!oclass && !typ) {
4569 if (!strncmpi(bp, "polearm", 7)) {
4570 typ = rnd_otyp_by_wpnskill(P_POLEARMS);
4572 } else if (!strncmpi(bp, "hammer", 6)) {
4573 typ = rnd_otyp_by_wpnskill(P_HAMMER);
4580 return ((struct obj *) 0);
4583 oclass = wrpsym[rn2((int) sizeof wrpsym)];
4586 oclass = objects[typ].oc_class;
4588 /* handle some objects that are only allowed in wizard mode */
4589 if (typ && !wizard) {
4591 case AMULET_OF_YENDOR:
4592 typ = FAKE_AMULET_OF_YENDOR;
4594 case CANDELABRUM_OF_INVOCATION:
4595 typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
4597 case BELL_OF_OPENING:
4600 case SPE_BOOK_OF_THE_DEAD:
4601 typ = SPE_BLANK_PAPER;
4607 /* catch any other non-wishable objects (venom) */
4608 if (objects[typ].oc_nowish)
4609 return (struct obj *) 0;
4615 * Create the object, then fine-tune it.
4617 otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE);
4618 typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */
4620 if (islit && (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN
4621 || Is_candle(otmp) || typ == POT_OIL)) {
4622 place_object(otmp, u.ux, u.uy); /* make it viable light source */
4623 begin_burn(otmp, FALSE);
4624 obj_extract_self(otmp); /* now release it for caller's use */
4627 /* if player specified a reasonable count, maybe honor it */
4628 if (cnt > 0 && objects[typ].oc_merge
4629 && (wizard || cnt < rnd(6) || (cnt <= 7 && Is_candle(otmp))
4630 || (cnt <= 20 && ((oclass == WEAPON_CLASS && is_ammo(otmp))
4631 || typ == ROCK || is_missile(otmp)))))
4632 otmp->quan = (long) cnt;
4634 if (oclass == VENOM_CLASS)
4639 } else if (wizard) {
4640 ; /* no alteration to spe */
4641 } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS
4643 || (oclass == RING_CLASS && objects[typ].oc_charged)) {
4644 if (spe > rnd(5) && spe > otmp->spe)
4646 if (spe > 2 && Luck < 0)
4649 if (oclass == WAND_CLASS) {
4650 if (spe > 1 && spesgn == -1)
4653 if (spe > 0 && spesgn == -1)
4656 if (spe > otmp->spe)
4663 /* set otmp->spe. This may, or may not, use spe... */
4666 if (contents == EMPTY) {
4667 otmp->corpsenm = NON_PM;
4669 } else if (contents == SPINACH) {
4670 otmp->corpsenm = NON_PM;
4676 otmp->spe = wetness;
4684 case HEAVY_IRON_BALL:
4687 /* otmp->cobj already done in mksobj() */
4691 /* 0: delivered in-game via external event (or randomly for fake mail);
4692 1: from bones or wishing; 2: written with marker */
4698 otmp->spe = (rn2(10) ? -1 : 0);
4706 /* set otmp->corpsenm or dragon scale [mail] */
4707 if (mntmp >= LOW_PM) {
4708 if (mntmp == PM_LONG_WORM_TAIL)
4709 mntmp = PM_LONG_WORM;
4713 otmp->spe = 0; /* No spinach */
4714 if (dead_species(mntmp, FALSE)) {
4715 otmp->corpsenm = NON_PM; /* it's empty */
4716 } else if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4717 && !(mvitals[mntmp].mvflags & G_NOCORPSE)
4718 && mons[mntmp].cnutrit != 0) {
4719 otmp->corpsenm = mntmp;
4723 if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4724 && !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
4725 if (mons[mntmp].msound == MS_GUARDIAN)
4726 mntmp = genus(mntmp, 1);
4727 set_corpsenm(otmp, mntmp);
4731 mntmp = can_be_hatched(mntmp);
4732 /* this also sets hatch timer if appropriate */
4733 set_corpsenm(otmp, mntmp);
4736 if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
4738 && mntmp != PM_MAIL_DAEMON
4741 otmp->corpsenm = mntmp;
4744 otmp->corpsenm = mntmp;
4745 if (Has_contents(otmp) && verysmall(&mons[mntmp]))
4746 delete_contents(otmp); /* no spellbook */
4747 otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
4750 /* Dragon mail - depends on the order of objects & dragons. */
4751 if (mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON)
4752 otmp->otyp = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4757 /* set blessed/cursed -- setting the fields directly is safe
4758 * since weight() is called below and addinv() will take care
4762 } else if (uncursed) {
4764 otmp->cursed = (Luck < 0 && !wizard);
4765 } else if (blessed) {
4766 otmp->blessed = (Luck >= 0 || wizard);
4767 otmp->cursed = (Luck < 0 && !wizard);
4768 } else if (spesgn < 0) {
4772 /* set eroded and erodeproof */
4773 if (erosion_matters(otmp)) {
4774 if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
4775 otmp->oeroded = eroded;
4776 if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
4777 otmp->oeroded2 = eroded2;
4779 * 3.6.1: earlier versions included `&& !eroded && !eroded2' here,
4780 * but damageproof combined with damaged is feasible (eroded
4781 * armor modified by confused reading of cursed destroy armor)
4782 * so don't prevent player from wishing for such a combination.
4784 if (erodeproof && (is_damageable(otmp) || otmp->otyp == CRYSKNIFE))
4785 otmp->oerodeproof = (Luck >= 0 || wizard);
4788 /* set otmp->recharged */
4789 if (oclass == WAND_CLASS) {
4790 /* prevent wishing abuse */
4791 if (otmp->otyp == WAN_WISHING && !wizard)
4793 otmp->recharged = (unsigned) rechrg;
4798 if (is_poisonable(otmp))
4799 otmp->opoisoned = (Luck >= 0);
4800 else if (oclass == FOOD_CLASS)
4801 /* try to taint by making it as old as possible */
4804 /* and [un]trapped */
4806 if (Is_box(otmp) || typ == TIN)
4807 otmp->otrapped = (trapped == 1);
4809 /* empty for containers rather than for tins */
4810 if (contents == EMPTY) {
4811 if (otmp->otyp == BAG_OF_TRICKS || otmp->otyp == HORN_OF_PLENTY) {
4814 } else if (Has_contents(otmp)) {
4815 /* this assumes that artifacts can't be randomly generated
4816 inside containers */
4817 delete_contents(otmp);
4818 otmp->owt = weight(otmp);
4821 /* set locked/unlocked/broken */
4824 otmp->olocked = 1, otmp->obroken = 0;
4825 } else if (unlocked) {
4826 otmp->olocked = 0, otmp->obroken = 0;
4827 } else if (broken) {
4828 otmp->olocked = 0, otmp->obroken = 1;
4835 if (isdiluted && otmp->oclass == POTION_CLASS && otmp->otyp != POT_WATER)
4838 /* set tin variety */
4839 if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard))
4840 set_tin_variety(otmp, tvariety);
4846 /* an artifact name might need capitalization fixing */
4847 aname = artifact_name(name, &objtyp);
4848 if (aname && objtyp == otmp->otyp)
4851 /* 3.6 tribute - fix up novel */
4852 if (otmp->otyp == SPE_NOVEL) {
4853 const char *novelname;
4855 novelname = lookup_novel(name, &otmp->novelidx);
4860 otmp = oname(otmp, name);
4861 /* name==aname => wished for artifact (otmp->oartifact => got it) */
4862 if (otmp->oartifact || name == aname) {
4864 u.uconduct.wisharti++; /* KMH, conduct */
4868 /* more wishing abuse: don't allow wishing for certain artifacts */
4869 /* and make them pay; charge them for the wish anyway! */
4870 if ((is_quest_artifact(otmp)
4871 || (otmp->oartifact && rn2(nartifact_exist()) > 1)) && !wizard) {
4872 artifact_exists(otmp, safe_oname(otmp), FALSE);
4873 obfree(otmp, (struct obj *) 0);
4874 otmp = (struct obj *) &zeroobj;
4876 pline("For a moment, you feel %s in your %s, but it disappears!",
4878 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",
4879 something, makeplural(body_part(HAND)));
4883 if (halfeaten && otmp->oclass == FOOD_CLASS) {
4884 if (otmp->otyp == CORPSE)
4885 otmp->oeaten = mons[otmp->corpsenm].cnutrit;
4887 otmp->oeaten = objects[otmp->otyp].oc_nutrition;
4888 /* (do this adjustment before setting up object's weight) */
4889 consume_oeaten(otmp, 1);
4891 otmp->owt = weight(otmp);
4892 if (very && otmp->otyp == HEAVY_IRON_BALL)
4893 otmp->owt += IRON_BALL_W_INCR;
4894 else if (gsize > 1 && otmp->globby)
4895 /* 0: unspecified => small; 1: small => keep default owt of 20;
4896 2: medium => 120; 3: large => 320; 4: very large => 520 */
4897 otmp->owt += 100 + (gsize - 2) * 200;
4903 rnd_class(first, last)
4910 for (i = first; i <= last; i++)
4911 sum += objects[i].oc_prob;
4912 if (!sum) /* all zero */
4913 return first + rn2(last - first + 1);
4915 for (i = first; i <= last; i++)
4916 if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
4921 STATIC_OVL const char *
4922 Japanese_item_name(i)
4925 struct Jitem *j = Japanese_items;
4932 return (const char *) 0;
4936 suit_simple_name(suit)
4939 const char *suitnm, *esuitp;
4942 if (Is_dragon_mail(suit))
4944 return "dragon mail"; /* <color> dragon scale mail */
4946 return "
\97Ø
\8aZ"; /* <color> dragon scale mail */
4948 else if (Is_dragon_scales(suit))
4950 return "dragon scales";
4953 suitnm = OBJ_NAME(objects[suit->otyp]);
4954 esuitp = eos((char *) suitnm);
4956 if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
4957 return "mail"; /* most suits fall into this category */
4959 if (strlen(suitnm) > 2 && !strcmp(esuitp - 2, "
\8aZ"))
4960 return "
\8aZ"; /* most suits fall into this category */
4963 else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
4964 return "jacket"; /* leather jacket */
4967 /* "suit" is lame but "armor" is ambiguous and "body armor" is absurd */
4975 cloak_simple_name(cloak)
4979 switch (cloak->otyp) {
4984 return "
\83\8d\81[
\83u";
4985 case MUMMY_WRAPPING:
4991 return (objects[cloak->otyp].oc_name_known && cloak->dknown)
4995 ? "
\83X
\83\82\83b
\83N"
4999 : "
\83G
\83v
\83\8d\83\93";
5007 return "
\83N
\83\8d\81[
\83N";
5010 /* helm vs hat for messages */
5012 helm_simple_name(helmet)
5016 * There is some wiggle room here; the result has been chosen
5017 * for consistency with the "protected by hard helmet" messages
5018 * given for various bonks on the head: headgear that provides
5019 * such protection is a "helm", that which doesn't is a "hat".
5021 * elven leather helm / leather hat -> hat
5022 * dwarvish iron helm / hard hat -> helm
5023 * The rest are completely straightforward:
5024 * fedora, cornuthaum, dunce cap -> hat
5025 * all other types of helmets -> helm
5028 return (helmet && !is_metallic(helmet)) ? "hat" : "helm";
5030 return (helmet && !is_metallic(helmet)) ? "
\96X
\8eq" : "
\8a\95";
5034 mimic_obj_name(mtmp)
5037 if (M_AP_TYPE(mtmp) == M_AP_OBJECT) {
5038 if (mtmp->mappearance == GOLD_PIECE)
5043 if (mtmp->mappearance != STRANGE_OBJECT)
5044 return simple_typename(mtmp->mappearance);
5047 return "whatcha-may-callit";
5049 return "
\89½
\82Æ
\82©
\82¢
\82¤
\82à
\82Ì";
5053 * Construct a query prompt string, based around an object name, which is
5054 * guaranteed to fit within [QBUFSZ]. Takes an optional prefix, three
5055 * choices for filling in the middle (two object formatting functions and a
5056 * last resort literal which should be very short), and an optional suffix.
5059 safe_qbuf(qbuf, qprefix, qsuffix, obj, func, altfunc, lastR)
5060 char *qbuf; /* output buffer */
5061 const char *qprefix, *qsuffix;
5063 char *FDECL((*func), (OBJ_P)), *FDECL((*altfunc), (OBJ_P));
5067 /* convert size_t (or int for ancient systems) to ordinary unsigned */
5068 unsigned len, lenlimit,
5069 len_qpfx = (unsigned) (qprefix ? strlen(qprefix) : 0),
5070 len_qsfx = (unsigned) (qsuffix ? strlen(qsuffix) : 0),
5071 len_lastR = (unsigned) strlen(lastR);
5073 lenlimit = QBUFSZ - 1;
5074 endp = qbuf + lenlimit;
5075 /* sanity check, aimed mainly at paniclog (it's conceivable for
5076 the result of short_oname() to be shorter than the length of
5077 the last resort string, but we ignore that possibility here) */
5078 if (len_qpfx > lenlimit)
5079 impossible("safe_qbuf: prefix too long (%u characters).", len_qpfx);
5080 else if (len_qpfx + len_qsfx > lenlimit)
5081 impossible("safe_qbuf: suffix too long (%u + %u characters).",
5082 len_qpfx, len_qsfx);
5083 else if (len_qpfx + len_lastR + len_qsfx > lenlimit)
5084 impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
5085 len_qpfx, len_lastR, len_qsfx);
5087 /* the output buffer might be the same as the prefix if caller
5088 has already partially filled it */
5089 if (qbuf == qprefix) {
5090 /* prefix is already in the buffer */
5092 } else if (qprefix) {
5093 /* put prefix into the buffer */
5094 (void) strncpy(qbuf, qprefix, lenlimit);
5097 /* no prefix; output buffer starts out empty */
5100 len = (unsigned) strlen(qbuf);
5102 if (len + len_lastR + len_qsfx > lenlimit) {
5103 /* too long; skip formatting, last resort output is truncated */
5104 if (len < lenlimit) {
5105 (void) strncpy(&qbuf[len], lastR, lenlimit - len);
5107 len = (unsigned) strlen(qbuf);
5108 if (qsuffix && len < lenlimit) {
5109 (void) strncpy(&qbuf[len], qsuffix, lenlimit - len);
5111 /* len = (unsigned) strlen(qbuf); */
5115 /* suffix and last resort are guaranteed to fit */
5116 len += len_qsfx; /* include the pending suffix */
5117 /* format the object */
5118 bufp = short_oname(obj, func, altfunc, lenlimit - len);
5119 if (len + strlen(bufp) <= lenlimit)
5120 Strcat(qbuf, bufp); /* formatted name fits */
5122 Strcat(qbuf, lastR); /* use last resort */
5126 Strcat(qbuf, qsuffix);
5128 /* assert( strlen(qbuf) < QBUFSZ ); */