1 /* NetHack 3.6 objnam.c $NHDT-Date: 1447490776 2015/11/14 08:46:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.154 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
8 /* JNetHack may be freely redistributed. See license for details. */
12 /* "an uncursed greased partly eaten guardian naga hatchling [corpse]" */
14 #define PREFIX 80 /* (56) */
16 /*
\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*/
22 STATIC_DCL char *FDECL(strprepend, (char *, const char *));
23 STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
24 STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
25 STATIC_DCL char *NDECL(nextobuf);
26 STATIC_DCL void FDECL(releaseobuf, (char *));
27 STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
28 STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
30 FDECL(singplur_lookup, (char *, char *, BOOLEAN_P, const char *const *));
31 STATIC_DCL char *FDECL(singplur_compound, (char *));
32 STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
34 static char *FDECL(substitute, (char *, char *, char *));
35 static char *FDECL(transpose, (char *buf,char *));
36 static char *FDECL(delete, (char *, char *str));
37 static int FDECL(digit_8, (int));
38 static int FDECL(atoi_8, (const char *));
46 #define BSTRCMPI(base, ptr, str) ((ptr) < base || strcmpi((ptr), str))
47 #define BSTRNCMPI(base, ptr, str, num) \
48 ((ptr) < base || strncmpi((ptr), str, num))
49 #define Strcasecpy(dst, src) (void) strcasecpy(dst, src)
51 /* true for gems/rocks that should have " stone" appended to their names */
52 #define GemStone(typ) \
54 || (objects[typ].oc_material == GEMSTONE \
55 && (typ != DILITHIUM_CRYSTAL && typ != RUBY && typ != DIAMOND \
56 && typ != SAPPHIRE && typ != BLACK_OPAL && typ != EMERALD \
60 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "wakizashi" },
61 { BROADSWORD, "ninja-to" },
62 { FLAIL, "nunchaku" },
63 { GLAIVE, "naginata" },
64 { LOCK_PICK, "osaku" },
65 { WOODEN_HARP, "koto" },
67 { PLATE_MAIL, "tanko" },
69 { LEATHER_GLOVES, "yugake" },
70 { FOOD_RATION, "gunyoki" },
71 { POT_BOOZE, "sake" },
74 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "
\98e
\8d·
\82µ" },
75 { BROADSWORD, "
\94E
\8eÒ
\93\81" },
76 { FLAIL, "
\83k
\83\93\83`
\83\83\83N" },
77 { GLAIVE, "
\82È
\82¬
\82È
\82½" },
78 { LOCK_PICK, "
\82¨
\82³
\82" },
79 { WOODEN_HARP, "
\8bÕ" },
80 { KNIFE, "
\8eh
\93\81" },
81 { PLATE_MAIL, "
\92Z
\8db" },
83 { LEATHER_GLOVES, "
\8b|
\8c\9c" },
84 { FOOD_RATION, "
\8aÛ
\96ò" },
85 { POT_BOOZE, "
\8eð" },
89 STATIC_DCL const char *FDECL(Japanese_item_name, (int i));
94 register const char *pref;
96 register int i = (int) strlen(pref);
99 impossible("PREFIX too short (for %d).%s//%s", i, s, pref);
103 (void) strncpy(s, pref, i); /* do not copy trailing 0 */
107 /* manage a pool of BUFSZ buffers, so callers don't have to */
108 static char NEARDATA obufs[NUMOBUF][BUFSZ];
109 static int obufidx = 0;
114 obufidx = (obufidx + 1) % NUMOBUF;
115 return obufs[obufidx];
118 /* put the most recently allocated buffer back if possible */
123 /* caller may not know whether bufp is the most recently allocated
124 buffer; if it isn't, do nothing */
125 if (bufp == obufs[obufidx])
126 obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
133 char *buf = nextobuf();
134 register struct objclass *ocl = &objects[otyp];
135 register const char *actualn = OBJ_NAME(*ocl);
136 register const char *dn = OBJ_DESCR(*ocl);
137 register const char *un = ocl->oc_uname;
138 register int nn = ocl->oc_name_known;
140 if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
141 actualn = Japanese_item_name(otyp);
144 Sprintf(buf, "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é", un);
146 switch (ocl->oc_class) {
151 Strcat(buf, "
\8bà
\89Ý");
155 Strcpy(buf, "potion");
161 Strcpy(buf, "scroll");
163 Strcat(buf, "
\8aª
\95¨");
173 Strcpy(buf, "spellbook");
175 Strcat(buf, "
\96\82\96@
\8f\91");
181 Strcat(buf, "
\8ew
\97Ö");
186 Strcpy(buf, actualn);
188 Strcpy(buf, "amulet");
190 Sprintf(eos(buf), " called %s", un);
192 Sprintf(eos(buf), " (%s)", dn);
196 Strcat(buf, actualn);
198 Strcat(buf, "
\96\82\8f\9c\82¯");
204 Strcat(buf, actualn);
206 Strcat(buf, "
\95ó
\90Î");
212 Strcpy(buf, actualn);
214 Strcat(buf, " stone");
216 Sprintf(eos(buf), " called %s", un);
218 Sprintf(eos(buf), " (%s)", dn);
220 Strcat(buf, actualn);
224 Strcpy(buf, dn ? dn : actualn);
225 if (ocl->oc_class == GEM_CLASS)
227 (ocl->oc_material == MINERAL) ? " stone" : " gem");
229 Sprintf(eos(buf), " called %s", un);
231 Strcat(buf, dn ? dn : actualn);
240 /* here for ring/scroll/potion/wand */
244 Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
246 Sprintf(eos(buf), " of %s", actualn);
248 Strcpy(buf, actualn);
253 Sprintf(eos(buf), " called %s", un);
257 Sprintf(eos(buf), " (%s)", dn);
259 Sprintf(eos(buf), "(%s)", dn);
264 /* less verbose result than obj_typename(); either the actual name
265 or the description (but not both); user-assigned name is ignored */
267 simple_typename(otyp)
270 char *bufp, *pp, *save_uname = objects[otyp].oc_uname;
272 objects[otyp].oc_uname = 0; /* suppress any name given by user */
273 bufp = obj_typename(otyp);
274 objects[otyp].oc_uname = save_uname;
275 if ((pp = strstri(bufp, " (")) != 0)
276 *pp = '\0'; /* strip the appended description */
284 if (!obj->oartifact || !has_oname(obj))
286 if (!program_state.gameover && !iflags.override_ID) {
287 if (not_fully_identified(obj))
293 /* Give the name of an object seen at a distance. Unlike xname/doname,
294 * we don't want to set dknown if it's not set already. The kludge used is
295 * to temporarily set Blind so that xname() skips the dknown setting. This
296 * assumes that we don't want to do this too often; if this function becomes
297 * frequently used, it'd probably be better to pass a parameter to xname()
298 * or doname() instead.
301 distant_name(obj, func)
303 char *FDECL((*func), (OBJ_P));
307 long save_Blinded = Blinded;
310 Blinded = save_Blinded;
314 /* convert player specified fruit name into corresponding fruit juice name
315 ("slice of pizza" -> "pizza juice" rather than "slice of pizza juice") */
318 boolean juice; /* whether or not to append " juice" to the name */
320 #if 1 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\82»
\82±
\82Ü
\82Å
\82µ
\82È
\82¢*/
321 char *buf = nextobuf();
322 Sprintf(buf, "%s%s", pl_fruit, juice ? "
\83W
\83\85\81[
\83X" : "");
325 char *buf = nextobuf();
326 const char *fruit_nam = strstri(pl_fruit, " of ");
329 fruit_nam += 4; /* skip past " of " */
331 fruit_nam = pl_fruit; /* use it as is */
333 Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
342 return xname_flags(obj, CXN_NORMAL);
346 xname_flags(obj, cxn_flags)
347 register struct obj *obj;
348 unsigned cxn_flags; /* bitmask of CXN_xxx values */
351 register int typ = obj->otyp;
352 register struct objclass *ocl = &objects[typ];
353 int nn = ocl->oc_name_known, omndx = obj->corpsenm;
354 const char *actualn = OBJ_NAME(*ocl);
355 const char *dn = OBJ_DESCR(*ocl);
356 const char *un = ocl->oc_uname;
357 boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
358 boolean known, dknown, bknown;
360 buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
361 if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
362 actualn = Japanese_item_name(typ);
366 * clean up known when it's tied to oc_name_known, eg after AD_DRIN
367 * This is only required for unique objects since the article
368 * printed for the object is tied to the combination of the two
369 * and printing the wrong article gives away information.
371 if (!nn && ocl->oc_uses_known && ocl->oc_unique)
375 if (Role_if(PM_PRIEST))
378 if (iflags.override_ID) {
379 known = dknown = bknown = TRUE;
383 dknown = obj->dknown;
384 bknown = obj->bknown;
387 if (obj_is_pname(obj))
392 Strcat(buf, ONAME(obj));
397 if (has_oname(obj) && dknown) {
398 Strcat(buf, ONAME(obj));
399 Strcat(buf, "
\82Æ
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½");
402 switch (obj->oclass) {
406 Strcpy(buf, "amulet");
408 Strcat(buf, "
\96\82\8f\9c\82¯");
409 else if (typ == AMULET_OF_YENDOR || typ == FAKE_AMULET_OF_YENDOR)
410 /* each must be identified individually */
411 Strcpy(buf, known ? actualn : dn);
413 Strcpy(buf, actualn);
416 Sprintf(buf, "amulet called %s", un);
418 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96\82\8f\9c\82¯", un);
421 Sprintf(buf, "%s amulet", dn);
423 Sprintf(eos(buf), "%s", dn);
426 if (is_poisonable(obj) && obj->opoisoned)
428 Strcpy(buf, "poisoned ");
430 Strcpy(buf, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
435 Sprintf(eos(buf), "%s
\82Ì", mons[obj->corpsenm].mname);
439 Strcpy(buf, "pair of ");
441 Strcpy(buf, "
\88ê
\91Î
\82Ì");
442 else if (is_wet_towel(obj))
444 Strcpy(buf, (obj->spe < 3) ? "moist " : "wet ");
446 Strcpy(buf, (obj->spe < 3) ? "
\8e¼
\82Á
\82½" : "
\94G
\82ê
\82½");
449 Strcat(buf, dn ? dn : actualn);
451 Strcat(buf, actualn);
454 Strcat(buf, dn ? dn : actualn);
455 Strcat(buf, " called ");
459 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é");
460 Strcat(buf, dn ? dn : actualn);
463 Strcat(buf, dn ? dn : actualn);
464 #if 0 /*JP*/ /*
\82±
\82ê
\82Í
\8cê
\8f\87\82Ì
\8aÖ
\8cW
\82©
\82ç
\8fã
\82Ì
\95û
\82Å
\92è
\8b`*/
465 /* If we use an() here we'd have to remember never to use */
466 /* it whenever calling doname() or xname(). */
467 if (typ == FIGURINE && omndx != NON_PM) {
468 Sprintf(eos(buf), " of a%s %s",
469 index(vowels, *mons[omndx].mname) ? "n" : "",
471 } else if (is_wet_towel(obj)) {
473 if (is_wet_towel(obj)) {
476 Sprintf(eos(buf), " (%d)", obj->spe);
480 /* depends on order of the dragon scales objects */
481 if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
483 Sprintf(buf, "set of %s", actualn);
485 Sprintf(buf, "%s
\88ê
\8e®", actualn);
488 if (is_boots(obj) || is_gloves(obj))
490 Strcpy(buf, "pair of ");
492 Strcat(buf,"
\88ê
\91Î
\82Ì");
494 if (obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
497 Strcpy(buf, "shield");
499 Strcat(buf, "
\8f\82");
502 if (obj->otyp == SHIELD_OF_REFLECTION && !dknown) {
504 Strcpy(buf, "smooth shield");
506 Strcat(buf, "
\82·
\82×
\82·
\82×
\82µ
\82½
\8f\82");
511 Strcat(buf, actualn);
515 Strcat(buf, "boots");
516 else if (is_gloves(obj))
517 Strcat(buf, "gloves");
518 else if (is_cloak(obj))
519 Strcpy(buf, "cloak");
520 else if (is_helmet(obj))
521 Strcpy(buf, "helmet");
522 else if (is_shield(obj))
523 Strcpy(buf, "shield");
525 Strcpy(buf, "armor");
526 Strcat(buf, " called ");
532 else if (is_gloves(obj))
534 else if (is_cloak(obj))
535 p = "
\83N
\83\8d\81[
\83N";
536 else if (is_helmet(obj))
538 else if (is_shield(obj))
542 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", un, p);
548 if (typ == SLIME_MOLD) {
549 register struct fruit *f;
551 for (f = ffruit; f; f = f->nextf) {
552 if (f->fid == obj->spe) {
553 Strcpy(buf, f->fname);
558 impossible("Bad fruit #%d?", obj->spe);
559 Strcpy(buf, "fruit");
560 } else if (pluralize) {
561 /* ick; already pluralized fruit names
562 are allowed--we want to try to avoid
563 adding a redundant plural suffix */
564 Strcpy(buf, makeplural(makesingular(buf)));
569 if (Is_pudding(obj)) {
580 ? "
\82Æ
\82Ä
\82à
\91å
\82«
\82¢"
592 Strcpy(buf, actualn);
593 if (typ == TIN && known)
594 tin_details(obj, omndx, buf);
596 if (typ == TIN && known)
597 /*JP
\81u
\81`
\82Ì
\93÷
\82Ì
\81v*/
598 tin_details(obj, omndx, buf);
599 Strcat(buf, actualn);
605 Strcpy(buf, actualn);
607 Strcat(buf, actualn);
611 if (typ == STATUE && omndx != NON_PM)
613 Sprintf(buf, "%s%s of %s%s",
614 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
618 type_is_pname(&mons[omndx])
620 : the_unique_pm(&mons[omndx])
622 : index(vowels, *mons[omndx].mname)
627 Sprintf(eos(buf), "%s%s
\82Ì%s",
628 (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
631 mons[obj->corpsenm].mname, actualn);
635 Strcpy(buf, actualn);
637 Strcat(buf, actualn);
642 Sprintf(buf, "%sheavy iron ball",
643 (obj->owt > ocl->oc_weight) ? "very " : "");
645 Sprintf(eos(buf), "%s
\8fd
\82¢
\93S
\8b\85",
646 (obj->owt > ocl->oc_weight) ? "
\82Æ
\82Ä
\82à" : "");
650 if (dknown && obj->odiluted)
652 Strcpy(buf, "diluted ");
654 Strcat(buf, "
\94\96\82Ü
\82Á
\82½");
655 if (nn || un || !dknown) {
657 Strcat(buf, "potion");
670 if (typ == POT_WATER && bknown
671 && (obj->blessed || obj->cursed)) {
673 Strcat(buf, obj->blessed ? "holy " : "unholy ");
675 Strcat(buf, obj->blessed ? "
\90¹" : "
\95s
\8fò
\82È");
677 Strcat(buf, actualn);
680 Strcat(buf, " called ");
684 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96ò");
689 #if 0 /*JP*//*
\95s
\8am
\92è
\96¼
\82É
\81u
\96ò
\81v
\82Í
\95t
\82¢
\82Ä
\82¢
\82é*/
690 Strcat(buf, " potion");
696 Strcpy(buf, "scroll");
701 Strcat(buf,"
\8aª
\95¨");
709 Strcat(buf, actualn);
712 Strcat(buf, " called ");
716 Strcat(buf, "
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8aª
\95¨");
718 } else if (ocl->oc_magic) {
720 Strcat(buf, " labeled ");
726 Strcat(buf, " scroll");
740 Sprintf(buf, "wand of %s", actualn);
742 Strcat(buf, actualn);
745 Sprintf(buf, "wand called %s", un);
747 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8fñ", un);
750 Sprintf(buf, "%s wand", dn);
755 if (typ == SPE_NOVEL) { /* 3.6 tribute */
759 Strcpy(buf, actualn);
761 Sprintf(buf, "novel called %s", un);
763 Sprintf(buf, "%s book", dn);
766 } else if (!dknown) {
768 Strcpy(buf, "spellbook");
770 Strcat(buf, "
\96\82\96@
\8f\91");
773 if (typ != SPE_BOOK_OF_THE_DEAD)
774 Strcpy(buf, "spellbook of ");
776 Strcat(buf, actualn);
779 Sprintf(buf, "spellbook called %s", un);
781 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\96\82\96@
\8f\91", un);
784 Sprintf(buf, "%s spellbook", dn);
786 Sprintf(eos(buf), "%s", dn);
793 Strcat(buf, "
\8ew
\97Ö");
796 Sprintf(buf, "ring of %s", actualn);
798 Strcat(buf, actualn);
801 Sprintf(buf, "ring called %s", un);
803 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é
\8ew
\97Ö", un);
806 Sprintf(buf, "%s ring", dn);
812 const char *rock = (ocl->oc_material == MINERAL) ? "stone" : "gem";
814 const char *rock = (ocl->oc_material == MINERAL) ? "
\90Î" : "
\95ó
\90Î";
825 Sprintf(buf, "%s called %s", rock, un);
827 Sprintf(eos(buf), "%s
\82Æ
\8cÄ
\82Î
\82ê
\82é%s", un, rock);
830 Sprintf(buf, "%s %s", dn, rock);
834 Strcpy(buf, actualn);
837 Strcat(buf, " stone");
843 Sprintf(buf, "glorkum %d %d %d", obj->oclass, typ, obj->spe);
847 Strcpy(buf, makeplural(buf));
850 if (obj->otyp == T_SHIRT && program_state.gameover) {
854 Sprintf(eos(buf), " with text \"%s\"", tshirt_text(obj, tmpbuf));
856 Sprintf(eos(buf), "(
\81u%s
\81v
\82Æ
\8f\91\82¢
\82Ä
\82 \82é)", tshirt_text(obj, tmpbuf));
860 if (has_oname(obj) && dknown) {
861 Strcat(buf, " named ");
863 Strcat(buf, ONAME(obj));
866 if (!strncmpi(buf, "the ", 4))
874 /* similar to simple_typename but minimal_xname operates on a particular
875 object rather than its general type; it formats the most basic info:
876 potion -- if description not known
877 brown potion -- if oc_name_known not set
878 potion of object detection -- if discovered
886 struct objclass saveobcls;
887 int otyp = obj->otyp;
889 /* suppress user-supplied name */
890 saveobcls.oc_uname = objects[otyp].oc_uname;
891 objects[otyp].oc_uname = 0;
892 /* suppress actual name if object's description is unknown */
893 saveobcls.oc_name_known = objects[otyp].oc_name_known;
895 objects[otyp].oc_name_known = 0;
897 /* caveat: this makes a lot of assumptions about which fields
898 are required in order for xname() to yield a sensible result */
901 bareobj.oclass = obj->oclass;
902 bareobj.dknown = obj->dknown;
903 /* suppress known except for amulets (needed for fakes and real A-of-Y) */
904 bareobj.known = (obj->oclass == AMULET_CLASS)
906 /* default is "on" for types which don't use it */
907 : !objects[otyp].oc_uses_known;
908 bareobj.quan = 1L; /* don't want plural */
909 bareobj.corpsenm = NON_PM; /* suppress statue and figurine details */
910 /* but suppressing fruit details leads to "bad fruit #0"
911 [perhaps we should force "slime mold" rather than use xname?] */
912 if (obj->otyp == SLIME_MOLD)
913 bareobj.spe = obj->spe;
915 bufp = distant_name(&bareobj, xname); /* xname(&bareobj) */
917 if (!strncmp(bufp, "uncursed ", 9))
918 bufp += 9; /* Role_if(PM_PRIEST) */
920 if (!strncmp(bufp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢", 14))
921 bufp += 14; /* Role_if(PM_PRIEST) */
924 objects[otyp].oc_uname = saveobcls.oc_uname;
925 objects[otyp].oc_name_known = saveobcls.oc_name_known;
929 /* xname() output augmented for multishot missile feedback */
935 char *onm = xname(obj);
937 if (m_shot.n > 1 && m_shot.o == obj->otyp) {
938 /* "the Nth arrow"; value will eventually be passed to an() or
939 The(), both of which correctly handle this "the " prefix */
941 Sprintf(tmpbuf, "the %d%s ", m_shot.i, ordin(m_shot.i));
943 Sprintf(tmpbuf, "%d%s
\96Ú
\82Ì", m_shot.i, numeral(obj));
944 onm = strprepend(onm, tmpbuf);
949 /* used for naming "the unique_item" instead of "a unique_item" */
955 boolean known = (obj->known || iflags.override_ID);
957 if (!obj->dknown && !iflags.override_ID)
959 else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !known)
960 return TRUE; /* lie */
962 return (boolean) (objects[obj->otyp].oc_unique
963 && (known || obj->otyp == AMULET_OF_YENDOR));
969 /* should monster type be prefixed with "the"? (mostly used for corpses) */
972 struct permonst *ptr;
976 /* even though monsters with personal names are unique, we want to
977 describe them as "Name" rather than "the Name" */
978 if (type_is_pname(ptr))
981 uniq = (ptr->geno & G_UNIQ) ? TRUE : FALSE;
982 /* high priest is unique if it includes "of <deity>", otherwise not
983 (caller needs to handle the 1st possibility; we assume the 2nd);
984 worm tail should be irrelevant but is included for completeness */
985 if (ptr == &mons[PM_HIGH_PRIEST] || ptr == &mons[PM_LONG_WORM_TAIL])
987 /* Wizard no longer needs this; he's flagged as unique these days */
988 if (ptr == &mons[PM_WIZARD_OF_YENDOR])
994 add_erosion_words(obj, prefix)
998 boolean iscrys = (obj->otyp == CRYSKNIFE);
1001 rknown = (iflags.override_ID == 0) ? obj->rknown : TRUE;
1003 if (!is_damageable(obj) && !iscrys)
1006 /* The only cases where any of these bits do double duty are for
1007 * rotted food and diluted potions, which are all not is_damageable().
1009 if (obj->oeroded && !iscrys) {
1010 switch (obj->oeroded) {
1013 Strcat(prefix, "very ");
1015 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1019 Strcat(prefix, "thoroughly ");
1021 Strcat(prefix, "
\82©
\82È
\82è");
1025 Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
1027 Strcat(prefix, is_rustprone(obj) ? "
\8eK
\82Ñ
\82½" : "
\8f\9d\82Â
\82¢
\82½");
1029 if (obj->oeroded2 && !iscrys) {
1030 switch (obj->oeroded2) {
1033 Strcat(prefix, "very ");
1035 Strcat(prefix, "
\82Æ
\82Ä
\82à");
1039 Strcat(prefix, "thoroughly ");
1041 Strcat(prefix, "
\82©
\82È
\82è");
1045 Strcat(prefix, is_corrodeable(obj) ? "corroded " : "rotted ");
1047 Strcat(prefix, is_corrodeable(obj) ? "
\95\85\90H
\82µ
\82½" : "
\95\85\82Á
\82½");
1049 if (rknown && obj->oerodeproof)
1050 Strcat(prefix, iscrys
1054 ? "
\88À
\92è
\82µ
\82½"
1059 ? "
\8eK
\82Ñ
\82È
\82¢"
1060 : is_corrodeable(obj)
1062 ? "corrodeproof " /* "stainless"? */
1064 ? "
\95\85\90H
\82µ
\82È
\82¢" /* "stainless"? */
1070 ? "
\94R
\82¦
\82È
\82¢"
1075 doname_base(obj, with_price)
1076 register struct obj *obj;
1079 boolean ispoisoned = FALSE;
1080 boolean known, cknown, bknown, lknown;
1081 int omndx = obj->corpsenm;
1082 char prefix[PREFIX];
1083 char tmpbuf[PREFIX + 1]; /* for when we have to add something at
1084 the start of prefix instead of the
1085 end (Strcat is used on the end) */
1086 register char *bp = xname(obj);
1087 #if 1 /*JP*//*
\8f\87\8f\98\93ü
\82ê
\91Ö
\82¦
\82É
\8eg
\82¤*/
1088 char preprefix[PREFIX];
1091 if (iflags.override_ID) {
1092 known = cknown = bknown = lknown = TRUE;
1095 cknown = obj->cknown;
1096 bknown = obj->bknown;
1097 lknown = obj->lknown;
1100 /* When using xname, we want "poisoned arrow", and when using
1101 * doname, we want "poisoned +0 arrow". This kludge is about the only
1102 * way to do it, at least until someone overhauls xname() and doname(),
1103 * combining both into one function taking a parameter.
1105 /* must check opoisoned--someone can have a weirdly-named fruit */
1107 if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
1112 if (!strncmp(bp, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½", 12) && obj->opoisoned) {
1119 *
\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
1120 *
\82Ì
\82Ù
\82¤
\82ª
\8e©
\91R
\82Å
\82 \82é
\81D
1124 preprefix[0] = '\0';
1125 if((tp = strstri(bp, "
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½")) != NULL){
1126 tp += 12; /*
\81u
\96¼
\82Ã
\82¯
\82ç
\82ê
\82½
\81v*/
1127 strncpy(preprefix, bp, tp - bp);
1128 preprefix[tp - bp] = '\0';
1135 if (obj->quan != 1L) {
1137 Sprintf(prefix, "%ld ", obj->quan);
1138 #else /*
\93ú
\96{
\8cê
\82Æ
\82µ
\82Ä
\82Í
\90\94\8e\8c\82ª
\82È
\82¢
\82Ì
\82Í
\95s
\8e©
\91R */
1139 Sprintf(prefix, "%ld%s
\82Ì", obj->quan, numeral(obj));
1141 } else if (obj->otyp == CORPSE) {
1142 /* skip article prefix for corpses [else corpse_xname()
1143 would have to be taught how to strip it off again] */
1145 #if 0 /*JP*/ /*
\8a¥
\8e\8c\82Í
\95s
\97v */
1146 } else if (obj_is_pname(obj) || the_unique_obj(obj)) {
1147 if (!strncmpi(bp, "the ", 4))
1149 Strcpy(prefix, "the ");
1151 Strcpy(prefix, "a ");
1152 #else /*prefix
\82Ì
\8f\89\8aú
\89»*/
1158 /* "empty" goes at the beginning, but item count goes at the end */
1160 /* bag of tricks: include "empty" prefix if it's known to
1161 be empty but its precise number of charges isn't known
1162 (when that is known, suffix of "(n:0)" will be appended,
1163 making the prefix be redundant; note that 'known' flag
1164 isn't set when emptiness gets discovered because then
1165 charging magic would yield known number of new charges) */
1166 && (obj->otyp == BAG_OF_TRICKS
1167 ? (obj->spe == 0 && !obj->known)
1168 /* not bag of tricks: empty if container which has no contents */
1169 : (Is_container(obj) || obj->otyp == STATUE)
1170 && !Has_contents(obj)))
1172 Strcat(prefix, "empty ");
1174 Strcat(prefix, "
\8bó
\82Ì");
1176 if (bknown && obj->oclass != COIN_CLASS
1177 && (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
1178 || (!obj->cursed && !obj->blessed))) {
1179 /* allow 'blessed clear potion' if we don't know it's holy water;
1180 * always allow "uncursed potion of water"
1184 Strcat(prefix, "cursed ");
1186 Strcat(prefix, "
\8eô
\82í
\82ê
\82½");
1187 else if (obj->blessed)
1189 Strcat(prefix, "blessed ");
1191 Strcat(prefix, "
\8fj
\95\9f\82³
\82ê
\82½");
1192 else if (!iflags.implicit_uncursed
1193 /* For most items with charges or +/-, if you know how many
1194 * charges are left or what the +/- is, then you must have
1195 * totally identified the item, so "uncursed" is unnecessary,
1196 * because an identified object not described as "blessed" or
1197 * "cursed" must be uncursed.
1199 * If the charges or +/- is not known, "uncursed" must be
1200 * printed to avoid ambiguity between an item whose curse
1201 * status is unknown, and an item known to be uncursed.
1203 || ((!known || !objects[obj->otyp].oc_charged
1204 || obj->oclass == ARMOR_CLASS
1205 || obj->oclass == RING_CLASS)
1207 && obj->otyp != SCR_MAIL
1209 && obj->otyp != FAKE_AMULET_OF_YENDOR
1210 && obj->otyp != AMULET_OF_YENDOR
1211 && !Role_if(PM_PRIEST)))
1213 Strcat(prefix, "uncursed ");
1215 Strcat(prefix, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢");
1218 if (lknown && Is_box(obj)) {
1221 Strcat(prefix, "unlockable ");
1223 Strcat(prefix, "
\8c®
\82Ì
\89ó
\82ê
\82½");
1224 else if (obj->olocked)
1226 Strcat(prefix, "locked ");
1228 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82½");
1231 Strcat(prefix, "unlocked ");
1233 Strcat(prefix, "
\8c®
\82Ì
\8a|
\82©
\82Á
\82Ä
\82¢
\82È
\82¢");
1238 Strcat(prefix, "greased ");
1240 Strcat(prefix, "
\96û
\82Ì
\93h
\82ç
\82ê
\82½");
1242 if (cknown && Has_contents(obj)) {
1243 /* we count all objects (obj->quantity); perhaps we should
1244 count separate stacks instead (or even introduce a user
1245 preference option to choose between the two alternatives)
1246 since it's somewhat odd so see "containing 1002 items"
1247 when there are 2 scrolls plus 1000 gold pieces */
1248 long itemcount = count_contents(obj, FALSE, FALSE, TRUE);
1251 Sprintf(eos(bp), " containing %ld item%s", itemcount,
1254 Sprintf(eos(bp), "(%ld
\8cÂ
\93ü
\82Á
\82Ä
\82¢
\82é)", itemcount);
1258 switch (obj->oclass) {
1260 if (obj->owornmask & W_AMUL)
1262 Strcat(bp, " (being worn)");
1264 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1269 Strcat(prefix, "poisoned ");
1271 Strcat(prefix, "
\93Å
\82Ì
\93h
\82ç
\82ê
\82½");
1273 add_erosion_words(obj, prefix);
1275 Strcat(prefix, sitoa(obj->spe));
1276 Strcat(prefix, " ");
1280 if (obj->owornmask & W_ARMOR)
1282 Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
1284 Strcat(bp, (obj == uskin) ? "(
\94§
\82É
\96\84\82ß
\82±
\82Ü
\82ê
\82Ä
\82¢
\82é)"
1288 : "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1291 /* weptools already get this done when we go to the +n code */
1292 if (!is_weptool(obj))
1293 add_erosion_words(obj, prefix);
1294 if (obj->owornmask & (W_TOOL /* blindfold */ | W_SADDLE)) {
1296 Strcat(bp, " (being worn)");
1298 Strcat(bp, "(
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é)");
1301 if (obj->otyp == LEASH && obj->leashmon != 0) {
1303 Strcat(bp, " (in use)");
1305 Strcat(bp, "(
\8c\8b\82Ñ
\82Â
\82¯
\82Ä
\82¢
\82é)");
1308 if (is_weptool(obj))
1310 if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
1313 Strcpy(tmpbuf, "no");
1315 Sprintf(tmpbuf, "%d", obj->spe);
1316 Sprintf(eos(bp), " (%s candle%s%s)", tmpbuf, plur(obj->spe),
1317 !obj->lamplit ? " attached" : ", lit");
1320 Sprintf(eos(bp), "(
\88ê
\96{
\82à
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82È
\82¢)");
1323 Sprintf(eos(bp), "(%d
\96{
\8eæ
\82è
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é)", obj->spe);
1325 Sprintf(eos(bp), "(%d
\96{
\8cõ
\82Á
\82Ä
\82¢
\82é)", obj->spe);
1329 } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
1330 || obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
1332 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
1334 Strcat(prefix, "partly used ");
1336 Strcat(prefix, "
\8eg
\82¢
\82³
\82µ
\82Ì");
1339 Strcat(bp, " (lit)");
1341 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1344 if (objects[obj->otyp].oc_charged)
1348 add_erosion_words(obj, prefix);
1352 Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
1354 Sprintf(eos(bp), "(%d:%d)", (int) obj->recharged, obj->spe);
1357 if (obj->otyp == POT_OIL && obj->lamplit)
1359 Strcat(bp, " (lit)");
1361 Strcat(bp, "(
\8cõ
\82Á
\82Ä
\82¢
\82é)");
1364 add_erosion_words(obj, prefix);
1366 if (obj->owornmask & W_RINGR)
1368 Strcat(bp, " (on right ");
1370 Strcat(bp, "(
\89E");
1371 if (obj->owornmask & W_RINGL)
1373 Strcat(bp, " (on left ");
1375 Strcat(bp, "(
\8d¶");
1376 if (obj->owornmask & W_RING) {
1377 Strcat(bp, body_part(HAND));
1380 if (known && objects[obj->otyp].oc_charged) {
1382 Strcat(prefix, " ");
1384 Strcat(prefix, sitoa(obj->spe));
1385 Strcat(prefix, " ");
1391 Strcat(prefix, "partly eaten ");
1393 Strcat(prefix, "
\90H
\82×
\82©
\82¯
\82Ì");
1394 if (obj->otyp == CORPSE) {
1396 Sprintf(prefix, "%s ",
1397 corpse_xname(obj, prefix, CXN_ARTICLE | CXN_NOCORPSE));
1399 Sprintf(prefix, "%s
\82Ì",
1400 corpse_xname(obj, prefix, CXN_ARTICLE | CXN_NOCORPSE));
1402 } else if (obj->otyp == EGG) {
1403 #if 0 /* corpses don't tell if they're stale either */
1404 if (known && stale_egg(obj))
1405 Strcat(prefix, "stale ");
1408 && (known || (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
1410 Strcat(prefix, mons[omndx].mname);
1411 Strcat(prefix, " ");
1413 Strcat(prefix, mons[omndx].mname);
1414 Strcat(prefix, "
\82Ì");
1418 Strcat(bp, " (laid by you)");
1420 Strcat(bp, "(
\82 \82È
\82½
\82ª
\8eY
\82ñ
\82¾)");
1423 if (obj->otyp == MEAT_RING)
1428 add_erosion_words(obj, prefix);
1429 if (obj->owornmask & W_BALL)
1431 Strcat(bp, " (chained to you)");
1433 Strcat(bp, "(
\82 \82È
\82½
\82É
\8cq
\82ª
\82ê
\82Ä
\82¢
\82é)");
1437 if ((obj->owornmask & W_WEP) && !mrg_to_wielded) {
1438 if (obj->quan != 1L) {
1440 Strcat(bp, " (wielded)");
1442 Strcat(bp, "(
\91\95\94õ
\82µ
\82Ä
\82¢
\82é)");
1444 const char *hand_s = body_part(HAND);
1447 hand_s = makeplural(hand_s);
1449 Sprintf(eos(bp), " (weapon in %s)", hand_s);
1451 Sprintf(eos(bp), "(%s
\82É
\82µ
\82Ä
\82¢
\82é)", hand_s);
1453 if (warn_obj_cnt && obj == uwep && (EWarn_of_mon & W_WEP) != 0L) {
1454 /* presumably can be felt when blind */
1456 Strcat(bp, " (glowing");
1458 Sprintf(eos(bp), " %s", glow_color(obj->oartifact));
1462 Strcat(bp, " (
\94M
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82é)");
1464 Sprintf(eos(bp), " (%s
\8bP
\82¢
\82Ä
\82¢
\82é)",
1465 glow_color(obj->oartifact));
1470 if (obj->owornmask & W_SWAPWEP) {
1473 Sprintf(eos(bp), " (wielded in other %s)", body_part(HAND));
1475 Sprintf(eos(bp), "(
\8d¶%s
\82É
\82µ
\82Ä
\82¢
\82é)", body_part(HAND));
1478 Strcat(bp, " (alternate weapon; not wielded)");
1480 Strcat(bp, "(
\97\
\94õ
\82Ì
\95\90\8aí;
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢)");
1482 if (obj->owornmask & W_QUIVER) {
1483 switch (obj->oclass) {
1486 if (objects[obj->otyp].oc_skill == -P_BOW) {
1487 /* Ammo for a bow */
1489 Strcat(bp, " (in quiver)");
1491 Strcat(bp, "(
\96î
\93\9b\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1494 /* Ammo not for a bow */
1496 Strcat(bp, " (in quiver pouch)");
1498 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1502 /* Weapons not considered ammo */
1504 Strcat(bp, " (at the ready)");
1506 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1509 /* Small things and ammo not for a bow */
1516 Strcat(bp, " (in quiver pouch)");
1518 Strcat(bp, "(
\92e
\93ü
\82ê
\82É
\93ü
\82Á
\82Ä
\82¢
\82é)");
1520 default: /* odd things */
1522 Strcat(bp, " (at the ready)");
1524 Strcat(bp, "(
\8f\80\94õ
\82µ
\82Ä
\82¢
\82é)");
1527 if (!iflags.suppress_price && is_unpaid(obj)) {
1528 long quotedprice = unpaid_cost(obj, TRUE);
1530 Sprintf(eos(bp), " (%s, %ld %s)",
1531 obj->unpaid ? "unpaid" : "contents",
1532 quotedprice, currency(quotedprice));
1533 } else if (with_price) {
1534 long price = get_cost_of_shop_item(obj);
1537 Sprintf(eos(bp), " (%ld %s)", price, currency(price));
1539 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
1540 if (!strncmp(prefix, "a ", 2)
1541 && index(vowels, *(prefix + 2) ? *(prefix + 2) : *bp)
1543 || (strncmp(bp, "uranium", 7) && strncmp(bp, "unicorn", 7)
1544 && strncmp(bp, "eucalyptus", 10)))) {
1545 Strcpy(tmpbuf, prefix);
1546 Strcpy(prefix, "an ");
1547 Strcpy(prefix + 3, tmpbuf + 2);
1551 /* show weight for items (debug tourist info)
1552 * aum is stolen from Crawl's "Arbitrary Unit of Measure" */
1554 Sprintf(eos(bp), " (%d aum)", obj->owt);
1557 bp = strprepend(bp, prefix);
1558 #else /*JP:
\81u
\96¼
\95t
\82¯
\82ç
\82ê
\82½
\81v
\82ð
\96ß
\82·*/
1559 Strcat(preprefix, prefix);
1560 bp = strprepend(bp, preprefix);
1567 register struct obj *obj;
1569 return doname_base(obj, FALSE);
1572 /* Name of object including price. */
1574 doname_with_price(obj)
1575 register struct obj *obj;
1577 return doname_base(obj, TRUE);
1580 /* used from invent.c */
1582 not_fully_identified(otmp)
1583 register struct obj *otmp;
1585 /* gold doesn't have any interesting attributes [yet?] */
1586 if (otmp->oclass == COIN_CLASS)
1587 return FALSE; /* always fully ID'd */
1588 /* check fundamental ID hallmarks first */
1589 if (!otmp->known || !otmp->dknown
1591 || (!otmp->bknown && otmp->otyp != SCR_MAIL)
1595 || !objects[otmp->otyp].oc_name_known)
1597 if ((!otmp->cknown && (Is_container(otmp) || otmp->otyp == STATUE))
1598 || (!otmp->lknown && Is_box(otmp)))
1600 if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
1602 /* otmp->rknown is the only item of interest if we reach here */
1604 * Note: if a revision ever allows scrolls to become fireproof or
1605 * rings to become shockproof, this checking will need to be revised.
1606 * `rknown' ID only matters if xname() will provide the info about it.
1609 || (otmp->oclass != ARMOR_CLASS && otmp->oclass != WEAPON_CLASS
1610 && !is_weptool(otmp) /* (redundant) */
1611 && otmp->oclass != BALL_CLASS)) /* (useless) */
1613 else /* lack of `rknown' only matters for vulnerable objects */
1614 return (boolean) (is_rustprone(otmp) || is_corrodeable(otmp)
1615 || is_flammable(otmp));
1619 corpse_xname(otmp, adjective, cxn_flags)
1621 const char *adjective;
1622 unsigned cxn_flags; /* bitmask of CXN_xxx values */
1624 char *nambuf = nextobuf();
1625 int omndx = otmp->corpsenm;
1626 boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0,
1627 /* suppress "the" from "the unique monster corpse" */
1628 no_prefix = (cxn_flags & CXN_NO_PFX) != 0,
1629 /* include "the" for "the woodchuck corpse */
1630 the_prefix = (cxn_flags & CXN_PFX_THE) != 0,
1631 /* include "an" for "an ogre corpse */
1632 any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
1633 /* leave off suffix (do_name() appends "corpse" itself) */
1634 omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0, possessive = FALSE;
1637 if (omndx == NON_PM) { /* paranoia */
1642 /* [Possible enhancement: check whether corpse has monster traits
1643 attached in order to use priestname() for priests and minions.] */
1644 } else if (omndx == PM_ALIGNED_PRIEST) {
1645 /* avoid "aligned priest"; it just exposes internal details */
1651 mname = mons[omndx].mname;
1652 if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) {
1653 mname = s_suffix(mname);
1655 /* don't precede personal name like "Medusa" with an article */
1656 if (type_is_pname(&mons[omndx]))
1658 /* always precede non-personal unique monster name like
1659 "Oracle" with "the" unless explicitly overridden */
1660 else if (the_unique_pm(&mons[omndx]) && !no_prefix)
1665 the_prefix = any_prefix = FALSE;
1666 else if (the_prefix)
1667 any_prefix = FALSE; /* mutually exclusive */
1670 /* can't use the() the way we use an() below because any capitalized
1671 Name causes it to assume a personal name and return Name as-is;
1672 that's usually the behavior wanted, but here we need to force "the"
1673 to precede capitalized unique monsters (pnames are handled above) */
1674 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
1676 Strcat(nambuf, "the ");
1679 if (!adjective || !*adjective) {
1680 /* normal case: newt corpse */
1681 Strcat(nambuf, mname);
1683 /* adjective positioning depends upon format of monster name */
1684 if (possessive) /* Medusa's cursed partly eaten corpse */
1686 Sprintf(eos(nambuf), "%s %s", mname, adjective);
1688 Sprintf(eos(nambuf), "%s%s", mname, adjective);
1689 else /* cursed partly eaten troll corpse */
1691 Sprintf(eos(nambuf), "%s %s", adjective, mname);
1693 Sprintf(eos(nambuf), "%s%s", adjective, mname);
1694 /* in case adjective has a trailing space, squeeze it out */
1696 /* doname() might include a count in the adjective argument;
1697 if so, don't prepend an article */
1698 if (digit(*adjective))
1704 Strcat(nambuf, " corpse");
1705 /* makeplural(nambuf) => append "s" to "corpse" */
1706 if (otmp->quan > 1L && !ignore_quan) {
1707 Strcat(nambuf, "s");
1708 any_prefix = FALSE; /* avoid "a newt corpses" */
1711 Strcat(nambuf, "
\82Ì
\8e\80\91Ì");
1715 /* it's safe to overwrite our nambuf after an() has copied
1716 its old value into another buffer */
1718 Strcpy(nambuf, an(nambuf));
1723 /* xname doesn't include monster type for "corpse"; cxname does */
1728 if (obj->otyp == CORPSE)
1729 return corpse_xname(obj, (const char *) 0, CXN_NORMAL);
1733 /* like cxname, but ignores quantity */
1735 cxname_singular(obj)
1738 if (obj->otyp == CORPSE)
1739 return corpse_xname(obj, (const char *) 0, CXN_SINGULAR);
1740 return xname_flags(obj, CXN_SINGULAR);
1743 /* treat an object as fully ID'd when it might be used as reason for death */
1748 struct obj save_obj;
1749 unsigned save_ocknown;
1750 char *buf, *save_ocuname, *save_oname = (char *) 0;
1752 /* bypass object twiddling for artifacts */
1754 return bare_artifactname(obj);
1756 /* remember original settings for core of the object;
1757 oextra structs other than oname don't matter here--since they
1758 aren't modified they don't need to be saved and restored */
1761 save_oname = ONAME(obj);
1763 /* killer name should be more specific than general xname; however, exact
1764 info like blessed/cursed and rustproof makes things be too verbose */
1765 obj->known = obj->dknown = 1;
1766 obj->bknown = obj->rknown = obj->greased = 0;
1767 /* if character is a priest[ess], bknown will get toggled back on */
1768 if (obj->otyp != POT_WATER)
1769 obj->blessed = obj->cursed = 0;
1771 obj->bknown = 1; /* describe holy/unholy water as such */
1772 /* "killed by poisoned <obj>" would be misleading when poison is
1773 not the cause of death and "poisoned by poisoned <obj>" would
1774 be redundant when it is, so suppress "poisoned" prefix */
1776 /* strip user-supplied name; artifacts keep theirs */
1777 if (!obj->oartifact && save_oname)
1778 ONAME(obj) = (char *) 0;
1779 /* temporarily identify the type of object */
1780 save_ocknown = objects[obj->otyp].oc_name_known;
1781 objects[obj->otyp].oc_name_known = 1;
1782 save_ocuname = objects[obj->otyp].oc_uname;
1783 objects[obj->otyp].oc_uname = 0; /* avoid "foo called bar" */
1785 /* format the object */
1786 if (obj->otyp == CORPSE) {
1788 Strcpy(buf, corpse_xname(obj, (const char *) 0, CXN_NORMAL));
1789 } else if (obj->otyp == SLIME_MOLD) {
1790 /* concession to "most unique deaths competition" in the annual
1791 devnull tournament, suppress player supplied fruit names because
1792 those can be used to fake other objects and dungeon features */
1795 Sprintf(buf, "deadly slime mold%s", plur(obj->quan));
1797 Strcpy(buf, "
\8aë
\8c¯
\82È
\82Ë
\82Î
\82Ë
\82Î
\83J
\83r");
1801 /* apply an article if appropriate; caller should always use KILLED_BY */
1802 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
1803 if (obj->quan == 1L && !strstri(buf, "'s ") && !strstri(buf, "s' "))
1804 buf = (obj_is_pname(obj) || the_unique_obj(obj)) ? the(buf) : an(buf);
1807 objects[obj->otyp].oc_name_known = save_ocknown;
1808 objects[obj->otyp].oc_uname = save_ocuname;
1809 *obj = save_obj; /* restore object's core settings */
1810 if (!obj->oartifact && save_oname)
1811 ONAME(obj) = save_oname;
1816 /* xname,doname,&c with long results reformatted to omit some stuff */
1818 short_oname(obj, func, altfunc, lenlimit)
1820 char *FDECL((*func), (OBJ_P)), /* main formatting routine */
1821 *FDECL((*altfunc), (OBJ_P)); /* alternate for shortest result */
1824 struct obj save_obj;
1825 char unamebuf[12], onamebuf[12], *save_oname, *save_uname, *outbuf;
1827 outbuf = (*func)(obj);
1828 if ((unsigned) strlen(outbuf) <= lenlimit)
1831 /* shorten called string to fairly small amount */
1832 save_uname = objects[obj->otyp].oc_uname;
1833 if (save_uname && strlen(save_uname) >= sizeof unamebuf) {
1834 (void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
1835 Strcpy(unamebuf + sizeof unamebuf - 4, "...");
1836 objects[obj->otyp].oc_uname = unamebuf;
1837 releaseobuf(outbuf);
1838 outbuf = (*func)(obj);
1839 objects[obj->otyp].oc_uname = save_uname; /* restore called string */
1840 if ((unsigned) strlen(outbuf) <= lenlimit)
1844 /* shorten named string to fairly small amount */
1845 save_oname = has_oname(obj) ? ONAME(obj) : 0;
1846 if (save_oname && strlen(save_oname) >= sizeof onamebuf) {
1847 (void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
1848 Strcpy(onamebuf + sizeof onamebuf - 4, "...");
1849 ONAME(obj) = onamebuf;
1850 releaseobuf(outbuf);
1851 outbuf = (*func)(obj);
1852 ONAME(obj) = save_oname; /* restore named string */
1853 if ((unsigned) strlen(outbuf) <= lenlimit)
1857 /* shorten both called and named strings;
1858 unamebuf and onamebuf have both already been populated */
1859 if (save_uname && strlen(save_uname) >= sizeof unamebuf && save_oname
1860 && strlen(save_oname) >= sizeof onamebuf) {
1861 objects[obj->otyp].oc_uname = unamebuf;
1862 ONAME(obj) = onamebuf;
1863 releaseobuf(outbuf);
1864 outbuf = (*func)(obj);
1865 if ((unsigned) strlen(outbuf) <= lenlimit) {
1866 objects[obj->otyp].oc_uname = save_uname;
1867 ONAME(obj) = save_oname;
1872 /* still long; strip several name-lengthening attributes;
1873 called and named strings are still in truncated form */
1875 obj->bknown = obj->rknown = obj->greased = 0;
1876 obj->oeroded = obj->oeroded2 = 0;
1877 releaseobuf(outbuf);
1878 outbuf = (*func)(obj);
1879 if (altfunc && (unsigned) strlen(outbuf) > lenlimit) {
1880 /* still long; use the alternate function (usually one of
1881 the jackets around minimal_xname()) */
1882 releaseobuf(outbuf);
1883 outbuf = (*altfunc)(obj);
1885 /* restore the object */
1888 ONAME(obj) = save_oname;
1890 objects[obj->otyp].oc_uname = save_uname;
1892 /* use whatever we've got, whether it's too long or not */
1897 * Used if only one of a collection of objects is named (e.g. in eat.c).
1900 singular(otmp, func)
1901 register struct obj *otmp;
1902 char *FDECL((*func), (OBJ_P));
1907 /* using xname for corpses does not give the monster type */
1908 if (otmp->otyp == CORPSE && func == xname)
1911 savequan = otmp->quan;
1913 nam = (*func)(otmp);
1914 otmp->quan = savequan;
1920 register const char *str;
1922 char *buf = nextobuf();
1924 #if 0 /*JP*//*
\95s
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
1927 if (strncmpi(str, "the ", 4) && strcmp(str, "molten lava")
1928 && strcmp(str, "iron bars") && strcmp(str, "ice")) {
1929 if (index(vowels, *str) && strncmp(str, "one-", 4)
1930 && strncmp(str, "useful", 6) && strncmp(str, "unicorn", 7)
1931 && strncmp(str, "uranium", 7) && strncmp(str, "eucalyptus", 10))
1938 #else /*
\92P
\82É
\83R
\83s
\81[*/
1948 char *tmp = an(str);
1950 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
1957 * Prepend "the" if necessary; assumes str is a subject derived from xname.
1958 * Use type_is_pname() for monster names, not the(). the() is idempotent.
1964 char *buf = nextobuf();
1965 #if 0 /*JP*//*
\92è
\8a¥
\8e\8c\82Í
\95s
\97v*/
1966 boolean insert_the = FALSE;
1968 if (!strncmpi(str, "the ", 4)) {
1969 buf[0] = lowc(*str);
1970 Strcpy(&buf[1], str + 1);
1972 } else if (*str < 'A' || *str > 'Z') {
1973 /* not a proper name, needs an article */
1976 /* Probably a proper name, might not need an article */
1977 register char *tmp, *named, *called;
1980 /* some objects have capitalized adjectives in their names */
1981 if (((tmp = rindex(str, ' ')) != 0 || (tmp = rindex(str, '-')) != 0)
1982 && (tmp[1] < 'A' || tmp[1] > 'Z')) {
1984 } else if (tmp && index(str, ' ') < tmp) { /* has spaces */
1985 /* it needs an article if the name contains "of" */
1986 tmp = strstri(str, " of ");
1987 named = strstri(str, " named ");
1988 called = strstri(str, " called ");
1989 if (called && (!named || called < named))
1992 if (tmp && (!named || tmp < named)) /* found an "of" */
1994 /* stupid special case: lacks "of" but needs "the" */
1995 else if (!named && (l = strlen(str)) >= 31
1996 && !strcmp(&str[l - 31],
1997 "Platinum Yendorian Express Card"))
2002 Strcpy(buf, "the ");
2007 #else /*
\92P
\82É
\83R
\83s
\81[*/
2017 char *tmp = the(str);
2019 #if 0 /*JP*//*
\91å
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
2028 register struct obj *otmp;
2029 register const char *verb;
2035 /* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */
2041 char prefix[PREFIX];
2042 char *bp = cxname(otmp);
2044 if (otmp->quan != 1L) {
2045 Sprintf(prefix, "%ld ", otmp->quan);
2046 bp = strprepend(bp, prefix);
2050 Strcat(bp, otense(otmp, verb));
2056 /* combine yname and aobjnam eg "your count cxname(otmp)" */
2062 char *s = aobjnam(obj, verb);
2064 /* leave off "your" for most of your artifacts, but prepend
2065 * "your" for unique objects and "foo of bar" quest artifacts */
2066 if (!carried(obj) || !obj_is_pname(obj)
2067 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2068 char *outbuf = shk_your(nextobuf(), obj);
2069 int space_left = BUFSZ - 1 - strlen(outbuf);
2071 s = strncat(outbuf, s, space_left);
2076 /* combine Yname2 and aobjnam eg "Your count cxname(otmp)" */
2082 register char *s = yobjnam(obj, verb);
2090 /* like aobjnam, but prepend "The", not count, and use xname */
2096 char *bp = The(xname(otmp));
2098 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2101 Strcat(bp, otense(otmp, verb));
2107 /* capitalized variant of doname() */
2112 char *s = doname(obj);
2118 /* returns "[your ]xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
2123 char *s = cxname(obj);
2125 /* leave off "your" for most of your artifacts, but prepend
2126 * "your" for unique objects and "foo of bar" quest artifacts */
2127 if (!carried(obj) || !obj_is_pname(obj)
2128 || obj->oartifact >= ART_ORB_OF_DETECTION) {
2129 char *outbuf = shk_your(nextobuf(), obj);
2130 int space_left = BUFSZ - 1 - strlen(outbuf);
2132 s = strncat(outbuf, s, space_left);
2138 /* capitalized variant of yname() */
2143 char *s = yname(obj);
2151 /* returns "your minimal_xname(obj)"
2152 * or "Foobar's minimal_xname(obj)"
2153 * or "the minimal_xname(obj)"
2159 char *outbuf = nextobuf();
2160 char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
2162 int space_left = BUFSZ - 1 - strlen(s);
2164 return strncat(s, minimal_xname(obj), space_left);
2166 int space_left = BUFSZ - strlen(s);
2168 return strncat(s, minimal_xname(obj), space_left);
2172 /* capitalized variant of ysimple_name() */
2177 char *s = ysimple_name(obj);
2185 /* "scroll" or "scrolls" */
2190 char *simpleoname = minimal_xname(obj);
2192 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2193 if (obj->quan != 1L)
2194 simpleoname = makeplural(simpleoname);
2199 /* "a scroll" or "scrolls"; "a silver bell" or "the Bell of Opening" */
2204 char *simpleoname = simpleonames(obj);
2205 int otyp = obj->otyp;
2207 /* prefix with "the" if a unique item, or a fake one imitating same,
2208 has been formatted with its actual name (we let typename() handle
2209 any `known' and `dknown' checking necessary) */
2210 if (otyp == FAKE_AMULET_OF_YENDOR)
2211 otyp = AMULET_OF_YENDOR;
2212 if (objects[otyp].oc_unique
2213 && !strcmp(simpleoname, OBJ_NAME(objects[otyp])))
2214 return the(simpleoname);
2216 /* simpleoname is singular if quan==1, plural otherwise */
2217 if (obj->quan == 1L)
2218 simpleoname = an(simpleoname);
2222 /* "the scroll" or "the scrolls" */
2227 char *simpleoname = simpleonames(obj);
2229 return the(simpleoname);
2232 /* artifact's name without any object type or known/dknown/&c feedback */
2234 bare_artifactname(obj)
2239 if (obj->oartifact) {
2240 outbuf = nextobuf();
2241 Strcpy(outbuf, artiname(obj->oartifact));
2243 if (!strncmp(outbuf, "The ", 4))
2244 outbuf[0] = lowc(outbuf[0]);
2247 outbuf = xname(obj);
2252 static const char *wrp[] = {
2253 "wand", "ring", "potion", "scroll", "gem",
2254 "amulet", "spellbook", "spell book",
2255 /* for non-specific wishes */
2256 "weapon", "armor", "tool", "food", "comestible",
2258 static const char wrpsym[] = { WAND_CLASS, RING_CLASS, POTION_CLASS,
2259 SCROLL_CLASS, GEM_CLASS, AMULET_CLASS,
2260 SPBOOK_CLASS, SPBOOK_CLASS, WEAPON_CLASS,
2261 ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
2264 /* return form of the verb (input plural) if xname(otmp) were the subject */
2273 * verb is given in plural (without trailing s). Return as input
2274 * if the result of xname(otmp) would be plural. Don't bother
2275 * recomputing xname(otmp) at this time.
2277 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2278 if (!is_plural(otmp))
2279 return vtense((char *) 0, verb);
2287 /* various singular words that vtense would otherwise categorize as plural;
2288 also used by makesingular() to catch some special cases */
2289 static const char *const special_subjs[] = {
2290 "erinys", "manes", /* this one is ambiguous */
2291 "Cyclops", "Hippocrates", "Pelias", "aklys",
2292 "amnesia", "detect monsters", "paralysis", "shape changers",
2294 /* note: "detect monsters" and "shape changers" are normally
2295 caught via "<something>(s) of <whatever>", but they can be
2296 wished for using the shorter form, so we include them here
2297 to accommodate usage by makesingular during wishing */
2300 /* return form of the verb (input plural) for present tense 3rd person subj */
2303 register const char *subj;
2304 register const char *verb;
2306 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8eO
\92P
\8c»
\82Ìs
\82Í
\82È
\82¢*/
2307 char *buf = nextobuf(), *bspot;
2309 const char *sp, *spot;
2310 const char *const *spec;
2313 * verb is given in plural (without trailing s). Return as input
2314 * if subj appears to be plural. Add special cases as necessary.
2315 * Many hard cases can already be handled by using otense() instead.
2316 * If this gets much bigger, consider decomposing makeplural.
2317 * Note: monster names are not expected here (except before corpse).
2319 * Special case: allow null sobj to get the singular 3rd person
2320 * present tense form so we don't duplicate this code elsewhere.
2323 if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
2325 spot = (const char *) 0;
2326 for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
2327 if (!strncmpi(sp, " of ", 4) || !strncmpi(sp, " from ", 6)
2328 || !strncmpi(sp, " called ", 8) || !strncmpi(sp, " named ", 7)
2329 || !strncmpi(sp, " labeled ", 9)) {
2335 len = (int) strlen(subj);
2337 spot = subj + len - 1;
2340 * plural: anything that ends in 's', but not '*us' or '*ss'.
2341 * Guess at a few other special cases that makeplural creates.
2343 if ((lowc(*spot) == 's' && spot != subj
2344 && !index("us", lowc(*(spot - 1))))
2345 || !BSTRNCMPI(subj, spot - 3, "eeth", 4)
2346 || !BSTRNCMPI(subj, spot - 3, "feet", 4)
2347 || !BSTRNCMPI(subj, spot - 1, "ia", 2)
2348 || !BSTRNCMPI(subj, spot - 1, "ae", 2)) {
2349 /* check for special cases to avoid false matches */
2350 len = (int) (spot - subj) + 1;
2351 for (spec = special_subjs; *spec; spec++) {
2352 ltmp = strlen(*spec);
2353 if (len == ltmp && !strncmpi(*spec, subj, len))
2355 /* also check for <prefix><space><special_subj>
2356 to catch things like "the invisible erinys" */
2357 if (len > ltmp && *(spot - ltmp) == ' '
2358 && !strncmpi(*spec, spot - ltmp + 1, ltmp))
2362 return strcpy(buf, verb);
2365 * 3rd person plural doesn't end in telltale 's';
2366 * 2nd person singular behaves as if plural.
2368 if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
2369 return strcpy(buf, verb);
2374 len = (int) strlen(buf);
2375 bspot = buf + len - 1;
2377 if (!strcmpi(buf, "are")) {
2378 Strcasecpy(buf, "is");
2379 } else if (!strcmpi(buf, "have")) {
2380 Strcasecpy(bspot - 1, "s");
2381 } else if (index("zxs", lowc(*bspot))
2382 || (len >= 2 && lowc(*bspot) == 'h'
2383 && index("cs", lowc(*(bspot - 1))))
2384 || (len == 2 && lowc(*bspot) == 'o')) {
2385 /* Ends in z, x, s, ch, sh; add an "es" */
2386 Strcasecpy(bspot + 1, "es");
2387 } else if (lowc(*bspot) == 'y' && !index(vowels, lowc(*(bspot - 1)))) {
2388 /* like "y" case in makeplural */
2389 Strcasecpy(bspot, "ies");
2391 Strcasecpy(bspot + 1, "s");
2404 const char *sing, *plur;
2407 /* word pairs that don't fit into formula-based transformations;
2408 also some suffices which have very few--often one--matches or
2409 which aren't systematically reversible (knives, staves) */
2410 static struct sing_plur one_off[] = {
2412 "children" }, /* (for wise guys who give their food funny names) */
2413 { "cubus", "cubi" }, /* in-/suc-cubus */
2414 { "culus", "culi" }, /* homunculus */
2415 { "djinni", "djinn" },
2416 { "erinys", "erinyes" },
2418 { "fungus", "fungi" },
2419 { "knife", "knives" },
2420 { "labrum", "labra" }, /* candelabrum */
2421 { "louse", "lice" },
2422 { "mouse", "mice" },
2423 { "mumak", "mumakil" },
2424 { "nemesis", "nemeses" },
2425 { "rtex", "rtices" }, /* vortex */
2426 { "tooth", "teeth" },
2427 { "staff", "staves" },
2431 static const char *const as_is[] = {
2432 /* makesingular() leaves these plural due to how they're used */
2433 "boots", "shoes", "gloves", "lenses", "scales",
2434 "eyes", "gauntlets", "iron bars",
2435 /* both singular and plural are spelled the same */
2436 "deer", "fish", "tuna", "yaki", "-hai",
2437 "krill", "manes", "ninja", "sheep", "ronin",
2438 "roshi", "shito", "tengu", "ki-rin", "Nazgul",
2439 "gunyoki", "piranha", "samurai", "shuriken", 0,
2440 /* Note: "fish" and "piranha" are collective plurals, suitable
2441 for "wiped out all <foo>". For "3 <foo>", they should be
2442 "fishes" and "piranhas" instead. We settle for collective
2443 variant instead of attempting to support both. */
2446 /* singularize/pluralize decisions common to both makesingular & makeplural
2449 singplur_lookup(basestr, endstring, to_plural, alt_as_is)
2450 char *basestr, *endstring; /* base string, pointer to eos(string) */
2451 boolean to_plural; /* true => makeplural, false => makesingular */
2452 const char *const *alt_as_is; /* another set like as_is[] */
2454 const struct sing_plur *sp;
2455 const char *same, *other, *const *as;
2458 for (as = as_is; *as; ++as) {
2459 al = (int) strlen(*as);
2460 if (!BSTRCMPI(basestr, endstring - al, *as))
2464 for (as = alt_as_is; *as; ++as) {
2465 al = (int) strlen(*as);
2466 if (!BSTRCMPI(basestr, endstring - al, *as))
2471 for (sp = one_off; sp->sing; sp++) {
2472 /* check whether endstring already matches */
2473 same = to_plural ? sp->plur : sp->sing;
2474 al = (int) strlen(same);
2475 if (!BSTRCMPI(basestr, endstring - al, same))
2476 return TRUE; /* use as-is */
2477 /* check whether it matches the inverse; if so, transform it */
2478 other = to_plural ? sp->sing : sp->plur;
2479 al = (int) strlen(other);
2480 if (!BSTRCMPI(basestr, endstring - al, other)) {
2481 Strcasecpy(endstring - al, same);
2482 return TRUE; /* one_off[] transformation */
2488 /* searches for common compounds, ex. lump of royal jelly */
2490 singplur_compound(str)
2493 /* if new entries are added, be sure to keep compound_start[] in sync */
2494 static const char *const compounds[] =
2496 " of ", " labeled ", " called ",
2497 " named ", " above", /* lurkers above */
2498 " versus ", " from ", " in ",
2499 " on ", " a la ", " with", /* " with "? */
2500 " de ", " d'", " du ",
2502 }, /* list of first characters for all compounds[] entries */
2503 compound_start[] = " -";
2505 const char *const *cmpd;
2508 for (p = str; *p; ++p) {
2509 /* substring starting at p can only match if *p is found
2510 within compound_start[] */
2511 if (!index(compound_start, *p))
2514 /* check current substring against all words in the compound[] list */
2515 for (cmpd = compounds; *cmpd; ++cmpd)
2516 if (!strncmpi(p, *cmpd, (int) strlen(*cmpd)))
2519 /* wasn't recognized as a compound phrase */
2523 /* Plural routine; chiefly used for user-defined fruits. We have to try to
2524 * account for everything reasonable the player has; something unreasonable
2525 * can still break the code. However, it's still a lot more accurate than
2526 * "just add an s at the end", which Rogue uses...
2528 * Also used for plural monster names ("Wiped out all homunculi." or the
2529 * vanquished monsters list) and body parts. A lot of unique monsters have
2530 * names which get mangled by makeplural and/or makesingular. They're not
2531 * genocidable, and vanquished-mon handling does its own special casing
2532 * (for uniques who've been revived and re-killed), so we don't bother
2533 * trying to get those right here.
2535 * Also misused by muse.c to convert 1st person present verbs to 2nd person.
2536 * 3.6.0: made case-insensitive.
2542 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2543 register char *spot;
2544 char lo_c, *str = nextobuf();
2545 const char *excess = (char *) 0;
2549 while (*oldstr == ' ')
2551 if (!oldstr || !*oldstr) {
2552 impossible("plural of null?");
2556 Strcpy(str, oldstr);
2559 * Skip changing "pair of" to "pairs of". According to Webster, usual
2560 * English usage is use pairs for humans, e.g. 3 pairs of dancers,
2561 * and pair for objects and non-humans, e.g. 3 pair of boots. We don't
2562 * refer to pairs of humans in this game so just skip to the bottom.
2564 if (!strncmpi(str, "pair of ", 8))
2567 /* look for "foo of bar" so that we can focus on "foo" */
2568 if ((spot = singplur_compound(str)) != 0) {
2569 excess = oldstr + (int) (spot - str);
2575 while (spot > str && *spot == ' ')
2576 spot--; /* Strip blanks from end */
2578 /* Now spot is the last character of the string */
2582 /* Single letters */
2583 if (len == 1 || !letter(*spot)) {
2584 Strcpy(spot + 1, "'s");
2588 /* dispense with some words which don't need pluralization */
2590 static const char *const already_plural[] = {
2591 "ae", /* algae, larvae, &c */
2592 "men", /* also catches women, watchmen */
2596 /* spot+1: synch up with makesingular's usage */
2597 if (singplur_lookup(str, spot + 1, TRUE, already_plural))
2600 /* more of same, but not suitable for blanket loop checking */
2601 if ((len == 2 && !strcmpi(str, "ya"))
2602 || (len >= 3 && !strcmpi(spot - 2, " ya")))
2606 /* man/men ("Wiped out all cavemen.") */
2607 if (len >= 3 && !strcmpi(spot - 2, "man")
2608 /* exclude shamans and humans */
2609 && (len < 6 || strcmpi(spot - 5, "shaman"))
2610 && (len < 5 || strcmpi(spot - 4, "human"))) {
2611 Strcasecpy(spot - 1, "en");
2614 if (lowc(*spot) == 'f') { /* (staff handled via one_off[]) */
2615 lo_c = lowc(*(spot - 1));
2616 if (len >= 3 && !strcmpi(spot - 2, "erf")) {
2617 /* avoid "nerf" -> "nerves", "serf" -> "serves" */
2618 ; /* fall through to default (append 's') */
2619 } else if (index("lr", lo_c) || index(vowels, lo_c)) {
2620 /* [aeioulr]f to [aeioulr]ves */
2621 Strcasecpy(spot, "ves");
2625 /* ium/ia (mycelia, baluchitheria) */
2626 if (len >= 3 && !strcmpi(spot - 2, "ium")) {
2627 Strcasecpy(spot - 2, "ia");
2630 /* algae, larvae, hyphae (another fungus part) */
2631 if ((len >= 4 && !strcmpi(spot - 3, "alga"))
2633 && (!strcmpi(spot - 4, "hypha") || !strcmpi(spot - 4, "larva")))
2634 || (len >= 6 && !strcmpi(spot - 5, "amoeba"))
2635 || (len >= 8 && (!strcmpi(spot - 7, "vertebra")))) {
2637 Strcasecpy(spot + 1, "e");
2640 /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
2641 if (len > 3 && !strcmpi(spot - 1, "us")
2642 && !((len >= 5 && !strcmpi(spot - 4, "lotus"))
2643 || (len >= 6 && !strcmpi(spot - 5, "wumpus")))) {
2644 Strcasecpy(spot - 1, "i");
2647 /* sis/ses (nemesis) */
2648 if (len >= 3 && !strcmpi(spot - 2, "sis")) {
2649 Strcasecpy(spot - 1, "es");
2652 /* matzoh/matzot, possible food name */
2654 && (!strcmpi(spot - 5, "matzoh") || !strcmpi(spot - 5, "matzah"))) {
2655 Strcasecpy(spot - 1, "ot"); /* oh/ah -> ot */
2659 && (!strcmpi(spot - 4, "matzo") || !strcmpi(spot - 4, "matza"))) {
2660 Strcasecpy(spot, "ot"); /* o/a -> ot */
2664 /* note: -eau/-eaux (gateau, bordeau...) */
2665 /* note: ox/oxen, VAX/VAXen, goose/geese */
2669 /* Ends in z, x, s, ch, sh; add an "es" */
2670 if (index("zxs", lo_c)
2671 || (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot - 1))))
2672 /* Kludge to get "tomatoes" and "potatoes" right */
2673 || (len >= 4 && !strcmpi(spot - 2, "ato"))
2674 || (len >= 5 && !strcmpi(spot - 4, "dingo"))) {
2675 Strcasecpy(spot + 1, "es"); /* append es */
2678 /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
2679 if (lo_c == 'y' && !index(vowels, lowc(*(spot - 1)))) {
2680 Strcasecpy(spot, "ies"); /* y -> ies */
2683 /* Default: append an 's' */
2684 Strcasecpy(spot + 1, "s");
2688 Strcat(str, excess);
2690 char *str = nextobuf();
2691 Strcpy(str, oldstr);
2697 * Singularize a string the user typed in; this helps reduce the complexity
2698 * of readobjnam, and is also used in pager.c to singularize the string
2699 * for which help is sought.
2701 * "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)?
2702 * Its inclusion in as_is[]/special_subj[] makes it get treated as the former.
2704 * A lot of unique monsters have names ending in s; plural, or singular
2705 * from plural, doesn't make much sense for them so we don't bother trying.
2706 * 3.6.0: made case-insensitive.
2709 makesingular(oldstr)
2712 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Í
\92P
\95¡
\93¯
\8c^*/
2713 register char *p, *bp;
2714 const char *excess = 0;
2715 char *str = nextobuf();
2718 while (*oldstr == ' ')
2720 if (!oldstr || !*oldstr) {
2721 impossible("singular of null?");
2726 bp = strcpy(str, oldstr);
2728 /* check for "foo of bar" so that we can focus on "foo" */
2729 if ((p = singplur_compound(bp)) != 0) {
2730 excess = oldstr + (int) (p - bp);
2735 /* dispense with some words which don't need singularization */
2736 if (singplur_lookup(bp, p, FALSE, special_subjs))
2739 /* remove -s or -es (boxes) or -ies (rubies) */
2740 if (p >= bp + 1 && lowc(p[-1]) == 's') {
2741 if (p >= bp + 2 && lowc(p[-2]) == 'e') {
2742 if (p >= bp + 3 && lowc(p[-3]) == 'i') { /* "ies" */
2743 if (!BSTRCMPI(bp, p - 7, "cookies")
2744 || !BSTRCMPI(bp, p - 4, "pies")
2745 || !BSTRCMPI(bp, p - 5, "mbies") /* zombie */
2746 || !BSTRCMPI(bp, p - 5, "yries")) /* valkyrie */
2748 Strcasecpy(p - 3, "y"); /* ies -> y */
2751 /* wolves, but f to ves isn't fully reversible */
2752 if (p - 4 >= bp && (index("lr", lowc(*(p - 4)))
2753 || index(vowels, lowc(*(p - 4))))
2754 && !BSTRCMPI(bp, p - 3, "ves")) {
2755 if (!BSTRCMPI(bp, p - 6, "cloves")
2756 || !BSTRCMPI(bp, p - 6, "nerves"))
2758 Strcasecpy(p - 3, "f"); /* ves -> f */
2761 /* note: nurses, axes but boxes, wumpuses */
2762 if (!BSTRCMPI(bp, p - 4, "eses")
2763 || !BSTRCMPI(bp, p - 4, "oxes") /* boxes, foxes */
2764 || !BSTRCMPI(bp, p - 4, "nxes") /* lynxes */
2765 || !BSTRCMPI(bp, p - 4, "ches")
2766 || !BSTRCMPI(bp, p - 4, "uses") /* lotuses */
2767 || !BSTRCMPI(bp, p - 4, "sses") /* priestesses */
2768 || !BSTRCMPI(bp, p - 5, "atoes") /* tomatoes */
2769 || !BSTRCMPI(bp, p - 7, "dingoes")
2770 || !BSTRCMPI(bp, p - 7, "Aleaxes")) {
2771 *(p - 2) = '\0'; /* drop es */
2773 } /* else fall through to mins */
2775 /* ends in 's' but not 'es' */
2776 } else if (!BSTRCMPI(bp, p - 2, "us")) { /* lotus, fungus... */
2777 if (BSTRCMPI(bp, p - 6, "tengus") /* but not these... */
2778 && BSTRCMPI(bp, p - 7, "hezrous"))
2780 } else if (!BSTRCMPI(bp, p - 2, "ss")
2781 || !BSTRCMPI(bp, p - 5, " lens")
2782 || (p - 4 == bp && !strcmpi(p - 4, "lens"))) {
2786 *(p - 1) = '\0'; /* drop s */
2788 } else { /* input doesn't end in 's' */
2790 if (!BSTRCMPI(bp, p - 3, "men")) {
2791 Strcasecpy(p - 2, "an");
2794 /* matzot -> matzo, algae -> alga */
2795 if (!BSTRCMPI(bp, p - 6, "matzot") || !BSTRCMPI(bp, p - 2, "ae")) {
2796 *(p - 1) = '\0'; /* drop t/e */
2799 /* balactheria -> balactherium */
2800 if (p - 4 >= bp && !strcmpi(p - 2, "ia")
2801 && index("lr", lowc(*(p - 3))) && lowc(*(p - 4)) == 'e') {
2802 Strcasecpy(p - 1, "um"); /* a -> um */
2805 /* here we cannot find the plural suffix */
2809 /* if we stripped off a suffix (" of bar" from "foo of bar"),
2810 put it back now [strcat() isn't actually 100% safe here...] */
2816 char *str = nextobuf();
2817 Strcpy(str, oldstr);
2822 /* compare user string against object name string using fuzzy matching */
2824 wishymatch(u_str, o_str, retry_inverted)
2825 const char *u_str; /* from user, so might be variant spelling */
2826 const char *o_str; /* from objects[], so is in canonical form */
2827 boolean retry_inverted; /* optional extra "of" handling */
2829 static NEARDATA const char detect_SP[] = "detect ",
2830 SP_detection[] = " detection";
2831 char *p, buf[BUFSZ];
2833 /* ignore spaces & hyphens and upper/lower case when comparing */
2834 if (fuzzymatch(u_str, o_str, " -", TRUE))
2837 if (retry_inverted) {
2838 const char *u_of, *o_of;
2840 /* when just one of the strings is in the form "foo of bar",
2841 convert it into "bar foo" and perform another comparison */
2842 u_of = strstri(u_str, " of ");
2843 o_of = strstri(o_str, " of ");
2844 if (u_of && !o_of) {
2845 Strcpy(buf, u_of + 4);
2846 p = eos(strcat(buf, " "));
2847 while (u_str < u_of)
2850 return fuzzymatch(buf, o_str, " -", TRUE);
2851 } else if (o_of && !u_of) {
2852 Strcpy(buf, o_of + 4);
2853 p = eos(strcat(buf, " "));
2854 while (o_str < o_of)
2857 return fuzzymatch(u_str, buf, " -", TRUE);
2861 /* [note: if something like "elven speed boots" ever gets added, these
2862 special cases should be changed to call wishymatch() recursively in
2863 order to get the "of" inversion handling] */
2864 if (!strncmp(o_str, "dwarvish ", 9)) {
2865 if (!strncmpi(u_str, "dwarven ", 8))
2866 return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
2867 } else if (!strncmp(o_str, "elven ", 6)) {
2868 if (!strncmpi(u_str, "elvish ", 7))
2869 return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
2870 else if (!strncmpi(u_str, "elfin ", 6))
2871 return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
2872 } else if (!strncmp(o_str, detect_SP, sizeof detect_SP - 1)) {
2873 /* check for "detect <foo>" vs "<foo> detection" */
2874 if ((p = strstri(u_str, SP_detection)) != 0
2875 && !*(p + sizeof SP_detection - 1)) {
2876 /* convert "<foo> detection" into "detect <foo>" */
2878 Strcat(strcpy(buf, detect_SP), u_str);
2879 /* "detect monster" -> "detect monsters" */
2880 if (!strcmpi(u_str, "monster"))
2883 return fuzzymatch(buf, o_str, " -", TRUE);
2885 } else if (strstri(o_str, SP_detection)) {
2886 /* and the inverse, "<foo> detection" vs "detect <foo>" */
2887 if (!strncmpi(u_str, detect_SP, sizeof detect_SP - 1)) {
2888 /* convert "detect <foo>s" into "<foo> detection" */
2889 p = makesingular(u_str + sizeof detect_SP - 1);
2890 Strcat(strcpy(buf, p), SP_detection);
2891 /* caller may be looping through objects[], so avoid
2892 churning through all the obufs */
2894 return fuzzymatch(buf, o_str, " -", TRUE);
2896 } else if (strstri(o_str, "ability")) {
2897 /* when presented with "foo of bar", makesingular() used to
2898 singularize both foo & bar, but now only does so for foo */
2899 /* catch "{potion(s),ring} of {gain,restore,sustain} abilities" */
2900 if ((p = strstri(u_str, "abilities")) != 0
2901 && !*(p + sizeof "abilities" - 1)) {
2902 (void) strncpy(buf, u_str, (unsigned) (p - u_str));
2903 Strcpy(buf + (p - u_str), "ability");
2904 return fuzzymatch(buf, o_str, " -", TRUE);
2906 } else if (!strcmp(o_str, "aluminum")) {
2907 /* this special case doesn't really fit anywhere else... */
2908 /* (note that " wand" will have been stripped off by now) */
2909 if (!strcmpi(u_str, "aluminium"))
2910 return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
2917 const char *name, oclass;
2918 int f_o_range, l_o_range;
2921 /* wishable subranges of objects */
2922 STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
2923 { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
2924 { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
2925 { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
2926 { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
2927 { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
2928 { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
2929 { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
2930 { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
2931 { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
2932 { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
2933 { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
2934 { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
2935 { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
2936 { "dragon scales", ARMOR_CLASS, GRAY_DRAGON_SCALES,
2937 YELLOW_DRAGON_SCALES },
2938 { "dragon scale mail", ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL,
2939 YELLOW_DRAGON_SCALE_MAIL },
2940 { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
2941 { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
2942 { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
2943 { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
2947 #if 0 /*JP*//*not used*/
2948 /* alternate spellings; if the difference is only the presence or
2949 absence of spaces and/or hyphens (such as "pickaxe" vs "pick axe"
2950 vs "pick-axe") then there is no need for inclusion in this list;
2951 likewise for ``"of" inversions'' ("boots of speed" vs "speed boots") */
2952 struct alt_spellings {
2956 { "pickax", PICK_AXE },
2957 { "whip", BULLWHIP },
2958 { "saber", SILVER_SABER },
2959 { "silver sabre", SILVER_SABER },
2960 { "smooth shield", SHIELD_OF_REFLECTION },
2961 { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
2962 { "grey dragon scales", GRAY_DRAGON_SCALES },
2963 { "iron ball", HEAVY_IRON_BALL },
2964 { "lantern", BRASS_LANTERN },
2965 { "mattock", DWARVISH_MATTOCK },
2966 { "amulet of poison resistance", AMULET_VERSUS_POISON },
2967 { "potion of sleep", POT_SLEEPING },
2969 { "camera", EXPENSIVE_CAMERA },
2970 { "tee shirt", T_SHIRT },
2972 { "can opener", TIN_OPENER },
2973 { "kelp", KELP_FROND },
2974 { "eucalyptus", EUCALYPTUS_LEAF },
2975 { "royal jelly", LUMP_OF_ROYAL_JELLY },
2976 { "lembas", LEMBAS_WAFER },
2977 { "marker", MAGIC_MARKER },
2978 { "hook", GRAPPLING_HOOK },
2979 { "grappling iron", GRAPPLING_HOOK },
2980 { "grapnel", GRAPPLING_HOOK },
2981 { "grapple", GRAPPLING_HOOK },
2982 /* normally we wouldn't have to worry about unnecessary <space>, but
2983 " stone" will get stripped off, preventing a wishymatch; that actually
2984 lets "flint stone" be a match, so we also accept bogus "flintstone" */
2985 { "luck stone", LUCKSTONE },
2986 { "load stone", LOADSTONE },
2987 { "touch stone", TOUCHSTONE },
2988 { "flintstone", FLINT },
2989 { (const char *) 0, 0 },
2994 rnd_otyp_by_wpnskill(skill)
2998 short otyp = STRANGE_OBJECT;
2999 for (i = bases[WEAPON_CLASS];
3000 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3001 if (objects[i].oc_skill == skill) {
3007 for (i = bases[WEAPON_CLASS];
3008 i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3009 if (objects[i].oc_skill == skill)
3017 * Return something wished for. Specifying a null pointer for
3018 * the user request string results in a random object. Otherwise,
3019 * if asking explicitly for "nothing" (or "nil") return no_wish;
3020 * if not an object return &zeroobj; if an error (no matching object),
3025 readobjnam(bp, no_wish)
3027 struct obj *no_wish;
3031 register struct obj *otmp;
3032 int cnt, spe, spesgn, typ, very, rechrg;
3033 int blessed, uncursed, iscursed, ispoisoned, isgreased;
3034 int eroded, eroded2, erodeproof;
3035 int halfeaten, mntmp, contents;
3036 int islit, unlabeled, ishistoric, isdiluted, trapped;
3037 int tmp, tinv, tvariety;
3040 int ftype = context.current_fruit;
3041 char fruitbuf[BUFSZ];
3046 /* Fruits may not mess up the ability to wish for real objects (since
3047 * you can leave a fruit in a bones file and it will be added to
3048 * another person's game), so they must be checked for last, after
3049 * stripping all the possible prefixes and seeing if there's a real
3050 * name in there. So we have to save the full original name. However,
3051 * it's still possible to do things like "uncursed burnt Alaska",
3052 * or worse yet, "2 burned 5 course meals", so we need to loop to
3053 * strip off the prefixes again, this time stripping only the ones
3055 * We could get even more detailed so as to allow food names with
3056 * prefixes that _are_ possible on food, so you could wish for
3057 * "2 3 alarm chilis". Currently this isn't allowed; options.c
3058 * automatically sticks 'candied' in front of such names.
3061 char *un, *dn, *actualn;
3062 const char *name = 0;
3064 cnt = spe = spesgn = typ = very = rechrg = blessed = uncursed = iscursed =
3065 ispoisoned = isgreased = eroded = eroded2 = erodeproof = halfeaten =
3066 islit = unlabeled = ishistoric = isdiluted = trapped = 0;
3067 tvariety = RANDOM_TIN;
3072 contents = UNDEFINED;
3074 actualn = dn = un = 0;
3079 /* first, remove extra whitespace they may have typed */
3080 (void) mungspaces(bp);
3081 /* allow wishing for "nothing" to preserve wishless conduct...
3082 [now requires "wand of nothing" if that's what was really wanted] */
3084 if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil")
3085 || !strcmpi(bp, "none"))
3087 if (!strcmpi(bp, "
\82È
\82µ") || !strcmpi(bp, "
\96³
\82µ"))
3090 /* save the [nearly] unmodified choice string */
3091 Strcpy(fruitbuf, bp);
3098 if (!strncmpi(bp, "an ", l = 3) || !strncmpi(bp, "a ", l = 2)) {
3100 } else if (!strncmpi(bp, "the ", l = 4)) {
3101 ; /* just increment `bp' by `l' below */
3102 } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
3109 } else if (*bp == '+' || *bp == '-') {
3110 spesgn = (*bp++ == '+') ? 1 : -1;
3118 } else if (!strncmpi(bp, "blessed ", l = 8)
3119 || !strncmpi(bp, "holy ", l = 5)) {
3121 } else if (!strncmpi(bp, "
\8fj
\95\9f\82³
\82ê
\82½", l = 10)) {
3125 } else if (!strncmpi(bp, "moist ", l = 6)
3126 || !strncmpi(bp, "wet ", l = 4)) {
3128 } else if (!strncmpi(bp, "
\8e¼
\82Á
\82½", l = 6)
3129 || !strncmpi(bp, "
\94G
\82ê
\82½", l = 6)) {
3132 if (!strncmpi(bp, "wet ", 4))
3134 if (!strncmpi(bp, "
\94G
\82ê
\82½", 4))
3136 wetness = rn2(3) + 3;
3140 } else if (!strncmpi(bp, "cursed ", l = 7)
3141 || !strncmpi(bp, "unholy ", l = 7)) {
3143 } else if (!strncmpi(bp, "
\8eô
\82í
\82ê
\82½", l = 8)) {
3147 } else if (!strncmpi(bp, "uncursed ", l = 9)) {
3149 } else if (!strncmpi(bp, "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢", l = 9)) {
3153 } else if (!strncmpi(bp, "rustproof ", l = 10)
3154 || !strncmpi(bp, "erodeproof ", l = 11)
3155 || !strncmpi(bp, "corrodeproof ", l = 13)
3156 || !strncmpi(bp, "fixed ", l = 6)
3157 || !strncmpi(bp, "fireproof ", l = 10)
3158 || !strncmpi(bp, "rotproof ", l = 9)) {
3160 } else if (!strncmpi(bp, "
\8eK
\82Ñ
\82È
\82¢", l = 8)
3161 || !strncmpi(bp, "
\95\85\90H
\82µ
\82È
\82¢", l = 10)
3162 || !strncmpi(bp, "
\88À
\92è
\82µ
\82½", l = 8)
3163 || !strncmpi(bp, "
\94R
\82¦
\82È
\82¢", l = 8)) {
3166 } else if (!strncmpi(bp, "lit ", l = 4)
3167 || !strncmpi(bp, "burning ", l = 8)) {
3169 } else if (!strncmpi(bp, "unlit ", l = 6)
3170 || !strncmpi(bp, "extinguished ", l = 13)) {
3172 /* "unlabeled" and "blank" are synonymous */
3173 } else if (!strncmpi(bp, "unlabeled ", l = 10)
3174 || !strncmpi(bp, "unlabelled ", l = 11)
3175 || !strncmpi(bp, "blank ", l = 6)) {
3177 } else if (!strncmpi(bp, "poisoned ", l = 9)) {
3179 /* "trapped" recognized but not honored outside wizard mode */
3180 } else if (!strncmpi(bp, "trapped ", l = 8)) {
3181 trapped = 0; /* undo any previous "untrapped" */
3184 } else if (!strncmpi(bp, "untrapped ", l = 10)) {
3185 trapped = 2; /* not trapped */
3186 } else if (!strncmpi(bp, "greased ", l = 8)) {
3188 } else if (!strncmpi(bp, "very ", l = 5)) {
3189 /* very rusted very heavy iron ball */
3191 } else if (!strncmpi(bp, "thoroughly ", l = 11)) {
3193 } else if (!strncmpi(bp, "rusty ", l = 6)
3194 || !strncmpi(bp, "rusted ", l = 7)
3195 || !strncmpi(bp, "burnt ", l = 6)
3196 || !strncmpi(bp, "burned ", l = 7)) {
3199 } else if (!strncmpi(bp, "corroded ", l = 9)
3200 || !strncmpi(bp, "rotted ", l = 7)) {
3203 } else if (!strncmpi(bp, "partly eaten ", l = 13)
3204 || !strncmpi(bp, "partially eaten ", l = 16)) {
3206 } else if (!strncmpi(bp, "historic ", l = 9)) {
3208 } else if (!strncmpi(bp, "diluted ", l = 8)) {
3210 } else if (!strncmpi(bp, "empty ", l = 6)) {
3217 cnt = 1; /* %% what with "gems" etc. ? */
3218 if (strlen(bp) > 1 && (p = rindex(bp, '(')) != 0) {
3219 boolean keeptrailingchars = TRUE;
3221 p[(p > bp && p[-1] == ' ') ? -1 : 0] = '\0'; /*terminate bp */
3222 ++p; /* advance past '(' */
3223 if (!strncmpi(p, "lit)", 4)) {
3225 p += 4 - 1; /* point at ')' */
3239 /* mis-matched parentheses; rest of string will be ignored
3240 * [probably we should restore everything back to '('
3241 * instead since it might be part of "named ..."]
3243 keeptrailingchars = FALSE;
3248 if (keeptrailingchars) {
3251 /* 'pp' points at 'pb's terminating '\0',
3252 'p' points at ')' and will be incremented past it */
3259 * otmp->spe is type schar, so we don't want spe to be any bigger or
3260 * smaller. Also, spe should always be positive --some cheaters may
3261 * try to confuse atoi().
3264 spesgn = -1; /* cheaters get what they deserve */
3267 if (spe > SCHAR_LIM)
3269 if (rechrg < 0 || rechrg > 7)
3270 rechrg = 7; /* recharge_limit */
3272 /* now we have the actual name, as delivered by xname, say
3273 * green potions called whisky
3274 * scrolls labeled "QWERTY"
3277 * very heavy iron ball named hoei
3281 if ((p = strstri(bp, " named ")) != 0) {
3285 if ((p = strstri(bp, " called ")) != 0) {
3288 /* "helmet called telepathy" is not "helmet" (a specific type)
3289 * "shield called reflection" is not "shield" (a general type)
3291 for (i = 0; i < SIZE(o_ranges); i++)
3292 if (!strcmpi(bp, o_ranges[i].name)) {
3293 oclass = o_ranges[i].oclass;
3297 if ((p = strstri(bp, " labeled ")) != 0) {
3300 } else if ((p = strstri(bp, " labelled ")) != 0) {
3304 if ((p = strstri(bp, " of spinach")) != 0) {
3309 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8f\88\97\9d\82µ
\82È
\82¢*/
3311 Skip over "pair of ", "pairs of", "set of" and "sets of".
3313 Accept "3 pair of boots" as well as "3 pairs of boots". It is valid
3314 English either way. See makeplural() for more on pair/pairs.
3316 We should only double count if the object in question is not
3317 referred to as a "pair of". E.g. We should double if the player
3318 types "pair of spears", but not if the player types "pair of
3319 lenses". Luckily (?) all objects that are referred to as pairs
3320 -- boots, gloves, and lenses -- are also not mergable, so cnt is
3323 if (!strncmpi(bp, "pair of ", 8)) {
3326 } else if (cnt > 1 && !strncmpi(bp, "pairs of ", 9)) {
3329 } else if (!strncmpi(bp, "set of ", 7)) {
3331 } else if (!strncmpi(bp, "sets of ", 8)) {
3336 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8f\88\97\9d\82µ
\82È
\82¢*/
3337 /* intercept pudding globs here; they're a valid wish target,
3338 * but we need them to not get treated like a corpse.
3340 * also don't let player wish for multiple globs.
3342 if ((p = strstri(bp, "glob of ")) != 0
3343 || (p = strstri(bp, "globs of ")) != 0) {
3344 int globoffset = (*(p + 4) == 's') ? 9 : 8;
3345 if ((mntmp = name_to_mon(p + globoffset)) >= PM_GRAY_OOZE
3346 && mntmp <= PM_BLACK_PUDDING) {
3347 mntmp = NON_PM; /* lie to ourselves */
3348 cnt = 0; /* force only one */
3352 * Find corpse type using "of" (figurine of an orc, tin of orc meat)
3353 * Don't check if it's a wand or spellbook.
3354 * (avoid "wand/finger of death" confusion).
3356 if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
3357 && !strstri(bp, "finger ")) {
3358 if (((p = strstri(bp, "tin of ")) != 0)
3359 && (tmp = tin_variety_txt(p + 7, &tinv))
3360 && (mntmp = name_to_mon(p + 7 + tmp)) >= LOW_PM) {
3363 } else if ((p = strstri(bp, " of ")) != 0
3364 && (mntmp = name_to_mon(p + 4)) >= LOW_PM)
3369 /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
3370 if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */
3371 if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */
3372 if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */
3373 if (strncmpi(bp, "master key",
3374 10)) /* not the "master" rank */
3375 if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */
3376 if (mntmp < LOW_PM && strlen(bp) > 2
3377 && (mntmp = name_to_mon(bp)) >= LOW_PM) {
3379 mntmplen; /* double check for rank title */
3381 mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
3382 bp += mntmp != mntmptoo
3383 ? (int) strlen(mons[mntmp].mname)
3387 else if (!strncmpi(bp, "s ", 2))
3389 else if (!strncmpi(bp, "es ", 3))
3391 else if (!*bp && !actualn && !dn && !un
3393 /* no referent; they don't really mean a
3400 #if 0 /*JP*//*
\92P
\90\94\89»
\82Í
\82µ
\82È
\82¢*/
3401 /* first change to singular if necessary */
3403 char *sng = makesingular(bp);
3404 if (strcmp(bp, sng)) {
3412 #if 0 /*JP*//*
\83X
\83y
\83\8b\97h
\82ê
\8f\88\97\9d\82Í
\82µ
\82È
\82¢*/
3413 /* Alternate spellings (pick-ax, silver sabre, &c) */
3415 struct alt_spellings *as = spellings;
3418 if (fuzzymatch(bp, as->sp, " -", TRUE)) {
3424 /* can't use spellings list for this one due to shuffling */
3425 if (!strncmpi(bp, "grey spell", 10))
3428 if ((p = strstri(bp, "armour")) != 0) {
3429 /* skip past "armo", then copy remainder beyond "u" */
3431 while ((*p = *(p + 1)) != '\0')
3432 ++p; /* self terminating */
3437 /* dragon scales - assumes order of dragons */
3438 if (!strcmpi(bp, "scales") && mntmp >= PM_GRAY_DRAGON
3439 && mntmp <= PM_YELLOW_DRAGON) {
3440 typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
3441 mntmp = NON_PM; /* no monster */
3447 if (!BSTRCMPI(bp, p - 10, "holy water")) {
3449 if ((p - bp) >= 12 && *(p - 12) == 'u')
3450 iscursed = 1; /* unholy water */
3455 #else /*JP:
\90¹
\90\85\82Æ
\95s
\8fò
\82È
\90\85\82ð
\95Ê
\82É
\94»
\92è*/
3456 if (!BSTRCMPI(bp, p - 4, "
\90¹
\90\85")) {
3461 if (!BSTRCMPI(bp, p - 4, "
\95s
\8fò
\82È
\90\85")) {
3468 if (unlabeled && !BSTRCMPI(bp, p - 6, "scroll")) {
3470 if (unlabeled && !BSTRCMPI(bp, p - 4, "
\8aª
\95¨")) {
3472 typ = SCR_BLANK_PAPER;
3476 if (unlabeled && !BSTRCMPI(bp, p - 9, "spellbook")) {
3478 if (unlabeled && !BSTRCMPI(bp, p - 6, "
\96\82\96@
\8f\91")) {
3480 typ = SPE_BLANK_PAPER;
3484 * NOTE: Gold pieces are handled as objects nowadays, and therefore
3485 * this section should probably be reconsidered as well as the entire
3486 * gold/money concept. Maybe we want to add other monetary units as
3487 * well in the future. (TH)
3490 if (!BSTRCMPI(bp, p - 10, "gold piece") || !BSTRCMPI(bp, p - 7, "zorkmid")
3491 || !strcmpi(bp, "gold") || !strcmpi(bp, "money")
3492 || !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
3494 if (!BSTRCMPI(bp, p - 4, "
\8bà
\89Ý") || !BSTRCMPI(bp, p - 8, "
\83S
\81[
\83\8b\83h")
3495 || *bp == GOLD_SYM) {
3497 if (cnt > 5000 && !wizard)
3501 otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
3502 otmp->quan = (long) cnt;
3503 otmp->owt = weight(otmp);
3508 /* check for single character object class code ("/" for wand, &c) */
3509 if (strlen(bp) == 1 && (i = def_char_to_objclass(*bp)) < MAXOCLASSES
3510 && i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) {
3517 \89p
\8cê
\82È
\82ç XXXXX potion
\82Í
\95s
\8am
\92è
\96¼
\81Apotion of XXXXX
\82Í
\8am
\92è
\96¼
\82Æ
\82¢
\82¤
3518 \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¢
3520 /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */
3521 /* false hits on, e.g., rings for "ring mail". */
3522 if (strncmpi(bp, "enchant ", 8) && strncmpi(bp, "destroy ", 8)
3523 && strncmpi(bp, "detect food", 11)
3524 && strncmpi(bp, "food detection", 14) && strncmpi(bp, "ring mail", 9)
3525 && strncmpi(bp, "studded leather armor", 21)
3526 && strncmpi(bp, "leather armor", 13)
3527 && strncmpi(bp, "tooled horn", 11) && strncmpi(bp, "food ration", 11)
3528 && strncmpi(bp, "meat ring", 9))
3529 for (i = 0; i < (int) (sizeof wrpsym); i++) {
3530 register int j = strlen(wrp[i]);
3531 if (!strncmpi(bp, wrp[i], j)) {
3533 if (oclass != AMULET_CLASS) {
3535 if (!strncmpi(bp, " of ", 4))
3537 /* else if(*bp) ?? */
3542 if (!BSTRCMPI(bp, p - j, wrp[i])) {
3546 if (p > bp && p[-1] == ' ')
3554 /* Wishing in wizard mode can create traps and furniture.
3555 * Part I: distinguish between trap and object for the two
3556 * types of traps which have corresponding objects: bear trap
3557 * and land mine. "beartrap" (object) and "bear trap" (trap)
3558 * have a difference in spelling which we used to exploit by
3559 * adding a special case in wishymatch(), but "land mine" is
3560 * spelled the same either way so needs different handing.
3561 * Since we need something else for land mine, we've dropped
3562 * the bear trap hack so that both are handled exactly the
3563 * same. To get an armed trap instead of a disarmed object,
3564 * the player can prefix either the object name or the trap
3565 * name with "trapped " (which ordinarily applies to chests
3566 * and tins), or append something--anything at all except for
3567 * " object", but " trap" is suggested--to either the trap
3568 * name or the object name.
3570 if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) {
3571 boolean beartrap = (lowc(*bp) == 'b');
3572 char *zp = bp + 4; /* skip "bear"/"land" */
3575 ++zp; /* embedded space is optional */
3576 if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) {
3578 if (trapped == 2 || !strcmpi(zp, " object")) {
3579 /* "untrapped <foo>" or "<foo> object" */
3580 typ = beartrap ? BEARTRAP : LAND_MINE;
3582 } else if (trapped == 1 || *zp != '\0') {
3583 /* "trapped <foo>" or "<foo> trap" (actually "<foo>*") */
3584 int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE);
3586 /* use canonical trap spelling, skip object matching */
3587 Strcpy(bp, defsyms[idx].explanation);
3590 /* [no prefix or suffix; we're going to end up matching
3591 the object name and getting a disarmed trap object] */
3596 /* "grey stone" check must be before general "stone" */
3597 for (i = 0; i < SIZE(o_ranges); i++)
3598 if (!strcmpi(bp, o_ranges[i].name)) {
3599 typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
3603 if (!BSTRCMPI(bp, p - 6, " stone") || !BSTRCMPI(bp, p - 4, " gem")) {
3604 p[!strcmpi(p - 4, " gem") ? -4 : -6] = '\0';
3608 } else if (!strcmpi(bp, "looking glass")) {
3609 ; /* avoid false hit on "* glass" */
3610 } else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
3611 register char *g = bp;
3612 if (strstri(g, "broken"))
3613 return (struct obj *) 0;
3614 if (!strncmpi(g, "worthless ", 10))
3616 if (!strncmpi(g, "piece of ", 9))
3618 if (!strncmpi(g, "colored ", 8))
3620 else if (!strncmpi(g, "coloured ", 9))
3622 if (!strcmpi(g, "glass")) { /* choose random color */
3623 /* 9 different kinds */
3624 typ = LAST_GEM + rnd(9);
3625 if (objects[typ].oc_class == GEM_CLASS)
3628 typ = 0; /* somebody changed objects[]? punt */
3629 } else { /* try to construct canonical form */
3632 Strcpy(tbuf, "worthless piece of ");
3633 Strcat(tbuf, g); /* assume it starts with the color */
3640 dn = actualn; /* ex. "skull cap" */
3642 /* check real names of gems first */
3643 if (!oclass && actualn) {
3644 for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
3645 register const char *zn;
3647 if ((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) {
3653 i = oclass ? bases[(int) oclass] : 1;
3654 while (i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)) {
3655 register const char *zn;
3657 if (actualn && (zn = OBJ_NAME(objects[i])) != 0
3658 && wishymatch(actualn, zn, TRUE)) {
3663 if (dn && (zn = OBJ_DESCR(objects[i])) != 0
3664 && wishymatch(dn, zn, FALSE)) {
3666 *
\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É
3667 *
\82È
\82ç
\82È
\82¢
\82æ
\82¤
\82É
\82·
\82é
\81B
3668 *
\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
3670 if (i != FAKE_AMULET_OF_YENDOR &&
3671 dn && (zn = OBJ_DESCR(objects[i])) != 0
3672 && wishymatch(dn, zn, FALSE)) {
3674 /* don't match extra descriptions (w/o real name) */
3675 if (!OBJ_NAME(objects[i]))
3676 return (struct obj *) 0;
3680 if (un && (zn = objects[i].oc_uname) != 0
3681 && wishymatch(un, zn, FALSE)) {
3688 struct Jitem *j = Japanese_items;
3691 if (actualn && !strcmpi(actualn, j->name)) {
3698 /* if we've stripped off "armor" and failed to match anything
3699 in objects[], append "mail" and try again to catch misnamed
3700 requests like "plate armor" and "yellow dragon scale armor" */
3701 if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) {
3702 /* modifying bp's string is ok; we're about to resort
3703 to random armor if this also fails to match anything */
3704 Strcat(bp, " mail");
3708 if (!strcmpi(bp, "spinach")) {
3710 if (!strcmp(bp, "
\83z
\83E
\83\8c\83\93\91\90")) {
3716 /* Note: not strcmpi. 2 fruits, one capital, one not, are possible.
3717 Also not strncmp. We used to ignore trailing text with it, but
3718 that resulted in "grapefruit" matching "grape" if the latter came
3719 earlier than the former in the fruit list. */
3723 int blessedf, iscursedf, uncursedf, halfeatenf;
3725 blessedf = iscursedf = uncursedf = halfeatenf = 0;
3732 if (!strncmpi(fp, "an ", l = 3) || !strncmpi(fp, "a ", l = 2)) {
3734 } else if (!cntf && digit(*fp)) {
3741 } else if (!strncmpi(fp, "blessed ", l = 8)) {
3743 } else if (!strncmpi(fp, "cursed ", l = 7)) {
3745 } else if (!strncmpi(fp, "uncursed ", l = 9)) {
3747 } else if (!strncmpi(fp, "partly eaten ", l = 13)
3748 || !strncmpi(fp, "partially eaten ", l = 16)) {
3755 for (f = ffruit; f; f = f->nextf) {
3756 /* match type: 0=none, 1=exact, 2=singular, 3=plural */
3759 if (!strcmp(fp, f->fname))
3761 else if (!strcmp(fp, makesingular(f->fname)))
3763 else if (!strcmp(fp, makeplural(f->fname)))
3768 iscursed = iscursedf;
3769 uncursed = uncursedf;
3770 halfeaten = halfeatenf;
3771 /* adjust count if user explicitly asked for
3772 singular amount (can't happen unless fruit
3773 has been given an already pluralized name)
3774 or for plural amount */
3775 if (ftyp == 2 && !cntf)
3777 else if (ftyp == 3 && !cntf)
3786 if (!oclass && actualn) {
3789 /* Perhaps it's an artifact specified by name, not type */
3790 name = artifact_name(actualn, &objtyp);
3796 /* Let wizards wish for traps and furniture.
3797 * Must come after objects check so wizards can still wish for
3798 * trap objects like beartraps.
3799 * Disallow such topology tweaks for WIZKIT startup wishes.
3802 if (wizard && !program_state.wizkit_wishing) {
3804 int trap, x = u.ux, y = u.uy;
3806 for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
3810 tname = defsyms[trap_to_defsym(trap)].explanation;
3811 if (strncmpi(tname, bp, strlen(tname)))
3813 /* found it; avoid stupid mistakes */
3814 if ((trap == TRAPDOOR || trap == HOLE) && !Can_fall_thru(&u.uz))
3816 if ((t = maketrap(x, y, trap)) != 0) {
3818 tname = defsyms[trap_to_defsym(trap)].explanation;
3819 pline("%s%s.", An(tname),
3820 (trap != MAGIC_PORTAL) ? "" : " to nowhere");
3822 pline("Creation of %s failed.", an(tname));
3826 /* furniture and terrain */
3829 if (!BSTRCMPI(bp, p - 8, "fountain")) {
3830 lev->typ = FOUNTAIN;
3831 level.flags.nfountains++;
3832 if (!strncmpi(bp, "magic ", 6))
3833 lev->blessedftn = 1;
3834 pline("A %sfountain.", lev->blessedftn ? "magic " : "");
3838 if (!BSTRCMPI(bp, p - 6, "throne")) {
3844 if (!BSTRCMPI(bp, p - 4, "sink")) {
3846 level.flags.nsinks++;
3851 /* ("water" matches "potion of water" rather than terrain) */
3852 if (!BSTRCMPI(bp, p - 4, "pool") || !BSTRCMPI(bp, p - 4, "moat")) {
3853 lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT;
3855 pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
3856 /* Must manually make kelp! */
3857 water_damage_chain(level.objects[x][y], TRUE);
3861 if (!BSTRCMPI(bp, p - 4, "lava")) { /* also matches "molten lava" */
3862 lev->typ = LAVAPOOL;
3864 pline("A pool of molten lava.");
3865 if (!(Levitation || Flying))
3866 (void) lava_effects();
3871 if (!BSTRCMPI(bp, p - 5, "altar")) {
3875 if (!strncmpi(bp, "chaotic ", 8))
3877 else if (!strncmpi(bp, "neutral ", 8))
3879 else if (!strncmpi(bp, "lawful ", 7))
3881 else if (!strncmpi(bp, "unaligned ", 10))
3883 else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
3884 al = (!rn2(6)) ? A_NONE : rn2((int) A_LAWFUL + 2) - 1;
3885 lev->altarmask = Align2amask(al);
3886 pline("%s altar.", An(align_str(al)));
3891 if (!BSTRCMPI(bp, p - 5, "grave")
3892 || !BSTRCMPI(bp, p - 9, "headstone")) {
3893 make_grave(x, y, (char *) 0);
3894 pline("%s.", IS_GRAVE(lev->typ) ? "A grave"
3895 : "Can't place a grave here");
3900 if (!BSTRCMPI(bp, p - 4, "tree")) {
3908 if (!BSTRCMPI(bp, p - 4, "bars")) {
3909 lev->typ = IRONBARS;
3910 pline("Iron bars.");
3916 if (!oclass && !typ) {
3917 if (!strncmpi(bp, "polearm", 7)) {
3918 typ = rnd_otyp_by_wpnskill(P_POLEARMS);
3920 } else if (!strncmpi(bp, "hammer", 6)) {
3921 typ = rnd_otyp_by_wpnskill(P_HAMMER);
3927 return ((struct obj *) 0);
3930 oclass = wrpsym[rn2((int) sizeof(wrpsym))];
3933 oclass = objects[typ].oc_class;
3935 /* handle some objects that are only allowed in wizard mode */
3936 if (typ && !wizard) {
3938 case AMULET_OF_YENDOR:
3939 typ = FAKE_AMULET_OF_YENDOR;
3941 case CANDELABRUM_OF_INVOCATION:
3942 typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
3944 case BELL_OF_OPENING:
3947 case SPE_BOOK_OF_THE_DEAD:
3948 typ = SPE_BLANK_PAPER;
3954 /* catch any other non-wishable objects (venom) */
3955 if (objects[typ].oc_nowish)
3956 return (struct obj *) 0;
3962 * Create the object, then fine-tune it.
3964 otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE);
3965 typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */
3967 if (islit && (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN
3968 || Is_candle(otmp) || typ == POT_OIL)) {
3969 place_object(otmp, u.ux, u.uy); /* make it viable light source */
3970 begin_burn(otmp, FALSE);
3971 obj_extract_self(otmp); /* now release it for caller's use */
3974 /* if player specified a reasonable count, maybe honor it */
3975 if (cnt > 0 && objects[typ].oc_merge
3976 && (wizard || cnt < rnd(6) || (cnt <= 7 && Is_candle(otmp))
3977 || (cnt <= 20 && ((oclass == WEAPON_CLASS && is_ammo(otmp))
3978 || typ == ROCK || is_missile(otmp)))))
3979 otmp->quan = (long) cnt;
3981 if (oclass == VENOM_CLASS)
3986 } else if (wizard) {
3987 ; /* no alteration to spe */
3988 } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS
3990 || (oclass == RING_CLASS && objects[typ].oc_charged)) {
3991 if (spe > rnd(5) && spe > otmp->spe)
3993 if (spe > 2 && Luck < 0)
3996 if (oclass == WAND_CLASS) {
3997 if (spe > 1 && spesgn == -1)
4000 if (spe > 0 && spesgn == -1)
4003 if (spe > otmp->spe)
4010 /* set otmp->spe. This may, or may not, use spe... */
4013 if (contents == EMPTY) {
4014 otmp->corpsenm = NON_PM;
4016 } else if (contents == SPINACH) {
4017 otmp->corpsenm = NON_PM;
4023 otmp->spe = wetness;
4031 case HEAVY_IRON_BALL:
4034 /* otmp->cobj already done in mksobj() */
4043 otmp->spe = (rn2(10) ? -1 : 0);
4046 /* fall through, if wizard */
4051 /* set otmp->corpsenm or dragon scale [mail] */
4052 if (mntmp >= LOW_PM) {
4053 if (mntmp == PM_LONG_WORM_TAIL)
4054 mntmp = PM_LONG_WORM;
4058 otmp->spe = 0; /* No spinach */
4059 if (dead_species(mntmp, FALSE)) {
4060 otmp->corpsenm = NON_PM; /* it's empty */
4061 } else if (!(mons[mntmp].geno & G_UNIQ)
4062 && !(mvitals[mntmp].mvflags & G_NOCORPSE)
4063 && mons[mntmp].cnutrit != 0) {
4064 otmp->corpsenm = mntmp;
4068 if (!(mons[mntmp].geno & G_UNIQ)
4069 && !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
4070 if (mons[mntmp].msound == MS_GUARDIAN)
4071 mntmp = genus(mntmp, 1);
4072 set_corpsenm(otmp, mntmp);
4076 if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
4078 && mntmp != PM_MAIL_DAEMON
4081 otmp->corpsenm = mntmp;
4084 mntmp = can_be_hatched(mntmp);
4085 /* this also sets hatch timer if appropriate */
4086 set_corpsenm(otmp, mntmp);
4089 otmp->corpsenm = mntmp;
4090 if (Has_contents(otmp) && verysmall(&mons[mntmp]))
4091 delete_contents(otmp); /* no spellbook */
4092 otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
4095 /* Dragon mail - depends on the order of objects & dragons. */
4096 if (mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON)
4097 otmp->otyp = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4102 /* set blessed/cursed -- setting the fields directly is safe
4103 * since weight() is called below and addinv() will take care
4107 } else if (uncursed) {
4109 otmp->cursed = (Luck < 0 && !wizard);
4110 } else if (blessed) {
4111 otmp->blessed = (Luck >= 0 || wizard);
4112 otmp->cursed = (Luck < 0 && !wizard);
4113 } else if (spesgn < 0) {
4118 if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) {
4119 if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
4120 otmp->oeroded = eroded;
4121 if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
4122 otmp->oeroded2 = eroded2;
4124 /* set erodeproof */
4125 if (erodeproof && !eroded && !eroded2)
4126 otmp->oerodeproof = (Luck >= 0 || wizard);
4129 /* set otmp->recharged */
4130 if (oclass == WAND_CLASS) {
4131 /* prevent wishing abuse */
4132 if (otmp->otyp == WAN_WISHING && !wizard)
4134 otmp->recharged = (unsigned) rechrg;
4139 if (is_poisonable(otmp))
4140 otmp->opoisoned = (Luck >= 0);
4141 else if (oclass == FOOD_CLASS)
4142 /* try to taint by making it as old as possible */
4145 /* and [un]trapped */
4147 if (Is_box(otmp) || typ == TIN)
4148 otmp->otrapped = (trapped == 1);
4154 if (isdiluted && otmp->oclass == POTION_CLASS && otmp->otyp != POT_WATER)
4157 /* set tin variety */
4158 if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard))
4159 set_tin_variety(otmp, tvariety);
4165 /* an artifact name might need capitalization fixing */
4166 aname = artifact_name(name, &objtyp);
4167 if (aname && objtyp == otmp->otyp)
4170 /* 3.6.0 tribute - fix up novel */
4171 if (otmp->otyp == SPE_NOVEL) {
4172 const char *novelname;
4174 novelname = lookup_novel(name, &otmp->novelidx);
4179 otmp = oname(otmp, name);
4180 if (otmp->oartifact) {
4182 u.uconduct.wisharti++; /* KMH, conduct */
4186 /* more wishing abuse: don't allow wishing for certain artifacts */
4187 /* and make them pay; charge them for the wish anyway! */
4188 if ((is_quest_artifact(otmp)
4189 || (otmp->oartifact && rn2(nartifact_exist()) > 1)) && !wizard) {
4190 artifact_exists(otmp, safe_oname(otmp), FALSE);
4191 obfree(otmp, (struct obj *) 0);
4194 pline("For a moment, you feel %s in your %s, but it disappears!",
4196 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",
4197 something, makeplural(body_part(HAND)));
4200 if (halfeaten && otmp->oclass == FOOD_CLASS) {
4201 if (otmp->otyp == CORPSE)
4202 otmp->oeaten = mons[otmp->corpsenm].cnutrit;
4204 otmp->oeaten = objects[otmp->otyp].oc_nutrition;
4205 /* (do this adjustment before setting up object's weight) */
4206 consume_oeaten(otmp, 1);
4208 otmp->owt = weight(otmp);
4209 if (very && otmp->otyp == HEAVY_IRON_BALL)
4216 rnd_class(first, last)
4223 for (i = first; i <= last; i++)
4224 sum += objects[i].oc_prob;
4225 if (!sum) /* all zero */
4226 return first + rn2(last - first + 1);
4228 for (i = first; i <= last; i++)
4229 if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
4234 STATIC_OVL const char *
4235 Japanese_item_name(i)
4238 struct Jitem *j = Japanese_items;
4245 return (const char *) 0;
4249 suit_simple_name(suit)
4252 const char *suitnm, *esuitp;
4254 if (Is_dragon_mail(suit))
4255 return "dragon mail"; /* <color> dragon scale mail */
4256 else if (Is_dragon_scales(suit))
4257 return "dragon scales";
4258 suitnm = OBJ_NAME(objects[suit->otyp]);
4259 esuitp = eos((char *) suitnm);
4260 if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
4261 return "mail"; /* most suits fall into this category */
4262 else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
4263 return "jacket"; /* leather jacket */
4264 /* suit is lame but armor is ambiguous and body armor is absurd */
4269 cloak_simple_name(cloak)
4273 switch (cloak->otyp) {
4278 return "
\83\8d\81[
\83u";
4279 case MUMMY_WRAPPING:
4285 return (objects[cloak->otyp].oc_name_known && cloak->dknown)
4289 ? "
\83X
\83\82\83b
\83N"
4293 : "
\83G
\83v
\83\8d\83\93";
4301 return "
\83N
\83\8d\81[
\83N";
4304 /* helm vs hat for messages */
4306 helm_simple_name(helmet)
4310 * There is some wiggle room here; the result has been chosen
4311 * for consistency with the "protected by hard helmet" messages
4312 * given for various bonks on the head: headgear that provides
4313 * such protection is a "helm", that which doesn't is a "hat".
4315 * elven leather helm / leather hat -> hat
4316 * dwarvish iron helm / hard hat -> helm
4317 * The rest are completely straightforward:
4318 * fedora, cornuthaum, dunce cap -> hat
4319 * all other types of helmets -> helm
4322 return (helmet && !is_metallic(helmet)) ? "hat" : "helm";
4324 return (helmet && !is_metallic(helmet)) ? "
\96X
\8eq" : "
\8a\95";
4328 mimic_obj_name(mtmp)
4331 if (mtmp->m_ap_type == M_AP_OBJECT
4332 && mtmp->mappearance != STRANGE_OBJECT) {
4333 int idx = objects[mtmp->mappearance].oc_descr_idx;
4334 if (mtmp->mappearance == GOLD_PIECE)
4339 return obj_descr[idx].oc_name;
4342 return "whatcha-may-callit";
4344 return "
\89½
\82Æ
\82©
\82¢
\82¤
\82à
\82Ì";
4348 * Construct a query prompt string, based around an object name, which is
4349 * guaranteed to fit within [QBUFSZ]. Takes an optional prefix, three
4350 * choices for filling in the middle (two object formatting functions and a
4351 * last resort literal which should be very short), and an optional suffix.
4354 safe_qbuf(qbuf, qprefix, qsuffix, obj, func, altfunc, lastR)
4355 char *qbuf; /* output buffer */
4356 const char *qprefix, *qsuffix;
4358 char *FDECL((*func), (OBJ_P)), *FDECL((*altfunc), (OBJ_P));
4362 /* convert size_t (or int for ancient systems) to ordinary unsigned */
4363 unsigned len, lenlimit,
4364 len_qpfx = (unsigned) (qprefix ? strlen(qprefix) : 0),
4365 len_qsfx = (unsigned) (qsuffix ? strlen(qsuffix) : 0),
4366 len_lastR = (unsigned) strlen(lastR);
4368 lenlimit = QBUFSZ - 1;
4369 endp = qbuf + lenlimit;
4370 /* sanity check, aimed mainly at paniclog (it's conceivable for
4371 the result of short_oname() to be shorter than the length of
4372 the last resort string, but we ignore that possibility here) */
4373 if (len_qpfx > lenlimit)
4374 impossible("safe_qbuf: prefix too long (%u characters).", len_qpfx);
4375 else if (len_qpfx + len_qsfx > lenlimit)
4376 impossible("safe_qbuf: suffix too long (%u + %u characters).",
4377 len_qpfx, len_qsfx);
4378 else if (len_qpfx + len_lastR + len_qsfx > lenlimit)
4379 impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
4380 len_qpfx, len_lastR, len_qsfx);
4382 /* the output buffer might be the same as the prefix if caller
4383 has already partially filled it */
4384 if (qbuf == qprefix) {
4385 /* prefix is already in the buffer */
4387 } else if (qprefix) {
4388 /* put prefix into the buffer */
4389 (void) strncpy(qbuf, qprefix, lenlimit);
4392 /* no prefix; output buffer starts out empty */
4395 len = (unsigned) strlen(qbuf);
4397 if (len + len_lastR + len_qsfx > lenlimit) {
4398 /* too long; skip formatting, last resort output is truncated */
4399 if (len < lenlimit) {
4400 (void) strncpy(&qbuf[len], lastR, lenlimit - len);
4402 len = (unsigned) strlen(qbuf);
4403 if (qsuffix && len < lenlimit) {
4404 (void) strncpy(&qbuf[len], qsuffix, lenlimit - len);
4406 /* len = (unsigned) strlen(qbuf); */
4410 /* suffix and last resort are guaranteed to fit */
4411 len += len_qsfx; /* include the pending suffix */
4412 /* format the object */
4413 bufp = short_oname(obj, func, altfunc, lenlimit - len);
4414 if (len + strlen(bufp) <= lenlimit)
4415 Strcat(qbuf, bufp); /* formatted name fits */
4417 Strcat(qbuf, lastR); /* use last resort */
4421 Strcat(qbuf, qsuffix);
4423 /* assert( strlen(qbuf) < QBUFSZ ); */