Source:NetHack 3.4.0/cmd.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to cmd.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/cmd.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)cmd.c	3.4	2002/01/17	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    #include "func_tab.h"
7.    /* #define DEBUG */	/* uncomment for debugging */
8.    
9.    /*
10.    * Some systems may have getchar() return EOF for various reasons, and
11.    * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
12.    */
13.   #if defined(SYSV) || defined(DGUX) || defined(HPUX)
14.   #define NR_OF_EOFS	20
15.   #endif
16.   
17.   #define CMD_TRAVEL (char)0x90
18.   
19.   #ifdef DEBUG
20.   /*
21.    * only one "wiz_debug_cmd" routine should be available (in whatever
22.    * module you are trying to debug) or things are going to get rather
23.    * hard to link :-)
24.    */
25.   extern void NDECL(wiz_debug_cmd);
26.   #endif
27.   
28.   #ifdef DUMB	/* stuff commented out in extern.h, but needed here */
29.   extern int NDECL(doapply); /**/
30.   extern int NDECL(dorub); /**/
31.   extern int NDECL(dojump); /**/
32.   extern int NDECL(doextlist); /**/
33.   extern int NDECL(dodrop); /**/
34.   extern int NDECL(doddrop); /**/
35.   extern int NDECL(dodown); /**/
36.   extern int NDECL(doup); /**/
37.   extern int NDECL(donull); /**/
38.   extern int NDECL(dowipe); /**/
39.   extern int NDECL(do_mname); /**/
40.   extern int NDECL(ddocall); /**/
41.   extern int NDECL(dotakeoff); /**/
42.   extern int NDECL(doremring); /**/
43.   extern int NDECL(dowear); /**/
44.   extern int NDECL(doputon); /**/
45.   extern int NDECL(doddoremarm); /**/
46.   extern int NDECL(dokick); /**/
47.   extern int NDECL(dofire); /**/
48.   extern int NDECL(dothrow); /**/
49.   extern int NDECL(doeat); /**/
50.   extern int NDECL(done2); /**/
51.   extern int NDECL(doengrave); /**/
52.   extern int NDECL(dopickup); /**/
53.   extern int NDECL(ddoinv); /**/
54.   extern int NDECL(dotypeinv); /**/
55.   extern int NDECL(dolook); /**/
56.   extern int NDECL(doprgold); /**/
57.   extern int NDECL(doprwep); /**/
58.   extern int NDECL(doprarm); /**/
59.   extern int NDECL(doprring); /**/
60.   extern int NDECL(dopramulet); /**/
61.   extern int NDECL(doprtool); /**/
62.   extern int NDECL(dosuspend); /**/
63.   extern int NDECL(doforce); /**/
64.   extern int NDECL(doopen); /**/
65.   extern int NDECL(doclose); /**/
66.   extern int NDECL(dosh); /**/
67.   extern int NDECL(dodiscovered); /**/
68.   extern int NDECL(doset); /**/
69.   extern int NDECL(dotogglepickup); /**/
70.   extern int NDECL(dowhatis); /**/
71.   extern int NDECL(doquickwhatis); /**/
72.   extern int NDECL(dowhatdoes); /**/
73.   extern int NDECL(dohelp); /**/
74.   extern int NDECL(dohistory); /**/
75.   extern int NDECL(doloot); /**/
76.   extern int NDECL(dodrink); /**/
77.   extern int NDECL(dodip); /**/
78.   extern int NDECL(dosacrifice); /**/
79.   extern int NDECL(dopray); /**/
80.   extern int NDECL(doturn); /**/
81.   extern int NDECL(doredraw); /**/
82.   extern int NDECL(doread); /**/
83.   extern int NDECL(dosave); /**/
84.   extern int NDECL(dosearch); /**/
85.   extern int NDECL(doidtrap); /**/
86.   extern int NDECL(dopay); /**/
87.   extern int NDECL(dosit); /**/
88.   extern int NDECL(dotalk); /**/
89.   extern int NDECL(docast); /**/
90.   extern int NDECL(dovspell); /**/
91.   extern int NDECL(dotele); /**/
92.   extern int NDECL(dountrap); /**/
93.   extern int NDECL(doversion); /**/
94.   extern int NDECL(doextversion); /**/
95.   extern int NDECL(doswapweapon); /**/
96.   extern int NDECL(dowield); /**/
97.   extern int NDECL(dowieldquiver); /**/
98.   extern int NDECL(dozap); /**/
99.   extern int NDECL(doorganize); /**/
100.  #endif /* DUMB */
101.  
102.  #ifdef OVL1
103.  static int NDECL((*timed_occ_fn));
104.  #endif /* OVL1 */
105.  
106.  STATIC_PTR int NDECL(doprev_message);
107.  STATIC_PTR int NDECL(timed_occupation);
108.  STATIC_PTR int NDECL(doextcmd);
109.  STATIC_PTR int NDECL(domonability);
110.  STATIC_PTR int NDECL(dotravel);
111.  # ifdef WIZARD
112.  STATIC_PTR int NDECL(wiz_wish);
113.  STATIC_PTR int NDECL(wiz_identify);
114.  STATIC_PTR int NDECL(wiz_map);
115.  STATIC_PTR int NDECL(wiz_genesis);
116.  STATIC_PTR int NDECL(wiz_where);
117.  STATIC_PTR int NDECL(wiz_detect);
118.  STATIC_PTR int NDECL(wiz_polyself);
119.  STATIC_PTR int NDECL(wiz_level_tele);
120.  STATIC_PTR int NDECL(wiz_level_change);
121.  STATIC_PTR int NDECL(wiz_show_seenv);
122.  STATIC_PTR int NDECL(wiz_show_vision);
123.  STATIC_PTR int NDECL(wiz_mon_polycontrol);
124.  STATIC_PTR int NDECL(wiz_show_wmodes);
125.  #if defined(__BORLANDC__) && !defined(_WIN32)
126.  extern void FDECL(show_borlandc_stats, (winid));
127.  #endif
128.  STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *, BOOLEAN_P, BOOLEAN_P));
129.  STATIC_DCL void FDECL(obj_chain, (winid, const char *, struct obj *, long *, long *));
130.  STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *, long *, long *));
131.  STATIC_DCL void FDECL(mon_chain, (winid, const char *, struct monst *, long *, long *));
132.  STATIC_DCL void FDECL(contained, (winid, const char *, long *, long *));
133.  STATIC_PTR int NDECL(wiz_show_stats);
134.  # endif
135.  STATIC_PTR int NDECL(enter_explore_mode);
136.  STATIC_PTR int NDECL(doattributes);
137.  STATIC_PTR int NDECL(doconduct); /**/
138.  STATIC_PTR void NDECL(minimal_enlightenment);
139.  
140.  #ifdef OVLB
141.  STATIC_DCL void FDECL(enlght_line, (const char *,const char *,const char *));
142.  #ifdef UNIX
143.  static void NDECL(end_of_input);
144.  #endif
145.  #endif /* OVLB */
146.  
147.  static const char* readchar_queue="";
148.  
149.  STATIC_DCL char *NDECL(parse);
150.  
151.  #ifdef OVL1
152.  
153.  STATIC_PTR int
154.  doprev_message()
155.  {
156.      return nh_doprev_message();
157.  }
158.  
159.  /* Count down by decrementing multi */
160.  STATIC_PTR int
161.  timed_occupation()
162.  {
163.  	(*timed_occ_fn)();
164.  	if (multi > 0)
165.  		multi--;
166.  	return multi > 0;
167.  }
168.  
169.  /* If you have moved since initially setting some occupations, they
170.   * now shouldn't be able to restart.
171.   *
172.   * The basic rule is that if you are carrying it, you can continue
173.   * since it is with you.  If you are acting on something at a distance,
174.   * your orientation to it must have changed when you moved.
175.   *
176.   * The exception to this is taking off items, since they can be taken
177.   * off in a number of ways in the intervening time, screwing up ordering.
178.   *
179.   *	Currently:	Take off all armor.
180.   *			Picking Locks / Forcing Chests.
181.   *			Setting traps.
182.   */
183.  void
184.  reset_occupations()
185.  {
186.  	reset_remarm();
187.  	reset_pick();
188.  	reset_trapset();
189.  }
190.  
191.  /* If a time is given, use it to timeout this function, otherwise the
192.   * function times out by its own means.
193.   */
194.  void
195.  set_occupation(fn, txt, xtime)
196.  int NDECL((*fn));
197.  const char *txt;
198.  int xtime;
199.  {
200.  	if (xtime) {
201.  		occupation = timed_occupation;
202.  		timed_occ_fn = fn;
203.  	} else
204.  		occupation = fn;
205.  	occtxt = txt;
206.  	occtime = 0;
207.  	return;
208.  }
209.  
210.  #ifdef REDO
211.  
212.  static char NDECL(popch);
213.  
214.  /* Provide a means to redo the last command.  The flag `in_doagain' is set
215.   * to true while redoing the command.  This flag is tested in commands that
216.   * require additional input (like `throw' which requires a thing and a
217.   * direction), and the input prompt is not shown.  Also, while in_doagain is
218.   * TRUE, no keystrokes can be saved into the saveq.
219.   */
220.  #define BSIZE 20
221.  static char pushq[BSIZE], saveq[BSIZE];
222.  static NEARDATA int phead, ptail, shead, stail;
223.  
224.  static char
225.  popch() {
226.  	/* If occupied, return '\0', letting tgetch know a character should
227.  	 * be read from the keyboard.  If the character read is not the
228.  	 * ABORT character (as checked in pcmain.c), that character will be
229.  	 * pushed back on the pushq.
230.  	 */
231.  	if (occupation) return '\0';
232.  	if (in_doagain) return(char)((shead != stail) ? saveq[stail++] : '\0');
233.  	else		return(char)((phead != ptail) ? pushq[ptail++] : '\0');
234.  }
235.  
236.  char
237.  pgetchar() {		/* curtesy of aeb@cwi.nl */
238.  	register int ch;
239.  
240.  	if(!(ch = popch()))
241.  		ch = nhgetch();
242.  	return((char)ch);
243.  }
244.  
245.  /* A ch == 0 resets the pushq */
246.  void
247.  pushch(ch)
248.  char ch;
249.  {
250.  	if (!ch)
251.  		phead = ptail = 0;
252.  	if (phead < BSIZE)
253.  		pushq[phead++] = ch;
254.  	return;
255.  }
256.  
257.  /* A ch == 0 resets the saveq.	Only save keystrokes when not
258.   * replaying a previous command.
259.   */
260.  void
261.  savech(ch)
262.  char ch;
263.  {
264.  	if (!in_doagain) {
265.  		if (!ch)
266.  			phead = ptail = shead = stail = 0;
267.  		else if (shead < BSIZE)
268.  			saveq[shead++] = ch;
269.  	}
270.  	return;
271.  }
272.  #endif /* REDO */
273.  
274.  #endif /* OVL1 */
275.  #ifdef OVLB
276.  
277.  STATIC_PTR int
278.  doextcmd()	/* here after # - now read a full-word command */
279.  {
280.  	int idx, retval;
281.  
282.  	/* keep repeating until we don't run help or quit */
283.  	do {
284.  	    idx = get_ext_cmd();
285.  	    if (idx < 0) return 0;	/* quit */
286.  
287.  	    retval = (*extcmdlist[idx].ef_funct)();
288.  	} while (extcmdlist[idx].ef_funct == doextlist);
289.  
290.  	return retval;
291.  }
292.  
293.  int
294.  doextlist()	/* here after #? - now list all full-word commands */
295.  {
296.  	register const struct ext_func_tab *efp;
297.  	char	 buf[BUFSZ];
298.  	winid datawin;
299.  
300.  	datawin = create_nhwindow(NHW_TEXT);
301.  	putstr(datawin, 0, "");
302.  	putstr(datawin, 0, "            Extended Commands List");
303.  	putstr(datawin, 0, "");
304.  	putstr(datawin, 0, "    Press '#', then type:");
305.  	putstr(datawin, 0, "");
306.  
307.  	for(efp = extcmdlist; efp->ef_txt; efp++) {
308.  		Sprintf(buf, "    %-15s - %s.", efp->ef_txt, efp->ef_desc);
309.  		putstr(datawin, 0, buf);
310.  	}
311.  	display_nhwindow(datawin, FALSE);
312.  	destroy_nhwindow(datawin);
313.  	return 0;
314.  }
315.  
316.  #ifdef TTY_GRAPHICS
317.  #define MAX_EXT_CMD 40		/* Change if we ever have > 40 ext cmds */
318.  /*
319.   * This is currently used only by the tty port and is
320.   * controlled via runtime option 'extmenu'
321.   */
322.  int
323.  extcmd_via_menu()	/* here after # - now show pick-list of possible commands */
324.  {
325.      const struct ext_func_tab *efp;
326.      menu_item *pick_list = (menu_item *)0;
327.      winid win;
328.      anything any;
329.      const struct ext_func_tab *choices[MAX_EXT_CMD];
330.      char buf[BUFSZ];
331.      char cbuf[QBUFSZ], prompt[QBUFSZ], fmtstr[20];
332.      int i, n, nchoices, acount;
333.      int ret,  biggest;
334.      int accelerator, prevaccelerator;
335.      int  matchlevel = 0;
336.  
337.      ret = 0;
338.      cbuf[0] = '\0';
339.      biggest = 0;
340.      while (!ret) {
341.  	    i = n = 0;
342.  	    accelerator = 0;
343.  	    any.a_void = 0;
344.  	    /* populate choices */
345.  	    for(efp = extcmdlist; efp->ef_txt; efp++) {
346.  		if (!matchlevel || !strncmp(efp->ef_txt, cbuf, matchlevel)) {
347.  			choices[i++] = efp;
348.  			if ((int)strlen(efp->ef_desc) > biggest) {
349.  				biggest = strlen(efp->ef_desc);
350.  				Sprintf(fmtstr,"%%-%ds", biggest + 15);
351.  			}
352.  #ifdef DEBUG
353.  			if (i >= MAX_EXT_CMD - 2) {
354.  			    impossible("Exceeded %d extended commands in doextcmd() menu",
355.  					MAX_EXT_CMD - 2);
356.  			    return 0;
357.  			}
358.  #endif
359.  		}
360.  	    }
361.  	    choices[i] = (struct ext_func_tab *)0;
362.  	    nchoices = i;
363.  	    /* if we're down to one, we have our selection so get out of here */
364.  	    if (nchoices == 1) {
365.  		for (i = 0; extcmdlist[i].ef_txt != (char *)0; i++)
366.  			if (!strncmpi(extcmdlist[i].ef_txt, cbuf, matchlevel)) {
367.  				ret = i;
368.  				break;
369.  			}
370.  		break;
371.  	    }
372.  
373.  	    /* otherwise... */
374.  	    win = create_nhwindow(NHW_MENU);
375.  	    start_menu(win);
376.  	    prevaccelerator = 0;
377.  	    acount = 0;
378.  	    for(i = 0; choices[i]; ++i) {
379.  		accelerator = choices[i]->ef_txt[matchlevel];
380.  		if (accelerator != prevaccelerator || nchoices < (ROWNO - 3)) {
381.  		    if (acount) {
382.   			/* flush the extended commands for that letter already in buf */
383.  			Sprintf(buf, fmtstr, prompt);
384.  			any.a_char = prevaccelerator;
385.  			add_menu(win, NO_GLYPH, &any, any.a_char, 0,
386.  					ATR_NONE, buf, FALSE);
387.  			acount = 0;
388.  		    }
389.  		}
390.  		prevaccelerator = accelerator;
391.  		if (!acount || nchoices < (ROWNO - 3)) {
392.  		    Sprintf(prompt, "%s [%s]", choices[i]->ef_txt,
393.  				choices[i]->ef_desc);
394.  		} else if (acount == 1) {
395.  		    Sprintf(prompt, "%s or %s", choices[i-1]->ef_txt,
396.  				choices[i]->ef_txt);
397.  		} else {
398.  		    Strcat(prompt," or ");
399.  		    Strcat(prompt, choices[i]->ef_txt);
400.  		}
401.  		++acount;
402.  	    }
403.  	    if (acount) {
404.  		/* flush buf */
405.  		Sprintf(buf, fmtstr, prompt);
406.  		any.a_char = prevaccelerator;
407.  		add_menu(win, NO_GLYPH, &any, any.a_char, 0, ATR_NONE, buf, FALSE);
408.  	    }
409.  	    Sprintf(prompt, "Extended Command: %s", cbuf);
410.  	    end_menu(win, prompt);
411.  	    n = select_menu(win, PICK_ONE, &pick_list);
412.  	    destroy_nhwindow(win);
413.  	    if (n==1) {
414.  		if (matchlevel > (QBUFSZ - 2)) {
415.  			free((genericptr_t)pick_list);
416.  #ifdef DEBUG
417.  			impossible("Too many characters (%d) entered in extcmd_via_menu()",
418.  				matchlevel);
419.  #endif
420.  			ret = -1;
421.  		} else {
422.  			cbuf[matchlevel++] = pick_list[0].item.a_char;
423.  			cbuf[matchlevel] = '\0';
424.  			free((genericptr_t)pick_list);
425.  		}
426.  	    } else {
427.  		if (matchlevel) {
428.  			ret = 0;
429.  			matchlevel = 0;
430.  		} else
431.  			ret = -1;
432.  	    }
433.      }
434.      return ret;
435.  }
436.  #endif
437.  
438.  STATIC_PTR int
439.  domonability()
440.  {
441.  	if (can_breathe(youmonst.data)) return dobreathe();
442.  	else if (attacktype(youmonst.data, AT_SPIT)) return dospit();
443.  	else if (youmonst.data->mlet == S_NYMPH) return doremove();
444.  	else if (attacktype(youmonst.data, AT_GAZE)) return dogaze();
445.  	else if (is_were(youmonst.data)) return dosummon();
446.  	else if (webmaker(youmonst.data)) return dospinweb();
447.  	else if (is_hider(youmonst.data)) return dohide();
448.  	else if (is_mind_flayer(youmonst.data)) return domindblast();
449.  	else if (u.umonnum == PM_GREMLIN) {
450.  	    if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
451.  		if (split_mon(&youmonst, (struct monst *)0))
452.  		    dryup(u.ux, u.uy, TRUE);
453.  	    } else There("is no fountain here.");
454.  	} else if (is_unicorn(youmonst.data)) {
455.  	    use_unicorn_horn((struct obj *)0);
456.  	    return 1;
457.  	} else if (youmonst.data->msound == MS_SHRIEK) {
458.  	    You("shriek.");
459.  	    if(u.uburied)
460.  		pline("Unfortunately sound does not carry well through rock.");
461.  	    else aggravate();
462.  	} else if (Upolyd)
463.  		pline("Any special ability you may have is purely reflexive.");
464.  	else You("don't have a special ability in your normal form!");
465.  	return 0;
466.  }
467.  
468.  STATIC_PTR int
469.  enter_explore_mode()
470.  {
471.  	if(!discover && !wizard) {
472.  		pline("Beware!  From explore mode there will be no return to normal game.");
473.  		if (yn("Do you want to enter explore mode?") == 'y') {
474.  			clear_nhwindow(WIN_MESSAGE);
475.  			You("are now in non-scoring explore mode.");
476.  			discover = TRUE;
477.  		}
478.  		else {
479.  			clear_nhwindow(WIN_MESSAGE);
480.  			pline("Resuming normal game.");
481.  		}
482.  	}
483.  	return 0;
484.  }
485.  
486.  #ifdef WIZARD
487.  STATIC_PTR int
488.  wiz_wish()	/* Unlimited wishes for debug mode by Paul Polderman */
489.  {
490.  	if (wizard) {
491.  	    boolean save_verbose = flags.verbose;
492.  
493.  	    flags.verbose = FALSE;
494.  	    makewish();
495.  	    flags.verbose = save_verbose;
496.  	    (void) encumber_msg();
497.  	} else
498.  	    pline("Unavailable command '^W'.");
499.  	return 0;
500.  }
501.  
502.  STATIC_PTR int
503.  wiz_identify()
504.  {
505.  	if (wizard)	identify_pack(0);
506.  	else		pline("Unavailable command '^I'.");
507.  	return 0;
508.  }
509.  
510.  /* reveal the level map and any traps on it */
511.  STATIC_PTR int
512.  wiz_map()
513.  {
514.  	if (wizard) {
515.  	    struct trap *t;
516.  
517.  	    for (t = ftrap; t != 0; t = t->ntrap) {
518.  		t->tseen = 1;
519.  		map_trap(t, TRUE);
520.  	    }
521.  	    do_mapping();
522.  	} else
523.  	    pline("Unavailable command '^F'.");
524.  	return 0;
525.  }
526.  
527.  STATIC_PTR int
528.  wiz_genesis()
529.  {
530.  	if (wizard)	(void) create_particular();
531.  	else		pline("Unavailable command '^G'.");
532.  	return 0;
533.  }
534.  
535.  STATIC_PTR int
536.  wiz_where()
537.  {
538.  	if (wizard) print_dungeon();
539.  	else	    pline("Unavailable command '^O'.");
540.  	return 0;
541.  }
542.  
543.  STATIC_PTR int
544.  wiz_detect()
545.  {
546.  	if(wizard)  (void) findit();
547.  	else	    pline("Unavailable command '^E'.");
548.  	return 0;
549.  }
550.  
551.  STATIC_PTR int
552.  wiz_level_tele()
553.  {
554.  	if (wizard)	level_tele();
555.  	else		pline("Unavailable command '^V'.");
556.  	return 0;
557.  }
558.  
559.  STATIC_PTR int
560.  wiz_mon_polycontrol()
561.  {
562.      iflags.mon_polycontrol = !iflags.mon_polycontrol;
563.      pline("Monster polymorph control is %s.",
564.  	  iflags.mon_polycontrol ? "on" : "off");
565.      return 0;
566.  }
567.  
568.  STATIC_PTR int
569.  wiz_level_change()
570.  {
571.      char buf[BUFSZ];
572.      int newlevel;
573.      int ret;
574.  
575.      getlin("To what experience level do you want to be set?", buf);
576.      (void)mungspaces(buf);
577.      if (buf[0] == '\033' || buf[0] == '\0') ret = 0;
578.      else ret = sscanf(buf, "%d", &newlevel);
579.  
580.      if (ret != 1) {
581.  	pline(Never_mind);
582.  	return 0;
583.      }
584.      if (newlevel == u.ulevel) {
585.  	You("are already that experienced.");
586.      } else if (newlevel < u.ulevel) {
587.  	if (u.ulevel == 1) {
588.  	    You("are already as inexperienced as you can get.");
589.  	    return 0;
590.  	}
591.  	if (newlevel < 1) newlevel = 1;
592.  	while (u.ulevel > newlevel)
593.  	    losexp((const char *)0);
594.      } else {
595.  	if (u.ulevel >= MAXULEV) {
596.  	    You("are already as experienced as you can get.");
597.  	    return 0;
598.  	}
599.  	if (newlevel > MAXULEV) newlevel = MAXULEV;
600.  	while (u.ulevel < newlevel)
601.  	    pluslvl(FALSE);
602.      }
603.      u.ulevelmax = u.ulevel;
604.      return 0;
605.  }
606.  
607.  STATIC_PTR int
608.  wiz_polyself()
609.  {
610.          polyself(TRUE);
611.          return 0;
612.  }
613.  
614.  STATIC_PTR int
615.  wiz_show_seenv()
616.  {
617.  	winid win;
618.  	int x, y, v, startx, stopx, curx;
619.  	char row[COLNO+1];
620.  
621.  	win = create_nhwindow(NHW_TEXT);
622.  	/*
623.  	 * Each seenv description takes up 2 characters, so center
624.  	 * the seenv display around the hero.
625.  	 */
626.  	startx = max(1, u.ux-(COLNO/4));
627.  	stopx = min(startx+(COLNO/2), COLNO);
628.  	/* can't have a line exactly 80 chars long */
629.  	if (stopx - startx == COLNO/2) startx++;
630.  
631.  	for (y = 0; y < ROWNO; y++) {
632.  	    for (x = startx, curx = 0; x < stopx; x++, curx += 2) {
633.  		if (x == u.ux && y == u.uy) {
634.  		    row[curx] = row[curx+1] = '@';
635.  		} else {
636.  		    v = levl[x][y].seenv & 0xff;
637.  		    if (v == 0)
638.  			row[curx] = row[curx+1] = ' ';
639.  		    else
640.  			Sprintf(&row[curx], "%02x", v);
641.  		}
642.  	    }
643.  	    /* remove trailing spaces */
644.  	    for (x = curx-1; x >= 0; x--)
645.  		if (row[x] != ' ') break;
646.  	    row[x+1] = '\0';
647.  
648.  	    putstr(win, 0, row);
649.  	}
650.  	display_nhwindow(win, TRUE);
651.  	destroy_nhwindow(win);
652.  	return 0;
653.  }
654.  
655.  STATIC_PTR int
656.  wiz_show_vision()
657.  {
658.  	winid win;
659.  	int x, y, v;
660.  	char row[COLNO+1];
661.  
662.  	win = create_nhwindow(NHW_TEXT);
663.  	Sprintf(row, "Flags: 0x%x could see, 0x%x in sight, 0x%x temp lit",
664.  		COULD_SEE, IN_SIGHT, TEMP_LIT);
665.  	putstr(win, 0, row);
666.  	putstr(win, 0, "");
667.  	for (y = 0; y < ROWNO; y++) {
668.  	    for (x = 1; x < COLNO; x++) {
669.  		if (x == u.ux && y == u.uy)
670.  		    row[x] = '@';
671.  		else {
672.  		    v = viz_array[y][x]; /* data access should be hidden */
673.  		    if (v == 0)
674.  			row[x] = ' ';
675.  		    else
676.  			row[x] = '0' + viz_array[y][x];
677.  		}
678.  	    }
679.  	    /* remove trailing spaces */
680.  	    for (x = COLNO-1; x >= 1; x--)
681.  		if (row[x] != ' ') break;
682.  	    row[x+1] = '\0';
683.  
684.  	    putstr(win, 0, &row[1]);
685.  	}
686.  	display_nhwindow(win, TRUE);
687.  	destroy_nhwindow(win);
688.  	return 0;
689.  }
690.  
691.  STATIC_PTR int
692.  wiz_show_wmodes()
693.  {
694.  	winid win;
695.  	int x,y;
696.  	char row[COLNO+1];
697.  	struct rm *lev;
698.  
699.  	win = create_nhwindow(NHW_TEXT);
700.  	for (y = 0; y < ROWNO; y++) {
701.  	    for (x = 0; x < COLNO; x++) {
702.  		lev = &levl[x][y];
703.  		if (x == u.ux && y == u.uy)
704.  		    row[x] = '@';
705.  		else if (IS_WALL(lev->typ) || lev->typ == SDOOR)
706.  		    row[x] = '0' + (lev->wall_info & WM_MASK);
707.  		else if (lev->typ == CORR)
708.  		    row[x] = '#';
709.  		else if (IS_ROOM(lev->typ) || IS_DOOR(lev->typ))
710.  		    row[x] = '.';
711.  		else
712.  		    row[x] = 'x';
713.  	    }
714.  	    row[COLNO] = '\0';
715.  	    putstr(win, 0, row);
716.  	}
717.  	display_nhwindow(win, TRUE);
718.  	destroy_nhwindow(win);
719.  	return 0;
720.  }
721.  
722.  #endif /* WIZARD */
723.  
724.  
725.  /* -enlightenment and conduct- */
726.  static winid en_win;
727.  static const char
728.  	*You_ = "You ",
729.  	*are  = "are ",  *were  = "were ",
730.  	*have = "have ", *had   = "had ",
731.  	*can  = "can ",  *could = "could ";
732.  static const char
733.  	*have_been  = "have been ",
734.  	*have_never = "have never ", *never = "never ";
735.  
736.  #define enl_msg(prefix,present,past,suffix) \
737.  			enlght_line(prefix, final ? past : present, suffix)
738.  #define you_are(attr)	enl_msg(You_,are,were,attr)
739.  #define you_have(attr)	enl_msg(You_,have,had,attr)
740.  #define you_can(attr)	enl_msg(You_,can,could,attr)
741.  #define you_have_been(goodthing) enl_msg(You_,have_been,were,goodthing)
742.  #define you_have_never(badthing) enl_msg(You_,have_never,never,badthing)
743.  #define you_have_X(something)	enl_msg(You_,have,(const char *)"",something)
744.  
745.  static void
746.  enlght_line(start, middle, end)
747.  const char *start, *middle, *end;
748.  {
749.  	char buf[BUFSZ];
750.  
751.  	Sprintf(buf, "%s%s%s.", start, middle, end);
752.  	putstr(en_win, 0, buf);
753.  }
754.  
755.  void
756.  enlightenment(final)
757.  int final;	/* 0 => still in progress; 1 => over, survived; 2 => dead */
758.  {
759.  	int ltmp;
760.  	char buf[BUFSZ];
761.  
762.  	en_win = create_nhwindow(NHW_MENU);
763.  	putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:");
764.  	putstr(en_win, 0, "");
765.  
766.  #ifdef ELBERETH
767.  	if (u.uevent.uhand_of_elbereth) {
768.  	    static const char *hofe_titles[3] = {
769.  				"the Hand of Elbereth",
770.  				"the Envoy of Balance",
771.  				"the Glory of Arioch"
772.  	    };
773.  	    you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1]);
774.  	}
775.  #endif
776.  
777.  	/* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
778.  	if (u.ualign.record >= 20)	you_are("piously aligned");
779.  	else if (u.ualign.record > 13)	you_are("devoutly aligned");
780.  	else if (u.ualign.record > 8)	you_are("fervently aligned");
781.  	else if (u.ualign.record > 3)	you_are("stridently aligned");
782.  	else if (u.ualign.record == 3)	you_are("aligned");
783.  	else if (u.ualign.record > 0)	you_are("haltingly aligned");
784.  	else if (u.ualign.record == 0)	you_are("nominally aligned");
785.  	else if (u.ualign.record >= -3)	you_have("strayed");
786.  	else if (u.ualign.record >= -8)	you_have("sinned");
787.  	else you_have("transgressed");
788.  #ifdef WIZARD
789.  	if (wizard) {
790.  		Sprintf(buf, " %d", u.ualign.record);
791.  		enl_msg("Your alignment ", "is", "was", buf);
792.  	}
793.  #endif
794.  
795.  	/*** Resistances to troubles ***/
796.  	if (Fire_resistance) you_are("fire resistant");
797.  	if (Cold_resistance) you_are("cold resistant");
798.  	if (Sleep_resistance) you_are("sleep resistant");
799.  	if (Disint_resistance) you_are("disintegration-resistant");
800.  	if (Shock_resistance) you_are("shock resistant");
801.  	if (Poison_resistance) you_are("poison resistant");
802.  	if (Drain_resistance) you_are("level-drain resistant");
803.  	if (Sick_resistance) you_are("immune to sickness");
804.  	if (Antimagic) you_are("magic-protected");
805.  	if (Acid_resistance) you_are("acid resistant");
806.  	if (Stone_resistance)
807.  		you_are("petrification resistant");
808.  	if (Invulnerable) you_are("invulnerable");
809.  	if (u.uedibility) you_can("recognize detrimental food");
810.  
811.  	/*** Troubles ***/
812.  	if (Halluc_resistance)
813.  		enl_msg("You resist", "", "ed", " hallucinations");
814.  	if (final) {
815.  		if (Hallucination) you_are("hallucinating");
816.  		if (Stunned) you_are("stunned");
817.  		if (Confusion) you_are("confused");
818.  		if (Blinded) you_are("blinded");
819.  		if (Sick) {
820.  			if (u.usick_type & SICK_VOMITABLE)
821.  				you_are("sick from food poisoning");
822.  			if (u.usick_type & SICK_NONVOMITABLE)
823.  				you_are("sick from illness");
824.  		}
825.  		/* added by JDS */
826.  		if (u.uhitinc) {
827.  			Sprintf(buf, "%s%i %s to hit", u.uhitinc > 0 ? "+" : "",
828.  				u.uhitinc, u.uhitinc > 0 ? "bonus" : "penalty");
829.  			you_have(buf);
830.  			
831.  		}
832.  		if (u.udaminc) {
833.  			Sprintf(buf, "%s%i %s to damage", u.udaminc > 0 ? "+" : "",
834.  				u.udaminc, u.udaminc > 0 ? "bonus" : "penalty");
835.  			you_have(buf);
836.  		} /* end JDS portion */
837.  	}
838.  	if (Stoned) you_are("turning to stone");
839.  	if (Slimed) you_are("turning into slime");
840.  	if (Strangled) you_are((u.uburied) ? "buried" : "being strangled");
841.  	if (Glib) {
842.  		Sprintf(buf, "slippery %s", makeplural(body_part(FINGER)));
843.  		you_have(buf);
844.  	}
845.  	if (Fumbling) enl_msg("You fumble", "", "d", "");
846.  	if (Wounded_legs
847.  #ifdef STEED
848.  	    && !u.usteed
849.  #endif
850.  			  ) {
851.  		Sprintf(buf, "wounded %s", makeplural(body_part(LEG)));
852.  		you_have(buf);
853.  	}
854.  #if defined(WIZARD) && defined(STEED)
855.  	if (Wounded_legs && u.usteed && wizard) {
856.  	    Strcpy(buf, x_monnam(u.usteed, ARTICLE_YOUR, (char *)0, 
857.  		    SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION, FALSE));
858.  	    *buf = highc(*buf);
859.  	    enl_msg(buf, " has", " had", " wounded legs");
860.  	}
861.  #endif
862.  	if (Sleeping) enl_msg("You ", "fall", "fell", " asleep");
863.  	if (Hunger) enl_msg("You hunger", "", "ed", " rapidly");
864.  
865.  	/*** Vision and senses ***/
866.  	if (See_invisible) enl_msg(You_, "see", "saw", " invisible");
867.  	if (Blind_telepat) you_are("telepathic");
868.  	if (Warning) you_are("warned");
869.  	if (Warn_of_mon && flags.warntype) {
870.  		Sprintf(buf, "aware of the presence of %s",
871.  			(flags.warntype & M2_ORC) ? "orcs" :
872.  			(flags.warntype & M2_DEMON) ? "demons" :
873.  			something); 
874.  		you_are(buf);
875.  	}
876.  	if (Undead_warning) you_are("warned of undead");
877.  	if (Searching) you_have("automatic searching");
878.  	if (Clairvoyant) you_are("clairvoyant");
879.  	if (Infravision) you_have("infravision");
880.  	if (Detect_monsters) you_are("sensing the presence of monsters");
881.  	if (u.umconf) you_are("going to confuse monsters");
882.  
883.  	/*** Appearance and behavior ***/
884.  	if (Adornment) you_are("adorned");
885.  	if (Invisible) you_are("invisible");
886.  	else if (Invis) you_are("invisible to others");
887.  	/* ordinarily "visible" is redundant; this is a special case for
888.  	   the situation when invisibility would be an expected attribute */
889.  	else if ((HInvis || EInvis || pm_invisible(youmonst.data)) && BInvis)
890.  	    you_are("visible");
891.  	if (Displaced) you_are("displaced");
892.  	if (Stealth) you_are("stealthy");
893.  	if (Aggravate_monster) enl_msg("You aggravate", "", "d", " monsters");
894.  	if (Conflict) enl_msg("You cause", "", "d", " conflict");
895.  
896.  	/*** Transportation ***/
897.  	if (Jumping) you_can("jump");
898.  	if (Teleportation) you_can("teleport");
899.  	if (Teleport_control) you_have("teleport control");
900.  	if (Lev_at_will) you_are("levitating, at will");
901.  	else if (Levitation) you_are("levitating");	/* without control */
902.  	else if (Flying) you_can("fly");
903.  	if (Wwalking) you_can("walk on water");
904.  	if (Swimming) you_can("swim");        
905.  	if (Breathless) you_can("survive without air");
906.  	else if (Amphibious) you_can("breathe water");
907.  	if (Passes_walls) you_can("walk through walls");
908.  #ifdef STEED
909.  	if (u.usteed) {
910.  	    Sprintf(buf, "riding %s", y_monnam(u.usteed));
911.  	    you_are(buf);
912.  	}
913.  #endif
914.  	if (u.uswallow) {
915.  	    Sprintf(buf, "swallowed by %s", a_monnam(u.ustuck));
916.  #ifdef WIZARD
917.  	    if (wizard) Sprintf(eos(buf), " (%u)", u.uswldtim);
918.  #endif
919.  	    you_are(buf);
920.  	} else if (u.ustuck) {
921.  	    Sprintf(buf, "%s %s",
922.  		    (Upolyd && sticks(youmonst.data)) ? "holding" : "held by",
923.  		    a_monnam(u.ustuck));
924.  	    you_are(buf);
925.  	}
926.  
927.  	/*** Physical attributes ***/
928.  	if (Slow_digestion) you_have("slower digestion");
929.  	if (Regeneration) enl_msg("You regenerate", "", "d", "");
930.  	if (u.uspellprot || Protection) you_are("protected");
931.  	if (Protection_from_shape_changers)
932.  		you_are("protected from shape changers");
933.  	if (Polymorph) you_are("polymorphing");
934.  	if (Polymorph_control) you_have("polymorph control");
935.  	if (u.ulycn >= LOW_PM) {
936.  		Strcpy(buf, an(mons[u.ulycn].mname));
937.  		you_are(buf);
938.  	}
939.  	if (Upolyd) {
940.  	    if (u.ulycn >= LOW_PM) Strcpy(buf, "in beast form");
941.  	    else Sprintf(buf, "polymorphed into %s", an(youmonst.data->mname));
942.  #ifdef WIZARD
943.  	    if (wizard) Sprintf(eos(buf), " (%d)", u.mtimedone);
944.  #endif
945.  	    you_are(buf);
946.  	}
947.  	if (Unchanging) you_can("not change from your current form");
948.  	if (Fast) you_are(Very_fast ? "very fast" : "fast");
949.  	if (Reflecting) you_have("reflection");
950.  	if (Free_action) you_have("free action");
951.  	if (Fixed_abil) you_have("fixed abilities");
952.  	if (Lifesaved)
953.  		enl_msg("Your life ", "will be", "would have been", " saved");
954.  	if (u.twoweap) you_are("wielding two weapons at once");
955.  
956.  	/*** Miscellany ***/
957.  	if (Luck) {
958.  	    ltmp = abs((int)Luck);
959.  	    Sprintf(buf, "%s%slucky",
960.  		    ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "",
961.  		    Luck < 0 ? "un" : "");
962.  #ifdef WIZARD
963.  	    if (wizard) Sprintf(eos(buf), " (%d)", Luck);
964.  #endif
965.  	    you_are(buf);
966.  	}
967.  #ifdef WIZARD
968.  	 else if (wizard) enl_msg("Your luck ", "is", "was", " zero");
969.  #endif
970.  	if (u.moreluck > 0) you_have("extra luck");
971.  	else if (u.moreluck < 0) you_have("reduced luck");
972.  	if (carrying(LUCKSTONE) || stone_luck(TRUE)) {
973.  	    ltmp = stone_luck(FALSE);
974.  	    if (ltmp <= 0)
975.  		enl_msg("Bad luck ", "does", "did", " not time out for you");
976.  	    if (ltmp >= 0)
977.  		enl_msg("Good luck ", "does", "did", " not time out for you");
978.  	}
979.  
980.  	if (u.ugangr) {
981.  	    Sprintf(buf, " %sangry with you",
982.  		    u.ugangr > 6 ? "extremely " : u.ugangr > 3 ? "very " : "");
983.  #ifdef WIZARD
984.  	    if (wizard) Sprintf(eos(buf), " (%d)", u.ugangr);
985.  #endif
986.  	    enl_msg(u_gname(), " is", " was", buf);
987.  	} else
988.  	    /*
989.  	     * We need to suppress this when the game is over, because death
990.  	     * can change the value calculated by can_pray(), potentially
991.  	     * resulting in a false claim that you could have prayed safely.
992.  	     */
993.  	  if (!final) {
994.  #if 0
995.  	    /* "can [not] safely pray" vs "could [not] have safely prayed" */
996.  	    Sprintf(buf, "%s%ssafely pray%s", can_pray(FALSE) ? "" : "not ",
997.  		    final ? "have " : "", final ? "ed" : "");
998.  #else
999.  	    Sprintf(buf, "%ssafely pray", can_pray(FALSE) ? "" : "not ");
1000. #endif
1001. #ifdef WIZARD
1002. 	    if (wizard) Sprintf(eos(buf), " (%d)", u.ublesscnt);
1003. #endif
1004. 	    you_can(buf);
1005. 	}
1006. 
1007.     {
1008. 	const char *p;
1009. 
1010. 	buf[0] = '\0';
1011. 	if (final < 2) {    /* still in progress, or quit/escaped/ascended */
1012. 	    p = "survived after being killed ";
1013. 	    switch (u.umortality) {
1014. 	    case 0:  p = !final ? (char *)0 : "survived";  break;
1015. 	    case 1:  Strcpy(buf, "once");  break;
1016. 	    case 2:  Strcpy(buf, "twice");  break;
1017. 	    case 3:  Strcpy(buf, "thrice");  break;
1018. 	    default: Sprintf(buf, "%d times", u.umortality);
1019. 		     break;
1020. 	    }
1021. 	} else {		/* game ended in character's death */
1022. 	    p = "are dead";
1023. 	    switch (u.umortality) {
1024. 	    case 0:  impossible("dead without dying?");
1025. 	    case 1:  break;			/* just "are dead" */
1026. 	    default: Sprintf(buf, " (%d%s time!)", u.umortality,
1027. 			     ordin(u.umortality));
1028. 		     break;
1029. 	    }
1030. 	}
1031. 	if (p) enl_msg(You_, "have been killed ", p, buf);
1032.     }
1033. 
1034. 	display_nhwindow(en_win, TRUE);
1035. 	destroy_nhwindow(en_win);
1036. 	return;
1037. }
1038. 
1039. /*
1040.  * Courtesy function for non-debug, non-explorer mode players
1041.  * to help refresh them about who/what they are.
1042.  */
1043. STATIC_OVL void
1044. minimal_enlightenment()
1045. {
1046. 	winid tmpwin;
1047. 	menu_item *selected;
1048. 	anything any;
1049. 	char buf[BUFSZ], buf2[BUFSZ];
1050. 	static char fmtstr[] = "%-15s: %-12s";
1051. 	static char deity_fmtstr[] = "%-17s%s";
1052. 
1053. 	any.a_void = 0;
1054. 	buf[0] = buf2[0] = '\0';
1055. 	tmpwin = create_nhwindow(NHW_MENU);
1056. 	start_menu(tmpwin);
1057. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, "Starting", FALSE);
1058. 
1059. 	/* Starting name, race, role, gender */
1060. 	Sprintf(buf, fmtstr, "name", plname);
1061. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1062. 	Sprintf(buf, fmtstr, "race", urace.noun);
1063. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1064. 	Sprintf(buf, fmtstr, "role",
1065. 		(flags.initgend && urole.name.f) ? urole.name.f : urole.name.m);
1066. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1067. 	Sprintf(buf, fmtstr, "gender", genders[flags.initgend].adj);
1068. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1069. 
1070. 	/* Starting alignment */
1071. 	Sprintf(buf, fmtstr, "alignment", align_str(u.ualignbase[A_ORIGINAL]));
1072. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1073. 
1074. 	/* Current name, race, role, gender */
1075. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE);
1076. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, "Current", FALSE);
1077. 	Sprintf(buf, fmtstr, "race", Upolyd ? youmonst.data->mname : urace.noun);
1078. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1079. 	if (Upolyd) {
1080. 	    Sprintf(buf, fmtstr, "role (base)",
1081. 		(u.mfemale && urole.name.f) ? urole.name.f : urole.name.m);
1082. 	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1083. 	} else {
1084. 	    Sprintf(buf, fmtstr, "role",
1085. 		(flags.female && urole.name.f) ? urole.name.f : urole.name.m);
1086. 	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1087. 	}
1088. 	Sprintf(buf, fmtstr, "gender", genders[poly_gender()].adj);
1089. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1090. 
1091. 	if (Upolyd) {
1092. 	    Sprintf(buf, fmtstr, "gender (base)", genders[u.mfemale].adj);
1093. 	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1094. 	}
1095. 
1096. 	/* Current alignment */
1097. 	Sprintf(buf, fmtstr, "alignment", align_str(u.ualign.type));
1098. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1099. 
1100. 	/* Deity list */
1101. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE);
1102. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, "Deities", FALSE);
1103. 	Sprintf(buf2, deity_fmtstr, align_gname(A_CHAOTIC),
1104. 	    (u.ualignbase[A_ORIGINAL] == u.ualign.type
1105. 		&& u.ualign.type == A_CHAOTIC) ? " (s,c)" :
1106. 	    (u.ualignbase[A_ORIGINAL] == A_CHAOTIC)       ? " (s)" :
1107. 	    (u.ualign.type   == A_CHAOTIC)       ? " (c)" : "");
1108.     	Sprintf(buf, fmtstr, "chaotic deity", buf2);
1109. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1110. 
1111. 	Sprintf(buf2, deity_fmtstr, align_gname(A_NEUTRAL),
1112. 	    (u.ualignbase[A_ORIGINAL] == u.ualign.type
1113. 		&& u.ualign.type == A_NEUTRAL) ? " (s,c)" :
1114. 	    (u.ualignbase[A_ORIGINAL] == A_NEUTRAL)       ? " (s)" :
1115. 	    (u.ualign.type   == A_NEUTRAL)       ? " (c)" : "");
1116.     	Sprintf(buf, fmtstr, "neutral deity", buf2);
1117. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1118. 
1119. 	Sprintf(buf2, deity_fmtstr, align_gname(A_LAWFUL),
1120. 	    (u.ualignbase[A_ORIGINAL] == u.ualign.type && u.ualign.type == A_LAWFUL)  ? " (s,c)" :
1121. 	    (u.ualignbase[A_ORIGINAL] == A_LAWFUL)        ? " (s)" :
1122. 	    (u.ualign.type   == A_LAWFUL)        ? " (c)" : "");
1123.     	Sprintf(buf, fmtstr, "lawful  deity", buf2);
1124. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1125. 
1126. 	end_menu(tmpwin, "Base Attributes");
1127. 	(void) select_menu(tmpwin, PICK_NONE, &selected);
1128. 	destroy_nhwindow(tmpwin);
1129. }
1130. 
1131. STATIC_PTR int
1132. doattributes()
1133. {
1134. 	minimal_enlightenment();
1135. 	if (wizard || discover)
1136. 		enlightenment(0);
1137. 	return 0;
1138. }
1139. 
1140. /* KMH, #conduct
1141.  * (shares enlightenment's tense handling)
1142.  */
1143. STATIC_PTR int
1144. doconduct()
1145. {
1146. 	show_conduct(0);
1147. 	return 0;
1148. }
1149. 
1150. void
1151. show_conduct(final)
1152. int final;
1153. {
1154. 	char buf[BUFSZ];
1155. 	int ngenocided;
1156. 
1157. 	/* Create the conduct window */
1158. 	en_win = create_nhwindow(NHW_MENU);
1159. 	putstr(en_win, 0, "Voluntary challenges:");
1160. 	putstr(en_win, 0, "");
1161. 
1162. 	if (!u.uconduct.food)
1163. 	    enl_msg(You_, "have gone", "went", " without food");
1164. 	    /* But beverages are okay */
1165. 	else if (!u.uconduct.unvegan)
1166. 	    you_have_X("followed a strict vegan diet");
1167. 	else if (!u.uconduct.unvegetarian)
1168. 	    you_have_been("vegetarian");
1169. 
1170. 	if (!u.uconduct.gnostic)
1171. 	    you_have_been("an atheist");
1172. 
1173. 	if (!u.uconduct.weaphit)
1174. 	    you_have_never("hit with a wielded weapon");
1175. #ifdef WIZARD
1176. 	else if (wizard) {
1177. 	    Sprintf(buf, "used a wielded weapon %ld time%s",
1178. 		    u.uconduct.weaphit, plur(u.uconduct.weaphit));
1179. 	    you_have_X(buf);
1180. 	}
1181. #endif
1182. 	if (!u.uconduct.killer)
1183. 	    you_have_been("a pacifist");
1184. 
1185. 	if (!u.uconduct.literate)
1186. 	    you_have_been("illiterate");
1187. #ifdef WIZARD
1188. 	else if (wizard) {
1189. 	    Sprintf(buf, "read items or engraved %ld time%s",
1190. 		    u.uconduct.literate, plur(u.uconduct.literate));
1191. 	    you_have_X(buf);
1192. 	}
1193. #endif
1194. 
1195. 	ngenocided = num_genocides();
1196. 	if (ngenocided == 0) {
1197. 	    you_have_never("genocided any monsters");
1198. 	} else {
1199. 	    Sprintf(buf, "genocided %d type%s of monster%s",
1200. 		    ngenocided, plur(ngenocided), plur(ngenocided));
1201. 	    you_have_X(buf);
1202. 	}
1203. 
1204. 	if (!u.uconduct.polypiles)
1205. 	    you_have_never("polymorphed an object");
1206. #ifdef WIZARD
1207. 	else if (wizard) {
1208. 	    Sprintf(buf, "polymorphed %ld item%s",
1209. 		    u.uconduct.polypiles, plur(u.uconduct.polypiles));
1210. 	    you_have_X(buf);
1211. 	}
1212. #endif
1213. 
1214. 	if (!u.uconduct.polyselfs)
1215. 	    you_have_never("changed form");
1216. #ifdef WIZARD
1217. 	else if (wizard) {
1218. 	    Sprintf(buf, "changed form %ld time%s",
1219. 		    u.uconduct.polyselfs, plur(u.uconduct.polyselfs));
1220. 	    you_have_X(buf);
1221. 	}
1222. #endif
1223. 
1224. 	if (!u.uconduct.wishes)
1225. 	    you_have_X("used no wishes");
1226. 	else {
1227. 	    Sprintf(buf, "used %ld wish%s",
1228. 		    u.uconduct.wishes, (u.uconduct.wishes > 1L) ? "es" : "");
1229. 	    you_have_X(buf);
1230. 
1231. 	    if (!u.uconduct.wisharti)
1232. 		enl_msg(You_, "have not wished", "did not wish",
1233. 			" for any artifacts");
1234. 	}
1235. 
1236. 	/* Pop up the window and wait for a key */
1237. 	display_nhwindow(en_win, TRUE);
1238. 	destroy_nhwindow(en_win);
1239. }
1240. 
1241. #endif /* OVLB */
1242. #ifdef OVL1
1243. 
1244. #ifndef M
1245. # ifndef NHSTDC
1246. #  define M(c)		(0x80 | (c))
1247. # else
1248. #  define M(c)		((c) - 128)
1249. # endif /* NHSTDC */
1250. #endif
1251. #ifndef C
1252. #define C(c)		(0x1f & (c))
1253. #endif
1254. 
1255. static const struct func_tab cmdlist[] = {
1256. 	{C('d'), FALSE, dokick}, /* "D" is for door!...?  Msg is in dokick.c */
1257. #ifdef WIZARD
1258. 	{C('e'), TRUE, wiz_detect},
1259. 	{C('f'), TRUE, wiz_map},
1260. 	{C('g'), TRUE, wiz_genesis},
1261. 	{C('i'), TRUE, wiz_identify},
1262. #endif
1263. 	{C('l'), TRUE, doredraw}, /* if number_pad is set */
1264. #ifdef WIZARD
1265. 	{C('o'), TRUE, wiz_where},
1266. #endif
1267. 	{C('p'), TRUE, doprev_message},
1268. 	{C('r'), TRUE, doredraw},
1269. 	{C('t'), TRUE, dotele},
1270. #ifdef WIZARD
1271. 	{C('v'), TRUE, wiz_level_tele},
1272. 	{C('w'), TRUE, wiz_wish},
1273. #endif
1274. 	{C('x'), TRUE, doattributes},
1275. #ifdef SUSPEND
1276. 	{C('z'), TRUE, dosuspend},
1277. #endif
1278. 	{'a', FALSE, doapply},
1279. 	{'A', FALSE, doddoremarm},
1280. 	{M('a'), TRUE, doorganize},
1281. /*	'b', 'B' : go sw */
1282. 	{'c', FALSE, doclose},
1283. 	{'C', TRUE, do_mname},
1284. 	{M('c'), TRUE, dotalk},
1285. 	{'d', FALSE, dodrop},
1286. 	{'D', FALSE, doddrop},
1287. 	{M('d'), FALSE, dodip},
1288. 	{'e', FALSE, doeat},
1289. 	{'E', FALSE, doengrave},
1290. 	{M('e'), TRUE, enhance_weapon_skill},
1291. 	{'f', FALSE, dofire},
1292. /*	'F' : fight (one time) */
1293. 	{M('f'), FALSE, doforce},
1294. /*	'g', 'G' : multiple go */
1295. /*	'h', 'H' : go west */
1296. 	{'h', TRUE, dohelp}, /* if number_pad is set */
1297. 	{'i', TRUE, ddoinv},
1298. 	{'I', TRUE, dotypeinv},		/* Robert Viduya */
1299. 	{M('i'), TRUE, doinvoke},
1300. /*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
1301. 	{'j', FALSE, dojump}, /* if number_pad is on */
1302. 	{M('j'), FALSE, dojump},
1303. 	{'k', FALSE, dokick}, /* if number_pad is on */
1304. 	{'l', FALSE, doloot}, /* if number_pad is on */
1305. 	{M('l'), FALSE, doloot},
1306. /*	'n' prefixes a count if number_pad is on */
1307. 	{M('m'), TRUE, domonability},
1308. 	{'N', TRUE, ddocall}, /* if number_pad is on */
1309. 	{M('n'), TRUE, ddocall},
1310. 	{M('N'), TRUE, ddocall},
1311. 	{'o', FALSE, doopen},
1312. 	{'O', TRUE, doset},
1313. 	{M('o'), FALSE, dosacrifice},
1314. 	{'p', FALSE, dopay},
1315. 	{'P', FALSE, doputon},
1316. 	{M('p'), TRUE, dopray},
1317. 	{'q', FALSE, dodrink},
1318. 	{'Q', FALSE, dowieldquiver},
1319. 	{M('q'), TRUE, done2},
1320. 	{'r', FALSE, doread},
1321. 	{'R', FALSE, doremring},
1322. 	{M('r'), FALSE, dorub},
1323. 	{'s', TRUE, dosearch, "searching"},
1324. 	{'S', TRUE, dosave},
1325. 	{M('s'), FALSE, dosit},
1326. 	{'t', FALSE, dothrow},
1327. 	{'T', FALSE, dotakeoff},
1328. 	{M('t'), TRUE, doturn},
1329. /*	'u', 'U' : go ne */
1330. 	{'u', FALSE, dountrap}, /* if number_pad is on */
1331. 	{M('u'), FALSE, dountrap},
1332. 	{'v', TRUE, doversion},
1333. 	{'V', TRUE, dohistory},
1334. 	{M('v'), TRUE, doextversion},
1335. 	{'w', FALSE, dowield},
1336. 	{'W', FALSE, dowear},
1337. 	{M('w'), FALSE, dowipe},
1338. 	{'x', FALSE, doswapweapon},
1339. 	{'X', TRUE, enter_explore_mode},
1340. /*	'y', 'Y' : go nw */
1341. 	{'z', FALSE, dozap},
1342. 	{'Z', TRUE, docast},
1343. 	{'<', FALSE, doup},
1344. 	{'>', FALSE, dodown},
1345. 	{'/', TRUE, dowhatis},
1346. 	{'&', TRUE, dowhatdoes},
1347. 	{'?', TRUE, dohelp},
1348. 	{M('?'), TRUE, doextlist},
1349. #ifdef SHELL
1350. 	{'!', TRUE, dosh},
1351. #endif
1352. 	{'.', TRUE, donull, "waiting"},
1353. 	{' ', TRUE, donull, "waiting"},
1354. 	{',', FALSE, dopickup},
1355. 	{':', TRUE, dolook},
1356. 	{';', TRUE, doquickwhatis},
1357. 	{'^', TRUE, doidtrap},
1358. 	{'\\', TRUE, dodiscovered},		/* Robert Viduya */
1359. 	{'@', TRUE, dotogglepickup},
1360. 	{M('2'), FALSE, dotwoweapon},
1361. 	{WEAPON_SYM,  TRUE, doprwep},
1362. 	{ARMOR_SYM,  TRUE, doprarm},
1363. 	{RING_SYM,  TRUE, doprring},
1364. 	{AMULET_SYM, TRUE, dopramulet},
1365. 	{TOOL_SYM, TRUE, doprtool},
1366. 	{'*', TRUE, doprinuse},	/* inventory of all equipment in use */
1367. 	{GOLD_SYM, TRUE, doprgold},
1368. 	{SPBOOK_SYM, TRUE, dovspell},			/* Mike Stephenson */
1369. 	{'#', TRUE, doextcmd},
1370. 	{'_', TRUE, dotravel},
1371. 	{0,0,0,0}
1372. };
1373. 
1374. struct ext_func_tab extcmdlist[] = {
1375. 	{"adjust", "adjust inventory letters", doorganize, TRUE},
1376. 	{"chat", "talk to someone", dotalk, TRUE},	/* converse? */
1377. 	{"conduct", "list which challenges you have adhered to", doconduct, TRUE},
1378. 	{"dip", "dip an object into something", dodip, FALSE},
1379. 	{"enhance", "advance or check weapons skills", enhance_weapon_skill,
1380. 							TRUE},
1381. 	{"force", "force a lock", doforce, FALSE},
1382. 	{"invoke", "invoke an object's powers", doinvoke, TRUE},
1383. 	{"jump", "jump to a location", dojump, FALSE},
1384. 	{"loot", "loot a box on the floor", doloot, FALSE},
1385. 	{"monster", "use a monster's special ability", domonability, TRUE},
1386. 	{"name", "name an item or type of object", ddocall, TRUE},
1387. 	{"offer", "offer a sacrifice to the gods", dosacrifice, FALSE},
1388. 	{"pray", "pray to the gods for help", dopray, TRUE},
1389. 	{"quit", "exit without saving current game", done2, TRUE},
1390. #ifdef STEED
1391. 	{"ride", "ride (or stop riding) a monster", doride, FALSE},
1392. #endif
1393. 	{"rub", "rub a lamp or a stone", dorub, FALSE},
1394. 	{"sit", "sit down", dosit, FALSE},
1395. 	{"turn", "turn undead", doturn, TRUE},
1396. 	{"twoweapon", "toggle two-weapon combat", dotwoweapon, FALSE},
1397. 	{"untrap", "untrap something", dountrap, FALSE},
1398. 	{"version", "list compile time options for this version of NetHack",
1399. 		doextversion, TRUE},
1400. 	{"wipe", "wipe off your face", dowipe, FALSE},
1401. 	{"?", "get this list of extended commands", doextlist, TRUE},
1402. #if defined(WIZARD)
1403. 	/*
1404. 	 * There must be a blank entry here for every entry in the table
1405. 	 * below.
1406. 	 */
1407. 	{(char *)0, (char *)0, donull, TRUE},
1408. 	{(char *)0, (char *)0, donull, TRUE},
1409. 	{(char *)0, (char *)0, donull, TRUE},
1410. 	{(char *)0, (char *)0, donull, TRUE},
1411. 	{(char *)0, (char *)0, donull, TRUE},
1412.         {(char *)0, (char *)0, donull, TRUE},
1413. 	{(char *)0, (char *)0, donull, TRUE},
1414. 	{(char *)0, (char *)0, donull, TRUE},
1415. #ifdef DEBUG
1416. 	{(char *)0, (char *)0, donull, TRUE},
1417. #endif
1418. 	{(char *)0, (char *)0, donull, TRUE},
1419. #endif
1420. 	{(char *)0, (char *)0, donull, TRUE}	/* sentinel */
1421. };
1422. 
1423. #if defined(WIZARD)
1424. static const struct ext_func_tab debug_extcmdlist[] = {
1425. 	{"levelchange", "change experience level", wiz_level_change, TRUE},
1426. 	{"light sources", "show mobile light sources", wiz_light_sources, TRUE},
1427. 	{"monpoly_control", "control monster polymorphs", wiz_mon_polycontrol, TRUE},
1428. 	{"poly", "polymorph self", wiz_polyself, TRUE},
1429. 	{"seenv", "show seen vectors", wiz_show_seenv, TRUE},
1430. 	{"stats", "show memory statistics", wiz_show_stats, TRUE},
1431. 	{"timeout", "look at timeout queue", wiz_timeout_queue, TRUE},
1432. 	{"vision", "show vision array", wiz_show_vision, TRUE},
1433. #ifdef DEBUG
1434. 	{"wizdebug", "wizard debug command", wiz_debug_cmd, TRUE},
1435. #endif
1436. 	{"wmode", "show wall modes", wiz_show_wmodes, TRUE},
1437. 	{(char *)0, (char *)0, donull, TRUE}
1438. };
1439. 
1440. /*
1441.  * Insert debug commands into the extended command list.  This function
1442.  * assumes that the last entry will be the help entry.
1443.  *
1444.  * You must add entries in ext_func_tab every time you add one to the
1445.  * debug_extcmdlist().
1446.  */
1447. void
1448. add_debug_extended_commands()
1449. {
1450. 	int i, j, k, n;
1451. 
1452. 	/* count the # of help entries */
1453. 	for (n = 0; extcmdlist[n].ef_txt[0] != '?'; n++)
1454. 	    ;
1455. 
1456. 	for (i = 0; debug_extcmdlist[i].ef_txt; i++) {
1457. 	    for (j = 0; j < n; j++)
1458. 		if (strcmp(debug_extcmdlist[i].ef_txt, extcmdlist[j].ef_txt) < 0) break;
1459. 
1460. 	    /* insert i'th debug entry into extcmdlist[j], pushing down  */
1461. 	    for (k = n; k >= j; --k)
1462. 		extcmdlist[k+1] = extcmdlist[k];
1463. 	    extcmdlist[j] = debug_extcmdlist[i];
1464. 	    n++;	/* now an extra entry */
1465. 	}
1466. }
1467. 
1468. 
1469. static const char *template = "%-18s %4ld  %6ld";
1470. static const char *count_str = "                   count  bytes";
1471. static const char *separator = "------------------ -----  ------";
1472. 
1473. STATIC_OVL void
1474. count_obj(chain, total_count, total_size, top, recurse)
1475. 	struct obj *chain;
1476. 	long *total_count;
1477. 	long *total_size;
1478. 	boolean top;
1479. 	boolean recurse;
1480. {
1481. 	long count, size;
1482. 	struct obj *obj;
1483. 
1484. 	for (count = size = 0, obj = chain; obj; obj = obj->nobj) {
1485. 	    if (top) {
1486. 		count++;
1487. 		size += sizeof(struct obj) + obj->oxlth + obj->onamelth;
1488. 	    }
1489. 	    if (recurse && obj->cobj)
1490. 		count_obj(obj->cobj, total_count, total_size, TRUE, TRUE);
1491. 	}
1492. 	*total_count += count;
1493. 	*total_size += size;
1494. }
1495. 
1496. STATIC_OVL void
1497. obj_chain(win, src, chain, total_count, total_size)
1498. 	winid win;
1499. 	const char *src;
1500. 	struct obj *chain;
1501. 	long *total_count;
1502. 	long *total_size;
1503. {
1504. 	char buf[BUFSZ];
1505. 	long count = 0, size = 0;
1506. 
1507. 	count_obj(chain, &count, &size, TRUE, FALSE);
1508. 	*total_count += count;
1509. 	*total_size += size;
1510. 	Sprintf(buf, template, src, count, size);
1511. 	putstr(win, 0, buf);
1512. }
1513. 
1514. STATIC_OVL void
1515. mon_invent_chain(win, src, chain, total_count, total_size)
1516. 	winid win;
1517. 	const char *src;
1518. 	struct monst *chain;
1519. 	long *total_count;
1520. 	long *total_size;
1521. {
1522. 	char buf[BUFSZ];
1523. 	long count = 0, size = 0;
1524. 	struct monst *mon;
1525. 
1526. 	for (mon = chain; mon; mon = mon->nmon)
1527. 	    count_obj(mon->minvent, &count, &size, TRUE, FALSE);
1528. 	*total_count += count;
1529. 	*total_size += size;
1530. 	Sprintf(buf, template, src, count, size);
1531. 	putstr(win, 0, buf);
1532. }
1533. 
1534. STATIC_OVL void
1535. contained(win, src, total_count, total_size)
1536. 	winid win;
1537. 	const char *src;
1538. 	long *total_count;
1539. 	long *total_size;
1540. {
1541. 	char buf[BUFSZ];
1542. 	long count = 0, size = 0;
1543. 	struct monst *mon;
1544. 
1545. 	count_obj(invent, &count, &size, FALSE, TRUE);
1546. 	count_obj(fobj, &count, &size, FALSE, TRUE);
1547. 	count_obj(level.buriedobjlist, &count, &size, FALSE, TRUE);
1548. 	count_obj(migrating_objs, &count, &size, FALSE, TRUE);
1549. 	/* DEADMONSTER check not required in this loop since they have no inventory */
1550. 	for (mon = fmon; mon; mon = mon->nmon)
1551. 	    count_obj(mon->minvent, &count, &size, FALSE, TRUE);
1552. 	for (mon = migrating_mons; mon; mon = mon->nmon)
1553. 	    count_obj(mon->minvent, &count, &size, FALSE, TRUE);
1554. 
1555. 	*total_count += count; *total_size += size;
1556. 
1557. 	Sprintf(buf, template, src, count, size);
1558. 	putstr(win, 0, buf);
1559. }
1560. 
1561. STATIC_OVL void
1562. mon_chain(win, src, chain, total_count, total_size)
1563. 	winid win;
1564. 	const char *src;
1565. 	struct monst *chain;
1566. 	long *total_count;
1567. 	long *total_size;
1568. {
1569. 	char buf[BUFSZ];
1570. 	long count, size;
1571. 	struct monst *mon;
1572. 
1573. 	for (count = size = 0, mon = chain; mon; mon = mon->nmon) {
1574. 	    count++;
1575. 	    size += sizeof(struct monst) + mon->mxlth + mon->mnamelth;
1576. 	}
1577. 	*total_count += count;
1578. 	*total_size += size;
1579. 	Sprintf(buf, template, src, count, size);
1580. 	putstr(win, 0, buf);
1581. }
1582. 
1583. /*
1584.  * Display memory usage of all monsters and objects on the level.
1585.  */
1586. static int
1587. wiz_show_stats()
1588. {
1589. 	char buf[BUFSZ];
1590. 	winid win;
1591. 	long total_obj_size = 0, total_obj_count = 0;
1592. 	long total_mon_size = 0, total_mon_count = 0;
1593. 
1594. 	win = create_nhwindow(NHW_TEXT);
1595. 	putstr(win, 0, "Current memory statistics:");
1596. 	putstr(win, 0, "");
1597. 	Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj));
1598. 	putstr(win, 0, buf);
1599. 	putstr(win, 0, "");
1600. 	putstr(win, 0, count_str);
1601. 
1602. 	obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size);
1603. 	obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size);
1604. 	obj_chain(win, "buried", level.buriedobjlist,
1605. 				&total_obj_count, &total_obj_size);
1606. 	obj_chain(win, "migrating obj", migrating_objs,
1607. 				&total_obj_count, &total_obj_size);
1608. 	mon_invent_chain(win, "minvent", fmon,
1609. 				&total_obj_count,&total_obj_size);
1610. 	mon_invent_chain(win, "migrating minvent", migrating_mons,
1611. 				&total_obj_count, &total_obj_size);
1612. 
1613. 	contained(win, "contained",
1614. 				&total_obj_count, &total_obj_size);
1615. 
1616. 	putstr(win, 0, separator);
1617. 	Sprintf(buf, template, "Total", total_obj_count, total_obj_size);
1618. 	putstr(win, 0, buf);
1619. 
1620. 	putstr(win, 0, "");
1621. 	putstr(win, 0, "");
1622. 	Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst));
1623. 	putstr(win, 0, buf);
1624. 	putstr(win, 0, "");
1625. 
1626. 	mon_chain(win, "fmon", fmon,
1627. 				&total_mon_count, &total_mon_size);
1628. 	mon_chain(win, "migrating", migrating_mons,
1629. 				&total_mon_count, &total_mon_size);
1630. 
1631. 	putstr(win, 0, separator);
1632. 	Sprintf(buf, template, "Total", total_mon_count, total_mon_size);
1633. 	putstr(win, 0, buf);
1634. 
1635. #if defined(__BORLANDC__) && !defined(_WIN32)
1636. 	show_borlandc_stats(win);
1637. #endif
1638. 
1639. 	display_nhwindow(win, FALSE);
1640. 	destroy_nhwindow(win);
1641. 	return 0;
1642. }
1643. 
1644. void
1645. sanity_check()
1646. {
1647. 	obj_sanity_check();
1648. 	timer_sanity_check();
1649. }
1650. 
1651. #endif /* WIZARD */
1652. 
1653. #define unctrl(c)	((c) <= C('z') ? (0x60 | (c)) : (c))
1654. #define unmeta(c)	(0x7f & (c))
1655. 
1656. 
1657. void
1658. rhack(cmd)
1659. register char *cmd;
1660. {
1661. 	boolean do_walk, do_rush, prefix_seen, bad_command,
1662. 		firsttime = (cmd == 0);
1663. 
1664. 	if (firsttime) {
1665. 		flags.nopick = 0;
1666. 		cmd = parse();
1667. 	}
1668. 	if (*cmd == '\033') {
1669. 		flags.move = FALSE;
1670. 		return;
1671. 	}
1672. #ifdef REDO
1673. 	if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
1674. 		in_doagain = TRUE;
1675. 		stail = 0;
1676. 		rhack((char *)0);	/* read and execute command */
1677. 		in_doagain = FALSE;
1678. 		return;
1679. 	}
1680. 	/* Special case of *cmd == ' ' handled better below */
1681. 	if(!*cmd || *cmd == (char)0377)
1682. #else
1683. 	if(!*cmd || *cmd == (char)0377 || (!flags.rest_on_space && *cmd == ' '))
1684. #endif
1685. 	{
1686. 		nhbell();
1687. 		flags.move = FALSE;
1688. 		return;		/* probably we just had an interrupt */
1689. 	}
1690. 
1691. 	/* handle most movement commands */
1692. 	do_walk = do_rush = prefix_seen = FALSE;
1693. 	flags.travel = 0;
1694. 	switch (*cmd) {
1695. 	 case 'g':  if (movecmd(cmd[1])) {
1696. 			flags.run = 2;
1697. 			do_rush = TRUE;
1698. 		    } else
1699. 			prefix_seen = TRUE;
1700. 		    break;
1701. 	 case '5':  if (!iflags.num_pad) break;	/* else FALLTHRU */
1702. 	 case 'G':  if (movecmd(lowc(cmd[1]))) {
1703. 			flags.run = 3;
1704. 			do_rush = TRUE;
1705. 		    } else
1706. 			prefix_seen = TRUE;
1707. 		    break;
1708. 	 case '-':  if (!iflags.num_pad) break;	/* else FALLTHRU */
1709. 	/* Effects of movement commands and invisible monsters:
1710. 	 * m: always move onto space (even if 'I' remembered)
1711. 	 * F: always attack space (even if 'I' not remembered)
1712. 	 * normal movement: attack if 'I', move otherwise
1713. 	 */
1714. 	 case 'F':  if (movecmd(cmd[1])) {
1715. 			flags.forcefight = 1;
1716. 			do_walk = TRUE;
1717. 		    } else
1718. 			prefix_seen = TRUE;
1719. 		    break;
1720. 	 case 'm':  if (movecmd(cmd[1]) || u.dz) {
1721. 			flags.run = 0;
1722. 			flags.nopick = 1;
1723. 			if (!u.dz) do_walk = TRUE;
1724. 			else cmd[0] = cmd[1];	/* "m<" or "m>" */
1725. 		    } else
1726. 			prefix_seen = TRUE;
1727. 		    break;
1728. 	 case 'M':  if (movecmd(lowc(cmd[1]))) {
1729. 			flags.run = 1;
1730. 			flags.nopick = 1;
1731. 			do_rush = TRUE;
1732. 		    } else
1733. 			prefix_seen = TRUE;
1734. 		    break;
1735. 	 case '0':  if (!iflags.num_pad) break;
1736. 		    (void)ddoinv(); /* a convenience borrowed from the PC */
1737. 		    flags.move = FALSE;
1738. 		    multi = 0;
1739. 		    return;
1740. 	 case CMD_TRAVEL:
1741. 		    flags.travel = 1;
1742. 		    flags.run = 8;
1743. 		    flags.nopick = 1;
1744. 		    do_rush = TRUE;
1745. 		    break;
1746. 	 default:   if (movecmd(*cmd)) {	/* ordinary movement */
1747. 			do_walk = TRUE;
1748. 		    } else if (movecmd(iflags.num_pad ?
1749. 				       unmeta(*cmd) : lowc(*cmd))) {
1750. 			flags.run = 1;
1751. 			do_rush = TRUE;
1752. 		    } else if (movecmd(unctrl(*cmd))) {
1753. 			flags.run = 3;
1754. 			do_rush = TRUE;
1755. 		    }
1756. 		    break;
1757. 	}
1758. 	if (do_walk) {
1759. 	    if (multi) flags.mv = TRUE;
1760. 	    domove();
1761. 	    flags.forcefight = 0;
1762. 	    return;
1763. 	} else if (do_rush) {
1764. 	    if (firsttime) {
1765. 		if (!multi) multi = max(COLNO,ROWNO);
1766. 		u.last_str_turn = 0;
1767. 	    }
1768. 	    flags.mv = TRUE;
1769. 	    domove();
1770. 	    return;
1771. 	} else if (prefix_seen && cmd[1] == '\033') {	/* <prefix><escape> */
1772. 	    /* don't report "unknown command" for change of heart... */
1773. 	    bad_command = FALSE;
1774. 	} else if (*cmd == ' ' && !flags.rest_on_space) {
1775. 	    bad_command = TRUE;		/* skip cmdlist[] loop */
1776. 
1777. 	/* handle all other commands */
1778. 	} else {
1779. 	    register const struct func_tab *tlist;
1780. 	    int res, NDECL((*func));
1781. 
1782. 	    for (tlist = cmdlist; tlist->f_char; tlist++) {
1783. 		if ((*cmd & 0xff) != (tlist->f_char & 0xff)) continue;
1784. 
1785. 		if (u.uburied && !tlist->can_if_buried) {
1786. 		    You_cant("do that while you are buried!");
1787. 		    res = 0;
1788. 		} else {
1789. 		    /* we discard 'const' because some compilers seem to have
1790. 		       trouble with the pointer passed to set_occupation() */
1791. 		    func = ((struct func_tab *)tlist)->f_funct;
1792. 		    if (tlist->f_text && !occupation && multi)
1793. 			set_occupation(func, tlist->f_text, multi);
1794. 		    res = (*func)();		/* perform the command */
1795. 		}
1796. 		if (!res) {
1797. 		    flags.move = FALSE;
1798. 		    multi = 0;
1799. 		}
1800. 		return;
1801. 	    }
1802. 	    /* if we reach here, cmd wasn't found in cmdlist[] */
1803. 	    bad_command = TRUE;
1804. 	}
1805. 
1806. 	if (bad_command) {
1807. 	    char expcmd[10];
1808. 	    register char *cp = expcmd;
1809. 
1810. 	    while (*cmd && (int)(cp - expcmd) < (int)(sizeof expcmd - 3)) {
1811. 		if (*cmd >= 040 && *cmd < 0177) {
1812. 		    *cp++ = *cmd++;
1813. 		} else if (*cmd & 0200) {
1814. 		    *cp++ = 'M';
1815. 		    *cp++ = '-';
1816. 		    *cp++ = *cmd++ &= ~0200;
1817. 		} else {
1818. 		    *cp++ = '^';
1819. 		    *cp++ = *cmd++ ^ 0100;
1820. 		}
1821. 	    }
1822. 	    *cp = '\0';
1823. 	    Norep("Unknown command '%s'.", expcmd);
1824. 	}
1825. 	/* didn't move */
1826. 	flags.move = FALSE;
1827. 	multi = 0;
1828. 	return;
1829. }
1830. 
1831. int
1832. xytod(x, y)	/* convert an x,y pair into a direction code */
1833. schar x, y;
1834. {
1835. 	register int dd;
1836. 
1837. 	for(dd = 0; dd < 8; dd++)
1838. 	    if(x == xdir[dd] && y == ydir[dd]) return dd;
1839. 
1840. 	return -1;
1841. }
1842. 
1843. void
1844. dtoxy(cc,dd)	/* convert a direction code into an x,y pair */
1845. coord *cc;
1846. register int dd;
1847. {
1848. 	cc->x = xdir[dd];
1849. 	cc->y = ydir[dd];
1850. 	return;
1851. }
1852. 
1853. int
1854. movecmd(sym)	/* also sets u.dz, but returns false for <> */
1855. char sym;
1856. {
1857. 	register const char *dp;
1858. 	register const char *sdp;
1859. 	if(iflags.num_pad) sdp = ndir; else sdp = sdir;	/* DICE workaround */
1860. 
1861. 	u.dz = 0;
1862. 	if(!(dp = index(sdp, sym))) return 0;
1863. 	u.dx = xdir[dp-sdp];
1864. 	u.dy = ydir[dp-sdp];
1865. 	u.dz = zdir[dp-sdp];
1866. 	if (u.dx && u.dy && u.umonnum == PM_GRID_BUG) {
1867. 		u.dx = u.dy = 0;
1868. 		return 0;
1869. 	}
1870. 	return !u.dz;
1871. }
1872. 
1873. int
1874. getdir(s)
1875. const char *s;
1876. {
1877. 	char dirsym;
1878. 
1879. #ifdef REDO
1880. 	if(in_doagain || *readchar_queue)
1881. 	    dirsym = readchar();
1882. 	else
1883. #endif
1884. 	    dirsym = yn_function (s ? s : "In what direction?",
1885. 					(char *)0, '\0');
1886. #ifdef REDO
1887. 	savech(dirsym);
1888. #endif
1889. 	if(dirsym == '.' || dirsym == 's')
1890. 		u.dx = u.dy = u.dz = 0;
1891. 	else if(!movecmd(dirsym) && !u.dz) {
1892. 		if(!index(quitchars, dirsym))
1893. 			pline("What a strange direction!");
1894. 		return 0;
1895. 	}
1896. 	if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir();
1897. 	return 1;
1898. }
1899. 
1900. #endif /* OVL1 */
1901. #ifdef OVLB
1902. 
1903. void
1904. confdir()
1905. {
1906. 	register int x = (u.umonnum == PM_GRID_BUG) ? 2*rn2(4) : rn2(8);
1907. 	u.dx = xdir[x];
1908. 	u.dy = ydir[x];
1909. 	return;
1910. }
1911. 
1912. #endif /* OVLB */
1913. #ifdef OVL0
1914. 
1915. int
1916. isok(x,y)
1917. register int x, y;
1918. {
1919. 	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
1920. 	return x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1;
1921. }
1922. 
1923. static NEARDATA int last_multi;
1924. 
1925. /*
1926.  * convert a MAP window position into a movecmd
1927.  */
1928. const char *
1929. click_to_cmd(x, y, mod)
1930.     int x, y, mod;
1931. {
1932.     int dir;
1933.     static char cmd[4];
1934.     cmd[1]=0;
1935. 
1936.     x -= u.ux;
1937.     y -= u.uy;
1938. 
1939.     if ( abs(x) <= 1 && abs(y) <= 1 ) {
1940. 	x = sgn(x), y = sgn(y);
1941.     } else {
1942. 	u.tx = u.ux+x;
1943. 	u.ty = u.uy+y;
1944. 	cmd[0] = CMD_TRAVEL;
1945. 	return cmd;
1946.     }
1947. 
1948.     if(x == 0 && y == 0) {
1949. 	/* here */
1950. 	if(IS_FOUNTAIN(levl[u.ux][u.uy].typ) || IS_SINK(levl[u.ux][u.uy].typ)) {
1951. 	    cmd[0]=mod == CLICK_1 ? 'q' : M('d');
1952. 	    return cmd;
1953. 	} else if(IS_THRONE(levl[u.ux][u.uy].typ)) {
1954. 	    cmd[0]=M('s');
1955. 	    return cmd;
1956. 	} else if((u.ux == xupstair && u.uy == yupstair)
1957. 		  || (u.ux == sstairs.sx && u.uy == sstairs.sy && sstairs.up)
1958. 		  || (u.ux == xupladder && u.uy == yupladder)) {
1959. 	    return "<";
1960. 	} else if((u.ux == xdnstair && u.uy == ydnstair)
1961. 		  || (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)
1962. 		  || (u.ux == xdnladder && u.uy == ydnladder)) {
1963. 	    return ">";
1964. 	} else if(OBJ_AT(u.ux, u.uy)) {
1965. 	    cmd[0] = Is_container(level.objects[u.ux][u.uy]) ? M('l') : ',';
1966. 	    return cmd;
1967. 	} else {
1968. 	    return "."; /* just rest */
1969. 	}
1970.     }
1971. 
1972.     /* directional commands */
1973. 
1974.     dir = xytod(x, y);
1975. 
1976.     if (!m_at(u.ux+x, u.uy+y) && !test_move(u.ux, u.uy, x, y, 1)) {
1977. 	cmd[1] = (iflags.num_pad ? ndir[dir] : sdir[dir]);
1978. 	cmd[2] = 0;
1979. 	if (IS_DOOR(levl[u.ux+x][u.uy+y].typ)) {
1980. 	    /* slight assistance to the player: choose kick/open for them */
1981. 	    if (levl[u.ux+x][u.uy+y].doormask & D_LOCKED) {
1982. 		cmd[0] = C('d');
1983. 		return cmd;
1984. 	    }
1985. 	    if (levl[u.ux+x][u.uy+y].doormask & D_CLOSED) {
1986. 		cmd[0] = 'o';
1987. 		return cmd;
1988. 	    }
1989. 	}
1990. 	if (levl[u.ux+x][u.uy+y].typ <= SCORR) {
1991. 	    cmd[0] = 's';
1992. 	    cmd[1] = 0;
1993. 	    return cmd;
1994. 	}
1995.     }
1996. 
1997.     /* move, attack, etc. */
1998.     cmd[1] = 0;
1999.     if(mod == CLICK_1) {
2000. 	cmd[0] = (iflags.num_pad ? ndir[dir] : sdir[dir]);
2001.     } else {
2002. 	cmd[0] = (iflags.num_pad ? M(ndir[dir]) :
2003. 		(sdir[dir] - 'a' + 'A')); /* run command */
2004.     }
2005. 
2006.     return cmd;
2007. }
2008. 
2009. STATIC_OVL char *
2010. parse()
2011. {
2012. #ifdef LINT	/* static char in_line[COLNO]; */
2013. 	char in_line[COLNO];
2014. #else
2015. 	static char in_line[COLNO];
2016. #endif
2017. 	register int foo;
2018. 	boolean prezero = FALSE;
2019. 
2020. 	multi = 0;
2021. 	flags.move = 1;
2022. 	flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
2023. 
2024. 	if (!iflags.num_pad || (foo = readchar()) == 'n')
2025. 	    for (;;) {
2026. 		foo = readchar();
2027. 		if (foo >= '0' && foo <= '9') {
2028. 		    multi = 10 * multi + foo - '0';
2029. 		    if (multi < 0 || multi >= LARGEST_INT) multi = LARGEST_INT;
2030. 		    if (multi > 9) {
2031. 			clear_nhwindow(WIN_MESSAGE);
2032. 			Sprintf(in_line, "Count: %d", multi);
2033. 			pline(in_line);
2034. 			mark_synch();
2035. 		    }
2036. 		    last_multi = multi;
2037. 		    if (!multi && foo == '0') prezero = TRUE;
2038. 		} else break;	/* not a digit */
2039. 	    }
2040. 
2041. 	if (foo == '\033') {   /* esc cancels count (TH) */
2042. 	    clear_nhwindow(WIN_MESSAGE);
2043. 	    multi = last_multi = 0;
2044. # ifdef REDO
2045. 	} else if (foo == DOAGAIN || in_doagain) {
2046. 	    multi = last_multi;
2047. 	} else {
2048. 	    last_multi = multi;
2049. 	    savech(0);	/* reset input queue */
2050. 	    savech((char)foo);
2051. # endif
2052. 	}
2053. 
2054. 	if (multi) {
2055. 	    multi--;
2056. 	    save_cm = in_line;
2057. 	} else {
2058. 	    save_cm = (char *)0;
2059. 	}
2060. 	in_line[0] = foo;
2061. 	in_line[1] = '\0';
2062. 	if (foo == 'g' || foo == 'G' || foo == 'm' || foo == 'M' ||
2063. 	    foo == 'F' || (iflags.num_pad && (foo == '5' || foo == '-'))) {
2064. 	    foo = readchar();
2065. #ifdef REDO
2066. 	    savech((char)foo);
2067. #endif
2068. 	    in_line[1] = foo;
2069. 	    in_line[2] = 0;
2070. 	}
2071. 	clear_nhwindow(WIN_MESSAGE);
2072. 	if (prezero) in_line[0] = '\033';
2073. 	return(in_line);
2074. }
2075. 
2076. #endif /* OVL0 */
2077. #ifdef OVLB
2078. 
2079. #ifdef UNIX
2080. static
2081. void
2082. end_of_input()
2083. {
2084. 	exit_nhwindows("End of input?");
2085. #ifndef NOSAVEONHANGUP
2086. 	if (!program_state.done_hup++)
2087. 	    (void) dosave0();
2088. #endif
2089. 	clearlocks();
2090. 	terminate(EXIT_SUCCESS);
2091. }
2092. #endif
2093. 
2094. #endif /* OVLB */
2095. #ifdef OVL0
2096. 
2097. char
2098. readchar()
2099. {
2100. 	register int sym;
2101. 	int x = u.ux, y = u.uy, mod = 0;
2102. 
2103. 	if ( *readchar_queue )
2104. 	    sym = *readchar_queue++;
2105. 	else
2106. #ifdef REDO
2107. 	    sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod);
2108. #else
2109. 	    sym = Getchar();
2110. #endif
2111. 
2112. #ifdef UNIX
2113. # ifdef NR_OF_EOFS
2114. 	if (sym == EOF) {
2115. 	    register int cnt = NR_OF_EOFS;
2116. 	  /*
2117. 	   * Some SYSV systems seem to return EOFs for various reasons
2118. 	   * (?like when one hits break or for interrupted systemcalls?),
2119. 	   * and we must see several before we quit.
2120. 	   */
2121. 	    do {
2122. 		clearerr(stdin);	/* omit if clearerr is undefined */
2123. 		sym = Getchar();
2124. 	    } while (--cnt && sym == EOF);
2125. 	}
2126. # endif /* NR_OF_EOFS */
2127. 	if (sym == EOF)
2128. 	    end_of_input();
2129. #endif /* UNIX */
2130. 
2131. 	if(sym == 0) {
2132. 	    /* click event */
2133. 	    readchar_queue = click_to_cmd(x, y, mod);
2134. 	    sym = *readchar_queue++;
2135. 	}
2136. 	return((char) sym);
2137. }
2138. 
2139. STATIC_PTR int
2140. dotravel()
2141. {
2142. 	/* Keyboard travel command */
2143. 	static char cmd[2];
2144. 	coord cc;
2145. 	cmd[1]=0;
2146. 	cc.x = u.ux;
2147. 	cc.y = u.uy;
2148. 	pline("Where do you want to travel to?");
2149. 	if (getpos(&cc, TRUE, "the desired destination") < 0) {
2150. 		/* user pressed ESC */
2151. 		return 0;
2152. 	}
2153. 	u.tx = cc.x;
2154. 	u.ty = cc.y;
2155. 	cmd[0] = CMD_TRAVEL;
2156. 	readchar_queue = cmd;
2157. 	return 0;
2158. }
2159. 
2160. #endif /* OVL0 */
2161. 
2162. /*cmd.c*/