OSDN Git Service

update year to 2020
[jnethack/source.git] / src / do_name.c
1 /* NetHack 3.6  do_name.c       $NHDT-Date: 1582364431 2020/02/22 09:40:31 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.174 $ */
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-2020            */
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], 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         || !isok(cc.x, cc.y))
1387         return;
1388     cx = cc.x, 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     buf[0] = '\0';
1423 #ifdef EDIT_GETLIN
1424     /* if there's an existing name, make it be the default answer */
1425     if (has_mname(mtmp))
1426         Strcpy(buf, MNAME(mtmp));
1427 #endif
1428     getlin(qbuf, buf);
1429     if (!*buf || *buf == '\033')
1430         return;
1431     /* strip leading and trailing spaces; unnames monster if all spaces */
1432     (void) mungspaces(buf);
1433
1434     /* Unique monsters have their own specific names or titles.
1435      * Shopkeepers, temple priests and other minions use alternate
1436      * name formatting routines which ignore any user-supplied name.
1437      *
1438      * Don't say the name is being rejected if it happens to match
1439      * the existing name.
1440      *
1441      * TODO: should have an alternate message when the attempt is to
1442      * remove existing name without assigning a new one.
1443      */
1444     if ((mtmp->data->geno & G_UNIQ) && !mtmp->ispriest) {
1445         if (!alreadynamed(mtmp, monnambuf, buf))
1446 /*JP
1447             pline("%s doesn't like being called names!", upstart(monnambuf));
1448 */
1449             pline("%s\82Í\82 \82¾\96¼\82Å\8cÄ\82Î\82ê\82é\82Ì\82ª\8c\99\82¢\82È\82æ\82¤\82¾\81I", Monnam(mtmp));
1450     } else if (mtmp->isshk
1451                && !(Deaf || mtmp->msleeping || !mtmp->mcanmove
1452                     || mtmp->data->msound <= MS_ANIMAL)) {
1453         if (!alreadynamed(mtmp, monnambuf, buf))
1454 /*JP
1455             verbalize("I'm %s, not %s.", shkname(mtmp), buf);
1456 */
1457             verbalize("\8e\84\82Í%s\82¾\81C%s\82Å\82Í\82È\82¢\81D", shkname(mtmp), buf);
1458     } else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk) {
1459         if (!alreadynamed(mtmp, monnambuf, buf))
1460 /*JP
1461             pline("%s will not accept the name %s.", upstart(monnambuf), buf);
1462 */
1463             pline("%s\82Í%s\82Æ\82¢\82¤\96¼\91O\82ð\8eó\82¯\82¢\82ê\82È\82©\82Á\82½\81D", monnambuf, buf);
1464     } else
1465         (void) christen_monst(mtmp, buf);
1466 }
1467
1468 STATIC_VAR int via_naming = 0;
1469
1470 /*
1471  * This routine used to change the address of 'obj' so be unsafe if not
1472  * used with extreme care.  Applying a name to an object no longer
1473  * allocates a replacement object, so that old risk is gone.
1474  */
1475 STATIC_OVL
1476 void
1477 do_oname(obj)
1478 register struct obj *obj;
1479 {
1480     char *bufp, buf[BUFSZ], bufcpy[BUFSZ], qbuf[QBUFSZ];
1481     const char *aname;
1482     short objtyp;
1483
1484     /* Do this now because there's no point in even asking for a name */
1485     if (obj->otyp == SPE_NOVEL) {
1486 /*JP
1487         pline("%s already has a published name.", Ysimple_name2(obj));
1488 */
1489         pline("%s\82É\82Í\82·\82Å\82É\8fo\94Å\8e\9e\82Ì\96¼\91O\82ª\82 \82é\81D", Ysimple_name2(obj));
1490         return;
1491     }
1492
1493 #if 0 /*JP:T*/
1494     Sprintf(qbuf, "What do you want to name %s ",
1495             is_plural(obj) ? "these" : "this");
1496     (void) safe_qbuf(qbuf, qbuf, "?", obj, xname, simpleonames, "item");
1497 #else
1498     (void) safe_qbuf(qbuf, "", "\82ð\89½\82Æ\96¼\82Ã\82¯\82Ü\82·\82©\81H", obj, xname,
1499                      simpleonames, "\82»\82ê");
1500 #endif
1501     buf[0] = '\0';
1502 #ifdef EDIT_GETLIN
1503     /* if there's an existing name, make it be the default answer */
1504     if (has_oname(obj))
1505         Strcpy(buf, ONAME(obj));
1506 #endif
1507     getlin(qbuf, buf);
1508     if (!*buf || *buf == '\033')
1509         return;
1510     /* strip leading and trailing spaces; unnames item if all spaces */
1511     (void) mungspaces(buf);
1512
1513     /*
1514      * We don't violate illiteracy conduct here, although it is
1515      * arguable that we should for anything other than "X".  Doing so
1516      * would make attaching player's notes to hero's inventory have an
1517      * in-game effect, which may or may not be the correct thing to do.
1518      *
1519      * We do violate illiteracy in oname() if player creates Sting or
1520      * Orcrist, clearly being literate (no pun intended...).
1521      */
1522
1523     /* relax restrictions over proper capitalization for artifacts */
1524     if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp)
1525         Strcpy(buf, aname);
1526
1527     if (obj->oartifact) {
1528 /*JP
1529         pline_The("artifact seems to resist the attempt.");
1530 */
1531         pline("\90¹\8aí\82Í\96¼\82Ã\82¯\82ð\8b\91\94Û\82µ\82Ä\82¢\82é\82æ\82¤\82¾\81D");
1532         return;
1533     } else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) {
1534         /* this used to change one letter, substituting a value
1535            of 'a' through 'y' (due to an off by one error, 'z'
1536            would never be selected) and then force that to
1537            upper case if such was the case of the input;
1538            now, the hand slip scuffs one or two letters as if
1539            the text had been trodden upon, sometimes picking
1540            punctuation instead of an arbitrary letter;
1541            unfortunately, we have to cover the possibility of
1542            it targetting spaces so failing to make any change
1543            (we know that it must eventually target a nonspace
1544            because buf[] matches a valid artifact name) */
1545         Strcpy(bufcpy, buf);
1546         /* for "the Foo of Bar", only scuff "Foo of Bar" part */
1547         bufp = !strncmpi(bufcpy, "the ", 4) ? (buf + 4) : buf;
1548         do {
1549             wipeout_text(bufp, rn2_on_display_rng(2), (unsigned) 0);
1550         } while (!strcmp(buf, bufcpy));
1551 /*JP
1552         pline("While engraving, your %s slips.", body_part(HAND));
1553 */
1554         pline("\8d\8f\82ñ\82Å\82¢\82é\8aÔ\82É%s\82ª\8a\8a\82Á\82Ä\82µ\82Ü\82Á\82½\81D", body_part(HAND));
1555         display_nhwindow(WIN_MESSAGE, FALSE);
1556 /*JP
1557         You("engrave: \"%s\".", buf);
1558 */
1559         You("\8d\8f\82ñ\82¾: \81u%s\81v\81D",buf);
1560         /* violate illiteracy conduct since hero attempted to write
1561            a valid artifact name */
1562         u.uconduct.literate++;
1563     }
1564     ++via_naming; /* This ought to be an argument rather than a static... */
1565     obj = oname(obj, buf);
1566     --via_naming; /* ...but oname() is used in a lot of places, so defer. */
1567 }
1568
1569 struct obj *
1570 oname(obj, name)
1571 struct obj *obj;
1572 const char *name;
1573 {
1574     int lth;
1575     char buf[PL_PSIZ];
1576
1577     lth = *name ? (int) (strlen(name) + 1) : 0;
1578     if (lth > PL_PSIZ) {
1579         lth = PL_PSIZ;
1580 #if 0 /*JP*/
1581         name = strncpy(buf, name, PL_PSIZ - 1);
1582         buf[PL_PSIZ - 1] = '\0';
1583 #else
1584         if (is_kanji2(name, lth - 1))
1585             --lth;
1586         name = strncpy(buf, name, lth - 1);
1587         buf[lth - 1] = '\0';
1588 #endif
1589     }
1590     /* If named artifact exists in the game, do not create another.
1591      * Also trying to create an artifact shouldn't de-artifact
1592      * it (e.g. Excalibur from prayer). In this case the object
1593      * will retain its current name. */
1594     if (obj->oartifact || (lth && exist_artifact(obj->otyp, name)))
1595         return obj;
1596
1597     new_oname(obj, lth); /* removes old name if one is present */
1598     if (lth)
1599         Strcpy(ONAME(obj), name);
1600
1601     if (lth)
1602         artifact_exists(obj, name, TRUE);
1603     if (obj->oartifact) {
1604         /* can't dual-wield with artifact as secondary weapon */
1605         if (obj == uswapwep)
1606             untwoweapon();
1607         /* activate warning if you've just named your weapon "Sting" */
1608         if (obj == uwep)
1609             set_artifact_intrinsic(obj, TRUE, W_WEP);
1610         /* if obj is owned by a shop, increase your bill */
1611         if (obj->unpaid)
1612             alter_cost(obj, 0L);
1613         if (via_naming) {
1614             /* violate illiteracy conduct since successfully wrote arti-name */
1615             u.uconduct.literate++;
1616         }
1617     }
1618     if (carried(obj))
1619         update_inventory();
1620     return obj;
1621 }
1622
1623 static NEARDATA const char callable[] = {
1624     SCROLL_CLASS, POTION_CLASS, WAND_CLASS,  RING_CLASS, AMULET_CLASS,
1625     GEM_CLASS,    SPBOOK_CLASS, ARMOR_CLASS, TOOL_CLASS, 0
1626 };
1627
1628 boolean
1629 objtyp_is_callable(i)
1630 int i;
1631 {
1632     return (boolean) (objects[i].oc_uname
1633                       || (OBJ_DESCR(objects[i])
1634                           && index(callable, objects[i].oc_class)));
1635 }
1636
1637 /* C and #name commands - player can name monster or object or type of obj */
1638 int
1639 docallcmd()
1640 {
1641     struct obj *obj;
1642     winid win;
1643     anything any;
1644     menu_item *pick_list = 0;
1645     char ch, allowall[2];
1646     /* if player wants a,b,c instead of i,o when looting, do that here too */
1647     boolean abc = flags.lootabc;
1648
1649     win = create_nhwindow(NHW_MENU);
1650     start_menu(win);
1651     any = zeroany;
1652     any.a_char = 'm'; /* group accelerator 'C' */
1653     add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'C', ATR_NONE,
1654 /*JP
1655              "a monster", MENU_UNSELECTED);
1656 */
1657              "\89ö\95¨", MENU_UNSELECTED);
1658     if (invent) {
1659         /* we use y and n as accelerators so that we can accept user's
1660            response keyed to old "name an individual object?" prompt */
1661         any.a_char = 'i'; /* group accelerator 'y' */
1662         add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'y', ATR_NONE,
1663 /*JP
1664                  "a particular object in inventory", MENU_UNSELECTED);
1665 */
1666                  "\8e\9d\82¿\95¨\82Ì\92\86\82Ì\88ê\82Â\82Ì\83A\83C\83e\83\80", MENU_UNSELECTED);
1667         any.a_char = 'o'; /* group accelerator 'n' */
1668         add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'n', ATR_NONE,
1669 /*JP
1670                  "the type of an object in inventory", MENU_UNSELECTED);
1671 */
1672                  "\8e\9d\82¿\95¨\82Ì\92\86\82Ì\88ê\82Â\82Ì\83A\83C\83e\83\80\82Ì\8eí\97Þ", MENU_UNSELECTED);
1673     }
1674     any.a_char = 'f'; /* group accelerator ',' (or ':' instead?) */
1675     add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, ',', ATR_NONE,
1676 /*JP
1677              "the type of an object upon the floor", MENU_UNSELECTED);
1678 */
1679              "\8f°\82Ì\8fã\82É\82 \82é\88ê\82Â\82Ì\83A\83C\83e\83\80\82Ì\8eí\97Þ", MENU_UNSELECTED);
1680     any.a_char = 'd'; /* group accelerator '\' */
1681     add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, '\\', ATR_NONE,
1682 /*JP
1683              "the type of an object on discoveries list", MENU_UNSELECTED);
1684 */
1685              "\94­\8c©\95¨\88ê\97\97\82É\82 \82é\88ê\82Â\82Ì\83A\83C\83e\83\80\82Ì\8eí\97Þ", MENU_UNSELECTED);
1686     any.a_char = 'a'; /* group accelerator 'l' */
1687     add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'l', ATR_NONE,
1688 /*JP
1689              "record an annotation for the current level", MENU_UNSELECTED);
1690 */
1691              "\8c»\8dÝ\82Ì\8aK\82É\91Î\82·\82é\83\81\83\82\82Ì\8bL\98^", MENU_UNSELECTED);
1692 /*JP
1693     end_menu(win, "What do you want to name?");
1694 */
1695     end_menu(win, "\82Ç\82ê\82É\96¼\91O\82ð\82Â\82¯\82Ü\82·\82©\81H");
1696     if (select_menu(win, PICK_ONE, &pick_list) > 0) {
1697         ch = pick_list[0].item.a_char;
1698         free((genericptr_t) pick_list);
1699     } else
1700         ch = 'q';
1701     destroy_nhwindow(win);
1702
1703     switch (ch) {
1704     default:
1705     case 'q':
1706         break;
1707     case 'm': /* name a visible monster */
1708         do_mname();
1709         break;
1710     case 'i': /* name an individual object in inventory */
1711         allowall[0] = ALL_CLASSES;
1712         allowall[1] = '\0';
1713         obj = getobj(allowall, "name");
1714         if (obj)
1715             do_oname(obj);
1716         break;
1717     case 'o': /* name a type of object in inventory */
1718         obj = getobj(callable, "call");
1719         if (obj) {
1720             /* behave as if examining it in inventory;
1721                this might set dknown if it was picked up
1722                while blind and the hero can now see */
1723             (void) xname(obj);
1724
1725             if (!obj->dknown) {
1726 /*JP
1727                 You("would never recognize another one.");
1728 */
1729                 You("\91¼\82É\94F\8e¯\82Å\82«\82È\82¢\81D");
1730 #if 0
1731             } else if (!objtyp_is_callable(obj->otyp)) {
1732                 You("know those as well as you ever will.");
1733 #endif
1734             } else {
1735                 docall(obj);
1736             }
1737         }
1738         break;
1739     case 'f': /* name a type of object visible on the floor */
1740         namefloorobj();
1741         break;
1742     case 'd': /* name a type of object on the discoveries list */
1743         rename_disco();
1744         break;
1745     case 'a': /* annotate level */
1746         donamelevel();
1747         break;
1748     }
1749     return 0;
1750 }
1751
1752 /* for use by safe_qbuf() */
1753 STATIC_PTR char *
1754 docall_xname(obj)
1755 struct obj *obj;
1756 {
1757     struct obj otemp;
1758
1759     otemp = *obj;
1760     otemp.oextra = (struct oextra *) 0;
1761     otemp.quan = 1L;
1762     /* in case water is already known, convert "[un]holy water" to "water" */
1763     otemp.blessed = otemp.cursed = 0;
1764     /* remove attributes that are doname() caliber but get formatted
1765        by xname(); most of these fixups aren't really needed because the
1766        relevant type of object isn't callable so won't reach this far */
1767     if (otemp.oclass == WEAPON_CLASS)
1768         otemp.opoisoned = 0; /* not poisoned */
1769     else if (otemp.oclass == POTION_CLASS)
1770         otemp.odiluted = 0; /* not diluted */
1771     else if (otemp.otyp == TOWEL || otemp.otyp == STATUE)
1772         otemp.spe = 0; /* not wet or historic */
1773     else if (otemp.otyp == TIN)
1774         otemp.known = 0; /* suppress tin type (homemade, &c) and mon type */
1775     else if (otemp.otyp == FIGURINE)
1776         otemp.corpsenm = NON_PM; /* suppress mon type */
1777     else if (otemp.otyp == HEAVY_IRON_BALL)
1778         otemp.owt = objects[HEAVY_IRON_BALL].oc_weight; /* not "very heavy" */
1779     else if (otemp.oclass == FOOD_CLASS && otemp.globby)
1780         otemp.owt = 120; /* 6*20, neither a small glob nor a large one */
1781
1782     return an(xname(&otemp));
1783 }
1784
1785 void
1786 docall(obj)
1787 struct obj *obj;
1788 {
1789     char buf[BUFSZ], qbuf[QBUFSZ];
1790     char **str1;
1791
1792     if (!obj->dknown)
1793         return; /* probably blind */
1794     flush_screen(1); /* buffered updates might matter to player's response */
1795
1796     if (obj->oclass == POTION_CLASS && obj->fromsink)
1797         /* kludge, meaning it's sink water */
1798 /*JP
1799         Sprintf(qbuf, "Call a stream of %s fluid:",
1800 */
1801         Sprintf(qbuf, "%s\89t\91Ì:",
1802                 OBJ_DESCR(objects[obj->otyp]));
1803     else
1804 #if 0 /*JP:T*/
1805         (void) safe_qbuf(qbuf, "Call ", ":", obj,
1806                          docall_xname, simpleonames, "thing");
1807 #else
1808         (void) safe_qbuf(qbuf, "", "\82É\89½\82Æ\96¼\91O\82ð\95t\82¯\82é\81H", obj,
1809                          docall_xname, simpleonames, "\82±\82ê");
1810 #endif
1811     /* pointer to old name */
1812     str1 = &(objects[obj->otyp].oc_uname);
1813     buf[0] = '\0';
1814 #ifdef EDIT_GETLIN
1815     /* if there's an existing name, make it be the default answer */
1816     if (*str1)
1817         Strcpy(buf, *str1);
1818 #endif
1819     getlin(qbuf, buf);
1820     if (!*buf || *buf == '\033')
1821         return;
1822
1823     /* clear old name */
1824     if (*str1)
1825         free((genericptr_t) *str1);
1826
1827     /* strip leading and trailing spaces; uncalls item if all spaces */
1828     (void) mungspaces(buf);
1829     if (!*buf) {
1830         if (*str1) { /* had name, so possibly remove from disco[] */
1831             /* strip name first, for the update_inventory() call
1832                from undiscover_object() */
1833             *str1 = (char *) 0;
1834             undiscover_object(obj->otyp);
1835         }
1836     } else {
1837         *str1 = dupstr(buf);
1838         discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
1839     }
1840 }
1841
1842 STATIC_OVL void
1843 namefloorobj()
1844 {
1845     coord cc;
1846     int glyph;
1847     char buf[BUFSZ];
1848     struct obj *obj = 0;
1849 #if 0 /*JP*/
1850     boolean fakeobj = FALSE, use_plural;
1851 #else
1852     boolean fakeobj = FALSE;
1853 #endif
1854
1855     cc.x = u.ux, cc.y = u.uy;
1856     /* "dot for under/over you" only makes sense when the cursor hasn't
1857        been moved off the hero's '@' yet, but there's no way to adjust
1858        the help text once getpos() has started */
1859 #if 0 /*JP:T*/
1860     Sprintf(buf, "object on map (or '.' for one %s you)",
1861             (u.uundetected && hides_under(youmonst.data)) ? "over" : "under");
1862 #else
1863     Strcpy(buf, "\92n\90}\8fã\82Ì\95¨\91Ì(\82 \82é\82¢\82Í'.'\82Å\82 \82È\82½\82Ì\82¢\82é\8fê\8f\8a");
1864 #endif
1865     if (getpos(&cc, FALSE, buf) < 0 || cc.x <= 0)
1866         return;
1867     if (cc.x == u.ux && cc.y == u.uy) {
1868         obj = vobj_at(u.ux, u.uy);
1869     } else {
1870         glyph = glyph_at(cc.x, cc.y);
1871         if (glyph_is_object(glyph))
1872             fakeobj = object_from_map(glyph, cc.x, cc.y, &obj);
1873         /* else 'obj' stays null */
1874     }
1875     if (!obj) {
1876         /* "under you" is safe here since there's no object to hide under */
1877 #if 0 /*JP:T*/
1878         pline("There doesn't seem to be any object %s.",
1879               (cc.x == u.ux && cc.y == u.uy) ? "under you" : "there");
1880 #else
1881         pline("%s\82É\82Í\89½\82à\82È\82¢\82æ\82¤\82¾\81D",
1882               (cc.x == u.ux && cc.y == u.uy) ? "\82 \82È\82½\82Ì\89º" : "\82»\82±");
1883 #endif
1884         return;
1885     }
1886     /* note well: 'obj' might be an instance of STRANGE_OBJECT if target
1887        is a mimic; passing that to xname (directly or via simpleonames)
1888        would yield "glorkum" so we need to handle it explicitly; it will
1889        always fail the Hallucination test and pass the !callable test,
1890        resulting in the "can't be assigned a type name" message */
1891     Strcpy(buf, (obj->otyp != STRANGE_OBJECT)
1892                  ? simpleonames(obj)
1893                  : obj_descr[STRANGE_OBJECT].oc_name);
1894 #if 0 /*JP*/
1895     use_plural = (obj->quan > 1L);
1896 #endif
1897     if (Hallucination) {
1898         const char *unames[6];
1899         char tmpbuf[BUFSZ];
1900
1901         /* straight role name */
1902         unames[0] = ((Upolyd ? u.mfemale : flags.female) && urole.name.f)
1903                      ? urole.name.f
1904                      : urole.name.m;
1905         /* random rank title for hero's role
1906
1907            note: the 30 is hardcoded in xlev_to_rank, so should be
1908            hardcoded here too */
1909         unames[1] = rank_of(rn2_on_display_rng(30) + 1,
1910                             Role_switch, flags.female);
1911         /* random fake monster */
1912         unames[2] = bogusmon(tmpbuf, (char *) 0);
1913         /* increased chance for fake monster */
1914         unames[3] = unames[2];
1915         /* traditional */
1916         unames[4] = roguename();
1917         /* silly */
1918 /*JP
1919         unames[5] = "Wibbly Wobbly";
1920 */
1921         unames[5] = "\82¤\82ë\82¤\82ë";
1922 #if 0 /*JP:T*/
1923         pline("%s %s to call you \"%s.\"",
1924               The(buf), use_plural ? "decide" : "decides",
1925               unames[rn2_on_display_rng(SIZE(unames))]);
1926 #else
1927         pline("%s\82Í\82 \82È\82½\82ð\81u%s\81v\82Æ\8cÄ\82Ô\82±\82Æ\82É\8c\88\82ß\82½\81D",
1928               buf,
1929               unames[rn2_on_display_rng(SIZE(unames))]);
1930 #endif
1931     } else if (!objtyp_is_callable(obj->otyp)) {
1932 #if 0 /*JP:T*/
1933         pline("%s %s can't be assigned a type name.",
1934               use_plural ? "Those" : "That", buf);
1935 #else
1936         pline("%s\82É\8eí\97Þ\82Ì\96¼\91O\82ð\8a\84\82è\93\96\82Ä\82é\82±\82Æ\82Í\82Å\82«\82È\82¢\81D",
1937               buf);
1938 #endif
1939     } else if (!obj->dknown) {
1940 #if 0 /*JP:T*/
1941         You("don't know %s %s well enough to name %s.",
1942             use_plural ? "those" : "that", buf, use_plural ? "them" : "it");
1943 #else
1944         You("\96¼\91O\82ð\95t\82¯\82ç\82ê\82é\82Ù\82Ç%s\82Ì\82±\82Æ\82ð\82æ\82­\92m\82ç\82È\82¢\81D",
1945             buf);
1946 #endif
1947     } else {
1948         docall(obj);
1949     }
1950     if (fakeobj) {
1951         obj->where = OBJ_FREE; /* object_from_map() sets it to OBJ_FLOOR */
1952         dealloc_obj(obj);
1953     }
1954 }
1955
1956 static const char *const ghostnames[] = {
1957     /* these names should have length < PL_NSIZ */
1958     /* Capitalize the names for aesthetics -dgk */
1959     "Adri",    "Andries",       "Andreas",     "Bert",    "David",  "Dirk",
1960     "Emile",   "Frans",         "Fred",        "Greg",    "Hether", "Jay",
1961     "John",    "Jon",           "Karnov",      "Kay",     "Kenny",  "Kevin",
1962     "Maud",    "Michiel",       "Mike",        "Peter",   "Robert", "Ron",
1963     "Tom",     "Wilmar",        "Nick Danger", "Phoenix", "Jiro",   "Mizue",
1964     "Stephan", "Lance Braccus", "Shadowhawk"
1965 };
1966
1967 /* ghost names formerly set by x_monnam(), now by makemon() instead */
1968 const char *
1969 rndghostname()
1970 {
1971     return rn2(7) ? ghostnames[rn2(SIZE(ghostnames))] : (const char *) plname;
1972 }
1973
1974 /*
1975  * Monster naming functions:
1976  * x_monnam is the generic monster-naming function.
1977  *                seen        unseen       detected               named
1978  * mon_nam:     the newt        it      the invisible orc       Fido
1979  * noit_mon_nam:the newt (as if detected) the invisible orc     Fido
1980  * l_monnam:    newt            it      invisible orc           dog called Fido
1981  * Monnam:      The newt        It      The invisible orc       Fido
1982  * noit_Monnam: The newt (as if detected) The invisible orc     Fido
1983  * Adjmonnam:   The poor newt   It      The poor invisible orc  The poor Fido
1984  * Amonnam:     A newt          It      An invisible orc        Fido
1985  * a_monnam:    a newt          it      an invisible orc        Fido
1986  * m_monnam:    newt            xan     orc                     Fido
1987  * y_monnam:    your newt     your xan  your invisible orc      Fido
1988  * noname_monnam(mon,article):
1989  *              article newt    art xan art invisible orc       art dog
1990  */
1991
1992 /* Bug: if the monster is a priest or shopkeeper, not every one of these
1993  * options works, since those are special cases.
1994  */
1995 char *
1996 x_monnam(mtmp, article, adjective, suppress, called)
1997 register struct monst *mtmp;
1998 int article;
1999 /* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious
2000  * ARTICLE_YOUR: "your" on pets, "the" on everything else
2001  *
2002  * If the monster would be referred to as "it" or if the monster has a name
2003  * _and_ there is no adjective, "invisible", "saddled", etc., override this
2004  * and always use no article.
2005  */
2006 const char *adjective;
2007 int suppress;
2008 /* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE.
2009  * EXACT_NAME: combination of all the above
2010  * SUPPRESS_NAME: omit monster's assigned name (unless uniq w/ pname).
2011  */
2012 boolean called;
2013 {
2014     char *buf = nextmbuf();
2015     struct permonst *mdat = mtmp->data;
2016     const char *pm_name = mdat->mname;
2017     boolean do_hallu, do_invis, do_it, do_saddle, do_name;
2018 #if 0 /*JP*/
2019     boolean name_at_start, has_adjectives;
2020     char *bp;
2021 #endif
2022
2023     if (program_state.gameover)
2024         suppress |= SUPPRESS_HALLUCINATION;
2025     if (article == ARTICLE_YOUR && !mtmp->mtame)
2026         article = ARTICLE_THE;
2027
2028     do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION);
2029     do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE);
2030     do_it = !canspotmon(mtmp) && article != ARTICLE_YOUR
2031             && !program_state.gameover && mtmp != u.usteed
2032             && !(u.uswallow && mtmp == u.ustuck) && !(suppress & SUPPRESS_IT);
2033     do_saddle = !(suppress & SUPPRESS_SADDLE);
2034     do_name = !(suppress & SUPPRESS_NAME) || type_is_pname(mdat);
2035
2036     buf[0] = '\0';
2037
2038     /* unseen monsters, etc.  Use "it" */
2039     if (do_it) {
2040 /*JP
2041         Strcpy(buf, "it");
2042 */
2043         Strcpy(buf, "\89½\8eÒ\82©");
2044         return buf;
2045     }
2046
2047     /* priests and minions: don't even use this function */
2048     if (mtmp->ispriest || mtmp->isminion) {
2049         char priestnambuf[BUFSZ];
2050         char *name;
2051         long save_prop = EHalluc_resistance;
2052         unsigned save_invis = mtmp->minvis;
2053
2054         /* when true name is wanted, explicitly block Hallucination */
2055         if (!do_hallu)
2056             EHalluc_resistance = 1L;
2057         if (!do_invis)
2058             mtmp->minvis = 0;
2059         name = priestname(mtmp, priestnambuf);
2060         EHalluc_resistance = save_prop;
2061         mtmp->minvis = save_invis;
2062 #if 0 /*JP*/
2063         if (article == ARTICLE_NONE && !strncmp(name, "the ", 4))
2064             name += 4;
2065 #endif
2066         return strcpy(buf, name);
2067     }
2068     /* an "aligned priest" not flagged as a priest or minion should be
2069        "priest" or "priestess" (normally handled by priestname()) */
2070     if (mdat == &mons[PM_ALIGNED_PRIEST])
2071 /*JP
2072         pm_name = mtmp->female ? "priestess" : "priest";
2073 */
2074         pm_name = mtmp->female ? "\93ò\91m" : "\91m\97µ";
2075     else if (mdat == &mons[PM_HIGH_PRIEST] && mtmp->female)
2076 /*JP
2077         pm_name = "high priestess";
2078 */
2079         pm_name = "\96@\89¤";
2080
2081     /* Shopkeepers: use shopkeeper name.  For normal shopkeepers, just
2082      * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
2083      * shopkeeper" or "Asidonhopo the blue dragon".  If hallucinating,
2084      * none of this applies.
2085      */
2086     if (mtmp->isshk && !do_hallu) {
2087 #if 0 /*JP*/
2088         if (adjective && article == ARTICLE_THE) {
2089             /* pathological case: "the angry Asidonhopo the blue dragon"
2090                sounds silly */
2091             Strcpy(buf, "the ");
2092             Strcat(strcat(buf, adjective), " ");
2093             Strcat(buf, shkname(mtmp));
2094             return buf;
2095         }
2096         Strcat(buf, shkname(mtmp));
2097         if (mdat == &mons[PM_SHOPKEEPER] && !do_invis)
2098             return buf;
2099         Strcat(buf, " the ");
2100         if (do_invis)
2101             Strcat(buf, "invisible ");
2102         Strcat(buf, pm_name);
2103         return buf;
2104 #else
2105         if (mdat == &mons[PM_SHOPKEEPER] && !do_invis){
2106             Strcpy(buf, shkname(mtmp));
2107         } else {
2108             Sprintf(buf, "%s\82Æ\82¢\82¤\96¼\82Ì%s%s",
2109                     shkname(mtmp), do_invis ? "\8ep\82Ì\8c©\82¦\82È\82¢" : "",
2110                     pm_name);
2111         }
2112         return buf;
2113 #endif
2114     }
2115
2116     /* Put the adjectives in the buffer */
2117     if (adjective)
2118 /*JP
2119         Strcat(strcat(buf, adjective), " ");
2120 */
2121         Strcat(buf, adjective);
2122     if (do_invis)
2123 /*JP
2124         Strcat(buf, "invisible ");
2125 */
2126         Strcat(buf, "\8ep\82Ì\8c©\82¦\82È\82¢");
2127     if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind
2128         && !Hallucination)
2129 /*JP
2130         Strcat(buf, "saddled ");
2131 */
2132         Strcat(buf, "\88Æ\82Ì\82Â\82¢\82Ä\82¢\82é");
2133 #if 0 /*JP*/
2134     has_adjectives = (buf[0] != '\0');
2135 #endif
2136
2137     /* Put the actual monster name or type into the buffer now.
2138        Remember whether the buffer starts with a personal name. */
2139     if (do_hallu) {
2140         char rnamecode;
2141         char *rname = rndmonnam(&rnamecode);
2142
2143         Strcat(buf, rname);
2144 #if 0 /*JP*/
2145         name_at_start = bogon_is_pname(rnamecode);
2146 #endif
2147     } else if (do_name && has_mname(mtmp)) {
2148         char *name = MNAME(mtmp);
2149
2150         if (mdat == &mons[PM_GHOST]) {
2151 /*JP
2152             Sprintf(eos(buf), "%s ghost", s_suffix(name));
2153 */
2154             Sprintf(buf, "%s\82Ì\97H\97ì", name);
2155 #if 0 /*JP*/
2156             name_at_start = TRUE;
2157 #endif
2158         } else if (called) {
2159 /*JP
2160             Sprintf(eos(buf), "%s called %s", pm_name, name);
2161 */
2162             Sprintf(eos(buf), "%s\82Æ\82¢\82¤\96¼\82Ì%s", name, pm_name);
2163 #if 0 /*JP*/
2164             name_at_start = (boolean) type_is_pname(mdat);
2165 #endif
2166 #if 0 /*JP*//*\92è\8a¥\8e\8c\82Ì\8f\88\97\9d\82Í\95s\97v*/
2167         } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) {
2168             /* <name> the <adjective> <invisible> <saddled> <rank> */
2169             char pbuf[BUFSZ];
2170
2171             Strcpy(pbuf, name);
2172             pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */
2173             if (has_adjectives)
2174                 Strcat(pbuf, buf);
2175             Strcat(pbuf, bp + 5); /* append the rest of the name */
2176             Strcpy(buf, pbuf);
2177             article = ARTICLE_NONE;
2178             name_at_start = TRUE;
2179 #endif
2180         } else {
2181             Strcat(buf, name);
2182 #if 0 /*JP*/
2183             name_at_start = TRUE;
2184 #endif
2185         }
2186     } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) {
2187         char pbuf[BUFSZ];
2188
2189         Strcpy(pbuf, rank_of((int) mtmp->m_lev, monsndx(mdat),
2190                              (boolean) mtmp->female));
2191 #if 0 /*JP*/
2192         Strcat(buf, lcase(pbuf));
2193 #else
2194         Strcat(buf, pbuf);
2195 #endif
2196 #if 0 /*JP*/
2197         name_at_start = FALSE;
2198 #endif
2199     } else {
2200         Strcat(buf, pm_name);
2201 #if 0 /*JP*/
2202         name_at_start = (boolean) type_is_pname(mdat);
2203 #endif
2204     }
2205
2206 #if 0 /*JP*//*\93ú\96{\8cê\82É\8a¥\8e\8c\82Í\82È\82¢*/
2207     if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) {
2208         if (mdat == &mons[PM_WIZARD_OF_YENDOR])
2209             article = ARTICLE_THE;
2210         else
2211             article = ARTICLE_NONE;
2212     } else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) {
2213         article = ARTICLE_THE;
2214     }
2215
2216     {
2217         char buf2[BUFSZ];
2218
2219         switch (article) {
2220         case ARTICLE_YOUR:
2221             Strcpy(buf2, "your ");
2222             Strcat(buf2, buf);
2223             Strcpy(buf, buf2);
2224             return buf;
2225         case ARTICLE_THE:
2226             Strcpy(buf2, "the ");
2227             Strcat(buf2, buf);
2228             Strcpy(buf, buf2);
2229             return buf;
2230         case ARTICLE_A:
2231             return an(buf);
2232         case ARTICLE_NONE:
2233         default:
2234             return buf;
2235         }
2236     }
2237 #else
2238     return buf;
2239 #endif
2240 }
2241
2242 char *
2243 l_monnam(mtmp)
2244 struct monst *mtmp;
2245 {
2246     return x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
2247                     (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, TRUE);
2248 }
2249
2250 char *
2251 mon_nam(mtmp)
2252 struct monst *mtmp;
2253 {
2254     return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2255                     (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, FALSE);
2256 }
2257
2258 /* print the name as if mon_nam() was called, but assume that the player
2259  * can always see the monster--used for probing and for monsters aggravating
2260  * the player with a cursed potion of invisibility
2261  */
2262 char *
2263 noit_mon_nam(mtmp)
2264 struct monst *mtmp;
2265 {
2266     return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2267                     (has_mname(mtmp)) ? (SUPPRESS_SADDLE | SUPPRESS_IT)
2268                                       : SUPPRESS_IT,
2269                     FALSE);
2270 }
2271
2272 char *
2273 Monnam(mtmp)
2274 struct monst *mtmp;
2275 {
2276     register char *bp = mon_nam(mtmp);
2277
2278     *bp = highc(*bp);
2279     return  bp;
2280 }
2281
2282 char *
2283 noit_Monnam(mtmp)
2284 struct monst *mtmp;
2285 {
2286     register char *bp = noit_mon_nam(mtmp);
2287
2288     *bp = highc(*bp);
2289     return  bp;
2290 }
2291
2292 /* return "a dog" rather than "Fido", honoring hallucination and visibility */
2293 char *
2294 noname_monnam(mtmp, article)
2295 struct monst *mtmp;
2296 int article;
2297 {
2298     return x_monnam(mtmp, article, (char *) 0, SUPPRESS_NAME, FALSE);
2299 }
2300
2301 /* monster's own name -- overrides hallucination and [in]visibility
2302    so shouldn't be used in ordinary messages (mainly for disclosure) */
2303 char *
2304 m_monnam(mtmp)
2305 struct monst *mtmp;
2306 {
2307     return x_monnam(mtmp, ARTICLE_NONE, (char *) 0, EXACT_NAME, FALSE);
2308 }
2309
2310 /* pet name: "your little dog" */
2311 char *
2312 y_monnam(mtmp)
2313 struct monst *mtmp;
2314 {
2315     int prefix, suppression_flag;
2316
2317     prefix = mtmp->mtame ? ARTICLE_YOUR : ARTICLE_THE;
2318     suppression_flag = (has_mname(mtmp)
2319                         /* "saddled" is redundant when mounted */
2320                         || mtmp == u.usteed)
2321                            ? SUPPRESS_SADDLE
2322                            : 0;
2323
2324     return x_monnam(mtmp, prefix, (char *) 0, suppression_flag, FALSE);
2325 }
2326
2327 char *
2328 Adjmonnam(mtmp, adj)
2329 struct monst *mtmp;
2330 const char *adj;
2331 {
2332     char *bp = x_monnam(mtmp, ARTICLE_THE, adj,
2333                         has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2334
2335     *bp = highc(*bp);
2336     return  bp;
2337 }
2338
2339 char *
2340 a_monnam(mtmp)
2341 struct monst *mtmp;
2342 {
2343     return x_monnam(mtmp, ARTICLE_A, (char *) 0,
2344                     has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2345 }
2346
2347 char *
2348 Amonnam(mtmp)
2349 struct monst *mtmp;
2350 {
2351     char *bp = a_monnam(mtmp);
2352
2353     *bp = highc(*bp);
2354     return  bp;
2355 }
2356
2357 /* used for monster ID by the '/', ';', and 'C' commands to block remote
2358    identification of the endgame altars via their attending priests */
2359 char *
2360 distant_monnam(mon, article, outbuf)
2361 struct monst *mon;
2362 int article; /* only ARTICLE_NONE and ARTICLE_THE are handled here */
2363 char *outbuf;
2364 {
2365     /* high priest(ess)'s identity is concealed on the Astral Plane,
2366        unless you're adjacent (overridden for hallucination which does
2367        its own obfuscation) */
2368     if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination
2369         && Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) {
2370 #if 0 /*JP:T*/
2371         Strcpy(outbuf, article == ARTICLE_THE ? "the " : "");
2372         Strcat(outbuf, mon->female ? "high priestess" : "high priest");
2373 #else
2374         Strcpy(outbuf, "\96@\89¤");
2375 #endif
2376     } else {
2377         Strcpy(outbuf, x_monnam(mon, article, (char *) 0, 0, TRUE));
2378     }
2379     return outbuf;
2380 }
2381
2382 /* returns mon_nam(mon) relative to other_mon; normal name unless they're
2383    the same, in which case the reference is to {him|her|it} self */
2384 char *
2385 mon_nam_too(mon, other_mon)
2386 struct monst *mon, *other_mon;
2387 {
2388     char *outbuf;
2389
2390     if (mon != other_mon) {
2391         outbuf = mon_nam(mon);
2392     } else {
2393         outbuf = nextmbuf();
2394 #if 0 /*JP*/
2395         switch (pronoun_gender(mon, FALSE)) {
2396         case 0:
2397             Strcpy(outbuf, "himself");
2398             break;
2399         case 1:
2400             Strcpy(outbuf, "herself");
2401             break;
2402         default:
2403             Strcpy(outbuf, "itself");
2404             break;
2405         }
2406 #else
2407         Strcpy(outbuf, "\8e©\95ª\8e©\90g");
2408 #endif
2409     }
2410     return outbuf;
2411 }
2412
2413 /* for debugging messages, where data might be suspect and we aren't
2414    taking what the hero does or doesn't know into consideration */
2415 char *
2416 minimal_monnam(mon, ckloc)
2417 struct monst *mon;
2418 boolean ckloc;
2419 {
2420     struct permonst *ptr;
2421     char *outbuf = nextmbuf();
2422
2423     if (!mon) {
2424         Strcpy(outbuf, "[Null monster]");
2425     } else if ((ptr = mon->data) == 0) {
2426         Strcpy(outbuf, "[Null mon->data]");
2427     } else if (ptr < &mons[0]) {
2428         Sprintf(outbuf, "[Invalid mon->data %s < %s]",
2429                 fmt_ptr((genericptr_t) mon->data),
2430                 fmt_ptr((genericptr_t) &mons[0]));
2431     } else if (ptr >= &mons[NUMMONS]) {
2432         Sprintf(outbuf, "[Invalid mon->data %s >= %s]",
2433                 fmt_ptr((genericptr_t) mon->data),
2434                 fmt_ptr((genericptr_t) &mons[NUMMONS]));
2435     } else if (ckloc && ptr == &mons[PM_LONG_WORM]
2436                && level.monsters[mon->mx][mon->my] != mon) {
2437         Sprintf(outbuf, "%s <%d,%d>",
2438                 mons[PM_LONG_WORM_TAIL].mname, mon->mx, mon->my);
2439     } else {
2440         Sprintf(outbuf, "%s%s <%d,%d>",
2441                 mon->mtame ? "tame " : mon->mpeaceful ? "peaceful " : "",
2442                 mon->data->mname, mon->mx, mon->my);
2443         if (mon->cham != NON_PM)
2444             Sprintf(eos(outbuf), "{%s}", mons[mon->cham].mname);
2445     }
2446     return outbuf;
2447 }
2448
2449 /* fake monsters used to be in a hard-coded array, now in a data file */
2450 STATIC_OVL char *
2451 bogusmon(buf, code)
2452 char *buf, *code;
2453 {
2454     static const char bogon_codes[] = "-_+|="; /* see dat/bonusmon.txt */
2455     char *mname = buf;
2456
2457     if (code)
2458         *code = '\0';
2459     /* might fail (return empty buf[]) if the file isn't available */
2460     get_rnd_text(BOGUSMONFILE, buf, rn2_on_display_rng);
2461     if (!*mname) {
2462         Strcpy(buf, "bogon");
2463     } else if (index(bogon_codes, *mname)) { /* strip prefix if present */
2464         if (code)
2465             *code = *mname;
2466         ++mname;
2467     }
2468     return mname;
2469 }
2470
2471 /* return a random monster name, for hallucination */
2472 char *
2473 rndmonnam(code)
2474 char *code;
2475 {
2476     static char buf[BUFSZ];
2477     char *mname;
2478     int name;
2479 #define BOGUSMONSIZE 100 /* arbitrary */
2480
2481     if (code)
2482         *code = '\0';
2483
2484     do {
2485         name = rn2_on_display_rng(SPECIAL_PM + BOGUSMONSIZE - LOW_PM) + LOW_PM;
2486     } while (name < SPECIAL_PM
2487              && (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN)));
2488
2489     if (name >= SPECIAL_PM) {
2490         mname = bogusmon(buf, code);
2491     } else {
2492         mname = strcpy(buf, mons[name].mname);
2493     }
2494     return mname;
2495 #undef BOGUSMONSIZE
2496 }
2497
2498 /* check bogusmon prefix to decide whether it's a personal name */
2499 boolean
2500 bogon_is_pname(code)
2501 char code;
2502 {
2503     if (!code)
2504         return FALSE;
2505     return index("-+=", code) ? TRUE : FALSE;
2506 }
2507
2508 /* name of a Rogue player */
2509 const char *
2510 roguename()
2511 {
2512     char *i, *opts;
2513
2514     if ((opts = nh_getenv("ROGUEOPTS")) != 0) {
2515         for (i = opts; *i; i++)
2516             if (!strncmp("name=", i, 5)) {
2517                 char *j;
2518                 if ((j = index(i + 5, ',')) != 0)
2519                     *j = (char) 0;
2520                 return i + 5;
2521             }
2522     }
2523     /*JP:Rogue\82Ì\8aJ\94­\8eÒ\82Ì\96¼\91O*/
2524     return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
2525                   : "Glenn Wichman";
2526 }
2527
2528 static NEARDATA const char *const hcolors[] = {
2529 #if 0 /*JP:T*/
2530     "ultraviolet", "infrared", "bluish-orange", "reddish-green", "dark white",
2531     "light black", "sky blue-pink", "salty", "sweet", "sour", "bitter",
2532     "striped", "spiral", "swirly", "plaid", "checkered", "argyle", "paisley",
2533     "blotchy", "guernsey-spotted", "polka-dotted", "square", "round",
2534     "triangular", "cabernet", "sangria", "fuchsia", "wisteria", "lemon-lime",
2535     "strawberry-banana", "peppermint", "romantic", "incandescent",
2536     "octarine", /* Discworld: the Colour of Magic */
2537 #else
2538     "\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Ì",
2539     "\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¢",
2540     "\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Ì",
2541     "\82µ\82Ý\8fó\82Ì", "\90Â\90F\82Ì\94Á\93_\8fó\82Ì", "\93_\8fó\82Ì", "\8el\8ap\8c`\8fó\82Ì", "\8aÛ\8fó\82Ì",
2542     "\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Ì",
2543     "ä\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Ì",
2544     "\83I\83N\83^\83\8a\83\93\90F\82Ì",
2545 #endif
2546 };
2547
2548 const char *
2549 hcolor(colorpref)
2550 const char *colorpref;
2551 {
2552     return (Hallucination || !colorpref)
2553         ? hcolors[rn2_on_display_rng(SIZE(hcolors))]
2554         : colorpref;
2555 }
2556
2557 /* return a random real color unless hallucinating */
2558 const char *
2559 rndcolor()
2560 {
2561     int k = rn2(CLR_MAX);
2562
2563     return Hallucination ? hcolor((char *) 0)
2564 /*JP
2565                          : (k == NO_COLOR) ? "colorless"
2566 */
2567                          : (k == NO_COLOR) ? "\96³\90F\82Ì"
2568                                            : c_obj_colors[k];
2569 }
2570
2571 static NEARDATA const char *const hliquids[] = {
2572 #if 0 /*JP:T*/
2573     "yoghurt", "oobleck", "clotted blood", "diluted water", "purified water",
2574     "instant coffee", "tea", "herbal infusion", "liquid rainbow",
2575     "creamy foam", "mulled wine", "bouillon", "nectar", "grog", "flubber",
2576     "ketchup", "slow light", "oil", "vinaigrette", "liquid crystal", "honey",
2577     "caramel sauce", "ink", "aqueous humour", "milk substitute",
2578     "fruit juice", "glowing lava", "gastric acid", "mineral water",
2579     "cough syrup", "quicksilver", "sweet vitriol", "grey goo", "pink slime",
2580 #else
2581     "\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",
2582     "\83C\83\93\83X\83^\83\93\83g\83R\81[\83q\81[", "\8dg\92\83", "\83n\81[\83u\89t", "\89t\91Ì\82Ì\93ø",
2583     "\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[",
2584     "\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¨",
2585     "\83J\83\89\83\81\83\8b\83\\81[\83X", "\83C\83\93\83N", "\96[\90\85", "\91ã\97p\93û",
2586     "\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[",
2587     "\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",
2588 #endif
2589 };
2590
2591 const char *
2592 hliquid(liquidpref)
2593 const char *liquidpref;
2594 {
2595     return (Hallucination || !liquidpref) ? hliquids[rn2(SIZE(hliquids))]
2596                                           : liquidpref;
2597 }
2598
2599 /* Aliases for road-runner nemesis
2600  */
2601 static const char *const coynames[] = {
2602     "Carnivorous Vulgaris", "Road-Runnerus Digestus", "Eatibus Anythingus",
2603     "Famishus-Famishus", "Eatibus Almost Anythingus", "Eatius Birdius",
2604     "Famishius Fantasticus", "Eternalii Famishiis", "Famishus Vulgarus",
2605     "Famishius Vulgaris Ingeniusi", "Eatius-Slobbius", "Hardheadipus Oedipus",
2606     "Carnivorous Slobbius", "Hard-Headipus Ravenus", "Evereadii Eatibus",
2607     "Apetitius Giganticus", "Hungrii Flea-Bagius", "Overconfidentii Vulgaris",
2608     "Caninus Nervous Rex", "Grotesques Appetitus", "Nemesis Ridiculii",
2609     "Canis latrans"
2610 };
2611
2612 char *
2613 coyotename(mtmp, buf)
2614 struct monst *mtmp;
2615 char *buf;
2616 {
2617     if (mtmp && buf) {
2618         Sprintf(buf, "%s - %s",
2619                 x_monnam(mtmp, ARTICLE_NONE, (char *) 0, 0, TRUE),
2620                 mtmp->mcan ? coynames[SIZE(coynames) - 1]
2621                            : coynames[mtmp->m_id % (SIZE(coynames) - 1)]);
2622     }
2623     return buf;
2624 }
2625
2626 char *
2627 rndorcname(s)
2628 char *s;
2629 {
2630     static const char *v[] = { "a", "ai", "og", "u" };
2631     static const char *snd[] = { "gor", "gris", "un", "bane", "ruk",
2632                                  "oth","ul", "z", "thos","akh","hai" };
2633     int i, iend = rn1(2, 3), vstart = rn2(2);
2634
2635     if (s) {
2636         *s = '\0';
2637         for (i = 0; i < iend; ++i) {
2638             vstart = 1 - vstart;                /* 0 -> 1, 1 -> 0 */
2639             Sprintf(eos(s), "%s%s", (i > 0 && !rn2(30)) ? "-" : "",
2640                     vstart ? v[rn2(SIZE(v))] : snd[rn2(SIZE(snd))]);
2641         }
2642     }
2643     return s;
2644 }
2645
2646 struct monst *
2647 christen_orc(mtmp, gang, other)
2648 struct monst *mtmp;
2649 const char *gang, *other;
2650 {
2651     int sz = 0;
2652     char buf[BUFSZ], buf2[BUFSZ], *orcname;
2653
2654     orcname = rndorcname(buf2);
2655     sz = (int) strlen(orcname);
2656     if (gang)
2657         sz += (int) (strlen(gang) + sizeof " of " - sizeof "");
2658     else if (other)
2659         sz += (int) strlen(other);
2660
2661     if (sz < BUFSZ) {
2662         char gbuf[BUFSZ];
2663         boolean nameit = FALSE;
2664
2665         if (gang && orcname) {
2666             Sprintf(buf, "%s of %s", upstart(orcname),
2667                     upstart(strcpy(gbuf, gang)));
2668             nameit = TRUE;
2669         } else if (other && orcname) {
2670             Sprintf(buf, "%s%s", upstart(orcname), other);
2671             nameit = TRUE;
2672         }
2673         if (nameit)
2674             mtmp = christen_monst(mtmp, buf);
2675     }
2676     return mtmp;
2677 }
2678
2679 /* make sure "The Colour of Magic" remains the first entry in here */
2680 static const char *const sir_Terry_novels[] = {
2681     "The Colour of Magic", "The Light Fantastic", "Equal Rites", "Mort",
2682     "Sourcery", "Wyrd Sisters", "Pyramids", "Guards! Guards!", "Eric",
2683     "Moving Pictures", "Reaper Man", "Witches Abroad", "Small Gods",
2684     "Lords and Ladies", "Men at Arms", "Soul Music", "Interesting Times",
2685     "Maskerade", "Feet of Clay", "Hogfather", "Jingo", "The Last Continent",
2686     "Carpe Jugulum", "The Fifth Elephant", "The Truth", "Thief of Time",
2687     "The Last Hero", "The Amazing Maurice and His Educated Rodents",
2688     "Night Watch", "The Wee Free Men", "Monstrous Regiment",
2689     "A Hat Full of Sky", "Going Postal", "Thud!", "Wintersmith",
2690     "Making Money", "Unseen Academicals", "I Shall Wear Midnight", "Snuff",
2691     "Raising Steam", "The Shepherd's Crown"
2692 };
2693
2694 const char *
2695 noveltitle(novidx)
2696 int *novidx;
2697 {
2698     int j, k = SIZE(sir_Terry_novels);
2699
2700     j = rn2(k);
2701     if (novidx) {
2702         if (*novidx == -1)
2703             *novidx = j;
2704         else if (*novidx >= 0 && *novidx < k)
2705             j = *novidx;
2706     }
2707     return sir_Terry_novels[j];
2708 }
2709
2710 const char *
2711 lookup_novel(lookname, idx)
2712 const char *lookname;
2713 int *idx;
2714 {
2715     int k;
2716
2717     /* Take American or U.K. spelling of this one */
2718     if (!strcmpi(The(lookname), "The Color of Magic"))
2719         lookname = sir_Terry_novels[0];
2720
2721     for (k = 0; k < SIZE(sir_Terry_novels); ++k) {
2722         if (!strcmpi(lookname, sir_Terry_novels[k])
2723             || !strcmpi(The(lookname), sir_Terry_novels[k])) {
2724             if (idx)
2725                 *idx = k;
2726             return sir_Terry_novels[k];
2727         }
2728     }
2729     /* name not found; if novelidx is already set, override the name */
2730     if (idx && *idx >= 0 && *idx < SIZE(sir_Terry_novels))
2731         return sir_Terry_novels[*idx];
2732
2733     return (const char *) 0;
2734 }
2735
2736 /*do_name.c*/