1 /* NetHack 3.6 cmd.c $NHDT-Date: 1446975462 2015/11/08 09:37:42 $ $NHDT-Branch: master $:$NHDT-Revision: 1.206 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
8 /* JNetHack may be freely redistributed. See license for details. */
14 STATIC_VAR boolean alt_esc = FALSE;
17 struct cmd Cmd = { 0 }; /* flag.h */
19 extern const char *hu_stat[]; /* hunger status from eat.c */
20 extern const char *enc_stat[]; /* encumbrance status from botl.c */
24 * Some systems may have getchar() return EOF for various reasons, and
25 * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
27 #if defined(SYSV) || defined(DGUX) || defined(HPUX)
32 #define CMD_TRAVEL (char) 0x90
33 #define CMD_CLICKLOOK (char) 0x8F
36 extern int NDECL(wiz_debug_cmd_bury);
37 extern int NDECL(wiz_debug_cmd_traveldisplay);
40 #ifdef DUMB /* stuff commented out in extern.h, but needed here */
41 extern int NDECL(doapply); /**/
42 extern int NDECL(dorub); /**/
43 extern int NDECL(dojump); /**/
44 extern int NDECL(doextlist); /**/
45 extern int NDECL(enter_explore_mode); /**/
46 extern int NDECL(dodrop); /**/
47 extern int NDECL(doddrop); /**/
48 extern int NDECL(dodown); /**/
49 extern int NDECL(doup); /**/
50 extern int NDECL(donull); /**/
51 extern int NDECL(dowipe); /**/
52 extern int NDECL(docallcnd); /**/
53 extern int NDECL(dotakeoff); /**/
54 extern int NDECL(doremring); /**/
55 extern int NDECL(dowear); /**/
56 extern int NDECL(doputon); /**/
57 extern int NDECL(doddoremarm); /**/
58 extern int NDECL(dokick); /**/
59 extern int NDECL(dofire); /**/
60 extern int NDECL(dothrow); /**/
61 extern int NDECL(doeat); /**/
62 extern int NDECL(done2); /**/
63 extern int NDECL(vanquished); /**/
64 extern int NDECL(doengrave); /**/
65 extern int NDECL(dopickup); /**/
66 extern int NDECL(ddoinv); /**/
67 extern int NDECL(dotypeinv); /**/
68 extern int NDECL(dolook); /**/
69 extern int NDECL(doprgold); /**/
70 extern int NDECL(doprwep); /**/
71 extern int NDECL(doprarm); /**/
72 extern int NDECL(doprring); /**/
73 extern int NDECL(dopramulet); /**/
74 extern int NDECL(doprtool); /**/
75 extern int NDECL(dosuspend); /**/
76 extern int NDECL(doforce); /**/
77 extern int NDECL(doopen); /**/
78 extern int NDECL(doclose); /**/
79 extern int NDECL(dosh); /**/
80 extern int NDECL(dodiscovered); /**/
81 extern int NDECL(doclassdisco); /**/
82 extern int NDECL(doset); /**/
83 extern int NDECL(dotogglepickup); /**/
84 extern int NDECL(dowhatis); /**/
85 extern int NDECL(doquickwhatis); /**/
86 extern int NDECL(dowhatdoes); /**/
87 extern int NDECL(dohelp); /**/
88 extern int NDECL(dohistory); /**/
89 extern int NDECL(doloot); /**/
90 extern int NDECL(dodrink); /**/
91 extern int NDECL(dodip); /**/
92 extern int NDECL(dosacrifice); /**/
93 extern int NDECL(dopray); /**/
94 extern int NDECL(dotip); /**/
95 extern int NDECL(doturn); /**/
96 extern int NDECL(doredraw); /**/
97 extern int NDECL(doread); /**/
98 extern int NDECL(dosave); /**/
99 extern int NDECL(dosearch); /**/
100 extern int NDECL(doidtrap); /**/
101 extern int NDECL(dopay); /**/
102 extern int NDECL(dosit); /**/
103 extern int NDECL(dotalk); /**/
104 extern int NDECL(docast); /**/
105 extern int NDECL(dovspell); /**/
106 extern int NDECL(dotele); /**/
107 extern int NDECL(dountrap); /**/
108 extern int NDECL(doversion); /**/
109 extern int NDECL(doextversion); /**/
110 extern int NDECL(doswapweapon); /**/
111 extern int NDECL(dowield); /**/
112 extern int NDECL(dowieldquiver); /**/
113 extern int NDECL(dozap); /**/
114 extern int NDECL(doorganize); /**/
117 static int NDECL(dosuspend_core); /**/
119 static int NDECL((*timed_occ_fn));
121 STATIC_PTR int NDECL(doprev_message);
122 STATIC_PTR int NDECL(timed_occupation);
123 STATIC_PTR int NDECL(doextcmd);
124 STATIC_PTR int NDECL(domonability);
125 STATIC_PTR int NDECL(dooverview_or_wiz_where);
126 STATIC_PTR int NDECL(dotravel);
127 STATIC_PTR int NDECL(doterrain);
128 STATIC_PTR int NDECL(wiz_wish);
129 STATIC_PTR int NDECL(wiz_identify);
130 STATIC_PTR int NDECL(wiz_map);
131 STATIC_PTR int NDECL(wiz_genesis);
132 STATIC_PTR int NDECL(wiz_where);
133 STATIC_PTR int NDECL(wiz_detect);
134 STATIC_PTR int NDECL(wiz_panic);
135 STATIC_PTR int NDECL(wiz_polyself);
136 STATIC_PTR int NDECL(wiz_level_tele);
137 STATIC_PTR int NDECL(wiz_level_change);
138 STATIC_PTR int NDECL(wiz_show_seenv);
139 STATIC_PTR int NDECL(wiz_show_vision);
140 STATIC_PTR int NDECL(wiz_smell);
141 STATIC_PTR int NDECL(wiz_mon_polycontrol);
142 STATIC_PTR int NDECL(wiz_show_wmodes);
143 STATIC_DCL void NDECL(wiz_map_levltyp);
144 STATIC_DCL void NDECL(wiz_levltyp_legend);
145 #if defined(__BORLANDC__) && !defined(_WIN32)
146 extern void FDECL(show_borlandc_stats, (winid));
148 #ifdef DEBUG_MIGRATING_MONS
149 STATIC_PTR int NDECL(wiz_migrate_mons);
151 STATIC_DCL int FDECL(size_monst, (struct monst *));
152 STATIC_DCL int FDECL(size_obj, (struct obj *));
153 STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *,
154 BOOLEAN_P, BOOLEAN_P));
155 STATIC_DCL void FDECL(obj_chain, (winid, const char *, struct obj *,
157 STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *,
159 STATIC_DCL void FDECL(mon_chain, (winid, const char *, struct monst *,
161 STATIC_DCL void FDECL(contained, (winid, const char *, long *, long *));
162 STATIC_PTR int NDECL(wiz_show_stats);
163 STATIC_DCL boolean FDECL(accept_menu_prefix, (int NDECL((*))));
165 STATIC_DCL int NDECL(wiz_port_debug);
167 STATIC_PTR int NDECL(wiz_rumor_check);
168 STATIC_DCL char FDECL(cmd_from_func, (int NDECL((*))));
169 STATIC_PTR int NDECL(doattributes);
170 STATIC_PTR int NDECL(doconduct); /**/
172 STATIC_DCL void FDECL(enlght_line, (const char *, const char *, const char *,
174 STATIC_DCL char *FDECL(enlght_combatinc, (const char *, int, int, char *));
175 STATIC_DCL void FDECL(enlght_halfdmg, (int, int));
176 STATIC_DCL boolean NDECL(walking_on_water);
177 STATIC_DCL boolean FDECL(cause_known, (int));
178 STATIC_DCL char *FDECL(attrval, (int, int, char *));
179 STATIC_DCL void FDECL(background_enlightenment, (int, int));
180 STATIC_DCL void FDECL(characteristics_enlightenment, (int, int));
181 STATIC_DCL void FDECL(one_characteristic, (int, int, int));
182 STATIC_DCL void FDECL(status_enlightenment, (int, int));
183 STATIC_DCL void FDECL(attributes_enlightenment, (int, int));
185 static const char *readchar_queue = "";
186 static coord clicklook_cc;
188 STATIC_DCL char *NDECL(parse);
189 STATIC_DCL boolean FDECL(help_dir, (CHAR_P, const char *));
192 doprev_message(VOID_ARGS)
194 return nh_doprev_message();
197 /* Count down by decrementing multi */
199 timed_occupation(VOID_ARGS)
207 /* If you have moved since initially setting some occupations, they
208 * now shouldn't be able to restart.
210 * The basic rule is that if you are carrying it, you can continue
211 * since it is with you. If you are acting on something at a distance,
212 * your orientation to it must have changed when you moved.
214 * The exception to this is taking off items, since they can be taken
215 * off in a number of ways in the intervening time, screwing up ordering.
217 * Currently: Take off all armor.
218 * Picking Locks / Forcing Chests.
229 /* If a time is given, use it to timeout this function, otherwise the
230 * function times out by its own means.
233 set_occupation(fn, txt, xtime)
239 occupation = timed_occupation;
248 STATIC_DCL char NDECL(popch);
250 /* Provide a means to redo the last command. The flag `in_doagain' is set
251 * to true while redoing the command. This flag is tested in commands that
252 * require additional input (like `throw' which requires a thing and a
253 * direction), and the input prompt is not shown. Also, while in_doagain is
254 * TRUE, no keystrokes can be saved into the saveq.
257 static char pushq[BSIZE], saveq[BSIZE];
258 static NEARDATA int phead, ptail, shead, stail;
263 /* If occupied, return '\0', letting tgetch know a character should
264 * be read from the keyboard. If the character read is not the
265 * ABORT character (as checked in pcmain.c), that character will be
266 * pushed back on the pushq.
271 return (char) ((shead != stail) ? saveq[stail++] : '\0');
273 return (char) ((phead != ptail) ? pushq[ptail++] : '\0');
277 pgetchar() /* courtesy of aeb@cwi.nl */
286 /* A ch == 0 resets the pushq */
298 /* A ch == 0 resets the saveq. Only save keystrokes when not
299 * replaying a previous command.
307 phead = ptail = shead = stail = 0;
308 else if (shead < BSIZE)
314 /* here after # - now read a full-word command */
321 /* keep repeating until we don't run help or quit */
327 func = extcmdlist[idx].ef_funct;
328 if (iflags.menu_requested && !accept_menu_prefix(func)) {
329 pline("'m' prefix has no effect for this command.");
330 iflags.menu_requested = FALSE;
333 } while (func == doextlist);
338 /* here after #? - now list all full-word commands */
342 register const struct ext_func_tab *efp;
346 datawin = create_nhwindow(NHW_TEXT);
347 putstr(datawin, 0, "");
349 putstr(datawin, 0, " Extended Commands List");
351 putstr(datawin, 0, "
\8ag
\92£
\83R
\83}
\83\93\83h
\88ê
\97\97");
352 putstr(datawin, 0, "");
354 putstr(datawin, 0, " Press '#', then type:");
356 putstr(datawin, 0, " '#'
\82ð
\89\9f\82µ
\82½
\82 \82Æ
\83^
\83C
\83v
\82¹
\82æ:");
357 putstr(datawin, 0, "");
359 for (efp = extcmdlist; efp->ef_txt; efp++) {
360 Sprintf(buf, " %-15s - %s.", efp->ef_txt, efp->ef_desc);
361 putstr(datawin, 0, buf);
363 display_nhwindow(datawin, FALSE);
364 destroy_nhwindow(datawin);
369 #define MAX_EXT_CMD 50 /* Change if we ever have > 50 ext cmds */
372 * This is currently used only by the tty port and is
373 * controlled via runtime option 'extmenu'.
374 * ``# ?'' is counted towards the limit of the number of commands,
375 * so we actually support MAX_EXT_CMD-1 "real" extended commands.
377 * Here after # - now show pick-list of possible commands.
382 const struct ext_func_tab *efp;
383 menu_item *pick_list = (menu_item *) 0;
386 const struct ext_func_tab *choices[MAX_EXT_CMD + 1];
388 char cbuf[QBUFSZ], prompt[QBUFSZ], fmtstr[20];
389 int i, n, nchoices, acount;
391 int accelerator, prevaccelerator;
400 /* populate choices */
401 for (efp = extcmdlist; efp->ef_txt; efp++) {
402 if (!matchlevel || !strncmp(efp->ef_txt, cbuf, matchlevel)) {
404 if ((int) strlen(efp->ef_desc) > biggest) {
405 biggest = strlen(efp->ef_desc);
406 Sprintf(fmtstr, "%%-%ds", biggest + 15);
408 if (++i > MAX_EXT_CMD) {
411 "Exceeded %d extended commands in doextcmd() menu; 'extmenu' disabled.",
419 choices[i] = (struct ext_func_tab *) 0;
421 /* if we're down to one, we have our selection so get out of here */
423 for (i = 0; extcmdlist[i].ef_txt != (char *) 0; i++)
424 if (!strncmpi(extcmdlist[i].ef_txt, cbuf, matchlevel)) {
432 win = create_nhwindow(NHW_MENU);
434 accelerator = prevaccelerator = 0;
436 for (i = 0; choices[i]; ++i) {
437 accelerator = choices[i]->ef_txt[matchlevel];
438 if (accelerator != prevaccelerator || nchoices < (ROWNO - 3)) {
440 /* flush extended cmds for that letter already in buf */
441 Sprintf(buf, fmtstr, prompt);
442 any.a_char = prevaccelerator;
443 add_menu(win, NO_GLYPH, &any, any.a_char, 0, ATR_NONE,
448 prevaccelerator = accelerator;
449 if (!acount || nchoices < (ROWNO - 3)) {
450 Sprintf(prompt, "%s [%s]", choices[i]->ef_txt,
451 choices[i]->ef_desc);
452 } else if (acount == 1) {
454 Sprintf(prompt, "%s or %s", choices[i - 1]->ef_txt,
456 Sprintf(prompt, "%s
\82Ü
\82½
\82Í %s", choices[i-1]->ef_txt,
460 Strcat(prompt, " or ");
462 Strcat(prompt,"
\82Ü
\82½
\82Í ");
463 Strcat(prompt, choices[i]->ef_txt);
469 Sprintf(buf, fmtstr, prompt);
470 any.a_char = prevaccelerator;
471 add_menu(win, NO_GLYPH, &any, any.a_char, 0, ATR_NONE, buf,
475 Sprintf(prompt, "Extended Command: %s", cbuf);
477 Sprintf(prompt, "
\8ag
\92£
\83R
\83}
\83\93\83h: %s", cbuf);
478 end_menu(win, prompt);
479 n = select_menu(win, PICK_ONE, &pick_list);
480 destroy_nhwindow(win);
482 if (matchlevel > (QBUFSZ - 2)) {
483 free((genericptr_t) pick_list);
485 impossible("Too many chars (%d) entered in extcmd_via_menu()",
490 cbuf[matchlevel++] = pick_list[0].item.a_char;
491 cbuf[matchlevel] = '\0';
492 free((genericptr_t) pick_list);
504 #endif /* TTY_GRAPHICS */
506 /* #monster command - use special monster ability while polymorphed */
508 domonability(VOID_ARGS)
510 if (can_breathe(youmonst.data))
512 else if (attacktype(youmonst.data, AT_SPIT))
514 else if (youmonst.data->mlet == S_NYMPH)
516 else if (attacktype(youmonst.data, AT_GAZE))
518 else if (is_were(youmonst.data))
520 else if (webmaker(youmonst.data))
522 else if (is_hider(youmonst.data))
524 else if (is_mind_flayer(youmonst.data))
525 return domindblast();
526 else if (u.umonnum == PM_GREMLIN) {
527 if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
528 if (split_mon(&youmonst, (struct monst *) 0))
529 dryup(u.ux, u.uy, TRUE);
532 There("is no fountain here.");
534 pline("
\82±
\82±
\82É
\82Í
\90ò
\82Í
\82È
\82¢
\81D");
535 } else if (is_unicorn(youmonst.data)) {
536 use_unicorn_horn((struct obj *) 0);
538 } else if (youmonst.data->msound == MS_SHRIEK) {
542 You("
\8bà
\90Ø
\82è
\90º
\82ð
\82 \82°
\82½
\81D");
545 pline("Unfortunately sound does not carry well through rock.");
547 pline("
\8ec
\94O
\82È
\82ª
\82ç
\89¹
\82Í
\8aâ
\82ð
\82¤
\82Ü
\82
\93`
\82í
\82ç
\82È
\82¢
\81D");
550 } else if (youmonst.data->mlet == S_VAMPIRE)
554 pline("Any special ability you may have is purely reflexive.");
556 pline("
\82 \82È
\82½
\82Ì
\8e\9d\82Á
\82Ä
\82¢
\82é
\93Á
\8eê
\94\
\97Í
\82Í
\82Ç
\82ê
\82à
\8eó
\93®
\93I
\82¾
\81D");
559 You("don't have a special ability in your normal form!");
561 You("
\95\81\92i
\82Ì
\8ep
\82Å
\82Ì
\93Á
\8eê
\94\
\97Í
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81I");
566 enter_explore_mode(VOID_ARGS)
570 You("are in debug mode.");
572 You("
\82·
\82Å
\82É
\83f
\83o
\83b
\83O
\83\82\81[
\83h
\82¾
\81D");
573 } else if (discover) {
575 You("are already in explore mode.");
577 You("
\82·
\82Å
\82É
\92T
\8c\9f\83\82\81[
\83h
\82¾
\81D");
581 if (!sysopt.explorers || !sysopt.explorers[0]
582 || !check_user_string(sysopt.explorers)) {
584 You("cannot access explore mode.");
586 You("
\92T
\8c\9f\83\82\81[
\83h
\82É
\83A
\83N
\83Z
\83X
\82Å
\82«
\82È
\82¢
\81D");
593 "Beware! From explore mode there will be no return to normal game.");
595 "
\8cx
\8d\90\81I
\94
\8c©
\83\82\81[
\83h
\82É
\93ü
\82Á
\82½
\82ç
\92Ê
\8fí
\83\82\81[
\83h
\82É
\82Í
\96ß
\82ê
\82È
\82¢
\81D");
596 if (paranoid_query(ParanoidQuit,
598 "Do you want to enter explore mode?")) {
600 "
\94
\8c©
\83\82\81[
\83h
\82É
\88Ú
\82è
\82Ü
\82·
\82©
\81H")) {
601 clear_nhwindow(WIN_MESSAGE);
603 You("are now in non-scoring explore mode.");
605 You("
\83X
\83R
\83A
\82ª
\82Ì
\82ç
\82È
\82¢
\94
\8c©
\83\82\81[
\83h
\82É
\88Ú
\8ds
\82µ
\82½
\81D");
608 clear_nhwindow(WIN_MESSAGE);
610 pline("Resuming normal game.");
612 pline("
\92Ê
\8fí
\83\82\81[
\83h
\82ð
\91±
\82¯
\82é
\81D");
619 dooverview_or_wiz_where(VOID_ARGS)
628 /* ^W command - wish for something */
630 wiz_wish(VOID_ARGS) /* Unlimited wishes for debug mode by Paul Polderman */
633 boolean save_verbose = flags.verbose;
635 flags.verbose = FALSE;
637 flags.verbose = save_verbose;
638 (void) encumber_msg();
641 pline("Unavailable command '%s'.",
643 pline("'%s'
\83R
\83}
\83\93\83h
\82Í
\8eg
\82¦
\82È
\82¢
\81D",
644 visctrl((int) cmd_from_func(wiz_wish)));
648 /* ^I command - reveal and optionally identify hero's inventory */
650 wiz_identify(VOID_ARGS)
653 iflags.override_ID = (int) cmd_from_func(wiz_identify);
654 if (display_inventory((char *) 0, TRUE) == -1)
655 identify_pack(0, FALSE);
656 iflags.override_ID = 0;
659 pline("Unavailable command '%s'.",
661 pline("'%s'
\83R
\83}
\83\93\83h
\82Í
\8eg
\82¦
\82È
\82¢
\81D",
662 visctrl((int) cmd_from_func(wiz_identify)));
666 /* ^F command - reveal the level map and any traps on it */
672 long save_Hconf = HConfusion, save_Hhallu = HHallucination;
674 HConfusion = HHallucination = 0L;
675 for (t = ftrap; t != 0; t = t->ntrap) {
680 HConfusion = save_Hconf;
681 HHallucination = save_Hhallu;
684 pline("Unavailable command '%s'.",
686 pline("'%s'
\83R
\83}
\83\93\83h
\82Í
\8eg
\82¦
\82È
\82¢
\81D",
687 visctrl((int) cmd_from_func(wiz_map)));
691 /* ^G command - generate monster(s); a count prefix will be honored */
693 wiz_genesis(VOID_ARGS)
696 (void) create_particular();
699 pline("Unavailable command '%s'.",
701 pline("'%s'
\83R
\83}
\83\93\83h
\82Í
\8eg
\82¦
\82È
\82¢
\81D",
702 visctrl((int) cmd_from_func(wiz_genesis)));
706 /* ^O command - display dungeon layout */
711 (void) print_dungeon(FALSE, (schar *) 0, (xchar *) 0);
714 pline("Unavailable command '%s'.",
716 pline("'%s'
\83R
\83}
\83\93\83h
\82Í
\8eg
\82¦
\82È
\82¢
\81D",
717 visctrl((int) cmd_from_func(wiz_where)));
721 /* ^E command - detect unseen (secret doors, traps, hidden monsters) */
723 wiz_detect(VOID_ARGS)
729 pline("Unavailable command '%s'.",
731 pline("'%s'
\83R
\83}
\83\93\83h
\82Í
\8eg
\82¦
\82È
\82¢
\81D",
732 visctrl((int) cmd_from_func(wiz_detect)));
736 /* ^V command - level teleport */
738 wiz_level_tele(VOID_ARGS)
744 pline("Unavailable command '%s'.",
746 pline("'%s'
\83R
\83}
\83\93\83h
\82Í
\8eg
\82¦
\82È
\82¢
\81D",
747 visctrl((int) cmd_from_func(wiz_level_tele)));
751 /* #monpolycontrol command - choose new form for shapechangers, polymorphees */
753 wiz_mon_polycontrol(VOID_ARGS)
755 iflags.mon_polycontrol = !iflags.mon_polycontrol;
757 pline("Monster polymorph control is %s.",
758 iflags.mon_polycontrol ? "on" : "off");
760 pline("
\89ö
\95¨
\82Ì
\95Ï
\89»
\90§
\8cä: %s",
761 iflags.mon_polycontrol ? "
\83I
\83\93" : "
\83I
\83t");
766 /* #levelchange command - adjust hero's experience level */
768 wiz_level_change(VOID_ARGS)
775 getlin("To what experience level do you want to be set?", buf);
777 getlin("
\8co
\8c±
\83\8c\83x
\83\8b\82ð
\82¢
\82
\82Â
\82É
\90Ý
\92è
\82µ
\82Ü
\82·
\82©
\81H", buf);
778 (void) mungspaces(buf);
779 if (buf[0] == '\033' || buf[0] == '\0')
782 ret = sscanf(buf, "%d", &newlevel);
788 if (newlevel == u.ulevel) {
790 You("are already that experienced.");
792 You("
\82·
\82Å
\82É
\82»
\82Ì
\8co
\8c±
\83\8c\83x
\83\8b\82¾
\81D");
793 } else if (newlevel < u.ulevel) {
796 You("are already as inexperienced as you can get.");
798 You("
\82·
\82Å
\82É
\89Â
\94\
\82È
\8cÀ
\82è
\82Ì
\8dÅ
\92á
\82Ì
\8co
\8c±
\83\8c\83x
\83\8b\82¾
\81D");
803 while (u.ulevel > newlevel)
805 losexp("#levelchange");
807 losexp("#levelchange
\83R
\83}
\83\93\83h
\82Å");
809 if (u.ulevel >= MAXULEV) {
811 You("are already as experienced as you can get.");
813 You("
\82·
\82Å
\82É
\89Â
\94\
\82È
\8cÀ
\82è
\82Ì
\8dÅ
\91å
\82Ì
\8co
\8c±
\83\8c\83x
\83\8b\82¾
\81D");
816 if (newlevel > MAXULEV)
818 while (u.ulevel < newlevel)
821 u.ulevelmax = u.ulevel;
825 /* #panic command - test program's panic handling */
830 if (yn("Do you want to call panic() and end your game?") == 'y')
832 if (yn("panic()
\8aÖ
\90\94\82ð
\8cÄ
\82Ñ
\8fo
\82µ
\82Ä
\83Q
\81[
\83\80\82ð
\8fI
\97¹
\82³
\82¹
\82Ü
\82·
\82©
\81H") == 'y')
833 panic("Crash test.");
837 /* #polyself command - change hero's form */
839 wiz_polyself(VOID_ARGS)
847 wiz_show_seenv(VOID_ARGS)
850 int x, y, v, startx, stopx, curx;
853 win = create_nhwindow(NHW_TEXT);
855 * Each seenv description takes up 2 characters, so center
856 * the seenv display around the hero.
858 startx = max(1, u.ux - (COLNO / 4));
859 stopx = min(startx + (COLNO / 2), COLNO);
860 /* can't have a line exactly 80 chars long */
861 if (stopx - startx == COLNO / 2)
864 for (y = 0; y < ROWNO; y++) {
865 for (x = startx, curx = 0; x < stopx; x++, curx += 2) {
866 if (x == u.ux && y == u.uy) {
867 row[curx] = row[curx + 1] = '@';
869 v = levl[x][y].seenv & 0xff;
871 row[curx] = row[curx + 1] = ' ';
873 Sprintf(&row[curx], "%02x", v);
876 /* remove trailing spaces */
877 for (x = curx - 1; x >= 0; x--)
884 display_nhwindow(win, TRUE);
885 destroy_nhwindow(win);
889 /* #vision command */
891 wiz_show_vision(VOID_ARGS)
897 win = create_nhwindow(NHW_TEXT);
898 Sprintf(row, "Flags: 0x%x could see, 0x%x in sight, 0x%x temp lit",
899 COULD_SEE, IN_SIGHT, TEMP_LIT);
902 for (y = 0; y < ROWNO; y++) {
903 for (x = 1; x < COLNO; x++) {
904 if (x == u.ux && y == u.uy)
907 v = viz_array[y][x]; /* data access should be hidden */
911 row[x] = '0' + viz_array[y][x];
914 /* remove trailing spaces */
915 for (x = COLNO - 1; x >= 1; x--)
920 putstr(win, 0, &row[1]);
922 display_nhwindow(win, TRUE);
923 destroy_nhwindow(win);
929 wiz_show_wmodes(VOID_ARGS)
935 boolean istty = !strcmp(windowprocs.name, "tty");
937 win = create_nhwindow(NHW_TEXT);
939 putstr(win, 0, ""); /* tty only: blank top line */
940 for (y = 0; y < ROWNO; y++) {
941 for (x = 0; x < COLNO; x++) {
943 if (x == u.ux && y == u.uy)
945 else if (IS_WALL(lev->typ) || lev->typ == SDOOR)
946 row[x] = '0' + (lev->wall_info & WM_MASK);
947 else if (lev->typ == CORR)
949 else if (IS_ROOM(lev->typ) || IS_DOOR(lev->typ))
955 /* map column 0, levl[0][], is off the left edge of the screen */
956 putstr(win, 0, &row[1]);
958 display_nhwindow(win, TRUE);
959 destroy_nhwindow(win);
963 /* wizard mode variant of #terrain; internal levl[][].typ values in base-36 */
965 wiz_map_levltyp(VOID_ARGS)
970 boolean istty = !strcmp(windowprocs.name, "tty");
972 win = create_nhwindow(NHW_TEXT);
973 /* map row 0, levl[][0], is drawn on the second line of tty screen */
975 putstr(win, 0, ""); /* tty only: blank top line */
976 for (y = 0; y < ROWNO; y++) {
977 /* map column 0, levl[0][], is off the left edge of the screen;
978 it should always have terrain type "undiggable stone" */
979 for (x = 1; x < COLNO; x++) {
980 terrain = levl[x][y].typ;
981 /* assumes there aren't more than 10+26+26 terrain types */
982 row[x - 1] = (char) ((terrain == 0 && !may_dig(x, y))
988 : 'A' + terrain - 36);
990 if (levl[0][y].typ != 0 || may_dig(0, y))
998 s_level *slev = Is_special(&u.uz);
1000 Sprintf(dsc, "D:%d,L:%d", u.uz.dnum, u.uz.dlevel);
1001 /* [dungeon branch features currently omitted] */
1002 /* special level features */
1004 Sprintf(eos(dsc), " \"%s\"", slev->proto);
1005 /* special level flags (note: dungeon.def doesn't set `maze'
1006 or `hell' for any specific levels so those never show up) */
1007 if (slev->flags.maze_like)
1008 Strcat(dsc, " mazelike");
1009 if (slev->flags.hellish)
1010 Strcat(dsc, " hellish");
1011 if (slev->flags.town)
1012 Strcat(dsc, " town");
1013 if (slev->flags.rogue_like)
1014 Strcat(dsc, " roguelike");
1015 /* alignment currently omitted to save space */
1017 /* level features */
1018 if (level.flags.nfountains)
1019 Sprintf(eos(dsc), " %c:%d", defsyms[S_fountain].sym,
1020 (int) level.flags.nfountains);
1021 if (level.flags.nsinks)
1022 Sprintf(eos(dsc), " %c:%d", defsyms[S_sink].sym,
1023 (int) level.flags.nsinks);
1024 if (level.flags.has_vault)
1025 Strcat(dsc, " vault");
1026 if (level.flags.has_shop)
1027 Strcat(dsc, " shop");
1028 if (level.flags.has_temple)
1029 Strcat(dsc, " temple");
1030 if (level.flags.has_court)
1031 Strcat(dsc, " throne");
1032 if (level.flags.has_zoo)
1033 Strcat(dsc, " zoo");
1034 if (level.flags.has_morgue)
1035 Strcat(dsc, " morgue");
1036 if (level.flags.has_barracks)
1037 Strcat(dsc, " barracks");
1038 if (level.flags.has_beehive)
1039 Strcat(dsc, " hive");
1040 if (level.flags.has_swamp)
1041 Strcat(dsc, " swamp");
1043 if (level.flags.noteleport)
1044 Strcat(dsc, " noTport");
1045 if (level.flags.hardfloor)
1046 Strcat(dsc, " noDig");
1047 if (level.flags.nommap)
1048 Strcat(dsc, " noMMap");
1049 if (!level.flags.hero_memory)
1050 Strcat(dsc, " noMem");
1051 if (level.flags.shortsighted)
1052 Strcat(dsc, " shortsight");
1053 if (level.flags.graveyard)
1054 Strcat(dsc, " graveyard");
1055 if (level.flags.is_maze_lev)
1056 Strcat(dsc, " maze");
1057 if (level.flags.is_cavernous_lev)
1058 Strcat(dsc, " cave");
1059 if (level.flags.arboreal)
1060 Strcat(dsc, " tree");
1062 Strcat(dsc, " sokoban-rules");
1063 /* non-flag info; probably should include dungeon branching
1064 checks (extra stairs and magic portals) here */
1065 if (Invocation_lev(&u.uz))
1066 Strcat(dsc, " invoke");
1067 if (On_W_tower_level(&u.uz))
1068 Strcat(dsc, " tower");
1069 /* append a branch identifier for completeness' sake */
1071 Strcat(dsc, " dungeon");
1072 else if (u.uz.dnum == mines_dnum)
1073 Strcat(dsc, " mines");
1074 else if (In_sokoban(&u.uz))
1075 Strcat(dsc, " sokoban");
1076 else if (u.uz.dnum == quest_dnum)
1077 Strcat(dsc, " quest");
1078 else if (Is_knox(&u.uz))
1079 Strcat(dsc, " ludios");
1080 else if (u.uz.dnum == 1)
1081 Strcat(dsc, " gehennom");
1082 else if (u.uz.dnum == tower_dnum)
1083 Strcat(dsc, " vlad");
1084 else if (In_endgame(&u.uz))
1085 Strcat(dsc, " endgame");
1087 /* somebody's added a dungeon branch we're not expecting */
1088 const char *brname = dungeons[u.uz.dnum].dname;
1090 if (!brname || !*brname)
1092 if (!strncmpi(brname, "the ", 4))
1094 Sprintf(eos(dsc), " %s", brname);
1096 /* limit the line length to map width */
1097 if (strlen(dsc) >= COLNO)
1098 dsc[COLNO - 1] = '\0'; /* truncate */
1099 putstr(win, 0, dsc);
1102 display_nhwindow(win, TRUE);
1103 destroy_nhwindow(win);
1107 /* temporary? hack, since level type codes aren't the same as screen
1108 symbols and only the latter have easily accessible descriptions */
1109 static const char *levltyp[] = {
1110 "stone", "vertical wall", "horizontal wall", "top-left corner wall",
1111 "top-right corner wall", "bottom-left corner wall",
1112 "bottom-right corner wall", "cross wall", "tee-up wall", "tee-down wall",
1113 "tee-left wall", "tee-right wall", "drawbridge wall", "tree",
1114 "secret door", "secret corridor", "pool", "moat", "water",
1115 "drawbridge up", "lava pool", "iron bars", "door", "corridor", "room",
1116 "stairs", "ladder", "fountain", "throne", "sink", "grave", "altar", "ice",
1117 "drawbridge down", "air", "cloud",
1118 /* not a real terrain type, but used for undiggable stone
1119 by wiz_map_levltyp() */
1120 "unreachable/undiggable",
1121 /* padding in case the number of entries above is odd */
1125 /* explanation of base-36 output from wiz_map_levltyp() */
1127 wiz_levltyp_legend(VOID_ARGS)
1131 const char *dsc, *fmt;
1134 win = create_nhwindow(NHW_TEXT);
1135 putstr(win, 0, "#terrain encodings:");
1137 fmt = " %c - %-28s"; /* TODO: include tab-separated variant for win32 */
1139 /* output in pairs, left hand column holds [0],[1],...,[N/2-1]
1140 and right hand column holds [N/2],[N/2+1],...,[N-1];
1141 N ('last') will always be even, and may or may not include
1142 the empty string entry to pad out the final pair, depending
1143 upon how many other entries are present in levltyp[] */
1144 last = SIZE(levltyp) & ~1;
1145 for (i = 0; i < last / 2; ++i)
1146 for (j = i; j < last; j += last / 2) {
1149 : !strncmp(dsc, "unreachable", 11) ? '*'
1150 /* same int-to-char conversion as wiz_map_levltyp() */
1151 : (j < 10) ? '0' + j
1152 : (j < 36) ? 'a' + j - 10
1154 Sprintf(eos(buf), fmt, c, dsc);
1156 putstr(win, 0, buf);
1160 display_nhwindow(win, TRUE);
1161 destroy_nhwindow(win);
1165 /* #wizsmell command - test usmellmon(). */
1167 wiz_smell(VOID_ARGS)
1170 int mndx; /* monster index */
1171 coord cc; /* screen pos of unknown glyph */
1172 int glyph; /* glyph at selected position */
1176 mndx = 0; /* gcc -Wall lint */
1177 if (!olfaction(youmonst.data)) {
1178 You("are incapable of detecting odors in your present form.");
1182 pline("You can move the cursor to a monster that you want to smell.");
1184 pline("Pick a monster to smell.");
1185 ans = getpos(&cc, TRUE, "a monster");
1186 if (ans < 0 || cc.x < 0) {
1187 return 0; /* done */
1189 /* Convert the glyph at the selected position to a mndxbol. */
1190 glyph = glyph_at(cc.x, cc.y);
1191 if (glyph_is_monster(glyph))
1192 mndx = glyph_to_mon(glyph);
1195 /* Is it a monster? */
1197 if (!usmellmon(&mons[mndx]))
1198 pline("That monster seems to give off no smell.");
1200 pline("That is not a monster.");
1205 /* #wizrumorcheck command - verify each rumor access */
1207 wiz_rumor_check(VOID_ARGS)
1213 /* #terrain command -- show known map, inspired by crawl's '|' command */
1215 doterrain(VOID_ARGS)
1224 * normal play: choose between known map without mons, obj, and traps
1225 * (to see underlying terrain only), or
1226 * known map without mons and objs (to see traps under mons and objs), or
1227 * known map without mons (to see objects under monsters);
1228 * explore mode: normal choices plus full map (w/o mons, objs, traps);
1229 * wizard mode: normal and explore choices plus
1230 * a dump of the internal levl[][].typ codes w/ level flags, or
1231 * a legend for the levl[][].typ codes dump
1233 men = create_nhwindow(NHW_MENU);
1236 add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1237 "known map without monsters, objects, and traps",
1240 add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1241 "known map without monsters and objects",
1244 add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1245 "known map without monsters",
1247 if (discover || wizard) {
1249 add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1250 "full map without monsters, objects, and traps",
1254 add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1255 "internal levl[][].typ codes in base-36",
1258 add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1259 "legend of base-36 levl[][].typ codes",
1263 end_menu(men, "View which?");
1265 n = select_menu(men, PICK_ONE, &sel);
1266 destroy_nhwindow(men);
1268 * n < 0: player used ESC to cancel;
1269 * n == 0: preselected entry was explicitly chosen and got toggled off;
1270 * n == 1: preselected entry was implicitly chosen via <space>|<enter>;
1271 * n == 2: another entry was explicitly chosen, so skip preselected one.
1273 which = (n < 0) ? -1 : (n == 0) ? 1 : sel[0].item.a_int;
1274 if (n > 1 && which == 1)
1275 which = sel[1].item.a_int;
1277 free((genericptr_t) sel);
1280 case 1: reveal_terrain(0, 0); break; /* known map */
1281 case 2: reveal_terrain(0, 1); break; /* known map with traps */
1282 case 3: reveal_terrain(0, 1|2); break; /* known map w/ traps & objs */
1283 case 4: reveal_terrain(1, 0); break; /* full map */
1284 case 5: wiz_map_levltyp(); break; /* map internals */
1285 case 6: wiz_levltyp_legend(); break; /* internal details */
1288 return 0; /* no time elapses */
1291 /* -enlightenment and conduct- */
1292 static winid en_win = WIN_ERR;
1294 static const char You_[] = "You ", are[] = "are ", were[] = "were ",
1295 have[] = "have ", had[] = "had ", can[] = "can ",
1298 static const char You_[] = "
\82 \82È
\82½
\82Í",
1299 are[] = "
\82Å
\82 \82é", were[] = "
\82Å
\82 \82Á
\82½",
1300 have[] = "
\82ð
\82à
\82Á
\82Ä
\82¢
\82é", had[] = "
\82ð
\82à
\82Á
\82Ä
\82¢
\82½",
1301 can[] = "
\82Å
\82«
\82é", could[] = "
\82Å
\82«
\82½",
1302 iru[] = "
\82¢
\82é", ita[] = "
\82¢
\82½";
1304 #if 0 /*JP*//* not used */
1305 static const char have_been[] = "have been ", have_never[] = "have never ",
1310 #define enl_msg(prefix, present, past, suffix, ps) \
1311 enlght_line(prefix, final ? past : present, suffix, ps)
1313 #define enl_msg(prefix, present, past, suffix, ps) \
1314 enlght_line(prefix, suffix, final ? past : present, ps)
1316 #define you_are(attr, ps) enl_msg(You_, are, were, attr, ps)
1317 #define you_have(attr, ps) enl_msg(You_, have, had, attr, ps)
1318 #define you_can(attr, ps) enl_msg(You_, can, could, attr, ps)
1320 #define you_have_been(goodthing) enl_msg(You_, have_been, were, goodthing, "")
1322 #define you_have_been(goodthing) enl_msg(You_, are, were, goodthing, "")
1324 #define you_have_never(badthing) \
1325 enl_msg(You_, have_never, never, badthing, "")
1327 #define you_have_never(badthing) \
1328 enl_msg(badthing, "
\82Ä
\82¢
\82È
\82¢", "
\82È
\82©
\82Á
\82½", "", "")
1331 #define you_have_X(something) \
1332 enl_msg(You_, have, (const char *) "", something, "")
1334 #define you_have_X(something) \
1335 enl_msg(something, "
\82Ä
\82¢
\82é", "
\82½", "", "")
1338 #define you_are_ing(goodthing) enl_msg(You_, iru, ita, goodthing, "")
1342 enlght_line(start, middle, end, ps)
1343 const char *start, *middle, *end, *ps;
1348 Sprintf(buf, " %s%s%s%s.", start, middle, end, ps);
1350 Sprintf(buf, "%s%s%s%s
\81D", start, middle, end, ps);
1351 putstr(en_win, 0, buf);
1354 /* format increased chance to hit or damage or defense (Protection) */
1356 enlght_combatinc(inctyp, incamt, final, outbuf)
1361 const char *modif, *bonus;
1365 absamt = abs(incamt);
1366 /* Protection amount is typically larger than damage or to-hit;
1367 reduce magnitude by a third in order to stretch modifier ranges
1368 (small:1..5, moderate:6..10, large:11..19, huge:20+) */
1369 if (!strcmp(inctyp, "defense"))
1370 absamt = (absamt * 2) / 3;
1376 modif = "
\8bÍ
\82©
\82È";
1377 else if (absamt <= 6)
1381 modif = "
\92\86\92ö
\93x
\82Ì";
1382 else if (absamt <= 12)
1386 modif = "
\91å
\82«
\82È";
1391 modif = "
\8b
\91å
\82È";
1394 modif = !incamt ? "no" : an(modif); /* ("no" case shouldn't happen) */
1397 bonus = (incamt >= 0) ? "bonus" : "penalty";
1399 bonus = (incamt > 0) ? "
\83{
\81[
\83i
\83X" : "
\83y
\83i
\83\8b\83e
\83B";
1400 /* "bonus <foo>" (to hit) vs "<bar> bonus" (damage, defense) */
1401 invrt = strcmp(inctyp, "to hit") ? TRUE : FALSE;
1404 Sprintf(outbuf, "%s %s %s", modif, invrt ? inctyp : bonus,
1405 invrt ? bonus : inctyp);
1407 Sprintf(outbuf, "%s
\82É%s%s", inctyp, modif, bonus);
1409 if (final || wizard)
1410 Sprintf(eos(outbuf), " (%s%d)", (incamt > 0) ? "+" : "", incamt);
1415 /* report half physical or half spell damage */
1417 enlght_halfdmg(category, final)
1421 const char *category_name;
1426 category_name = "physical";
1429 category_name = "spell";
1432 category_name = "unknown";
1435 Sprintf(buf, " %s %s damage", (final || wizard) ? "half" : "reduced",
1437 enl_msg(You_, "take", "took", buf, from_what(category));
1440 /* is hero actively using water walking capability on water (or lava)? */
1444 if (u.uinwater || Levitation || Flying)
1446 return (boolean) (Wwalking
1447 && (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)));
1450 /* check whether hero is wearing something that player definitely knows
1451 confers the target property; item must have been seen and its type
1452 discovered but it doesn't necessarily have to be fully identified */
1454 cause_known(propindx)
1455 int propindx; /* index of a property which can be conveyed by worn item */
1457 register struct obj *o;
1458 long mask = W_ARMOR | W_AMUL | W_RING | W_TOOL;
1460 /* simpler than from_what()/what_gives(); we don't attempt to
1461 handle artifacts and we deliberately ignore wielded items */
1462 for (o = invent; o; o = o->nobj) {
1463 if (!(o->owornmask & mask))
1465 if ((int) objects[o->otyp].oc_oprop == propindx
1466 && objects[o->otyp].oc_name_known && o->dknown)
1472 /* format a characteristic value, accommodating Strength's strangeness */
1474 attrval(attrindx, attrvalue, resultbuf)
1475 int attrindx, attrvalue;
1476 char resultbuf[]; /* should be at least [7] to hold "18/100\0" */
1478 if (attrindx != A_STR || attrvalue <= 18)
1479 Sprintf(resultbuf, "%d", attrvalue);
1480 else if (attrvalue > STR18(100)) /* 19 to 25 */
1481 Sprintf(resultbuf, "%d", attrvalue - 100);
1482 else /* simplify "18/ **" to be "18/100" */
1483 Sprintf(resultbuf, "18/%02d", attrvalue - 18);
1488 enlightenment(mode, final)
1489 int mode; /* BASICENLIGHTENMENT | MAGICENLIGHTENMENT (| both) */
1490 int final; /* ENL_GAMEINPROGRESS:0, ENL_GAMEOVERALIVE, ENL_GAMEOVERDEAD */
1492 char buf[BUFSZ], tmpbuf[BUFSZ];
1494 Strcpy(tmpbuf, plname);
1495 *tmpbuf = highc(*tmpbuf); /* same adjustment as bottom line */
1496 /* as in background_enlightenment, when poly'd we need to use the saved
1497 gender in u.mfemale rather than the current you-as-monster gender */
1499 Sprintf(buf, "%s the %s's attributes:", tmpbuf,
1500 ((Upolyd ? u.mfemale : flags.female) && urole.name.f)
1504 Sprintf(buf, "%s
\82Ì%s
\82Ì
\91®
\90«:",
1505 ((Upolyd ? u.mfemale : flags.female) && urole.name.f)
1511 en_win = create_nhwindow(NHW_MENU);
1513 putstr(en_win, 0, buf); /* "Conan the Archeologist's attributes:" */
1514 /* background and characteristics; ^X or end-of-game disclosure */
1515 if (mode & BASICENLIGHTENMENT) {
1516 /* role, race, alignment, deities */
1517 background_enlightenment(mode, final);
1518 /* strength, dexterity, &c */
1519 characteristics_enlightenment(mode, final);
1521 /* expanded status line information, including things which aren't
1522 included there due to space considerations--such as obvious
1523 alternative movement indicators (riding, levitation, &c), and
1524 various troubles (turning to stone, trapped, confusion, &c);
1525 shown for both basic and magic enlightenment */
1526 status_enlightenment(mode, final);
1527 /* remaining attributes; shown for potion,&c or wizard mode and
1528 explore mode ^X or end of game disclosure */
1529 if (mode & MAGICENLIGHTENMENT) {
1530 /* intrinsics and other traditional enlightenment feedback */
1531 attributes_enlightenment(mode, final);
1533 display_nhwindow(en_win, TRUE);
1534 destroy_nhwindow(en_win);
1539 /* display role, race, alignment and such to en_win */
1541 background_enlightenment(unused_mode, final)
1542 int unused_mode UNUSED;
1545 const char *role_titl, *rank_titl;
1546 int innategend, difgend, difalgn;
1547 char buf[BUFSZ], tmpbuf[BUFSZ];
1549 /* note that if poly'd, we need to use u.mfemale instead of flags.female
1550 to access hero's saved gender-as-human/elf/&c rather than current one */
1551 innategend = (Upolyd ? u.mfemale : flags.female) ? 1 : 0;
1552 role_titl = (innategend && urole.name.f) ? urole.name.f : urole.name.m;
1553 rank_titl = rank_of(u.ulevel, Role_switch, innategend);
1555 putstr(en_win, 0, ""); /* separator after title */
1557 putstr(en_win, 0, "Background:");
1559 putstr(en_win, 0, "
\94w
\8ci
\8fî
\95ñ:");
1561 /* if polymorphed, report current shape before underlying role;
1562 will be repeated as first status: "you are transformed" and also
1563 among various attributes: "you are in beast form" (after being
1564 told about lycanthropy) or "you are polymorphed into <a foo>"
1565 (with countdown timer appended for wizard mode); we really want
1566 the player to know he's not a samurai at the moment... */
1568 struct permonst *uasmon = youmonst.data;
1571 /* here we always use current gender, not saved role gender */
1572 if (!is_male(uasmon) && !is_female(uasmon) && !is_neuter(uasmon))
1574 Sprintf(tmpbuf, "%s ", genders[flags.female ? 1 : 0].adj);
1576 Sprintf(tmpbuf, "%s", genders[flags.female ? 1 : 0].adj);
1577 Sprintf(buf, "%sin %s%s form", !final ? "currently " : "", tmpbuf,
1582 /* report role; omit gender if it's redundant (eg, "female priestess") */
1585 && ((urole.allow & ROLE_GENDMASK) == (ROLE_MALE | ROLE_FEMALE)
1586 || innategend != flags.initgend))
1588 Sprintf(tmpbuf, "%s ", genders[innategend].adj);
1590 Sprintf(tmpbuf, "%s", genders[innategend].adj);
1593 Strcpy(buf, "actually "); /* "You are actually a ..." */
1594 if (!strcmpi(rank_titl, role_titl)) {
1595 /* omit role when rank title matches it */
1597 Sprintf(eos(buf), "%s, level %d %s%s", an(rank_titl), u.ulevel,
1598 tmpbuf, urace.noun);
1600 Sprintf(eos(buf), "
\83\8c\83x
\83\8b%d
\82Ì%s
\82Ì%s%s", u.ulevel,
1601 tmpbuf, urace.adj, role_titl);
1605 Sprintf(eos(buf), "%s, a level %d %s%s %s", an(rank_titl), u.ulevel,
1606 tmpbuf, urace.adj, role_titl);
1608 Sprintf(eos(buf), "
\83\8c\83x
\83\8b%d
\82Ì%s
\82Ì%s%s
\82Ì%s", u.ulevel,
1609 tmpbuf, urace.adj, role_titl, rank_titl);
1614 /* report alignment (bypass you_are() in order to omit ending period) */
1616 Sprintf(buf, " %s%s%s, %son a mission for %s",
1617 You_, !final ? are : were,
1618 align_str(u.ualign.type),
1619 /* helm of opposite alignment (might hide conversion) */
1620 (u.ualign.type != u.ualignbase[A_CURRENT]) ? "temporarily "
1621 /* permanent conversion */
1622 : (u.ualign.type != u.ualignbase[A_ORIGINAL]) ? "now "
1623 /* atheist (ignored in very early game) */
1624 : (!u.uconduct.gnostic && moves > 1000L) ? "nominally "
1625 /* lastly, normal case */
1629 Sprintf(buf, "
\82 \82È
\82½
\82Í%s
\82Å, %s%s
\82Ì
\82½
\82ß
\82Ì
\94C
\96±
\82ð
\8ds
\82Á
\82Ä%s",
1630 align_str(u.ualign.type),
1631 /* helm of opposite alignment (might hide conversion) */
1632 (u.ualign.type != u.ualignbase[A_CURRENT]) ? "
\88ê
\8e\9e\93I
\82É"
1633 /* permanent conversion */
1634 : (u.ualign.type != u.ualignbase[A_ORIGINAL]) ? "
\8c»
\8dÝ"
1635 /* atheist (ignored in very early game) */
1636 : (!u.uconduct.gnostic && moves > 1000L) ? "
\96¼
\8b`
\8fã"
1637 /* lastly, normal case */
1639 u_gname(), !final ? iru : ita);
1641 putstr(en_win, 0, buf);
1642 /* show the rest of this game's pantheon (finishes previous sentence)
1643 [appending "also Moloch" at the end would allow for straightforward
1644 trailing "and" on all three aligned entries but looks too verbose] */
1646 Sprintf(buf, " who %s opposed by", !final ? "is" : "was");
1648 Strcpy(buf, "
\82 \82È
\82½
\82Í");
1650 if (u.ualign.type != A_LAWFUL)
1652 Sprintf(eos(buf), " %s (%s) and", align_gname(A_LAWFUL),
1653 align_str(A_LAWFUL));
1655 Sprintf(eos(buf), "%s(%s)
\82¨
\82æ
\82Ñ", align_gname(A_LAWFUL),
1656 align_str(A_LAWFUL));
1658 if (u.ualign.type != A_NEUTRAL)
1660 Sprintf(eos(buf), " %s (%s)%s", align_gname(A_NEUTRAL),
1661 align_str(A_NEUTRAL),
1662 (u.ualign.type != A_CHAOTIC) ? " and" : "");
1664 Sprintf(eos(buf), "%s(%s)%s", align_gname(A_NEUTRAL),
1665 align_str(A_NEUTRAL),
1666 (u.ualign.type != A_CHAOTIC) ? "
\82¨
\82æ
\82Ñ" : "");
1669 if (u.ualign.type != A_CHAOTIC)
1670 Sprintf(eos(buf), " %s (%s)", align_gname(A_CHAOTIC),
1671 align_str(A_CHAOTIC));
1673 if (u.ualign.type != A_CHAOTIC)
1674 Sprintf(eos(buf), "%s(%s)", align_gname(A_CHAOTIC),
1675 align_str(A_CHAOTIC));
1678 Strcat(buf, "."); /* terminate sentence */
1680 Sprintf(eos(buf), "
\82Æ
\91Î
\97§
\82µ
\82Ä%s
\81D", !final ? iru : ita);
1682 putstr(en_win, 0, buf);
1684 /* show original alignment,gender,race,role if any have been changed;
1685 giving separate message for temporary alignment change bypasses need
1686 for tricky phrasing otherwise necessitated by possibility of having
1687 helm of opposite alignment mask a permanent alignment conversion */
1688 difgend = (innategend != flags.initgend);
1689 difalgn = (((u.ualign.type != u.ualignbase[A_CURRENT]) ? 1 : 0)
1690 + ((u.ualignbase[A_CURRENT] != u.ualignbase[A_ORIGINAL])
1692 if (difalgn & 1) { /* have temporary alignment so report permanent one */
1693 Sprintf(buf, "actually %s", align_str(u.ualignbase[A_CURRENT]));
1695 difalgn &= ~1; /* suppress helm from "started out <foo>" message */
1697 if (difgend || difalgn) { /* sex change or perm align change or both */
1698 Sprintf(buf, " You started out %s%s%s.",
1699 difgend ? genders[flags.initgend].adj : "",
1700 (difgend && difalgn) ? " and " : "",
1701 difalgn ? align_str(u.ualignbase[A_ORIGINAL]) : "");
1702 putstr(en_win, 0, buf);
1706 /* characteristics: expanded version of bottom line strength, dexterity, &c */
1708 characteristics_enlightenment(mode, final)
1712 putstr(en_win, 0, ""); /* separator after background */
1715 final ? "Final Characteristics:" : "Current Characteristics:");
1717 final ? "
\8dÅ
\8fI
\91®
\90«
\81F" : "
\8c»
\8dÝ
\82Ì
\91®
\90«
\81F");
1719 /* bottom line order */
1720 one_characteristic(mode, final, A_STR); /* strength */
1721 one_characteristic(mode, final, A_DEX); /* dexterity */
1722 one_characteristic(mode, final, A_CON); /* constitution */
1723 one_characteristic(mode, final, A_INT); /* intelligence */
1724 one_characteristic(mode, final, A_WIS); /* wisdom */
1725 one_characteristic(mode, final, A_CHA); /* charisma */
1728 /* display one attribute value for characteristics_enlightenment() */
1730 one_characteristic(mode, final, attrindx)
1731 int mode, final, attrindx;
1733 boolean hide_innate_value = FALSE, interesting_alimit;
1734 int acurrent, abase, apeak, alimit;
1735 const char *attrname, *paren_pfx;
1736 char subjbuf[BUFSZ], valubuf[BUFSZ], valstring[32];
1738 /* being polymorphed or wearing certain cursed items prevents
1739 hero from reliably tracking changes to characteristics so
1740 we don't show base & peak values then; when the items aren't
1741 cursed, hero could take them off to check underlying values
1742 and we show those in such case so that player doesn't need
1743 to actually resort to doing that */
1745 hide_innate_value = TRUE;
1746 } else if (Fixed_abil) {
1747 if (stuck_ring(uleft, RIN_SUSTAIN_ABILITY)
1748 || stuck_ring(uright, RIN_SUSTAIN_ABILITY))
1749 hide_innate_value = TRUE;
1753 attrname = "strength";
1754 if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER && uarmg->cursed)
1755 hide_innate_value = TRUE;
1758 attrname = "dexterity";
1761 attrname = "constitution";
1764 attrname = "intelligence";
1765 if (uarmh && uarmh->otyp == DUNCE_CAP && uarmh->cursed)
1766 hide_innate_value = TRUE;
1769 attrname = "wisdom";
1770 if (uarmh && uarmh->otyp == DUNCE_CAP && uarmh->cursed)
1771 hide_innate_value = TRUE;
1774 attrname = "charisma";
1777 return; /* impossible */
1779 /* note: final disclosure includes MAGICENLIGHTENTMENT */
1780 if ((mode & MAGICENLIGHTENMENT) && !Upolyd)
1781 hide_innate_value = FALSE;
1783 acurrent = ACURR(attrindx);
1784 (void) attrval(attrindx, acurrent, valubuf); /* Sprintf(valubuf,"%d",) */
1785 Sprintf(subjbuf, "Your %s ", attrname);
1787 if (!hide_innate_value) {
1788 /* show abase, amax, and/or attrmax if acurr doesn't match abase
1789 (a magic bonus or penalty is in effect) or abase doesn't match
1790 amax (some points have been lost to poison or exercise abuse
1791 and are restorable) or attrmax is different from normal human
1792 (while game is in progress; trying to reduce dependency on
1793 spoilers to keep track of such stuff) or attrmax was different
1794 from abase (at end of game; this attribute wasn't maxed out) */
1795 abase = ABASE(attrindx);
1796 apeak = AMAX(attrindx);
1797 alimit = ATTRMAX(attrindx);
1798 /* criterium for whether the limit is interesting varies */
1799 interesting_alimit =
1800 final ? TRUE /* was originally `(abase != alimit)' */
1801 : (alimit != (attrindx != A_STR ? 18 : STR18(100)));
1802 paren_pfx = final ? " (" : " (current; ";
1803 if (acurrent != abase) {
1804 Sprintf(eos(valubuf), "%sbase:%s", paren_pfx,
1805 attrval(attrindx, abase, valstring));
1808 if (abase != apeak) {
1809 Sprintf(eos(valubuf), "%speak:%s", paren_pfx,
1810 attrval(attrindx, apeak, valstring));
1813 if (interesting_alimit) {
1814 Sprintf(eos(valubuf), "%s%slimit:%s", paren_pfx,
1815 /* more verbose if exceeding 'limit' due to magic bonus */
1816 (acurrent > alimit) ? "innate " : "",
1817 attrval(attrindx, alimit, valstring));
1818 /* paren_pfx = ", "; */
1820 if (acurrent != abase || abase != apeak || interesting_alimit)
1821 Strcat(valubuf, ")");
1823 enl_msg(subjbuf, "is ", "was ", valubuf, "");
1826 /* status: selected obvious capabilities, assorted troubles */
1828 status_enlightenment(mode, final)
1832 boolean magic = (mode & MAGICENLIGHTENMENT) ? TRUE : FALSE;
1834 char buf[BUFSZ], youtoo[BUFSZ];
1835 boolean Riding = (u.usteed
1836 /* if hero dies while dismounting, u.usteed will still
1837 be set; we want to ignore steed in that situation */
1838 && !(final == ENL_GAMEOVERDEAD
1839 && !strcmp(killer.name, "riding accident")));
1840 const char *steedname = (!Riding ? (char *) 0
1841 : x_monnam(u.usteed,
1842 u.usteed->mtame ? ARTICLE_YOUR : ARTICLE_THE,
1844 (SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION),
1848 * Status (many are abbreviated on bottom line; others are or
1849 * should be discernible to the hero hence to the player)
1851 putstr(en_win, 0, ""); /* separator after title or characteristics */
1852 putstr(en_win, 0, final ? "Final Status:" : "Current Status:");
1854 Strcpy(youtoo, You_);
1855 /* not a traditional status but inherently obvious to player; more
1856 detail given below (attributes section) for magic enlightenment */
1858 you_are("transformed", "");
1859 /* not a trouble, but we want to display riding status before maybe
1860 reporting steed as trapped or hero stuck to cursed saddle */
1862 Sprintf(buf, "riding %s", steedname);
1864 Sprintf(eos(youtoo), "and %s ", steedname);
1866 /* other movement situations that hero should always know */
1868 if (Lev_at_will && magic)
1869 you_are("levitating, at will", "");
1871 enl_msg(youtoo, are, were, "levitating", from_what(LEVITATION));
1872 } else if (Flying) { /* can only fly when not levitating */
1873 enl_msg(youtoo, are, were, "flying", from_what(FLYING));
1876 you_are("underwater", "");
1877 } else if (u.uinwater) {
1878 you_are(Swimming ? "swimming" : "in water", from_what(SWIMMING));
1879 } else if (walking_on_water()) {
1880 /* show active Wwalking here, potential Wwalking elsewhere */
1881 Sprintf(buf, "walking on %s",
1882 is_pool(u.ux, u.uy) ? "water"
1883 : is_lava(u.ux, u.uy) ? "lava"
1884 : surface(u.ux, u.uy)); /* catchall; shouldn't happen */
1885 you_are(buf, from_what(WWALKING));
1887 if (Upolyd && (u.uundetected || youmonst.m_ap_type != M_AP_NOTHING))
1888 youhiding(TRUE, final);
1890 /* internal troubles, mostly in the order that prayer ranks them */
1892 you_are("turning to stone", "");
1894 you_are("turning into slime", "");
1897 you_are("buried", "");
1899 Strcpy(buf, "being strangled");
1901 Sprintf(eos(buf), " (%ld)", (Strangled & TIMEOUT));
1902 you_are(buf, from_what(STRANGLED));
1906 /* prayer lumps these together; botl puts Ill before FoodPois */
1907 if (u.usick_type & SICK_NONVOMITABLE)
1908 you_are("terminally sick from illness", "");
1909 if (u.usick_type & SICK_VOMITABLE)
1910 you_are("terminally sick from food poisoning", "");
1913 you_are("nauseated", "");
1915 you_are("stunned", "");
1917 you_are("confused", "");
1919 you_are("hallucinating", "");
1921 /* from_what() (currently wizard-mode only) checks !haseyes()
1922 before u.uroleplay.blind, so we should too */
1923 Sprintf(buf, "%s blind",
1924 !haseyes(youmonst.data) ? "innately"
1925 : u.uroleplay.blind ? "permanently"
1926 /* better phrasing desperately wanted... */
1927 : Blindfolded_only ? "deliberately"
1929 if (wizard && (Blinded & TIMEOUT) != 0L
1930 && !u.uroleplay.blind && haseyes(youmonst.data))
1931 Sprintf(eos(buf), " (%ld)", (Blinded & TIMEOUT));
1932 /* !haseyes: avoid "you are innately blind innately" */
1933 you_are(buf, !haseyes(youmonst.data) ? "" : from_what(BLINDED));
1936 you_are("deaf", from_what(DEAF));
1938 /* external troubles, more or less */
1941 Sprintf(buf, "chained to %s", ansimpleoname(uball));
1943 impossible("Punished without uball?");
1944 Strcpy(buf, "punished");
1949 char predicament[BUFSZ];
1951 boolean anchored = (u.utraptype == TT_BURIEDBALL);
1954 Strcpy(predicament, "tethered to something buried");
1955 } else if (u.utraptype == TT_INFLOOR || u.utraptype == TT_LAVA) {
1956 Sprintf(predicament, "stuck in %s", the(surface(u.ux, u.uy)));
1958 Strcpy(predicament, "trapped");
1959 if ((t = t_at(u.ux, u.uy)) != 0)
1960 Sprintf(eos(predicament), " in %s",
1961 an(defsyms[trap_to_defsym(t->ttyp)].explanation));
1963 if (u.usteed) { /* not `Riding' here */
1964 Sprintf(buf, "%s%s ", anchored ? "you and " : "", steedname);
1966 enl_msg(buf, (anchored ? "are " : "is "),
1967 (anchored ? "were " : "was "), predicament, "");
1969 you_are(predicament, "");
1972 Sprintf(buf, "swallowed by %s", a_monnam(u.ustuck));
1974 Sprintf(eos(buf), " (%u)", u.uswldtim);
1976 } else if (u.ustuck) {
1977 Sprintf(buf, "%s %s",
1978 (Upolyd && sticks(youmonst.data)) ? "holding" : "held by",
1979 a_monnam(u.ustuck));
1983 struct obj *saddle = which_armor(u.usteed, W_SADDLE);
1985 if (saddle && saddle->cursed) {
1986 Sprintf(buf, "stuck to %s %s", s_suffix(steedname),
1987 simpleonames(saddle));
1992 /* when mounted, Wounded_legs applies to steed rather than to
1993 hero; we only report steed's wounded legs in wizard mode */
1994 if (u.usteed) { /* not `Riding' here */
1995 if (wizard && steedname) {
1996 Strcpy(buf, steedname);
1998 enl_msg(buf, " has", " had", " wounded legs", "");
2001 Sprintf(buf, "wounded %s", makeplural(body_part(LEG)));
2006 Sprintf(buf, "slippery %s", makeplural(body_part(FINGER)));
2010 if (magic || cause_known(FUMBLING))
2011 enl_msg(You_, "fumble", "fumbled", "", from_what(FUMBLING));
2014 if (magic || cause_known(SLEEPY)) {
2015 Strcpy(buf, from_what(SLEEPY));
2017 Sprintf(eos(buf), " (%ld)", (HSleepy & TIMEOUT));
2018 enl_msg("You ", "fall", "fell", " asleep uncontrollably", buf);
2021 /* hunger/nutrition */
2023 if (magic || cause_known(HUNGER))
2024 enl_msg(You_, "hunger", "hungered", " rapidly",
2027 Strcpy(buf, hu_stat[u.uhs]); /* hunger status; omitted if "normal" */
2028 mungspaces(buf); /* strip trailing spaces */
2030 *buf = lowc(*buf); /* override capitalization */
2031 if (!strcmp(buf, "weak"))
2032 Strcat(buf, " from severe hunger");
2033 else if (!strncmp(buf, "faint", 5)) /* fainting, fainted */
2034 Strcat(buf, " due to starvation");
2038 if ((cap = near_capacity()) > UNENCUMBERED) {
2039 const char *adj = "?_?"; /* (should always get overridden) */
2041 Strcpy(buf, enc_stat[cap]);
2046 break; /* burdened */
2049 break; /* stressed */
2052 break; /* strained */
2055 break; /* overtaxed */
2057 adj = "not possible";
2060 Sprintf(eos(buf), "; movement %s %s%s", !final ? "is" : "was", adj,
2061 (cap < OVERLOADED) ? " slowed" : "");
2064 /* last resort entry, guarantees Status section is non-empty
2065 (no longer needed for that purpose since weapon status added;
2066 still useful though) */
2067 you_are("unencumbered", "");
2069 /* report being weaponless; distinguish whether gloves are worn */
2071 you_are(uarmg ? "empty handed" /* gloves imply hands */
2072 : humanoid(youmonst.data)
2073 /* hands but no weapon and no gloves */
2075 /* alternate phrasing for paws or lack of hands */
2076 : "not wielding anything",
2078 /* two-weaponing implies a weapon (not other odd stuff) in each hand */
2079 } else if (u.twoweap) {
2080 you_are("wielding two weapons at once", "");
2081 /* report most weapons by their skill class (so a katana will be
2082 described as a long sword, for instance; mattock and hook are
2083 exceptions), or wielded non-weapon item by its object class */
2085 const char *what = weapon_descr(uwep);
2087 if (!strcmpi(what, "armor") || !strcmpi(what, "food")
2088 || !strcmpi(what, "venom"))
2089 Sprintf(buf, "wielding some %s", what);
2091 Sprintf(buf, "wielding %s",
2092 (uwep->quan == 1L) ? an(what) : makeplural(what));
2095 /* report 'nudity' */
2096 if (!uarm && !uarmu && !uarmc && !uarmg && !uarmf && !uarmh) {
2097 if (u.uroleplay.nudist)
2098 enl_msg(You_, "do", "did", " not wear any armor", "");
2100 you_are("not wearing any armor", "");
2104 /* attributes: intrinsics and the like, other non-obvious capabilities */
2106 attributes_enlightenment(unused_mode, final)
2107 int unused_mode UNUSED;
2110 static NEARDATA const char if_surroundings_permitted[] =
2111 " if surroundings permitted";
2118 putstr(en_win, 0, "");
2119 putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:");
2121 if (u.uevent.uhand_of_elbereth) {
2123 static const char *const hofe_titles[3] = { "the Hand of Elbereth",
2124 "the Envoy of Balance",
2125 "the Glory of Arioch" };
2127 static const char *const hofe_titles[3] = { "
\83G
\83\8b\83x
\83\8c\83X
\82Ì
\8cä
\8eè",
2128 "
\92²
\98a
\82Ì
\8eg
\8eÒ",
2129 "
\83A
\83\8a\83I
\83b
\83`
\82Ì
\96¼
\97_" };
2131 you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1], "");
2134 /* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
2135 if (u.ualign.record >= 20)
2137 you_are("piously aligned", "");
2139 you_have("
\8chåi
\82È
\90M
\8bÂ
\90S", "");
2140 else if (u.ualign.record > 13)
2142 you_are("devoutly aligned", "");
2144 you_have("
\90S
\82©
\82ç
\82Ì
\90M
\8bÂ
\90S", "");
2145 else if (u.ualign.record > 8)
2147 you_are("fervently aligned", "");
2149 you_have("
\94M
\90S
\82È
\90M
\8bÂ
\90S", "");
2150 else if (u.ualign.record > 3)
2152 you_are("stridently aligned", "");
2154 you_have("
\82¨
\82¨
\82°
\82³
\82È
\90M
\8bÂ
\90S", "");
2155 else if (u.ualign.record == 3)
2157 you_are("aligned", "");
2159 you_have("
\95\81\92Ê
\82Ì
\90M
\8bÂ
\90S", "");
2160 else if (u.ualign.record > 0)
2162 you_are("haltingly aligned", "");
2164 you_have("çSçO
\82µ
\82È
\82ª
\82ç
\82à
\90M
\8bÂ
\90S", "");
2165 else if (u.ualign.record == 0)
2167 you_are("nominally aligned", "");
2169 you_have("
\8c`
\82¾
\82¯
\82Ì
\90M
\8bÂ
\90S", "");
2170 else if (u.ualign.record >= -3)
2172 you_have("strayed", "");
2174 you_are_ing("
\90M
\8bÂ
\82É
\96À
\82¢
\82ð
\82à
\82Á
\82Ä");
2175 else if (u.ualign.record >= -8)
2177 you_have("sinned", "");
2179 you_are_ing("
\8dß
\82ð
\95\89\82Á
\82Ä");
2182 you_have("transgressed", "");
2184 you_are_ing("
\90M
\8bÂ
\82©
\82ç
\88í
\92E
\82µ
\82Ä");
2187 Sprintf(buf, " %d", u.ualign.record);
2188 enl_msg("Your alignment ", "is", "was", buf, "");
2190 Sprintf(buf, "
\82 \82È
\82½
\82Ì
\91®
\90«
\92l
\82Í%d", u.ualign.record);
2191 enl_msg(buf, "
\82Å
\82 \82é", "
\82¾
\82Á
\82½", "", "");
2195 /*** Resistances to troubles ***/
2197 you_are("invulnerable", from_what(INVULNERABLE));
2199 you_are("magic-protected", from_what(ANTIMAGIC));
2200 if (Fire_resistance)
2201 you_are("fire resistant", from_what(FIRE_RES));
2202 if (Cold_resistance)
2203 you_are("cold resistant", from_what(COLD_RES));
2204 if (Sleep_resistance)
2205 you_are("sleep resistant", from_what(SLEEP_RES));
2206 if (Disint_resistance)
2207 you_are("disintegration-resistant", from_what(DISINT_RES));
2208 if (Shock_resistance)
2209 you_are("shock resistant", from_what(SHOCK_RES));
2210 if (Poison_resistance)
2211 you_are("poison resistant", from_what(POISON_RES));
2212 if (Acid_resistance)
2213 you_are("acid resistant", from_what(ACID_RES));
2214 if (Drain_resistance)
2215 you_are("level-drain resistant", from_what(DRAIN_RES));
2216 if (Sick_resistance)
2217 you_are("immune to sickness", from_what(SICK_RES));
2218 if (Stone_resistance)
2219 you_are("petrification resistant", from_what(STONE_RES));
2220 if (Halluc_resistance)
2221 enl_msg(You_, "resist", "resisted", " hallucinations",
2222 from_what(HALLUC_RES));
2224 you_can("recognize detrimental food", "");
2226 /*** Vision and senses ***/
2227 if (!Blind && (Blinded || !haseyes(youmonst.data)))
2228 you_can("see", from_what(-BLINDED)); /* Eyes of the Overworld */
2229 if (See_invisible) {
2231 enl_msg(You_, "see", "saw", " invisible", from_what(SEE_INVIS));
2233 enl_msg(You_, "will see", "would have seen",
2234 " invisible when not blind", from_what(SEE_INVIS));
2237 you_are("telepathic", from_what(TELEPAT));
2239 you_are("warned", from_what(WARNING));
2240 if (Warn_of_mon && context.warntype.obj) {
2241 Sprintf(buf, "aware of the presence of %s",
2242 (context.warntype.obj & M2_ORC) ? "orcs"
2243 : (context.warntype.obj & M2_ELF) ? "elves"
2244 : (context.warntype.obj & M2_DEMON) ? "demons" : something);
2245 you_are(buf, from_what(WARN_OF_MON));
2247 if (Warn_of_mon && context.warntype.polyd) {
2248 Sprintf(buf, "aware of the presence of %s",
2249 ((context.warntype.polyd & (M2_HUMAN | M2_ELF))
2250 == (M2_HUMAN | M2_ELF))
2251 ? "humans and elves"
2252 : (context.warntype.polyd & M2_HUMAN)
2254 : (context.warntype.polyd & M2_ELF)
2256 : (context.warntype.polyd & M2_ORC)
2258 : (context.warntype.polyd & M2_DEMON)
2260 : "certain monsters");
2263 if (Warn_of_mon && context.warntype.speciesidx) {
2264 Sprintf(buf, "aware of the presence of %s",
2265 makeplural(mons[context.warntype.speciesidx].mname));
2266 you_are(buf, from_what(WARN_OF_MON));
2269 you_are("warned of undead", from_what(WARN_UNDEAD));
2271 you_have("automatic searching", from_what(SEARCHING));
2273 you_are("clairvoyant", from_what(CLAIRVOYANT));
2274 else if ((HClairvoyant || EClairvoyant) && BClairvoyant) {
2275 Strcpy(buf, from_what(-CLAIRVOYANT));
2276 if (!strncmp(buf, " because of ", 12))
2277 /* overwrite substring; strncpy doesn't add terminator */
2278 (void) strncpy(buf, " if not for ", 12);
2279 enl_msg(You_, "could be", "could have been", " clairvoyant", buf);
2282 you_have("infravision", from_what(INFRAVISION));
2283 if (Detect_monsters)
2284 you_are("sensing the presence of monsters", "");
2286 you_are("going to confuse monsters", "");
2288 /*** Appearance and behavior ***/
2292 if (uleft && uleft->otyp == RIN_ADORNMENT)
2293 adorn += uleft->spe;
2294 if (uright && uright->otyp == RIN_ADORNMENT)
2295 adorn += uright->spe;
2296 /* the sum might be 0 (+0 ring or two which negate each other);
2297 that yields "you are charismatic" (which isn't pointless
2298 because it potentially impacts seduction attacks) */
2299 Sprintf(buf, "%scharismatic",
2300 (adorn > 0) ? "more " : (adorn < 0) ? "less " : "");
2301 you_are(buf, from_what(ADORNED));
2304 you_are("invisible", from_what(INVIS));
2306 you_are("invisible to others", from_what(INVIS));
2307 /* ordinarily "visible" is redundant; this is a special case for
2308 the situation when invisibility would be an expected attribute */
2309 else if ((HInvis || EInvis) && BInvis)
2310 you_are("visible", from_what(-INVIS));
2312 you_are("displaced", from_what(DISPLACED));
2314 you_are("stealthy", from_what(STEALTH));
2315 if (Aggravate_monster)
2316 enl_msg("You aggravate", "", "d", " monsters",
2317 from_what(AGGRAVATE_MONSTER));
2319 enl_msg("You cause", "", "d", " conflict", from_what(CONFLICT));
2321 /*** Transportation ***/
2323 you_can("jump", from_what(JUMPING));
2325 you_can("teleport", from_what(TELEPORT));
2326 if (Teleport_control)
2327 you_have("teleport control", from_what(TELEPORT_CONTROL));
2328 /* actively levitating handled earlier as a status condition */
2329 if (BLevitation) { /* levitation is blocked */
2330 long save_BLev = BLevitation;
2334 enl_msg(You_, "would levitate", "would have levitated",
2335 if_surroundings_permitted, "");
2336 BLevitation = save_BLev;
2338 /* actively flying handled earlier as a status condition */
2339 if (BFlying) { /* flight is blocked */
2340 long save_BFly = BFlying;
2344 enl_msg(You_, "would fly", "would have flown",
2346 ? "if you weren't levitating"
2347 : (save_BFly == FROMOUTSIDE)
2348 ? if_surroundings_permitted
2349 /* both surroundings and [latent] levitation */
2350 : " if circumstances permitted",
2352 BFlying = save_BFly;
2354 /* actively walking on water handled earlier as a status condition */
2355 if (Wwalking && !walking_on_water())
2356 you_can("walk on water", from_what(WWALKING));
2357 /* actively swimming (in water but not under it) handled earlier */
2358 if (Swimming && (Underwater || !u.uinwater))
2359 you_can("swim", from_what(SWIMMING));
2361 you_can("survive without air", from_what(MAGICAL_BREATHING));
2362 else if (Amphibious)
2363 you_can("breathe water", from_what(MAGICAL_BREATHING));
2365 you_can("walk through walls", from_what(PASSES_WALLS));
2367 /*** Physical attributes ***/
2369 enl_msg("You regenerate", "", "d", "", from_what(REGENERATION));
2371 you_have("slower digestion", from_what(SLOW_DIGESTION));
2373 you_have(enlght_combatinc("to hit", u.uhitinc, final, buf), "");
2375 you_have(enlght_combatinc("damage", u.udaminc, final, buf), "");
2376 if (u.uspellprot || Protection) {
2379 if (uleft && uleft->otyp == RIN_PROTECTION)
2381 if (uright && uright->otyp == RIN_PROTECTION)
2382 prot += uright->spe;
2383 if (HProtection & INTRINSIC)
2385 prot += u.uspellprot;
2387 you_have(enlght_combatinc("defense", prot, final, buf), "");
2389 if ((armpro = magic_negation(&youmonst)) > 0) {
2390 /* magic cancellation factor, conferred by worn armor */
2391 static const char *const mc_types[] = {
2392 "" /*ordinary*/, "warded", "guarded", "protected",
2395 if (armpro >= SIZE(mc_types))
2396 armpro = SIZE(mc_types) - 1;
2397 you_are(mc_types[armpro], "");
2399 if (Half_physical_damage)
2400 enlght_halfdmg(HALF_PHDAM, final);
2401 if (Half_spell_damage)
2402 enlght_halfdmg(HALF_SPDAM, final);
2403 /* polymorph and other shape change */
2404 if (Protection_from_shape_changers)
2405 you_are("protected from shape changers",
2406 from_what(PROT_FROM_SHAPE_CHANGERS));
2408 const char *what = 0;
2410 if (!Upolyd) /* Upolyd handled below after current form */
2411 you_can("not change from your current form",
2412 from_what(UNCHANGING));
2413 /* blocked shape changes */
2415 what = !final ? "polymorph" : "have polymorphed";
2416 else if (u.ulycn >= LOW_PM)
2417 what = !final ? "change shape" : "have changed shape";
2419 Sprintf(buf, "would %s periodically", what);
2420 /* omit from_what(UNCHANGING); too verbose */
2421 enl_msg(You_, buf, buf, " if not locked into your current form",
2424 } else if (Polymorph) {
2425 you_are("polymorphing periodically", from_what(POLYMORPH));
2427 if (Polymorph_control)
2428 you_have("polymorph control", from_what(POLYMORPH_CONTROL));
2429 if (Upolyd && u.umonnum != u.ulycn) {
2430 /* foreign shape (except were-form which is handled below) */
2431 Sprintf(buf, "polymorphed into %s", an(youmonst.data->mname));
2433 Sprintf(eos(buf), " (%d)", u.mtimedone);
2436 if (lays_eggs(youmonst.data) && flags.female) /* Upolyd */
2437 you_can("lay eggs", "");
2438 if (u.ulycn >= LOW_PM) {
2439 /* "you are a werecreature [in beast form]" */
2440 Strcpy(buf, an(mons[u.ulycn].mname));
2441 if (u.umonnum == u.ulycn) {
2442 Strcat(buf, " in beast form");
2444 Sprintf(eos(buf), " (%d)", u.mtimedone);
2448 if (Unchanging && Upolyd) /* !Upolyd handled above */
2449 you_can("not change from your current form", from_what(UNCHANGING));
2451 you_are("harmed by silver", "");
2452 /* movement and non-armor-based protection */
2454 you_are(Very_fast ? "very fast" : "fast", from_what(FAST));
2456 you_have("reflection", from_what(REFLECTING));
2458 you_have("free action", from_what(FREE_ACTION));
2460 you_have("fixed abilities", from_what(FIXED_ABIL));
2462 enl_msg("Your life ", "will be", "would have been", " saved", "");
2464 /*** Miscellany ***/
2466 ltmp = abs((int) Luck);
2467 Sprintf(buf, "%s%slucky",
2468 ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "",
2469 Luck < 0 ? "un" : "");
2471 Sprintf(eos(buf), " (%d)", Luck);
2474 enl_msg("Your luck ", "is", "was", " zero", "");
2476 you_have("extra luck", "");
2477 else if (u.moreluck < 0)
2478 you_have("reduced luck", "");
2479 if (carrying(LUCKSTONE) || stone_luck(TRUE)) {
2480 ltmp = stone_luck(0);
2482 enl_msg("Bad luck ", "does", "did", " not time out for you", "");
2484 enl_msg("Good luck ", "does", "did", " not time out for you", "");
2488 Sprintf(buf, " %sangry with you",
2489 u.ugangr > 6 ? "extremely " : u.ugangr > 3 ? "very " : "");
2491 Sprintf(eos(buf), " (%d)", u.ugangr);
2492 enl_msg(u_gname(), " is", " was", buf, "");
2495 * We need to suppress this when the game is over, because death
2496 * can change the value calculated by can_pray(), potentially
2497 * resulting in a false claim that you could have prayed safely.
2502 /* "can [not] safely pray" vs "could [not] have safely prayed" */
2503 Sprintf(buf, "%s%ssafely pray%s", can_pray(FALSE) ? "" : "not ",
2504 final ? "have " : "", final ? "ed" : "");
2506 Sprintf(buf, "%ssafely pray", can_pray(FALSE) ? "" : "not ");
2509 Sprintf(eos(buf), " (%d)", u.ublesscnt);
2512 Sprintf(buf, "
\82 \82È
\82½
\82Í
\88À
\91S
\82É
\8bF
\82é
\82±
\82Æ
\82ª");
2513 Strcat(buf, can_pray(FALSE) ? can : "
\82Å
\82«
\82È
\82¢");
2515 Sprintf(eos(buf), " (%d)", u.ublesscnt);
2516 enl_msg(buf, "", "", "", "");
2521 /* named fruit debugging (doesn't really belong here...) */
2527 for (f = ffruit; f; f = f->nextf) {
2528 Sprintf(buf, "Fruit %d ", ++fcount);
2529 Sprintf(buf2, "%s (id %d)", f->fname, f->fid);
2530 enl_msg(buf, "is ", "was ", buf2, "");
2532 enl_msg("The current fruit ", "is ", "was ", pl_fruit, "");
2533 Sprintf(buf, "%d", flags.made_fruit);
2534 enl_msg("The made fruit flag ", "is ", "was ", buf, "");
2541 if (final < 2) { /* still in progress, or quit/escaped/ascended */
2543 p = "survived after being killed ";
2545 p = "
\8e\80\82ñ
\82¾
\8cã
\95\9c\8a\88\82µ
\82Ä
\82¢
\82½";
2546 switch (u.umortality) {
2549 p = !final ? (char *) 0 : "survived";
2551 p = !final ? (char *)0 : "
\90¶
\82«
\89\84\82Ñ
\82½";
2555 Strcpy(buf, "once");
2557 Strcpy(buf, "
\88ê
\93x");
2561 Strcpy(buf, "twice");
2563 Strcpy(buf, "
\93ñ
\93x");
2567 Strcpy(buf, "thrice");
2569 Strcpy(buf, "
\8eO
\93x");
2573 Sprintf(buf, "%d times", u.umortality);
2575 Sprintf(buf, "%d
\89ñ", u.umortality);
2578 } else { /* game ended in character's death */
2582 p = "
\8e\80\82ñ
\82Å
\82¢
\82é";
2583 switch (u.umortality) {
2585 impossible("dead without dying?");
2587 break; /* just "are dead" */
2590 Sprintf(buf, " (%d%s time!)", u.umortality,
2591 ordin(u.umortality));
2593 Sprintf(buf, "(%d
\89ñ
\81I)", u.umortality);
2600 enl_msg(You_, "have been killed ", p, buf, "");
2602 enl_msg(You_, "
\8e\80\82ñ
\82Å
\82¢
\82é", p, buf, "");
2606 #if 0 /* no longer used */
2607 STATIC_DCL boolean NDECL(minimal_enlightenment);
2610 * Courtesy function for non-debug, non-explorer mode players
2611 * to help refresh them about who/what they are.
2612 * Returns FALSE if menu cancelled (dismissed with ESC), TRUE otherwise.
2615 minimal_enlightenment()
2618 menu_item *selected;
2621 char buf[BUFSZ], buf2[BUFSZ];
2622 static const char untabbed_fmtstr[] = "%-15s: %-12s";
2623 static const char untabbed_deity_fmtstr[] = "%-17s%s";
2624 static const char tabbed_fmtstr[] = "%s:\t%-12s";
2625 static const char tabbed_deity_fmtstr[] = "%s\t%s";
2626 static const char *fmtstr;
2627 static const char *deity_fmtstr;
2629 fmtstr = iflags.menu_tab_sep ? tabbed_fmtstr : untabbed_fmtstr;
2630 deity_fmtstr = iflags.menu_tab_sep ? tabbed_deity_fmtstr
2631 : untabbed_deity_fmtstr;
2633 buf[0] = buf2[0] = '\0';
2634 tmpwin = create_nhwindow(NHW_MENU);
2636 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2639 /* Starting name, race, role, gender */
2640 Sprintf(buf, fmtstr, "name", plname);
2641 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2642 Sprintf(buf, fmtstr, "race", urace.noun);
2643 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2644 Sprintf(buf, fmtstr, "role",
2645 (flags.initgend && urole.name.f) ? urole.name.f : urole.name.m);
2646 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2647 Sprintf(buf, fmtstr, "gender", genders[flags.initgend].adj);
2648 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2650 /* Starting alignment */
2651 Sprintf(buf, fmtstr, "alignment", align_str(u.ualignbase[A_ORIGINAL]));
2652 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2654 /* Current name, race, role, gender */
2655 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE);
2656 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2658 Sprintf(buf, fmtstr, "race", Upolyd ? youmonst.data->mname : urace.noun);
2659 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2661 Sprintf(buf, fmtstr, "role (base)",
2662 (u.mfemale && urole.name.f) ? urole.name.f
2664 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2666 Sprintf(buf, fmtstr, "role",
2667 (flags.female && urole.name.f) ? urole.name.f
2669 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2671 /* don't want poly_gender() here; it forces `2' for non-humanoids */
2672 genidx = is_neuter(youmonst.data) ? 2 : flags.female;
2673 Sprintf(buf, fmtstr, "gender", genders[genidx].adj);
2674 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2675 if (Upolyd && (int) u.mfemale != genidx) {
2676 Sprintf(buf, fmtstr, "gender (base)", genders[u.mfemale].adj);
2677 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2680 /* Current alignment */
2681 Sprintf(buf, fmtstr, "alignment", align_str(u.ualign.type));
2682 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2685 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE);
2686 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2688 Sprintf(buf2, deity_fmtstr, align_gname(A_CHAOTIC),
2689 (u.ualignbase[A_ORIGINAL] == u.ualign.type
2690 && u.ualign.type == A_CHAOTIC) ? " (s,c)"
2691 : (u.ualignbase[A_ORIGINAL] == A_CHAOTIC) ? " (s)"
2692 : (u.ualign.type == A_CHAOTIC) ? " (c)" : "");
2693 Sprintf(buf, fmtstr, "Chaotic", buf2);
2694 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2696 Sprintf(buf2, deity_fmtstr, align_gname(A_NEUTRAL),
2697 (u.ualignbase[A_ORIGINAL] == u.ualign.type
2698 && u.ualign.type == A_NEUTRAL) ? " (s,c)"
2699 : (u.ualignbase[A_ORIGINAL] == A_NEUTRAL) ? " (s)"
2700 : (u.ualign.type == A_NEUTRAL) ? " (c)" : "");
2701 Sprintf(buf, fmtstr, "Neutral", buf2);
2702 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2704 Sprintf(buf2, deity_fmtstr, align_gname(A_LAWFUL),
2705 (u.ualignbase[A_ORIGINAL] == u.ualign.type
2706 && u.ualign.type == A_LAWFUL) ? " (s,c)"
2707 : (u.ualignbase[A_ORIGINAL] == A_LAWFUL) ? " (s)"
2708 : (u.ualign.type == A_LAWFUL) ? " (c)" : "");
2709 Sprintf(buf, fmtstr, "Lawful", buf2);
2710 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2712 end_menu(tmpwin, "Base Attributes");
2713 n = select_menu(tmpwin, PICK_NONE, &selected);
2714 destroy_nhwindow(tmpwin);
2715 return (boolean) (n != -1);
2721 doattributes(VOID_ARGS)
2723 int mode = BASICENLIGHTENMENT;
2725 /* show more--as if final disclosure--for wizard and explore modes */
2726 if (wizard || discover)
2727 mode |= MAGICENLIGHTENMENT;
2729 enlightenment(mode, ENL_GAMEINPROGRESS);
2734 youhiding(via_enlghtmt, msgflag)
2735 boolean via_enlghtmt; /* englightment line vs topl message */
2736 int msgflag; /* for variant message phrasing */
2738 char *bp, buf[BUFSZ];
2740 Strcpy(buf, "hiding");
2741 if (youmonst.m_ap_type != M_AP_NOTHING) {
2742 /* mimic; hero is only able to mimic a strange object or gold
2743 or hallucinatory alternative to gold, so we skip the details
2744 for the hypothetical furniture and monster cases */
2745 bp = eos(strcpy(buf, "mimicking"));
2746 if (youmonst.m_ap_type == M_AP_OBJECT) {
2747 Sprintf(bp, " %s", an(simple_typename(youmonst.mappearance)));
2748 } else if (youmonst.m_ap_type == M_AP_FURNITURE) {
2749 Strcpy(bp, " something");
2750 } else if (youmonst.m_ap_type == M_AP_MONSTER) {
2751 Strcpy(bp, " someone");
2753 ; /* something unexpected; leave 'buf' as-is */
2755 } else if (u.uundetected) {
2756 bp = eos(buf); /* points past "hiding" */
2757 if (youmonst.data->mlet == S_EEL) {
2758 if (is_pool(u.ux, u.uy))
2759 Sprintf(bp, " in the %s", waterbody_name(u.ux, u.uy));
2760 } else if (hides_under(youmonst.data)) {
2761 struct obj *o = level.objects[u.ux][u.uy];
2764 Sprintf(bp, " underneath %s", ansimpleoname(o));
2765 } else if (is_clinger(youmonst.data) || Flying) {
2766 /* Flying: 'lurker above' hides on ceiling but doesn't cling */
2767 Sprintf(bp, " on the %s", ceiling(u.ux, u.uy));
2769 /* on floor; is_hider() but otherwise not special: 'trapper' */
2770 if (u.utrap && u.utraptype == TT_PIT) {
2771 struct trap *t = t_at(u.ux, u.uy);
2773 Sprintf(bp, " in a %spit",
2774 (t && t->ttyp == SPIKED_PIT) ? "spiked " : "");
2776 Sprintf(bp, " on the %s", surface(u.ux, u.uy));
2779 ; /* shouldn't happen; will result in generic "you are hiding" */
2783 int final = msgflag; /* 'final' is used by you_are() macro */
2787 /* for dohide(), when player uses '#monster' command */
2788 You("are %s %s.", msgflag ? "already" : "now", buf);
2793 * (shares enlightenment's tense handling)
2796 doconduct(VOID_ARGS)
2809 /* Create the conduct window */
2810 en_win = create_nhwindow(NHW_MENU);
2812 putstr(en_win, 0, "Voluntary challenges:");
2814 putstr(en_win, 0, "
\8e©
\94
\93I
\92§
\90í:");
2816 if (u.uroleplay.blind)
2818 you_have_been("blind from birth");
2820 you_have_been("
\90¶
\82Ü
\82ê
\82È
\82ª
\82ç
\82É
\96Ó
\96Ú");
2821 if (u.uroleplay.nudist)
2823 you_have_been("faithfully nudist");
2825 you_have_been("
\92\89\8eÀ
\82È
\97\87\91°");
2827 if (!u.uconduct.food)
2829 enl_msg(You_, "have gone", "went", " without food", "");
2831 enl_msg("
\82 \82È
\82½
\82Í
\90H
\8e\96\82ð
\82µ", "
\82Ä
\82¢
\82È
\82¢", "
\82È
\82©
\82Á
\82½", "", "");
2832 /* But beverages are okay */
2833 else if (!u.uconduct.unvegan)
2835 you_have_X("followed a strict vegan diet");
2837 you_have_been("
\8cµ
\8ai
\82È
\8dØ
\90H
\8eå
\8b`
\8eÒ");
2838 else if (!u.uconduct.unvegetarian)
2840 you_have_been("vegetarian");
2842 you_have_been("
\8dØ
\90H
\8eå
\8b`
\8eÒ");
2844 if (!u.uconduct.gnostic)
2846 you_have_been("an atheist");
2848 you_have_been("
\96³
\90_
\98_
\8eÒ");
2850 if (!u.uconduct.weaphit) {
2852 you_have_never("hit with a wielded weapon");
2854 you_have_never("
\82 \82È
\82½
\82Í
\91\95\94õ
\82µ
\82Ä
\82¢
\82é
\95\90\8aí
\82Å
\8dU
\8c\82\82µ");
2855 } else if (wizard) {
2857 Sprintf(buf, "used a wielded weapon %ld time%s", u.uconduct.weaphit,
2858 plur(u.uconduct.weaphit));
2861 Sprintf(buf, "
\82 \82È
\82½
\82Í%ld
\89ñ
\91\95\94õ
\82µ
\82½
\95\90\8aí
\82ð
\8eg
\97p
\82µ", u.uconduct.weaphit);
2865 if (!u.uconduct.killer)
2867 you_have_been("a pacifist");
2869 you_have_been("
\95½
\98a
\8eå
\8b`
\8eÒ");
2871 if (!u.uconduct.literate) {
2873 you_have_been("illiterate");
2875 you_have_never("
\82 \82È
\82½
\82Í
\93Ç
\82Ý
\8f\91\82«
\82µ");
2876 } else if (wizard) {
2878 Sprintf(buf, "read items or engraved %ld time%s", u.uconduct.literate,
2879 plur(u.uconduct.literate));
2882 Sprintf(buf, "%ld
\89ñ
\93Ç
\82ñ
\82¾
\82è
\8f\91\82¢
\82½
\82è
\82µ", u.uconduct.literate);
2887 ngenocided = num_genocides();
2888 if (ngenocided == 0) {
2890 you_have_never("genocided any monsters");
2892 you_have_never("
\82 \82È
\82½
\82Í
\89ö
\95¨
\82ð
\8bs
\8eE
\82µ");
2895 Sprintf(buf, "genocided %d type%s of monster%s", ngenocided,
2896 plur(ngenocided), plur(ngenocided));
2899 Sprintf(buf, "%d
\8eí
\82Ì
\89ö
\95¨
\82ð
\8bs
\8eE
\82µ", ngenocided);
2904 if (!u.uconduct.polypiles) {
2906 you_have_never("polymorphed an object");
2908 you_have_never("
\82 \82È
\82½
\82Í
\95¨
\91Ì
\82ð
\95Ï
\89»
\82³
\82¹");
2909 } else if (wizard) {
2911 Sprintf(buf, "polymorphed %ld item%s", u.uconduct.polypiles,
2912 plur(u.uconduct.polypiles));
2915 Sprintf(buf, "%ld
\8cÂ
\82Ì
\93¹
\8bï
\82ð
\95Ï
\89»
\82³
\82¹", u.uconduct.polypiles);
2920 if (!u.uconduct.polyselfs) {
2922 you_have_never("changed form");
2924 you_have_never("
\82 \82È
\82½
\82Í
\95Ï
\89»
\82µ");
2925 } else if (wizard) {
2927 Sprintf(buf, "changed form %ld time%s", u.uconduct.polyselfs,
2928 plur(u.uconduct.polyselfs));
2931 Sprintf(buf, "%ld
\89ñ
\8ep
\82ð
\95Ï
\82¦", u.uconduct.polyselfs);
2936 if (!u.uconduct.wishes) {
2938 you_have_X("used no wishes");
2940 you_have_never("
\82 \82È
\82½
\82Í
\8aè
\82¢
\8e\96\82ð
\82µ");
2943 Sprintf(buf, "used %ld wish%s", u.uconduct.wishes,
2944 (u.uconduct.wishes > 1L) ? "es" : "");
2947 Sprintf(buf, "%ld
\89ñ
\8aè
\82¢
\8e\96\82ð
\82µ", u.uconduct.wishes);
2951 if (!u.uconduct.wisharti)
2953 enl_msg(You_, "have not wished", "did not wish",
2954 " for any artifacts", "");
2956 enl_msg("
\82 \82È
\82½
\82Í
\90¹
\8aí
\82ð
\8aè", "
\82Á
\82Ä
\82¢
\82È
\82¢", "
\82í
\82È
\82©
\82Á
\82½", "", "");
2960 /* Pop up the window and wait for a key */
2961 display_nhwindow(en_win, TRUE);
2962 destroy_nhwindow(en_win);
2968 #define M(c) (0x80 | (c))
2970 #define M(c) ((c) -128)
2974 #define C(c) (0x1f & (c))
2977 static const struct func_tab cmdlist[] = {
2978 { C('d'), FALSE, dokick }, /* "D" is for door!...? Msg is in dokick.c */
2979 { C('e'), TRUE, wiz_detect },
2980 { C('f'), TRUE, wiz_map },
2981 { C('g'), TRUE, wiz_genesis },
2982 { C('i'), TRUE, wiz_identify },
2983 { C('l'), TRUE, doredraw }, /* if number_pad is set */
2984 { C('n'), TRUE, donamelevel }, /* if number_pad is set */
2985 { C('o'), TRUE, dooverview_or_wiz_where }, /* depends on wizard status */
2986 { C('p'), TRUE, doprev_message },
2987 { C('r'), TRUE, doredraw },
2988 { C('t'), TRUE, dotele },
2989 { C('v'), TRUE, wiz_level_tele },
2990 { C('w'), TRUE, wiz_wish },
2991 { C('x'), TRUE, doattributes },
2992 { C('z'), TRUE, dosuspend_core },
2993 { 'a', FALSE, doapply },
2994 { 'A', FALSE, doddoremarm },
2995 { M('a'), TRUE, doorganize },
2996 { M('A'), TRUE, donamelevel }, /* #annotate */
2997 /* 'b', 'B' : go sw */
2998 { 'c', FALSE, doclose },
2999 { 'C', TRUE, docallcmd },
3000 { M('c'), TRUE, dotalk },
3001 { M('C'), TRUE, doconduct }, /* #conduct */
3002 { 'd', FALSE, dodrop },
3003 { 'D', FALSE, doddrop },
3004 { M('d'), FALSE, dodip },
3005 { 'e', FALSE, doeat },
3006 { 'E', FALSE, doengrave },
3007 { M('e'), TRUE, enhance_weapon_skill },
3008 { 'f', FALSE, dofire },
3009 /* 'F' : fight (one time) */
3010 { M('f'), FALSE, doforce },
3011 /* 'g', 'G' : multiple go */
3012 /* 'h', 'H' : go west */
3013 { 'h', TRUE, dohelp }, /* if number_pad is set */
3014 { 'i', TRUE, ddoinv },
3015 { 'I', TRUE, dotypeinv }, /* Robert Viduya */
3016 { M('i'), TRUE, doinvoke },
3017 /* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
3018 { 'j', FALSE, dojump }, /* if number_pad is on */
3019 { M('j'), FALSE, dojump },
3020 { 'k', FALSE, dokick }, /* if number_pad is on */
3021 { 'l', FALSE, doloot }, /* if number_pad is on */
3022 { M('l'), FALSE, doloot },
3023 /* 'n' prefixes a count if number_pad is on */
3024 { M('m'), TRUE, domonability },
3025 { 'N', TRUE, docallcmd }, /* if number_pad is on */
3026 { M('n'), TRUE, docallcmd },
3027 { M('N'), TRUE, docallcmd },
3028 { 'o', FALSE, doopen },
3029 { 'O', TRUE, doset },
3030 { M('o'), FALSE, dosacrifice },
3031 { M('O'), TRUE, dooverview }, /* #overview */
3032 { 'p', FALSE, dopay },
3033 { 'P', FALSE, doputon },
3034 { M('p'), TRUE, dopray },
3035 { 'q', FALSE, dodrink },
3036 { 'Q', FALSE, dowieldquiver },
3037 { M('q'), TRUE, done2 },
3038 { 'r', FALSE, doread },
3039 { 'R', FALSE, doremring },
3040 { M('r'), FALSE, dorub },
3041 { M('R'), FALSE, doride }, /* #ride */
3043 { 's', TRUE, dosearch, "searching" },
3045 { 's', TRUE, dosearch, "
\91{
\82·" },
3046 { 'S', TRUE, dosave },
3047 { M('s'), FALSE, dosit },
3048 { 't', FALSE, dothrow },
3049 { 'T', FALSE, dotakeoff },
3050 { M('t'), TRUE, doturn },
3051 { M('T'), FALSE, dotip }, /* #tip */
3052 /* 'u', 'U' : go ne */
3053 { 'u', FALSE, dountrap }, /* if number_pad is on */
3054 { M('u'), FALSE, dountrap },
3055 { 'v', TRUE, doversion },
3056 { 'V', TRUE, dohistory },
3057 { M('v'), TRUE, doextversion },
3058 { 'w', FALSE, dowield },
3059 { 'W', FALSE, dowear },
3060 { M('w'), FALSE, dowipe },
3061 { 'x', FALSE, doswapweapon },
3062 { 'X', FALSE, dotwoweapon },
3063 /* 'y', 'Y' : go nw */
3064 { 'z', FALSE, dozap },
3065 { 'Z', TRUE, docast },
3066 { '<', FALSE, doup },
3067 { '>', FALSE, dodown },
3068 { '/', TRUE, dowhatis },
3069 { '&', TRUE, dowhatdoes },
3070 { '?', TRUE, dohelp },
3071 { M('?'), TRUE, doextlist },
3073 { '!', TRUE, dosh },
3076 { '.', TRUE, donull, "waiting" },
3078 { '.', TRUE, donull, "
\8bx
\8ce
\82·
\82é" },
3080 { ' ', TRUE, donull, "waiting" },
3082 { ' ', TRUE, donull, "
\8bx
\8ce
\82·
\82é" },
3083 { ',', FALSE, dopickup },
3084 { ':', TRUE, dolook },
3085 { ';', TRUE, doquickwhatis },
3086 { '^', TRUE, doidtrap },
3087 { '\\', TRUE, dodiscovered }, /* Robert Viduya */
3088 { '`', TRUE, doclassdisco },
3089 { '@', TRUE, dotogglepickup },
3090 { M('2'), FALSE, dotwoweapon },
3091 { WEAPON_SYM, TRUE, doprwep },
3092 { ARMOR_SYM, TRUE, doprarm },
3093 { RING_SYM, TRUE, doprring },
3094 { AMULET_SYM, TRUE, dopramulet },
3095 { TOOL_SYM, TRUE, doprtool },
3096 { '*', TRUE, doprinuse }, /* inventory of all equipment in use */
3097 { GOLD_SYM, TRUE, doprgold },
3098 { SPBOOK_SYM, TRUE, dovspell }, /* Mike Stephenson */
3099 { '#', TRUE, doextcmd },
3100 { '_', TRUE, dotravel },
3104 struct ext_func_tab extcmdlist[] = {
3106 { "adjust", "adjust inventory letters", doorganize, TRUE },
3108 { "adjust", "
\8e\9d\82¿
\95¨
\88ê
\97\97\82Ì
\92²
\90®", doorganize, TRUE },
3110 { "annotate", "name current level", donamelevel, TRUE },
3112 { "annotate", "
\8c»
\8dÝ
\82Ì
\8aK
\82É
\96¼
\91O
\82ð
\82Â
\82¯
\82é", donamelevel, TRUE },
3114 { "chat", "talk to someone", dotalk, TRUE }, /* converse? */
3116 { "chat", "
\92N
\82©
\82Æ
\98b
\82·", dotalk, TRUE }, /* converse? */
3119 { "conduct", "list voluntary challenges you have maintained", doconduct,
3122 { "conduct", "
\82Ç
\82¤
\82¢
\82¤
\8ds
\93®
\82ð
\82Æ
\82Á
\82½
\82©
\8c©
\82é", doconduct, TRUE },
3125 { "dip", "dip an object into something", dodip, FALSE },
3127 { "dip", "
\89½
\82©
\82É
\95¨
\82ð
\90Z
\82·", dodip, FALSE },
3129 { "enhance", "advance or check weapon and spell skills",
3130 enhance_weapon_skill, TRUE },
3132 { "enhance", "
\95\90\8aí
\8fn
\97û
\93x
\82ð
\8d\82\82ß
\82é", enhance_weapon_skill, TRUE },
3135 { "exploremode", "enter explore mode", enter_explore_mode, TRUE },
3137 { "exploremode", "
\92T
\8c\9f\83\82\81[
\83h
\82É
\93ü
\82é", enter_explore_mode, TRUE },
3139 { "force", "force a lock", doforce, FALSE },
3141 { "force", "
\8c®
\82ð
\82±
\82¶
\82 \82¯
\82é", doforce, FALSE },
3143 { "invoke", "invoke an object's powers", doinvoke, TRUE },
3145 { "invoke", "
\95¨
\82Ì
\93Á
\95Ê
\82È
\97Í
\82ð
\8eg
\82¤", doinvoke, TRUE },
3147 { "jump", "jump to a location", dojump, FALSE },
3149 { "jump", "
\91¼
\82Ì
\88Ê
\92u
\82É
\94ò
\82Ñ
\82¤
\82Â
\82é", dojump, FALSE },
3151 { "loot", "loot a box on the floor", doloot, FALSE },
3153 { "loot", "
\8f°
\82Ì
\8fã
\82Ì
\94 \82ð
\8aJ
\82¯
\82é", doloot, TRUE },
3155 { "monster", "use a monster's special ability", domonability, TRUE },
3157 { "monster", "
\89ö
\95¨
\82Ì
\93Á
\95Ê
\94\
\97Í
\82ð
\8eg
\82¤", domonability, TRUE },
3159 { "name", "name a monster or an object", docallcmd, TRUE },
3161 { "name", "
\83A
\83C
\83e
\83\80\82â
\95¨
\82É
\96¼
\91O
\82ð
\82Â
\82¯
\82é", docallcmd, TRUE },
3163 { "offer", "offer a sacrifice to the gods", dosacrifice, FALSE },
3165 { "offer", "
\90_
\82É
\8b\9f\95¨
\82ð
\95ù
\82°
\82é", dosacrifice, FALSE },
3167 { "overview", "show an overview of the dungeon", dooverview, TRUE },
3169 { "overview", "
\96À
\8b{
\82Ì
\8aT
\97v
\82ð
\95\
\8e¦
\82·
\82é", dooverview, TRUE },
3171 { "pray", "pray to the gods for help", dopray, TRUE },
3173 { "pray", "
\90_
\82É
\8bF
\82é", dopray, TRUE },
3175 { "quit", "exit without saving current game", done2, TRUE },
3177 { "quit", "
\83Z
\81[
\83u
\82µ
\82È
\82¢
\82Å
\8fI
\97¹", done2, TRUE },
3179 { "ride", "ride (or stop riding) a monster", doride, FALSE },
3181 { "ride", "
\89ö
\95¨
\82É
\8fæ
\82é(
\82Ü
\82½
\82Í
\8d~
\82è
\82é)", doride, FALSE },
3183 { "rub", "rub a lamp or a stone", dorub, FALSE },
3185 { "rub", "
\83\89\83\93\83v
\82ð
\82±
\82·
\82é", dorub, FALSE },
3187 { "sit", "sit down", dosit, FALSE },
3189 { "sit", "
\8dÀ
\82é", dosit, FALSE },
3191 { "terrain", "show map without obstructions", doterrain, TRUE },
3193 { "terrain", "
\8e×
\96\82\82³
\82ê
\82¸
\82É
\92n
\90}
\82ð
\8c©
\82é", doterrain, TRUE },
3195 { "tip", "empty a container", dotip, FALSE },
3197 { "tip", "
\93ü
\82ê
\95¨
\82ð
\8bó
\82É
\82·
\82é", dotip, FALSE },
3199 { "turn", "turn undead", doturn, TRUE },
3201 { "turn", "
\83A
\83\93\83f
\83b
\83g
\82ð
\93y
\82É
\95Ô
\82·", doturn, TRUE },
3203 { "twoweapon", "toggle two-weapon combat", dotwoweapon, FALSE },
3205 { "twoweapon", "
\97¼
\8eè
\8e\9d\82¿
\82Ì
\90Ø
\82è
\91Ö
\82¦", dotwoweapon, FALSE },
3207 { "untrap", "untrap something", dountrap, FALSE },
3209 { "untrap", "ã©
\82ð
\82Í
\82¸
\82·", dountrap, FALSE },
3211 { "version", "list compile time options for this version of NetHack",
3212 doextversion, TRUE },
3214 { "version", "
\83R
\83\93\83p
\83C
\83\8b\8e\9e\82Ì
\83I
\83v
\83V
\83\87\83\93\82ð
\95\
\8e¦
\82·
\82é", doextversion, TRUE },
3217 { "wipe", "wipe off your face", dowipe, FALSE },
3219 { "wipe", "
\8aç
\82ð
\90@
\82¤", dowipe, FALSE },
3221 { "?", "get this list of extended commands", doextlist, TRUE },
3223 { "?", "
\82±
\82Ì
\8ag
\92£
\83R
\83}
\83\93\83h
\88ê
\97\97\82ð
\95\
\8e¦
\82·
\82é", doextlist, TRUE },
3225 * There must be a blank entry here for every entry in the table
3228 { (char *) 0, (char *) 0, donull, TRUE }, /* levelchange */
3229 { (char *) 0, (char *) 0, donull, TRUE }, /* lightsources */
3230 #ifdef DEBUG_MIGRATING_MONS
3231 { (char *) 0, (char *) 0, donull, TRUE }, /* migratemons */
3233 { (char *) 0, (char *) 0, donull, TRUE }, /* monpolycontrol */
3234 { (char *) 0, (char *) 0, donull, TRUE }, /* panic */
3235 { (char *) 0, (char *) 0, donull, TRUE }, /* polyself */
3237 { (char *) 0, (char *) 0, donull, TRUE }, /* portdebug */
3239 { (char *) 0, (char *) 0, donull, TRUE }, /* seenv */
3240 { (char *) 0, (char *) 0, donull, TRUE }, /* stats */
3241 { (char *) 0, (char *) 0, donull, TRUE }, /* timeout */
3242 { (char *) 0, (char *) 0, donull, TRUE }, /* vanquished */
3243 { (char *) 0, (char *) 0, donull, TRUE }, /* vision */
3244 { (char *) 0, (char *) 0, donull, TRUE }, /* wizsmell */
3246 { (char *) 0, (char *) 0, donull, TRUE }, /* wizdebug_traveldisplay */
3247 { (char *) 0, (char *) 0, donull, TRUE }, /* wizdebug_bury */
3249 { (char *) 0, (char *) 0, donull, TRUE }, /* wizrumorcheck */
3250 { (char *) 0, (char *) 0, donull, TRUE }, /* wmode */
3251 { (char *) 0, (char *) 0, donull, TRUE } /* sentinel */
3254 /* there must be a placeholder in the table above for every entry here */
3255 static const struct ext_func_tab debug_extcmdlist[] = {
3256 { "levelchange", "change experience level", wiz_level_change, TRUE },
3257 { "lightsources", "show mobile light sources", wiz_light_sources, TRUE },
3258 #ifdef DEBUG_MIGRATING_MONS
3259 { "migratemons", "migrate n random monsters", wiz_migrate_mons, TRUE },
3261 { "monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol,
3263 { "panic", "test panic routine (fatal to game)", wiz_panic, TRUE },
3264 { "polyself", "polymorph self", wiz_polyself, TRUE },
3266 { "portdebug", "wizard port debug command", wiz_port_debug, TRUE },
3268 { "seenv", "show seen vectors", wiz_show_seenv, TRUE },
3269 { "stats", "show memory statistics", wiz_show_stats, TRUE },
3270 { "timeout", "look at timeout queue", wiz_timeout_queue, TRUE },
3271 { "vanquished", "list vanquished monsters", dovanquished, TRUE },
3272 { "vision", "show vision array", wiz_show_vision, TRUE },
3273 { "wizsmell", "smell monster", wiz_smell, TRUE },
3275 { "wizdebug_traveldisplay", "wizard debug: toggle travel display",
3276 wiz_debug_cmd_traveldisplay, TRUE },
3277 { "wizdebug_bury", "wizard debug: bury objs under and around you",
3278 wiz_debug_cmd_bury, TRUE },
3280 { "wizrumorcheck", "verify rumor boundaries", wiz_rumor_check, TRUE },
3281 { "wmode", "show wall modes", wiz_show_wmodes, TRUE },
3282 { (char *) 0, (char *) 0, donull, TRUE }
3286 * Insert debug commands into the extended command list. This function
3287 * assumes that the last entry will be the help entry.
3289 * You must add entries in ext_func_tab every time you add one to the
3290 * debug_extcmdlist().
3293 add_debug_extended_commands()
3297 /* count the # of help entries */
3298 for (n = 0; extcmdlist[n].ef_txt[0] != '?'; n++)
3301 for (i = 0; debug_extcmdlist[i].ef_txt; i++) {
3302 /* need enough room for "?" entry plus terminator */
3303 if (n + 2 >= SIZE(extcmdlist))
3304 panic("Too many debugging commands!");
3305 for (j = 0; j < n; j++)
3306 if (strcmp(debug_extcmdlist[i].ef_txt, extcmdlist[j].ef_txt) < 0)
3309 /* insert i'th debug entry into extcmdlist[j], pushing down */
3310 for (k = n; k >= j; --k)
3311 extcmdlist[k + 1] = extcmdlist[k];
3312 extcmdlist[j] = debug_extcmdlist[i];
3313 n++; /* now an extra entry */
3322 for (i = 0; i < SIZE(cmdlist); ++i)
3323 if (cmdlist[i].f_funct == fn)
3324 return cmdlist[i].f_char;
3328 static const char template[] = "%-18s %4ld %6ld";
3329 static const char count_str[] = " count bytes";
3330 static const char separator[] = "------------------ ----- ------";
3336 int sz = (int) sizeof(struct obj);
3339 sz += (int) sizeof(struct oextra);
3341 sz += (int) strlen(ONAME(otmp)) + 1;
3343 sz += (int) sizeof(struct monst);
3345 sz += (int) sizeof(unsigned);
3347 sz += (int) sizeof(long);
3349 sz += (int) strlen(OMAILCMD(otmp)) + 1;
3355 count_obj(chain, total_count, total_size, top, recurse)
3365 for (count = size = 0, obj = chain; obj; obj = obj->nobj) {
3368 size += size_obj(obj);
3370 if (recurse && obj->cobj)
3371 count_obj(obj->cobj, total_count, total_size, TRUE, TRUE);
3373 *total_count += count;
3374 *total_size += size;
3378 obj_chain(win, src, chain, total_count, total_size)
3386 long count = 0, size = 0;
3388 count_obj(chain, &count, &size, TRUE, FALSE);
3389 *total_count += count;
3390 *total_size += size;
3391 Sprintf(buf, template, src, count, size);
3392 putstr(win, 0, buf);
3396 mon_invent_chain(win, src, chain, total_count, total_size)
3399 struct monst *chain;
3404 long count = 0, size = 0;
3407 for (mon = chain; mon; mon = mon->nmon)
3408 count_obj(mon->minvent, &count, &size, TRUE, FALSE);
3409 *total_count += count;
3410 *total_size += size;
3411 Sprintf(buf, template, src, count, size);
3412 putstr(win, 0, buf);
3416 contained(win, src, total_count, total_size)
3423 long count = 0, size = 0;
3426 count_obj(invent, &count, &size, FALSE, TRUE);
3427 count_obj(fobj, &count, &size, FALSE, TRUE);
3428 count_obj(level.buriedobjlist, &count, &size, FALSE, TRUE);
3429 count_obj(migrating_objs, &count, &size, FALSE, TRUE);
3430 /* DEADMONSTER check not required in this loop since they have no
3432 for (mon = fmon; mon; mon = mon->nmon)
3433 count_obj(mon->minvent, &count, &size, FALSE, TRUE);
3434 for (mon = migrating_mons; mon; mon = mon->nmon)
3435 count_obj(mon->minvent, &count, &size, FALSE, TRUE);
3437 *total_count += count;
3438 *total_size += size;
3440 Sprintf(buf, template, src, count, size);
3441 putstr(win, 0, buf);
3448 int sz = (int) sizeof(struct monst);
3451 sz += (int) sizeof(struct mextra);
3453 sz += (int) strlen(MNAME(mtmp)) + 1;
3455 sz += (int) sizeof(struct egd);
3457 sz += (int) sizeof(struct epri);
3459 sz += (int) sizeof(struct eshk);
3461 sz += (int) sizeof(struct emin);
3463 sz += (int) sizeof(struct edog);
3464 /* mextra->mcorpsenm doesn't point to more memory */
3470 mon_chain(win, src, chain, total_count, total_size)
3473 struct monst *chain;
3481 for (count = size = 0, mon = chain; mon; mon = mon->nmon) {
3483 size += size_monst(mon);
3485 *total_count += count;
3486 *total_size += size;
3487 Sprintf(buf, template, src, count, size);
3488 putstr(win, 0, buf);
3492 * Display memory usage of all monsters and objects on the level.
3499 long total_obj_size = 0, total_obj_count = 0;
3500 long total_mon_size = 0, total_mon_count = 0;
3502 win = create_nhwindow(NHW_TEXT);
3503 putstr(win, 0, "Current memory statistics:");
3505 Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj));
3506 putstr(win, 0, buf);
3508 putstr(win, 0, count_str);
3510 obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size);
3511 obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size);
3512 obj_chain(win, "buried", level.buriedobjlist, &total_obj_count,
3514 obj_chain(win, "migrating obj", migrating_objs, &total_obj_count,
3516 mon_invent_chain(win, "minvent", fmon, &total_obj_count, &total_obj_size);
3517 mon_invent_chain(win, "migrating minvent", migrating_mons,
3518 &total_obj_count, &total_obj_size);
3520 contained(win, "contained", &total_obj_count, &total_obj_size);
3522 putstr(win, 0, separator);
3523 Sprintf(buf, template, "Total", total_obj_count, total_obj_size);
3524 putstr(win, 0, buf);
3528 Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst));
3529 putstr(win, 0, buf);
3532 mon_chain(win, "fmon", fmon, &total_mon_count, &total_mon_size);
3533 mon_chain(win, "migrating", migrating_mons, &total_mon_count,
3536 putstr(win, 0, separator);
3537 Sprintf(buf, template, "Total", total_mon_count, total_mon_size);
3538 putstr(win, 0, buf);
3540 #if defined(__BORLANDC__) && !defined(_WIN32)
3541 show_borlandc_stats(win);
3544 display_nhwindow(win, FALSE);
3545 destroy_nhwindow(win);
3553 timer_sanity_check();
3555 light_sources_sanity_check();
3558 #ifdef DEBUG_MIGRATING_MONS
3564 struct permonst *ptr;
3568 getlin("How many random monsters to migrate? [0]", inbuf);
3569 if (*inbuf == '\033')
3571 mcount = atoi(inbuf);
3572 if (mcount < 0 || mcount > (COLNO * ROWNO) || Is_botlevel(&u.uz))
3574 while (mcount > 0) {
3575 if (Is_stronghold(&u.uz))
3576 assign_level(&tolevel, &valley_level);
3578 get_level(&tolevel, depth(&u.uz) + 1);
3580 mtmp = makemon(ptr, 0, 0, NO_MM_FLAGS);
3582 migrate_to_level(mtmp, ledger_no(&tolevel), MIGR_RANDOM,
3590 #define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
3591 #define unmeta(c) (0x7f & (c))
3593 /* called at startup and after number_pad is twiddled */
3595 reset_commands(initial)
3598 static const char sdir[] = "hykulnjb><",
3599 sdir_swap_yz[] = "hzkulnjb><",
3600 ndir[] = "47896321><",
3601 ndir_phone_layout[] = "41236987><";
3602 static const int ylist[] = {
3603 'y', 'Y', C('y'), M('y'), M('Y'), M(C('y'))
3605 const struct func_tab *cmdtmp;
3607 int c, i, updated = 0;
3611 for (i = 0; i < SIZE(cmdlist); i++) {
3612 c = cmdlist[i].f_char & 0xff;
3613 Cmd.commands[c] = &cmdlist[i];
3615 Cmd.num_pad = FALSE;
3616 Cmd.pcHack_compat = Cmd.phone_layout = Cmd.swap_yz = FALSE;
3619 flagtemp = iflags.num_pad;
3620 if (flagtemp != Cmd.num_pad) {
3621 Cmd.num_pad = flagtemp;
3624 /* swap_yz mode (only applicable for !num_pad) */
3625 flagtemp = (iflags.num_pad_mode & 1) ? !Cmd.num_pad : FALSE;
3626 if (flagtemp != Cmd.swap_yz) {
3627 Cmd.swap_yz = flagtemp;
3629 /* Cmd.swap_yz has been toggled;
3630 perform the swap (or reverse previous one) */
3631 for (i = 0; i < SIZE(ylist); i++) {
3632 c = ylist[i] & 0xff;
3633 cmdtmp = Cmd.commands[c]; /* tmp = [y] */
3634 Cmd.commands[c] = Cmd.commands[c + 1]; /* [y] = [z] */
3635 Cmd.commands[c + 1] = cmdtmp; /* [z] = tmp */
3638 /* MSDOS compatibility mode (only applicable for num_pad) */
3639 flagtemp = (iflags.num_pad_mode & 1) ? Cmd.num_pad : FALSE;
3640 if (flagtemp != Cmd.pcHack_compat) {
3641 Cmd.pcHack_compat = flagtemp;
3643 /* pcHack_compat has been toggled */
3645 cmdtmp = Cmd.commands['5'];
3646 Cmd.commands['5'] = Cmd.commands[c];
3647 Cmd.commands[c] = cmdtmp;
3649 Cmd.commands[c] = Cmd.pcHack_compat ? Cmd.commands['I'] : 0;
3651 /* phone keypad layout (only applicable for num_pad) */
3652 flagtemp = (iflags.num_pad_mode & 2) ? Cmd.num_pad : FALSE;
3653 if (flagtemp != Cmd.phone_layout) {
3654 Cmd.phone_layout = flagtemp;
3656 /* phone_layout has been toggled */
3657 for (i = 0; i < 3; i++) {
3658 c = '1' + i; /* 1,2,3 <-> 7,8,9 */
3659 cmdtmp = Cmd.commands[c]; /* tmp = [1] */
3660 Cmd.commands[c] = Cmd.commands[c + 6]; /* [1] = [7] */
3661 Cmd.commands[c + 6] = cmdtmp; /* [7] = tmp */
3662 c = (M('1') & 0xff) + i; /* M-1,M-2,M-3 <-> M-7,M-8,M-9 */
3663 cmdtmp = Cmd.commands[c]; /* tmp = [M-1] */
3664 Cmd.commands[c] = Cmd.commands[c + 6]; /* [M-1] = [M-7] */
3665 Cmd.commands[c + 6] = cmdtmp; /* [M-7] = tmp */
3672 Cmd.dirchars = !Cmd.num_pad
3673 ? (!Cmd.swap_yz ? sdir : sdir_swap_yz)
3674 : (!Cmd.phone_layout ? ndir : ndir_phone_layout);
3675 Cmd.alphadirchars = !Cmd.num_pad ? Cmd.dirchars : sdir;
3677 Cmd.move_W = Cmd.dirchars[0];
3678 Cmd.move_NW = Cmd.dirchars[1];
3679 Cmd.move_N = Cmd.dirchars[2];
3680 Cmd.move_NE = Cmd.dirchars[3];
3681 Cmd.move_E = Cmd.dirchars[4];
3682 Cmd.move_SE = Cmd.dirchars[5];
3683 Cmd.move_S = Cmd.dirchars[6];
3684 Cmd.move_SW = Cmd.dirchars[7];
3688 accept_menu_prefix(cmd_func)
3689 int NDECL((*cmd_func));
3691 if (cmd_func == dopickup || cmd_func == dotip
3692 || cmd_func == doextcmd || cmd_func == doextlist)
3701 boolean do_walk, do_rush, prefix_seen, bad_command,
3702 firsttime = (cmd == 0);
3704 iflags.menu_requested = FALSE;
3706 if (program_state.done_hup)
3713 if (*cmd == '\033') {
3714 context.move = FALSE;
3717 if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
3720 rhack((char *) 0); /* read and execute command */
3724 /* Special case of *cmd == ' ' handled better below */
3725 if (!*cmd || *cmd == (char) 0377) {
3727 context.move = FALSE;
3728 return; /* probably we just had an interrupt */
3731 /* handle most movement commands */
3732 do_walk = do_rush = prefix_seen = FALSE;
3733 context.travel = context.travel1 = 0;
3736 if (movecmd(cmd[1])) {
3744 break; /* else FALLTHRU */
3746 if (movecmd(lowc(cmd[1]))) {
3754 break; /* else FALLTHRU */
3755 /* Effects of movement commands and invisible monsters:
3756 * m: always move onto space (even if 'I' remembered)
3757 * F: always attack space (even if 'I' not remembered)
3758 * normal movement: attack if 'I', move otherwise.
3761 if (movecmd(cmd[1])) {
3762 context.forcefight = 1;
3768 if (movecmd(cmd[1]) || u.dz) {
3774 cmd[0] = cmd[1]; /* "m<" or "m>" */
3779 if (movecmd(lowc(cmd[1]))) {
3789 (void) ddoinv(); /* a convenience borrowed from the PC */
3790 context.move = FALSE;
3794 if (iflags.clicklook) {
3795 context.move = FALSE;
3796 do_look(2, &clicklook_cc);
3800 if (flags.travelcmd) {
3802 context.travel1 = 1;
3810 if (movecmd(*cmd)) { /* ordinary movement */
3811 context.run = 0; /* only matters here if it was 8 */
3813 } else if (movecmd(Cmd.num_pad ? unmeta(*cmd) : lowc(*cmd))) {
3816 } else if (movecmd(unctrl(*cmd))) {
3823 /* some special prefix handling */
3824 /* overload 'm' prefix to mean "request a menu" */
3825 if (prefix_seen && cmd[0] == 'm') {
3826 /* (for func_tab cast, see below) */
3827 const struct func_tab *ft = Cmd.commands[cmd[1] & 0xff];
3828 int NDECL((*func)) = ft ? ((struct func_tab *) ft)->f_funct : 0;
3830 if (func && accept_menu_prefix(func)) {
3831 iflags.menu_requested = TRUE;
3836 if ((do_walk || do_rush) && !context.travel && !dxdy_moveok()) {
3837 /* trying to move diagonally as a grid bug;
3838 this used to be treated by movecmd() as not being
3839 a movement attempt, but that didn't provide for any
3840 feedback and led to strangeness if the key pressed
3841 ('u' in particular) was overloaded for num_pad use */
3842 You_cant("get there from here...");
3844 context.nopick = context.forcefight = FALSE;
3845 context.move = context.mv = FALSE;
3854 context.forcefight = 0;
3856 } else if (do_rush) {
3859 multi = max(COLNO, ROWNO);
3860 u.last_str_turn = 0;
3865 } else if (prefix_seen && cmd[1] == '\033') { /* <prefix><escape> */
3866 /* don't report "unknown command" for change of heart... */
3867 bad_command = FALSE;
3868 } else if (*cmd == ' ' && !flags.rest_on_space) {
3869 bad_command = TRUE; /* skip cmdlist[] loop */
3871 /* handle all other commands */
3873 register const struct func_tab *tlist;
3874 int res, NDECL((*func));
3877 /* obsolete - scan through the cmdlist array looking for *cmd */
3878 for (tlist = cmdlist; tlist->f_char; tlist++) {
3879 if ((*cmd & 0xff) != (tlist->f_char & 0xff))
3882 /* current - use *cmd to directly index cmdlist array */
3883 if ((tlist = Cmd.commands[*cmd & 0xff]) != 0) {
3885 if (u.uburied && !tlist->can_if_buried) {
3887 You_cant("do that while you are buried!");
3889 You("
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é
\8e\9e\82É
\82»
\82ñ
\82È
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81I");
3892 /* we discard 'const' because some compilers seem to have
3893 trouble with the pointer passed to set_occupation() */
3894 func = ((struct func_tab *) tlist)->f_funct;
3895 if (tlist->f_text && !occupation && multi)
3896 set_occupation(func, tlist->f_text, multi);
3897 res = (*func)(); /* perform the command */
3900 context.move = FALSE;
3905 /* if we reach here, cmd wasn't found in cmdlist[] */
3911 register char c, *cp = expcmd;
3913 while ((c = *cmd++) != '\0'
3914 && (int) (cp - expcmd) < (int) (sizeof expcmd - 3)) {
3915 if (c >= 040 && c < 0177) {
3917 } else if (c & 0200) {
3927 if (!prefix_seen || !iflags.cmdassist
3929 || !help_dir(0, "Invalid direction key!"))
3931 || !help_dir(0, "
\96³
\8cø
\82È
\95û
\8cü
\8ew
\92è
\82Å
\82·
\81I"))
3933 Norep("Unknown command '%s'.", expcmd);
3935 Norep("'%s'
\83R
\83}
\83\93\83h
\81H", expcmd);
3938 context.move = FALSE;
3943 /* convert an x,y pair into a direction code */
3950 for (dd = 0; dd < 8; dd++)
3951 if (x == xdir[dd] && y == ydir[dd])
3956 /* convert a direction code into an x,y pair */
3967 /* also sets u.dz, but returns false for <> */
3972 register const char *dp = index(Cmd.dirchars, sym);
3977 u.dx = xdir[dp - Cmd.dirchars];
3978 u.dy = ydir[dp - Cmd.dirchars];
3979 u.dz = zdir[dp - Cmd.dirchars];
3980 #if 0 /* now handled elsewhere */
3981 if (u.dx && u.dy && NODIAG(u.umonnum)) {
3989 /* grid bug handling which used to be in movecmd() */
3993 if (u.dx && u.dy && NODIAG(u.umonnum))
3995 return u.dx || u.dy;
3998 /* decide whether a character (user input keystroke) requests screen repaint */
4003 return (boolean) (c == C('r') || (Cmd.num_pad && c == C('l')));
4007 * uses getdir() but unlike getdir() it specifically
4008 * produces coordinates using the direction from getdir()
4009 * and verifies that those coordinates are ok.
4011 * If the call to getdir() returns 0, Never_mind is displayed.
4012 * If the resulting coordinates are not okay, emsg is displayed.
4014 * Returns non-zero if coordinates in cc are valid.
4017 get_adjacent_loc(prompt, emsg, x, y, cc)
4018 const char *prompt, *emsg;
4023 if (!getdir(prompt)) {
4029 if (cc && isok(new_x, new_y)) {
4048 if (in_doagain || *readchar_queue)
4049 dirsym = readchar();
4052 dirsym = yn_function((s && *s != '^') ? s : "In what direction?",
4054 dirsym = yn_function((s && *s != '^') ? s : "
\82Ç
\82Ì
\95û
\8cü
\81H",
4056 /* remove the prompt string so caller won't have to */
4057 clear_nhwindow(WIN_MESSAGE);
4059 if (redraw_cmd(dirsym)) { /* ^R */
4060 docrt(); /* redraw */
4065 if (dirsym == '.' || dirsym == 's') {
4066 u.dx = u.dy = u.dz = 0;
4067 } else if (!(is_mov = movecmd(dirsym)) && !u.dz) {
4068 boolean did_help = FALSE, help_requested;
4070 if (!index(quitchars, dirsym)) {
4071 help_requested = (dirsym == '?');
4072 if (help_requested || iflags.cmdassist) {
4074 help_dir((s && *s == '^') ? dirsym : 0,
4075 help_requested ? (const char *) 0
4077 : "Invalid direction key!");
4079 : "
\96³
\8cø
\82È
\95û
\8cü
\8ew
\92è
\82Å
\82·
\81I");
4085 pline("What a strange direction!");
4087 pline("
\82¸
\82¢
\82Ô
\82ñ
\82Æ
\8aï
\96
\82È
\95û
\8cü
\82¾
\81I");
4090 } else if (is_mov && !dxdy_moveok()) {
4092 You_cant("orient yourself that direction.");
4094 You_cant("
\8cü
\82«
\82É
\8e©
\95ª
\8e©
\90g
\82ð
\8ew
\92è
\82Å
\82«
\82È
\82¢
\81D");
4097 if (!u.dz && (Stunned || (Confusion && !rn2(5))))
4109 static const char wiz_only_list[] = "EFGIOVW";
4110 char buf[BUFSZ], buf2[BUFSZ], *explain;
4112 win = create_nhwindow(NHW_TEXT);
4116 Sprintf(buf, "cmdassist: %s", msg);
4117 putstr(win, 0, buf);
4122 ctrl = (sym - 'A') + 1;
4123 if ((explain = dowhatdoes_core(ctrl, buf2))
4124 && (!index(wiz_only_list, sym) || wizard)) {
4125 Sprintf(buf, "Are you trying to use ^%c%s?", sym,
4126 index(wiz_only_list, sym)
4128 : " as specified in the Guidebook");
4129 putstr(win, 0, buf);
4131 putstr(win, 0, explain);
4133 putstr(win, 0, "To use that command, you press");
4134 Sprintf(buf, "the <Ctrl> key, and the <%c> key at the same time.",
4136 putstr(win, 0, buf);
4140 if (NODIAG(u.umonnum)) {
4141 putstr(win, 0, "Valid direction keys in your current form are:");
4142 Sprintf(buf, " %c ", Cmd.move_N);
4143 putstr(win, 0, buf);
4144 putstr(win, 0, " | ");
4145 Sprintf(buf, " %c- . -%c", Cmd.move_W, Cmd.move_E);
4146 putstr(win, 0, buf);
4147 putstr(win, 0, " | ");
4148 Sprintf(buf, " %c ", Cmd.move_S);
4149 putstr(win, 0, buf);
4151 putstr(win, 0, "Valid direction keys are:");
4152 Sprintf(buf, " %c %c %c", Cmd.move_NW, Cmd.move_N,
4154 putstr(win, 0, buf);
4155 putstr(win, 0, " \\ | / ");
4156 Sprintf(buf, " %c- . -%c", Cmd.move_W, Cmd.move_E);
4157 putstr(win, 0, buf);
4158 putstr(win, 0, " / | \\ ");
4159 Sprintf(buf, " %c %c %c", Cmd.move_SW, Cmd.move_S,
4161 putstr(win, 0, buf);
4164 putstr(win, 0, " < up");
4165 putstr(win, 0, " > down");
4166 putstr(win, 0, " . direct at yourself");
4168 /* non-null msg means that this wasn't an explicit user request */
4172 "(Suppress this message with !cmdassist in config file.)");
4174 "(
\82±
\82Ì
\83\81\83b
\83Z
\81[
\83W
\82ð
\95\
\8e¦
\82µ
\82½
\82
\82È
\82¢
\8fê
\8d\87\82Í
\90Ý
\92è
\83t
\83@
\83C
\83\8b\82É !cmdassist
\82ð
\90Ý
\92è
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81D)");
4176 display_nhwindow(win, FALSE);
4177 destroy_nhwindow(win);
4184 register int x = NODIAG(u.umonnum) ? 2 * rn2(4) : rn2(8);
4195 static NEARDATA const char *const dirnames[] = {
4196 "west", "northwest", "north", "northeast", "east",
4197 "southeast", "south", "southwest", "down", "up",
4200 if (dir < 0 || dir >= SIZE(dirnames))
4202 return dirnames[dir];
4209 /* x corresponds to curx, so x==1 is the first column. Ach. %% */
4210 return x >= 1 && x <= COLNO - 1 && y >= 0 && y <= ROWNO - 1;
4213 static NEARDATA int last_multi;
4216 * convert a MAP window position into a movecmd
4219 click_to_cmd(x, y, mod)
4226 if (iflags.clicklook && mod == CLICK_2) {
4229 cmd[0] = CMD_CLICKLOOK;
4236 if (flags.travelcmd) {
4237 if (abs(x) <= 1 && abs(y) <= 1) {
4238 x = sgn(x), y = sgn(y);
4242 cmd[0] = CMD_TRAVEL;
4246 if (x == 0 && y == 0) {
4248 if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)
4249 || IS_SINK(levl[u.ux][u.uy].typ)) {
4250 cmd[0] = mod == CLICK_1 ? 'q' : M('d');
4252 } else if (IS_THRONE(levl[u.ux][u.uy].typ)) {
4255 } else if ((u.ux == xupstair && u.uy == yupstair)
4256 || (u.ux == sstairs.sx && u.uy == sstairs.sy
4258 || (u.ux == xupladder && u.uy == yupladder)) {
4260 } else if ((u.ux == xdnstair && u.uy == ydnstair)
4261 || (u.ux == sstairs.sx && u.uy == sstairs.sy
4263 || (u.ux == xdnladder && u.uy == ydnladder)) {
4265 } else if (OBJ_AT(u.ux, u.uy)) {
4267 Is_container(level.objects[u.ux][u.uy]) ? M('l') : ',';
4270 return "."; /* just rest */
4274 /* directional commands */
4278 if (!m_at(u.ux + x, u.uy + y)
4279 && !test_move(u.ux, u.uy, x, y, TEST_MOVE)) {
4280 cmd[1] = Cmd.dirchars[dir];
4282 if (IS_DOOR(levl[u.ux + x][u.uy + y].typ)) {
4283 /* slight assistance to the player: choose kick/open for them
4285 if (levl[u.ux + x][u.uy + y].doormask & D_LOCKED) {
4289 if (levl[u.ux + x][u.uy + y].doormask & D_CLOSED) {
4294 if (levl[u.ux + x][u.uy + y].typ <= SCORR) {
4301 /* convert without using floating point, allowing sloppy clicking */
4304 else if (y > 2 * abs(x))
4306 else if (x < -2 * abs(y))
4308 else if (y < -2 * abs(x))
4311 x = sgn(x), y = sgn(y);
4313 if (x == 0 && y == 0) /* map click on player to "rest" command */
4319 /* move, attack, etc. */
4321 if (mod == CLICK_1) {
4322 cmd[0] = Cmd.dirchars[dir];
4324 cmd[0] = (Cmd.num_pad
4325 ? M(Cmd.dirchars[dir])
4326 : (Cmd.dirchars[dir] - 'a' + 'A')); /* run command */
4335 #ifdef LINT /* static char in_line[COLNO]; */
4336 char in_line[COLNO];
4338 static char in_line[COLNO];
4341 boolean prezero = FALSE;
4345 flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
4348 alt_esc = iflags.altmeta; /* readchar() hack */
4350 if (!Cmd.num_pad || (foo = readchar()) == 'n')
4353 if (foo >= '0' && foo <= '9') {
4354 multi = 10 * multi + foo - '0';
4355 if (multi < 0 || multi >= LARGEST_INT)
4356 multi = LARGEST_INT;
4358 clear_nhwindow(WIN_MESSAGE);
4360 Sprintf(in_line, "Count: %d", multi);
4362 Sprintf(in_line, "
\90\94: %d", multi);
4367 if (!multi && foo == '0')
4370 break; /* not a digit */
4373 alt_esc = FALSE; /* readchar() reset */
4376 if (foo == '\033') { /* esc cancels count (TH) */
4377 clear_nhwindow(WIN_MESSAGE);
4378 multi = last_multi = 0;
4379 } else if (foo == DOAGAIN || in_doagain) {
4383 savech(0); /* reset input queue */
4391 save_cm = (char *) 0;
4393 /* in 3.4.3 this was in rhack(), where it was too late to handle M-5 */
4394 if (Cmd.pcHack_compat) {
4395 /* This handles very old inconsistent DOS/Windows behaviour
4396 in a different way: earlier, the keyboard handler mapped
4397 these, which caused counts to be strange when entered
4398 from the number pad. Now do not map them until here. */
4416 if (foo == 'g' || foo == 'G' || foo == 'm' || foo == 'M' || foo == 'F'
4417 || (Cmd.num_pad && (foo == '5' || foo == '-'))) {
4423 clear_nhwindow(WIN_MESSAGE);
4425 in_line[0] = '\033';
4429 #ifdef HANGUPHANDLING
4430 /* some very old systems, or descendents of such systems, expect signal
4431 handlers to have return type `int', but they don't actually inspect
4432 the return value so we should be safe using `void' unconditionally */
4435 hangup(sig_unused) /* called as signal() handler, so sent at least one arg */
4436 int sig_unused UNUSED;
4438 if (program_state.exiting)
4439 program_state.in_moveloop = 0;
4442 /* When using SAFERHANGUP, the done_hup flag it tested in rhack
4443 and a couple of other places; actual hangup handling occurs then.
4444 This is 'safer' because it disallows certain cheats and also
4445 protects against losing objects in the process of being thrown,
4446 but also potentially riskier because the disconnected program
4447 must continue running longer before attempting a hangup save. */
4448 program_state.done_hup++;
4449 /* defer hangup iff game appears to be in progress */
4450 if (program_state.in_moveloop && program_state.something_worth_saving)
4452 #endif /* SAFERHANGUP */
4459 #ifdef NOSAVEONHANGUP
4461 if (flags.ins_chkpt && program_state.something_worth_saving)
4462 program_statue.preserve_locks = 1; /* keep files for recovery */
4464 program_state.something_worth_saving = 0; /* don't save */
4468 if (!program_state.done_hup++)
4470 if (program_state.something_worth_saving)
4472 if (iflags.window_inited)
4473 exit_nhwindows((char *) 0);
4475 terminate(EXIT_SUCCESS);
4476 /*NOTREACHED*/ /* not necessarily true for vms... */
4479 #endif /* HANGUPHANDLING */
4485 int x = u.ux, y = u.uy, mod = 0;
4487 if (*readchar_queue)
4488 sym = *readchar_queue++;
4490 sym = in_doagain ? pgetchar() : nh_poskey(&x, &y, &mod);
4494 register int cnt = NR_OF_EOFS;
4496 * Some SYSV systems seem to return EOFs for various reasons
4497 * (?like when one hits break or for interrupted systemcalls?),
4498 * and we must see several before we quit.
4501 clearerr(stdin); /* omit if clearerr is undefined */
4503 } while (--cnt && sym == EOF);
4505 #endif /* NR_OF_EOFS */
4508 #ifdef HANGUPHANDLING
4509 hangup(0); /* call end_of_input() or set program_state.done_hup */
4513 } else if (sym == '\033' && alt_esc) {
4514 /* iflags.altmeta: treat two character ``ESC c'' as single `M-c' */
4515 sym = *readchar_queue ? *readchar_queue++ : pgetchar();
4516 if (sym == EOF || sym == 0)
4518 else if (sym != '\033')
4519 sym |= 0200; /* force 8th bit on */
4521 } else if (sym == 0) {
4523 readchar_queue = click_to_cmd(x, y, mod);
4524 sym = *readchar_queue++;
4532 /* Keyboard travel command */
4536 if (!flags.travelcmd)
4539 cc.x = iflags.travelcc.x;
4540 cc.y = iflags.travelcc.y;
4541 if (cc.x == -1 && cc.y == -1) {
4542 /* No cached destination, start attempt from current position */
4547 pline("Where do you want to travel to?");
4549 pline("
\82Ç
\82±
\82É
\88Ú
\93®
\82·
\82é
\81H");
4551 if (getpos(&cc, TRUE, "the desired destination") < 0) {
4553 if (getpos(&cc, TRUE, "
\88Ú
\93®
\90æ") < 0) {
4554 /* user pressed ESC */
4557 iflags.travelcc.x = u.tx = cc.x;
4558 iflags.travelcc.y = u.ty = cc.y;
4559 cmd[0] = CMD_TRAVEL;
4560 readchar_queue = cmd;
4565 extern void NDECL(win32con_debug_keystrokes);
4566 extern void NDECL(win32con_handler_info);
4575 int num_menu_selections;
4576 struct menu_selection_struct {
4579 } menu_selections[] = {
4581 { "test win32 keystrokes (tty only)", win32con_debug_keystrokes },
4582 { "show keystroke handler information (tty only)",
4583 win32con_handler_info },
4585 { (char *) 0, (void NDECL((*) )) 0 } /* array terminator */
4588 num_menu_selections = SIZE(menu_selections) - 1;
4589 if (num_menu_selections > 0) {
4590 menu_item *pick_list;
4591 win = create_nhwindow(NHW_MENU);
4593 for (k = 0; k < num_menu_selections; ++k) {
4595 add_menu(win, NO_GLYPH, &any, item++, 0, ATR_NONE,
4596 menu_selections[k].menutext, MENU_UNSELECTED);
4598 end_menu(win, "Which port debugging feature?");
4599 n = select_menu(win, PICK_ONE, &pick_list);
4600 destroy_nhwindow(win);
4602 n = pick_list[0].item.a_int - 1;
4603 free((genericptr_t) pick_list);
4604 /* execute the function */
4605 (*menu_selections[n].fn)();
4608 pline("No port-specific debug capability defined.");
4611 #endif /*PORT_DEBUG*/
4614 * Parameter validator for generic yes/no function to prevent
4615 * the core from sending too long a prompt string to the
4616 * window port causing a buffer overflow there.
4619 yn_function(query, resp, def)
4620 const char *query, *resp;
4625 iflags.last_msg = PLNMSG_UNKNOWN; /* most recent pline is clobbered */
4627 /* maximum acceptable length is QBUFSZ-1 */
4628 if (strlen(query) < QBUFSZ)
4629 return (*windowprocs.win_yn_function)(query, resp, def);
4631 /* caller shouldn't have passed anything this long */
4632 paniclog("Query truncated: ", query);
4633 (void) strncpy(qbuf, query, QBUFSZ - 1 - 3);
4634 Strcpy(&qbuf[QBUFSZ - 1 - 3], "...");
4635 return (*windowprocs.win_yn_function)(qbuf, resp, def);
4638 /* for paranoid_confirm:quit,die,attack prompting */
4640 paranoid_query(be_paranoid, prompt)
4641 boolean be_paranoid;
4644 boolean confirmed_ok;
4646 /* when paranoid, player must respond with "yes" rather than just 'y'
4647 to give the go-ahead for this query; default is "no" unless the
4648 ParanoidConfirm flag is set in which case there's no default */
4650 char qbuf[QBUFSZ], ans[BUFSZ];
4651 const char *promptprefix = "", *responsetype = ParanoidConfirm
4654 int trylimit = 6; /* 1 normal, 5 more with "Yes or No:" prefix */
4656 /* in addition to being paranoid about this particular
4657 query, we might be even more paranoid about all paranoia
4658 responses (ie, ParanoidConfirm is set) in which case we
4659 require "no" to reject in addition to "yes" to confirm
4660 (except we won't loop if response is ESC; it means no) */
4662 Sprintf(qbuf, "%s%s %s", promptprefix, prompt, responsetype);
4664 (void) mungspaces(ans);
4665 confirmed_ok = !strcmpi(ans, "yes");
4666 if (confirmed_ok || *ans == '\033')
4668 promptprefix = "\"Yes\" or \"No\": ";
4669 } while (ParanoidConfirm && strcmpi(ans, "no") && --trylimit);
4671 confirmed_ok = (yn(prompt) == 'y');
4673 return confirmed_ok;
4680 /* Does current window system support suspend? */
4681 if ((*windowprocs.win_can_suspend)()) {
4682 /* NB: SYSCF SHELLERS handled in port code. */
4686 Norep("Suspend command not available.");