OSDN Git Service

patch artifact
[jnethack/source.git] / src / cmd.c
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. */
4
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. */
9
10 #include "hack.h"
11 #include "func_tab.h"
12
13 #ifdef ALTMETA
14 STATIC_VAR boolean alt_esc = FALSE;
15 #endif
16
17 struct cmd Cmd = { 0 }; /* flag.h */
18
19 extern const char *hu_stat[];  /* hunger status from eat.c */
20 extern const char *enc_stat[]; /* encumbrance status from botl.c */
21
22 #ifdef UNIX
23 /*
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.
26  */
27 #if defined(SYSV) || defined(DGUX) || defined(HPUX)
28 #define NR_OF_EOFS 20
29 #endif
30 #endif
31
32 #define CMD_TRAVEL (char) 0x90
33 #define CMD_CLICKLOOK (char) 0x8F
34
35 #ifdef DEBUG
36 extern int NDECL(wiz_debug_cmd_bury);
37 extern int NDECL(wiz_debug_cmd_traveldisplay);
38 #endif
39
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);         /**/
115 #endif                                /* DUMB */
116
117 static int NDECL(dosuspend_core); /**/
118
119 static int NDECL((*timed_occ_fn));
120
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));
147 #endif
148 #ifdef DEBUG_MIGRATING_MONS
149 STATIC_PTR int NDECL(wiz_migrate_mons);
150 #endif
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 *,
156                                   long *, long *));
157 STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *,
158                                          long *, long *));
159 STATIC_DCL void FDECL(mon_chain, (winid, const char *, struct monst *,
160                                   long *, long *));
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((*))));
164 #ifdef PORT_DEBUG
165 STATIC_DCL int NDECL(wiz_port_debug);
166 #endif
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); /**/
171
172 STATIC_DCL void FDECL(enlght_line, (const char *, const char *, const char *,
173                                     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));
184
185 static const char *readchar_queue = "";
186 static coord clicklook_cc;
187
188 STATIC_DCL char *NDECL(parse);
189 STATIC_DCL boolean FDECL(help_dir, (CHAR_P, const char *));
190
191 STATIC_PTR int
192 doprev_message(VOID_ARGS)
193 {
194     return nh_doprev_message();
195 }
196
197 /* Count down by decrementing multi */
198 STATIC_PTR int
199 timed_occupation(VOID_ARGS)
200 {
201     (*timed_occ_fn)();
202     if (multi > 0)
203         multi--;
204     return multi > 0;
205 }
206
207 /* If you have moved since initially setting some occupations, they
208  * now shouldn't be able to restart.
209  *
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.
213  *
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.
216  *
217  *      Currently:      Take off all armor.
218  *                      Picking Locks / Forcing Chests.
219  *                      Setting traps.
220  */
221 void
222 reset_occupations()
223 {
224     reset_remarm();
225     reset_pick();
226     reset_trapset();
227 }
228
229 /* If a time is given, use it to timeout this function, otherwise the
230  * function times out by its own means.
231  */
232 void
233 set_occupation(fn, txt, xtime)
234 int NDECL((*fn));
235 const char *txt;
236 int xtime;
237 {
238     if (xtime) {
239         occupation = timed_occupation;
240         timed_occ_fn = fn;
241     } else
242         occupation = fn;
243     occtxt = txt;
244     occtime = 0;
245     return;
246 }
247
248 STATIC_DCL char NDECL(popch);
249
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.
255  */
256 #define BSIZE 20
257 static char pushq[BSIZE], saveq[BSIZE];
258 static NEARDATA int phead, ptail, shead, stail;
259
260 STATIC_OVL char
261 popch()
262 {
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.
267      */
268     if (occupation)
269         return '\0';
270     if (in_doagain)
271         return (char) ((shead != stail) ? saveq[stail++] : '\0');
272     else
273         return (char) ((phead != ptail) ? pushq[ptail++] : '\0');
274 }
275
276 char
277 pgetchar() /* courtesy of aeb@cwi.nl */
278 {
279     register int ch;
280
281     if (!(ch = popch()))
282         ch = nhgetch();
283     return (char) ch;
284 }
285
286 /* A ch == 0 resets the pushq */
287 void
288 pushch(ch)
289 char ch;
290 {
291     if (!ch)
292         phead = ptail = 0;
293     if (phead < BSIZE)
294         pushq[phead++] = ch;
295     return;
296 }
297
298 /* A ch == 0 resets the saveq.  Only save keystrokes when not
299  * replaying a previous command.
300  */
301 void
302 savech(ch)
303 char ch;
304 {
305     if (!in_doagain) {
306         if (!ch)
307             phead = ptail = shead = stail = 0;
308         else if (shead < BSIZE)
309             saveq[shead++] = ch;
310     }
311     return;
312 }
313
314 /* here after # - now read a full-word command */
315 STATIC_PTR int
316 doextcmd(VOID_ARGS)
317 {
318     int idx, retval;
319     int NDECL((*func));
320
321     /* keep repeating until we don't run help or quit */
322     do {
323         idx = get_ext_cmd();
324         if (idx < 0)
325             return 0; /* quit */
326
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;
331         }
332         retval = (*func)();
333     } while (func == doextlist);
334
335     return retval;
336 }
337
338 /* here after #? - now list all full-word commands */
339 int
340 doextlist(VOID_ARGS)
341 {
342     register const struct ext_func_tab *efp;
343     char buf[BUFSZ];
344     winid datawin;
345
346     datawin = create_nhwindow(NHW_TEXT);
347     putstr(datawin, 0, "");
348 /*JP
349     putstr(datawin, 0, "            Extended Commands List");
350 */
351     putstr(datawin, 0, "            \8ag\92£\83R\83}\83\93\83h\88ê\97\97");
352     putstr(datawin, 0, "");
353 /*JP
354     putstr(datawin, 0, "    Press '#', then type:");
355 */
356     putstr(datawin, 0, "    '#'\82ð\89\9f\82µ\82½\82 \82Æ\83^\83C\83v\82¹\82æ:");
357     putstr(datawin, 0, "");
358
359     for (efp = extcmdlist; efp->ef_txt; efp++) {
360         Sprintf(buf, "    %-15s - %s.", efp->ef_txt, efp->ef_desc);
361         putstr(datawin, 0, buf);
362     }
363     display_nhwindow(datawin, FALSE);
364     destroy_nhwindow(datawin);
365     return 0;
366 }
367
368 #ifdef TTY_GRAPHICS
369 #define MAX_EXT_CMD 50 /* Change if we ever have > 50 ext cmds */
370
371 /*
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.
376  *
377  * Here after # - now show pick-list of possible commands.
378  */
379 int
380 extcmd_via_menu()
381 {
382     const struct ext_func_tab *efp;
383     menu_item *pick_list = (menu_item *) 0;
384     winid win;
385     anything any;
386     const struct ext_func_tab *choices[MAX_EXT_CMD + 1];
387     char buf[BUFSZ];
388     char cbuf[QBUFSZ], prompt[QBUFSZ], fmtstr[20];
389     int i, n, nchoices, acount;
390     int ret, biggest;
391     int accelerator, prevaccelerator;
392     int matchlevel = 0;
393
394     ret = 0;
395     cbuf[0] = '\0';
396     biggest = 0;
397     while (!ret) {
398         i = n = 0;
399         any = zeroany;
400         /* populate choices */
401         for (efp = extcmdlist; efp->ef_txt; efp++) {
402             if (!matchlevel || !strncmp(efp->ef_txt, cbuf, matchlevel)) {
403                 choices[i] = efp;
404                 if ((int) strlen(efp->ef_desc) > biggest) {
405                     biggest = strlen(efp->ef_desc);
406                     Sprintf(fmtstr, "%%-%ds", biggest + 15);
407                 }
408                 if (++i > MAX_EXT_CMD) {
409 #if defined(BETA)
410                     impossible(
411       "Exceeded %d extended commands in doextcmd() menu; 'extmenu' disabled.",
412                                MAX_EXT_CMD);
413 #endif /* BETA */
414                     iflags.extmenu = 0;
415                     return -1;
416                 }
417             }
418         }
419         choices[i] = (struct ext_func_tab *) 0;
420         nchoices = i;
421         /* if we're down to one, we have our selection so get out of here */
422         if (nchoices == 1) {
423             for (i = 0; extcmdlist[i].ef_txt != (char *) 0; i++)
424                 if (!strncmpi(extcmdlist[i].ef_txt, cbuf, matchlevel)) {
425                     ret = i;
426                     break;
427                 }
428             break;
429         }
430
431         /* otherwise... */
432         win = create_nhwindow(NHW_MENU);
433         start_menu(win);
434         accelerator = prevaccelerator = 0;
435         acount = 0;
436         for (i = 0; choices[i]; ++i) {
437             accelerator = choices[i]->ef_txt[matchlevel];
438             if (accelerator != prevaccelerator || nchoices < (ROWNO - 3)) {
439                 if (acount) {
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,
444                              buf, FALSE);
445                     acount = 0;
446                 }
447             }
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) {
453 /*JP
454                 Sprintf(prompt, "%s or %s", choices[i - 1]->ef_txt,
455 */
456                 Sprintf(prompt, "%s \82Ü\82½\82Í %s", choices[i-1]->ef_txt,
457                         choices[i]->ef_txt);
458             } else {
459 /*JP
460                 Strcat(prompt, " or ");
461 */
462                 Strcat(prompt," \82Ü\82½\82Í ");
463                 Strcat(prompt, choices[i]->ef_txt);
464             }
465             ++acount;
466         }
467         if (acount) {
468             /* flush buf */
469             Sprintf(buf, fmtstr, prompt);
470             any.a_char = prevaccelerator;
471             add_menu(win, NO_GLYPH, &any, any.a_char, 0, ATR_NONE, buf,
472                      FALSE);
473         }
474 /*JP
475         Sprintf(prompt, "Extended Command: %s", cbuf);
476 */
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);
481         if (n == 1) {
482             if (matchlevel > (QBUFSZ - 2)) {
483                 free((genericptr_t) pick_list);
484 #if defined(BETA)
485                 impossible("Too many chars (%d) entered in extcmd_via_menu()",
486                            matchlevel);
487 #endif
488                 ret = -1;
489             } else {
490                 cbuf[matchlevel++] = pick_list[0].item.a_char;
491                 cbuf[matchlevel] = '\0';
492                 free((genericptr_t) pick_list);
493             }
494         } else {
495             if (matchlevel) {
496                 ret = 0;
497                 matchlevel = 0;
498             } else
499                 ret = -1;
500         }
501     }
502     return ret;
503 }
504 #endif /* TTY_GRAPHICS */
505
506 /* #monster command - use special monster ability while polymorphed */
507 STATIC_PTR int
508 domonability(VOID_ARGS)
509 {
510     if (can_breathe(youmonst.data))
511         return dobreathe();
512     else if (attacktype(youmonst.data, AT_SPIT))
513         return dospit();
514     else if (youmonst.data->mlet == S_NYMPH)
515         return doremove();
516     else if (attacktype(youmonst.data, AT_GAZE))
517         return dogaze();
518     else if (is_were(youmonst.data))
519         return dosummon();
520     else if (webmaker(youmonst.data))
521         return dospinweb();
522     else if (is_hider(youmonst.data))
523         return dohide();
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);
530         } else
531 /*JP
532             There("is no fountain here.");
533 */
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);
537         return 1;
538     } else if (youmonst.data->msound == MS_SHRIEK) {
539 /*JP
540         You("shriek.");
541 */
542         You("\8bà\90Ø\82è\90º\82ð\82 \82°\82½\81D");
543         if (u.uburied)
544 /*JP
545             pline("Unfortunately sound does not carry well through rock.");
546 */
547             pline("\8ec\94O\82È\82ª\82ç\89¹\82Í\8aâ\82ð\82¤\82Ü\82­\93`\82í\82ç\82È\82¢\81D");
548         else
549             aggravate();
550     } else if (youmonst.data->mlet == S_VAMPIRE)
551         return dopoly();
552     else if (Upolyd)
553 /*JP
554         pline("Any special ability you may have is purely reflexive.");
555 */
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");
557     else
558 /*JP
559         You("don't have a special ability in your normal form!");
560 */
561         You("\95\81\92i\82Ì\8ep\82Å\82Ì\93Á\8eê\94\\97Í\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81I");
562     return 0;
563 }
564
565 int
566 enter_explore_mode(VOID_ARGS)
567 {
568     if (wizard) {
569 /*JP
570         You("are in debug mode.");
571 */
572         You("\82·\82Å\82É\83f\83o\83b\83O\83\82\81[\83h\82¾\81D");
573     } else if (discover) {
574 /*JP
575         You("are already in explore mode.");
576 */
577         You("\82·\82Å\82É\92T\8c\9f\83\82\81[\83h\82¾\81D");
578     } else {
579 #ifdef SYSCF
580 #if defined(UNIX)
581         if (!sysopt.explorers || !sysopt.explorers[0]
582             || !check_user_string(sysopt.explorers)) {
583 /*JP
584             You("cannot access explore mode.");
585 */
586             You("\92T\8c\9f\83\82\81[\83h\82É\83A\83N\83Z\83X\82Å\82«\82È\82¢\81D");
587             return 0;
588         }
589 #endif
590 #endif
591         pline(
592 /*JP
593         "Beware!  From explore mode there will be no return to normal game.");
594 */
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,
597 /*JP
598                            "Do you want to enter explore mode?")) {
599 */
600                            "\94­\8c©\83\82\81[\83h\82É\88Ú\82è\82Ü\82·\82©\81H")) {
601             clear_nhwindow(WIN_MESSAGE);
602 /*JP
603             You("are now in non-scoring explore mode.");
604 */
605             You("\83X\83R\83A\82ª\82Ì\82ç\82È\82¢\94­\8c©\83\82\81[\83h\82É\88Ú\8ds\82µ\82½\81D");
606             discover = TRUE;
607         } else {
608             clear_nhwindow(WIN_MESSAGE);
609 /*JP
610             pline("Resuming normal game.");
611 */
612             pline("\92Ê\8fí\83\82\81[\83h\82ð\91±\82¯\82é\81D");
613         }
614     }
615     return 0;
616 }
617
618 STATIC_PTR int
619 dooverview_or_wiz_where(VOID_ARGS)
620 {
621     if (wizard)
622         return wiz_where();
623     else
624         dooverview();
625     return 0;
626 }
627
628 /* ^W command - wish for something */
629 STATIC_PTR int
630 wiz_wish(VOID_ARGS) /* Unlimited wishes for debug mode by Paul Polderman */
631 {
632     if (wizard) {
633         boolean save_verbose = flags.verbose;
634
635         flags.verbose = FALSE;
636         makewish();
637         flags.verbose = save_verbose;
638         (void) encumber_msg();
639     } else
640 /*JP
641         pline("Unavailable command '%s'.",
642 */
643         pline("'%s'\83R\83}\83\93\83h\82Í\8eg\82¦\82È\82¢\81D",
644               visctrl((int) cmd_from_func(wiz_wish)));
645     return 0;
646 }
647
648 /* ^I command - reveal and optionally identify hero's inventory */
649 STATIC_PTR int
650 wiz_identify(VOID_ARGS)
651 {
652     if (wizard) {
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;
657     } else
658 /*JP
659         pline("Unavailable command '%s'.",
660 */
661         pline("'%s'\83R\83}\83\93\83h\82Í\8eg\82¦\82È\82¢\81D",
662               visctrl((int) cmd_from_func(wiz_identify)));
663     return 0;
664 }
665
666 /* ^F command - reveal the level map and any traps on it */
667 STATIC_PTR int
668 wiz_map(VOID_ARGS)
669 {
670     if (wizard) {
671         struct trap *t;
672         long save_Hconf = HConfusion, save_Hhallu = HHallucination;
673
674         HConfusion = HHallucination = 0L;
675         for (t = ftrap; t != 0; t = t->ntrap) {
676             t->tseen = 1;
677             map_trap(t, TRUE);
678         }
679         do_mapping();
680         HConfusion = save_Hconf;
681         HHallucination = save_Hhallu;
682     } else
683 /*JP
684         pline("Unavailable command '%s'.",
685 */
686         pline("'%s'\83R\83}\83\93\83h\82Í\8eg\82¦\82È\82¢\81D",
687               visctrl((int) cmd_from_func(wiz_map)));
688     return 0;
689 }
690
691 /* ^G command - generate monster(s); a count prefix will be honored */
692 STATIC_PTR int
693 wiz_genesis(VOID_ARGS)
694 {
695     if (wizard)
696         (void) create_particular();
697     else
698 /*JP
699         pline("Unavailable command '%s'.",
700 */
701         pline("'%s'\83R\83}\83\93\83h\82Í\8eg\82¦\82È\82¢\81D",
702               visctrl((int) cmd_from_func(wiz_genesis)));
703     return 0;
704 }
705
706 /* ^O command - display dungeon layout */
707 STATIC_PTR int
708 wiz_where(VOID_ARGS)
709 {
710     if (wizard)
711         (void) print_dungeon(FALSE, (schar *) 0, (xchar *) 0);
712     else
713 /*JP
714         pline("Unavailable command '%s'.",
715 */
716         pline("'%s'\83R\83}\83\93\83h\82Í\8eg\82¦\82È\82¢\81D",
717               visctrl((int) cmd_from_func(wiz_where)));
718     return 0;
719 }
720
721 /* ^E command - detect unseen (secret doors, traps, hidden monsters) */
722 STATIC_PTR int
723 wiz_detect(VOID_ARGS)
724 {
725     if (wizard)
726         (void) findit();
727     else
728 /*JP
729         pline("Unavailable command '%s'.",
730 */
731         pline("'%s'\83R\83}\83\93\83h\82Í\8eg\82¦\82È\82¢\81D",
732               visctrl((int) cmd_from_func(wiz_detect)));
733     return 0;
734 }
735
736 /* ^V command - level teleport */
737 STATIC_PTR int
738 wiz_level_tele(VOID_ARGS)
739 {
740     if (wizard)
741         level_tele();
742     else
743 /*JP
744         pline("Unavailable command '%s'.",
745 */
746         pline("'%s'\83R\83}\83\93\83h\82Í\8eg\82¦\82È\82¢\81D",
747               visctrl((int) cmd_from_func(wiz_level_tele)));
748     return 0;
749 }
750
751 /* #monpolycontrol command - choose new form for shapechangers, polymorphees */
752 STATIC_PTR int
753 wiz_mon_polycontrol(VOID_ARGS)
754 {
755     iflags.mon_polycontrol = !iflags.mon_polycontrol;
756 #if 0 /*JP*/
757     pline("Monster polymorph control is %s.",
758           iflags.mon_polycontrol ? "on" : "off");
759 #else
760     pline("\89ö\95¨\82Ì\95Ï\89»\90§\8cä: %s",
761           iflags.mon_polycontrol ? "\83I\83\93" : "\83I\83t");
762 #endif
763     return 0;
764 }
765
766 /* #levelchange command - adjust hero's experience level */
767 STATIC_PTR int
768 wiz_level_change(VOID_ARGS)
769 {
770     char buf[BUFSZ];
771     int newlevel;
772     int ret;
773
774 /*JP
775     getlin("To what experience level do you want to be set?", buf);
776 */
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')
780         ret = 0;
781     else
782         ret = sscanf(buf, "%d", &newlevel);
783
784     if (ret != 1) {
785         pline1(Never_mind);
786         return 0;
787     }
788     if (newlevel == u.ulevel) {
789 /*JP
790         You("are already that experienced.");
791 */
792         You("\82·\82Å\82É\82»\82Ì\8co\8c±\83\8c\83x\83\8b\82¾\81D");
793     } else if (newlevel < u.ulevel) {
794         if (u.ulevel == 1) {
795 /*JP
796             You("are already as inexperienced as you can get.");
797 */
798             You("\82·\82Å\82É\89Â\94\\82È\8cÀ\82è\82Ì\8dÅ\92á\82Ì\8co\8c±\83\8c\83x\83\8b\82¾\81D");
799             return 0;
800         }
801         if (newlevel < 1)
802             newlevel = 1;
803         while (u.ulevel > newlevel)
804 /*JP
805             losexp("#levelchange");
806 */
807             losexp("#levelchange\83R\83}\83\93\83h\82Å");
808     } else {
809         if (u.ulevel >= MAXULEV) {
810 /*JP
811             You("are already as experienced as you can get.");
812 */
813             You("\82·\82Å\82É\89Â\94\\82È\8cÀ\82è\82Ì\8dÅ\91å\82Ì\8co\8c±\83\8c\83x\83\8b\82¾\81D");
814             return 0;
815         }
816         if (newlevel > MAXULEV)
817             newlevel = MAXULEV;
818         while (u.ulevel < newlevel)
819             pluslvl(FALSE);
820     }
821     u.ulevelmax = u.ulevel;
822     return 0;
823 }
824
825 /* #panic command - test program's panic handling */
826 STATIC_PTR int
827 wiz_panic(VOID_ARGS)
828 {
829 /*JP
830     if (yn("Do you want to call panic() and end your game?") == 'y')
831 */
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.");
834     return 0;
835 }
836
837 /* #polyself command - change hero's form */
838 STATIC_PTR int
839 wiz_polyself(VOID_ARGS)
840 {
841     polyself(1);
842     return 0;
843 }
844
845 /* #seenv command */
846 STATIC_PTR int
847 wiz_show_seenv(VOID_ARGS)
848 {
849     winid win;
850     int x, y, v, startx, stopx, curx;
851     char row[COLNO + 1];
852
853     win = create_nhwindow(NHW_TEXT);
854     /*
855      * Each seenv description takes up 2 characters, so center
856      * the seenv display around the hero.
857      */
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)
862         startx++;
863
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] = '@';
868             } else {
869                 v = levl[x][y].seenv & 0xff;
870                 if (v == 0)
871                     row[curx] = row[curx + 1] = ' ';
872                 else
873                     Sprintf(&row[curx], "%02x", v);
874             }
875         }
876         /* remove trailing spaces */
877         for (x = curx - 1; x >= 0; x--)
878             if (row[x] != ' ')
879                 break;
880         row[x + 1] = '\0';
881
882         putstr(win, 0, row);
883     }
884     display_nhwindow(win, TRUE);
885     destroy_nhwindow(win);
886     return 0;
887 }
888
889 /* #vision command */
890 STATIC_PTR int
891 wiz_show_vision(VOID_ARGS)
892 {
893     winid win;
894     int x, y, v;
895     char row[COLNO + 1];
896
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);
900     putstr(win, 0, row);
901     putstr(win, 0, "");
902     for (y = 0; y < ROWNO; y++) {
903         for (x = 1; x < COLNO; x++) {
904             if (x == u.ux && y == u.uy)
905                 row[x] = '@';
906             else {
907                 v = viz_array[y][x]; /* data access should be hidden */
908                 if (v == 0)
909                     row[x] = ' ';
910                 else
911                     row[x] = '0' + viz_array[y][x];
912             }
913         }
914         /* remove trailing spaces */
915         for (x = COLNO - 1; x >= 1; x--)
916             if (row[x] != ' ')
917                 break;
918         row[x + 1] = '\0';
919
920         putstr(win, 0, &row[1]);
921     }
922     display_nhwindow(win, TRUE);
923     destroy_nhwindow(win);
924     return 0;
925 }
926
927 /* #wmode command */
928 STATIC_PTR int
929 wiz_show_wmodes(VOID_ARGS)
930 {
931     winid win;
932     int x, y;
933     char row[COLNO + 1];
934     struct rm *lev;
935     boolean istty = !strcmp(windowprocs.name, "tty");
936
937     win = create_nhwindow(NHW_TEXT);
938     if (istty)
939         putstr(win, 0, ""); /* tty only: blank top line */
940     for (y = 0; y < ROWNO; y++) {
941         for (x = 0; x < COLNO; x++) {
942             lev = &levl[x][y];
943             if (x == u.ux && y == u.uy)
944                 row[x] = '@';
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)
948                 row[x] = '#';
949             else if (IS_ROOM(lev->typ) || IS_DOOR(lev->typ))
950                 row[x] = '.';
951             else
952                 row[x] = 'x';
953         }
954         row[COLNO] = '\0';
955         /* map column 0, levl[0][], is off the left edge of the screen */
956         putstr(win, 0, &row[1]);
957     }
958     display_nhwindow(win, TRUE);
959     destroy_nhwindow(win);
960     return 0;
961 }
962
963 /* wizard mode variant of #terrain; internal levl[][].typ values in base-36 */
964 STATIC_OVL void
965 wiz_map_levltyp(VOID_ARGS)
966 {
967     winid win;
968     int x, y, terrain;
969     char row[COLNO + 1];
970     boolean istty = !strcmp(windowprocs.name, "tty");
971
972     win = create_nhwindow(NHW_TEXT);
973     /* map row 0, levl[][0], is drawn on the second line of tty screen */
974     if (istty)
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))
983                                     ? '*'
984                                     : (terrain < 10)
985                                        ? '0' + terrain
986                                        : (terrain < 36)
987                                           ? 'a' + terrain - 10
988                                           : 'A' + terrain - 36);
989         }
990         if (levl[0][y].typ != 0 || may_dig(0, y))
991             row[x++] = '!';
992         row[x] = '\0';
993         putstr(win, 0, row);
994     }
995
996     {
997         char dsc[BUFSZ];
998         s_level *slev = Is_special(&u.uz);
999
1000         Sprintf(dsc, "D:%d,L:%d", u.uz.dnum, u.uz.dlevel);
1001         /* [dungeon branch features currently omitted] */
1002         /* special level features */
1003         if (slev) {
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 */
1016         }
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");
1042         /* level flags */
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");
1061         if (Sokoban)
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 */
1070         if (u.uz.dnum == 0)
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");
1086         else {
1087             /* somebody's added a dungeon branch we're not expecting */
1088             const char *brname = dungeons[u.uz.dnum].dname;
1089
1090             if (!brname || !*brname)
1091                 brname = "unknown";
1092             if (!strncmpi(brname, "the ", 4))
1093                 brname += 4;
1094             Sprintf(eos(dsc), " %s", brname);
1095         }
1096         /* limit the line length to map width */
1097         if (strlen(dsc) >= COLNO)
1098             dsc[COLNO - 1] = '\0'; /* truncate */
1099         putstr(win, 0, dsc);
1100     }
1101
1102     display_nhwindow(win, TRUE);
1103     destroy_nhwindow(win);
1104     return;
1105 }
1106
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 */
1122     ""
1123 };
1124
1125 /* explanation of base-36 output from wiz_map_levltyp() */
1126 STATIC_OVL void
1127 wiz_levltyp_legend(VOID_ARGS)
1128 {
1129     winid win;
1130     int i, j, last, c;
1131     const char *dsc, *fmt;
1132     char buf[BUFSZ];
1133
1134     win = create_nhwindow(NHW_TEXT);
1135     putstr(win, 0, "#terrain encodings:");
1136     putstr(win, 0, "");
1137     fmt = " %c - %-28s"; /* TODO: include tab-separated variant for win32 */
1138     *buf = '\0';
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) {
1147             dsc = levltyp[j];
1148             c = !*dsc ? ' '
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
1153                             : 'A' + j - 36;
1154             Sprintf(eos(buf), fmt, c, dsc);
1155             if (j > i) {
1156                 putstr(win, 0, buf);
1157                 *buf = '\0';
1158             }
1159         }
1160     display_nhwindow(win, TRUE);
1161     destroy_nhwindow(win);
1162     return;
1163 }
1164
1165 /* #wizsmell command - test usmellmon(). */
1166 STATIC_PTR int
1167 wiz_smell(VOID_ARGS)
1168 {
1169     int ans = 0;
1170     int mndx;  /* monster index */
1171     coord cc;  /* screen pos of unknown glyph */
1172     int glyph; /* glyph at selected position */
1173
1174     cc.x = u.ux;
1175     cc.y = u.uy;
1176     mndx = 0; /* gcc -Wall lint */
1177     if (!olfaction(youmonst.data)) {
1178         You("are incapable of detecting odors in your present form.");
1179         return 0;
1180     }
1181
1182     pline("You can move the cursor to a monster that you want to smell.");
1183     do {
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 */
1188         }
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);
1193         else
1194             mndx = 0;
1195         /* Is it a monster? */
1196         if (mndx) {
1197             if (!usmellmon(&mons[mndx]))
1198                 pline("That monster seems to give off no smell.");
1199         } else
1200             pline("That is not a monster.");
1201     } while (TRUE);
1202     return 0;
1203 }
1204
1205 /* #wizrumorcheck command - verify each rumor access */
1206 STATIC_PTR int
1207 wiz_rumor_check(VOID_ARGS)
1208 {
1209     rumor_check();
1210     return 0;
1211 }
1212
1213 /* #terrain command -- show known map, inspired by crawl's '|' command */
1214 STATIC_PTR int
1215 doterrain(VOID_ARGS)
1216 {
1217     winid men;
1218     menu_item *sel;
1219     anything any;
1220     int n;
1221     int which;
1222
1223     /*
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
1232      */
1233     men = create_nhwindow(NHW_MENU);
1234     any = zeroany;
1235     any.a_int = 1;
1236     add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1237              "known map without monsters, objects, and traps",
1238              MENU_SELECTED);
1239     any.a_int = 2;
1240     add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1241              "known map without monsters and objects",
1242              MENU_UNSELECTED);
1243     any.a_int = 3;
1244     add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1245              "known map without monsters",
1246              MENU_UNSELECTED);
1247     if (discover || wizard) {
1248         any.a_int = 4;
1249         add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1250                  "full map without monsters, objects, and traps",
1251                  MENU_UNSELECTED);
1252         if (wizard) {
1253             any.a_int = 5;
1254             add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1255                      "internal levl[][].typ codes in base-36",
1256                      MENU_UNSELECTED);
1257             any.a_int = 6;
1258             add_menu(men, NO_GLYPH, &any, 0, 0, ATR_NONE,
1259                      "legend of base-36 levl[][].typ codes",
1260                      MENU_UNSELECTED);
1261         }
1262     }
1263     end_menu(men, "View which?");
1264
1265     n = select_menu(men, PICK_ONE, &sel);
1266     destroy_nhwindow(men);
1267     /*
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.
1272      */
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;
1276     if (n > 0)
1277         free((genericptr_t) sel);
1278
1279     switch (which) {
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 */
1286     default: break;
1287     }
1288     return 0; /* no time elapses */
1289 }
1290
1291 /* -enlightenment and conduct- */
1292 static winid en_win = WIN_ERR;
1293 #if 0 /*JP*/
1294 static const char You_[] = "You ", are[] = "are ", were[] = "were ",
1295                   have[] = "have ", had[] = "had ", can[] = "can ",
1296                   could[] = "could ";
1297 #else
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½";
1303 #endif
1304 #if 0 /*JP*//* not used */
1305 static const char have_been[] = "have been ", have_never[] = "have never ",
1306                   never[] = "never ";
1307 #endif
1308
1309 #if 0 /*JP*/
1310 #define enl_msg(prefix, present, past, suffix, ps) \
1311     enlght_line(prefix, final ? past : present, suffix, ps)
1312 #else
1313 #define enl_msg(prefix, present, past, suffix, ps) \
1314     enlght_line(prefix, suffix, final ? past : present, ps)
1315 #endif
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)
1319 /*JP
1320 #define you_have_been(goodthing) enl_msg(You_, have_been, were, goodthing, "")
1321 */
1322 #define you_have_been(goodthing) enl_msg(You_, are, were, goodthing, "")
1323 #if 0 /*JP*/
1324 #define you_have_never(badthing) \
1325     enl_msg(You_, have_never, never, badthing, "")
1326 #else
1327 #define you_have_never(badthing) \
1328     enl_msg(badthing, "\82Ä\82¢\82È\82¢", "\82È\82©\82Á\82½", "", "")
1329 #endif
1330 #if 0 /*JP*/
1331 #define you_have_X(something) \
1332     enl_msg(You_, have, (const char *) "", something, "")
1333 #else
1334 #define you_have_X(something) \
1335     enl_msg(something, "\82Ä\82¢\82é", "\82½", "", "")
1336 #endif
1337 #if 1 /*JP*/
1338 #define you_are_ing(goodthing) enl_msg(You_, iru, ita, goodthing, "")
1339 #endif
1340
1341 static void
1342 enlght_line(start, middle, end, ps)
1343 const char *start, *middle, *end, *ps;
1344 {
1345     char buf[BUFSZ];
1346
1347 /*JP
1348     Sprintf(buf, " %s%s%s%s.", start, middle, end, ps);
1349 */
1350     Sprintf(buf, "%s%s%s%s\81D", start, middle, end, ps);
1351     putstr(en_win, 0, buf);
1352 }
1353
1354 /* format increased chance to hit or damage or defense (Protection) */
1355 static char *
1356 enlght_combatinc(inctyp, incamt, final, outbuf)
1357 const char *inctyp;
1358 int incamt, final;
1359 char *outbuf;
1360 {
1361     const char *modif, *bonus;
1362     boolean invrt;
1363     int absamt;
1364
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;
1371
1372     if (absamt <= 3)
1373 /*JP
1374         modif = "small";
1375 */
1376         modif = "\8bÍ\82©\82È";
1377     else if (absamt <= 6)
1378 /*JP
1379         modif = "moderate";
1380 */
1381         modif = "\92\86\92ö\93x\82Ì";
1382     else if (absamt <= 12)
1383 /*JP
1384         modif = "large";
1385 */
1386         modif = "\91å\82«\82È";
1387     else
1388 /*JP
1389         modif = "huge";
1390 */
1391         modif = "\8b­\91å\82È";
1392
1393 #if 0 /*JP*/
1394     modif = !incamt ? "no" : an(modif); /* ("no" case shouldn't happen) */
1395 #endif
1396 /*JP
1397     bonus = (incamt >= 0) ? "bonus" : "penalty";
1398 */
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;
1402
1403 #if 0 /*JP*/
1404     Sprintf(outbuf, "%s %s %s", modif, invrt ? inctyp : bonus,
1405             invrt ? bonus : inctyp);
1406 #else
1407     Sprintf(outbuf, "%s\82É%s%s", inctyp, modif, bonus);
1408 #endif
1409     if (final || wizard)
1410         Sprintf(eos(outbuf), " (%s%d)", (incamt > 0) ? "+" : "", incamt);
1411
1412     return outbuf;
1413 }
1414
1415 /* report half physical or half spell damage */
1416 STATIC_OVL void
1417 enlght_halfdmg(category, final)
1418 int category;
1419 int final;
1420 {
1421     const char *category_name;
1422     char buf[BUFSZ];
1423
1424     switch (category) {
1425     case HALF_PHDAM:
1426         category_name = "physical";
1427         break;
1428     case HALF_SPDAM:
1429         category_name = "spell";
1430         break;
1431     default:
1432         category_name = "unknown";
1433         break;
1434     }
1435     Sprintf(buf, " %s %s damage", (final || wizard) ? "half" : "reduced",
1436             category_name);
1437     enl_msg(You_, "take", "took", buf, from_what(category));
1438 }
1439
1440 /* is hero actively using water walking capability on water (or lava)? */
1441 STATIC_OVL boolean
1442 walking_on_water()
1443 {
1444     if (u.uinwater || Levitation || Flying)
1445         return FALSE;
1446     return (boolean) (Wwalking
1447                       && (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)));
1448 }
1449
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 */
1453 STATIC_OVL boolean
1454 cause_known(propindx)
1455 int propindx; /* index of a property which can be conveyed by worn item */
1456 {
1457     register struct obj *o;
1458     long mask = W_ARMOR | W_AMUL | W_RING | W_TOOL;
1459
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))
1464             continue;
1465         if ((int) objects[o->otyp].oc_oprop == propindx
1466             && objects[o->otyp].oc_name_known && o->dknown)
1467             return TRUE;
1468     }
1469     return FALSE;
1470 }
1471
1472 /* format a characteristic value, accommodating Strength's strangeness */
1473 STATIC_OVL char *
1474 attrval(attrindx, attrvalue, resultbuf)
1475 int attrindx, attrvalue;
1476 char resultbuf[]; /* should be at least [7] to hold "18/100\0" */
1477 {
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);
1484     return resultbuf;
1485 }
1486
1487 void
1488 enlightenment(mode, final)
1489 int mode;  /* BASICENLIGHTENMENT | MAGICENLIGHTENMENT (| both) */
1490 int final; /* ENL_GAMEINPROGRESS:0, ENL_GAMEOVERALIVE, ENL_GAMEOVERDEAD */
1491 {
1492     char buf[BUFSZ], tmpbuf[BUFSZ];
1493
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 */
1498 #if 0 /*JP*/
1499     Sprintf(buf, "%s the %s's attributes:", tmpbuf,
1500             ((Upolyd ? u.mfemale : flags.female) && urole.name.f)
1501                 ? urole.name.f
1502                 : urole.name.m);
1503 #else
1504     Sprintf(buf, "%s\82Ì%s\82Ì\91®\90«:",
1505             ((Upolyd ? u.mfemale : flags.female) && urole.name.f)
1506                 ? urole.name.f
1507                 : urole.name.m,
1508              tmpbuf);
1509 #endif
1510
1511     en_win = create_nhwindow(NHW_MENU);
1512     /* title */
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);
1520     }
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);
1532     }
1533     display_nhwindow(en_win, TRUE);
1534     destroy_nhwindow(en_win);
1535     en_win = WIN_ERR;
1536 }
1537
1538 /*ARGSUSED*/
1539 /* display role, race, alignment and such to en_win */
1540 STATIC_OVL void
1541 background_enlightenment(unused_mode, final)
1542 int unused_mode UNUSED;
1543 int final;
1544 {
1545     const char *role_titl, *rank_titl;
1546     int innategend, difgend, difalgn;
1547     char buf[BUFSZ], tmpbuf[BUFSZ];
1548
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);
1554
1555     putstr(en_win, 0, ""); /* separator after title */
1556 /*JP
1557     putstr(en_win, 0, "Background:");
1558 */
1559     putstr(en_win, 0, "\94w\8ci\8fî\95ñ:");
1560
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... */
1567     if (Upolyd) {
1568         struct permonst *uasmon = youmonst.data;
1569
1570         tmpbuf[0] = '\0';
1571         /* here we always use current gender, not saved role gender */
1572         if (!is_male(uasmon) && !is_female(uasmon) && !is_neuter(uasmon))
1573 /*JP
1574             Sprintf(tmpbuf, "%s ", genders[flags.female ? 1 : 0].adj);
1575 */
1576             Sprintf(tmpbuf, "%s", genders[flags.female ? 1 : 0].adj);
1577         Sprintf(buf, "%sin %s%s form", !final ? "currently " : "", tmpbuf,
1578                 uasmon->mname);
1579         you_are(buf, "");
1580     }
1581
1582     /* report role; omit gender if it's redundant (eg, "female priestess") */
1583     tmpbuf[0] = '\0';
1584     if (!urole.name.f
1585         && ((urole.allow & ROLE_GENDMASK) == (ROLE_MALE | ROLE_FEMALE)
1586             || innategend != flags.initgend))
1587 /*JP
1588         Sprintf(tmpbuf, "%s ", genders[innategend].adj);
1589 */
1590         Sprintf(tmpbuf, "%s", genders[innategend].adj);
1591     buf[0] = '\0';
1592     if (Upolyd)
1593         Strcpy(buf, "actually "); /* "You are actually a ..." */
1594     if (!strcmpi(rank_titl, role_titl)) {
1595         /* omit role when rank title matches it */
1596 #if 0 /*JP*/
1597         Sprintf(eos(buf), "%s, level %d %s%s", an(rank_titl), u.ulevel,
1598                 tmpbuf, urace.noun);
1599 #else
1600         Sprintf(eos(buf), "\83\8c\83x\83\8b%d\82Ì%s\82Ì%s%s", u.ulevel,
1601                 tmpbuf, urace.adj, role_titl);
1602 #endif
1603     } else {
1604 #if 0 /*JP*/
1605         Sprintf(eos(buf), "%s, a level %d %s%s %s", an(rank_titl), u.ulevel,
1606                 tmpbuf, urace.adj, role_titl);
1607 #else
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);
1610 #endif
1611     }
1612     you_are(buf, "");
1613
1614     /* report alignment (bypass you_are() in order to omit ending period) */
1615 #if 0 /*JP*/
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 */
1626                      : "",
1627             u_gname());
1628 #else
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 */
1638                      : "",
1639             u_gname(), !final ? iru : ita);
1640 #endif
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] */
1645 #if 0 /*JP*/
1646     Sprintf(buf, " who %s opposed by", !final ? "is" : "was");
1647 #else
1648     Strcpy(buf, "\82 \82È\82½\82Í");
1649 #endif
1650     if (u.ualign.type != A_LAWFUL)
1651 #if 0 /*JP*/
1652         Sprintf(eos(buf), " %s (%s) and", align_gname(A_LAWFUL),
1653                 align_str(A_LAWFUL));
1654 #else
1655         Sprintf(eos(buf), "%s(%s)\82¨\82æ\82Ñ", align_gname(A_LAWFUL),
1656                 align_str(A_LAWFUL));
1657 #endif
1658     if (u.ualign.type != A_NEUTRAL)
1659 #if 0 /*JP*/
1660         Sprintf(eos(buf), " %s (%s)%s", align_gname(A_NEUTRAL),
1661                 align_str(A_NEUTRAL),
1662                 (u.ualign.type != A_CHAOTIC) ? " and" : "");
1663 #else
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Ñ" : "");
1667 #endif
1668 #if 0 /*JP*/
1669     if (u.ualign.type != A_CHAOTIC)
1670         Sprintf(eos(buf), " %s (%s)", align_gname(A_CHAOTIC),
1671                 align_str(A_CHAOTIC));
1672 #else
1673     if (u.ualign.type != A_CHAOTIC)
1674         Sprintf(eos(buf), "%s(%s)", align_gname(A_CHAOTIC),
1675                 align_str(A_CHAOTIC));
1676 #endif
1677 #if 0 /*JP*/
1678     Strcat(buf, "."); /* terminate sentence */
1679 #else
1680     Sprintf(eos(buf), "\82Æ\91Î\97§\82µ\82Ä%s\81D", !final ? iru : ita);
1681 #endif
1682     putstr(en_win, 0, buf);
1683
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])
1691                   ? 2 : 0));
1692     if (difalgn & 1) { /* have temporary alignment so report permanent one */
1693         Sprintf(buf, "actually %s", align_str(u.ualignbase[A_CURRENT]));
1694         you_are(buf, "");
1695         difalgn &= ~1; /* suppress helm from "started out <foo>" message */
1696     }
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);
1703     }
1704 }
1705
1706 /* characteristics: expanded version of bottom line strength, dexterity, &c */
1707 STATIC_OVL void
1708 characteristics_enlightenment(mode, final)
1709 int mode;
1710 int final;
1711 {
1712     putstr(en_win, 0, ""); /* separator after background */
1713     putstr(en_win, 0,
1714 /*JP
1715            final ? "Final Characteristics:" : "Current Characteristics:");
1716 */
1717            final ? "\8dÅ\8fI\91®\90«\81F" : "\8c»\8dÝ\82Ì\91®\90«\81F");
1718
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 */
1726 }
1727
1728 /* display one attribute value for characteristics_enlightenment() */
1729 STATIC_OVL void
1730 one_characteristic(mode, final, attrindx)
1731 int mode, final, attrindx;
1732 {
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];
1737
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 */
1744     if (Upolyd) {
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;
1750     }
1751     switch (attrindx) {
1752     case A_STR:
1753         attrname = "strength";
1754         if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER && uarmg->cursed)
1755             hide_innate_value = TRUE;
1756         break;
1757     case A_DEX:
1758         attrname = "dexterity";
1759         break;
1760     case A_CON:
1761         attrname = "constitution";
1762         break;
1763     case A_INT:
1764         attrname = "intelligence";
1765         if (uarmh && uarmh->otyp == DUNCE_CAP && uarmh->cursed)
1766             hide_innate_value = TRUE;
1767         break;
1768     case A_WIS:
1769         attrname = "wisdom";
1770         if (uarmh && uarmh->otyp == DUNCE_CAP && uarmh->cursed)
1771             hide_innate_value = TRUE;
1772         break;
1773     case A_CHA:
1774         attrname = "charisma";
1775         break;
1776     default:
1777         return; /* impossible */
1778     };
1779     /* note: final disclosure includes MAGICENLIGHTENTMENT */
1780     if ((mode & MAGICENLIGHTENMENT) && !Upolyd)
1781         hide_innate_value = FALSE;
1782
1783     acurrent = ACURR(attrindx);
1784     (void) attrval(attrindx, acurrent, valubuf); /* Sprintf(valubuf,"%d",) */
1785     Sprintf(subjbuf, "Your %s ", attrname);
1786
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));
1806             paren_pfx = ", ";
1807         }
1808         if (abase != apeak) {
1809             Sprintf(eos(valubuf), "%speak:%s", paren_pfx,
1810                     attrval(attrindx, apeak, valstring));
1811             paren_pfx = ", ";
1812         }
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 = ", "; */
1819         }
1820         if (acurrent != abase || abase != apeak || interesting_alimit)
1821             Strcat(valubuf, ")");
1822     }
1823     enl_msg(subjbuf, "is ", "was ", valubuf, "");
1824 }
1825
1826 /* status: selected obvious capabilities, assorted troubles */
1827 STATIC_OVL void
1828 status_enlightenment(mode, final)
1829 int mode;
1830 int final;
1831 {
1832     boolean magic = (mode & MAGICENLIGHTENMENT) ? TRUE : FALSE;
1833     int cap;
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,
1843                                  (char *) 0,
1844                                  (SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION),
1845                                  FALSE));
1846
1847     /*\
1848      * Status (many are abbreviated on bottom line; others are or
1849      *     should be discernible to the hero hence to the player)
1850     \*/
1851     putstr(en_win, 0, ""); /* separator after title or characteristics */
1852     putstr(en_win, 0, final ? "Final Status:" : "Current Status:");
1853
1854     Strcpy(youtoo, You_);
1855     /* not a traditional status but inherently obvious to player; more
1856        detail given below (attributes section) for magic enlightenment */
1857     if (Upolyd)
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 */
1861     if (Riding) {
1862         Sprintf(buf, "riding %s", steedname);
1863         you_are(buf, "");
1864         Sprintf(eos(youtoo), "and %s ", steedname);
1865     }
1866     /* other movement situations that hero should always know */
1867     if (Levitation) {
1868         if (Lev_at_will && magic)
1869             you_are("levitating, at will", "");
1870         else
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));
1874     }
1875     if (Underwater) {
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));
1886     }
1887     if (Upolyd && (u.uundetected || youmonst.m_ap_type != M_AP_NOTHING))
1888         youhiding(TRUE, final);
1889
1890     /* internal troubles, mostly in the order that prayer ranks them */
1891     if (Stoned)
1892         you_are("turning to stone", "");
1893     if (Slimed)
1894         you_are("turning into slime", "");
1895     if (Strangled) {
1896         if (u.uburied) {
1897             you_are("buried", "");
1898         } else {
1899             Strcpy(buf, "being strangled");
1900             if (wizard)
1901                 Sprintf(eos(buf), " (%ld)", (Strangled & TIMEOUT));
1902             you_are(buf, from_what(STRANGLED));
1903         }
1904     }
1905     if (Sick) {
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", "");
1911     }
1912     if (Vomiting)
1913         you_are("nauseated", "");
1914     if (Stunned)
1915         you_are("stunned", "");
1916     if (Confusion)
1917         you_are("confused", "");
1918     if (Hallucination)
1919         you_are("hallucinating", "");
1920     if (Blind) {
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"
1928                     : "temporarily");
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));
1934     }
1935     if (Deaf)
1936         you_are("deaf", from_what(DEAF));
1937
1938     /* external troubles, more or less */
1939     if (Punished) {
1940         if (uball) {
1941             Sprintf(buf, "chained to %s", ansimpleoname(uball));
1942         } else {
1943             impossible("Punished without uball?");
1944             Strcpy(buf, "punished");
1945         }
1946         you_are(buf, "");
1947     }
1948     if (u.utrap) {
1949         char predicament[BUFSZ];
1950         struct trap *t;
1951         boolean anchored = (u.utraptype == TT_BURIEDBALL);
1952
1953         if (anchored) {
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)));
1957         } else {
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));
1962         }
1963         if (u.usteed) { /* not `Riding' here */
1964             Sprintf(buf, "%s%s ", anchored ? "you and " : "", steedname);
1965             *buf = highc(*buf);
1966             enl_msg(buf, (anchored ? "are " : "is "),
1967                     (anchored ? "were " : "was "), predicament, "");
1968         } else
1969             you_are(predicament, "");
1970     } /* (u.utrap) */
1971     if (u.uswallow) {
1972         Sprintf(buf, "swallowed by %s", a_monnam(u.ustuck));
1973         if (wizard)
1974             Sprintf(eos(buf), " (%u)", u.uswldtim);
1975         you_are(buf, "");
1976     } else if (u.ustuck) {
1977         Sprintf(buf, "%s %s",
1978                 (Upolyd && sticks(youmonst.data)) ? "holding" : "held by",
1979                 a_monnam(u.ustuck));
1980         you_are(buf, "");
1981     }
1982     if (Riding) {
1983         struct obj *saddle = which_armor(u.usteed, W_SADDLE);
1984
1985         if (saddle && saddle->cursed) {
1986             Sprintf(buf, "stuck to %s %s", s_suffix(steedname),
1987                     simpleonames(saddle));
1988             you_are(buf, "");
1989         }
1990     }
1991     if (Wounded_legs) {
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);
1997                 *buf = highc(*buf);
1998                 enl_msg(buf, " has", " had", " wounded legs", "");
1999             }
2000         } else {
2001             Sprintf(buf, "wounded %s", makeplural(body_part(LEG)));
2002             you_have(buf, "");
2003         }
2004     }
2005     if (Glib) {
2006         Sprintf(buf, "slippery %s", makeplural(body_part(FINGER)));
2007         you_have(buf, "");
2008     }
2009     if (Fumbling) {
2010         if (magic || cause_known(FUMBLING))
2011             enl_msg(You_, "fumble", "fumbled", "", from_what(FUMBLING));
2012     }
2013     if (Sleepy) {
2014         if (magic || cause_known(SLEEPY)) {
2015             Strcpy(buf, from_what(SLEEPY));
2016             if (wizard)
2017                 Sprintf(eos(buf), " (%ld)", (HSleepy & TIMEOUT));
2018             enl_msg("You ", "fall", "fell", " asleep uncontrollably", buf);
2019         }
2020     }
2021     /* hunger/nutrition */
2022     if (Hunger) {
2023         if (magic || cause_known(HUNGER))
2024             enl_msg(You_, "hunger", "hungered", " rapidly",
2025                     from_what(HUNGER));
2026     }
2027     Strcpy(buf, hu_stat[u.uhs]); /* hunger status; omitted if "normal" */
2028     mungspaces(buf);             /* strip trailing spaces */
2029     if (*buf) {
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");
2035         you_are(buf, "");
2036     }
2037     /* encumbrance */
2038     if ((cap = near_capacity()) > UNENCUMBERED) {
2039         const char *adj = "?_?"; /* (should always get overridden) */
2040
2041         Strcpy(buf, enc_stat[cap]);
2042         *buf = lowc(*buf);
2043         switch (cap) {
2044         case SLT_ENCUMBER:
2045             adj = "slightly";
2046             break; /* burdened */
2047         case MOD_ENCUMBER:
2048             adj = "moderately";
2049             break; /* stressed */
2050         case HVY_ENCUMBER:
2051             adj = "very";
2052             break; /* strained */
2053         case EXT_ENCUMBER:
2054             adj = "extremely";
2055             break; /* overtaxed */
2056         case OVERLOADED:
2057             adj = "not possible";
2058             break;
2059         }
2060         Sprintf(eos(buf), "; movement %s %s%s", !final ? "is" : "was", adj,
2061                 (cap < OVERLOADED) ? " slowed" : "");
2062         you_are(buf, "");
2063     } else {
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", "");
2068     }
2069     /* report being weaponless; distinguish whether gloves are worn */
2070     if (!uwep) {
2071         you_are(uarmg ? "empty handed" /* gloves imply hands */
2072                       : humanoid(youmonst.data)
2073                          /* hands but no weapon and no gloves */
2074                          ? "bare handed"
2075                          /* alternate phrasing for paws or lack of hands */
2076                          : "not wielding anything",
2077                 "");
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 */
2084     } else {
2085         const char *what = weapon_descr(uwep);
2086
2087         if (!strcmpi(what, "armor") || !strcmpi(what, "food")
2088             || !strcmpi(what, "venom"))
2089             Sprintf(buf, "wielding some %s", what);
2090         else
2091             Sprintf(buf, "wielding %s",
2092                     (uwep->quan == 1L) ? an(what) : makeplural(what));
2093         you_are(buf, "");
2094     }
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", "");
2099         else
2100             you_are("not wearing any armor", "");
2101     }
2102 }
2103
2104 /* attributes: intrinsics and the like, other non-obvious capabilities */
2105 void
2106 attributes_enlightenment(unused_mode, final)
2107 int unused_mode UNUSED;
2108 int final;
2109 {
2110     static NEARDATA const char if_surroundings_permitted[] =
2111         " if surroundings permitted";
2112     int ltmp, armpro;
2113     char buf[BUFSZ];
2114
2115     /*\
2116      *  Attributes
2117     \*/
2118     putstr(en_win, 0, "");
2119     putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:");
2120
2121     if (u.uevent.uhand_of_elbereth) {
2122 #if 0 /*JP*/
2123         static const char *const hofe_titles[3] = { "the Hand of Elbereth",
2124                                                     "the Envoy of Balance",
2125                                                     "the Glory of Arioch" };
2126 #else
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_" };
2130 #endif
2131         you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1], "");
2132     }
2133
2134     /* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
2135     if (u.ualign.record >= 20)
2136 /*JP
2137         you_are("piously aligned", "");
2138 */
2139       you_have("\8chåi\82È\90M\8bÂ\90S", "");
2140     else if (u.ualign.record > 13)
2141 /*JP
2142         you_are("devoutly aligned", "");
2143 */
2144       you_have("\90S\82©\82ç\82Ì\90M\8bÂ\90S", "");
2145     else if (u.ualign.record > 8)
2146 /*JP
2147         you_are("fervently aligned", "");
2148 */
2149       you_have("\94M\90S\82È\90M\8bÂ\90S", "");
2150     else if (u.ualign.record > 3)
2151 /*JP
2152         you_are("stridently aligned", "");
2153 */
2154       you_have("\82¨\82¨\82°\82³\82È\90M\8bÂ\90S", "");
2155     else if (u.ualign.record == 3)
2156 /*JP
2157         you_are("aligned", "");
2158 */
2159       you_have("\95\81\92Ê\82Ì\90M\8bÂ\90S", "");
2160     else if (u.ualign.record > 0)
2161 /*JP
2162         you_are("haltingly aligned", "");
2163 */
2164       you_have("çSçO\82µ\82È\82ª\82ç\82à\90M\8bÂ\90S", "");
2165     else if (u.ualign.record == 0)
2166 /*JP
2167         you_are("nominally aligned", "");
2168 */
2169       you_have("\8c`\82¾\82¯\82Ì\90M\8bÂ\90S", "");
2170     else if (u.ualign.record >= -3)
2171 /*JP
2172         you_have("strayed", "");
2173 */
2174       you_are_ing("\90M\8bÂ\82É\96À\82¢\82ð\82à\82Á\82Ä");
2175     else if (u.ualign.record >= -8)
2176 /*JP
2177         you_have("sinned", "");
2178 */
2179       you_are_ing("\8dß\82ð\95\89\82Á\82Ä");
2180     else
2181 /*JP
2182         you_have("transgressed", "");
2183 */
2184       you_are_ing("\90M\8bÂ\82©\82ç\88í\92E\82µ\82Ä");
2185     if (wizard) {
2186 #if 0 /*JP*/
2187         Sprintf(buf, " %d", u.ualign.record);
2188         enl_msg("Your alignment ", "is", "was", buf, "");
2189 #else
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½", "", "");
2192 #endif
2193     }
2194
2195     /*** Resistances to troubles ***/
2196     if (Invulnerable)
2197         you_are("invulnerable", from_what(INVULNERABLE));
2198     if (Antimagic)
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));
2223     if (u.uedibility)
2224         you_can("recognize detrimental food", "");
2225
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) {
2230         if (!Blind)
2231             enl_msg(You_, "see", "saw", " invisible", from_what(SEE_INVIS));
2232         else
2233             enl_msg(You_, "will see", "would have seen",
2234                     " invisible when not blind", from_what(SEE_INVIS));
2235     }
2236     if (Blind_telepat)
2237         you_are("telepathic", from_what(TELEPAT));
2238     if (Warning)
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));
2246     }
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)
2253                           ? "humans"
2254                           : (context.warntype.polyd & M2_ELF)
2255                                 ? "elves"
2256                                 : (context.warntype.polyd & M2_ORC)
2257                                       ? "orcs"
2258                                       : (context.warntype.polyd & M2_DEMON)
2259                                             ? "demons"
2260                                             : "certain monsters");
2261         you_are(buf, "");
2262     }
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));
2267     }
2268     if (Undead_warning)
2269         you_are("warned of undead", from_what(WARN_UNDEAD));
2270     if (Searching)
2271         you_have("automatic searching", from_what(SEARCHING));
2272     if (Clairvoyant)
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);
2280     }
2281     if (Infravision)
2282         you_have("infravision", from_what(INFRAVISION));
2283     if (Detect_monsters)
2284         you_are("sensing the presence of monsters", "");
2285     if (u.umconf)
2286         you_are("going to confuse monsters", "");
2287
2288     /*** Appearance and behavior ***/
2289     if (Adornment) {
2290         int adorn = 0;
2291
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));
2302     }
2303     if (Invisible)
2304         you_are("invisible", from_what(INVIS));
2305     else if (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));
2311     if (Displaced)
2312         you_are("displaced", from_what(DISPLACED));
2313     if (Stealth)
2314         you_are("stealthy", from_what(STEALTH));
2315     if (Aggravate_monster)
2316         enl_msg("You aggravate", "", "d", " monsters",
2317                 from_what(AGGRAVATE_MONSTER));
2318     if (Conflict)
2319         enl_msg("You cause", "", "d", " conflict", from_what(CONFLICT));
2320
2321     /*** Transportation ***/
2322     if (Jumping)
2323         you_can("jump", from_what(JUMPING));
2324     if (Teleportation)
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;
2331
2332         BLevitation = 0L;
2333         if (Levitation)
2334             enl_msg(You_, "would levitate", "would have levitated",
2335                     if_surroundings_permitted, "");
2336         BLevitation = save_BLev;
2337     }
2338     /* actively flying handled earlier as a status condition */
2339     if (BFlying) { /* flight is blocked */
2340         long save_BFly = BFlying;
2341
2342         BFlying = 0L;
2343         if (Flying)
2344             enl_msg(You_, "would fly", "would have flown",
2345                     Levitation
2346                        ? "if you weren't levitating"
2347                        : (save_BFly == FROMOUTSIDE)
2348                           ? if_surroundings_permitted
2349                           /* both surroundings and [latent] levitation */
2350                           : " if circumstances permitted",
2351                     "");
2352         BFlying = save_BFly;
2353     }
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));
2360     if (Breathless)
2361         you_can("survive without air", from_what(MAGICAL_BREATHING));
2362     else if (Amphibious)
2363         you_can("breathe water", from_what(MAGICAL_BREATHING));
2364     if (Passes_walls)
2365         you_can("walk through walls", from_what(PASSES_WALLS));
2366
2367     /*** Physical attributes ***/
2368     if (Regeneration)
2369         enl_msg("You regenerate", "", "d", "", from_what(REGENERATION));
2370     if (Slow_digestion)
2371         you_have("slower digestion", from_what(SLOW_DIGESTION));
2372     if (u.uhitinc)
2373         you_have(enlght_combatinc("to hit", u.uhitinc, final, buf), "");
2374     if (u.udaminc)
2375         you_have(enlght_combatinc("damage", u.udaminc, final, buf), "");
2376     if (u.uspellprot || Protection) {
2377         int prot = 0;
2378
2379         if (uleft && uleft->otyp == RIN_PROTECTION)
2380             prot += uleft->spe;
2381         if (uright && uright->otyp == RIN_PROTECTION)
2382             prot += uright->spe;
2383         if (HProtection & INTRINSIC)
2384             prot += u.ublessed;
2385         prot += u.uspellprot;
2386         if (prot)
2387             you_have(enlght_combatinc("defense", prot, final, buf), "");
2388     }
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",
2393         };
2394         /* sanity check */
2395         if (armpro >= SIZE(mc_types))
2396             armpro = SIZE(mc_types) - 1;
2397         you_are(mc_types[armpro], "");
2398     }
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));
2407     if (Unchanging) {
2408         const char *what = 0;
2409
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 */
2414         if (Polymorph)
2415             what = !final ? "polymorph" : "have polymorphed";
2416         else if (u.ulycn >= LOW_PM)
2417             what = !final ? "change shape" : "have changed shape";
2418         if (what) {
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",
2422                     "");
2423         }
2424     } else if (Polymorph) {
2425         you_are("polymorphing periodically", from_what(POLYMORPH));
2426     }
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));
2432         if (wizard)
2433             Sprintf(eos(buf), " (%d)", u.mtimedone);
2434         you_are(buf, "");
2435     }
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");
2443             if (wizard)
2444                 Sprintf(eos(buf), " (%d)", u.mtimedone);
2445         }
2446         you_are(buf, "");
2447     }
2448     if (Unchanging && Upolyd) /* !Upolyd handled above */
2449         you_can("not change from your current form", from_what(UNCHANGING));
2450     if (Hate_silver)
2451         you_are("harmed by silver", "");
2452     /* movement and non-armor-based protection */
2453     if (Fast)
2454         you_are(Very_fast ? "very fast" : "fast", from_what(FAST));
2455     if (Reflecting)
2456         you_have("reflection", from_what(REFLECTING));
2457     if (Free_action)
2458         you_have("free action", from_what(FREE_ACTION));
2459     if (Fixed_abil)
2460         you_have("fixed abilities", from_what(FIXED_ABIL));
2461     if (Lifesaved)
2462         enl_msg("Your life ", "will be", "would have been", " saved", "");
2463
2464     /*** Miscellany ***/
2465     if (Luck) {
2466         ltmp = abs((int) Luck);
2467         Sprintf(buf, "%s%slucky",
2468                 ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "",
2469                 Luck < 0 ? "un" : "");
2470         if (wizard)
2471             Sprintf(eos(buf), " (%d)", Luck);
2472         you_are(buf, "");
2473     } else if (wizard)
2474         enl_msg("Your luck ", "is", "was", " zero", "");
2475     if (u.moreluck > 0)
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);
2481         if (ltmp <= 0)
2482             enl_msg("Bad luck ", "does", "did", " not time out for you", "");
2483         if (ltmp >= 0)
2484             enl_msg("Good luck ", "does", "did", " not time out for you", "");
2485     }
2486
2487     if (u.ugangr) {
2488         Sprintf(buf, " %sangry with you",
2489                 u.ugangr > 6 ? "extremely " : u.ugangr > 3 ? "very " : "");
2490         if (wizard)
2491             Sprintf(eos(buf), " (%d)", u.ugangr);
2492         enl_msg(u_gname(), " is", " was", buf, "");
2493     } else {
2494         /*
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.
2498          */
2499         if (!final) {
2500 #if 0 /*JP*/
2501 #if 0
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" : "");
2505 #else
2506             Sprintf(buf, "%ssafely pray", can_pray(FALSE) ? "" : "not ");
2507 #endif
2508             if (wizard)
2509                 Sprintf(eos(buf), " (%d)", u.ublesscnt);
2510             you_can(buf, "");
2511 #else /*JP*/
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¢");
2514             if (wizard)
2515               Sprintf(eos(buf), " (%d)", u.ublesscnt);
2516             enl_msg(buf, "", "", "", "");
2517 #endif
2518         }
2519     }
2520
2521     /* named fruit debugging (doesn't really belong here...) */
2522     if (wizard) {
2523         int fcount = 0;
2524         struct fruit *f;
2525         char buf2[BUFSZ];
2526
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, "");
2531         }
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, "");
2535     }
2536
2537     {
2538         const char *p;
2539
2540         buf[0] = '\0';
2541         if (final < 2) { /* still in progress, or quit/escaped/ascended */
2542 /*JP
2543             p = "survived after being killed ";
2544 */
2545             p = "\8e\80\82ñ\82¾\8cã\95\9c\8a\88\82µ\82Ä\82¢\82½";
2546             switch (u.umortality) {
2547             case 0:
2548 /*JP
2549                 p = !final ? (char *) 0 : "survived";
2550 */
2551                 p = !final ? (char *)0 : "\90\82«\89\84\82Ñ\82½";
2552                 break;
2553             case 1:
2554 /*JP
2555                 Strcpy(buf, "once");
2556 */
2557                 Strcpy(buf, "\88ê\93x");
2558                 break;
2559             case 2:
2560 /*JP
2561                 Strcpy(buf, "twice");
2562 */
2563                 Strcpy(buf, "\93ñ\93x");
2564                 break;
2565             case 3:
2566 /*JP
2567                 Strcpy(buf, "thrice");
2568 */
2569                 Strcpy(buf, "\8eO\93x");
2570                 break;
2571             default:
2572 /*JP
2573                 Sprintf(buf, "%d times", u.umortality);
2574 */
2575                 Sprintf(buf, "%d\89ñ", u.umortality);
2576                 break;
2577             }
2578         } else { /* game ended in character's death */
2579 /*JP
2580             p = "are dead";
2581 */
2582             p = "\8e\80\82ñ\82Å\82¢\82é";
2583             switch (u.umortality) {
2584             case 0:
2585                 impossible("dead without dying?");
2586             case 1:
2587                 break; /* just "are dead" */
2588             default:
2589 #if 0 /*JP*/
2590                 Sprintf(buf, " (%d%s time!)", u.umortality,
2591                         ordin(u.umortality));
2592 #else
2593                  Sprintf(buf, "(%d\89ñ\81I)", u.umortality);
2594 #endif
2595                 break;
2596             }
2597         }
2598         if (p)
2599 /*JP
2600             enl_msg(You_, "have been killed ", p, buf, "");
2601 */
2602             enl_msg(You_, "\8e\80\82ñ\82Å\82¢\82é", p, buf, "");
2603     }
2604 }
2605
2606 #if 0  /* no longer used */
2607 STATIC_DCL boolean NDECL(minimal_enlightenment);
2608
2609 /*
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.
2613  */
2614 STATIC_OVL boolean
2615 minimal_enlightenment()
2616 {
2617     winid tmpwin;
2618     menu_item *selected;
2619     anything any;
2620     int genidx, n;
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;
2628
2629     fmtstr = iflags.menu_tab_sep ? tabbed_fmtstr : untabbed_fmtstr;
2630     deity_fmtstr = iflags.menu_tab_sep ? tabbed_deity_fmtstr
2631                                        : untabbed_deity_fmtstr;
2632     any = zeroany;
2633     buf[0] = buf2[0] = '\0';
2634     tmpwin = create_nhwindow(NHW_MENU);
2635     start_menu(tmpwin);
2636     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2637              "Starting", FALSE);
2638
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);
2649
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);
2653
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,
2657              "Current", FALSE);
2658     Sprintf(buf, fmtstr, "race", Upolyd ? youmonst.data->mname : urace.noun);
2659     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2660     if (Upolyd) {
2661         Sprintf(buf, fmtstr, "role (base)",
2662                 (u.mfemale && urole.name.f) ? urole.name.f
2663                                             : urole.name.m);
2664         add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2665     } else {
2666         Sprintf(buf, fmtstr, "role",
2667                 (flags.female && urole.name.f) ? urole.name.f
2668                                                : urole.name.m);
2669         add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
2670     }
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);
2678     }
2679
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);
2683
2684     /* Deity list */
2685     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE);
2686     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2687              "Deities", FALSE);
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);
2695
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);
2703
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);
2711
2712     end_menu(tmpwin, "Base Attributes");
2713     n = select_menu(tmpwin, PICK_NONE, &selected);
2714     destroy_nhwindow(tmpwin);
2715     return (boolean) (n != -1);
2716 }
2717 #endif /*0*/
2718
2719 /* ^X command */
2720 STATIC_PTR int
2721 doattributes(VOID_ARGS)
2722 {
2723     int mode = BASICENLIGHTENMENT;
2724
2725     /* show more--as if final disclosure--for wizard and explore modes */
2726     if (wizard || discover)
2727         mode |= MAGICENLIGHTENMENT;
2728
2729     enlightenment(mode, ENL_GAMEINPROGRESS);
2730     return 0;
2731 }
2732
2733 void
2734 youhiding(via_enlghtmt, msgflag)
2735 boolean via_enlghtmt; /* englightment line vs topl message */
2736 int msgflag;          /* for variant message phrasing */
2737 {
2738     char *bp, buf[BUFSZ];
2739
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");
2752         } else {
2753             ; /* something unexpected; leave 'buf' as-is */
2754         }
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];
2762
2763             if (o)
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));
2768         } else {
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);
2772
2773                 Sprintf(bp, " in a %spit",
2774                         (t && t->ttyp == SPIKED_PIT) ? "spiked " : "");
2775             } else
2776                 Sprintf(bp, " on the %s", surface(u.ux, u.uy));
2777         }
2778     } else {
2779         ; /* shouldn't happen; will result in generic "you are hiding" */
2780     }
2781
2782     if (via_enlghtmt) {
2783         int final = msgflag; /* 'final' is used by you_are() macro */
2784
2785         you_are(buf, "");
2786     } else {
2787         /* for dohide(), when player uses '#monster' command */
2788         You("are %s %s.", msgflag ? "already" : "now", buf);
2789     }
2790 }
2791
2792 /* KMH, #conduct
2793  * (shares enlightenment's tense handling)
2794  */
2795 STATIC_PTR int
2796 doconduct(VOID_ARGS)
2797 {
2798     show_conduct(0);
2799     return 0;
2800 }
2801
2802 void
2803 show_conduct(final)
2804 int final;
2805 {
2806     char buf[BUFSZ];
2807     int ngenocided;
2808
2809     /* Create the conduct window */
2810     en_win = create_nhwindow(NHW_MENU);
2811 /*JP
2812     putstr(en_win, 0, "Voluntary challenges:");
2813 */
2814     putstr(en_win, 0, "\8e©\94­\93I\92§\90í:");
2815
2816     if (u.uroleplay.blind)
2817 /*JP
2818         you_have_been("blind from birth");
2819 */
2820         you_have_been("\90\82Ü\82ê\82È\82ª\82ç\82É\96Ó\96Ú");
2821     if (u.uroleplay.nudist)
2822 /*JP
2823         you_have_been("faithfully nudist");
2824 */
2825         you_have_been("\92\89\8eÀ\82È\97\87\91°");
2826
2827     if (!u.uconduct.food)
2828 /*JP
2829         enl_msg(You_, "have gone", "went", " without food", "");
2830 */
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)
2834 /*JP
2835         you_have_X("followed a strict vegan diet");
2836 */
2837         you_have_been("\8cµ\8ai\82È\8dØ\90H\8eå\8b`\8eÒ");
2838     else if (!u.uconduct.unvegetarian)
2839 /*JP
2840         you_have_been("vegetarian");
2841 */
2842         you_have_been("\8dØ\90H\8eå\8b`\8eÒ");
2843
2844     if (!u.uconduct.gnostic)
2845 /*JP
2846         you_have_been("an atheist");
2847 */
2848         you_have_been("\96³\90_\98_\8eÒ");
2849
2850     if (!u.uconduct.weaphit) {
2851 /*JP
2852         you_have_never("hit with a wielded weapon");
2853 */
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) {
2856 #if 0 /*JP*/
2857         Sprintf(buf, "used a wielded weapon %ld time%s", u.uconduct.weaphit,
2858                 plur(u.uconduct.weaphit));
2859         you_have_X(buf);
2860 #else
2861         Sprintf(buf, "\82 \82È\82½\82Í%ld\89ñ\91\95\94õ\82µ\82½\95\90\8aí\82ð\8eg\97p\82µ", u.uconduct.weaphit);
2862         you_have_X(buf);
2863 #endif
2864     }
2865     if (!u.uconduct.killer)
2866 /*JP
2867         you_have_been("a pacifist");
2868 */
2869         you_have_been("\95½\98a\8eå\8b`\8eÒ");
2870
2871     if (!u.uconduct.literate) {
2872 /*JP
2873         you_have_been("illiterate");
2874 */
2875         you_have_never("\82 \82È\82½\82Í\93Ç\82Ý\8f\91\82«\82µ");
2876     } else if (wizard) {
2877 #if 0 /*JP*/
2878         Sprintf(buf, "read items or engraved %ld time%s", u.uconduct.literate,
2879                 plur(u.uconduct.literate));
2880         you_have_X(buf);
2881 #else
2882         Sprintf(buf, "%ld\89ñ\93Ç\82ñ\82¾\82è\8f\91\82¢\82½\82è\82µ", u.uconduct.literate);
2883         you_have_X(buf);
2884 #endif
2885     }
2886
2887     ngenocided = num_genocides();
2888     if (ngenocided == 0) {
2889 /*JP
2890         you_have_never("genocided any monsters");
2891 */
2892         you_have_never("\82 \82È\82½\82Í\89ö\95¨\82ð\8bs\8eE\82µ");
2893     } else {
2894 #if 0 /*JP*/
2895         Sprintf(buf, "genocided %d type%s of monster%s", ngenocided,
2896                 plur(ngenocided), plur(ngenocided));
2897         you_have_X(buf);
2898 #else
2899         Sprintf(buf, "%d\8eí\82Ì\89ö\95¨\82ð\8bs\8eE\82µ", ngenocided);
2900         you_have_X(buf);
2901 #endif
2902     }
2903
2904     if (!u.uconduct.polypiles) {
2905 /*JP
2906         you_have_never("polymorphed an object");
2907 */
2908         you_have_never("\82 \82È\82½\82Í\95¨\91Ì\82ð\95Ï\89»\82³\82¹");
2909     } else if (wizard) {
2910 #if 0 /*JP*/
2911         Sprintf(buf, "polymorphed %ld item%s", u.uconduct.polypiles,
2912                 plur(u.uconduct.polypiles));
2913         you_have_X(buf);
2914 #else
2915         Sprintf(buf, "%ld\8cÂ\82Ì\93¹\8bï\82ð\95Ï\89»\82³\82¹", u.uconduct.polypiles);
2916         you_have_X(buf);
2917 #endif
2918     }
2919
2920     if (!u.uconduct.polyselfs) {
2921 /*JP
2922         you_have_never("changed form");
2923 */
2924         you_have_never("\82 \82È\82½\82Í\95Ï\89»\82µ");
2925     } else if (wizard) {
2926 #if 0 /*JP*/
2927         Sprintf(buf, "changed form %ld time%s", u.uconduct.polyselfs,
2928                 plur(u.uconduct.polyselfs));
2929         you_have_X(buf);
2930 #else
2931         Sprintf(buf, "%ld\89ñ\8ep\82ð\95Ï\82¦", u.uconduct.polyselfs);
2932         you_have_X(buf);
2933 #endif
2934     }
2935
2936     if (!u.uconduct.wishes) {
2937 /*JP
2938         you_have_X("used no wishes");
2939 */
2940         you_have_never("\82 \82È\82½\82Í\8aè\82¢\8e\96\82ð\82µ");
2941     } else {
2942 #if 0 /*JP*/
2943         Sprintf(buf, "used %ld wish%s", u.uconduct.wishes,
2944                 (u.uconduct.wishes > 1L) ? "es" : "");
2945         you_have_X(buf);
2946 #else
2947         Sprintf(buf, "%ld\89ñ\8aè\82¢\8e\96\82ð\82µ", u.uconduct.wishes);
2948         you_have_X(buf);
2949 #endif
2950
2951         if (!u.uconduct.wisharti)
2952 #if 0 /*JP*/
2953             enl_msg(You_, "have not wished", "did not wish",
2954                     " for any artifacts", "");
2955 #else
2956             enl_msg("\82 \82È\82½\82Í\90¹\8aí\82ð\8aè", "\82Á\82Ä\82¢\82È\82¢", "\82í\82È\82©\82Á\82½", "", "");
2957 #endif
2958     }
2959
2960     /* Pop up the window and wait for a key */
2961     display_nhwindow(en_win, TRUE);
2962     destroy_nhwindow(en_win);
2963     en_win = WIN_ERR;
2964 }
2965
2966 #ifndef M
2967 #ifndef NHSTDC
2968 #define M(c) (0x80 | (c))
2969 #else
2970 #define M(c) ((c) -128)
2971 #endif /* NHSTDC */
2972 #endif
2973 #ifndef C
2974 #define C(c) (0x1f & (c))
2975 #endif
2976
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 */
3042 /*JP
3043     { 's', TRUE, dosearch, "searching" },
3044 */
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 },
3072 #ifdef SHELL
3073     { '!', TRUE, dosh },
3074 #endif
3075 /*JP
3076     { '.', TRUE, donull, "waiting" },
3077 */
3078     { '.', TRUE, donull, "\8bx\8ce\82·\82é" },
3079 /*JP
3080     { ' ', TRUE, donull, "waiting" },
3081 */
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 },
3101     { 0, 0, 0, 0 }
3102 };
3103
3104 struct ext_func_tab extcmdlist[] = {
3105 /*JP
3106     { "adjust", "adjust inventory letters", doorganize, TRUE },
3107 */
3108     { "adjust", "\8e\9d\82¿\95¨\88ê\97\97\82Ì\92²\90®", doorganize, TRUE },
3109 /*JP
3110     { "annotate", "name current level", donamelevel, TRUE },
3111 */
3112     { "annotate", "\8c»\8dÝ\82Ì\8aK\82É\96¼\91O\82ð\82Â\82¯\82é", donamelevel, TRUE },
3113 #if 0 /*JP*/
3114     { "chat", "talk to someone", dotalk, TRUE }, /* converse? */
3115 #else
3116     { "chat", "\92N\82©\82Æ\98b\82·", dotalk, TRUE }, /* converse? */
3117 #endif
3118 #if 0 /*JP*/
3119     { "conduct", "list voluntary challenges you have maintained", doconduct,
3120       TRUE },
3121 #else
3122     { "conduct", "\82Ç\82¤\82¢\82¤\8ds\93®\82ð\82Æ\82Á\82½\82©\8c©\82é", doconduct, TRUE },
3123 #endif
3124 /*JP
3125     { "dip", "dip an object into something", dodip, FALSE },
3126 */
3127     { "dip", "\89½\82©\82É\95¨\82ð\90Z\82·", dodip, FALSE },
3128 #if 0 /*JP*/
3129     { "enhance", "advance or check weapon and spell skills",
3130       enhance_weapon_skill, TRUE },
3131 #else
3132     { "enhance", "\95\90\8aí\8fn\97û\93x\82ð\8d\82\82ß\82é", enhance_weapon_skill, TRUE },
3133 #endif
3134 /*JP
3135     { "exploremode", "enter explore mode", enter_explore_mode, TRUE },
3136 */
3137     { "exploremode", "\92T\8c\9f\83\82\81[\83h\82É\93ü\82é", enter_explore_mode, TRUE },
3138 /*JP
3139     { "force", "force a lock", doforce, FALSE },
3140 */
3141     { "force", "\8c®\82ð\82±\82\82 \82¯\82é", doforce, FALSE },
3142 /*JP
3143     { "invoke", "invoke an object's powers", doinvoke, TRUE },
3144 */
3145     { "invoke", "\95¨\82Ì\93Á\95Ê\82È\97Í\82ð\8eg\82¤", doinvoke, TRUE },
3146 /*JP
3147     { "jump", "jump to a location", dojump, FALSE },
3148 */
3149     { "jump", "\91¼\82Ì\88Ê\92u\82É\94ò\82Ñ\82¤\82Â\82é", dojump, FALSE },
3150 /*JP
3151     { "loot", "loot a box on the floor", doloot, FALSE },
3152 */
3153     { "loot", "\8f°\82Ì\8fã\82Ì\94 \82ð\8aJ\82¯\82é", doloot, TRUE },
3154 /*JP
3155     { "monster", "use a monster's special ability", domonability, TRUE },
3156 */
3157     { "monster", "\89ö\95¨\82Ì\93Á\95Ê\94\\97Í\82ð\8eg\82¤", domonability, TRUE },
3158 /*JP
3159     { "name", "name a monster or an object", docallcmd, TRUE },
3160 */
3161     { "name", "\83A\83C\83e\83\80\82â\95¨\82É\96¼\91O\82ð\82Â\82¯\82é", docallcmd, TRUE },
3162 /*JP
3163     { "offer", "offer a sacrifice to the gods", dosacrifice, FALSE },
3164 */
3165     { "offer", "\90_\82É\8b\9f\95¨\82ð\95ù\82°\82é", dosacrifice, FALSE },
3166 /*JP
3167     { "overview", "show an overview of the dungeon", dooverview, TRUE },
3168 */
3169     { "overview", "\96À\8b{\82Ì\8aT\97v\82ð\95\\8e¦\82·\82é", dooverview, TRUE },
3170 /*JP
3171     { "pray", "pray to the gods for help", dopray, TRUE },
3172 */
3173     { "pray", "\90_\82É\8bF\82é", dopray, TRUE },
3174 /*JP
3175     { "quit", "exit without saving current game", done2, TRUE },
3176 */
3177     { "quit", "\83Z\81[\83u\82µ\82È\82¢\82Å\8fI\97¹", done2, TRUE },
3178 /*JP
3179     { "ride", "ride (or stop riding) a monster", doride, FALSE },
3180 */
3181     { "ride", "\89ö\95¨\82É\8fæ\82é(\82Ü\82½\82Í\8d~\82è\82é)", doride, FALSE },
3182 /*JP
3183     { "rub", "rub a lamp or a stone", dorub, FALSE },
3184 */
3185     { "rub", "\83\89\83\93\83v\82ð\82±\82·\82é", dorub, FALSE },
3186 /*JP
3187     { "sit", "sit down", dosit, FALSE },
3188 */
3189     { "sit", "\8dÀ\82é", dosit, FALSE },
3190 /*JP
3191     { "terrain", "show map without obstructions", doterrain, TRUE },
3192 */
3193     { "terrain", "\8e×\96\82\82³\82ê\82¸\82É\92n\90}\82ð\8c©\82é", doterrain, TRUE },
3194 /*JP
3195     { "tip", "empty a container", dotip, FALSE },
3196 */
3197     { "tip", "\93ü\82ê\95¨\82ð\8bó\82É\82·\82é", dotip, FALSE },
3198 /*JP
3199     { "turn", "turn undead", doturn, TRUE },
3200 */
3201     { "turn", "\83A\83\93\83f\83b\83g\82ð\93y\82É\95Ô\82·", doturn, TRUE },
3202 /*JP
3203     { "twoweapon", "toggle two-weapon combat", dotwoweapon, FALSE },
3204 */
3205     { "twoweapon", "\97¼\8eè\8e\9d\82¿\82Ì\90Ø\82è\91Ö\82¦", dotwoweapon, FALSE },
3206 /*JP
3207     { "untrap", "untrap something", dountrap, FALSE },
3208 */
3209     { "untrap", "ã©\82ð\82Í\82¸\82·", dountrap, FALSE },
3210 #if 0 /*JP*/
3211     { "version", "list compile time options for this version of NetHack",
3212       doextversion, TRUE },
3213 #else
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 },
3215 #endif
3216 /*JP
3217     { "wipe", "wipe off your face", dowipe, FALSE },
3218 */
3219     { "wipe", "\8aç\82ð\90@\82¤", dowipe, FALSE },
3220 /*JP
3221     { "?", "get this list of extended commands", doextlist, TRUE },
3222 */
3223     { "?", "\82±\82Ì\8ag\92£\83R\83}\83\93\83h\88ê\97\97\82ð\95\\8e¦\82·\82é", doextlist, TRUE },
3224     /*
3225      * There must be a blank entry here for every entry in the table
3226      * below.
3227      */
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 */
3232 #endif
3233     { (char *) 0, (char *) 0, donull, TRUE }, /* monpolycontrol */
3234     { (char *) 0, (char *) 0, donull, TRUE }, /* panic */
3235     { (char *) 0, (char *) 0, donull, TRUE }, /* polyself */
3236 #ifdef PORT_DEBUG
3237     { (char *) 0, (char *) 0, donull, TRUE }, /* portdebug */
3238 #endif
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 */
3245 #ifdef DEBUG
3246     { (char *) 0, (char *) 0, donull, TRUE }, /* wizdebug_traveldisplay */
3247     { (char *) 0, (char *) 0, donull, TRUE }, /* wizdebug_bury */
3248 #endif
3249     { (char *) 0, (char *) 0, donull, TRUE }, /* wizrumorcheck */
3250     { (char *) 0, (char *) 0, donull, TRUE }, /* wmode */
3251     { (char *) 0, (char *) 0, donull, TRUE }  /* sentinel */
3252 };
3253
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 },
3260 #endif
3261     { "monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol,
3262       TRUE },
3263     { "panic", "test panic routine (fatal to game)", wiz_panic, TRUE },
3264     { "polyself", "polymorph self", wiz_polyself, TRUE },
3265 #ifdef PORT_DEBUG
3266     { "portdebug", "wizard port debug command", wiz_port_debug, TRUE },
3267 #endif
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 },
3274 #ifdef DEBUG
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 },
3279 #endif
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 }
3283 };
3284
3285 /*
3286  * Insert debug commands into the extended command list.  This function
3287  * assumes that the last entry will be the help entry.
3288  *
3289  * You must add entries in ext_func_tab every time you add one to the
3290  * debug_extcmdlist().
3291  */
3292 void
3293 add_debug_extended_commands()
3294 {
3295     int i, j, k, n;
3296
3297     /* count the # of help entries */
3298     for (n = 0; extcmdlist[n].ef_txt[0] != '?'; n++)
3299         ;
3300
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)
3307                 break;
3308
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 */
3314     }
3315 }
3316
3317 STATIC_OVL char
3318 cmd_from_func(fn)
3319 int NDECL((*fn));
3320 {
3321     int i;
3322     for (i = 0; i < SIZE(cmdlist); ++i)
3323         if (cmdlist[i].f_funct == fn)
3324             return cmdlist[i].f_char;
3325     return 0;
3326 }
3327
3328 static const char template[] = "%-18s %4ld  %6ld";
3329 static const char count_str[] = "                   count  bytes";
3330 static const char separator[] = "------------------ -----  ------";
3331
3332 STATIC_OVL int
3333 size_obj(otmp)
3334 struct obj *otmp;
3335 {
3336     int sz = (int) sizeof(struct obj);
3337
3338     if (otmp->oextra) {
3339         sz += (int) sizeof(struct oextra);
3340         if (ONAME(otmp))
3341             sz += (int) strlen(ONAME(otmp)) + 1;
3342         if (OMONST(otmp))
3343             sz += (int) sizeof(struct monst);
3344         if (OMID(otmp))
3345             sz += (int) sizeof(unsigned);
3346         if (OLONG(otmp))
3347             sz += (int) sizeof(long);
3348         if (OMAILCMD(otmp))
3349             sz += (int) strlen(OMAILCMD(otmp)) + 1;
3350     }
3351     return sz;
3352 }
3353
3354 STATIC_OVL void
3355 count_obj(chain, total_count, total_size, top, recurse)
3356 struct obj *chain;
3357 long *total_count;
3358 long *total_size;
3359 boolean top;
3360 boolean recurse;
3361 {
3362     long count, size;
3363     struct obj *obj;
3364
3365     for (count = size = 0, obj = chain; obj; obj = obj->nobj) {
3366         if (top) {
3367             count++;
3368             size += size_obj(obj);
3369         }
3370         if (recurse && obj->cobj)
3371             count_obj(obj->cobj, total_count, total_size, TRUE, TRUE);
3372     }
3373     *total_count += count;
3374     *total_size += size;
3375 }
3376
3377 STATIC_OVL void
3378 obj_chain(win, src, chain, total_count, total_size)
3379 winid win;
3380 const char *src;
3381 struct obj *chain;
3382 long *total_count;
3383 long *total_size;
3384 {
3385     char buf[BUFSZ];
3386     long count = 0, size = 0;
3387
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);
3393 }
3394
3395 STATIC_OVL void
3396 mon_invent_chain(win, src, chain, total_count, total_size)
3397 winid win;
3398 const char *src;
3399 struct monst *chain;
3400 long *total_count;
3401 long *total_size;
3402 {
3403     char buf[BUFSZ];
3404     long count = 0, size = 0;
3405     struct monst *mon;
3406
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);
3413 }
3414
3415 STATIC_OVL void
3416 contained(win, src, total_count, total_size)
3417 winid win;
3418 const char *src;
3419 long *total_count;
3420 long *total_size;
3421 {
3422     char buf[BUFSZ];
3423     long count = 0, size = 0;
3424     struct monst *mon;
3425
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
3431      * inventory */
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);
3436
3437     *total_count += count;
3438     *total_size += size;
3439
3440     Sprintf(buf, template, src, count, size);
3441     putstr(win, 0, buf);
3442 }
3443
3444 STATIC_OVL int
3445 size_monst(mtmp)
3446 struct monst *mtmp;
3447 {
3448     int sz = (int) sizeof(struct monst);
3449
3450     if (mtmp->mextra) {
3451         sz += (int) sizeof(struct mextra);
3452         if (MNAME(mtmp))
3453             sz += (int) strlen(MNAME(mtmp)) + 1;
3454         if (EGD(mtmp))
3455             sz += (int) sizeof(struct egd);
3456         if (EPRI(mtmp))
3457             sz += (int) sizeof(struct epri);
3458         if (ESHK(mtmp))
3459             sz += (int) sizeof(struct eshk);
3460         if (EMIN(mtmp))
3461             sz += (int) sizeof(struct emin);
3462         if (EDOG(mtmp))
3463             sz += (int) sizeof(struct edog);
3464         /* mextra->mcorpsenm doesn't point to more memory */
3465     }
3466     return sz;
3467 }
3468
3469 STATIC_OVL void
3470 mon_chain(win, src, chain, total_count, total_size)
3471 winid win;
3472 const char *src;
3473 struct monst *chain;
3474 long *total_count;
3475 long *total_size;
3476 {
3477     char buf[BUFSZ];
3478     long count, size;
3479     struct monst *mon;
3480
3481     for (count = size = 0, mon = chain; mon; mon = mon->nmon) {
3482         count++;
3483         size += size_monst(mon);
3484     }
3485     *total_count += count;
3486     *total_size += size;
3487     Sprintf(buf, template, src, count, size);
3488     putstr(win, 0, buf);
3489 }
3490
3491 /*
3492  * Display memory usage of all monsters and objects on the level.
3493  */
3494 static int
3495 wiz_show_stats()
3496 {
3497     char buf[BUFSZ];
3498     winid win;
3499     long total_obj_size = 0, total_obj_count = 0;
3500     long total_mon_size = 0, total_mon_count = 0;
3501
3502     win = create_nhwindow(NHW_TEXT);
3503     putstr(win, 0, "Current memory statistics:");
3504     putstr(win, 0, "");
3505     Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj));
3506     putstr(win, 0, buf);
3507     putstr(win, 0, "");
3508     putstr(win, 0, count_str);
3509
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,
3513               &total_obj_size);
3514     obj_chain(win, "migrating obj", migrating_objs, &total_obj_count,
3515               &total_obj_size);
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);
3519
3520     contained(win, "contained", &total_obj_count, &total_obj_size);
3521
3522     putstr(win, 0, separator);
3523     Sprintf(buf, template, "Total", total_obj_count, total_obj_size);
3524     putstr(win, 0, buf);
3525
3526     putstr(win, 0, "");
3527     putstr(win, 0, "");
3528     Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst));
3529     putstr(win, 0, buf);
3530     putstr(win, 0, "");
3531
3532     mon_chain(win, "fmon", fmon, &total_mon_count, &total_mon_size);
3533     mon_chain(win, "migrating", migrating_mons, &total_mon_count,
3534               &total_mon_size);
3535
3536     putstr(win, 0, separator);
3537     Sprintf(buf, template, "Total", total_mon_count, total_mon_size);
3538     putstr(win, 0, buf);
3539
3540 #if defined(__BORLANDC__) && !defined(_WIN32)
3541     show_borlandc_stats(win);
3542 #endif
3543
3544     display_nhwindow(win, FALSE);
3545     destroy_nhwindow(win);
3546     return 0;
3547 }
3548
3549 void
3550 sanity_check()
3551 {
3552     obj_sanity_check();
3553     timer_sanity_check();
3554     mon_sanity_check();
3555     light_sources_sanity_check();
3556 }
3557
3558 #ifdef DEBUG_MIGRATING_MONS
3559 static int
3560 wiz_migrate_mons()
3561 {
3562     int mcount = 0;
3563     char inbuf[BUFSZ];
3564     struct permonst *ptr;
3565     struct monst *mtmp;
3566     d_level tolevel;
3567
3568     getlin("How many random monsters to migrate? [0]", inbuf);
3569     if (*inbuf == '\033')
3570         return 0;
3571     mcount = atoi(inbuf);
3572     if (mcount < 0 || mcount > (COLNO * ROWNO) || Is_botlevel(&u.uz))
3573         return 0;
3574     while (mcount > 0) {
3575         if (Is_stronghold(&u.uz))
3576             assign_level(&tolevel, &valley_level);
3577         else
3578             get_level(&tolevel, depth(&u.uz) + 1);
3579         ptr = rndmonst();
3580         mtmp = makemon(ptr, 0, 0, NO_MM_FLAGS);
3581         if (mtmp)
3582             migrate_to_level(mtmp, ledger_no(&tolevel), MIGR_RANDOM,
3583                              (coord *) 0);
3584         mcount--;
3585     }
3586     return 0;
3587 }
3588 #endif
3589
3590 #define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c))
3591 #define unmeta(c) (0x7f & (c))
3592
3593 /* called at startup and after number_pad is twiddled */
3594 void
3595 reset_commands(initial)
3596 boolean initial;
3597 {
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'))
3604     };
3605     const struct func_tab *cmdtmp;
3606     boolean flagtemp;
3607     int c, i, updated = 0;
3608
3609     if (initial) {
3610         updated = 1;
3611         for (i = 0; i < SIZE(cmdlist); i++) {
3612             c = cmdlist[i].f_char & 0xff;
3613             Cmd.commands[c] = &cmdlist[i];
3614         }
3615         Cmd.num_pad = FALSE;
3616         Cmd.pcHack_compat = Cmd.phone_layout = Cmd.swap_yz = FALSE;
3617     } else {
3618         /* basic num_pad */
3619         flagtemp = iflags.num_pad;
3620         if (flagtemp != Cmd.num_pad) {
3621             Cmd.num_pad = flagtemp;
3622             ++updated;
3623         }
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;
3628             ++updated;
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 */
3636             }
3637         }
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;
3642             ++updated;
3643             /* pcHack_compat has been toggled */
3644             c = M('5') & 0xff;
3645             cmdtmp = Cmd.commands['5'];
3646             Cmd.commands['5'] = Cmd.commands[c];
3647             Cmd.commands[c] = cmdtmp;
3648             c = M('0') & 0xff;
3649             Cmd.commands[c] = Cmd.pcHack_compat ? Cmd.commands['I'] : 0;
3650         }
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;
3655             ++updated;
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 */
3666             }
3667         }
3668     } /*?initial*/
3669
3670     if (updated)
3671         Cmd.serialno++;
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;
3676
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];
3685 }
3686
3687 STATIC_OVL boolean
3688 accept_menu_prefix(cmd_func)
3689 int NDECL((*cmd_func));
3690 {
3691     if (cmd_func == dopickup || cmd_func == dotip
3692         || cmd_func == doextcmd || cmd_func == doextlist)
3693         return TRUE;
3694     return FALSE;
3695 }
3696
3697 void
3698 rhack(cmd)
3699 register char *cmd;
3700 {
3701     boolean do_walk, do_rush, prefix_seen, bad_command,
3702         firsttime = (cmd == 0);
3703
3704     iflags.menu_requested = FALSE;
3705 #ifdef SAFERHANGUP
3706     if (program_state.done_hup)
3707         end_of_input();
3708 #endif
3709     if (firsttime) {
3710         context.nopick = 0;
3711         cmd = parse();
3712     }
3713     if (*cmd == '\033') {
3714         context.move = FALSE;
3715         return;
3716     }
3717     if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
3718         in_doagain = TRUE;
3719         stail = 0;
3720         rhack((char *) 0); /* read and execute command */
3721         in_doagain = FALSE;
3722         return;
3723     }
3724     /* Special case of *cmd == ' ' handled better below */
3725     if (!*cmd || *cmd == (char) 0377) {
3726         nhbell();
3727         context.move = FALSE;
3728         return; /* probably we just had an interrupt */
3729     }
3730
3731     /* handle most movement commands */
3732     do_walk = do_rush = prefix_seen = FALSE;
3733     context.travel = context.travel1 = 0;
3734     switch (*cmd) {
3735     case 'g':
3736         if (movecmd(cmd[1])) {
3737             context.run = 2;
3738             do_rush = TRUE;
3739         } else
3740             prefix_seen = TRUE;
3741         break;
3742     case '5':
3743         if (!Cmd.num_pad)
3744             break; /* else FALLTHRU */
3745     case 'G':
3746         if (movecmd(lowc(cmd[1]))) {
3747             context.run = 3;
3748             do_rush = TRUE;
3749         } else
3750             prefix_seen = TRUE;
3751         break;
3752     case '-':
3753         if (!Cmd.num_pad)
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.
3759      */
3760     case 'F':
3761         if (movecmd(cmd[1])) {
3762             context.forcefight = 1;
3763             do_walk = TRUE;
3764         } else
3765             prefix_seen = TRUE;
3766         break;
3767     case 'm':
3768         if (movecmd(cmd[1]) || u.dz) {
3769             context.run = 0;
3770             context.nopick = 1;
3771             if (!u.dz)
3772                 do_walk = TRUE;
3773             else
3774                 cmd[0] = cmd[1]; /* "m<" or "m>" */
3775         } else
3776             prefix_seen = TRUE;
3777         break;
3778     case 'M':
3779         if (movecmd(lowc(cmd[1]))) {
3780             context.run = 1;
3781             context.nopick = 1;
3782             do_rush = TRUE;
3783         } else
3784             prefix_seen = TRUE;
3785         break;
3786     case '0':
3787         if (!Cmd.num_pad)
3788             break;
3789         (void) ddoinv(); /* a convenience borrowed from the PC */
3790         context.move = FALSE;
3791         multi = 0;
3792         return;
3793     case CMD_CLICKLOOK:
3794         if (iflags.clicklook) {
3795             context.move = FALSE;
3796             do_look(2, &clicklook_cc);
3797         }
3798         return;
3799     case CMD_TRAVEL:
3800         if (flags.travelcmd) {
3801             context.travel = 1;
3802             context.travel1 = 1;
3803             context.run = 8;
3804             context.nopick = 1;
3805             do_rush = TRUE;
3806             break;
3807         }
3808         /*FALLTHRU*/
3809     default:
3810         if (movecmd(*cmd)) { /* ordinary movement */
3811             context.run = 0; /* only matters here if it was 8 */
3812             do_walk = TRUE;
3813         } else if (movecmd(Cmd.num_pad ? unmeta(*cmd) : lowc(*cmd))) {
3814             context.run = 1;
3815             do_rush = TRUE;
3816         } else if (movecmd(unctrl(*cmd))) {
3817             context.run = 3;
3818             do_rush = TRUE;
3819         }
3820         break;
3821     }
3822
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;
3829
3830         if (func && accept_menu_prefix(func)) {
3831             iflags.menu_requested = TRUE;
3832             ++cmd;
3833         }
3834     }
3835
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...");
3843         context.run = 0;
3844         context.nopick = context.forcefight = FALSE;
3845         context.move = context.mv = FALSE;
3846         multi = 0;
3847         return;
3848     }
3849
3850     if (do_walk) {
3851         if (multi)
3852             context.mv = TRUE;
3853         domove();
3854         context.forcefight = 0;
3855         return;
3856     } else if (do_rush) {
3857         if (firsttime) {
3858             if (!multi)
3859                 multi = max(COLNO, ROWNO);
3860             u.last_str_turn = 0;
3861         }
3862         context.mv = TRUE;
3863         domove();
3864         return;
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 */
3870
3871         /* handle all other commands */
3872     } else {
3873         register const struct func_tab *tlist;
3874         int res, NDECL((*func));
3875
3876 #if 0
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))
3880                 continue;
3881 #else
3882         /* current - use *cmd to directly index cmdlist array */
3883         if ((tlist = Cmd.commands[*cmd & 0xff]) != 0) {
3884 #endif
3885             if (u.uburied && !tlist->can_if_buried) {
3886 /*JP
3887                 You_cant("do that while you are buried!");
3888 */
3889                 You("\96\84\82Ü\82Á\82Ä\82¢\82é\8e\9e\82É\82»\82ñ\82È\82±\82Æ\82Í\82Å\82«\82È\82¢\81I");
3890                 res = 0;
3891             } else {
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 */
3898             }
3899             if (!res) {
3900                 context.move = FALSE;
3901                 multi = 0;
3902             }
3903             return;
3904         }
3905         /* if we reach here, cmd wasn't found in cmdlist[] */
3906         bad_command = TRUE;
3907     }
3908
3909     if (bad_command) {
3910         char expcmd[10];
3911         register char c, *cp = expcmd;
3912
3913         while ((c = *cmd++) != '\0'
3914                && (int) (cp - expcmd) < (int) (sizeof expcmd - 3)) {
3915             if (c >= 040 && c < 0177) {
3916                 *cp++ = c;
3917             } else if (c & 0200) {
3918                 *cp++ = 'M';
3919                 *cp++ = '-';
3920                 *cp++ = c & ~0200;
3921             } else {
3922                 *cp++ = '^';
3923                 *cp++ = c ^ 0100;
3924             }
3925         }
3926         *cp = '\0';
3927         if (!prefix_seen || !iflags.cmdassist
3928 /*JP
3929             || !help_dir(0, "Invalid direction key!"))
3930 */
3931             || !help_dir(0, "\96³\8cø\82È\95û\8cü\8ew\92è\82Å\82·\81I"))
3932 /*JP
3933             Norep("Unknown command '%s'.", expcmd);
3934 */
3935             Norep("'%s'\83R\83}\83\93\83h\81H", expcmd);
3936     }
3937     /* didn't move */
3938     context.move = FALSE;
3939     multi = 0;
3940     return;
3941 }
3942
3943 /* convert an x,y pair into a direction code */
3944 int
3945 xytod(x, y)
3946 schar x, y;
3947 {
3948     register int dd;
3949
3950     for (dd = 0; dd < 8; dd++)
3951         if (x == xdir[dd] && y == ydir[dd])
3952             return dd;
3953     return -1;
3954 }
3955
3956 /* convert a direction code into an x,y pair */
3957 void
3958 dtoxy(cc, dd)
3959 coord *cc;
3960 register int dd;
3961 {
3962     cc->x = xdir[dd];
3963     cc->y = ydir[dd];
3964     return;
3965 }
3966
3967 /* also sets u.dz, but returns false for <> */
3968 int
3969 movecmd(sym)
3970 char sym;
3971 {
3972     register const char *dp = index(Cmd.dirchars, sym);
3973
3974     u.dz = 0;
3975     if (!dp || !*dp)
3976         return 0;
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)) {
3982         u.dx = u.dy = 0;
3983         return 0;
3984     }
3985 #endif
3986     return !u.dz;
3987 }
3988
3989 /* grid bug handling which used to be in movecmd() */
3990 int
3991 dxdy_moveok()
3992 {
3993     if (u.dx && u.dy && NODIAG(u.umonnum))
3994         u.dx = u.dy = 0;
3995     return u.dx || u.dy;
3996 }
3997
3998 /* decide whether a character (user input keystroke) requests screen repaint */
3999 boolean
4000 redraw_cmd(c)
4001 char c;
4002 {
4003     return (boolean) (c == C('r') || (Cmd.num_pad && c == C('l')));
4004 }
4005
4006 /*
4007  * uses getdir() but unlike getdir() it specifically
4008  * produces coordinates using the direction from getdir()
4009  * and verifies that those coordinates are ok.
4010  *
4011  * If the call to getdir() returns 0, Never_mind is displayed.
4012  * If the resulting coordinates are not okay, emsg is displayed.
4013  *
4014  * Returns non-zero if coordinates in cc are valid.
4015  */
4016 int
4017 get_adjacent_loc(prompt, emsg, x, y, cc)
4018 const char *prompt, *emsg;
4019 xchar x, y;
4020 coord *cc;
4021 {
4022     xchar new_x, new_y;
4023     if (!getdir(prompt)) {
4024         pline1(Never_mind);
4025         return 0;
4026     }
4027     new_x = x + u.dx;
4028     new_y = y + u.dy;
4029     if (cc && isok(new_x, new_y)) {
4030         cc->x = new_x;
4031         cc->y = new_y;
4032     } else {
4033         if (emsg)
4034             pline1(emsg);
4035         return 0;
4036     }
4037     return 1;
4038 }
4039
4040 int
4041 getdir(s)
4042 const char *s;
4043 {
4044     char dirsym;
4045     int is_mov;
4046
4047 retry:
4048     if (in_doagain || *readchar_queue)
4049         dirsym = readchar();
4050     else
4051 /*JP
4052         dirsym = yn_function((s && *s != '^') ? s : "In what direction?",
4053 */
4054         dirsym = yn_function((s && *s != '^') ? s : "\82Ç\82Ì\95û\8cü\81H",
4055                              (char *) 0, '\0');
4056     /* remove the prompt string so caller won't have to */
4057     clear_nhwindow(WIN_MESSAGE);
4058
4059     if (redraw_cmd(dirsym)) { /* ^R */
4060         docrt();              /* redraw */
4061         goto retry;
4062     }
4063     savech(dirsym);
4064
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;
4069
4070         if (!index(quitchars, dirsym)) {
4071             help_requested = (dirsym == '?');
4072             if (help_requested || iflags.cmdassist) {
4073                 did_help =
4074                     help_dir((s && *s == '^') ? dirsym : 0,
4075                              help_requested ? (const char *) 0
4076 /*JP
4077                                             : "Invalid direction key!");
4078 */
4079                                             : "\96³\8cø\82È\95û\8cü\8ew\92è\82Å\82·\81I");
4080                 if (help_requested)
4081                     goto retry;
4082             }
4083             if (!did_help)
4084 /*JP
4085                 pline("What a strange direction!");
4086 */
4087                 pline("\82¸\82¢\82Ô\82ñ\82Æ\8aï\96­\82È\95û\8cü\82¾\81I");
4088         }
4089         return 0;
4090     } else if (is_mov && !dxdy_moveok()) {
4091 /*JP
4092         You_cant("orient yourself that direction.");
4093 */
4094         You_cant("\8cü\82«\82É\8e©\95ª\8e©\90g\82ð\8ew\92è\82Å\82«\82È\82¢\81D");
4095         return 0;
4096     }
4097     if (!u.dz && (Stunned || (Confusion && !rn2(5))))
4098         confdir();
4099     return 1;
4100 }
4101
4102 STATIC_OVL boolean
4103 help_dir(sym, msg)
4104 char sym;
4105 const char *msg;
4106 {
4107     char ctrl;
4108     winid win;
4109     static const char wiz_only_list[] = "EFGIOVW";
4110     char buf[BUFSZ], buf2[BUFSZ], *explain;
4111
4112     win = create_nhwindow(NHW_TEXT);
4113     if (!win)
4114         return FALSE;
4115     if (msg) {
4116         Sprintf(buf, "cmdassist: %s", msg);
4117         putstr(win, 0, buf);
4118         putstr(win, 0, "");
4119     }
4120     if (letter(sym)) {
4121         sym = highc(sym);
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)
4127                         ? ""
4128                         : " as specified in the Guidebook");
4129             putstr(win, 0, buf);
4130             putstr(win, 0, "");
4131             putstr(win, 0, explain);
4132             putstr(win, 0, "");
4133             putstr(win, 0, "To use that command, you press");
4134             Sprintf(buf, "the <Ctrl> key, and the <%c> key at the same time.",
4135                     sym);
4136             putstr(win, 0, buf);
4137             putstr(win, 0, "");
4138         }
4139     }
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);
4150     } else {
4151         putstr(win, 0, "Valid direction keys are:");
4152         Sprintf(buf, "          %c  %c  %c", Cmd.move_NW, Cmd.move_N,
4153                 Cmd.move_NE);
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,
4160                 Cmd.move_SE);
4161         putstr(win, 0, buf);
4162     };
4163     putstr(win, 0, "");
4164     putstr(win, 0, "          <  up");
4165     putstr(win, 0, "          >  down");
4166     putstr(win, 0, "          .  direct at yourself");
4167     if (msg) {
4168         /* non-null msg means that this wasn't an explicit user request */
4169         putstr(win, 0, "");
4170         putstr(win, 0,
4171 /*JP
4172                "(Suppress this message with !cmdassist in config file.)");
4173 */
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)");
4175     }
4176     display_nhwindow(win, FALSE);
4177     destroy_nhwindow(win);
4178     return TRUE;
4179 }
4180
4181 void
4182 confdir()
4183 {
4184     register int x = NODIAG(u.umonnum) ? 2 * rn2(4) : rn2(8);
4185
4186     u.dx = xdir[x];
4187     u.dy = ydir[x];
4188     return;
4189 }
4190
4191 const char *
4192 directionname(dir)
4193 int dir;
4194 {
4195     static NEARDATA const char *const dirnames[] = {
4196         "west",      "northwest", "north",     "northeast", "east",
4197         "southeast", "south",     "southwest", "down",      "up",
4198     };
4199
4200     if (dir < 0 || dir >= SIZE(dirnames))
4201         return "invalid";
4202     return dirnames[dir];
4203 }
4204
4205 int
4206 isok(x, y)
4207 register int x, y;
4208 {
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;
4211 }
4212
4213 static NEARDATA int last_multi;
4214
4215 /*
4216  * convert a MAP window position into a movecmd
4217  */
4218 const char *
4219 click_to_cmd(x, y, mod)
4220 int x, y, mod;
4221 {
4222     int dir;
4223     static char cmd[4];
4224     cmd[1] = 0;
4225
4226     if (iflags.clicklook && mod == CLICK_2) {
4227         clicklook_cc.x = x;
4228         clicklook_cc.y = y;
4229         cmd[0] = CMD_CLICKLOOK;
4230         return cmd;
4231     }
4232
4233     x -= u.ux;
4234     y -= u.uy;
4235
4236     if (flags.travelcmd) {
4237         if (abs(x) <= 1 && abs(y) <= 1) {
4238             x = sgn(x), y = sgn(y);
4239         } else {
4240             u.tx = u.ux + x;
4241             u.ty = u.uy + y;
4242             cmd[0] = CMD_TRAVEL;
4243             return cmd;
4244         }
4245
4246         if (x == 0 && y == 0) {
4247             /* here */
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');
4251                 return cmd;
4252             } else if (IS_THRONE(levl[u.ux][u.uy].typ)) {
4253                 cmd[0] = M('s');
4254                 return cmd;
4255             } else if ((u.ux == xupstair && u.uy == yupstair)
4256                        || (u.ux == sstairs.sx && u.uy == sstairs.sy
4257                            && sstairs.up)
4258                        || (u.ux == xupladder && u.uy == yupladder)) {
4259                 return "<";
4260             } else if ((u.ux == xdnstair && u.uy == ydnstair)
4261                        || (u.ux == sstairs.sx && u.uy == sstairs.sy
4262                            && !sstairs.up)
4263                        || (u.ux == xdnladder && u.uy == ydnladder)) {
4264                 return ">";
4265             } else if (OBJ_AT(u.ux, u.uy)) {
4266                 cmd[0] =
4267                     Is_container(level.objects[u.ux][u.uy]) ? M('l') : ',';
4268                 return cmd;
4269             } else {
4270                 return "."; /* just rest */
4271             }
4272         }
4273
4274         /* directional commands */
4275
4276         dir = xytod(x, y);
4277
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];
4281             cmd[2] = '\0';
4282             if (IS_DOOR(levl[u.ux + x][u.uy + y].typ)) {
4283                 /* slight assistance to the player: choose kick/open for them
4284                  */
4285                 if (levl[u.ux + x][u.uy + y].doormask & D_LOCKED) {
4286                     cmd[0] = C('d');
4287                     return cmd;
4288                 }
4289                 if (levl[u.ux + x][u.uy + y].doormask & D_CLOSED) {
4290                     cmd[0] = 'o';
4291                     return cmd;
4292                 }
4293             }
4294             if (levl[u.ux + x][u.uy + y].typ <= SCORR) {
4295                 cmd[0] = 's';
4296                 cmd[1] = 0;
4297                 return cmd;
4298             }
4299         }
4300     } else {
4301         /* convert without using floating point, allowing sloppy clicking */
4302         if (x > 2 * abs(y))
4303             x = 1, y = 0;
4304         else if (y > 2 * abs(x))
4305             x = 0, y = 1;
4306         else if (x < -2 * abs(y))
4307             x = -1, y = 0;
4308         else if (y < -2 * abs(x))
4309             x = 0, y = -1;
4310         else
4311             x = sgn(x), y = sgn(y);
4312
4313         if (x == 0 && y == 0) /* map click on player to "rest" command */
4314             return ".";
4315
4316         dir = xytod(x, y);
4317     }
4318
4319     /* move, attack, etc. */
4320     cmd[1] = 0;
4321     if (mod == CLICK_1) {
4322         cmd[0] = Cmd.dirchars[dir];
4323     } else {
4324         cmd[0] = (Cmd.num_pad
4325                      ? M(Cmd.dirchars[dir])
4326                      : (Cmd.dirchars[dir] - 'a' + 'A')); /* run command */
4327     }
4328
4329     return cmd;
4330 }
4331
4332 STATIC_OVL char *
4333 parse()
4334 {
4335 #ifdef LINT /* static char in_line[COLNO]; */
4336     char in_line[COLNO];
4337 #else
4338     static char in_line[COLNO];
4339 #endif
4340     register int foo;
4341     boolean prezero = FALSE;
4342
4343     multi = 0;
4344     context.move = 1;
4345     flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
4346
4347 #ifdef ALTMETA
4348     alt_esc = iflags.altmeta; /* readchar() hack */
4349 #endif
4350     if (!Cmd.num_pad || (foo = readchar()) == 'n')
4351         for (;;) {
4352             foo = readchar();
4353             if (foo >= '0' && foo <= '9') {
4354                 multi = 10 * multi + foo - '0';
4355                 if (multi < 0 || multi >= LARGEST_INT)
4356                     multi = LARGEST_INT;
4357                 if (multi > 9) {
4358                     clear_nhwindow(WIN_MESSAGE);
4359 /*JP
4360                     Sprintf(in_line, "Count: %d", multi);
4361 */
4362                     Sprintf(in_line, "\90\94: %d", multi);
4363                     pline1(in_line);
4364                     mark_synch();
4365                 }
4366                 last_multi = multi;
4367                 if (!multi && foo == '0')
4368                     prezero = TRUE;
4369             } else
4370                 break; /* not a digit */
4371         }
4372 #ifdef ALTMETA
4373     alt_esc = FALSE; /* readchar() reset */
4374 #endif
4375
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) {
4380         multi = last_multi;
4381     } else {
4382         last_multi = multi;
4383         savech(0); /* reset input queue */
4384         savech((char) foo);
4385     }
4386
4387     if (multi) {
4388         multi--;
4389         save_cm = in_line;
4390     } else {
4391         save_cm = (char *) 0;
4392     }
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. */
4399         switch (foo) {
4400         case '5':
4401             foo = 'g';
4402             break;
4403         case M('5'):
4404             foo = 'G';
4405             break;
4406         case M('0'):
4407             foo = 'I';
4408             break;
4409         default:
4410             break; /* as is */
4411         }
4412     }
4413
4414     in_line[0] = foo;
4415     in_line[1] = '\0';
4416     if (foo == 'g' || foo == 'G' || foo == 'm' || foo == 'M' || foo == 'F'
4417         || (Cmd.num_pad && (foo == '5' || foo == '-'))) {
4418         foo = readchar();
4419         savech((char) foo);
4420         in_line[1] = foo;
4421         in_line[2] = 0;
4422     }
4423     clear_nhwindow(WIN_MESSAGE);
4424     if (prezero)
4425         in_line[0] = '\033';
4426     return in_line;
4427 }
4428
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 */
4433 /*ARGUSED*/
4434 void
4435 hangup(sig_unused) /* called as signal() handler, so sent at least one arg */
4436 int sig_unused UNUSED;
4437 {
4438     if (program_state.exiting)
4439         program_state.in_moveloop = 0;
4440     nhwindows_hangup();
4441 #ifdef SAFERHANGUP
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)
4451         return;
4452 #endif /* SAFERHANGUP */
4453     end_of_input();
4454 }
4455
4456 void
4457 end_of_input()
4458 {
4459 #ifdef NOSAVEONHANGUP
4460 #ifdef INSURANCE
4461     if (flags.ins_chkpt && program_state.something_worth_saving)
4462         program_statue.preserve_locks = 1; /* keep files for recovery */
4463 #endif
4464     program_state.something_worth_saving = 0; /* don't save */
4465 #endif
4466
4467 #ifndef SAFERHANGUP
4468     if (!program_state.done_hup++)
4469 #endif
4470         if (program_state.something_worth_saving)
4471             (void) dosave0();
4472     if (iflags.window_inited)
4473         exit_nhwindows((char *) 0);
4474     clearlocks();
4475     terminate(EXIT_SUCCESS);
4476     /*NOTREACHED*/ /* not necessarily true for vms... */
4477     return;
4478 }
4479 #endif /* HANGUPHANDLING */
4480
4481 char
4482 readchar()
4483 {
4484     register int sym;
4485     int x = u.ux, y = u.uy, mod = 0;
4486
4487     if (*readchar_queue)
4488         sym = *readchar_queue++;
4489     else
4490         sym = in_doagain ? pgetchar() : nh_poskey(&x, &y, &mod);
4491
4492 #ifdef NR_OF_EOFS
4493     if (sym == EOF) {
4494         register int cnt = NR_OF_EOFS;
4495         /*
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.
4499          */
4500         do {
4501             clearerr(stdin); /* omit if clearerr is undefined */
4502             sym = pgetchar();
4503         } while (--cnt && sym == EOF);
4504     }
4505 #endif /* NR_OF_EOFS */
4506
4507     if (sym == EOF) {
4508 #ifdef HANGUPHANDLING
4509         hangup(0); /* call end_of_input() or set program_state.done_hup */
4510 #endif
4511         sym = '\033';
4512 #ifdef ALTMETA
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)
4517             sym = '\033';
4518         else if (sym != '\033')
4519             sym |= 0200; /* force 8th bit on */
4520 #endif                   /*ALTMETA*/
4521     } else if (sym == 0) {
4522         /* click event */
4523         readchar_queue = click_to_cmd(x, y, mod);
4524         sym = *readchar_queue++;
4525     }
4526     return (char) sym;
4527 }
4528
4529 STATIC_PTR int
4530 dotravel(VOID_ARGS)
4531 {
4532     /* Keyboard travel command */
4533     static char cmd[2];
4534     coord cc;
4535
4536     if (!flags.travelcmd)
4537         return 0;
4538     cmd[1] = 0;
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 */
4543         cc.x = u.ux;
4544         cc.y = u.uy;
4545     }
4546 /*JP
4547     pline("Where do you want to travel to?");
4548 */
4549     pline("\82Ç\82±\82É\88Ú\93®\82·\82é\81H");
4550 /*JP
4551     if (getpos(&cc, TRUE, "the desired destination") < 0) {
4552 */
4553     if (getpos(&cc, TRUE, "\88Ú\93®\90æ") < 0) {
4554         /* user pressed ESC */
4555         return 0;
4556     }
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;
4561     return 0;
4562 }
4563
4564 #ifdef PORT_DEBUG
4565 extern void NDECL(win32con_debug_keystrokes);
4566 extern void NDECL(win32con_handler_info);
4567
4568 int
4569 wiz_port_debug()
4570 {
4571     int n, k;
4572     winid win;
4573     anything any;
4574     int item = 'a';
4575     int num_menu_selections;
4576     struct menu_selection_struct {
4577         char *menutext;
4578         void NDECL((*fn));
4579     } menu_selections[] = {
4580 #ifdef WIN32
4581         { "test win32 keystrokes (tty only)", win32con_debug_keystrokes },
4582         { "show keystroke handler information (tty only)",
4583           win32con_handler_info },
4584 #endif
4585         { (char *) 0, (void NDECL((*) )) 0 } /* array terminator */
4586     };
4587
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);
4592         start_menu(win);
4593         for (k = 0; k < num_menu_selections; ++k) {
4594             any.a_int = k + 1;
4595             add_menu(win, NO_GLYPH, &any, item++, 0, ATR_NONE,
4596                      menu_selections[k].menutext, MENU_UNSELECTED);
4597         }
4598         end_menu(win, "Which port debugging feature?");
4599         n = select_menu(win, PICK_ONE, &pick_list);
4600         destroy_nhwindow(win);
4601         if (n > 0) {
4602             n = pick_list[0].item.a_int - 1;
4603             free((genericptr_t) pick_list);
4604             /* execute the function */
4605             (*menu_selections[n].fn)();
4606         }
4607     } else
4608         pline("No port-specific debug capability defined.");
4609     return 0;
4610 }
4611 #endif /*PORT_DEBUG*/
4612
4613 /*
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.
4617  */
4618 char
4619 yn_function(query, resp, def)
4620 const char *query, *resp;
4621 char def;
4622 {
4623     char qbuf[QBUFSZ];
4624
4625     iflags.last_msg = PLNMSG_UNKNOWN; /* most recent pline is clobbered */
4626
4627     /* maximum acceptable length is QBUFSZ-1 */
4628     if (strlen(query) < QBUFSZ)
4629         return (*windowprocs.win_yn_function)(query, resp, def);
4630
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);
4636 }
4637
4638 /* for paranoid_confirm:quit,die,attack prompting */
4639 boolean
4640 paranoid_query(be_paranoid, prompt)
4641 boolean be_paranoid;
4642 const char *prompt;
4643 {
4644     boolean confirmed_ok;
4645
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 */
4649     if (be_paranoid) {
4650         char qbuf[QBUFSZ], ans[BUFSZ];
4651         const char *promptprefix = "", *responsetype = ParanoidConfirm
4652                                                            ? "(yes|no)"
4653                                                            : "(yes) [no]";
4654         int trylimit = 6; /* 1 normal, 5 more with "Yes or No:" prefix */
4655
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) */
4661         do {
4662             Sprintf(qbuf, "%s%s %s", promptprefix, prompt, responsetype);
4663             getlin(qbuf, ans);
4664             (void) mungspaces(ans);
4665             confirmed_ok = !strcmpi(ans, "yes");
4666             if (confirmed_ok || *ans == '\033')
4667                 break;
4668             promptprefix = "\"Yes\" or \"No\": ";
4669         } while (ParanoidConfirm && strcmpi(ans, "no") && --trylimit);
4670     } else
4671         confirmed_ok = (yn(prompt) == 'y');
4672
4673     return confirmed_ok;
4674 }
4675
4676 int
4677 dosuspend_core()
4678 {
4679 #ifdef SUSPEND
4680     /* Does current window system support suspend? */
4681     if ((*windowprocs.win_can_suspend)()) {
4682         /* NB: SYSCF SHELLERS handled in port code. */
4683         dosuspend();
4684     } else
4685 #endif
4686         Norep("Suspend command not available.");
4687     return 0;
4688 }
4689
4690 /*cmd.c*/