OSDN Git Service

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