Wikia

Wikihack

Source:SLASH'EM 0.0.7E7F2/cmd.c

2,032pages on
this wiki
Talk0

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.
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*/

Around Wikia's network

Random Wiki