1 /* NetHack 3.6 do_name.c $NHDT-Date: 1555627306 2019/04/18 22:41:46 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.145 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Pasi Kallinen, 2018. */
4 /* NetHack may be freely redistributed. See license for details. */
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 static const char *const gloc_descr[NUM_GLOCS][4] = {
65 { "any monsters", "monster", "next/previous monster", "monsters" },
66 { "any items", "item", "next/previous object", "objects" },
67 { "any doors", "door", "next/previous door or doorway", "doors or doorways" },
68 { "any unexplored areas", "unexplored area", "unexplored location",
69 "unexplored locations" },
70 { "anything interesting", "interesting thing", "anything interesting",
71 "anything interesting" },
72 { "any valid locations", "valid location", "valid location",
75 { "
\89ö
\95¨", "
\89ö
\95¨", "
\89ö
\95¨
\82Ì
\97×", "
\89ö
\95¨" },
76 { "
\95¨", "
\95¨", "
\95¨
\82Ì
\97×", "
\95¨" },
77 { "
\94à", "
\94à", "
\94à
\82â
\8fo
\93ü
\82è
\8cû
\82Ì
\97×", "
\94à
\82â
\8fo
\93ü
\82è
\8cû" },
78 { "
\96¢
\92T
\8dõ
\95\94\95ª", "
\96¢
\92T
\8dõ
\95\94\95ª", "
\96¢
\92T
\8dõ
\82Ì
\88Ê
\92u", "
\96¢
\92T
\8dõ
\82Ì
\88Ê
\92u" },
79 { "
\8aÖ
\90S
\82Ì
\82 \82é
\82à
\82Ì", "
\8aÖ
\90S
\82Ì
\82 \82é
\82à
\82Ì", "
\8aÖ
\90S
\82Ì
\82 \82é
\82à
\82Ì", "
\8aÖ
\90S
\82Ì
\82 \82é
\82à
\82Ì" },
80 { "
\97L
\8cø
\82È
\88Ê
\92u", "
\97L
\8cø
\82È
\88Ê
\92u", "
\97L
\8cø
\82È
\88Ê
\92u", "
\97L
\8cø
\82È
\88Ê
\92u" },
84 static const char *const gloc_filtertxt[NUM_GFILTER] = {
91 "
\8e\8b\8aE
\82Ì
\92\86\82Ì",
92 "
\82±
\82Ì
\83G
\83\8a\83A
\82Ì"
97 getpos_help_keyxhelp(tmpwin, k1, k2, gloc)
106 Sprintf(sbuf, "Use '%s'/'%s' to %s%s%s.",
108 iflags.getloc_usemenu ? "get a menu of "
109 : "move the cursor to ",
110 gloc_descr[gloc][2 + iflags.getloc_usemenu],
111 gloc_filtertxt[iflags.getloc_filter]);
113 Sprintf(sbuf, "'%s'
\82©'%s'
\82Å%s%s%s
\81D",
115 gloc_filtertxt[iflags.getloc_filter],
116 gloc_descr[gloc][2 + iflags.getloc_usemenu],
117 iflags.getloc_usemenu ? "
\82Ì
\83\81\83j
\83\85\81[
\82ð
\8fo
\82·"
118 : "
\82É
\83J
\81[
\83\
\83\8b\82ð
\93®
\82©
\82·");
120 putstr(tmpwin, 0, sbuf);
123 /* the response for '?' help request in getpos() */
125 getpos_help(force, goal)
130 static const char *const fastmovemode[2] = { "8 units at a time",
131 "skipping same glyphs" };
133 static const char *const fastmovemode[2] = { "
\88ê
\93x
\82É8
\83}
\83X",
134 "
\93¯
\82¶
\92n
\8c`
\82ð
\94ò
\82Î
\82µ
\82Ä" };
137 boolean doing_what_is;
138 winid tmpwin = create_nhwindow(NHW_MENU);
142 "Use '%c', '%c', '%c', '%c' to move the cursor to %s.", /* hjkl */
143 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal);
146 "[%c%c%c%c]
\82Å%s
\82Ö
\88Ú
\93®
\82Å
\82«
\82é
\81D",
147 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E, goal);
149 putstr(tmpwin, 0, sbuf);
152 "Use 'H', 'J', 'K', 'L' to fast-move the cursor, %s.",
153 fastmovemode[iflags.getloc_moveskip]);
156 "'H', 'J', 'K', 'L'
\82Å%s
\88Ú
\93®
\82Å
\82«
\82é
\81D",
157 fastmovemode[iflags.getloc_moveskip]);
159 putstr(tmpwin, 0, sbuf);
161 putstr(tmpwin, 0, "Or enter a background symbol (ex. '<').");
163 putstr(tmpwin, 0, "
\94w
\8ci
\82Ì
\83V
\83\93\83{
\83\8b\82ð
\93ü
\97Í
\82·
\82é
\82Æ
\82»
\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é(
\97á
\81F'<')
\81D");
165 Sprintf(sbuf, "Use '%s' to move the cursor on yourself.",
166 visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
168 Sprintf(sbuf, "'%s'
\82Å
\8e©
\95ª
\8e©
\90g
\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é
\81D",
169 visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
171 putstr(tmpwin, 0, sbuf);
172 if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
173 getpos_help_keyxhelp(tmpwin,
174 visctrl(Cmd.spkeys[NHKF_GETPOS_MON_NEXT]),
175 visctrl(Cmd.spkeys[NHKF_GETPOS_MON_PREV]),
178 if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
179 getpos_help_keyxhelp(tmpwin,
180 visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]),
181 visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_PREV]),
184 if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) {
185 /* these are primarily useful when choosing a travel
186 destination for the '_' command */
187 getpos_help_keyxhelp(tmpwin,
188 visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_NEXT]),
189 visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_PREV]),
191 getpos_help_keyxhelp(tmpwin,
192 visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_NEXT]),
193 visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_PREV]),
195 getpos_help_keyxhelp(tmpwin,
196 visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_NEXT]),
197 visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_PREV]),
201 Sprintf(sbuf, "Use '%s' to change fast-move mode to %s.",
202 visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
203 fastmovemode[!iflags.getloc_moveskip]);
205 Sprintf(sbuf, "'%s'
\82Å
\8d\82\91¬
\88Ú
\93®
\83\82\81[
\83h
\82ð%s
\88Ú
\93®
\82É
\82·
\82é
\81D",
206 visctrl(Cmd.spkeys[NHKF_GETPOS_MOVESKIP]),
207 fastmovemode[!iflags.getloc_moveskip]);
209 putstr(tmpwin, 0, sbuf);
210 if (!iflags.terrainmode || (iflags.terrainmode & TER_DETECT) == 0) {
212 Sprintf(sbuf, "Use '%s' to toggle menu listing for possible targets.",
213 visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
215 Sprintf(sbuf, "'%s'
\82Å
\89Â
\94\
\82È
\83^
\81[
\83Q
\83b
\83g
\82Ì
\83\81\83j
\83\85\81[
\95\
\8e¦
\82ð
\90Ø
\82è
\91Ö
\82¦
\82é
\81D",
216 visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
218 putstr(tmpwin, 0, sbuf);
221 "Use '%s' to change the mode of limiting possible targets.",
222 visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
225 "'%s'
\82Å
\90§
\8cÀ
\82³
\82ê
\82½
\89Â
\94\
\82È
\83^
\81[
\83Q
\83b
\83g
\82Ì
\83\82\81[
\83h
\82ð
\90Ø
\82è
\91Ö
\82¦
\82é
\81D",
226 visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
228 putstr(tmpwin, 0, sbuf);
230 if (!iflags.terrainmode) {
233 if (getpos_getvalid) {
235 Sprintf(sbuf, "Use '%s' or '%s' to move to valid locations.",
236 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
237 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
239 Sprintf(sbuf, "'%s'
\82©'%s'
\82Å
\90³
\93\96\82È
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é
\81D",
240 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_NEXT]),
241 visctrl(Cmd.spkeys[NHKF_GETPOS_VALID_PREV]));
243 putstr(tmpwin, 0, sbuf);
245 if (getpos_hilitefunc) {
247 Sprintf(sbuf, "Use '%s' to display valid locations.",
248 visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
250 Sprintf(sbuf, "'%s'
\82Å
\89Â
\94\
\82È
\88Ê
\92u
\82ð
\95\
\8e¦
\82·
\82é
\81D",
251 visctrl(Cmd.spkeys[NHKF_GETPOS_SHOWVALID]));
253 putstr(tmpwin, 0, sbuf);
256 Sprintf(sbuf, "Use '%s' to toggle automatic description.",
257 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
259 Sprintf(sbuf, "'%s'
\82Å
\90à
\96¾
\82Ì
\8e©
\93®
\95\
\8e¦
\82ð
\90Ø
\82è
\91Ö
\82¦
\82é
\81D",
260 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
262 putstr(tmpwin, 0, sbuf);
263 if (iflags.cmdassist) { /* assisting the '/' command, I suppose... */
266 (iflags.getpos_coords == GPCOORDS_NONE)
267 ? "(Set 'whatis_coord' option to include coordinates with '%s' text.)"
268 : "(Reset 'whatis_coord' option to omit coordinates from '%s' text.)",
269 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
272 (iflags.getpos_coords == GPCOORDS_NONE)
273 ? "('%s'
\82É
\8dÀ
\95W
\82ð
\8aÜ
\82Þ
\82É
\82Í'whatis_coord'
\83I
\83v
\83V
\83\87\83\93\82ð
\83I
\83\93\82É
\82·
\82é
\81D)"
274 : "('%s'
\82©
\82ç
\8dÀ
\95W
\82ð
\8f\9c\82
\82É
\82Í'whatis_coord'
\83I
\83v
\83V
\83\87\83\93\82ð
\83I
\83t
\82É
\82·
\82é
\81D)",
275 visctrl(Cmd.spkeys[NHKF_GETPOS_AUTODESC]));
278 /* disgusting hack; the alternate selection characters work for any
279 getpos call, but only matter for dowhatis (and doquickwhatis) */
280 doing_what_is = (goal == what_is_an_unknown_object);
283 Sprintf(kbuf, "'%s' or '%s' or '%s' or '%s'",
284 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
285 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]),
286 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]),
287 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
289 Sprintf(kbuf, "'%s'
\82©'%s'
\82©'%s'
\82©'%s'",
290 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
291 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]),
292 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]),
293 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
296 Sprintf(kbuf, "'%s'", visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
299 Sprintf(sbuf, "Type a %s when you are at the right place.", kbuf);
301 Sprintf(sbuf, "[.]%s
\82Å
\8c\88\92è
\81D", kbuf);
303 putstr(tmpwin, 0, sbuf);
307 " '%s' describe current spot, show 'more info', move to another spot.",
308 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
311 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81A
\92Ç
\89Á
\8fî
\95ñ
\82ð
\95\
\8e¦
\82µ
\81A
\8e\9f\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é
\81D",
312 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_V]));
314 putstr(tmpwin, 0, sbuf);
317 " '%s' describe current spot,%s move to another spot;",
318 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
319 flags.help ? " prompt if 'more info'," : "");
322 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81C%s
\8e\9f\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é;",
323 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]),
324 flags.help ? "
\92Ç
\89Á
\8fî
\95ñ
\82ª
\82 \82ê
\82Î
\8am
\94F
\82µ
\81C" : "");
326 putstr(tmpwin, 0, sbuf);
329 " '%s' describe current spot, move to another spot;",
330 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]));
333 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81C
\8e\9f\82Ì
\88Ê
\92u
\82É
\88Ú
\93®
\82·
\82é;",
334 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_Q]));
336 putstr(tmpwin, 0, sbuf);
339 " '%s' describe current spot, stop looking at things;",
340 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]));
343 " '%s'
\82Í
\8c»
\8dÝ
\82Ì
\88Ê
\92u
\82ð
\90à
\96¾
\82µ
\81C
\8c©
\82é
\82Ì
\82ð
\82â
\82ß
\82é;",
344 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK_O]));
346 putstr(tmpwin, 0, sbuf);
351 putstr(tmpwin, 0, "Type Space or Escape when you're done.");
353 putstr(tmpwin, 0, "
\83X
\83y
\81[
\83X
\82Ü
\82½
\82Í
\83G
\83X
\83P
\81[
\83v
\82Å
\8fI
\97¹
\81D");
354 putstr(tmpwin, 0, "");
355 display_nhwindow(tmpwin, TRUE);
356 destroy_nhwindow(tmpwin);
360 cmp_coord_distu(a, b)
366 int dx, dy, dist_1, dist_2;
370 dist_1 = max(abs(dx), abs(dy));
373 dist_2 = max(abs(dx), abs(dy));
375 if (dist_1 == dist_2)
376 return (c1->y != c2->y) ? (c1->y - c2->y) : (c1->x - c2->x);
378 return dist_1 - dist_2;
381 #define IS_UNEXPLORED_LOC(x,y) \
383 && glyph_is_cmap(levl[(x)][(y)].glyph) \
384 && glyph_to_cmap(levl[(x)][(y)].glyph) == S_stone \
385 && !levl[(x)][(y)].seenv)
387 static struct opvar *gloc_filter_map = (struct opvar *) 0;
389 #define GLOC_SAME_AREA(x,y) \
391 && (selection_getpoint((x),(y), gloc_filter_map)))
393 static int gloc_filter_floodfill_match_glyph;
396 gloc_filter_classify_glyph(glyph)
401 if (!glyph_is_cmap(glyph))
404 c = glyph_to_cmap(glyph);
406 if (is_cmap_room(c) || is_cmap_furniture(c))
408 else if (is_cmap_wall(c) || c == S_tree)
410 else if (is_cmap_corr(c))
412 else if (is_cmap_water(c))
414 else if (is_cmap_lava(c))
420 gloc_filter_floodfill_matcharea(x, y)
423 int glyph = back_to_glyph(x, y);
425 if (!levl[x][y].seenv)
428 if (glyph == gloc_filter_floodfill_match_glyph)
431 if (gloc_filter_classify_glyph(glyph)
432 == gloc_filter_classify_glyph(gloc_filter_floodfill_match_glyph))
439 gloc_filter_floodfill(x, y)
442 gloc_filter_floodfill_match_glyph = back_to_glyph(x, y);
444 set_selection_floodfillchk(gloc_filter_floodfill_matcharea);
445 selection_floodfill(gloc_filter_map, x, y, FALSE);
451 if (iflags.getloc_filter == GFILTER_AREA) {
452 if (!gloc_filter_map) {
453 gloc_filter_map = selection_opvar((char *) 0);
455 /* special case: if we're in a doorway, try to figure out which
456 direction we're moving, and use that side of the doorway */
457 if (IS_DOOR(levl[u.ux][u.uy].typ)) {
459 gloc_filter_floodfill(u.ux + u.dx, u.uy + u.dy);
461 /* TODO: maybe add both sides of the doorway? */
464 gloc_filter_floodfill(u.ux, u.uy);
472 if (gloc_filter_map) {
473 opvar_free_x(gloc_filter_map);
474 gloc_filter_map = (struct opvar *) 0;
479 gather_locs_interesting(x, y, gloc)
482 /* TODO: if glyph is a pile glyph, convert to ordinary one
483 * in order to keep tail/boulder/rock check simple.
485 int glyph = glyph_at(x, y);
487 if (iflags.getloc_filter == GFILTER_VIEW && !cansee(x, y))
489 if (iflags.getloc_filter == GFILTER_AREA && !GLOC_SAME_AREA(x, y)
490 && !GLOC_SAME_AREA(x - 1, y) && !GLOC_SAME_AREA(x, y - 1)
491 && !GLOC_SAME_AREA(x + 1, y) && !GLOC_SAME_AREA(x, y + 1))
497 /* unlike '/M', this skips monsters revealed by
498 warning glyphs and remembered unseen ones */
499 return (glyph_is_monster(glyph)
500 && glyph != monnum_to_glyph(PM_LONG_WORM_TAIL));
502 return (glyph_is_object(glyph)
503 && glyph != objnum_to_glyph(BOULDER)
504 && glyph != objnum_to_glyph(ROCK));
506 return (glyph_is_cmap(glyph)
507 && (is_cmap_door(glyph_to_cmap(glyph))
508 || is_cmap_drawbridge(glyph_to_cmap(glyph))
509 || glyph_to_cmap(glyph) == S_ndoor));
511 return (glyph_is_cmap(glyph)
512 && (is_cmap_door(glyph_to_cmap(glyph))
513 || is_cmap_drawbridge(glyph_to_cmap(glyph))
514 || glyph_to_cmap(glyph) == S_ndoor
515 || glyph_to_cmap(glyph) == S_room
516 || glyph_to_cmap(glyph) == S_darkroom
517 || glyph_to_cmap(glyph) == S_corr
518 || glyph_to_cmap(glyph) == S_litcorr)
519 && (IS_UNEXPLORED_LOC(x + 1, y)
520 || IS_UNEXPLORED_LOC(x - 1, y)
521 || IS_UNEXPLORED_LOC(x, y + 1)
522 || IS_UNEXPLORED_LOC(x, y - 1)));
525 return (*getpos_getvalid)(x,y);
527 case GLOC_INTERESTING:
528 return gather_locs_interesting(x,y, GLOC_DOOR)
529 || !(glyph_is_cmap(glyph)
530 && (is_cmap_wall(glyph_to_cmap(glyph))
531 || glyph_to_cmap(glyph) == S_tree
532 || glyph_to_cmap(glyph) == S_bars
533 || glyph_to_cmap(glyph) == S_ice
534 || glyph_to_cmap(glyph) == S_air
535 || glyph_to_cmap(glyph) == S_cloud
536 || glyph_to_cmap(glyph) == S_lava
537 || glyph_to_cmap(glyph) == S_water
538 || glyph_to_cmap(glyph) == S_pool
539 || glyph_to_cmap(glyph) == S_ndoor
540 || glyph_to_cmap(glyph) == S_room
541 || glyph_to_cmap(glyph) == S_darkroom
542 || glyph_to_cmap(glyph) == S_corr
543 || glyph_to_cmap(glyph) == S_litcorr));
549 /* gather locations for monsters or objects shown on the map */
551 gather_locs(arr_p, cnt_p, gloc)
559 * We always include the hero's location even if there is no monster
560 * (invisible hero without see invisible) or object (usual case)
561 * displayed there. That way, the count will always be at least 1,
562 * and player has a visual indicator (cursor returns to hero's spot)
563 * highlighting when successive 'm's or 'o's have cycled all the way
564 * through all monsters or objects.
566 * Hero's spot will always sort to array[0] because it will always
567 * be the shortest distance (namely, 0 units) away from <u.ux,u.uy>.
573 for (pass = 0; pass < 2; pass++) {
574 for (x = 1; x < COLNO; x++)
575 for (y = 0; y < ROWNO; y++) {
576 if ((x == u.ux && y == u.uy)
577 || gather_locs_interesting(x, y, gloc)) {
588 if (!pass) /* end of first pass */
589 *arr_p = (coord *) alloc(*cnt_p * sizeof (coord));
590 else /* end of second pass */
591 qsort(*arr_p, *cnt_p, sizeof (coord), cmp_coord_distu);
598 dxdy_to_dist_descr(dx, dy, fulldir)
607 Sprintf(buf, "here");
609 Sprintf(buf, "
\82±
\82±");
610 } else if ((dst = xytod(dx, dy)) != -1) {
611 /* explicit direction; 'one step' is implicit */
612 Sprintf(buf, "%s", directionname(dst));
614 static const char *dirnames[4][2] = {
627 /* 9999: protect buf[] against overflow caused by invalid values */
631 Sprintf(eos(buf), "%d%s%s", abs(dy), dirnames[(dy > 0)][fulldir],
637 Sprintf(eos(buf), "%d%s", abs(dx),
638 dirnames[2 + (dx > 0)][fulldir]);
644 /* coordinate formatting for 'whatis_coord' option */
646 coord_desc(x, y, outbuf, cmode)
650 static char screen_fmt[16]; /* [12] suffices: "[%02d,%02d]" */
657 case GPCOORDS_COMFULL:
658 case GPCOORDS_COMPASS:
659 /* "east", "3s", "2n,4w" */
662 Sprintf(outbuf, "(%s)",
663 dxdy_to_dist_descr(dx, dy, cmode == GPCOORDS_COMFULL));
665 case GPCOORDS_MAP: /* x,y */
666 /* upper left corner of map is <1,0>;
667 with default COLNO,ROWNO lower right corner is <79,20> */
668 Sprintf(outbuf, "<%d,%d>", x, y);
670 case GPCOORDS_SCREEN: /* y+2,x */
671 /* for normal map sizes, force a fixed-width formatting so that
672 /m, /M, /o, and /O output lines up cleanly; map sizes bigger
673 than Nx999 or 999xM will still work, but not line up like normal
674 when displayed in a column setting */
676 Sprintf(screen_fmt, "[%%%sd,%%%sd]",
677 (ROWNO - 1 + 2 < 100) ? "02" : "03",
678 (COLNO - 1 < 100) ? "02" : "03");
679 /* map line 0 is screen row 2;
680 map column 0 isn't used, map column 1 is screen column 1 */
681 Sprintf(outbuf, screen_fmt, y + 2, x);
688 auto_describe(cx, cy)
695 const char *firstmatch = "unknown";
697 const char *firstmatch = "
\95s
\96¾";
701 if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch,
702 (struct permonst **) 0)) {
703 (void) coord_desc(cx, cy, tmpbuf, iflags.getpos_coords);
705 custompline(SUPPRESS_HISTORY,
706 "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
708 && getpos_getvalid && !(*getpos_getvalid)(cx, cy))
710 (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
711 ? " (no travel path)" : "");
713 custompline(SUPPRESS_HISTORY,
714 "%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
716 && getpos_getvalid && !getpos_getvalid(cx, cy))
717 ? " (
\95s
\90³)" : "",
718 (iflags.getloc_travelmode && !is_valid_travelpt(cx, cy))
719 ? " (
\8co
\98H
\82È
\82µ)" : "");
721 curs(WIN_MAP, cx, cy);
727 getpos_menu(ccp, gloc)
736 menu_item *picks = (menu_item *) 0;
739 gather_locs(&garr, &gcount, gloc);
741 if (gcount < 2) { /* gcount always includes the hero */
742 free((genericptr_t) garr);
745 iflags.getloc_filter == GFILTER_VIEW ? "see" : "detect",
746 gloc_descr[gloc][0]);
748 You("%s
\82ð%s
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D",
750 iflags.getloc_filter == GFILTER_VIEW ? "
\8c©
\82é" : "
\8c©
\82Â
\82¯
\82é");
755 tmpwin = create_nhwindow(NHW_MENU);
759 /* gather_locs returns array[0] == you. skip it. */
760 for (i = 1; i < gcount; i++) {
764 const char *firstmatch = "unknown";
766 const char *firstmatch = "
\95s
\96¾";
772 if (do_screen_description(tmpcc, TRUE, sym, tmpbuf,
773 &firstmatch, (struct permonst **)0)) {
774 (void) coord_desc(garr[i].x, garr[i].y, tmpbuf,
775 iflags.getpos_coords);
776 Sprintf(fullbuf, "%s%s%s", firstmatch,
777 (*tmpbuf ? " " : ""), tmpbuf);
778 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, fullbuf,
784 Sprintf(tmpbuf, "Pick %s%s%s",
785 an(gloc_descr[gloc][1]),
786 gloc_filtertxt[iflags.getloc_filter],
787 iflags.getloc_travelmode ? " for travel destination" : "");
789 Sprintf(tmpbuf, "%s%s
\82Å
\96Ú
\95W
\82Æ
\82·
\82é%s
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢",
790 iflags.getloc_travelmode ? "
\88Ú
\93®
\82Ì
\82½
\82ß
\82É" : "",
791 gloc_filtertxt[iflags.getloc_filter],
792 gloc_descr[gloc][1]);
794 end_menu(tmpwin, tmpbuf);
795 pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
796 destroy_nhwindow(tmpwin);
798 ccp->x = garr[picks->item.a_int - 1].x;
799 ccp->y = garr[picks->item.a_int - 1].y;
800 free((genericptr_t) picks);
802 free((genericptr_t) garr);
803 return (pick_cnt > 0);
807 getpos(ccp, force, goal)
815 } const pick_chars_def[] = {
816 { NHKF_GETPOS_PICK, LOOK_TRADITIONAL },
817 { NHKF_GETPOS_PICK_Q, LOOK_QUICK },
818 { NHKF_GETPOS_PICK_O, LOOK_ONCE },
819 { NHKF_GETPOS_PICK_V, LOOK_VERBOSE }
821 static const int mMoOdDxX_def[] = {
822 NHKF_GETPOS_MON_NEXT,
823 NHKF_GETPOS_MON_PREV,
824 NHKF_GETPOS_OBJ_NEXT,
825 NHKF_GETPOS_OBJ_PREV,
826 NHKF_GETPOS_DOOR_NEXT,
827 NHKF_GETPOS_DOOR_PREV,
828 NHKF_GETPOS_UNEX_NEXT,
829 NHKF_GETPOS_UNEX_PREV,
830 NHKF_GETPOS_INTERESTING_NEXT,
831 NHKF_GETPOS_INTERESTING_PREV,
832 NHKF_GETPOS_VALID_NEXT,
833 NHKF_GETPOS_VALID_PREV
840 boolean msg_given = TRUE; /* clear message window by default */
841 boolean show_goal_msg = FALSE;
842 boolean hilite_state = FALSE;
843 coord *garr[NUM_GLOCS] = DUMMY;
844 int gcount[NUM_GLOCS] = DUMMY;
845 int gidx[NUM_GLOCS] = DUMMY;
847 for (i = 0; i < SIZE(pick_chars_def); i++)
848 pick_chars[i] = Cmd.spkeys[pick_chars_def[i].nhkf];
849 pick_chars[SIZE(pick_chars_def)] = '\0';
851 for (i = 0; i < SIZE(mMoOdDxX_def); i++)
852 mMoOdDxX[i] = Cmd.spkeys[mMoOdDxX_def[i]];
853 mMoOdDxX[SIZE(mMoOdDxX_def)] = '\0';
857 goal = "desired location";
859 goal = "
\96Ú
\93I
\92n";
862 pline("(For instructions type a '%s')",
863 visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
865 pline("('%s'
\82Å
\83w
\83\8b\83v)",
866 visctrl(Cmd.spkeys[NHKF_GETPOS_HELP]));
875 curs(WIN_MAP, cx, cy);
878 lock_mouse_cursor(TRUE);
883 pline("Move cursor to %s:", goal);
885 pline("
\83J
\81[
\83\
\83\8b\82ð%s
\82É
\93®
\82©
\82µ
\82Ä
\82
\82¾
\82³
\82¢:", goal);
886 curs(WIN_MAP, cx, cy);
888 show_goal_msg = FALSE;
889 } else if (iflags.autodescribe && !msg_given && !hilite_state) {
890 auto_describe(cx, cy);
893 c = nh_poskey(&tx, &ty, &sidx);
896 (*getpos_hilitefunc)(2);
897 hilite_state = FALSE;
898 curs(WIN_MAP, cx, cy);
902 if (iflags.autodescribe)
905 if (c == Cmd.spkeys[NHKF_ESC]) {
907 msg_given = TRUE; /* force clear */
914 /* a mouse click event, just assign and return */
919 if ((cp = index(pick_chars, c)) != 0) {
920 /* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */
921 result = pick_chars_def[(int) (cp - pick_chars)].ret;
924 for (i = 0; i < 8; i++) {
927 if (Cmd.dirchars[i] == c) {
928 /* a normal movement letter or digit */
931 } else if (Cmd.alphadirchars[i] == lowc((char) c)
932 || (Cmd.num_pad && Cmd.dirchars[i] == (c & 0177))) {
933 /* a shifted movement letter or Meta-digit */
934 if (iflags.getloc_moveskip) {
935 /* skip same glyphs */
936 int glyph = glyph_at(cx, cy);
940 while (isok(cx + dx, cy + dy)
941 && glyph == glyph_at(cx + dx, cy + dy)
942 && isok(cx + dx + xdir[i], cy + dy + ydir[i])
943 && glyph == glyph_at(cx + dx + xdir[i],
944 cy + dy + ydir[i])) {
955 /* truncate at map edge; diagonal moves complicate this... */
957 dy -= sgn(dy) * (1 - (cx + dx));
958 dx = 1 - cx; /* so that (cx+dx == 1) */
959 } else if (cx + dx > COLNO - 1) {
960 dy += sgn(dy) * ((COLNO - 1) - (cx + dx));
961 dx = (COLNO - 1) - cx;
964 dx -= sgn(dx) * (0 - (cy + dy));
965 dy = 0 - cy; /* so that (cy+dy == 0) */
966 } else if (cy + dy > ROWNO - 1) {
967 dx += sgn(dx) * ((ROWNO - 1) - (cy + dy));
968 dy = (ROWNO - 1) - cy;
975 if (c == Cmd.spkeys[NHKF_GETPOS_HELP] || redraw_cmd(c)) {
976 if (c == Cmd.spkeys[NHKF_GETPOS_HELP])
977 getpos_help(force, goal);
979 docrt(); /* redraw */
980 /* update message window to reflect that we're still targetting */
981 show_goal_msg = TRUE;
983 } else if (c == Cmd.spkeys[NHKF_GETPOS_SHOWVALID]
984 && getpos_hilitefunc) {
986 (*getpos_hilitefunc)(0);
987 (*getpos_hilitefunc)(1);
991 } else if (c == Cmd.spkeys[NHKF_GETPOS_AUTODESC]) {
992 iflags.autodescribe = !iflags.autodescribe;
994 pline("Automatic description %sis %s.",
995 flags.verbose ? "of features under cursor " : "",
996 iflags.autodescribe ? "on" : "off");
998 pline("%s
\90à
\96¾
\8e©
\93®
\95\
\8e¦
\81F%s",
999 flags.verbose ? "
\83J
\81[
\83\
\83\8b\82Ì
\89º
\82É
\82 \82é
\82à
\82Ì
\82Ì" : "",
1000 iflags.autodescribe ? "
\83I
\83\93" : "
\83I
\83t");
1002 if (!iflags.autodescribe)
1003 show_goal_msg = TRUE;
1006 } else if (c == Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]) {
1007 static const char *const view_filters[NUM_GFILTER] = {
1009 "Not limiting targets",
1010 "Limiting targets to those in sight",
1011 "Limiting targets to those in same area"
1013 "
\83^
\81[
\83Q
\83b
\83g
\82ð
\90§
\8cÀ
\82µ
\82È
\82¢",
1014 "
\8e\8b\8aE
\93à
\82É
\83^
\81[
\83Q
\83b
\83g
\82ð
\90§
\8cÀ
\82·
\82é",
1015 "
\93¯
\82¶
\83G
\83\8a\83A
\82É
\83^
\81[
\83Q
\83b
\83g
\82ð
\90§
\8cÀ
\82·
\82é"
1019 iflags.getloc_filter = (iflags.getloc_filter + 1) % NUM_GFILTER;
1020 for (i = 0; i < NUM_GLOCS; i++) {
1022 free((genericptr_t) garr[i]);
1025 gidx[i] = gcount[i] = 0;
1028 pline("%s.", view_filters[iflags.getloc_filter]);
1030 pline("%s
\81D", view_filters[iflags.getloc_filter]);
1033 } else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]) {
1034 iflags.getloc_usemenu = !iflags.getloc_usemenu;
1036 pline("%s a menu to show possible targets%s.",
1037 iflags.getloc_usemenu ? "Using" : "Not using",
1038 iflags.getloc_usemenu
1039 ? " for 'm|M', 'o|O', 'd|D', and 'x|X'" : "");
1041 pline("
\89Â
\94\
\82È
\83^
\81[
\83Q
\83b
\83g
\82ð
\8c©
\82é
\82Ì
\82É
\83\81\83j
\83\85\81[
\82ð
\8eg%s
\81D%s",
1042 iflags.getloc_usemenu ? "
\82¤" : "
\82í
\82È
\82¢",
1043 iflags.getloc_usemenu
1044 ? "('m|M', 'o|O', 'd|D', 'x|X'
\97p)" : "");
1048 } else if (c == Cmd.spkeys[NHKF_GETPOS_SELF]) {
1049 /* reset 'm&M', 'o&O', &c; otherwise, there's no way for player
1050 to achieve that except by manually cycling through all spots */
1051 for (i = 0; i < NUM_GLOCS; i++)
1056 } else if (c == Cmd.spkeys[NHKF_GETPOS_MOVESKIP]) {
1057 iflags.getloc_moveskip = !iflags.getloc_moveskip;
1059 pline("%skipping over similar terrain when fastmoving the cursor.",
1060 iflags.getloc_moveskip ? "S" : "Not s");
1062 pline("
\83J
\81[
\83\
\83\8b\82ð
\8d\82\91¬
\88Ú
\93®
\82³
\82¹
\82é
\82Æ
\82«
\82É
\8e\97\82½
\82æ
\82¤
\82È
\92n
\8c`
\82ð
\94ò
\82Î%s
\81D",
1063 iflags.getloc_moveskip ? "
\82·" : "
\82³
\82È
\82¢");
1065 } else if ((cp = index(mMoOdDxX, c)) != 0) { /* 'm|M', 'o|O', &c */
1066 /* nearest or farthest monster or object or door or unexplored */
1067 int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
1068 gloc = gtmp >> 1; /* 0..3 */
1070 if (iflags.getloc_usemenu) {
1073 if (getpos_menu(&tmpcrd, gloc)) {
1081 gather_locs(&garr[gloc], &gcount[gloc], gloc);
1082 gidx[gloc] = 0; /* garr[][0] is hero's spot */
1084 if (!(gtmp & 1)) { /* c=='m' || c=='o' || c=='d' || c=='x') */
1085 gidx[gloc] = (gidx[gloc] + 1) % gcount[gloc];
1086 } else { /* c=='M' || c=='O' || c=='D' || c=='X') */
1087 if (--gidx[gloc] < 0)
1088 gidx[gloc] = gcount[gloc] - 1;
1090 cx = garr[gloc][gidx[gloc]].x;
1091 cy = garr[gloc][gidx[gloc]].y;
1094 if (!index(quitchars, c)) {
1095 char matching[MAXPCHARS];
1096 int pass, lo_x, lo_y, hi_x, hi_y, k = 0;
1098 (void) memset((genericptr_t) matching, 0, sizeof matching);
1099 for (sidx = 1; sidx < MAXPCHARS; sidx++) { /* [0] left as 0 */
1100 if (IS_DOOR(sidx) || IS_WALL(sidx)
1101 || sidx == SDOOR || sidx == SCORR
1102 || glyph_to_cmap(k) == S_room
1103 || glyph_to_cmap(k) == S_darkroom
1104 || glyph_to_cmap(k) == S_corr
1105 || glyph_to_cmap(k) == S_litcorr)
1107 if (c == defsyms[sidx].sym || c == (int) showsyms[sidx])
1108 matching[sidx] = (char) ++k;
1111 for (pass = 0; pass <= 1; pass++) {
1112 /* pass 0: just past current pos to lower right;
1113 pass 1: upper left corner to current pos */
1114 lo_y = (pass == 0) ? cy : 0;
1115 hi_y = (pass == 0) ? ROWNO - 1 : cy;
1116 for (ty = lo_y; ty <= hi_y; ty++) {
1117 lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
1118 hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
1119 for (tx = lo_x; tx <= hi_x; tx++) {
1120 /* first, look at what is currently visible
1121 (might be monster) */
1122 k = glyph_at(tx, ty);
1123 if (glyph_is_cmap(k)
1124 && matching[glyph_to_cmap(k)])
1126 /* next, try glyph that's remembered here
1127 (might be trap or object) */
1128 if (level.flags.hero_memory
1129 /* !terrainmode: don't move to remembered
1130 trap or object if not currently shown */
1131 && !iflags.terrainmode) {
1132 k = levl[tx][ty].glyph;
1133 if (glyph_is_cmap(k)
1134 && matching[glyph_to_cmap(k)])
1137 /* last, try actual terrain here (shouldn't
1138 we be using lastseentyp[][] instead?) */
1139 if (levl[tx][ty].seenv) {
1140 k = back_to_glyph(tx, ty);
1141 if (glyph_is_cmap(k)
1142 && matching[glyph_to_cmap(k)])
1149 clear_nhwindow(WIN_MESSAGE);
1157 pline("Can't find dungeon feature '%c'.", c);
1159 pline("'%c'
\81H", c);
1167 Strcpy(note, "aborted");
1169 Strcpy(note, "
\92\86\92f
\82µ
\82½");
1172 Sprintf(note, "use '%c', '%c', '%c', '%c' or '%s'",
1173 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
1174 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
1176 Sprintf(note, "%c%c%c%c
\82Å
\88Ú
\93®
\81C%s
\82Å
\8fI
\97¹",
1177 Cmd.move_W, Cmd.move_S, Cmd.move_N, Cmd.move_E,
1178 visctrl(Cmd.spkeys[NHKF_GETPOS_PICK]));
1181 pline("Unknown direction: '%s' (%s).", visctrl((char) c),
1183 pline("
\82»
\82Ì
\95û
\8cü
\82Í
\82È
\82¢
\81F'%s' (%s)", visctrl((char) c),
1186 } /* k => matching */
1193 pline("
\88È
\8fã
\81D");
1194 msg_given = FALSE; /* suppress clear */
1197 result = 0; /* not -1 */
1205 curs(WIN_MAP, cx, cy);
1209 lock_mouse_cursor(FALSE);
1212 clear_nhwindow(WIN_MESSAGE);
1215 for (i = 0; i < NUM_GLOCS; i++)
1217 free((genericptr_t) garr[i]);
1218 getpos_hilitefunc = (void FDECL((*), (int))) 0;
1219 getpos_getvalid = (boolean FDECL((*), (int, int))) 0;
1223 /* allocate space for a monster's name; removes old name if there is one */
1227 int lth; /* desired length (caller handles adding 1 for terminator) */
1230 /* allocate mextra if necessary; otherwise get rid of old name */
1232 mon->mextra = newmextra();
1234 free_mname(mon); /* already has mextra, might also have name */
1235 MNAME(mon) = (char *) alloc((unsigned) lth);
1237 /* zero length: the new name is empty; get rid of the old name */
1243 /* release a monster's name; retains mextra even if all fields are now null */
1248 if (has_mname(mon)) {
1249 free((genericptr_t) MNAME(mon));
1250 MNAME(mon) = (char *) 0;
1254 /* allocate space for an object's name; removes old name if there is one */
1258 int lth; /* desired length (caller handles adding 1 for terminator) */
1261 /* allocate oextra if necessary; otherwise get rid of old name */
1263 obj->oextra = newoextra();
1265 free_oname(obj); /* already has oextra, might also have name */
1266 ONAME(obj) = (char *) alloc((unsigned) lth);
1268 /* zero length: the new name is empty; get rid of the old name */
1274 /* release an object's name; retains oextra even if all fields are now null */
1279 if (has_oname(obj)) {
1280 free((genericptr_t) ONAME(obj));
1281 ONAME(obj) = (char *) 0;
1285 /* safe_oname() always returns a valid pointer to
1286 * a string, either the pointer to an object's name
1287 * if it has one, or a pointer to an empty string
1299 /* historical note: this returns a monster pointer because it used to
1300 allocate a new bigger block of memory to hold the monster and its name */
1302 christen_monst(mtmp, name)
1309 /* dogname & catname are PL_PSIZ arrays; object names have same limit */
1310 lth = (name && *name) ? ((int) strlen(name) + 1) : 0;
1311 if (lth > PL_PSIZ) {
1313 if (is_kanji2(buf, lth - 1))
1317 name = strncpy(buf, name, PL_PSIZ - 1);
1318 buf[PL_PSIZ - 1] = '\0';
1320 new_mname(mtmp, lth); /* removes old name if one is present */
1322 Strcpy(MNAME(mtmp), name);
1326 /* check whether user-supplied name matches or nearly matches an unnameable
1327 monster's name; if so, give an alternate reject message for do_mname() */
1329 alreadynamed(mtmp, monnambuf, usrbuf)
1331 char *monnambuf, *usrbuf;
1333 char pronounbuf[10], *p;
1335 if (fuzzymatch(usrbuf, monnambuf, " -_", TRUE)
1336 /* catch trying to name "the Oracle" as "Oracle" */
1337 || (!strncmpi(monnambuf, "the ", 4)
1338 && fuzzymatch(usrbuf, monnambuf + 4, " -_", TRUE))
1339 /* catch trying to name "invisible Orcus" as "Orcus" */
1340 || ((p = strstri(monnambuf, "invisible ")) != 0
1341 && fuzzymatch(usrbuf, p + 10, " -_", TRUE))
1342 /* catch trying to name "the {priest,Angel} of Crom" as "Crom" */
1343 || ((p = strstri(monnambuf, " of ")) != 0
1344 && fuzzymatch(usrbuf, p + 4, " -_", TRUE))) {
1346 pline("%s is already called %s.",
1347 upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
1349 pline("%s
\82Í
\8aù
\82É%s
\82Æ
\8cÄ
\82Î
\82ê
\82Ä
\82¢
\82é
\81D",
1350 upstart(strcpy(pronounbuf, mhe(mtmp))), monnambuf);
1353 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8eg
\82í
\82È
\82¢*/
1354 } else if (mtmp->data == &mons[PM_JUIBLEX]
1355 && strstri(monnambuf, "Juiblex")
1356 && !strcmpi(usrbuf, "Jubilex")) {
1357 pline("%s doesn't like being called %s.", upstart(monnambuf), usrbuf);
1364 /* allow player to assign a name to some chosen monster */
1368 char buf[BUFSZ] = DUMMY, monnambuf[BUFSZ], qbuf[QBUFSZ];
1371 struct monst *mtmp = 0;
1373 if (Hallucination) {
1375 You("would never recognize it anyway.");
1377 You("
\82»
\82ê
\82ð
\94F
\8e¯
\82Å
\82«
\82È
\82¢
\81D");
1383 if (getpos(&cc, FALSE, "the monster you want to name") < 0
1385 if (getpos(&cc, FALSE, "
\82 \82È
\82½
\82ª
\96¼
\82Ã
\82¯
\82½
\82¢
\89ö
\95¨") < 0
1390 if (cx == u.ux && cy == u.uy) {
1391 if (u.usteed && canspotmon(u.usteed)) {
1395 pline("This %s creature is called %s and cannot be renamed.",
1397 pline("
\82±
\82Ì%s
\90¶
\82«
\95¨
\82Í%s
\82Æ
\8cÄ
\82Î
\82ê
\82Ä
\82¢
\82Ä
\81C
\96¼
\91O
\82Í
\95Ï
\8dX
\82Å
\82«
\82È
\82¢
\81D",
1398 beautiful(), plname);
1402 mtmp = m_at(cx, cy);
1406 && (!(cansee(cx, cy) || see_with_infrared(mtmp))
1407 || mtmp->mundetected || M_AP_TYPE(mtmp) == M_AP_FURNITURE
1408 || M_AP_TYPE(mtmp) == M_AP_OBJECT
1409 || (mtmp->minvis && !See_invisible)))) {
1411 pline("I see no monster there.");
1413 pline("
\82»
\82±
\82É
\89ö
\95¨
\82Í
\82¢
\82È
\82¢
\81D");
1416 /* special case similar to the one in lookat() */
1418 Sprintf(qbuf, "What do you want to call %s?",
1420 Sprintf(qbuf, "%s
\82ð
\89½
\82Æ
\8cÄ
\82Ñ
\82Ü
\82·
\82©
\81H",
1421 distant_monnam(mtmp, ARTICLE_THE, monnambuf));
1423 if (!*buf || *buf == '\033')
1425 /* strip leading and trailing spaces; unnames monster if all spaces */
1426 (void) mungspaces(buf);
1428 /* Unique monsters have their own specific names or titles.
1429 * Shopkeepers, temple priests and other minions use alternate
1430 * name formatting routines which ignore any user-supplied name.
1432 * Don't say the name is being rejected if it happens to match
1433 * the existing name.
1435 if ((mtmp->data->geno & G_UNIQ) && !mtmp->ispriest) {
1436 if (!alreadynamed(mtmp, monnambuf, buf))
1438 pline("%s doesn't like being called names!", upstart(monnambuf));
1440 pline("%s
\82Í
\82 \82¾
\96¼
\82Å
\8cÄ
\82Î
\82ê
\82é
\82Ì
\82ª
\8c\99\82¢
\82È
\82æ
\82¤
\82¾
\81I", Monnam(mtmp));
1441 } else if (mtmp->isshk
1442 && !(Deaf || mtmp->msleeping || !mtmp->mcanmove
1443 || mtmp->data->msound <= MS_ANIMAL)) {
1444 if (!alreadynamed(mtmp, monnambuf, buf))
1446 verbalize("I'm %s, not %s.", shkname(mtmp), buf);
1448 verbalize("
\8e\84\82Í%s
\82¾
\81C%s
\82Å
\82Í
\82È
\82¢
\81D", shkname(mtmp), buf);
1449 } else if (mtmp->ispriest || mtmp->isminion || mtmp->isshk) {
1450 if (!alreadynamed(mtmp, monnambuf, buf))
1452 pline("%s will not accept the name %s.", upstart(monnambuf), buf);
1454 pline("%s
\82Í%s
\82Æ
\82¢
\82¤
\96¼
\91O
\82ð
\8eó
\82¯
\82¢
\82ê
\82È
\82©
\82Á
\82½
\81D", monnambuf, buf);
1456 (void) christen_monst(mtmp, buf);
1459 STATIC_VAR int via_naming = 0;
1462 * This routine used to change the address of 'obj' so be unsafe if not
1463 * used with extreme care. Applying a name to an object no longer
1464 * allocates a replacement object, so that old risk is gone.
1469 register struct obj *obj;
1471 char *bufp, buf[BUFSZ] = DUMMY, bufcpy[BUFSZ], qbuf[QBUFSZ];
1475 /* Do this now because there's no point in even asking for a name */
1476 if (obj->otyp == SPE_NOVEL) {
1478 pline("%s already has a published name.", Ysimple_name2(obj));
1480 pline("%s
\82É
\82Í
\82·
\82Å
\82É
\8fo
\94Å
\8e\9e\82Ì
\96¼
\91O
\82ª
\82 \82é
\81D", Ysimple_name2(obj));
1485 Sprintf(qbuf, "What do you want to name %s ",
1486 is_plural(obj) ? "these" : "this");
1487 (void) safe_qbuf(qbuf, qbuf, "?", obj, xname, simpleonames, "item");
1489 (void) safe_qbuf(qbuf, "", "
\82ð
\89½
\82Æ
\96¼
\82Ã
\82¯
\82Ü
\82·
\82©
\81H", obj, xname,
1490 simpleonames, "
\82»
\82ê");
1493 if (!*buf || *buf == '\033')
1495 /* strip leading and trailing spaces; unnames item if all spaces */
1496 (void) mungspaces(buf);
1499 * We don't violate illiteracy conduct here, although it is
1500 * arguable that we should for anything other than "X". Doing so
1501 * would make attaching player's notes to hero's inventory have an
1502 * in-game effect, which may or may not be the correct thing to do.
1504 * We do violate illiteracy in oname() if player creates Sting or
1505 * Orcrist, clearly being literate (no pun intended...).
1508 /* relax restrictions over proper capitalization for artifacts */
1509 if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp)
1512 if (obj->oartifact) {
1514 pline_The("artifact seems to resist the attempt.");
1516 pline("
\90¹
\8aí
\82Í
\96¼
\82Ã
\82¯
\82ð
\8b\91\94Û
\82µ
\82Ä
\82¢
\82é
\82æ
\82¤
\82¾
\81D");
1518 } else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) {
1519 /* this used to change one letter, substituting a value
1520 of 'a' through 'y' (due to an off by one error, 'z'
1521 would never be selected) and then force that to
1522 upper case if such was the case of the input;
1523 now, the hand slip scuffs one or two letters as if
1524 the text had been trodden upon, sometimes picking
1525 punctuation instead of an arbitrary letter;
1526 unfortunately, we have to cover the possibility of
1527 it targetting spaces so failing to make any change
1528 (we know that it must eventually target a nonspace
1529 because buf[] matches a valid artifact name) */
1530 Strcpy(bufcpy, buf);
1531 /* for "the Foo of Bar", only scuff "Foo of Bar" part */
1532 bufp = !strncmpi(bufcpy, "the ", 4) ? (buf + 4) : buf;
1534 wipeout_text(bufp, rn2_on_display_rng(2), (unsigned) 0);
1535 } while (!strcmp(buf, bufcpy));
1537 pline("While engraving, your %s slips.", body_part(HAND));
1539 pline("
\8d\8f\82ñ
\82Å
\82¢
\82é
\8aÔ
\82É%s
\82ª
\8a\8a\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D", body_part(HAND));
1540 display_nhwindow(WIN_MESSAGE, FALSE);
1542 You("engrave: \"%s\".", buf);
1544 You("
\8d\8f\82ñ
\82¾:
\81u%s
\81v
\81D",buf);
1545 /* violate illiteracy conduct since hero attempted to write
1546 a valid artifact name */
1547 u.uconduct.literate++;
1549 ++via_naming; /* This ought to be an argument rather than a static... */
1550 obj = oname(obj, buf);
1551 --via_naming; /* ...but oname() is used in a lot of places, so defer. */
1562 lth = *name ? (int) (strlen(name) + 1) : 0;
1563 if (lth > PL_PSIZ) {
1566 name = strncpy(buf, name, PL_PSIZ - 1);
1567 buf[PL_PSIZ - 1] = '\0';
1569 if (is_kanji2(name, lth - 1))
1571 name = strncpy(buf, name, lth - 1);
1572 buf[lth - 1] = '\0';
1575 /* If named artifact exists in the game, do not create another.
1576 * Also trying to create an artifact shouldn't de-artifact
1577 * it (e.g. Excalibur from prayer). In this case the object
1578 * will retain its current name. */
1579 if (obj->oartifact || (lth && exist_artifact(obj->otyp, name)))
1582 new_oname(obj, lth); /* removes old name if one is present */
1584 Strcpy(ONAME(obj), name);
1587 artifact_exists(obj, name, TRUE);
1588 if (obj->oartifact) {
1589 /* can't dual-wield with artifact as secondary weapon */
1590 if (obj == uswapwep)
1592 /* activate warning if you've just named your weapon "Sting" */
1594 set_artifact_intrinsic(obj, TRUE, W_WEP);
1595 /* if obj is owned by a shop, increase your bill */
1597 alter_cost(obj, 0L);
1599 /* violate illiteracy conduct since successfully wrote arti-name */
1600 u.uconduct.literate++;
1608 static NEARDATA const char callable[] = {
1609 SCROLL_CLASS, POTION_CLASS, WAND_CLASS, RING_CLASS, AMULET_CLASS,
1610 GEM_CLASS, SPBOOK_CLASS, ARMOR_CLASS, TOOL_CLASS, 0
1614 objtyp_is_callable(i)
1617 return (boolean) (objects[i].oc_uname
1618 || (OBJ_DESCR(objects[i])
1619 && index(callable, objects[i].oc_class)));
1622 /* C and #name commands - player can name monster or object or type of obj */
1629 menu_item *pick_list = 0;
1630 char ch, allowall[2];
1631 /* if player wants a,b,c instead of i,o when looting, do that here too */
1632 boolean abc = flags.lootabc;
1634 win = create_nhwindow(NHW_MENU);
1637 any.a_char = 'm'; /* group accelerator 'C' */
1638 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'C', ATR_NONE,
1640 "a monster", MENU_UNSELECTED);
1642 "
\89ö
\95¨", MENU_UNSELECTED);
1644 /* we use y and n as accelerators so that we can accept user's
1645 response keyed to old "name an individual object?" prompt */
1646 any.a_char = 'i'; /* group accelerator 'y' */
1647 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'y', ATR_NONE,
1649 "a particular object in inventory", MENU_UNSELECTED);
1651 "
\8e\9d\82¿
\95¨
\82Ì
\92\86\82Ì
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80", MENU_UNSELECTED);
1652 any.a_char = 'o'; /* group accelerator 'n' */
1653 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'n', ATR_NONE,
1655 "the type of an object in inventory", MENU_UNSELECTED);
1657 "
\8e\9d\82¿
\95¨
\82Ì
\92\86\82Ì
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80\82Ì
\8eí
\97Þ", MENU_UNSELECTED);
1659 any.a_char = 'f'; /* group accelerator ',' (or ':' instead?) */
1660 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, ',', ATR_NONE,
1662 "the type of an object upon the floor", MENU_UNSELECTED);
1664 "
\8f°
\82Ì
\8fã
\82É
\82 \82é
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80\82Ì
\8eí
\97Þ", MENU_UNSELECTED);
1665 any.a_char = 'd'; /* group accelerator '\' */
1666 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, '\\', ATR_NONE,
1668 "the type of an object on discoveries list", MENU_UNSELECTED);
1670 "
\94
\8c©
\95¨
\88ê
\97\97\82É
\82 \82é
\88ê
\82Â
\82Ì
\83A
\83C
\83e
\83\80\82Ì
\8eí
\97Þ", MENU_UNSELECTED);
1671 any.a_char = 'a'; /* group accelerator 'l' */
1672 add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'l', ATR_NONE,
1674 "record an annotation for the current level", MENU_UNSELECTED);
1676 "
\8c»
\8dÝ
\82Ì
\8aK
\82É
\91Î
\82·
\82é
\83\81\83\82\82Ì
\8bL
\98^", MENU_UNSELECTED);
1678 end_menu(win, "What do you want to name?");
1680 end_menu(win, "
\82Ç
\82ê
\82É
\96¼
\91O
\82ð
\82Â
\82¯
\82Ü
\82·
\82©
\81H");
1681 if (select_menu(win, PICK_ONE, &pick_list) > 0) {
1682 ch = pick_list[0].item.a_char;
1683 free((genericptr_t) pick_list);
1686 destroy_nhwindow(win);
1692 case 'm': /* name a visible monster */
1695 case 'i': /* name an individual object in inventory */
1696 allowall[0] = ALL_CLASSES;
1698 obj = getobj(allowall, "name");
1702 case 'o': /* name a type of object in inventory */
1703 obj = getobj(callable, "call");
1705 /* behave as if examining it in inventory;
1706 this might set dknown if it was picked up
1707 while blind and the hero can now see */
1712 You("would never recognize another one.");
1714 You("
\91¼
\82É
\94F
\8e¯
\82Å
\82«
\82È
\82¢
\81D");
1716 } else if (!objtyp_is_callable(obj->otyp)) {
1717 You("know those as well as you ever will.");
1724 case 'f': /* name a type of object visible on the floor */
1727 case 'd': /* name a type of object on the discoveries list */
1730 case 'a': /* annotate level */
1737 /* for use by safe_qbuf() */
1745 otemp.oextra = (struct oextra *) 0;
1747 /* in case water is already known, convert "[un]holy water" to "water" */
1748 otemp.blessed = otemp.cursed = 0;
1749 /* remove attributes that are doname() caliber but get formatted
1750 by xname(); most of these fixups aren't really needed because the
1751 relevant type of object isn't callable so won't reach this far */
1752 if (otemp.oclass == WEAPON_CLASS)
1753 otemp.opoisoned = 0; /* not poisoned */
1754 else if (otemp.oclass == POTION_CLASS)
1755 otemp.odiluted = 0; /* not diluted */
1756 else if (otemp.otyp == TOWEL || otemp.otyp == STATUE)
1757 otemp.spe = 0; /* not wet or historic */
1758 else if (otemp.otyp == TIN)
1759 otemp.known = 0; /* suppress tin type (homemade, &c) and mon type */
1760 else if (otemp.otyp == FIGURINE)
1761 otemp.corpsenm = NON_PM; /* suppress mon type */
1762 else if (otemp.otyp == HEAVY_IRON_BALL)
1763 otemp.owt = objects[HEAVY_IRON_BALL].oc_weight; /* not "very heavy" */
1764 else if (otemp.oclass == FOOD_CLASS && otemp.globby)
1765 otemp.owt = 120; /* 6*20, neither a small glob nor a large one */
1767 return an(xname(&otemp));
1774 char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
1778 return; /* probably blind */
1780 if (obj->oclass == POTION_CLASS && obj->fromsink)
1781 /* kludge, meaning it's sink water */
1783 Sprintf(qbuf, "Call a stream of %s fluid:",
1785 Sprintf(qbuf, "%s
\89t
\91Ì:",
1786 OBJ_DESCR(objects[obj->otyp]));
1789 (void) safe_qbuf(qbuf, "Call ", ":", obj,
1790 docall_xname, simpleonames, "thing");
1792 (void) safe_qbuf(qbuf, "", "
\82É
\89½
\82Æ
\96¼
\91O
\82ð
\95t
\82¯
\82é
\81H", obj,
1793 docall_xname, simpleonames, "
\82±
\82ê");
1796 if (!*buf || *buf == '\033')
1799 /* clear old name */
1800 str1 = &(objects[obj->otyp].oc_uname);
1802 free((genericptr_t) *str1);
1804 /* strip leading and trailing spaces; uncalls item if all spaces */
1805 (void) mungspaces(buf);
1807 if (*str1) { /* had name, so possibly remove from disco[] */
1808 /* strip name first, for the update_inventory() call
1809 from undiscover_object() */
1811 undiscover_object(obj->otyp);
1814 *str1 = dupstr(buf);
1815 discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
1825 struct obj *obj = 0;
1827 boolean fakeobj = FALSE, use_plural;
1829 boolean fakeobj = FALSE;
1832 cc.x = u.ux, cc.y = u.uy;
1833 /* "dot for under/over you" only makes sense when the cursor hasn't
1834 been moved off the hero's '@' yet, but there's no way to adjust
1835 the help text once getpos() has started */
1837 Sprintf(buf, "object on map (or '.' for one %s you)",
1838 (u.uundetected && hides_under(youmonst.data)) ? "over" : "under");
1840 Strcpy(buf, "
\92n
\90}
\8fã
\82Ì
\95¨
\91Ì(
\82 \82é
\82¢
\82Í'.'
\82Å
\82 \82È
\82½
\82Ì
\82¢
\82é
\8fê
\8f\8a");
1842 if (getpos(&cc, FALSE, buf) < 0 || cc.x <= 0)
1844 if (cc.x == u.ux && cc.y == u.uy) {
1845 obj = vobj_at(u.ux, u.uy);
1847 glyph = glyph_at(cc.x, cc.y);
1848 if (glyph_is_object(glyph))
1849 fakeobj = object_from_map(glyph, cc.x, cc.y, &obj);
1850 /* else 'obj' stays null */
1853 /* "under you" is safe here since there's no object to hide under */
1855 pline("There doesn't seem to be any object %s.",
1856 (cc.x == u.ux && cc.y == u.uy) ? "under you" : "there");
1858 pline("%s
\82É
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82¾
\81D",
1859 (cc.x == u.ux && cc.y == u.uy) ? "
\82 \82È
\82½
\82Ì
\89º" : "
\82»
\82±");
1863 /* note well: 'obj' might be an instance of STRANGE_OBJECT if target
1864 is a mimic; passing that to xname (directly or via simpleonames)
1865 would yield "glorkum" so we need to handle it explicitly; it will
1866 always fail the Hallucination test and pass the !callable test,
1867 resulting in the "can't be assigned a type name" message */
1868 Strcpy(buf, (obj->otyp != STRANGE_OBJECT)
1870 : obj_descr[STRANGE_OBJECT].oc_name);
1872 use_plural = (obj->quan > 1L);
1874 if (Hallucination) {
1875 const char *unames[6];
1878 /* straight role name */
1879 unames[0] = ((Upolyd ? u.mfemale : flags.female) && urole.name.f)
1882 /* random rank title for hero's role
1884 note: the 30 is hardcoded in xlev_to_rank, so should be
1885 hardcoded here too */
1886 unames[1] = rank_of(rn2_on_display_rng(30) + 1,
1887 Role_switch, flags.female);
1888 /* random fake monster */
1889 unames[2] = bogusmon(tmpbuf, (char *) 0);
1890 /* increased chance for fake monster */
1891 unames[3] = unames[2];
1893 unames[4] = roguename();
1896 unames[5] = "Wibbly Wobbly";
1898 unames[5] = "
\82¤
\82ë
\82¤
\82ë";
1900 pline("%s %s to call you \"%s.\"",
1901 The(buf), use_plural ? "decide" : "decides",
1902 unames[rn2_on_display_rng(SIZE(unames))]);
1904 pline("%s
\82Í
\82 \82È
\82½
\82ð
\81u%s
\81v
\82Æ
\8cÄ
\82Ô
\82±
\82Æ
\82É
\8c\88\82ß
\82½
\81D",
1906 unames[rn2_on_display_rng(SIZE(unames))]);
1908 } else if (!objtyp_is_callable(obj->otyp)) {
1910 pline("%s %s can't be assigned a type name.",
1911 use_plural ? "Those" : "That", buf);
1913 pline("%s
\82É
\8eí
\97Þ
\82Ì
\96¼
\91O
\82ð
\8a\84\82è
\93\96\82Ä
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
1916 } else if (!obj->dknown) {
1918 You("don't know %s %s well enough to name %s.",
1919 use_plural ? "those" : "that", buf, use_plural ? "them" : "it");
1921 You("
\96¼
\91O
\82ð
\95t
\82¯
\82ç
\82ê
\82é
\82Ù
\82Ç%s
\82Ì
\82±
\82Æ
\82ð
\82æ
\82
\92m
\82ç
\82È
\82¢
\81D",
1928 obj->where = OBJ_FREE; /* object_from_map() sets it to OBJ_FLOOR */
1933 static const char *const ghostnames[] = {
1934 /* these names should have length < PL_NSIZ */
1935 /* Capitalize the names for aesthetics -dgk */
1936 "Adri", "Andries", "Andreas", "Bert", "David", "Dirk",
1937 "Emile", "Frans", "Fred", "Greg", "Hether", "Jay",
1938 "John", "Jon", "Karnov", "Kay", "Kenny", "Kevin",
1939 "Maud", "Michiel", "Mike", "Peter", "Robert", "Ron",
1940 "Tom", "Wilmar", "Nick Danger", "Phoenix", "Jiro", "Mizue",
1941 "Stephan", "Lance Braccus", "Shadowhawk"
1944 /* ghost names formerly set by x_monnam(), now by makemon() instead */
1948 return rn2(7) ? ghostnames[rn2(SIZE(ghostnames))] : (const char *) plname;
1952 * Monster naming functions:
1953 * x_monnam is the generic monster-naming function.
1954 * seen unseen detected named
1955 * mon_nam: the newt it the invisible orc Fido
1956 * noit_mon_nam:the newt (as if detected) the invisible orc Fido
1957 * l_monnam: newt it invisible orc dog called Fido
1958 * Monnam: The newt It The invisible orc Fido
1959 * noit_Monnam: The newt (as if detected) The invisible orc Fido
1960 * Adjmonnam: The poor newt It The poor invisible orc The poor Fido
1961 * Amonnam: A newt It An invisible orc Fido
1962 * a_monnam: a newt it an invisible orc Fido
1963 * m_monnam: newt xan orc Fido
1964 * y_monnam: your newt your xan your invisible orc Fido
1965 * noname_monnam(mon,article):
1966 * article newt art xan art invisible orc art dog
1969 /* Bug: if the monster is a priest or shopkeeper, not every one of these
1970 * options works, since those are special cases.
1973 x_monnam(mtmp, article, adjective, suppress, called)
1974 register struct monst *mtmp;
1976 /* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious
1977 * ARTICLE_YOUR: "your" on pets, "the" on everything else
1979 * If the monster would be referred to as "it" or if the monster has a name
1980 * _and_ there is no adjective, "invisible", "saddled", etc., override this
1981 * and always use no article.
1983 const char *adjective;
1985 /* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE.
1986 * EXACT_NAME: combination of all the above
1987 * SUPPRESS_NAME: omit monster's assigned name (unless uniq w/ pname).
1991 char *buf = nextmbuf();
1992 struct permonst *mdat = mtmp->data;
1993 const char *pm_name = mdat->mname;
1994 boolean do_hallu, do_invis, do_it, do_saddle, do_name;
1996 boolean name_at_start, has_adjectives;
2000 if (program_state.gameover)
2001 suppress |= SUPPRESS_HALLUCINATION;
2002 if (article == ARTICLE_YOUR && !mtmp->mtame)
2003 article = ARTICLE_THE;
2005 do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION);
2006 do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE);
2007 do_it = !canspotmon(mtmp) && article != ARTICLE_YOUR
2008 && !program_state.gameover && mtmp != u.usteed
2009 && !(u.uswallow && mtmp == u.ustuck) && !(suppress & SUPPRESS_IT);
2010 do_saddle = !(suppress & SUPPRESS_SADDLE);
2011 do_name = !(suppress & SUPPRESS_NAME) || type_is_pname(mdat);
2015 /* unseen monsters, etc. Use "it" */
2020 Strcpy(buf, "
\89½
\8eÒ
\82©");
2024 /* priests and minions: don't even use this function */
2025 if (mtmp->ispriest || mtmp->isminion) {
2026 char priestnambuf[BUFSZ];
2028 long save_prop = EHalluc_resistance;
2029 unsigned save_invis = mtmp->minvis;
2031 /* when true name is wanted, explicitly block Hallucination */
2033 EHalluc_resistance = 1L;
2036 name = priestname(mtmp, priestnambuf);
2037 EHalluc_resistance = save_prop;
2038 mtmp->minvis = save_invis;
2040 if (article == ARTICLE_NONE && !strncmp(name, "the ", 4))
2043 return strcpy(buf, name);
2045 /* an "aligned priest" not flagged as a priest or minion should be
2046 "priest" or "priestess" (normally handled by priestname()) */
2047 if (mdat == &mons[PM_ALIGNED_PRIEST])
2049 pm_name = mtmp->female ? "priestess" : "priest";
2051 pm_name = mtmp->female ? "
\93ò
\91m" : "
\91m
\97µ";
2052 else if (mdat == &mons[PM_HIGH_PRIEST] && mtmp->female)
2054 pm_name = "high priestess";
2056 pm_name = "
\96@
\89¤";
2058 /* Shopkeepers: use shopkeeper name. For normal shopkeepers, just
2059 * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
2060 * shopkeeper" or "Asidonhopo the blue dragon". If hallucinating,
2061 * none of this applies.
2063 if (mtmp->isshk && !do_hallu) {
2065 if (adjective && article == ARTICLE_THE) {
2066 /* pathological case: "the angry Asidonhopo the blue dragon"
2068 Strcpy(buf, "the ");
2069 Strcat(strcat(buf, adjective), " ");
2070 Strcat(buf, shkname(mtmp));
2073 Strcat(buf, shkname(mtmp));
2074 if (mdat == &mons[PM_SHOPKEEPER] && !do_invis)
2076 Strcat(buf, " the ");
2078 Strcat(buf, "invisible ");
2079 Strcat(buf, pm_name);
2082 if (mdat == &mons[PM_SHOPKEEPER] && !do_invis){
2083 Strcpy(buf, shkname(mtmp));
2085 Sprintf(buf, "%s
\82Æ
\82¢
\82¤
\96¼
\82Ì%s%s",
2086 shkname(mtmp), do_invis ? "
\8ep
\82Ì
\8c©
\82¦
\82È
\82¢" : "",
2093 /* Put the adjectives in the buffer */
2096 Strcat(strcat(buf, adjective), " ");
2098 Strcat(buf, adjective);
2101 Strcat(buf, "invisible ");
2103 Strcat(buf, "
\8ep
\82Ì
\8c©
\82¦
\82È
\82¢");
2104 if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind
2107 Strcat(buf, "saddled ");
2109 Strcat(buf, "
\88Æ
\82Ì
\82Â
\82¢
\82Ä
\82¢
\82é");
2111 has_adjectives = (buf[0] != '\0');
2114 /* Put the actual monster name or type into the buffer now */
2115 /* Be sure to remember whether the buffer starts with a name */
2118 char *rname = rndmonnam(&rnamecode);
2122 name_at_start = bogon_is_pname(rnamecode);
2124 } else if (do_name && has_mname(mtmp)) {
2125 char *name = MNAME(mtmp);
2127 if (mdat == &mons[PM_GHOST]) {
2129 Sprintf(eos(buf), "%s ghost", s_suffix(name));
2131 Sprintf(buf, "%s
\82Ì
\97H
\97ì", name);
2133 name_at_start = TRUE;
2135 } else if (called) {
2137 Sprintf(eos(buf), "%s called %s", pm_name, name);
2139 Sprintf(eos(buf), "%s
\82Æ
\82¢
\82¤
\96¼
\82Ì%s", name, pm_name);
2141 name_at_start = (boolean) type_is_pname(mdat);
2143 #if 0 /*JP*//*
\92è
\8a¥
\8e\8c\82Ì
\8f\88\97\9d\82Í
\95s
\97v*/
2144 } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) {
2145 /* <name> the <adjective> <invisible> <saddled> <rank> */
2149 pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */
2152 Strcat(pbuf, bp + 5); /* append the rest of the name */
2154 article = ARTICLE_NONE;
2155 name_at_start = TRUE;
2160 name_at_start = TRUE;
2163 } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) {
2166 Strcpy(pbuf, rank_of((int) mtmp->m_lev, monsndx(mdat),
2167 (boolean) mtmp->female));
2169 Strcat(buf, lcase(pbuf));
2174 name_at_start = FALSE;
2177 Strcat(buf, pm_name);
2179 name_at_start = (boolean) type_is_pname(mdat);
2183 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\8a¥
\8e\8c\82Í
\82È
\82¢*/
2184 if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) {
2185 if (mdat == &mons[PM_WIZARD_OF_YENDOR])
2186 article = ARTICLE_THE;
2188 article = ARTICLE_NONE;
2189 } else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) {
2190 article = ARTICLE_THE;
2198 Strcpy(buf2, "your ");
2203 Strcpy(buf2, "the ");
2223 return x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
2224 (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, TRUE);
2231 return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2232 (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, FALSE);
2235 /* print the name as if mon_nam() was called, but assume that the player
2236 * can always see the monster--used for probing and for monsters aggravating
2237 * the player with a cursed potion of invisibility
2243 return x_monnam(mtmp, ARTICLE_THE, (char *) 0,
2244 (has_mname(mtmp)) ? (SUPPRESS_SADDLE | SUPPRESS_IT)
2253 register char *bp = mon_nam(mtmp);
2263 register char *bp = noit_mon_nam(mtmp);
2269 /* return "a dog" rather than "Fido", honoring hallucination and visibility */
2271 noname_monnam(mtmp, article)
2275 return x_monnam(mtmp, article, (char *) 0, SUPPRESS_NAME, FALSE);
2278 /* monster's own name -- overrides hallucination and [in]visibility
2279 so shouldn't be used in ordinary messages (mainly for disclosure) */
2284 return x_monnam(mtmp, ARTICLE_NONE, (char *) 0, EXACT_NAME, FALSE);
2287 /* pet name: "your little dog" */
2292 int prefix, suppression_flag;
2294 prefix = mtmp->mtame ? ARTICLE_YOUR : ARTICLE_THE;
2295 suppression_flag = (has_mname(mtmp)
2296 /* "saddled" is redundant when mounted */
2297 || mtmp == u.usteed)
2301 return x_monnam(mtmp, prefix, (char *) 0, suppression_flag, FALSE);
2305 Adjmonnam(mtmp, adj)
2309 char *bp = x_monnam(mtmp, ARTICLE_THE, adj,
2310 has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2320 return x_monnam(mtmp, ARTICLE_A, (char *) 0,
2321 has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE);
2328 char *bp = a_monnam(mtmp);
2334 /* used for monster ID by the '/', ';', and 'C' commands to block remote
2335 identification of the endgame altars via their attending priests */
2337 distant_monnam(mon, article, outbuf)
2339 int article; /* only ARTICLE_NONE and ARTICLE_THE are handled here */
2342 /* high priest(ess)'s identity is concealed on the Astral Plane,
2343 unless you're adjacent (overridden for hallucination which does
2344 its own obfuscation) */
2345 if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination
2346 && Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) {
2348 Strcpy(outbuf, article == ARTICLE_THE ? "the " : "");
2349 Strcat(outbuf, mon->female ? "high priestess" : "high priest");
2351 Strcpy(outbuf, "
\96@
\89¤");
2354 Strcpy(outbuf, x_monnam(mon, article, (char *) 0, 0, TRUE));
2359 /* fake monsters used to be in a hard-coded array, now in a data file */
2366 get_rnd_text(BOGUSMONFILE, buf, rn2_on_display_rng);
2367 /* strip prefix if present */
2368 if (!letter(*mname)) {
2379 /* return a random monster name, for hallucination */
2384 static char buf[BUFSZ];
2387 #define BOGUSMONSIZE 100 /* arbitrary */
2393 name = rn2_on_display_rng(SPECIAL_PM + BOGUSMONSIZE - LOW_PM) + LOW_PM;
2394 } while (name < SPECIAL_PM
2395 && (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN)));
2397 if (name >= SPECIAL_PM) {
2398 mname = bogusmon(buf, code);
2400 mname = strcpy(buf, mons[name].mname);
2406 /* check bogusmon prefix to decide whether it's a personal name */
2408 bogon_is_pname(code)
2413 return index("-+=", code) ? TRUE : FALSE;
2416 /* name of a Rogue player */
2422 if ((opts = nh_getenv("ROGUEOPTS")) != 0) {
2423 for (i = opts; *i; i++)
2424 if (!strncmp("name=", i, 5)) {
2426 if ((j = index(i + 5, ',')) != 0)
2431 /*JP:Rogue
\82Ì
\8aJ
\94
\8eÒ
\82Ì
\96¼
\91O*/
2432 return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
2436 static NEARDATA const char *const hcolors[] = {
2438 "ultraviolet", "infrared", "bluish-orange", "reddish-green", "dark white",
2439 "light black", "sky blue-pink", "salty", "sweet", "sour", "bitter",
2440 "striped", "spiral", "swirly", "plaid", "checkered", "argyle", "paisley",
2441 "blotchy", "guernsey-spotted", "polka-dotted", "square", "round",
2442 "triangular", "cabernet", "sangria", "fuchsia", "wisteria", "lemon-lime",
2443 "strawberry-banana", "peppermint", "romantic", "incandescent",
2444 "octarine", /* Discworld: the Colour of Magic */
2446 "
\8e\87\8aO
\90F
\82Ì", "
\90Ô
\8aO
\90F
\82Ì", "
\90Â
\90F
\82ª
\82©
\82Á
\82½
\83I
\83\8c\83\93\83W
\90F
\82Ì", "
\90Ô
\82Ý
\82ª
\82©
\82Á
\82½
\97Î
\90F
\82Ì", "
\88Ã
\82¢
\94\92\90F
\82Ì",
2447 "
\96¾
\82é
\82¢
\8d\95\82Ì", "
\90\85\90F
\82ª
\82©
\82Á
\82½
\83s
\83\93\83N
\90F
\82Ì", "
\89\96\90h
\82¢", "
\8aÃ
\82¢", "
\82·
\82Á
\82Ï
\82¢", "
\8bê
\82¢",
2448 "
\82µ
\82Ü
\96Í
\97l
\82Ì", "
\82ç
\82¹
\82ñ
\8fó
\82Ì", "
\94g
\8fó
\82Ì", "
\8ai
\8eq
\96Í
\97l
\8fó
\82Ì", "
\83`
\83F
\83b
\83N
\8fó
\82Ì", "
\95ú
\8eË
\8fó
\82Ì", "
\83y
\81[
\83Y
\83\8a\81[
\96Í
\97l
\82Ì",
2449 "
\82µ
\82Ý
\8fó
\82Ì", "
\90Â
\90F
\82Ì
\94Á
\93_
\8fó
\82Ì", "
\93_
\8fó
\82Ì", "
\8el
\8ap
\8c`
\8fó
\82Ì", "
\8aÛ
\8fó
\82Ì",
2450 "
\8eO
\8ap
\8fó
\82Ì", "
\83J
\83x
\83\8b\83l
\90F
\82Ì", "
\83T
\83\93\83O
\83\8a\83A
\90F
\82Ì", "
\91N
\82â
\82©
\82È
\90Ô
\8e\87\90F
\82Ì", "
\93¡
\90F
\82Ì", "
\83\8c\83\82\83\93\83\89\83C
\83\80\90F
\82Ì",
2451 "ä
\95\83o
\83i
\83i
\90F
\82Ì", "
\83y
\83p
\81[
\83~
\83\93\83g
\90F
\82Ì", "
\83\8d\83}
\83\93\83`
\83b
\83N
\82È
\90F
\82Ì", "
\94\92\94M
\90F
\82Ì",
2452 "
\83I
\83N
\83^
\83\8a\83\93\90F
\82Ì",
2458 const char *colorpref;
2460 return (Hallucination || !colorpref)
2461 ? hcolors[rn2_on_display_rng(SIZE(hcolors))]
2465 /* return a random real color unless hallucinating */
2469 int k = rn2(CLR_MAX);
2471 return Hallucination ? hcolor((char *) 0)
2473 : (k == NO_COLOR) ? "colorless"
2475 : (k == NO_COLOR) ? "
\96³
\90F
\82Ì"
2479 static NEARDATA const char *const hliquids[] = {
2481 "yoghurt", "oobleck", "clotted blood", "diluted water", "purified water",
2482 "instant coffee", "tea", "herbal infusion", "liquid rainbow",
2483 "creamy foam", "mulled wine", "bouillon", "nectar", "grog", "flubber",
2484 "ketchup", "slow light", "oil", "vinaigrette", "liquid crystal", "honey",
2485 "caramel sauce", "ink", "aqueous humour", "milk substitute",
2486 "fruit juice", "glowing lava", "gastric acid", "mineral water",
2487 "cough syrup", "quicksilver", "sweet vitriol", "grey goo", "pink slime",
2489 "
\83\88\81[
\83O
\83\8b\83g", "
\83E
\81[
\83u
\83\8c\83b
\83N", "
\8c\8c\8cÐ", "
\8fö
\97¯
\90\85", "
\90¸
\90»
\90\85",
2490 "
\83C
\83\93\83X
\83^
\83\93\83g
\83R
\81[
\83q
\81[", "
\8dg
\92\83", "
\83n
\81[
\83u
\89t", "
\89t
\91Ì
\82Ì
\93ø",
2491 "
\83N
\83\8a\81[
\83~
\81[
\83t
\83H
\81[
\83\80", "
\83z
\83b
\83g
\83\8f\83C
\83\93", "
\83u
\83C
\83\88\83\93", "
\89Ê
\8f`", "
\83O
\83\8d\83b
\83O", "
\83t
\83\89\83o
\81[",
2492 "
\83P
\83`
\83\83\83b
\83v", "
\92á
\91¬
\8cõ", "
\96û", "
\83r
\83l
\83O
\83\8c\83b
\83g
\83\
\81[
\83X", "
\89t
\91Ì
\90\85\8f»", "
\96I
\96¨",
2493 "
\83J
\83\89\83\81\83\8b\83\
\81[
\83X", "
\83C
\83\93\83N", "
\96[
\90\85", "
\91ã
\97p
\93û",
2494 "
\83t
\83\8b\81[
\83c
\83W
\83\85\81[
\83X", "
\97¬
\82ê
\82é
\97n
\8aâ", "
\88Ý
\8e_", "
\83~
\83l
\83\89\83\8b\83E
\83H
\81[
\83^
\81[",
2495 "
\8aP
\8e~
\82ß
\83V
\83\8d\83b
\83v", "
\90\85\8bâ", "
\83W
\83G
\83`
\83\8b\83G
\81[
\83e
\83\8b", "
\83O
\83\8c\83C
\83O
\81[", "
\83s
\83\93\83N
\83X
\83\89\83C
\83\80",
2501 const char *liquidpref;
2503 return (Hallucination || !liquidpref) ? hliquids[rn2(SIZE(hliquids))]
2507 /* Aliases for road-runner nemesis
2509 static const char *const coynames[] = {
2510 "Carnivorous Vulgaris", "Road-Runnerus Digestus", "Eatibus Anythingus",
2511 "Famishus-Famishus", "Eatibus Almost Anythingus", "Eatius Birdius",
2512 "Famishius Fantasticus", "Eternalii Famishiis", "Famishus Vulgarus",
2513 "Famishius Vulgaris Ingeniusi", "Eatius-Slobbius", "Hardheadipus Oedipus",
2514 "Carnivorous Slobbius", "Hard-Headipus Ravenus", "Evereadii Eatibus",
2515 "Apetitius Giganticus", "Hungrii Flea-Bagius", "Overconfidentii Vulgaris",
2516 "Caninus Nervous Rex", "Grotesques Appetitus", "Nemesis Ridiculii",
2521 coyotename(mtmp, buf)
2526 Sprintf(buf, "%s - %s",
2527 x_monnam(mtmp, ARTICLE_NONE, (char *) 0, 0, TRUE),
2528 mtmp->mcan ? coynames[SIZE(coynames) - 1]
2529 : coynames[mtmp->m_id % (SIZE(coynames) - 1)]);
2538 static const char *v[] = { "a", "ai", "og", "u" };
2539 static const char *snd[] = { "gor", "gris", "un", "bane", "ruk",
2540 "oth","ul", "z", "thos","akh","hai" };
2541 int i, iend = rn1(2, 3), vstart = rn2(2);
2545 for (i = 0; i < iend; ++i) {
2546 vstart = 1 - vstart; /* 0 -> 1, 1 -> 0 */
2547 Sprintf(eos(s), "%s%s", (i > 0 && !rn2(30)) ? "-" : "",
2548 vstart ? v[rn2(SIZE(v))] : snd[rn2(SIZE(snd))]);
2555 christen_orc(mtmp, gang, other)
2557 const char *gang, *other;
2560 char buf[BUFSZ], buf2[BUFSZ], *orcname;
2562 orcname = rndorcname(buf2);
2563 sz = (int) strlen(orcname);
2565 sz += (int) (strlen(gang) + sizeof " of " - sizeof "");
2567 sz += (int) strlen(other);
2571 boolean nameit = FALSE;
2573 if (gang && orcname) {
2574 Sprintf(buf, "%s of %s", upstart(orcname),
2575 upstart(strcpy(gbuf, gang)));
2577 } else if (other && orcname) {
2578 Sprintf(buf, "%s%s", upstart(orcname), other);
2582 mtmp = christen_monst(mtmp, buf);
2587 /* make sure "The Colour of Magic" remains the first entry in here */
2588 static const char *const sir_Terry_novels[] = {
2589 "The Colour of Magic", "The Light Fantastic", "Equal Rites", "Mort",
2590 "Sourcery", "Wyrd Sisters", "Pyramids", "Guards! Guards!", "Eric",
2591 "Moving Pictures", "Reaper Man", "Witches Abroad", "Small Gods",
2592 "Lords and Ladies", "Men at Arms", "Soul Music", "Interesting Times",
2593 "Maskerade", "Feet of Clay", "Hogfather", "Jingo", "The Last Continent",
2594 "Carpe Jugulum", "The Fifth Elephant", "The Truth", "Thief of Time",
2595 "The Last Hero", "The Amazing Maurice and His Educated Rodents",
2596 "Night Watch", "The Wee Free Men", "Monstrous Regiment",
2597 "A Hat Full of Sky", "Going Postal", "Thud!", "Wintersmith",
2598 "Making Money", "Unseen Academicals", "I Shall Wear Midnight", "Snuff",
2599 "Raising Steam", "The Shepherd's Crown"
2606 int j, k = SIZE(sir_Terry_novels);
2612 else if (*novidx >= 0 && *novidx < k)
2615 return sir_Terry_novels[j];
2619 lookup_novel(lookname, idx)
2620 const char *lookname;
2625 /* Take American or U.K. spelling of this one */
2626 if (!strcmpi(The(lookname), "The Color of Magic"))
2627 lookname = sir_Terry_novels[0];
2629 for (k = 0; k < SIZE(sir_Terry_novels); ++k) {
2630 if (!strcmpi(lookname, sir_Terry_novels[k])
2631 || !strcmpi(The(lookname), sir_Terry_novels[k])) {
2634 return sir_Terry_novels[k];
2637 /* name not found; if novelidx is already set, override the name */
2638 if (idx && *idx >= 0 && *idx < SIZE(sir_Terry_novels))
2639 return sir_Terry_novels[*idx];
2641 return (const char *) 0;