OSDN Git Service

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