OSDN Git Service

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