OSDN Git Service

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