OSDN Git Service

update year to 2019
[jnethack/source.git] / src / do_name.c
1 /* NetHack 3.6  do_name.c       $NHDT-Date: 1519420054 2018/02/23 21:07:34 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.128 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Pasi Kallinen, 2018. */
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-2019            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12
13 STATIC_DCL char *NDECL(nextmbuf);
14 STATIC_DCL void FDECL(getpos_help, (BOOLEAN_P, const char *));
15 STATIC_DCL int FDECL(CFDECLSPEC cmp_coord_distu, (const void *, const void *));
16 STATIC_DCL boolean FDECL(gather_locs_interesting, (int, int, int));
17 STATIC_DCL void FDECL(gather_locs, (coord **, int *, int));
18 STATIC_DCL int FDECL(gloc_filter_floodfill_matcharea, (int, int));
19 STATIC_DCL void FDECL(auto_describe, (int, int));
20 STATIC_DCL void NDECL(do_mname);
21 STATIC_DCL boolean FDECL(alreadynamed, (struct monst *, char *, char *));
22 STATIC_DCL void FDECL(do_oname, (struct obj *));
23 STATIC_PTR char *FDECL(docall_xname, (struct obj *));
24 STATIC_DCL void NDECL(namefloorobj);
25 STATIC_DCL char *FDECL(bogusmon, (char *,char *));
26
27 extern const char what_is_an_unknown_object[]; /* from pager.c */
28
29 #define NUMMBUF 5
30
31 /* manage a pool of BUFSZ buffers, so callers don't have to */
32 STATIC_OVL char *
33 nextmbuf()
34 {
35     static char NEARDATA bufs[NUMMBUF][BUFSZ];
36     static int bufidx = 0;
37
38     bufidx = (bufidx + 1) % NUMMBUF;
39     return bufs[bufidx];
40 }
41
42 /* function for getpos() to highlight desired map locations.
43  * parameter value 0 = initialize, 1 = highlight, 2 = done
44  */
45 static void FDECL((*getpos_hilitefunc), (int)) = (void FDECL((*), (int))) 0;
46 static boolean FDECL((*getpos_getvalid), (int, int)) =
47                                            (boolean FDECL((*), (int, int))) 0;
48
49 void
50 getpos_sethilite(gp_hilitef, gp_getvalidf)
51 void FDECL((*gp_hilitef), (int));
52 boolean FDECL((*gp_getvalidf), (int, int));
53 {
54     getpos_hilitefunc = gp_hilitef;
55     getpos_getvalid = gp_getvalidf;
56 }
57
58 /*JP:
59   [0] "cannot see %s"
60   [1] "pick a %s"
61   [2] "use XXX to move the cursor to %s"
62   */
63 const char *const gloc_descr[NUM_GLOCS][4] = {
64 #if 0 /*JP*/
65     { "any monsters", "monster", "next monster", "monsters" },
66     { "any items", "item", "next object", "objects" },
67     { "any doors", "door", "next door or doorway", "doors or doorways" },
68     { "any unexplored areas", "unexplored area", "unexplored location",
69       "unexplored locations" },
70     { "anything interesting", "interesting thing", "anything interesting",
71       "anything interesting" }
72 #else
73     { "\89ö\95¨", "\89ö\95¨", "\89ö\95¨\82Ì\97×", "\89ö\95¨" },
74     { "\95¨", "\95¨", "\95¨\82Ì\97×", "\95¨" },
75     { "\94à", "\94à", "\94à\82â\8fo\93ü\82è\8cû\82Ì\97×", "\94à\82â\8fo\93ü\82è\8cû" },
76     { "\96¢\92T\8dõ\95\94\95ª", "\96¢\92T\8dõ\95\94\95ª", "\96¢\92T\8dõ\82Ì\88Ê\92u", "\96¢\92T\8dõ\82Ì\88Ê\92u" },
77     { "\8aÖ\90S\82Ì\82 \82é\82à\82Ì", "\8aÖ\90S\82Ì\82 \82é\82à\82Ì", "\8aÖ\90S\82Ì\82 \82é\82à\82Ì", "\8aÖ\90S\82Ì\82 \82é\82à\82Ì" }
78 #endif
79 };
80
81 const char *const gloc_filtertxt[NUM_GFILTER] = {
82 #if 0 /*JP*/
83     "",
84     " in view",
85     " in this area"
86 #else
87     "",
88     "\8e\8b\8aE\82Ì\92\86\82Ì",
89     "\82±\82Ì\83G\83\8a\83A\82Ì"
90 #endif
91 };
92
93 void
94 getpos_help_keyxhelp(tmpwin, k1, k2, gloc)
95 winid tmpwin;
96 const char *k1;
97 const char *k2;
98 int gloc;
99 {
100     char sbuf[BUFSZ];
101
102 #if 0 /*JP*/
103     Sprintf(sbuf, "Use '%s' or '%s' to %s%s%s.",
104             k1, k2,
105             iflags.getloc_usemenu ? "get a menu of "
106                                   : "move the cursor to ",
107             gloc_descr[gloc][2 + iflags.getloc_usemenu],
108             gloc_filtertxt[iflags.getloc_filter]);
109 #else
110     Sprintf(sbuf, "'%s'\82©'%s'\82Å%s%s%s\81D",
111             k1, k2,
112             gloc_filtertxt[iflags.getloc_filter],
113             gloc_descr[gloc][2 + iflags.getloc_usemenu],
114             iflags.getloc_usemenu ? "\82Ì\83\81\83j\83\85\81[\82ð\8fo\82·"
115                                   : "\82É\83J\81[\83\\83\8b\82ð\93®\82©\82·");
116 #endif
117     putstr(tmpwin, 0, sbuf);
118 }
119
120 /* the response for '?' help request in getpos() */
121 STATIC_OVL void
122 getpos_help(force, goal)
123 boolean force;
124 const char *goal;
125 {
126     char sbuf[BUFSZ];
127     boolean doing_what_is;
128     winid tmpwin = create_nhwindow(NHW_MENU);
129 #if 0 /*JP*/
130     const char *const fastmovemode[2] = { "8 units at a time",
131                                           "skipping same glyphs" };
132 #else
133     const char *const fastmovemode[2] = { "\88ê\93x\82É8\83}\83X",
134                                           "\93¯\82\92n\8c`\82ð\94ò\82Î\82µ\82Ä" };
135 #endif
136
137 #if 0 /*JP*/
138     Sprintf(sbuf,
139             "Use '%c', '%c', '%c', '%c' to move the cursor to %s.", /* hjkl */
140             Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal);
141 #else
142     Sprintf(sbuf,
143             "[%c%c%c%c]\82Å%s\82Ö\88Ú\93®\82Å\82«\82é\81D",
144             Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal);
145 #endif
146     putstr(tmpwin, 0, sbuf);
147 #if 0 /*JP*/
148     Sprintf(sbuf,
149             "Use 'H', 'J', 'K', 'L' to fast-move the cursor, %s.",
150             fastmovemode[iflags.getloc_moveskip]);
151 #else
152     Sprintf(sbuf,
153             "'H', 'J', 'K', 'L' \82Å%s\88Ú\93®\82Å\82«\82é\81D",
154             fastmovemode[iflags.getloc_moveskip]);
155 #endif
156     putstr(tmpwin, 0, sbuf);
157 /*JP
158     putstr(tmpwin, 0, "Or enter a background symbol (ex. '<').");
159 */
160     putstr(tmpwin, 0, "\94w\8ci\82Ì\83V\83\93\83{\83\8b\82ð\93ü\97Í\82·\82é\82Æ\82»\82Ì\88Ê\92u\82É\88Ú\93®\82·\82é(\97á\81F'<')\81D");
161 #if 0 /*JP*/
162     Sprintf(sbuf, "Use '%s' to move the cursor on yourself.",
163            visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
164 #else
165     Sprintf(sbuf, "'%s'\82Å\8e©\95ª\8e©\90g\82Ì\88Ê\92u\82É\88Ú\93®\82·\82é\81D",
166            visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
167 #endif
168     putstr(tmpwin, 0, sbuf);
169     if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
170         getpos_help_keyxhelp(tmpwin,
171                              visctrl(Cmd.spkeys[NHKF_GETPOS_MON_NEXT]),
172                              visctrl(Cmd.spkeys[NHKF_GETPOS_MON_PREV]),
173                              GLOC_MONS);
174     }
175     if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
176         getpos_help_keyxhelp(tmpwin,
177                              visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]),
178                              visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_PREV]),
179                              GLOC_OBJS);
180     }
181     if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) {
182         /* these are primarily useful when choosing a travel
183            destination for the '_' command */
184         getpos_help_keyxhelp(tmpwin,
185                              visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_NEXT]),
186                              visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_PREV]),
187                              GLOC_DOOR);
188         getpos_help_keyxhelp(tmpwin,
189                              visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_NEXT]),
190                              visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_PREV]),
191                              GLOC_EXPLORE);
192         getpos_help_keyxhelp(tmpwin,
193                              visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_NEXT]),
194                              visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_PREV]),
195                              GLOC_INTERESTING);
196     }
197 #if 0 /*JP*/
198     Sprintf(sbuf, "Use '%s' to change fast-move mode to %s.",
199             visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
200             fastmovemode[!iflags.getloc_moveskip]);
201 #else
202     Sprintf(sbuf, "'%s'\82Å\8d\82\91¬\88Ú\93®\83\82\81[\83h\82ð%s\88Ú\93®\82É\82·\82é\81D",
203             visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
204             fastmovemode[!iflags.getloc_moveskip]);
205 #endif
206     putstr(tmpwin, 0, sbuf);
207     if (!iflags.terrainmode || (iflags.terrainmode & TER_DETECT) == 0) {
208 #if 0 /*JP*/
209         Sprintf(sbuf, "Use '%s' to toggle menu listing for possible targets.",
210                 visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
211 #else
212         Sprintf(sbuf, "'%s'\82Å\89Â\94\\82È\83^\81[\83Q\83b\83g\82Ì\83\81\83j\83\85\81[\95\\8e¦\82ð\90Ø\82è\91Ö\82¦\82é\81D",
213                 visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
214 #endif
215         putstr(tmpwin, 0, sbuf);
216 #if 0 /*JP*/
217         Sprintf(sbuf,
218                 "Use '%s' to change the mode of limiting possible targets.",
219                 visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
220 #else
221         Sprintf(sbuf,
222                 "'%s'\82Å\90§\8cÀ\82³\82ê\82½\89Â\94\\82È\83^\81[\83Q\83b\83g\82Ì\83\82\81[\83h\82ð\90Ø\82è\91Ö\82¦\82é\81D",
223                 visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
224 #endif
225         putstr(tmpwin, 0, sbuf);
226     }
227     if (!iflags.terrainmode) {
228         char kbuf[BUFSZ];
229
230         if (getpos_getvalid) {
231 #if 0 /*JP*/
232             Sprintf(sbuf, "Use '%s' or '%s' to move to valid locations.",
233                     visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
234                     visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
235 #else
236             Sprintf(sbuf, "'%s'\82©'%s'\82Å\90³\93\96\82È\88Ê\92u\82É\88Ú\93®\82·\82é\81D",
237                     visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
238                     visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
239 #endif
240             putstr(tmpwin, 0, sbuf);
241         }
242         if (getpos_hilitefunc) {
243 #if 0 /*JP:T*/
244             Sprintf(sbuf, "Use '%s' to display valid locations.",
245                     visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
246 #else
247             Sprintf(sbuf, "'%s'\82Å\89Â\94\\82È\88Ê\92u\82ð\95\\8e¦\82·\82é\81D",
248                     visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
249 #endif
250             putstr(tmpwin, 0, sbuf);
251         }
252 #if 0 /*JP:T*/
253         Sprintf(sbuf, "Use '%s' to toggle automatic description.",
254                 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
255 #else
256         Sprintf(sbuf, "'%s'\82Å\90à\96¾\82Ì\8e©\93®\95\\8e¦\82ð\90Ø\82è\91Ö\82¦\82é\81D",
257                 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
258 #endif
259         putstr(tmpwin, 0, sbuf);
260         if (iflags.cmdassist) { /* assisting the '/' command, I suppose... */
261 #if 0 /*JP*/
262             Sprintf(sbuf,
263                     (iflags.getpos_coords == GPCOORDS_NONE)
264          ? "(Set 'whatis_coord' option to include coordinates with '%s' text.)"
265          : "(Reset 'whatis_coord' option to omit coordinates from '%s' text.)",
266                     visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
267 #else
268             Sprintf(sbuf,
269                     (iflags.getpos_coords == GPCOORDS_NONE)
270          ? "('%s'\82É\8dÀ\95W\82ð\8aÜ\82Þ\82É\82Í'whatis_coord'\83I\83v\83V\83\87\83\93\82ð\83I\83\93\82É\82·\82é\81D)"
271          : "('%s'\82©\82ç\8dÀ\95W\82ð\8f\9c\82­\82É\82Í'whatis_coord'\83I\83v\83V\83\87\83\93\82ð\83I\83t\82É\82·\82é\81D)",
272                     visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
273 #endif
274         }
275         /* disgusting hack; the alternate selection characters work for any
276            getpos call, but only matter for dowhatis (and doquickwhatis) */
277         doing_what_is = (goal == what_is_an_unknown_object);
278         if (doing_what_is) {
279 #if 0 /*JP*/
280             Sprintf(kbuf, "'%s' or '%s' or '%s' or '%s'",
281                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
282                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]),
283                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]),
284                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
285 #else
286             Sprintf(kbuf, "'%s'\82©'%s'\82©'%s'\82©'%s'",
287                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
288                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]),
289                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]),
290                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
291 #endif
292         } else {
293             Sprintf(kbuf, "'%s'", visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
294         }
295 #if 0 /*JP:T*/
296         Sprintf(sbuf, "Type a %s when you are at the right place.", kbuf);
297 #else
298         Sprintf(sbuf, "[.]%s\82Å\8c\88\92è\81D", kbuf);
299 #endif
300         putstr(tmpwin, 0, sbuf);
301         if (doing_what_is) {
302 #if 0 /*JP*/
303             Sprintf(sbuf,
304        "  '%s' describe current spot, show 'more info', move to another spot.",
305                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
306 #else
307             Sprintf(sbuf,
308        "  '%s'\82Í\8c»\8dÝ\82Ì\88Ê\92u\82ð\90à\96¾\82µ\81A\92Ç\89Á\8fî\95ñ\82ð\95\\8e¦\82µ\81A\8e\9f\82Ì\88Ê\92u\82É\88Ú\93®\82·\82é\81D",
309                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
310 #endif
311             putstr(tmpwin, 0, sbuf);
312 #if 0 /*JP*/
313             Sprintf(sbuf,
314                     "  '%s' describe current spot,%s move to another spot;",
315                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
316                     flags.help ? " prompt if 'more info'," : "");
317 #else
318             Sprintf(sbuf,
319                     "  '%s'\82Í\8c»\8dÝ\82Ì\88Ê\92u\82ð\90à\96¾\82µ\81C%s\8e\9f\82Ì\88Ê\92u\82É\88Ú\93®\82·\82é;",
320                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
321                     flags.help ? "\92Ç\89Á\8fî\95ñ\82ª\82 \82ê\82Î\8am\94F\82µ\81C" : "");
322 #endif
323             putstr(tmpwin, 0, sbuf);
324 #if 0 /*JP*/
325             Sprintf(sbuf,
326                     "  '%s' describe current spot, move to another spot;",
327                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]));
328 #else
329             Sprintf(sbuf,
330                     "  '%s'\82Í\8c»\8dÝ\82Ì\88Ê\92u\82ð\90à\96¾\82µ\81C\8e\9f\82Ì\88Ê\92u\82É\88Ú\93®\82·\82é;",
331                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]));
332 #endif
333             putstr(tmpwin, 0, sbuf);
334 #if 0 /*JP*/
335             Sprintf(sbuf,
336                     "  '%s' describe current spot, stop looking at things;",
337                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]));
338 #else
339             Sprintf(sbuf,
340                     "  '%s'\82Í\8c»\8dÝ\82Ì\88Ê\92u\82ð\90à\96¾\82µ\81C\8c©\82é\82Ì\82ð\82â\82ß\82é;",
341                     visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]));
342 #endif
343             putstr(tmpwin, 0, sbuf);
344         }
345     }
346     if (!force)
347 /*JP
348         putstr(tmpwin, 0, "Type Space or Escape when you're done.");
349 */
350         putstr(tmpwin, 0, "\83X\83y\81[\83X\82Ü\82½\82Í\83G\83X\83P\81[\83v\82Å\8fI\97¹\81D");
351     putstr(tmpwin, 0, "");
352     display_nhwindow(tmpwin, TRUE);
353     destroy_nhwindow(tmpwin);
354 }
355
356 STATIC_OVL int
357 cmp_coord_distu(a, b)
358 const void *a;
359 const void *b;
360 {
361     const coord *c1 = a;
362     const coord *c2 = b;
363     int dx, dy, dist_1, dist_2;
364
365     dx = u.ux - c1->x;
366     dy = u.uy - c1->y;
367     dist_1 = max(abs(dx), abs(dy));
368     dx = u.ux - c2->x;
369     dy = u.uy - c2->y;
370     dist_2 = max(abs(dx), abs(dy));
371
372     if (dist_1 == dist_2)
373         return (c1->y != c2->y) ? (c1->y - c2->y) : (c1->x - c2->x);
374
375     return dist_1 - dist_2;
376 }
377
378 #define IS_UNEXPLORED_LOC(x,y) \
379     (isok((x), (y))                                     \
380      && glyph_is_cmap(levl[(x)][(y)].glyph)             \
381      && glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone  \
382      && !levl[(x)][(y)].seenv)
383
384 static struct opvar *gloc_filter_map = (struct opvar *) 0;
385
386 #define GLOC_SAME_AREA(x,y)                                     \
387     (isok((x), (y))                                             \
388      && (selection_getpoint((x),(y), gloc_filter_map)))
389
390 static int gloc_filter_floodfill_match_glyph;
391
392 int
393 gloc_filter_classify_glyph(glyph)
394 int glyph;
395 {
396     int c;
397
398     if (!glyph_is_cmap(glyph))
399         return 0;
400
401     c = glyph_to_cmap(glyph);
402
403     if (is_cmap_room(c) || is_cmap_furniture(c))
404         return 1;
405     else if (is_cmap_wall(c) || c == S_tree)
406         return 2;
407     else if (is_cmap_corr(c))
408         return 3;
409     else if (is_cmap_water(c))
410         return 4;
411     else if (is_cmap_lava(c))
412         return 5;
413     return 0;
414 }
415
416 STATIC_OVL int
417 gloc_filter_floodfill_matcharea(x,y)
418 int x,y;
419 {
420     int glyph = back_to_glyph(x, y);
421
422     if (!levl[x][y].seenv)
423         return FALSE;
424
425     if (glyph == gloc_filter_floodfill_match_glyph)
426         return TRUE;
427
428     if (gloc_filter_classify_glyph(glyph)
429         == gloc_filter_classify_glyph(gloc_filter_floodfill_match_glyph))
430         return TRUE;
431
432     return FALSE;
433 }
434
435 void
436 gloc_filter_floodfill(x, y)
437 int x, y;
438 {
439     gloc_filter_floodfill_match_glyph = back_to_glyph(x, y);
440
441     set_selection_floodfillchk(gloc_filter_floodfill_matcharea);
442     selection_floodfill(gloc_filter_map, x, y, FALSE);
443 }
444
445 void
446 gloc_filter_init()
447 {
448     if (iflags.getloc_filter == GFILTER_AREA) {
449         if (!gloc_filter_map) {
450             gloc_filter_map = selection_opvar(NULL);
451         }
452         /* special case: if we're in a doorway, try to figure out which
453            direction we're moving, and use that side of the doorway */
454         if (IS_DOOR(levl[u.ux][u.uy].typ)) {
455             if (u.dx || u.dy) {
456                 gloc_filter_floodfill(u.ux + u.dx, u.uy + u.dy);
457             } else {
458                 /* TODO: maybe add both sides of the doorway? */
459             }
460         } else {
461             gloc_filter_floodfill(u.ux, u.uy);
462         }
463
464
465     }
466 }
467
468 void
469 gloc_filter_done()
470 {
471     if (gloc_filter_map) {
472         opvar_free_x(gloc_filter_map);
473         gloc_filter_map = NULL;
474     }
475 }
476
477 STATIC_OVL boolean
478 gather_locs_interesting(x, y, gloc)
479 int x, y, gloc;
480 {
481     /* TODO: if glyph is a pile glyph, convert to ordinary one
482      *       in order to keep tail/boulder/rock check simple.
483      */
484     int glyph = glyph_at(x, y);
485
486     if (iflags.getloc_filter == GFILTER_VIEW && !cansee(x, y))
487         return FALSE;
488     if (iflags.getloc_filter == GFILTER_AREA && !GLOC_SAME_AREA(x, y)
489         && !GLOC_SAME_AREA(x - 1, y) && !GLOC_SAME_AREA(x, y - 1)
490         && !GLOC_SAME_AREA(x + 1, y) && !GLOC_SAME_AREA(x, y + 1))
491         return FALSE;
492
493     switch (gloc) {
494     default:
495     case GLOC_MONS:
496         /* unlike '/M', this skips monsters revealed by
497            warning glyphs and remembered unseen ones */
498         return (glyph_is_monster(glyph)
499                 && glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
500     case GLOC_OBJS:
501         return (glyph_is_object(glyph)
502                 && glyph != objnum_to_glyph(BOULDER)
503                 && glyph != objnum_to_glyph(ROCK));
504     case GLOC_DOOR:
505         return (glyph_is_cmap(glyph)
506                 && (is_cmap_door(glyph_to_cmap(glyph))
507                     || is_cmap_drawbridge(glyph_to_cmap(glyph))
508                     || glyph_to_cmap(glyph) == S_ndoor));
509     case GLOC_EXPLORE:
510         return (glyph_is_cmap(glyph)
511                 && (is_cmap_door(glyph_to_cmap(glyph))
512                     || is_cmap_drawbridge(glyph_to_cmap(glyph))
513                     || glyph_to_cmap(glyph) == S_ndoor
514                     || glyph_to_cmap(glyph) == S_room
515                     || glyph_to_cmap(glyph) == S_darkroom
516                     || glyph_to_cmap(glyph) == S_corr
517                     || glyph_to_cmap(glyph) == S_litcorr)
518                 && (IS_UNEXPLORED_LOC(x + 1, y)
519                     || IS_UNEXPLORED_LOC(x - 1, y)
520                     || IS_UNEXPLORED_LOC(x, y + 1)
521                     || IS_UNEXPLORED_LOC(x, y - 1)));
522     case GLOC_INTERESTING:
523         return gather_locs_interesting(x,y, GLOC_DOOR)
524             || !(glyph_is_cmap(glyph)
525                  && (is_cmap_wall(glyph_to_cmap(glyph))
526                      || glyph_to_cmap(glyph) == S_tree
527                      || glyph_to_cmap(glyph) == S_bars
528                      || glyph_to_cmap(glyph) == S_ice
529                      || glyph_to_cmap(glyph) == S_air
530                      || glyph_to_cmap(glyph) == S_cloud
531                      || glyph_to_cmap(glyph) == S_lava
532                      || glyph_to_cmap(glyph) == S_water
533                      || glyph_to_cmap(glyph) == S_pool
534                      || glyph_to_cmap(glyph) == S_ndoor
535                      || glyph_to_cmap(glyph) == S_room
536                      || glyph_to_cmap(glyph) == S_darkroom
537                      || glyph_to_cmap(glyph) == S_corr
538                      || glyph_to_cmap(glyph) == S_litcorr));
539     case GLOC_VALID:
540         return (getpos_getvalid && getpos_getvalid(x,y));
541     }
542     /*NOTREACHED*/
543     return FALSE;
544 }
545
546 /* gather locations for monsters or objects shown on the map */
547 STATIC_OVL void
548 gather_locs(arr_p, cnt_p, gloc)
549 coord **arr_p;
550 int *cnt_p;
551 int gloc;
552 {
553     int x, y, pass, idx;
554
555     /*
556      * We always include the hero's location even if there is no monster
557      * (invisible hero without see invisible) or object (usual case)
558      * displayed there.  That way, the count will always be at least 1,
559      * and player has a visual indicator (cursor returns to hero's spot)
560      * highlighting when successive 'm's or 'o's have cycled all the way
561      * through all monsters or objects.
562      *
563      * Hero's spot will always sort to array[0] because it will always
564      * be the shortest distance (namely, 0 units) away from <u.ux,u.uy>.
565      */
566
567     gloc_filter_init();
568
569     *cnt_p = idx = 0;
570     for (pass = 0; pass < 2; pass++) {
571         for (x = 1; x < COLNO; x++)
572             for (y = 0; y < ROWNO; y++) {
573                 if ((x == u.ux && y == u.uy)
574                     || gather_locs_interesting(x, y, gloc)) {
575                     if (!pass) {
576                         ++*cnt_p;
577                     } else {
578                         (*arr_p)[idx].x = x;
579                         (*arr_p)[idx].y = y;
580                         ++idx;
581                     }
582                 }
583             }
584
585         if (!pass) /* end of first pass */
586             *arr_p = (coord *) alloc(*cnt_p * sizeof (coord));
587         else /* end of second pass */
588             qsort(*arr_p, *cnt_p, sizeof (coord), cmp_coord_distu);
589     } /* pass */
590
591     gloc_filter_done();
592 }
593
594 char *
595 dxdy_to_dist_descr(dx, dy, fulldir)
596 int dx, dy;
597 boolean fulldir;
598 {
599     static char buf[30];
600     int dst;
601
602     if (!dx && !dy) {
603 /*JP
604         Sprintf(buf, "here");
605 */
606         Sprintf(buf, "\82±\82±");
607     } else if ((dst = xytod(dx, dy)) != -1) {
608         /* explicit direction; 'one step' is implicit */
609         Sprintf(buf, "%s", directionname(dst));
610     } else {
611         const char *dirnames[4][2] = {
612 #if 0 /*JP*/
613             { "n", "north" },
614             { "s", "south" },
615             { "w", "west" },
616             { "e", "east" } };
617 #else
618             { "n", "\96k" },
619             { "s", "\93ì" },
620             { "w", "\90¼" },
621             { "e", "\93\8c" } };
622 #endif
623         buf[0] = '\0';
624         /* 9999: protect buf[] against overflow caused by invalid values */
625         if (dy) {
626             if (abs(dy) > 9999)
627                 dy = sgn(dy) * 9999;
628             Sprintf(eos(buf), "%d%s%s", abs(dy), dirnames[(dy > 0)][fulldir],
629                     dx ? "," : "");
630         }
631         if (dx) {
632             if (abs(dx) > 9999)
633                 dx = sgn(dx) * 9999;
634             Sprintf(eos(buf), "%d%s", abs(dx),
635                     dirnames[2 + (dx > 0)][fulldir]);
636         }
637     }
638     return buf;
639 }
640
641 /* coordinate formatting for 'whatis_coord' option */
642 char *
643 coord_desc(x, y, outbuf, cmode)
644 int x, y;
645 char *outbuf, cmode;
646 {
647     static char screen_fmt[16]; /* [12] suffices: "[%02d,%02d]" */
648     int dx, dy;
649
650     outbuf[0] = '\0';
651     switch (cmode) {
652     default:
653         break;
654     case GPCOORDS_COMFULL:
655     case GPCOORDS_COMPASS:
656         /* "east", "3s", "2n,4w" */
657         dx = x - u.ux;
658         dy = y - u.uy;
659         Sprintf(outbuf, "(%s)",
660                 dxdy_to_dist_descr(dx, dy, cmode == GPCOORDS_COMFULL));
661         break;
662     case GPCOORDS_MAP: /* x,y */
663         /* upper left corner of map is <1,0>;
664            with default COLNO,ROWNO lower right corner is <79,20> */
665         Sprintf(outbuf, "<%d,%d>", x, y);
666         break;
667     case GPCOORDS_SCREEN: /* y+2,x */
668         /* for normal map sizes, force a fixed-width formatting so that
669            /m, /M, /o, and /O output lines up cleanly; map sizes bigger
670            than Nx999 or 999xM will still work, but not line up like normal
671            when displayed in a column setting */
672         if (!*screen_fmt)
673             Sprintf(screen_fmt, "[%%%sd,%%%sd]",
674                     (ROWNO - 1 + 2 < 100) ? "02" :  "03",
675                     (COLNO - 1 < 100) ? "02" : "03");
676         /* map line 0 is screen row 2;
677            map column 0 isn't used, map column 1 is screen column 1 */
678         Sprintf(outbuf, screen_fmt, y + 2, x);
679         break;
680     }
681     return outbuf;
682 }
683
684 STATIC_OVL void
685 auto_describe(cx, cy)
686 int cx, cy;
687 {
688     coord cc;
689     int sym = 0;
690     char tmpbuf[BUFSZ];
691 /*JP
692     const char *firstmatch = "unknown";
693 */
694     const char *firstmatch = "\95s\96¾";
695
696     cc.x = cx;
697     cc.y = cy;
698     if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) {
699         (void) coord_desc(cx, cy, tmpbuf, iflags.getpos_coords);
700 #if 0 /*JP*/
701         custompline(SUPPRESS_HISTORY,
702                     "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
703                     (iflags.autodescribe
704                      && getpos_getvalid && !getpos_getvalid(cx, cy))
705                       ? " (illegal)" : "",
706                     (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
707                       ? " (no travel path)" : "");
708 #else
709         custompline(SUPPRESS_HISTORY,
710                     "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
711                     (iflags.autodescribe
712                      && getpos_getvalid && !getpos_getvalid(cx, cy))
713                       ? " (\95s\90³)" : "",
714                     (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
715                       ? " (\8co\98H\82È\82µ)" : "");
716 #endif
717         curs(WIN_MAP, cx, cy);
718         flush_screen(0);
719     }
720 }
721
722 boolean
723 getpos_menu(ccp, gloc)
724 coord *ccp;
725 int gloc;
726 {
727     coord *garr = DUMMY;
728     int gcount = 0;
729     winid tmpwin;
730     anything any;
731     int i, pick_cnt;
732     menu_item *picks = (menu_item *) 0;
733     char tmpbuf[BUFSZ];
734
735     gather_locs(&garr, &gcount, gloc);
736
737     if (gcount < 2) { /* gcount always includes the hero */
738         free((genericptr_t) garr);
739 #if 0 /*JP*/
740         You("cannot %s %s.",
741             iflags.getloc_filter == GFILTER_VIEW ? "see" : "detect",
742             gloc_descr[gloc][0]);
743 #else
744         You("%s\82ð%s\82±\82Æ\82ª\82Å\82«\82È\82¢\81D",
745             gloc_descr[gloc][0],
746             iflags.getloc_filter == GFILTER_VIEW ? "\8c©\82é" : "\8c©\82Â\82¯\82é");
747 #endif
748         return FALSE;
749     }
750
751     tmpwin = create_nhwindow(NHW_MENU);
752     start_menu(tmpwin);
753     any = zeroany;
754
755     /* gather_locs returns array[0] == you. skip it. */
756     for (i = 1; i < gcount; i++) {
757         char fullbuf[BUFSZ];
758         coord tmpcc;
759 /*JP
760         const char *firstmatch = "unknown";
761 */
762         const char *firstmatch = "\95s\96¾";
763         int sym = 0;
764         any.a_int = i + 1;
765         tmpcc.x = garr[i].x;
766         tmpcc.y = garr[i].y;
767         if (do_screen_description(tmpcc, TRUE, sym, tmpbuf, &firstmatch)) {
768             (void) coord_desc(garr[i].x, garr[i].y, tmpbuf,
769                               iflags.getpos_coords);
770             Sprintf(fullbuf, "%s%s%s", firstmatch,
771                     (*tmpbuf ? " " : ""), tmpbuf);
772             add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, fullbuf,
773                      MENU_UNSELECTED);
774         }
775     }
776
777 #if 0 /*JP*/
778     Sprintf(tmpbuf, "Pick a target %s%s%s",
779             gloc_descr[gloc][1],
780             gloc_filtertxt[iflags.getloc_filter],
781             iflags.getloc_travelmode ? " for travel" : "");
782 #else
783     Sprintf(tmpbuf, "%s%s\82Å\96Ú\95W\82Æ\82·\82é%s\82ð\91I\91ð\82µ\82Ä\82­\82¾\82³\82¢",
784             iflags.getloc_travelmode ? "\88Ú\93®\82Ì\82½\82ß\82É" : "",
785             gloc_filtertxt[iflags.getloc_filter],
786             gloc_descr[gloc][1]);
787 #endif
788     end_menu(tmpwin, tmpbuf);
789     pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
790     destroy_nhwindow(tmpwin);
791     if (pick_cnt > 0) {
792         ccp->x = garr[picks->item.a_int - 1].x;
793         ccp->y = garr[picks->item.a_int - 1].y;
794         free((genericptr_t) picks);
795     }
796     free((genericptr_t) garr);
797     return (pick_cnt > 0);
798 }
799
800 int
801 getpos(ccp, force, goal)
802 coord *ccp;
803 boolean force;
804 const char *goal;
805 {
806     const char *cp;
807     struct {
808         int nhkf, ret;
809     } const pick_chars_def[] = {
810         { NHKF_GETPOS_PICK, LOOK_TRADITIONAL },
811         { NHKF_GETPOS_PICK_Q, LOOK_QUICK },
812         { NHKF_GETPOS_PICK_O, LOOK_ONCE },
813         { NHKF_GETPOS_PICK_V, LOOK_VERBOSE }
814     };
815     const int mMoOdDxX_def[] = {
816         NHKF_GETPOS_MON_NEXT,
817         NHKF_GETPOS_MON_PREV,
818         NHKF_GETPOS_OBJ_NEXT,
819         NHKF_GETPOS_OBJ_PREV,
820         NHKF_GETPOS_DOOR_NEXT,
821         NHKF_GETPOS_DOOR_PREV,
822         NHKF_GETPOS_UNEX_NEXT,
823         NHKF_GETPOS_UNEX_PREV,
824         NHKF_GETPOS_INTERESTING_NEXT,
825         NHKF_GETPOS_INTERESTING_PREV,
826         NHKF_GETPOS_VALID_NEXT,
827         NHKF_GETPOS_VALID_PREV
828     };
829     char pick_chars[6];
830     char mMoOdDxX[13];
831     int result = 0;
832     int cx, cy, i, c;
833     int sidx, tx, ty;
834     boolean msg_given = TRUE; /* clear message window by default */
835     boolean show_goal_msg = FALSE;
836     boolean hilite_state = FALSE;
837     coord *garr[NUM_GLOCS] = DUMMY;
838     int gcount[NUM_GLOCS] = DUMMY;
839     int gidx[NUM_GLOCS] = DUMMY;
840
841     for (i = 0; i < SIZE(pick_chars_def); i++)
842         pick_chars[i] = Cmd.spkeys[pick_chars_def[i].nhkf];
843     pick_chars[SIZE(pick_chars_def)] = '\0';
844
845     for (i = 0; i < SIZE(mMoOdDxX_def); i++)
846         mMoOdDxX[i] = Cmd.spkeys[mMoOdDxX_def[i]];
847     mMoOdDxX[SIZE(mMoOdDxX_def)] = '\0';
848
849     if (!goal)
850 /*JP
851         goal = "desired location";
852 */
853         goal = "\96Ú\93I\92n";
854     if (flags.verbose) {
855 #if 0 /*JP*/
856         pline("(For instructions type a '%s')",
857               visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
858 #else
859         pline("('%s'\82Å\83w\83\8b\83v)",
860               visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
861 #endif
862         msg_given = TRUE;
863     }
864     cx = ccp->x;
865     cy = ccp->y;
866 #ifdef CLIPPING
867     cliparound(cx, cy);
868 #endif
869     curs(WIN_MAP, cx, cy);
870     flush_screen(0);
871 #ifdef MAC
872     lock_mouse_cursor(TRUE);
873 #endif
874     for (;;) {
875         if (show_goal_msg) {
876 /*JP
877             pline("Move cursor to %s:", goal);
878 */
879             pline("\83J\81[\83\\83\8b\82ð%s\82É\93®\82©\82µ\82Ä\82­\82¾\82³\82¢:", goal);
880             curs(WIN_MAP, cx, cy);
881             flush_screen(0);
882             show_goal_msg = FALSE;
883         } else if (iflags.autodescribe && !msg_given && !hilite_state) {
884             auto_describe(cx, cy);
885         }
886
887         c = nh_poskey(&tx, &ty, &sidx);
888
889         if (hilite_state) {
890             (*getpos_hilitefunc)(2);
891             hilite_state = FALSE;
892             curs(WIN_MAP, cx, cy);
893             flush_screen(0);
894         }
895
896         if (iflags.autodescribe)
897             msg_given = FALSE;
898
899         if (c == Cmd.spkeys[NHKF_ESC]) {
900             cx = cy = -10;
901             msg_given = TRUE; /* force clear */
902             result = -1;
903             break;
904         }
905         if (c == 0) {
906             if (!isok(tx, ty))
907                 continue;
908             /* a mouse click event, just assign and return */
909             cx = tx;
910             cy = ty;
911             break;
912         }
913         if ((cp = index(pick_chars, c)) != 0) {
914             /* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */
915             result = pick_chars_def[(int) (cp - pick_chars)].ret;
916             break;
917         }
918         for (i = 0; i < 8; i++) {
919             int dx, dy;
920
921             if (Cmd.dirchars[i] == c) {
922                 /* a normal movement letter or digit */
923                 dx = xdir[i];
924                 dy = ydir[i];
925             } else if (Cmd.alphadirchars[i] == lowc((char) c)
926                        || (Cmd.num_pad && Cmd.dirchars[i] == (c & 0177))) {
927                 /* a shifted movement letter or Meta-digit */
928                 if (iflags.getloc_moveskip) {
929                     /* skip same glyphs */
930                     int glyph = glyph_at(cx, cy);
931
932                     dx = xdir[i];
933                     dy = ydir[i];
934                     while (isok(cx + dx, cy + dy)
935                            && glyph == glyph_at(cx + dx, cy + dy)
936                            && isok(cx + dx + xdir[i], cy + dy + ydir[i])
937                            && glyph == glyph_at(cx + dx + xdir[i],
938                                                 cy + dy + ydir[i])) {
939                         dx += xdir[i];
940                         dy += ydir[i];
941                     }
942                 } else {
943                     dx = 8 * xdir[i];
944                     dy = 8 * ydir[i];
945                 }
946             } else
947                 continue;
948
949             /* truncate at map edge; diagonal moves complicate this... */
950             if (cx + dx < 1) {
951                 dy -= sgn(dy) * (1 - (cx + dx));
952                 dx = 1 - cx; /* so that (cx+dx == 1) */
953             } else if (cx + dx > COLNO - 1) {
954                 dy += sgn(dy) * ((COLNO - 1) - (cx + dx));
955                 dx = (COLNO - 1) - cx;
956             }
957             if (cy + dy < 0) {
958                 dx -= sgn(dx) * (0 - (cy + dy));
959                 dy = 0 - cy; /* so that (cy+dy == 0) */
960             } else if (cy + dy > ROWNO - 1) {
961                 dx += sgn(dx) * ((ROWNO - 1) - (cy + dy));
962                 dy = (ROWNO - 1) - cy;
963             }
964             cx += dx;
965             cy += dy;
966             goto nxtc;
967         }
968
969         if (c == Cmd.spkeys[NHKF_GETPOS_HELP] || redraw_cmd(c)) {
970             if (c == Cmd.spkeys[NHKF_GETPOS_HELP])
971                 getpos_help(force, goal);
972             else /* ^R */
973                 docrt(); /* redraw */
974             /* update message window to reflect that we're still targetting */
975             show_goal_msg = TRUE;
976             msg_given = TRUE;
977         } else if (c == Cmd.spkeys[NHKF_GETPOS_SHOWVALID]
978                    && getpos_hilitefunc) {
979             if (!hilite_state) {
980                 (*getpos_hilitefunc)(0);
981                 (*getpos_hilitefunc)(1);
982                 hilite_state = TRUE;
983             }
984             goto nxtc;
985         } else if (c == Cmd.spkeys[NHKF_GETPOS_AUTODESC]) {
986             iflags.autodescribe = !iflags.autodescribe;
987 #if 0 /*JP:T*/
988             pline("Automatic description %sis %s.",
989                   flags.verbose ? "of features under cursor " : "",
990                   iflags.autodescribe ? "on" : "off");
991 #else
992             pline("%s\90à\96¾\8e©\93®\95\\8e¦\81F%s",
993                   flags.verbose ? "\83J\81[\83\\83\8b\82Ì\89º\82É\82 \82é\82à\82Ì\82Ì" : "",
994                   iflags.autodescribe ? "\83I\83\93" : "\83I\83t");
995 #endif
996             if (!iflags.autodescribe)
997                 show_goal_msg = TRUE;
998             msg_given = TRUE;
999             goto nxtc;
1000         } else if (c == Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]) {
1001             const char *const view_filters[NUM_GFILTER] = {
1002 #if 0 /*JP*/
1003                 "Not limiting targets",
1004                 "Limiting targets to in sight",
1005                 "Limiting targets to in same area"
1006 #else
1007                 "\83^\81[\83Q\83b\83g\82ð\90§\8cÀ\82µ\82È\82¢",
1008                 "\8e\8b\8aE\93à\82É\83^\81[\83Q\83b\83g\82ð\90§\8cÀ\82·\82é",
1009                 "\93¯\82\83G\83\8a\83A\82É\83^\81[\83Q\83b\83g\82ð\90§\8cÀ\82·\82é"
1010 #endif
1011             };
1012             iflags.getloc_filter = (iflags.getloc_filter + 1) % NUM_GFILTER;
1013             for (i = 0; i < NUM_GLOCS; i++) {
1014                 if (garr[i]) {
1015                     free((genericptr_t) garr[i]);
1016                     garr[i] = NULL;
1017                 }
1018                 gidx[i] = gcount[i] = 0;
1019             }
1020 /*JP
1021             pline("%s.", view_filters[iflags.getloc_filter]);
1022 */
1023             pline("%s\81D", view_filters[iflags.getloc_filter]);
1024             msg_given = TRUE;
1025             goto nxtc;
1026         } else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]) {
1027             iflags.getloc_usemenu = !iflags.getloc_usemenu;
1028 #if 0 /*JP*/
1029             pline("%s a menu to show possible targets.",
1030                   iflags.getloc_usemenu ? "Using" : "Not using");
1031 #else
1032             pline("\89Â\94\\82È\83^\81[\83Q\83b\83g\82ð\8c©\82é\82Ì\82É\83\81\83j\83\85\81[\82ð\8eg%s\81D",
1033                   iflags.getloc_usemenu ? "\82¤" : "\82í\82È\82¢");
1034 #endif
1035             msg_given = TRUE;
1036             goto nxtc;
1037         } else if (c == Cmd.spkeys[NHKF_GETPOS_SELF]) {
1038             /* reset 'm&M', 'o&O', &c; otherwise, there's no way for player
1039                to achieve that except by manually cycling through all spots */
1040             for (i = 0; i < NUM_GLOCS; i++)
1041                 gidx[i] = 0;
1042             cx = u.ux;
1043             cy = u.uy;
1044             goto nxtc;
1045         } else if (c == Cmd.spkeys[NHKF_GETPOS_MOVESKIP]) {
1046             iflags.getloc_moveskip = !iflags.getloc_moveskip;
1047 #if 0 /*JP*/
1048             pline("%skipping over similar terrain when fastmoving the cursor.",
1049                   iflags.getloc_moveskip ? "S" : "Not s");
1050 #else
1051             pline("\83J\81[\83\\83\8b\82ð\8d\82\91¬\88Ú\93®\82³\82¹\82é\82Æ\82«\82É\8e\97\82½\82æ\82¤\82È\92n\8c`\82ð\94ò\82Î%s\81D",
1052                   iflags.getloc_moveskip ? "\82·" : "\82³\82È\82¢");
1053 #endif
1054         } else if ((cp = index(mMoOdDxX, c)) != 0) { /* 'm|M', 'o|O', &c */
1055             /* nearest or farthest monster or object or door or unexplored */
1056             int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
1057                 gloc = gtmp >> 1;             /* 0..3 */
1058
1059             if (iflags.getloc_usemenu) {
1060                 coord tmpcrd;
1061                 if (getpos_menu(&tmpcrd, gloc)) {
1062                     cx = tmpcrd.x;
1063                     cy = tmpcrd.y;
1064                 }
1065                 goto nxtc;
1066             }
1067
1068             if (!garr[gloc]) {
1069                 gather_locs(&garr[gloc], &gcount[gloc], gloc);
1070                 gidx[gloc] = 0; /* garr[][0] is hero's spot */
1071             }
1072             if (!(gtmp & 1)) {  /* c=='m' || c=='o' || c=='d' || c=='x') */
1073                 gidx[gloc] = (gidx[gloc] + 1) % gcount[gloc];
1074             } else {            /* c=='M' || c=='O' || c=='D' || c=='X') */
1075                 if (--gidx[gloc] < 0)
1076                     gidx[gloc] = gcount[gloc] - 1;
1077             }
1078             cx = garr[gloc][gidx[gloc]].x;
1079             cy = garr[gloc][gidx[gloc]].y;
1080             goto nxtc;
1081         } else {
1082             if (!index(quitchars, c)) {
1083                 char matching[MAXPCHARS];
1084                 int pass, lo_x, lo_y, hi_x, hi_y, k = 0;
1085
1086                 (void) memset((genericptr_t) matching, 0, sizeof matching);
1087                 for (sidx = 1; sidx < MAXPCHARS; sidx++) { /* [0] left as 0 */
1088                     if (IS_DOOR(sidx) || IS_WALL(sidx)
1089                         || sidx == SDOOR || sidx == SCORR
1090                         || glyph_to_cmap(k) == S_room
1091                         || glyph_to_cmap(k) == S_darkroom
1092                         || glyph_to_cmap(k) == S_corr
1093                         || glyph_to_cmap(k) == S_litcorr)
1094                         continue;
1095                     if (c == defsyms[sidx].sym || c == (int) showsyms[sidx])
1096                         matching[sidx] = (char) ++k;
1097                 }
1098                 if (k) {
1099                     for (pass = 0; pass <= 1; pass++) {
1100                         /* pass 0: just past current pos to lower right;
1101                            pass 1: upper left corner to current pos */
1102                         lo_y = (pass == 0) ? cy : 0;
1103                         hi_y = (pass == 0) ? ROWNO - 1 : cy;
1104                         for (ty = lo_y; ty <= hi_y; ty++) {
1105                             lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
1106                             hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
1107                             for (tx = lo_x; tx <= hi_x; tx++) {
1108                                 /* first, look at what is currently visible
1109                                    (might be monster) */
1110                                 k = glyph_at(tx, ty);
1111                                 if (glyph_is_cmap(k)
1112                                     && matching[glyph_to_cmap(k)])
1113                                     goto foundc;
1114                                 /* next, try glyph that's remembered here
1115                                    (might be trap or object) */
1116                                 if (level.flags.hero_memory
1117                                     /* !terrainmode: don't move to remembered
1118                                        trap or object if not currently shown */
1119                                     && !iflags.terrainmode) {
1120                                     k = levl[tx][ty].glyph;
1121                                     if (glyph_is_cmap(k)
1122                                         && matching[glyph_to_cmap(k)])
1123                                         goto foundc;
1124                                 }
1125                                 /* last, try actual terrain here (shouldn't
1126                                    we be using lastseentyp[][] instead?) */
1127                                 if (levl[tx][ty].seenv) {
1128                                     k = back_to_glyph(tx, ty);
1129                                     if (glyph_is_cmap(k)
1130                                         && matching[glyph_to_cmap(k)])
1131                                         goto foundc;
1132                                 }
1133                                 continue;
1134                             foundc:
1135                                 cx = tx, cy = ty;
1136                                 if (msg_given) {
1137                                     clear_nhwindow(WIN_MESSAGE);
1138                                     msg_given = FALSE;
1139                                 }
1140                                 goto nxtc;
1141                             } /* column */
1142                         }     /* row */
1143                     }         /* pass */
1144 /*JP
1145                     pline("Can't find dungeon feature '%c'.", c);
1146 */
1147                     pline("'%c'\81H", c);
1148                     msg_given = TRUE;
1149                     goto nxtc;
1150                 } else {
1151                     char note[QBUFSZ];
1152
1153                     if (!force)
1154 /*JP
1155                         Strcpy(note, "aborted");
1156 */
1157                         Strcpy(note, "\92\86\92f\82µ\82½");
1158                     else /* hjkl */
1159 #if 0 /*JP*/
1160                         Sprintf(note, "use '%c', '%c', '%c', '%c' or '%s'",
1161                                 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
1162                                 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
1163 #else
1164                         Sprintf(note, "%c%c%c%c\82Å\88Ú\93®\81C%s\82Å\8fI\97¹",
1165                                 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
1166                                 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
1167 #endif
1168 /*JP
1169                     pline("Unknown direction: '%s' (%s).", visctrl((char) c),
1170 */
1171                     pline("\82»\82Ì\95û\8cü\82Í\82È\82¢\81F'%s' (%s)", visctrl((char) c),
1172                           note);
1173                     msg_given = TRUE;
1174                 } /* k => matching */
1175             }     /* !quitchars */
1176             if (force)
1177                 goto nxtc;
1178 /*JP
1179             pline("Done.");
1180 */
1181             pline("\88È\8fã\81D");
1182             msg_given = FALSE; /* suppress clear */
1183             cx = -1;
1184             cy = 0;
1185             result = 0; /* not -1 */
1186             break;
1187         }
1188     nxtc:
1189         ;
1190 #ifdef CLIPPING
1191         cliparound(cx, cy);
1192 #endif
1193         curs(WIN_MAP, cx, cy);
1194         flush_screen(0);
1195     }
1196 #ifdef MAC
1197     lock_mouse_cursor(FALSE);
1198 #endif
1199     if (msg_given)
1200         clear_nhwindow(WIN_MESSAGE);
1201     ccp->x = cx;
1202     ccp->y = cy;
1203     for (i = 0; i < NUM_GLOCS; i++)
1204         if (garr[i])
1205             free((genericptr_t) garr[i]);
1206     getpos_hilitefunc = (void FDECL((*), (int))) 0;
1207     getpos_getvalid = (boolean FDECL((*), (int, int))) 0;
1208     return result;
1209 }
1210
1211 /* allocate space for a monster's name; removes old name if there is one */
1212 void
1213 new_mname(mon, lth)
1214 struct monst *mon;
1215 int lth; /* desired length (caller handles adding 1 for terminator) */
1216 {
1217     if (lth) {
1218         /* allocate mextra if necessary; otherwise get rid of old name */
1219         if (!mon->mextra)
1220             mon->mextra = newmextra();
1221         else
1222             free_mname(mon); /* already has mextra, might also have name */
1223         MNAME(mon) = (char *) alloc((unsigned) lth);
1224     } else {
1225         /* zero length: the new name is empty; get rid of the old name */
1226         if (has_mname(mon))
1227             free_mname(mon);
1228     }
1229 }
1230
1231 /* release a monster's name; retains mextra even if all fields are now null */
1232 void
1233 free_mname(mon)
1234 struct monst *mon;
1235 {
1236     if (has_mname(mon)) {
1237         free((genericptr_t) MNAME(mon));
1238         MNAME(mon) = (char *) 0;
1239     }
1240 }
1241
1242 /* allocate space for an object's name; removes old name if there is one */
1243 void
1244 new_oname(obj, lth)
1245 struct obj *obj;
1246 int lth; /* desired length (caller handles adding 1 for terminator) */
1247 {
1248     if (lth) {
1249         /* allocate oextra if necessary; otherwise get rid of old name */
1250         if (!obj->oextra)
1251             obj->oextra = newoextra();
1252         else
1253             free_oname(obj); /* already has oextra, might also have name */
1254         ONAME(obj) = (char *) alloc((unsigned) lth);
1255     } else {
1256         /* zero length: the new name is empty; get rid of the old name */
1257         if (has_oname(obj))
1258             free_oname(obj);
1259     }
1260 }
1261
1262 /* release an object's name; retains oextra even if all fields are now null */
1263 void
1264 free_oname(obj)
1265 struct obj *obj;
1266 {
1267     if (has_oname(obj)) {
1268         free((genericptr_t) ONAME(obj));
1269         ONAME(obj) = (char *) 0;
1270     }
1271 }
1272
1273 /*  safe_oname() always returns a valid pointer to
1274  *  a string, either the pointer to an object's name
1275  *  if it has one, or a pointer to an empty string
1276  *  if it doesn't.
1277  */
1278 const char *
1279 safe_oname(obj)
1280 struct obj *obj;
1281 {
1282     if (has_oname(obj))
1283         return ONAME(obj);
1284     return "";
1285 }
1286
1287 /* historical note: this returns a monster pointer because it used to
1288    allocate a new bigger block of memory to hold the monster and its name */
1289 struct monst *
1290 christen_monst(mtmp, name)
1291 struct monst *mtmp;
1292 const char *name;
1293 {
1294     int lth;
1295     char buf[PL_PSIZ];
1296
1297     /* dogname & catname are PL_PSIZ arrays; object names have same limit */
1298     lth = (name && *name) ? ((int) strlen(name) + 1) : 0;
1299     if (lth > PL_PSIZ) {
1300 #if 1 /*JP*/
1301         if (is_kanji2(buf, lth - 1))
1302             --lth;
1303 #endif
1304         lth = PL_PSIZ;
1305         name = strncpy(buf, name, PL_PSIZ - 1);
1306         buf[PL_PSIZ - 1] = '\0';
1307     }
1308     new_mname(mtmp, lth); /* removes old name if one is present */
1309     if (lth)
1310         Strcpy(MNAME(mtmp), name);
1311     return mtmp;
1312 }
1313
1314 /* check whether user-supplied name matches or nearly matches an unnameable
1315    monster's name; if so, give an alternate reject message for do_mname() */
1316 STATIC_OVL boolean
1317 alreadynamed(mtmp, monnambuf, usrbuf)
1318 struct monst *mtmp;
1319 char *monnambuf, *usrbuf;
1320 {
1321     char pronounbuf[10], *p;
1322
1323     if (fuzzymatch(usrbuf, monnambuf, " -_", TRUE)
1324         /* catch trying to name "the Oracle" as "Oracle" */
1325         || (!strncmpi(monnambuf, "the ", 4)
1326             && fuzzymatch(usrbuf, monnambuf + 4, " -_", TRUE))
1327         /* catch trying to name "invisible Orcus" as "Orcus" */
1328         || ((p = strstri(monnambuf, "invisible ")) != 0
1329             && fuzzymatch(usrbuf, p + 10, " -_", TRUE))
1330         /* catch trying to name "the {priest,Angel} of Crom" as "Crom" */
1331         || ((p = strstri(monnambuf, " of ")) != 0
1332             && fuzzymatch(usrbuf, p + 4, " -_", TRUE))) {
1333 #if 0 /*JP*/
1334         pline("%s is already called %s.",
1335               upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
1336 #else
1337         pline("%s\82Í\8aù\82É%s\82Æ\8cÄ\82Î\82ê\82Ä\82¢\82é\81D",
1338               upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
1339 #endif
1340         return TRUE;
1341 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\8eg\82í\82È\82¢*/
1342     } else if (mtmp->data == &mons[PM_JUIBLEX]
1343                && strstri(monnambuf, "Juiblex")
1344                && !strcmpi(usrbuf, "Jubilex")) {
1345         pline("%s doesn't like being called %s.", upstart(monnambuf), usrbuf);
1346         return TRUE;
1347 #endif
1348     }
1349     return FALSE;
1350 }
1351
1352 /* allow player to assign a name to some chosen monster */
1353 STATIC_OVL void
1354 do_mname()
1355 {
1356     char buf[BUFSZ] = DUMMY, monnambuf[BUFSZ], qbuf[QBUFSZ];
1357     coord cc;
1358     int cx, cy;
1359     struct monst *mtmp = 0;
1360
1361     if (Hallucination) {
1362 /*JP
1363         You("would never recognize it anyway.");
1364 */
1365         You("\82»\82ê\82ð\94F\8e¯\82Å\82«\82È\82¢\81D");
1366         return;
1367     }
1368     cc.x = u.ux;
1369     cc.y = u.uy;
1370 /*JP
1371     if (getpos(&cc, FALSE, "the monster you want to name") < 0
1372 */
1373     if (getpos(&cc, FALSE, "\82 \82È\82½\82ª\96¼\82Ã\82¯\82½\82¢\89ö\95¨") < 0
1374         || (cx = cc.x) < 0)
1375         return;
1376     cy = cc.y;
1377
1378     if (cx == u.ux && cy == u.uy) {
1379         if (u.usteed && canspotmon(u.usteed)) {
1380             mtmp = u.usteed;
1381         } else {
1382 /*JP
1383             pline("This %s creature is called %s and cannot be renamed.",
1384 */
1385             pline("\82±\82Ì%s\90\82«\95¨\82Í%s\82Æ\8cÄ\82Î\82ê\82Ä\82¢\82Ä\81C\96¼\91O\82Í\95Ï\8dX\82Å\82«\82È\82¢\81D",
1386                   beautiful(), plname);
1387             return;
1388         }
1389     } else
1390         mtmp = m_at(cx, cy);
1391
1392     if (!mtmp
1393         || (!sensemon(mtmp)
1394             && (!(cansee(cx, cy) || see_with_infrared(mtmp))
1395                 || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE
1396                 || mtmp->m_ap_type == M_AP_OBJECT
1397                 || (mtmp->minvis && !See_invisible)))) {
1398 /*JP
1399         pline("I see no monster there.");
1400 */
1401         pline("\82»\82±\82É\89ö\95¨\82Í\82¢\82È\82¢\81D");
1402         return;
1403     }
1404     /* special case similar to the one in lookat() */
1405 /*JP
1406     Sprintf(qbuf, "What do you want to call %s?",
1407 */
1408     Sprintf(qbuf, "%s\82ð\89½\82Æ\8cÄ\82Ñ\82Ü\82·\82©\81H",
1409             distant_monnam(mtmp, ARTICLE_THE, monnambuf));
1410     getlin(qbuf, buf);
1411     if (!*buf || *buf == '\033')
1412         return;
1413     /* strip leading and trailing spaces; unnames monster if all spaces */
1414     (void) mungspaces(buf);
1415
1416     /* Unique monsters have their own specific names or titles.
1417      * Shopkeepers, temple priests and other minions use alternate
1418      * name formatting routines which ignore any user-supplied name.
1419      *
1420      * Don't say the name is being rejected if it happens to match
1421      * the existing name.
1422      */
1423     if ((mtmp->data->geno & G_UNIQ) && !mtmp->ispriest) {
1424         if (!alreadynamed(mtmp, monnambuf, buf))
1425 /*JP
1426         pline("%s doesn't like being called names!", upstart(monnambuf));
1427 */
1428         pline("%s\82Í\82 \82¾\96¼\82Å\8cÄ\82Î\82ê\82é\82Ì\82ª\8c\99\82¢\82È\82æ\82¤\82¾\81I", Monnam(mtmp));
1429     } else if (mtmp->isshk
1430                && !(Deaf || mtmp->msleeping || !mtmp->mcanmove
1431                     || mtmp->data->msound <= MS_ANIMAL)) {
1432         if (!alreadynamed(mtmp, monnambuf, buf))
1433 /*JP
1434         verbalize("I'm %s, not %s.", shkname(mtmp), buf);
1435 */
1436         verbalize("\8e\84\82Í%s\82¾\81C%s\82Å\82Í\82È\82¢\81D", shkname(mtmp), buf);
1437     } else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk) {
1438         if (!alreadynamed(mtmp, monnambuf, buf))
1439 /*JP
1440         pline("%s will not accept the name %s.", upstart(monnambuf), buf);
1441 */
1442         pline("%s\82Í%s\82Æ\82¢\82¤\96¼\91O\82ð\8eó\82¯\82¢\82ê\82È\82©\82Á\82½\81D", monnambuf, buf);
1443     } else
1444         (void) christen_monst(mtmp, buf);
1445 }
1446
1447 STATIC_VAR int via_naming = 0;
1448
1449 /*
1450  * This routine used to change the address of 'obj' so be unsafe if not
1451  * used with extreme care.  Applying a name to an object no longer
1452  * allocates a replacement object, so that old risk is gone.
1453  */
1454 STATIC_OVL
1455 void
1456 do_oname(obj)
1457 register struct obj *obj;
1458 {
1459     char *bufp, buf[BUFSZ] = DUMMY, bufcpy[BUFSZ], qbuf[QBUFSZ];
1460     const char *aname;
1461     short objtyp;
1462
1463     /* Do this now because there's no point in even asking for a name */
1464     if (obj->otyp == SPE_NOVEL) {
1465 /*JP
1466         pline("%s already has a published name.", Ysimple_name2(obj));
1467 */
1468         pline("%s\82É\82Í\82·\82Å\82É\8fo\94Å\8e\9e\82Ì\96¼\91O\82ª\82 \82é\81D", Ysimple_name2(obj));
1469         return;
1470     }
1471
1472 #if 0 /*JP*/
1473     Sprintf(qbuf, "What do you want to name %s ",
1474             is_plural(obj) ? "these" : "this");
1475     (void) safe_qbuf(qbuf, qbuf, "?", obj, xname, simpleonames, "item");
1476 #else
1477     (void) safe_qbuf(qbuf, "", "\82ð\89½\82Æ\96¼\82Ã\82¯\82Ü\82·\82©\81H", obj, xname, simpleonames, "item");
1478 #endif
1479     getlin(qbuf, buf);
1480     if (!*buf || *buf == '\033')
1481         return;
1482     /* strip leading and trailing spaces; unnames item if all spaces */
1483     (void) mungspaces(buf);
1484
1485     /*
1486      * We don't violate illiteracy conduct here, although it is
1487      * arguable that we should for anything other than "X".  Doing so
1488      * would make attaching player's notes to hero's inventory have an
1489      * in-game effect, which may or may not be the correct thing to do.
1490      *
1491      * We do violate illiteracy in oname() if player creates Sting or
1492      * Orcrist, clearly being literate (no pun intended...).
1493      */
1494
1495     /* relax restrictions over proper capitalization for artifacts */
1496     if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp)
1497         Strcpy(buf, aname);
1498
1499     if (obj->oartifact) {
1500 /*JP
1501         pline_The("artifact seems to resist the attempt.");
1502 */
1503         pline("\90¹\8aí\82Í\96¼\82Ã\82¯\82ð\8b\91\94Û\82µ\82Ä\82¢\82é\82æ\82¤\82¾\81D");
1504         return;
1505     } else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) {
1506         /* this used to change one letter, substituting a value
1507            of 'a' through 'y' (due to an off by one error, 'z'
1508            would never be selected) and then force that to
1509            upper case if such was the case of the input;
1510            now, the hand slip scuffs one or two letters as if
1511            the text had been trodden upon, sometimes picking
1512            punctuation instead of an arbitrary letter;
1513            unfortunately, we have to cover the possibility of
1514            it targetting spaces so failing to make any change
1515            (we know that it must eventually target a nonspace
1516            because buf[] matches a valid artifact name) */
1517         Strcpy(bufcpy, buf);
1518         /* for "the Foo of Bar", only scuff "Foo of Bar" part */
1519         bufp = !strncmpi(bufcpy, "the ", 4) ? (buf + 4) : buf;
1520         do {
1521             wipeout_text(bufp, rnd(2), (unsigned) 0);
1522         } while (!strcmp(buf, bufcpy));
1523 /*JP
1524         pline("While engraving, your %s slips.", body_part(HAND));
1525 */
1526         pline("\8d\8f\82ñ\82Å\82¢\82é\8aÔ\82É%s\82ª\8a\8a\82Á\82Ä\82µ\82Ü\82Á\82½\81D", body_part(HAND));
1527         display_nhwindow(WIN_MESSAGE, FALSE);
1528 /*JP
1529         You("engrave: \"%s\".", buf);
1530 */
1531         You("\8d\8f\82ñ\82¾: \81u%s\81v\81D",buf);
1532         /* violate illiteracy conduct since hero attempted to write
1533            a valid artifact name */
1534         u.uconduct.literate++;
1535     }
1536     ++via_naming; /* This ought to be an argument rather than a static... */
1537     obj = oname(obj, buf);
1538     --via_naming; /* ...but oname() is used in a lot of places, so defer. */
1539 }
1540
1541 struct obj *
1542 oname(obj, name)
1543 struct obj *obj;
1544 const char *name;
1545 {
1546     int lth;
1547     char buf[PL_PSIZ];
1548
1549     lth = *name ? (int) (strlen(name) + 1) : 0;
1550     if (lth > PL_PSIZ) {
1551         lth = PL_PSIZ;
1552 #if 0 /*JP*/
1553         name = strncpy(buf, name, PL_PSIZ - 1);
1554         buf[PL_PSIZ - 1] = '\0';
1555 #else
1556         if (is_kanji2(name, lth - 1))
1557             --lth;
1558         name = strncpy(buf, name, lth - 1);
1559         buf[lth - 1] = '\0';
1560 #endif
1561     }
1562     /* If named artifact exists in the game, do not create another.
1563      * Also trying to create an artifact shouldn't de-artifact
1564      * it (e.g. Excalibur from prayer). In this case the object
1565      * will retain its current name. */
1566     if (obj->oartifact || (lth && exist_artifact(obj->otyp, name)))
1567         return obj;
1568
1569     new_oname(obj, lth); /* removes old name if one is present */
1570     if (lth)
1571         Strcpy(ONAME(obj), name);
1572
1573     if (lth)
1574         artifact_exists(obj, name, TRUE);
1575     if (obj->oartifact) {
1576         /* can't dual-wield with artifact as secondary weapon */
1577         if (obj == uswapwep)
1578             untwoweapon();
1579         /* activate warning if you've just named your weapon "Sting" */
1580         if (obj == uwep)
1581             set_artifact_intrinsic(obj, TRUE, W_WEP);
1582         /* if obj is owned by a shop, increase your bill */
1583         if (obj->unpaid)
1584             alter_cost(obj, 0L);
1585         if (via_naming) {
1586             /* violate illiteracy conduct since successfully wrote arti-name */
1587             u.uconduct.literate++;
1588         }
1589     }
1590     if (carried(obj))
1591         update_inventory();
1592     return obj;
1593 }
1594
1595 static NEARDATA const char callable[] = {
1596     SCROLL_CLASS, POTION_CLASS, WAND_CLASS,  RING_CLASS, AMULET_CLASS,
1597     GEM_CLASS,    SPBOOK_CLASS, ARMOR_CLASS, TOOL_CLASS, 0
1598 };
1599
1600 boolean
1601 objtyp_is_callable(i)
1602 int i;
1603 {
1604     return (boolean) (objects[i].oc_uname
1605                       || (OBJ_DESCR(objects[i])
1606                           && index(callable, objects[i].oc_class)));
1607 }
1608
1609 /* C and #name commands - player can name monster or object or type of obj */
1610 int
1611 docallcmd()
1612 {
1613     struct obj *obj;
1614     winid win;
1615     anything any;
1616     menu_item *pick_list = 0;
1617     char ch, allowall[2];
1618     /* if player wants a,b,c instead of i,o when looting, do that here too */
1619     boolean abc = flags.lootabc;
1620
1621     win = create_nhwindow(NHW_MENU);
1622     start_menu(win);
1623     any = zeroany;
1624     any.a_char = 'm'; /* group accelerator 'C' */
1625     add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'C', ATR_NONE,
1626 /*JP
1627              "a monster", MENU_UNSELECTED);
1628 */
1629              "\89ö\95¨", MENU_UNSELECTED);
1630     if (invent) {
1631         /* we use y and n as accelerators so that we can accept user's
1632            response keyed to old "name an individual object?" prompt */
1633         any.a_char = 'i'; /* group accelerator 'y' */
1634         add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'y', ATR_NONE,
1635 /*JP
1636                  "a particular object in inventory", MENU_UNSELECTED);
1637 */
1638                  "\8e\9d\82¿\95¨\82Ì\92\86\82Ì\88ê\82Â\82Ì\83A\83C\83e\83\80", MENU_UNSELECTED);
1639         any.a_char = 'o'; /* group accelerator 'n' */
1640         add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'n', ATR_NONE,
1641 /*JP
1642                  "the type of an object in inventory", MENU_UNSELECTED);
1643 */
1644                  "\8e\9d\82¿\95¨\82Ì\92\86\82Ì\88ê\82Â\82Ì\83A\83C\83e\83\80\82Ì\8eí\97Þ", MENU_UNSELECTED);
1645     }
1646     any.a_char = 'f'; /* group accelerator ',' (or ':' instead?) */
1647     add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, ',', ATR_NONE,
1648 /*JP
1649              "the type of an object upon the floor", MENU_UNSELECTED);
1650 */
1651              "\8f°\82Ì\8fã\82É\82 \82é\88ê\82Â\82Ì\83A\83C\83e\83\80\82Ì\8eí\97Þ", MENU_UNSELECTED);
1652     any.a_char = 'd'; /* group accelerator '\' */
1653     add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, '\\', ATR_NONE,
1654 /*JP
1655              "the type of an object on discoveries list", MENU_UNSELECTED);
1656 */
1657              "\94­\8c©\95¨\88ê\97\97\82É\82 \82é\88ê\82Â\82Ì\83A\83C\83e\83\80\82Ì\8eí\97Þ", MENU_UNSELECTED);
1658     any.a_char = 'a'; /* group accelerator 'l' */
1659     add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'l', ATR_NONE,
1660 /*JP
1661              "record an annotation for the current level", MENU_UNSELECTED);
1662 */
1663              "\8c»\8dÝ\82Ì\8aK\82É\91Î\82·\82é\83\81\83\82\82Ì\8bL\98^", MENU_UNSELECTED);
1664 /*JP
1665     end_menu(win, "What do you want to name?");
1666 */
1667     end_menu(win, "\82Ç\82ê\82É\96¼\91O\82ð\82Â\82¯\82Ü\82·\82©\81H");
1668     if (select_menu(win, PICK_ONE, &pick_list) > 0) {
1669         ch = pick_list[0].item.a_char;
1670         free((genericptr_t) pick_list);
1671     } else
1672         ch = 'q';
1673     destroy_nhwindow(win);
1674
1675     switch (ch) {
1676     default:
1677     case 'q':
1678         break;
1679     case 'm': /* name a visible monster */
1680         do_mname();
1681         break;
1682     case 'i': /* name an individual object in inventory */
1683         allowall[0] = ALL_CLASSES;
1684         allowall[1] = '\0';
1685         obj = getobj(allowall, "name");
1686         if (obj)
1687             do_oname(obj);
1688         break;
1689     case 'o': /* name a type of object in inventory */
1690         obj = getobj(callable, "call");
1691         if (obj) {
1692             /* behave as if examining it in inventory;
1693                this might set dknown if it was picked up
1694                while blind and the hero can now see */
1695             (void) xname(obj);
1696
1697             if (!obj->dknown) {
1698 /*JP
1699                 You("would never recognize another one.");
1700 */
1701                 You("\91¼\82É\94F\8e¯\82Å\82«\82È\82¢\81D");
1702 #if 0
1703             } else if (!objtyp_is_callable(obj->otyp)) {
1704                 You("know those as well as you ever will.");
1705 #endif
1706             } else {
1707                 docall(obj);
1708             }
1709         }
1710         break;
1711     case 'f': /* name a type of object visible on the floor */
1712         namefloorobj();
1713         break;
1714     case 'd': /* name a type of object on the discoveries list */
1715         rename_disco();
1716         break;
1717     case 'a': /* annotate level */
1718         donamelevel();
1719         break;
1720     }
1721     return 0;
1722 }
1723
1724 /* for use by safe_qbuf() */
1725 STATIC_PTR char *
1726 docall_xname(obj)
1727 struct obj *obj;
1728 {
1729     struct obj otemp;
1730
1731     otemp = *obj;
1732     otemp.oextra = (struct oextra *) 0;
1733     otemp.quan = 1L;
1734     /* in case water is already known, convert "[un]holy water" to "water" */
1735     otemp.blessed = otemp.cursed = 0;
1736     /* remove attributes that are doname() caliber but get formatted
1737        by xname(); most of these fixups aren't really needed because the
1738        relevant type of object isn't callable so won't reach this far */
1739     if (otemp.oclass == WEAPON_CLASS)
1740         otemp.opoisoned = 0; /* not poisoned */
1741     else if (otemp.oclass == POTION_CLASS)
1742         otemp.odiluted = 0; /* not diluted */
1743     else if (otemp.otyp == TOWEL || otemp.otyp == STATUE)
1744         otemp.spe = 0; /* not wet or historic */
1745     else if (otemp.otyp == TIN)
1746         otemp.known = 0; /* suppress tin type (homemade, &c) and mon type */
1747     else if (otemp.otyp == FIGURINE)
1748         otemp.corpsenm = NON_PM; /* suppress mon type */
1749     else if (otemp.otyp == HEAVY_IRON_BALL)
1750         otemp.owt = objects[HEAVY_IRON_BALL].oc_weight; /* not "very heavy" */
1751     else if (otemp.oclass == FOOD_CLASS && otemp.globby)
1752         otemp.owt = 120; /* 6*20, neither a small glob nor a large one */
1753
1754     return an(xname(&otemp));
1755 }
1756
1757 void
1758 docall(obj)
1759 struct obj *obj;
1760 {
1761     char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
1762     char **str1;
1763
1764     if (!obj->dknown)
1765         return; /* probably blind */
1766
1767     if (obj->oclass == POTION_CLASS && obj->fromsink)
1768         /* kludge, meaning it's sink water */
1769 /*JP
1770         Sprintf(qbuf, "Call a stream of %s fluid:",
1771 */
1772         Sprintf(qbuf, "%s\89t\91Ì:",
1773                 OBJ_DESCR(objects[obj->otyp]));
1774     else
1775 #if 0 /*JP*/
1776         (void) safe_qbuf(qbuf, "Call ", ":", obj,
1777                          docall_xname, simpleonames, "thing");
1778 #else
1779         (void) safe_qbuf(qbuf, "", "\82É\89½\82Æ\96¼\91O\82ð\95t\82¯\82é\81H", obj,
1780                          docall_xname, simpleonames, "\82±\82ê");
1781 #endif
1782     getlin(qbuf, buf);
1783     if (!*buf || *buf == '\033')
1784         return;
1785
1786     /* clear old name */
1787     str1 = &(objects[obj->otyp].oc_uname);
1788     if (*str1)
1789         free((genericptr_t) *str1);
1790
1791     /* strip leading and trailing spaces; uncalls item if all spaces */
1792     (void) mungspaces(buf);
1793     if (!*buf) {
1794         if (*str1) { /* had name, so possibly remove from disco[] */
1795             /* strip name first, for the update_inventory() call
1796                from undiscover_object() */
1797             *str1 = (char *) 0;
1798             undiscover_object(obj->otyp);
1799         }
1800     } else {
1801         *str1 = dupstr(buf);
1802         discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
1803     }
1804 }
1805
1806 STATIC_OVL void
1807 namefloorobj()
1808 {
1809     coord cc;
1810     int glyph;
1811     char buf[BUFSZ];
1812     struct obj *obj = 0;
1813 #if 0 /*JP*/
1814     boolean fakeobj = FALSE, use_plural;
1815 #else
1816     boolean fakeobj = FALSE;
1817 #endif
1818
1819     cc.x = u.ux, cc.y = u.uy;
1820     /* "dot for under/over you" only makes sense when the cursor hasn't
1821        been moved off the hero's '@' yet, but there's no way to adjust
1822        the help text once getpos() has started */
1823 #if 0 /*JP*/
1824     Sprintf(buf, "object on map (or '.' for one %s you)",
1825             (u.uundetected && hides_under(youmonst.data)) ? "over" : "under");
1826 #else
1827     Strcpy(buf, "\92n\90}\8fã\82Ì\95¨\91Ì(\82 \82é\82¢\82Í'.'\82Å\82 \82È\82½\82Ì\82¢\82é\8fê\8f\8a");
1828 #endif
1829     if (getpos(&cc, FALSE, buf) < 0 || cc.x <= 0)
1830         return;
1831     if (cc.x == u.ux && cc.y == u.uy) {
1832         obj = vobj_at(u.ux, u.uy);
1833     } else {
1834         glyph = glyph_at(cc.x, cc.y);
1835         if (glyph_is_object(glyph))
1836             fakeobj = object_from_map(glyph, cc.x, cc.y, &obj);
1837         /* else 'obj' stays null */
1838     }
1839     if (!obj) {
1840         /* "under you" is safe here since there's no object to hide under */
1841 #if 0 /*JP*/
1842         pline("There doesn't seem to be any object %s.",
1843               (cc.x == u.ux && cc.y == u.uy) ? "under you" : "there");
1844 #else
1845         pline("%s\82É\82Í\89½\82à\82È\82¢\82æ\82¤\82¾\81D",
1846               (cc.x == u.ux && cc.y == u.uy) ? "\82 \82È\82½\82Ì\89º" : "\82»\82±");
1847 #endif
1848         return;
1849     }
1850     /* note well: 'obj' might be as instance of STRANGE_OBJECT if target
1851        is a mimic; passing that to xname (directly or via simpleonames)
1852        would yield "glorkum" so we need to handle it explicitly; it will
1853        always fail the Hallucination test and pass the !callable test,
1854        resulting in the "can't be assigned a type name" message */
1855     Strcpy(buf, (obj->otyp != STRANGE_OBJECT)
1856                  ? simpleonames(obj)
1857                  : obj_descr[STRANGE_OBJECT].oc_name);
1858 #if 0 /*JP*/
1859     use_plural = (obj->quan > 1L);
1860 #endif
1861     if (Hallucination) {
1862         const char *unames[6];
1863         char tmpbuf[BUFSZ];
1864
1865         /* straight role name */
1866         unames[0] = ((Upolyd ? u.mfemale : flags.female) && urole.name.f)
1867                      ? urole.name.f
1868                      : urole.name.m;
1869         /* random rank title for hero's role */
1870         unames[1] = rank_of(rnd(30), Role_switch, flags.female);
1871         /* random fake monster */
1872         unames[2] = bogusmon(tmpbuf, (char *) 0);
1873         /* increased chance for fake monster */
1874         unames[3] = unames[2];
1875         /* traditional */
1876         unames[4] = roguename();
1877         /* silly */
1878 /*JP
1879         unames[5] = "Wibbly Wobbly";
1880 */
1881         unames[5] = "\82¤\82ë\82¤\82ë";
1882 #if 0 /*JP*/
1883         pline("%s %s to call you \"%s.\"",
1884               The(buf), use_plural ? "decide" : "decides",
1885               unames[rn2(SIZE(unames))]);
1886 #else
1887         pline("%s\82Í\82 \82È\82½\82ð\81u%s\81v\82Æ\8cÄ\82Ô\82±\82Æ\82É\8c\88\82ß\82½\81D",
1888               buf,
1889               unames[rn2(SIZE(unames))]);
1890 #endif
1891     } else if (!objtyp_is_callable(obj->otyp)) {
1892 #if 0 /*JP*/
1893         pline("%s %s can't be assigned a type name.",
1894               use_plural ? "Those" : "That", buf);
1895 #else
1896         pline("%s\82É\8eí\97Þ\82Ì\96¼\91O\82ð\8a\84\82è\93\96\82Ä\82é\82±\82Æ\82Í\82Å\82«\82È\82¢\81D",
1897               buf);
1898 #endif
1899     } else if (!obj->dknown) {
1900 #if 0 /*JP*/
1901         You("don't know %s %s well enough to name %s.",
1902             use_plural ? "those" : "that", buf, use_plural ? "them" : "it");
1903 #else
1904         You("\96¼\91O\82ð\95t\82¯\82ç\82ê\82é\82Ù\82Ç%s\82Ì\82±\82Æ\82ð\82æ\82­\92m\82ç\82È\82¢\81D",
1905             buf);
1906 #endif
1907     } else {
1908         docall(obj);
1909     }
1910     if (fakeobj)
1911         dealloc_obj(obj);
1912 }
1913
1914 static const char *const ghostnames[] = {
1915     /* these names should have length < PL_NSIZ */
1916     /* Capitalize the names for aesthetics -dgk */
1917     "Adri",    "Andries",       "Andreas",     "Bert",    "David",  "Dirk",
1918     "Emile",   "Frans",         "Fred",        "Greg",    "Hether", "Jay",
1919     "John",    "Jon",           "Karnov",      "Kay",     "Kenny",  "Kevin",
1920     "Maud",    "Michiel",       "Mike",        "Peter",   "Robert", "Ron",
1921     "Tom",     "Wilmar",        "Nick Danger", "Phoenix", "Jiro",   "Mizue",
1922     "Stephan", "Lance Braccus", "Shadowhawk"
1923 };
1924
1925 /* ghost names formerly set by x_monnam(), now by makemon() instead */
1926 const char *
1927 rndghostname()
1928 {
1929     return rn2(7) ? ghostnames[rn2(SIZE(ghostnames))] : (const char *) plname;
1930 }
1931
1932 /*
1933  * Monster naming functions:
1934  * x_monnam is the generic monster-naming function.
1935  *                seen        unseen       detected               named
1936  * mon_nam:     the newt        it      the invisible orc       Fido
1937  * noit_mon_nam:the newt (as if detected) the invisible orc     Fido
1938  * l_monnam:    newt            it      invisible orc           dog called Fido
1939  * Monnam:      The newt        It      The invisible orc       Fido
1940  * noit_Monnam: The newt (as if detected) The invisible orc     Fido
1941  * Adjmonnam:   The poor newt   It      The poor invisible orc  The poor Fido
1942  * Amonnam:     A newt          It      An invisible orc        Fido
1943  * a_monnam:    a newt          it      an invisible orc        Fido
1944  * m_monnam:    newt            xan     orc                     Fido
1945  * y_monnam:    your newt     your xan  your invisible orc      Fido
1946  * noname_monnam(mon,article):
1947  *              article newt    art xan art invisible orc       art dog
1948  */
1949
1950 /* Bug: if the monster is a priest or shopkeeper, not every one of these
1951  * options works, since those are special cases.
1952  */
1953 char *
1954 x_monnam(mtmp, article, adjective, suppress, called)
1955 register struct monst *mtmp;
1956 int article;
1957 /* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious
1958  * ARTICLE_YOUR: "your" on pets, "the" on everything else
1959  *
1960  * If the monster would be referred to as "it" or if the monster has a name
1961  * _and_ there is no adjective, "invisible", "saddled", etc., override this
1962  * and always use no article.
1963  */
1964 const char *adjective;
1965 int suppress;
1966 /* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE.
1967  * EXACT_NAME: combination of all the above
1968  * SUPPRESS_NAME: omit monster's assigned name (unless uniq w/ pname).
1969  */
1970 boolean called;
1971 {
1972     char *buf = nextmbuf();
1973     struct permonst *mdat = mtmp->data;
1974     const char *pm_name = mdat->mname;
1975     boolean do_hallu, do_invis, do_it, do_saddle, do_name;
1976 #if 0 /*JP*/
1977     boolean name_at_start, has_adjectives;
1978     char *bp;
1979 #endif
1980
1981     if (program_state.gameover)
1982         suppress |= SUPPRESS_HALLUCINATION;
1983     if (article == ARTICLE_YOUR && !mtmp->mtame)
1984         article = ARTICLE_THE;
1985
1986     do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION);
1987     do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE);
1988     do_it = !canspotmon(mtmp) && article != ARTICLE_YOUR
1989             && !program_state.gameover && mtmp != u.usteed
1990             && !(u.uswallow && mtmp == u.ustuck) && !(suppress & SUPPRESS_IT);
1991     do_saddle = !(suppress & SUPPRESS_SADDLE);
1992     do_name = !(suppress & SUPPRESS_NAME) || type_is_pname(mdat);
1993
1994     buf[0] = '\0';
1995
1996     /* unseen monsters, etc.  Use "it" */
1997     if (do_it) {
1998 /*JP
1999         Strcpy(buf, "it");
2000 */
2001         Strcpy(buf, "\89½\8eÒ\82©");
2002         return buf;
2003     }
2004
2005     /* priests and minions: don't even use this function */
2006     if (mtmp->ispriest || mtmp->isminion) {
2007         char priestnambuf[BUFSZ];
2008         char *name;
2009         long save_prop = EHalluc_resistance;
2010         unsigned save_invis = mtmp->minvis;
2011
2012         /* when true name is wanted, explicitly block Hallucination */
2013         if (!do_hallu)
2014             EHalluc_resistance = 1L;
2015         if (!do_invis)
2016             mtmp->minvis = 0;
2017         name = priestname(mtmp, priestnambuf);
2018         EHalluc_resistance = save_prop;
2019         mtmp->minvis = save_invis;
2020 #if 0 /*JP*/
2021         if (article == ARTICLE_NONE && !strncmp(name, "the ", 4))
2022             name += 4;
2023 #endif
2024         return strcpy(buf, name);
2025     }
2026     /* an "aligned priest" not flagged as a priest or minion should be
2027        "priest" or "priestess" (normally handled by priestname()) */
2028     if (mdat == &mons[PM_ALIGNED_PRIEST])
2029 /*JP
2030         pm_name = mtmp->female ? "priestess" : "priest";
2031 */
2032         pm_name = mtmp->female ? "\93ò\91m" : "\91m\97µ";
2033     else if (mdat == &mons[PM_HIGH_PRIEST] && mtmp->female)
2034 /*JP
2035         pm_name = "high priestess";
2036 */
2037         pm_name = "\96@\89¤";
2038
2039     /* Shopkeepers: use shopkeeper name.  For normal shopkeepers, just
2040      * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
2041      * shopkeeper" or "Asidonhopo the blue dragon".  If hallucinating,
2042      * none of this applies.
2043      */
2044     if (mtmp->isshk && !do_hallu) {
2045 #if 0 /*JP*/
2046         if (adjective && article == ARTICLE_THE) {
2047             /* pathological case: "the angry Asidonhopo the blue dragon"
2048                sounds silly */
2049             Strcpy(buf, "the ");
2050             Strcat(strcat(buf, adjective), " ");
2051             Strcat(buf, shkname(mtmp));
2052             return buf;
2053         }
2054         Strcat(buf, shkname(mtmp));
2055         if (mdat == &mons[PM_SHOPKEEPER] && !do_invis)
2056             return buf;
2057         Strcat(buf, " the ");
2058         if (do_invis)
2059             Strcat(buf, "invisible ");
2060         Strcat(buf, pm_name);
2061         return buf;
2062 #else
2063         if (mdat == &mons[PM_SHOPKEEPER] && !do_invis){
2064             Strcpy(buf, shkname(mtmp));
2065         } else {
2066             Sprintf(buf, "%s\82Æ\82¢\82¤\96¼\82Ì%s%s",
2067                     shkname(mtmp), do_invis ? "\8ep\82Ì\8c©\82¦\82È\82¢" : "",
2068                     pm_name);
2069         }
2070         return buf;
2071 #endif
2072     }
2073
2074     /* Put the adjectives in the buffer */
2075     if (adjective)
2076 /*JP
2077         Strcat(strcat(buf, adjective), " ");
2078 */
2079         Strcat(buf, adjective);
2080     if (do_invis)
2081 /*JP
2082         Strcat(buf, "invisible ");
2083 */
2084         Strcat(buf, "\8ep\82Ì\8c©\82¦\82È\82¢");
2085     if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind
2086         && !Hallucination)
2087 /*JP
2088         Strcat(buf, "saddled ");
2089 */
2090         Strcat(buf, "\88Æ\82Ì\82Â\82¢\82Ä\82¢\82é");
2091 #if 0 /*JP*/
2092     if (buf[0] != 0)
2093         has_adjectives = TRUE;
2094     else
2095         has_adjectives = FALSE;
2096 #endif
2097
2098     /* Put the actual monster name or type into the buffer now */
2099     /* Be sure to remember whether the buffer starts with a name */
2100     if (do_hallu) {
2101         char rnamecode;
2102         char *rname = rndmonnam(&rnamecode);
2103
2104         Strcat(buf, rname);
2105 #if 0 /*JP*/
2106         name_at_start = bogon_is_pname(rnamecode);
2107 #endif
2108     } else if (do_name && has_mname(mtmp)) {
2109         char *name = MNAME(mtmp);
2110
2111         if (mdat == &mons[PM_GHOST]) {
2112 /*JP
2113             Sprintf(eos(buf), "%s ghost", s_suffix(name));
2114 */
2115             Sprintf(buf, "%s\82Ì\97H\97ì", name);
2116 #if 0 /*JP*/
2117             name_at_start = TRUE;
2118 #endif
2119         } else if (called) {
2120 /*JP
2121             Sprintf(eos(buf), "%s called %s", pm_name, name);
2122 */
2123             Sprintf(eos(buf), "%s\82Æ\82¢\82¤\96¼\82Ì%s", name, pm_name);
2124 #if 0 /*JP*/
2125             name_at_start = (boolean) type_is_pname(mdat);
2126 #endif
2127 #if 0 /*JP*//*\92è\8a¥\8e\8c\82Ì\8f\88\97\9d\82Í\95s\97v*/
2128         } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) {
2129             /* <name> the <adjective> <invisible> <saddled> <rank> */
2130             char pbuf[BUFSZ];
2131
2132             Strcpy(pbuf, name);
2133             pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */
2134             if (has_adjectives)
2135                 Strcat(pbuf, buf);
2136             Strcat(pbuf, bp + 5); /* append the rest of the name */
2137             Strcpy(buf, pbuf);
2138             article = ARTICLE_NONE;
2139             name_at_start = TRUE;
2140 #endif
2141         } else {
2142             Strcat(buf, name);
2143 #if 0 /*JP*/
2144             name_at_start = TRUE;
2145 #endif
2146         }
2147     } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) {
2148         char pbuf[BUFSZ];
2149
2150         Strcpy(pbuf, rank_of((int) mtmp->m_lev, monsndx(mdat),
2151                              (boolean) mtmp->female));
2152 #if 0 /*JP*/
2153         Strcat(buf, lcase(pbuf));
2154 #else
2155         Strcat(buf, pbuf);
2156 #endif
2157 #if 0 /*JP*/
2158         name_at_start = FALSE;
2159 #endif
2160     } else {
2161         Strcat(buf, pm_name);
2162 #if 0 /*JP*/
2163         name_at_start = (boolean) type_is_pname(mdat);
2164 #endif
2165     }
2166
2167 #if 0 /*JP*//*\93ú\96{\8cê\82É\8a¥\8e\8c\82Í\82È\82¢*/
2168     if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) {
2169         if (mdat == &mons[PM_WIZARD_OF_YENDOR])
2170             article = ARTICLE_THE;
2171         else
2172             article = ARTICLE_NONE;
2173     } else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) {
2174         article = ARTICLE_THE;
2175     }
2176
2177     {
2178         char buf2[BUFSZ];
2179
2180         switch (article) {
2181         case ARTICLE_YOUR:
2182             Strcpy(buf2, "your ");
2183             Strcat(buf2, buf);
2184             Strcpy(buf, buf2);
2185             return buf;
2186         case ARTICLE_THE:
2187             Strcpy(buf2, "the ");
2188             Strcat(buf2, buf);
2189             Strcpy(buf, buf2);
2190             return buf;
2191         case ARTICLE_A:
2192             return an(buf);
2193         case ARTICLE_NONE:
2194         default:
2195             return buf;
2196         }
2197     }
2198 #else
2199     return buf;
2200 #endif
2201 }
2202
2203 char *
2204 l_monnam(mtmp)
2205 struct monst *mtmp;
2206 {
2207     return x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
2208                     (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, TRUE);
2209 }
2210
2211 char *
2212 mon_nam(mtmp)
2213 struct monst *mtmp;
2214 {
2215     return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2216                     (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, FALSE);
2217 }
2218
2219 /* print the name as if mon_nam() was called, but assume that the player
2220  * can always see the monster--used for probing and for monsters aggravating
2221  * the player with a cursed potion of invisibility
2222  */
2223 char *
2224 noit_mon_nam(mtmp)
2225 struct monst *mtmp;
2226 {
2227     return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2228                     (has_mname(mtmp)) ? (SUPPRESS_SADDLE | SUPPRESS_IT)
2229                                       : SUPPRESS_IT,
2230                     FALSE);
2231 }
2232
2233 char *
2234 Monnam(mtmp)
2235 struct monst *mtmp;
2236 {
2237     register char *bp = mon_nam(mtmp);
2238
2239     *bp = highc(*bp);
2240     return  bp;
2241 }
2242
2243 char *
2244 noit_Monnam(mtmp)
2245 struct monst *mtmp;
2246 {
2247     register char *bp = noit_mon_nam(mtmp);
2248
2249     *bp = highc(*bp);
2250     return  bp;
2251 }
2252
2253 /* return "a dog" rather than "Fido", honoring hallucination and visibility */
2254 char *
2255 noname_monnam(mtmp, article)
2256 struct monst *mtmp;
2257 int article;
2258 {
2259     return x_monnam(mtmp, article, (char *) 0, SUPPRESS_NAME, FALSE);
2260 }
2261
2262 /* monster's own name -- overrides hallucination and [in]visibility
2263    so shouldn't be used in ordinary messages (mainly for disclosure) */
2264 char *
2265 m_monnam(mtmp)
2266 struct monst *mtmp;
2267 {
2268     return x_monnam(mtmp, ARTICLE_NONE, (char *) 0, EXACT_NAME, FALSE);
2269 }
2270
2271 /* pet name: "your little dog" */
2272 char *
2273 y_monnam(mtmp)
2274 struct monst *mtmp;
2275 {
2276     int prefix, suppression_flag;
2277
2278     prefix = mtmp->mtame ? ARTICLE_YOUR : ARTICLE_THE;
2279     suppression_flag = (has_mname(mtmp)
2280                         /* "saddled" is redundant when mounted */
2281                         || mtmp == u.usteed)
2282                            ? SUPPRESS_SADDLE
2283                            : 0;
2284
2285     return x_monnam(mtmp, prefix, (char *) 0, suppression_flag, FALSE);
2286 }
2287
2288 char *
2289 Adjmonnam(mtmp, adj)
2290 struct monst *mtmp;
2291 const char *adj;
2292 {
2293     char *bp = x_monnam(mtmp, ARTICLE_THE, adj,
2294                         has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2295
2296     *bp = highc(*bp);
2297     return  bp;
2298 }
2299
2300 char *
2301 a_monnam(mtmp)
2302 struct monst *mtmp;
2303 {
2304     return x_monnam(mtmp, ARTICLE_A, (char *) 0,
2305                     has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2306 }
2307
2308 char *
2309 Amonnam(mtmp)
2310 struct monst *mtmp;
2311 {
2312     char *bp = a_monnam(mtmp);
2313
2314     *bp = highc(*bp);
2315     return  bp;
2316 }
2317
2318 /* used for monster ID by the '/', ';', and 'C' commands to block remote
2319    identification of the endgame altars via their attending priests */
2320 char *
2321 distant_monnam(mon, article, outbuf)
2322 struct monst *mon;
2323 int article; /* only ARTICLE_NONE and ARTICLE_THE are handled here */
2324 char *outbuf;
2325 {
2326     /* high priest(ess)'s identity is concealed on the Astral Plane,
2327        unless you're adjacent (overridden for hallucination which does
2328        its own obfuscation) */
2329     if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination
2330         && Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) {
2331 #if 0 /*JP*/
2332         Strcpy(outbuf, article == ARTICLE_THE ? "the " : "");
2333         Strcat(outbuf, mon->female ? "high priestess" : "high priest");
2334 #else
2335         Strcpy(outbuf, "\96@\89¤");
2336 #endif
2337     } else {
2338         Strcpy(outbuf, x_monnam(mon, article, (char *) 0, 0, TRUE));
2339     }
2340     return outbuf;
2341 }
2342
2343 /* fake monsters used to be in a hard-coded array, now in a data file */
2344 STATIC_OVL char *
2345 bogusmon(buf, code)
2346 char *buf, *code;
2347 {
2348     char *mname = buf;
2349
2350     get_rnd_text(BOGUSMONFILE, buf);
2351     /* strip prefix if present */
2352     if (!letter(*mname)) {
2353         if (code)
2354             *code = *mname;
2355         ++mname;
2356     } else {
2357         if (code)
2358             *code = '\0';
2359     }
2360     return mname;
2361 }
2362
2363 /* return a random monster name, for hallucination */
2364 char *
2365 rndmonnam(code)
2366 char *code;
2367 {
2368     static char buf[BUFSZ];
2369     char *mname;
2370     int name;
2371 #define BOGUSMONSIZE 100 /* arbitrary */
2372
2373     if (code)
2374         *code = '\0';
2375
2376     do {
2377         name = rn1(SPECIAL_PM + BOGUSMONSIZE - LOW_PM, LOW_PM);
2378     } while (name < SPECIAL_PM
2379              && (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN)));
2380
2381     if (name >= SPECIAL_PM) {
2382         mname = bogusmon(buf, code);
2383     } else {
2384         mname = strcpy(buf, mons[name].mname);
2385     }
2386     return mname;
2387 #undef BOGUSMONSIZE
2388 }
2389
2390 /* check bogusmon prefix to decide whether it's a personal name */
2391 boolean
2392 bogon_is_pname(code)
2393 char code;
2394 {
2395     if (!code)
2396         return FALSE;
2397     return index("-+=", code) ? TRUE : FALSE;
2398 }
2399
2400 /* name of a Rogue player */
2401 const char *
2402 roguename()
2403 {
2404     char *i, *opts;
2405
2406     if ((opts = nh_getenv("ROGUEOPTS")) != 0) {
2407         for (i = opts; *i; i++)
2408             if (!strncmp("name=", i, 5)) {
2409                 char *j;
2410                 if ((j = index(i + 5, ',')) != 0)
2411                     *j = (char) 0;
2412                 return i + 5;
2413             }
2414     }
2415     /*JP:Rogue\82Ì\8aJ\94­\8eÒ\82Ì\96¼\91O*/
2416     return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
2417                   : "Glenn Wichman";
2418 }
2419
2420 static NEARDATA const char *const hcolors[] = {
2421 #if 0 /*JP*/
2422     "ultraviolet", "infrared", "bluish-orange", "reddish-green", "dark white",
2423     "light black", "sky blue-pink", "salty", "sweet", "sour", "bitter",
2424     "striped", "spiral", "swirly", "plaid", "checkered", "argyle", "paisley",
2425     "blotchy", "guernsey-spotted", "polka-dotted", "square", "round",
2426     "triangular", "cabernet", "sangria", "fuchsia", "wisteria", "lemon-lime",
2427     "strawberry-banana", "peppermint", "romantic", "incandescent",
2428     "octarine", /* Discworld: the Colour of Magic */
2429 #else
2430     "\8e\87\8aO\90F\82Ì", "\90Ô\8aO\90F\82Ì", "\90Â\90F\82ª\82©\82Á\82½\83I\83\8c\83\93\83W\90F\82Ì", "\90Ô\82Ý\82ª\82©\82Á\82½\97Î\90F\82Ì", "\88Ã\82¢\94\92\90F\82Ì",
2431     "\96¾\82é\82¢\8d\95\82Ì", "\90\85\90F\82ª\82©\82Á\82½\83s\83\93\83N\90F\82Ì", "\89\96\90h\82¢", "\8aÃ\82¢", "\82·\82Á\82Ï\82¢", "\8bê\82¢",
2432     "\82µ\82Ü\96Í\97l\82Ì", "\82ç\82¹\82ñ\8fó\82Ì", "\94g\8fó\82Ì", "\8ai\8eq\96Í\97l\8fó\82Ì", "\83`\83F\83b\83N\8fó\82Ì", "\95ú\8eË\8fó\82Ì", "\83y\81[\83Y\83\8a\81[\96Í\97l\82Ì",
2433     "\82µ\82Ý\8fó\82Ì", "\90Â\90F\82Ì\94Á\93_\8fó\82Ì", "\93_\8fó\82Ì", "\8el\8ap\8c`\8fó\82Ì", "\8aÛ\8fó\82Ì",
2434     "\8eO\8ap\8fó\82Ì", "\83J\83x\83\8b\83l\90F\82Ì", "\83T\83\93\83O\83\8a\83A\90F\82Ì", "\91N\82â\82©\82È\90Ô\8e\87\90F\82Ì", "\93¡\90F\82Ì", "\83\8c\83\82\83\93\83\89\83C\83\80\90F\82Ì",
2435     "ä\95\83o\83i\83i\90F\82Ì", "\83y\83p\81[\83~\83\93\83g\90F\82Ì", "\83\8d\83}\83\93\83`\83b\83N\82È\90F\82Ì", "\94\92\94M\90F\82Ì",
2436     "\83I\83N\83^\83\8a\83\93\90F\82Ì",
2437 #endif
2438 };
2439
2440 const char *
2441 hcolor(colorpref)
2442 const char *colorpref;
2443 {
2444     return (Hallucination || !colorpref) ? hcolors[rn2(SIZE(hcolors))]
2445                                          : colorpref;
2446 }
2447
2448 /* return a random real color unless hallucinating */
2449 const char *
2450 rndcolor()
2451 {
2452     int k = rn2(CLR_MAX);
2453
2454     return Hallucination ? hcolor((char *) 0)
2455 /*JP
2456                          : (k == NO_COLOR) ? "colorless"
2457 */
2458                          : (k == NO_COLOR) ? "\96³\90F\82Ì"
2459                                            : c_obj_colors[k];
2460 }
2461
2462 static NEARDATA const char *const hliquids[] = {
2463 #if 0 /*JP*/
2464     "yoghurt", "oobleck", "clotted blood", "diluted water", "purified water",
2465     "instant coffee", "tea", "herbal infusion", "liquid rainbow",
2466     "creamy foam", "mulled wine", "bouillon", "nectar", "grog", "flubber",
2467     "ketchup", "slow light", "oil", "vinaigrette", "liquid crystal", "honey",
2468     "caramel sauce", "ink", "aqueous humour", "milk substitute", "fruit juice",
2469     "glowing lava", "gastric acid", "mineral water", "cough syrup", "quicksilver",
2470     "sweet vitriol", "grey goo", "pink slime",
2471 #else
2472     "\83\88\81[\83O\83\8b\83g", "\83E\81[\83u\83\8c\83b\83N", "\8c\8c\8cÐ", "\8fö\97¯\90\85", "\90¸\90»\90\85",
2473     "\83C\83\93\83X\83^\83\93\83g\83R\81[\83q\81[", "\8dg\92\83", "\83n\81[\83u\89t", "\89t\91Ì\82Ì\93ø",
2474     "\83N\83\8a\81[\83~\81[\83t\83H\81[\83\80", "\83z\83b\83g\83\8f\83C\83\93", "\83u\83C\83\88\83\93", "\89Ê\8f`", "\83O\83\8d\83b\83O", "\83t\83\89\83o\81[",
2475     "\83P\83`\83\83\83b\83v", "\92á\91¬\8cõ", "\96û", "\83r\83l\83O\83\8c\83b\83g\83\\81[\83X", "\89t\91Ì\90\85\8f»", "\96I\96¨",
2476     "\83J\83\89\83\81\83\8b\83\\81[\83X", "\83C\83\93\83N", "\96[\90\85", "\91ã\97p\93û", "\83t\83\8b\81[\83c\83W\83\85\81[\83X",
2477     "\97¬\82ê\82é\97n\8aâ", "\88Ý\8e_", "\83~\83l\83\89\83\8b\83E\83H\81[\83^\81[", "\8aP\8e~\82ß\83V\83\8d\83b\83v", "\90\85\8bâ",
2478     "\83W\83G\83`\83\8b\83G\81[\83e\83\8b", "\83O\83\8c\83C\83O\81[", "\83s\83\93\83N\83X\83\89\83C\83\80",
2479 #endif
2480 };
2481
2482 const char *
2483 hliquid(liquidpref)
2484 const char *liquidpref;
2485 {
2486     return (Hallucination || !liquidpref) ? hliquids[rn2(SIZE(hliquids))]
2487                                          : liquidpref;
2488 }
2489
2490 /* Aliases for road-runner nemesis
2491  */
2492 static const char *const coynames[] = {
2493     "Carnivorous Vulgaris", "Road-Runnerus Digestus", "Eatibus Anythingus",
2494     "Famishus-Famishus", "Eatibus Almost Anythingus", "Eatius Birdius",
2495     "Famishius Fantasticus", "Eternalii Famishiis", "Famishus Vulgarus",
2496     "Famishius Vulgaris Ingeniusi", "Eatius-Slobbius", "Hardheadipus Oedipus",
2497     "Carnivorous Slobbius", "Hard-Headipus Ravenus", "Evereadii Eatibus",
2498     "Apetitius Giganticus", "Hungrii Flea-Bagius", "Overconfidentii Vulgaris",
2499     "Caninus Nervous Rex", "Grotesques Appetitus", "Nemesis Ridiculii",
2500     "Canis latrans"
2501 };
2502
2503 char *
2504 coyotename(mtmp, buf)
2505 struct monst *mtmp;
2506 char *buf;
2507 {
2508     if (mtmp && buf) {
2509         Sprintf(buf, "%s - %s",
2510                 x_monnam(mtmp, ARTICLE_NONE, (char *) 0, 0, TRUE),
2511                 mtmp->mcan ? coynames[SIZE(coynames) - 1]
2512                            : coynames[mtmp->m_id % (SIZE(coynames) - 1)]);
2513     }
2514     return buf;
2515 }
2516
2517 /* make sure "The Colour of Magic" remains the first entry in here */
2518 static const char *const sir_Terry_novels[] = {
2519     "The Colour of Magic", "The Light Fantastic", "Equal Rites", "Mort",
2520     "Sourcery", "Wyrd Sisters", "Pyramids", "Guards! Guards!", "Eric",
2521     "Moving Pictures", "Reaper Man", "Witches Abroad", "Small Gods",
2522     "Lords and Ladies", "Men at Arms", "Soul Music", "Interesting Times",
2523     "Maskerade", "Feet of Clay", "Hogfather", "Jingo", "The Last Continent",
2524     "Carpe Jugulum", "The Fifth Elephant", "The Truth", "Thief of Time",
2525     "The Last Hero", "The Amazing Maurice and His Educated Rodents",
2526     "Night Watch", "The Wee Free Men", "Monstrous Regiment",
2527     "A Hat Full of Sky", "Going Postal", "Thud!", "Wintersmith",
2528     "Making Money", "Unseen Academicals", "I Shall Wear Midnight", "Snuff",
2529     "Raising Steam", "The Shepherd's Crown"
2530 };
2531
2532 const char *
2533 noveltitle(novidx)
2534 int *novidx;
2535 {
2536     int j, k = SIZE(sir_Terry_novels);
2537
2538     j = rn2(k);
2539     if (novidx) {
2540         if (*novidx == -1)
2541             *novidx = j;
2542         else if (*novidx >= 0 && *novidx < k)
2543             j = *novidx;
2544     }
2545     return sir_Terry_novels[j];
2546 }
2547
2548 const char *
2549 lookup_novel(lookname, idx)
2550 const char *lookname;
2551 int *idx;
2552 {
2553     int k;
2554
2555     /* Take American or U.K. spelling of this one */
2556     if (!strcmpi(The(lookname), "The Color of Magic"))
2557         lookname = sir_Terry_novels[0];
2558
2559     for (k = 0; k < SIZE(sir_Terry_novels); ++k) {
2560         if (!strcmpi(lookname, sir_Terry_novels[k])
2561             || !strcmpi(The(lookname), sir_Terry_novels[k])) {
2562             if (idx)
2563                 *idx = k;
2564             return sir_Terry_novels[k];
2565         }
2566     }
2567     /* name not found; if novelidx is already set, override the name */
2568     if (idx && *idx >= 0 && *idx < SIZE(sir_Terry_novels))
2569         return sir_Terry_novels[*idx];
2570
2571     return (const char *) 0;
2572 }
2573
2574 /*do_name.c*/