Source:SLASH'EM 0.0.7E7F2/cmd.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to cmd.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/cmd.c#line123]], for example.

The latest source code for vanilla NetHack is at 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	2003/02/06	*/
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 int 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(dofire); /**/
49.   extern int NDECL(dothrow); /**/
50.   extern int NDECL(doeat); /**/
51.   extern int NDECL(done2); /**/
52.   extern int NDECL(doengrave); /**/
53.   extern int NDECL(dopickup); /**/
54.   extern int NDECL(ddoinv); /**/
55.   extern int NDECL(dotypeinv); /**/
56.   extern int NDECL(dolook); /**/
57.   extern int NDECL(doprgold); /**/
58.   extern int NDECL(doprwep); /**/
59.   extern int NDECL(doprarm); /**/
60.   extern int NDECL(doprring); /**/
61.   extern int NDECL(dopramulet); /**/
62.   extern int NDECL(doprtool); /**/
63.   extern int NDECL(dosuspend); /**/
64.   extern int NDECL(doforce); /**/
65.   extern int NDECL(doopen); /**/
66.   extern int NDECL(doclose); /**/
67.   extern int NDECL(dosh); /**/
68.   extern int NDECL(dodiscovered); /**/
69.   extern int NDECL(doset); /**/
70.   extern int NDECL(dotogglepickup); /**/
71.   extern int NDECL(dowhatis); /**/
72.   extern int NDECL(doquickwhatis); /**/
73.   extern int NDECL(dowhatdoes); /**/
74.   extern int NDECL(dohelp); /**/
75.   extern int NDECL(dohistory); /**/
76.   extern int NDECL(doloot); /**/
77.   extern int NDECL(dodrink); /**/
78.   extern int NDECL(dodip); /**/
79.   extern int NDECL(dosacrifice); /**/
80.   extern int NDECL(dopray); /**/
81.   extern int NDECL(doturn); /**/
82.   extern int NDECL(dotech); /**/
83.   extern int NDECL(doredraw); /**/
84.   extern int NDECL(doread); /**/
85.   extern int NDECL(dosave); /**/
86.   extern int NDECL(dosearch); /**/
87.   extern int NDECL(doidtrap); /**/
88.   extern int NDECL(dopay); /**/
89.   extern int NDECL(dosit); /**/
90.   extern int NDECL(dotalk); /**/
91.   extern int NDECL(docast); /**/
92.   extern int NDECL(dovspell); /**/
93.   extern int NDECL(dotele); /**/
94.   extern int NDECL(dountrap); /**/
95.   extern int NDECL(doversion); /**/
96.   extern int NDECL(doextversion); /**/
97.   extern int NDECL(doswapweapon); /**/
98.   extern int NDECL(doswapweapon); /**/
99.   extern int NDECL(dowield); /**/
100.  extern int NDECL(dowieldquiver); /**/
101.  extern int NDECL(dowieldquiver); /**/
102.  extern int NDECL(dozap); /**/
103.  extern int NDECL(doorganize); /**/
104.  extern int NDECL(dolistvanq); /**/
105.  
106.  #endif /* DUMB */
107.  
108.  #ifdef OVL1
109.  static int NDECL((*timed_occ_fn));
110.  #endif /* OVL1 */
111.  
112.  STATIC_PTR int NDECL(doprev_message);
113.  STATIC_PTR int NDECL(timed_occupation);
114.  STATIC_PTR int NDECL(doextcmd);
115.  #ifdef BORG
116.  STATIC_PTR int NDECL(doborgtoggle);
117.  #endif
118.  STATIC_PTR int NDECL(domonability);
119.  STATIC_PTR int NDECL(dotravel);
120.  STATIC_PTR int NDECL(playersteal);
121.  #if 0
122.  STATIC_PTR int NDECL(specialpower); /* WAC -- use techniques */
123.  #endif
124.  # ifdef WIZARD
125.  STATIC_PTR int NDECL(wiz_wish);
126.  STATIC_PTR int NDECL(wiz_identify);
127.  STATIC_PTR int NDECL(wiz_map);
128.  /* BEGIN TSANTH'S CODE */
129.  STATIC_PTR int NDECL(wiz_gain_ac);
130.  STATIC_PTR int NDECL(wiz_gain_level);
131.  STATIC_PTR int NDECL(wiz_toggle_invulnerability);
132.  /* END TSANTH'S CODE */
133.  STATIC_PTR int NDECL(wiz_genesis);
134.  STATIC_PTR int NDECL(wiz_where);
135.  STATIC_PTR int NDECL(wiz_detect);
136.  STATIC_PTR int NDECL(wiz_panic);
137.  STATIC_PTR int NDECL(wiz_polyself);
138.  STATIC_PTR int NDECL(wiz_level_tele);
139.  STATIC_PTR int NDECL(wiz_level_change);
140.  STATIC_PTR int NDECL(wiz_show_seenv);
141.  STATIC_PTR int NDECL(wiz_show_vision);
142.  STATIC_PTR int NDECL(wiz_mon_polycontrol);
143.  STATIC_PTR int NDECL(wiz_show_wmodes);
144.  #if defined(__BORLANDC__) && !defined(_WIN32)
145.  extern void FDECL(show_borlandc_stats, (winid));
146.  #endif
147.  #ifdef DEBUG_MIGRATING_MONS
148.  STATIC_PTR int NDECL(wiz_migrate_mons);
149.  #endif
150.  STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *, BOOLEAN_P, BOOLEAN_P));
151.  STATIC_DCL void FDECL(obj_chain, (winid, const char *, struct obj *, long *, long *));
152.  STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *, long *, long *));
153.  STATIC_DCL void FDECL(mon_chain, (winid, const char *, struct monst *, long *, long *));
154.  STATIC_DCL void FDECL(contained, (winid, const char *, long *, long *));
155.  STATIC_PTR int NDECL(wiz_show_stats);
156.  #ifdef DISPLAY_LAYERS
157.  STATIC_PTR int NDECL(wiz_show_display);
158.  #endif
159.  #  ifdef PORT_DEBUG
160.  STATIC_DCL int NDECL(wiz_port_debug);
161.  #  endif
162.  # endif
163.  STATIC_PTR int NDECL(enter_explore_mode);
164.  STATIC_PTR int NDECL(doattributes);
165.  STATIC_PTR int NDECL(doconduct); /**/
166.  STATIC_PTR boolean NDECL(minimal_enlightenment);
167.  STATIC_PTR int FDECL(makemenu, (const char *, struct menu_list *));
168.  
169.  static NEARDATA struct rm *maploc;
170.  
171.  #ifdef OVLB
172.  STATIC_DCL void FDECL(enlght_line, (const char *,const char *,const char *));
173.  STATIC_DCL char *FDECL(enlght_combatinc, (const char *,int,int,char *));
174.  #ifdef UNIX
175.  static void NDECL(end_of_input);
176.  #endif
177.  #endif /* OVLB */
178.  
179.  static const char* readchar_queue="";
180.  
181.  STATIC_DCL char *NDECL(parse);
182.  STATIC_DCL boolean FDECL(help_dir, (CHAR_P,const char *));
183.  
184.  STATIC_PTR int NDECL(domenusystem); /* WAC the menus*/
185.  
186.  #ifdef BORG
187.  /* in borg.c */
188.  extern char borg_on;
189.  extern char borg_line[80];
190.  char borg_input(void);
191.  #endif
192.  #ifdef OVL1
193.  
194.  STATIC_PTR int
195.  doprev_message()
196.  {
197.      return nh_doprev_message();
198.  }
199.  
200.  
201.  /* Count down by decrementing multi */
202.  STATIC_PTR int
203.  timed_occupation()
204.  {
205.  	(*timed_occ_fn)();
206.  	if (multi > 0)
207.  		multi--;
208.  	return multi > 0;
209.  }
210.  
211.  /* If you have moved since initially setting some occupations, they
212.   * now shouldn't be able to restart.
213.   *
214.   * The basic rule is that if you are carrying it, you can continue
215.   * since it is with you.  If you are acting on something at a distance,
216.   * your orientation to it must have changed when you moved.
217.   *
218.   * The exception to this is taking off items, since they can be taken
219.   * off in a number of ways in the intervening time, screwing up ordering.
220.   *
221.   *	Currently:	Take off all armor.
222.   *			Picking Locks / Forcing Chests.
223.   *			Setting traps.
224.   */
225.  void
226.  reset_occupations()
227.  {
228.  	reset_remarm();
229.  	reset_pick();
230.  	reset_trapset();
231.  }
232.  
233.  /* If a time is given, use it to timeout this function, otherwise the
234.   * function times out by its own means.
235.   */
236.  void
237.  set_occupation(fn, txt, xtime)
238.  int NDECL((*fn));
239.  const char *txt;
240.  int xtime;
241.  {
242.  	if (xtime) {
243.  		occupation = timed_occupation;
244.  		timed_occ_fn = fn;
245.  	} else
246.  		occupation = fn;
247.  	occtxt = txt;
248.  	occtime = 0;
249.  	return;
250.  }
251.  
252.  #ifdef REDO
253.  
254.  static char NDECL(popch);
255.  
256.  /* Provide a means to redo the last command.  The flag `in_doagain' is set
257.   * to true while redoing the command.  This flag is tested in commands that
258.   * require additional input (like `throw' which requires a thing and a
259.   * direction), and the input prompt is not shown.  Also, while in_doagain is
260.   * TRUE, no keystrokes can be saved into the saveq.
261.   */
262.  #define BSIZE 20
263.  static char pushq[BSIZE], saveq[BSIZE];
264.  static NEARDATA int phead, ptail, shead, stail;
265.  
266.  static char
267.  popch() {
268.  	/* If occupied, return '\0', letting tgetch know a character should
269.  	 * be read from the keyboard.  If the character read is not the
270.  	 * ABORT character (as checked in pcmain.c), that character will be
271.  	 * pushed back on the pushq.
272.  	 */
273.  	if (occupation) return '\0';
274.  	if (in_doagain) return(char)((shead != stail) ? saveq[stail++] : '\0');
275.  	else		return(char)((phead != ptail) ? pushq[ptail++] : '\0');
276.  }
277.  
278.  char
279.  pgetchar() {		/* curtesy of aeb@cwi.nl */
280.  	register int ch;
281.  
282.  	if(!(ch = popch()))
283.  		ch = nhgetch();
284.  	return((char)ch);
285.  }
286.  
287.  /* A ch == 0 resets the pushq */
288.  void
289.  pushch(ch)
290.  char ch;
291.  {
292.  	if (!ch)
293.  		phead = ptail = 0;
294.  	if (phead < BSIZE)
295.  		pushq[phead++] = ch;
296.  	return;
297.  }
298.  
299.  /* A ch == 0 resets the saveq.	Only save keystrokes when not
300.   * replaying a previous command.
301.   */
302.  void
303.  savech(ch)
304.  char ch;
305.  {
306.  	if (!in_doagain) {
307.  		if (!ch)
308.  			phead = ptail = shead = stail = 0;
309.  		else if (shead < BSIZE)
310.  			saveq[shead++] = ch;
311.  	}
312.  	return;
313.  }
314.  #endif /* REDO */
315.  
316.  #endif /* OVL1 */
317.  #ifdef OVLB
318.  
319.  STATIC_PTR int
320.  doextcmd()	/* here after # - now read a full-word command */
321.  {
322.  	int idx, retval;
323.  
324.  	/* keep repeating until we don't run help or quit */
325.  	do {
326.  	    idx = get_ext_cmd();
327.  	    if (idx < 0) return 0;	/* quit */
328.  
329.  	    retval = (*extcmdlist[idx].ef_funct)();
330.  	} while (extcmdlist[idx].ef_funct == doextlist);
331.  
332.  	return retval;
333.  }
334.  
335.  int
336.  doextlist()	/* here after #? - now list all full-word commands */
337.  {
338.  	register const struct ext_func_tab *efp;
339.  	char	 buf[BUFSZ];
340.  	winid datawin;
341.  
342.  	datawin = create_nhwindow(NHW_TEXT);
343.  	putstr(datawin, 0, "");
344.  	putstr(datawin, 0, "            Extended Commands List");
345.  	putstr(datawin, 0, "");
346.  	putstr(datawin, 0, "    Press '#', then type:");
347.  	putstr(datawin, 0, "");
348.  
349.  	for(efp = extcmdlist; efp->ef_txt; efp++) {
350.  		Sprintf(buf, "    %-15s - %s.", efp->ef_txt, efp->ef_desc);
351.  		putstr(datawin, 0, buf);
352.  	}
353.  	display_nhwindow(datawin, FALSE);
354.  	destroy_nhwindow(datawin);
355.  	return 0;
356.  }
357.  
358.  #ifdef BORG
359.  STATIC_PTR int 
360.  doborgtoggle()
361.  {
362.  	char    qbuf[QBUFSZ];
363.  	char    c;
364.  	Strcpy(qbuf,"Really enable cyborg?");
365.  	if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
366.  		borg_on = 1;
367.  		pline("The cyborg is enabled.... Good luck!");
368.  	}
369.  	return 0;
370.  }
371.  #endif
372.  
373.  #if defined(TTY_GRAPHICS) || defined(GL_GRAPHICS) || defined(SDL_GRAPHICS)
374.  #define MAX_EXT_CMD 40		/* Change if we ever have > 40 ext cmds */
375.  /*
376.   * This is currently used only by the tty port and is
377.   * controlled via runtime option 'extmenu'
378.   * -AJA- The SDL/GL window systems use it too.
379.   */
380.  int
381.  extcmd_via_menu()	/* here after # - now show pick-list of possible commands */
382.  {
383.      const struct ext_func_tab *efp;
384.      menu_item *pick_list = (menu_item *)0;
385.      winid win;
386.      anything any;
387.      const struct ext_func_tab *choices[MAX_EXT_CMD];
388.      char buf[BUFSZ];
389.      char cbuf[QBUFSZ], prompt[QBUFSZ], fmtstr[20];
390.      int i, n, nchoices, acount;
391.      int ret,  biggest;
392.      int accelerator, prevaccelerator;
393.      int  matchlevel = 0;
394.  
395.      ret = 0;
396.      cbuf[0] = '\0';
397.      biggest = 0;
398.      while (!ret) {
399.  	    i = n = 0;
400.  	    accelerator = 0;
401.  	    any.a_void = 0;
402.  	    /* populate choices */
403.  	    for(efp = extcmdlist; efp->ef_txt; efp++) {
404.  		if (!matchlevel || !strncmp(efp->ef_txt, cbuf, matchlevel)) {
405.  			choices[i++] = efp;
406.  			if ((int)strlen(efp->ef_desc) > biggest) {
407.  				biggest = strlen(efp->ef_desc);
408.  				Sprintf(fmtstr,"%%-%ds", biggest + 15);
409.  			}
410.  #ifdef DEBUG
411.  			if (i >= MAX_EXT_CMD - 2) {
412.  			    impossible("Exceeded %d extended commands in doextcmd() menu",
413.  					MAX_EXT_CMD - 2);
414.  			    return 0;
415.  			}
416.  #endif
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.  	    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 the extended commands 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,
444.  					ATR_NONE, 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.  		    Sprintf(prompt, "%s or %s", choices[i-1]->ef_txt,
454.  				choices[i]->ef_txt);
455.  		} else {
456.  		    Strcat(prompt," or ");
457.  		    Strcat(prompt, choices[i]->ef_txt);
458.  		}
459.  		++acount;
460.  	    }
461.  	    if (acount) {
462.  		/* flush buf */
463.  		Sprintf(buf, fmtstr, prompt);
464.  		any.a_char = prevaccelerator;
465.  		add_menu(win, NO_GLYPH, &any, any.a_char, 0, ATR_NONE, buf, FALSE);
466.  	    }
467.  	    Sprintf(prompt, "Extended Command: %s", cbuf);
468.  	    end_menu(win, prompt);
469.  	    n = select_menu(win, PICK_ONE, &pick_list);
470.  	    destroy_nhwindow(win);
471.  	    if (n==1) {
472.  		if (matchlevel > (QBUFSZ - 2)) {
473.  			free((genericptr_t)pick_list);
474.  #ifdef DEBUG
475.  			impossible("Too many characters (%d) entered in extcmd_via_menu()",
476.  				matchlevel);
477.  #endif
478.  			ret = -1;
479.  		} else {
480.  			cbuf[matchlevel++] = pick_list[0].item.a_char;
481.  			cbuf[matchlevel] = '\0';
482.  			free((genericptr_t)pick_list);
483.  		}
484.  	    } else {
485.  		if (matchlevel) {
486.  			ret = 0;
487.  			matchlevel = 0;
488.  		} else
489.  			ret = -1;
490.  	    }
491.      }
492.      return ret;
493.  }
494.  #endif
495.  
496.  /* #monster command - use special monster ability while polymorphed */
497.  STATIC_PTR int
498.  domonability()
499.  {
500.  	if (can_breathe(youmonst.data)) return dobreathe();
501.  	else if (attacktype(youmonst.data, AT_SPIT)) return dospit();
502.  	else if (youmonst.data->mlet == S_NYMPH) return doremove();
503.  	else if (attacktype(youmonst.data, AT_GAZE)) return dogaze();
504.  	else if (is_were(youmonst.data)) return dosummon();
505.  	else if (webmaker(youmonst.data)) return dospinweb();
506.  	else if (is_hider(youmonst.data)) return dohide();
507.  	else if (is_mind_flayer(youmonst.data)) return domindblast();
508.  	else if (u.umonnum == PM_GREMLIN) {
509.  	    if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
510.  		if (split_mon(&youmonst, (struct monst *)0))
511.  		    dryup(u.ux, u.uy, TRUE);
512.  	    } else There("is no fountain here.");
513.  	} else if (is_unicorn(youmonst.data)) {
514.  	    use_unicorn_horn((struct obj *)0);
515.  	    return 1;
516.  	} else if (youmonst.data->msound == MS_SHRIEK) {
517.  	    You("shriek.");
518.  	    if(u.uburied)
519.  		pline("Unfortunately sound does not carry well through rock.");
520.  	    else aggravate();
521.  	} else if (Upolyd)
522.  		pline("Any special ability you may have is purely reflexive.");
523.  	else You("don't have a special ability in your normal form!");
524.  	return 0;
525.  }
526.  
527.  STATIC_PTR int
528.  enter_explore_mode()
529.  {
530.  	if(!discover && !wizard) {
531.  		pline("Beware!  From explore mode there will be no return to normal game.");
532.  		if (yn("Do you want to enter explore mode?") == 'y') {
533.  			clear_nhwindow(WIN_MESSAGE);
534.  			You("are now in non-scoring explore mode.");
535.  			discover = TRUE;
536.  		}
537.  		else {
538.  			clear_nhwindow(WIN_MESSAGE);
539.  			pline("Resuming normal game.");
540.  		}
541.  	}
542.  	return 0;
543.  }
544.  
545.  
546.  STATIC_PTR int
547.  playersteal()
548.  {
549.  	register int x, y;
550.          int temp, chanch, base, dexadj, statbonus = 0;
551.  	boolean no_steal = FALSE;
552.  
553.  	if (nohands(youmonst.data)) {
554.  		pline("Could be hard without hands ...");
555.  		no_steal = TRUE;
556.  	} else
557.  	if (near_capacity() > SLT_ENCUMBER) {
558.  		Your("load is too heavy to attempt to steal.");
559.  		no_steal = TRUE;
560.  	}
561.  	if (no_steal) {
562.  		/* discard direction typeahead, if any */
563.  		display_nhwindow(WIN_MESSAGE, TRUE);    /* --More-- */
564.  		return(0);
565.  	}
566.  
567.  	if(!getdir(NULL)) return(0);
568.  	if(!u.dx && !u.dy) return(0);
569.  
570.  	x = u.ux + u.dx;
571.  	y = u.uy + u.dy;
572.  	
573.  	if(u.uswallow) {
574.  		pline("You search around but don't find anything.");
575.  		return(1);
576.  	}
577.  
578.  	u_wipe_engr(2);
579.  
580.  	maploc = &levl[x][y];
581.  
582.  	if(MON_AT(x, y)) {
583.  		register struct monst *mdat = m_at(x, y);
584.  
585.  		/* calculate chanch of sucess */
586.  		base = 5;
587.  		dexadj = 1;
588.  		if (Role_if(PM_ROGUE)) {
589.  			base = 5 + (u.ulevel * 2);
590.  			dexadj = 3;
591.  		}
592.  		if (ACURR(A_DEX) < 10) statbonus = (ACURR(A_DEX) - 10) * dexadj;
593.  		else 
594.  		if (ACURR(A_DEX) > 14) statbonus = (ACURR(A_DEX) - 14) * dexadj;
595.  
596.  		chanch = base + statbonus;
597.  
598.  		if (uarmg && uarmg->otyp != GAUNTLETS_OF_DEXTERITY)
599.  				chanch -= 5;
600.  		if (!uarmg)     chanch += 5;
601.  		if (uarms)      chanch -= 10;
602.  		if (uarm && uarm->owt < 75)       chanch += 10;
603.  		else if (uarm && uarm->owt < 125) chanch += 5;
604.  		else if (uarm && uarm->owt < 175) chanch += 0;
605.  		else if (uarm && uarm->owt < 225) chanch -= 5;
606.  		else if (uarm && uarm->owt < 275) chanch -= 10;
607.  		else if (uarm && uarm->owt < 325) chanch -= 15;
608.  		else if (uarm && uarm->owt < 375) chanch -= 20;
609.  		else if (uarm)                    chanch -= 25;
610.  		if (chanch < 5) chanch = 5;
611.  		if (chanch > 95) chanch = 95;
612.  		if (rnd(100) < chanch || mdat->mtame) {
613.  
614.  #ifdef GOLDOBJ
615.  			/* [CWC] This will steal money from the monster from the
616.  			 * first found goldobj - we could be really clever here and
617.  			 * then move onwards to the next goldobj in invent if we
618.  			 * still have coins left to steal, but lets leave that until
619.  			 * we actually have other coin types to test it on.
620.  			 */
621.  			struct obj *gold = findgold(mdat->minvent);
622.  			if (gold) {
623.  				int mongold;
624.  				int coinstolen;
625.  				coinstolen = (u.ulevel * rn1(25,25));
626.  				mongold = (int)gold->quan;
627.  				if (coinstolen > mongold) coinstolen = mongold;
628.  				if (coinstolen > 0)	{
629.  					if (coinstolen != mongold) 
630.  						gold = splitobj(gold, coinstolen);
631.  					obj_extract_self(gold);
632.  		      if (merge_choice(invent, gold) || inv_cnt() < 52) {
633.  				    addinv(gold);
634.  						You("steal %s.", doname(gold));
635.  					} else {
636.              You("grab %s, but find no room in your knapsack.", doname(gold));
637.  			    	dropy(gold);
638.  					}
639.  				}
640.  				else
641.  				impossible("cmd.c:playersteal() stealing negative money");
642.  #else
643.  			if (mdat->mgold) {
644.  				temp = (u.ulevel * rn1(25,25));
645.  				if (temp > mdat->mgold) temp = mdat->mgold;
646.  				u.ugold += temp;
647.  				mdat->mgold -= temp;
648.  				You("steal %d gold.",temp);
649.  #endif
650.  			} else
651.  				You("don't find anything to steal.");
652.  
653.  			if (!mdat->mtame) exercise(A_DEX, TRUE);
654.  			return(1);
655.  		} else {
656.  			You("failed to steal anything.");
657.  			setmangry(mdat);
658.  			return(1);
659.  	       }
660.  	} else {
661.  		pline("I don't see anybody to rob there!");
662.  		return(0);
663.  	}
664.  
665.  	return(0);
666.  } 
667.  
668.  #ifdef WIZARD
669.  
670.  /* ^W command - wish for something */
671.  STATIC_PTR int
672.  wiz_wish()	/* Unlimited wishes for debug mode by Paul Polderman */
673.  {
674.  	if (wizard) {
675.  	    boolean save_verbose = flags.verbose;
676.  
677.  	    flags.verbose = FALSE;
678.  	    makewish();
679.  	    flags.verbose = save_verbose;
680.  	    (void) encumber_msg();
681.  	} else
682.  	    pline("Unavailable command '^W'.");
683.  	return 0;
684.  }
685.  
686.  
687.  #if 0	/* WAC -- Now uses techniques */
688.  STATIC_PTR int
689.  specialpower()      /* Special class abilites [modified by Tom] */
690.  {
691.  	/*
692.  	 * STEPHEN WHITE'S NEW CODE
693.  	 *
694.  	 * For clarification, lastuse (as declared in decl.{c|h}) is the
695.  	 * actual length of time the power is active, nextuse is when you can
696.  	 * next use the ability.
697.  	 */
698.  
699.          /*Added wizard mode can choose to use ability - wAC*/
700.  	if (u.unextuse) {
701.  	    You("have to wait %s before using your ability again.",
702.  		(u.unextuse > 500) ? "for a while" : "a little longer");
703.  #ifdef WIZARD
704.              if (!wizard || (yn("Use ability anyways?") == 'n'))
705.  #endif
706.                  return(0);
707.  	}
708.  
709.  	switch (u.role) {
710.  	    case 'A':
711.  /*WAC stolen from the spellcasters...'A' can identify from
712.          historical research*/
713.  		if(Hallucination || Stunned || Confusion) {
714.  		    You("can't concentrate right now!");
715.  		    break;
716.  		} else if((ACURR(A_INT) + ACURR(A_WIS)) < rnd(60)) {
717.  			pline("Nothing in your pack looks familiar.");
718.  		    u.unextuse = rn1(500,500);
719.  		    break;
720.  		} else if(invent) {
721.  		    int ret;
722.  			You("examine your possessions.");
723.  			identify_pack(1);
724.  /*WAC this should be better - made like scroll of identify*/
725.  /* KMH -- also commented out use of 'ret' without initialization */
726.  /*                  ret = ggetobj("identify", identify, 1, FALSE);*/
727.  /*		    if (ret < 0) break; *//* quit or no eligible items */
728.  /*                  ret = ggetobj("identify", identify, 1, FALSE);*/
729.  		} else {
730.  			/* KMH -- fixed non-compliant string */
731.  			You("are already quite familiar with the contents of your pack.");
732.  		    break;
733.  		}
734.  		u.unextuse = rn1(500,1500);
735.  		break;
736.  	    case 'G':
737.  			Your("ability, gem identification, is automatic.");
738.  			return(0);
739.  		case 'P':
740.  			Your("ability, bless and curse detection, is automatic.");
741.  			return(0);
742.  	    case 'D':
743.  			/* KMH -- Just do it!  (Besides, Alt isn't portable...) */
744.  			return (polyatwill());
745.  			/*Your("ability, polymorphing, uses the alt-y key.");*/
746.  			/*return(0);*/
747.  	    case 'L':
748.  		/*only when empty handed, in human form!*/
749.  		if (Upolyd) {
750.  			You("can't do this while polymorphed!");
751.  			break;
752.  		}
753.  		if (uwep == 0) {
754.  			Your("fingernails extend into claws!");
755.  			aggravate();
756.  			u.ulastuse = d(2,4) + (u.ulevel/5) + 1; /* [max] was d(2,8) */
757.  			u.unextuse = rn1(1000,1000); /* [max] increased delay */
758.  		}
759.  		else You("can't do this while holding a weapon!");
760.  		break;
761.  	    case 'R':
762.  	    /* KMH -- Just do it!  (Besides, Alt isn't portable...) */
763.  	    return (playersteal());
764.  		/*Your("ability, stealing, uses the alt-b key.");*/
765.          /*return(0);*/
766.  		break;
767.  	    case 'M':
768.  		Your("special ability is unarmed combat, and it is automatic.");
769.                  return(0);
770.  		break;
771.  	    case 'C':
772.  	    case 'T':
773.  		You("don't have a special ability!");
774.                  return(0);
775.  		break;
776.  	    case 'B':
777.  		You("fly into a berserk rage!");
778.  		u.ulastuse = d(2,8) + (u.ulevel/5) + 1;
779.  		incr_itimeout(&HFast, u.ulastuse);
780.  		u.unextuse = rn1(1000,500);
781.  		return(0);
782.  		break;
783.  	    case 'F':
784.  	    case 'I':
785.  	    case 'N':
786.  	    case 'W':
787.              /* WAC spell-users can study their known spells*/
788.  		if(Hallucination || Stunned || Confusion) {
789.  		    You("can't concentrate right now!");
790.  		    break;
791.  		} else {
792.  			You("concentrate...");
793.  			studyspell(); /*in spell.c*/
794.  		}
795.  		break;
796.  	    case 'E':
797.                  Your("%s %s become blurs as they reach for your quiver!",
798.  			uarmg ? "gloved" : "bare",      /* Del Lamb */
799.  			makeplural(body_part(HAND)));
800.                  u.ulastuse = rnd((int) (u.ulevel/6 + 1)) + 1;
801.  		u.unextuse = rn1(1000,500);
802.  		break;
803.  	    case 'U':
804.  	    case 'V':
805.  		if(!uwep || (weapon_type(uwep) == P_NONE)) {
806.  		    You("are not wielding a weapon!");
807.  		    break;
808.  		} else if(uwep->known == TRUE) {
809.                      You("study and practice with your %s %s.",
810.                          uarmg ? "gloved" : "bare",      /* Del Lamb */
811.  			makeplural(body_part(HAND)));
812.                      practice_weapon();
813.  		} else {
814.                      if (not_fully_identified(uwep)) {
815.                          You("examine %s.", doname(uwep));
816.                              if (rnd(15) <= ACURR(A_INT)) {
817.                                  makeknown(uwep->otyp);
818.                                  uwep->known = TRUE;
819.                                  You("discover it is %s",doname(uwep));
820.                                  } else
821.                       pline("Unfortunately, you didn't learn anything new.");
822.                      } 
823.                  /*WAC Added practicing code - in weapon.c*/
824.                      practice_weapon();
825.  		}
826.                  u.unextuse = rn1(500,500);
827.  		break;
828.  	    case 'H':
829.  		if (Hallucination || Stunned || Confusion) {
830.  		    You("are in no condition to perform surgery!");
831.  		    break;
832.  		}
833.  		if ((Sick) || (Slimed)) {       /* WAC cure sliming too */
834.  		    if(carrying(SCALPEL)) {
835.  			pline("Using your scalpel (ow!), you cure your infection!");
836.  			make_sick(0L,(char *)0, TRUE,SICK_ALL);
837.  			Slimed = 0;
838.  			if(u.uhp > 6) u.uhp -= 5;
839.  			else          u.uhp = 1;
840.  			u.unextuse = rn1(500,500);
841.  			break;
842.  		    } else pline("If only you had a scalpel...");
843.  		}
844.  		if (u.uhp < u.uhpmax) {
845.  		    if(carrying(MEDICAL_KIT)) {
846.  			pline("Using your medical kit, you bandage your wounds.");
847.  			u.uhp += (u.ulevel * (rnd(2)+1)) + rn1(5,5);
848.  		    } else {
849.  			pline("You bandage your wounds as best you can.");
850.  			u.uhp += (u.ulevel) + rn1(5,5);
851.  		    }
852.  		    u.unextuse = rn1(1000,500);
853.  		    if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
854.  		} else pline("You don't need your healing powers!");
855.  		break;
856.  	    case 'K':
857.  		if (u.uhp < u.uhpmax || Sick || Slimed) { /*WAC heal sliming */
858.  			if (Sick) You("lay your hands on the foul sickness...");
859.  			pline("A warm glow spreads through your body!");
860.  			if (Slimed) pline_The("slime is removed.");
861.  			Slimed = 0;
862.  			if(Sick) make_sick(0L,(char*)0, TRUE, SICK_ALL);
863.  			else     u.uhp += (u.ulevel * 4);
864.  			if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
865.  			u.unextuse = 3000;
866.  		} else pline(nothing_happens);
867.  		break;
868.  	    case 'S':
869.  		You("scream \"KIIILLL!\"");
870.  		aggravate();
871.  		u.ulastuse = rnd((int) (u.ulevel/6 + 1)) + 1;
872.  		u.unextuse = rn1(1000,500);
873.  		return(0);
874.  		break;
875.  #ifdef YEOMAN
876.  		case 'Y':
877.  #ifdef STEED
878.  			if (u.usteed) {
879.  				pline("%s gets tamer.", Monnam(u.usteed));
880.  				tamedog(u.usteed, (struct obj *) 0);
881.  				u.unextuse = rn1(1000,500);
882.  			} else
883.  				Your("special ability is only effective when riding a monster.");
884.  			break;
885.  #else
886.  			You("don't have a special ability!");
887.  			return(0);
888.  #endif
889.  #endif
890.  	    default:
891.  		break;
892.  	  }
893.  /*By default,  action should take a turn*/
894.  	return(1);
895.  }
896.  #endif
897.  
898.  
899.  /* ^I command - identify hero's inventory */
900.  STATIC_PTR int
901.  wiz_identify()
902.  {
903.  	if (wizard)	identify_pack(0);
904.  	else		pline("Unavailable command '^I'.");
905.  	return 0;
906.  }
907.  
908.  /* ^F command - reveal the level map and any traps on it */
909.  STATIC_PTR int
910.  wiz_map()
911.  {
912.  	if (wizard) {
913.  	    struct trap *t;
914.  	    long save_Hconf = HConfusion,
915.  		 save_Hhallu = HHallucination;
916.  
917.  	    HConfusion = HHallucination = 0L;
918.  	    for (t = ftrap; t != 0; t = t->ntrap) {
919.  		t->tseen = 1;
920.  		map_trap(t, TRUE);
921.  	    }
922.  	    do_mapping();
923.  	    HConfusion = save_Hconf;
924.  	    HHallucination = save_Hhallu;
925.  	} else
926.  	    pline("Unavailable command '^F'.");
927.  	return 0;
928.  }
929.  
930.  /* ^G command - generate monster(s); a count prefix will be honored */
931.  STATIC_PTR int
932.  wiz_gain_level()
933.  {
934.  	if (wizard) pluslvl(FALSE);
935.  	else            pline("Unavailable command '^J'.");
936.  	return 0;
937.  }
938.  
939.  /* BEGIN TSANTH'S CODE */
940.  STATIC_PTR int
941.  wiz_gain_ac()
942.  {
943.  	if (wizard) {
944.  		if (u.ublessed < 20) {
945.  			pline("Intrinsic AC increased by 1.");
946.  			HProtection |= FROMOUTSIDE;
947.  			u.ublessed++;
948.  			flags.botl = 1;
949.  		} else
950.  			pline("Intrinsic AC is already maximized.");
951.  	}
952.  	else
953.  		pline("Unavailable command '^C'.");
954.  	return 0;
955.  }
956.  
957.  STATIC_PTR int
958.  wiz_toggle_invulnerability()
959.  {
960.  	if (wizard) {
961.  	    if ((Invulnerable == 0) && (u.uinvulnerable == FALSE)) {
962.  	            You("will be invulnerable for 32000 turns.");
963.  	            Invulnerable = 32000;
964.  	            u.uinvulnerable = TRUE;
965.  	    }
966.  	    else {
967.  	            You("are no longer invulnerable.");
968.  	            Invulnerable = 0;
969.  	            u.uinvulnerable = FALSE;
970.  	    }
971.  	}
972.  	else            pline("Unavailable command '^N'.");
973.  	return 0;
974.  }
975.  /* END TSANTH'S CODE */
976.  
977.  STATIC_PTR int
978.  wiz_genesis()
979.  {
980.  	if (wizard)	(void) create_particular();
981.  	else		pline("Unavailable command '^G'.");
982.  	return 0;
983.  }
984.  
985.  /* ^O command - display dungeon layout */
986.  STATIC_PTR int
987.  wiz_where()
988.  {
989.  	if (wizard) (void) print_dungeon(FALSE, (schar *)0, (xchar *)0);
990.  	else	    pline("Unavailable command '^O'.");
991.  	return 0;
992.  }
993.  
994.  /* ^E command - detect unseen (secret doors, traps, hidden monsters) */
995.  STATIC_PTR int
996.  wiz_detect()
997.  {
998.  	if(wizard)  (void) findit();
999.  	else	    pline("Unavailable command '^E'.");
1000. 	return 0;
1001. }
1002. 
1003. /* ^V command - level teleport */
1004. STATIC_PTR int
1005. wiz_level_tele()
1006. {
1007. 	if (wizard)	level_tele();
1008. 	else		pline("Unavailable command '^V'.");
1009. 	return 0;
1010. }
1011. 
1012. /* #monpolycontrol command - choose new form for shapechangers, polymorphees */
1013. STATIC_PTR int
1014. wiz_mon_polycontrol()
1015. {
1016.     iflags.mon_polycontrol = !iflags.mon_polycontrol;
1017.     pline("Monster polymorph control is %s.",
1018. 	  iflags.mon_polycontrol ? "on" : "off");
1019.     return 0;
1020. }
1021. 
1022. /* #levelchange command - adjust hero's experience level */
1023. STATIC_PTR int
1024. wiz_level_change()
1025. {
1026.     char buf[BUFSZ];
1027.     int newlevel;
1028.     int ret;
1029. 
1030.     getlin("To what experience level do you want to be set?", buf);
1031.     (void)mungspaces(buf);
1032.     if (buf[0] == '\033' || buf[0] == '\0') ret = 0;
1033.     else ret = sscanf(buf, "%d", &newlevel);
1034. 
1035.     if (ret != 1) {
1036. 	pline(Never_mind);
1037. 	return 0;
1038.     }
1039.     if (newlevel == u.ulevel) {
1040. 	You("are already that experienced.");
1041.     } else if (newlevel < u.ulevel) {
1042. 	if (u.ulevel == 1) {
1043. 	    You("are already as inexperienced as you can get.");
1044. 	    return 0;
1045. 	}
1046. 	if (newlevel < 1) newlevel = 1;
1047. 	while (u.ulevel > newlevel)
1048. 	    losexp("#levelchange", TRUE);
1049.     } else {
1050. 	if (u.ulevel >= MAXULEV) {
1051. 	    You("are already as experienced as you can get.");
1052. 	    return 0;
1053. 	}
1054. 	if (newlevel > MAXULEV) newlevel = MAXULEV;
1055. 	while (u.ulevel < newlevel)
1056. 	    pluslvl(FALSE);
1057.     }
1058.     u.ulevelmax = u.ulevel;
1059.     return 0;
1060. }
1061. 
1062. /* #panic command - test program's panic handling */
1063. STATIC_PTR int
1064. wiz_panic()
1065. {
1066. 	if (yn("Do you want to call panic() and end your game?") == 'y')
1067. 		panic("crash test.");
1068.         return 0;
1069. }
1070. 
1071. /* #polyself command - change hero's form */
1072. STATIC_PTR int
1073. wiz_polyself()
1074. {
1075.         polyself(TRUE);
1076.         return 0;
1077. }
1078. 
1079. /* #seenv command */
1080. STATIC_PTR int
1081. wiz_show_seenv()
1082. {
1083. 	winid win;
1084. 	int x, y, v, startx, stopx, curx;
1085. 	char row[COLNO+1];
1086. 
1087. 	win = create_nhwindow(NHW_TEXT);
1088. 	/*
1089. 	 * Each seenv description takes up 2 characters, so center
1090. 	 * the seenv display around the hero.
1091. 	 */
1092. 	startx = max(1, u.ux-(COLNO/4));
1093. 	stopx = min(startx+(COLNO/2), COLNO);
1094. 	/* can't have a line exactly 80 chars long */
1095. 	if (stopx - startx == COLNO/2) startx++;
1096. 
1097. 	for (y = 0; y < ROWNO; y++) {
1098. 	    for (x = startx, curx = 0; x < stopx; x++, curx += 2) {
1099. 		if (x == u.ux && y == u.uy) {
1100. 		    row[curx] = row[curx+1] = '@';
1101. 		} else {
1102. 		    v = levl[x][y].seenv & 0xff;
1103. 		    if (v == 0)
1104. 			row[curx] = row[curx+1] = ' ';
1105. 		    else
1106. 			Sprintf(&row[curx], "%02x", v);
1107. 		}
1108. 	    }
1109. 	    /* remove trailing spaces */
1110. 	    for (x = curx-1; x >= 0; x--)
1111. 		if (row[x] != ' ') break;
1112. 	    row[x+1] = '\0';
1113. 
1114. 	    putstr(win, 0, row);
1115. 	}
1116. 	display_nhwindow(win, TRUE);
1117. 	destroy_nhwindow(win);
1118. 	return 0;
1119. }
1120. 
1121. /* #vision command */
1122. STATIC_PTR int
1123. wiz_show_vision()
1124. {
1125. 	winid win;
1126. 	int x, y, v;
1127. 	char row[COLNO+1];
1128. 
1129. 	win = create_nhwindow(NHW_TEXT);
1130. 	Sprintf(row, "Flags: 0x%x could see, 0x%x in sight, 0x%x temp lit",
1131. 		COULD_SEE, IN_SIGHT, TEMP_LIT);
1132. 	putstr(win, 0, row);
1133. 	putstr(win, 0, "");
1134. 	for (y = 0; y < ROWNO; y++) {
1135. 	    for (x = 1; x < COLNO; x++) {
1136. 		if (x == u.ux && y == u.uy)
1137. 		    row[x] = '@';
1138. 		else {
1139. 		    v = viz_array[y][x]; /* data access should be hidden */
1140. 		    if (v == 0)
1141. 			row[x] = ' ';
1142. 		    else
1143. 			row[x] = '0' + viz_array[y][x];
1144. 		}
1145. 	    }
1146. 	    /* remove trailing spaces */
1147. 	    for (x = COLNO-1; x >= 1; x--)
1148. 		if (row[x] != ' ') break;
1149. 	    row[x+1] = '\0';
1150. 
1151. 	    putstr(win, 0, &row[1]);
1152. 	}
1153. 	display_nhwindow(win, TRUE);
1154. 	destroy_nhwindow(win);
1155. 	return 0;
1156. }
1157. 
1158. /* #wmode command */
1159. STATIC_PTR int
1160. wiz_show_wmodes()
1161. {
1162. 	winid win;
1163. 	int x,y;
1164. 	char row[COLNO+1];
1165. 	struct rm *lev;
1166. 
1167. 	win = create_nhwindow(NHW_TEXT);
1168. 	for (y = 0; y < ROWNO; y++) {
1169. 	    for (x = 0; x < COLNO; x++) {
1170. 		lev = &levl[x][y];
1171. 		if (x == u.ux && y == u.uy)
1172. 		    row[x] = '@';
1173. 		else if (IS_WALL(lev->typ) || lev->typ == SDOOR)
1174. 		    row[x] = '0' + (lev->wall_info & WM_MASK);
1175. 		else if (lev->typ == CORR)
1176. 		    row[x] = '#';
1177. 		else if (IS_ROOM(lev->typ) || IS_DOOR(lev->typ))
1178. 		    row[x] = '.';
1179. 		else
1180. 		    row[x] = 'x';
1181. 	    }
1182. 	    row[COLNO] = '\0';
1183. 	    putstr(win, 0, row);
1184. 	}
1185. 	display_nhwindow(win, TRUE);
1186. 	destroy_nhwindow(win);
1187. 	return 0;
1188. }
1189. 
1190. #endif /* WIZARD */
1191. 
1192. 
1193. /* -enlightenment and conduct- */
1194. static winid en_win;
1195. static const char
1196. 	You_[] = "You ",
1197. 	are[]  = "are ",  were[]  = "were ",
1198. 	have[] = "have ", had[]   = "had ",
1199. 	can[]  = "can ",  could[] = "could ";
1200. static const char
1201. 	have_been[]  = "have been ",
1202. 	have_never[] = "have never ", never[] = "never ";
1203. 
1204. #define enl_msg(prefix,present,past,suffix) \
1205. 			enlght_line(prefix, final ? past : present, suffix)
1206. #define you_are(attr)	enl_msg(You_,are,were,attr)
1207. #define you_have(attr)	enl_msg(You_,have,had,attr)
1208. #define you_can(attr)	enl_msg(You_,can,could,attr)
1209. #define you_have_been(goodthing) enl_msg(You_,have_been,were,goodthing)
1210. #define you_have_never(badthing) enl_msg(You_,have_never,never,badthing)
1211. #define you_have_X(something)	enl_msg(You_,have,(const char *)"",something)
1212. 
1213. static void
1214. enlght_line(start, middle, end)
1215. const char *start, *middle, *end;
1216. {
1217. 	char buf[BUFSZ];
1218. 
1219. 	Sprintf(buf, "%s%s%s.", start, middle, end);
1220. 	putstr(en_win, 0, buf);
1221. }
1222. 
1223. 
1224. 
1225. /* KMH, intrinsic patch -- several of these are updated */
1226. void
1227. enlightenment(final)
1228. int final;	/* 0 => still in progress; 1 => over, survived; 2 => dead */
1229. {
1230. 	int ltmp;
1231. 	char buf[BUFSZ];
1232. 
1233. 	en_win = create_nhwindow(NHW_MENU);
1234. 	putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:");
1235. 	putstr(en_win, 0, "");
1236. 
1237. #ifdef ELBERETH
1238. 	if (u.uevent.uhand_of_elbereth) {
1239. 	    static const char * const hofe_titles[3] = {
1240. 				"the Hand of Elbereth",
1241. 				"the Envoy of Balance",
1242. 				"the Glory of Arioch"
1243. 	    };
1244. 	    you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1]);
1245. 	}
1246. #endif
1247. 
1248. 	/* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
1249. 	if (u.ualign.record >= 20)	you_are("piously aligned");
1250. 	else if (u.ualign.record > 13)	you_are("devoutly aligned");
1251. 	else if (u.ualign.record > 8)	you_are("fervently aligned");
1252. 	else if (u.ualign.record > 3)	you_are("stridently aligned");
1253. 	else if (u.ualign.record == 3)	you_are("aligned");
1254. 	else if (u.ualign.record > 0)	you_are("haltingly aligned");
1255. 	else if (u.ualign.record == 0)	you_are("nominally aligned");
1256. 	else if (u.ualign.record >= -3)	you_have("strayed");
1257. 	else if (u.ualign.record >= -8)	you_have("sinned");
1258. 	else you_have("transgressed");
1259. #ifdef WIZARD
1260. 	if (wizard) {
1261. 		Sprintf(buf, " %d", u.ualign.record);
1262. 		enl_msg("Your alignment ", "is", "was", buf);
1263. 	}
1264. #endif
1265. 
1266. 	/*** Resistances to troubles ***/
1267. 	if (Fire_resistance) you_are("fire resistant");
1268. 	if (Cold_resistance) you_are("cold resistant");
1269. 	if (Sleep_resistance) you_are("sleep resistant");
1270. 	if (Disint_resistance) you_are("disintegration-resistant");
1271. 	if (Shock_resistance) you_are("shock resistant");
1272. 	if (Poison_resistance) you_are("poison resistant");
1273. 	if (Drain_resistance) you_are("level-drain resistant");
1274. 	if (Sick_resistance) you_are("immune to sickness");
1275. 	if (Antimagic) you_are("magic-protected");
1276. 	if (Acid_resistance) you_are("acid resistant");
1277. 	if (Stone_resistance)
1278. 		you_are("petrification resistant");
1279. 	if (Invulnerable) you_are("invulnerable");
1280. 	if (u.uedibility) you_can("recognize detrimental food");
1281. 
1282. 	/*** Troubles ***/
1283. 	if (Halluc_resistance)
1284. 		enl_msg("You resist", "", "ed", " hallucinations");
1285. 	if (final) {
1286. 		if (Hallucination) you_are("hallucinating");
1287. 		if (Stunned) you_are("stunned");
1288. 		if (Confusion) you_are("confused");
1289. 		if (Blinded) you_are("blinded");
1290. 		if (Sick) {
1291. 			if (u.usick_type & SICK_VOMITABLE)
1292. 				you_are("sick from food poisoning");
1293. 			if (u.usick_type & SICK_NONVOMITABLE)
1294. 				you_are("sick from illness");
1295. 		}
1296. 	}
1297. 	if (Stoned) you_are("turning to stone");
1298. 	if (Slimed) you_are("turning into slime");
1299. 	if (Strangled) you_are((u.uburied) ? "buried" : "being strangled");
1300. 	if (Glib) {
1301. 		Sprintf(buf, "slippery %s", makeplural(body_part(FINGER)));
1302. 		you_have(buf);
1303. 	}
1304. 	if (Fumbling) enl_msg("You fumble", "", "d", "");
1305. 	if (Wounded_legs
1306. #ifdef STEED
1307. 	    && !u.usteed
1308. #endif
1309. 			  ) {
1310. 		Sprintf(buf, "wounded %s", makeplural(body_part(LEG)));
1311. 		you_have(buf);
1312. 	}
1313. #if defined(WIZARD) && defined(STEED)
1314. 	if (Wounded_legs && u.usteed && wizard) {
1315. 	    Strcpy(buf, x_monnam(u.usteed, ARTICLE_YOUR, (char *)0, 
1316. 		    SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION, FALSE));
1317. 	    *buf = highc(*buf);
1318. 	    enl_msg(buf, " has", " had", " wounded legs");
1319. 	}
1320. #endif
1321. 	if (Sleeping) enl_msg("You ", "fall", "fell", " asleep");
1322. 	if (Hunger) enl_msg("You hunger", "", "ed", " rapidly");
1323. 
1324. 	/*** Vision and senses ***/
1325. 	if (See_invisible) enl_msg(You_, "see", "saw", " invisible");
1326. 	if (Blind_telepat) you_are("telepathic");
1327. 	if (Warning) you_are("warned");
1328. 	if (Warn_of_mon && flags.warntype) {
1329. 	    /* [ALI] Add support for undead */
1330. 	    int i, nth = 0;
1331. 	    unsigned long warntype = flags.warntype;
1332. 	    struct { unsigned long mask; const char *str; } warntypes[] = {
1333. 		M2_ORC,		"orcs",
1334. 		M2_DEMON,	"demons",
1335. 		M2_UNDEAD,	"undead",
1336. 	    };
1337. 
1338. 	    Sprintf(buf, "aware of the presence of ");
1339. 	    for(i = 0; i < SIZE(warntypes); i++)
1340. 	    {
1341. 		if (warntype & warntypes[i].mask) {
1342. 		    warntype &= ~warntypes[i].mask;
1343. 		    if (nth) {
1344. 			if (warntype)
1345. 			    strcat(buf, ", ");
1346. 			else
1347. 			    strcat(buf, " and ");
1348. 		    }
1349. 		    else
1350. 			nth = 1;
1351. 		    strcat(buf, warntypes[i].str);
1352. 		}
1353. 	    }
1354. 	    if (warntype)
1355. 	    {
1356. 		if (nth)
1357. 		    strcat(buf, " and ");
1358. 		strcat(buf, something); 
1359. 	    }
1360. 		you_are(buf);
1361. 	}
1362. #if 0	/* ALI - dealt with under Warn_of_mon */
1363. 	if (Undead_warning) you_are("warned of undead");
1364. #endif
1365. 	if (Searching) you_have("automatic searching");
1366. 	if (Clairvoyant) you_are("clairvoyant");
1367. 	if (Infravision) you_have("infravision");
1368. 	if (Detect_monsters) you_are("sensing the presence of monsters");
1369. 	if (u.umconf) you_are("going to confuse monsters");
1370. 
1371. 	/*** Appearance and behavior ***/
1372. 	if (Adornment) {
1373. 	    int adorn = 0;
1374. 
1375. 	    if(uleft && uleft->otyp == RIN_ADORNMENT) adorn += uleft->spe;
1376. 	    if(uright && uright->otyp == RIN_ADORNMENT) adorn += uright->spe;
1377. 	    if (adorn < 0)
1378. 		you_are("poorly adorned");
1379. 	    else
1380. 		you_are("adorned");
1381. 	}
1382. 	if (Invisible) you_are("invisible");
1383. 	else if (Invis) you_are("invisible to others");
1384. 	/* ordinarily "visible" is redundant; this is a special case for
1385. 	   the situation when invisibility would be an expected attribute */
1386. 	else if ((HInvis || EInvis || pm_invisible(youmonst.data)) && BInvis)
1387. 	    you_are("visible");
1388. 	if (Displaced) you_are("displaced");
1389. 	if (Stealth) you_are("stealthy");
1390. 	if (Aggravate_monster) enl_msg("You aggravate", "", "d", " monsters");
1391. 	if (Conflict) enl_msg("You cause", "", "d", " conflict");
1392. 
1393. 	/*** Transportation ***/
1394. 	if (Jumping) you_can("jump");
1395. 	if (Teleportation) you_can("teleport");
1396. 	if (Teleport_control) you_have("teleport control");
1397. 	if (Lev_at_will) you_are("levitating, at will");
1398. 	else if (Levitation) you_are("levitating");	/* without control */
1399. 	else if (Flying) you_can("fly");
1400. 	if (Wwalking) you_can("walk on water");
1401. 	if (Swimming) you_can("swim");        
1402. 	if (Breathless) you_can("survive without air");
1403. 	else if (Amphibious) you_can("breathe water");
1404. 	if (Passes_walls) you_can("walk through walls");
1405. #ifdef STEED
1406. 	/* If you die while dismounting, u.usteed is still set.  Since several
1407. 	 * places in the done() sequence depend on u.usteed, just detect this
1408. 	 * special case. */
1409. 	if (u.usteed && (final < 2 || strcmp(killer, "riding accident"))) {
1410. 	    Sprintf(buf, "riding %s", y_monnam(u.usteed));
1411. 	    you_are(buf);
1412. 	}
1413. #endif
1414. 	if (u.uswallow) {
1415. 	    Sprintf(buf, "swallowed by %s", a_monnam(u.ustuck));
1416. #ifdef WIZARD
1417. 	    if (wizard) Sprintf(eos(buf), " (%u)", u.uswldtim);
1418. #endif
1419. 	    you_are(buf);
1420. 	} else if (u.ustuck) {
1421. 	    Sprintf(buf, "%s %s",
1422. 		    (Upolyd && sticks(youmonst.data)) ? "holding" : "held by",
1423. 		    a_monnam(u.ustuck));
1424. 	    you_are(buf);
1425. 	}
1426. 
1427. 	/*** Physical attributes ***/
1428. 	if (u.uhitinc)
1429. 	    you_have(enlght_combatinc("to hit", u.uhitinc, final, buf));
1430. 	if (u.udaminc)
1431. 	    you_have(enlght_combatinc("damage", u.udaminc, final, buf));
1432. 	if (Slow_digestion) you_have("slower digestion");
1433. 	if (Regeneration) enl_msg("You regenerate", "", "d", "");
1434. 	if (u.uspellprot || Protection) {
1435. 	    int prot = 0;
1436. 
1437. 	    if(uleft && uleft->otyp == RIN_PROTECTION) prot += uleft->spe;
1438. 	    if(uright && uright->otyp == RIN_PROTECTION) prot += uright->spe;
1439. 	    if (HProtection & INTRINSIC) prot += u.ublessed;
1440. 	    prot += u.uspellprot;
1441. 
1442. 	    if (prot < 0)
1443. 		you_are("ineffectively protected");
1444. 	    else
1445. 		you_are("protected");
1446. 	}
1447. 	if (Protection_from_shape_changers)
1448. 		you_are("protected from shape changers");
1449. 	if (Polymorph) you_are("polymorphing");
1450. 	if (Polymorph_control) you_have("polymorph control");
1451. 	if (u.ulycn >= LOW_PM) {
1452. 		Strcpy(buf, an(mons[u.ulycn].mname));
1453. 		you_are(buf);
1454. 	}
1455. 	if (Upolyd) {
1456. 	    if (u.umonnum == u.ulycn) Strcpy(buf, "in beast form");
1457. 	    else Sprintf(buf, "polymorphed into %s", an(youmonst.data->mname));
1458. #ifdef WIZARD
1459. 	    if (wizard) Sprintf(eos(buf), " (%d)", u.mtimedone);
1460. #endif
1461. 	    you_are(buf);
1462. 	}
1463. 	if (Unchanging) you_can("not change from your current form");
1464. 	if (Fast) you_are(Very_fast ? "very fast" : "fast");
1465. 	if (Reflecting) you_have("reflection");
1466. 	if (Free_action) you_have("free action");
1467. 	if (Fixed_abil) you_have("fixed abilities");
1468. 	if (uamul && uamul->otyp == AMULET_VERSUS_STONE)
1469. 		enl_msg("You ", "will be", "would have been", " depetrified");
1470. 	if (Lifesaved)
1471. 		enl_msg("Your life ", "will be", "would have been", " saved");
1472. 	if (u.twoweap) {
1473. 	    if (uwep && uswapwep)
1474. 		Sprintf(buf, "wielding two weapons at once");
1475. 	    else if (uwep || uswapwep)
1476. 		Sprintf(buf, "fighting with a weapon and your %s %s",
1477. 			uwep ? "left" : "right", body_part(HAND));
1478. 	    else
1479. 		Sprintf(buf, "fighting with two %s",
1480. 			makeplural(body_part(HAND)));
1481. 	    you_are(buf);
1482. 	}
1483. 
1484. 	/*** Miscellany ***/
1485. 	if (Luck) {
1486. 	    ltmp = abs((int)Luck);
1487. 	    Sprintf(buf, "%s%slucky",
1488. 		    ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "",
1489. 		    Luck < 0 ? "un" : "");
1490. #ifdef WIZARD
1491. 	    if (wizard) Sprintf(eos(buf), " (%d)", Luck);
1492. #endif
1493. 	    you_are(buf);
1494. 	}
1495. #ifdef WIZARD
1496. 	 else if (wizard) enl_msg("Your luck ", "is", "was", " zero");
1497. #endif
1498. 	if (u.moreluck > 0) you_have("extra luck");
1499. 	else if (u.moreluck < 0) you_have("reduced luck");
1500. 	if (carrying(LUCKSTONE) || stone_luck(TRUE)) {
1501. 	    ltmp = stone_luck(FALSE);
1502. 	    if (ltmp <= 0)
1503. 		enl_msg("Bad luck ", "does", "did", " not time out for you");
1504. 	    if (ltmp >= 0)
1505. 		enl_msg("Good luck ", "does", "did", " not time out for you");
1506. 	}
1507. 
1508. 	/* KMH, balance patch -- healthstones affect health */
1509. 	if (u.uhealbonus)
1510. 	{
1511. 		Sprintf(buf, "%s health", u.uhealbonus > 0 ? "extra" :
1512. 			"reduced");
1513. #ifdef WIZARD
1514. 	    if (wizard) Sprintf(eos(buf), " (%d)", u.uhealbonus);
1515. #endif
1516. 		you_have(buf);
1517. 	}
1518. #ifdef WIZARD
1519. 	 else if (wizard) enl_msg("Your health bonus ", "is", "was", " zero");
1520. #endif
1521. 
1522. 	if (u.ugangr) {
1523. 	    Sprintf(buf, " %sangry with you",
1524. 		    u.ugangr > 6 ? "extremely " : u.ugangr > 3 ? "very " : "");
1525. #ifdef WIZARD
1526. 	    if (wizard) Sprintf(eos(buf), " (%d)", u.ugangr);
1527. #endif
1528. 	    enl_msg(u_gname(), " is", " was", buf);
1529. 	} else
1530. 	    /*
1531. 	     * We need to suppress this when the game is over, because death
1532. 	     * can change the value calculated by can_pray(), potentially
1533. 	     * resulting in a false claim that you could have prayed safely.
1534. 	     */
1535. 	  if (!final) {
1536. #if 0
1537. 	    /* "can [not] safely pray" vs "could [not] have safely prayed" */
1538. 	    Sprintf(buf, "%s%ssafely pray%s", can_pray(FALSE) ? "" : "not ",
1539. 		    final ? "have " : "", final ? "ed" : "");
1540. #else
1541. 	    Sprintf(buf, "%ssafely pray", can_pray(FALSE) ? "" : "not ");
1542. #endif
1543. #ifdef WIZARD
1544. 	    if (wizard) Sprintf(eos(buf), " (%d)", u.ublesscnt);
1545. #endif
1546. 	    you_can(buf);
1547. #if 0	/* WAC -- replaced by techniques */
1548. /*	    Sprintf(buf, "%s%suse%s your special", !u.unextuse ? "" : "not ",
1549. 		    final ? "have " : "", final ? "d" : "");*/
1550. 	    Sprintf(buf, "%suse your special", !u.unextuse ? "" : "not ");
1551. #ifdef WIZARD
1552. 	    if (wizard) Sprintf(eos(buf), " (%d)", u.unextuse);
1553. #endif
1554. 	    you_can(buf);
1555. #endif
1556. 	}
1557. 
1558.     {
1559. 	const char *p;
1560. 
1561. 	buf[0] = '\0';
1562. 	if (final < 2) {    /* still in progress, or quit/escaped/ascended */
1563. 	    p = "survived after being killed ";
1564. 	    switch (u.umortality) {
1565. 	    case 0:  p = !final ? (char *)0 : "survived";  break;
1566. 	    case 1:  Strcpy(buf, "once");  break;
1567. 	    case 2:  Strcpy(buf, "twice");  break;
1568. 	    case 3:  Strcpy(buf, "thrice");  break;
1569. 	    default: Sprintf(buf, "%d times", u.umortality);
1570. 		     break;
1571. 	    }
1572. 	} else {		/* game ended in character's death */
1573. 	    p = "are dead";
1574. 	    switch (u.umortality) {
1575. 	    case 0:  impossible("dead without dying?");
1576. 	    case 1:  break;			/* just "are dead" */
1577. 	    default: Sprintf(buf, " (%d%s time!)", u.umortality,
1578. 			     ordin(u.umortality));
1579. 		     break;
1580. 	    }
1581. 	}
1582. 	if (p) enl_msg(You_, "have been killed ", p, buf);
1583.     }
1584. 
1585. 	display_nhwindow(en_win, TRUE);
1586. 	destroy_nhwindow(en_win);
1587. 	return;
1588. }
1589. 
1590. /*
1591.  * Courtesy function for non-debug, non-explorer mode players
1592.  * to help refresh them about who/what they are.
1593.  * Returns FALSE if menu cancelled (dismissed with ESC), TRUE otherwise.
1594.  */
1595. STATIC_OVL boolean
1596. minimal_enlightenment()
1597. {
1598. 	winid tmpwin;
1599. 	menu_item *selected;
1600. 	anything any;
1601. 	int genidx, n;
1602. 	char buf[BUFSZ], buf2[BUFSZ];
1603. 	static const char untabbed_fmtstr[] = "%-15s: %-12s";
1604. 	static const char untabbed_deity_fmtstr[] = "%-17s%s";
1605. 	static const char tabbed_fmtstr[] = "%s:\t%-12s";
1606. 	static const char tabbed_deity_fmtstr[] = "%s\t%s";
1607. 	static const char *fmtstr;
1608. 	static const char *deity_fmtstr;
1609. 
1610. 	fmtstr = iflags.menu_tab_sep ? tabbed_fmtstr : untabbed_fmtstr;
1611. 	deity_fmtstr = iflags.menu_tab_sep ?
1612. 			tabbed_deity_fmtstr : untabbed_deity_fmtstr; 
1613. 	any.a_void = 0;
1614. 	buf[0] = buf2[0] = '\0';
1615. 	tmpwin = create_nhwindow(NHW_MENU);
1616. 	start_menu(tmpwin);
1617. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Starting", FALSE);
1618. 
1619. 	/* Starting name, race, role, gender */
1620. 	Sprintf(buf, fmtstr, "name", plname);
1621. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1622. 	Sprintf(buf, fmtstr, "race", urace.noun);
1623. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1624. 	Sprintf(buf, fmtstr, "role",
1625. 		(flags.initgend && urole.name.f) ? urole.name.f : urole.name.m);
1626. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1627. 	Sprintf(buf, fmtstr, "gender", genders[flags.initgend].adj);
1628. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1629. 
1630. 	/* Starting alignment */
1631. 	Sprintf(buf, fmtstr, "alignment", align_str(u.ualignbase[A_ORIGINAL]));
1632. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1633. 
1634. 	/* Current name, race, role, gender */
1635. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE);
1636. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Current", FALSE);
1637. 	Sprintf(buf, fmtstr, "race", Upolyd ? youmonst.data->mname : urace.noun);
1638. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1639. 	if (Upolyd) {
1640. 	    Sprintf(buf, fmtstr, "role (base)",
1641. 		(u.mfemale && urole.name.f) ? urole.name.f : urole.name.m);
1642. 	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1643. 	} else {
1644. 	    Sprintf(buf, fmtstr, "role",
1645. 		(flags.female && urole.name.f) ? urole.name.f : urole.name.m);
1646. 	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1647. 	}
1648. 	/* don't want poly_gender() here; it forces `2' for non-humanoids */
1649. 	genidx = is_neuter(youmonst.data) ? 2 : flags.female;
1650. 	Sprintf(buf, fmtstr, "gender", genders[genidx].adj);
1651. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1652. 	if (Upolyd && (int)u.mfemale != genidx) {
1653. 	    Sprintf(buf, fmtstr, "gender (base)", genders[u.mfemale].adj);
1654. 	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1655. 	}
1656. 
1657. 	/* Current alignment */
1658. 	Sprintf(buf, fmtstr, "alignment", align_str(u.ualign.type));
1659. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1660. 
1661. 	/* Deity list */
1662. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE);
1663. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Deities", FALSE);
1664. 	Sprintf(buf2, deity_fmtstr, align_gname(A_CHAOTIC),
1665. 	    (u.ualignbase[A_ORIGINAL] == u.ualign.type
1666. 		&& u.ualign.type == A_CHAOTIC) ? " (s,c)" :
1667. 	    (u.ualignbase[A_ORIGINAL] == A_CHAOTIC)       ? " (s)" :
1668. 	    (u.ualign.type   == A_CHAOTIC)       ? " (c)" : "");
1669. 	Sprintf(buf, fmtstr, "Chaotic", buf2);
1670. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1671. 
1672. 	Sprintf(buf2, deity_fmtstr, align_gname(A_NEUTRAL),
1673. 	    (u.ualignbase[A_ORIGINAL] == u.ualign.type
1674. 		&& u.ualign.type == A_NEUTRAL) ? " (s,c)" :
1675. 	    (u.ualignbase[A_ORIGINAL] == A_NEUTRAL)       ? " (s)" :
1676. 	    (u.ualign.type   == A_NEUTRAL)       ? " (c)" : "");
1677. 	Sprintf(buf, fmtstr, "Neutral", buf2);
1678. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1679. 
1680. 	Sprintf(buf2, deity_fmtstr, align_gname(A_LAWFUL),
1681. 	    (u.ualignbase[A_ORIGINAL] == u.ualign.type &&
1682. 		u.ualign.type == A_LAWFUL)  ? " (s,c)" :
1683. 	    (u.ualignbase[A_ORIGINAL] == A_LAWFUL)        ? " (s)" :
1684. 	    (u.ualign.type   == A_LAWFUL)        ? " (c)" : "");
1685. 	Sprintf(buf, fmtstr, "Lawful", buf2);
1686. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
1687. 
1688. 	end_menu(tmpwin, "Base Attributes");
1689. 	n = select_menu(tmpwin, PICK_NONE, &selected);
1690. 	destroy_nhwindow(tmpwin);
1691. 	return (n != -1);
1692. }
1693. 
1694. STATIC_PTR int
1695. doattributes()
1696. {
1697. 	if (!minimal_enlightenment())
1698. 		return 0;
1699. 	if (wizard || discover)
1700. 		enlightenment(0);
1701. 	return 0;
1702. }
1703. 
1704. static const struct menu_tab game_menu[] = {
1705. 	{'O', TRUE, doset, "Options"},
1706. 	{'r', TRUE, doredraw, "Redraw Screen"},
1707. 	{'x', TRUE, enter_explore_mode, "Enter Explore Mode"},
1708. #ifdef SHELL
1709. 	{'!', TRUE, dosh, "Jump to Shell"},
1710. #endif
1711. 	{'S', TRUE, dosave, "Save"},
1712. 	{'q', TRUE, done2, "Quit [M-q]"},
1713. 	{0,0,0,0},
1714. };
1715. 
1716. static const struct menu_tab inv_menu[] = {
1717. 	{(char)0, TRUE, (void *)0, "View Inventory"},
1718. 	{'i', TRUE, ddoinv, "Inventory List"},
1719. 	{'I', TRUE, dotypeinv, "Inventory List by Type"},
1720. 	{'*', TRUE, doprinuse, "Items in use"},
1721. 	{(char)0, TRUE, (void *)0, "Ready Items"},
1722. 	{'w', FALSE, dowield, "Wield Weapon"},
1723. 	{'W', FALSE, dowear, "Wear Protective Gear"},
1724. 	{'Q', FALSE, dowieldquiver, "Prepare missile weapon (in Quiver)"},
1725. 	{'T', FALSE, dotakeoff, "Take off Protective Gear"},
1726. 	{(char)0, TRUE, (void *)0, "Manipulate Items"},
1727. 	{'a', FALSE, doapply, "Apply an object"},
1728. 	{'d', FALSE, dodip, "Dip an object [M-d]"},
1729. 	{'E', FALSE, doengrave, "Engrave into the ground"},
1730. 	{'f', FALSE, dofire, "Fire your prepared missile weapon"},
1731. 	{'i', TRUE, doinvoke, "Invoke your weapon"},
1732. 	{'t', FALSE, dothrow, "Throw an item"},
1733. 	{(char)0, TRUE, (void *)0, "Drop Items"},
1734. 	{'d', FALSE, dodrop, "Drop an object"},
1735. 	{'D', FALSE, doddrop, "Multi-Drop"},
1736. 	{0,0,0,0}
1737. };
1738. 
1739. static const struct menu_tab action_menu[] = {
1740. 	{'c', FALSE, doclose, "Close a door"},
1741. 	{'e', FALSE, doeat, "Eat some food"},
1742. 	{'f', FALSE, doforce, "Force a lock [M-f]"},
1743. 	{'l', FALSE, doloot, "Loot an object"},
1744. 	{'o', FALSE, doopen, "Open a door"},
1745. 	{'q', TRUE, dodrink, "Quaff a potion"},
1746. 	{'r', FALSE, doread, "Read an object"},
1747. 	{'u', FALSE, dountrap, "Untrap"}, 
1748. 	{'z', FALSE, dozap, "Zap a wand"},
1749. 	{'Z', TRUE, docast, "Cast a spell"},
1750. 	{0,0,0,0}
1751. };
1752. 
1753. static const struct menu_tab player_menu[] = {
1754. 	{'b', FALSE, playersteal, "Steal from Monsters [M-b]"},
1755. 	{'c', TRUE, dotalk, "Chat with Monsters [M-c]"},
1756. 	{'d', FALSE, dokick, "Do Kick"}, 
1757. 	/*        {'e', FALSE, specialpower, "Use your Class Ability [M-e]"},*/
1758. 	{'e', TRUE, enhance_weapon_skill, "Weapon Skills [M-k]"},
1759. 	{'m', TRUE, domonability, "Use your Monster Ability [M-m]"},
1760. 	{'o', FALSE, dosacrifice, "Offer a Sacrifice [M-o]"},
1761. 	{'p', FALSE, dopay, "Pay the Shopkeeper"},
1762. 	{'s', FALSE, dosit, "Sit down [M-s]"},
1763. 	{'t', TRUE, dotele, "Controlled Teleport [C-t]"},
1764. /*	{'T', TRUE, doturn, "Turn Undead [M-t]"},*/
1765. 	{'T', TRUE, dotech, "Use Techniques [M-t]"},
1766. 	{'x', TRUE, doattributes, "Show attributes"},
1767. 	{'y', TRUE, polyatwill, "Self-Polymorph [M-y]"},
1768. 	{0,0,0,0}
1769. };
1770. 
1771. #ifdef WIZARD
1772. static const struct menu_tab wizard_menu[] = {
1773. 	{'c', TRUE, wiz_gain_ac, "Increase AC"},
1774. #ifdef DISPLAY_LAYERS
1775. 	{'d', TRUE, wiz_show_display, "Detail display layers"},
1776. #endif
1777. 	{'e', TRUE, wiz_detect, "Detect secret doors and traps"},
1778. 	{'f', TRUE, wiz_map, "Do magic mapping"},
1779. 	{'g', TRUE, wiz_genesis, "Create monster"},
1780. 	{'i', TRUE, wiz_identify, "Identify items in pack"},
1781. 	{'j', TRUE, wiz_gain_level, "Go up an experience level"},
1782. 	{'n', TRUE, wiz_toggle_invulnerability, "Toggle invulnerability"},
1783. 	{'o', TRUE, wiz_where, "Tell locations of special levels"},
1784. 	{'v', TRUE, wiz_level_tele, "Do trans-level teleport"},
1785. 	{'w', TRUE, wiz_wish,  "Make wish"},
1786. 	{'L', TRUE, wiz_light_sources, "show mobile light sources"},
1787. 	{'M', TRUE, wiz_show_stats, "show memory statistics"},
1788. 	{'S', TRUE, wiz_show_seenv, "show seen vectors"},
1789. 	{'T', TRUE, wiz_timeout_queue, "look at timeout queue"},
1790. 	{'V', TRUE, wiz_show_vision, "show vision array"},
1791. 	{'W', TRUE, wiz_show_wmodes, "show wall modes"},
1792. #ifdef DEBUG
1793. 	{'&', TRUE, wiz_debug_cmd, "wizard debug command"},
1794. #endif
1795. 	{0,0,0,0,0},
1796. };
1797. #endif
1798. 
1799. static const struct menu_tab help_menu[] = {
1800. 	{'?', TRUE, dohelp, "Help Contents"},
1801. 	{'v', TRUE, doextversion, "Version"},
1802. 	{'/', TRUE, dowhatis, "Identify an object on the screen" },
1803. 	{'&', TRUE, dowhatdoes, "Determine what a key does"},
1804. 	{0,0,0,0,0},
1805. };
1806. 
1807. static const struct menu_tab main_menu[] = {
1808. 	{'g', TRUE, (void *)0, "Game"},
1809. 	{'i', TRUE, (void *)0, "Inventory"},
1810. 	{'a', TRUE, (void *)0, "Action"},
1811. 	{'p', TRUE, (void *)0, "Player"},
1812. 	{'d', TRUE, (void *)0, "Discoveries"},
1813. #ifdef WIZARD
1814. 	{'w', TRUE, (void *)0, "Wizard"},
1815. #endif
1816. 	{'?', TRUE, (void *)0, "Help"},
1817. 	{0,0,0,0},
1818. };
1819. 
1820. static const struct menu_tab discover_menu[] = {
1821. 	{'X', TRUE, dovspell, "View known spells"},                  /* Mike Stephenson */
1822. 	{'d', TRUE, dodiscovered, "Items already discovered [\\]"},             /* Robert Viduya */
1823. 	{'C', TRUE, do_mname, "Name a monster"},
1824. 	{0,0,0,0},
1825. };
1826. 
1827. static struct menu_list main_menustruct[] = {
1828. 	{"Game", "Main Menu", game_menu},
1829. 	{"Inventory", "Main Menu", inv_menu},
1830. 	{"Action", "Main Menu", action_menu},
1831. 	{"Player", "Main Menu", player_menu},
1832. 	{"Discoveries", "Main Menu", discover_menu},
1833. #ifdef WIZARD
1834. 	{"Wizard", "Main Menu", wizard_menu},
1835. #endif
1836. 	{"Help", "Main Menu", help_menu},
1837. 	{"Main Menu",(char *)0, main_menu},
1838. 	{0,0,0},
1839. };
1840. 
1841. STATIC_PTR int
1842. makemenu(menuname, menu_struct)
1843. const char *menuname;
1844. struct menu_list menu_struct[];
1845. {
1846. 	winid win;
1847. 	anything any;
1848. 	menu_item *selected;
1849.         int n, i, NDECL((*func));
1850.         const struct menu_tab *current_menu;
1851. 
1852. 	any.a_void = 0;
1853. 	win = create_nhwindow(NHW_MENU);
1854. 	start_menu(win);
1855. 
1856.         for (i = 0; menu_struct[i].m_header; i++) {
1857.                 if (strcmp(menu_struct[i].m_header,menuname)) continue;
1858.                 current_menu = menu_struct[i].m_menu;
1859.                 for (n = 0; current_menu[n].m_item; n++) {
1860.                         if (u.uburied && !current_menu[n].can_if_buried) continue;
1861. #ifdef WIZARD
1862. 			if (!wizard && !current_menu[n].m_funct && !strcmp(current_menu[n].m_item,"Wizard")) continue;
1863. #endif
1864.                         if (current_menu[n].m_char == (char)0) {
1865.                                 any.a_int = 0; 
1866.                                 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_BOLD,
1867.                                      current_menu[n].m_item, MENU_UNSELECTED);
1868.                                 continue;
1869.                         }
1870.                         any.a_int = n + 1; /* non-zero */
1871.                         add_menu(win, NO_GLYPH, &any, current_menu[n].m_char,
1872.                         0, ATR_NONE, current_menu[n].m_item, MENU_UNSELECTED);
1873.                 }
1874.                 break;
1875.         }
1876.         end_menu(win, menuname);
1877.         n = select_menu(win, PICK_ONE, &selected);
1878.         destroy_nhwindow(win);
1879.         if (n > 0) {
1880.                 /* we discard 'const' because some compilers seem to have
1881. 		       trouble with the pointer passed to set_occupation() */
1882.                 i = selected[0].item.a_int - 1;
1883.                 func = current_menu[i].m_funct;
1884.                 if (current_menu[i].m_text && !occupation && multi)
1885.                       set_occupation(func, current_menu[i].m_text, multi);
1886.                 /*WAC catch void into makemenu */
1887.                 if (func == (void *)0)
1888.                         return (makemenu(current_menu[i].m_item, menu_struct));
1889.                 else return (*func)();            /* perform the command */
1890.         } else if (n < 0) {
1891.                 for (i = 0; menu_struct[i].m_header; i++){
1892.                    if (menuname == menu_struct[i].m_header) {
1893.                     if (menu_struct[i].m_parent)
1894.                       return (makemenu(menu_struct[i].m_parent, menu_struct));
1895.                     else return (0);
1896.                 }
1897.         }
1898.         }
1899.         return 0;
1900. }
1901. 
1902. STATIC_PTR int
1903. domenusystem()  /* WAC add helpful menus ;B */
1904. {
1905.         return (makemenu("Main Menu", main_menustruct));
1906. }
1907. 
1908. /* KMH, #conduct
1909.  * (shares enlightenment's tense handling)
1910.  */
1911. STATIC_PTR int
1912. doconduct()
1913. {
1914. 	show_conduct(0);
1915. 	return 0;
1916. }
1917. 
1918. /* format increased damage or chance to hit */
1919. static char *
1920. enlght_combatinc(inctyp, incamt, final, outbuf)
1921. const char *inctyp;
1922. int incamt, final;
1923. char *outbuf;
1924. {
1925. 	char numbuf[24];
1926. 	const char *modif, *bonus;
1927. 
1928. 	if (final
1929. #ifdef WIZARD
1930. 		|| wizard
1931. #endif
1932. 	  ) {
1933. 	    Sprintf(numbuf, "%s%d",
1934. 		    (incamt > 0) ? "+" : "", incamt);
1935. 	    modif = (const char *) numbuf;
1936. 	} else {
1937. 	    int absamt = abs(incamt);
1938. 
1939. 	    if (absamt <= 3) modif = "small";
1940. 	    else if (absamt <= 6) modif = "moderate";
1941. 	    else if (absamt <= 12) modif = "large";
1942. 	    else modif = "huge";
1943. 	}
1944. 	bonus = (incamt > 0) ? "bonus" : "penalty";
1945. 	/* "bonus to hit" vs "damage bonus" */
1946. 	if (!strcmp(inctyp, "damage")) {
1947. 	    const char *ctmp = inctyp;
1948. 	    inctyp = bonus;
1949. 	    bonus = ctmp;
1950. 	}
1951. 	Sprintf(outbuf, "%s %s %s", an(modif), bonus, inctyp);
1952. 	return outbuf;
1953. }
1954. 
1955. void
1956. show_conduct(final)
1957. int final;
1958. {
1959. 	char buf[BUFSZ];
1960. 	int ngenocided;
1961. 
1962. 	/* Create the conduct window */
1963. 	en_win = create_nhwindow(NHW_MENU);
1964. 	putstr(en_win, 0, "Voluntary challenges:");
1965. 	putstr(en_win, 0, "");
1966. 
1967. 	if (!u.uconduct.food && !u.uconduct.unvegan)
1968. 	    enl_msg(You_, "have gone", "went", " without food");
1969. 	    /* But beverages are okay */
1970. 	else if (!u.uconduct.food)
1971. 	    enl_msg(You_, "have gone", "went", " without eating");
1972. 	    /* But quaffing animal products (eg., blood) is okay */
1973. 	else if (!u.uconduct.unvegan)
1974. 	    you_have_X("followed a strict vegan diet");
1975. 	else if (!u.uconduct.unvegetarian)
1976. 	    you_have_been("vegetarian");
1977. 
1978. 	if (!u.uconduct.gnostic)
1979. 	    you_have_been("an atheist");
1980. 
1981. 	if (!u.uconduct.weaphit)
1982. 	    you_have_never("hit with a wielded weapon");
1983. #ifdef WIZARD
1984. 	else if (wizard) {
1985. 	    Sprintf(buf, "used a wielded weapon %ld time%s",
1986. 		    u.uconduct.weaphit, plur(u.uconduct.weaphit));
1987. 	    you_have_X(buf);
1988. 	}
1989. #endif
1990. 	if (!u.uconduct.killer)
1991. 	    you_have_been("a pacifist");
1992. 
1993. 	if (!u.uconduct.literate)
1994. 	    you_have_been("illiterate");
1995. #ifdef WIZARD
1996. 	else if (wizard) {
1997. 	    Sprintf(buf, "read items or engraved %ld time%s",
1998. 		    u.uconduct.literate, plur(u.uconduct.literate));
1999. 	    you_have_X(buf);
2000. 	}
2001. #endif
2002. 
2003. 	ngenocided = num_genocides();
2004. 	if (ngenocided == 0) {
2005. 	    you_have_never("genocided any monsters");
2006. 	} else {
2007. 	    Sprintf(buf, "genocided %d type%s of monster%s",
2008. 		    ngenocided, plur(ngenocided), plur(ngenocided));
2009. 	    you_have_X(buf);
2010. 	}
2011. 
2012. 	if (!u.uconduct.polypiles)
2013. 	    you_have_never("polymorphed an object");
2014. #ifdef WIZARD
2015. 	else if (wizard) {
2016. 	    Sprintf(buf, "polymorphed %ld item%s",
2017. 		    u.uconduct.polypiles, plur(u.uconduct.polypiles));
2018. 	    you_have_X(buf);
2019. 	}
2020. #endif
2021. 
2022. 	if (!u.uconduct.polyselfs)
2023. 	    you_have_never("changed form");
2024. #ifdef WIZARD
2025. 	else if (wizard) {
2026. 	    Sprintf(buf, "changed form %ld time%s",
2027. 		    u.uconduct.polyselfs, plur(u.uconduct.polyselfs));
2028. 	    you_have_X(buf);
2029. 	}
2030. #endif
2031. 
2032. 	if (!u.uconduct.wishes)
2033. 	    you_have_X("used no wishes");
2034. 	else {
2035. 	    Sprintf(buf, "used %ld wish%s",
2036. 		    u.uconduct.wishes, (u.uconduct.wishes > 1L) ? "es" : "");
2037. 	    you_have_X(buf);
2038. 
2039. 	    if (!u.uconduct.wisharti)
2040. 		enl_msg(You_, "have not wished", "did not wish",
2041. 			" for any artifacts");
2042. 	}
2043. 
2044. 
2045. 	if (!u.uconduct.celibacy)
2046. 		you_have_X("remained celibate");
2047. #ifdef WIZARD
2048. 	else if (wizard) {
2049. 		Sprintf(buf, "broken your vow of celibacy %ld time%s.",
2050. 			u.uconduct.celibacy, u.uconduct.celibacy > 1 ? "s" : "");
2051. 		you_have_X(buf);
2052. 	}
2053. #endif
2054. 
2055. 	/* Pop up the window and wait for a key */
2056. 	display_nhwindow(en_win, TRUE);
2057. 	destroy_nhwindow(en_win);
2058. }
2059. 
2060. #endif /* OVLB */
2061. #ifdef OVL1
2062. 
2063. #ifndef M
2064. # ifndef NHSTDC
2065. #  define M(c)		(0x80 | (c))
2066. # else
2067. #  define M(c)		((c) - 128)
2068. # endif /* NHSTDC */
2069. #endif
2070. #ifndef C
2071. #define C(c)		(0x1f & (c))
2072. #endif
2073. 
2074. static const struct func_tab cmdlist[] = {
2075. 	{C('d'), FALSE, dokick}, /* "D" is for door!...?  Msg is in dokick.c */
2076. #ifdef WIZARD
2077. 	{C('b'), FALSE, playersteal},
2078. /* BEGIN TSANTH'S CODE */
2079. 	{C('c'), TRUE, wiz_gain_ac},
2080. /* END TSANTH'S CODE */
2081. 	{C('e'), TRUE, wiz_detect},
2082. 	{C('f'), TRUE, wiz_map},
2083. 	{C('g'), TRUE, wiz_genesis},
2084. 	{C('i'), TRUE, wiz_identify},
2085. 	{C('j'), TRUE, wiz_gain_level},
2086. #endif
2087. 	{C('l'), TRUE, doredraw}, /* if number_pad is set */
2088. #ifdef WIZARD
2089. /* BEGIN TSANTH'S CODE */
2090. 	{C('n'), TRUE, wiz_toggle_invulnerability},
2091. /* END TSANTH'S CODE */
2092. 	{C('o'), TRUE, wiz_where},
2093. #endif
2094. 	{C('p'), TRUE, doprev_message},
2095. 	{C('q'), TRUE, done2},
2096. 	{C('r'), TRUE, doredraw},
2097. /*	{C('s'), FALSE, specialpower},*/
2098. 	{C('s'), TRUE, dosave},
2099. 	{C('t'), TRUE, dotele},
2100. #ifdef WIZARD
2101. 	{C('v'), TRUE, wiz_level_tele},
2102. 	{C('w'), TRUE, wiz_wish},
2103. #endif
2104. 	{C('x'), TRUE, doattributes},
2105. 	{C('y'), TRUE, polyatwill},
2106. #ifdef SUSPEND
2107. 	{C('z'), TRUE, dosuspend},
2108. #endif
2109. 	{'a', FALSE, doapply},
2110. 	{'A', FALSE, doddoremarm},
2111. 	{M('a'), TRUE, doorganize},
2112. /*	'b', 'B' : go sw */
2113. #ifdef BORG
2114. 	{'B', TRUE, doborgtoggle}, /* [Tom] */
2115. #endif
2116. 	{M('b'), FALSE, playersteal},   /* jla */
2117. #if 0
2118. 	{M('b'), FALSE, specialpower},   /* jla */
2119. #endif
2120. 	{'c', FALSE, doclose},
2121. 	{'C', TRUE, do_mname},
2122. 	{M('c'), TRUE, dotalk},
2123. 	{'d', FALSE, dodrop},
2124. 	{'D', FALSE, doddrop},
2125. 	{M('d'), FALSE, dodip},
2126. 	{'e', FALSE, doeat},
2127. 	{'E', FALSE, doengrave},
2128. 	{M('e'), TRUE, enhance_weapon_skill},
2129. 	{'f', FALSE, dofire},
2130. /*	'F' : fight (one time) */
2131. 	{M('f'), FALSE, doforce},
2132. /*	'g', 'G' : multiple go */
2133. /*	'h', 'H' : go west */
2134. 	{'h', TRUE, dohelp}, /* if number_pad is set */
2135. 	{'i', TRUE, ddoinv},
2136. 	{'I', TRUE, dotypeinv},		/* Robert Viduya */
2137. 	{M('i'), TRUE, doinvoke},
2138. /*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
2139. 	{'j', FALSE, dojump}, /* if number_pad is on */
2140. 	{M('j'), FALSE, dojump},
2141. 	{'k', FALSE, dokick}, /* if number_pad is on */
2142. 	{'K', TRUE, dolistvanq}, /* if number_pad is on */
2143. 	{M('k'), TRUE, enhance_weapon_skill},
2144. 	{'l', FALSE, doloot}, /* if number_pad is on */
2145. 	{M('l'), FALSE, doloot},
2146. /*	'n' prefixes a count if number_pad is on */
2147. 	{M('m'), TRUE, domonability},
2148. 	{'N', TRUE, ddocall}, /* if number_pad is on */
2149. 	{M('n'), TRUE, ddocall},
2150. 	{'o', FALSE, doopen},
2151. 	{'O', TRUE, doset},
2152. 	{M('o'), FALSE, dosacrifice},
2153. 	{'p', FALSE, dopay},
2154. /*WAC replace with dowear*/
2155. 	{'P', FALSE, doputon},
2156. 	{M('p'), TRUE, dopray},
2157. 	{'q', FALSE, dodrink},
2158. 	{'Q', FALSE, dowieldquiver},
2159. 	{M('q'), TRUE, done2},
2160. 	{'r', FALSE, doread},
2161. 	{'R', FALSE, doremring},
2162. 	{M('r'), FALSE, dorub},
2163. 	{'s', TRUE, dosearch, "searching"},
2164. 	{'S', TRUE, dosave},
2165. 	{M('s'), FALSE, dosit},
2166. 	{'t', FALSE, dothrow},
2167. 	{'T', FALSE, dotakeoff},
2168. /*	{M('t'), TRUE, doturn},*/
2169. 	{M('t'), TRUE, dotech},
2170. /*	'u', 'U' : go ne */
2171. 	{'u', FALSE, dountrap}, /* if number_pad is on */
2172. 	{M('u'), FALSE, dountrap},
2173. 	{'v', TRUE, doversion},
2174. 	{'V', TRUE, dohistory},
2175. 	{M('v'), TRUE, doextversion},
2176. /*replaced with dowear*/
2177. 	{'w', FALSE, dowield},
2178. 	{'W', FALSE, dowear},
2179. 	{M('w'), FALSE, dowipe},
2180. 	{'x', FALSE, doswapweapon},                    /* [Tom] */        
2181. 	{'X', TRUE, enter_explore_mode},
2182. #if 0
2183.         {M('x'), TRUE, dovspell},                  /* Mike Stephenson */
2184. #endif
2185. /*	'y', 'Y' : go nw */
2186. 	{M('y'), FALSE, polyatwill},  /* jla */        
2187. 	{'z', FALSE, dozap},
2188. 	{'Z', TRUE, docast},
2189. 	{'<', FALSE, doup},
2190. 	{'>', FALSE, dodown},
2191. 	{'/', TRUE, dowhatis},
2192. 	{'&', TRUE, dowhatdoes},
2193. 	{'?', TRUE, dohelp},
2194. 	{M('?'), TRUE, doextlist},
2195. #ifdef SHELL
2196. 	{'!', TRUE, dosh},
2197. #endif
2198. 	{'.', TRUE, donull, "waiting"},
2199. 	{' ', TRUE, donull, "waiting"},
2200. 	{',', FALSE, dopickup},
2201. 	{':', TRUE, dolook},
2202. 	{';', TRUE, doquickwhatis},
2203. 	{'^', TRUE, doidtrap},
2204. 	{'\\', TRUE, dodiscovered},		/* Robert Viduya */
2205. 	{'@', TRUE, dotogglepickup},
2206. 	{M('2'), FALSE, dotwoweapon},
2207. /* WAC Angband style items in use, menusystem
2208. 	{'*', TRUE, doinvinuse}, */
2209. 	{'`', TRUE, domenusystem},
2210. 	{'~', TRUE, domenusystem},
2211. 	{WEAPON_SYM,  TRUE, doprwep},
2212. 	{ARMOR_SYM,  TRUE, doprarm},
2213. 	{RING_SYM,  TRUE, doprring},
2214. 	{AMULET_SYM, TRUE, dopramulet},
2215. 	{TOOL_SYM, TRUE, doprtool},
2216. 	{'*', TRUE, doprinuse},	/* inventory of all equipment in use */
2217. 	{GOLD_SYM, TRUE, doprgold},
2218. 	{SPBOOK_SYM, TRUE, dovspell},			/* Mike Stephenson */
2219. 	{'#', TRUE, doextcmd},
2220. 	{'_', TRUE, dotravel},
2221. 	{0,0,0,0}
2222. };
2223. 
2224. struct ext_func_tab extcmdlist[] = {
2225. 	{"2weapon", "toggle two-weapon combat", dotwoweapon, FALSE},
2226. 	{"adjust", "adjust inventory letters", doorganize, TRUE},
2227. 	{"borrow", "steal from monsters", playersteal, FALSE},  /* jla */        
2228. 	{"chat", "talk to someone", dotalk, TRUE},	/* converse? */
2229. 	{"conduct", "list which challenges you have adhered to", doconduct, TRUE},
2230. 	{"dip", "dip an object into something", dodip, FALSE},
2231. 	{"enhance", "advance or check weapons skills", enhance_weapon_skill,
2232. 							TRUE},
2233. #if 0
2234. 	{"ethics", "list which challenges you have adhered to", doethics, TRUE},
2235. #endif
2236. 	{"explore", "enter explore mode", enter_explore_mode, TRUE},
2237. 	{"force", "force a lock", doforce, FALSE},
2238. 	{"invoke", "invoke an object's powers", doinvoke, TRUE},
2239. 	{"jump", "jump to a location", dojump, FALSE},
2240. 	{"loot", "loot a box on the floor", doloot, FALSE},
2241. 	{"monster", "use a monster's special ability", domonability, TRUE},
2242. 	{"name", "name an item or type of object", ddocall, TRUE},
2243. 	{"offer", "offer a sacrifice to the gods", dosacrifice, FALSE},
2244. 	{"pray", "pray to the gods for help", dopray, TRUE},
2245. 	{"quit", "exit without saving current game", done2, TRUE},
2246. #ifdef STEED
2247. 	{"ride", "ride (or stop riding) a monster", doride, FALSE},
2248. #endif
2249. 	{"rub", "rub a lamp or a stone", dorub, FALSE},
2250. 	{"sit", "sit down", dosit, FALSE},
2251. #ifdef SHOUT
2252. 	{"shout", "say something loud", doyell, TRUE}, /* jrn */
2253. #endif
2254. 	{"technique", "perform a technique", dotech, TRUE},
2255. 	{"turn", "turn undead", doturn, TRUE},
2256. 	{"twoweapon", "toggle two-weapon combat", dotwoweapon, FALSE},
2257. 	{"untrap", "untrap something", dountrap, FALSE},
2258. 	{"vanquished", "list vanquished monsters", dolistvanq, TRUE},
2259. 	{"version", "list compile time options for this version of Slash'EM",
2260. 		doextversion, TRUE},
2261. 	{"wipe", "wipe off your face", dowipe, FALSE},
2262. 	{"youpoly", "polymorph at will", polyatwill, FALSE},  /* jla */        
2263. 	{"?", "get this list of extended commands", doextlist, TRUE},
2264. #if defined(WIZARD)
2265. 	/*
2266. 	 * There must be a blank entry here for every entry in the table
2267. 	 * below.
2268. 	 */
2269. #ifdef DISPLAY_LAYERS
2270. 	{(char *)0, (char *)0, donull, TRUE},
2271. #endif
2272. 	{(char *)0, (char *)0, donull, TRUE},
2273. 	{(char *)0, (char *)0, donull, TRUE},
2274. #ifdef DEBUG_MIGRATING_MONS
2275. 	{(char *)0, (char *)0, donull, TRUE},
2276. #endif
2277. 	{(char *)0, (char *)0, donull, TRUE},
2278. 	{(char *)0, (char *)0, donull, TRUE},
2279. #ifdef PORT_DEBUG
2280. 	{(char *)0, (char *)0, donull, TRUE},
2281. #endif
2282. 	{(char *)0, (char *)0, donull, TRUE},
2283. 	{(char *)0, (char *)0, donull, TRUE},
2284.         {(char *)0, (char *)0, donull, TRUE},
2285. 	{(char *)0, (char *)0, donull, TRUE},
2286. 	{(char *)0, (char *)0, donull, TRUE},
2287. #ifdef DEBUG
2288. 	{(char *)0, (char *)0, donull, TRUE},
2289. #endif
2290. 	{(char *)0, (char *)0, donull, TRUE},
2291. #endif
2292. 	{(char *)0, (char *)0, donull, TRUE}	/* sentinel */
2293. };
2294. 
2295. #if defined(WIZARD)
2296. static const struct ext_func_tab debug_extcmdlist[] = {
2297. #ifdef DISPLAY_LAYERS
2298. 	{"display", "detail display layers", wiz_show_display, TRUE},
2299. #endif
2300. 	{"levelchange", "change experience level", wiz_level_change, TRUE},
2301. 	{"lightsources", "show mobile light sources", wiz_light_sources, TRUE},
2302. #ifdef DEBUG_MIGRATING_MONS
2303. 	{"migratemons", "migrate n random monsters", wiz_migrate_mons, TRUE},
2304. #endif
2305. 	{"monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol, TRUE},
2306. 	{"panic", "test panic routine (fatal to game)", wiz_panic, TRUE},
2307. 	{"polyself", "polymorph self", wiz_polyself, TRUE},
2308. #ifdef PORT_DEBUG
2309. 	{"portdebug", "wizard port debug command", wiz_port_debug, TRUE},
2310. #endif
2311. 	{"seenv", "show seen vectors", wiz_show_seenv, TRUE},
2312. 	{"stats", "show memory statistics", wiz_show_stats, TRUE},
2313. 	{"timeout", "look at timeout queue", wiz_timeout_queue, TRUE},
2314. 	{"vision", "show vision array", wiz_show_vision, TRUE},
2315. #ifdef DEBUG
2316. 	{"wizdebug", "wizard debug command", wiz_debug_cmd, TRUE},
2317. #endif
2318. 	{"wmode", "show wall modes", wiz_show_wmodes, TRUE},
2319. 	{(char *)0, (char *)0, donull, TRUE}
2320. };
2321. 
2322. /*
2323.  * Insert debug commands into the extended command list.  This function
2324.  * assumes that the last entry will be the help entry.
2325.  *
2326.  * You must add entries in ext_func_tab every time you add one to the
2327.  * debug_extcmdlist().
2328.  */
2329. void
2330. add_debug_extended_commands()
2331. {
2332. 	int i, j, k, n;
2333. 
2334. 	/* count the # of help entries */
2335. 	for (n = 0; extcmdlist[n].ef_txt[0] != '?'; n++)
2336. 	    ;
2337. 
2338. 	for (i = 0; debug_extcmdlist[i].ef_txt; i++) {
2339. 	    for (j = 0; j < n; j++)
2340. 		if (strcmp(debug_extcmdlist[i].ef_txt, extcmdlist[j].ef_txt) < 0) break;
2341. 
2342. 	    /* insert i'th debug entry into extcmdlist[j], pushing down  */
2343. 	    for (k = n; k >= j; --k)
2344. 		extcmdlist[k+1] = extcmdlist[k];
2345. 	    extcmdlist[j] = debug_extcmdlist[i];
2346. 	    n++;	/* now an extra entry */
2347. 	}
2348. }
2349. 
2350. 
2351. static const char template[] = "%-18s %4ld  %6ld";
2352. static const char count_str[] = "                   count  bytes";
2353. static const char separator[] = "------------------ -----  ------";
2354. 
2355. STATIC_OVL void
2356. count_obj(chain, total_count, total_size, top, recurse)
2357. 	struct obj *chain;
2358. 	long *total_count;
2359. 	long *total_size;
2360. 	boolean top;
2361. 	boolean recurse;
2362. {
2363. 	long count, size;
2364. 	struct obj *obj;
2365. 
2366. 	for (count = size = 0, obj = chain; obj; obj = obj->nobj) {
2367. 	    if (top) {
2368. 		count++;
2369. 		size += sizeof(struct obj) + obj->oxlth + obj->onamelth;
2370. 	    }
2371. 	    if (recurse && obj->cobj)
2372. 		count_obj(obj->cobj, total_count, total_size, TRUE, TRUE);
2373. 	}
2374. 	*total_count += count;
2375. 	*total_size += size;
2376. }
2377. 
2378. STATIC_OVL void
2379. obj_chain(win, src, chain, total_count, total_size)
2380. 	winid win;
2381. 	const char *src;
2382. 	struct obj *chain;
2383. 	long *total_count;
2384. 	long *total_size;
2385. {
2386. 	char buf[BUFSZ];
2387. 	long count = 0, size = 0;
2388. 
2389. 	count_obj(chain, &count, &size, TRUE, FALSE);
2390. 	*total_count += count;
2391. 	*total_size += size;
2392. 	Sprintf(buf, template, src, count, size);
2393. 	putstr(win, 0, buf);
2394. }
2395. 
2396. STATIC_OVL void
2397. mon_invent_chain(win, src, chain, total_count, total_size)
2398. 	winid win;
2399. 	const char *src;
2400. 	struct monst *chain;
2401. 	long *total_count;
2402. 	long *total_size;
2403. {
2404. 	char buf[BUFSZ];
2405. 	long count = 0, size = 0;
2406. 	struct monst *mon;
2407. 
2408. 	for (mon = chain; mon; mon = mon->nmon)
2409. 	    count_obj(mon->minvent, &count, &size, TRUE, FALSE);
2410. 	*total_count += count;
2411. 	*total_size += size;
2412. 	Sprintf(buf, template, src, count, size);
2413. 	putstr(win, 0, buf);
2414. }
2415. 
2416. STATIC_OVL void
2417. contained(win, src, total_count, total_size)
2418. 	winid win;
2419. 	const char *src;
2420. 	long *total_count;
2421. 	long *total_size;
2422. {
2423. 	char buf[BUFSZ];
2424. 	long count = 0, size = 0;
2425. 	struct monst *mon;
2426. 
2427. 	count_obj(invent, &count, &size, FALSE, TRUE);
2428. 	count_obj(fobj, &count, &size, FALSE, TRUE);
2429. 	count_obj(level.buriedobjlist, &count, &size, FALSE, TRUE);
2430. 	count_obj(migrating_objs, &count, &size, FALSE, TRUE);
2431. 	/* DEADMONSTER check not required in this loop since they have no inventory */
2432. 	for (mon = fmon; mon; mon = mon->nmon)
2433. 	    count_obj(mon->minvent, &count, &size, FALSE, TRUE);
2434. 	for (mon = migrating_mons; mon; mon = mon->nmon)
2435. 	    count_obj(mon->minvent, &count, &size, FALSE, TRUE);
2436. 
2437. 	*total_count += count; *total_size += size;
2438. 
2439. 	Sprintf(buf, template, src, count, size);
2440. 	putstr(win, 0, buf);
2441. }
2442. 
2443. STATIC_OVL void
2444. mon_chain(win, src, chain, total_count, total_size)
2445. 	winid win;
2446. 	const char *src;
2447. 	struct monst *chain;
2448. 	long *total_count;
2449. 	long *total_size;
2450. {
2451. 	char buf[BUFSZ];
2452. 	long count, size;
2453. 	struct monst *mon;
2454. 
2455. 	for (count = size = 0, mon = chain; mon; mon = mon->nmon) {
2456. 	    count++;
2457. 	    size += sizeof(struct monst) + mon->mxlth + mon->mnamelth;
2458. 	}
2459. 	*total_count += count;
2460. 	*total_size += size;
2461. 	Sprintf(buf, template, src, count, size);
2462. 	putstr(win, 0, buf);
2463. }
2464. 
2465. /*
2466.  * Display memory usage of all monsters and objects on the level.
2467.  */
2468. static int
2469. wiz_show_stats()
2470. {
2471. 	char buf[BUFSZ];
2472. 	winid win;
2473. 	long total_obj_size = 0, total_obj_count = 0;
2474. 	long total_mon_size = 0, total_mon_count = 0;
2475. 
2476. 	win = create_nhwindow(NHW_TEXT);
2477. 	putstr(win, 0, "Current memory statistics:");
2478. 	putstr(win, 0, "");
2479. 	Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj));
2480. 	putstr(win, 0, buf);
2481. 	putstr(win, 0, "");
2482. 	putstr(win, 0, count_str);
2483. 
2484. 	obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size);
2485. 	obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size);
2486. 	obj_chain(win, "buried", level.buriedobjlist,
2487. 				&total_obj_count, &total_obj_size);
2488. 	obj_chain(win, "migrating obj", migrating_objs,
2489. 				&total_obj_count, &total_obj_size);
2490. 	mon_invent_chain(win, "minvent", fmon,
2491. 				&total_obj_count,&total_obj_size);
2492. 	mon_invent_chain(win, "migrating minvent", migrating_mons,
2493. 				&total_obj_count, &total_obj_size);
2494. 
2495. 	contained(win, "contained",
2496. 				&total_obj_count, &total_obj_size);
2497. 
2498. 	putstr(win, 0, separator);
2499. 	Sprintf(buf, template, "Total", total_obj_count, total_obj_size);
2500. 	putstr(win, 0, buf);
2501. 
2502. 	putstr(win, 0, "");
2503. 	putstr(win, 0, "");
2504. 	Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst));
2505. 	putstr(win, 0, buf);
2506. 	putstr(win, 0, "");
2507. 
2508. 	mon_chain(win, "fmon", fmon,
2509. 				&total_mon_count, &total_mon_size);
2510. 	mon_chain(win, "migrating", migrating_mons,
2511. 				&total_mon_count, &total_mon_size);
2512. 
2513. 	putstr(win, 0, separator);
2514. 	Sprintf(buf, template, "Total", total_mon_count, total_mon_size);
2515. 	putstr(win, 0, buf);
2516. 
2517. #if defined(__BORLANDC__) && !defined(_WIN32)
2518. 	show_borlandc_stats(win);
2519. #endif
2520. 
2521. 	display_nhwindow(win, FALSE);
2522. 	destroy_nhwindow(win);
2523. 	return 0;
2524. }
2525. 
2526. void
2527. sanity_check()
2528. {
2529. 	obj_sanity_check();
2530. 	timer_sanity_check();
2531. }
2532. 
2533. #ifdef DISPLAY_LAYERS
2534. /*
2535.  * Detail contents of each display layer at specified location(s).
2536.  */
2537. static int
2538. wiz_show_display()
2539. {
2540.     int ans, glyph;
2541.     coord cc;
2542.     winid win;
2543.     char buf[BUFSZ];
2544.     struct rm *lev;
2545. 
2546.     cc.x = u.ux;
2547.     cc.y = u.uy;
2548.     pline("Pick a location.");
2549.     ans = getpos(&cc, FALSE, "a location of interest");
2550.     if (ans < 0 || cc.x < 0)
2551. 	return 0;	/* done */
2552.     lev = &levl[cc.x][cc.y];
2553.     win = create_nhwindow(NHW_MENU);
2554.     Sprintf(buf, "Contents of hero's memory at (%d, %d):", cc.x, cc.y);
2555.     putstr(win, 0, buf);
2556.     putstr(win, 0, "");
2557.     Sprintf(buf, "Invisible monster: %s",
2558. 	    lev->mem_invis ? "present" : "none");
2559.     putstr(win, 0, buf);
2560.     if (lev->mem_obj && lev->mem_corpse)
2561. 	if (mons[lev->mem_obj - 1].geno & G_UNIQ)
2562. 	    Sprintf(buf, "Object: %s%s corpse",
2563. 		    type_is_pname(&mons[lev->mem_obj - 1]) ? "" : "the ",
2564. 		    s_suffix(mons[lev->mem_obj - 1].mname));
2565. 	else
2566. 	    Sprintf(buf, "Object: %s corpse", mons[lev->mem_obj - 1].mname);
2567.     else
2568. 	Sprintf(buf, "Object: %s", lev->mem_obj ?
2569. 		obj_typename(lev->mem_obj - 1) : "none");
2570.     putstr(win, 0, buf);
2571.     Sprintf(buf, "Trap: %s", lev->mem_trap ?
2572. 	    defsyms[trap_to_defsym(lev->mem_trap)].explanation : "none");
2573.     putstr(win, 0, buf);
2574.     Sprintf(buf, "Backgroud: %s", defsyms[lev->mem_bg].explanation);
2575.     putstr(win, 0, buf);
2576.     putstr(win, 0, "");
2577.     glyph = glyph_at(cc.x, cc.y);
2578.     Sprintf(buf, "Buffered (3rd screen): ");
2579.     if (glyph_is_monster(glyph)) {
2580. 	Strcat(buf, mons[glyph_to_mon(glyph)].mname);
2581. 	if (glyph_is_pet(glyph))
2582. 	    Strcat(buf, " (tame)");
2583. 	if (glyph_is_ridden_monster(glyph))
2584. 	    Strcat(buf, " (ridden)");
2585. 	if (glyph_is_detected_monster(glyph))
2586. 	    Strcat(buf, " (detected)");
2587.     } else if (glyph_is_object(glyph)) {
2588. 	if (glyph_is_body(glyph)) {
2589. 	    int corpse = glyph_to_body(glyph);
2590. 	    if (mons[corpse].geno & G_UNIQ)
2591. 		Sprintf(eos(buf), "%s%s corpse",
2592. 			type_is_pname(&mons[corpse]) ? "" : "the ",
2593. 			s_suffix(mons[corpse].mname));
2594. 	    else
2595. 		Sprintf(eos(buf), "%s corpse", mons[corpse].mname);
2596. 	} else
2597. 	    Strcat(buf, obj_typename(glyph_to_obj(glyph)));
2598.     } else if (glyph_is_invisible(glyph))
2599. 	Strcat(buf, "invisible monster");
2600.     else if (glyph_is_cmap(glyph))
2601. 	Strcat(buf, defsyms[glyph_to_cmap(glyph)].explanation);
2602.     else
2603. 	Sprintf(eos(buf), "[%d]", glyph);
2604.     putstr(win, 0, buf);
2605.     display_nhwindow(win, FALSE);
2606.     destroy_nhwindow(win);
2607.     return 0;
2608. }
2609. #endif
2610. 
2611. #ifdef DEBUG_MIGRATING_MONS
2612. static int
2613. wiz_migrate_mons()
2614. {
2615. 	int mcount = 0;
2616. 	char inbuf[BUFSZ];
2617. 	struct permonst *ptr;
2618. 	struct monst *mtmp;
2619. 	d_level tolevel;
2620. 	getlin("How many random monsters to migrate? [0]", inbuf);
2621. 	if (*inbuf == '\033') return 0;
2622. 	mcount = atoi(inbuf);
2623. 	if (mcount < 0 || mcount > (COLNO * ROWNO) || Is_botlevel(&u.uz))
2624. 		return 0;
2625. 	while (mcount > 0) {
2626. 		if (Is_stronghold(&u.uz))
2627. 		    assign_level(&tolevel, &valley_level);
2628. 		else
2629. 		    get_level(&tolevel, depth(&u.uz) + 1);
2630. 		ptr = rndmonst();
2631. 		mtmp = makemon(ptr, 0, 0, NO_MM_FLAGS);
2632. 		if (mtmp) migrate_to_level(mtmp, ledger_no(&tolevel),
2633. 				MIGR_RANDOM, (coord *)0);
2634. 		mcount--;
2635. 	}
2636. 	return 0;
2637. }
2638. #endif
2639. 
2640. #endif /* WIZARD */
2641. 
2642. #define unctrl(c)	((c) <= C('z') ? (0x60 | (c)) : (c))
2643. #define unmeta(c)	(0x7f & (c))
2644. 
2645. 
2646. void
2647. rhack(cmd)
2648. register char *cmd;
2649. {
2650. 	boolean do_walk, do_rush, prefix_seen, bad_command,
2651. 		firsttime = (cmd == 0);
2652. 
2653. 	iflags.menu_requested = FALSE;
2654. 	if (firsttime) {
2655. 		flags.nopick = 0;
2656. 		cmd = parse();
2657. 	}
2658. 	if (*cmd == '\033') { /* <esc> key - user might be panicking */
2659. 		/* Bring up the menu */
2660. 		if (multi || !flags.menu_on_esc || !(domenusystem())) {
2661. 		flags.move = FALSE;
2662. 		    multi = 0;
2663. 		}
2664. 		return;
2665. #if 0
2666. 		flags.move = FALSE;
2667. 		return;
2668. #endif
2669. 	}
2670. #ifdef REDO
2671. 	if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
2672. 		in_doagain = TRUE;
2673. 		stail = 0;
2674. 		rhack((char *)0);	/* read and execute command */
2675. 		in_doagain = FALSE;
2676. 		return;
2677. 	}
2678. 	/* Special case of *cmd == ' ' handled better below */
2679. 	if(!*cmd || *cmd == (char)0377)
2680. #else
2681. 	if(!*cmd || *cmd == (char)0377 || (!flags.rest_on_space && *cmd == ' '))
2682. #endif
2683. 	{
2684. 		nhbell();
2685. 		flags.move = FALSE;
2686. 		return;		/* probably we just had an interrupt */
2687. 	}
2688. 	if (iflags.num_pad && iflags.num_pad_mode == 1) {
2689. 		/* This handles very old inconsistent DOS/Windows behaviour
2690. 		 * in a new way: earlier, the keyboard handler mapped these,
2691. 		 * which caused counts to be strange when entered from the
2692. 		 * number pad. Now do not map them until here. 
2693. 		 */
2694. 		switch (*cmd) {
2695. 		    case '5':       *cmd = 'g'; break;
2696. 		    case M('5'):    *cmd = 'G'; break;
2697. 		    case M('0'):    *cmd = 'I'; break;
2698.         	}
2699.         }
2700. 	/* handle most movement commands */
2701. 	do_walk = do_rush = prefix_seen = FALSE;
2702. 	flags.travel = iflags.travel1 = 0;
2703. 	switch (*cmd) {
2704. 	 case 'g':  if (movecmd(cmd[1])) {
2705. 			flags.run = 2;
2706. 			do_rush = TRUE;
2707. 		    } else
2708. 			prefix_seen = TRUE;
2709. 		    break;
2710. 	 case '5':  if (!iflags.num_pad) break;	/* else FALLTHRU */
2711. 	 case 'G':  if (movecmd(lowc(cmd[1]))) {
2712. 			flags.run = 3;
2713. 			do_rush = TRUE;
2714. 		    } else
2715. 			prefix_seen = TRUE;
2716. 		    break;
2717. 	 case '-':  if (!iflags.num_pad) break;	/* else FALLTHRU */
2718. 	/* Effects of movement commands and invisible monsters:
2719. 	 * m: always move onto space (even if 'I' remembered)
2720. 	 * F: always attack space (even if 'I' not remembered)
2721. 	 * normal movement: attack if 'I', move otherwise
2722. 	 */
2723. 	 case 'F':  if (movecmd(cmd[1])) {
2724. 			flags.forcefight = 1;
2725. 			do_walk = TRUE;
2726. 		    } else
2727. 			prefix_seen = TRUE;
2728. 		    break;
2729. 	 case 'm':  if (movecmd(cmd[1]) || u.dz) {
2730. 			flags.run = 0;
2731. 			flags.nopick = 1;
2732. 			if (!u.dz) do_walk = TRUE;
2733. 			else cmd[0] = cmd[1];	/* "m<" or "m>" */
2734. 		    } else
2735. 			prefix_seen = TRUE;
2736. 		    break;
2737. 	 case 'M':  if (movecmd(lowc(cmd[1]))) {
2738. 			flags.run = 1;
2739. 			flags.nopick = 1;
2740. 			do_rush = TRUE;
2741. 		    } else
2742. 			prefix_seen = TRUE;
2743. 		    break;
2744. 	 case '0':  if (!iflags.num_pad) break;
2745. 		    (void)ddoinv(); /* a convenience borrowed from the PC */
2746. 		    flags.move = FALSE;
2747. 		    multi = 0;
2748. 		    return;
2749. 	 case CMD_TRAVEL:
2750. 		    if (iflags.travelcmd) {
2751. 			    flags.travel = 1;
2752. 			    iflags.travel1 = 1;
2753. 			    flags.run = 8;
2754. 			    flags.nopick = 1;
2755. 			    do_rush = TRUE;
2756. 			    break;
2757. 		    }
2758. 		    /*FALLTHRU*/
2759. 	 default:   if (movecmd(*cmd)) {	/* ordinary movement */
2760. 			flags.run = 0;	/* only matters here if it was 8 */
2761. 			do_walk = TRUE;
2762. 		    } else if (movecmd(iflags.num_pad ?
2763. 				       unmeta(*cmd) : lowc(*cmd))) {
2764. 			flags.run = 1;
2765. 			do_rush = TRUE;
2766. 		    } else if (movecmd(unctrl(*cmd))) {
2767. 			flags.run = 3;
2768. 			do_rush = TRUE;
2769. 		    }
2770. 		    break;
2771. 	}
2772. 
2773. 	/* some special prefix handling */
2774. 	/* overload 'm' prefix for ',' to mean "request a menu" */
2775. 	if (prefix_seen && cmd[1] == ',') {
2776. 		iflags.menu_requested = TRUE;
2777. 		++cmd;
2778. 	}
2779. 
2780. 	if (do_walk) {
2781. 	    if (multi) flags.mv = TRUE;
2782. 	    domove();
2783. 	    flags.forcefight = 0;
2784. 	    return;
2785. 	} else if (do_rush) {
2786. 	    if (firsttime) {
2787. 		if (!multi) multi = max(COLNO,ROWNO);
2788. 		u.last_str_turn = 0;
2789. 	    }
2790. 	    flags.mv = TRUE;
2791. 	    domove();
2792. 	    return;
2793. 	} else if (prefix_seen && cmd[1] == '\033') {	/* <prefix><escape> */
2794. 	    /* don't report "unknown command" for change of heart... */
2795. 	    bad_command = FALSE;
2796. 	} else if (*cmd == ' ' && !flags.rest_on_space) {
2797. 	    bad_command = TRUE;		/* skip cmdlist[] loop */
2798. 	/* handle all other commands */
2799. 	} else {
2800. 	    register const struct func_tab *tlist;
2801. 	    int res, NDECL((*func));
2802. 	    for (tlist = cmdlist; tlist->f_char; tlist++) {
2803. 		if ((*cmd & 0xff) != (tlist->f_char & 0xff)) continue;
2804. 
2805. 		if (u.uburied && !tlist->can_if_buried) {
2806. 		    You_cant("do that while you are buried!");
2807. 		    res = 0;
2808. 		} else {
2809. 		    /* we discard 'const' because some compilers seem to have
2810. 		       trouble with the pointer passed to set_occupation() */
2811. 		    func = ((struct func_tab *)tlist)->f_funct;
2812. 		    if (tlist->f_text && !occupation && multi)
2813. 			set_occupation(func, tlist->f_text, multi);
2814. 		    res = (*func)();		/* perform the command */
2815. 		}
2816. 		if (!res) {
2817. 		    flags.move = FALSE;
2818. 		    multi = 0;
2819. 		}
2820. 		return;
2821. 	    }
2822. 	    /* if we reach here, cmd wasn't found in cmdlist[] */
2823. 	    bad_command = TRUE;
2824. 	}
2825. 	if (bad_command) {
2826. 	    char expcmd[10];
2827. 	    register char *cp = expcmd;
2828. 
2829. 	    while (*cmd && (int)(cp - expcmd) < (int)(sizeof expcmd - 3)) {
2830. 		if (*cmd >= 040 && *cmd < 0177) {
2831. 		    *cp++ = *cmd++;
2832. 		} else if (*cmd & 0200) {
2833. 		    *cp++ = 'M';
2834. 		    *cp++ = '-';
2835. 		    *cp++ = *cmd++ &= ~0200;
2836. 		} else {
2837. 		    *cp++ = '^';
2838. 		    *cp++ = *cmd++ ^ 0100;
2839. 		}
2840. 	    }
2841. 	    *cp = '\0';
2842. 	    if (!prefix_seen || !iflags.cmdassist ||
2843. 		!help_dir(0, "Invalid direction key!"))
2844. 	    Norep("Unknown command '%s'.", expcmd);
2845. 	}
2846. 	/* didn't move */
2847. 	flags.move = FALSE;
2848. 	multi = 0;
2849. 	return;
2850. }
2851. 
2852. int
2853. xytod(x, y)	/* convert an x,y pair into a direction code */
2854. schar x, y;
2855. {
2856. 	register int dd;
2857. 
2858. 	for(dd = 0; dd < 8; dd++)
2859. 	    if(x == xdir[dd] && y == ydir[dd]) return dd;
2860. 
2861. 	return -1;
2862. }
2863. 
2864. void
2865. dtoxy(cc,dd)	/* convert a direction code into an x,y pair */
2866. coord *cc;
2867. register int dd;
2868. {
2869. 	cc->x = xdir[dd];
2870. 	cc->y = ydir[dd];
2871. 	return;
2872. }
2873. 
2874. int
2875. movecmd(sym)	/* also sets u.dz, but returns false for <> */
2876. char sym;
2877. {
2878. 	register const char *dp;
2879. 	register const char *sdp;
2880. 	if(iflags.num_pad) sdp = ndir; else sdp = sdir;	/* DICE workaround */
2881. 
2882. 	u.dz = 0;
2883. 	if(!(dp = index(sdp, sym))) return 0;
2884. 	u.dx = xdir[dp-sdp];
2885. 	u.dy = ydir[dp-sdp];
2886. 	u.dz = zdir[dp-sdp];
2887. 	if (u.dx && u.dy && u.umonnum == PM_GRID_BUG) {
2888. 		u.dx = u.dy = 0;
2889. 		return 0;
2890. 	}
2891. 	return !u.dz;
2892. }
2893. 
2894. /*
2895.  * uses getdir() but unlike getdir() it specifically
2896.  * produces coordinates using the direction from getdir()
2897.  * and verifies that those coordinates are ok.
2898.  *
2899.  * If the call to getdir() returns 0, Never_mind is displayed.
2900.  * If the resulting coordinates are not okay, emsg is displayed.
2901.  *
2902.  * Returns non-zero if coordinates in cc are valid.
2903.  */
2904. int get_adjacent_loc(prompt,emsg,x,y,cc)
2905. const char *prompt, *emsg;
2906. xchar x,y;
2907. coord *cc;
2908. {
2909. 	xchar new_x, new_y;
2910. 	if (!getdir(prompt)) {
2911. 		pline(Never_mind);
2912. 		return 0;
2913. 	}
2914. 	new_x = x + u.dx;
2915. 	new_y = y + u.dy;
2916. 	if (cc && isok(new_x,new_y)) {
2917. 		cc->x = new_x;
2918. 		cc->y = new_y;
2919. 	} else {
2920. 		if (emsg) pline(emsg);
2921. 		return 0;
2922. 	}
2923. 	return 1;
2924. }
2925. 
2926. int
2927. getdir(s)
2928. const char *s;
2929. {
2930. 	char dirsym;
2931. 	/* WAC add dirsymbols to generic prompt */
2932. 	char buf[BUFSZ];
2933.         
2934. 	Sprintf(buf, "In what direction? [%s]",
2935.                 (iflags.num_pad ? ndir : sdir));
2936. 
2937. 
2938. #ifdef REDO
2939. 	if(in_doagain || *readchar_queue)
2940. 	    dirsym = readchar();
2941. 	else
2942. #endif
2943. 	do {
2944. 	    dirsym = yn_function ((s && *s != '^') ? s : buf, (char *)0, '\0');
2945. 	} while (!movecmd(dirsym) && !index(quitchars, dirsym)
2946.                 && dirsym == '.' && dirsym == 's' && !u.dz);
2947. 
2948. #ifdef REDO
2949. 	savech(dirsym);
2950. #endif
2951. 	if(dirsym == '.' || dirsym == 's')
2952. 		u.dx = u.dy = u.dz = 0;
2953. 	else if(!movecmd(dirsym) && !u.dz) {
2954. 		boolean did_help = FALSE;
2955. 		if(!index(quitchars, dirsym)) {
2956. 		    if (iflags.cmdassist) {
2957. 			did_help = help_dir((s && *s == '^') ? dirsym : 0,
2958. 					    "Invalid direction key!");
2959. 		    }
2960. 		    if (!did_help) pline("What a strange direction!");
2961. 		}
2962. 		return 0;
2963. 	}
2964. 	if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir();
2965. 	return 1;
2966. }
2967. 
2968. STATIC_OVL boolean
2969. help_dir(sym, msg)
2970. char sym;
2971. const char *msg;
2972. {
2973. 	char ctrl;
2974. 	winid win;
2975. 	static const char wiz_only_list[] = "EFGIOVW";
2976. 	char buf[BUFSZ], buf2[BUFSZ], *expln;
2977. 
2978. 	win = create_nhwindow(NHW_TEXT);
2979. 	if (!win) return FALSE;
2980. 	if (msg) {
2981. 		Sprintf(buf, "cmdassist: %s", msg);
2982. 		putstr(win, 0, buf);
2983. 		putstr(win, 0, "");
2984. 	}
2985. 	if (letter(sym)) { 
2986. 	    sym = highc(sym);
2987. 	    ctrl = (sym - 'A') + 1;
2988. 	    if ((expln = dowhatdoes_core(ctrl, buf2))
2989. 		&& (!index(wiz_only_list, sym)
2990. #ifdef WIZARD
2991. 		    || wizard
2992. #endif
2993. 	                     )) {
2994. 		Sprintf(buf, "Are you trying to use ^%c%s?", sym,
2995. 			index(wiz_only_list, sym) ? "" :
2996. 			" as specified in the Guidebook");
2997. 		putstr(win, 0, buf);
2998. 		putstr(win, 0, "");
2999. 		putstr(win, 0, expln);
3000. 		putstr(win, 0, "");
3001. 		putstr(win, 0, "To use that command, you press");
3002. 		Sprintf(buf,
3003. 			"the <Ctrl> key, and the <%c> key at the same time.", sym);
3004. 		putstr(win, 0, buf);
3005. 		putstr(win, 0, "");
3006. 	    }
3007. 	}
3008. 	if (iflags.num_pad && u.umonnum == PM_GRID_BUG) {
3009. 	    putstr(win, 0, "Valid direction keys in your current form (with number_pad on) are:");
3010. 	    putstr(win, 0, "             8   ");
3011. 	    putstr(win, 0, "             |   ");
3012. 	    putstr(win, 0, "          4- . -6");
3013. 	    putstr(win, 0, "             |   ");
3014. 	    putstr(win, 0, "             2   ");
3015. 	} else if (u.umonnum == PM_GRID_BUG) {
3016. 	    putstr(win, 0, "Valid direction keys in your current form are:");
3017. 	    putstr(win, 0, "             k   ");
3018. 	    putstr(win, 0, "             |   ");
3019. 	    putstr(win, 0, "          h- . -l");
3020. 	    putstr(win, 0, "             |   ");
3021. 	    putstr(win, 0, "             j   ");
3022. 	} else if (iflags.num_pad) {
3023. 	    putstr(win, 0, "Valid direction keys (with number_pad on) are:");
3024. 	    putstr(win, 0, "          7  8  9");
3025. 	    putstr(win, 0, "           \\ | / ");
3026. 	    putstr(win, 0, "          4- . -6");
3027. 	    putstr(win, 0, "           / | \\ ");
3028. 	    putstr(win, 0, "          1  2  3");
3029. 	} else {
3030. 	    putstr(win, 0, "Valid direction keys are:");
3031. 	    putstr(win, 0, "          y  k  u");
3032. 	    putstr(win, 0, "           \\ | / ");
3033. 	    putstr(win, 0, "          h- . -l");
3034. 	    putstr(win, 0, "           / | \\ ");
3035. 	    putstr(win, 0, "          b  j  n");
3036. 	};
3037. 	putstr(win, 0, "");
3038. 	putstr(win, 0, "          <  up");
3039. 	putstr(win, 0, "          >  down");
3040. 	putstr(win, 0, "          .  direct at yourself");
3041. 	putstr(win, 0, "");
3042. 	putstr(win, 0, "(Suppress this message with !cmdassist in config file.)");
3043. 	display_nhwindow(win, FALSE);
3044. 	destroy_nhwindow(win);
3045. 	return TRUE;
3046. }
3047. 
3048. #endif /* OVL1 */
3049. #ifdef OVLB
3050. 
3051. void
3052. confdir()
3053. {
3054. 	register int x = (u.umonnum == PM_GRID_BUG) ? 2*rn2(4) : rn2(8);
3055. 	u.dx = xdir[x];
3056. 	u.dy = ydir[x];
3057. 	return;
3058. }
3059. 
3060. #endif /* OVLB */
3061. #ifdef OVL0
3062. 
3063. int
3064. isok(x,y)
3065. register int x, y;
3066. {
3067. 	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
3068. 	return x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1;
3069. }
3070. 
3071. static NEARDATA int last_multi;
3072. 
3073. /*
3074.  * convert a MAP window position into a movecmd
3075.  */
3076. const char *
3077. click_to_cmd(x, y, mod)
3078.     int x, y, mod;
3079. {
3080.     int dir;
3081.     static char cmd[4];
3082.     cmd[1]=0;
3083. 
3084.     x -= u.ux;
3085.     y -= u.uy;
3086. 
3087.     if (iflags.travelcmd) {
3088.         if (abs(x) <= 1 && abs(y) <= 1 ) {
3089. 	x = sgn(x), y = sgn(y);
3090.     } else {
3091. 	u.tx = u.ux+x;
3092. 	u.ty = u.uy+y;
3093. 	cmd[0] = CMD_TRAVEL;
3094. 	return cmd;
3095.     }
3096. 
3097.     if(x == 0 && y == 0) {
3098. 	/* here */
3099. 	if(IS_FOUNTAIN(levl[u.ux][u.uy].typ) || IS_SINK(levl[u.ux][u.uy].typ)) {
3100. 	    cmd[0]=mod == CLICK_1 ? 'q' : M('d');
3101. 	    return cmd;
3102. 	} else if(IS_THRONE(levl[u.ux][u.uy].typ)) {
3103. 	    cmd[0]=M('s');
3104. 	    return cmd;
3105. 	} else if((u.ux == xupstair && u.uy == yupstair)
3106. 		  || (u.ux == sstairs.sx && u.uy == sstairs.sy && sstairs.up)
3107. 		  || (u.ux == xupladder && u.uy == yupladder)) {
3108. 	    return "<";
3109. 	} else if((u.ux == xdnstair && u.uy == ydnstair)
3110. 		  || (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)
3111. 		  || (u.ux == xdnladder && u.uy == ydnladder)) {
3112. 	    return ">";
3113. 	} else if(OBJ_AT(u.ux, u.uy)) {
3114. 	    cmd[0] = Is_container(level.objects[u.ux][u.uy]) ? M('l') : ',';
3115. 	    return cmd;
3116. 	} else {
3117. 	    return "."; /* just rest */
3118. 	}
3119.     }
3120. 
3121.     /* directional commands */
3122. 
3123.     dir = xytod(x, y);
3124. 
3125. 	if (!m_at(u.ux+x, u.uy+y) && !test_move(u.ux, u.uy, x, y, TEST_MOVE)) {
3126. 	cmd[1] = (iflags.num_pad ? ndir[dir] : sdir[dir]);
3127. 	cmd[2] = 0;
3128. 	if (IS_DOOR(levl[u.ux+x][u.uy+y].typ)) {
3129. 	    /* slight assistance to the player: choose kick/open for them */
3130. 	    if (levl[u.ux+x][u.uy+y].doormask & D_LOCKED) {
3131. 		cmd[0] = C('d');
3132. 		return cmd;
3133. 	    }
3134. 	    if (levl[u.ux+x][u.uy+y].doormask & D_CLOSED) {
3135. 		cmd[0] = 'o';
3136. 		return cmd;
3137. 	    }
3138. 	}
3139. 	if (levl[u.ux+x][u.uy+y].typ <= SCORR) {
3140. 	    cmd[0] = 's';
3141. 	    cmd[1] = 0;
3142. 	    return cmd;
3143. 	}
3144.     }
3145.     } else {
3146.         /* convert without using floating point, allowing sloppy clicking */
3147.         if(x > 2*abs(y))
3148.             x = 1, y = 0;
3149.         else if(y > 2*abs(x))
3150.             x = 0, y = 1;
3151.         else if(x < -2*abs(y))
3152.             x = -1, y = 0;
3153.         else if(y < -2*abs(x))
3154.             x = 0, y = -1;
3155.         else
3156.             x = sgn(x), y = sgn(y);
3157. 
3158.         if(x == 0 && y == 0)	/* map click on player to "rest" command */
3159.             return ".";
3160. 
3161.         dir = xytod(x, y);
3162.     }
3163. 
3164.     /* move, attack, etc. */
3165.     cmd[1] = 0;
3166.     if(mod == CLICK_1) {
3167. 	cmd[0] = (iflags.num_pad ? ndir[dir] : sdir[dir]);
3168.     } else {
3169. 	cmd[0] = (iflags.num_pad ? M(ndir[dir]) :
3170. 		(sdir[dir] - 'a' + 'A')); /* run command */
3171.     }
3172. 
3173.     return cmd;
3174. }
3175. 
3176. STATIC_OVL char *
3177. parse()
3178. {
3179. #ifdef LINT	/* static char in_line[COLNO]; */
3180. 	char in_line[COLNO];
3181. #else
3182. 	static char in_line[COLNO];
3183. #endif
3184. 	register int foo;
3185. #ifdef BORG
3186. 	char junk_char;
3187. #endif
3188. 	static char repeat_char;
3189. 	boolean prezero = FALSE;
3190. 
3191. 	multi = 0;
3192. 	flags.move = 1;
3193. 	flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
3194. 
3195. #ifdef BORG
3196. 	if (borg_on) {
3197. 	/* KMH -- Danger!  kbhit() is non-standard! */
3198. 	   if (!kbhit()) {
3199. 	       borg_input();
3200. 	       return(borg_line);
3201. 	   } else {
3202. 		 junk_char = readchar();
3203. 		 pline("Cyborg terminated.");
3204. 		 borg_on = 0;
3205. 	   }
3206. 
3207. 	} else 
3208. #endif
3209. 	/* [Tom] for those who occasionally go insane... */
3210. 	if (repeat_hit) {
3211. 		/* Sanity checks for repeat_hit */
3212. 		if (repeat_hit < 0) repeat_hit = 0;
3213. 		else {
3214. 			/* Don't want things to get too out of hand */
3215. 			if (repeat_hit > 10) repeat_hit = 10;
3216. 			
3217. 			repeat_hit--;
3218. 			in_line[0] = repeat_char;
3219. 			in_line[1] = 0;
3220. 			return (in_line);
3221. 		}
3222. 	}
3223. 
3224. 	if (!iflags.num_pad || (foo = readchar()) == 'n')
3225. 	    for (;;) {
3226. 		foo = readchar();
3227. 		if (foo >= '0' && foo <= '9') {
3228. 		    multi = 10 * multi + foo - '0';
3229. 		    if (multi < 0 || multi >= LARGEST_INT) multi = LARGEST_INT;
3230. 		    if (multi > 9) {
3231. 			clear_nhwindow(WIN_MESSAGE);
3232. 			Sprintf(in_line, "Count: %d", multi);
3233. 			pline(in_line);
3234. 			mark_synch();
3235. 		    }
3236. 		    last_multi = multi;
3237. 		    if (!multi && foo == '0') prezero = TRUE;
3238. 		} else break;	/* not a digit */
3239. 	    }
3240. 
3241. 	if (foo == '\033') {   /* esc cancels count (TH) */
3242. 	    clear_nhwindow(WIN_MESSAGE);
3243. 	    /* multi = */ last_multi = 0;  /* WAC multi is cleared later in rhack */
3244. # ifdef REDO
3245. 	} else if (foo == DOAGAIN || in_doagain) {
3246. 	    multi = last_multi;
3247. 	} else {
3248. 	    last_multi = multi;
3249. 	    savech(0);	/* reset input queue */
3250. 	    savech((char)foo);
3251. # endif
3252. 	}
3253. 
3254. 	if (multi) {
3255. 	    multi--;
3256. 	    save_cm = in_line;
3257. 	} else {
3258. 	    save_cm = (char *)0;
3259. 	}
3260. 	in_line[0] = foo;
3261. 	in_line[1] = '\0';
3262. 
3263. 	if (foo == 'g' || foo == 'G' || foo == 'm' || foo == 'M' ||
3264. 	    foo == 'F' || (iflags.num_pad && (foo == '5' || foo == '-'))) {
3265. 	    foo = readchar();
3266. #ifdef REDO
3267. 	    savech((char)foo);
3268. #endif
3269. 	    in_line[1] = foo;
3270. 	    in_line[2] = 0;
3271. 	}
3272. 	clear_nhwindow(WIN_MESSAGE);
3273. 
3274. 	if (prezero) in_line[0] = '\033';
3275. 	repeat_char = in_line[0];
3276. 	
3277. 	return(in_line);
3278. }
3279. 
3280. #endif /* OVL0 */
3281. #ifdef OVLB
3282. 
3283. #ifdef UNIX
3284. static
3285. void
3286. end_of_input()
3287. {
3288. #ifndef NOSAVEONHANGUP
3289. 	if (!program_state.done_hup++ && program_state.something_worth_saving)
3290. 	    (void) dosave0();
3291. #endif
3292. 	exit_nhwindows((char *)0);
3293. 	clearlocks();
3294. 	terminate(EXIT_SUCCESS);
3295. }
3296. #endif
3297. 
3298. #endif /* OVLB */
3299. #ifdef OVL0
3300. 
3301. char
3302. readchar()
3303. {
3304. 	register int sym;
3305. 	int x = u.ux, y = u.uy, mod = 0;
3306. 
3307. 	if ( *readchar_queue )
3308. 	    sym = *readchar_queue++;
3309. 	else
3310. #ifdef REDO
3311. 	    sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod);
3312. #else
3313. 	    sym = Getchar();
3314. #endif
3315. 
3316. #ifdef UNIX
3317. # ifdef NR_OF_EOFS
3318. 	if (sym == EOF) {
3319. 	    register int cnt = NR_OF_EOFS;
3320. 	  /*
3321. 	   * Some SYSV systems seem to return EOFs for various reasons
3322. 	   * (?like when one hits break or for interrupted systemcalls?),
3323. 	   * and we must see several before we quit.
3324. 	   */
3325. 	    do {
3326. 		clearerr(stdin);	/* omit if clearerr is undefined */
3327. 		sym = Getchar();
3328. 	    } while (--cnt && sym == EOF);
3329. 	}
3330. # endif /* NR_OF_EOFS */
3331. 	if (sym == EOF)
3332. 	    end_of_input();
3333. #endif /* UNIX */
3334. 
3335. 	if(sym == 0) {
3336. 	    /* click event */
3337. 	    readchar_queue = click_to_cmd(x, y, mod);
3338. 	    sym = *readchar_queue++;
3339. 	}
3340. 	return((char) sym);
3341. }
3342. 
3343. STATIC_PTR int
3344. dotravel()
3345. {
3346. 	/* Keyboard travel command */
3347. 	static char cmd[2];
3348. 	coord cc;
3349. 
3350. 	if (!iflags.travelcmd) return 0;
3351. 	cmd[1]=0;
3352. 	cc.x = iflags.travelcc.x;
3353. 	cc.y = iflags.travelcc.y;
3354. 	if (cc.x == -1 && cc.y == -1) {
3355. 	    /* No cached destination, start attempt from current position */
3356. 	    cc.x = u.ux;
3357. 	    cc.y = u.uy;
3358. 	}
3359. 	pline("Where do you want to travel to?");
3360. 	if (getpos(&cc, TRUE, "the desired destination") < 0) {
3361. 		/* user pressed ESC */
3362. 		return 0;
3363. 	}
3364. 	iflags.travelcc.x = u.tx = cc.x;
3365. 	iflags.travelcc.y = u.ty = cc.y;
3366. 	cmd[0] = CMD_TRAVEL;
3367. 	readchar_queue = cmd;
3368. 	return 0;
3369. }
3370. 
3371. #ifdef PORT_DEBUG
3372. # ifdef WIN32CON
3373. extern void NDECL(win32con_debug_keystrokes);
3374. extern void NDECL(win32con_handler_info);
3375. # endif
3376. 
3377. int
3378. wiz_port_debug()
3379. {
3380. 	int n, k;
3381. 	winid win;
3382. 	anything any;
3383. 	int item = 'a';
3384. 	int num_menu_selections;
3385. 	struct menu_selection_struct {
3386. 		char *menutext;
3387. 		char *portname;
3388. 		void NDECL((*fn));
3389. 	} menu_selections[] = {
3390. #ifdef WIN32CON
3391. 		{"test win32 keystrokes", "tty", win32con_debug_keystrokes},
3392. 		{"show keystroke handler information", "tty",
3393. 				win32con_handler_info},
3394. #endif
3395. 		{(char *)0, (char *)0, (void NDECL((*)))0}/* array terminator */
3396. 	};
3397. 
3398. 	num_menu_selections = SIZE(menu_selections) - 1;
3399. 	for (k=n=0; k < num_menu_selections; ++k)
3400. 		if (!strcmp(menu_selections[k].portname, windowprocs.name))
3401. 			n++;
3402. 	if (n > 0) {
3403. 		menu_item *pick_list;
3404. 		win = create_nhwindow(NHW_MENU);
3405. 		start_menu(win);
3406. 		for (k=0; k < num_menu_selections; ++k) {
3407. 			if (strcmp(menu_selections[k].portname,
3408. 				   windowprocs.name))
3409. 				continue;
3410. 			any.a_int = k+1;
3411. 			add_menu(win, NO_GLYPH, &any, item++, 0, ATR_NONE,
3412. 				menu_selections[k].menutext, MENU_UNSELECTED);
3413. 		}
3414. 		end_menu(win, "Which port debugging feature?");
3415. 		n = select_menu(win, PICK_ONE, &pick_list);
3416. 		destroy_nhwindow(win);
3417. 		if (n > 0) {
3418. 			n = pick_list[0].item.a_int - 1;
3419. 			free((genericptr_t) pick_list);
3420. 			/* execute the function */
3421. 			(*menu_selections[n].fn)();
3422. 		}
3423. 	} else
3424. 		pline("No port-specific debug capability defined.");
3425. 	return 0;
3426. }
3427. # endif /*PORT_DEBUG*/
3428. 
3429. #endif /* OVL0 */
3430. #ifdef OVLB
3431. /*
3432.  *   Parameter validator for generic yes/no function to prevent
3433.  *   the core from sending too long a prompt string to the
3434.  *   window port causing a buffer overflow there.
3435.  */
3436. char
3437. yn_function(query,resp, def)
3438. const char *query,*resp;
3439. char def;
3440. {
3441. 	char qbuf[QBUFSZ];
3442. 	unsigned truncspot, reduction = sizeof(" [N]  ?") + 1;
3443. 
3444. 	if (resp) reduction += strlen(resp) + sizeof(" () ");
3445. 	if (strlen(query) < (QBUFSZ - reduction))
3446. 		return (*windowprocs.win_yn_function)(query, resp, def);
3447. 	paniclog("Query truncated: ", query);
3448. 	reduction += sizeof("...");
3449. 	truncspot = QBUFSZ - reduction;
3450. 	(void) strncpy(qbuf, query, (int)truncspot);
3451. 	qbuf[truncspot] = '\0';
3452. 	Strcat(qbuf,"...");
3453. 	return (*windowprocs.win_yn_function)(qbuf, resp, def);
3454. }
3455. #endif
3456. 
3457. /*cmd.c*/