1 /* NetHack 3.6 objnam.c $NHDT-Date: 1674864732 2023/01/28 00:12:12 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.259 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2011. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2022 */
9 /* JNetHack may be freely redistributed. See license for details. */
13 /* "an uncursed greased partly eaten guardian naga hatchling [corpse]" */
15 #define PREFIX 80 /* (56) */
17 /*
\81u
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\96û
\82Ì
\93h
\82ç
\82ê
\82½
\90H
\82×
\82©
\82¯
\82Ì
\83N
\83\8d\83}
\83e
\83B
\83b
\83N
\81E
\83h
\83\89\83S
\83\93(
\82Ì
\8e\80\91Ì)
\81v*/
23 STATIC_DCL char *FDECL(strprepend, (char *, const char *));
25 STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
27 STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (const char *, CHAR_P, int));
28 STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
29 STATIC_DCL char *NDECL(nextobuf);
30 STATIC_DCL void FDECL(releaseobuf, (char *));
31 STATIC_DCL void FDECL(xcalled, (char *, int, const char *, const char *));
32 STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
33 STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
34 STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned));
35 STATIC_DCL char *FDECL(just_an, (char *str, const char *));
37 STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
38 const char *const *));
39 STATIC_DCL char *FDECL(singplur_compound, (char *));
41 STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
43 STATIC_DCL boolean FDECL(badman, (const char *, BOOLEAN_P));
45 STATIC_DCL char *FDECL(globwt, (struct obj *, char *, boolean *));
52 #define BSTRCMPI(base, ptr, str) ((ptr) < base || strcmpi((ptr), str))
53 #define BSTRNCMPI(base, ptr, str, num) \
54 ((ptr) < base || strncmpi((ptr), str, num))
55 #define Strcasecpy(dst, src) (void) strcasecpy(dst, src)
57 #define STRNCMPEX(x, y) strncmp(x, y, l = strlen(y))
60 /* true for gems/rocks that should have " stone" appended to their names */
61 #define GemStone(typ) \
63 || (objects[typ].oc_material == GEMSTONE \
64 && (typ != DILITHIUM_CRYSTAL && typ != RUBY && typ != DIAMOND \
65 && typ != SAPPHIRE && typ != BLACK_OPAL && typ != EMERALD \
69 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "wakizashi" },
70 { BROADSWORD, "ninja-to" },
71 { FLAIL, "nunchaku" },
72 { GLAIVE, "naginata" },
73 { LOCK_PICK, "osaku" },
74 { WOODEN_HARP, "koto" },
76 { PLATE_MAIL, "tanko" },
78 { LEATHER_GLOVES, "yugake" },
79 { FOOD_RATION, "gunyoki" },
80 { POT_BOOZE, "sake" },
83 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "
\98e
\8d·
\82µ" },
84 { BROADSWORD, "
\94E
\8eÒ
\93\81" },
85 { FLAIL, "
\83k
\83\93\83`
\83\83\83N" },
86 { GLAIVE, "
\82È
\82¬
\82È
\82½" },
87 { LOCK_PICK, "
\82¨
\82³
\82" },
88 { WOODEN_HARP, "
\8bÕ" },
89 { KNIFE, "
\8eh
\93\81" },
90 { PLATE_MAIL, "
\92Z
\8db" },
92 { LEATHER_GLOVES, "
\8b|
\8c\9c" },
93 { FOOD_RATION, "
\8aÛ
\96ò" },
94 { POT_BOOZE, "
\8eð" },
98 STATIC_DCL const char *FDECL(Japanese_item_name, (int i));
103 register const char *pref;
105 register int i = (int) strlen(pref);
108 impossible("PREFIX too short (for %d).", i);
112 (void) strncpy(s, pref, i); /* do not copy trailing 0 */
116 /* manage a pool of BUFSZ buffers, so callers don't have to */
117 static char NEARDATA obufs[NUMOBUF][BUFSZ];
118 static int obufidx = 0;
123 obufidx = (obufidx + 1) % NUMOBUF;
124 return obufs[obufidx];
127 /* put the most recently allocated buffer back if possible */
132 /* caller may not know whether bufp is the most recently allocated
133 buffer; if it isn't, do nothing; note that because of the somewhat
134 obscure PREFIX handling for object name formatting by xname(),
135 the pointer our caller has and is passing to us might be into the
136 middle of an obuf rather than the address returned by nextobuf() */
137 if (bufp >= obufs[obufidx]
138 && bufp < obufs[obufidx] + sizeof obufs[obufidx]) /* obufs[][BUFSZ] */
139 obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
146 char *buf = nextobuf();
147 struct objclass *ocl = &objects[otyp];
148 const char *actualn = OBJ_NAME(*ocl);
149 const char *dn = OBJ_DESCR(*ocl);
150 const char *un = ocl->oc_uname;
151 int nn = ocl->oc_name_known;
153 if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
154 actualn = Japanese_item_name(otyp);
158 /*
\89p
\8cê
\82Å
\82Í
\8cµ
\96§
\82É
\83T
\83C
\83Y
\82ð
\8eZ
\8fo
\82µ
\82Ä
\82¢
\82é
\82ª
\93ú
\96{
\8cê
\82Í
\8cê
\8f\87\82Ì
\93s
\8d\87\82Å
159 \90³
\8am
\82É
\8eZ
\8fo
\82·
\82é
\82Ì
\82ª
\91å
\95Ï
\82È
\82Ì
\82Å
\97]
\97T
\82ð
\8e\9d\82Á
\82½
\92l
\82É
\82·
\82é */
161 BUFSZ - PREFIX - (dn ? (int) strlen(dn) + 3 : 0), "", un);
164 switch (ocl->oc_class) {
169 Strcat(buf, "
\8bà
\89Ý");
173 Strcpy(buf, "potion");
179 Strcpy(buf, "scroll");
181 Strcat(buf, "
\8aª
\95¨");
190 if (otyp != SPE_NOVEL) {
192 Strcpy(buf, "spellbook");
194 Strcat(buf, "
\96\82\96@
\8f\91");
197 Strcpy(buf, !nn ? "book" : "novel");
199 Strcpy(buf, !nn ? "
\96{" : "
\8f¬
\90à");
207 Strcat(buf, "
\8ew
\97Ö");
212 Strcpy(buf, actualn);
214 Strcpy(buf, "amulet");
216 xcalled(buf, BUFSZ - (dn ? (int) strlen(dn) + 3 : 0), "", un);
218 Sprintf(eos(buf), " (%s)", dn);
222 Strcat(buf, actualn);
224 Strcat(buf, "
\96\82\8f\9c\82¯");
230 Strcat(buf, actualn);
232 Strcat(buf, "
\95ó
\90Î");
238 Strcpy(buf, actualn);
240 Strcat(buf, " stone");
241 if (un) /* 3: length of " (" + ")" which will enclose 'dn' */
242 xcalled(buf, BUFSZ - (dn ? (int) strlen(dn) + 3 : 0), "", un);
244 Sprintf(eos(buf), " (%s)", dn);
246 Strcat(buf, actualn);
250 Strcpy(buf, dn ? dn : actualn);
251 if (ocl->oc_class == GEM_CLASS)
253 (ocl->oc_material == MINERAL) ? " stone" : " gem");
255 xcalled(buf, BUFSZ, "", un);
257 Strcat(buf, dn ? dn : actualn);
266 /* here for ring/scroll/potion/wand */
270 Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
272 Sprintf(eos(buf), " of %s", actualn);
274 Strcpy(buf, actualn);
278 if (un) /* 3: length of " (" + ")" which will enclose 'dn' */
279 xcalled(buf, BUFSZ - (dn ? (int) strlen(dn) + 3 : 0), "", un);
283 Sprintf(eos(buf), " (%s)", dn);
285 Sprintf(eos(buf), "(%s)", dn);
290 /* less verbose result than obj_typename(); either the actual name
291 or the description (but not both); user-assigned name is ignored */
293 simple_typename(otyp)
296 char *bufp, *pp, *save_uname = objects[otyp].oc_uname;
298 objects[otyp].oc_uname = 0; /* suppress any name given by user */
299 bufp = obj_typename(otyp);
300 objects[otyp].oc_uname = save_uname;
301 if ((pp = strstri(bufp, " (")) != 0)
302 *pp = '\0'; /* strip the appended description */
306 /* typename for debugging feedback where data involved might be suspect */
311 unsigned save_nameknown;
314 if (otyp < STRANGE_OBJECT || otyp >= NUM_OBJECTS
315 || !OBJ_NAME(objects[otyp])) {
317 Sprintf(res, "glorkum[%d]", otyp);
319 /* force it to be treated as fully discovered */
320 save_nameknown = objects[otyp].oc_name_known;
321 objects[otyp].oc_name_known = 1;
322 res = simple_typename(otyp);
323 objects[otyp].oc_name_known = save_nameknown;
332 if (!obj->oartifact || !has_oname(obj))
334 if (!program_state.gameover && !iflags.override_ID) {
335 if (not_fully_identified(obj))
341 /* used by distant_name() to pass extra information to xname_flags();
342 it would be much cleaner if this were a parameter, but that would
343 require all of the xname() and doname() calls to be modified */
344 static int distantname = 0;
346 /* Give the name of an object seen at a distance. Unlike xname/doname,
347 * we don't want to set dknown if it's not set already.
350 distant_name(obj, func)
352 char *FDECL((*func), (OBJ_P));
356 /* 3.6.1: this used to save Blind, set it, make the call, then restore
357 * the saved value; but the Eyes of the Overworld override blindness
358 * and let characters wearing them get dknown set for distant items.
360 * TODO? if the hero is wearing those Eyes, figure out whether the
361 * object is within X-ray radius and only treat it as distant when
362 * beyond that radius. Logic is iffy but result might be interesting.
370 /* convert player specified fruit name into corresponding fruit juice name
371 ("slice of pizza" -> "pizza juice" rather than "slice of pizza juice") */
374 boolean juice; /* whether or not to append " juice" to the name */
377 char *buf = nextobuf();
378 const char *fruit_nam = strstri(pl_fruit, " of ");
381 fruit_nam += 4; /* skip past " of " */
383 fruit_nam = pl_fruit; /* use it as is */
385 Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
388 /*
\93ú
\96{
\8cê
\82Å
\82Í
\82»
\82±
\82Ü
\82Å
\82µ
\82È
\82¢*/
389 char *buf = nextobuf();
390 Sprintf(buf, "%s%s", pl_fruit, juice ? "
\83W
\83\85\81[
\83X" : "");
395 /* look up a named fruit by index (1..127) */
397 fruit_from_indx(indx)
402 for (f = ffruit; f; f = f->nextf)
408 /* look up a named fruit by name */
410 fruit_from_name(fname, exact, highest_fid)
412 boolean exact; /* False => prefix or exact match, True = exact match only */
413 int *highest_fid; /* optional output; only valid if 'fname' isn't found */
415 struct fruit *f, *tentativef;
419 * note: named fruits are case-senstive...
424 /* first try for an exact match */
425 for (f = ffruit; f; f = f->nextf)
426 if (!strcmp(f->fname, fname))
428 else if (highest_fid && f->fid > *highest_fid)
429 *highest_fid = f->fid;
431 /* didn't match as-is; if caller is willing to accept a prefix
432 match, try to find one; we want to find the longest prefix that
433 matches, not the first */
436 for (f = ffruit; f; f = f->nextf) {
437 k = strlen(f->fname);
438 if (!strncmp(f->fname, fname, k)
439 && (!fname[k] || fname[k] == ' ')
440 && (!tentativef || k > strlen(tentativef->fname)))
445 /* if we still don't have a match, try singularizing the target;
446 for exact match, that's trivial, but for prefix, it's hard */
448 altfname = makesingular(fname);
449 for (f = ffruit; f; f = f->nextf) {
450 if (!strcmp(f->fname, altfname))
453 releaseobuf(altfname);
456 char fnamebuf[BUFSZ], *p;
457 unsigned fname_k = strlen(fname); /* length of assumed plural fname */
460 for (f = ffruit; f; f = f->nextf) {
461 k = strlen(f->fname);
462 /* reload fnamebuf[] each iteration in case it gets modified;
463 there's no need to recalculate fname_k */
464 Strcpy(fnamebuf, fname);
465 /* bug? if singular of fname is longer than plural,
466 failing the 'fname_k > k' test could skip a viable
467 candidate; unfortunately, we can't singularize until
468 after stripping off trailing stuff and we can't get
469 accurate fname_k until fname has been singularized;
470 compromise and use 'fname_k >= k' instead of '>',
471 accepting 1 char length discrepancy without risking
472 false match (I hope...) */
473 if (fname_k >= k && (p = index(&fnamebuf[k], ' ')) != 0) {
474 *p = '\0'; /* truncate at 1st space past length of f->fname */
475 altfname = makesingular(fnamebuf);
476 k = strlen(altfname); /* actually revised 'fname_k' */
477 if (!strcmp(f->fname, altfname)
478 && (!tentativef || k > strlen(tentativef->fname)))
480 releaseobuf(altfname); /* avoid churning through all obufs */
488 /* sort the named-fruit linked list by fruit index number */
490 reorder_fruit(forward)
493 struct fruit *f, *allfr[1 + 127];
494 int i, j, k = SIZE(allfr);
496 for (i = 0; i < k; ++i)
497 allfr[i] = (struct fruit *) 0;
498 for (f = ffruit; f; f = f->nextf) {
499 /* without sanity checking, this would reduce to 'allfr[f->fid]=f' */
501 if (j < 1 || j >= k) {
502 impossible("reorder_fruit: fruit index (%d) out of range", j);
503 return; /* don't sort after all; should never happen... */
504 } else if (allfr[j]) {
505 impossible("reorder_fruit: duplicate fruit index (%d)", j);
510 ffruit = 0; /* reset linked list; we're rebuilding it from scratch */
511 /* slot [0] will always be empty; must start 'i' at 1 to avoid
512 [k - i] being out of bounds during first iteration */
513 for (i = 1; i < k; ++i) {
514 /* for forward ordering, go through indices from high to low;
515 for backward ordering, go from low to high */
516 j = forward ? (k - i) : i;
518 allfr[j]->nextf = ffruit;
524 /* add "<pfx> called <sfx>" to end of buf, truncating if necessary */
526 xcalled(buf, siz, pfx, sfx)
527 char *buf; /* eos(obuf) or eos(&obuf[PREFIX]) */
528 int siz; /* BUFSZ or BUFSZ-PREFIX */
529 const char *pfx; /* usually class string, sometimes more specific */
530 const char *sfx; /* user assigned type name */
532 int bufsiz = siz - 1 - (int) strlen(buf),
534 pfxlen = (int) (strlen(pfx) + sizeof " called " - sizeof "");
536 pfxlen = (int) (strlen(pfx) + sizeof "
\82Æ
\8cÄ
\82Î
\82ê
\82é" - sizeof "");
539 panic("xcalled: not enough room for prefix (%d > %d)",
543 Sprintf(eos(buf), "%s called %.*s", pfx, bufsiz - pfxlen, sfx);
546 int sfxlen = bufsiz - pfxlen;
547 /*
\91S
\8ap
\82Ì
\93r
\92\86\82Å
\90Ø
\82ê
\82»
\82¤
\82È
\82Æ
\82«
\82É
\82Í
\82»
\82Ì
\8e\9a\82Ì
\90æ
\93ª
\82Ü
\82Å
\96ß
\82é */
548 sfxlen = sfxlen - offset_in_kanji(sfx, sfxlen);
549 /*
\95Ï
\90\94\96¼
\82ð
\95Ï
\82¦
\82é
\82±
\82Æ
\82Í
\82µ
\82È
\82¢
\82ª
\81Asfx
\82ª
\91O
\81Apfx
\82ª
\8cã
\82ë
\82É
\82È
\82é */
550 Sprintf(eos(buf), "%.*s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", sfxlen, sfx, pfx);
559 return xname_flags(obj, CXN_NORMAL);
563 xname_flags(obj, cxn_flags)
564 register struct obj *obj;
565 unsigned cxn_flags; /* bitmask of CXN_xxx values */
568 register int typ = obj->otyp;
569 register struct objclass *ocl = &objects[typ];
570 int nn = ocl->oc_name_known, omndx = obj->corpsenm;
571 const char *actualn = OBJ_NAME(*ocl);
572 const char *dn = OBJ_DESCR(*ocl);
573 const char *un = ocl->oc_uname;
574 boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
575 boolean known, dknown, bknown;
577 buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
578 if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
579 actualn = Japanese_item_name(typ);
580 /* 3.6.2: this used to be part of 'dn's initialization, but it
581 needs to come after possibly overriding 'actualn' */
587 * clean up known when it's tied to oc_name_known, eg after AD_DRIN
588 * This is only required for unique objects since the article
589 * printed for the object is tied to the combination of the two
590 * and printing the wrong article gives away information.
592 if (!nn && ocl->oc_uses_known && ocl->oc_unique)
594 if (!Blind && !distantname)
596 if (Role_if(PM_PRIEST))
597 obj->bknown = 1; /* actively avoid set_bknown();
598 * we mustn't call update_inventory() now because
599 * it would call xname() (via doname()) recursively
600 * and could end up clobbering all the obufs... */
602 if (iflags.override_ID) {
603 known = dknown = bknown = TRUE;
607 dknown = obj->dknown;
608 bknown = obj->bknown;
611 if (obj_is_pname(obj))
616 Strcat(buf, ONAME(obj));
621 if (has_oname(obj) && dknown) {
622 Strcat(buf, ONAME(obj));
623 Strcat(buf, "
\82Æ
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½");
626 switch (obj->oclass) {
630 Strcpy(buf, "amulet");
632 Strcat(buf, "
\96\82\8f\9c\82¯");
633 else if (typ == AMULET_OF_YENDOR || typ == FAKE_AMULET_OF_YENDOR)
634 /* each must be identified individually */
635 Strcpy(buf, known ? actualn : dn);
637 Strcpy(buf, actualn);
640 xcalled(buf, BUFSZ - PREFIX, "amulet", un);
642 xcalled(buf, BUFSZ - PREFIX, "
\96\82\8f\9c\82¯", un);
645 Sprintf(buf, "%s amulet", dn);
647 Sprintf(eos(buf), "%s", dn);
650 if (is_poisonable(obj) && obj->opoisoned)
652 Strcpy(buf, "poisoned ");
654 Strcpy(buf, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
660 Sprintf(eos(buf), "%s
\82Ì", mons[obj->corpsenm].mname);
664 Strcpy(buf, "pair of ");
666 Strcpy(buf, "
\88ê
\91Î
\82Ì");
667 else if (is_wet_towel(obj))
669 Strcpy(buf, (obj->spe < 3) ? "moist " : "wet ");
671 Strcpy(buf, (obj->spe < 3) ? "
\8e¼
\82Á
\82½" : "
\94G
\82ê
\82½");
676 Strcat(buf, actualn);
678 xcalled(buf, BUFSZ - PREFIX, dn, un);
682 #if 0 /*JP*/ /*
\82±
\82ê
\82Í
\8cê
\8f\87\82Ì
\8aÖ
\8cW
\82©
\82ç
\8fã
\82Ì
\95û
\82Å
\92è
\8b`*/
683 if (typ == FIGURINE && omndx != NON_PM) {
684 char anbuf[10]; /* [4] would be enough: 'a','n',' ','\0' */
686 Sprintf(eos(buf), " of %s%s",
687 just_an(anbuf, mons[omndx].mname),
689 } else if (is_wet_towel(obj)) {
691 if (is_wet_towel(obj)) {
694 Sprintf(eos(buf), " (%d)", obj->spe);
698 /* depends on order of the dragon scales objects */
699 if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
701 Sprintf(buf, "set of %s", actualn);
703 Sprintf(buf, "%s
\88ê
\8e®", actualn);
706 if (is_boots(obj) || is_gloves(obj))
708 Strcpy(buf, "pair of ");
710 Strcat(buf,"
\88ê
\91Î
\82Ì");
712 if (obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
715 Strcpy(buf, "shield");
717 Strcat(buf, "
\8f\82");
720 if (obj->otyp == SHIELD_OF_REFLECTION && !dknown) {
722 Strcpy(buf, "smooth shield");
724 Strcat(buf, "
\82·
\82×
\82·
\82×
\82µ
\82½
\8f\82");
729 Strcat(buf, actualn);
733 Strcat(buf, "boots");
734 else if (is_gloves(obj))
735 Strcat(buf, "gloves");
736 else if (is_cloak(obj))
737 Strcpy(buf, "cloak");
738 else if (is_helmet(obj))
739 Strcpy(buf, "helmet");
740 else if (is_shield(obj))
741 Strcpy(buf, "shield");
743 Strcpy(buf, "armor");
744 Strcat(buf, " called ");
750 else if (is_gloves(obj))
752 else if (is_cloak(obj))
753 p = "
\83N
\83\8d\81[
\83N";
754 else if (is_helmet(obj))
756 else if (is_shield(obj))
760 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", un, p);
766 if (typ == SLIME_MOLD) {
767 struct fruit *f = fruit_from_indx(obj->spe);
770 impossible("Bad fruit #%d?", obj->spe);
771 Strcpy(buf, "fruit");
773 Strcpy(buf, f->fname);
775 /* ick; already pluralized fruit names
776 are allowed--we want to try to avoid
777 adding a redundant plural suffix */
778 Strcpy(buf, makeplural(makesingular(buf)));
795 ? "
\82Æ
\82Ä
\82à
\91å
\82«
\82¢"
807 Strcpy(buf, actualn);
808 if (typ == TIN && known)
809 tin_details(obj, omndx, buf);
811 if (typ == TIN && known)
812 /*JP
\81u
\81`
\82Ì
\93÷
\82Ì
\81v*/
813 tin_details(obj, omndx, buf);
814 Strcat(buf, actualn);
820 Strcpy(buf, actualn);
822 Strcat(buf, actualn);
826 if (typ == STATUE && omndx != NON_PM) {
830 Sprintf(buf, "%s%s of %s%s",
831 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
835 type_is_pname(&mons[omndx])
837 : the_unique_pm(&mons[omndx])
839 : just_an(anbuf, mons[omndx].mname),
842 Sprintf(eos(buf), "%s%s
\82Ì%s",
843 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
846 mons[obj->corpsenm].mname, actualn);
850 Strcpy(buf, actualn);
852 Strcat(buf, actualn);
857 Sprintf(buf, "%sheavy iron ball",
858 (obj->owt > ocl->oc_weight) ? "very " : "");
860 Sprintf(eos(buf), "%s
\8fd
\82¢
\93S
\8b\85",
861 (obj->owt > ocl->oc_weight) ? "
\82Æ
\82Ä
\82à" : "");
865 if (dknown && obj->odiluted)
867 Strcpy(buf, "diluted ");
869 Strcat(buf, "
\94\96\82Ü
\82Á
\82½");
870 if (nn || un || !dknown) {
872 Strcat(buf, "potion");
885 if (typ == POT_WATER && bknown
886 && (obj->blessed || obj->cursed)) {
888 Strcat(buf, obj->blessed ? "holy " : "unholy ");
890 Strcat(buf, obj->blessed ? "
\90¹" : "
\95s
\8fò
\82È");
892 Strcat(buf, actualn);
895 xcalled(buf, BUFSZ - PREFIX, "", un);
897 xcalled(buf, BUFSZ - PREFIX, "
\96ò", un);
902 #if 0 /*JP*//*
\95s
\8am
\92è
\96¼
\82É
\81u
\96ò
\81v
\82Í
\95t
\82¢
\82Ä
\82¢
\82é*/
903 Strcat(buf, " potion");
909 Strcpy(buf, "scroll");
914 Strcat(buf,"
\8aª
\95¨");
922 Strcat(buf, actualn);
925 xcalled(buf, BUFSZ - PREFIX, "", un);
927 xcalled(buf, BUFSZ - PREFIX, "
\8aª
\95¨", un);
929 } else if (ocl->oc_magic) {
931 Strcat(buf, " labeled ");
937 Strcat(buf, " scroll");
951 Sprintf(buf, "wand of %s", actualn);
953 Strcat(buf, actualn);
956 xcalled(buf, BUFSZ - PREFIX, "wand", un);
958 xcalled(buf, BUFSZ - PREFIX, "
\8fñ", un);
961 Sprintf(buf, "%s wand", dn);
966 if (typ == SPE_NOVEL) { /* 3.6 tribute */
973 Strcpy(buf, actualn);
976 xcalled(buf, BUFSZ - PREFIX, "novel", un);
978 xcalled(buf, BUFSZ - PREFIX, "
\8f¬
\90à", un);
981 Sprintf(buf, "%s book", dn);
983 Sprintf(buf, "%s
\96{", dn);
986 } else if (!dknown) {
988 Strcpy(buf, "spellbook");
990 Strcat(buf, "
\96\82\96@
\8f\91");
993 if (typ != SPE_BOOK_OF_THE_DEAD)
994 Strcpy(buf, "spellbook of ");
996 Strcat(buf, actualn);
999 xcalled(buf, BUFSZ - PREFIX, "spellbook", un);
1001 xcalled(buf, BUFSZ - PREFIX, "
\96\82\96@
\8f\91", un);
1004 Sprintf(buf, "%s spellbook", dn);
1006 Sprintf(eos(buf), "%s", dn);
1011 Strcpy(buf, "ring");
1013 Strcat(buf, "
\8ew
\97Ö");
1016 Sprintf(buf, "ring of %s", actualn);
1018 Strcat(buf, actualn);
1021 xcalled(buf, BUFSZ - PREFIX, "ring", un);
1023 xcalled(buf, BUFSZ - PREFIX, "
\8ew
\97Ö", un);
1026 Sprintf(buf, "%s ring", dn);
1032 const char *rock = (ocl->oc_material == MINERAL) ? "stone" : "gem";
1034 const char *rock = (ocl->oc_material == MINERAL) ? "
\90Î" : "
\95ó
\90Î";
1044 xcalled(buf, BUFSZ - PREFIX, rock, un);
1047 Sprintf(buf, "%s %s", dn, rock);
1051 Strcpy(buf, actualn);
1054 Strcat(buf, " stone");
1060 Sprintf(buf, "glorkum %d %d %d", obj->oclass, typ, obj->spe);
1064 Strcpy(buf, makeplural(buf));
1067 if (obj->otyp == T_SHIRT && program_state.gameover) {
1071 Sprintf(eos(buf), " with text \"%s\"", tshirt_text(obj, tmpbuf));
1073 Sprintf(eos(buf), "(
\81u%s
\81v
\82Æ
\8f\91\82¢
\82Ä
\82 \82é)", tshirt_text(obj, tmpbuf));
1077 if (has_oname(obj) && dknown) {
1078 Strcat(buf, " named ");
1080 (void) strncat(buf, ONAME(obj),
1081 BUFSZ - 1 - PREFIX - (unsigned) strlen(buf));
1084 if (!strncmpi(buf, "the ", 4))
1092 /* similar to simple_typename but minimal_xname operates on a particular
1093 object rather than its general type; it formats the most basic info:
1094 potion -- if description not known
1095 brown potion -- if oc_name_known not set
1096 potion of object detection -- if discovered
1104 struct objclass saveobcls;
1105 int otyp = obj->otyp;
1110 /* suppress user-supplied name */
1111 saveobcls.oc_uname = objects[otyp].oc_uname;
1112 objects[otyp].oc_uname = 0;
1113 /* suppress actual name if object's description is unknown */
1114 saveobcls.oc_name_known = objects[otyp].oc_name_known;
1116 objects[otyp].oc_name_known = 0;
1118 /* caveat: this makes a lot of assumptions about which fields
1119 are required in order for xname() to yield a sensible result */
1121 bareobj.otyp = otyp;
1122 bareobj.oclass = obj->oclass;
1123 bareobj.dknown = obj->dknown;
1124 /* suppress known except for amulets (needed for fakes and real A-of-Y) */
1125 bareobj.known = (obj->oclass == AMULET_CLASS)
1127 /* default is "on" for types which don't use it */
1128 : !objects[otyp].oc_uses_known;
1129 bareobj.quan = 1L; /* don't want plural */
1130 bareobj.corpsenm = NON_PM; /* suppress statue and figurine details */
1131 /* but suppressing fruit details leads to "bad fruit #0"
1132 [perhaps we should force "slime mold" rather than use xname?] */
1133 if (obj->otyp == SLIME_MOLD)
1134 bareobj.spe = obj->spe;
1136 bufp = distant_name(&bareobj, xname); /* xname(&bareobj) */
1138 if (!strncmp(bufp, "uncursed ", 9))
1139 bufp += 9; /* Role_if(PM_PRIEST) */
1141 if (!STRNCMPEX(bufp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢"))
1142 bufp += l; /* Role_if(PM_PRIEST) */
1145 objects[otyp].oc_uname = saveobcls.oc_uname;
1146 objects[otyp].oc_name_known = saveobcls.oc_name_known;
1150 /* xname() output augmented for multishot missile feedback */
1156 char *onm = xname(obj);
1158 if (m_shot.n > 1 && m_shot.o == obj->otyp) {
1159 /* "the Nth arrow"; value will eventually be passed to an() or
1160 The(), both of which correctly handle this "the " prefix */
1162 Sprintf(tmpbuf, "the %d%s ", m_shot.i, ordin(m_shot.i));
1164 Sprintf(tmpbuf, "%d%s
\96Ú
\82Ì", m_shot.i, numeral(obj));
1165 onm = strprepend(onm, tmpbuf);
1170 /* used for naming "the unique_item" instead of "a unique_item" */
1176 boolean known = (obj->known || iflags.override_ID);
1178 if (!obj->dknown && !iflags.override_ID)
1180 else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !known)
1181 return TRUE; /* lie */
1183 return (boolean) (objects[obj->otyp].oc_unique
1184 && (known || obj->otyp == AMULET_OF_YENDOR));
1190 /* should monster type be prefixed with "the"? (mostly used for corpses) */
1193 struct permonst *ptr;
1197 /* even though monsters with personal names are unique, we want to
1198 describe them as "Name" rather than "the Name" */
1199 if (type_is_pname(ptr))
1202 uniq = (ptr->geno & G_UNIQ) ? TRUE : FALSE;
1203 /* high priest is unique if it includes "of <deity>", otherwise not
1204 (caller needs to handle the 1st possibility; we assume the 2nd);
1205 worm tail should be irrelevant but is included for completeness */
1206 if (ptr == &mons[PM_HIGH_PRIEST] || ptr == &mons[PM_LONG_WORM_TAIL])
1208 /* Wizard no longer needs this; he's flagged as unique these days */
1209 if (ptr == &mons[PM_WIZARD_OF_YENDOR])
1215 add_erosion_words(obj, prefix)
1219 boolean iscrys = (obj->otyp == CRYSKNIFE);
1222 rknown = (iflags.override_ID == 0) ? obj->rknown : TRUE;
1224 if (!is_damageable(obj) && !iscrys)
1227 /* The only cases where any of these bits do double duty are for
1228 * rotted food and diluted potions, which are all not is_damageable().
1230 if (obj->oeroded && !iscrys) {
1231 switch (obj->oeroded) {
1234 Strcat(prefix, "very ");
1236 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1240 Strcat(prefix, "thoroughly ");
1242 Strcat(prefix, "
\82©
\82È
\82è");
1246 Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
1248 Strcat(prefix, is_rustprone(obj) ? "
\8eK
\82Ñ
\82½" : "
\8f\9d\82Â
\82¢
\82½");
1250 if (obj->oeroded2 && !iscrys) {
1251 switch (obj->oeroded2) {
1254 Strcat(prefix, "very ");
1256 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1260 Strcat(prefix, "thoroughly ");
1262 Strcat(prefix, "
\82©
\82È
\82è");
1266 Strcat(prefix, is_corrodeable(obj) ? "corroded " : "rotted ");
1268 Strcat(prefix, is_corrodeable(obj) ? "
\95\85\90H
\82µ
\82½" : "
\95\85\82Á
\82½");
1270 if (rknown && obj->oerodeproof)
1272 Strcat(prefix, iscrys
1276 : is_corrodeable(obj)
1277 ? "corrodeproof " /* "stainless"? */
1282 Strcat(prefix, iscrys
1283 ? "
\88À
\92è
\82µ
\82½"
1285 ? "
\8eK
\82Ñ
\82È
\82¢"
1286 : is_corrodeable(obj)
1287 ? "
\95\85\90H
\82µ
\82È
\82¢" /* "stainless"? */
1289 ? "
\94R
\82¦
\82È
\82¢"
1294 /* used to prevent rust on items where rust makes no difference */
1296 erosion_matters(obj)
1299 switch (obj->oclass) {
1301 /* it's possible for a rusty weptool to be polymorphed into some
1302 non-weptool iron tool, in which case the rust implicitly goes
1303 away, but it's also possible for it to be polymorphed into a
1304 non-iron tool, in which case rust also implicitly goes away,
1305 so there's no particular reason to try to handle the first
1306 instance differently [this comment belongs in poly_obj()...] */
1307 return is_weptool(obj) ? TRUE : FALSE;
1319 #define DONAME_WITH_PRICE 1
1320 #define DONAME_VAGUE_QUAN 2
1323 doname_base(obj, doname_flags)
1325 unsigned doname_flags;
1327 boolean ispoisoned = FALSE,
1328 with_price = (doname_flags & DONAME_WITH_PRICE) != 0,
1329 vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0,
1330 weightshown = FALSE;
1331 boolean known, dknown, cknown, bknown, lknown;
1332 int omndx = obj->corpsenm;
1333 char prefix[PREFIX], globbuf[QBUFSZ];
1335 char tmpbuf[PREFIX + 1]; /* for when we have to add something at
1336 the start of prefix instead of the
1337 end (Strcat is used on the end) */
1339 register char *bp = xname(obj);
1341 char preprefix[PREFIX]; /*
\8f\87\8f\98\93ü
\82ê
\91Ö
\82¦
\82É
\8eg
\82¤*/
1345 if (iflags.override_ID) {
1346 known = dknown = cknown = bknown = lknown = TRUE;
1349 dknown = obj->dknown;
1350 cknown = obj->cknown;
1351 bknown = obj->bknown;
1352 lknown = obj->lknown;
1355 /* When using xname, we want "poisoned arrow", and when using
1356 * doname, we want "poisoned +0 arrow". This kludge is about the only
1357 * way to do it, at least until someone overhauls xname() and doname(),
1358 * combining both into one function taking a parameter.
1360 /* must check opoisoned--someone can have a weirdly-named fruit */
1362 if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
1367 if (!STRNCMPEX(bp, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½") && obj->opoisoned) {
1374 *
\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
1375 *
\82Ì
\82Ù
\82¤
\82ª
\8e©
\91R
\82Å
\82 \82é
\81D
1379 preprefix[0] = '\0';
1380 if((tp = strstri(bp, "
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½")) != NULL){
1381 tp += 12; /*
\81u
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½
\81v*/
1382 strncpy(preprefix, bp, tp - bp);
1383 preprefix[tp - bp] = '\0';
1390 if (obj->quan != 1L) {
1391 if (dknown || !vague_quan)
1393 Sprintf(prefix, "%ld ", obj->quan);
1394 #else /*
\93ú
\96{
\8cê
\82Æ
\82µ
\82Ä
\82Í
\90\94\8e\8c\82ª
\82È
\82¢
\82Ì
\82Í
\95s
\8e©
\91R */
1395 Sprintf(prefix, "%ld%s
\82Ì", obj->quan, numeral(obj));
1399 Strcpy(prefix, "some ");
1401 Strcpy(prefix, "
\82¢
\82
\82Â
\82©
\82Ì");
1402 } else if (obj->otyp == CORPSE) {
1403 /* skip article prefix for corpses [else corpse_xname()
1404 would have to be taught how to strip it off again] */
1406 #if 0 /*JP*/ /*
\8a¥
\8e\8c\82Í
\95s
\97v */
1407 } else if (obj_is_pname(obj) || the_unique_obj(obj)) {
1408 if (!strncmpi(bp, "the ", 4))
1410 Strcpy(prefix, "the ");
1412 Strcpy(prefix, "a ");
1413 #else /*prefix
\82Ì
\8f\89\8aú
\89»*/
1419 /* "empty" goes at the beginning, but item count goes at the end */
1421 /* bag of tricks: include "empty" prefix if it's known to
1422 be empty but its precise number of charges isn't known
1423 (when that is known, suffix of "(n:0)" will be appended,
1424 making the prefix be redundant; note that 'known' flag
1425 isn't set when emptiness gets discovered because then
1426 charging magic would yield known number of new charges) */
1427 && ((obj->otyp == BAG_OF_TRICKS)
1428 ? (obj->spe == 0 && !obj->known)
1429 /* not bag of tricks: empty if container which has no contents */
1430 : ((Is_container(obj) || obj->otyp == STATUE)
1431 && !Has_contents(obj))))
1433 Strcat(prefix, "empty ");
1435 Strcat(prefix, "
\8bó
\82Ì");
1437 if (bknown && obj->oclass != COIN_CLASS
1438 && (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
1439 || (!obj->cursed && !obj->blessed))) {
1440 /* allow 'blessed clear potion' if we don't know it's holy water;
1441 * always allow "uncursed potion of water"
1445 Strcat(prefix, "cursed ");
1447 Strcat(prefix, "
\8eô
\82í
\82ê
\82½");
1448 else if (obj->blessed)
1450 Strcat(prefix, "blessed ");
1452 Strcat(prefix, "
\8fj
\95\9f\82³
\82ê
\82½");
1453 else if (!iflags.implicit_uncursed
1454 /* For most items with charges or +/-, if you know how many
1455 * charges are left or what the +/- is, then you must have
1456 * totally identified the item, so "uncursed" is unnecessary,
1457 * because an identified object not described as "blessed" or
1458 * "cursed" must be uncursed.
1460 * If the charges or +/- is not known, "uncursed" must be
1461 * printed to avoid ambiguity between an item whose curse
1462 * status is unknown, and an item known to be uncursed.
1464 || ((!known || !objects[obj->otyp].oc_charged
1465 || obj->oclass == ARMOR_CLASS
1466 || obj->oclass == RING_CLASS)
1468 && obj->otyp != SCR_MAIL
1470 && obj->otyp != FAKE_AMULET_OF_YENDOR
1471 && obj->otyp != AMULET_OF_YENDOR
1472 && !Role_if(PM_PRIEST)))
1474 Strcat(prefix, "uncursed ");
1476 Strcat(prefix, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢");
1479 if (lknown && Is_box(obj)) {
1481 /* 3.6.0 used "unlockable" here but that could be misunderstood
1482 to mean "capable of being unlocked" rather than the intended
1483 "not capable of being locked" */
1485 Strcat(prefix, "broken ");
1487 Strcat(prefix, "
\8c®
\82Ì
\89ó
\82ê
\82½");
1488 else if (obj->olocked)
1490 Strcat(prefix, "locked ");
1492 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82½");
1495 Strcat(prefix, "unlocked ");
1497 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82Ä
\82¢
\82È
\82¢");
1502 Strcat(prefix, "greased ");
1504 Strcat(prefix, "
\96û
\82Ì
\93h
\82ç
\82ê
\82½");
1506 if (cknown && Has_contents(obj)) {
1507 /* we count the number of separate stacks, which corresponds
1508 to the number of inventory slots needed to be able to take
1509 everything out if no merges occur */
1510 long itemcount = count_contents(obj, FALSE, FALSE, TRUE, FALSE);
1513 Sprintf(eos(bp), " containing %ld item%s", itemcount,
1516 Sprintf(eos(bp), "(%ld
\8cÂ
\93ü
\82Á
\82Ä
\82¢
\82é)", itemcount);
1520 switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
1522 if (obj->owornmask & W_AMUL)
1524 Strcat(bp, " (being worn)");
1526 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1529 if (obj->owornmask & W_ARMOR) {
1531 Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
1533 Strcat(bp, (obj == uskin) ? "(
\94§
\82É
\96\84\82ß
\82±
\82Ü
\82ê
\82Ä
\82¢
\82é)"
1534 /* in case of perm_invent update while Wear/Takeoff
1535 is in progress; check doffing() before donning()
1536 because donning() returns True for both cases */
1538 : doffing(obj) ? " (being doffed)"
1540 : doffing(obj) ? " (
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é
\93r
\92\86)"
1542 : donning(obj) ? " (being donned)"
1544 : donning(obj) ? " (
\92E
\82¢
\82Å
\82¢
\82é
\93r
\92\86)"
1548 : "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1549 /* slippery fingers is an intrinsic condition of the hero
1550 rather than extrinsic condition of objects, but gloves
1551 are described as slippery when hero has slippery fingers */
1552 if (obj == uarmg && Glib) /* just appended "(something)",
1553 * change to "(something; slippery)" */
1555 Strcpy(rindex(bp, ')'), "; slippery)");
1557 Strcpy(rindex(bp, ')'), ";
\82Ê
\82é
\82Ê
\82é)");
1563 Strcat(prefix, "poisoned ");
1565 Strcat(prefix, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
1566 add_erosion_words(obj, prefix);
1568 Strcat(prefix, sitoa(obj->spe));
1569 Strcat(prefix, " ");
1573 if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
1575 Strcat(bp, " (being worn)");
1577 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1580 if (obj->otyp == LEASH && obj->leashmon != 0) {
1581 struct monst *mlsh = find_mid(obj->leashmon, FM_FMON);
1584 impossible("leashed monster not on this level");
1588 Sprintf(eos(bp), " (attached to %s)",
1589 noit_mon_nam(mlsh));
1591 Sprintf(eos(bp), " (%s
\82É
\8c\8b\82Ñ
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é)",
1592 noit_mon_nam(mlsh));
1597 if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
1600 Strcpy(tmpbuf, "no");
1602 Sprintf(tmpbuf, "%d", obj->spe);
1603 Sprintf(eos(bp), " (%s candle%s%s)", tmpbuf, plur(obj->spe),
1604 !obj->lamplit ? " attached" : ", lit");
1607 Sprintf(eos(bp), "(
\88ê
\96{
\82à
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82È
\82¢)");
1610 Sprintf(eos(bp), "(%d
\96{
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é)", obj->spe);
1612 Sprintf(eos(bp), "(%d
\96{
\8cõ
\82Á
\82Ä
\82¢
\82é)", obj->spe);
1616 } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
1617 || obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
1619 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
1621 Strcat(prefix, "partly used ");
1623 Strcat(prefix, "
\8eg
\82¢
\82³
\82µ
\82Ì");
1626 Strcat(bp, " (lit)");
1628 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1631 if (objects[obj->otyp].oc_charged)
1638 Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
1640 Sprintf(eos(bp), "(%d:%d)", (int) obj->recharged, obj->spe);
1643 if (obj->otyp == POT_OIL && obj->lamplit)
1645 Strcat(bp, " (lit)");
1647 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1651 if (obj->owornmask & W_RINGR)
1653 Strcat(bp, " (on right ");
1655 Strcat(bp, "(
\89E");
1656 if (obj->owornmask & W_RINGL)
1658 Strcat(bp, " (on left ");
1660 Strcat(bp, "(
\8d¶");
1661 if (obj->owornmask & W_RING) {
1662 Strcat(bp, body_part(HAND));
1665 if (known && objects[obj->otyp].oc_charged) {
1667 Strcat(prefix, " ");
1669 Strcat(prefix, sitoa(obj->spe));
1670 Strcat(prefix, " ");
1676 Strcat(prefix, "partly eaten ");
1678 Strcat(prefix, "
\90H
\82×
\82©
\82¯
\82Ì");
1679 if (obj->otyp == CORPSE) {
1680 /* (quan == 1) => want corpse_xname() to supply article,
1681 (quan != 1) => already have count or "some" as prefix;
1682 "corpse" is already in the buffer returned by xname() */
1683 unsigned cxarg = (((obj->quan != 1L) ? 0 : CXN_ARTICLE)
1685 char *cxstr = corpse_xname(obj, prefix, cxarg);
1688 Sprintf(prefix, "%s ", cxstr);
1690 Sprintf(prefix, "%s
\82Ì", cxstr);
1692 /* avoid having doname(corpse) consume an extra obuf */
1694 } else if (obj->otyp == EGG) {
1695 #if 0 /* corpses don't tell if they're stale either */
1696 if (known && stale_egg(obj))
1697 Strcat(prefix, "stale ");
1700 && (known || (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
1702 Strcat(prefix, mons[omndx].mname);
1703 Strcat(prefix, " ");
1705 Strcat(prefix, mons[omndx].mname);
1706 Strcat(prefix, "
\82Ì");
1710 Strcat(bp, " (laid by you)");
1712 Strcat(bp, "(
\82 \82È
\82½
\82ª
\8eY
\82ñ
\82¾)");
1715 if (obj->otyp == MEAT_RING)
1720 add_erosion_words(obj, prefix);
1721 if (obj->owornmask & W_BALL)
1723 Strcat(bp, " (chained to you)");
1725 Strcat(bp, "(
\82 \82È
\82½
\82É
\8cq
\82ª
\82ê
\82Ä
\82¢
\82é)");
1729 if ((obj->owornmask & W_WEP) && !mrg_to_wielded) {
1730 if (obj->quan != 1L) {
1732 Strcat(bp, " (wielded)");
1734 Strcat(bp, "(
\91\95\94õ
\82µ
\82Ä
\82¢
\82é)");
1736 const char *hand_s = body_part(HAND);
1739 hand_s = makeplural(hand_s);
1740 /* note: Sting's glow message, if added, will insert text
1741 in front of "(weapon in hand)"'s closing paren */
1743 Sprintf(eos(bp), " (%sweapon in %s)",
1744 (obj->otyp == AKLYS) ? "tethered " : "", hand_s);
1745 #else /*
\83A
\83L
\83\8a\83X
\82ð
\93Á
\95Ê
\88µ
\82¢
\82µ
\82È
\82¢*/
1746 Sprintf(eos(bp), "(%s
\82É
\82µ
\82Ä
\82¢
\82é)", hand_s);
1749 if (warn_obj_cnt && obj == uwep && (EWarn_of_mon & W_WEP) != 0L) {
1750 if (!Blind) /* we know bp[] ends with ')'; overwrite that */
1752 Sprintf(eos(bp) - 1, ", %s %s)",
1753 glow_verb(warn_obj_cnt, TRUE),
1754 glow_color(obj->oartifact));
1756 Sprintf(eos(bp) - 1, ", %s%s
\82¢
\82é)",
1757 glow_color(obj->oartifact),
1758 jconj(glow_verb(warn_obj_cnt, TRUE), "
\82Ä"));
1763 if (obj->owornmask & W_SWAPWEP) {
1766 Sprintf(eos(bp), " (wielded in other %s)", body_part(HAND));
1768 Sprintf(eos(bp), "(
\8d¶%s
\82É
\82µ
\82Ä
\82¢
\82é)", body_part(HAND));
1771 Strcat(bp, " (alternate weapon; not wielded)");
1773 Strcat(bp, "(
\97\
\94õ
\82Ì
\95\90\8aí;
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢)");
1775 if (obj->owornmask & W_QUIVER) {
1776 switch (obj->oclass) {
1779 if (objects[obj->otyp].oc_skill == -P_BOW) {
1780 /* Ammo for a bow */
1782 Strcat(bp, " (in quiver)");
1784 Strcat(bp, "(
\96î
\93\9b\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1787 /* Ammo not for a bow */
1789 Strcat(bp, " (in quiver pouch)");
1791 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1795 /* Weapons not considered ammo */
1797 Strcat(bp, " (at the ready)");
1799 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1802 /* Small things and ammo not for a bow */
1809 Strcat(bp, " (in quiver pouch)");
1811 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1813 default: /* odd things */
1815 Strcat(bp, " (at the ready)");
1817 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1820 /* treat 'restoring' like suppress_price because shopkeeper and
1821 bill might not be available yet while restore is in progress
1822 (objects won't normally be formatted during that time, but if
1823 'perm_invent' is enabled then they might be) */
1824 if (iflags.suppress_price || restoring) {
1825 ; /* don't attempt to obtain any stop pricing, even if 'with_price' */
1826 } else if (is_unpaid(obj)) { /* in inventory or in container in invent */
1827 long quotedprice = unpaid_cost(obj, TRUE);
1830 Sprintf(eos(bp), " (%s, %s%ld %s)",
1831 obj->unpaid ? "unpaid" : "contents",
1832 globwt(obj, globbuf, &weightshown),
1833 quotedprice, currency(quotedprice));
1835 Sprintf(eos(bp), " (%s, %s%ld%s)",
1836 obj->unpaid ? "
\96¢
\95¥
\82¢" : "
\92\86\90g",
1837 globwt(obj, globbuf, &weightshown),
1838 quotedprice, currency(quotedprice));
1840 } else if (with_price) { /* on floor or in container on floor */
1842 long price = get_cost_of_shop_item(obj, &nochrg);
1846 Sprintf(eos(bp), " (%s, %s%ld %s)",
1847 nochrg ? "contents" : "for sale",
1848 globwt(obj, globbuf, &weightshown),
1849 price, currency(price));
1851 Sprintf(eos(bp), " (%s, %s%ld%s)",
1852 nochrg ? "
\92\86\90g" : "
\8f¤
\95i",
1853 globwt(obj, globbuf, &weightshown),
1854 price, currency(price));
1856 else if (nochrg > 0)
1858 Sprintf(eos(bp), " (%sno charge)",
1859 globwt(obj, globbuf, &weightshown));
1861 Sprintf(eos(bp), " (%s
\96³
\97¿)",
1862 globwt(obj, globbuf, &weightshown));
1865 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
1866 if (!strncmp(prefix, "a ", 2)) {
1867 /* save current prefix, without "a "; might be empty */
1868 Strcpy(tmpbuf, prefix + 2);
1869 /* set prefix[] to "", "a ", or "an " */
1870 (void) just_an(prefix, *tmpbuf ? tmpbuf : bp);
1871 /* append remainder of original prefix */
1872 Strcat(prefix, tmpbuf);
1876 /* show weight for items (debug tourist info);
1877 "aum" is stolen from Crawl's "Arbitrary Unit of Measure" */
1878 if (wizard && iflags.wizweight) {
1879 /* wizard mode user has asked to see object weights;
1880 globs with shop pricing attached already include it */
1882 Sprintf(eos(bp), " (%u aum)", obj->owt);
1885 bp = strprepend(bp, prefix);
1886 #else /*JP:
\81u
\96¼
\95t
\82¯
\82ç
\82ê
\82½
\81v
\82ð
\96ß
\82·*/
1887 Strcat(preprefix, prefix);
1888 bp = strprepend(bp, preprefix);
1897 return doname_base(obj, (unsigned) 0);
1900 /* Name of object including price. */
1902 doname_with_price(obj)
1905 return doname_base(obj, DONAME_WITH_PRICE);
1908 /* "some" instead of precise quantity if obj->dknown not set */
1910 doname_vague_quan(obj)
1914 * If it hasn't been seen up close and quantity is more than one,
1915 * use "some" instead of the quantity: "some gold pieces" rather
1916 * than "25 gold pieces". This is suboptimal, to put it mildly,
1917 * because lookhere and pickup report the precise amount.
1918 * Picking the item up while blind also shows the precise amount
1919 * for inventory display, then dropping it while still blind leaves
1920 * obj->dknown unset so the count reverts to "some" for farlook.
1922 * TODO: add obj->qknown flag for 'quantity known' on stackable
1923 * items; it could overlay obj->cknown since no containers stack.
1925 return doname_base(obj, DONAME_VAGUE_QUAN);
1928 /* used from invent.c */
1930 not_fully_identified(otmp)
1933 /* gold doesn't have any interesting attributes [yet?] */
1934 if (otmp->oclass == COIN_CLASS)
1935 return FALSE; /* always fully ID'd */
1936 /* check fundamental ID hallmarks first */
1937 if (!otmp->known || !otmp->dknown
1939 || (!otmp->bknown && otmp->otyp != SCR_MAIL)
1943 || !objects[otmp->otyp].oc_name_known)
1945 if ((!otmp->cknown && (Is_container(otmp) || otmp->otyp == STATUE))
1946 || (!otmp->lknown && Is_box(otmp)))
1948 if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
1950 /* otmp->rknown is the only item of interest if we reach here */
1952 * Note: if a revision ever allows scrolls to become fireproof or
1953 * rings to become shockproof, this checking will need to be revised.
1954 * `rknown' ID only matters if xname() will provide the info about it.
1957 || (otmp->oclass != ARMOR_CLASS && otmp->oclass != WEAPON_CLASS
1958 && !is_weptool(otmp) /* (redundant) */
1959 && otmp->oclass != BALL_CLASS)) /* (useless) */
1961 else /* lack of `rknown' only matters for vulnerable objects */
1962 return (boolean) (is_rustprone(otmp) || is_corrodeable(otmp)
1963 || is_flammable(otmp));
1966 /* format a corpse name (xname() omits monster type; doname() calls us);
1967 eatcorpse() also uses us for death reason when eating tainted glob */
1969 corpse_xname(otmp, adjective, cxn_flags)
1971 const char *adjective;
1972 unsigned cxn_flags; /* bitmask of CXN_xxx values */
1974 /* some callers [aobjnam()] rely on prefix area that xname() sets aside */
1975 char *nambuf = nextobuf() + PREFIX;
1976 int omndx = otmp->corpsenm;
1978 boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0,
1979 /* suppress "the" from "the unique monster corpse" */
1983 no_prefix = (cxn_flags & CXN_NO_PFX) != 0,
1984 /* include "the" for "the woodchuck corpse */
1985 the_prefix = (cxn_flags & CXN_PFX_THE) != 0,
1986 /* include "an" for "an ogre corpse */
1987 any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
1988 /* leave off suffix (do_name() appends "corpse" itself) */
1989 omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
1991 glob = (otmp->otyp != CORPSE && otmp->globby);
1995 mname = OBJ_NAME(objects[otmp->otyp]); /* "glob of <monster>" */
1996 } else if (omndx == NON_PM) { /* paranoia */
2001 /* [Possible enhancement: check whether corpse has monster traits
2002 attached in order to use priestname() for priests and minions.] */
2003 } else if (omndx == PM_ALIGNED_PRIEST) {
2004 /* avoid "aligned priest"; it just exposes internal details */
2010 mname = mons[omndx].mname;
2011 if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) {
2012 mname = s_suffix(mname);
2014 /* don't precede personal name like "Medusa" with an article */
2015 if (type_is_pname(&mons[omndx]))
2017 /* always precede non-personal unique monster name like
2018 "Oracle" with "the" unless explicitly overridden */
2019 else if (the_unique_pm(&mons[omndx]) && !no_prefix)
2024 the_prefix = any_prefix = FALSE;
2025 else if (the_prefix)
2026 any_prefix = FALSE; /* mutually exclusive */
2029 /* can't use the() the way we use an() below because any capitalized
2030 Name causes it to assume a personal name and return Name as-is;
2031 that's usually the behavior wanted, but here we need to force "the"
2032 to precede capitalized unique monsters (pnames are handled above) */
2033 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2035 Strcat(nambuf, "the ");
2038 if (!adjective || !*adjective) {
2039 /* normal case: newt corpse */
2040 Strcat(nambuf, mname);
2042 /* adjective positioning depends upon format of monster name */
2043 if (possessive) /* Medusa's cursed partly eaten corpse */
2045 Sprintf(eos(nambuf), "%s %s", mname, adjective);
2047 Sprintf(eos(nambuf), "%s%s", mname, adjective);
2048 else /* cursed partly eaten troll corpse */
2050 Sprintf(eos(nambuf), "%s %s", adjective, mname);
2052 Sprintf(eos(nambuf), "%s%s", adjective, mname);
2053 /* in case adjective has a trailing space, squeeze it out */
2055 /* doname() might include a count in the adjective argument;
2056 if so, don't prepend an article */
2057 if (digit(*adjective))
2062 ; /* omit_corpse doesn't apply; quantity is always 1 */
2063 } else if (!omit_corpse) {
2065 Strcat(nambuf, " corpse");
2066 /* makeplural(nambuf) => append "s" to "corpse" */
2067 if (otmp->quan > 1L && !ignore_quan) {
2068 Strcat(nambuf, "s");
2069 any_prefix = FALSE; /* avoid "a newt corpses" */
2072 Strcat(nambuf, "
\82Ì
\8e\80\91Ì");
2076 /* it's safe to overwrite our nambuf after an() has copied
2077 its old value into another buffer */
2079 Strcpy(nambuf, an(nambuf));
2084 /* xname doesn't include monster type for "corpse"; cxname does */
2089 if (obj->otyp == CORPSE)
2090 return corpse_xname(obj, (const char *) 0, CXN_NORMAL);
2094 /* like cxname, but ignores quantity */
2096 cxname_singular(obj)
2099 if (obj->otyp == CORPSE)
2100 return corpse_xname(obj, (const char *) 0, CXN_SINGULAR);
2101 return xname_flags(obj, CXN_SINGULAR);
2104 /* treat an object as fully ID'd when it might be used as reason for death */
2109 struct obj save_obj;
2110 unsigned save_ocknown;
2111 char *buf, *save_ocuname, *save_oname = (char *) 0;
2113 /* bypass object twiddling for artifacts */
2115 return bare_artifactname(obj);
2117 /* remember original settings for core of the object;
2118 oextra structs other than oname don't matter here--since they
2119 aren't modified they don't need to be saved and restored */
2122 save_oname = ONAME(obj);
2124 /* killer name should be more specific than general xname; however, exact
2125 info like blessed/cursed and rustproof makes things be too verbose */
2126 obj->known = obj->dknown = 1;
2127 obj->bknown = obj->rknown = obj->greased = 0;
2128 /* if character is a priest[ess], bknown will get toggled back on */
2129 if (obj->otyp != POT_WATER)
2130 obj->blessed = obj->cursed = 0;
2132 obj->bknown = 1; /* describe holy/unholy water as such */
2133 /* "killed by poisoned <obj>" would be misleading when poison is
2134 not the cause of death and "poisoned by poisoned <obj>" would
2135 be redundant when it is, so suppress "poisoned" prefix */
2137 /* strip user-supplied name; artifacts keep theirs */
2138 if (!obj->oartifact && save_oname)
2139 ONAME(obj) = (char *) 0;
2140 /* temporarily identify the type of object */
2141 save_ocknown = objects[obj->otyp].oc_name_known;
2142 objects[obj->otyp].oc_name_known = 1;
2143 save_ocuname = objects[obj->otyp].oc_uname;
2144 objects[obj->otyp].oc_uname = 0; /* avoid "foo called bar" */
2146 /* format the object */
2147 if (obj->otyp == CORPSE) {
2148 buf = corpse_xname(obj, (const char *) 0, CXN_NORMAL);
2149 } else if (obj->otyp == SLIME_MOLD) {
2150 /* concession to "most unique deaths competition" in the annual
2151 devnull tournament, suppress player supplied fruit names because
2152 those can be used to fake other objects and dungeon features */
2155 Sprintf(buf, "deadly slime mold%s", plur(obj->quan));
2157 Strcpy(buf, "
\8aë
\8c¯
\82È
\82Ë
\82Î
\82Ë
\82Î
\83J
\83r");
2161 /* apply an article if appropriate; caller should always use KILLED_BY */
2162 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
2163 if (obj->quan == 1L && !strstri(buf, "'s ") && !strstri(buf, "s' "))
2164 buf = (obj_is_pname(obj) || the_unique_obj(obj)) ? the(buf) : an(buf);
2167 objects[obj->otyp].oc_name_known = save_ocknown;
2168 objects[obj->otyp].oc_uname = save_ocuname;
2169 *obj = save_obj; /* restore object's core settings */
2170 if (!obj->oartifact && save_oname)
2171 ONAME(obj) = save_oname;
2176 /* xname,doname,&c with long results reformatted to omit some stuff */
2178 short_oname(obj, func, altfunc, lenlimit)
2180 char *FDECL((*func), (OBJ_P)), /* main formatting routine */
2181 *FDECL((*altfunc), (OBJ_P)); /* alternate for shortest result */
2184 struct obj save_obj;
2185 char unamebuf[12], onamebuf[12], *save_oname, *save_uname, *outbuf;
2187 outbuf = (*func)(obj);
2188 if ((unsigned) strlen(outbuf) <= lenlimit)
2191 /* shorten called string to fairly small amount */
2192 save_uname = objects[obj->otyp].oc_uname;
2193 if (save_uname && strlen(save_uname) >= sizeof unamebuf) {
2194 (void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
2195 Strcpy(unamebuf + sizeof unamebuf - 4, "...");
2196 objects[obj->otyp].oc_uname = unamebuf;
2197 releaseobuf(outbuf);
2198 outbuf = (*func)(obj);
2199 objects[obj->otyp].oc_uname = save_uname; /* restore called string */
2200 if ((unsigned) strlen(outbuf) <= lenlimit)
2204 /* shorten named string to fairly small amount */
2205 save_oname = has_oname(obj) ? ONAME(obj) : 0;
2206 if (save_oname && strlen(save_oname) >= sizeof onamebuf) {
2207 (void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
2208 Strcpy(onamebuf + sizeof onamebuf - 4, "...");
2209 ONAME(obj) = onamebuf;
2210 releaseobuf(outbuf);
2211 outbuf = (*func)(obj);
2212 ONAME(obj) = save_oname; /* restore named string */
2213 if ((unsigned) strlen(outbuf) <= lenlimit)
2217 /* shorten both called and named strings;
2218 unamebuf and onamebuf have both already been populated */
2219 if (save_uname && strlen(save_uname) >= sizeof unamebuf && save_oname
2220 && strlen(save_oname) >= sizeof onamebuf) {
2221 objects[obj->otyp].oc_uname = unamebuf;
2222 ONAME(obj) = onamebuf;
2223 releaseobuf(outbuf);
2224 outbuf = (*func)(obj);
2225 if ((unsigned) strlen(outbuf) <= lenlimit) {
2226 objects[obj->otyp].oc_uname = save_uname;
2227 ONAME(obj) = save_oname;
2232 /* still long; strip several name-lengthening attributes;
2233 called and named strings are still in truncated form */
2235 obj->bknown = obj->rknown = obj->greased = 0;
2236 obj->oeroded = obj->oeroded2 = 0;
2237 releaseobuf(outbuf);
2238 outbuf = (*func)(obj);
2239 if (altfunc && (unsigned) strlen(outbuf) > lenlimit) {
2240 /* still long; use the alternate function (usually one of
2241 the jackets around minimal_xname()) */
2242 releaseobuf(outbuf);
2243 outbuf = (*altfunc)(obj);
2245 /* restore the object */
2248 ONAME(obj) = save_oname;
2250 objects[obj->otyp].oc_uname = save_uname;
2252 /* use whatever we've got, whether it's too long or not */
2257 * Used if only one of a collection of objects is named (e.g. in eat.c).
2260 singular(otmp, func)
2261 register struct obj *otmp;
2262 char *FDECL((*func), (OBJ_P));
2267 /* using xname for corpses does not give the monster type */
2268 if (otmp->otyp == CORPSE && func == xname)
2271 savequan = otmp->quan;
2273 nam = (*func)(otmp);
2274 otmp->quan = savequan;
2278 /* pick "", "a ", or "an " as article for 'str'; used by an() and doname() */
2280 just_an(outbuf, str)
2284 #if 0 /*JP*//*
\95s
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2290 /* single letter; might be used for named fruit */
2291 Strcpy(outbuf, index("aefhilmnosx", c0) ? "an " : "a ");
2292 } else if (!strncmpi(str, "the ", 4) || !strcmpi(str, "molten lava")
2293 || !strcmpi(str, "iron bars") || !strcmpi(str, "ice")) {
2296 if ((index(vowels, c0) && strncmpi(str, "one-", 4)
2297 && strncmpi(str, "eucalyptus", 10) && strncmpi(str, "unicorn", 7)
2298 && strncmpi(str, "uranium", 7) && strncmpi(str, "useful", 6))
2299 || (index("x", c0) && !index(vowels, lowc(str[1]))))
2300 Strcpy(outbuf, "an ");
2302 Strcpy(outbuf, "a ");
2314 char *buf = nextobuf();
2316 if (!str || !*str) {
2317 impossible("Alphabet soup: 'an(%s)'.", str ? "\"\"" : "<null>");
2318 return strcpy(buf, "an []");
2320 (void) just_an(buf, str);
2321 return strncat(buf, str, BUFSZ - 1 - (unsigned) strlen(buf));
2328 char *tmp = an(str);
2330 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
2337 * Prepend "the" if necessary; assumes str is a subject derived from xname.
2338 * Use type_is_pname() for monster names, not the(). the() is idempotent.
2344 char *buf = nextobuf();
2345 #if 0 /*JP*//*
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
2346 boolean insert_the = FALSE;
2348 if (!str || !*str) {
2349 impossible("Alphabet soup: 'the(%s)'.", str ? "\"\"" : "<null>");
2350 return strcpy(buf, "the []");
2352 if (!strncmpi(str, "the ", 4)) {
2353 buf[0] = lowc(*str);
2354 Strcpy(&buf[1], str + 1);
2356 } else if (*str < 'A' || *str > 'Z'
2357 /* treat named fruit as not a proper name, even if player
2358 has assigned a capitalized proper name as his/her fruit */
2359 || fruit_from_name(str, TRUE, (int *) 0)) {
2360 /* not a proper name, needs an article */
2363 /* Probably a proper name, might not need an article */
2364 register char *tmp, *named, *called;
2367 /* some objects have capitalized adjectives in their names */
2368 if (((tmp = rindex(str, ' ')) != 0 || (tmp = rindex(str, '-')) != 0)
2369 && (tmp[1] < 'A' || tmp[1] > 'Z')) {
2371 } else if (tmp && index(str, ' ') < tmp) { /* has spaces */
2372 /* it needs an article if the name contains "of" */
2373 tmp = strstri(str, " of ");
2374 named = strstri(str, " named ");
2375 called = strstri(str, " called ");
2376 if (called && (!named || called < named))
2379 if (tmp && (!named || tmp < named)) /* found an "of" */
2381 /* stupid special case: lacks "of" but needs "the" */
2382 else if (!named && (l = strlen(str)) >= 31
2383 && !strcmp(&str[l - 31],
2384 "Platinum Yendorian Express Card"))
2389 Strcpy(buf, "the ");
2392 return strncat(buf, str, BUFSZ - 1 - (unsigned) strlen(buf));
2393 #else /*
\92P
\82É
\83R
\83s
\81[*/
2403 char *tmp = the(str);
2405 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
2414 register struct obj *otmp;
2415 register const char *verb;
2421 /* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */
2427 char prefix[PREFIX];
2428 char *bp = cxname(otmp);
2430 if (otmp->quan != 1L) {
2431 Sprintf(prefix, "%ld ", otmp->quan);
2432 bp = strprepend(bp, prefix);
2436 Strcat(bp, otense(otmp, verb));
2442 /* combine yname and aobjnam eg "your count cxname(otmp)" */
2448 char *s = aobjnam(obj, verb);
2450 /* leave off "your" for most of your artifacts, but prepend
2451 * "your" for unique objects and "foo of bar" quest artifacts */
2452 if (!carried(obj) || !obj_is_pname(obj)
2453 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2454 char *outbuf = shk_your(nextobuf(), obj);
2455 int space_left = BUFSZ - 1 - strlen(outbuf);
2457 s = strncat(outbuf, s, space_left);
2462 /* combine Yname2 and aobjnam eg "Your count cxname(otmp)" */
2468 register char *s = yobjnam(obj, verb);
2476 /* like aobjnam, but prepend "The", not count, and use xname */
2482 char *bp = The(xname(otmp));
2484 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2487 Strcat(bp, otense(otmp, verb));
2493 /* capitalized variant of doname() */
2498 char *s = doname(obj);
2504 #if 0 /* stalled-out work in progress */
2505 /* Doname2() for itemized buying of 'obj' from a shop */
2510 static const char and_contents[] = " and its contents";
2511 char *p = doname(obj);
2513 if (Is_container(obj) && !obj->cknown) {
2515 if ((int) strlen(p) + sizeof and_contents - 1 < BUFSZ - PREFIX)
2516 Strcat(p, and_contents);
2519 p = strprepend(p, "Contents of ");
2528 /* returns "[your ]xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
2533 char *s = cxname(obj);
2535 /* leave off "your" for most of your artifacts, but prepend
2536 * "your" for unique objects and "foo of bar" quest artifacts */
2537 if (!carried(obj) || !obj_is_pname(obj)
2538 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2539 char *outbuf = shk_your(nextobuf(), obj);
2540 int space_left = BUFSZ - 1 - strlen(outbuf);
2542 s = strncat(outbuf, s, space_left);
2548 /* capitalized variant of yname() */
2553 char *s = yname(obj);
2561 /* returns "your minimal_xname(obj)"
2562 * or "Foobar's minimal_xname(obj)"
2563 * or "the minimal_xname(obj)"
2569 char *outbuf = nextobuf();
2570 char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
2572 int space_left = BUFSZ - 1 - strlen(s);
2574 return strncat(s, minimal_xname(obj), space_left);
2576 int space_left = BUFSZ - strlen(s);
2578 return strncat(s, minimal_xname(obj), space_left);
2582 /* capitalized variant of ysimple_name() */
2587 char *s = ysimple_name(obj);
2595 /* "scroll" or "scrolls" */
2600 char *simpleoname = minimal_xname(obj);
2602 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2603 if (obj->quan != 1L)
2604 simpleoname = makeplural(simpleoname);
2609 /* "a scroll" or "scrolls"; "a silver bell" or "the Bell of Opening" */
2614 char *simpleoname = simpleonames(obj);
2615 int otyp = obj->otyp;
2617 /* prefix with "the" if a unique item, or a fake one imitating same,
2618 has been formatted with its actual name (we let typename() handle
2619 any `known' and `dknown' checking necessary) */
2620 if (otyp == FAKE_AMULET_OF_YENDOR)
2621 otyp = AMULET_OF_YENDOR;
2622 if (objects[otyp].oc_unique
2623 && !strcmp(simpleoname, OBJ_NAME(objects[otyp])))
2624 return the(simpleoname);
2626 /* simpleoname is singular if quan==1, plural otherwise */
2627 if (obj->quan == 1L)
2628 simpleoname = an(simpleoname);
2632 /* "the scroll" or "the scrolls" */
2637 char *simpleoname = simpleonames(obj);
2639 return the(simpleoname);
2642 /* artifact's name without any object type or known/dknown/&c feedback */
2644 bare_artifactname(obj)
2649 if (obj->oartifact) {
2650 outbuf = nextobuf();
2651 Strcpy(outbuf, artiname(obj->oartifact));
2653 if (!strncmp(outbuf, "The ", 4))
2654 outbuf[0] = lowc(outbuf[0]);
2657 outbuf = xname(obj);
2663 static const char *wrp[] = {
2664 "wand", "ring", "potion", "scroll", "gem",
2665 "amulet", "spellbook", "spell book",
2666 /* for non-specific wishes */
2667 "weapon", "armor", "tool", "food", "comestible",
2670 static const char wrpsym[] = { WAND_CLASS, RING_CLASS, POTION_CLASS,
2671 SCROLL_CLASS, GEM_CLASS, AMULET_CLASS,
2672 SPBOOK_CLASS, SPBOOK_CLASS, WEAPON_CLASS,
2673 ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
2676 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2677 /* return form of the verb (input plural) if xname(otmp) were the subject */
2686 * verb is given in plural (without trailing s). Return as input
2687 * if the result of xname(otmp) would be plural. Don't bother
2688 * recomputing xname(otmp) at this time.
2690 if (!is_plural(otmp))
2691 return vtense((char *) 0, verb);
2698 /* various singular words that vtense would otherwise categorize as plural;
2699 also used by makesingular() to catch some special cases */
2700 static const char *const special_subjs[] = {
2701 "erinys", "manes", /* this one is ambiguous */
2702 "Cyclops", "Hippocrates", "Pelias", "aklys",
2703 "amnesia", "detect monsters", "paralysis", "shape changers",
2705 /* note: "detect monsters" and "shape changers" are normally
2706 caught via "<something>(s) of <whatever>", but they can be
2707 wished for using the shorter form, so we include them here
2708 to accommodate usage by makesingular during wishing */
2711 /* return form of the verb (input plural) for present tense 3rd person subj */
2714 register const char *subj;
2715 register const char *verb;
2717 char *buf = nextobuf(), *bspot;
2719 const char *sp, *spot;
2720 const char *const *spec;
2723 * verb is given in plural (without trailing s). Return as input
2724 * if subj appears to be plural. Add special cases as necessary.
2725 * Many hard cases can already be handled by using otense() instead.
2726 * If this gets much bigger, consider decomposing makeplural.
2727 * Note: monster names are not expected here (except before corpse).
2729 * Special case: allow null sobj to get the singular 3rd person
2730 * present tense form so we don't duplicate this code elsewhere.
2733 if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
2735 spot = (const char *) 0;
2736 for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
2737 if (!strncmpi(sp, " of ", 4) || !strncmpi(sp, " from ", 6)
2738 || !strncmpi(sp, " called ", 8) || !strncmpi(sp, " named ", 7)
2739 || !strncmpi(sp, " labeled ", 9)) {
2745 len = (int) strlen(subj);
2747 spot = subj + len - 1;
2750 * plural: anything that ends in 's', but not '*us' or '*ss'.
2751 * Guess at a few other special cases that makeplural creates.
2753 if ((lowc(*spot) == 's' && spot != subj
2754 && !index("us", lowc(*(spot - 1))))
2755 || !BSTRNCMPI(subj, spot - 3, "eeth", 4)
2756 || !BSTRNCMPI(subj, spot - 3, "feet", 4)
2757 || !BSTRNCMPI(subj, spot - 1, "ia", 2)
2758 || !BSTRNCMPI(subj, spot - 1, "ae", 2)) {
2759 /* check for special cases to avoid false matches */
2760 len = (int) (spot - subj) + 1;
2761 for (spec = special_subjs; *spec; spec++) {
2762 ltmp = strlen(*spec);
2763 if (len == ltmp && !strncmpi(*spec, subj, len))
2765 /* also check for <prefix><space><special_subj>
2766 to catch things like "the invisible erinys" */
2767 if (len > ltmp && *(spot - ltmp) == ' '
2768 && !strncmpi(*spec, spot - ltmp + 1, ltmp))
2772 return strcpy(buf, verb);
2775 * 3rd person plural doesn't end in telltale 's';
2776 * 2nd person singular behaves as if plural.
2778 if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
2779 return strcpy(buf, verb);
2784 len = (int) strlen(buf);
2785 bspot = buf + len - 1;
2787 if (!strcmpi(buf, "are")) {
2788 Strcasecpy(buf, "is");
2789 } else if (!strcmpi(buf, "have")) {
2790 Strcasecpy(bspot - 1, "s");
2791 } else if (index("zxs", lowc(*bspot))
2792 || (len >= 2 && lowc(*bspot) == 'h'
2793 && index("cs", lowc(*(bspot - 1))))
2794 || (len == 2 && lowc(*bspot) == 'o')) {
2795 /* Ends in z, x, s, ch, sh; add an "es" */
2796 Strcasecpy(bspot + 1, "es");
2797 } else if (lowc(*bspot) == 'y' && !index(vowels, lowc(*(bspot - 1)))) {
2798 /* like "y" case in makeplural */
2799 Strcasecpy(bspot, "ies");
2801 Strcasecpy(bspot + 1, "s");
2810 const char *sing, *plur;
2813 /* word pairs that don't fit into formula-based transformations;
2814 also some suffices which have very few--often one--matches or
2815 which aren't systematically reversible (knives, staves) */
2816 static struct sing_plur one_off[] = {
2818 "children" }, /* (for wise guys who give their food funny names) */
2819 { "cubus", "cubi" }, /* in-/suc-cubus */
2820 { "culus", "culi" }, /* homunculus */
2821 { "djinni", "djinn" },
2822 { "erinys", "erinyes" },
2824 { "fungus", "fungi" },
2825 { "goose", "geese" },
2826 { "knife", "knives" },
2827 { "labrum", "labra" }, /* candelabrum */
2828 { "louse", "lice" },
2829 { "mouse", "mice" },
2830 { "mumak", "mumakil" },
2831 { "nemesis", "nemeses" },
2834 { "passerby", "passersby" },
2835 { "rtex", "rtices" }, /* vortex */
2836 { "serum", "sera" },
2837 { "staff", "staves" },
2838 { "tooth", "teeth" },
2842 static const char *const as_is[] = {
2843 /* makesingular() leaves these plural due to how they're used */
2844 "boots", "shoes", "gloves", "lenses", "scales",
2845 "eyes", "gauntlets", "iron bars",
2846 /* both singular and plural are spelled the same */
2847 "bison", "deer", "elk", "fish", "fowl",
2848 "tuna", "yaki", "-hai", "krill", "manes",
2849 "moose", "ninja", "sheep", "ronin", "roshi",
2850 "shito", "tengu", "ki-rin", "Nazgul", "gunyoki",
2851 "piranha", "samurai", "shuriken", 0,
2852 /* Note: "fish" and "piranha" are collective plurals, suitable
2853 for "wiped out all <foo>". For "3 <foo>", they should be
2854 "fishes" and "piranhas" instead. We settle for collective
2855 variant instead of attempting to support both. */
2858 /* singularize/pluralize decisions common to both makesingular & makeplural */
2860 singplur_lookup(basestr, endstring, to_plural, alt_as_is)
2861 char *basestr, *endstring; /* base string, pointer to eos(string) */
2862 boolean to_plural; /* true => makeplural, false => makesingular */
2863 const char *const *alt_as_is; /* another set like as_is[] */
2865 const struct sing_plur *sp;
2866 const char *same, *other, *const *as;
2868 int baselen = strlen(basestr);
2870 for (as = as_is; *as; ++as) {
2871 al = (int) strlen(*as);
2872 if (!BSTRCMPI(basestr, endstring - al, *as))
2876 for (as = alt_as_is; *as; ++as) {
2877 al = (int) strlen(*as);
2878 if (!BSTRCMPI(basestr, endstring - al, *as))
2883 /* Leave "craft" as a suffix as-is (aircraft, hovercraft);
2884 "craft" itself is (arguably) not included in our likely context */
2885 if ((baselen > 5) && (!BSTRCMPI(basestr, endstring - 5, "craft")))
2887 /* avoid false hit on one_off[].plur == "lice" or .sing == "goose";
2888 if more of these turn up, one_off[] entries will need to flagged
2889 as to which are whole words and which are matchable as suffices
2890 then matching in the loop below will end up becoming more complex */
2891 if (!strcmpi(basestr, "slice")
2892 || !strcmpi(basestr, "mongoose")) {
2894 Strcasecpy(endstring, "s");
2897 /* skip "ox" -> "oxen" entry when pluralizing "<something>ox"
2898 unless it is muskox */
2899 if (to_plural && baselen > 2 && !strcmpi(endstring - 2, "ox")
2900 && !(baselen > 5 && !strcmpi(endstring - 6, "muskox"))) {
2901 /* "fox" -> "foxes" */
2902 Strcasecpy(endstring, "es");
2906 if (baselen > 2 && !strcmpi(endstring - 3, "man")
2907 && badman(basestr, to_plural)) {
2908 Strcasecpy(endstring, "s");
2912 if (baselen > 2 && !strcmpi(endstring - 3, "men")
2913 && badman(basestr, to_plural))
2916 for (sp = one_off; sp->sing; sp++) {
2917 /* check whether endstring already matches */
2918 same = to_plural ? sp->plur : sp->sing;
2919 al = (int) strlen(same);
2920 if (!BSTRCMPI(basestr, endstring - al, same))
2921 return TRUE; /* use as-is */
2922 /* check whether it matches the inverse; if so, transform it */
2923 other = to_plural ? sp->sing : sp->plur;
2924 al = (int) strlen(other);
2925 if (!BSTRCMPI(basestr, endstring - al, other)) {
2926 Strcasecpy(endstring - al, same);
2927 return TRUE; /* one_off[] transformation */
2933 /* searches for common compounds, ex. lump of royal jelly */
2935 singplur_compound(str)
2938 /* if new entries are added, be sure to keep compound_start[] in sync */
2939 static const char *const compounds[] =
2941 " of ", " labeled ", " called ",
2942 " named ", " above", /* lurkers above */
2943 " versus ", " from ", " in ",
2944 " on ", " a la ", " with", /* " with "? */
2945 " de ", " d'", " du ",
2947 }, /* list of first characters for all compounds[] entries */
2948 compound_start[] = " -";
2950 const char *const *cmpd;
2953 for (p = str; *p; ++p) {
2954 /* substring starting at p can only match if *p is found
2955 within compound_start[] */
2956 if (!index(compound_start, *p))
2959 /* check current substring against all words in the compound[] list */
2960 for (cmpd = compounds; *cmpd; ++cmpd)
2961 if (!strncmpi(p, *cmpd, (int) strlen(*cmpd)))
2964 /* wasn't recognized as a compound phrase */
2969 /* Plural routine; once upon a time it may have been chiefly used for
2970 * user-defined fruits, but it is now used extensively throughout the
2973 * For fruit, we have to try to account for everything reasonable the
2974 * player has; something unreasonable can still break the code.
2975 * However, it's still a lot more accurate than "just add an 's' at the
2976 * end", which Rogue uses...
2978 * Also used for plural monster names ("Wiped out all homunculi." or the
2979 * vanquished monsters list) and body parts. A lot of unique monsters have
2980 * names which get mangled by makeplural and/or makesingular. They're not
2981 * genocidable, and vanquished-mon handling does its own special casing
2982 * (for uniques who've been revived and re-killed), so we don't bother
2983 * trying to get those right here.
2985 * Also misused by muse.c to convert 1st person present verbs to 2nd person.
2986 * 3.6.0: made case-insensitive.
2992 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2993 register char *spot;
2994 char lo_c, *str = nextobuf();
2995 const char *excess = (char *) 0;
2999 while (*oldstr == ' ')
3001 if (!oldstr || !*oldstr) {
3002 impossible("plural of null?");
3006 Strcpy(str, oldstr);
3009 * Skip changing "pair of" to "pairs of". According to Webster, usual
3010 * English usage is use pairs for humans, e.g. 3 pairs of dancers,
3011 * and pair for objects and non-humans, e.g. 3 pair of boots. We don't
3012 * refer to pairs of humans in this game so just skip to the bottom.
3014 if (!strncmpi(str, "pair of ", 8))
3017 /* look for "foo of bar" so that we can focus on "foo" */
3018 if ((spot = singplur_compound(str)) != 0) {
3019 excess = oldstr + (int) (spot - str);
3025 while (spot > str && *spot == ' ')
3026 spot--; /* Strip blanks from end */
3028 /* Now spot is the last character of the string */
3032 /* Single letters */
3033 if (len == 1 || !letter(*spot)) {
3034 Strcpy(spot + 1, "'s");
3038 /* dispense with some words which don't need pluralization */
3040 static const char *const already_plural[] = {
3041 "ae", /* algae, larvae, &c */
3045 /* spot+1: synch up with makesingular's usage */
3046 if (singplur_lookup(str, spot + 1, TRUE, already_plural))
3049 /* more of same, but not suitable for blanket loop checking */
3050 if ((len == 2 && !strcmpi(str, "ya"))
3051 || (len >= 3 && !strcmpi(spot - 2, " ya")))
3055 /* man/men ("Wiped out all cavemen.") */
3056 if (len >= 3 && !strcmpi(spot - 2, "man")
3057 /* exclude shamans and humans etc */
3058 && !badman(str, TRUE)) {
3059 Strcasecpy(spot - 1, "en");
3062 if (lowc(*spot) == 'f') { /* (staff handled via one_off[]) */
3063 lo_c = lowc(*(spot - 1));
3064 if (len >= 3 && !strcmpi(spot - 2, "erf")) {
3065 /* avoid "nerf" -> "nerves", "serf" -> "serves" */
3066 ; /* fall through to default (append 's') */
3067 } else if (index("lr", lo_c) || index(vowels, lo_c)) {
3068 /* [aeioulr]f to [aeioulr]ves */
3069 Strcasecpy(spot, "ves");
3073 /* ium/ia (mycelia, baluchitheria) */
3074 if (len >= 3 && !strcmpi(spot - 2, "ium")) {
3075 Strcasecpy(spot - 2, "ia");
3078 /* algae, larvae, hyphae (another fungus part) */
3079 if ((len >= 4 && !strcmpi(spot - 3, "alga"))
3081 && (!strcmpi(spot - 4, "hypha") || !strcmpi(spot - 4, "larva")))
3082 || (len >= 6 && !strcmpi(spot - 5, "amoeba"))
3083 || (len >= 8 && (!strcmpi(spot - 7, "vertebra")))) {
3085 Strcasecpy(spot + 1, "e");
3088 /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
3089 if (len > 3 && !strcmpi(spot - 1, "us")
3090 && !((len >= 5 && !strcmpi(spot - 4, "lotus"))
3091 || (len >= 6 && !strcmpi(spot - 5, "wumpus")))) {
3092 Strcasecpy(spot - 1, "i");
3095 /* sis/ses (nemesis) */
3096 if (len >= 3 && !strcmpi(spot - 2, "sis")) {
3097 Strcasecpy(spot - 1, "es");
3100 /* matzoh/matzot, possible food name */
3102 && (!strcmpi(spot - 5, "matzoh") || !strcmpi(spot - 5, "matzah"))) {
3103 Strcasecpy(spot - 1, "ot"); /* oh/ah -> ot */
3107 && (!strcmpi(spot - 4, "matzo") || !strcmpi(spot - 4, "matza"))) {
3108 Strcasecpy(spot, "ot"); /* o/a -> ot */
3112 /* note: -eau/-eaux (gateau, bordeau...) */
3113 /* note: ox/oxen, VAX/VAXen, goose/geese */
3117 /* codex/spadix/neocortex and the like */
3119 && (!strcmpi(spot - 2, "dex")
3120 ||!strcmpi(spot - 2, "dix")
3121 ||!strcmpi(spot - 2, "tex"))
3122 /* indices would have been ok too, but stick with indexes */
3123 && (strcmpi(spot - 4,"index") != 0)) {
3124 Strcasecpy(spot - 1, "ices"); /* ex|ix -> ices */
3127 /* Ends in z, x, s, ch, sh; add an "es" */
3128 if (index("zxs", lo_c)
3129 || (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot - 1)))
3130 /* 21st century k-sound */
3132 ((lowc(*(spot - 2)) == 'e'
3133 && index("mt", lowc(*(spot - 3)))) ||
3134 (lowc(*(spot - 2)) == 'o'
3135 && index("lp", lowc(*(spot - 3)))))))
3136 /* Kludge to get "tomatoes" and "potatoes" right */
3137 || (len >= 4 && !strcmpi(spot - 2, "ato"))
3138 || (len >= 5 && !strcmpi(spot - 4, "dingo"))) {
3139 Strcasecpy(spot + 1, "es"); /* append es */
3142 /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
3143 if (lo_c == 'y' && !index(vowels, lowc(*(spot - 1)))) {
3144 Strcasecpy(spot, "ies"); /* y -> ies */
3147 /* Default: append an 's' */
3148 Strcasecpy(spot + 1, "s");
3152 Strcat(str, excess);
3153 #else /*JP*//*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
3154 char *str = nextobuf();
3155 Strcpy(str, oldstr);
3161 * Singularize a string the user typed in; this helps reduce the complexity
3162 * of readobjnam, and is also used in pager.c to singularize the string
3163 * for which help is sought.
3165 * "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)?
3166 * Its inclusion in as_is[]/special_subj[] makes it get treated as the former.
3168 * A lot of unique monsters have names ending in s; plural, or singular
3169 * from plural, doesn't make much sense for them so we don't bother trying.
3170 * 3.6.0: made case-insensitive.
3173 makesingular(oldstr)
3176 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
3177 register char *p, *bp;
3178 const char *excess = 0;
3179 char *str = nextobuf();
3182 while (*oldstr == ' ')
3184 if (!oldstr || !*oldstr) {
3185 impossible("singular of null?");
3190 bp = strcpy(str, oldstr);
3192 /* check for "foo of bar" so that we can focus on "foo" */
3193 if ((p = singplur_compound(bp)) != 0) {
3194 excess = oldstr + (int) (p - bp);
3199 /* dispense with some words which don't need singularization */
3200 if (singplur_lookup(bp, p, FALSE, special_subjs))
3203 /* remove -s or -es (boxes) or -ies (rubies) */
3204 if (p >= bp + 1 && lowc(p[-1]) == 's') {
3205 if (p >= bp + 2 && lowc(p[-2]) == 'e') {
3206 if (p >= bp + 3 && lowc(p[-3]) == 'i') { /* "ies" */
3207 if (!BSTRCMPI(bp, p - 7, "cookies")
3208 || (!BSTRCMPI(bp, p - 4, "pies")
3209 /* avoid false match for "harpies" */
3210 && (p - 4 == bp || p[-5] == ' '))
3211 /* alternate djinni/djinn spelling; not really needed */
3212 || (!BSTRCMPI(bp, p - 6, "genies")
3213 /* avoid false match for "progenies" */
3214 && (p - 6 == bp || p[-7] == ' '))
3215 || !BSTRCMPI(bp, p - 5, "mbies") /* zombie */
3216 || !BSTRCMPI(bp, p - 5, "yries")) /* valkyrie */
3218 Strcasecpy(p - 3, "y"); /* ies -> y */
3221 /* wolves, but f to ves isn't fully reversible */
3222 if (p - 4 >= bp && (index("lr", lowc(*(p - 4)))
3223 || index(vowels, lowc(*(p - 4))))
3224 && !BSTRCMPI(bp, p - 3, "ves")) {
3225 if (!BSTRCMPI(bp, p - 6, "cloves")
3226 || !BSTRCMPI(bp, p - 6, "nerves"))
3228 Strcasecpy(p - 3, "f"); /* ves -> f */
3231 /* note: nurses, axes but boxes, wumpuses */
3232 if (!BSTRCMPI(bp, p - 4, "eses")
3233 || !BSTRCMPI(bp, p - 4, "oxes") /* boxes, foxes */
3234 || !BSTRCMPI(bp, p - 4, "nxes") /* lynxes */
3235 || !BSTRCMPI(bp, p - 4, "ches")
3236 || !BSTRCMPI(bp, p - 4, "uses") /* lotuses */
3237 || !BSTRCMPI(bp, p - 4, "sses") /* priestesses */
3238 || !BSTRCMPI(bp, p - 5, "atoes") /* tomatoes */
3239 || !BSTRCMPI(bp, p - 7, "dingoes")
3240 || !BSTRCMPI(bp, p - 7, "Aleaxes")) {
3241 *(p - 2) = '\0'; /* drop es */
3243 } /* else fall through to mins */
3245 /* ends in 's' but not 'es' */
3246 } else if (!BSTRCMPI(bp, p - 2, "us")) { /* lotus, fungus... */
3247 if (BSTRCMPI(bp, p - 6, "tengus") /* but not these... */
3248 && BSTRCMPI(bp, p - 7, "hezrous"))
3250 } else if (!BSTRCMPI(bp, p - 2, "ss")
3251 || !BSTRCMPI(bp, p - 5, " lens")
3252 || (p - 4 == bp && !strcmpi(p - 4, "lens"))) {
3256 *(p - 1) = '\0'; /* drop s */
3258 } else { /* input doesn't end in 's' */
3260 if (!BSTRCMPI(bp, p - 3, "men")
3261 && !badman(bp, FALSE)) {
3262 Strcasecpy(p - 2, "an");
3265 /* matzot -> matzo, algae -> alga */
3266 if (!BSTRCMPI(bp, p - 6, "matzot") || !BSTRCMPI(bp, p - 2, "ae")) {
3267 *(p - 1) = '\0'; /* drop t/e */
3270 /* balactheria -> balactherium */
3271 if (p - 4 >= bp && !strcmpi(p - 2, "ia")
3272 && index("lr", lowc(*(p - 3))) && lowc(*(p - 4)) == 'e') {
3273 Strcasecpy(p - 1, "um"); /* a -> um */
3276 /* here we cannot find the plural suffix */
3280 /* if we stripped off a suffix (" of bar" from "foo of bar"),
3281 put it back now [strcat() isn't actually 100% safe here...] */
3286 #else /*JP*//*
\90V
\82µ
\82¢
\83o
\83b
\83t
\83@
\82Í
\95K
\97v*/
3287 char *str = nextobuf();
3288 Strcpy(str, oldstr);
3295 badman(basestr, to_plural)
3296 const char *basestr;
3297 boolean to_plural; /* true => makeplural, false => makesingular */
3299 /* these are all the prefixes for *man that don't have a *men plural */
3300 static const char *no_men[] = {
3301 "albu", "antihu", "anti", "ata", "auto", "bildungsro", "cai", "cay",
3302 "ceru", "corner", "decu", "des", "dura", "fir", "hanu", "het",
3303 "infrahu", "inhu", "nonhu", "otto", "out", "prehu", "protohu",
3304 "subhu", "superhu", "talis", "unhu", "sha",
3305 "hu", "un", "le", "re", "so", "to", "at", "a",
3307 /* these are all the prefixes for *men that don't have a *man singular */
3308 static const char *no_man[] = {
3309 "abdo", "acu", "agno", "ceru", "cogno", "cycla", "fleh", "grava",
3310 "hegu", "preno", "sonar", "speci", "dai", "exa", "fla", "sta", "teg",
3311 "tegu", "vela", "da", "hy", "lu", "no", "nu", "ra", "ru", "se", "vi",
3315 const char *endstr, *spot;
3317 if (!basestr || strlen(basestr) < 4)
3320 endstr = eos((char *) basestr);
3323 for (i = 0; i < SIZE(no_men); i++) {
3324 al = (int) strlen(no_men[i]);
3325 spot = endstr - (al + 3);
3326 if (!BSTRNCMPI(basestr, spot, no_men[i], al)
3327 && (spot == basestr || *(spot - 1) == ' '))
3331 for (i = 0; i < SIZE(no_man); i++) {
3332 al = (int) strlen(no_man[i]);
3333 spot = endstr - (al + 3);
3334 if (!BSTRNCMPI(basestr, spot, no_man[i], al)
3335 && (spot == basestr || *(spot - 1) == ' '))
3343 /* compare user string against object name string using fuzzy matching */
3345 wishymatch(u_str, o_str, retry_inverted)
3346 const char *u_str; /* from user, so might be variant spelling */
3347 const char *o_str; /* from objects[], so is in canonical form */
3348 boolean retry_inverted; /* optional extra "of" handling */
3350 static NEARDATA const char detect_SP[] = "detect ",
3351 SP_detection[] = " detection";
3352 char *p, buf[BUFSZ];
3354 /* ignore spaces & hyphens and upper/lower case when comparing */
3355 if (fuzzymatch(u_str, o_str, " -", TRUE))
3358 if (retry_inverted) {
3359 const char *u_of, *o_of;
3361 /* when just one of the strings is in the form "foo of bar",
3362 convert it into "bar foo" and perform another comparison */
3363 u_of = strstri(u_str, " of ");
3364 o_of = strstri(o_str, " of ");
3365 if (u_of && !o_of) {
3366 Strcpy(buf, u_of + 4);
3367 p = eos(strcat(buf, " "));
3368 while (u_str < u_of)
3371 return fuzzymatch(buf, o_str, " -", TRUE);
3372 } else if (o_of && !u_of) {
3373 Strcpy(buf, o_of + 4);
3374 p = eos(strcat(buf, " "));
3375 while (o_str < o_of)
3378 return fuzzymatch(u_str, buf, " -", TRUE);
3382 /* [note: if something like "elven speed boots" ever gets added, these
3383 special cases should be changed to call wishymatch() recursively in
3384 order to get the "of" inversion handling] */
3385 if (!strncmp(o_str, "dwarvish ", 9)) {
3386 if (!strncmpi(u_str, "dwarven ", 8))
3387 return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
3388 } else if (!strncmp(o_str, "elven ", 6)) {
3389 if (!strncmpi(u_str, "elvish ", 7))
3390 return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
3391 else if (!strncmpi(u_str, "elfin ", 6))
3392 return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
3393 } else if (!strncmp(o_str, detect_SP, sizeof detect_SP - 1)) {
3394 /* check for "detect <foo>" vs "<foo> detection" */
3395 if ((p = strstri(u_str, SP_detection)) != 0
3396 && !*(p + sizeof SP_detection - 1)) {
3397 /* convert "<foo> detection" into "detect <foo>" */
3399 Strcat(strcpy(buf, detect_SP), u_str);
3400 /* "detect monster" -> "detect monsters" */
3401 if (!strcmpi(u_str, "monster"))
3404 return fuzzymatch(buf, o_str, " -", TRUE);
3406 } else if (strstri(o_str, SP_detection)) {
3407 /* and the inverse, "<foo> detection" vs "detect <foo>" */
3408 if (!strncmpi(u_str, detect_SP, sizeof detect_SP - 1)) {
3409 /* convert "detect <foo>s" into "<foo> detection" */
3410 p = makesingular(u_str + sizeof detect_SP - 1);
3411 Strcat(strcpy(buf, p), SP_detection);
3412 /* caller may be looping through objects[], so avoid
3413 churning through all the obufs */
3415 return fuzzymatch(buf, o_str, " -", TRUE);
3417 } else if (strstri(o_str, "ability")) {
3418 /* when presented with "foo of bar", makesingular() used to
3419 singularize both foo & bar, but now only does so for foo */
3420 /* catch "{potion(s),ring} of {gain,restore,sustain} abilities" */
3421 if ((p = strstri(u_str, "abilities")) != 0
3422 && !*(p + sizeof "abilities" - 1)) {
3423 (void) strncpy(buf, u_str, (unsigned) (p - u_str));
3424 Strcpy(buf + (p - u_str), "ability");
3425 return fuzzymatch(buf, o_str, " -", TRUE);
3427 } else if (!strcmp(o_str, "aluminum")) {
3428 /* this special case doesn't really fit anywhere else... */
3429 /* (note that " wand" will have been stripped off by now) */
3430 if (!strcmpi(u_str, "aluminium"))
3431 return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
3438 const char *name, oclass;
3439 int f_o_range, l_o_range;
3442 #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¢*/
3443 /* wishable subranges of objects */
3444 STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
3445 { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
3446 { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
3447 { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
3448 { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
3449 { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
3450 { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
3451 { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
3452 { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3453 { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3454 { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
3455 { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
3456 { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
3457 { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
3458 { "dragon scales", ARMOR_CLASS, GRAY_DRAGON_SCALES,
3459 YELLOW_DRAGON_SCALES },
3460 { "dragon scale mail", ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL,
3461 YELLOW_DRAGON_SCALE_MAIL },
3462 { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
3463 { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
3464 { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
3465 { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
3470 #if 0 /*JP*//*not used*/
3471 /* alternate spellings; if the difference is only the presence or
3472 absence of spaces and/or hyphens (such as "pickaxe" vs "pick axe"
3473 vs "pick-axe") then there is no need for inclusion in this list;
3474 likewise for ``"of" inversions'' ("boots of speed" vs "speed boots") */
3475 static const struct alt_spellings {
3479 { "pickax", PICK_AXE },
3480 { "whip", BULLWHIP },
3481 { "saber", SILVER_SABER },
3482 { "silver sabre", SILVER_SABER },
3483 { "smooth shield", SHIELD_OF_REFLECTION },
3484 { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
3485 { "grey dragon scales", GRAY_DRAGON_SCALES },
3486 { "iron ball", HEAVY_IRON_BALL },
3487 { "lantern", BRASS_LANTERN },
3488 { "mattock", DWARVISH_MATTOCK },
3489 { "amulet of poison resistance", AMULET_VERSUS_POISON },
3490 { "potion of sleep", POT_SLEEPING },
3492 { "camera", EXPENSIVE_CAMERA },
3493 { "tee shirt", T_SHIRT },
3495 { "can opener", TIN_OPENER },
3496 { "kelp", KELP_FROND },
3497 { "eucalyptus", EUCALYPTUS_LEAF },
3498 { "royal jelly", LUMP_OF_ROYAL_JELLY },
3499 { "lembas", LEMBAS_WAFER },
3500 { "cookie", FORTUNE_COOKIE },
3501 { "pie", CREAM_PIE },
3502 { "marker", MAGIC_MARKER },
3503 { "hook", GRAPPLING_HOOK },
3504 { "grappling iron", GRAPPLING_HOOK },
3505 { "grapnel", GRAPPLING_HOOK },
3506 { "grapple", GRAPPLING_HOOK },
3507 { "protection from shape shifters", RIN_PROTECTION_FROM_SHAPE_CHAN },
3508 /* if we ever add other sizes, move this to o_ranges[] with "bag" */
3509 { "box", LARGE_BOX },
3510 /* normally we wouldn't have to worry about unnecessary <space>, but
3511 " stone" will get stripped off, preventing a wishymatch; that actually
3512 lets "flint stone" be a match, so we also accept bogus "flintstone" */
3513 { "luck stone", LUCKSTONE },
3514 { "load stone", LOADSTONE },
3515 { "touch stone", TOUCHSTONE },
3516 { "flintstone", FLINT },
3517 { (const char *) 0, 0 },
3521 rnd_otyp_by_wpnskill(skill)
3525 short otyp = STRANGE_OBJECT;
3527 for (i = bases[WEAPON_CLASS];
3528 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3529 if (objects[i].oc_skill == skill) {
3535 for (i = bases[WEAPON_CLASS];
3536 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3537 if (objects[i].oc_skill == skill)
3546 rnd_otyp_by_namedesc(name, oclass, xtra_prob)
3549 int xtra_prob; /* to force 0% random generation items to also be considered */
3552 short validobjs[NUM_OBJECTS];
3553 register const char *zn;
3554 int prob, maxprob = 0;
3556 if (!name || !*name)
3557 return STRANGE_OBJECT;
3559 memset((genericptr_t) validobjs, 0, sizeof validobjs);
3562 * When this spans classes (the !oclass case), the item
3563 * probabilities are not very useful because they don't take
3564 * the class generation probability into account. [If 10%
3565 * of spellbooks were blank and 1% of scrolls were blank,
3566 * "blank" would have 10/11 chance to yield a book even though
3567 * scrolls are supposed to be much more common than books.]
3569 for (i = oclass ? bases[(int) oclass] : STRANGE_OBJECT + 1;
3570 i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
3572 /* don't match extra descriptions (w/o real name) */
3573 if ((zn = OBJ_NAME(objects[i])) == 0)
3577 *
\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É
3578 *
\82È
\82ç
\82È
\82¢
\82æ
\82¤
\82É
\82·
\82é
\81B
3579 *
\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
3581 if (i == FAKE_AMULET_OF_YENDOR)
3584 if (wishymatch(name, zn, TRUE)
3585 || ((zn = OBJ_DESCR(objects[i])) != 0
3586 && wishymatch(name, zn, FALSE))
3587 || ((zn = objects[i].oc_uname) != 0
3588 && wishymatch(name, zn, FALSE))) {
3589 validobjs[n++] = (short) i;
3590 maxprob += (objects[i].oc_prob + xtra_prob);
3594 if (n > 0 && maxprob) {
3595 prob = rn2(maxprob);
3596 for (i = 0; i < n - 1; i++)
3597 if ((prob -= (objects[validobjs[i]].oc_prob + xtra_prob)) < 0)
3599 return validobjs[i];
3601 return STRANGE_OBJECT;
3608 return (int) rnd_otyp_by_namedesc("shiny", oclass, 0);
3612 * Return something wished for. Specifying a null pointer for
3613 * the user request string results in a random object. Otherwise,
3614 * if asking explicitly for "nothing" (or "nil") return no_wish;
3615 * if not an object return &zeroobj; if an error (no matching object),
3620 readobjnam(bp, no_wish)
3622 struct obj *no_wish;
3626 register struct obj *otmp;
3627 int cnt, spe, spesgn, typ, very, rechrg;
3628 int blessed, uncursed, iscursed, ispoisoned, isgreased;
3629 int eroded, eroded2, erodeproof, locked, unlocked, broken;
3630 int halfeaten, mntmp, contents;
3631 int islit, unlabeled, ishistoric, isdiluted, trapped;
3633 int tmp, tinv, tvariety;
3637 int wetness, gsize = 0;
3639 int ftype = context.current_fruit;
3641 char fruitbuf[BUFSZ], globbuf[BUFSZ];
3643 char fruitbuf[BUFSZ];
3645 /* Fruits may not mess up the ability to wish for real objects (since
3646 * you can leave a fruit in a bones file and it will be added to
3647 * another person's game), so they must be checked for last, after
3648 * stripping all the possible prefixes and seeing if there's a real
3649 * name in there. So we have to save the full original name. However,
3650 * it's still possible to do things like "uncursed burnt Alaska",
3651 * or worse yet, "2 burned 5 course meals", so we need to loop to
3652 * strip off the prefixes again, this time stripping only the ones
3654 * We could get even more detailed so as to allow food names with
3655 * prefixes that _are_ possible on food, so you could wish for
3656 * "2 3 alarm chilis". Currently this isn't allowed; options.c
3657 * automatically sticks 'candied' in front of such names.
3660 char *un, *dn, *actualn, *origbp = bp;
3661 const char *name = 0;
3663 cnt = spe = spesgn = typ = 0;
3664 very = rechrg = blessed = uncursed = iscursed = ispoisoned =
3665 isgreased = eroded = eroded2 = erodeproof = halfeaten =
3666 islit = unlabeled = ishistoric = isdiluted = trapped =
3667 locked = unlocked = broken = 0;
3668 tvariety = RANDOM_TIN;
3673 contents = UNDEFINED;
3675 actualn = dn = un = 0;
3680 /* first, remove extra whitespace they may have typed */
3681 (void) mungspaces(bp);
3682 /* allow wishing for "nothing" to preserve wishless conduct...
3683 [now requires "wand of nothing" if that's what was really wanted] */
3685 if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil")
3686 || !strcmpi(bp, "none"))
3688 if (!strcmpi(bp, "
\82È
\82µ") || !strcmpi(bp, "
\96³
\82µ"))
3691 /* save the [nearly] unmodified choice string */
3692 Strcpy(fruitbuf, bp);
3699 if (!strncmpi(bp, "an ", l = 3) || !strncmpi(bp, "a ", l = 2)) {
3701 } else if (!strncmpi(bp, "the ", l = 4)) {
3702 ; /* just increment `bp' by `l' below */
3703 } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
3710 #if 1 /*JP*//*
\8cã
\82É
\90\94\8e\8c\82ª
\82 \82é
\82Æ
\82«
\82Í
\8dí
\8f\9c */
3711 if(!STRNCMPEX(bp, "
\8dû
\82Ì") ||
3712 !STRNCMPEX(bp, "
\96{
\82Ì") ||
3713 !STRNCMPEX(bp, "
\92\85\82Ì") ||
3714 !STRNCMPEX(bp, "
\8cÂ
\82Ì") ||
3715 !STRNCMPEX(bp, "
\96\87\82Ì") ||
3716 !STRNCMPEX(bp, "
\82Â
\82Ì") ||
3717 !STRNCMPEX(bp, "
\82Ì"))
3722 } else if (*bp == '+' || *bp == '-') {
3723 spesgn = (*bp++ == '+') ? 1 : -1;
3731 } else if (!strncmpi(bp, "blessed ", l = 8)
3732 || !strncmpi(bp, "holy ", l = 5)) {
3734 } else if (!STRNCMPEX(bp, "
\8fj
\95\9f\82³
\82ê
\82½")) {
3738 } else if (!strncmpi(bp, "moist ", l = 6)
3739 || !strncmpi(bp, "wet ", l = 4)) {
3741 } else if (!STRNCMPEX(bp, "
\8e¼
\82Á
\82½")
3742 || !STRNCMPEX(bp, "
\94G
\82ê
\82½")) {
3745 if (!strncmpi(bp, "wet ", 4))
3747 if (!STRNCMP2(bp, "
\94G
\82ê
\82½"))
3749 wetness = rn2(3) + 3;
3753 } else if (!strncmpi(bp, "cursed ", l = 7)
3754 || !strncmpi(bp, "unholy ", l = 7)) {
3756 } else if (!STRNCMPEX(bp, "
\8eô
\82í
\82ê
\82½")) {
3760 } else if (!strncmpi(bp, "uncursed ", l = 9)) {
3762 } else if (!STRNCMPEX(bp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢")) {
3766 } else if (!strncmpi(bp, "rustproof ", l = 10)
3767 || !strncmpi(bp, "erodeproof ", l = 11)
3768 || !strncmpi(bp, "corrodeproof ", l = 13)
3769 || !strncmpi(bp, "fixed ", l = 6)
3770 || !strncmpi(bp, "fireproof ", l = 10)
3771 || !strncmpi(bp, "rotproof ", l = 9)) {
3773 } else if (!STRNCMPEX(bp, "
\8eK
\82Ñ
\82È
\82¢")
3774 || !STRNCMPEX(bp, "
\95\85\90H
\82µ
\82È
\82¢")
3775 || !STRNCMPEX(bp, "
\88À
\92è
\82µ
\82½")
3776 || !STRNCMPEX(bp, "
\94R
\82¦
\82È
\82¢")) {
3780 } else if (!strncmpi(bp, "lit ", l = 4)
3781 || !strncmpi(bp, "burning ", l = 8)) {
3783 } else if (!STRNCMPEX(bp, "
\8cõ
\82Á
\82Ä
\82¢
\82é")
3784 || !STRNCMPEX(bp, "
\94R
\82¦
\82Ä
\82¢
\82é")) {
3788 } else if (!strncmpi(bp, "unlit ", l = 6)
3789 || !strncmpi(bp, "extinguished ", l = 13)) {
3791 } else if (!STRNCMPEX(bp, "
\8fÁ
\82¦
\82Ä
\82¢
\82é")) {
3794 /* "unlabeled" and "blank" are synonymous */
3796 } else if (!strncmpi(bp, "unlabeled ", l = 10)
3797 || !strncmpi(bp, "unlabelled ", l = 11)
3798 || !strncmpi(bp, "blank ", l = 6)) {
3800 } else if (!STRNCMPEX(bp, "
\83\89\83x
\83\8b\82Ì
\82È
\82¢")
3801 || !STRNCMPEX(bp, "
\90^
\82Á
\94\92\82È")) {
3805 } else if (!strncmpi(bp, "poisoned ", l = 9)) {
3807 } else if (!STRNCMPEX(bp, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½")) {
3810 /* "trapped" recognized but not honored outside wizard mode */
3811 } else if (!strncmpi(bp, "trapped ", l = 8)) {
3812 trapped = 0; /* undo any previous "untrapped" */
3815 } else if (!strncmpi(bp, "untrapped ", l = 10)) {
3816 trapped = 2; /* not trapped */
3817 /* locked, unlocked, broken: box/chest lock states */
3819 } else if (!strncmpi(bp, "locked ", l = 7)) {
3821 } else if (!STRNCMPEX(bp, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82½")) {
3823 locked = 1, unlocked = broken = 0;
3825 } else if (!strncmpi(bp, "unlocked ", l = 9)) {
3827 } else if (!STRNCMPEX(bp, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82Ä
\82¢
\82È
\82¢")) {
3829 unlocked = 1, locked = broken = 0;
3831 } else if (!strncmpi(bp, "broken ", l = 7)) {
3833 } else if (!STRNCMPEX(bp, "
\8c®
\82Ì
\89ó
\82ê
\82½")) {
3835 broken = 1, locked = unlocked = 0;
3837 } else if (!strncmpi(bp, "greased ", l = 8)) {
3839 } else if (!STRNCMPEX(bp, "
\96û
\82Ì
\93h
\82ç
\82ê
\82½")
3840 || !STRNCMPEX(bp, "
\8e\89\82Ì
\93h
\82ç
\82ê
\82½")) {
3844 } else if (!strncmpi(bp, "very ", l = 5)) {
3846 } else if (!STRNCMPEX(bp, "
\82Æ
\82Ä
\82à")) {
3848 /* very rusted very heavy iron ball */
3851 } else if (!strncmpi(bp, "thoroughly ", l = 11)) {
3853 } else if (!STRNCMPEX(bp, "
\82©
\82È
\82è")) {
3857 } else if (!strncmpi(bp, "rusty ", l = 6)
3858 || !strncmpi(bp, "rusted ", l = 7)
3859 || !strncmpi(bp, "burnt ", l = 6)
3860 || !strncmpi(bp, "burned ", l = 7)) {
3862 } else if (!STRNCMPEX(bp, "
\8eK
\82Ñ
\82½")
3863 || !STRNCMPEX(bp, "
\94R
\82¦
\82½")) {
3868 } else if (!strncmpi(bp, "corroded ", l = 9)
3869 || !strncmpi(bp, "rotted ", l = 7)) {
3871 } else if (!STRNCMPEX(bp, "
\95\85\90H
\82µ
\82½")
3872 || !STRNCMPEX(bp, "
\95\85\82Á
\82½")) {
3877 } else if (!strncmpi(bp, "partly eaten ", l = 13)
3878 || !strncmpi(bp, "partially eaten ", l = 16)) {
3880 } else if (!STRNCMPEX(bp, "
\90H
\82×
\82©
\82¯
\82Ì")) {
3884 } else if (!strncmpi(bp, "historic ", l = 9)) {
3886 } else if (!STRNCMPEX(bp, "
\97ð
\8ej
\93I
\82È")) {
3890 } else if (!strncmpi(bp, "diluted ", l = 8)) {
3892 } else if (!STRNCMPEX(bp, "
\94\96\82Ü
\82Á
\82½")) {
3896 } else if (!strncmpi(bp, "empty ", l = 6)) {
3898 } else if (!STRNCMPEX(bp, "
\8bó
\82Á
\82Û
\82Ì")) {
3902 } else if (!strncmpi(bp, "small ", l = 6)) { /* glob sizes */
3904 } else if (!STRNCMPEX(bp, "
\8f¬
\82³
\82¢")) { /* glob sizes */
3906 /* "small" might be part of monster name (mimic, if wishing
3907 for its corpse) rather than prefix for glob size; when
3908 used for globs, it might be either "small glob of <foo>" or
3909 "small <foo> glob" and user might add 's' even though plural
3910 doesn't accomplish anything because globs don't stack */
3911 if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
3915 } else if (!strncmpi(bp, "medium ", l = 7)) {
3917 } else if (!STRNCMPEX(bp, "
\92\86\82
\82ç
\82¢
\82Ì")) {
3919 /* xname() doesn't display "medium" but without this
3920 there'd be no way to ask for the intermediate size
3921 ("glob" without size prefix yields smallest one) */
3924 } else if (!strncmpi(bp, "large ", l = 6)) {
3926 } else if (!STRNCMPEX(bp, "
\91å
\82«
\82¢")) {
3928 /* "large" might be part of monster name (dog, cat, koboold,
3929 mimic) or object name (box, round shield) rather than
3930 prefix for glob size */
3931 if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
3933 /* "very large " had "very " peeled off on previous iteration */
3934 gsize = (very != 1) ? 3 : 4;
3940 cnt = 1; /* will be changed to 2 if makesingular() changes string */
3941 if (strlen(bp) > 1 && (p = rindex(bp, '(')) != 0) {
3942 boolean keeptrailingchars = TRUE;
3944 p[(p > bp && p[-1] == ' ') ? -1 : 0] = '\0'; /*terminate bp */
3945 ++p; /* advance past '(' */
3946 if (!strncmpi(p, "lit)", 4)) {
3948 p += 4 - 1; /* point at ')' */
3962 /* mis-matched parentheses; rest of string will be ignored
3963 * [probably we should restore everything back to '('
3964 * instead since it might be part of "named ..."]
3966 keeptrailingchars = FALSE;
3971 if (keeptrailingchars) {
3974 /* 'pp' points at 'pb's terminating '\0',
3975 'p' points at ')' and will be incremented past it */
3982 * otmp->spe is type schar, so we don't want spe to be any bigger or
3983 * smaller. Also, spe should always be positive --some cheaters may
3984 * try to confuse atoi().
3987 spesgn = -1; /* cheaters get what they deserve */
3990 if (spe > SCHAR_LIM)
3992 if (rechrg < 0 || rechrg > 7)
3993 rechrg = 7; /* recharge_limit */
3995 /* now we have the actual name, as delivered by xname, say
3996 * green potions called whisky
3997 * scrolls labeled "QWERTY"
4000 * very heavy iron ball named hoei
4004 if ((p = strstri(bp, " named ")) != 0) {
4006 /* note: if 'name' is too long, oname() will truncate it */
4009 if ((p = strstri(bp, " called ")) != 0) {
4011 /* note: if 'un' is too long, obj lookup just won't match anything */
4013 #if 0 /*JP*//*
\83^
\83C
\83v
\95Ê
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢*/
4014 /* "helmet called telepathy" is not "helmet" (a specific type)
4015 * "shield called reflection" is not "shield" (a general type)
4017 for (i = 0; i < SIZE(o_ranges); i++)
4018 if (!strcmpi(bp, o_ranges[i].name)) {
4019 oclass = o_ranges[i].oclass;
4024 if ((p = strstri(bp, " labeled ")) != 0) {
4027 } else if ((p = strstri(bp, " labelled ")) != 0) {
4031 if ((p = strstri(bp, " of spinach")) != 0) {
4036 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8f\88\97\9d\82µ
\82È
\82¢*/
4038 * Skip over "pair of ", "pairs of", "set of" and "sets of".
4040 * Accept "3 pair of boots" as well as "3 pairs of boots". It is
4041 * valid English either way. See makeplural() for more on pair/pairs.
4043 * We should only double count if the object in question is not
4044 * referred to as a "pair of". E.g. We should double if the player
4045 * types "pair of spears", but not if the player types "pair of
4046 * lenses". Luckily (?) all objects that are referred to as pairs
4047 * -- boots, gloves, and lenses -- are also not mergable, so cnt is
4050 if (!strncmpi(bp, "pair of ", 8)) {
4053 } else if (!strncmpi(bp, "pairs of ", 9)) {
4057 } else if (!strncmpi(bp, "set of ", 7)) {
4059 } else if (!strncmpi(bp, "sets of ", 8)) {
4065 /* intercept pudding globs here; they're a valid wish target,
4066 * but we need them to not get treated like a corpse.
4068 * also don't let player wish for multiple globs.
4070 i = (int) strlen(bp);
4072 /* check for "glob", "<foo> glob", and "glob of <foo>" */
4073 if (!strcmpi(bp, "glob") || !BSTRCMPI(bp, bp + i - 5, " glob")
4074 || !strcmpi(bp, "globs") || !BSTRCMPI(bp, bp + i - 6, " globs")
4075 || (p = strstri(bp, "glob of ")) != 0
4076 || (p = strstri(bp, "globs of ")) != 0) {
4077 mntmp = name_to_mon(!p ? bp : (strstri(p, " of ") + 4));
4078 /* if we didn't recognize monster type, pick a valid one at random */
4079 if (mntmp == NON_PM)
4080 mntmp = rn1(PM_BLACK_PUDDING - PM_GRAY_OOZE, PM_GRAY_OOZE);
4081 /* construct canonical spelling in case name_to_mon() recognized a
4082 variant (grey ooze) or player used inverted syntax (<foo> glob);
4083 if player has given a valid monster type but not valid glob type,
4084 object name lookup won't find it and wish attempt will fail */
4085 Sprintf(globbuf, "glob of %s", mons[mntmp].mname);
4087 mntmp = NON_PM; /* not useful for "glob of <foo>" object lookup */
4088 cnt = 0; /* globs don't stack */
4089 oclass = FOOD_CLASS;
4090 actualn = bp, dn = 0;
4094 * Find corpse type using "of" (figurine of an orc, tin of orc meat)
4095 * Don't check if it's a wand or spellbook.
4096 * (avoid "wand/finger of death" confusion).
4098 if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
4099 && !strstri(bp, "finger ")) {
4100 if ((p = strstri(bp, "tin of ")) != 0) {
4101 if (!strcmpi(p + 7, "spinach")) {
4105 tmp = tin_variety_txt(p + 7, &tinv);
4107 mntmp = name_to_mon(p + 7 + tmp);
4111 } else if ((p = strstri(bp, " of ")) != 0
4112 && (mntmp = name_to_mon(p + 4)) >= LOW_PM)
4116 /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
4117 if (strncmpi(bp, "samurai sword", 13) /* not the "samurai" monster! */
4118 && strncmpi(bp, "wizard lock", 11) /* not the "wizard" monster! */
4119 && strncmpi(bp, "ninja-to", 8) /* not the "ninja" rank */
4120 && strncmpi(bp, "master key", 10) /* not the "master" rank */
4121 && strncmpi(bp, "magenta", 7)) { /* not the "mage" rank */
4122 if (mntmp < LOW_PM && strlen(bp) > 2
4123 && (mntmp = name_to_mon(bp)) >= LOW_PM) {
4124 int mntmptoo, mntmplen; /* double check for rank title */
4127 mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
4128 bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname)
4132 } else if (!strncmpi(bp, "s ", 2)) {
4134 } else if (!strncmpi(bp, "es ", 3)) {
4136 } else if (!*bp && !actualn && !dn && !un && !oclass) {
4137 /* no referent; they don't really mean a monster type */
4145 /*JP
\81u(
\89ö
\95¨
\96¼)
\82Ì
\89ò
\81v
\82Í
\8cÂ
\81X
\82ÉID
\82ª
\82 \82é
\82Ì
\82Å
\95Ê
\88µ
\82¢ */
4147 int l2 = strlen("
\82Ì
\89ò");
4148 if (l > 4 && strncmp(bp + l - l2, "
\82Ì
\89ò", l2) == 0) {
4149 if ((mntmp = name_to_mon(bp)) >= PM_GRAY_OOZE
4150 && mntmp <= PM_BLACK_PUDDING) {
4151 mntmp = NON_PM; /* lie to ourselves */
4152 cnt = 0; /* force only one */
4155 /*JP:
\81u(
\89ö
\95¨
\96¼)
\82Ì(
\83A
\83C
\83e
\83\80)
\81v
\91Î
\89\9e */
4156 if ((mntmp = name_to_mon(bp)) >= LOW_PM) {
4157 const char *mp = mons[mntmp].mname;
4158 bp = strstri(bp, mp) + strlen(mp) + 2;
4164 #if 0 /*JP*//*
\92P
\90\94\89»
\82Í
\82µ
\82È
\82¢*/
4165 /* first change to singular if necessary */
4167 char *sng = makesingular(bp);
4169 if (strcmp(bp, sng)) {
4177 #if 0 /*JP*//*
\83X
\83y
\83\8b\97h
\82ê
\8f\88\97\9d\82Í
\82µ
\82È
\82¢*/
4178 /* Alternate spellings (pick-ax, silver sabre, &c) */
4180 const struct alt_spellings *as = spellings;
4183 if (fuzzymatch(bp, as->sp, " -", TRUE)) {
4189 /* can't use spellings list for this one due to shuffling */
4190 if (!strncmpi(bp, "grey spell", 10))
4193 if ((p = strstri(bp, "armour")) != 0) {
4194 /* skip past "armo", then copy remainder beyond "u" */
4196 while ((*p = *(p + 1)) != '\0')
4197 ++p; /* self terminating */
4203 /* dragon scales - assumes order of dragons */
4204 if (!strcmpi(bp, "scales") && mntmp >= PM_GRAY_DRAGON
4205 && mntmp <= PM_YELLOW_DRAGON) {
4206 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
4207 mntmp = NON_PM; /* no monster */
4211 /*JP:
\81u
\97Ø
\8aZ
\81v
\82ð
\90æ
\82É
\8f\88\97\9d\82µ
\82Ä
\82¨
\82 */
4212 if (!strcmpi(bp, "
\97Ø
\8aZ") && mntmp >= PM_GRAY_DRAGON
4213 && mntmp <= PM_YELLOW_DRAGON) {
4214 typ = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4215 mntmp = NON_PM; /* no monster */
4219 if (!strcmpi(bp, "
\97Ø") && mntmp >= PM_GRAY_DRAGON
4220 && mntmp <= PM_YELLOW_DRAGON) {
4221 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
4222 mntmp = NON_PM; /* no monster */
4229 if (!BSTRCMPI(bp, p - 10, "holy water")) {
4231 if ((p - bp) >= 12 && *(p - 12) == 'u')
4232 iscursed = 1; /* unholy water */
4237 #else /*JP:
\90¹
\90\85\82Æ
\95s
\8fò
\82È
\90\85\82ð
\95Ê
\82É
\94»
\92è*/
4238 if (!BSTRCMPI(bp, p - 4, "
\90¹
\90\85")) {
4243 if (!BSTRCMPI(bp, p - 8, "
\95s
\8fò
\82È
\90\85")) {
4250 if (unlabeled && !BSTRCMPI(bp, p - 6, "scroll")) {
4252 if (unlabeled && !BSTRCMPI(bp, p - 4, "
\8aª
\95¨")) {
4254 typ = SCR_BLANK_PAPER;
4258 if (unlabeled && !BSTRCMPI(bp, p - 9, "spellbook")) {
4260 if (unlabeled && !BSTRCMPI(bp, p - 6, "
\96\82\96@
\8f\91")) {
4262 typ = SPE_BLANK_PAPER;
4265 /* specific food rather than color of gem/potion/spellbook[/scales] */
4266 if (!BSTRCMPI(bp, p - 6, "orange") && mntmp == NON_PM) {
4271 * NOTE: Gold pieces are handled as objects nowadays, and therefore
4272 * this section should probably be reconsidered as well as the entire
4273 * gold/money concept. Maybe we want to add other monetary units as
4274 * well in the future. (TH)
4277 if (!BSTRCMPI(bp, p - 10, "gold piece")
4278 || !BSTRCMPI(bp, p - 7, "zorkmid")
4279 || !strcmpi(bp, "gold") || !strcmpi(bp, "money")
4280 || !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
4282 if (!BSTRCMPI(bp, p - 4, "
\8bà
\89Ý") || !BSTRCMPI(bp, p - 8, "
\83S
\81[
\83\8b\83h")
4283 || *bp == GOLD_SYM) {
4285 if (cnt > 5000 && !wizard)
4289 otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
4290 otmp->quan = (long) cnt;
4291 otmp->owt = weight(otmp);
4296 /* check for single character object class code ("/" for wand, &c) */
4297 if (strlen(bp) == 1 && (i = def_char_to_objclass(*bp)) < MAXOCLASSES
4298 && i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) {
4305 \89p
\8cê
\82È
\82ç XXXXX potion
\82Í
\95s
\8am
\92è
\96¼
\81Apotion of XXXXX
\82Í
\8am
\92è
\96¼
\82Æ
\82¢
\82¤
4306 \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¢
4308 /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */
4309 /* false hits on, e.g., rings for "ring mail". */
4310 if (strncmpi(bp, "enchant ", 8)
4311 && strncmpi(bp, "destroy ", 8)
4312 && strncmpi(bp, "detect food", 11)
4313 && strncmpi(bp, "food detection", 14)
4314 && strncmpi(bp, "ring mail", 9)
4315 && strncmpi(bp, "studded leather armor", 21)
4316 && strncmpi(bp, "leather armor", 13)
4317 && strncmpi(bp, "tooled horn", 11)
4318 && strncmpi(bp, "food ration", 11)
4319 && strncmpi(bp, "meat ring", 9))
4320 for (i = 0; i < (int) (sizeof wrpsym); i++) {
4321 register int j = strlen(wrp[i]);
4323 /* check for "<class> [ of ] something" */
4324 if (!strncmpi(bp, wrp[i], j)) {
4326 if (oclass != AMULET_CLASS) {
4328 if (!strncmpi(bp, " of ", 4))
4330 /* else if(*bp) ?? */
4335 /* check for "something <class>" */
4336 if (!BSTRCMPI(bp, p - j, wrp[i])) {
4338 /* for "foo amulet", leave the class name so that
4339 wishymatch() can do "of inversion" to try matching
4340 "amulet of foo"; other classes don't include their
4341 class name in their full object names (where
4342 "potion of healing" is just "healing", for instance) */
4343 if (oclass != AMULET_CLASS) {
4346 if (p > bp && p[-1] == ' ')
4349 /* amulet without "of"; convoluted wording but better a
4350 special case that's handled than one that's missing */
4351 if (!strncmpi(bp, "versus poison ", 14)) {
4352 typ = AMULET_VERSUS_POISON;
4362 /* Wishing in wizard mode can create traps and furniture.
4363 * Part I: distinguish between trap and object for the two
4364 * types of traps which have corresponding objects: bear trap
4365 * and land mine. "beartrap" (object) and "bear trap" (trap)
4366 * have a difference in spelling which we used to exploit by
4367 * adding a special case in wishymatch(), but "land mine" is
4368 * spelled the same either way so needs different handing.
4369 * Since we need something else for land mine, we've dropped
4370 * the bear trap hack so that both are handled exactly the
4371 * same. To get an armed trap instead of a disarmed object,
4372 * the player can prefix either the object name or the trap
4373 * name with "trapped " (which ordinarily applies to chests
4374 * and tins), or append something--anything at all except for
4375 * " object", but " trap" is suggested--to either the trap
4376 * name or the object name.
4378 if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) {
4379 boolean beartrap = (lowc(*bp) == 'b');
4380 char *zp = bp + 4; /* skip "bear"/"land" */
4383 ++zp; /* embedded space is optional */
4384 if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) {
4386 if (trapped == 2 || !strcmpi(zp, " object")) {
4387 /* "untrapped <foo>" or "<foo> object" */
4388 typ = beartrap ? BEARTRAP : LAND_MINE;
4390 } else if (trapped == 1 || *zp != '\0') {
4391 /* "trapped <foo>" or "<foo> trap" (actually "<foo>*") */
4392 int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE);
4394 /* use canonical trap spelling, skip object matching */
4395 Strcpy(bp, defsyms[idx].explanation);
4398 /* [no prefix or suffix; we're going to end up matching
4399 the object name and getting a disarmed trap object] */
4403 #if 0 /*JP*//* mail/armor
\8aÖ
\98A
\82Å
\82Ì
\82Ý
\8eg
\82¤
\83\89\83x
\83\8b */
4406 #if 0 /*JP*//*
\83^
\83C
\83v
\95Ê
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢ */
4407 /* "grey stone" check must be before general "stone" */
4408 for (i = 0; i < SIZE(o_ranges); i++)
4409 if (!strcmpi(bp, o_ranges[i].name)) {
4410 typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
4415 #if 0 /*JP*//*
\90Î
\82Ì
\93Á
\95Ê
\8f\88\97\9d\82Í
\95s
\97v */
4416 if (!BSTRCMPI(bp, p - 6, " stone") || !BSTRCMPI(bp, p - 4, " gem")) {
4417 p[!strcmpi(p - 4, " gem") ? -4 : -6] = '\0';
4421 } else if (!strcmpi(bp, "looking glass")) {
4422 ; /* avoid false hit on "* glass" */
4423 } else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
4424 register char *g = bp;
4426 /* treat "broken glass" as a non-existent item; since "broken" is
4427 also a chest/box prefix it might have been stripped off above */
4428 if (broken || strstri(g, "broken"))
4429 return (struct obj *) 0;
4430 if (!strncmpi(g, "worthless ", 10))
4432 if (!strncmpi(g, "piece of ", 9))
4434 if (!strncmpi(g, "colored ", 8))
4436 else if (!strncmpi(g, "coloured ", 9))
4438 if (!strcmpi(g, "glass")) { /* choose random color */
4439 /* 9 different kinds */
4440 typ = LAST_GEM + rnd(9);
4441 if (objects[typ].oc_class == GEM_CLASS)
4444 typ = 0; /* somebody changed objects[]? punt */
4445 } else { /* try to construct canonical form */
4448 Strcpy(tbuf, "worthless piece of ");
4449 Strcat(tbuf, g); /* assume it starts with the color */
4457 dn = actualn; /* ex. "skull cap" */
4461 /* check real names of gems first */
4462 if (!oclass && actualn) {
4463 for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
4464 register const char *zn;
4466 if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) {
4471 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í"tin"
\82ð
\96ó
\82µ
\95ª
\82¯
\82Ä
\82¢
\82é
\82Ì
\82Å
\95s
\97v */
4472 /* "tin of foo" would be caught above, but plain "tin" has
4473 a random chance of yielding "tin wand" unless we do this */
4474 if (!strcmpi(actualn, "tin")) {
4481 if (((typ = rnd_otyp_by_namedesc(actualn, oclass, 1)) != STRANGE_OBJECT)
4482 || ((typ = rnd_otyp_by_namedesc(dn, oclass, 1)) != STRANGE_OBJECT)
4483 || ((typ = rnd_otyp_by_namedesc(un, oclass, 1)) != STRANGE_OBJECT)
4484 || ((typ = rnd_otyp_by_namedesc(origbp, oclass, 1)) != STRANGE_OBJECT))
4489 struct Jitem *j = Japanese_items;
4492 if (actualn && !strcmpi(actualn, j->name)) {
4499 #if 0 /*JP*//* mail/armor
\82Ì
\95\
\8bL
\97h
\82ê
\83`
\83F
\83b
\83N
\82Í
\95s
\97v */
4500 /* if we've stripped off "armor" and failed to match anything
4501 in objects[], append "mail" and try again to catch misnamed
4502 requests like "plate armor" and "yellow dragon scale armor" */
4503 if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) {
4504 /* modifying bp's string is ok; we're about to resort
4505 to random armor if this also fails to match anything */
4506 Strcat(bp, " mail");
4511 if (!strcmpi(bp, "spinach")) {
4513 if (!strcmp(bp, "
\83z
\83E
\83\8c\83\93\91\90")) {
4519 /* Note: not strcmpi. 2 fruits, one capital, one not, are possible.
4520 Also not strncmp. We used to ignore trailing text with it, but
4521 that resulted in "grapefruit" matching "grape" if the latter came
4522 earlier than the former in the fruit list. */
4526 int blessedf, iscursedf, uncursedf, halfeatenf;
4528 blessedf = iscursedf = uncursedf = halfeatenf = 0;
4535 if (!strncmpi(fp, "an ", l = 3) || !strncmpi(fp, "a ", l = 2)) {
4537 } else if (!cntf && digit(*fp)) {
4544 } else if (!strncmpi(fp, "blessed ", l = 8)) {
4546 } else if (!strncmpi(fp, "cursed ", l = 7)) {
4548 } else if (!strncmpi(fp, "uncursed ", l = 9)) {
4550 } else if (!strncmpi(fp, "partly eaten ", l = 13)
4551 || !strncmpi(fp, "partially eaten ", l = 16)) {
4558 for (f = ffruit; f; f = f->nextf) {
4559 /* match type: 0=none, 1=exact, 2=singular, 3=plural */
4562 if (!strcmp(fp, f->fname))
4564 else if (!strcmp(fp, makesingular(f->fname)))
4566 else if (!strcmp(fp, makeplural(f->fname)))
4571 iscursed = iscursedf;
4572 uncursed = uncursedf;
4573 halfeaten = halfeatenf;
4574 /* adjust count if user explicitly asked for
4575 singular amount (can't happen unless fruit
4576 has been given an already pluralized name)
4577 or for plural amount */
4578 if (ftyp == 2 && !cntf)
4580 else if (ftyp == 3 && !cntf)
4589 if (!oclass && actualn) {
4592 /* Perhaps it's an artifact specified by name, not type */
4593 name = artifact_name(actualn, &objtyp);
4601 * Let wizards wish for traps and furniture.
4602 * Must come after objects check so wizards can still wish for
4603 * trap objects like beartraps.
4604 * Disallow such topology tweaks for WIZKIT startup wishes.
4607 if (wizard && !program_state.wizkit_wishing) {
4609 boolean madeterrain = FALSE;
4610 int trap, x = u.ux, y = u.uy;
4612 for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
4616 tname = defsyms[trap_to_defsym(trap)].explanation;
4617 if (strncmpi(tname, bp, strlen(tname)))
4619 /* found it; avoid stupid mistakes */
4620 if (is_hole(trap) && !Can_fall_thru(&u.uz))
4622 if ((t = maketrap(x, y, trap)) != 0) {
4624 tname = defsyms[trap_to_defsym(trap)].explanation;
4625 pline("%s%s.", An(tname),
4626 (trap != MAGIC_PORTAL) ? "" : " to nowhere");
4628 pline("Creation of %s failed.", an(tname));
4629 return (struct obj *) &zeroobj;
4632 /* furniture and terrain (use at your own risk; can clobber stairs
4633 or place furniture on existing traps which shouldn't be allowed) */
4636 if (!BSTRCMPI(bp, p - 8, "fountain")) {
4637 lev->typ = FOUNTAIN;
4638 level.flags.nfountains++;
4639 if (!strncmpi(bp, "magic ", 6))
4640 lev->blessedftn = 1;
4641 pline("A %sfountain.", lev->blessedftn ? "magic " : "");
4643 } else if (!BSTRCMPI(bp, p - 6, "throne")) {
4647 } else if (!BSTRCMPI(bp, p - 4, "sink")) {
4649 level.flags.nsinks++;
4653 /* ("water" matches "potion of water" rather than terrain) */
4654 } else if (!BSTRCMPI(bp, p - 4, "pool")
4655 || !BSTRCMPI(bp, p - 4, "moat")) {
4656 lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT;
4658 pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
4659 /* Must manually make kelp! */
4660 water_damage_chain(level.objects[x][y], TRUE);
4663 /* also matches "molten lava" */
4664 } else if (!BSTRCMPI(bp, p - 4, "lava")) {
4665 lev->typ = LAVAPOOL;
4667 pline("A pool of molten lava.");
4668 if (!(Levitation || Flying))
4671 } else if (!BSTRCMPI(bp, p - 5, "altar")) {
4675 if (!strncmpi(bp, "chaotic ", 8))
4677 else if (!strncmpi(bp, "neutral ", 8))
4679 else if (!strncmpi(bp, "lawful ", 7))
4681 else if (!strncmpi(bp, "unaligned ", 10))
4683 else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
4684 al = !rn2(6) ? A_NONE : (rn2((int) A_LAWFUL + 2) - 1);
4685 lev->altarmask = Align2amask(al);
4686 pline("%s altar.", An(align_str(al)));
4688 } else if (!BSTRCMPI(bp, p - 5, "grave")
4689 || !BSTRCMPI(bp, p - 9, "headstone")) {
4690 make_grave(x, y, (char *) 0);
4691 pline("%s.", IS_GRAVE(lev->typ) ? "A grave"
4692 : "Can't place a grave here");
4694 } else if (!BSTRCMPI(bp, p - 4, "tree")) {
4699 } else if (!BSTRCMPI(bp, p - 4, "bars")) {
4700 lev->typ = IRONBARS;
4701 pline("Iron bars.");
4706 feel_newsym(x, y); /* map the spot where the wish occurred */
4707 /* hero started at <x,y> but might not be there anymore (create
4708 lava, decline to die, and get teleported away to safety) */
4709 if (u.uinwater && !is_pool(u.ux, u.uy)) {
4710 u.uinwater = 0; /* leave the water */
4712 vision_full_recalc = 1;
4713 } else if (u.utrap && u.utraptype == TT_LAVA
4714 && !is_lava(u.ux, u.uy)) {
4717 /* cast 'const' away; caller won't modify this */
4718 return (struct obj *) &zeroobj;
4720 } /* end of wizard mode traps and terrain */
4722 #if 0 /*JP*//*
\83^
\83C
\83v
\95Ê
\82Í
\82Æ
\82è
\82 \82¦
\82¸
\82µ
\82È
\82¢ */
4723 if (!oclass && !typ) {
4724 if (!strncmpi(bp, "polearm", 7)) {
4725 typ = rnd_otyp_by_wpnskill(P_POLEARMS);
4727 } else if (!strncmpi(bp, "hammer", 6)) {
4728 typ = rnd_otyp_by_wpnskill(P_HAMMER);
4735 return ((struct obj *) 0);
4738 oclass = wrpsym[rn2((int) sizeof wrpsym)];
4741 oclass = objects[typ].oc_class;
4743 /* handle some objects that are only allowed in wizard mode */
4744 if (typ && !wizard) {
4746 case AMULET_OF_YENDOR:
4747 typ = FAKE_AMULET_OF_YENDOR;
4749 case CANDELABRUM_OF_INVOCATION:
4750 typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
4752 case BELL_OF_OPENING:
4755 case SPE_BOOK_OF_THE_DEAD:
4756 typ = SPE_BLANK_PAPER;
4762 /* catch any other non-wishable objects (venom) */
4763 if (objects[typ].oc_nowish)
4764 return (struct obj *) 0;
4770 * Create the object, then fine-tune it.
4772 otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE);
4773 typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */
4775 if (islit && (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN
4776 || Is_candle(otmp) || typ == POT_OIL)) {
4777 place_object(otmp, u.ux, u.uy); /* make it viable light source */
4778 begin_burn(otmp, FALSE);
4779 obj_extract_self(otmp); /* now release it for caller's use */
4782 /* if player specified a reasonable count, maybe honor it */
4783 if (cnt > 0 && objects[typ].oc_merge
4784 && (wizard || cnt < rnd(6) || (cnt <= 7 && Is_candle(otmp))
4785 || (cnt <= 20 && ((oclass == WEAPON_CLASS && is_ammo(otmp))
4786 || typ == ROCK || is_missile(otmp)))))
4787 otmp->quan = (long) cnt;
4789 if (oclass == VENOM_CLASS)
4794 } else if (wizard) {
4795 ; /* no alteration to spe */
4796 } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS
4798 || (oclass == RING_CLASS && objects[typ].oc_charged)) {
4799 if (spe > rnd(5) && spe > otmp->spe)
4801 if (spe > 2 && Luck < 0)
4804 if (oclass == WAND_CLASS) {
4805 if (spe > 1 && spesgn == -1)
4808 if (spe > 0 && spesgn == -1)
4811 if (spe > otmp->spe)
4818 /* set otmp->spe. This may, or may not, use spe... */
4821 if (contents == EMPTY) {
4822 otmp->corpsenm = NON_PM;
4824 } else if (contents == SPINACH) {
4825 otmp->corpsenm = NON_PM;
4831 otmp->spe = wetness;
4839 case HEAVY_IRON_BALL:
4842 /* otmp->cobj already done in mksobj() */
4846 /* 0: delivered in-game via external event (or randomly for fake mail);
4847 1: from bones or wishing; 2: written with marker */
4853 otmp->spe = (rn2(10) ? -1 : 0);
4861 /* set otmp->corpsenm or dragon scale [mail] */
4862 if (mntmp >= LOW_PM) {
4863 if (mntmp == PM_LONG_WORM_TAIL)
4864 mntmp = PM_LONG_WORM;
4868 otmp->spe = 0; /* No spinach */
4869 if (dead_species(mntmp, FALSE)) {
4870 otmp->corpsenm = NON_PM; /* it's empty */
4871 } else if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4872 && !(mvitals[mntmp].mvflags & G_NOCORPSE)
4873 && mons[mntmp].cnutrit != 0) {
4874 otmp->corpsenm = mntmp;
4878 if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4879 && !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
4880 if (mons[mntmp].msound == MS_GUARDIAN)
4881 mntmp = genus(mntmp, 1);
4882 set_corpsenm(otmp, mntmp);
4886 mntmp = can_be_hatched(mntmp);
4887 /* this also sets hatch timer if appropriate */
4888 set_corpsenm(otmp, mntmp);
4891 if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
4893 && mntmp != PM_MAIL_DAEMON
4896 otmp->corpsenm = mntmp;
4899 otmp->corpsenm = mntmp;
4900 if (Has_contents(otmp) && verysmall(&mons[mntmp]))
4901 delete_contents(otmp); /* no spellbook */
4902 otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
4905 /* Dragon mail - depends on the order of objects & dragons. */
4906 if (mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON)
4907 otmp->otyp = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4912 /* set blessed/cursed -- setting the fields directly is safe
4913 * since weight() is called below and addinv() will take care
4917 } else if (uncursed) {
4919 otmp->cursed = (Luck < 0 && !wizard);
4920 } else if (blessed) {
4921 otmp->blessed = (Luck >= 0 || wizard);
4922 otmp->cursed = (Luck < 0 && !wizard);
4923 } else if (spesgn < 0) {
4927 /* set eroded and erodeproof */
4928 if (erosion_matters(otmp)) {
4929 if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
4930 otmp->oeroded = eroded;
4931 if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
4932 otmp->oeroded2 = eroded2;
4934 * 3.6.1: earlier versions included `&& !eroded && !eroded2' here,
4935 * but damageproof combined with damaged is feasible (eroded
4936 * armor modified by confused reading of cursed destroy armor)
4937 * so don't prevent player from wishing for such a combination.
4939 if (erodeproof && (is_damageable(otmp) || otmp->otyp == CRYSKNIFE))
4940 otmp->oerodeproof = (Luck >= 0 || wizard);
4943 /* set otmp->recharged */
4944 if (oclass == WAND_CLASS) {
4945 /* prevent wishing abuse */
4946 if (otmp->otyp == WAN_WISHING && !wizard)
4948 otmp->recharged = (unsigned) rechrg;
4953 if (is_poisonable(otmp))
4954 otmp->opoisoned = (Luck >= 0);
4955 else if (oclass == FOOD_CLASS)
4956 /* try to taint by making it as old as possible */
4959 /* and [un]trapped */
4961 if (Is_box(otmp) || typ == TIN)
4962 otmp->otrapped = (trapped == 1);
4964 /* empty for containers rather than for tins */
4965 if (contents == EMPTY) {
4966 if (otmp->otyp == BAG_OF_TRICKS || otmp->otyp == HORN_OF_PLENTY) {
4969 } else if (Has_contents(otmp)) {
4970 /* this assumes that artifacts can't be randomly generated
4971 inside containers */
4972 delete_contents(otmp);
4973 otmp->owt = weight(otmp);
4976 /* set locked/unlocked/broken */
4979 otmp->olocked = 1, otmp->obroken = 0;
4980 } else if (unlocked) {
4981 otmp->olocked = 0, otmp->obroken = 0;
4982 } else if (broken) {
4983 otmp->olocked = 0, otmp->obroken = 1;
4990 if (isdiluted && otmp->oclass == POTION_CLASS && otmp->otyp != POT_WATER)
4993 /* set tin variety */
4994 if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard))
4995 set_tin_variety(otmp, tvariety);
5001 /* an artifact name might need capitalization fixing */
5002 aname = artifact_name(name, &objtyp);
5003 if (aname && objtyp == otmp->otyp)
5006 /* 3.6 tribute - fix up novel */
5007 if (otmp->otyp == SPE_NOVEL) {
5008 const char *novelname;
5010 novelname = lookup_novel(name, &otmp->novelidx);
5015 otmp = oname(otmp, name);
5016 /* name==aname => wished for artifact (otmp->oartifact => got it) */
5017 if (otmp->oartifact || name == aname) {
5019 u.uconduct.wisharti++; /* KMH, conduct */
5023 /* more wishing abuse: don't allow wishing for certain artifacts */
5024 /* and make them pay; charge them for the wish anyway! */
5025 if ((is_quest_artifact(otmp)
5026 || (otmp->oartifact && rn2(nartifact_exist()) > 1)) && !wizard) {
5027 artifact_exists(otmp, safe_oname(otmp), FALSE);
5028 obfree(otmp, (struct obj *) 0);
5029 otmp = (struct obj *) &zeroobj;
5031 pline("For a moment, you feel %s in your %s, but it disappears!",
5033 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",
5034 something, makeplural(body_part(HAND)));
5038 if (halfeaten && otmp->oclass == FOOD_CLASS) {
5039 if (otmp->otyp == CORPSE)
5040 otmp->oeaten = mons[otmp->corpsenm].cnutrit;
5042 otmp->oeaten = objects[otmp->otyp].oc_nutrition;
5043 /* (do this adjustment before setting up object's weight) */
5044 consume_oeaten(otmp, 1);
5046 otmp->owt = weight(otmp);
5047 if (very && otmp->otyp == HEAVY_IRON_BALL)
5048 otmp->owt += IRON_BALL_W_INCR;
5049 else if (gsize > 1 && otmp->globby)
5050 /* 0: unspecified => small; 1: small => keep default owt of 20;
5051 2: medium => 120; 3: large => 320; 4: very large => 520 */
5052 otmp->owt += 100 + (gsize - 2) * 200;
5058 rnd_class(first, last)
5065 for (i = first; i <= last; i++)
5066 sum += objects[i].oc_prob;
5067 if (!sum) /* all zero */
5068 return first + rn2(last - first + 1);
5070 for (i = first; i <= last; i++)
5071 if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
5076 STATIC_OVL const char *
5077 Japanese_item_name(i)
5080 struct Jitem *j = Japanese_items;
5087 return (const char *) 0;
5091 suit_simple_name(suit)
5094 const char *suitnm, *esuitp;
5097 if (Is_dragon_mail(suit))
5099 return "dragon mail"; /* <color> dragon scale mail */
5101 return "
\97Ø
\8aZ"; /* <color> dragon scale mail */
5103 else if (Is_dragon_scales(suit))
5105 return "dragon scales";
5108 suitnm = OBJ_NAME(objects[suit->otyp]);
5109 esuitp = eos((char *) suitnm);
5111 if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
5112 return "mail"; /* most suits fall into this category */
5114 if (strlen(suitnm) > 2 && !strcmp(esuitp - 2, "
\8aZ"))
5115 return "
\8aZ"; /* most suits fall into this category */
5118 else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
5119 return "jacket"; /* leather jacket */
5122 /* "suit" is lame but "armor" is ambiguous and "body armor" is absurd */
5130 cloak_simple_name(cloak)
5134 switch (cloak->otyp) {
5139 return "
\83\8d\81[
\83u";
5140 case MUMMY_WRAPPING:
5146 return (objects[cloak->otyp].oc_name_known && cloak->dknown)
5150 ? "
\83X
\83\82\83b
\83N"
5154 : "
\83G
\83v
\83\8d\83\93";
5162 return "
\83N
\83\8d\81[
\83N";
5165 /* helm vs hat for messages */
5167 helm_simple_name(helmet)
5171 * There is some wiggle room here; the result has been chosen
5172 * for consistency with the "protected by hard helmet" messages
5173 * given for various bonks on the head: headgear that provides
5174 * such protection is a "helm", that which doesn't is a "hat".
5176 * elven leather helm / leather hat -> hat
5177 * dwarvish iron helm / hard hat -> helm
5178 * The rest are completely straightforward:
5179 * fedora, cornuthaum, dunce cap -> hat
5180 * all other types of helmets -> helm
5183 return (helmet && !is_metallic(helmet)) ? "hat" : "helm";
5185 return (helmet && !is_metallic(helmet)) ? "
\96X
\8eq" : "
\8a\95";
5188 /* gloves vs gauntlets; depends upon discovery state */
5190 gloves_simple_name(gloves)
5194 static const char gauntlets[] = "gauntlets";
5196 static const char gauntlets[] = "
\8f¬
\8eè";
5198 if (gloves && gloves->dknown) {
5199 int otyp = gloves->otyp;
5200 struct objclass *ocl = &objects[otyp];
5201 const char *actualn = OBJ_NAME(*ocl),
5202 *descrpn = OBJ_DESCR(*ocl);
5204 if (strstri(objects[otyp].oc_name_known ? actualn : descrpn,
5215 mimic_obj_name(mtmp)
5218 if (M_AP_TYPE(mtmp) == M_AP_OBJECT) {
5219 if (mtmp->mappearance == GOLD_PIECE)
5224 if (mtmp->mappearance != STRANGE_OBJECT)
5225 return simple_typename(mtmp->mappearance);
5228 return "whatcha-may-callit";
5230 return "
\89½
\82Æ
\82©
\82¢
\82¤
\82à
\82Ì";
5234 * Construct a query prompt string, based around an object name, which is
5235 * guaranteed to fit within [QBUFSZ]. Takes an optional prefix, three
5236 * choices for filling in the middle (two object formatting functions and a
5237 * last resort literal which should be very short), and an optional suffix.
5240 safe_qbuf(qbuf, qprefix, qsuffix, obj, func, altfunc, lastR)
5241 char *qbuf; /* output buffer */
5242 const char *qprefix, *qsuffix;
5244 char *FDECL((*func), (OBJ_P)), *FDECL((*altfunc), (OBJ_P));
5248 /* convert size_t (or int for ancient systems) to ordinary unsigned */
5249 unsigned len, lenlimit,
5250 len_qpfx = (unsigned) (qprefix ? strlen(qprefix) : 0),
5251 len_qsfx = (unsigned) (qsuffix ? strlen(qsuffix) : 0),
5252 len_lastR = (unsigned) strlen(lastR);
5254 lenlimit = QBUFSZ - 1;
5255 endp = qbuf + lenlimit;
5256 /* sanity check, aimed mainly at paniclog (it's conceivable for
5257 the result of short_oname() to be shorter than the length of
5258 the last resort string, but we ignore that possibility here) */
5259 if (len_qpfx > lenlimit)
5260 impossible("safe_qbuf: prefix too long (%u characters).", len_qpfx);
5261 else if (len_qpfx + len_qsfx > lenlimit)
5262 impossible("safe_qbuf: suffix too long (%u + %u characters).",
5263 len_qpfx, len_qsfx);
5264 else if (len_qpfx + len_lastR + len_qsfx > lenlimit)
5265 impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
5266 len_qpfx, len_lastR, len_qsfx);
5268 /* the output buffer might be the same as the prefix if caller
5269 has already partially filled it */
5270 if (qbuf == qprefix) {
5271 /* prefix is already in the buffer */
5273 } else if (qprefix) {
5274 /* put prefix into the buffer */
5275 (void) strncpy(qbuf, qprefix, lenlimit);
5278 /* no prefix; output buffer starts out empty */
5281 len = (unsigned) strlen(qbuf);
5283 if (len + len_lastR + len_qsfx > lenlimit) {
5284 /* too long; skip formatting, last resort output is truncated */
5285 if (len < lenlimit) {
5286 (void) strncpy(&qbuf[len], lastR, lenlimit - len);
5288 len = (unsigned) strlen(qbuf);
5289 if (qsuffix && len < lenlimit) {
5290 (void) strncpy(&qbuf[len], qsuffix, lenlimit - len);
5292 /* len = (unsigned) strlen(qbuf); */
5296 /* suffix and last resort are guaranteed to fit */
5297 len += len_qsfx; /* include the pending suffix */
5298 /* format the object */
5299 bufp = short_oname(obj, func, altfunc, lenlimit - len);
5300 if (len + strlen(bufp) <= lenlimit)
5301 Strcat(qbuf, bufp); /* formatted name fits */
5303 Strcat(qbuf, lastR); /* use last resort */
5307 Strcat(qbuf, qsuffix);
5309 /* assert( strlen(qbuf) < QBUFSZ ); */
5314 globwt(otmp, buf, weightformatted_p)
5317 boolean *weightformatted_p;
5321 Sprintf(buf, "%u aum, ", otmp->owt);
5322 *weightformatted_p = TRUE;
5324 *weightformatted_p = FALSE;