OSDN Git Service

update year to 2020
[jnethack/source.git] / src / objnam.c
1 /* NetHack 3.6  objnam.c        $NHDT-Date: 1583315888 2020/03/04 09:58:08 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.293 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2011. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12
13 /* "an uncursed greased partly eaten guardian naga hatchling [corpse]" */
14 #if 0 /*JP*/
15 #define PREFIX 80 /* (56) */
16 #else
17 /* \81u\8eô\82í\82ê\82Ä\82¢\82È\82¢\96û\82Ì\93h\82ç\82ê\82½\90H\82×\82©\82¯\82Ì\83N\83\8d\83}\83e\83B\83b\83N\81E\83h\83\89\83S\83\93(\82Ì\8e\80\91Ì)\81v*/
18 #define PREFIX 100
19 #endif
20 #define SCHAR_LIM 127
21 #define NUMOBUF 12
22
23 STATIC_DCL char *FDECL(strprepend, (char *, const char *));
24 #if 0 /*JP*/
25 STATIC_DCL short FDECL(rnd_otyp_by_wpnskill, (SCHAR_P));
26 #endif
27 STATIC_DCL short FDECL(rnd_otyp_by_namedesc, (const char *, CHAR_P, int));
28 STATIC_DCL boolean FDECL(wishymatch, (const char *, const char *, BOOLEAN_P));
29 STATIC_DCL char *NDECL(nextobuf);
30 STATIC_DCL void FDECL(releaseobuf, (char *));
31 STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
32 STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
33 STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned));
34 STATIC_DCL char *FDECL(just_an, (char *str, const char *));
35 #if 0 /*JP*/
36 STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
37                                            const char *const *));
38 STATIC_DCL char *FDECL(singplur_compound, (char *));
39 #endif
40 STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
41 #if 0 /*JP*/
42 STATIC_DCL boolean FDECL(badman, (const char *, BOOLEAN_P));
43 #endif
44 STATIC_DCL char *FDECL(globwt, (struct obj *, char *, boolean *));
45
46 struct Jitem {
47     int item;
48     const char *name;
49 };
50
51 #define BSTRCMPI(base, ptr, str) ((ptr) < base || strcmpi((ptr), str))
52 #define BSTRNCMPI(base, ptr, str, num) \
53     ((ptr) < base || strncmpi((ptr), str, num))
54 #define Strcasecpy(dst, src) (void) strcasecpy(dst, src)
55
56 /* true for gems/rocks that should have " stone" appended to their names */
57 #define GemStone(typ)                                                  \
58     (typ == FLINT                                                      \
59      || (objects[typ].oc_material == GEMSTONE                          \
60          && (typ != DILITHIUM_CRYSTAL && typ != RUBY && typ != DIAMOND \
61              && typ != SAPPHIRE && typ != BLACK_OPAL && typ != EMERALD \
62              && typ != OPAL)))
63
64 #if 0 /*JP:T*/
65 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "wakizashi" },
66                                              { BROADSWORD, "ninja-to" },
67                                              { FLAIL, "nunchaku" },
68                                              { GLAIVE, "naginata" },
69                                              { LOCK_PICK, "osaku" },
70                                              { WOODEN_HARP, "koto" },
71                                              { KNIFE, "shito" },
72                                              { PLATE_MAIL, "tanko" },
73                                              { HELMET, "kabuto" },
74                                              { LEATHER_GLOVES, "yugake" },
75                                              { FOOD_RATION, "gunyoki" },
76                                              { POT_BOOZE, "sake" },
77                                              { 0, "" } };
78 #else
79 STATIC_OVL struct Jitem Japanese_items[] = { { SHORT_SWORD, "\98e\8d·\82µ" },
80                                              { BROADSWORD, "\94E\8eÒ\93\81" },
81                                              { FLAIL, "\83k\83\93\83`\83\83\83N" },
82                                              { GLAIVE, "\82È\82¬\82È\82½" },
83                                              { LOCK_PICK, "\82¨\82³\82­" },
84                                              { WOODEN_HARP, "\8bÕ" },
85                                              { KNIFE, "\8eh\93\81" },
86                                              { PLATE_MAIL, "\92Z\8db" },
87                                              { HELMET, "\8a\95" },
88                                              { LEATHER_GLOVES, "\8b|\8c\9c" },
89                                              { FOOD_RATION, "\8aÛ\96ò" },
90                                              { POT_BOOZE, "\8eð" },
91                                              { 0, "" } };
92 #endif
93
94 STATIC_DCL const char *FDECL(Japanese_item_name, (int i));
95
96 STATIC_OVL char *
97 strprepend(s, pref)
98 register char *s;
99 register const char *pref;
100 {
101     register int i = (int) strlen(pref);
102
103     if (i > PREFIX) {
104         impossible("PREFIX too short (for %d).", i);
105         return s;
106     }
107     s -= i;
108     (void) strncpy(s, pref, i); /* do not copy trailing 0 */
109     return s;
110 }
111
112 /* manage a pool of BUFSZ buffers, so callers don't have to */
113 static char NEARDATA obufs[NUMOBUF][BUFSZ];
114 static int obufidx = 0;
115
116 STATIC_OVL char *
117 nextobuf()
118 {
119     obufidx = (obufidx + 1) % NUMOBUF;
120     return obufs[obufidx];
121 }
122
123 /* put the most recently allocated buffer back if possible */
124 STATIC_OVL void
125 releaseobuf(bufp)
126 char *bufp;
127 {
128     /* caller may not know whether bufp is the most recently allocated
129        buffer; if it isn't, do nothing; note that because of the somewhat
130        obscure PREFIX handling for object name formatting by xname(),
131        the pointer our caller has and is passing to us might be into the
132        middle of an obuf rather than the address returned by nextobuf() */
133     if (bufp >= obufs[obufidx]
134         && bufp < obufs[obufidx] + sizeof obufs[obufidx]) /* obufs[][BUFSZ] */
135         obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
136 }
137
138 char *
139 obj_typename(otyp)
140 register int otyp;
141 {
142     char *buf = nextobuf();
143     struct objclass *ocl = &objects[otyp];
144     const char *actualn = OBJ_NAME(*ocl);
145     const char *dn = OBJ_DESCR(*ocl);
146     const char *un = ocl->oc_uname;
147     int nn = ocl->oc_name_known;
148
149     if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
150         actualn = Japanese_item_name(otyp);
151 #if 1 /*JP*/
152     if(un)
153         Sprintf(buf, "%s\82Æ\8cÄ\82Î\82ê\82é", un);
154 #endif
155     switch (ocl->oc_class) {
156     case COIN_CLASS:
157 /*JP
158         Strcpy(buf, "coin");
159 */
160         Strcat(buf, "\8bà\89Ý");
161         break;
162     case POTION_CLASS:
163 /*JP
164         Strcpy(buf, "potion");
165 */
166         Strcat(buf, "\96ò");
167         break;
168     case SCROLL_CLASS:
169 /*JP
170         Strcpy(buf, "scroll");
171 */
172         Strcat(buf, "\8aª\95¨");
173         break;
174     case WAND_CLASS:
175 /*JP
176         Strcpy(buf, "wand");
177 */
178         Strcat(buf, "\8fñ");
179         break;
180     case SPBOOK_CLASS:
181         if (otyp != SPE_NOVEL) {
182 /*JP
183             Strcpy(buf, "spellbook");
184 */
185             Strcat(buf, "\96\82\96@\8f\91");
186         } else {
187 /*JP
188             Strcpy(buf, !nn ? "book" : "novel");
189 */
190             Strcpy(buf, !nn ? "\96{" : "\8f¬\90à");
191             nn = 0;
192         }
193         break;
194     case RING_CLASS:
195 /*JP
196         Strcpy(buf, "ring");
197 */
198         Strcat(buf, "\8ew\97Ö");
199         break;
200     case AMULET_CLASS:
201 #if 0 /*JP*/
202         if (nn)
203             Strcpy(buf, actualn);
204         else
205             Strcpy(buf, "amulet");
206         if (un)
207             Sprintf(eos(buf), " called %s", un);
208         if (dn)
209             Sprintf(eos(buf), " (%s)", dn);
210         return buf;
211 #else
212         if (nn)
213             Strcat(buf, actualn);
214         else if(un)
215             Strcat(buf, "\96\82\8f\9c\82¯");
216         break;
217 #endif
218 #if 1 /*JP*/
219     case GEM_CLASS:
220         if(nn)
221           Strcat(buf, actualn);
222         else if(un)
223           Strcat(buf, "\95ó\90Î");
224         break;
225 #endif
226     default:
227         if (nn) {
228 #if 0 /*JP*/
229             Strcpy(buf, actualn);
230             if (GemStone(otyp))
231                 Strcat(buf, " stone");
232             if (un)
233                 Sprintf(eos(buf), " called %s", un);
234             if (dn)
235                 Sprintf(eos(buf), " (%s)", dn);
236 #else
237             Strcat(buf, actualn);
238 #endif
239         } else {
240 #if 0 /*JP*/
241             Strcpy(buf, dn ? dn : actualn);
242             if (ocl->oc_class == GEM_CLASS)
243                 Strcat(buf,
244                        (ocl->oc_material == MINERAL) ? " stone" : " gem");
245             if (un)
246                 Sprintf(eos(buf), " called %s", un);
247 #else
248             Strcat(buf, dn ? dn : actualn);
249 #endif
250         }
251 #if 0 /*JP*/
252         return buf;
253 #else
254         break;
255 #endif
256     }
257     /* here for ring/scroll/potion/wand */
258     if (nn) {
259 #if 0 /*JP*/
260         if (ocl->oc_unique)
261             Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
262         else
263             Sprintf(eos(buf), " of %s", actualn);
264 #else
265         Strcpy(buf, actualn);
266 #endif
267     }
268 #if 0 /*JP*/
269     if (un)
270         Sprintf(eos(buf), " called %s", un);
271 #endif
272     if (dn)
273 #if 0 /*JP*/
274         Sprintf(eos(buf), " (%s)", dn);
275 #else
276         Sprintf(eos(buf), "(%s)", dn);
277 #endif
278     return buf;
279 }
280
281 /* less verbose result than obj_typename(); either the actual name
282    or the description (but not both); user-assigned name is ignored */
283 char *
284 simple_typename(otyp)
285 int otyp;
286 {
287     char *bufp, *pp, *save_uname = objects[otyp].oc_uname;
288
289     objects[otyp].oc_uname = 0; /* suppress any name given by user */
290     bufp = obj_typename(otyp);
291     objects[otyp].oc_uname = save_uname;
292     if ((pp = strstri(bufp, " (")) != 0)
293         *pp = '\0'; /* strip the appended description */
294     return bufp;
295 }
296
297 /* typename for debugging feedback where data involved might be suspect */
298 char *
299 safe_typename(otyp)
300 int otyp;
301 {
302     unsigned save_nameknown;
303     char *res = 0;
304
305     if (otyp < STRANGE_OBJECT || otyp >= NUM_OBJECTS
306         || !OBJ_NAME(objects[otyp])) {
307         res = nextobuf();
308         Sprintf(res, "glorkum[%d]", otyp);
309     } else {
310         /* force it to be treated as fully discovered */
311         save_nameknown = objects[otyp].oc_name_known;
312         objects[otyp].oc_name_known = 1;
313         res = simple_typename(otyp);
314         objects[otyp].oc_name_known = save_nameknown;
315     }
316     return res;
317 }
318
319 boolean
320 obj_is_pname(obj)
321 struct obj *obj;
322 {
323     if (!obj->oartifact || !has_oname(obj))
324         return FALSE;
325     if (!program_state.gameover && !iflags.override_ID) {
326         if (not_fully_identified(obj))
327             return FALSE;
328     }
329     return TRUE;
330 }
331
332 /* used by distant_name() to pass extra information to xname_flags();
333    it would be much cleaner if this were a parameter, but that would
334    require all of the xname() and doname() calls to be modified */
335 static int distantname = 0;
336
337 /* Give the name of an object seen at a distance.  Unlike xname/doname,
338  * we don't want to set dknown if it's not set already.
339  */
340 char *
341 distant_name(obj, func)
342 struct obj *obj;
343 char *FDECL((*func), (OBJ_P));
344 {
345     char *str;
346
347     /* 3.6.1: this used to save Blind, set it, make the call, then restore
348      * the saved value; but the Eyes of the Overworld override blindness
349      * and let characters wearing them get dknown set for distant items.
350      *
351      * TODO? if the hero is wearing those Eyes, figure out whether the
352      * object is within X-ray radius and only treat it as distant when
353      * beyond that radius.  Logic is iffy but result might be interesting.
354      */
355     ++distantname;
356     str = (*func)(obj);
357     --distantname;
358     return str;
359 }
360
361 /* convert player specified fruit name into corresponding fruit juice name
362    ("slice of pizza" -> "pizza juice" rather than "slice of pizza juice") */
363 char *
364 fruitname(juice)
365 boolean juice; /* whether or not to append " juice" to the name */
366 {
367 #if 0 /*JP*/
368     char *buf = nextobuf();
369     const char *fruit_nam = strstri(pl_fruit, " of ");
370
371     if (fruit_nam)
372         fruit_nam += 4; /* skip past " of " */
373     else
374         fruit_nam = pl_fruit; /* use it as is */
375
376     Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
377     return buf;
378 #else
379     /*\93ú\96{\8cê\82Å\82Í\82»\82±\82Ü\82Å\82µ\82È\82¢*/
380     char *buf = nextobuf();
381     Sprintf(buf, "%s%s", pl_fruit, juice ? "\83W\83\85\81[\83X" : "");
382     return buf;
383 #endif
384 }
385
386 /* look up a named fruit by index (1..127) */
387 struct fruit *
388 fruit_from_indx(indx)
389 int indx;
390 {
391     struct fruit *f;
392
393     for (f = ffruit; f; f = f->nextf)
394         if (f->fid == indx)
395             break;
396     return f;
397 }
398
399 /* look up a named fruit by name */
400 struct fruit *
401 fruit_from_name(fname, exact, highest_fid)
402 const char *fname;
403 boolean exact; /* False => prefix or exact match, True = exact match only */
404 int *highest_fid; /* optional output; only valid if 'fname' isn't found */
405 {
406     struct fruit *f, *tentativef;
407     char *altfname;
408     unsigned k;
409     /*
410      * note: named fruits are case-senstive...
411      */
412
413     if (highest_fid)
414         *highest_fid = 0;
415     /* first try for an exact match */
416     for (f = ffruit; f; f = f->nextf)
417         if (!strcmp(f->fname, fname))
418             return f;
419         else if (highest_fid && f->fid > *highest_fid)
420             *highest_fid = f->fid;
421
422     /* didn't match as-is; if caller is willing to accept a prefix
423        match, try to find one; we want to find the longest prefix that
424        matches, not the first */
425     if (!exact) {
426         tentativef = 0;
427         for (f = ffruit; f; f = f->nextf) {
428             k = strlen(f->fname);
429             if (!strncmp(f->fname, fname, k)
430                 && (!fname[k] || fname[k] == ' ')
431                 && (!tentativef || k > strlen(tentativef->fname)))
432                 tentativef = f;
433         }
434         f = tentativef;
435     }
436     /* if we still don't have a match, try singularizing the target;
437        for exact match, that's trivial, but for prefix, it's hard */
438     if (!f) {
439         altfname = makesingular(fname);
440         for (f = ffruit; f; f = f->nextf) {
441             if (!strcmp(f->fname, altfname))
442                 break;
443         }
444         releaseobuf(altfname);
445     }
446     if (!f && !exact) {
447         char fnamebuf[BUFSZ], *p;
448         unsigned fname_k = strlen(fname); /* length of assumed plural fname */
449
450         tentativef = 0;
451         for (f = ffruit; f; f = f->nextf) {
452             k = strlen(f->fname);
453             /* reload fnamebuf[] each iteration in case it gets modified;
454                there's no need to recalculate fname_k */
455             Strcpy(fnamebuf, fname);
456             /* bug? if singular of fname is longer than plural,
457                failing the 'fname_k > k' test could skip a viable
458                candidate; unfortunately, we can't singularize until
459                after stripping off trailing stuff and we can't get
460                accurate fname_k until fname has been singularized;
461                compromise and use 'fname_k >= k' instead of '>',
462                accepting 1 char length discrepancy without risking
463                false match (I hope...) */
464             if (fname_k >= k && (p = index(&fnamebuf[k], ' ')) != 0) {
465                 *p = '\0'; /* truncate at 1st space past length of f->fname */
466                 altfname = makesingular(fnamebuf);
467                 k = strlen(altfname); /* actually revised 'fname_k' */
468                 if (!strcmp(f->fname, altfname)
469                     && (!tentativef || k > strlen(tentativef->fname)))
470                     tentativef = f;
471                 releaseobuf(altfname); /* avoid churning through all obufs */
472             }
473         }
474         f = tentativef;
475     }
476     return f;
477 }
478
479 /* sort the named-fruit linked list by fruit index number */
480 void
481 reorder_fruit(forward)
482 boolean forward;
483 {
484     struct fruit *f, *allfr[1 + 127];
485     int i, j, k = SIZE(allfr);
486
487     for (i = 0; i < k; ++i)
488         allfr[i] = (struct fruit *) 0;
489     for (f = ffruit; f; f = f->nextf) {
490         /* without sanity checking, this would reduce to 'allfr[f->fid]=f' */
491         j = f->fid;
492         if (j < 1 || j >= k) {
493             impossible("reorder_fruit: fruit index (%d) out of range", j);
494             return; /* don't sort after all; should never happen... */
495         } else if (allfr[j]) {
496             impossible("reorder_fruit: duplicate fruit index (%d)", j);
497             return;
498         }
499         allfr[j] = f;
500     }
501     ffruit = 0; /* reset linked list; we're rebuilding it from scratch */
502     /* slot [0] will always be empty; must start 'i' at 1 to avoid
503        [k - i] being out of bounds during first iteration */
504     for (i = 1; i < k; ++i) {
505         /* for forward ordering, go through indices from high to low;
506            for backward ordering, go from low to high */
507         j = forward ? (k - i) : i;
508         if (allfr[j]) {
509             allfr[j]->nextf = ffruit;
510             ffruit = allfr[j];
511         }
512     }
513 }
514
515 char *
516 xname(obj)
517 struct obj *obj;
518 {
519     return xname_flags(obj, CXN_NORMAL);
520 }
521
522 STATIC_OVL char *
523 xname_flags(obj, cxn_flags)
524 register struct obj *obj;
525 unsigned cxn_flags; /* bitmask of CXN_xxx values */
526 {
527     register char *buf;
528     register int typ = obj->otyp;
529     register struct objclass *ocl = &objects[typ];
530     int nn = ocl->oc_name_known, omndx = obj->corpsenm;
531     const char *actualn = OBJ_NAME(*ocl);
532     const char *dn = OBJ_DESCR(*ocl);
533     const char *un = ocl->oc_uname;
534     boolean pluralize = (obj->quan != 1L) && !(cxn_flags & CXN_SINGULAR);
535     boolean known, dknown, bknown;
536
537     buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
538     if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
539         actualn = Japanese_item_name(typ);
540     /* As of 3.6.2: this used to be part of 'dn's initialization, but it
541        needs to come after possibly overriding 'actualn' */
542     if (!dn)
543         dn = actualn;
544
545     buf[0] = '\0';
546     /*
547      * clean up known when it's tied to oc_name_known, eg after AD_DRIN
548      * This is only required for unique objects since the article
549      * printed for the object is tied to the combination of the two
550      * and printing the wrong article gives away information.
551      */
552     if (!nn && ocl->oc_uses_known && ocl->oc_unique)
553         obj->known = 0;
554     if (!Blind && !distantname)
555         obj->dknown = 1;
556     if (Role_if(PM_PRIEST))
557         obj->bknown = 1; /* actively avoid set_bknown();
558                           * we mustn't call update_inventory() now because
559                           * it would call xname() (via doname()) recursively
560                           * and could end up clobbering all the obufs... */
561
562     if (iflags.override_ID) {
563         known = dknown = bknown = TRUE;
564         nn = 1;
565     } else {
566         known = obj->known;
567         dknown = obj->dknown;
568         bknown = obj->bknown;
569     }
570
571     if (obj_is_pname(obj))
572 #if 0 /*JP*/
573         goto nameit;
574 #else
575     {
576         Strcat(buf, ONAME(obj));
577         goto nameit;
578     }
579 #endif
580 #if 1 /*JP*/
581     if (has_oname(obj) && dknown) {
582         Strcat(buf, ONAME(obj));
583         Strcat(buf, "\82Æ\96¼\82Ã\82¯\82ç\82ê\82½");
584     }
585 #endif
586     switch (obj->oclass) {
587     case AMULET_CLASS:
588         if (!dknown)
589 /*JP
590             Strcpy(buf, "amulet");
591 */
592             Strcat(buf, "\96\82\8f\9c\82¯");  
593         else if (typ == AMULET_OF_YENDOR || typ == FAKE_AMULET_OF_YENDOR)
594             /* each must be identified individually */
595             Strcpy(buf, known ? actualn : dn);
596         else if (nn)
597             Strcpy(buf, actualn);
598         else if (un)
599 /*JP
600             Sprintf(buf, "amulet called %s", un);
601 */
602             Sprintf(eos(buf), "%s\82Æ\8cÄ\82Î\82ê\82é\96\82\8f\9c\82¯", un);
603         else
604 /*JP
605             Sprintf(buf, "%s amulet", dn);
606 */
607             Sprintf(eos(buf), "%s", dn);
608         break;
609     case WEAPON_CLASS:
610         if (is_poisonable(obj) && obj->opoisoned)
611 /*JP
612             Strcpy(buf, "poisoned ");
613 */
614             Strcpy(buf, "\93Å\82Ì\93h\82ç\82ê\82½");
615         /*FALLTHRU*/
616     case VENOM_CLASS:
617     case TOOL_CLASS:
618 #if 1 /*JP*/
619         if (typ == FIGURINE)
620             Sprintf(eos(buf), "%s\82Ì", mons[obj->corpsenm].mname);
621 #endif
622         if (typ == LENSES)
623 /*JP
624             Strcpy(buf, "pair of ");
625 */
626             Strcpy(buf, "\88ê\91Î\82Ì");
627         else if (is_wet_towel(obj))
628 /*JP
629             Strcpy(buf, (obj->spe < 3) ? "moist " : "wet ");
630 */
631             Strcpy(buf, (obj->spe < 3) ? "\8e¼\82Á\82½" : "\94G\82ê\82½");
632
633         if (!dknown)
634             Strcat(buf, dn);
635         else if (nn)
636             Strcat(buf, actualn);
637         else if (un) {
638 #if 0 /*JP*/
639             Strcat(buf, dn);
640             Strcat(buf, " called ");
641             Strcat(buf, un);
642 #else
643             Strcat(buf, un);
644             Strcat(buf, "\82Æ\8cÄ\82Î\82ê\82é");
645             Strcat(buf, dn);
646 #endif
647         } else
648             Strcat(buf, dn);
649
650 #if 0 /*JP*/ /*\82±\82ê\82Í\8cê\8f\87\82Ì\8aÖ\8cW\82©\82ç\8fã\82Ì\95û\82Å\92è\8b`*/
651         if (typ == FIGURINE && omndx != NON_PM) {
652             char anbuf[10]; /* [4] would be enough: 'a','n',' ','\0' */
653
654             Sprintf(eos(buf), " of %s%s",
655                     just_an(anbuf, mons[omndx].mname),
656                     mons[omndx].mname);
657         } else if (is_wet_towel(obj)) {
658 #else
659         if (is_wet_towel(obj)) {
660 #endif
661             if (wizard)
662                 Sprintf(eos(buf), " (%d)", obj->spe);
663         }
664         break;
665     case ARMOR_CLASS:
666         /* depends on order of the dragon scales objects */
667         if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
668 /*JP
669             Sprintf(buf, "set of %s", actualn);
670 */
671             Sprintf(buf, "%s\88ê\8e®", actualn);
672             break;
673         }
674         if (is_boots(obj) || is_gloves(obj))
675 /*JP
676             Strcpy(buf, "pair of ");
677 */
678             Strcat(buf,"\88ê\91Î\82Ì");
679
680         if (obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
681             && !dknown) {
682 /*JP
683             Strcpy(buf, "shield");
684 */
685             Strcat(buf, "\8f\82");
686             break;
687         }
688         if (obj->otyp == SHIELD_OF_REFLECTION && !dknown) {
689 /*JP
690             Strcpy(buf, "smooth shield");
691 */
692             Strcat(buf, "\82·\82×\82·\82×\82µ\82½\8f\82");
693             break;
694         }
695
696         if (nn) {
697             Strcat(buf, actualn);
698         } else if (un) {
699 #if 0 /*JP*/
700             if (is_boots(obj))
701                 Strcat(buf, "boots");
702             else if (is_gloves(obj))
703                 Strcat(buf, "gloves");
704             else if (is_cloak(obj))
705                 Strcpy(buf, "cloak");
706             else if (is_helmet(obj))
707                 Strcpy(buf, "helmet");
708             else if (is_shield(obj))
709                 Strcpy(buf, "shield");
710             else
711                 Strcpy(buf, "armor");
712             Strcat(buf, " called ");
713             Strcat(buf, un);
714 #else
715             const char *p;
716             if (is_boots(obj))
717                 p = "\8cC";
718             else if (is_gloves(obj))
719                 p = "\8f¬\8eè";
720             else if (is_cloak(obj))
721                 p = "\83N\83\8d\81[\83N";
722             else if (is_helmet(obj))
723                 p = "\8a\95";
724             else if (is_shield(obj))
725                 p = "\8f\82";
726             else
727                 p = "\8aZ";
728             Sprintf(eos(buf), "%s\82Æ\8cÄ\82Î\82ê\82é%s", un, p);
729 #endif
730         } else
731             Strcat(buf, dn);
732         break;
733     case FOOD_CLASS:
734         if (typ == SLIME_MOLD) {
735             struct fruit *f = fruit_from_indx(obj->spe);
736
737             if (!f) {
738                 impossible("Bad fruit #%d?", obj->spe);
739                 Strcpy(buf, "fruit");
740             } else {
741                 Strcpy(buf, f->fname);
742                 if (pluralize) {
743                     /* ick; already pluralized fruit names
744                        are allowed--we want to try to avoid
745                        adding a redundant plural suffix */
746                     Strcpy(buf, makeplural(makesingular(buf)));
747                     pluralize = FALSE;
748                 }
749             }
750             break;
751         }
752         if (obj->globby) {
753             Sprintf(buf, "%s%s",
754                     (obj->owt <= 100)
755 /*JP
756                        ? "small "
757 */
758                        ? "\8f¬\82³\82¢"
759                        : (obj->owt > 500)
760 /*JP
761                           ? "very large "
762 */
763                           ? "\82Æ\82Ä\82à\91å\82«\82¢"
764                           : (obj->owt > 300)
765 /*JP
766                              ? "large "
767 */
768                              ? "\91å\82«\82¢"
769                              : "",
770                     actualn);
771             break;
772         }
773
774 #if 0 /*JP*/
775         Strcpy(buf, actualn);
776         if (typ == TIN && known)
777             tin_details(obj, omndx, buf);
778 #else
779         if (typ == TIN && known)
780             /*JP \81u\81`\82Ì\93÷\82Ì\81v*/
781             tin_details(obj, omndx, buf);
782         Strcat(buf, actualn);
783 #endif
784         break;
785     case COIN_CLASS:
786     case CHAIN_CLASS:
787 #if 0 /*JP*/
788         Strcpy(buf, actualn);
789 #else
790         Strcat(buf, actualn);
791 #endif
792         break;
793     case ROCK_CLASS:
794         if (typ == STATUE && omndx != NON_PM) {
795 #if 0 /*JP*/
796             char anbuf[10];
797
798             Sprintf(buf, "%s%s of %s%s",
799                     (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
800                        ? "historic "
801                        : "",
802                     actualn,
803                     type_is_pname(&mons[omndx])
804                        ? ""
805                        : the_unique_pm(&mons[omndx])
806                           ? "the "
807                           : just_an(anbuf, mons[omndx].mname),
808                     mons[omndx].mname);
809 #else
810             Sprintf(eos(buf), "%s%s\82Ì%s", 
811                     (Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC))
812                     ? "\97ð\8ej\93I\82È"
813                     : "",
814                     mons[obj->corpsenm].mname, actualn);
815 #endif
816         } else
817 #if 0 /*JP*/
818             Strcpy(buf, actualn);
819 #else
820             Strcat(buf, actualn);
821 #endif
822         break;
823     case BALL_CLASS:
824 #if 0 /*JP*/
825         Sprintf(buf, "%sheavy iron ball",
826                 (obj->owt > ocl->oc_weight) ? "very " : "");
827 #else
828         Sprintf(eos(buf), "%s\8fd\82¢\93S\8b\85",
829                 (obj->owt > ocl->oc_weight) ? "\82Æ\82Ä\82à" : "");
830 #endif
831         break;
832     case POTION_CLASS:
833         if (dknown && obj->odiluted)
834 /*JP
835             Strcpy(buf, "diluted ");
836 */
837             Strcat(buf, "\94\96\82Ü\82Á\82½");
838         if (nn || un || !dknown) {
839 #if 0 /*JP*/
840             Strcat(buf, "potion");
841             if (!dknown)
842                 break;
843 #else
844             if (!dknown){
845                 Strcat(buf, "\96ò");
846                 break;
847             }
848 #endif
849             if (nn) {
850 #if 0 /*JP*/
851                 Strcat(buf, " of ");
852 #endif
853                 if (typ == POT_WATER && bknown
854                     && (obj->blessed || obj->cursed)) {
855 /*JP
856                     Strcat(buf, obj->blessed ? "holy " : "unholy ");
857 */
858                     Strcat(buf, obj->blessed ? "\90¹" : "\95s\8fò\82È");
859                 }
860                 Strcat(buf, actualn);
861             } else {
862 #if 0 /*JP*/
863                 Strcat(buf, " called ");
864                 Strcat(buf, un);
865 #else
866                 Strcat(buf, un);
867                 Strcat(buf, "\82Æ\8cÄ\82Î\82ê\82é\96ò");
868 #endif
869             }
870         } else {
871             Strcat(buf, dn);
872 #if 0 /*JP*//*\95s\8am\92è\96¼\82É\81u\96ò\81v\82Í\95t\82¢\82Ä\82¢\82é*/
873             Strcat(buf, " potion");
874 #endif
875         }
876         break;
877     case SCROLL_CLASS:
878 #if 0 /*JP*/
879         Strcpy(buf, "scroll");
880         if (!dknown)
881             break;
882 #else
883         if(!dknown){
884             Strcat(buf,"\8aª\95¨");
885             break;
886         }
887 #endif
888         if (nn) {
889 #if 0 /*JP*/
890             Strcat(buf, " of ");
891 #endif
892             Strcat(buf, actualn);
893         } else if (un) {
894 #if 0 /*JP*/
895             Strcat(buf, " called ");
896             Strcat(buf, un);
897 #else
898             Strcat(buf, un);
899             Strcat(buf, "\82Æ\8cÄ\82Î\82ê\82é\8aª\95¨");
900 #endif
901         } else if (ocl->oc_magic) {
902 #if 0 /*JP*/
903             Strcat(buf, " labeled ");
904 #endif
905             Strcat(buf, dn);
906         } else {
907 #if 0 /*JP*/
908             Strcpy(buf, dn);
909             Strcat(buf, " scroll");
910 #else
911             Strcat(buf, dn);
912 #endif
913         }
914         break;
915     case WAND_CLASS:
916         if (!dknown)
917 /*JP
918             Strcpy(buf, "wand");
919 */
920             Strcat(buf, "\8fñ");
921         else if (nn)
922 /*JP
923             Sprintf(buf, "wand of %s", actualn);
924 */
925             Strcat(buf, actualn);
926         else if (un)
927 /*JP
928             Sprintf(buf, "wand called %s", un);
929 */
930             Sprintf(eos(buf), "%s\82Æ\8cÄ\82Î\82ê\82é\8fñ", un);
931         else
932 /*JP
933             Sprintf(buf, "%s wand", dn);
934 */
935             Strcat(buf, dn);
936         break;
937     case SPBOOK_CLASS:
938         if (typ == SPE_NOVEL) { /* 3.6 tribute */
939             if (!dknown)
940 /*JP
941                 Strcpy(buf, "book");
942 */
943                 Strcpy(buf, "\96{");
944             else if (nn)
945                 Strcpy(buf, actualn);
946             else if (un)
947 /*JP
948                 Sprintf(buf, "novel called %s", un);
949 */
950                 Sprintf(buf, "%s\82Æ\82¢\82¤\8f¬\90à", un);
951             else
952 /*JP
953                 Sprintf(buf, "%s book", dn);
954 */
955                 Sprintf(buf, "%s\96{", dn);
956             break;
957             /* end of tribute */
958         } else if (!dknown) {
959 /*JP
960             Strcpy(buf, "spellbook");
961 */
962             Strcat(buf, "\96\82\96@\8f\91");
963         } else if (nn) {
964 #if 0 /*JP*/
965             if (typ != SPE_BOOK_OF_THE_DEAD)
966                 Strcpy(buf, "spellbook of ");
967 #endif
968             Strcat(buf, actualn);
969         } else if (un) {
970 /*JP
971             Sprintf(buf, "spellbook called %s", un);
972 */
973             Sprintf(eos(buf), "%s\82Æ\8cÄ\82Î\82ê\82é\96\82\96@\8f\91", un);
974         } else
975 /*JP
976             Sprintf(buf, "%s spellbook", dn);
977 */
978             Sprintf(eos(buf), "%s", dn);
979         break;
980     case RING_CLASS:
981         if (!dknown)
982 /*JP
983             Strcpy(buf, "ring");
984 */
985             Strcat(buf, "\8ew\97Ö");
986         else if (nn)
987 /*JP
988             Sprintf(buf, "ring of %s", actualn);
989 */
990             Strcat(buf, actualn);
991         else if (un)
992 /*JP
993             Sprintf(buf, "ring called %s", un);
994 */
995             Sprintf(eos(buf), "%s\82Æ\8cÄ\82Î\82ê\82é\8ew\97Ö", un);
996         else
997 /*JP
998             Sprintf(buf, "%s ring", dn);
999 */
1000             Strcat(buf, dn);
1001         break;
1002     case GEM_CLASS: {
1003 /*JP
1004         const char *rock = (ocl->oc_material == MINERAL) ? "stone" : "gem";
1005 */
1006         const char *rock = (ocl->oc_material == MINERAL) ? "\90Î" : "\95ó\90Î";
1007
1008         if (!dknown) {
1009 #if 0 /*JP*/
1010             Strcpy(buf, rock);
1011 #else
1012             Strcat(buf, rock);
1013 #endif
1014         } else if (!nn) {
1015             if (un)
1016 /*JP
1017                 Sprintf(buf, "%s called %s", rock, un);
1018 */
1019                 Sprintf(eos(buf), "%s\82Æ\8cÄ\82Î\82ê\82é%s", un, rock);
1020             else
1021 /*JP
1022                 Sprintf(buf, "%s %s", dn, rock);
1023 */
1024                 Strcat(buf, dn);
1025         } else {
1026             Strcpy(buf, actualn);
1027 #if 0 /*JP*/
1028             if (GemStone(typ))
1029                 Strcat(buf, " stone");
1030 #endif
1031         }
1032         break;
1033     }
1034     default:
1035         Sprintf(buf, "glorkum %d %d %d", obj->oclass, typ, obj->spe);
1036     }
1037 #if 0 /*JP*/
1038     if (pluralize)
1039         Strcpy(buf, makeplural(buf));
1040 #endif
1041
1042     if (obj->otyp == T_SHIRT && program_state.gameover) {
1043         char tmpbuf[BUFSZ];
1044
1045 /*JP
1046         Sprintf(eos(buf), " with text \"%s\"", tshirt_text(obj, tmpbuf));
1047 */
1048         Sprintf(eos(buf), "(\81u%s\81v\82Æ\8f\91\82¢\82Ä\82 \82é)", tshirt_text(obj, tmpbuf));
1049     }
1050
1051 #if 0 /*JP*/
1052     if (has_oname(obj) && dknown) {
1053         Strcat(buf, " named ");
1054  nameit:
1055         Strcat(buf, ONAME(obj));
1056     }
1057
1058     if (!strncmpi(buf, "the ", 4))
1059         buf += 4;
1060 #else
1061 nameit:
1062 #endif
1063     return buf;
1064 }
1065
1066 /* similar to simple_typename but minimal_xname operates on a particular
1067    object rather than its general type; it formats the most basic info:
1068      potion                     -- if description not known
1069      brown potion               -- if oc_name_known not set
1070      potion of object detection -- if discovered
1071  */
1072 STATIC_OVL char *
1073 minimal_xname(obj)
1074 struct obj *obj;
1075 {
1076     char *bufp;
1077     struct obj bareobj;
1078     struct objclass saveobcls;
1079     int otyp = obj->otyp;
1080
1081     /* suppress user-supplied name */
1082     saveobcls.oc_uname = objects[otyp].oc_uname;
1083     objects[otyp].oc_uname = 0;
1084     /* suppress actual name if object's description is unknown */
1085     saveobcls.oc_name_known = objects[otyp].oc_name_known;
1086     if (!obj->dknown)
1087         objects[otyp].oc_name_known = 0;
1088
1089     /* caveat: this makes a lot of assumptions about which fields
1090        are required in order for xname() to yield a sensible result */
1091     bareobj = zeroobj;
1092     bareobj.otyp = otyp;
1093     bareobj.oclass = obj->oclass;
1094     bareobj.dknown = obj->dknown;
1095     /* suppress known except for amulets (needed for fakes and real A-of-Y) */
1096     bareobj.known = (obj->oclass == AMULET_CLASS)
1097                         ? obj->known
1098                         /* default is "on" for types which don't use it */
1099                         : !objects[otyp].oc_uses_known;
1100     bareobj.quan = 1L;         /* don't want plural */
1101     bareobj.corpsenm = NON_PM; /* suppress statue and figurine details */
1102     /* but suppressing fruit details leads to "bad fruit #0"
1103        [perhaps we should force "slime mold" rather than use xname?] */
1104     if (obj->otyp == SLIME_MOLD)
1105         bareobj.spe = obj->spe;
1106
1107     bufp = distant_name(&bareobj, xname); /* xname(&bareobj) */
1108 #if 0 /*JP:T*/
1109     if (!strncmp(bufp, "uncursed ", 9))
1110         bufp += 9; /* Role_if(PM_PRIEST) */
1111 #else
1112     if (!strncmp(bufp, "\8eô\82í\82ê\82Ä\82¢\82È\82¢", 14))
1113         bufp += 14; /* Role_if(PM_PRIEST) */
1114 #endif
1115
1116     objects[otyp].oc_uname = saveobcls.oc_uname;
1117     objects[otyp].oc_name_known = saveobcls.oc_name_known;
1118     return bufp;
1119 }
1120
1121 /* xname() output augmented for multishot missile feedback */
1122 char *
1123 mshot_xname(obj)
1124 struct obj *obj;
1125 {
1126     char tmpbuf[BUFSZ];
1127     char *onm = xname(obj);
1128
1129     if (m_shot.n > 1 && m_shot.o == obj->otyp) {
1130         /* "the Nth arrow"; value will eventually be passed to an() or
1131            The(), both of which correctly handle this "the " prefix */
1132 /*JP
1133         Sprintf(tmpbuf, "the %d%s ", m_shot.i, ordin(m_shot.i));
1134 */
1135         Sprintf(tmpbuf, "%d%s\96Ú\82Ì", m_shot.i, numeral(obj));
1136         onm = strprepend(onm, tmpbuf);
1137     }
1138     return onm;
1139 }
1140
1141 /* used for naming "the unique_item" instead of "a unique_item" */
1142 boolean
1143 the_unique_obj(obj)
1144 struct obj *obj;
1145 {
1146 #if 0 /*JP*/
1147     boolean known = (obj->known || iflags.override_ID);
1148
1149     if (!obj->dknown && !iflags.override_ID)
1150         return FALSE;
1151     else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !known)
1152         return TRUE; /* lie */
1153     else
1154         return (boolean) (objects[obj->otyp].oc_unique
1155                           && (known || obj->otyp == AMULET_OF_YENDOR));
1156 #else
1157     return FALSE;
1158 #endif
1159 }
1160
1161 /* should monster type be prefixed with "the"? (mostly used for corpses) */
1162 boolean
1163 the_unique_pm(ptr)
1164 struct permonst *ptr;
1165 {
1166     boolean uniq;
1167
1168     /* even though monsters with personal names are unique, we want to
1169        describe them as "Name" rather than "the Name" */
1170     if (type_is_pname(ptr))
1171         return FALSE;
1172
1173     uniq = (ptr->geno & G_UNIQ) ? TRUE : FALSE;
1174     /* high priest is unique if it includes "of <deity>", otherwise not
1175        (caller needs to handle the 1st possibility; we assume the 2nd);
1176        worm tail should be irrelevant but is included for completeness */
1177     if (ptr == &mons[PM_HIGH_PRIEST] || ptr == &mons[PM_LONG_WORM_TAIL])
1178         uniq = FALSE;
1179     /* Wizard no longer needs this; he's flagged as unique these days */
1180     if (ptr == &mons[PM_WIZARD_OF_YENDOR])
1181         uniq = TRUE;
1182     return uniq;
1183 }
1184
1185 STATIC_OVL void
1186 add_erosion_words(obj, prefix)
1187 struct obj *obj;
1188 char *prefix;
1189 {
1190     boolean iscrys = (obj->otyp == CRYSKNIFE);
1191     boolean rknown;
1192
1193     rknown = (iflags.override_ID == 0) ? obj->rknown : TRUE;
1194
1195     if (!is_damageable(obj) && !iscrys)
1196         return;
1197
1198     /* The only cases where any of these bits do double duty are for
1199      * rotted food and diluted potions, which are all not is_damageable().
1200      */
1201     if (obj->oeroded && !iscrys) {
1202         switch (obj->oeroded) {
1203         case 2:
1204 /*JP
1205             Strcat(prefix, "very ");
1206 */
1207             Strcat(prefix, "\82Æ\82Ä\82à");
1208             break;
1209         case 3:
1210 /*JP
1211             Strcat(prefix, "thoroughly ");
1212 */
1213             Strcat(prefix, "\82©\82È\82è");
1214             break;
1215         }
1216 /*JP
1217         Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
1218 */
1219         Strcat(prefix, is_rustprone(obj) ? "\8eK\82Ñ\82½" : "\8f\9d\82Â\82¢\82½");
1220     }
1221     if (obj->oeroded2 && !iscrys) {
1222         switch (obj->oeroded2) {
1223         case 2:
1224 /*JP
1225             Strcat(prefix, "very ");
1226 */
1227             Strcat(prefix, "\82Æ\82Ä\82à");
1228             break;
1229         case 3:
1230 /*JP
1231             Strcat(prefix, "thoroughly ");
1232 */
1233             Strcat(prefix, "\82©\82È\82è");
1234             break;
1235         }
1236 /*JP
1237         Strcat(prefix, is_corrodeable(obj) ? "corroded " : "rotted ");
1238 */
1239         Strcat(prefix, is_corrodeable(obj) ? "\95\85\90H\82µ\82½" : "\95\85\82Á\82½");
1240     }
1241     if (rknown && obj->oerodeproof)
1242 #if 0 /*JP:T*/
1243         Strcat(prefix, iscrys
1244                           ? "fixed "
1245                           : is_rustprone(obj)
1246                              ? "rustproof "
1247                              : is_corrodeable(obj)
1248                                 ? "corrodeproof " /* "stainless"? */
1249                                 : is_flammable(obj)
1250                                    ? "fireproof "
1251                                    : "");
1252 #else
1253         Strcat(prefix, iscrys
1254                           ? "\88À\92è\82µ\82½"
1255                           : is_rustprone(obj)
1256                              ? "\8eK\82Ñ\82È\82¢"
1257                              : is_corrodeable(obj)
1258                                 ? "\95\85\90H\82µ\82È\82¢" /* "stainless"? */
1259                                 : is_flammable(obj)
1260                                    ? "\94R\82¦\82È\82¢"
1261                                    : "");
1262 #endif
1263 }
1264
1265 /* used to prevent rust on items where rust makes no difference */
1266 boolean
1267 erosion_matters(obj)
1268 struct obj *obj;
1269 {
1270     switch (obj->oclass) {
1271     case TOOL_CLASS:
1272         /* it's possible for a rusty weptool to be polymorphed into some
1273            non-weptool iron tool, in which case the rust implicitly goes
1274            away, but it's also possible for it to be polymorphed into a
1275            non-iron tool, in which case rust also implicitly goes away,
1276            so there's no particular reason to try to handle the first
1277            instance differently [this comment belongs in poly_obj()...] */
1278         return is_weptool(obj) ? TRUE : FALSE;
1279     case WEAPON_CLASS:
1280     case ARMOR_CLASS:
1281     case BALL_CLASS:
1282     case CHAIN_CLASS:
1283         return TRUE;
1284     default:
1285         break;
1286     }
1287     return FALSE;
1288 }
1289
1290 #define DONAME_WITH_PRICE 1
1291 #define DONAME_VAGUE_QUAN 2
1292
1293 STATIC_OVL char *
1294 doname_base(obj, doname_flags)
1295 struct obj *obj;
1296 unsigned doname_flags;
1297 {
1298     boolean ispoisoned = FALSE,
1299             with_price = (doname_flags & DONAME_WITH_PRICE) != 0,
1300             vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0,
1301             weightshown = FALSE;
1302     boolean known, dknown, cknown, bknown, lknown;
1303     int omndx = obj->corpsenm;
1304     char prefix[PREFIX], globbuf[QBUFSZ];
1305 #if 0 /*JP*/
1306     char tmpbuf[PREFIX + 1]; /* for when we have to add something at
1307                                 the start of prefix instead of the
1308                                 end (Strcat is used on the end) */
1309 #endif
1310     register char *bp = xname(obj);
1311 #if 1 /*JP*//*\8f\87\8f\98\93ü\82ê\91Ö\82¦\82É\8eg\82¤*/
1312     char preprefix[PREFIX];
1313 #endif
1314
1315     if (iflags.override_ID) {
1316         known = dknown = cknown = bknown = lknown = TRUE;
1317     } else {
1318         known = obj->known;
1319         dknown = obj->dknown;
1320         cknown = obj->cknown;
1321         bknown = obj->bknown;
1322         lknown = obj->lknown;
1323     }
1324
1325     /* When using xname, we want "poisoned arrow", and when using
1326      * doname, we want "poisoned +0 arrow".  This kludge is about the only
1327      * way to do it, at least until someone overhauls xname() and doname(),
1328      * combining both into one function taking a parameter.
1329      */
1330     /* must check opoisoned--someone can have a weirdly-named fruit */
1331 #if 0 /*JP:T*/
1332     if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
1333         bp += 9;
1334         ispoisoned = TRUE;
1335     }
1336 #else
1337     if (!strncmp(bp, "\93Å\82Ì\93h\82ç\82ê\82½", 12) && obj->opoisoned) {
1338         bp += 12;
1339         ispoisoned = TRUE;
1340     }
1341 #endif
1342 #if 1 /*JP*/
1343     /* JP
1344      *\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
1345      *  \82Ì\82Ù\82¤\82ª\8e©\91R\82Å\82 \82é\81D
1346      */
1347     {
1348         char *tp;
1349         preprefix[0] = '\0';
1350         if((tp = strstri(bp, "\96¼\82Ã\82¯\82ç\82ê\82½")) != NULL){
1351             tp += 12; /* \81u\96¼\82Ã\82¯\82ç\82ê\82½\81v*/
1352             strncpy(preprefix, bp, tp - bp);
1353             preprefix[tp - bp] = '\0';
1354             bp = tp;
1355         }
1356         Strcpy(prefix, "");
1357     }
1358 #endif
1359
1360     if (obj->quan != 1L) {
1361         if (dknown || !vague_quan)
1362 #if 0 /*JP*/
1363             Sprintf(prefix, "%ld ", obj->quan);
1364 #else /* \93ú\96{\8cê\82Æ\82µ\82Ä\82Í\90\94\8e\8c\82ª\82È\82¢\82Ì\82Í\95s\8e©\91R */
1365             Sprintf(prefix, "%ld%s\82Ì", obj->quan, numeral(obj));
1366 #endif
1367         else
1368 /*JP
1369             Strcpy(prefix, "some ");
1370 */
1371             Strcpy(prefix, "\82¢\82­\82Â\82©\82Ì");
1372     } else if (obj->otyp == CORPSE) {
1373         /* skip article prefix for corpses [else corpse_xname()
1374            would have to be taught how to strip it off again] */
1375         *prefix = '\0';
1376 #if 0 /*JP*/ /* \8a¥\8e\8c\82Í\95s\97v */
1377     } else if (obj_is_pname(obj) || the_unique_obj(obj)) {
1378         if (!strncmpi(bp, "the ", 4))
1379             bp += 4;
1380         Strcpy(prefix, "the ");
1381     } else {
1382         Strcpy(prefix, "a ");
1383 #else /*prefix\82Ì\8f\89\8aú\89»*/
1384     } else {
1385         Strcpy(prefix, "");
1386 #endif
1387     }
1388
1389     /* "empty" goes at the beginning, but item count goes at the end */
1390     if (cknown
1391         /* bag of tricks: include "empty" prefix if it's known to
1392            be empty but its precise number of charges isn't known
1393            (when that is known, suffix of "(n:0)" will be appended,
1394            making the prefix be redundant; note that 'known' flag
1395            isn't set when emptiness gets discovered because then
1396            charging magic would yield known number of new charges) */
1397         && ((obj->otyp == BAG_OF_TRICKS)
1398              ? (obj->spe == 0 && !obj->known)
1399              /* not bag of tricks: empty if container which has no contents */
1400              : ((Is_container(obj) || obj->otyp == STATUE)
1401                 && !Has_contents(obj))))
1402 /*JP
1403         Strcat(prefix, "empty ");
1404 */
1405         Strcat(prefix, "\8bó\82Ì");
1406
1407     if (bknown && obj->oclass != COIN_CLASS
1408         && (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
1409             || (!obj->cursed && !obj->blessed))) {
1410         /* allow 'blessed clear potion' if we don't know it's holy water;
1411          * always allow "uncursed potion of water"
1412          */
1413         if (obj->cursed)
1414 /*JP
1415             Strcat(prefix, "cursed ");
1416 */
1417             Strcat(prefix, "\8eô\82í\82ê\82½");
1418         else if (obj->blessed)
1419 /*JP
1420             Strcat(prefix, "blessed ");
1421 */
1422             Strcat(prefix, "\8fj\95\9f\82³\82ê\82½");
1423         else if (!iflags.implicit_uncursed
1424             /* For most items with charges or +/-, if you know how many
1425              * charges are left or what the +/- is, then you must have
1426              * totally identified the item, so "uncursed" is unnecessary,
1427              * because an identified object not described as "blessed" or
1428              * "cursed" must be uncursed.
1429              *
1430              * If the charges or +/- is not known, "uncursed" must be
1431              * printed to avoid ambiguity between an item whose curse
1432              * status is unknown, and an item known to be uncursed.
1433              */
1434                  || ((!known || !objects[obj->otyp].oc_charged
1435                       || obj->oclass == ARMOR_CLASS
1436                       || obj->oclass == RING_CLASS)
1437 #ifdef MAIL
1438                      && obj->otyp != SCR_MAIL
1439 #endif
1440                      && obj->otyp != FAKE_AMULET_OF_YENDOR
1441                      && obj->otyp != AMULET_OF_YENDOR
1442                      && !Role_if(PM_PRIEST)))
1443 /*JP
1444             Strcat(prefix, "uncursed ");
1445 */
1446             Strcat(prefix, "\8eô\82í\82ê\82Ä\82¢\82È\82¢");
1447     }
1448
1449     if (lknown && Is_box(obj)) {
1450         if (obj->obroken)
1451             /* 3.6.0 used "unlockable" here but that could be misunderstood
1452                to mean "capable of being unlocked" rather than the intended
1453                "not capable of being locked" */
1454 /*JP
1455             Strcat(prefix, "broken ");
1456 */
1457             Strcat(prefix, "\8c®\82Ì\89ó\82ê\82½");
1458         else if (obj->olocked)
1459 /*JP
1460             Strcat(prefix, "locked ");
1461 */
1462             Strcat(prefix, "\8c®\82Ì\8a|\82©\82Á\82½");
1463         else
1464 /*JP
1465             Strcat(prefix, "unlocked ");
1466 */
1467             Strcat(prefix, "\8c®\82Ì\8a|\82©\82Á\82Ä\82¢\82È\82¢");
1468     }
1469
1470     if (obj->greased)
1471 /*JP
1472         Strcat(prefix, "greased ");
1473 */
1474         Strcat(prefix, "\96û\82Ì\93h\82ç\82ê\82½");
1475
1476     if (cknown && Has_contents(obj)) {
1477         /* we count the number of separate stacks, which corresponds
1478            to the number of inventory slots needed to be able to take
1479            everything out if no merges occur */
1480         long itemcount = count_contents(obj, FALSE, FALSE, TRUE, FALSE);
1481
1482 #if 0 /*JP*/
1483         Sprintf(eos(bp), " containing %ld item%s", itemcount,
1484                 plur(itemcount));
1485 #else
1486         Sprintf(eos(bp), "(%ld\8cÂ\93ü\82Á\82Ä\82¢\82é)", itemcount);
1487 #endif
1488     }
1489
1490     switch (is_weptool(obj) ? WEAPON_CLASS : obj->oclass) {
1491     case AMULET_CLASS:
1492         if (obj->owornmask & W_AMUL)
1493 /*JP
1494             Strcat(bp, " (being worn)");
1495 */
1496             Strcat(bp, "(\90g\82É\82Â\82¯\82Ä\82¢\82é)");
1497         break;
1498     case ARMOR_CLASS:
1499         if (obj->owornmask & W_ARMOR) {
1500 /*JP
1501             Strcat(bp, (obj == uskin) ? " (embedded in your skin)"
1502 */
1503             Strcat(bp, (obj == uskin) ? "(\94§\82É\96\84\82ß\82±\82Ü\82ê\82Ä\82¢\82é)"
1504                        /* in case of perm_invent update while Wear/Takeoff
1505                           is in progress; check doffing() before donning()
1506                           because donning() returns True for both cases */
1507 /*JP
1508                        : doffing(obj) ? " (being doffed)"
1509 */
1510                        : doffing(obj) ? " (\90g\82É\82Â\82¯\82Ä\82¢\82é\93r\92\86)"
1511 /*JP
1512                          : donning(obj) ? " (being donned)"
1513 */
1514                          : donning(obj) ? " (\92E\82¢\82Å\82¢\82é\93r\92\86)"
1515 /*JP
1516                            : " (being worn)");
1517 */
1518                            : "(\90g\82É\82Â\82¯\82Ä\82¢\82é)");
1519             /* slippery fingers is an intrinsic condition of the hero
1520                rather than extrinsic condition of objects, but gloves
1521                are described as slippery when hero has slippery fingers */
1522             if (obj == uarmg && Glib) /* just appended "(something)",
1523                                        * change to "(something; slippery)" */
1524 /*JP
1525                 Strcpy(rindex(bp, ')'), "; slippery)");
1526 */
1527                 Strcpy(rindex(bp, ')'), "; \82Ê\82é\82Ê\82é)");
1528         }
1529         /*FALLTHRU*/
1530     case WEAPON_CLASS:
1531         if (ispoisoned)
1532 /*JP
1533             Strcat(prefix, "poisoned ");
1534 */
1535             Strcat(prefix, "\93Å\82Ì\93h\82ç\82ê\82½");
1536         add_erosion_words(obj, prefix);
1537         if (known) {
1538             Strcat(prefix, sitoa(obj->spe));
1539             Strcat(prefix, " ");
1540         }
1541         break;
1542     case TOOL_CLASS:
1543         if (obj->owornmask & (W_TOOL | W_SADDLE)) { /* blindfold */
1544 /*JP
1545             Strcat(bp, " (being worn)");
1546 */
1547             Strcat(bp, "(\90g\82É\82Â\82¯\82Ä\82¢\82é)");
1548             break;
1549         }
1550         if (obj->otyp == LEASH && obj->leashmon != 0) {
1551             struct monst *mlsh = find_mid(obj->leashmon, FM_FMON);
1552
1553             if (!mlsh) {
1554                 impossible("leashed monster not on this level");
1555                 obj->leashmon = 0;
1556             } else {
1557 #if 0 /*JP:T*/
1558                 Sprintf(eos(bp), " (attached to %s)",
1559                         noit_mon_nam(mlsh));
1560 #else
1561                 Sprintf(eos(bp), " (%s\82É\8c\8b\82Ñ\82Â\82¯\82ç\82ê\82Ä\82¢\82é)",
1562                         noit_mon_nam(mlsh));
1563 #endif
1564             }
1565             break;
1566         }
1567         if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
1568 #if 0 /*JP*/
1569             if (!obj->spe)
1570                 Strcpy(tmpbuf, "no");
1571             else
1572                 Sprintf(tmpbuf, "%d", obj->spe);
1573             Sprintf(eos(bp), " (%s candle%s%s)", tmpbuf, plur(obj->spe),
1574                     !obj->lamplit ? " attached" : ", lit");
1575 #else
1576             if(!obj->spe)
1577                 Sprintf(eos(bp), "(\88ê\96{\82à\8eæ\82è\82Â\82¯\82ç\82ê\82Ä\82¢\82È\82¢)");
1578             else {
1579                 if(!obj->lamplit)
1580                   Sprintf(eos(bp), "(%d\96{\8eæ\82è\82Â\82¯\82ç\82ê\82Ä\82¢\82é)", obj->spe);
1581                 else
1582                   Sprintf(eos(bp), "(%d\96{\8cõ\82Á\82Ä\82¢\82é)", obj->spe);
1583             }
1584 #endif
1585             break;
1586         } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
1587                    || obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
1588             if (Is_candle(obj)
1589                 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
1590 /*JP
1591                 Strcat(prefix, "partly used ");
1592 */
1593                 Strcat(prefix, "\8eg\82¢\82³\82µ\82Ì");
1594             if (obj->lamplit)
1595 /*JP
1596                 Strcat(bp, " (lit)");
1597 */
1598                 Strcat(bp, "(\8cõ\82Á\82Ä\82¢\82é)");
1599             break;
1600         }
1601         if (objects[obj->otyp].oc_charged)
1602             goto charges;
1603         break;
1604     case WAND_CLASS:
1605  charges:
1606         if (known)
1607 /*JP
1608             Sprintf(eos(bp), " (%d:%d)", (int) obj->recharged, obj->spe);
1609 */
1610             Sprintf(eos(bp), "(%d:%d)", (int) obj->recharged, obj->spe);
1611         break;
1612     case POTION_CLASS:
1613         if (obj->otyp == POT_OIL && obj->lamplit)
1614 /*JP
1615             Strcat(bp, " (lit)");
1616 */
1617             Strcat(bp, "(\8cõ\82Á\82Ä\82¢\82é)");
1618         break;
1619     case RING_CLASS:
1620  ring:
1621         if (obj->owornmask & W_RINGR)
1622 /*JP
1623             Strcat(bp, " (on right ");
1624 */
1625             Strcat(bp, "(\89E");
1626         if (obj->owornmask & W_RINGL)
1627 /*JP
1628             Strcat(bp, " (on left ");
1629 */
1630             Strcat(bp, "(\8d¶");
1631         if (obj->owornmask & W_RING) {
1632             Strcat(bp, body_part(HAND));
1633             Strcat(bp, ")");
1634         }
1635         if (known && objects[obj->otyp].oc_charged) {
1636 #if 1 /*JP*/
1637             Strcat(prefix, " ");
1638 #endif
1639             Strcat(prefix, sitoa(obj->spe));
1640             Strcat(prefix, " ");
1641         }
1642         break;
1643     case FOOD_CLASS:
1644         if (obj->oeaten)
1645 /*JP
1646             Strcat(prefix, "partly eaten ");
1647 */
1648             Strcat(prefix, "\90H\82×\82©\82¯\82Ì");
1649         if (obj->otyp == CORPSE) {
1650             /* (quan == 1) => want corpse_xname() to supply article,
1651                (quan != 1) => already have count or "some" as prefix;
1652                "corpse" is already in the buffer returned by xname() */
1653             unsigned cxarg = (((obj->quan != 1L) ? 0 : CXN_ARTICLE)
1654                               | CXN_NOCORPSE);
1655             char *cxstr = corpse_xname(obj, prefix, cxarg);
1656
1657 #if 0 /*JP*/
1658             Sprintf(prefix, "%s ", cxstr);
1659 #else
1660             Sprintf(prefix, "%s\82Ì", cxstr);
1661 #endif
1662             /* avoid having doname(corpse) consume an extra obuf */
1663             releaseobuf(cxstr);
1664         } else if (obj->otyp == EGG) {
1665 #if 0 /* corpses don't tell if they're stale either */
1666             if (known && stale_egg(obj))
1667                 Strcat(prefix, "stale ");
1668 #endif
1669             if (omndx >= LOW_PM
1670                 && (known || (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
1671 #if 0 /*JP:T*/
1672                 Strcat(prefix, mons[omndx].mname);
1673                 Strcat(prefix, " ");
1674 #else
1675                 Strcat(prefix, mons[omndx].mname);
1676                 Strcat(prefix, "\82Ì");
1677 #endif
1678                 if (obj->spe)
1679 /*JP
1680                     Strcat(bp, " (laid by you)");
1681 */
1682                     Strcat(bp, "(\82 \82È\82½\82ª\8eY\82ñ\82¾)");
1683             }
1684         }
1685         if (obj->otyp == MEAT_RING)
1686             goto ring;
1687         break;
1688     case BALL_CLASS:
1689     case CHAIN_CLASS:
1690         add_erosion_words(obj, prefix);
1691         if (obj->owornmask & W_BALL)
1692 /*JP
1693             Strcat(bp, " (chained to you)");
1694 */
1695             Strcat(bp, "(\82 \82È\82½\82É\8cq\82ª\82ê\82Ä\82¢\82é)");
1696         break;
1697     }
1698
1699     if ((obj->owornmask & W_WEP) && !mrg_to_wielded) {
1700         if (obj->quan != 1L) {
1701 /*JP
1702             Strcat(bp, " (wielded)");
1703 */
1704             Strcat(bp, "(\91\95\94õ\82µ\82Ä\82¢\82é)");
1705         } else {
1706             const char *hand_s = body_part(HAND);
1707
1708             if (bimanual(obj))
1709                 hand_s = makeplural(hand_s);
1710             /* note: Sting's glow message, if added, will insert text
1711                in front of "(weapon in hand)"'s closing paren */
1712 #if 0 /*JP*/
1713             Sprintf(eos(bp), " (%sweapon in %s)",
1714                     (obj->otyp == AKLYS) ? "tethered " : "", hand_s);
1715 #else /*\83A\83L\83\8a\83X\82ð\93Á\95Ê\88µ\82¢\82µ\82È\82¢*/
1716             Sprintf(eos(bp), "(%s\82É\82µ\82Ä\82¢\82é)", hand_s);
1717 #endif
1718
1719             if (warn_obj_cnt && obj == uwep && (EWarn_of_mon & W_WEP) != 0L) {
1720                 if (!Blind) /* we know bp[] ends with ')'; overwrite that */
1721 #if 0 /*JP*/
1722                     Sprintf(eos(bp) - 1, ", %s %s)",
1723                             glow_verb(warn_obj_cnt, TRUE),
1724                             glow_color(obj->oartifact));
1725 #else
1726                     Sprintf(eos(bp) - 1, ", %s%s\82¢\82é)",
1727                             jconj_adj(glow_color(obj->oartifact)),
1728                             jconj(glow_verb(warn_obj_cnt, TRUE), "\82Ä"));
1729 #endif
1730             }
1731         }
1732     }
1733     if (obj->owornmask & W_SWAPWEP) {
1734         if (u.twoweap)
1735 /*JP
1736             Sprintf(eos(bp), " (wielded in other %s)", body_part(HAND));
1737 */
1738             Sprintf(eos(bp), "(\8d¶%s\82É\82µ\82Ä\82¢\82é)", body_part(HAND));
1739         else
1740 /*JP
1741             Strcat(bp, " (alternate weapon; not wielded)");
1742 */
1743             Strcat(bp, "(\97\\94õ\82Ì\95\90\8aí;\91\95\94õ\82µ\82Ä\82¢\82È\82¢)");
1744     }
1745     if (obj->owornmask & W_QUIVER) {
1746         switch (obj->oclass) {
1747         case WEAPON_CLASS:
1748             if (is_ammo(obj)) {
1749                 if (objects[obj->otyp].oc_skill == -P_BOW) {
1750                     /* Ammo for a bow */
1751 /*JP
1752                     Strcat(bp, " (in quiver)");
1753 */
1754                     Strcat(bp, "(\96î\93\9b\82É\93ü\82Á\82Ä\82¢\82é)");
1755                     break;
1756                 } else {
1757                     /* Ammo not for a bow */
1758 /*JP
1759                     Strcat(bp, " (in quiver pouch)");
1760 */
1761                     Strcat(bp, "(\92e\93ü\82ê\82É\93ü\82Á\82Ä\82¢\82é)");
1762                     break;
1763                 }
1764             } else {
1765                 /* Weapons not considered ammo */
1766 /*JP
1767                 Strcat(bp, " (at the ready)");
1768 */
1769                 Strcat(bp, "(\8f\80\94õ\82µ\82Ä\82¢\82é)");
1770                 break;
1771             }
1772         /* Small things and ammo not for a bow */
1773         case RING_CLASS:
1774         case AMULET_CLASS:
1775         case WAND_CLASS:
1776         case COIN_CLASS:
1777         case GEM_CLASS:
1778 /*JP
1779             Strcat(bp, " (in quiver pouch)");
1780 */
1781             Strcat(bp, "(\92e\93ü\82ê\82É\93ü\82Á\82Ä\82¢\82é)");
1782             break;
1783         default: /* odd things */
1784 /*JP
1785             Strcat(bp, " (at the ready)");
1786 */
1787             Strcat(bp, "(\8f\80\94õ\82µ\82Ä\82¢\82é)");
1788         }
1789     }
1790     /* treat 'restoring' like suppress_price because shopkeeper and
1791        bill might not be available yet while restore is in progress
1792        (objects won't normally be formatted during that time, but if
1793        'perm_invent' is enabled then they might be) */
1794     if (iflags.suppress_price || restoring) {
1795         ; /* don't attempt to obtain any stop pricing, even if 'with_price' */
1796     } else if (is_unpaid(obj)) { /* in inventory or in container in invent */
1797         long quotedprice = unpaid_cost(obj, TRUE);
1798
1799 #if 0 /*JP:T*/
1800         Sprintf(eos(bp), " (%s, %s%ld %s)",
1801                 obj->unpaid ? "unpaid" : "contents",
1802                 globwt(obj, globbuf, &weightshown),
1803                 quotedprice, currency(quotedprice));
1804 #else
1805         Sprintf(eos(bp), " (%s, %s%ld%s)",
1806                 obj->unpaid ? "\96¢\95¥\82¢" : "\92\86\90g",
1807                 globwt(obj, globbuf, &weightshown),
1808                 quotedprice, currency(quotedprice));
1809 #endif
1810     } else if (with_price) { /* on floor or in container on floor */
1811         int nochrg = 0;
1812         long price = get_cost_of_shop_item(obj, &nochrg);
1813
1814         if (price > 0L)
1815 #if 0 /*JP:T*/
1816             Sprintf(eos(bp), " (%s, %s%ld %s)",
1817                     nochrg ? "contents" : "for sale",
1818                     globwt(obj, globbuf, &weightshown),
1819                     price, currency(price));
1820 #else
1821             Sprintf(eos(bp), " (%s, %s%ld%s)",
1822                     nochrg ? "\92\86\90g" : "\8f¤\95i",
1823                     globwt(obj, globbuf, &weightshown),
1824                     price, currency(price));
1825 #endif
1826         else if (nochrg > 0)
1827 #if 0 /*JP:T*/
1828             Sprintf(eos(bp), " (%sno charge)",
1829                     globwt(obj, globbuf, &weightshown));
1830 #else
1831             Sprintf(eos(bp), " (%s\96³\97¿)",
1832                     globwt(obj, globbuf, &weightshown));
1833 #endif
1834     }
1835 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\95s\97v*/
1836     if (!strncmp(prefix, "a ", 2)) {
1837         /* save current prefix, without "a "; might be empty */
1838         Strcpy(tmpbuf, prefix + 2);
1839         /* set prefix[] to "", "a ", or "an " */
1840         (void) just_an(prefix, *tmpbuf ? tmpbuf : bp);
1841         /* append remainder of original prefix */
1842         Strcat(prefix, tmpbuf);
1843     }
1844 #endif
1845
1846     /* show weight for items (debug tourist info);
1847        "aum" is stolen from Crawl's "Arbitrary Unit of Measure" */
1848     if (wizard && iflags.wizweight) {
1849         /* wizard mode user has asked to see object weights;
1850            globs with shop pricing attached already include it */
1851         if (!weightshown)
1852             Sprintf(eos(bp), " (%u aum)", obj->owt);
1853     }
1854 #if 0 /*JP*/
1855     bp = strprepend(bp, prefix);
1856 #else /*JP:\81u\96¼\95t\82¯\82ç\82ê\82½\81v\82ð\96ß\82·*/
1857     Strcat(preprefix, prefix);
1858     bp = strprepend(bp, preprefix);
1859 #endif
1860     return bp;
1861 }
1862
1863 char *
1864 doname(obj)
1865 struct obj *obj;
1866 {
1867     return doname_base(obj, (unsigned) 0);
1868 }
1869
1870 /* Name of object including price. */
1871 char *
1872 doname_with_price(obj)
1873 struct obj *obj;
1874 {
1875     return doname_base(obj, DONAME_WITH_PRICE);
1876 }
1877
1878 /* "some" instead of precise quantity if obj->dknown not set */
1879 char *
1880 doname_vague_quan(obj)
1881 struct obj *obj;
1882 {
1883     /* Used by farlook.
1884      * If it hasn't been seen up close and quantity is more than one,
1885      * use "some" instead of the quantity: "some gold pieces" rather
1886      * than "25 gold pieces".  This is suboptimal, to put it mildly,
1887      * because lookhere and pickup report the precise amount.
1888      * Picking the item up while blind also shows the precise amount
1889      * for inventory display, then dropping it while still blind leaves
1890      * obj->dknown unset so the count reverts to "some" for farlook.
1891      *
1892      * TODO: add obj->qknown flag for 'quantity known' on stackable
1893      * items; it could overlay obj->cknown since no containers stack.
1894      */
1895     return doname_base(obj, DONAME_VAGUE_QUAN);
1896 }
1897
1898 /* used from invent.c */
1899 boolean
1900 not_fully_identified(otmp)
1901 struct obj *otmp;
1902 {
1903     /* gold doesn't have any interesting attributes [yet?] */
1904     if (otmp->oclass == COIN_CLASS)
1905         return FALSE; /* always fully ID'd */
1906     /* check fundamental ID hallmarks first */
1907     if (!otmp->known || !otmp->dknown
1908 #ifdef MAIL
1909         || (!otmp->bknown && otmp->otyp != SCR_MAIL)
1910 #else
1911         || !otmp->bknown
1912 #endif
1913         || !objects[otmp->otyp].oc_name_known)
1914         return TRUE;
1915     if ((!otmp->cknown && (Is_container(otmp) || otmp->otyp == STATUE))
1916         || (!otmp->lknown && Is_box(otmp)))
1917         return TRUE;
1918     if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
1919         return TRUE;
1920     /* otmp->rknown is the only item of interest if we reach here */
1921     /*
1922      *  Note:  if a revision ever allows scrolls to become fireproof or
1923      *  rings to become shockproof, this checking will need to be revised.
1924      *  `rknown' ID only matters if xname() will provide the info about it.
1925      */
1926     if (otmp->rknown
1927         || (otmp->oclass != ARMOR_CLASS && otmp->oclass != WEAPON_CLASS
1928             && !is_weptool(otmp)            /* (redundant) */
1929             && otmp->oclass != BALL_CLASS)) /* (useless) */
1930         return FALSE;
1931     else /* lack of `rknown' only matters for vulnerable objects */
1932         return (boolean) (is_rustprone(otmp) || is_corrodeable(otmp)
1933                           || is_flammable(otmp));
1934 }
1935
1936 /* format a corpse name (xname() omits monster type; doname() calls us);
1937    eatcorpse() also uses us for death reason when eating tainted glob */
1938 char *
1939 corpse_xname(otmp, adjective, cxn_flags)
1940 struct obj *otmp;
1941 const char *adjective;
1942 unsigned cxn_flags; /* bitmask of CXN_xxx values */
1943 {
1944     /* some callers [aobjnam()] rely on prefix area that xname() sets aside */
1945     char *nambuf = nextobuf() + PREFIX;
1946     int omndx = otmp->corpsenm;
1947 #if 0 /*JP*/
1948     boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0,
1949             /* suppress "the" from "the unique monster corpse" */
1950 #else
1951     boolean
1952 #endif
1953         no_prefix = (cxn_flags & CXN_NO_PFX) != 0,
1954             /* include "the" for "the woodchuck corpse */
1955         the_prefix = (cxn_flags & CXN_PFX_THE) != 0,
1956             /* include "an" for "an ogre corpse */
1957         any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
1958             /* leave off suffix (do_name() appends "corpse" itself) */
1959         omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
1960         possessive = FALSE,
1961         glob = (otmp->otyp != CORPSE && otmp->globby);
1962     const char *mname;
1963
1964     if (glob) {
1965         mname = OBJ_NAME(objects[otmp->otyp]); /* "glob of <monster>" */
1966     } else if (omndx == NON_PM) { /* paranoia */
1967 /*JP
1968         mname = "thing";
1969 */
1970         mname = "\89½\82©";
1971         /* [Possible enhancement:  check whether corpse has monster traits
1972             attached in order to use priestname() for priests and minions.] */
1973     } else if (omndx == PM_ALIGNED_PRIEST) {
1974         /* avoid "aligned priest"; it just exposes internal details */
1975 /*JP
1976         mname = "priest";
1977 */
1978         mname = "\91m\97µ";
1979     } else {
1980         mname = mons[omndx].mname;
1981         if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) {
1982             mname = s_suffix(mname);
1983             possessive = TRUE;
1984             /* don't precede personal name like "Medusa" with an article */
1985             if (type_is_pname(&mons[omndx]))
1986                 no_prefix = TRUE;
1987             /* always precede non-personal unique monster name like
1988                "Oracle" with "the" unless explicitly overridden */
1989             else if (the_unique_pm(&mons[omndx]) && !no_prefix)
1990                 the_prefix = TRUE;
1991         }
1992     }
1993     if (no_prefix)
1994         the_prefix = any_prefix = FALSE;
1995     else if (the_prefix)
1996         any_prefix = FALSE; /* mutually exclusive */
1997
1998     *nambuf = '\0';
1999     /* can't use the() the way we use an() below because any capitalized
2000        Name causes it to assume a personal name and return Name as-is;
2001        that's usually the behavior wanted, but here we need to force "the"
2002        to precede capitalized unique monsters (pnames are handled above) */
2003 #if 0 /*JP*//*\93ú\96{\8cê\82É\92è\8a¥\8e\8c\82Í\95s\97v*/
2004     if (the_prefix)
2005         Strcat(nambuf, "the ");
2006 #endif
2007
2008     if (!adjective || !*adjective) {
2009         /* normal case:  newt corpse */
2010         Strcat(nambuf, mname);
2011     } else {
2012         /* adjective positioning depends upon format of monster name */
2013         if (possessive) /* Medusa's cursed partly eaten corpse */
2014 /*JP
2015             Sprintf(eos(nambuf), "%s %s", mname, adjective);
2016 */
2017             Sprintf(eos(nambuf), "%s%s", mname, adjective);
2018         else /* cursed partly eaten troll corpse */
2019 /*JP
2020             Sprintf(eos(nambuf), "%s %s", adjective, mname);
2021 */
2022             Sprintf(eos(nambuf), "%s%s", adjective, mname);
2023         /* in case adjective has a trailing space, squeeze it out */
2024         mungspaces(nambuf);
2025         /* doname() might include a count in the adjective argument;
2026            if so, don't prepend an article */
2027         if (digit(*adjective))
2028             any_prefix = FALSE;
2029     }
2030
2031     if (glob) {
2032         ; /* omit_corpse doesn't apply; quantity is always 1 */
2033     } else if (!omit_corpse) {
2034 #if 0 /*JP*/
2035         Strcat(nambuf, " corpse");
2036         /* makeplural(nambuf) => append "s" to "corpse" */
2037         if (otmp->quan > 1L && !ignore_quan) {
2038             Strcat(nambuf, "s");
2039             any_prefix = FALSE; /* avoid "a newt corpses" */
2040         }
2041 #else
2042         Strcat(nambuf, "\82Ì\8e\80\91Ì");
2043 #endif
2044     }
2045
2046     /* it's safe to overwrite our nambuf after an() has copied
2047        its old value into another buffer */
2048     if (any_prefix)
2049         Strcpy(nambuf, an(nambuf));
2050
2051     return nambuf;
2052 }
2053
2054 /* xname doesn't include monster type for "corpse"; cxname does */
2055 char *
2056 cxname(obj)
2057 struct obj *obj;
2058 {
2059     if (obj->otyp == CORPSE)
2060         return corpse_xname(obj, (const char *) 0, CXN_NORMAL);
2061     return xname(obj);
2062 }
2063
2064 /* like cxname, but ignores quantity */
2065 char *
2066 cxname_singular(obj)
2067 struct obj *obj;
2068 {
2069     if (obj->otyp == CORPSE)
2070         return corpse_xname(obj, (const char *) 0, CXN_SINGULAR);
2071     return xname_flags(obj, CXN_SINGULAR);
2072 }
2073
2074 /* treat an object as fully ID'd when it might be used as reason for death */
2075 char *
2076 killer_xname(obj)
2077 struct obj *obj;
2078 {
2079     struct obj save_obj;
2080     unsigned save_ocknown;
2081     char *buf, *save_ocuname, *save_oname = (char *) 0;
2082
2083     /* bypass object twiddling for artifacts */
2084     if (obj->oartifact)
2085         return bare_artifactname(obj);
2086
2087     /* remember original settings for core of the object;
2088        oextra structs other than oname don't matter here--since they
2089        aren't modified they don't need to be saved and restored */
2090     save_obj = *obj;
2091     if (has_oname(obj))
2092         save_oname = ONAME(obj);
2093
2094     /* killer name should be more specific than general xname; however, exact
2095        info like blessed/cursed and rustproof makes things be too verbose */
2096     obj->known = obj->dknown = 1;
2097     obj->bknown = obj->rknown = obj->greased = 0;
2098     /* if character is a priest[ess], bknown will get toggled back on */
2099     if (obj->otyp != POT_WATER)
2100         obj->blessed = obj->cursed = 0;
2101     else
2102         obj->bknown = 1; /* describe holy/unholy water as such */
2103     /* "killed by poisoned <obj>" would be misleading when poison is
2104        not the cause of death and "poisoned by poisoned <obj>" would
2105        be redundant when it is, so suppress "poisoned" prefix */
2106     obj->opoisoned = 0;
2107     /* strip user-supplied name; artifacts keep theirs */
2108     if (!obj->oartifact && save_oname)
2109         ONAME(obj) = (char *) 0;
2110     /* temporarily identify the type of object */
2111     save_ocknown = objects[obj->otyp].oc_name_known;
2112     objects[obj->otyp].oc_name_known = 1;
2113     save_ocuname = objects[obj->otyp].oc_uname;
2114     objects[obj->otyp].oc_uname = 0; /* avoid "foo called bar" */
2115
2116     /* format the object */
2117     if (obj->otyp == CORPSE) {
2118         buf = corpse_xname(obj, (const char *) 0, CXN_NORMAL);
2119     } else if (obj->otyp == SLIME_MOLD) {
2120         /* concession to "most unique deaths competition" in the annual
2121            devnull tournament, suppress player supplied fruit names because
2122            those can be used to fake other objects and dungeon features */
2123         buf = nextobuf();
2124 /*JP
2125         Sprintf(buf, "deadly slime mold%s", plur(obj->quan));
2126 */
2127         Strcpy(buf, "\8aë\8c¯\82È\82Ë\82Î\82Ë\82Î\83J\83r");
2128     } else {
2129         buf = xname(obj);
2130     }
2131     /* apply an article if appropriate; caller should always use KILLED_BY */
2132 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\95s\97v*/
2133     if (obj->quan == 1L && !strstri(buf, "'s ") && !strstri(buf, "s' "))
2134         buf = (obj_is_pname(obj) || the_unique_obj(obj)) ? the(buf) : an(buf);
2135 #endif
2136
2137     objects[obj->otyp].oc_name_known = save_ocknown;
2138     objects[obj->otyp].oc_uname = save_ocuname;
2139     *obj = save_obj; /* restore object's core settings */
2140     if (!obj->oartifact && save_oname)
2141         ONAME(obj) = save_oname;
2142
2143     return buf;
2144 }
2145
2146 /* xname,doname,&c with long results reformatted to omit some stuff */
2147 char *
2148 short_oname(obj, func, altfunc, lenlimit)
2149 struct obj *obj;
2150 char *FDECL((*func), (OBJ_P)),    /* main formatting routine */
2151      *FDECL((*altfunc), (OBJ_P)); /* alternate for shortest result */
2152 unsigned lenlimit;
2153 {
2154     struct obj save_obj;
2155     char unamebuf[12], onamebuf[12], *save_oname, *save_uname, *outbuf;
2156
2157     outbuf = (*func)(obj);
2158     if ((unsigned) strlen(outbuf) <= lenlimit)
2159         return outbuf;
2160
2161     /* shorten called string to fairly small amount */
2162     save_uname = objects[obj->otyp].oc_uname;
2163     if (save_uname && strlen(save_uname) >= sizeof unamebuf) {
2164         (void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
2165         Strcpy(unamebuf + sizeof unamebuf - 4, "...");
2166         objects[obj->otyp].oc_uname = unamebuf;
2167         releaseobuf(outbuf);
2168         outbuf = (*func)(obj);
2169         objects[obj->otyp].oc_uname = save_uname; /* restore called string */
2170         if ((unsigned) strlen(outbuf) <= lenlimit)
2171             return outbuf;
2172     }
2173
2174     /* shorten named string to fairly small amount */
2175     save_oname = has_oname(obj) ? ONAME(obj) : 0;
2176     if (save_oname && strlen(save_oname) >= sizeof onamebuf) {
2177         (void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
2178         Strcpy(onamebuf + sizeof onamebuf - 4, "...");
2179         ONAME(obj) = onamebuf;
2180         releaseobuf(outbuf);
2181         outbuf = (*func)(obj);
2182         ONAME(obj) = save_oname; /* restore named string */
2183         if ((unsigned) strlen(outbuf) <= lenlimit)
2184             return outbuf;
2185     }
2186
2187     /* shorten both called and named strings;
2188        unamebuf and onamebuf have both already been populated */
2189     if (save_uname && strlen(save_uname) >= sizeof unamebuf && save_oname
2190         && strlen(save_oname) >= sizeof onamebuf) {
2191         objects[obj->otyp].oc_uname = unamebuf;
2192         ONAME(obj) = onamebuf;
2193         releaseobuf(outbuf);
2194         outbuf = (*func)(obj);
2195         if ((unsigned) strlen(outbuf) <= lenlimit) {
2196             objects[obj->otyp].oc_uname = save_uname;
2197             ONAME(obj) = save_oname;
2198             return outbuf;
2199         }
2200     }
2201
2202     /* still long; strip several name-lengthening attributes;
2203        called and named strings are still in truncated form */
2204     save_obj = *obj;
2205     obj->bknown = obj->rknown = obj->greased = 0;
2206     obj->oeroded = obj->oeroded2 = 0;
2207     releaseobuf(outbuf);
2208     outbuf = (*func)(obj);
2209     if (altfunc && (unsigned) strlen(outbuf) > lenlimit) {
2210         /* still long; use the alternate function (usually one of
2211            the jackets around minimal_xname()) */
2212         releaseobuf(outbuf);
2213         outbuf = (*altfunc)(obj);
2214     }
2215     /* restore the object */
2216     *obj = save_obj;
2217     if (save_oname)
2218         ONAME(obj) = save_oname;
2219     if (save_uname)
2220         objects[obj->otyp].oc_uname = save_uname;
2221
2222     /* use whatever we've got, whether it's too long or not */
2223     return outbuf;
2224 }
2225
2226 /*
2227  * Used if only one of a collection of objects is named (e.g. in eat.c).
2228  */
2229 const char *
2230 singular(otmp, func)
2231 register struct obj *otmp;
2232 char *FDECL((*func), (OBJ_P));
2233 {
2234     long savequan;
2235     char *nam;
2236
2237     /* using xname for corpses does not give the monster type */
2238     if (otmp->otyp == CORPSE && func == xname)
2239         func = cxname;
2240
2241     savequan = otmp->quan;
2242     otmp->quan = 1L;
2243     nam = (*func)(otmp);
2244     otmp->quan = savequan;
2245     return nam;
2246 }
2247
2248 /* pick "", "a ", or "an " as article for 'str'; used by an() and doname() */
2249 STATIC_OVL char *
2250 just_an(outbuf, str)
2251 char *outbuf;
2252 const char *str;
2253 {
2254 #if 0 /*JP*//*\95s\92è\8a¥\8e\8c\82Í\95s\97v*/
2255     char c0;
2256
2257     *outbuf = '\0';
2258     c0 = lowc(*str);
2259     if (!str[1]) {
2260         /* single letter; might be used for named fruit */
2261         Strcpy(outbuf, index("aefhilmnosx", c0) ? "an " : "a ");
2262     } else if (!strncmpi(str, "the ", 4) || !strcmpi(str, "molten lava")
2263                || !strcmpi(str, "iron bars") || !strcmpi(str, "ice")) {
2264         ; /* no article */
2265     } else {
2266         if ((index(vowels, c0) && strncmpi(str, "one-", 4)
2267              && strncmpi(str, "eucalyptus", 10) && strncmpi(str, "unicorn", 7)
2268              && strncmpi(str, "uranium", 7) && strncmpi(str, "useful", 6))
2269             || (index("x", c0) && !index(vowels, lowc(str[1]))))
2270             Strcpy(outbuf, "an ");
2271         else
2272             Strcpy(outbuf, "a ");
2273     }
2274 #else
2275     *outbuf = '\0';
2276 #endif
2277     return outbuf;
2278 }
2279
2280 char *
2281 an(str)
2282 const char *str;
2283 {
2284     char *buf = nextobuf();
2285
2286     if (!str || !*str) {
2287         impossible("Alphabet soup: 'an(%s)'.", str ? "\"\"" : "<null>");
2288         return strcpy(buf, "an []");
2289     }
2290     (void) just_an(buf, str);
2291     return strcat(buf, str);
2292 }
2293
2294 char *
2295 An(str)
2296 const char *str;
2297 {
2298     char *tmp = an(str);
2299
2300 #if 0 /*JP*//*\91å\95\8e\9a\89»\82µ\82È\82¢*/
2301     *tmp = highc(*tmp);
2302 #endif
2303     return tmp;
2304 }
2305
2306 /*
2307  * Prepend "the" if necessary; assumes str is a subject derived from xname.
2308  * Use type_is_pname() for monster names, not the().  the() is idempotent.
2309  */
2310 char *
2311 the(str)
2312 const char *str;
2313 {
2314     char *buf = nextobuf();
2315 #if 0 /*JP*//*\92è\8a¥\8e\8c\82Í\95s\97v*/
2316     boolean insert_the = FALSE;
2317
2318     if (!str || !*str) {
2319         impossible("Alphabet soup: 'the(%s)'.", str ? "\"\"" : "<null>");
2320         return strcpy(buf, "the []");
2321     }
2322     if (!strncmpi(str, "the ", 4)) {
2323         buf[0] = lowc(*str);
2324         Strcpy(&buf[1], str + 1);
2325         return buf;
2326     } else if (*str < 'A' || *str > 'Z'
2327                /* treat named fruit as not a proper name, even if player
2328                   has assigned a capitalized proper name as his/her fruit */
2329                || fruit_from_name(str, TRUE, (int *) 0)) {
2330         /* not a proper name, needs an article */
2331         insert_the = TRUE;
2332     } else {
2333         /* Probably a proper name, might not need an article */
2334         register char *tmp, *named, *called;
2335         int l;
2336
2337         /* some objects have capitalized adjectives in their names */
2338         if (((tmp = rindex(str, ' ')) != 0 || (tmp = rindex(str, '-')) != 0)
2339             && (tmp[1] < 'A' || tmp[1] > 'Z')) {
2340             insert_the = TRUE;
2341         } else if (tmp && index(str, ' ') < tmp) { /* has spaces */
2342             /* it needs an article if the name contains "of" */
2343             tmp = strstri(str, " of ");
2344             named = strstri(str, " named ");
2345             called = strstri(str, " called ");
2346             if (called && (!named || called < named))
2347                 named = called;
2348
2349             if (tmp && (!named || tmp < named)) /* found an "of" */
2350                 insert_the = TRUE;
2351             /* stupid special case: lacks "of" but needs "the" */
2352             else if (!named && (l = strlen(str)) >= 31
2353                      && !strcmp(&str[l - 31],
2354                                 "Platinum Yendorian Express Card"))
2355                 insert_the = TRUE;
2356         }
2357     }
2358     if (insert_the)
2359         Strcpy(buf, "the ");
2360     else
2361         buf[0] = '\0';
2362     Strcat(buf, str);
2363
2364 #else /*\92P\82É\83R\83s\81[*/
2365     Strcpy(buf, str);
2366 #endif /*JP*/
2367     return buf;
2368 }
2369
2370 char *
2371 The(str)
2372 const char *str;
2373 {
2374     char *tmp = the(str);
2375
2376 #if 0 /*JP*//*\91å\95\8e\9a\89»\82µ\82È\82¢*/
2377     *tmp = highc(*tmp);
2378 #endif
2379     return tmp;
2380 }
2381
2382 #if 1 /*JP*/
2383 char *
2384 aobjnam(otmp, verb)
2385 register struct obj *otmp;
2386 register const char *verb;
2387 {
2388     return xname(otmp);
2389 }
2390
2391 #else
2392 /* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */
2393 char *
2394 aobjnam(otmp, verb)
2395 struct obj *otmp;
2396 const char *verb;
2397 {
2398     char prefix[PREFIX];
2399     char *bp = cxname(otmp);
2400
2401     if (otmp->quan != 1L) {
2402         Sprintf(prefix, "%ld ", otmp->quan);
2403         bp = strprepend(bp, prefix);
2404     }
2405     if (verb) {
2406         Strcat(bp, " ");
2407         Strcat(bp, otense(otmp, verb));
2408     }
2409     return bp;
2410 }
2411 #endif /*JP*/
2412
2413 /* combine yname and aobjnam eg "your count cxname(otmp)" */
2414 char *
2415 yobjnam(obj, verb)
2416 struct obj *obj;
2417 const char *verb;
2418 {
2419     char *s = aobjnam(obj, verb);
2420
2421     /* leave off "your" for most of your artifacts, but prepend
2422      * "your" for unique objects and "foo of bar" quest artifacts */
2423     if (!carried(obj) || !obj_is_pname(obj)
2424         || obj->oartifact >= ART_ORB_OF_DETECTION) {
2425         char *outbuf = shk_your(nextobuf(), obj);
2426         int space_left = BUFSZ - 1 - strlen(outbuf);
2427
2428         s = strncat(outbuf, s, space_left);
2429     }
2430     return s;
2431 }
2432
2433 /* combine Yname2 and aobjnam eg "Your count cxname(otmp)" */
2434 char *
2435 Yobjnam2(obj, verb)
2436 struct obj *obj;
2437 const char *verb;
2438 {
2439     register char *s = yobjnam(obj, verb);
2440
2441 #if 0 /*JP*/
2442     *s = highc(*s);
2443 #endif
2444     return s;
2445 }
2446
2447 /* like aobjnam, but prepend "The", not count, and use xname */
2448 char *
2449 Tobjnam(otmp, verb)
2450 struct obj *otmp;
2451 const char *verb;
2452 {
2453     char *bp = The(xname(otmp));
2454
2455 #if 0 /*JP*//*\93ú\96{\8cê\82É\82Í\8eO\92P\8c»\82Ìs\82Í\82È\82¢*/
2456     if (verb) {
2457         Strcat(bp, " ");
2458         Strcat(bp, otense(otmp, verb));
2459     }
2460 #endif /*JP*/
2461     return bp;
2462 }
2463
2464 /* capitalized variant of doname() */
2465 char *
2466 Doname2(obj)
2467 struct obj *obj;
2468 {
2469     char *s = doname(obj);
2470
2471     *s = highc(*s);
2472     return s;
2473 }
2474
2475 #if 0 /* stalled-out work in progress */
2476 /* Doname2() for itemized buying of 'obj' from a shop */
2477 char *
2478 payDoname(obj)
2479 struct obj *obj;
2480 {
2481     static const char and_contents[] = " and its contents";
2482     char *p = doname(obj);
2483
2484     if (Is_container(obj) && !obj->cknown) {
2485         if (obj->unpaid) {
2486             if ((int) strlen(p) + sizeof and_contents - 1 < BUFSZ - PREFIX)
2487                 Strcat(p, and_contents);
2488             *p = highc(*p);
2489         } else {
2490             p = strprepend(p, "Contents of ");
2491         }
2492     } else {
2493         *p = highc(*p);
2494     }
2495     return p;
2496 }
2497 #endif /*0*/
2498
2499 /* returns "[your ]xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
2500 char *
2501 yname(obj)
2502 struct obj *obj;
2503 {
2504     char *s = cxname(obj);
2505
2506     /* leave off "your" for most of your artifacts, but prepend
2507      * "your" for unique objects and "foo of bar" quest artifacts */
2508     if (!carried(obj) || !obj_is_pname(obj)
2509         || obj->oartifact >= ART_ORB_OF_DETECTION) {
2510         char *outbuf = shk_your(nextobuf(), obj);
2511         int space_left = BUFSZ - 1 - strlen(outbuf);
2512
2513         s = strncat(outbuf, s, space_left);
2514     }
2515
2516     return s;
2517 }
2518
2519 /* capitalized variant of yname() */
2520 char *
2521 Yname2(obj)
2522 struct obj *obj;
2523 {
2524     char *s = yname(obj);
2525
2526 #if 0 /*JP*/
2527     *s = highc(*s);
2528 #endif
2529     return s;
2530 }
2531
2532 /* returns "your minimal_xname(obj)"
2533  * or "Foobar's minimal_xname(obj)"
2534  * or "the minimal_xname(obj)"
2535  */
2536 char *
2537 ysimple_name(obj)
2538 struct obj *obj;
2539 {
2540     char *outbuf = nextobuf();
2541     char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
2542 #if 0 /*JP*/
2543     int space_left = BUFSZ - 1 - strlen(s);
2544
2545     return strncat(s, minimal_xname(obj), space_left);
2546 #else
2547     int space_left = BUFSZ - strlen(s);
2548
2549     return strncat(s, minimal_xname(obj), space_left);
2550 #endif
2551 }
2552
2553 /* capitalized variant of ysimple_name() */
2554 char *
2555 Ysimple_name2(obj)
2556 struct obj *obj;
2557 {
2558     char *s = ysimple_name(obj);
2559
2560 #if 0 /*JP*/
2561     *s = highc(*s);
2562 #endif
2563     return s;
2564 }
2565
2566 /* "scroll" or "scrolls" */
2567 char *
2568 simpleonames(obj)
2569 struct obj *obj;
2570 {
2571     char *simpleoname = minimal_xname(obj);
2572
2573 #if 0 /*JP*//*\93ú\96{\8cê\82Í\92P\95¡\93¯\8c^*/
2574     if (obj->quan != 1L)
2575         simpleoname = makeplural(simpleoname);
2576 #endif
2577     return simpleoname;
2578 }
2579
2580 /* "a scroll" or "scrolls"; "a silver bell" or "the Bell of Opening" */
2581 char *
2582 ansimpleoname(obj)
2583 struct obj *obj;
2584 {
2585     char *simpleoname = simpleonames(obj);
2586     int otyp = obj->otyp;
2587
2588     /* prefix with "the" if a unique item, or a fake one imitating same,
2589        has been formatted with its actual name (we let typename() handle
2590        any `known' and `dknown' checking necessary) */
2591     if (otyp == FAKE_AMULET_OF_YENDOR)
2592         otyp = AMULET_OF_YENDOR;
2593     if (objects[otyp].oc_unique
2594         && !strcmp(simpleoname, OBJ_NAME(objects[otyp])))
2595         return the(simpleoname);
2596
2597     /* simpleoname is singular if quan==1, plural otherwise */
2598     if (obj->quan == 1L)
2599         simpleoname = an(simpleoname);
2600     return simpleoname;
2601 }
2602
2603 /* "the scroll" or "the scrolls" */
2604 char *
2605 thesimpleoname(obj)
2606 struct obj *obj;
2607 {
2608     char *simpleoname = simpleonames(obj);
2609
2610     return the(simpleoname);
2611 }
2612
2613 /* artifact's name without any object type or known/dknown/&c feedback */
2614 char *
2615 bare_artifactname(obj)
2616 struct obj *obj;
2617 {
2618     char *outbuf;
2619
2620     if (obj->oartifact) {
2621         outbuf = nextobuf();
2622         Strcpy(outbuf, artiname(obj->oartifact));
2623 #if 0 /*JP*/
2624         if (!strncmp(outbuf, "The ", 4))
2625             outbuf[0] = lowc(outbuf[0]);
2626 #endif
2627     } else {
2628         outbuf = xname(obj);
2629     }
2630     return outbuf;
2631 }
2632
2633 #if 0 /*JP*/
2634 static const char *wrp[] = {
2635     "wand",   "ring",      "potion",     "scroll", "gem",
2636     "amulet", "spellbook", "spell book",
2637     /* for non-specific wishes */
2638     "weapon", "armor",     "tool",       "food",   "comestible",
2639 };
2640 #endif
2641 static const char wrpsym[] = { WAND_CLASS,   RING_CLASS,   POTION_CLASS,
2642                                SCROLL_CLASS, GEM_CLASS,    AMULET_CLASS,
2643                                SPBOOK_CLASS, SPBOOK_CLASS, WEAPON_CLASS,
2644                                ARMOR_CLASS,  TOOL_CLASS,   FOOD_CLASS,
2645                                FOOD_CLASS };
2646
2647 #if 0 /*JP*//*\93ú\96{\8cê\82É\82Í\8eO\92P\8c»\82Ìs\82Í\82È\82¢*/
2648 /* return form of the verb (input plural) if xname(otmp) were the subject */
2649 char *
2650 otense(otmp, verb)
2651 struct obj *otmp;
2652 const char *verb;
2653 {
2654     char *buf;
2655
2656     /*
2657      * verb is given in plural (without trailing s).  Return as input
2658      * if the result of xname(otmp) would be plural.  Don't bother
2659      * recomputing xname(otmp) at this time.
2660      */
2661     if (!is_plural(otmp))
2662         return vtense((char *) 0, verb);
2663
2664     buf = nextobuf();
2665     Strcpy(buf, verb);
2666     return buf;
2667 }
2668
2669 /* various singular words that vtense would otherwise categorize as plural;
2670    also used by makesingular() to catch some special cases */
2671 static const char *const special_subjs[] = {
2672     "erinys",  "manes", /* this one is ambiguous */
2673     "Cyclops", "Hippocrates",     "Pelias",    "aklys",
2674     "amnesia", "detect monsters", "paralysis", "shape changers",
2675     "nemesis", 0
2676     /* note: "detect monsters" and "shape changers" are normally
2677        caught via "<something>(s) of <whatever>", but they can be
2678        wished for using the shorter form, so we include them here
2679        to accommodate usage by makesingular during wishing */
2680 };
2681
2682 /* return form of the verb (input plural) for present tense 3rd person subj */
2683 char *
2684 vtense(subj, verb)
2685 register const char *subj;
2686 register const char *verb;
2687 {
2688     char *buf = nextobuf(), *bspot;
2689     int len, ltmp;
2690     const char *sp, *spot;
2691     const char *const *spec;
2692
2693     /*
2694      * verb is given in plural (without trailing s).  Return as input
2695      * if subj appears to be plural.  Add special cases as necessary.
2696      * Many hard cases can already be handled by using otense() instead.
2697      * If this gets much bigger, consider decomposing makeplural.
2698      * Note: monster names are not expected here (except before corpse).
2699      *
2700      * Special case: allow null sobj to get the singular 3rd person
2701      * present tense form so we don't duplicate this code elsewhere.
2702      */
2703     if (subj) {
2704         if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
2705             goto sing;
2706         spot = (const char *) 0;
2707         for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
2708             if (!strncmpi(sp, " of ", 4) || !strncmpi(sp, " from ", 6)
2709                 || !strncmpi(sp, " called ", 8) || !strncmpi(sp, " named ", 7)
2710                 || !strncmpi(sp, " labeled ", 9)) {
2711                 if (sp != subj)
2712                     spot = sp - 1;
2713                 break;
2714             }
2715         }
2716         len = (int) strlen(subj);
2717         if (!spot)
2718             spot = subj + len - 1;
2719
2720         /*
2721          * plural: anything that ends in 's', but not '*us' or '*ss'.
2722          * Guess at a few other special cases that makeplural creates.
2723          */
2724         if ((lowc(*spot) == 's' && spot != subj
2725              && !index("us", lowc(*(spot - 1))))
2726             || !BSTRNCMPI(subj, spot - 3, "eeth", 4)
2727             || !BSTRNCMPI(subj, spot - 3, "feet", 4)
2728             || !BSTRNCMPI(subj, spot - 1, "ia", 2)
2729             || !BSTRNCMPI(subj, spot - 1, "ae", 2)) {
2730             /* check for special cases to avoid false matches */
2731             len = (int) (spot - subj) + 1;
2732             for (spec = special_subjs; *spec; spec++) {
2733                 ltmp = strlen(*spec);
2734                 if (len == ltmp && !strncmpi(*spec, subj, len))
2735                     goto sing;
2736                 /* also check for <prefix><space><special_subj>
2737                    to catch things like "the invisible erinys" */
2738                 if (len > ltmp && *(spot - ltmp) == ' '
2739                     && !strncmpi(*spec, spot - ltmp + 1, ltmp))
2740                     goto sing;
2741             }
2742
2743             return strcpy(buf, verb);
2744         }
2745         /*
2746          * 3rd person plural doesn't end in telltale 's';
2747          * 2nd person singular behaves as if plural.
2748          */
2749         if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
2750             return strcpy(buf, verb);
2751     }
2752
2753  sing:
2754     Strcpy(buf, verb);
2755     len = (int) strlen(buf);
2756     bspot = buf + len - 1;
2757
2758     if (!strcmpi(buf, "are")) {
2759         Strcasecpy(buf, "is");
2760     } else if (!strcmpi(buf, "have")) {
2761         Strcasecpy(bspot - 1, "s");
2762     } else if (index("zxs", lowc(*bspot))
2763                || (len >= 2 && lowc(*bspot) == 'h'
2764                    && index("cs", lowc(*(bspot - 1))))
2765                || (len == 2 && lowc(*bspot) == 'o')) {
2766         /* Ends in z, x, s, ch, sh; add an "es" */
2767         Strcasecpy(bspot + 1, "es");
2768     } else if (lowc(*bspot) == 'y' && !index(vowels, lowc(*(bspot - 1)))) {
2769         /* like "y" case in makeplural */
2770         Strcasecpy(bspot, "ies");
2771     } else {
2772         Strcasecpy(bspot + 1, "s");
2773     }
2774
2775     return buf;
2776 }
2777 #endif
2778
2779 #if 0 /*JP*/
2780 struct sing_plur {
2781     const char *sing, *plur;
2782 };
2783
2784 /* word pairs that don't fit into formula-based transformations;
2785    also some suffices which have very few--often one--matches or
2786    which aren't systematically reversible (knives, staves) */
2787 static struct sing_plur one_off[] = {
2788     { "child",
2789       "children" },      /* (for wise guys who give their food funny names) */
2790     { "cubus", "cubi" }, /* in-/suc-cubus */
2791     { "culus", "culi" }, /* homunculus */
2792     { "djinni", "djinn" },
2793     { "erinys", "erinyes" },
2794     { "foot", "feet" },
2795     { "fungus", "fungi" },
2796     { "goose", "geese" },
2797     { "knife", "knives" },
2798     { "labrum", "labra" }, /* candelabrum */
2799     { "louse", "lice" },
2800     { "mouse", "mice" },
2801     { "mumak", "mumakil" },
2802     { "nemesis", "nemeses" },
2803     { "ovum", "ova" },
2804     { "ox", "oxen" },
2805     { "passerby", "passersby" },
2806     { "rtex", "rtices" }, /* vortex */
2807     { "serum", "sera" },
2808     { "staff", "staves" },
2809     { "tooth", "teeth" },
2810     { 0, 0 }
2811 };
2812
2813 static const char *const as_is[] = {
2814     /* makesingular() leaves these plural due to how they're used */
2815     "boots",   "shoes",     "gloves",    "lenses",   "scales",
2816     "eyes",    "gauntlets", "iron bars",
2817     /* both singular and plural are spelled the same */
2818     "bison",   "deer",      "elk",       "fish",      "fowl",
2819     "tuna",    "yaki",      "-hai",      "krill",     "manes",
2820     "moose",   "ninja",     "sheep",     "ronin",     "roshi",
2821     "shito",   "tengu",     "ki-rin",    "Nazgul",    "gunyoki",
2822     "piranha", "samurai",   "shuriken", 0,
2823     /* Note:  "fish" and "piranha" are collective plurals, suitable
2824        for "wiped out all <foo>".  For "3 <foo>", they should be
2825        "fishes" and "piranhas" instead.  We settle for collective
2826        variant instead of attempting to support both. */
2827 };
2828
2829 /* singularize/pluralize decisions common to both makesingular & makeplural */
2830 STATIC_OVL boolean
2831 singplur_lookup(basestr, endstring, to_plural, alt_as_is)
2832 char *basestr, *endstring;    /* base string, pointer to eos(string) */
2833 boolean to_plural;            /* true => makeplural, false => makesingular */
2834 const char *const *alt_as_is; /* another set like as_is[] */
2835 {
2836     const struct sing_plur *sp;
2837     const char *same, *other, *const *as;
2838     int al;
2839     int baselen = strlen(basestr);
2840
2841     for (as = as_is; *as; ++as) {
2842         al = (int) strlen(*as);
2843         if (!BSTRCMPI(basestr, endstring - al, *as))
2844             return TRUE;
2845     }
2846     if (alt_as_is) {
2847         for (as = alt_as_is; *as; ++as) {
2848             al = (int) strlen(*as);
2849             if (!BSTRCMPI(basestr, endstring - al, *as))
2850                 return TRUE;
2851         }
2852     }
2853
2854    /* Leave "craft" as a suffix as-is (aircraft, hovercraft);
2855       "craft" itself is (arguably) not included in our likely context */
2856    if ((baselen > 5) && (!BSTRCMPI(basestr, endstring - 5, "craft")))
2857        return TRUE;
2858    /* avoid false hit on one_off[].plur == "lice" or .sing == "goose";
2859        if more of these turn up, one_off[] entries will need to flagged
2860        as to which are whole words and which are matchable as suffices
2861        then matching in the loop below will end up becoming more complex */
2862     if (!strcmpi(basestr, "slice")
2863         || !strcmpi(basestr, "mongoose")) {
2864         if (to_plural)
2865             Strcasecpy(endstring, "s");
2866         return TRUE;
2867     }
2868     /* skip "ox" -> "oxen" entry when pluralizing "<something>ox"
2869        unless it is muskox */
2870     if (to_plural && baselen > 2 && !strcmpi(endstring - 2, "ox")
2871         && !(baselen > 5 && !strcmpi(endstring - 6, "muskox"))) {
2872         /* "fox" -> "foxes" */
2873         Strcasecpy(endstring, "es");
2874         return TRUE;
2875     }
2876     if (to_plural) {
2877         if (baselen > 2 && !strcmpi(endstring - 3, "man")
2878             && badman(basestr, to_plural)) {
2879             Strcasecpy(endstring, "s");
2880             return TRUE;
2881         }
2882     } else {
2883         if (baselen > 2 && !strcmpi(endstring - 3, "men")
2884             && badman(basestr, to_plural))
2885             return TRUE;
2886     }
2887     for (sp = one_off; sp->sing; sp++) {
2888         /* check whether endstring already matches */
2889         same = to_plural ? sp->plur : sp->sing;
2890         al = (int) strlen(same);
2891         if (!BSTRCMPI(basestr, endstring - al, same))
2892             return TRUE; /* use as-is */
2893         /* check whether it matches the inverse; if so, transform it */
2894         other = to_plural ? sp->sing : sp->plur;
2895         al = (int) strlen(other);
2896         if (!BSTRCMPI(basestr, endstring - al, other)) {
2897             Strcasecpy(endstring - al, same);
2898             return TRUE; /* one_off[] transformation */
2899         }
2900     }
2901     return FALSE;
2902 }
2903
2904 /* searches for common compounds, ex. lump of royal jelly */
2905 STATIC_OVL char *
2906 singplur_compound(str)
2907 char *str;
2908 {
2909     /* if new entries are added, be sure to keep compound_start[] in sync */
2910     static const char *const compounds[] =
2911         {
2912           " of ",     " labeled ", " called ",
2913           " named ",  " above", /* lurkers above */
2914           " versus ", " from ",    " in ",
2915           " on ",     " a la ",    " with", /* " with "? */
2916           " de ",     " d'",       " du ",
2917           "-in-",     "-at-",      0
2918         }, /* list of first characters for all compounds[] entries */
2919         compound_start[] = " -";
2920
2921     const char *const *cmpd;
2922     char *p;
2923
2924     for (p = str; *p; ++p) {
2925         /* substring starting at p can only match if *p is found
2926            within compound_start[] */
2927         if (!index(compound_start, *p))
2928             continue;
2929
2930         /* check current substring against all words in the compound[] list */
2931         for (cmpd = compounds; *cmpd; ++cmpd)
2932             if (!strncmpi(p, *cmpd, (int) strlen(*cmpd)))
2933                 return p;
2934     }
2935     /* wasn't recognized as a compound phrase */
2936     return 0;
2937 }
2938 #endif
2939
2940 /* Plural routine; once upon a time it may have been chiefly used for
2941  * user-defined fruits, but it is now used extensively throughout the
2942  * program.
2943  *
2944  * For fruit, we have to try to account for everything reasonable the
2945  * player has; something unreasonable can still break the code.
2946  * However, it's still a lot more accurate than "just add an 's' at the
2947  * end", which Rogue uses...
2948  *
2949  * Also used for plural monster names ("Wiped out all homunculi." or the
2950  * vanquished monsters list) and body parts.  A lot of unique monsters have
2951  * names which get mangled by makeplural and/or makesingular.  They're not
2952  * genocidable, and vanquished-mon handling does its own special casing
2953  * (for uniques who've been revived and re-killed), so we don't bother
2954  * trying to get those right here.
2955  *
2956  * Also misused by muse.c to convert 1st person present verbs to 2nd person.
2957  * 3.6.0: made case-insensitive.
2958  */
2959 char *
2960 makeplural(oldstr)
2961 const char *oldstr;
2962 {
2963 #if 0 /*JP*//*\93ú\96{\8cê\82Í\92P\95¡\93¯\8c^*/
2964     register char *spot;
2965     char lo_c, *str = nextobuf();
2966     const char *excess = (char *) 0;
2967     int len;
2968
2969     if (oldstr)
2970         while (*oldstr == ' ')
2971             oldstr++;
2972     if (!oldstr || !*oldstr) {
2973         impossible("plural of null?");
2974         Strcpy(str, "s");
2975         return str;
2976     }
2977     Strcpy(str, oldstr);
2978
2979     /*
2980      * Skip changing "pair of" to "pairs of".  According to Webster, usual
2981      * English usage is use pairs for humans, e.g. 3 pairs of dancers,
2982      * and pair for objects and non-humans, e.g. 3 pair of boots.  We don't
2983      * refer to pairs of humans in this game so just skip to the bottom.
2984      */
2985     if (!strncmpi(str, "pair of ", 8))
2986         goto bottom;
2987
2988     /* look for "foo of bar" so that we can focus on "foo" */
2989     if ((spot = singplur_compound(str)) != 0) {
2990         excess = oldstr + (int) (spot - str);
2991         *spot = '\0';
2992     } else
2993         spot = eos(str);
2994
2995     spot--;
2996     while (spot > str && *spot == ' ')
2997         spot--; /* Strip blanks from end */
2998     *(spot + 1) = '\0';
2999     /* Now spot is the last character of the string */
3000
3001     len = strlen(str);
3002
3003     /* Single letters */
3004     if (len == 1 || !letter(*spot)) {
3005         Strcpy(spot + 1, "'s");
3006         goto bottom;
3007     }
3008
3009     /* dispense with some words which don't need pluralization */
3010     {
3011         static const char *const already_plural[] = {
3012             "ae",  /* algae, larvae, &c */
3013             "matzot", 0,
3014         };
3015
3016         /* spot+1: synch up with makesingular's usage */
3017         if (singplur_lookup(str, spot + 1, TRUE, already_plural))
3018             goto bottom;
3019
3020         /* more of same, but not suitable for blanket loop checking */
3021         if ((len == 2 && !strcmpi(str, "ya"))
3022             || (len >= 3 && !strcmpi(spot - 2, " ya")))
3023             goto bottom;
3024     }
3025
3026     /* man/men ("Wiped out all cavemen.") */
3027     if (len >= 3 && !strcmpi(spot - 2, "man")
3028         /* exclude shamans and humans etc */
3029         && !badman(str, TRUE)) {
3030         Strcasecpy(spot - 1, "en");
3031         goto bottom;
3032     }
3033     if (lowc(*spot) == 'f') { /* (staff handled via one_off[]) */
3034         lo_c = lowc(*(spot - 1));
3035         if (len >= 3 && !strcmpi(spot - 2, "erf")) {
3036             /* avoid "nerf" -> "nerves", "serf" -> "serves" */
3037             ; /* fall through to default (append 's') */
3038         } else if (index("lr", lo_c) || index(vowels, lo_c)) {
3039             /* [aeioulr]f to [aeioulr]ves */
3040             Strcasecpy(spot, "ves");
3041             goto bottom;
3042         }
3043     }
3044     /* ium/ia (mycelia, baluchitheria) */
3045     if (len >= 3 && !strcmpi(spot - 2, "ium")) {
3046         Strcasecpy(spot - 2, "ia");
3047         goto bottom;
3048     }
3049     /* algae, larvae, hyphae (another fungus part) */
3050     if ((len >= 4 && !strcmpi(spot - 3, "alga"))
3051         || (len >= 5
3052             && (!strcmpi(spot - 4, "hypha") || !strcmpi(spot - 4, "larva")))
3053         || (len >= 6 && !strcmpi(spot - 5, "amoeba"))
3054         || (len >= 8 && (!strcmpi(spot - 7, "vertebra")))) {
3055         /* a to ae */
3056         Strcasecpy(spot + 1, "e");
3057         goto bottom;
3058     }
3059     /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
3060     if (len > 3 && !strcmpi(spot - 1, "us")
3061         && !((len >= 5 && !strcmpi(spot - 4, "lotus"))
3062              || (len >= 6 && !strcmpi(spot - 5, "wumpus")))) {
3063         Strcasecpy(spot - 1, "i");
3064         goto bottom;
3065     }
3066     /* sis/ses (nemesis) */
3067     if (len >= 3 && !strcmpi(spot - 2, "sis")) {
3068         Strcasecpy(spot - 1, "es");
3069         goto bottom;
3070     }
3071     /* matzoh/matzot, possible food name */
3072     if (len >= 6
3073         && (!strcmpi(spot - 5, "matzoh") || !strcmpi(spot - 5, "matzah"))) {
3074         Strcasecpy(spot - 1, "ot"); /* oh/ah -> ot */
3075         goto bottom;
3076     }
3077     if (len >= 5
3078         && (!strcmpi(spot - 4, "matzo") || !strcmpi(spot - 4, "matza"))) {
3079         Strcasecpy(spot, "ot"); /* o/a -> ot */
3080         goto bottom;
3081     }
3082
3083     /* note: -eau/-eaux (gateau, bordeau...) */
3084     /* note: ox/oxen, VAX/VAXen, goose/geese */
3085
3086     lo_c = lowc(*spot);
3087
3088     /* codex/spadix/neocortex and the like */
3089     if (len >= 5
3090         && (!strcmpi(spot - 2, "dex")
3091             ||!strcmpi(spot - 2, "dix")
3092             ||!strcmpi(spot - 2, "tex"))
3093            /* indices would have been ok too, but stick with indexes */
3094         && (strcmpi(spot - 4,"index") != 0)) {
3095         Strcasecpy(spot - 1, "ices"); /* ex|ix -> ices */
3096         goto bottom;
3097     }
3098     /* Ends in z, x, s, ch, sh; add an "es" */
3099     if (index("zxs", lo_c)
3100         || (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot - 1)))
3101             /* 21st century k-sound */
3102             && !(len >= 4 &&
3103                  ((lowc(*(spot - 2)) == 'e'
3104                     && index("mt", lowc(*(spot - 3)))) ||
3105                   (lowc(*(spot - 2)) == 'o'
3106                     && index("lp", lowc(*(spot - 3)))))))
3107         /* Kludge to get "tomatoes" and "potatoes" right */
3108         || (len >= 4 && !strcmpi(spot - 2, "ato"))
3109         || (len >= 5 && !strcmpi(spot - 4, "dingo"))) {
3110         Strcasecpy(spot + 1, "es"); /* append es */
3111         goto bottom;
3112     }
3113     /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
3114     if (lo_c == 'y' && !index(vowels, lowc(*(spot - 1)))) {
3115         Strcasecpy(spot, "ies"); /* y -> ies */
3116         goto bottom;
3117     }
3118     /* Default: append an 's' */
3119     Strcasecpy(spot + 1, "s");
3120
3121  bottom:
3122     if (excess)
3123         Strcat(str, excess);
3124 #else /*JP*//*\90V\82µ\82¢\83o\83b\83t\83@\82Í\95K\97v*/
3125     char *str = nextobuf();
3126     Strcpy(str, oldstr);
3127 #endif
3128     return str;
3129 }
3130
3131 /*
3132  * Singularize a string the user typed in; this helps reduce the complexity
3133  * of readobjnam, and is also used in pager.c to singularize the string
3134  * for which help is sought.
3135  *
3136  * "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)?
3137  * Its inclusion in as_is[]/special_subj[] makes it get treated as the former.
3138  *
3139  * A lot of unique monsters have names ending in s; plural, or singular
3140  * from plural, doesn't make much sense for them so we don't bother trying.
3141  * 3.6.0: made case-insensitive.
3142  */
3143 char *
3144 makesingular(oldstr)
3145 const char *oldstr;
3146 {
3147 #if 0 /*JP*//*\93ú\96{\8cê\82Í\92P\95¡\93¯\8c^*/
3148     register char *p, *bp;
3149     const char *excess = 0;
3150     char *str = nextobuf();
3151
3152     if (oldstr)
3153         while (*oldstr == ' ')
3154             oldstr++;
3155     if (!oldstr || !*oldstr) {
3156         impossible("singular of null?");
3157         str[0] = '\0';
3158         return str;
3159     }
3160
3161     bp = strcpy(str, oldstr);
3162
3163     /* check for "foo of bar" so that we can focus on "foo" */
3164     if ((p = singplur_compound(bp)) != 0) {
3165         excess = oldstr + (int) (p - bp);
3166         *p = '\0';
3167     } else
3168         p = eos(bp);
3169
3170     /* dispense with some words which don't need singularization */
3171     if (singplur_lookup(bp, p, FALSE, special_subjs))
3172         goto bottom;
3173
3174     /* remove -s or -es (boxes) or -ies (rubies) */
3175     if (p >= bp + 1 && lowc(p[-1]) == 's') {
3176         if (p >= bp + 2 && lowc(p[-2]) == 'e') {
3177             if (p >= bp + 3 && lowc(p[-3]) == 'i') { /* "ies" */
3178                 if (!BSTRCMPI(bp, p - 7, "cookies")
3179                     || (!BSTRCMPI(bp, p - 4, "pies")
3180                         /* avoid false match for "harpies" */
3181                         && (p - 4 == bp || p[-5] == ' '))
3182                     /* alternate djinni/djinn spelling; not really needed */
3183                     || (!BSTRCMPI(bp, p - 6, "genies")
3184                         /* avoid false match for "progenies" */
3185                         && (p - 6 == bp || p[-7] == ' '))
3186                     || !BSTRCMPI(bp, p - 5, "mbies") /* zombie */
3187                     || !BSTRCMPI(bp, p - 5, "yries")) /* valkyrie */
3188                     goto mins;
3189                 Strcasecpy(p - 3, "y"); /* ies -> y */
3190                 goto bottom;
3191             }
3192             /* wolves, but f to ves isn't fully reversible */
3193             if (p - 4 >= bp && (index("lr", lowc(*(p - 4)))
3194                                 || index(vowels, lowc(*(p - 4))))
3195                 && !BSTRCMPI(bp, p - 3, "ves")) {
3196                 if (!BSTRCMPI(bp, p - 6, "cloves")
3197                     || !BSTRCMPI(bp, p - 6, "nerves"))
3198                     goto mins;
3199                 Strcasecpy(p - 3, "f"); /* ves -> f */
3200                 goto bottom;
3201             }
3202             /* note: nurses, axes but boxes, wumpuses */
3203             if (!BSTRCMPI(bp, p - 4, "eses")
3204                 || !BSTRCMPI(bp, p - 4, "oxes") /* boxes, foxes */
3205                 || !BSTRCMPI(bp, p - 4, "nxes") /* lynxes */
3206                 || !BSTRCMPI(bp, p - 4, "ches")
3207                 || !BSTRCMPI(bp, p - 4, "uses") /* lotuses */
3208                 || !BSTRCMPI(bp, p - 4, "sses") /* priestesses */
3209                 || !BSTRCMPI(bp, p - 5, "atoes") /* tomatoes */
3210                 || !BSTRCMPI(bp, p - 7, "dingoes")
3211                 || !BSTRCMPI(bp, p - 7, "Aleaxes")) {
3212                 *(p - 2) = '\0'; /* drop es */
3213                 goto bottom;
3214             } /* else fall through to mins */
3215
3216             /* ends in 's' but not 'es' */
3217         } else if (!BSTRCMPI(bp, p - 2, "us")) { /* lotus, fungus... */
3218             if (BSTRCMPI(bp, p - 6, "tengus") /* but not these... */
3219                 && BSTRCMPI(bp, p - 7, "hezrous"))
3220                 goto bottom;
3221         } else if (!BSTRCMPI(bp, p - 2, "ss")
3222                    || !BSTRCMPI(bp, p - 5, " lens")
3223                    || (p - 4 == bp && !strcmpi(p - 4, "lens"))) {
3224             goto bottom;
3225         }
3226  mins:
3227         *(p - 1) = '\0'; /* drop s */
3228
3229     } else { /* input doesn't end in 's' */
3230
3231         if (!BSTRCMPI(bp, p - 3, "men")
3232             && !badman(bp, FALSE)) {
3233             Strcasecpy(p - 2, "an");
3234             goto bottom;
3235         }
3236         /* matzot -> matzo, algae -> alga */
3237         if (!BSTRCMPI(bp, p - 6, "matzot") || !BSTRCMPI(bp, p - 2, "ae")) {
3238             *(p - 1) = '\0'; /* drop t/e */
3239             goto bottom;
3240         }
3241         /* balactheria -> balactherium */
3242         if (p - 4 >= bp && !strcmpi(p - 2, "ia")
3243             && index("lr", lowc(*(p - 3))) && lowc(*(p - 4)) == 'e') {
3244             Strcasecpy(p - 1, "um"); /* a -> um */
3245         }
3246
3247         /* here we cannot find the plural suffix */
3248     }
3249
3250  bottom:
3251     /* if we stripped off a suffix (" of bar" from "foo of bar"),
3252        put it back now [strcat() isn't actually 100% safe here...] */
3253     if (excess)
3254         Strcat(bp, excess);
3255
3256     return bp;
3257 #else /*JP*//*\90V\82µ\82¢\83o\83b\83t\83@\82Í\95K\97v*/
3258     char *str = nextobuf();
3259     Strcpy(str, oldstr);
3260     return str;
3261 #endif
3262 }
3263
3264 #if 0 /*JP*/
3265 STATIC_OVL boolean
3266 badman(basestr, to_plural)
3267 const char *basestr;
3268 boolean to_plural;            /* true => makeplural, false => makesingular */
3269 {
3270     /* these are all the prefixes for *man that don't have a *men plural */
3271     static const char *no_men[] = {
3272         "albu", "antihu", "anti", "ata", "auto", "bildungsro", "cai", "cay",
3273         "ceru", "corner", "decu", "des", "dura", "fir", "hanu", "het",
3274         "infrahu", "inhu", "nonhu", "otto", "out", "prehu", "protohu",
3275         "subhu", "superhu", "talis", "unhu", "sha",
3276         "hu", "un", "le", "re", "so", "to", "at", "a",
3277     };
3278     /* these are all the prefixes for *men that don't have a *man singular */
3279     static const char *no_man[] = {
3280         "abdo", "acu", "agno", "ceru", "cogno", "cycla", "fleh", "grava",
3281         "hegu", "preno", "sonar", "speci", "dai", "exa", "fla", "sta", "teg",
3282         "tegu", "vela", "da", "hy", "lu", "no", "nu", "ra", "ru", "se", "vi",
3283         "ya", "o", "a",
3284     };
3285     int i, al;
3286     const char *endstr, *spot;
3287
3288     if (!basestr || strlen(basestr) < 4)
3289         return FALSE;
3290
3291     endstr = eos((char *) basestr);
3292
3293     if (to_plural) {
3294         for (i = 0; i < SIZE(no_men); i++) {
3295             al = (int) strlen(no_men[i]);
3296             spot = endstr - (al + 3);
3297             if (!BSTRNCMPI(basestr, spot, no_men[i], al)
3298                 && (spot == basestr || *(spot - 1) == ' '))
3299                 return TRUE;
3300         }
3301     } else {
3302         for (i = 0; i < SIZE(no_man); i++) {
3303             al = (int) strlen(no_man[i]);
3304             spot = endstr - (al + 3);
3305             if (!BSTRNCMPI(basestr, spot, no_man[i], al)
3306                 && (spot == basestr || *(spot - 1) == ' '))
3307                 return TRUE;
3308         }
3309     }
3310     return FALSE;
3311 }
3312 #endif
3313
3314 /* compare user string against object name string using fuzzy matching */
3315 STATIC_OVL boolean
3316 wishymatch(u_str, o_str, retry_inverted)
3317 const char *u_str;      /* from user, so might be variant spelling */
3318 const char *o_str;      /* from objects[], so is in canonical form */
3319 boolean retry_inverted; /* optional extra "of" handling */
3320 {
3321     static NEARDATA const char detect_SP[] = "detect ",
3322                                SP_detection[] = " detection";
3323     char *p, buf[BUFSZ];
3324
3325     /* ignore spaces & hyphens and upper/lower case when comparing */
3326     if (fuzzymatch(u_str, o_str, " -", TRUE))
3327         return TRUE;
3328
3329     if (retry_inverted) {
3330         const char *u_of, *o_of;
3331
3332         /* when just one of the strings is in the form "foo of bar",
3333            convert it into "bar foo" and perform another comparison */
3334         u_of = strstri(u_str, " of ");
3335         o_of = strstri(o_str, " of ");
3336         if (u_of && !o_of) {
3337             Strcpy(buf, u_of + 4);
3338             p = eos(strcat(buf, " "));
3339             while (u_str < u_of)
3340                 *p++ = *u_str++;
3341             *p = '\0';
3342             return fuzzymatch(buf, o_str, " -", TRUE);
3343         } else if (o_of && !u_of) {
3344             Strcpy(buf, o_of + 4);
3345             p = eos(strcat(buf, " "));
3346             while (o_str < o_of)
3347                 *p++ = *o_str++;
3348             *p = '\0';
3349             return fuzzymatch(u_str, buf, " -", TRUE);
3350         }
3351     }
3352
3353     /* [note: if something like "elven speed boots" ever gets added, these
3354        special cases should be changed to call wishymatch() recursively in
3355        order to get the "of" inversion handling] */
3356     if (!strncmp(o_str, "dwarvish ", 9)) {
3357         if (!strncmpi(u_str, "dwarven ", 8))
3358             return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
3359     } else if (!strncmp(o_str, "elven ", 6)) {
3360         if (!strncmpi(u_str, "elvish ", 7))
3361             return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
3362         else if (!strncmpi(u_str, "elfin ", 6))
3363             return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
3364     } else if (!strncmp(o_str, detect_SP, sizeof detect_SP - 1)) {
3365         /* check for "detect <foo>" vs "<foo> detection" */
3366         if ((p = strstri(u_str, SP_detection)) != 0
3367             && !*(p + sizeof SP_detection - 1)) {
3368             /* convert "<foo> detection" into "detect <foo>" */
3369             *p = '\0';
3370             Strcat(strcpy(buf, detect_SP), u_str);
3371             /* "detect monster" -> "detect monsters" */
3372             if (!strcmpi(u_str, "monster"))
3373                 Strcat(buf, "s");
3374             *p = ' ';
3375             return fuzzymatch(buf, o_str, " -", TRUE);
3376         }
3377     } else if (strstri(o_str, SP_detection)) {
3378         /* and the inverse, "<foo> detection" vs "detect <foo>" */
3379         if (!strncmpi(u_str, detect_SP, sizeof detect_SP - 1)) {
3380             /* convert "detect <foo>s" into "<foo> detection" */
3381             p = makesingular(u_str + sizeof detect_SP - 1);
3382             Strcat(strcpy(buf, p), SP_detection);
3383             /* caller may be looping through objects[], so avoid
3384                churning through all the obufs */
3385             releaseobuf(p);
3386             return fuzzymatch(buf, o_str, " -", TRUE);
3387         }
3388     } else if (strstri(o_str, "ability")) {
3389         /* when presented with "foo of bar", makesingular() used to
3390            singularize both foo & bar, but now only does so for foo */
3391         /* catch "{potion(s),ring} of {gain,restore,sustain} abilities" */
3392         if ((p = strstri(u_str, "abilities")) != 0
3393             && !*(p + sizeof "abilities" - 1)) {
3394             (void) strncpy(buf, u_str, (unsigned) (p - u_str));
3395             Strcpy(buf + (p - u_str), "ability");
3396             return fuzzymatch(buf, o_str, " -", TRUE);
3397         }
3398     } else if (!strcmp(o_str, "aluminum")) {
3399         /* this special case doesn't really fit anywhere else... */
3400         /* (note that " wand" will have been stripped off by now) */
3401         if (!strcmpi(u_str, "aluminium"))
3402             return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
3403     }
3404
3405     return FALSE;
3406 }
3407
3408 struct o_range {
3409     const char *name, oclass;
3410     int f_o_range, l_o_range;
3411 };
3412
3413 #if 0 /*JP*//*\95\94\95ª\93I\82È\83W\83\83\83\93\83\8b\8ew\92è\82Å\82Ì\8aè\82¢\97p\81B\93ú\96{\8cê\82Å\82Í\82Æ\82è\82 \82¦\82¸\82µ\82È\82¢*/
3414 /* wishable subranges of objects */
3415 STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
3416     { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
3417     { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
3418     { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
3419     { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
3420     { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
3421     { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
3422     { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
3423     { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3424     { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
3425     { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
3426     { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
3427     { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
3428     { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
3429     { "dragon scales", ARMOR_CLASS, GRAY_DRAGON_SCALES,
3430       YELLOW_DRAGON_SCALES },
3431     { "dragon scale mail", ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL,
3432       YELLOW_DRAGON_SCALE_MAIL },
3433     { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
3434     { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
3435     { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
3436     { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
3437 };
3438 #endif
3439
3440
3441 #if 0 /*JP*//*not used*/
3442 /* alternate spellings; if the difference is only the presence or
3443    absence of spaces and/or hyphens (such as "pickaxe" vs "pick axe"
3444    vs "pick-axe") then there is no need for inclusion in this list;
3445    likewise for ``"of" inversions'' ("boots of speed" vs "speed boots") */
3446 static const struct alt_spellings {
3447     const char *sp;
3448     int ob;
3449 } spellings[] = {
3450     { "pickax", PICK_AXE },
3451     { "whip", BULLWHIP },
3452     { "saber", SILVER_SABER },
3453     { "silver sabre", SILVER_SABER },
3454     { "smooth shield", SHIELD_OF_REFLECTION },
3455     { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
3456     { "grey dragon scales", GRAY_DRAGON_SCALES },
3457     { "iron ball", HEAVY_IRON_BALL },
3458     { "lantern", BRASS_LANTERN },
3459     { "mattock", DWARVISH_MATTOCK },
3460     { "amulet of poison resistance", AMULET_VERSUS_POISON },
3461     { "potion of sleep", POT_SLEEPING },
3462     { "stone", ROCK },
3463     { "camera", EXPENSIVE_CAMERA },
3464     { "tee shirt", T_SHIRT },
3465     { "can", TIN },
3466     { "can opener", TIN_OPENER },
3467     { "kelp", KELP_FROND },
3468     { "eucalyptus", EUCALYPTUS_LEAF },
3469     { "royal jelly", LUMP_OF_ROYAL_JELLY },
3470     { "lembas", LEMBAS_WAFER },
3471     { "cookie", FORTUNE_COOKIE },
3472     { "pie", CREAM_PIE },
3473     { "marker", MAGIC_MARKER },
3474     { "hook", GRAPPLING_HOOK },
3475     { "grappling iron", GRAPPLING_HOOK },
3476     { "grapnel", GRAPPLING_HOOK },
3477     { "grapple", GRAPPLING_HOOK },
3478     { "protection from shape shifters", RIN_PROTECTION_FROM_SHAPE_CHAN },
3479     /* if we ever add other sizes, move this to o_ranges[] with "bag" */
3480     { "box", LARGE_BOX },
3481     /* normally we wouldn't have to worry about unnecessary <space>, but
3482        " stone" will get stripped off, preventing a wishymatch; that actually
3483        lets "flint stone" be a match, so we also accept bogus "flintstone" */
3484     { "luck stone", LUCKSTONE },
3485     { "load stone", LOADSTONE },
3486     { "touch stone", TOUCHSTONE },
3487     { "flintstone", FLINT },
3488     { (const char *) 0, 0 },
3489 };
3490
3491 STATIC_OVL short
3492 rnd_otyp_by_wpnskill(skill)
3493 schar skill;
3494 {
3495     int i, n = 0;
3496     short otyp = STRANGE_OBJECT;
3497
3498     for (i = bases[WEAPON_CLASS];
3499          i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3500         if (objects[i].oc_skill == skill) {
3501             n++;
3502             otyp = i;
3503         }
3504     if (n > 0) {
3505         n = rn2(n);
3506         for (i = bases[WEAPON_CLASS];
3507              i < NUM_OBJECTS && objects[i].oc_class == WEAPON_CLASS; i++)
3508             if (objects[i].oc_skill == skill)
3509                 if (--n < 0)
3510                     return i;
3511     }
3512     return otyp;
3513 }
3514 #endif
3515
3516 STATIC_OVL short
3517 rnd_otyp_by_namedesc(name, oclass, xtra_prob)
3518 const char *name;
3519 char oclass;
3520 int xtra_prob; /* to force 0% random generation items to also be considered */
3521 {
3522     int i, n = 0;
3523     short validobjs[NUM_OBJECTS];
3524     register const char *zn;
3525     int prob, maxprob = 0;
3526
3527     if (!name || !*name)
3528         return STRANGE_OBJECT;
3529
3530     memset((genericptr_t) validobjs, 0, sizeof validobjs);
3531
3532     /* FIXME:
3533      * When this spans classes (the !oclass case), the item
3534      * probabilities are not very useful because they don't take
3535      * the class generation probability into account.  [If 10%
3536      * of spellbooks were blank and 1% of scrolls were blank,
3537      * "blank" would have 10/11 chance to yield a book even though
3538      * scrolls are supposed to be much more common than books.]
3539      */
3540     for (i = oclass ? bases[(int) oclass] : STRANGE_OBJECT + 1;
3541          i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass);
3542          ++i) {
3543         /* don't match extra descriptions (w/o real name) */
3544         if ((zn = OBJ_NAME(objects[i])) == 0)
3545             continue;
3546 #if 1 /*JP*/
3547         /*
3548          * \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É
3549          * \82È\82ç\82È\82¢\82æ\82¤\82É\82·\82é\81B
3550          * \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
3551          */
3552         if (i == FAKE_AMULET_OF_YENDOR)
3553             continue;
3554 #endif
3555         if (wishymatch(name, zn, TRUE)
3556             || ((zn = OBJ_DESCR(objects[i])) != 0
3557                 && wishymatch(name, zn, FALSE))
3558             || ((zn = objects[i].oc_uname) != 0
3559                 && wishymatch(name, zn, FALSE))) {
3560             validobjs[n++] = (short) i;
3561             maxprob += (objects[i].oc_prob + xtra_prob);
3562         }
3563     }
3564
3565     if (n > 0 && maxprob) {
3566         prob = rn2(maxprob);
3567         for (i = 0; i < n - 1; i++)
3568             if ((prob -= (objects[validobjs[i]].oc_prob + xtra_prob)) < 0)
3569                 break;
3570         return validobjs[i];
3571     }
3572     return STRANGE_OBJECT;
3573 }
3574
3575 int
3576 shiny_obj(oclass)
3577 char oclass;
3578 {
3579     return (int) rnd_otyp_by_namedesc("shiny", oclass, 0);
3580 }
3581
3582 /*
3583  * Return something wished for.  Specifying a null pointer for
3584  * the user request string results in a random object.  Otherwise,
3585  * if asking explicitly for "nothing" (or "nil") return no_wish;
3586  * if not an object return &zeroobj; if an error (no matching object),
3587  * return null.
3588  */
3589
3590 struct obj *
3591 readobjnam(bp, no_wish)
3592 register char *bp;
3593 struct obj *no_wish;
3594 {
3595     register char *p;
3596     register int i;
3597     register struct obj *otmp;
3598     int cnt, spe, spesgn, typ, very, rechrg;
3599     int blessed, uncursed, iscursed, ispoisoned, isgreased;
3600     int eroded, eroded2, erodeproof, locked, unlocked, broken;
3601     int halfeaten, mntmp, contents;
3602     int islit, unlabeled, ishistoric, isdiluted, trapped;
3603 #if 0 /*JP*/
3604     int tmp, tinv, tvariety;
3605 #else
3606     int tvariety;
3607 #endif
3608     int wetness, gsize = 0;
3609     struct fruit *f;
3610     int ftype = context.current_fruit;
3611 #if 0 /*JP*/
3612     char fruitbuf[BUFSZ], globbuf[BUFSZ];
3613 #else
3614     char fruitbuf[BUFSZ];
3615 #endif
3616     /* Fruits may not mess up the ability to wish for real objects (since
3617      * you can leave a fruit in a bones file and it will be added to
3618      * another person's game), so they must be checked for last, after
3619      * stripping all the possible prefixes and seeing if there's a real
3620      * name in there.  So we have to save the full original name.  However,
3621      * it's still possible to do things like "uncursed burnt Alaska",
3622      * or worse yet, "2 burned 5 course meals", so we need to loop to
3623      * strip off the prefixes again, this time stripping only the ones
3624      * possible on food.
3625      * We could get even more detailed so as to allow food names with
3626      * prefixes that _are_ possible on food, so you could wish for
3627      * "2 3 alarm chilis".  Currently this isn't allowed; options.c
3628      * automatically sticks 'candied' in front of such names.
3629      */
3630     char oclass;
3631     char *un, *dn, *actualn, *origbp = bp;
3632     const char *name = 0;
3633
3634     cnt = spe = spesgn = typ = 0;
3635     very = rechrg = blessed = uncursed = iscursed = ispoisoned =
3636         isgreased = eroded = eroded2 = erodeproof = halfeaten =
3637         islit = unlabeled = ishistoric = isdiluted = trapped =
3638         locked = unlocked = broken = 0;
3639     tvariety = RANDOM_TIN;
3640     mntmp = NON_PM;
3641 #define UNDEFINED 0
3642 #define EMPTY 1
3643 #define SPINACH 2
3644     contents = UNDEFINED;
3645     oclass = 0;
3646     actualn = dn = un = 0;
3647     wetness = 0;
3648
3649     if (!bp)
3650         goto any;
3651     /* first, remove extra whitespace they may have typed */
3652     (void) mungspaces(bp);
3653     /* allow wishing for "nothing" to preserve wishless conduct...
3654        [now requires "wand of nothing" if that's what was really wanted] */
3655 #if 0 /*JP*/
3656     if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil")
3657         || !strcmpi(bp, "none"))
3658 #else
3659     if (!strcmpi(bp, "\82È\82µ") || !strcmpi(bp, "\96³\82µ"))
3660 #endif
3661         return no_wish;
3662     /* save the [nearly] unmodified choice string */
3663     Strcpy(fruitbuf, bp);
3664
3665     for (;;) {
3666         register int l;
3667
3668         if (!bp || !*bp)
3669             goto any;
3670         if (!strncmpi(bp, "an ", l = 3) || !strncmpi(bp, "a ", l = 2)) {
3671             cnt = 1;
3672         } else if (!strncmpi(bp, "the ", l = 4)) {
3673             ; /* just increment `bp' by `l' below */
3674         } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
3675             cnt = atoi(bp);
3676             while (digit(*bp))
3677                 bp++;
3678             while (*bp == ' ')
3679                 bp++;
3680             l = 0;
3681 #if 1 /*JP*//* \8cã\82É\90\94\8e\8c\82ª\82 \82é\82Æ\82«\82Í\8dí\8f\9c */
3682             if(!strncmp(bp, "\8dû\82Ì", l = 4) ||
3683                !strncmp(bp, "\96{\82Ì", l = 4) ||
3684                !strncmp(bp, "\92\85\82Ì", l = 4) ||
3685                !strncmp(bp, "\8cÂ\82Ì", l = 4) ||
3686                !strncmp(bp, "\96\87\82Ì", l = 4) ||
3687                !strncmp(bp, "\82Â\82Ì", l = 4) ||
3688                !strncmp(bp, "\82Ì", l = 2))
3689               ;
3690             else
3691               l = 0;
3692 #endif
3693         } else if (*bp == '+' || *bp == '-') {
3694             spesgn = (*bp++ == '+') ? 1 : -1;
3695             spe = atoi(bp);
3696             while (digit(*bp))
3697                 bp++;
3698             while (*bp == ' ')
3699                 bp++;
3700             l = 0;
3701 #if 0 /*JP:T*/
3702         } else if (!strncmpi(bp, "blessed ", l = 8)
3703                    || !strncmpi(bp, "holy ", l = 5)) {
3704 #else
3705         } else if (!strncmpi(bp, "\8fj\95\9f\82³\82ê\82½", l = 10)) {
3706 #endif
3707             blessed = 1;
3708 #if 0 /*JP:T*/
3709         } else if (!strncmpi(bp, "moist ", l = 6)
3710                    || !strncmpi(bp, "wet ", l = 4)) {
3711 #else
3712         } else if (!strncmpi(bp, "\8e¼\82Á\82½", l = 6)
3713                    || !strncmpi(bp, "\94G\82ê\82½", l = 6)) {
3714 #endif
3715 #if 0 /*JP:T*/
3716             if (!strncmpi(bp, "wet ", 4))
3717 #else
3718             if (!strncmpi(bp, "\94G\82ê\82½", 6))
3719 #endif
3720                 wetness = rn2(3) + 3;
3721             else
3722                 wetness = rnd(2);
3723 #if 0 /*JP:T*/
3724         } else if (!strncmpi(bp, "cursed ", l = 7)
3725                    || !strncmpi(bp, "unholy ", l = 7)) {
3726 #else
3727         } else if (!strncmpi(bp, "\8eô\82í\82ê\82½", l = 8)) {
3728 #endif
3729             iscursed = 1;
3730 #if 0 /*JP:T*/
3731         } else if (!strncmpi(bp, "uncursed ", l = 9)) {
3732 #else
3733         } else if (!strncmpi(bp, "\8eô\82í\82ê\82Ä\82¢\82È\82¢", l = 14)) {
3734 #endif
3735             uncursed = 1;
3736 #if 0 /*JP:T*/
3737         } else if (!strncmpi(bp, "rustproof ", l = 10)
3738                    || !strncmpi(bp, "erodeproof ", l = 11)
3739                    || !strncmpi(bp, "corrodeproof ", l = 13)
3740                    || !strncmpi(bp, "fixed ", l = 6)
3741                    || !strncmpi(bp, "fireproof ", l = 10)
3742                    || !strncmpi(bp, "rotproof ", l = 9)) {
3743 #else
3744         } else if (!strncmpi(bp, "\8eK\82Ñ\82È\82¢", l = 8)
3745                    || !strncmpi(bp, "\95\85\90H\82µ\82È\82¢", l = 10)
3746                    || !strncmpi(bp, "\88À\92è\82µ\82½", l = 8)
3747                    || !strncmpi(bp, "\94R\82¦\82È\82¢", l = 8)) {
3748 #endif
3749             erodeproof = 1;
3750 #if 0 /*JP:T*/
3751         } else if (!strncmpi(bp, "lit ", l = 4)
3752                    || !strncmpi(bp, "burning ", l = 8)) {
3753 #else
3754         } else if (!strncmpi(bp, "\8cõ\82Á\82Ä\82¢\82é", l = 10)
3755                    || !strncmpi(bp, "\94R\82¦\82Ä\82¢\82é", l = 10)) {
3756 #endif
3757             islit = 1;
3758 #if 0 /*JP:T*/
3759         } else if (!strncmpi(bp, "unlit ", l = 6)
3760                    || !strncmpi(bp, "extinguished ", l = 13)) {
3761 #else
3762         } else if (!strncmpi(bp, "\8fÁ\82¦\82Ä\82¢\82é", l = 10)) {
3763 #endif
3764             islit = 0;
3765             /* "unlabeled" and "blank" are synonymous */
3766 #if 0 /*JP:T*/
3767         } else if (!strncmpi(bp, "unlabeled ", l = 10)
3768                    || !strncmpi(bp, "unlabelled ", l = 11)
3769                    || !strncmpi(bp, "blank ", l = 6)) {
3770 #else
3771         } else if (!strncmpi(bp, "\83\89\83x\83\8b\82Ì\82È\82¢", l = 12)
3772                    || !strncmpi(bp, "\90^\82Á\94\92\82È", l = 8)) {
3773 #endif
3774             unlabeled = 1;
3775 #if 0 /*JP:T*/
3776         } else if (!strncmpi(bp, "poisoned ", l = 9)) {
3777 #else
3778         } else if (!strncmpi(bp, "\93Å\82Ì\93h\82ç\82ê\82½", l = 12)) {
3779 #endif
3780             ispoisoned = 1;
3781             /* "trapped" recognized but not honored outside wizard mode */
3782         } else if (!strncmpi(bp, "trapped ", l = 8)) {
3783             trapped = 0; /* undo any previous "untrapped" */
3784             if (wizard)
3785                 trapped = 1;
3786         } else if (!strncmpi(bp, "untrapped ", l = 10)) {
3787             trapped = 2; /* not trapped */
3788         /* locked, unlocked, broken: box/chest lock states */
3789 #if 0 /*JP:T*/
3790         } else if (!strncmpi(bp, "locked ", l = 7)) {
3791 #else
3792         } else if (!strncmpi(bp, "\8c®\82Ì\8a|\82©\82Á\82½", l = 12)) {
3793 #endif
3794             locked = 1, unlocked = broken = 0;
3795 #if 0 /*JP:T*/
3796         } else if (!strncmpi(bp, "unlocked ", l = 9)) {
3797 #else
3798         } else if (!strncmpi(bp, "\8c®\82Ì\8a|\82©\82Á\82Ä\82¢\82È\82¢", l = 18)) {
3799 #endif
3800             unlocked = 1, locked = broken = 0;
3801 #if 0 /*JP:T*/
3802         } else if (!strncmpi(bp, "broken ", l = 7)) {
3803 #else
3804         } else if (!strncmpi(bp, "\8c®\82Ì\89ó\82ê\82½", l = 10)) {
3805 #endif
3806             broken = 1, locked = unlocked = 0;
3807 #if 0 /*JP:T*/
3808         } else if (!strncmpi(bp, "greased ", l = 8)) {
3809 #else
3810         } else if (!strncmpi(bp, "\96û\82Ì\93h\82ç\82ê\82½", l = 12)
3811                    || !strncmpi(bp, "\8e\89\82Ì\93h\82ç\82ê\82½", l = 12)) {
3812 #endif
3813             isgreased = 1;
3814 #if 0 /*JP:T*/
3815         } else if (!strncmpi(bp, "very ", l = 5)) {
3816 #else
3817         } else if (!strncmpi(bp, "\82Æ\82Ä\82à", l = 6)) {
3818 #endif
3819             /* very rusted very heavy iron ball */
3820             very = 1;
3821 #if 0 /*JP:T*/
3822         } else if (!strncmpi(bp, "thoroughly ", l = 11)) {
3823 #else
3824         } else if (!strncmpi(bp, "\82©\82È\82è", l = 6)) {
3825 #endif
3826             very = 2;
3827 #if 0 /*JP:T*/
3828         } else if (!strncmpi(bp, "rusty ", l = 6)
3829                    || !strncmpi(bp, "rusted ", l = 7)
3830                    || !strncmpi(bp, "burnt ", l = 6)
3831                    || !strncmpi(bp, "burned ", l = 7)) {
3832 #else
3833         } else if (!strncmpi(bp, "\8eK\82Ñ\82½", l = 6)
3834                    || !strncmpi(bp, "\94R\82¦\82½", l = 6)) {
3835 #endif
3836             eroded = 1 + very;
3837             very = 0;
3838 #if 0 /*JP:T*/
3839         } else if (!strncmpi(bp, "corroded ", l = 9)
3840                    || !strncmpi(bp, "rotted ", l = 7)) {
3841 #else
3842         } else if (!strncmpi(bp, "\95\85\90H\82µ\82½", l = 8)
3843                    || !strncmpi(bp, "\95\85\82Á\82½", l = 6)) {
3844 #endif
3845             eroded2 = 1 + very;
3846             very = 0;
3847 #if 0 /*JP:T*/
3848         } else if (!strncmpi(bp, "partly eaten ", l = 13)
3849                    || !strncmpi(bp, "partially eaten ", l = 16)) {
3850 #else
3851         } else if (!strncmpi(bp, "\90H\82×\82©\82¯\82Ì", l = 10)) {
3852 #endif
3853             halfeaten = 1;
3854 #if 0 /*JP:T*/
3855         } else if (!strncmpi(bp, "historic ", l = 9)) {
3856 #else
3857         } else if (!strncmpi(bp, "\97ð\8ej\93I\82È", l = 8)) {
3858 #endif
3859             ishistoric = 1;
3860 #if 0 /*JP:T*/
3861         } else if (!strncmpi(bp, "diluted ", l = 8)) {
3862 #else
3863         } else if (!strncmpi(bp, "\94\96\82Ü\82Á\82½", l = 8)) {
3864 #endif
3865             isdiluted = 1;
3866 #if 0 /*JP:T*/
3867         } else if (!strncmpi(bp, "empty ", l = 6)) {
3868 #else
3869         } else if (!strncmpi(bp, "\8bó\82Á\82Û\82Ì", l = 8)) {
3870 #endif
3871             contents = EMPTY;
3872 #if 0 /*JP:T*/
3873         } else if (!strncmpi(bp, "small ", l = 6)) { /* glob sizes */
3874 #else
3875         } else if (!strncmpi(bp, "\8f¬\82³\82¢", l = 6)) { /* glob sizes */
3876 #endif
3877             /* "small" might be part of monster name (mimic, if wishing
3878                for its corpse) rather than prefix for glob size; when
3879                used for globs, it might be either "small glob of <foo>" or
3880                "small <foo> glob" and user might add 's' even though plural
3881                doesn't accomplish anything because globs don't stack */
3882             if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
3883                 break;
3884             gsize = 1;
3885 #if 0 /*JP:T*/
3886         } else if (!strncmpi(bp, "medium ", l = 7)) {
3887 #else
3888         } else if (!strncmpi(bp, "\92\86\82­\82ç\82¢\82Ì", l = 10)) {
3889 #endif
3890             /* xname() doesn't display "medium" but without this
3891                there'd be no way to ask for the intermediate size
3892                ("glob" without size prefix yields smallest one) */
3893             gsize = 2;
3894 #if 0 /*JP:T*/
3895         } else if (!strncmpi(bp, "large ", l = 6)) {
3896 #else
3897         } else if (!strncmpi(bp, "\91å\82«\82¢", l = 6)) {
3898 #endif
3899             /* "large" might be part of monster name (dog, cat, koboold,
3900                mimic) or object name (box, round shield) rather than
3901                prefix for glob size */
3902             if (strncmpi(bp + l, "glob", 4) && !strstri(bp + l, " glob"))
3903                 break;
3904             /* "very large " had "very " peeled off on previous iteration */
3905             gsize = (very != 1) ? 3 : 4;
3906         } else
3907             break;
3908         bp += l;
3909     }
3910     if (!cnt)
3911         cnt = 1; /* will be changed to 2 if makesingular() changes string */
3912     if (strlen(bp) > 1 && (p = rindex(bp, '(')) != 0) {
3913         boolean keeptrailingchars = TRUE;
3914
3915         p[(p > bp && p[-1] == ' ') ? -1 : 0] = '\0'; /*terminate bp */
3916         ++p; /* advance past '(' */
3917         if (!strncmpi(p, "lit)", 4)) {
3918             islit = 1;
3919             p += 4 - 1; /* point at ')' */
3920         } else {
3921             spe = atoi(p);
3922             while (digit(*p))
3923                 p++;
3924             if (*p == ':') {
3925                 p++;
3926                 rechrg = spe;
3927                 spe = atoi(p);
3928                 while (digit(*p))
3929                     p++;
3930             }
3931             if (*p != ')') {
3932                 spe = rechrg = 0;
3933                 /* mis-matched parentheses; rest of string will be ignored
3934                  * [probably we should restore everything back to '('
3935                  * instead since it might be part of "named ..."]
3936                  */
3937                 keeptrailingchars = FALSE;
3938             } else {
3939                 spesgn = 1;
3940             }
3941         }
3942         if (keeptrailingchars) {
3943             char *pp = eos(bp);
3944
3945             /* 'pp' points at 'pb's terminating '\0',
3946                'p' points at ')' and will be incremented past it */
3947             do {
3948                 *pp++ = *++p;
3949             } while (*p);
3950         }
3951     }
3952     /*
3953      * otmp->spe is type schar, so we don't want spe to be any bigger or
3954      * smaller.  Also, spe should always be positive --some cheaters may
3955      * try to confuse atoi().
3956      */
3957     if (spe < 0) {
3958         spesgn = -1; /* cheaters get what they deserve */
3959         spe = abs(spe);
3960     }
3961     if (spe > SCHAR_LIM)
3962         spe = SCHAR_LIM;
3963     if (rechrg < 0 || rechrg > 7)
3964         rechrg = 7; /* recharge_limit */
3965
3966     /* now we have the actual name, as delivered by xname, say
3967      *  green potions called whisky
3968      *  scrolls labeled "QWERTY"
3969      *  egg
3970      *  fortune cookies
3971      *  very heavy iron ball named hoei
3972      *  wand of wishing
3973      *  elven cloak
3974      */
3975     if ((p = strstri(bp, " named ")) != 0) {
3976         *p = 0;
3977         name = p + 7;
3978     }
3979     if ((p = strstri(bp, " called ")) != 0) {
3980         *p = 0;
3981         un = p + 8;
3982 #if 0 /*JP*//*\83^\83C\83v\95Ê\82Í\82Æ\82è\82 \82¦\82¸\82µ\82È\82¢*/
3983         /* "helmet called telepathy" is not "helmet" (a specific type)
3984          * "shield called reflection" is not "shield" (a general type)
3985          */
3986         for (i = 0; i < SIZE(o_ranges); i++)
3987             if (!strcmpi(bp, o_ranges[i].name)) {
3988                 oclass = o_ranges[i].oclass;
3989                 goto srch;
3990             }
3991 #endif
3992     }
3993     if ((p = strstri(bp, " labeled ")) != 0) {
3994         *p = 0;
3995         dn = p + 9;
3996     } else if ((p = strstri(bp, " labelled ")) != 0) {
3997         *p = 0;
3998         dn = p + 10;
3999     }
4000     if ((p = strstri(bp, " of spinach")) != 0) {
4001         *p = 0;
4002         contents = SPINACH;
4003     }
4004
4005 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\8f\88\97\9d\82µ\82È\82¢*/
4006     /*
4007      * Skip over "pair of ", "pairs of", "set of" and "sets of".
4008      *
4009      * Accept "3 pair of boots" as well as "3 pairs of boots".  It is
4010      * valid English either way.  See makeplural() for more on pair/pairs.
4011      *
4012      * We should only double count if the object in question is not
4013      * referred to as a "pair of".  E.g. We should double if the player
4014      * types "pair of spears", but not if the player types "pair of
4015      * lenses".  Luckily (?) all objects that are referred to as pairs
4016      * -- boots, gloves, and lenses -- are also not mergable, so cnt is
4017      * ignored anyway.
4018      */
4019     if (!strncmpi(bp, "pair of ", 8)) {
4020         bp += 8;
4021         cnt *= 2;
4022     } else if (!strncmpi(bp, "pairs of ", 9)) {
4023         bp += 9;
4024         if (cnt > 1)
4025             cnt *= 2;
4026     } else if (!strncmpi(bp, "set of ", 7)) {
4027         bp += 7;
4028     } else if (!strncmpi(bp, "sets of ", 8)) {
4029         bp += 8;
4030     }
4031 #endif
4032
4033 #if 0 /*JP*/
4034     /* intercept pudding globs here; they're a valid wish target,
4035      * but we need them to not get treated like a corpse.
4036      *
4037      * also don't let player wish for multiple globs.
4038      */
4039     i = (int) strlen(bp);
4040     p = (char *) 0;
4041     /* check for "glob", "<foo> glob", and "glob of <foo>" */
4042     if (!strcmpi(bp, "glob") || !BSTRCMPI(bp, bp + i - 5, " glob")
4043         || !strcmpi(bp, "globs") || !BSTRCMPI(bp, bp + i - 6, " globs")
4044         || (p = strstri(bp, "glob of ")) != 0
4045         || (p = strstri(bp, "globs of ")) != 0) {
4046         mntmp = name_to_mon(!p ? bp : (strstri(p, " of ") + 4));
4047         /* if we didn't recognize monster type, pick a valid one at random */
4048         if (mntmp == NON_PM)
4049             mntmp = rn1(PM_BLACK_PUDDING - PM_GRAY_OOZE, PM_GRAY_OOZE);
4050         /* construct canonical spelling in case name_to_mon() recognized a
4051            variant (grey ooze) or player used inverted syntax (<foo> glob);
4052            if player has given a valid monster type but not valid glob type,
4053            object name lookup won't find it and wish attempt will fail */
4054         Sprintf(globbuf, "glob of %s", mons[mntmp].mname);
4055         bp = globbuf;
4056         mntmp = NON_PM; /* not useful for "glob of <foo>" object lookup */
4057         cnt = 0; /* globs don't stack */
4058         oclass = FOOD_CLASS;
4059         actualn = bp, dn = 0;
4060         goto srch;
4061     } else {
4062         /*
4063          * Find corpse type using "of" (figurine of an orc, tin of orc meat)
4064          * Don't check if it's a wand or spellbook.
4065          * (avoid "wand/finger of death" confusion).
4066          */
4067         if (!strstri(bp, "wand ") && !strstri(bp, "spellbook ")
4068             && !strstri(bp, "finger ")) {
4069             if ((p = strstri(bp, "tin of ")) != 0) {
4070                 if (!strcmpi(p + 7, "spinach")) {
4071                     contents = SPINACH;
4072                     mntmp = NON_PM;
4073                 } else {
4074                     tmp = tin_variety_txt(p + 7, &tinv);
4075                     tvariety = tinv;
4076                     mntmp = name_to_mon(p + 7 + tmp);
4077                 }
4078                 typ = TIN;
4079                 goto typfnd;
4080             } else if ((p = strstri(bp, " of ")) != 0
4081                        && (mntmp = name_to_mon(p + 4)) >= LOW_PM)
4082                 *p = 0;
4083         }
4084     }
4085     /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
4086     if (strncmpi(bp, "samurai sword", 13)  /* not the "samurai" monster! */
4087         && strncmpi(bp, "wizard lock", 11) /* not the "wizard" monster! */
4088         && strncmpi(bp, "ninja-to", 8)     /* not the "ninja" rank */
4089         && strncmpi(bp, "master key", 10)  /* not the "master" rank */
4090         && strncmpi(bp, "magenta", 7)) {   /* not the "mage" rank */
4091         if (mntmp < LOW_PM && strlen(bp) > 2
4092             && (mntmp = name_to_mon(bp)) >= LOW_PM) {
4093             int mntmptoo, mntmplen; /* double check for rank title */
4094             char *obp = bp;
4095
4096             mntmptoo = title_to_mon(bp, (int *) 0, &mntmplen);
4097             bp += (mntmp != mntmptoo) ? (int) strlen(mons[mntmp].mname)
4098                                       : mntmplen;
4099             if (*bp == ' ') {
4100                 bp++;
4101             } else if (!strncmpi(bp, "s ", 2)) {
4102                 bp += 2;
4103             } else if (!strncmpi(bp, "es ", 3)) {
4104                 bp += 3;
4105             } else if (!*bp && !actualn && !dn && !un && !oclass) {
4106                 /* no referent; they don't really mean a monster type */
4107                 bp = obp;
4108                 mntmp = NON_PM;
4109             }
4110         }
4111     }
4112 #else
4113     {
4114         /*JP \81u(\89ö\95¨\96¼)\82Ì\89ò\81v\82Í\8cÂ\81X\82ÉID\82ª\82 \82é\82Ì\82Å\95Ê\88µ\82¢ */
4115         int l = strlen(bp);
4116         if (l > 4 && strncmp(bp + l - 4, "\82Ì\89ò", 4) == 0) {
4117             if ((mntmp = name_to_mon(bp)) >= PM_GRAY_OOZE
4118                 && mntmp <= PM_BLACK_PUDDING) {
4119                 mntmp = NON_PM; /* lie to ourselves */
4120                 cnt = 0;        /* force only one */
4121             }
4122         } else {
4123             /*JP:\81u(\89ö\95¨\96¼)\82Ì(\83A\83C\83e\83\80)\81v\91Î\89\9e */
4124             if ((mntmp = name_to_mon(bp)) >= LOW_PM) {
4125                 const char *mp = mons[mntmp].mname;
4126                 bp = strstri(bp, mp) + strlen(mp) + 2;
4127             }
4128         }
4129     }
4130 #endif
4131
4132 #if 0 /*JP*//*\92P\90\94\89»\82Í\82µ\82È\82¢*/
4133     /* first change to singular if necessary */
4134     if (*bp) {
4135         char *sng = makesingular(bp);
4136
4137         if (strcmp(bp, sng)) {
4138             if (cnt == 1)
4139                 cnt = 2;
4140             Strcpy(bp, sng);
4141         }
4142     }
4143 #endif
4144
4145 #if 0 /*JP*//*\83X\83y\83\8b\97h\82ê\8f\88\97\9d\82Í\82µ\82È\82¢*/
4146     /* Alternate spellings (pick-ax, silver sabre, &c) */
4147     {
4148         const struct alt_spellings *as = spellings;
4149
4150         while (as->sp) {
4151             if (fuzzymatch(bp, as->sp, " -", TRUE)) {
4152                 typ = as->ob;
4153                 goto typfnd;
4154             }
4155             as++;
4156         }
4157         /* can't use spellings list for this one due to shuffling */
4158         if (!strncmpi(bp, "grey spell", 10))
4159             *(bp + 2) = 'a';
4160
4161         if ((p = strstri(bp, "armour")) != 0) {
4162             /* skip past "armo", then copy remainder beyond "u" */
4163             p += 4;
4164             while ((*p = *(p + 1)) != '\0')
4165                 ++p; /* self terminating */
4166         }
4167     }
4168 #endif
4169
4170 #if 0 /*JP*/
4171     /* dragon scales - assumes order of dragons */
4172     if (!strcmpi(bp, "scales") && mntmp >= PM_GRAY_DRAGON
4173         && mntmp <= PM_YELLOW_DRAGON) {
4174         typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
4175         mntmp = NON_PM; /* no monster */
4176         goto typfnd;
4177     }
4178 #else
4179     /*JP: \81u\97Ø\8aZ\81v\82ð\90æ\82É\8f\88\97\9d\82µ\82Ä\82¨\82­ */
4180     if (!strcmpi(bp, "\97Ø\8aZ") && mntmp >= PM_GRAY_DRAGON
4181         && mntmp <= PM_YELLOW_DRAGON) {
4182         typ = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4183         mntmp = NON_PM; /* no monster */
4184         goto typfnd;
4185     }
4186
4187     if (!strcmpi(bp, "\97Ø") && mntmp >= PM_GRAY_DRAGON
4188         && mntmp <= PM_YELLOW_DRAGON) {
4189         typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
4190         mntmp = NON_PM; /* no monster */
4191         goto typfnd;
4192     }
4193 #endif
4194
4195     p = eos(bp);
4196 #if 0 /*JP*/
4197     if (!BSTRCMPI(bp, p - 10, "holy water")) {
4198         typ = POT_WATER;
4199         if ((p - bp) >= 12 && *(p - 12) == 'u')
4200             iscursed = 1; /* unholy water */
4201         else
4202             blessed = 1;
4203         goto typfnd;
4204     }
4205 #else /*JP:\90¹\90\85\82Æ\95s\8fò\82È\90\85\82ð\95Ê\82É\94»\92è*/
4206     if (!BSTRCMPI(bp, p - 4, "\90¹\90\85")) {
4207         typ = POT_WATER;
4208         blessed = 1;
4209         goto typfnd;
4210     }
4211     if (!BSTRCMPI(bp, p - 8, "\95s\8fò\82È\90\85")) {
4212         typ = POT_WATER;
4213         iscursed = 1;
4214         goto typfnd;
4215     }
4216 #endif
4217 #if 0 /*JP*/
4218     if (unlabeled && !BSTRCMPI(bp, p - 6, "scroll")) {
4219 #else
4220     if (unlabeled && !BSTRCMPI(bp, p - 4, "\8aª\95¨")) {
4221 #endif
4222         typ = SCR_BLANK_PAPER;
4223         goto typfnd;
4224     }
4225 #if 0 /*JP*/
4226     if (unlabeled && !BSTRCMPI(bp, p - 9, "spellbook")) {
4227 #else
4228     if (unlabeled && !BSTRCMPI(bp, p - 6, "\96\82\96@\8f\91")) {
4229 #endif
4230         typ = SPE_BLANK_PAPER;
4231         goto typfnd;
4232     }
4233     /* specific food rather than color of gem/potion/spellbook[/scales] */
4234     if (!BSTRCMPI(bp, p - 6, "orange") && mntmp == NON_PM) {
4235         typ = ORANGE;
4236         goto typfnd;
4237     }
4238     /*
4239      * NOTE: Gold pieces are handled as objects nowadays, and therefore
4240      * this section should probably be reconsidered as well as the entire
4241      * gold/money concept.  Maybe we want to add other monetary units as
4242      * well in the future. (TH)
4243      */
4244 #if 0 /*JP*/
4245     if (!BSTRCMPI(bp, p - 10, "gold piece")
4246         || !BSTRCMPI(bp, p - 7, "zorkmid")
4247         || !strcmpi(bp, "gold") || !strcmpi(bp, "money")
4248         || !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
4249 #else
4250     if (!BSTRCMPI(bp, p - 4, "\8bà\89Ý") || !BSTRCMPI(bp, p - 8, "\83S\81[\83\8b\83h")
4251         || *bp == GOLD_SYM) {
4252 #endif
4253         if (cnt > 5000 && !wizard)
4254             cnt = 5000;
4255         else if (cnt < 1)
4256             cnt = 1;
4257         otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
4258         otmp->quan = (long) cnt;
4259         otmp->owt = weight(otmp);
4260         context.botl = 1;
4261         return otmp;
4262     }
4263
4264     /* check for single character object class code ("/" for wand, &c) */
4265     if (strlen(bp) == 1 && (i = def_char_to_objclass(*bp)) < MAXOCLASSES
4266         && i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) {
4267         oclass = i;
4268         goto any;
4269     }
4270
4271 #if 0 /*JP*/
4272     /*JP
4273       \89p\8cê\82È\82ç XXXXX potion \82Í\95s\8am\92è\96¼\81Apotion of XXXXX \82Í\8am\92è\96¼\82Æ\82¢\82¤
4274       \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¢
4275       */
4276     /* Search for class names: XXXXX potion, scroll of XXXXX.  Avoid */
4277     /* false hits on, e.g., rings for "ring mail". */
4278     if (strncmpi(bp, "enchant ", 8)
4279         && strncmpi(bp, "destroy ", 8)
4280         && strncmpi(bp, "detect food", 11)
4281         && strncmpi(bp, "food detection", 14)
4282         && strncmpi(bp, "ring mail", 9)
4283         && strncmpi(bp, "studded leather armor", 21)
4284         && strncmpi(bp, "leather armor", 13)
4285         && strncmpi(bp, "tooled horn", 11)
4286         && strncmpi(bp, "food ration", 11)
4287         && strncmpi(bp, "meat ring", 9))
4288         for (i = 0; i < (int) (sizeof wrpsym); i++) {
4289             register int j = strlen(wrp[i]);
4290
4291             /* check for "<class> [ of ] something" */
4292             if (!strncmpi(bp, wrp[i], j)) {
4293                 oclass = wrpsym[i];
4294                 if (oclass != AMULET_CLASS) {
4295                     bp += j;
4296                     if (!strncmpi(bp, " of ", 4))
4297                         actualn = bp + 4;
4298                     /* else if(*bp) ?? */
4299                 } else
4300                     actualn = bp;
4301                 goto srch;
4302             }
4303             /* check for "something <class>" */
4304             if (!BSTRCMPI(bp, p - j, wrp[i])) {
4305                 oclass = wrpsym[i];
4306                 /* for "foo amulet", leave the class name so that
4307                    wishymatch() can do "of inversion" to try matching
4308                    "amulet of foo"; other classes don't include their
4309                    class name in their full object names (where
4310                    "potion of healing" is just "healing", for instance) */
4311                 if (oclass != AMULET_CLASS) {
4312                     p -= j;
4313                     *p = '\0';
4314                     if (p > bp && p[-1] == ' ')
4315                         p[-1] = '\0';
4316                 } else {
4317                     /* amulet without "of"; convoluted wording but better a
4318                        special case that's handled than one that's missing */
4319                     if (!strncmpi(bp, "versus poison ", 14)) {
4320                         typ = AMULET_VERSUS_POISON;
4321                         goto typfnd;
4322                     }
4323                 }
4324                 actualn = dn = bp;
4325                 goto srch;
4326             }
4327         }
4328 #endif
4329
4330     /* Wishing in wizard mode can create traps and furniture.
4331      * Part I:  distinguish between trap and object for the two
4332      * types of traps which have corresponding objects:  bear trap
4333      * and land mine.  "beartrap" (object) and "bear trap" (trap)
4334      * have a difference in spelling which we used to exploit by
4335      * adding a special case in wishymatch(), but "land mine" is
4336      * spelled the same either way so needs different handing.
4337      * Since we need something else for land mine, we've dropped
4338      * the bear trap hack so that both are handled exactly the
4339      * same.  To get an armed trap instead of a disarmed object,
4340      * the player can prefix either the object name or the trap
4341      * name with "trapped " (which ordinarily applies to chests
4342      * and tins), or append something--anything at all except for
4343      * " object", but " trap" is suggested--to either the trap
4344      * name or the object name.
4345      */
4346     if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) {
4347         boolean beartrap = (lowc(*bp) == 'b');
4348         char *zp = bp + 4; /* skip "bear"/"land" */
4349
4350         if (*zp == ' ')
4351             ++zp; /* embedded space is optional */
4352         if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) {
4353             zp += 4;
4354             if (trapped == 2 || !strcmpi(zp, " object")) {
4355                 /* "untrapped <foo>" or "<foo> object" */
4356                 typ = beartrap ? BEARTRAP : LAND_MINE;
4357                 goto typfnd;
4358             } else if (trapped == 1 || *zp != '\0') {
4359                 /* "trapped <foo>" or "<foo> trap" (actually "<foo>*") */
4360                 int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE);
4361
4362                 /* use canonical trap spelling, skip object matching */
4363                 Strcpy(bp, defsyms[idx].explanation);
4364                 goto wiztrap;
4365             }
4366             /* [no prefix or suffix; we're going to end up matching
4367                the object name and getting a disarmed trap object] */
4368         }
4369     }
4370
4371 #if 0 /*JP*//* mail/armor\8aÖ\98A\82Å\82Ì\82Ý\8eg\82¤\83\89\83x\83\8b */
4372  retry:
4373 #endif
4374 #if 0 /*JP*//* \83^\83C\83v\95Ê\82Í\82Æ\82è\82 \82¦\82¸\82µ\82È\82¢ */
4375     /* "grey stone" check must be before general "stone" */
4376     for (i = 0; i < SIZE(o_ranges); i++)
4377         if (!strcmpi(bp, o_ranges[i].name)) {
4378             typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
4379             goto typfnd;
4380         }
4381 #endif
4382
4383 #if 0 /*JP*//* \90Î\82Ì\93Á\95Ê\8f\88\97\9d\82Í\95s\97v */
4384     if (!BSTRCMPI(bp, p - 6, " stone") || !BSTRCMPI(bp, p - 4, " gem")) {
4385         p[!strcmpi(p - 4, " gem") ? -4 : -6] = '\0';
4386         oclass = GEM_CLASS;
4387         dn = actualn = bp;
4388         goto srch;
4389     } else if (!strcmpi(bp, "looking glass")) {
4390         ; /* avoid false hit on "* glass" */
4391     } else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
4392         register char *g = bp;
4393
4394         /* treat "broken glass" as a non-existent item; since "broken" is
4395            also a chest/box prefix it might have been stripped off above */
4396         if (broken || strstri(g, "broken"))
4397             return (struct obj *) 0;
4398         if (!strncmpi(g, "worthless ", 10))
4399             g += 10;
4400         if (!strncmpi(g, "piece of ", 9))
4401             g += 9;
4402         if (!strncmpi(g, "colored ", 8))
4403             g += 8;
4404         else if (!strncmpi(g, "coloured ", 9))
4405             g += 9;
4406         if (!strcmpi(g, "glass")) { /* choose random color */
4407             /* 9 different kinds */
4408             typ = LAST_GEM + rnd(9);
4409             if (objects[typ].oc_class == GEM_CLASS)
4410                 goto typfnd;
4411             else
4412                 typ = 0; /* somebody changed objects[]? punt */
4413         } else { /* try to construct canonical form */
4414             char tbuf[BUFSZ];
4415
4416             Strcpy(tbuf, "worthless piece of ");
4417             Strcat(tbuf, g); /* assume it starts with the color */
4418             Strcpy(bp, tbuf);
4419         }
4420     }
4421 #endif
4422
4423     actualn = bp;
4424     if (!dn)
4425         dn = actualn; /* ex. "skull cap" */
4426 #if 0 /*JP*/
4427  srch:
4428 #endif
4429     /* check real names of gems first */
4430     if (!oclass && actualn) {
4431         for (i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
4432             register const char *zn;
4433
4434             if ((zn = OBJ_NAME(objects[i])) != 0 && !strcmpi(actualn, zn)) {
4435                 typ = i;
4436                 goto typfnd;
4437             }
4438         }
4439 #if 0 /*JP*//* \93ú\96{\8cê\82Í"tin"\82ð\96ó\82µ\95ª\82¯\82Ä\82¢\82é\82Ì\82Å\95s\97v */
4440         /* "tin of foo" would be caught above, but plain "tin" has
4441            a random chance of yielding "tin wand" unless we do this */
4442         if (!strcmpi(actualn, "tin")) {
4443             typ = TIN;
4444             goto typfnd;
4445         }
4446 #endif
4447     }
4448
4449     if (((typ = rnd_otyp_by_namedesc(actualn, oclass, 1)) != STRANGE_OBJECT)
4450         || ((typ = rnd_otyp_by_namedesc(dn, oclass, 1)) != STRANGE_OBJECT)
4451         || ((typ = rnd_otyp_by_namedesc(un, oclass, 1)) != STRANGE_OBJECT)
4452         || ((typ = rnd_otyp_by_namedesc(origbp, oclass, 1)) != STRANGE_OBJECT))
4453         goto typfnd;
4454     typ = 0;
4455
4456     if (actualn) {
4457         struct Jitem *j = Japanese_items;
4458
4459         while (j->item) {
4460             if (actualn && !strcmpi(actualn, j->name)) {
4461                 typ = j->item;
4462                 goto typfnd;
4463             }
4464             j++;
4465         }
4466     }
4467 #if 0 /*JP*//* mail/armor\82Ì\95\\8bL\97h\82ê\83`\83F\83b\83N\82Í\95s\97v */
4468     /* if we've stripped off "armor" and failed to match anything
4469        in objects[], append "mail" and try again to catch misnamed
4470        requests like "plate armor" and "yellow dragon scale armor" */
4471     if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) {
4472         /* modifying bp's string is ok; we're about to resort
4473            to random armor if this also fails to match anything */
4474         Strcat(bp, " mail");
4475         goto retry;
4476     }
4477 #endif
4478 #if 0 /*JP*/
4479     if (!strcmpi(bp, "spinach")) {
4480 #else
4481     if (!strcmp(bp, "\83z\83E\83\8c\83\93\91\90")) {
4482 #endif
4483         contents = SPINACH;
4484         typ = TIN;
4485         goto typfnd;
4486     }
4487     /* Note: not strcmpi.  2 fruits, one capital, one not, are possible.
4488        Also not strncmp.  We used to ignore trailing text with it, but
4489        that resulted in "grapefruit" matching "grape" if the latter came
4490        earlier than the former in the fruit list. */
4491     {
4492         char *fp;
4493         int l, cntf;
4494         int blessedf, iscursedf, uncursedf, halfeatenf;
4495
4496         blessedf = iscursedf = uncursedf = halfeatenf = 0;
4497         cntf = 0;
4498
4499         fp = fruitbuf;
4500         for (;;) {
4501             if (!fp || !*fp)
4502                 break;
4503             if (!strncmpi(fp, "an ", l = 3) || !strncmpi(fp, "a ", l = 2)) {
4504                 cntf = 1;
4505             } else if (!cntf && digit(*fp)) {
4506                 cntf = atoi(fp);
4507                 while (digit(*fp))
4508                     fp++;
4509                 while (*fp == ' ')
4510                     fp++;
4511                 l = 0;
4512             } else if (!strncmpi(fp, "blessed ", l = 8)) {
4513                 blessedf = 1;
4514             } else if (!strncmpi(fp, "cursed ", l = 7)) {
4515                 iscursedf = 1;
4516             } else if (!strncmpi(fp, "uncursed ", l = 9)) {
4517                 uncursedf = 1;
4518             } else if (!strncmpi(fp, "partly eaten ", l = 13)
4519                        || !strncmpi(fp, "partially eaten ", l = 16)) {
4520                 halfeatenf = 1;
4521             } else
4522                 break;
4523             fp += l;
4524         }
4525
4526         for (f = ffruit; f; f = f->nextf) {
4527             /* match type: 0=none, 1=exact, 2=singular, 3=plural */
4528             int ftyp = 0;
4529
4530             if (!strcmp(fp, f->fname))
4531                 ftyp = 1;
4532             else if (!strcmp(fp, makesingular(f->fname)))
4533                 ftyp = 2;
4534             else if (!strcmp(fp, makeplural(f->fname)))
4535                 ftyp = 3;
4536             if (ftyp) {
4537                 typ = SLIME_MOLD;
4538                 blessed = blessedf;
4539                 iscursed = iscursedf;
4540                 uncursed = uncursedf;
4541                 halfeaten = halfeatenf;
4542                 /* adjust count if user explicitly asked for
4543                    singular amount (can't happen unless fruit
4544                    has been given an already pluralized name)
4545                    or for plural amount */
4546                 if (ftyp == 2 && !cntf)
4547                     cntf = 1;
4548                 else if (ftyp == 3 && !cntf)
4549                     cntf = 2;
4550                 cnt = cntf;
4551                 ftype = f->fid;
4552                 goto typfnd;
4553             }
4554         }
4555     }
4556
4557     if (!oclass && actualn) {
4558         short objtyp;
4559
4560         /* Perhaps it's an artifact specified by name, not type */
4561         name = artifact_name(actualn, &objtyp);
4562         if (name) {
4563             typ = objtyp;
4564             goto typfnd;
4565         }
4566     }
4567
4568     /*
4569      * Let wizards wish for traps and furniture.
4570      * Must come after objects check so wizards can still wish for
4571      * trap objects like beartraps.
4572      * Disallow such topology tweaks for WIZKIT startup wishes.
4573      */
4574  wiztrap:
4575     if (wizard && !program_state.wizkit_wishing) {
4576         struct rm *lev;
4577         boolean madeterrain = FALSE;
4578         int trap, x = u.ux, y = u.uy;
4579
4580         for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
4581             struct trap *t;
4582             const char *tname;
4583
4584             tname = defsyms[trap_to_defsym(trap)].explanation;
4585             if (strncmpi(tname, bp, strlen(tname)))
4586                 continue;
4587             /* found it; avoid stupid mistakes */
4588             if (is_hole(trap) && !Can_fall_thru(&u.uz))
4589                 trap = ROCKTRAP;
4590             if ((t = maketrap(x, y, trap)) != 0) {
4591                 trap = t->ttyp;
4592                 tname = defsyms[trap_to_defsym(trap)].explanation;
4593                 pline("%s%s.", An(tname),
4594                       (trap != MAGIC_PORTAL) ? "" : " to nowhere");
4595             } else
4596                 pline("Creation of %s failed.", an(tname));
4597             return (struct obj *) &zeroobj;
4598         }
4599
4600         /* furniture and terrain (use at your own risk; can clobber stairs
4601            or place furniture on existing traps which shouldn't be allowed) */
4602         lev = &levl[x][y];
4603         p = eos(bp);
4604         if (!BSTRCMPI(bp, p - 8, "fountain")) {
4605             lev->typ = FOUNTAIN;
4606             level.flags.nfountains++;
4607             if (!strncmpi(bp, "magic ", 6))
4608                 lev->blessedftn = 1;
4609             pline("A %sfountain.", lev->blessedftn ? "magic " : "");
4610             madeterrain = TRUE;
4611         } else if (!BSTRCMPI(bp, p - 6, "throne")) {
4612             lev->typ = THRONE;
4613             pline("A throne.");
4614             madeterrain = TRUE;
4615         } else if (!BSTRCMPI(bp, p - 4, "sink")) {
4616             lev->typ = SINK;
4617             level.flags.nsinks++;
4618             pline("A sink.");
4619             madeterrain = TRUE;
4620
4621         /* ("water" matches "potion of water" rather than terrain) */
4622         } else if (!BSTRCMPI(bp, p - 4, "pool")
4623                    || !BSTRCMPI(bp, p - 4, "moat")) {
4624             lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT;
4625             del_engr_at(x, y);
4626             pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
4627             /* Must manually make kelp! */
4628             water_damage_chain(level.objects[x][y], TRUE);
4629             madeterrain = TRUE;
4630
4631         /* also matches "molten lava" */
4632         } else if (!BSTRCMPI(bp, p - 4, "lava")) {
4633             lev->typ = LAVAPOOL;
4634             del_engr_at(x, y);
4635             pline("A pool of molten lava.");
4636             if (!(Levitation || Flying))
4637                 pooleffects(FALSE);
4638             madeterrain = TRUE;
4639         } else if (!BSTRCMPI(bp, p - 5, "altar")) {
4640             aligntyp al;
4641
4642             lev->typ = ALTAR;
4643             if (!strncmpi(bp, "chaotic ", 8))
4644                 al = A_CHAOTIC;
4645             else if (!strncmpi(bp, "neutral ", 8))
4646                 al = A_NEUTRAL;
4647             else if (!strncmpi(bp, "lawful ", 7))
4648                 al = A_LAWFUL;
4649             else if (!strncmpi(bp, "unaligned ", 10))
4650                 al = A_NONE;
4651             else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
4652                 al = !rn2(6) ? A_NONE : (rn2((int) A_LAWFUL + 2) - 1);
4653             lev->altarmask = Align2amask(al);
4654             pline("%s altar.", An(align_str(al)));
4655             madeterrain = TRUE;
4656         } else if (!BSTRCMPI(bp, p - 5, "grave")
4657                    || !BSTRCMPI(bp, p - 9, "headstone")) {
4658             make_grave(x, y, (char *) 0);
4659             pline("%s.", IS_GRAVE(lev->typ) ? "A grave"
4660                                             : "Can't place a grave here");
4661             madeterrain = TRUE;
4662         } else if (!BSTRCMPI(bp, p - 4, "tree")) {
4663             lev->typ = TREE;
4664             pline("A tree.");
4665             block_point(x, y);
4666             madeterrain = TRUE;
4667         } else if (!BSTRCMPI(bp, p - 4, "bars")) {
4668             lev->typ = IRONBARS;
4669             pline("Iron bars.");
4670             madeterrain = TRUE;
4671         }
4672
4673         if (madeterrain) {
4674             feel_newsym(x, y); /* map the spot where the wish occurred */
4675             /* hero started at <x,y> but might not be there anymore (create
4676                lava, decline to die, and get teleported away to safety) */
4677             if (u.uinwater && !is_pool(u.ux, u.uy)) {
4678                 u.uinwater = 0; /* leave the water */
4679                 docrt();
4680                 vision_full_recalc = 1;
4681             } else if (u.utrap && u.utraptype == TT_LAVA
4682                        && !is_lava(u.ux, u.uy)) {
4683                 reset_utrap(FALSE);
4684             }
4685             /* cast 'const' away; caller won't modify this */
4686             return (struct obj *) &zeroobj;
4687         }
4688     } /* end of wizard mode traps and terrain */
4689
4690 #if 0 /*JP*//* \83^\83C\83v\95Ê\82Í\82Æ\82è\82 \82¦\82¸\82µ\82È\82¢ */
4691     if (!oclass && !typ) {
4692         if (!strncmpi(bp, "polearm", 7)) {
4693             typ = rnd_otyp_by_wpnskill(P_POLEARMS);
4694             goto typfnd;
4695         } else if (!strncmpi(bp, "hammer", 6)) {
4696             typ = rnd_otyp_by_wpnskill(P_HAMMER);
4697             goto typfnd;
4698         }
4699     }
4700 #endif
4701
4702     if (!oclass)
4703         return ((struct obj *) 0);
4704  any:
4705     if (!oclass)
4706         oclass = wrpsym[rn2((int) sizeof wrpsym)];
4707  typfnd:
4708     if (typ)
4709         oclass = objects[typ].oc_class;
4710
4711     /* handle some objects that are only allowed in wizard mode */
4712     if (typ && !wizard) {
4713         switch (typ) {
4714         case AMULET_OF_YENDOR:
4715             typ = FAKE_AMULET_OF_YENDOR;
4716             break;
4717         case CANDELABRUM_OF_INVOCATION:
4718             typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
4719             break;
4720         case BELL_OF_OPENING:
4721             typ = BELL;
4722             break;
4723         case SPE_BOOK_OF_THE_DEAD:
4724             typ = SPE_BLANK_PAPER;
4725             break;
4726         case MAGIC_LAMP:
4727             typ = OIL_LAMP;
4728             break;
4729         default:
4730             /* catch any other non-wishable objects (venom) */
4731             if (objects[typ].oc_nowish)
4732                 return (struct obj *) 0;
4733             break;
4734         }
4735     }
4736
4737     /*
4738      * Create the object, then fine-tune it.
4739      */
4740     otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE);
4741     typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */
4742
4743     if (islit && (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN
4744                   || Is_candle(otmp) || typ == POT_OIL)) {
4745         place_object(otmp, u.ux, u.uy); /* make it viable light source */
4746         begin_burn(otmp, FALSE);
4747         obj_extract_self(otmp); /* now release it for caller's use */
4748     }
4749
4750     /* if player specified a reasonable count, maybe honor it */
4751     if (cnt > 0 && objects[typ].oc_merge
4752         && (wizard || cnt < rnd(6) || (cnt <= 7 && Is_candle(otmp))
4753             || (cnt <= 20 && ((oclass == WEAPON_CLASS && is_ammo(otmp))
4754                               || typ == ROCK || is_missile(otmp)))))
4755         otmp->quan = (long) cnt;
4756
4757     if (oclass == VENOM_CLASS)
4758         otmp->spe = 1;
4759
4760     if (spesgn == 0) {
4761         spe = otmp->spe;
4762     } else if (wizard) {
4763         ; /* no alteration to spe */
4764     } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS
4765                || is_weptool(otmp)
4766                || (oclass == RING_CLASS && objects[typ].oc_charged)) {
4767         if (spe > rnd(5) && spe > otmp->spe)
4768             spe = 0;
4769         if (spe > 2 && Luck < 0)
4770             spesgn = -1;
4771     } else {
4772         if (oclass == WAND_CLASS) {
4773             if (spe > 1 && spesgn == -1)
4774                 spe = 1;
4775         } else {
4776             if (spe > 0 && spesgn == -1)
4777                 spe = 0;
4778         }
4779         if (spe > otmp->spe)
4780             spe = otmp->spe;
4781     }
4782
4783     if (spesgn == -1)
4784         spe = -spe;
4785
4786     /* set otmp->spe.  This may, or may not, use spe... */
4787     switch (typ) {
4788     case TIN:
4789         if (contents == EMPTY) {
4790             otmp->corpsenm = NON_PM;
4791             otmp->spe = 0;
4792         } else if (contents == SPINACH) {
4793             otmp->corpsenm = NON_PM;
4794             otmp->spe = 1;
4795         }
4796         break;
4797     case TOWEL:
4798         if (wetness)
4799             otmp->spe = wetness;
4800         break;
4801     case SLIME_MOLD:
4802         otmp->spe = ftype;
4803     /* Fall through */
4804     case SKELETON_KEY:
4805     case CHEST:
4806     case LARGE_BOX:
4807     case HEAVY_IRON_BALL:
4808     case IRON_CHAIN:
4809     case STATUE:
4810         /* otmp->cobj already done in mksobj() */
4811         break;
4812 #ifdef MAIL
4813     case SCR_MAIL:
4814         /* 0: delivered in-game via external event (or randomly for fake mail);
4815            1: from bones or wishing; 2: written with marker */
4816         otmp->spe = 1;
4817         break;
4818 #endif
4819     case WAN_WISHING:
4820         if (!wizard) {
4821             otmp->spe = (rn2(10) ? -1 : 0);
4822             break;
4823         }
4824         /*FALLTHRU*/
4825     default:
4826         otmp->spe = spe;
4827     }
4828
4829     /* set otmp->corpsenm or dragon scale [mail] */
4830     if (mntmp >= LOW_PM) {
4831         if (mntmp == PM_LONG_WORM_TAIL)
4832             mntmp = PM_LONG_WORM;
4833
4834         switch (typ) {
4835         case TIN:
4836             otmp->spe = 0; /* No spinach */
4837             if (dead_species(mntmp, FALSE)) {
4838                 otmp->corpsenm = NON_PM; /* it's empty */
4839             } else if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4840                        && !(mvitals[mntmp].mvflags & G_NOCORPSE)
4841                        && mons[mntmp].cnutrit != 0) {
4842                 otmp->corpsenm = mntmp;
4843             }
4844             break;
4845         case CORPSE:
4846             if ((!(mons[mntmp].geno & G_UNIQ) || wizard)
4847                 && !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
4848                 if (mons[mntmp].msound == MS_GUARDIAN)
4849                     mntmp = genus(mntmp, 1);
4850                 set_corpsenm(otmp, mntmp);
4851             }
4852             break;
4853         case EGG:
4854             mntmp = can_be_hatched(mntmp);
4855             /* this also sets hatch timer if appropriate */
4856             set_corpsenm(otmp, mntmp);
4857             break;
4858         case FIGURINE:
4859             if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
4860 #ifdef MAIL
4861                 && mntmp != PM_MAIL_DAEMON
4862 #endif
4863                 )
4864                 otmp->corpsenm = mntmp;
4865             break;
4866         case STATUE:
4867             otmp->corpsenm = mntmp;
4868             if (Has_contents(otmp) && verysmall(&mons[mntmp]))
4869                 delete_contents(otmp); /* no spellbook */
4870             otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
4871             break;
4872         case SCALE_MAIL:
4873             /* Dragon mail - depends on the order of objects & dragons. */
4874             if (mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON)
4875                 otmp->otyp = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON;
4876             break;
4877         }
4878     }
4879
4880     /* set blessed/cursed -- setting the fields directly is safe
4881      * since weight() is called below and addinv() will take care
4882      * of luck */
4883     if (iscursed) {
4884         curse(otmp);
4885     } else if (uncursed) {
4886         otmp->blessed = 0;
4887         otmp->cursed = (Luck < 0 && !wizard);
4888     } else if (blessed) {
4889         otmp->blessed = (Luck >= 0 || wizard);
4890         otmp->cursed = (Luck < 0 && !wizard);
4891     } else if (spesgn < 0) {
4892         curse(otmp);
4893     }
4894
4895     /* set eroded and erodeproof */
4896     if (erosion_matters(otmp)) {
4897         if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
4898             otmp->oeroded = eroded;
4899         if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
4900             otmp->oeroded2 = eroded2;
4901         /*
4902          * 3.6.1: earlier versions included `&& !eroded && !eroded2' here,
4903          * but damageproof combined with damaged is feasible (eroded
4904          * armor modified by confused reading of cursed destroy armor)
4905          * so don't prevent player from wishing for such a combination.
4906          */
4907         if (erodeproof && (is_damageable(otmp) || otmp->otyp == CRYSKNIFE))
4908             otmp->oerodeproof = (Luck >= 0 || wizard);
4909     }
4910
4911     /* set otmp->recharged */
4912     if (oclass == WAND_CLASS) {
4913         /* prevent wishing abuse */
4914         if (otmp->otyp == WAN_WISHING && !wizard)
4915             rechrg = 1;
4916         otmp->recharged = (unsigned) rechrg;
4917     }
4918
4919     /* set poisoned */
4920     if (ispoisoned) {
4921         if (is_poisonable(otmp))
4922             otmp->opoisoned = (Luck >= 0);
4923         else if (oclass == FOOD_CLASS)
4924             /* try to taint by making it as old as possible */
4925             otmp->age = 1L;
4926     }
4927     /* and [un]trapped */
4928     if (trapped) {
4929         if (Is_box(otmp) || typ == TIN)
4930             otmp->otrapped = (trapped == 1);
4931     }
4932     /* empty for containers rather than for tins */
4933     if (contents == EMPTY) {
4934         if (otmp->otyp == BAG_OF_TRICKS || otmp->otyp == HORN_OF_PLENTY) {
4935             if (otmp->spe > 0)
4936                 otmp->spe = 0;
4937         } else if (Has_contents(otmp)) {
4938             /* this assumes that artifacts can't be randomly generated
4939                inside containers */
4940             delete_contents(otmp);
4941             otmp->owt = weight(otmp);
4942         }
4943     }
4944     /* set locked/unlocked/broken */
4945     if (Is_box(otmp)) {
4946         if (locked) {
4947             otmp->olocked = 1, otmp->obroken = 0;
4948         } else if (unlocked) {
4949             otmp->olocked = 0, otmp->obroken = 0;
4950         } else if (broken) {
4951             otmp->olocked = 0, otmp->obroken = 1;
4952         }
4953     }
4954
4955     if (isgreased)
4956         otmp->greased = 1;
4957
4958     if (isdiluted && otmp->oclass == POTION_CLASS && otmp->otyp != POT_WATER)
4959         otmp->odiluted = 1;
4960
4961     /* set tin variety */
4962     if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard))
4963         set_tin_variety(otmp, tvariety);
4964
4965     if (name) {
4966         const char *aname;
4967         short objtyp;
4968
4969         /* an artifact name might need capitalization fixing */
4970         aname = artifact_name(name, &objtyp);
4971         if (aname && objtyp == otmp->otyp)
4972             name = aname;
4973
4974         /* 3.6 tribute - fix up novel */
4975         if (otmp->otyp == SPE_NOVEL) {
4976             const char *novelname;
4977
4978             novelname = lookup_novel(name, &otmp->novelidx);
4979             if (novelname)
4980                 name = novelname;
4981         }
4982
4983         otmp = oname(otmp, name);
4984         /* name==aname => wished for artifact (otmp->oartifact => got it) */
4985         if (otmp->oartifact || name == aname) {
4986             otmp->quan = 1L;
4987             u.uconduct.wisharti++; /* KMH, conduct */
4988         }
4989     }
4990
4991     /* more wishing abuse: don't allow wishing for certain artifacts */
4992     /* and make them pay; charge them for the wish anyway! */
4993     if ((is_quest_artifact(otmp)
4994          || (otmp->oartifact && rn2(nartifact_exist()) > 1)) && !wizard) {
4995         artifact_exists(otmp, safe_oname(otmp), FALSE);
4996         obfree(otmp, (struct obj *) 0);
4997         otmp = (struct obj *) &zeroobj;
4998 /*JP
4999         pline("For a moment, you feel %s in your %s, but it disappears!",
5000 */
5001         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",
5002               something, makeplural(body_part(HAND)));
5003         return otmp;
5004     }
5005
5006     if (halfeaten && otmp->oclass == FOOD_CLASS) {
5007         if (otmp->otyp == CORPSE)
5008             otmp->oeaten = mons[otmp->corpsenm].cnutrit;
5009         else
5010             otmp->oeaten = objects[otmp->otyp].oc_nutrition;
5011         /* (do this adjustment before setting up object's weight) */
5012         consume_oeaten(otmp, 1);
5013     }
5014     otmp->owt = weight(otmp);
5015     if (very && otmp->otyp == HEAVY_IRON_BALL)
5016         otmp->owt += IRON_BALL_W_INCR;
5017     else if (gsize > 1 && otmp->globby)
5018         /* 0: unspecified => small; 1: small => keep default owt of 20;
5019            2: medium => 120; 3: large => 320; 4: very large => 520 */
5020         otmp->owt += 100 + (gsize - 2) * 200;
5021
5022     return otmp;
5023 }
5024
5025 int
5026 rnd_class(first, last)
5027 int first, last;
5028 {
5029     int i, x, sum = 0;
5030
5031     if (first == last)
5032         return first;
5033     for (i = first; i <= last; i++)
5034         sum += objects[i].oc_prob;
5035     if (!sum) /* all zero */
5036         return first + rn2(last - first + 1);
5037     x = rnd(sum);
5038     for (i = first; i <= last; i++)
5039         if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
5040             return i;
5041     return 0;
5042 }
5043
5044 STATIC_OVL const char *
5045 Japanese_item_name(i)
5046 int i;
5047 {
5048     struct Jitem *j = Japanese_items;
5049
5050     while (j->item) {
5051         if (i == j->item)
5052             return j->name;
5053         j++;
5054     }
5055     return (const char *) 0;
5056 }
5057
5058 const char *
5059 suit_simple_name(suit)
5060 struct obj *suit;
5061 {
5062     const char *suitnm, *esuitp;
5063
5064     if (suit) {
5065         if (Is_dragon_mail(suit))
5066 #if 0 /*JP:T*/
5067             return "dragon mail"; /* <color> dragon scale mail */
5068 #else
5069             return "\97Ø\8aZ"; /* <color> dragon scale mail */
5070 #endif
5071         else if (Is_dragon_scales(suit))
5072 /*JP
5073             return "dragon scales";
5074 */
5075             return "\97Ø";
5076         suitnm = OBJ_NAME(objects[suit->otyp]);
5077         esuitp = eos((char *) suitnm);
5078 #if 0 /*JP:T*/
5079         if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
5080             return "mail"; /* most suits fall into this category */
5081 #else
5082         if (strlen(suitnm) > 2 && !strcmp(esuitp - 2, "\8aZ"))
5083             return "\8aZ"; /* most suits fall into this category */
5084 #endif
5085 #if 0 /*JP*/
5086         else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
5087             return "jacket"; /* leather jacket */
5088 #endif
5089     }
5090     /* "suit" is lame but "armor" is ambiguous and "body armor" is absurd */
5091 /*JP
5092     return "suit";
5093 */
5094     return "\95\9e";
5095 }
5096
5097 const char *
5098 cloak_simple_name(cloak)
5099 struct obj *cloak;
5100 {
5101     if (cloak) {
5102         switch (cloak->otyp) {
5103         case ROBE:
5104 /*JP
5105             return "robe";
5106 */
5107             return "\83\8d\81[\83u";
5108         case MUMMY_WRAPPING:
5109 /*JP
5110             return "wrapping";
5111 */
5112             return "\95ï\91Ñ";
5113         case ALCHEMY_SMOCK:
5114             return (objects[cloak->otyp].oc_name_known && cloak->dknown)
5115 /*JP
5116                        ? "smock"
5117 */
5118                        ? "\83X\83\82\83b\83N"
5119 /*JP
5120                        : "apron";
5121 */
5122                        : "\83G\83v\83\8d\83\93";
5123         default:
5124             break;
5125         }
5126     }
5127 /*JP
5128     return "cloak";
5129 */
5130     return "\83N\83\8d\81[\83N";
5131 }
5132
5133 /* helm vs hat for messages */
5134 const char *
5135 helm_simple_name(helmet)
5136 struct obj *helmet;
5137 {
5138     /*
5139      *  There is some wiggle room here; the result has been chosen
5140      *  for consistency with the "protected by hard helmet" messages
5141      *  given for various bonks on the head:  headgear that provides
5142      *  such protection is a "helm", that which doesn't is a "hat".
5143      *
5144      *      elven leather helm / leather hat    -> hat
5145      *      dwarvish iron helm / hard hat       -> helm
5146      *  The rest are completely straightforward:
5147      *      fedora, cornuthaum, dunce cap       -> hat
5148      *      all other types of helmets          -> helm
5149      */
5150 /*JP
5151     return (helmet && !is_metallic(helmet)) ? "hat" : "helm";
5152 */
5153     return (helmet && !is_metallic(helmet)) ? "\96X\8eq" : "\8a\95";
5154 }
5155
5156 /* gloves vs gauntlets; depends upon discovery state */
5157 const char *
5158 gloves_simple_name(gloves)
5159 struct obj *gloves;
5160 {
5161     static const char gauntlets[] = "gauntlets";
5162
5163     if (gloves && gloves->dknown) {
5164         int otyp = gloves->otyp;
5165         struct objclass *ocl = &objects[otyp];
5166         const char *actualn = OBJ_NAME(*ocl),
5167                    *descrpn = OBJ_DESCR(*ocl);
5168
5169         if (strstri(objects[otyp].oc_name_known ? actualn : descrpn,
5170                     gauntlets))
5171             return gauntlets;
5172     }
5173     return "gloves";
5174 }
5175
5176 const char *
5177 mimic_obj_name(mtmp)
5178 struct monst *mtmp;
5179 {
5180     if (M_AP_TYPE(mtmp) == M_AP_OBJECT) {
5181         if (mtmp->mappearance == GOLD_PIECE)
5182 /*JP
5183             return "gold";
5184 */
5185             return "\8bà\89Ý";
5186         if (mtmp->mappearance != STRANGE_OBJECT)
5187             return simple_typename(mtmp->mappearance);
5188     }
5189 /*JP
5190     return "whatcha-may-callit";
5191 */
5192     return "\89½\82Æ\82©\82¢\82¤\82à\82Ì";
5193 }
5194
5195 /*
5196  * Construct a query prompt string, based around an object name, which is
5197  * guaranteed to fit within [QBUFSZ].  Takes an optional prefix, three
5198  * choices for filling in the middle (two object formatting functions and a
5199  * last resort literal which should be very short), and an optional suffix.
5200  */
5201 char *
5202 safe_qbuf(qbuf, qprefix, qsuffix, obj, func, altfunc, lastR)
5203 char *qbuf; /* output buffer */
5204 const char *qprefix, *qsuffix;
5205 struct obj *obj;
5206 char *FDECL((*func), (OBJ_P)), *FDECL((*altfunc), (OBJ_P));
5207 const char *lastR;
5208 {
5209     char *bufp, *endp;
5210     /* convert size_t (or int for ancient systems) to ordinary unsigned */
5211     unsigned len, lenlimit,
5212         len_qpfx = (unsigned) (qprefix ? strlen(qprefix) : 0),
5213         len_qsfx = (unsigned) (qsuffix ? strlen(qsuffix) : 0),
5214         len_lastR = (unsigned) strlen(lastR);
5215
5216     lenlimit = QBUFSZ - 1;
5217     endp = qbuf + lenlimit;
5218     /* sanity check, aimed mainly at paniclog (it's conceivable for
5219        the result of short_oname() to be shorter than the length of
5220        the last resort string, but we ignore that possibility here) */
5221     if (len_qpfx > lenlimit)
5222         impossible("safe_qbuf: prefix too long (%u characters).", len_qpfx);
5223     else if (len_qpfx + len_qsfx > lenlimit)
5224         impossible("safe_qbuf: suffix too long (%u + %u characters).",
5225                    len_qpfx, len_qsfx);
5226     else if (len_qpfx + len_lastR + len_qsfx > lenlimit)
5227         impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
5228                    len_qpfx, len_lastR, len_qsfx);
5229
5230     /* the output buffer might be the same as the prefix if caller
5231        has already partially filled it */
5232     if (qbuf == qprefix) {
5233         /* prefix is already in the buffer */
5234         *endp = '\0';
5235     } else if (qprefix) {
5236         /* put prefix into the buffer */
5237         (void) strncpy(qbuf, qprefix, lenlimit);
5238         *endp = '\0';
5239     } else {
5240         /* no prefix; output buffer starts out empty */
5241         qbuf[0] = '\0';
5242     }
5243     len = (unsigned) strlen(qbuf);
5244
5245     if (len + len_lastR + len_qsfx > lenlimit) {
5246         /* too long; skip formatting, last resort output is truncated */
5247         if (len < lenlimit) {
5248             (void) strncpy(&qbuf[len], lastR, lenlimit - len);
5249             *endp = '\0';
5250             len = (unsigned) strlen(qbuf);
5251             if (qsuffix && len < lenlimit) {
5252                 (void) strncpy(&qbuf[len], qsuffix, lenlimit - len);
5253                 *endp = '\0';
5254                 /* len = (unsigned) strlen(qbuf); */
5255             }
5256         }
5257     } else {
5258         /* suffix and last resort are guaranteed to fit */
5259         len += len_qsfx; /* include the pending suffix */
5260         /* format the object */
5261         bufp = short_oname(obj, func, altfunc, lenlimit - len);
5262         if (len + strlen(bufp) <= lenlimit)
5263             Strcat(qbuf, bufp); /* formatted name fits */
5264         else
5265             Strcat(qbuf, lastR); /* use last resort */
5266         releaseobuf(bufp);
5267
5268         if (qsuffix)
5269             Strcat(qbuf, qsuffix);
5270     }
5271     /* assert( strlen(qbuf) < QBUFSZ ); */
5272     return qbuf;
5273 }
5274
5275 STATIC_OVL char *
5276 globwt(otmp, buf, weightformatted_p)
5277 struct obj *otmp;
5278 char *buf;
5279 boolean *weightformatted_p;
5280 {
5281     *buf = '\0';
5282     if (otmp->globby) {
5283         Sprintf(buf, "%u aum, ", otmp->owt);
5284         *weightformatted_p = TRUE;
5285     } else {
5286         *weightformatted_p = FALSE;
5287     }
5288     return buf;
5289 }
5290
5291 /*objnam.c*/