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-2019 */
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 */
140 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal);
143 "[%c%c%c%c]
\82Å%s
\82Ö
\88Ú
\93®
\82Å
\82«
\82é
\81D",
144 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal);
146 putstr(tmpwin, 0, sbuf);
149 "Use 'H', 'J', 'K', 'L' to fast-move the cursor, %s.",
150 fastmovemode[iflags.getloc_moveskip]);
153 "'H', 'J', 'K', 'L'
\82Å%s
\88Ú
\93®
\82Å
\82«
\82é
\81D",
154 fastmovemode[iflags.getloc_moveskip]);
156 putstr(tmpwin, 0, sbuf);
158 putstr(tmpwin, 0, "Or enter a background symbol (ex. '<').");
160 putstr(tmpwin, 0, "
\94w
\8ci
\82Ì
\83V
\83\93\83{
\83\8b\82ð
\93ü
\97Í
\82·
\82é
\82Æ
\82»
\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é(
\97á
\81F'<')
\81D");
162 Sprintf(sbuf, "Use '%s' to move the cursor on yourself.",
163 visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
165 Sprintf(sbuf, "'%s'
\82Å
\8e©
\95ª
\8e©
\90g
\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é
\81D",
166 visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
168 putstr(tmpwin, 0, sbuf);
169 if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
170 getpos_help_keyxhelp(tmpwin,
171 visctrl(Cmd.spkeys[NHKF_GETPOS_MON_NEXT]),
172 visctrl(Cmd.spkeys[NHKF_GETPOS_MON_PREV]),
175 if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
176 getpos_help_keyxhelp(tmpwin,
177 visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]),
178 visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_PREV]),
181 if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) {
182 /* these are primarily useful when choosing a travel
183 destination for the '_' command */
184 getpos_help_keyxhelp(tmpwin,
185 visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_NEXT]),
186 visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_PREV]),
188 getpos_help_keyxhelp(tmpwin,
189 visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_NEXT]),
190 visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_PREV]),
192 getpos_help_keyxhelp(tmpwin,
193 visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_NEXT]),
194 visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_PREV]),
198 Sprintf(sbuf, "Use '%s' to change fast-move mode to %s.",
199 visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
200 fastmovemode[!iflags.getloc_moveskip]);
202 Sprintf(sbuf, "'%s'
\82Å
\8d\82\91¬
\88Ú
\93®
\83\82\81[
\83h
\82ð%s
\88Ú
\93®
\82É
\82·
\82é
\81D",
203 visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
204 fastmovemode[!iflags.getloc_moveskip]);
206 putstr(tmpwin, 0, sbuf);
207 if (!iflags.terrainmode || (iflags.terrainmode & TER_DETECT) == 0) {
209 Sprintf(sbuf, "Use '%s' to toggle menu listing for possible targets.",
210 visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
212 Sprintf(sbuf, "'%s'
\82Å
\89Â
\94\
\82È
\83^
\81[
\83Q
\83b
\83g
\82Ì
\83\81\83j
\83\85\81[
\95\
\8e¦
\82ð
\90Ø
\82è
\91Ö
\82¦
\82é
\81D",
213 visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
215 putstr(tmpwin, 0, sbuf);
218 "Use '%s' to change the mode of limiting possible targets.",
219 visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
222 "'%s'
\82Å
\90§
\8cÀ
\82³
\82ê
\82½
\89Â
\94\
\82È
\83^
\81[
\83Q
\83b
\83g
\82Ì
\83\82\81[
\83h
\82ð
\90Ø
\82è
\91Ö
\82¦
\82é
\81D",
223 visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
225 putstr(tmpwin, 0, sbuf);
227 if (!iflags.terrainmode) {
230 if (getpos_getvalid) {
232 Sprintf(sbuf, "Use '%s' or '%s' to move to valid locations.",
233 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
234 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
236 Sprintf(sbuf, "'%s'
\82©'%s'
\82Å
\90³
\93\96\82È
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é
\81D",
237 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
238 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
240 putstr(tmpwin, 0, sbuf);
242 if (getpos_hilitefunc) {
244 Sprintf(sbuf, "Use '%s' to display valid locations.",
245 visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
247 Sprintf(sbuf, "'%s'
\82Å
\89Â
\94\
\82È
\88Ê
\92u
\82ð
\95\
\8e¦
\82·
\82é
\81D",
248 visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
250 putstr(tmpwin, 0, sbuf);
253 Sprintf(sbuf, "Use '%s' to toggle automatic description.",
254 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
256 Sprintf(sbuf, "'%s'
\82Å
\90à
\96¾
\82Ì
\8e©
\93®
\95\
\8e¦
\82ð
\90Ø
\82è
\91Ö
\82¦
\82é
\81D",
257 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
259 putstr(tmpwin, 0, sbuf);
260 if (iflags.cmdassist) { /* assisting the '/' command, I suppose... */
263 (iflags.getpos_coords == GPCOORDS_NONE)
264 ? "(Set 'whatis_coord' option to include coordinates with '%s' text.)"
265 : "(Reset 'whatis_coord' option to omit coordinates from '%s' text.)",
266 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
269 (iflags.getpos_coords == GPCOORDS_NONE)
270 ? "('%s'
\82É
\8dÀ
\95W
\82ð
\8aÜ
\82Þ
\82É
\82Í'whatis_coord'
\83I
\83v
\83V
\83\87\83\93\82ð
\83I
\83\93\82É
\82·
\82é
\81D)"
271 : "('%s'
\82©
\82ç
\8dÀ
\95W
\82ð
\8f\9c\82
\82É
\82Í'whatis_coord'
\83I
\83v
\83V
\83\87\83\93\82ð
\83I
\83t
\82É
\82·
\82é
\81D)",
272 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
275 /* disgusting hack; the alternate selection characters work for any
276 getpos call, but only matter for dowhatis (and doquickwhatis) */
277 doing_what_is = (goal == what_is_an_unknown_object);
280 Sprintf(kbuf, "'%s' or '%s' or '%s' or '%s'",
281 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
282 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]),
283 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]),
284 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
286 Sprintf(kbuf, "'%s'
\82©'%s'
\82©'%s'
\82©'%s'",
287 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
288 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]),
289 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]),
290 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
293 Sprintf(kbuf, "'%s'", visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
296 Sprintf(sbuf, "Type a %s when you are at the right place.", kbuf);
298 Sprintf(sbuf, "[.]%s
\82Å
\8c\88\92è
\81D", kbuf);
300 putstr(tmpwin, 0, sbuf);
304 " '%s' describe current spot, show 'more info', move to another spot.",
305 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
308 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81A
\92Ç
\89Á
\8fî
\95ñ
\82ð
\95\
\8e¦
\82µ
\81A
\8e\9f\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é
\81D",
309 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
311 putstr(tmpwin, 0, sbuf);
314 " '%s' describe current spot,%s move to another spot;",
315 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
316 flags.help ? " prompt if 'more info'," : "");
319 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81C%s
\8e\9f\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é;",
320 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
321 flags.help ? "
\92Ç
\89Á
\8fî
\95ñ
\82ª
\82 \82ê
\82Î
\8am
\94F
\82µ
\81C" : "");
323 putstr(tmpwin, 0, sbuf);
326 " '%s' describe current spot, move to another spot;",
327 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]));
330 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81C
\8e\9f\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é;",
331 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]));
333 putstr(tmpwin, 0, sbuf);
336 " '%s' describe current spot, stop looking at things;",
337 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]));
340 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81C
\8c©
\82é
\82Ì
\82ð
\82â
\82ß
\82é;",
341 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]));
343 putstr(tmpwin, 0, sbuf);
348 putstr(tmpwin, 0, "Type Space or Escape when you're done.");
350 putstr(tmpwin, 0, "
\83X
\83y
\81[
\83X
\82Ü
\82½
\82Í
\83G
\83X
\83P
\81[
\83v
\82Å
\8fI
\97¹
\81D");
351 putstr(tmpwin, 0, "");
352 display_nhwindow(tmpwin, TRUE);
353 destroy_nhwindow(tmpwin);
357 cmp_coord_distu(a, b)
363 int dx, dy, dist_1, dist_2;
367 dist_1 = max(abs(dx), abs(dy));
370 dist_2 = max(abs(dx), abs(dy));
372 if (dist_1 == dist_2)
373 return (c1->y != c2->y) ? (c1->y - c2->y) : (c1->x - c2->x);
375 return dist_1 - dist_2;
378 #define IS_UNEXPLORED_LOC(x,y) \
380 && glyph_is_cmap(levl[(x)][(y)].glyph) \
381 && glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone \
382 && !levl[(x)][(y)].seenv)
384 static struct opvar *gloc_filter_map = (struct opvar *) 0;
386 #define GLOC_SAME_AREA(x,y) \
388 && (selection_getpoint((x),(y), gloc_filter_map)))
390 static int gloc_filter_floodfill_match_glyph;
393 gloc_filter_classify_glyph(glyph)
398 if (!glyph_is_cmap(glyph))
401 c = glyph_to_cmap(glyph);
403 if (is_cmap_room(c) || is_cmap_furniture(c))
405 else if (is_cmap_wall(c) || c == S_tree)
407 else if (is_cmap_corr(c))
409 else if (is_cmap_water(c))
411 else if (is_cmap_lava(c))
417 gloc_filter_floodfill_matcharea(x,y)
420 int glyph = back_to_glyph(x, y);
422 if (!levl[x][y].seenv)
425 if (glyph == gloc_filter_floodfill_match_glyph)
428 if (gloc_filter_classify_glyph(glyph)
429 == gloc_filter_classify_glyph(gloc_filter_floodfill_match_glyph))
436 gloc_filter_floodfill(x, y)
439 gloc_filter_floodfill_match_glyph = back_to_glyph(x, y);
441 set_selection_floodfillchk(gloc_filter_floodfill_matcharea);
442 selection_floodfill(gloc_filter_map, x, y, FALSE);
448 if (iflags.getloc_filter == GFILTER_AREA) {
449 if (!gloc_filter_map) {
450 gloc_filter_map = selection_opvar(NULL);
452 /* special case: if we're in a doorway, try to figure out which
453 direction we're moving, and use that side of the doorway */
454 if (IS_DOOR(levl[u.ux][u.uy].typ)) {
456 gloc_filter_floodfill(u.ux + u.dx, u.uy + u.dy);
458 /* TODO: maybe add both sides of the doorway? */
461 gloc_filter_floodfill(u.ux, u.uy);
471 if (gloc_filter_map) {
472 opvar_free_x(gloc_filter_map);
473 gloc_filter_map = NULL;
478 gather_locs_interesting(x, y, gloc)
481 /* TODO: if glyph is a pile glyph, convert to ordinary one
482 * in order to keep tail/boulder/rock check simple.
484 int glyph = glyph_at(x, y);
486 if (iflags.getloc_filter == GFILTER_VIEW && !cansee(x, y))
488 if (iflags.getloc_filter == GFILTER_AREA && !GLOC_SAME_AREA(x, y)
489 && !GLOC_SAME_AREA(x - 1, y) && !GLOC_SAME_AREA(x, y - 1)
490 && !GLOC_SAME_AREA(x + 1, y) && !GLOC_SAME_AREA(x, y + 1))
496 /* unlike '/M', this skips monsters revealed by
497 warning glyphs and remembered unseen ones */
498 return (glyph_is_monster(glyph)
499 && glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
501 return (glyph_is_object(glyph)
502 && glyph != objnum_to_glyph(BOULDER)
503 && glyph != objnum_to_glyph(ROCK));
505 return (glyph_is_cmap(glyph)
506 && (is_cmap_door(glyph_to_cmap(glyph))
507 || is_cmap_drawbridge(glyph_to_cmap(glyph))
508 || glyph_to_cmap(glyph) == S_ndoor));
510 return (glyph_is_cmap(glyph)
511 && (is_cmap_door(glyph_to_cmap(glyph))
512 || is_cmap_drawbridge(glyph_to_cmap(glyph))
513 || glyph_to_cmap(glyph) == S_ndoor
514 || glyph_to_cmap(glyph) == S_room
515 || glyph_to_cmap(glyph) == S_darkroom
516 || glyph_to_cmap(glyph) == S_corr
517 || glyph_to_cmap(glyph) == S_litcorr)
518 && (IS_UNEXPLORED_LOC(x + 1, y)
519 || IS_UNEXPLORED_LOC(x - 1, y)
520 || IS_UNEXPLORED_LOC(x, y + 1)
521 || IS_UNEXPLORED_LOC(x, y - 1)));
522 case GLOC_INTERESTING:
523 return gather_locs_interesting(x,y, GLOC_DOOR)
524 || !(glyph_is_cmap(glyph)
525 && (is_cmap_wall(glyph_to_cmap(glyph))
526 || glyph_to_cmap(glyph) == S_tree
527 || glyph_to_cmap(glyph) == S_bars
528 || glyph_to_cmap(glyph) == S_ice
529 || glyph_to_cmap(glyph) == S_air
530 || glyph_to_cmap(glyph) == S_cloud
531 || glyph_to_cmap(glyph) == S_lava
532 || glyph_to_cmap(glyph) == S_water
533 || glyph_to_cmap(glyph) == S_pool
534 || glyph_to_cmap(glyph) == S_ndoor
535 || glyph_to_cmap(glyph) == S_room
536 || glyph_to_cmap(glyph) == S_darkroom
537 || glyph_to_cmap(glyph) == S_corr
538 || glyph_to_cmap(glyph) == S_litcorr));
540 return (getpos_getvalid && getpos_getvalid(x,y));
546 /* gather locations for monsters or objects shown on the map */
548 gather_locs(arr_p, cnt_p, gloc)
556 * We always include the hero's location even if there is no monster
557 * (invisible hero without see invisible) or object (usual case)
558 * displayed there. That way, the count will always be at least 1,
559 * and player has a visual indicator (cursor returns to hero's spot)
560 * highlighting when successive 'm's or 'o's have cycled all the way
561 * through all monsters or objects.
563 * Hero's spot will always sort to array[0] because it will always
564 * be the shortest distance (namely, 0 units) away from <u.ux,u.uy>.
570 for (pass = 0; pass < 2; pass++) {
571 for (x = 1; x < COLNO; x++)
572 for (y = 0; y < ROWNO; y++) {
573 if ((x == u.ux && y == u.uy)
574 || gather_locs_interesting(x, y, gloc)) {
585 if (!pass) /* end of first pass */
586 *arr_p = (coord *) alloc(*cnt_p * sizeof (coord));
587 else /* end of second pass */
588 qsort(*arr_p, *cnt_p, sizeof (coord), cmp_coord_distu);
595 dxdy_to_dist_descr(dx, dy, fulldir)
604 Sprintf(buf, "here");
606 Sprintf(buf, "
\82±
\82±");
607 } else if ((dst = xytod(dx, dy)) != -1) {
608 /* explicit direction; 'one step' is implicit */
609 Sprintf(buf, "%s", directionname(dst));
611 const char *dirnames[4][2] = {
624 /* 9999: protect buf[] against overflow caused by invalid values */
628 Sprintf(eos(buf), "%d%s%s", abs(dy), dirnames[(dy > 0)][fulldir],
634 Sprintf(eos(buf), "%d%s", abs(dx),
635 dirnames[2 + (dx > 0)][fulldir]);
641 /* coordinate formatting for 'whatis_coord' option */
643 coord_desc(x, y, outbuf, cmode)
647 static char screen_fmt[16]; /* [12] suffices: "[%02d,%02d]" */
654 case GPCOORDS_COMFULL:
655 case GPCOORDS_COMPASS:
656 /* "east", "3s", "2n,4w" */
659 Sprintf(outbuf, "(%s)",
660 dxdy_to_dist_descr(dx, dy, cmode == GPCOORDS_COMFULL));
662 case GPCOORDS_MAP: /* x,y */
663 /* upper left corner of map is <1,0>;
664 with default COLNO,ROWNO lower right corner is <79,20> */
665 Sprintf(outbuf, "<%d,%d>", x, y);
667 case GPCOORDS_SCREEN: /* y+2,x */
668 /* for normal map sizes, force a fixed-width formatting so that
669 /m, /M, /o, and /O output lines up cleanly; map sizes bigger
670 than Nx999 or 999xM will still work, but not line up like normal
671 when displayed in a column setting */
673 Sprintf(screen_fmt, "[%%%sd,%%%sd]",
674 (ROWNO - 1 + 2 < 100) ? "02" : "03",
675 (COLNO - 1 < 100) ? "02" : "03");
676 /* map line 0 is screen row 2;
677 map column 0 isn't used, map column 1 is screen column 1 */
678 Sprintf(outbuf, screen_fmt, y + 2, x);
685 auto_describe(cx, cy)
692 const char *firstmatch = "unknown";
694 const char *firstmatch = "
\95s
\96¾";
698 if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) {
699 (void) coord_desc(cx, cy, tmpbuf, iflags.getpos_coords);
701 custompline(SUPPRESS_HISTORY,
702 "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
704 && getpos_getvalid && !getpos_getvalid(cx, cy))
706 (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
707 ? " (no travel path)" : "");
709 custompline(SUPPRESS_HISTORY,
710 "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
712 && getpos_getvalid && !getpos_getvalid(cx, cy))
713 ? " (
\95s
\90³)" : "",
714 (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
715 ? " (
\8co
\98H
\82È
\82µ)" : "");
717 curs(WIN_MAP, cx, cy);
723 getpos_menu(ccp, gloc)
732 menu_item *picks = (menu_item *) 0;
735 gather_locs(&garr, &gcount, gloc);
737 if (gcount < 2) { /* gcount always includes the hero */
738 free((genericptr_t) garr);
741 iflags.getloc_filter == GFILTER_VIEW ? "see" : "detect",
742 gloc_descr[gloc][0]);
744 You("%s
\82ð%s
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D",
746 iflags.getloc_filter == GFILTER_VIEW ? "
\8c©
\82é" : "
\8c©
\82Â
\82¯
\82é");
751 tmpwin = create_nhwindow(NHW_MENU);
755 /* gather_locs returns array[0] == you. skip it. */
756 for (i = 1; i < gcount; i++) {
760 const char *firstmatch = "unknown";
762 const char *firstmatch = "
\95s
\96¾";
767 if (do_screen_description(tmpcc, TRUE, sym, tmpbuf, &firstmatch)) {
768 (void) coord_desc(garr[i].x, garr[i].y, tmpbuf,
769 iflags.getpos_coords);
770 Sprintf(fullbuf, "%s%s%s", firstmatch,
771 (*tmpbuf ? " " : ""), tmpbuf);
772 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, fullbuf,
778 Sprintf(tmpbuf, "Pick a target %s%s%s",
780 gloc_filtertxt[iflags.getloc_filter],
781 iflags.getloc_travelmode ? " for travel" : "");
783 Sprintf(tmpbuf, "%s%s
\82Å
\96Ú
\95W
\82Æ
\82·
\82é%s
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢",
784 iflags.getloc_travelmode ? "
\88Ú
\93®
\82Ì
\82½
\82ß
\82É" : "",
785 gloc_filtertxt[iflags.getloc_filter],
786 gloc_descr[gloc][1]);
788 end_menu(tmpwin, tmpbuf);
789 pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
790 destroy_nhwindow(tmpwin);
792 ccp->x = garr[picks->item.a_int - 1].x;
793 ccp->y = garr[picks->item.a_int - 1].y;
794 free((genericptr_t) picks);
796 free((genericptr_t) garr);
797 return (pick_cnt > 0);
801 getpos(ccp, force, goal)
809 } const pick_chars_def[] = {
810 { NHKF_GETPOS_PICK, LOOK_TRADITIONAL },
811 { NHKF_GETPOS_PICK_Q, LOOK_QUICK },
812 { NHKF_GETPOS_PICK_O, LOOK_ONCE },
813 { NHKF_GETPOS_PICK_V, LOOK_VERBOSE }
815 const int mMoOdDxX_def[] = {
816 NHKF_GETPOS_MON_NEXT,
817 NHKF_GETPOS_MON_PREV,
818 NHKF_GETPOS_OBJ_NEXT,
819 NHKF_GETPOS_OBJ_PREV,
820 NHKF_GETPOS_DOOR_NEXT,
821 NHKF_GETPOS_DOOR_PREV,
822 NHKF_GETPOS_UNEX_NEXT,
823 NHKF_GETPOS_UNEX_PREV,
824 NHKF_GETPOS_INTERESTING_NEXT,
825 NHKF_GETPOS_INTERESTING_PREV,
826 NHKF_GETPOS_VALID_NEXT,
827 NHKF_GETPOS_VALID_PREV
834 boolean msg_given = TRUE; /* clear message window by default */
835 boolean show_goal_msg = FALSE;
836 boolean hilite_state = FALSE;
837 coord *garr[NUM_GLOCS] = DUMMY;
838 int gcount[NUM_GLOCS] = DUMMY;
839 int gidx[NUM_GLOCS] = DUMMY;
841 for (i = 0; i < SIZE(pick_chars_def); i++)
842 pick_chars[i] = Cmd.spkeys[pick_chars_def[i].nhkf];
843 pick_chars[SIZE(pick_chars_def)] = '\0';
845 for (i = 0; i < SIZE(mMoOdDxX_def); i++)
846 mMoOdDxX[i] = Cmd.spkeys[mMoOdDxX_def[i]];
847 mMoOdDxX[SIZE(mMoOdDxX_def)] = '\0';
851 goal = "desired location";
853 goal = "
\96Ú
\93I
\92n";
856 pline("(For instructions type a '%s')",
857 visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
859 pline("('%s'
\82Å
\83w
\83\8b\83v)",
860 visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
869 curs(WIN_MAP, cx, cy);
872 lock_mouse_cursor(TRUE);
877 pline("Move cursor to %s:", goal);
879 pline("
\83J
\81[
\83\
\83\8b\82ð%s
\82É
\93®
\82©
\82µ
\82Ä
\82
\82¾
\82³
\82¢:", goal);
880 curs(WIN_MAP, cx, cy);
882 show_goal_msg = FALSE;
883 } else if (iflags.autodescribe && !msg_given && !hilite_state) {
884 auto_describe(cx, cy);
887 c = nh_poskey(&tx, &ty, &sidx);
890 (*getpos_hilitefunc)(2);
891 hilite_state = FALSE;
892 curs(WIN_MAP, cx, cy);
896 if (iflags.autodescribe)
899 if (c == Cmd.spkeys[NHKF_ESC]) {
901 msg_given = TRUE; /* force clear */
908 /* a mouse click event, just assign and return */
913 if ((cp = index(pick_chars, c)) != 0) {
914 /* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */
915 result = pick_chars_def[(int) (cp - pick_chars)].ret;
918 for (i = 0; i < 8; i++) {
921 if (Cmd.dirchars[i] == c) {
922 /* a normal movement letter or digit */
925 } else if (Cmd.alphadirchars[i] == lowc((char) c)
926 || (Cmd.num_pad && Cmd.dirchars[i] == (c & 0177))) {
927 /* a shifted movement letter or Meta-digit */
928 if (iflags.getloc_moveskip) {
929 /* skip same glyphs */
930 int glyph = glyph_at(cx, cy);
934 while (isok(cx + dx, cy + dy)
935 && glyph == glyph_at(cx + dx, cy + dy)
936 && isok(cx + dx + xdir[i], cy + dy + ydir[i])
937 && glyph == glyph_at(cx + dx + xdir[i],
938 cy + dy + ydir[i])) {
949 /* truncate at map edge; diagonal moves complicate this... */
951 dy -= sgn(dy) * (1 - (cx + dx));
952 dx = 1 - cx; /* so that (cx+dx == 1) */
953 } else if (cx + dx > COLNO - 1) {
954 dy += sgn(dy) * ((COLNO - 1) - (cx + dx));
955 dx = (COLNO - 1) - cx;
958 dx -= sgn(dx) * (0 - (cy + dy));
959 dy = 0 - cy; /* so that (cy+dy == 0) */
960 } else if (cy + dy > ROWNO - 1) {
961 dx += sgn(dx) * ((ROWNO - 1) - (cy + dy));
962 dy = (ROWNO - 1) - cy;
969 if (c == Cmd.spkeys[NHKF_GETPOS_HELP] || redraw_cmd(c)) {
970 if (c == Cmd.spkeys[NHKF_GETPOS_HELP])
971 getpos_help(force, goal);
973 docrt(); /* redraw */
974 /* update message window to reflect that we're still targetting */
975 show_goal_msg = TRUE;
977 } else if (c == Cmd.spkeys[NHKF_GETPOS_SHOWVALID]
978 && getpos_hilitefunc) {
980 (*getpos_hilitefunc)(0);
981 (*getpos_hilitefunc)(1);
985 } else if (c == Cmd.spkeys[NHKF_GETPOS_AUTODESC]) {
986 iflags.autodescribe = !iflags.autodescribe;
988 pline("Automatic description %sis %s.",
989 flags.verbose ? "of features under cursor " : "",
990 iflags.autodescribe ? "on" : "off");
992 pline("%s
\90à
\96¾
\8e©
\93®
\95\
\8e¦
\81F%s",
993 flags.verbose ? "
\83J
\81[
\83\
\83\8b\82Ì
\89º
\82É
\82 \82é
\82à
\82Ì
\82Ì" : "",
994 iflags.autodescribe ? "
\83I
\83\93" : "
\83I
\83t");
996 if (!iflags.autodescribe)
997 show_goal_msg = TRUE;
1000 } else if (c == Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]) {
1001 const char *const view_filters[NUM_GFILTER] = {
1003 "Not limiting targets",
1004 "Limiting targets to in sight",
1005 "Limiting targets to in same area"
1007 "
\83^
\81[
\83Q
\83b
\83g
\82ð
\90§
\8cÀ
\82µ
\82È
\82¢",
1008 "
\8e\8b\8aE
\93à
\82É
\83^
\81[
\83Q
\83b
\83g
\82ð
\90§
\8cÀ
\82·
\82é",
1009 "
\93¯
\82¶
\83G
\83\8a\83A
\82É
\83^
\81[
\83Q
\83b
\83g
\82ð
\90§
\8cÀ
\82·
\82é"
1012 iflags.getloc_filter = (iflags.getloc_filter + 1) % NUM_GFILTER;
1013 for (i = 0; i < NUM_GLOCS; i++) {
1015 free((genericptr_t) garr[i]);
1018 gidx[i] = gcount[i] = 0;
1021 pline("%s.", view_filters[iflags.getloc_filter]);
1023 pline("%s
\81D", view_filters[iflags.getloc_filter]);
1026 } else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]) {
1027 iflags.getloc_usemenu = !iflags.getloc_usemenu;
1029 pline("%s a menu to show possible targets.",
1030 iflags.getloc_usemenu ? "Using" : "Not using");
1032 pline("
\89Â
\94\
\82È
\83^
\81[
\83Q
\83b
\83g
\82ð
\8c©
\82é
\82Ì
\82É
\83\81\83j
\83\85\81[
\82ð
\8eg%s
\81D",
1033 iflags.getloc_usemenu ? "
\82¤" : "
\82í
\82È
\82¢");
1037 } else if (c == Cmd.spkeys[NHKF_GETPOS_SELF]) {
1038 /* reset 'm&M', 'o&O', &c; otherwise, there's no way for player
1039 to achieve that except by manually cycling through all spots */
1040 for (i = 0; i < NUM_GLOCS; i++)
1045 } else if (c == Cmd.spkeys[NHKF_GETPOS_MOVESKIP]) {
1046 iflags.getloc_moveskip = !iflags.getloc_moveskip;
1048 pline("%skipping over similar terrain when fastmoving the cursor.",
1049 iflags.getloc_moveskip ? "S" : "Not s");
1051 pline("
\83J
\81[
\83\
\83\8b\82ð
\8d\82\91¬
\88Ú
\93®
\82³
\82¹
\82é
\82Æ
\82«
\82É
\8e\97\82½
\82æ
\82¤
\82È
\92n
\8c`
\82ð
\94ò
\82Î%s
\81D",
1052 iflags.getloc_moveskip ? "
\82·" : "
\82³
\82È
\82¢");
1054 } else if ((cp = index(mMoOdDxX, c)) != 0) { /* 'm|M', 'o|O', &c */
1055 /* nearest or farthest monster or object or door or unexplored */
1056 int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
1057 gloc = gtmp >> 1; /* 0..3 */
1059 if (iflags.getloc_usemenu) {
1061 if (getpos_menu(&tmpcrd, gloc)) {
1069 gather_locs(&garr[gloc], &gcount[gloc], gloc);
1070 gidx[gloc] = 0; /* garr[][0] is hero's spot */
1072 if (!(gtmp & 1)) { /* c=='m' || c=='o' || c=='d' || c=='x') */
1073 gidx[gloc] = (gidx[gloc] + 1) % gcount[gloc];
1074 } else { /* c=='M' || c=='O' || c=='D' || c=='X') */
1075 if (--gidx[gloc] < 0)
1076 gidx[gloc] = gcount[gloc] - 1;
1078 cx = garr[gloc][gidx[gloc]].x;
1079 cy = garr[gloc][gidx[gloc]].y;
1082 if (!index(quitchars, c)) {
1083 char matching[MAXPCHARS];
1084 int pass, lo_x, lo_y, hi_x, hi_y, k = 0;
1086 (void) memset((genericptr_t) matching, 0, sizeof matching);
1087 for (sidx = 1; sidx < MAXPCHARS; sidx++) { /* [0] left as 0 */
1088 if (IS_DOOR(sidx) || IS_WALL(sidx)
1089 || sidx == SDOOR || sidx == SCORR
1090 || glyph_to_cmap(k) == S_room
1091 || glyph_to_cmap(k) == S_darkroom
1092 || glyph_to_cmap(k) == S_corr
1093 || glyph_to_cmap(k) == S_litcorr)
1095 if (c == defsyms[sidx].sym || c == (int) showsyms[sidx])
1096 matching[sidx] = (char) ++k;
1099 for (pass = 0; pass <= 1; pass++) {
1100 /* pass 0: just past current pos to lower right;
1101 pass 1: upper left corner to current pos */
1102 lo_y = (pass == 0) ? cy : 0;
1103 hi_y = (pass == 0) ? ROWNO - 1 : cy;
1104 for (ty = lo_y; ty <= hi_y; ty++) {
1105 lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
1106 hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
1107 for (tx = lo_x; tx <= hi_x; tx++) {
1108 /* first, look at what is currently visible
1109 (might be monster) */
1110 k = glyph_at(tx, ty);
1111 if (glyph_is_cmap(k)
1112 && matching[glyph_to_cmap(k)])
1114 /* next, try glyph that's remembered here
1115 (might be trap or object) */
1116 if (level.flags.hero_memory
1117 /* !terrainmode: don't move to remembered
1118 trap or object if not currently shown */
1119 && !iflags.terrainmode) {
1120 k = levl[tx][ty].glyph;
1121 if (glyph_is_cmap(k)
1122 && matching[glyph_to_cmap(k)])
1125 /* last, try actual terrain here (shouldn't
1126 we be using lastseentyp[][] instead?) */
1127 if (levl[tx][ty].seenv) {
1128 k = back_to_glyph(tx, ty);
1129 if (glyph_is_cmap(k)
1130 && matching[glyph_to_cmap(k)])
1137 clear_nhwindow(WIN_MESSAGE);
1145 pline("Can't find dungeon feature '%c'.", c);
1147 pline("'%c'
\81H", c);
1155 Strcpy(note, "aborted");
1157 Strcpy(note, "
\92\86\92f
\82µ
\82½");
1160 Sprintf(note, "use '%c', '%c', '%c', '%c' or '%s'",
1161 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
1162 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
1164 Sprintf(note, "%c%c%c%c
\82Å
\88Ú
\93®
\81C%s
\82Å
\8fI
\97¹",
1165 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
1166 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
1169 pline("Unknown direction: '%s' (%s).", visctrl((char) c),
1171 pline("
\82»
\82Ì
\95û
\8cü
\82Í
\82È
\82¢
\81F'%s' (%s)", visctrl((char) c),
1174 } /* k => matching */
1181 pline("
\88È
\8fã
\81D");
1182 msg_given = FALSE; /* suppress clear */
1185 result = 0; /* not -1 */
1193 curs(WIN_MAP, cx, cy);
1197 lock_mouse_cursor(FALSE);
1200 clear_nhwindow(WIN_MESSAGE);
1203 for (i = 0; i < NUM_GLOCS; i++)
1205 free((genericptr_t) garr[i]);
1206 getpos_hilitefunc = (void FDECL((*), (int))) 0;
1207 getpos_getvalid = (boolean FDECL((*), (int, int))) 0;
1211 /* allocate space for a monster's name; removes old name if there is one */
1215 int lth; /* desired length (caller handles adding 1 for terminator) */
1218 /* allocate mextra if necessary; otherwise get rid of old name */
1220 mon->mextra = newmextra();
1222 free_mname(mon); /* already has mextra, might also have name */
1223 MNAME(mon) = (char *) alloc((unsigned) lth);
1225 /* zero length: the new name is empty; get rid of the old name */
1231 /* release a monster's name; retains mextra even if all fields are now null */
1236 if (has_mname(mon)) {
1237 free((genericptr_t) MNAME(mon));
1238 MNAME(mon) = (char *) 0;
1242 /* allocate space for an object's name; removes old name if there is one */
1246 int lth; /* desired length (caller handles adding 1 for terminator) */
1249 /* allocate oextra if necessary; otherwise get rid of old name */
1251 obj->oextra = newoextra();
1253 free_oname(obj); /* already has oextra, might also have name */
1254 ONAME(obj) = (char *) alloc((unsigned) lth);
1256 /* zero length: the new name is empty; get rid of the old name */
1262 /* release an object's name; retains oextra even if all fields are now null */
1267 if (has_oname(obj)) {
1268 free((genericptr_t) ONAME(obj));
1269 ONAME(obj) = (char *) 0;
1273 /* safe_oname() always returns a valid pointer to
1274 * a string, either the pointer to an object's name
1275 * if it has one, or a pointer to an empty string
1287 /* historical note: this returns a monster pointer because it used to
1288 allocate a new bigger block of memory to hold the monster and its name */
1290 christen_monst(mtmp, name)
1297 /* dogname & catname are PL_PSIZ arrays; object names have same limit */
1298 lth = (name && *name) ? ((int) strlen(name) + 1) : 0;
1299 if (lth > PL_PSIZ) {
1301 if (is_kanji2(buf, lth - 1))
1305 name = strncpy(buf, name, PL_PSIZ - 1);
1306 buf[PL_PSIZ - 1] = '\0';
1308 new_mname(mtmp, lth); /* removes old name if one is present */
1310 Strcpy(MNAME(mtmp), name);
1314 /* check whether user-supplied name matches or nearly matches an unnameable
1315 monster's name; if so, give an alternate reject message for do_mname() */
1317 alreadynamed(mtmp, monnambuf, usrbuf)
1319 char *monnambuf, *usrbuf;
1321 char pronounbuf[10], *p;
1323 if (fuzzymatch(usrbuf, monnambuf, " -_", TRUE)
1324 /* catch trying to name "the Oracle" as "Oracle" */
1325 || (!strncmpi(monnambuf, "the ", 4)
1326 && fuzzymatch(usrbuf, monnambuf + 4, " -_", TRUE))
1327 /* catch trying to name "invisible Orcus" as "Orcus" */
1328 || ((p = strstri(monnambuf, "invisible ")) != 0
1329 && fuzzymatch(usrbuf, p + 10, " -_", TRUE))
1330 /* catch trying to name "the {priest,Angel} of Crom" as "Crom" */
1331 || ((p = strstri(monnambuf, " of ")) != 0
1332 && fuzzymatch(usrbuf, p + 4, " -_", TRUE))) {
1334 pline("%s is already called %s.",
1335 upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
1337 pline("%s
\82Í
\8aù
\82É%s
\82Æ
\8cÄ
\82Î
\82ê
\82Ä
\82¢
\82é
\81D",
1338 upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
1341 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8eg
\82í
\82È
\82¢*/
1342 } else if (mtmp->data == &mons[PM_JUIBLEX]
1343 && strstri(monnambuf, "Juiblex")
1344 && !strcmpi(usrbuf, "Jubilex")) {
1345 pline("%s doesn't like being called %s.", upstart(monnambuf), usrbuf);
1352 /* allow player to assign a name to some chosen monster */
1356 char buf[BUFSZ] = DUMMY, monnambuf[BUFSZ], qbuf[QBUFSZ];
1359 struct monst *mtmp = 0;
1361 if (Hallucination) {
1363 You("would never recognize it anyway.");
1365 You("
\82»
\82ê
\82ð
\94F
\8e¯
\82Å
\82«
\82È
\82¢
\81D");
1371 if (getpos(&cc, FALSE, "the monster you want to name") < 0
1373 if (getpos(&cc, FALSE, "
\82 \82È
\82½
\82ª
\96¼
\82Ã
\82¯
\82½
\82¢
\89ö
\95¨") < 0
1378 if (cx == u.ux && cy == u.uy) {
1379 if (u.usteed && canspotmon(u.usteed)) {
1383 pline("This %s creature is called %s and cannot be renamed.",
1385 pline("
\82±
\82Ì%s
\90¶
\82«
\95¨
\82Í%s
\82Æ
\8cÄ
\82Î
\82ê
\82Ä
\82¢
\82Ä
\81C
\96¼
\91O
\82Í
\95Ï
\8dX
\82Å
\82«
\82È
\82¢
\81D",
1386 beautiful(), plname);
1390 mtmp = m_at(cx, cy);
1394 && (!(cansee(cx, cy) || see_with_infrared(mtmp))
1395 || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE
1396 || mtmp->m_ap_type == M_AP_OBJECT
1397 || (mtmp->minvis && !See_invisible)))) {
1399 pline("I see no monster there.");
1401 pline("
\82»
\82±
\82É
\89ö
\95¨
\82Í
\82¢
\82È
\82¢
\81D");
1404 /* special case similar to the one in lookat() */
1406 Sprintf(qbuf, "What do you want to call %s?",
1408 Sprintf(qbuf, "%s
\82ð
\89½
\82Æ
\8cÄ
\82Ñ
\82Ü
\82·
\82©
\81H",
1409 distant_monnam(mtmp, ARTICLE_THE, monnambuf));
1411 if (!*buf || *buf == '\033')
1413 /* strip leading and trailing spaces; unnames monster if all spaces */
1414 (void) mungspaces(buf);
1416 /* Unique monsters have their own specific names or titles.
1417 * Shopkeepers, temple priests and other minions use alternate
1418 * name formatting routines which ignore any user-supplied name.
1420 * Don't say the name is being rejected if it happens to match
1421 * the existing name.
1423 if ((mtmp->data->geno & G_UNIQ) && !mtmp->ispriest) {
1424 if (!alreadynamed(mtmp, monnambuf, buf))
1426 pline("%s doesn't like being called names!", upstart(monnambuf));
1428 pline("%s
\82Í
\82 \82¾
\96¼
\82Å
\8cÄ
\82Î
\82ê
\82é
\82Ì
\82ª
\8c\99\82¢
\82È
\82æ
\82¤
\82¾
\81I", Monnam(mtmp));
1429 } else if (mtmp->isshk
1430 && !(Deaf || mtmp->msleeping || !mtmp->mcanmove
1431 || mtmp->data->msound <= MS_ANIMAL)) {
1432 if (!alreadynamed(mtmp, monnambuf, buf))
1434 verbalize("I'm %s, not %s.", shkname(mtmp), buf);
1436 verbalize("
\8e\84\82Í%s
\82¾
\81C%s
\82Å
\82Í
\82È
\82¢
\81D", shkname(mtmp), buf);
1437 } else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk) {
1438 if (!alreadynamed(mtmp, monnambuf, buf))
1440 pline("%s will not accept the name %s.", upstart(monnambuf), buf);
1442 pline("%s
\82Í%s
\82Æ
\82¢
\82¤
\96¼
\91O
\82ð
\8eó
\82¯
\82¢
\82ê
\82È
\82©
\82Á
\82½
\81D", monnambuf, buf);
1444 (void) christen_monst(mtmp, buf);
1447 STATIC_VAR int via_naming = 0;
1450 * This routine used to change the address of 'obj' so be unsafe if not
1451 * used with extreme care. Applying a name to an object no longer
1452 * allocates a replacement object, so that old risk is gone.
1457 register struct obj *obj;
1459 char *bufp, buf[BUFSZ] = DUMMY, bufcpy[BUFSZ], qbuf[QBUFSZ];
1463 /* Do this now because there's no point in even asking for a name */
1464 if (obj->otyp == SPE_NOVEL) {
1466 pline("%s already has a published name.", Ysimple_name2(obj));
1468 pline("%s
\82É
\82Í
\82·
\82Å
\82É
\8fo
\94Å
\8e\9e\82Ì
\96¼
\91O
\82ª
\82 \82é
\81D", Ysimple_name2(obj));
1473 Sprintf(qbuf, "What do you want to name %s ",
1474 is_plural(obj) ? "these" : "this");
1475 (void) safe_qbuf(qbuf, qbuf, "?", obj, xname, simpleonames, "item");
1477 (void) safe_qbuf(qbuf, "", "
\82ð
\89½
\82Æ
\96¼
\82Ã
\82¯
\82Ü
\82·
\82©
\81H", obj, xname, simpleonames, "item");
1480 if (!*buf || *buf == '\033')
1482 /* strip leading and trailing spaces; unnames item if all spaces */
1483 (void) mungspaces(buf);
1486 * We don't violate illiteracy conduct here, although it is
1487 * arguable that we should for anything other than "X". Doing so
1488 * would make attaching player's notes to hero's inventory have an
1489 * in-game effect, which may or may not be the correct thing to do.
1491 * We do violate illiteracy in oname() if player creates Sting or
1492 * Orcrist, clearly being literate (no pun intended...).
1495 /* relax restrictions over proper capitalization for artifacts */
1496 if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp)
1499 if (obj->oartifact) {
1501 pline_The("artifact seems to resist the attempt.");
1503 pline("
\90¹
\8aí
\82Í
\96¼
\82Ã
\82¯
\82ð
\8b\91\94Û
\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82¾
\81D");
1505 } else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) {
1506 /* this used to change one letter, substituting a value
1507 of 'a' through 'y' (due to an off by one error, 'z'
1508 would never be selected) and then force that to
1509 upper case if such was the case of the input;
1510 now, the hand slip scuffs one or two letters as if
1511 the text had been trodden upon, sometimes picking
1512 punctuation instead of an arbitrary letter;
1513 unfortunately, we have to cover the possibility of
1514 it targetting spaces so failing to make any change
1515 (we know that it must eventually target a nonspace
1516 because buf[] matches a valid artifact name) */
1517 Strcpy(bufcpy, buf);
1518 /* for "the Foo of Bar", only scuff "Foo of Bar" part */
1519 bufp = !strncmpi(bufcpy, "the ", 4) ? (buf + 4) : buf;
1521 wipeout_text(bufp, rnd(2), (unsigned) 0);
1522 } while (!strcmp(buf, bufcpy));
1524 pline("While engraving, your %s slips.", body_part(HAND));
1526 pline("
\8d\8f\82ñ
\82Å
\82¢
\82é
\8aÔ
\82É%s
\82ª
\8a\8a\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D", body_part(HAND));
1527 display_nhwindow(WIN_MESSAGE, FALSE);
1529 You("engrave: \"%s\".", buf);
1531 You("
\8d\8f\82ñ
\82¾:
\81u%s
\81v
\81D",buf);
1532 /* violate illiteracy conduct since hero attempted to write
1533 a valid artifact name */
1534 u.uconduct.literate++;
1536 ++via_naming; /* This ought to be an argument rather than a static... */
1537 obj = oname(obj, buf);
1538 --via_naming; /* ...but oname() is used in a lot of places, so defer. */
1549 lth = *name ? (int) (strlen(name) + 1) : 0;
1550 if (lth > PL_PSIZ) {
1553 name = strncpy(buf, name, PL_PSIZ - 1);
1554 buf[PL_PSIZ - 1] = '\0';
1556 if (is_kanji2(name, lth - 1))
1558 name = strncpy(buf, name, lth - 1);
1559 buf[lth - 1] = '\0';
1562 /* If named artifact exists in the game, do not create another.
1563 * Also trying to create an artifact shouldn't de-artifact
1564 * it (e.g. Excalibur from prayer). In this case the object
1565 * will retain its current name. */
1566 if (obj->oartifact || (lth && exist_artifact(obj->otyp, name)))
1569 new_oname(obj, lth); /* removes old name if one is present */
1571 Strcpy(ONAME(obj), name);
1574 artifact_exists(obj, name, TRUE);
1575 if (obj->oartifact) {
1576 /* can't dual-wield with artifact as secondary weapon */
1577 if (obj == uswapwep)
1579 /* activate warning if you've just named your weapon "Sting" */
1581 set_artifact_intrinsic(obj, TRUE, W_WEP);
1582 /* if obj is owned by a shop, increase your bill */
1584 alter_cost(obj, 0L);
1586 /* violate illiteracy conduct since successfully wrote arti-name */
1587 u.uconduct.literate++;
1595 static NEARDATA const char callable[] = {
1596 SCROLL_CLASS, POTION_CLASS, WAND_CLASS, RING_CLASS, AMULET_CLASS,
1597 GEM_CLASS, SPBOOK_CLASS, ARMOR_CLASS, TOOL_CLASS, 0
1601 objtyp_is_callable(i)
1604 return (boolean) (objects[i].oc_uname
1605 || (OBJ_DESCR(objects[i])
1606 && index(callable, objects[i].oc_class)));
1609 /* C and #name commands - player can name monster or object or type of obj */
1616 menu_item *pick_list = 0;
1617 char ch, allowall[2];
1618 /* if player wants a,b,c instead of i,o when looting, do that here too */
1619 boolean abc = flags.lootabc;
1621 win = create_nhwindow(NHW_MENU);
1624 any.a_char = 'm'; /* group accelerator 'C' */
1625 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'C', ATR_NONE,
1627 "a monster", MENU_UNSELECTED);
1629 "
\89ö
\95¨", MENU_UNSELECTED);
1631 /* we use y and n as accelerators so that we can accept user's
1632 response keyed to old "name an individual object?" prompt */
1633 any.a_char = 'i'; /* group accelerator 'y' */
1634 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'y', ATR_NONE,
1636 "a particular object in inventory", MENU_UNSELECTED);
1638 "
\8e\9d\82¿
\95¨
\82Ì
\92\86\82Ì
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80", MENU_UNSELECTED);
1639 any.a_char = 'o'; /* group accelerator 'n' */
1640 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'n', ATR_NONE,
1642 "the type of an object in inventory", MENU_UNSELECTED);
1644 "
\8e\9d\82¿
\95¨
\82Ì
\92\86\82Ì
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80\82Ì
\8eí
\97Þ", MENU_UNSELECTED);
1646 any.a_char = 'f'; /* group accelerator ',' (or ':' instead?) */
1647 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, ',', ATR_NONE,
1649 "the type of an object upon the floor", MENU_UNSELECTED);
1651 "
\8f°
\82Ì
\8fã
\82É
\82 \82é
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80\82Ì
\8eí
\97Þ", MENU_UNSELECTED);
1652 any.a_char = 'd'; /* group accelerator '\' */
1653 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, '\\', ATR_NONE,
1655 "the type of an object on discoveries list", MENU_UNSELECTED);
1657 "
\94
\8c©
\95¨
\88ê
\97\97\82É
\82 \82é
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80\82Ì
\8eí
\97Þ", MENU_UNSELECTED);
1658 any.a_char = 'a'; /* group accelerator 'l' */
1659 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'l', ATR_NONE,
1661 "record an annotation for the current level", MENU_UNSELECTED);
1663 "
\8c»
\8dÝ
\82Ì
\8aK
\82É
\91Î
\82·
\82é
\83\81\83\82\82Ì
\8bL
\98^", MENU_UNSELECTED);
1665 end_menu(win, "What do you want to name?");
1667 end_menu(win, "
\82Ç
\82ê
\82É
\96¼
\91O
\82ð
\82Â
\82¯
\82Ü
\82·
\82©
\81H");
1668 if (select_menu(win, PICK_ONE, &pick_list) > 0) {
1669 ch = pick_list[0].item.a_char;
1670 free((genericptr_t) pick_list);
1673 destroy_nhwindow(win);
1679 case 'm': /* name a visible monster */
1682 case 'i': /* name an individual object in inventory */
1683 allowall[0] = ALL_CLASSES;
1685 obj = getobj(allowall, "name");
1689 case 'o': /* name a type of object in inventory */
1690 obj = getobj(callable, "call");
1692 /* behave as if examining it in inventory;
1693 this might set dknown if it was picked up
1694 while blind and the hero can now see */
1699 You("would never recognize another one.");
1701 You("
\91¼
\82É
\94F
\8e¯
\82Å
\82«
\82È
\82¢
\81D");
1703 } else if (!objtyp_is_callable(obj->otyp)) {
1704 You("know those as well as you ever will.");
1711 case 'f': /* name a type of object visible on the floor */
1714 case 'd': /* name a type of object on the discoveries list */
1717 case 'a': /* annotate level */
1724 /* for use by safe_qbuf() */
1732 otemp.oextra = (struct oextra *) 0;
1734 /* in case water is already known, convert "[un]holy water" to "water" */
1735 otemp.blessed = otemp.cursed = 0;
1736 /* remove attributes that are doname() caliber but get formatted
1737 by xname(); most of these fixups aren't really needed because the
1738 relevant type of object isn't callable so won't reach this far */
1739 if (otemp.oclass == WEAPON_CLASS)
1740 otemp.opoisoned = 0; /* not poisoned */
1741 else if (otemp.oclass == POTION_CLASS)
1742 otemp.odiluted = 0; /* not diluted */
1743 else if (otemp.otyp == TOWEL || otemp.otyp == STATUE)
1744 otemp.spe = 0; /* not wet or historic */
1745 else if (otemp.otyp == TIN)
1746 otemp.known = 0; /* suppress tin type (homemade, &c) and mon type */
1747 else if (otemp.otyp == FIGURINE)
1748 otemp.corpsenm = NON_PM; /* suppress mon type */
1749 else if (otemp.otyp == HEAVY_IRON_BALL)
1750 otemp.owt = objects[HEAVY_IRON_BALL].oc_weight; /* not "very heavy" */
1751 else if (otemp.oclass == FOOD_CLASS && otemp.globby)
1752 otemp.owt = 120; /* 6*20, neither a small glob nor a large one */
1754 return an(xname(&otemp));
1761 char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
1765 return; /* probably blind */
1767 if (obj->oclass == POTION_CLASS && obj->fromsink)
1768 /* kludge, meaning it's sink water */
1770 Sprintf(qbuf, "Call a stream of %s fluid:",
1772 Sprintf(qbuf, "%s
\89t
\91Ì:",
1773 OBJ_DESCR(objects[obj->otyp]));
1776 (void) safe_qbuf(qbuf, "Call ", ":", obj,
1777 docall_xname, simpleonames, "thing");
1779 (void) safe_qbuf(qbuf, "", "
\82É
\89½
\82Æ
\96¼
\91O
\82ð
\95t
\82¯
\82é
\81H", obj,
1780 docall_xname, simpleonames, "
\82±
\82ê");
1783 if (!*buf || *buf == '\033')
1786 /* clear old name */
1787 str1 = &(objects[obj->otyp].oc_uname);
1789 free((genericptr_t) *str1);
1791 /* strip leading and trailing spaces; uncalls item if all spaces */
1792 (void) mungspaces(buf);
1794 if (*str1) { /* had name, so possibly remove from disco[] */
1795 /* strip name first, for the update_inventory() call
1796 from undiscover_object() */
1798 undiscover_object(obj->otyp);
1801 *str1 = dupstr(buf);
1802 discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
1812 struct obj *obj = 0;
1814 boolean fakeobj = FALSE, use_plural;
1816 boolean fakeobj = FALSE;
1819 cc.x = u.ux, cc.y = u.uy;
1820 /* "dot for under/over you" only makes sense when the cursor hasn't
1821 been moved off the hero's '@' yet, but there's no way to adjust
1822 the help text once getpos() has started */
1824 Sprintf(buf, "object on map (or '.' for one %s you)",
1825 (u.uundetected && hides_under(youmonst.data)) ? "over" : "under");
1827 Strcpy(buf, "
\92n
\90}
\8fã
\82Ì
\95¨
\91Ì(
\82 \82é
\82¢
\82Í'.'
\82Å
\82 \82È
\82½
\82Ì
\82¢
\82é
\8fê
\8f\8a");
1829 if (getpos(&cc, FALSE, buf) < 0 || cc.x <= 0)
1831 if (cc.x == u.ux && cc.y == u.uy) {
1832 obj = vobj_at(u.ux, u.uy);
1834 glyph = glyph_at(cc.x, cc.y);
1835 if (glyph_is_object(glyph))
1836 fakeobj = object_from_map(glyph, cc.x, cc.y, &obj);
1837 /* else 'obj' stays null */
1840 /* "under you" is safe here since there's no object to hide under */
1842 pline("There doesn't seem to be any object %s.",
1843 (cc.x == u.ux && cc.y == u.uy) ? "under you" : "there");
1845 pline("%s
\82É
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82¾
\81D",
1846 (cc.x == u.ux && cc.y == u.uy) ? "
\82 \82È
\82½
\82Ì
\89º" : "
\82»
\82±");
1850 /* note well: 'obj' might be as instance of STRANGE_OBJECT if target
1851 is a mimic; passing that to xname (directly or via simpleonames)
1852 would yield "glorkum" so we need to handle it explicitly; it will
1853 always fail the Hallucination test and pass the !callable test,
1854 resulting in the "can't be assigned a type name" message */
1855 Strcpy(buf, (obj->otyp != STRANGE_OBJECT)
1857 : obj_descr[STRANGE_OBJECT].oc_name);
1859 use_plural = (obj->quan > 1L);
1861 if (Hallucination) {
1862 const char *unames[6];
1865 /* straight role name */
1866 unames[0] = ((Upolyd ? u.mfemale : flags.female) && urole.name.f)
1869 /* random rank title for hero's role */
1870 unames[1] = rank_of(rnd(30), Role_switch, flags.female);
1871 /* random fake monster */
1872 unames[2] = bogusmon(tmpbuf, (char *) 0);
1873 /* increased chance for fake monster */
1874 unames[3] = unames[2];
1876 unames[4] = roguename();
1879 unames[5] = "Wibbly Wobbly";
1881 unames[5] = "
\82¤
\82ë
\82¤
\82ë";
1883 pline("%s %s to call you \"%s.\"",
1884 The(buf), use_plural ? "decide" : "decides",
1885 unames[rn2(SIZE(unames))]);
1887 pline("%s
\82Í
\82 \82È
\82½
\82ð
\81u%s
\81v
\82Æ
\8cÄ
\82Ô
\82±
\82Æ
\82É
\8c\88\82ß
\82½
\81D",
1889 unames[rn2(SIZE(unames))]);
1891 } else if (!objtyp_is_callable(obj->otyp)) {
1893 pline("%s %s can't be assigned a type name.",
1894 use_plural ? "Those" : "That", buf);
1896 pline("%s
\82É
\8eí
\97Þ
\82Ì
\96¼
\91O
\82ð
\8a\84\82è
\93\96\82Ä
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
1899 } else if (!obj->dknown) {
1901 You("don't know %s %s well enough to name %s.",
1902 use_plural ? "those" : "that", buf, use_plural ? "them" : "it");
1904 You("
\96¼
\91O
\82ð
\95t
\82¯
\82ç
\82ê
\82é
\82Ù
\82Ç%s
\82Ì
\82±
\82Æ
\82ð
\82æ
\82
\92m
\82ç
\82È
\82¢
\81D",
1914 static const char *const ghostnames[] = {
1915 /* these names should have length < PL_NSIZ */
1916 /* Capitalize the names for aesthetics -dgk */
1917 "Adri", "Andries", "Andreas", "Bert", "David", "Dirk",
1918 "Emile", "Frans", "Fred", "Greg", "Hether", "Jay",
1919 "John", "Jon", "Karnov", "Kay", "Kenny", "Kevin",
1920 "Maud", "Michiel", "Mike", "Peter", "Robert", "Ron",
1921 "Tom", "Wilmar", "Nick Danger", "Phoenix", "Jiro", "Mizue",
1922 "Stephan", "Lance Braccus", "Shadowhawk"
1925 /* ghost names formerly set by x_monnam(), now by makemon() instead */
1929 return rn2(7) ? ghostnames[rn2(SIZE(ghostnames))] : (const char *) plname;
1933 * Monster naming functions:
1934 * x_monnam is the generic monster-naming function.
1935 * seen unseen detected named
1936 * mon_nam: the newt it the invisible orc Fido
1937 * noit_mon_nam:the newt (as if detected) the invisible orc Fido
1938 * l_monnam: newt it invisible orc dog called Fido
1939 * Monnam: The newt It The invisible orc Fido
1940 * noit_Monnam: The newt (as if detected) The invisible orc Fido
1941 * Adjmonnam: The poor newt It The poor invisible orc The poor Fido
1942 * Amonnam: A newt It An invisible orc Fido
1943 * a_monnam: a newt it an invisible orc Fido
1944 * m_monnam: newt xan orc Fido
1945 * y_monnam: your newt your xan your invisible orc Fido
1946 * noname_monnam(mon,article):
1947 * article newt art xan art invisible orc art dog
1950 /* Bug: if the monster is a priest or shopkeeper, not every one of these
1951 * options works, since those are special cases.
1954 x_monnam(mtmp, article, adjective, suppress, called)
1955 register struct monst *mtmp;
1957 /* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious
1958 * ARTICLE_YOUR: "your" on pets, "the" on everything else
1960 * If the monster would be referred to as "it" or if the monster has a name
1961 * _and_ there is no adjective, "invisible", "saddled", etc., override this
1962 * and always use no article.
1964 const char *adjective;
1966 /* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE.
1967 * EXACT_NAME: combination of all the above
1968 * SUPPRESS_NAME: omit monster's assigned name (unless uniq w/ pname).
1972 char *buf = nextmbuf();
1973 struct permonst *mdat = mtmp->data;
1974 const char *pm_name = mdat->mname;
1975 boolean do_hallu, do_invis, do_it, do_saddle, do_name;
1977 boolean name_at_start, has_adjectives;
1981 if (program_state.gameover)
1982 suppress |= SUPPRESS_HALLUCINATION;
1983 if (article == ARTICLE_YOUR && !mtmp->mtame)
1984 article = ARTICLE_THE;
1986 do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION);
1987 do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE);
1988 do_it = !canspotmon(mtmp) && article != ARTICLE_YOUR
1989 && !program_state.gameover && mtmp != u.usteed
1990 && !(u.uswallow && mtmp == u.ustuck) && !(suppress & SUPPRESS_IT);
1991 do_saddle = !(suppress & SUPPRESS_SADDLE);
1992 do_name = !(suppress & SUPPRESS_NAME) || type_is_pname(mdat);
1996 /* unseen monsters, etc. Use "it" */
2001 Strcpy(buf, "
\89½
\8eÒ
\82©");
2005 /* priests and minions: don't even use this function */
2006 if (mtmp->ispriest || mtmp->isminion) {
2007 char priestnambuf[BUFSZ];
2009 long save_prop = EHalluc_resistance;
2010 unsigned save_invis = mtmp->minvis;
2012 /* when true name is wanted, explicitly block Hallucination */
2014 EHalluc_resistance = 1L;
2017 name = priestname(mtmp, priestnambuf);
2018 EHalluc_resistance = save_prop;
2019 mtmp->minvis = save_invis;
2021 if (article == ARTICLE_NONE && !strncmp(name, "the ", 4))
2024 return strcpy(buf, name);
2026 /* an "aligned priest" not flagged as a priest or minion should be
2027 "priest" or "priestess" (normally handled by priestname()) */
2028 if (mdat == &mons[PM_ALIGNED_PRIEST])
2030 pm_name = mtmp->female ? "priestess" : "priest";
2032 pm_name = mtmp->female ? "
\93ò
\91m" : "
\91m
\97µ";
2033 else if (mdat == &mons[PM_HIGH_PRIEST] && mtmp->female)
2035 pm_name = "high priestess";
2037 pm_name = "
\96@
\89¤";
2039 /* Shopkeepers: use shopkeeper name. For normal shopkeepers, just
2040 * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
2041 * shopkeeper" or "Asidonhopo the blue dragon". If hallucinating,
2042 * none of this applies.
2044 if (mtmp->isshk && !do_hallu) {
2046 if (adjective && article == ARTICLE_THE) {
2047 /* pathological case: "the angry Asidonhopo the blue dragon"
2049 Strcpy(buf, "the ");
2050 Strcat(strcat(buf, adjective), " ");
2051 Strcat(buf, shkname(mtmp));
2054 Strcat(buf, shkname(mtmp));
2055 if (mdat == &mons[PM_SHOPKEEPER] && !do_invis)
2057 Strcat(buf, " the ");
2059 Strcat(buf, "invisible ");
2060 Strcat(buf, pm_name);
2063 if (mdat == &mons[PM_SHOPKEEPER] && !do_invis){
2064 Strcpy(buf, shkname(mtmp));
2066 Sprintf(buf, "%s
\82Æ
\82¢
\82¤
\96¼
\82Ì%s%s",
2067 shkname(mtmp), do_invis ? "
\8ep
\82Ì
\8c©
\82¦
\82È
\82¢" : "",
2074 /* Put the adjectives in the buffer */
2077 Strcat(strcat(buf, adjective), " ");
2079 Strcat(buf, adjective);
2082 Strcat(buf, "invisible ");
2084 Strcat(buf, "
\8ep
\82Ì
\8c©
\82¦
\82È
\82¢");
2085 if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind
2088 Strcat(buf, "saddled ");
2090 Strcat(buf, "
\88Æ
\82Ì
\82Â
\82¢
\82Ä
\82¢
\82é");
2093 has_adjectives = TRUE;
2095 has_adjectives = FALSE;
2098 /* Put the actual monster name or type into the buffer now */
2099 /* Be sure to remember whether the buffer starts with a name */
2102 char *rname = rndmonnam(&rnamecode);
2106 name_at_start = bogon_is_pname(rnamecode);
2108 } else if (do_name && has_mname(mtmp)) {
2109 char *name = MNAME(mtmp);
2111 if (mdat == &mons[PM_GHOST]) {
2113 Sprintf(eos(buf), "%s ghost", s_suffix(name));
2115 Sprintf(buf, "%s
\82Ì
\97H
\97ì", name);
2117 name_at_start = TRUE;
2119 } else if (called) {
2121 Sprintf(eos(buf), "%s called %s", pm_name, name);
2123 Sprintf(eos(buf), "%s
\82Æ
\82¢
\82¤
\96¼
\82Ì%s", name, pm_name);
2125 name_at_start = (boolean) type_is_pname(mdat);
2127 #if 0 /*JP*//*
\92è
\8a¥
\8e\8c\82Ì
\8f\88\97\9d\82Í
\95s
\97v*/
2128 } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) {
2129 /* <name> the <adjective> <invisible> <saddled> <rank> */
2133 pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */
2136 Strcat(pbuf, bp + 5); /* append the rest of the name */
2138 article = ARTICLE_NONE;
2139 name_at_start = TRUE;
2144 name_at_start = TRUE;
2147 } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) {
2150 Strcpy(pbuf, rank_of((int) mtmp->m_lev, monsndx(mdat),
2151 (boolean) mtmp->female));
2153 Strcat(buf, lcase(pbuf));
2158 name_at_start = FALSE;
2161 Strcat(buf, pm_name);
2163 name_at_start = (boolean) type_is_pname(mdat);
2167 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\8a¥
\8e\8c\82Í
\82È
\82¢*/
2168 if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) {
2169 if (mdat == &mons[PM_WIZARD_OF_YENDOR])
2170 article = ARTICLE_THE;
2172 article = ARTICLE_NONE;
2173 } else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) {
2174 article = ARTICLE_THE;
2182 Strcpy(buf2, "your ");
2187 Strcpy(buf2, "the ");
2207 return x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
2208 (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, TRUE);
2215 return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2216 (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, FALSE);
2219 /* print the name as if mon_nam() was called, but assume that the player
2220 * can always see the monster--used for probing and for monsters aggravating
2221 * the player with a cursed potion of invisibility
2227 return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2228 (has_mname(mtmp)) ? (SUPPRESS_SADDLE | SUPPRESS_IT)
2237 register char *bp = mon_nam(mtmp);
2247 register char *bp = noit_mon_nam(mtmp);
2253 /* return "a dog" rather than "Fido", honoring hallucination and visibility */
2255 noname_monnam(mtmp, article)
2259 return x_monnam(mtmp, article, (char *) 0, SUPPRESS_NAME, FALSE);
2262 /* monster's own name -- overrides hallucination and [in]visibility
2263 so shouldn't be used in ordinary messages (mainly for disclosure) */
2268 return x_monnam(mtmp, ARTICLE_NONE, (char *) 0, EXACT_NAME, FALSE);
2271 /* pet name: "your little dog" */
2276 int prefix, suppression_flag;
2278 prefix = mtmp->mtame ? ARTICLE_YOUR : ARTICLE_THE;
2279 suppression_flag = (has_mname(mtmp)
2280 /* "saddled" is redundant when mounted */
2281 || mtmp == u.usteed)
2285 return x_monnam(mtmp, prefix, (char *) 0, suppression_flag, FALSE);
2289 Adjmonnam(mtmp, adj)
2293 char *bp = x_monnam(mtmp, ARTICLE_THE, adj,
2294 has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2304 return x_monnam(mtmp, ARTICLE_A, (char *) 0,
2305 has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2312 char *bp = a_monnam(mtmp);
2318 /* used for monster ID by the '/', ';', and 'C' commands to block remote
2319 identification of the endgame altars via their attending priests */
2321 distant_monnam(mon, article, outbuf)
2323 int article; /* only ARTICLE_NONE and ARTICLE_THE are handled here */
2326 /* high priest(ess)'s identity is concealed on the Astral Plane,
2327 unless you're adjacent (overridden for hallucination which does
2328 its own obfuscation) */
2329 if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination
2330 && Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) {
2332 Strcpy(outbuf, article == ARTICLE_THE ? "the " : "");
2333 Strcat(outbuf, mon->female ? "high priestess" : "high priest");
2335 Strcpy(outbuf, "
\96@
\89¤");
2338 Strcpy(outbuf, x_monnam(mon, article, (char *) 0, 0, TRUE));
2343 /* fake monsters used to be in a hard-coded array, now in a data file */
2350 get_rnd_text(BOGUSMONFILE, buf);
2351 /* strip prefix if present */
2352 if (!letter(*mname)) {
2363 /* return a random monster name, for hallucination */
2368 static char buf[BUFSZ];
2371 #define BOGUSMONSIZE 100 /* arbitrary */
2377 name = rn1(SPECIAL_PM + BOGUSMONSIZE - LOW_PM, LOW_PM);
2378 } while (name < SPECIAL_PM
2379 && (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN)));
2381 if (name >= SPECIAL_PM) {
2382 mname = bogusmon(buf, code);
2384 mname = strcpy(buf, mons[name].mname);
2390 /* check bogusmon prefix to decide whether it's a personal name */
2392 bogon_is_pname(code)
2397 return index("-+=", code) ? TRUE : FALSE;
2400 /* name of a Rogue player */
2406 if ((opts = nh_getenv("ROGUEOPTS")) != 0) {
2407 for (i = opts; *i; i++)
2408 if (!strncmp("name=", i, 5)) {
2410 if ((j = index(i + 5, ',')) != 0)
2415 /*JP:Rogue
\82Ì
\8aJ
\94
\8eÒ
\82Ì
\96¼
\91O*/
2416 return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
2420 static NEARDATA const char *const hcolors[] = {
2422 "ultraviolet", "infrared", "bluish-orange", "reddish-green", "dark white",
2423 "light black", "sky blue-pink", "salty", "sweet", "sour", "bitter",
2424 "striped", "spiral", "swirly", "plaid", "checkered", "argyle", "paisley",
2425 "blotchy", "guernsey-spotted", "polka-dotted", "square", "round",
2426 "triangular", "cabernet", "sangria", "fuchsia", "wisteria", "lemon-lime",
2427 "strawberry-banana", "peppermint", "romantic", "incandescent",
2428 "octarine", /* Discworld: the Colour of Magic */
2430 "
\8e\87\8aO
\90F
\82Ì", "
\90Ô
\8aO
\90F
\82Ì", "
\90Â
\90F
\82ª
\82©
\82Á
\82½
\83I
\83\8c\83\93\83W
\90F
\82Ì", "
\90Ô
\82Ý
\82ª
\82©
\82Á
\82½
\97Î
\90F
\82Ì", "
\88Ã
\82¢
\94\92\90F
\82Ì",
2431 "
\96¾
\82é
\82¢
\8d\95\82Ì", "
\90\85\90F
\82ª
\82©
\82Á
\82½
\83s
\83\93\83N
\90F
\82Ì", "
\89\96\90h
\82¢", "
\8aÃ
\82¢", "
\82·
\82Á
\82Ï
\82¢", "
\8bê
\82¢",
2432 "
\82µ
\82Ü
\96Í
\97l
\82Ì", "
\82ç
\82¹
\82ñ
\8fó
\82Ì", "
\94g
\8fó
\82Ì", "
\8ai
\8eq
\96Í
\97l
\8fó
\82Ì", "
\83`
\83F
\83b
\83N
\8fó
\82Ì", "
\95ú
\8eË
\8fó
\82Ì", "
\83y
\81[
\83Y
\83\8a\81[
\96Í
\97l
\82Ì",
2433 "
\82µ
\82Ý
\8fó
\82Ì", "
\90Â
\90F
\82Ì
\94Á
\93_
\8fó
\82Ì", "
\93_
\8fó
\82Ì", "
\8el
\8ap
\8c`
\8fó
\82Ì", "
\8aÛ
\8fó
\82Ì",
2434 "
\8eO
\8ap
\8fó
\82Ì", "
\83J
\83x
\83\8b\83l
\90F
\82Ì", "
\83T
\83\93\83O
\83\8a\83A
\90F
\82Ì", "
\91N
\82â
\82©
\82È
\90Ô
\8e\87\90F
\82Ì", "
\93¡
\90F
\82Ì", "
\83\8c\83\82\83\93\83\89\83C
\83\80\90F
\82Ì",
2435 "ä
\95\83o
\83i
\83i
\90F
\82Ì", "
\83y
\83p
\81[
\83~
\83\93\83g
\90F
\82Ì", "
\83\8d\83}
\83\93\83`
\83b
\83N
\82È
\90F
\82Ì", "
\94\92\94M
\90F
\82Ì",
2436 "
\83I
\83N
\83^
\83\8a\83\93\90F
\82Ì",
2442 const char *colorpref;
2444 return (Hallucination || !colorpref) ? hcolors[rn2(SIZE(hcolors))]
2448 /* return a random real color unless hallucinating */
2452 int k = rn2(CLR_MAX);
2454 return Hallucination ? hcolor((char *) 0)
2456 : (k == NO_COLOR) ? "colorless"
2458 : (k == NO_COLOR) ? "
\96³
\90F
\82Ì"
2462 static NEARDATA const char *const hliquids[] = {
2464 "yoghurt", "oobleck", "clotted blood", "diluted water", "purified water",
2465 "instant coffee", "tea", "herbal infusion", "liquid rainbow",
2466 "creamy foam", "mulled wine", "bouillon", "nectar", "grog", "flubber",
2467 "ketchup", "slow light", "oil", "vinaigrette", "liquid crystal", "honey",
2468 "caramel sauce", "ink", "aqueous humour", "milk substitute", "fruit juice",
2469 "glowing lava", "gastric acid", "mineral water", "cough syrup", "quicksilver",
2470 "sweet vitriol", "grey goo", "pink slime",
2472 "
\83\88\81[
\83O
\83\8b\83g", "
\83E
\81[
\83u
\83\8c\83b
\83N", "
\8c\8c\8cÐ", "
\8fö
\97¯
\90\85", "
\90¸
\90»
\90\85",
2473 "
\83C
\83\93\83X
\83^
\83\93\83g
\83R
\81[
\83q
\81[", "
\8dg
\92\83", "
\83n
\81[
\83u
\89t", "
\89t
\91Ì
\82Ì
\93ø",
2474 "
\83N
\83\8a\81[
\83~
\81[
\83t
\83H
\81[
\83\80", "
\83z
\83b
\83g
\83\8f\83C
\83\93", "
\83u
\83C
\83\88\83\93", "
\89Ê
\8f`", "
\83O
\83\8d\83b
\83O", "
\83t
\83\89\83o
\81[",
2475 "
\83P
\83`
\83\83\83b
\83v", "
\92á
\91¬
\8cõ", "
\96û", "
\83r
\83l
\83O
\83\8c\83b
\83g
\83\
\81[
\83X", "
\89t
\91Ì
\90\85\8f»", "
\96I
\96¨",
2476 "
\83J
\83\89\83\81\83\8b\83\
\81[
\83X", "
\83C
\83\93\83N", "
\96[
\90\85", "
\91ã
\97p
\93û", "
\83t
\83\8b\81[
\83c
\83W
\83\85\81[
\83X",
2477 "
\97¬
\82ê
\82é
\97n
\8aâ", "
\88Ý
\8e_", "
\83~
\83l
\83\89\83\8b\83E
\83H
\81[
\83^
\81[", "
\8aP
\8e~
\82ß
\83V
\83\8d\83b
\83v", "
\90\85\8bâ",
2478 "
\83W
\83G
\83`
\83\8b\83G
\81[
\83e
\83\8b", "
\83O
\83\8c\83C
\83O
\81[", "
\83s
\83\93\83N
\83X
\83\89\83C
\83\80",
2484 const char *liquidpref;
2486 return (Hallucination || !liquidpref) ? hliquids[rn2(SIZE(hliquids))]
2490 /* Aliases for road-runner nemesis
2492 static const char *const coynames[] = {
2493 "Carnivorous Vulgaris", "Road-Runnerus Digestus", "Eatibus Anythingus",
2494 "Famishus-Famishus", "Eatibus Almost Anythingus", "Eatius Birdius",
2495 "Famishius Fantasticus", "Eternalii Famishiis", "Famishus Vulgarus",
2496 "Famishius Vulgaris Ingeniusi", "Eatius-Slobbius", "Hardheadipus Oedipus",
2497 "Carnivorous Slobbius", "Hard-Headipus Ravenus", "Evereadii Eatibus",
2498 "Apetitius Giganticus", "Hungrii Flea-Bagius", "Overconfidentii Vulgaris",
2499 "Caninus Nervous Rex", "Grotesques Appetitus", "Nemesis Ridiculii",
2504 coyotename(mtmp, buf)
2509 Sprintf(buf, "%s - %s",
2510 x_monnam(mtmp, ARTICLE_NONE, (char *) 0, 0, TRUE),
2511 mtmp->mcan ? coynames[SIZE(coynames) - 1]
2512 : coynames[mtmp->m_id % (SIZE(coynames) - 1)]);
2517 /* make sure "The Colour of Magic" remains the first entry in here */
2518 static const char *const sir_Terry_novels[] = {
2519 "The Colour of Magic", "The Light Fantastic", "Equal Rites", "Mort",
2520 "Sourcery", "Wyrd Sisters", "Pyramids", "Guards! Guards!", "Eric",
2521 "Moving Pictures", "Reaper Man", "Witches Abroad", "Small Gods",
2522 "Lords and Ladies", "Men at Arms", "Soul Music", "Interesting Times",
2523 "Maskerade", "Feet of Clay", "Hogfather", "Jingo", "The Last Continent",
2524 "Carpe Jugulum", "The Fifth Elephant", "The Truth", "Thief of Time",
2525 "The Last Hero", "The Amazing Maurice and His Educated Rodents",
2526 "Night Watch", "The Wee Free Men", "Monstrous Regiment",
2527 "A Hat Full of Sky", "Going Postal", "Thud!", "Wintersmith",
2528 "Making Money", "Unseen Academicals", "I Shall Wear Midnight", "Snuff",
2529 "Raising Steam", "The Shepherd's Crown"
2536 int j, k = SIZE(sir_Terry_novels);
2542 else if (*novidx >= 0 && *novidx < k)
2545 return sir_Terry_novels[j];
2549 lookup_novel(lookname, idx)
2550 const char *lookname;
2555 /* Take American or U.K. spelling of this one */
2556 if (!strcmpi(The(lookname), "The Color of Magic"))
2557 lookname = sir_Terry_novels[0];
2559 for (k = 0; k < SIZE(sir_Terry_novels); ++k) {
2560 if (!strcmpi(lookname, sir_Terry_novels[k])
2561 || !strcmpi(The(lookname), sir_Terry_novels[k])) {
2564 return sir_Terry_novels[k];
2567 /* name not found; if novelidx is already set, override the name */
2568 if (idx && *idx >= 0 && *idx < SIZE(sir_Terry_novels))
2569 return sir_Terry_novels[*idx];
2571 return (const char *) 0;