1 /* NetHack 3.6 do_name.c $NHDT-Date: 1519420054 2018/02/23 21:07:34 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.128 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Pasi Kallinen, 2018. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2018 */
9 /* JNetHack may be freely redistributed. See license for details. */
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 *));
27 extern const char what_is_an_unknown_object[]; /* from pager.c */
31 /* manage a pool of BUFSZ buffers, so callers don't have to */
35 static char NEARDATA bufs[NUMMBUF][BUFSZ];
36 static int bufidx = 0;
38 bufidx = (bufidx + 1) % NUMMBUF;
42 /* function for getpos() to highlight desired map locations.
43 * parameter value 0 = initialize, 1 = highlight, 2 = done
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;
50 getpos_sethilite(gp_hilitef, gp_getvalidf)
51 void FDECL((*gp_hilitef), (int));
52 boolean FDECL((*gp_getvalidf), (int, int));
54 getpos_hilitefunc = gp_hilitef;
55 getpos_getvalid = gp_getvalidf;
61 [2] "use XXX to move the cursor to %s"
63 const char *const gloc_descr[NUM_GLOCS][4] = {
65 { "any monsters", "monster", "next monster", "monsters" },
66 { "any items", "item", "next object", "objects" },
67 { "any doors", "door", "next door or doorway", "doors or doorways" },
68 { "any unexplored areas", "unexplored area", "unexplored location",
69 "unexplored locations" },
70 { "anything interesting", "interesting thing", "anything interesting",
71 "anything interesting" }
73 { "
\89ö
\95¨", "
\89ö
\95¨", "
\89ö
\95¨
\82Ì
\97×", "
\89ö
\95¨" },
74 { "
\95¨", "
\95¨", "
\95¨
\82Ì
\97×", "
\95¨" },
75 { "
\94à", "
\94à", "
\94à
\82â
\8fo
\93ü
\82è
\8cû
\82Ì
\97×", "
\94à
\82â
\8fo
\93ü
\82è
\8cû" },
76 { "
\96¢
\92T
\8dõ
\95\94\95ª", "
\96¢
\92T
\8dõ
\95\94\95ª", "
\96¢
\92T
\8dõ
\82Ì
\88Ê
\92u", "
\96¢
\92T
\8dõ
\82Ì
\88Ê
\92u" },
77 { "
\8aÖ
\90S
\82Ì
\82 \82é
\82à
\82Ì", "
\8aÖ
\90S
\82Ì
\82 \82é
\82à
\82Ì", "
\8aÖ
\90S
\82Ì
\82 \82é
\82à
\82Ì", "
\8aÖ
\90S
\82Ì
\82 \82é
\82à
\82Ì" }
81 const char *const gloc_filtertxt[NUM_GFILTER] = {
88 "
\8e\8b\8aE
\82Ì
\92\86\82Ì",
89 "
\82±
\82Ì
\83G
\83\8a\83A
\82Ì"
94 getpos_help_keyxhelp(tmpwin, k1, k2, gloc)
103 Sprintf(sbuf, "Use '%s' or '%s' to %s%s%s.",
105 iflags.getloc_usemenu ? "get a menu of "
106 : "move the cursor to ",
107 gloc_descr[gloc][2 + iflags.getloc_usemenu],
108 gloc_filtertxt[iflags.getloc_filter]);
110 Sprintf(sbuf, "'%s'
\82©'%s'
\82Å%s%s%s
\81D",
112 gloc_filtertxt[iflags.getloc_filter],
113 gloc_descr[gloc][2 + iflags.getloc_usemenu],
114 iflags.getloc_usemenu ? "
\82Ì
\83\81\83j
\83\85\81[
\82ð
\8fo
\82·"
115 : "
\82É
\83J
\81[
\83\
\83\8b\82ð
\93®
\82©
\82·");
117 putstr(tmpwin, 0, sbuf);
120 /* the response for '?' help request in getpos() */
122 getpos_help(force, goal)
127 boolean doing_what_is;
128 winid tmpwin = create_nhwindow(NHW_MENU);
130 const char *const fastmovemode[2] = { "8 units at a time",
131 "skipping same glyphs" };
133 const char *const fastmovemode[2] = { "
\88ê
\93x
\82É8
\83}
\83X",
134 "
\93¯
\82¶
\92n
\8c`
\82ð
\94ò
\82Î
\82µ
\82Ä" };
139 "Use '%c', '%c', '%c', '%c' to move the cursor to %s.", /* hjkl */
141 "[%c%c%c%c]
\82Å%s
\82Ö
\88Ú
\93®
\82Å
\82«
\82é
\81D",
143 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal);
144 putstr(tmpwin, 0, sbuf);
147 "Use 'H', 'J', 'K', 'L' to fast-move the cursor, %s.",
148 fastmovemode[iflags.getloc_moveskip]);
151 "'H', 'J', 'K', 'L'
\82Å%s
\88Ú
\93®
\82Å
\82«
\82é
\81D",
152 fastmovemode[iflags.getloc_moveskip]);
154 putstr(tmpwin, 0, sbuf);
156 putstr(tmpwin, 0, "Or enter a background symbol (ex. '<').");
158 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");
160 Sprintf(sbuf, "Use '%s' to move the cursor on yourself.",
161 visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
163 Sprintf(sbuf, "'%s'
\82Å
\8e©
\95ª
\8e©
\90g
\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é
\81D",
164 visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
166 putstr(tmpwin, 0, sbuf);
167 if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
168 getpos_help_keyxhelp(tmpwin,
169 visctrl(Cmd.spkeys[NHKF_GETPOS_MON_NEXT]),
170 visctrl(Cmd.spkeys[NHKF_GETPOS_MON_PREV]),
173 if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
174 getpos_help_keyxhelp(tmpwin,
175 visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]),
176 visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_PREV]),
179 if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) {
180 /* these are primarily useful when choosing a travel
181 destination for the '_' command */
182 getpos_help_keyxhelp(tmpwin,
183 visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_NEXT]),
184 visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_PREV]),
186 getpos_help_keyxhelp(tmpwin,
187 visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_NEXT]),
188 visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_PREV]),
190 getpos_help_keyxhelp(tmpwin,
191 visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_NEXT]),
192 visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_PREV]),
196 Sprintf(sbuf, "Use '%s' to change fast-move mode to %s.",
197 visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
198 fastmovemode[!iflags.getloc_moveskip]);
200 Sprintf(sbuf, "'%s'
\82Å
\8d\82\91¬
\88Ú
\93®
\83\82\81[
\83h
\82ð%s
\88Ú
\93®
\82É
\82·
\82é
\81D",
201 visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
202 fastmovemode[!iflags.getloc_moveskip]);
204 putstr(tmpwin, 0, sbuf);
205 if (!iflags.terrainmode || (iflags.terrainmode & TER_DETECT) == 0) {
207 Sprintf(sbuf, "Use '%s' to toggle menu listing for possible targets.",
208 visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
210 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",
211 visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
213 putstr(tmpwin, 0, sbuf);
216 "Use '%s' to change the mode of limiting possible targets.",
217 visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
220 "'%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",
221 visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
223 putstr(tmpwin, 0, sbuf);
225 if (!iflags.terrainmode) {
228 if (getpos_getvalid) {
230 Sprintf(sbuf, "Use '%s' or '%s' to move to valid locations.",
231 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
232 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
234 Sprintf(sbuf, "'%s'
\82©'%s'
\82Å
\90³
\93\96\82È
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é
\81D",
235 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
236 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
238 putstr(tmpwin, 0, sbuf);
240 if (getpos_hilitefunc) {
242 Sprintf(sbuf, "Use '%s' to display valid locations.",
243 visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
245 Sprintf(sbuf, "'%s'
\82Å
\89Â
\94\
\82È
\88Ê
\92u
\82ð
\95\
\8e¦
\82·
\82é
\81D",
246 visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
248 putstr(tmpwin, 0, sbuf);
251 Sprintf(sbuf, "Use '%s' to toggle automatic description.",
252 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
254 Sprintf(sbuf, "'%s'
\82Å
\90à
\96¾
\82Ì
\8e©
\93®
\95\
\8e¦
\82ð
\90Ø
\82è
\91Ö
\82¦
\82é
\81D",
255 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
257 putstr(tmpwin, 0, sbuf);
258 if (iflags.cmdassist) { /* assisting the '/' command, I suppose... */
261 (iflags.getpos_coords == GPCOORDS_NONE)
262 ? "(Set 'whatis_coord' option to include coordinates with '%s' text.)"
263 : "(Reset 'whatis_coord' option to omit coordinates from '%s' text.)",
264 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
267 (iflags.getpos_coords == GPCOORDS_NONE)
268 ? "('%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)"
269 : "('%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)",
270 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
273 /* disgusting hack; the alternate selection characters work for any
274 getpos call, but only matter for dowhatis (and doquickwhatis) */
275 doing_what_is = (goal == what_is_an_unknown_object);
278 Sprintf(kbuf, "'%s' or '%s' or '%s' or '%s'",
279 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
280 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]),
281 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]),
282 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
284 Sprintf(kbuf, "'%s'
\82©'%s'
\82©'%s'
\82©'%s'",
285 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
286 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]),
287 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]),
288 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
291 Sprintf(kbuf, "'%s'", visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
294 Sprintf(sbuf, "Type a %s when you are at the right place.", kbuf);
296 Sprintf(sbuf, "[.]%s
\82Å
\8c\88\92è
\81D", kbuf);
298 putstr(tmpwin, 0, sbuf);
302 " '%s' describe current spot, show 'more info', move to another spot.",
303 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
306 " '%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",
307 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
309 putstr(tmpwin, 0, sbuf);
312 " '%s' describe current spot,%s move to another spot;",
313 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
314 flags.help ? " prompt if 'more info'," : "");
317 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81C%s
\8e\9f\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é;",
318 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
319 flags.help ? "
\92Ç
\89Á
\8fî
\95ñ
\82ª
\82 \82ê
\82Î
\8am
\94F
\82µ
\81C" : "");
321 putstr(tmpwin, 0, sbuf);
324 " '%s' describe current spot, move to another spot;",
325 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]));
328 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81C
\8e\9f\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é;",
329 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]));
331 putstr(tmpwin, 0, sbuf);
334 " '%s' describe current spot, stop looking at things;",
335 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]));
338 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81C
\8c©
\82é
\82Ì
\82ð
\82â
\82ß
\82é;",
339 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]));
341 putstr(tmpwin, 0, sbuf);
346 putstr(tmpwin, 0, "Type Space or Escape when you're done.");
348 putstr(tmpwin, 0, "
\83X
\83y
\81[
\83X
\82Ü
\82½
\82Í
\83G
\83X
\83P
\81[
\83v
\82Å
\8fI
\97¹
\81D");
349 putstr(tmpwin, 0, "");
350 display_nhwindow(tmpwin, TRUE);
351 destroy_nhwindow(tmpwin);
355 cmp_coord_distu(a, b)
361 int dx, dy, dist_1, dist_2;
365 dist_1 = max(abs(dx), abs(dy));
368 dist_2 = max(abs(dx), abs(dy));
370 if (dist_1 == dist_2)
371 return (c1->y != c2->y) ? (c1->y - c2->y) : (c1->x - c2->x);
373 return dist_1 - dist_2;
376 #define IS_UNEXPLORED_LOC(x,y) \
378 && glyph_is_cmap(levl[(x)][(y)].glyph) \
379 && glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone \
380 && !levl[(x)][(y)].seenv)
382 static struct opvar *gloc_filter_map = (struct opvar *) 0;
384 #define GLOC_SAME_AREA(x,y) \
386 && (selection_getpoint((x),(y), gloc_filter_map)))
388 static int gloc_filter_floodfill_match_glyph;
391 gloc_filter_classify_glyph(glyph)
396 if (!glyph_is_cmap(glyph))
399 c = glyph_to_cmap(glyph);
401 if (is_cmap_room(c) || is_cmap_furniture(c))
403 else if (is_cmap_wall(c) || c == S_tree)
405 else if (is_cmap_corr(c))
407 else if (is_cmap_water(c))
409 else if (is_cmap_lava(c))
415 gloc_filter_floodfill_matcharea(x,y)
418 int glyph = back_to_glyph(x, y);
420 if (!levl[x][y].seenv)
423 if (glyph == gloc_filter_floodfill_match_glyph)
426 if (gloc_filter_classify_glyph(glyph)
427 == gloc_filter_classify_glyph(gloc_filter_floodfill_match_glyph))
434 gloc_filter_floodfill(x, y)
437 gloc_filter_floodfill_match_glyph = back_to_glyph(x, y);
439 set_selection_floodfillchk(gloc_filter_floodfill_matcharea);
440 selection_floodfill(gloc_filter_map, x, y, FALSE);
446 if (iflags.getloc_filter == GFILTER_AREA) {
447 if (!gloc_filter_map) {
448 gloc_filter_map = selection_opvar(NULL);
450 /* special case: if we're in a doorway, try to figure out which
451 direction we're moving, and use that side of the doorway */
452 if (IS_DOOR(levl[u.ux][u.uy].typ)) {
454 gloc_filter_floodfill(u.ux + u.dx, u.uy + u.dy);
456 /* TODO: maybe add both sides of the doorway? */
459 gloc_filter_floodfill(u.ux, u.uy);
469 if (gloc_filter_map) {
470 opvar_free_x(gloc_filter_map);
471 gloc_filter_map = NULL;
476 gather_locs_interesting(x, y, gloc)
479 /* TODO: if glyph is a pile glyph, convert to ordinary one
480 * in order to keep tail/boulder/rock check simple.
482 int glyph = glyph_at(x, y);
484 if (iflags.getloc_filter == GFILTER_VIEW && !cansee(x, y))
486 if (iflags.getloc_filter == GFILTER_AREA && !GLOC_SAME_AREA(x, y)
487 && !GLOC_SAME_AREA(x - 1, y) && !GLOC_SAME_AREA(x, y - 1)
488 && !GLOC_SAME_AREA(x + 1, y) && !GLOC_SAME_AREA(x, y + 1))
494 /* unlike '/M', this skips monsters revealed by
495 warning glyphs and remembered unseen ones */
496 return (glyph_is_monster(glyph)
497 && glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
499 return (glyph_is_object(glyph)
500 && glyph != objnum_to_glyph(BOULDER)
501 && glyph != objnum_to_glyph(ROCK));
503 return (glyph_is_cmap(glyph)
504 && (is_cmap_door(glyph_to_cmap(glyph))
505 || is_cmap_drawbridge(glyph_to_cmap(glyph))
506 || glyph_to_cmap(glyph) == S_ndoor));
508 return (glyph_is_cmap(glyph)
509 && (is_cmap_door(glyph_to_cmap(glyph))
510 || is_cmap_drawbridge(glyph_to_cmap(glyph))
511 || glyph_to_cmap(glyph) == S_ndoor
512 || glyph_to_cmap(glyph) == S_room
513 || glyph_to_cmap(glyph) == S_darkroom
514 || glyph_to_cmap(glyph) == S_corr
515 || glyph_to_cmap(glyph) == S_litcorr)
516 && (IS_UNEXPLORED_LOC(x + 1, y)
517 || IS_UNEXPLORED_LOC(x - 1, y)
518 || IS_UNEXPLORED_LOC(x, y + 1)
519 || IS_UNEXPLORED_LOC(x, y - 1)));
520 case GLOC_INTERESTING:
521 return gather_locs_interesting(x,y, GLOC_DOOR)
522 || !(glyph_is_cmap(glyph)
523 && (is_cmap_wall(glyph_to_cmap(glyph))
524 || glyph_to_cmap(glyph) == S_tree
525 || glyph_to_cmap(glyph) == S_bars
526 || glyph_to_cmap(glyph) == S_ice
527 || glyph_to_cmap(glyph) == S_air
528 || glyph_to_cmap(glyph) == S_cloud
529 || glyph_to_cmap(glyph) == S_lava
530 || glyph_to_cmap(glyph) == S_water
531 || glyph_to_cmap(glyph) == S_pool
532 || glyph_to_cmap(glyph) == S_ndoor
533 || glyph_to_cmap(glyph) == S_room
534 || glyph_to_cmap(glyph) == S_darkroom
535 || glyph_to_cmap(glyph) == S_corr
536 || glyph_to_cmap(glyph) == S_litcorr));
538 return (getpos_getvalid && getpos_getvalid(x,y));
544 /* gather locations for monsters or objects shown on the map */
546 gather_locs(arr_p, cnt_p, gloc)
554 * We always include the hero's location even if there is no monster
555 * (invisible hero without see invisible) or object (usual case)
556 * displayed there. That way, the count will always be at least 1,
557 * and player has a visual indicator (cursor returns to hero's spot)
558 * highlighting when successive 'm's or 'o's have cycled all the way
559 * through all monsters or objects.
561 * Hero's spot will always sort to array[0] because it will always
562 * be the shortest distance (namely, 0 units) away from <u.ux,u.uy>.
568 for (pass = 0; pass < 2; pass++) {
569 for (x = 1; x < COLNO; x++)
570 for (y = 0; y < ROWNO; y++) {
571 if ((x == u.ux && y == u.uy)
572 || gather_locs_interesting(x, y, gloc)) {
583 if (!pass) /* end of first pass */
584 *arr_p = (coord *) alloc(*cnt_p * sizeof (coord));
585 else /* end of second pass */
586 qsort(*arr_p, *cnt_p, sizeof (coord), cmp_coord_distu);
593 dxdy_to_dist_descr(dx, dy, fulldir)
602 Sprintf(buf, "here");
604 Sprintf(buf, "
\82±
\82±");
605 } else if ((dst = xytod(dx, dy)) != -1) {
606 /* explicit direction; 'one step' is implicit */
607 Sprintf(buf, "%s", directionname(dst));
609 const char *dirnames[4][2] = {
622 /* 9999: protect buf[] against overflow caused by invalid values */
626 Sprintf(eos(buf), "%d%s%s", abs(dy), dirnames[(dy > 0)][fulldir],
632 Sprintf(eos(buf), "%d%s", abs(dx),
633 dirnames[2 + (dx > 0)][fulldir]);
639 /* coordinate formatting for 'whatis_coord' option */
641 coord_desc(x, y, outbuf, cmode)
645 static char screen_fmt[16]; /* [12] suffices: "[%02d,%02d]" */
652 case GPCOORDS_COMFULL:
653 case GPCOORDS_COMPASS:
654 /* "east", "3s", "2n,4w" */
657 Sprintf(outbuf, "(%s)",
658 dxdy_to_dist_descr(dx, dy, cmode == GPCOORDS_COMFULL));
660 case GPCOORDS_MAP: /* x,y */
661 /* upper left corner of map is <1,0>;
662 with default COLNO,ROWNO lower right corner is <79,20> */
663 Sprintf(outbuf, "<%d,%d>", x, y);
665 case GPCOORDS_SCREEN: /* y+2,x */
666 /* for normal map sizes, force a fixed-width formatting so that
667 /m, /M, /o, and /O output lines up cleanly; map sizes bigger
668 than Nx999 or 999xM will still work, but not line up like normal
669 when displayed in a column setting */
671 Sprintf(screen_fmt, "[%%%sd,%%%sd]",
672 (ROWNO - 1 + 2 < 100) ? "02" : "03",
673 (COLNO - 1 < 100) ? "02" : "03");
674 /* map line 0 is screen row 2;
675 map column 0 isn't used, map column 1 is screen column 1 */
676 Sprintf(outbuf, screen_fmt, y + 2, x);
683 auto_describe(cx, cy)
690 const char *firstmatch = "unknown";
692 const char *firstmatch = "
\95s
\96¾";
696 if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) {
697 (void) coord_desc(cx, cy, tmpbuf, iflags.getpos_coords);
699 custompline(SUPPRESS_HISTORY,
700 "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
702 && getpos_getvalid && !getpos_getvalid(cx, cy))
704 (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
705 ? " (no travel path)" : "");
707 custompline(SUPPRESS_HISTORY,
708 "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
710 && getpos_getvalid && !getpos_getvalid(cx, cy))
711 ? " (
\95s
\90³)" : "",
712 (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
713 ? " (
\8co
\98H
\82È
\82µ)" : "");
715 curs(WIN_MAP, cx, cy);
721 getpos_menu(ccp, gloc)
730 menu_item *picks = (menu_item *) 0;
733 gather_locs(&garr, &gcount, gloc);
735 if (gcount < 2) { /* gcount always includes the hero */
736 free((genericptr_t) garr);
739 iflags.getloc_filter == GFILTER_VIEW ? "see" : "detect",
740 gloc_descr[gloc][0]);
742 You("%s
\82ð%s
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D",
744 iflags.getloc_filter == GFILTER_VIEW ? "
\8c©
\82é" : "
\8c©
\82Â
\82¯
\82é");
749 tmpwin = create_nhwindow(NHW_MENU);
753 /* gather_locs returns array[0] == you. skip it. */
754 for (i = 1; i < gcount; i++) {
758 const char *firstmatch = "unknown";
760 const char *firstmatch = "
\95s
\96¾";
765 if (do_screen_description(tmpcc, TRUE, sym, tmpbuf, &firstmatch)) {
766 (void) coord_desc(garr[i].x, garr[i].y, tmpbuf,
767 iflags.getpos_coords);
768 Sprintf(fullbuf, "%s%s%s", firstmatch,
769 (*tmpbuf ? " " : ""), tmpbuf);
770 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, fullbuf,
776 Sprintf(tmpbuf, "Pick a target %s%s%s",
778 gloc_filtertxt[iflags.getloc_filter],
779 iflags.getloc_travelmode ? " for travel" : "");
781 Sprintf(tmpbuf, "%s%s
\82Å
\96Ú
\95W
\82Æ
\82·
\82é%s
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢",
782 iflags.getloc_travelmode ? "
\88Ú
\93®
\82Ì
\82½
\82ß
\82É" : "",
783 gloc_filtertxt[iflags.getloc_filter],
784 gloc_descr[gloc][1]);
786 end_menu(tmpwin, tmpbuf);
787 pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
788 destroy_nhwindow(tmpwin);
790 ccp->x = garr[picks->item.a_int - 1].x;
791 ccp->y = garr[picks->item.a_int - 1].y;
792 free((genericptr_t) picks);
794 free((genericptr_t) garr);
795 return (pick_cnt > 0);
799 getpos(ccp, force, goal)
807 } const pick_chars_def[] = {
808 { NHKF_GETPOS_PICK, LOOK_TRADITIONAL },
809 { NHKF_GETPOS_PICK_Q, LOOK_QUICK },
810 { NHKF_GETPOS_PICK_O, LOOK_ONCE },
811 { NHKF_GETPOS_PICK_V, LOOK_VERBOSE }
813 const int mMoOdDxX_def[] = {
814 NHKF_GETPOS_MON_NEXT,
815 NHKF_GETPOS_MON_PREV,
816 NHKF_GETPOS_OBJ_NEXT,
817 NHKF_GETPOS_OBJ_PREV,
818 NHKF_GETPOS_DOOR_NEXT,
819 NHKF_GETPOS_DOOR_PREV,
820 NHKF_GETPOS_UNEX_NEXT,
821 NHKF_GETPOS_UNEX_PREV,
822 NHKF_GETPOS_INTERESTING_NEXT,
823 NHKF_GETPOS_INTERESTING_PREV,
824 NHKF_GETPOS_VALID_NEXT,
825 NHKF_GETPOS_VALID_PREV
832 boolean msg_given = TRUE; /* clear message window by default */
833 boolean show_goal_msg = FALSE;
834 boolean hilite_state = FALSE;
835 coord *garr[NUM_GLOCS] = DUMMY;
836 int gcount[NUM_GLOCS] = DUMMY;
837 int gidx[NUM_GLOCS] = DUMMY;
839 for (i = 0; i < SIZE(pick_chars_def); i++)
840 pick_chars[i] = Cmd.spkeys[pick_chars_def[i].nhkf];
841 pick_chars[SIZE(pick_chars_def)] = '\0';
843 for (i = 0; i < SIZE(mMoOdDxX_def); i++)
844 mMoOdDxX[i] = Cmd.spkeys[mMoOdDxX_def[i]];
845 mMoOdDxX[SIZE(mMoOdDxX_def)] = '\0';
849 goal = "desired location";
851 goal = "
\96Ú
\93I
\92n";
854 pline("(For instructions type a '%s')",
855 visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
857 pline("('%s'
\82Å
\83w
\83\8b\83v)",
858 visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
867 curs(WIN_MAP, cx, cy);
870 lock_mouse_cursor(TRUE);
875 pline("Move cursor to %s:", goal);
877 pline("
\83J
\81[
\83\
\83\8b\82ð%s
\82É
\93®
\82©
\82µ
\82Ä
\82
\82¾
\82³
\82¢:", goal);
878 curs(WIN_MAP, cx, cy);
880 show_goal_msg = FALSE;
881 } else if (iflags.autodescribe && !msg_given && !hilite_state) {
882 auto_describe(cx, cy);
885 c = nh_poskey(&tx, &ty, &sidx);
888 (*getpos_hilitefunc)(2);
889 hilite_state = FALSE;
890 curs(WIN_MAP, cx, cy);
894 if (iflags.autodescribe)
897 if (c == Cmd.spkeys[NHKF_ESC]) {
899 msg_given = TRUE; /* force clear */
906 /* a mouse click event, just assign and return */
911 if ((cp = index(pick_chars, c)) != 0) {
912 /* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */
913 result = pick_chars_def[(int) (cp - pick_chars)].ret;
916 for (i = 0; i < 8; i++) {
919 if (Cmd.dirchars[i] == c) {
920 /* a normal movement letter or digit */
923 } else if (Cmd.alphadirchars[i] == lowc((char) c)
924 || (Cmd.num_pad && Cmd.dirchars[i] == (c & 0177))) {
925 /* a shifted movement letter or Meta-digit */
926 if (iflags.getloc_moveskip) {
927 /* skip same glyphs */
928 int glyph = glyph_at(cx, cy);
932 while (isok(cx + dx, cy + dy)
933 && glyph == glyph_at(cx + dx, cy + dy)
934 && isok(cx + dx + xdir[i], cy + dy + ydir[i])
935 && glyph == glyph_at(cx + dx + xdir[i],
936 cy + dy + ydir[i])) {
947 /* truncate at map edge; diagonal moves complicate this... */
949 dy -= sgn(dy) * (1 - (cx + dx));
950 dx = 1 - cx; /* so that (cx+dx == 1) */
951 } else if (cx + dx > COLNO - 1) {
952 dy += sgn(dy) * ((COLNO - 1) - (cx + dx));
953 dx = (COLNO - 1) - cx;
956 dx -= sgn(dx) * (0 - (cy + dy));
957 dy = 0 - cy; /* so that (cy+dy == 0) */
958 } else if (cy + dy > ROWNO - 1) {
959 dx += sgn(dx) * ((ROWNO - 1) - (cy + dy));
960 dy = (ROWNO - 1) - cy;
967 if (c == Cmd.spkeys[NHKF_GETPOS_HELP] || redraw_cmd(c)) {
968 if (c == Cmd.spkeys[NHKF_GETPOS_HELP])
969 getpos_help(force, goal);
971 docrt(); /* redraw */
972 /* update message window to reflect that we're still targetting */
973 show_goal_msg = TRUE;
975 } else if (c == Cmd.spkeys[NHKF_GETPOS_SHOWVALID]
976 && getpos_hilitefunc) {
978 (*getpos_hilitefunc)(0);
979 (*getpos_hilitefunc)(1);
983 } else if (c == Cmd.spkeys[NHKF_GETPOS_AUTODESC]) {
984 iflags.autodescribe = !iflags.autodescribe;
986 pline("Automatic description %sis %s.",
987 flags.verbose ? "of features under cursor " : "",
988 iflags.autodescribe ? "on" : "off");
990 pline("%s
\90à
\96¾
\8e©
\93®
\95\
\8e¦
\81F%s",
991 flags.verbose ? "
\83J
\81[
\83\
\83\8b\82Ì
\89º
\82É
\82 \82é
\82à
\82Ì
\82Ì" : "",
992 iflags.autodescribe ? "
\83I
\83\93" : "
\83I
\83t");
994 if (!iflags.autodescribe)
995 show_goal_msg = TRUE;
998 } else if (c == Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]) {
999 const char *const view_filters[NUM_GFILTER] = {
1001 "Not limiting targets",
1002 "Limiting targets to in sight",
1003 "Limiting targets to in same area"
1005 "
\83^
\81[
\83Q
\83b
\83g
\82ð
\90§
\8cÀ
\82µ
\82È
\82¢",
1006 "
\8e\8b\8aE
\93à
\82É
\83^
\81[
\83Q
\83b
\83g
\82ð
\90§
\8cÀ
\82·
\82é",
1007 "
\93¯
\82¶
\83G
\83\8a\83A
\82É
\83^
\81[
\83Q
\83b
\83g
\82ð
\90§
\8cÀ
\82·
\82é"
1010 iflags.getloc_filter = (iflags.getloc_filter + 1) % NUM_GFILTER;
1011 for (i = 0; i < NUM_GLOCS; i++) {
1013 free((genericptr_t) garr[i]);
1016 gidx[i] = gcount[i] = 0;
1019 pline("%s.", view_filters[iflags.getloc_filter]);
1021 pline("%s
\81D", view_filters[iflags.getloc_filter]);
1024 } else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]) {
1025 iflags.getloc_usemenu = !iflags.getloc_usemenu;
1027 pline("%s a menu to show possible targets.",
1028 iflags.getloc_usemenu ? "Using" : "Not using");
1030 pline("
\89Â
\94\
\82È
\83^
\81[
\83Q
\83b
\83g
\82ð
\8c©
\82é
\82Ì
\82É
\83\81\83j
\83\85\81[
\82ð
\8eg%s
\81D",
1031 iflags.getloc_usemenu ? "
\82¤" : "
\82í
\82È
\82¢");
1035 } else if (c == Cmd.spkeys[NHKF_GETPOS_SELF]) {
1036 /* reset 'm&M', 'o&O', &c; otherwise, there's no way for player
1037 to achieve that except by manually cycling through all spots */
1038 for (i = 0; i < NUM_GLOCS; i++)
1043 } else if (c == Cmd.spkeys[NHKF_GETPOS_MOVESKIP]) {
1044 iflags.getloc_moveskip = !iflags.getloc_moveskip;
1046 pline("%skipping over similar terrain when fastmoving the cursor.",
1047 iflags.getloc_moveskip ? "S" : "Not s");
1049 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",
1050 iflags.getloc_moveskip ? "
\82·" : "
\82³
\82È
\82¢");
1052 } else if ((cp = index(mMoOdDxX, c)) != 0) { /* 'm|M', 'o|O', &c */
1053 /* nearest or farthest monster or object or door or unexplored */
1054 int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
1055 gloc = gtmp >> 1; /* 0..3 */
1057 if (iflags.getloc_usemenu) {
1059 if (getpos_menu(&tmpcrd, gloc)) {
1067 gather_locs(&garr[gloc], &gcount[gloc], gloc);
1068 gidx[gloc] = 0; /* garr[][0] is hero's spot */
1070 if (!(gtmp & 1)) { /* c=='m' || c=='o' || c=='d' || c=='x') */
1071 gidx[gloc] = (gidx[gloc] + 1) % gcount[gloc];
1072 } else { /* c=='M' || c=='O' || c=='D' || c=='X') */
1073 if (--gidx[gloc] < 0)
1074 gidx[gloc] = gcount[gloc] - 1;
1076 cx = garr[gloc][gidx[gloc]].x;
1077 cy = garr[gloc][gidx[gloc]].y;
1080 if (!index(quitchars, c)) {
1081 char matching[MAXPCHARS];
1082 int pass, lo_x, lo_y, hi_x, hi_y, k = 0;
1084 (void) memset((genericptr_t) matching, 0, sizeof matching);
1085 for (sidx = 1; sidx < MAXPCHARS; sidx++) { /* [0] left as 0 */
1086 if (IS_DOOR(sidx) || IS_WALL(sidx)
1087 || sidx == SDOOR || sidx == SCORR
1088 || glyph_to_cmap(k) == S_room
1089 || glyph_to_cmap(k) == S_darkroom
1090 || glyph_to_cmap(k) == S_corr
1091 || glyph_to_cmap(k) == S_litcorr)
1093 if (c == defsyms[sidx].sym || c == (int) showsyms[sidx])
1094 matching[sidx] = (char) ++k;
1097 for (pass = 0; pass <= 1; pass++) {
1098 /* pass 0: just past current pos to lower right;
1099 pass 1: upper left corner to current pos */
1100 lo_y = (pass == 0) ? cy : 0;
1101 hi_y = (pass == 0) ? ROWNO - 1 : cy;
1102 for (ty = lo_y; ty <= hi_y; ty++) {
1103 lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
1104 hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
1105 for (tx = lo_x; tx <= hi_x; tx++) {
1106 /* first, look at what is currently visible
1107 (might be monster) */
1108 k = glyph_at(tx, ty);
1109 if (glyph_is_cmap(k)
1110 && matching[glyph_to_cmap(k)])
1112 /* next, try glyph that's remembered here
1113 (might be trap or object) */
1114 if (level.flags.hero_memory
1115 /* !terrainmode: don't move to remembered
1116 trap or object if not currently shown */
1117 && !iflags.terrainmode) {
1118 k = levl[tx][ty].glyph;
1119 if (glyph_is_cmap(k)
1120 && matching[glyph_to_cmap(k)])
1123 /* last, try actual terrain here (shouldn't
1124 we be using lastseentyp[][] instead?) */
1125 if (levl[tx][ty].seenv) {
1126 k = back_to_glyph(tx, ty);
1127 if (glyph_is_cmap(k)
1128 && matching[glyph_to_cmap(k)])
1135 clear_nhwindow(WIN_MESSAGE);
1143 pline("Can't find dungeon feature '%c'.", c);
1145 pline("'%c'
\81H", c);
1153 Strcpy(note, "aborted");
1155 Strcpy(note, "
\92\86\92f
\82µ
\82½");
1158 Sprintf(note, "use '%c', '%c', '%c', '%c' or '%s'",
1159 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
1160 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
1162 Sprintf(note, "%c%c%c%c
\82Å
\88Ú
\93®
\81C%s
\82Å
\8fI
\97¹",
1163 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
1164 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
1167 pline("Unknown direction: '%s' (%s).", visctrl((char) c),
1169 pline("
\82»
\82Ì
\95û
\8cü
\82Í
\82È
\82¢
\81F'%s' (%s)", visctrl((char) c),
1172 } /* k => matching */
1179 pline("
\88È
\8fã
\81D");
1180 msg_given = FALSE; /* suppress clear */
1183 result = 0; /* not -1 */
1191 curs(WIN_MAP, cx, cy);
1195 lock_mouse_cursor(FALSE);
1198 clear_nhwindow(WIN_MESSAGE);
1201 for (i = 0; i < NUM_GLOCS; i++)
1203 free((genericptr_t) garr[i]);
1204 getpos_hilitefunc = (void FDECL((*), (int))) 0;
1205 getpos_getvalid = (boolean FDECL((*), (int, int))) 0;
1209 /* allocate space for a monster's name; removes old name if there is one */
1213 int lth; /* desired length (caller handles adding 1 for terminator) */
1216 /* allocate mextra if necessary; otherwise get rid of old name */
1218 mon->mextra = newmextra();
1220 free_mname(mon); /* already has mextra, might also have name */
1221 MNAME(mon) = (char *) alloc((unsigned) lth);
1223 /* zero length: the new name is empty; get rid of the old name */
1229 /* release a monster's name; retains mextra even if all fields are now null */
1234 if (has_mname(mon)) {
1235 free((genericptr_t) MNAME(mon));
1236 MNAME(mon) = (char *) 0;
1240 /* allocate space for an object's name; removes old name if there is one */
1244 int lth; /* desired length (caller handles adding 1 for terminator) */
1247 /* allocate oextra if necessary; otherwise get rid of old name */
1249 obj->oextra = newoextra();
1251 free_oname(obj); /* already has oextra, might also have name */
1252 ONAME(obj) = (char *) alloc((unsigned) lth);
1254 /* zero length: the new name is empty; get rid of the old name */
1260 /* release an object's name; retains oextra even if all fields are now null */
1265 if (has_oname(obj)) {
1266 free((genericptr_t) ONAME(obj));
1267 ONAME(obj) = (char *) 0;
1271 /* safe_oname() always returns a valid pointer to
1272 * a string, either the pointer to an object's name
1273 * if it has one, or a pointer to an empty string
1285 /* historical note: this returns a monster pointer because it used to
1286 allocate a new bigger block of memory to hold the monster and its name */
1288 christen_monst(mtmp, name)
1295 /* dogname & catname are PL_PSIZ arrays; object names have same limit */
1296 lth = (name && *name) ? ((int) strlen(name) + 1) : 0;
1297 if (lth > PL_PSIZ) {
1299 if (is_kanji2(buf, lth - 1))
1303 name = strncpy(buf, name, PL_PSIZ - 1);
1304 buf[PL_PSIZ - 1] = '\0';
1306 new_mname(mtmp, lth); /* removes old name if one is present */
1308 Strcpy(MNAME(mtmp), name);
1312 /* check whether user-supplied name matches or nearly matches an unnameable
1313 monster's name; if so, give an alternate reject message for do_mname() */
1315 alreadynamed(mtmp, monnambuf, usrbuf)
1317 char *monnambuf, *usrbuf;
1319 char pronounbuf[10], *p;
1321 if (fuzzymatch(usrbuf, monnambuf, " -_", TRUE)
1322 /* catch trying to name "the Oracle" as "Oracle" */
1323 || (!strncmpi(monnambuf, "the ", 4)
1324 && fuzzymatch(usrbuf, monnambuf + 4, " -_", TRUE))
1325 /* catch trying to name "invisible Orcus" as "Orcus" */
1326 || ((p = strstri(monnambuf, "invisible ")) != 0
1327 && fuzzymatch(usrbuf, p + 10, " -_", TRUE))
1328 /* catch trying to name "the {priest,Angel} of Crom" as "Crom" */
1329 || ((p = strstri(monnambuf, " of ")) != 0
1330 && fuzzymatch(usrbuf, p + 4, " -_", TRUE))) {
1332 pline("%s is already called %s.",
1333 upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
1335 pline("%s
\82Í
\8aù
\82É%s
\82Æ
\8cÄ
\82Î
\82ê
\82Ä
\82¢
\82é
\81D",
1336 upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
1339 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8eg
\82í
\82È
\82¢*/
1340 } else if (mtmp->data == &mons[PM_JUIBLEX]
1341 && strstri(monnambuf, "Juiblex")
1342 && !strcmpi(usrbuf, "Jubilex")) {
1343 pline("%s doesn't like being called %s.", upstart(monnambuf), usrbuf);
1350 /* allow player to assign a name to some chosen monster */
1354 char buf[BUFSZ] = DUMMY, monnambuf[BUFSZ], qbuf[QBUFSZ];
1357 struct monst *mtmp = 0;
1359 if (Hallucination) {
1361 You("would never recognize it anyway.");
1363 You("
\82»
\82ê
\82ð
\94F
\8e¯
\82Å
\82«
\82È
\82¢
\81D");
1369 if (getpos(&cc, FALSE, "the monster you want to name") < 0
1371 if (getpos(&cc, FALSE, "
\82 \82È
\82½
\82ª
\96¼
\82Ã
\82¯
\82½
\82¢
\89ö
\95¨") < 0
1376 if (cx == u.ux && cy == u.uy) {
1377 if (u.usteed && canspotmon(u.usteed)) {
1381 pline("This %s creature is called %s and cannot be renamed.",
1383 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",
1384 beautiful(), plname);
1388 mtmp = m_at(cx, cy);
1392 && (!(cansee(cx, cy) || see_with_infrared(mtmp))
1393 || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE
1394 || mtmp->m_ap_type == M_AP_OBJECT
1395 || (mtmp->minvis && !See_invisible)))) {
1397 pline("I see no monster there.");
1399 pline("
\82»
\82±
\82É
\89ö
\95¨
\82Í
\82¢
\82È
\82¢
\81D");
1402 /* special case similar to the one in lookat() */
1404 Sprintf(qbuf, "What do you want to call %s?",
1406 Sprintf(qbuf, "%s
\82ð
\89½
\82Æ
\8cÄ
\82Ñ
\82Ü
\82·
\82©
\81H",
1407 distant_monnam(mtmp, ARTICLE_THE, monnambuf));
1409 if (!*buf || *buf == '\033')
1411 /* strip leading and trailing spaces; unnames monster if all spaces */
1412 (void) mungspaces(buf);
1414 /* Unique monsters have their own specific names or titles.
1415 * Shopkeepers, temple priests and other minions use alternate
1416 * name formatting routines which ignore any user-supplied name.
1418 * Don't say the name is being rejected if it happens to match
1419 * the existing name.
1421 if ((mtmp->data->geno & G_UNIQ) && !mtmp->ispriest) {
1422 if (!alreadynamed(mtmp, monnambuf, buf))
1424 pline("%s doesn't like being called names!", upstart(monnambuf));
1426 pline("%s
\82Í
\82 \82¾
\96¼
\82Å
\8cÄ
\82Î
\82ê
\82é
\82Ì
\82ª
\8c\99\82¢
\82È
\82æ
\82¤
\82¾
\81I", Monnam(mtmp));
1427 } else if (mtmp->isshk
1428 && !(Deaf || mtmp->msleeping || !mtmp->mcanmove
1429 || mtmp->data->msound <= MS_ANIMAL)) {
1430 if (!alreadynamed(mtmp, monnambuf, buf))
1432 verbalize("I'm %s, not %s.", shkname(mtmp), buf);
1434 verbalize("
\8e\84\82Í%s
\82¾
\81C%s
\82Å
\82Í
\82È
\82¢
\81D", shkname(mtmp), buf);
1435 } else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk) {
1436 if (!alreadynamed(mtmp, monnambuf, buf))
1438 pline("%s will not accept the name %s.", upstart(monnambuf), buf);
1440 pline("%s
\82Í%s
\82Æ
\82¢
\82¤
\96¼
\91O
\82ð
\8eó
\82¯
\82¢
\82ê
\82È
\82©
\82Á
\82½
\81D", monnambuf, buf);
1442 (void) christen_monst(mtmp, buf);
1445 STATIC_VAR int via_naming = 0;
1448 * This routine used to change the address of 'obj' so be unsafe if not
1449 * used with extreme care. Applying a name to an object no longer
1450 * allocates a replacement object, so that old risk is gone.
1455 register struct obj *obj;
1457 char *bufp, buf[BUFSZ] = DUMMY, bufcpy[BUFSZ], qbuf[QBUFSZ];
1461 /* Do this now because there's no point in even asking for a name */
1462 if (obj->otyp == SPE_NOVEL) {
1464 pline("%s already has a published name.", Ysimple_name2(obj));
1466 pline("%s
\82É
\82Í
\82·
\82Å
\82É
\8fo
\94Å
\8e\9e\82Ì
\96¼
\91O
\82ª
\82 \82é
\81D", Ysimple_name2(obj));
1471 Sprintf(qbuf, "What do you want to name %s ",
1472 is_plural(obj) ? "these" : "this");
1473 (void) safe_qbuf(qbuf, qbuf, "?", obj, xname, simpleonames, "item");
1475 (void) safe_qbuf(qbuf, "", "
\82ð
\89½
\82Æ
\96¼
\82Ã
\82¯
\82Ü
\82·
\82©
\81H", obj, xname, simpleonames, "item");
1478 if (!*buf || *buf == '\033')
1480 /* strip leading and trailing spaces; unnames item if all spaces */
1481 (void) mungspaces(buf);
1484 * We don't violate illiteracy conduct here, although it is
1485 * arguable that we should for anything other than "X". Doing so
1486 * would make attaching player's notes to hero's inventory have an
1487 * in-game effect, which may or may not be the correct thing to do.
1489 * We do violate illiteracy in oname() if player creates Sting or
1490 * Orcrist, clearly being literate (no pun intended...).
1493 /* relax restrictions over proper capitalization for artifacts */
1494 if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp)
1497 if (obj->oartifact) {
1499 pline_The("artifact seems to resist the attempt.");
1501 pline("
\90¹
\8aí
\82Í
\96¼
\82Ã
\82¯
\82ð
\8b\91\94Û
\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82¾
\81D");
1503 } else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) {
1504 /* this used to change one letter, substituting a value
1505 of 'a' through 'y' (due to an off by one error, 'z'
1506 would never be selected) and then force that to
1507 upper case if such was the case of the input;
1508 now, the hand slip scuffs one or two letters as if
1509 the text had been trodden upon, sometimes picking
1510 punctuation instead of an arbitrary letter;
1511 unfortunately, we have to cover the possibility of
1512 it targetting spaces so failing to make any change
1513 (we know that it must eventually target a nonspace
1514 because buf[] matches a valid artifact name) */
1515 Strcpy(bufcpy, buf);
1516 /* for "the Foo of Bar", only scuff "Foo of Bar" part */
1517 bufp = !strncmpi(bufcpy, "the ", 4) ? (buf + 4) : buf;
1519 wipeout_text(bufp, rnd(2), (unsigned) 0);
1520 } while (!strcmp(buf, bufcpy));
1522 pline("While engraving, your %s slips.", body_part(HAND));
1524 pline("
\8d\8f\82ñ
\82Å
\82¢
\82é
\8aÔ
\82É%s
\82ª
\8a\8a\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D", body_part(HAND));
1525 display_nhwindow(WIN_MESSAGE, FALSE);
1527 You("engrave: \"%s\".", buf);
1529 You("
\8d\8f\82ñ
\82¾:
\81u%s
\81v
\81D",buf);
1530 /* violate illiteracy conduct since hero attempted to write
1531 a valid artifact name */
1532 u.uconduct.literate++;
1534 ++via_naming; /* This ought to be an argument rather than a static... */
1535 obj = oname(obj, buf);
1536 --via_naming; /* ...but oname() is used in a lot of places, so defer. */
1547 lth = *name ? (int) (strlen(name) + 1) : 0;
1548 if (lth > PL_PSIZ) {
1551 name = strncpy(buf, name, PL_PSIZ - 1);
1552 buf[PL_PSIZ - 1] = '\0';
1554 if (is_kanji2(name, lth - 1))
1556 name = strncpy(buf, name, lth - 1);
1557 buf[lth - 1] = '\0';
1560 /* If named artifact exists in the game, do not create another.
1561 * Also trying to create an artifact shouldn't de-artifact
1562 * it (e.g. Excalibur from prayer). In this case the object
1563 * will retain its current name. */
1564 if (obj->oartifact || (lth && exist_artifact(obj->otyp, name)))
1567 new_oname(obj, lth); /* removes old name if one is present */
1569 Strcpy(ONAME(obj), name);
1572 artifact_exists(obj, name, TRUE);
1573 if (obj->oartifact) {
1574 /* can't dual-wield with artifact as secondary weapon */
1575 if (obj == uswapwep)
1577 /* activate warning if you've just named your weapon "Sting" */
1579 set_artifact_intrinsic(obj, TRUE, W_WEP);
1580 /* if obj is owned by a shop, increase your bill */
1582 alter_cost(obj, 0L);
1584 /* violate illiteracy conduct since successfully wrote arti-name */
1585 u.uconduct.literate++;
1593 static NEARDATA const char callable[] = {
1594 SCROLL_CLASS, POTION_CLASS, WAND_CLASS, RING_CLASS, AMULET_CLASS,
1595 GEM_CLASS, SPBOOK_CLASS, ARMOR_CLASS, TOOL_CLASS, 0
1599 objtyp_is_callable(i)
1602 return (boolean) (objects[i].oc_uname
1603 || (OBJ_DESCR(objects[i])
1604 && index(callable, objects[i].oc_class)));
1607 /* C and #name commands - player can name monster or object or type of obj */
1614 menu_item *pick_list = 0;
1615 char ch, allowall[2];
1616 /* if player wants a,b,c instead of i,o when looting, do that here too */
1617 boolean abc = flags.lootabc;
1619 win = create_nhwindow(NHW_MENU);
1622 any.a_char = 'm'; /* group accelerator 'C' */
1623 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'C', ATR_NONE,
1625 "a monster", MENU_UNSELECTED);
1627 "
\89ö
\95¨", MENU_UNSELECTED);
1629 /* we use y and n as accelerators so that we can accept user's
1630 response keyed to old "name an individual object?" prompt */
1631 any.a_char = 'i'; /* group accelerator 'y' */
1632 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'y', ATR_NONE,
1634 "a particular object in inventory", MENU_UNSELECTED);
1636 "
\8e\9d\82¿
\95¨
\82Ì
\92\86\82Ì
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80", MENU_UNSELECTED);
1637 any.a_char = 'o'; /* group accelerator 'n' */
1638 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'n', ATR_NONE,
1640 "the type of an object in inventory", MENU_UNSELECTED);
1642 "
\8e\9d\82¿
\95¨
\82Ì
\92\86\82Ì
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80\82Ì
\8eí
\97Þ", MENU_UNSELECTED);
1644 any.a_char = 'f'; /* group accelerator ',' (or ':' instead?) */
1645 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, ',', ATR_NONE,
1647 "the type of an object upon the floor", MENU_UNSELECTED);
1649 "
\8f°
\82Ì
\8fã
\82É
\82 \82é
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80\82Ì
\8eí
\97Þ", MENU_UNSELECTED);
1650 any.a_char = 'd'; /* group accelerator '\' */
1651 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, '\\', ATR_NONE,
1653 "the type of an object on discoveries list", MENU_UNSELECTED);
1655 "
\94
\8c©
\95¨
\88ê
\97\97\82É
\82 \82é
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80\82Ì
\8eí
\97Þ", MENU_UNSELECTED);
1656 any.a_char = 'a'; /* group accelerator 'l' */
1657 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'l', ATR_NONE,
1659 "record an annotation for the current level", MENU_UNSELECTED);
1661 "
\8c»
\8dÝ
\82Ì
\8aK
\82É
\91Î
\82·
\82é
\83\81\83\82\82Ì
\8bL
\98^", MENU_UNSELECTED);
1663 end_menu(win, "What do you want to name?");
1665 end_menu(win, "
\82Ç
\82ê
\82É
\96¼
\91O
\82ð
\82Â
\82¯
\82Ü
\82·
\82©
\81H");
1666 if (select_menu(win, PICK_ONE, &pick_list) > 0) {
1667 ch = pick_list[0].item.a_char;
1668 free((genericptr_t) pick_list);
1671 destroy_nhwindow(win);
1677 case 'm': /* name a visible monster */
1680 case 'i': /* name an individual object in inventory */
1681 allowall[0] = ALL_CLASSES;
1683 obj = getobj(allowall, "name");
1687 case 'o': /* name a type of object in inventory */
1688 obj = getobj(callable, "call");
1690 /* behave as if examining it in inventory;
1691 this might set dknown if it was picked up
1692 while blind and the hero can now see */
1697 You("would never recognize another one.");
1699 You("
\91¼
\82É
\94F
\8e¯
\82Å
\82«
\82È
\82¢
\81D");
1701 } else if (!objtyp_is_callable(obj->otyp)) {
1702 You("know those as well as you ever will.");
1709 case 'f': /* name a type of object visible on the floor */
1712 case 'd': /* name a type of object on the discoveries list */
1715 case 'a': /* annotate level */
1722 /* for use by safe_qbuf() */
1730 otemp.oextra = (struct oextra *) 0;
1732 /* in case water is already known, convert "[un]holy water" to "water" */
1733 otemp.blessed = otemp.cursed = 0;
1734 /* remove attributes that are doname() caliber but get formatted
1735 by xname(); most of these fixups aren't really needed because the
1736 relevant type of object isn't callable so won't reach this far */
1737 if (otemp.oclass == WEAPON_CLASS)
1738 otemp.opoisoned = 0; /* not poisoned */
1739 else if (otemp.oclass == POTION_CLASS)
1740 otemp.odiluted = 0; /* not diluted */
1741 else if (otemp.otyp == TOWEL || otemp.otyp == STATUE)
1742 otemp.spe = 0; /* not wet or historic */
1743 else if (otemp.otyp == TIN)
1744 otemp.known = 0; /* suppress tin type (homemade, &c) and mon type */
1745 else if (otemp.otyp == FIGURINE)
1746 otemp.corpsenm = NON_PM; /* suppress mon type */
1747 else if (otemp.otyp == HEAVY_IRON_BALL)
1748 otemp.owt = objects[HEAVY_IRON_BALL].oc_weight; /* not "very heavy" */
1749 else if (otemp.oclass == FOOD_CLASS && otemp.globby)
1750 otemp.owt = 120; /* 6*20, neither a small glob nor a large one */
1752 return an(xname(&otemp));
1759 char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
1763 return; /* probably blind */
1765 if (obj->oclass == POTION_CLASS && obj->fromsink)
1766 /* kludge, meaning it's sink water */
1768 Sprintf(qbuf, "Call a stream of %s fluid:",
1770 Sprintf(qbuf, "%s
\89t
\91Ì:",
1771 OBJ_DESCR(objects[obj->otyp]));
1774 (void) safe_qbuf(qbuf, "Call ", ":", obj,
1775 docall_xname, simpleonames, "thing");
1777 (void) safe_qbuf(qbuf, "", "
\82É
\89½
\82Æ
\96¼
\91O
\82ð
\95t
\82¯
\82é
\81H", obj,
1778 docall_xname, simpleonames, "
\82±
\82ê");
1781 if (!*buf || *buf == '\033')
1784 /* clear old name */
1785 str1 = &(objects[obj->otyp].oc_uname);
1787 free((genericptr_t) *str1);
1789 /* strip leading and trailing spaces; uncalls item if all spaces */
1790 (void) mungspaces(buf);
1792 if (*str1) { /* had name, so possibly remove from disco[] */
1793 /* strip name first, for the update_inventory() call
1794 from undiscover_object() */
1796 undiscover_object(obj->otyp);
1799 *str1 = dupstr(buf);
1800 discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
1810 struct obj *obj = 0;
1812 boolean fakeobj = FALSE, use_plural;
1814 boolean fakeobj = FALSE;
1817 cc.x = u.ux, cc.y = u.uy;
1818 /* "dot for under/over you" only makes sense when the cursor hasn't
1819 been moved off the hero's '@' yet, but there's no way to adjust
1820 the help text once getpos() has started */
1822 Sprintf(buf, "object on map (or '.' for one %s you)",
1823 (u.uundetected && hides_under(youmonst.data)) ? "over" : "under");
1825 Strcpy(buf, "
\92n
\90}
\8fã
\82Ì
\95¨
\91Ì(
\82 \82é
\82¢
\82Í'.'
\82Å
\82 \82È
\82½
\82Ì
\82¢
\82é
\8fê
\8f\8a");
1827 if (getpos(&cc, FALSE, buf) < 0 || cc.x <= 0)
1829 if (cc.x == u.ux && cc.y == u.uy) {
1830 obj = vobj_at(u.ux, u.uy);
1832 glyph = glyph_at(cc.x, cc.y);
1833 if (glyph_is_object(glyph))
1834 fakeobj = object_from_map(glyph, cc.x, cc.y, &obj);
1835 /* else 'obj' stays null */
1838 /* "under you" is safe here since there's no object to hide under */
1840 pline("There doesn't seem to be any object %s.",
1841 (cc.x == u.ux && cc.y == u.uy) ? "under you" : "there");
1843 pline("%s
\82É
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82¾
\81D",
1844 (cc.x == u.ux && cc.y == u.uy) ? "
\82 \82È
\82½
\82Ì
\89º" : "
\82»
\82±");
1848 /* note well: 'obj' might be as instance of STRANGE_OBJECT if target
1849 is a mimic; passing that to xname (directly or via simpleonames)
1850 would yield "glorkum" so we need to handle it explicitly; it will
1851 always fail the Hallucination test and pass the !callable test,
1852 resulting in the "can't be assigned a type name" message */
1853 Strcpy(buf, (obj->otyp != STRANGE_OBJECT)
1855 : obj_descr[STRANGE_OBJECT].oc_name);
1857 use_plural = (obj->quan > 1L);
1859 if (Hallucination) {
1860 const char *unames[6];
1863 /* straight role name */
1864 unames[0] = ((Upolyd ? u.mfemale : flags.female) && urole.name.f)
1867 /* random rank title for hero's role */
1868 unames[1] = rank_of(rnd(30), Role_switch, flags.female);
1869 /* random fake monster */
1870 unames[2] = bogusmon(tmpbuf, (char *) 0);
1871 /* increased chance for fake monster */
1872 unames[3] = unames[2];
1874 unames[4] = roguename();
1877 unames[5] = "Wibbly Wobbly";
1879 unames[5] = "
\82¤
\82ë
\82¤
\82ë";
1881 pline("%s %s to call you \"%s.\"",
1882 The(buf), use_plural ? "decide" : "decides",
1883 unames[rn2(SIZE(unames))]);
1885 pline("%s
\82Í
\82 \82È
\82½
\82ð
\81u%s
\81v
\82Æ
\8cÄ
\82Ô
\82±
\82Æ
\82É
\8c\88\82ß
\82½
\81D",
1887 unames[rn2(SIZE(unames))]);
1889 } else if (!objtyp_is_callable(obj->otyp)) {
1891 pline("%s %s can't be assigned a type name.",
1892 use_plural ? "Those" : "That", buf);
1894 pline("%s
\82É
\8eí
\97Þ
\82Ì
\96¼
\91O
\82ð
\8a\84\82è
\93\96\82Ä
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
1897 } else if (!obj->dknown) {
1899 You("don't know %s %s well enough to name %s.",
1900 use_plural ? "those" : "that", buf, use_plural ? "them" : "it");
1902 You("
\96¼
\91O
\82ð
\95t
\82¯
\82ç
\82ê
\82é
\82Ù
\82Ç%s
\82Ì
\82±
\82Æ
\82ð
\82æ
\82
\92m
\82ç
\82È
\82¢
\81D",
1912 static const char *const ghostnames[] = {
1913 /* these names should have length < PL_NSIZ */
1914 /* Capitalize the names for aesthetics -dgk */
1915 "Adri", "Andries", "Andreas", "Bert", "David", "Dirk",
1916 "Emile", "Frans", "Fred", "Greg", "Hether", "Jay",
1917 "John", "Jon", "Karnov", "Kay", "Kenny", "Kevin",
1918 "Maud", "Michiel", "Mike", "Peter", "Robert", "Ron",
1919 "Tom", "Wilmar", "Nick Danger", "Phoenix", "Jiro", "Mizue",
1920 "Stephan", "Lance Braccus", "Shadowhawk"
1923 /* ghost names formerly set by x_monnam(), now by makemon() instead */
1927 return rn2(7) ? ghostnames[rn2(SIZE(ghostnames))] : (const char *) plname;
1931 * Monster naming functions:
1932 * x_monnam is the generic monster-naming function.
1933 * seen unseen detected named
1934 * mon_nam: the newt it the invisible orc Fido
1935 * noit_mon_nam:the newt (as if detected) the invisible orc Fido
1936 * l_monnam: newt it invisible orc dog called Fido
1937 * Monnam: The newt It The invisible orc Fido
1938 * noit_Monnam: The newt (as if detected) The invisible orc Fido
1939 * Adjmonnam: The poor newt It The poor invisible orc The poor Fido
1940 * Amonnam: A newt It An invisible orc Fido
1941 * a_monnam: a newt it an invisible orc Fido
1942 * m_monnam: newt xan orc Fido
1943 * y_monnam: your newt your xan your invisible orc Fido
1944 * noname_monnam(mon,article):
1945 * article newt art xan art invisible orc art dog
1948 /* Bug: if the monster is a priest or shopkeeper, not every one of these
1949 * options works, since those are special cases.
1952 x_monnam(mtmp, article, adjective, suppress, called)
1953 register struct monst *mtmp;
1955 /* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious
1956 * ARTICLE_YOUR: "your" on pets, "the" on everything else
1958 * If the monster would be referred to as "it" or if the monster has a name
1959 * _and_ there is no adjective, "invisible", "saddled", etc., override this
1960 * and always use no article.
1962 const char *adjective;
1964 /* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE.
1965 * EXACT_NAME: combination of all the above
1966 * SUPPRESS_NAME: omit monster's assigned name (unless uniq w/ pname).
1970 char *buf = nextmbuf();
1971 struct permonst *mdat = mtmp->data;
1972 const char *pm_name = mdat->mname;
1973 boolean do_hallu, do_invis, do_it, do_saddle, do_name;
1975 boolean name_at_start, has_adjectives;
1979 if (program_state.gameover)
1980 suppress |= SUPPRESS_HALLUCINATION;
1981 if (article == ARTICLE_YOUR && !mtmp->mtame)
1982 article = ARTICLE_THE;
1984 do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION);
1985 do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE);
1986 do_it = !canspotmon(mtmp) && article != ARTICLE_YOUR
1987 && !program_state.gameover && mtmp != u.usteed
1988 && !(u.uswallow && mtmp == u.ustuck) && !(suppress & SUPPRESS_IT);
1989 do_saddle = !(suppress & SUPPRESS_SADDLE);
1990 do_name = !(suppress & SUPPRESS_NAME) || type_is_pname(mdat);
1994 /* unseen monsters, etc. Use "it" */
1999 Strcpy(buf, "
\89½
\8eÒ
\82©");
2003 /* priests and minions: don't even use this function */
2004 if (mtmp->ispriest || mtmp->isminion) {
2005 char priestnambuf[BUFSZ];
2007 long save_prop = EHalluc_resistance;
2008 unsigned save_invis = mtmp->minvis;
2010 /* when true name is wanted, explicitly block Hallucination */
2012 EHalluc_resistance = 1L;
2015 name = priestname(mtmp, priestnambuf);
2016 EHalluc_resistance = save_prop;
2017 mtmp->minvis = save_invis;
2019 if (article == ARTICLE_NONE && !strncmp(name, "the ", 4))
2022 return strcpy(buf, name);
2024 /* an "aligned priest" not flagged as a priest or minion should be
2025 "priest" or "priestess" (normally handled by priestname()) */
2026 if (mdat == &mons[PM_ALIGNED_PRIEST])
2028 pm_name = mtmp->female ? "priestess" : "priest";
2030 pm_name = mtmp->female ? "
\93ò
\91m" : "
\91m
\97µ";
2031 else if (mdat == &mons[PM_HIGH_PRIEST] && mtmp->female)
2033 pm_name = "high priestess";
2035 pm_name = "
\96@
\89¤";
2037 /* Shopkeepers: use shopkeeper name. For normal shopkeepers, just
2038 * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
2039 * shopkeeper" or "Asidonhopo the blue dragon". If hallucinating,
2040 * none of this applies.
2042 if (mtmp->isshk && !do_hallu) {
2044 if (adjective && article == ARTICLE_THE) {
2045 /* pathological case: "the angry Asidonhopo the blue dragon"
2047 Strcpy(buf, "the ");
2048 Strcat(strcat(buf, adjective), " ");
2049 Strcat(buf, shkname(mtmp));
2052 Strcat(buf, shkname(mtmp));
2053 if (mdat == &mons[PM_SHOPKEEPER] && !do_invis)
2055 Strcat(buf, " the ");
2057 Strcat(buf, "invisible ");
2058 Strcat(buf, pm_name);
2061 if (mdat == &mons[PM_SHOPKEEPER] && !do_invis){
2062 Strcpy(buf, shkname(mtmp));
2064 Sprintf(buf, "%s
\82Æ
\82¢
\82¤
\96¼
\82Ì%s%s",
2065 shkname(mtmp), do_invis ? "
\8ep
\82Ì
\8c©
\82¦
\82È
\82¢" : "",
2072 /* Put the adjectives in the buffer */
2075 Strcat(strcat(buf, adjective), " ");
2077 Strcat(buf, adjective);
2080 Strcat(buf, "invisible ");
2082 Strcat(buf, "
\8ep
\82Ì
\8c©
\82¦
\82È
\82¢");
2083 if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind
2086 Strcat(buf, "saddled ");
2088 Strcat(buf, "
\88Æ
\82Ì
\82Â
\82¢
\82Ä
\82¢
\82é");
2091 has_adjectives = TRUE;
2093 has_adjectives = FALSE;
2096 /* Put the actual monster name or type into the buffer now */
2097 /* Be sure to remember whether the buffer starts with a name */
2100 char *rname = rndmonnam(&rnamecode);
2104 name_at_start = bogon_is_pname(rnamecode);
2106 } else if (do_name && has_mname(mtmp)) {
2107 char *name = MNAME(mtmp);
2109 if (mdat == &mons[PM_GHOST]) {
2111 Sprintf(eos(buf), "%s ghost", s_suffix(name));
2113 Sprintf(buf, "%s
\82Ì
\97H
\97ì", name);
2115 name_at_start = TRUE;
2117 } else if (called) {
2119 Sprintf(eos(buf), "%s called %s", pm_name, name);
2121 Sprintf(eos(buf), "%s
\82Æ
\82¢
\82¤
\96¼
\82Ì%s", name, pm_name);
2123 name_at_start = (boolean) type_is_pname(mdat);
2125 #if 0 /*JP*//*
\92è
\8a¥
\8e\8c\82Ì
\8f\88\97\9d\82Í
\95s
\97v*/
2126 } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) {
2127 /* <name> the <adjective> <invisible> <saddled> <rank> */
2131 pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */
2134 Strcat(pbuf, bp + 5); /* append the rest of the name */
2136 article = ARTICLE_NONE;
2137 name_at_start = TRUE;
2142 name_at_start = TRUE;
2145 } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) {
2148 Strcpy(pbuf, rank_of((int) mtmp->m_lev, monsndx(mdat),
2149 (boolean) mtmp->female));
2151 Strcat(buf, lcase(pbuf));
2156 name_at_start = FALSE;
2159 Strcat(buf, pm_name);
2161 name_at_start = (boolean) type_is_pname(mdat);
2165 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\8a¥
\8e\8c\82Í
\82È
\82¢*/
2166 if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) {
2167 if (mdat == &mons[PM_WIZARD_OF_YENDOR])
2168 article = ARTICLE_THE;
2170 article = ARTICLE_NONE;
2171 } else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) {
2172 article = ARTICLE_THE;
2180 Strcpy(buf2, "your ");
2185 Strcpy(buf2, "the ");
2205 return x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
2206 (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, TRUE);
2213 return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2214 (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, FALSE);
2217 /* print the name as if mon_nam() was called, but assume that the player
2218 * can always see the monster--used for probing and for monsters aggravating
2219 * the player with a cursed potion of invisibility
2225 return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2226 (has_mname(mtmp)) ? (SUPPRESS_SADDLE | SUPPRESS_IT)
2235 register char *bp = mon_nam(mtmp);
2245 register char *bp = noit_mon_nam(mtmp);
2251 /* return "a dog" rather than "Fido", honoring hallucination and visibility */
2253 noname_monnam(mtmp, article)
2257 return x_monnam(mtmp, article, (char *) 0, SUPPRESS_NAME, FALSE);
2260 /* monster's own name -- overrides hallucination and [in]visibility
2261 so shouldn't be used in ordinary messages (mainly for disclosure) */
2266 return x_monnam(mtmp, ARTICLE_NONE, (char *) 0, EXACT_NAME, FALSE);
2269 /* pet name: "your little dog" */
2274 int prefix, suppression_flag;
2276 prefix = mtmp->mtame ? ARTICLE_YOUR : ARTICLE_THE;
2277 suppression_flag = (has_mname(mtmp)
2278 /* "saddled" is redundant when mounted */
2279 || mtmp == u.usteed)
2283 return x_monnam(mtmp, prefix, (char *) 0, suppression_flag, FALSE);
2287 Adjmonnam(mtmp, adj)
2291 char *bp = x_monnam(mtmp, ARTICLE_THE, adj,
2292 has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2302 return x_monnam(mtmp, ARTICLE_A, (char *) 0,
2303 has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2310 char *bp = a_monnam(mtmp);
2316 /* used for monster ID by the '/', ';', and 'C' commands to block remote
2317 identification of the endgame altars via their attending priests */
2319 distant_monnam(mon, article, outbuf)
2321 int article; /* only ARTICLE_NONE and ARTICLE_THE are handled here */
2324 /* high priest(ess)'s identity is concealed on the Astral Plane,
2325 unless you're adjacent (overridden for hallucination which does
2326 its own obfuscation) */
2327 if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination
2328 && Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) {
2330 Strcpy(outbuf, article == ARTICLE_THE ? "the " : "");
2331 Strcat(outbuf, mon->female ? "high priestess" : "high priest");
2333 Strcpy(outbuf, "
\96@
\89¤");
2336 Strcpy(outbuf, x_monnam(mon, article, (char *) 0, 0, TRUE));
2341 /* fake monsters used to be in a hard-coded array, now in a data file */
2348 get_rnd_text(BOGUSMONFILE, buf);
2349 /* strip prefix if present */
2350 if (!letter(*mname)) {
2361 /* return a random monster name, for hallucination */
2366 static char buf[BUFSZ];
2369 #define BOGUSMONSIZE 100 /* arbitrary */
2375 name = rn1(SPECIAL_PM + BOGUSMONSIZE - LOW_PM, LOW_PM);
2376 } while (name < SPECIAL_PM
2377 && (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN)));
2379 if (name >= SPECIAL_PM) {
2380 mname = bogusmon(buf, code);
2382 mname = strcpy(buf, mons[name].mname);
2388 /* check bogusmon prefix to decide whether it's a personal name */
2390 bogon_is_pname(code)
2395 return index("-+=", code) ? TRUE : FALSE;
2398 /* name of a Rogue player */
2404 if ((opts = nh_getenv("ROGUEOPTS")) != 0) {
2405 for (i = opts; *i; i++)
2406 if (!strncmp("name=", i, 5)) {
2408 if ((j = index(i + 5, ',')) != 0)
2413 /*JP:Rogue
\82Ì
\8aJ
\94
\8eÒ
\82Ì
\96¼
\91O*/
2414 return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
2418 static NEARDATA const char *const hcolors[] = {
2420 "ultraviolet", "infrared", "bluish-orange", "reddish-green", "dark white",
2421 "light black", "sky blue-pink", "salty", "sweet", "sour", "bitter",
2422 "striped", "spiral", "swirly", "plaid", "checkered", "argyle", "paisley",
2423 "blotchy", "guernsey-spotted", "polka-dotted", "square", "round",
2424 "triangular", "cabernet", "sangria", "fuchsia", "wisteria", "lemon-lime",
2425 "strawberry-banana", "peppermint", "romantic", "incandescent",
2426 "octarine", /* Discworld: the Colour of Magic */
2428 "
\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Ì",
2429 "
\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¢",
2430 "
\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Ì",
2431 "
\82µ
\82Ý
\8fó
\82Ì", "
\90Â
\90F
\82Ì
\94Á
\93_
\8fó
\82Ì", "
\93_
\8fó
\82Ì", "
\8el
\8ap
\8c`
\8fó
\82Ì", "
\8aÛ
\8fó
\82Ì",
2432 "
\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Ì",
2433 "ä
\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Ì",
2434 "
\83I
\83N
\83^
\83\8a\83\93\90F
\82Ì",
2440 const char *colorpref;
2442 return (Hallucination || !colorpref) ? hcolors[rn2(SIZE(hcolors))]
2446 /* return a random real color unless hallucinating */
2450 int k = rn2(CLR_MAX);
2452 return Hallucination ? hcolor((char *) 0)
2454 : (k == NO_COLOR) ? "colorless"
2456 : (k == NO_COLOR) ? "
\96³
\90F
\82Ì"
2460 static NEARDATA const char *const hliquids[] = {
2462 "yoghurt", "oobleck", "clotted blood", "diluted water", "purified water",
2463 "instant coffee", "tea", "herbal infusion", "liquid rainbow",
2464 "creamy foam", "mulled wine", "bouillon", "nectar", "grog", "flubber",
2465 "ketchup", "slow light", "oil", "vinaigrette", "liquid crystal", "honey",
2466 "caramel sauce", "ink", "aqueous humour", "milk substitute", "fruit juice",
2467 "glowing lava", "gastric acid", "mineral water", "cough syrup", "quicksilver",
2468 "sweet vitriol", "grey goo", "pink slime",
2470 "
\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",
2471 "
\83C
\83\93\83X
\83^
\83\93\83g
\83R
\81[
\83q
\81[", "
\8dg
\92\83", "
\83n
\81[
\83u
\89t", "
\89t
\91Ì
\82Ì
\93ø",
2472 "
\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[",
2473 "
\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¨",
2474 "
\83J
\83\89\83\81\83\8b\83\
\81[
\83X", "
\83C
\83\93\83N", "
\96[
\90\85", "
\91ã
\97p
\93û", "
\83t
\83\8b\81[
\83c
\83W
\83\85\81[
\83X",
2475 "
\97¬
\82ê
\82é
\97n
\8aâ", "
\88Ý
\8e_", "
\83~
\83l
\83\89\83\8b\83E
\83H
\81[
\83^
\81[", "
\8aP
\8e~
\82ß
\83V
\83\8d\83b
\83v", "
\90\85\8bâ",
2476 "
\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",
2482 const char *liquidpref;
2484 return (Hallucination || !liquidpref) ? hliquids[rn2(SIZE(hliquids))]
2488 /* Aliases for road-runner nemesis
2490 static const char *const coynames[] = {
2491 "Carnivorous Vulgaris", "Road-Runnerus Digestus", "Eatibus Anythingus",
2492 "Famishus-Famishus", "Eatibus Almost Anythingus", "Eatius Birdius",
2493 "Famishius Fantasticus", "Eternalii Famishiis", "Famishus Vulgarus",
2494 "Famishius Vulgaris Ingeniusi", "Eatius-Slobbius", "Hardheadipus Oedipus",
2495 "Carnivorous Slobbius", "Hard-Headipus Ravenus", "Evereadii Eatibus",
2496 "Apetitius Giganticus", "Hungrii Flea-Bagius", "Overconfidentii Vulgaris",
2497 "Caninus Nervous Rex", "Grotesques Appetitus", "Nemesis Ridiculii",
2502 coyotename(mtmp, buf)
2507 Sprintf(buf, "%s - %s",
2508 x_monnam(mtmp, ARTICLE_NONE, (char *) 0, 0, TRUE),
2509 mtmp->mcan ? coynames[SIZE(coynames) - 1]
2510 : coynames[mtmp->m_id % (SIZE(coynames) - 1)]);
2515 /* make sure "The Colour of Magic" remains the first entry in here */
2516 static const char *const sir_Terry_novels[] = {
2517 "The Colour of Magic", "The Light Fantastic", "Equal Rites", "Mort",
2518 "Sourcery", "Wyrd Sisters", "Pyramids", "Guards! Guards!", "Eric",
2519 "Moving Pictures", "Reaper Man", "Witches Abroad", "Small Gods",
2520 "Lords and Ladies", "Men at Arms", "Soul Music", "Interesting Times",
2521 "Maskerade", "Feet of Clay", "Hogfather", "Jingo", "The Last Continent",
2522 "Carpe Jugulum", "The Fifth Elephant", "The Truth", "Thief of Time",
2523 "The Last Hero", "The Amazing Maurice and His Educated Rodents",
2524 "Night Watch", "The Wee Free Men", "Monstrous Regiment",
2525 "A Hat Full of Sky", "Going Postal", "Thud!", "Wintersmith",
2526 "Making Money", "Unseen Academicals", "I Shall Wear Midnight", "Snuff",
2527 "Raising Steam", "The Shepherd's Crown"
2534 int j, k = SIZE(sir_Terry_novels);
2540 else if (*novidx >= 0 && *novidx < k)
2543 return sir_Terry_novels[j];
2547 lookup_novel(lookname, idx)
2548 const char *lookname;
2553 /* Take American or U.K. spelling of this one */
2554 if (!strcmpi(The(lookname), "The Color of Magic"))
2555 lookname = sir_Terry_novels[0];
2557 for (k = 0; k < SIZE(sir_Terry_novels); ++k) {
2558 if (!strcmpi(lookname, sir_Terry_novels[k])
2559 || !strcmpi(The(lookname), sir_Terry_novels[k])) {
2562 return sir_Terry_novels[k];
2565 /* name not found; if novelidx is already set, override the name */
2566 if (idx && *idx >= 0 && *idx < SIZE(sir_Terry_novels))
2567 return sir_Terry_novels[*idx];
2569 return (const char *) 0;