Fandom

Wikihack

Source:NetHack 3.2.0/cmd.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

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

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)cmd.c	3.2	95/08/12	*/
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.   #ifdef DEBUG
18.   /*
19.    * only one "wiz_debug_cmd" routine should be available (in whatever
20.    * module you are trying to debug) or things are going to get rather
21.    * hard to link :-)
22.    */
23.   extern void NDECL(wiz_debug_cmd);
24.   #endif
25.   
26.   #ifdef DUMB	/* stuff commented out in extern.h, but needed here */
27.   extern int NDECL(doapply); /**/
28.   extern int NDECL(dorub); /**/
29.   extern int NDECL(dojump); /**/
30.   extern int NDECL(doextlist); /**/
31.   extern int NDECL(dodrop); /**/
32.   extern int NDECL(doddrop); /**/
33.   extern int NDECL(dodown); /**/
34.   extern int NDECL(doup); /**/
35.   extern int NDECL(donull); /**/
36.   extern int NDECL(dowipe); /**/
37.   extern int NDECL(do_mname); /**/
38.   extern int NDECL(ddocall); /**/
39.   extern int NDECL(dotakeoff); /**/
40.   extern int NDECL(doremring); /**/
41.   extern int NDECL(dowear); /**/
42.   extern int NDECL(doputon); /**/
43.   extern int NDECL(doddoremarm); /**/
44.   extern int NDECL(dokick); /**/
45.   extern int NDECL(dothrow); /**/
46.   extern int NDECL(doeat); /**/
47.   extern int NDECL(done2); /**/
48.   extern int NDECL(doengrave); /**/
49.   extern int NDECL(dopickup); /**/
50.   extern int NDECL(ddoinv); /**/
51.   extern int NDECL(dotypeinv); /**/
52.   extern int NDECL(dolook); /**/
53.   extern int NDECL(doprgold); /**/
54.   extern int NDECL(doprwep); /**/
55.   extern int NDECL(doprarm); /**/
56.   extern int NDECL(doprring); /**/
57.   extern int NDECL(dopramulet); /**/
58.   extern int NDECL(doprtool); /**/
59.   extern int NDECL(dosuspend); /**/
60.   extern int NDECL(doforce); /**/
61.   extern int NDECL(doopen); /**/
62.   extern int NDECL(doclose); /**/
63.   extern int NDECL(dosh); /**/
64.   extern int NDECL(dodiscovered); /**/
65.   extern int NDECL(doset); /**/
66.   extern int NDECL(dotogglepickup); /**/
67.   extern int NDECL(dowhatis); /**/
68.   extern int NDECL(doquickwhatis); /**/
69.   extern int NDECL(dowhatdoes); /**/
70.   extern int NDECL(dohelp); /**/
71.   extern int NDECL(dohistory); /**/
72.   extern int NDECL(doloot); /**/
73.   extern int NDECL(dodrink); /**/
74.   extern int NDECL(dodip); /**/
75.   extern int NDECL(dosacrifice); /**/
76.   extern int NDECL(dopray); /**/
77.   extern int NDECL(doturn); /**/
78.   extern int NDECL(doredraw); /**/
79.   extern int NDECL(doread); /**/
80.   extern int NDECL(dosave); /**/
81.   extern int NDECL(dosearch); /**/
82.   extern int NDECL(doidtrap); /**/
83.   extern int NDECL(dopay); /**/
84.   extern int NDECL(dosit); /**/
85.   extern int NDECL(dotalk); /**/
86.   extern int NDECL(docast); /**/
87.   extern int NDECL(dovspell); /**/
88.   extern int NDECL(dotele); /**/
89.   extern int NDECL(dountrap); /**/
90.   extern int NDECL(doversion); /**/
91.   extern int NDECL(doextversion); /**/
92.   extern int NDECL(dowield); /**/
93.   extern int NDECL(dozap); /**/
94.   extern int NDECL(doorganize); /**/
95.   #endif /* DUMB */
96.   
97.   #ifdef OVL1
98.   static int NDECL((*timed_occ_fn));
99.   #endif /* OVL1 */
100.  
101.  STATIC_PTR int NDECL(doprev_message);
102.  STATIC_PTR int NDECL(timed_occupation);
103.  STATIC_PTR int NDECL(doextcmd);
104.  STATIC_PTR int NDECL(domonability);
105.  # ifdef WIZARD
106.  STATIC_PTR int NDECL(wiz_wish);
107.  STATIC_PTR int NDECL(wiz_identify);
108.  STATIC_PTR int NDECL(wiz_map);
109.  STATIC_PTR int NDECL(wiz_genesis);
110.  STATIC_PTR int NDECL(wiz_where);
111.  STATIC_PTR int NDECL(wiz_detect);
112.  STATIC_PTR int NDECL(wiz_level_tele);
113.  STATIC_PTR int NDECL(wiz_show_seenv);
114.  STATIC_PTR int NDECL(wiz_show_vision);
115.  STATIC_PTR int NDECL(wiz_show_wmodes);
116.  #ifdef __BORLANDC__
117.  extern void FDECL(show_borlandc_stats, (winid));
118.  #endif
119.  static void FDECL(count_obj, (struct obj *, long *, long *, BOOLEAN_P, BOOLEAN_P));
120.  static void FDECL(obj_chain, (winid, const char *, struct obj *, long *, long *));
121.  static void FDECL(mon_invent_chain, (winid, const char *, struct monst *, long *, long *));
122.  static void FDECL(mon_chain, (winid, const char *, struct monst *, long *, long *));
123.  static void FDECL(contained, (winid, const char *, long *, long *));
124.  STATIC_PTR int NDECL(wiz_show_stats);
125.  # endif
126.  STATIC_PTR int NDECL(enter_explore_mode);
127.  STATIC_PTR int NDECL(wiz_attributes);
128.  
129.  #ifdef OVLB
130.  static void FDECL(enlght_line, (const char *,const char *,const char *));
131.  #ifdef UNIX
132.  static void NDECL(end_of_input);
133.  #endif
134.  #endif /* OVLB */
135.  
136.  STATIC_DCL char *NDECL(parse);
137.  
138.  #ifdef OVL1
139.  
140.  STATIC_PTR int
141.  doprev_message()
142.  {
143.      return nh_doprev_message();
144.  }
145.  
146.  /* Count down by decrementing multi */
147.  STATIC_PTR int
148.  timed_occupation() {
149.  	(*timed_occ_fn)();
150.  	if (multi > 0)
151.  		multi--;
152.  	return multi > 0;
153.  }
154.  
155.  /* If you have moved since initially setting some occupations, they
156.   * now shouldn't be able to restart.
157.   *
158.   * The basic rule is that if you are carrying it, you can continue
159.   * since it is with you.  If you are acting on something at a distance,
160.   * your orientation to it must have changed when you moved.
161.   *
162.   * The exception to this is taking off items, since they can be taken
163.   * off in a number of ways in the intervening time, screwing up ordering.
164.   *
165.   *	Currently:	Take off all armor.
166.   *			Picking Locks / Forcing Chests.
167.   */
168.  void
169.  reset_occupations() {
170.  
171.  	reset_remarm();
172.  	reset_pick();
173.  }
174.  
175.  /* If a time is given, use it to timeout this function, otherwise the
176.   * function times out by its own means.
177.   */
178.  void
179.  set_occupation(fn, txt, xtime)
180.  int NDECL((*fn));
181.  const char *txt;
182.  int xtime;
183.  {
184.  	if (xtime) {
185.  		occupation = timed_occupation;
186.  		timed_occ_fn = fn;
187.  	} else
188.  		occupation = fn;
189.  	occtxt = txt;
190.  	occtime = 0;
191.  	return;
192.  }
193.  
194.  #ifdef REDO
195.  
196.  static char NDECL(popch);
197.  
198.  /* Provide a means to redo the last command.  The flag `in_doagain' is set
199.   * to true while redoing the command.  This flag is tested in commands that
200.   * require additional input (like `throw' which requires a thing and a
201.   * direction), and the input prompt is not shown.  Also, while in_doagain is
202.   * TRUE, no keystrokes can be saved into the saveq.
203.   */
204.  #define BSIZE 20
205.  static char pushq[BSIZE], saveq[BSIZE];
206.  static NEARDATA int phead, ptail, shead, stail;
207.  
208.  static char
209.  popch() {
210.  	/* If occupied, return '\0', letting tgetch know a character should
211.  	 * be read from the keyboard.  If the character read is not the
212.  	 * ABORT character (as checked in pcmain.c), that character will be
213.  	 * pushed back on the pushq.
214.  	 */
215.  	if (occupation) return '\0';
216.  	if (in_doagain) return(char)((shead != stail) ? saveq[stail++] : '\0');
217.  	else		return(char)((phead != ptail) ? pushq[ptail++] : '\0');
218.  }
219.  
220.  char
221.  pgetchar() {		/* curtesy of aeb@cwi.nl */
222.  	register int ch;
223.  
224.  	if(!(ch = popch()))
225.  		ch = nhgetch();
226.  	return((char)ch);
227.  }
228.  
229.  /* A ch == 0 resets the pushq */
230.  void
231.  pushch(ch)
232.  char ch;
233.  {
234.  	if (!ch)
235.  		phead = ptail = 0;
236.  	if (phead < BSIZE)
237.  		pushq[phead++] = ch;
238.  	return;
239.  }
240.  
241.  /* A ch == 0 resets the saveq.	Only save keystrokes when not
242.   * replaying a previous command.
243.   */
244.  void
245.  savech(ch)
246.  char ch;
247.  {
248.  	if (!in_doagain) {
249.  		if (!ch)
250.  			phead = ptail = shead = stail = 0;
251.  		else if (shead < BSIZE)
252.  			saveq[shead++] = ch;
253.  	}
254.  	return;
255.  }
256.  #endif /* REDO */
257.  
258.  #endif /* OVL1 */
259.  #ifdef OVLB
260.  
261.  STATIC_PTR int
262.  doextcmd()	/* here after # - now read a full-word command */
263.  {
264.  	int idx, retval;
265.  
266.  	/* keep repeating until we don't run help or quit */
267.  	do {
268.  	    idx = get_ext_cmd();
269.  	    if (idx < 0) return 0;	/* quit */
270.  
271.  	    retval = (*extcmdlist[idx].ef_funct)();
272.  	} while (extcmdlist[idx].ef_funct == doextlist);
273.  
274.  	return retval;
275.  }
276.  
277.  int
278.  doextlist()	/* here after #? - now list all full-word commands */
279.  {
280.  	register const struct ext_func_tab *efp;
281.  	char	 buf[BUFSZ];
282.  	winid datawin;
283.  
284.  	datawin = create_nhwindow(NHW_TEXT);
285.  	putstr(datawin, 0, "");
286.  	putstr(datawin, 0, "            Extended Commands List");
287.  	putstr(datawin, 0, "");
288.  	putstr(datawin, 0, "    Press '#', then type:");
289.  	putstr(datawin, 0, "");
290.  
291.  	for(efp = extcmdlist; efp->ef_txt; efp++) {
292.  		Sprintf(buf, "    %-14s  - %s.", efp->ef_txt, efp->ef_desc);
293.  		putstr(datawin, 0, buf);
294.  	}
295.  	display_nhwindow(datawin, FALSE);
296.  	destroy_nhwindow(datawin);
297.  	return 0;
298.  }
299.  
300.  STATIC_PTR int
301.  domonability()
302.  {
303.  	if (can_breathe(uasmon)) return dobreathe();
304.  	else if (attacktype(uasmon, AT_SPIT)) return dospit();
305.  	else if (u.usym == S_NYMPH) return doremove();
306.  	else if (u.usym == S_UMBER) return doconfuse();
307.  	else if (is_were(uasmon)) return dosummon();
308.  	else if (webmaker(uasmon)) return dospinweb();
309.  	else if (is_hider(uasmon)) return dohide();
310.  	else if(u.umonnum == PM_GREMLIN) {
311.  	    if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
312.  		struct monst *mtmp;
313.  		if ((mtmp = cloneu()) != 0) {
314.  			mtmp->mhpmax = (u.mhmax /= 2);
315.  			You("multiply.");
316.  			dryup(u.ux,u.uy);
317.  		}
318.  	    } else pline("There is no fountain here.");
319.  	}
320.  	else if (u.usym == S_UNICORN) {
321.  	    use_unicorn_horn((struct obj *)0);
322.  	    return 1;
323.  	} else if (u.umonnum == PM_MIND_FLAYER) return domindblast();
324.  	else if (uasmon->msound == MS_SHRIEK) {
325.  	    You("shriek.");
326.  	    if(u.uburied)
327.  		pline("Unfortunately sound does not carry well through rock.");
328.  	    else aggravate();
329.  	} else if (Upolyd)
330.  		pline("Any special ability you may have is purely reflexive.");
331.  	else You("don't have a special ability!");
332.  	return 0;
333.  }
334.  
335.  STATIC_PTR int
336.  enter_explore_mode()
337.  {
338.  	if(!discover && !wizard) {
339.  		pline("Beware!  From explore mode there will be no return to normal game.");
340.  		if (yn("Do you want to enter explore mode?") == 'y') {
341.  			clear_nhwindow(WIN_MESSAGE);
342.  			You("are now in non-scoring explore mode.");
343.  			discover = TRUE;
344.  		}
345.  		else {
346.  			clear_nhwindow(WIN_MESSAGE);
347.  			pline("Resuming normal game.");
348.  		}
349.  	}
350.  	return 0;
351.  }
352.  
353.  #ifdef WIZARD
354.  STATIC_PTR int
355.  wiz_wish()	/* Unlimited wishes for debug mode by Paul Polderman */
356.  {
357.  	if (wizard) {
358.  	    boolean save_verbose = flags.verbose;
359.  
360.  	    flags.verbose = FALSE;
361.  	    makewish();
362.  	    flags.verbose = save_verbose;
363.  	    (void) encumber_msg();
364.  	} else
365.  	    pline("Unavailable command '^W'.");
366.  	return 0;
367.  }
368.  
369.  STATIC_PTR int
370.  wiz_identify()
371.  {
372.  	if (wizard)	identify_pack(0);
373.  	else		pline("Unavailable command '^I'.");
374.  	return 0;
375.  }
376.  
377.  STATIC_PTR int
378.  wiz_map()
379.  {
380.  	if (wizard)	do_mapping();
381.  	else		pline("Unavailable command '^F'.");
382.  	return 0;
383.  }
384.  
385.  STATIC_PTR int
386.  wiz_genesis()
387.  {
388.  	if (wizard)	(void) create_particular();
389.  	else		pline("Unavailable command '^G'.");
390.  	return 0;
391.  }
392.  
393.  STATIC_PTR int
394.  wiz_where()
395.  {
396.  	if (wizard) print_dungeon();
397.  	else	    pline("Unavailable command '^O'.");
398.  	return 0;
399.  }
400.  
401.  STATIC_PTR int
402.  wiz_detect()
403.  {
404.  	if(wizard)  (void) findit();
405.  	else	    pline("Unavailable command '^E'.");
406.  	return 0;
407.  }
408.  
409.  STATIC_PTR int
410.  wiz_level_tele()
411.  {
412.  	if (wizard)	level_tele();
413.  	else		pline("Unavailable command '^V'.");
414.  	return 0;
415.  }
416.  
417.  STATIC_PTR int
418.  wiz_show_seenv()
419.  {
420.  	winid win;
421.  	int x, y, v, startx, stopx, curx;
422.  	char row[COLNO+1];
423.  
424.  	win = create_nhwindow(NHW_TEXT);
425.  	/*
426.  	 * Each seenv description takes up 2 characters, so center
427.  	 * the seenv display around the hero.
428.  	 */
429.  	startx = max(1, u.ux-(COLNO/4));
430.  	stopx = min(startx+(COLNO/2), COLNO);
431.  	/* can't have a line exactly 80 chars long */
432.  	if (stopx - startx == COLNO/2) startx++;
433.  
434.  	for (y = 0; y < ROWNO; y++) {
435.  	    for (x = startx, curx = 0; x < stopx; x++, curx += 2) {
436.  		if (x == u.ux && y == u.uy) {
437.  		    row[curx] = row[curx+1] = '@';
438.  		} else {
439.  		    v = levl[x][y].seenv & 0xff;
440.  		    if (v == 0)
441.  			row[curx] = row[curx+1] = ' ';
442.  		    else
443.  			Sprintf(&row[curx], "%02x", v);
444.  		}
445.  	    }
446.  	    /* remove trailing spaces */
447.  	    for (x = curx-1; x >= 0; x--)
448.  		if (row[x] != ' ') break;
449.  	    row[x+1] = '\0';
450.  
451.  	    putstr(win, 0, row);
452.  	}
453.  	display_nhwindow(win, TRUE);
454.  	destroy_nhwindow(win);
455.  	return 0;
456.  }
457.  
458.  STATIC_PTR int
459.  wiz_show_vision()
460.  {
461.  	winid win;
462.  	int x, y, v;
463.  	char row[COLNO+1];
464.  
465.  	win = create_nhwindow(NHW_TEXT);
466.  	Sprintf(row, "Flags: 0x%x could see, 0x%x in sight, 0x%x temp lit",
467.  		COULD_SEE, IN_SIGHT, TEMP_LIT);
468.  	putstr(win, 0, row);
469.  	putstr(win, 0, "");
470.  	for (y = 0; y < ROWNO; y++) {
471.  	    for (x = 1; x < COLNO; x++) {
472.  		if (x == u.ux && y == u.uy)
473.  		    row[x] = '@';
474.  		else {
475.  		    v = viz_array[y][x]; /* data access should be hidden */
476.  		    if (v == 0)
477.  			row[x] = ' ';
478.  		    else
479.  			row[x] = '0' + viz_array[y][x];
480.  		}
481.  	    }
482.  	    /* remove trailing spaces */
483.  	    for (x = COLNO-1; x >= 1; x--)
484.  		if (row[x] != ' ') break;
485.  	    row[x+1] = '\0';
486.  
487.  	    putstr(win, 0, &row[1]);
488.  	}
489.  	display_nhwindow(win, TRUE);
490.  	destroy_nhwindow(win);
491.  	return 0;
492.  }
493.  
494.  STATIC_PTR int
495.  wiz_show_wmodes()
496.  {
497.  	winid win;
498.  	int x,y;
499.  	char row[COLNO+1];
500.  	struct rm *lev;
501.  
502.  	win = create_nhwindow(NHW_TEXT);
503.  	for (y = 0; y < ROWNO; y++) {
504.  	    for (x = 0; x < COLNO; x++) {
505.  		lev = &levl[x][y];
506.  		if (x == u.ux && y == u.uy)
507.  		    row[x] = '@';
508.  		if (IS_WALL(lev->typ) || lev->typ == SDOOR)
509.  		    row[x] = '0' + (lev->wall_info & WM_MASK);
510.  		else if (lev->typ == CORR)
511.  		    row[x] = '#';
512.  		else if (IS_ROOM(lev->typ) || IS_DOOR(lev->typ))
513.  		    row[x] = '.';
514.  		else
515.  		    row[x] = 'x';
516.  	    }
517.  	    row[COLNO] = '\0';
518.  	    putstr(win, 0, row);
519.  	}
520.  	display_nhwindow(win, TRUE);
521.  	destroy_nhwindow(win);
522.  	return 0;
523.  }
524.  
525.  #endif /* WIZARD */
526.  
527.  /* -enlightenment- */
528.  static winid en_win;
529.  static const char
530.  	*You_ = "You ",
531.  	*are  = "are ",  *were  = "were ",
532.  	*have = "have ", *had   = "had ",
533.  	*can  = "can ",  *could = "could ";
534.  
535.  #define enl_msg(prefix,present,past,suffix) \
536.  			enlght_line(prefix, final ? past : present, suffix)
537.  #define you_are(attr)	enl_msg(You_,are,were,attr)
538.  #define you_have(attr)	enl_msg(You_,have,had,attr)
539.  #define you_can(attr)	enl_msg(You_,can,could,attr)
540.  
541.  static void
542.  enlght_line(start, middle, end)
543.  const char *start, *middle, *end;
544.  {
545.  	char buf[BUFSZ];
546.  
547.  	Sprintf(buf, "%s%s%s.", start, middle, end);
548.  	putstr(en_win, 0, buf);
549.  }
550.  
551.  void
552.  enlightenment(final)
553.  int final;	/* 0 => still in progress; 1 => over, survived; 2 => dead */
554.  {
555.  	int ltmp;
556.  	char buf[BUFSZ];
557.  
558.  	en_win = create_nhwindow(NHW_MENU);
559.  	putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:");
560.  	putstr(en_win, 0, "");
561.  
562.  #ifdef ELBERETH
563.  	if (u.uevent.uhand_of_elbereth) {
564.  	    static const char *hofe_titles[3] = {
565.  				"the Hand of Elbereth",
566.  				"the Envoy of Balance",
567.  				"the Glory of Arioch"
568.  	    };
569.  	    you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1]);
570.  	}
571.  #endif
572.  
573.  	/* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
574.  	if (u.ualign.record >= 20)	you_are("piously aligned");
575.  	else if (u.ualign.record > 13)	you_are("devoutly aligned");
576.  	else if (u.ualign.record > 8)	you_are("fervently aligned");
577.  	else if (u.ualign.record > 3)	you_are("stridently aligned");
578.  	else if (u.ualign.record == 3)	you_are("aligned");
579.  	else if (u.ualign.record > 0)	you_are("haltingly aligned");
580.  	else if (u.ualign.record == 0)	you_are("nominally aligned");
581.  	else if (u.ualign.record >= -3)	you_have("strayed");
582.  	else if (u.ualign.record >= -8)	you_have("sinned");
583.  	else you_have("transgressed");
584.  #ifdef WIZARD
585.  	if (wizard) {
586.  		Sprintf(buf, " %d", u.ualign.record);
587.  		enl_msg("Your alignment ", "is", "was", buf);
588.  	}
589.  #endif
590.  
591.  	if (Telepat) you_are("telepathic");
592.  	if (Searching) you_have("automatic searching");
593.  	if (Teleportation) you_can("teleport");
594.  	if (Teleport_control) you_have("teleport control");
595.  	if (See_invisible) enl_msg(You_, "see", "saw", " invisible");
596.  	if (Invisible) you_are("invisible");
597.  	else if (Invis) you_are("invisible to others");
598.  	/* ordinarily "visible" is redundant; this is a special case for
599.  	   the situation when invisibility would be an expected attribute */
600.  	else if ((HInvis & I_BLOCKED) != 0L &&
601.  		 ((HInvis & ~I_BLOCKED) != 0L || pm_invisible(uasmon)))
602.  	    you_are("visible");
603.  	if (Fast) you_are((Fast & ~INTRINSIC) ? "very fast" : "fast");
604.  	if (Stealth) you_are("stealthy");
605.  	if (Regeneration) enl_msg("You regenerate", "", "d", "");
606.  	if (Hunger) enl_msg("You hunger", "", "ed", " rapidly");
607.  	if (Conflict) enl_msg("You cause", "", "d", " conflict");
608.  	if (Aggravate_monster) enl_msg("You aggravate", "", "d", " monsters");
609.  	if (Poison_resistance) you_are("poison resistant");
610.  	if (Fire_resistance) you_are("fire resistant");
611.  	if (Cold_resistance) you_are("cold resistant");
612.  	if (Shock_resistance) you_are("shock resistant");
613.  	if (Sleep_resistance) you_are("sleep resistant");
614.  	if (Disint_resistance) you_are("disintegration-resistant");
615.  	if (Protection_from_shape_changers)
616.  		you_are("protected from shape changers");
617.  	if (Polymorph) you_are("polymorphing");
618.  	if (Polymorph_control) you_have("polymorph control");
619.  	if (HHalluc_resistance)
620.  		enl_msg("You resist", "", "ed", " hallucinations");
621.  	if (final) {
622.  		if (Hallucination) you_are("hallucinating");
623.  		if (Stunned) you_are("stunned");
624.  		if (Confusion) you_are("confused");
625.  		if (Sick) {
626.  			if (u.usick_type & SICK_VOMITABLE)
627.  				you_are("sick from food poisoning");
628.  			if (u.usick_type & SICK_NONVOMITABLE)
629.  				you_are("sick from illness");
630.  		}
631.  		if (Blinded) you_are("blinded");
632.  	}
633.  	if (Wounded_legs) {
634.  		Sprintf(buf, "wounded %s", makeplural(body_part(LEG)));
635.  		you_have(buf);
636.  	}
637.  	if (Glib) {
638.  		Sprintf(buf, "slippery %s", makeplural(body_part(FINGER)));
639.  		you_have(buf);
640.  	}
641.  	if (Strangled) you_are((u.uburied) ? "buried" : "being strangled");
642.  	if (Stoned) you_are("turning to stone");
643.  	if (Lifesaved)
644.  		enl_msg("Your life ", "will be", "would have been", " saved");
645.  	if (Adornment) you_are("adorned");
646.  	if (Warning) you_are("warned");
647.  	if (Protection) you_are("protected");
648.  	if (Reflecting) you_have("reflection");
649.  	if ((HLevitation & (I_SPECIAL|W_ARTI)) != 0L &&
650.  	    (HLevitation & ~(I_SPECIAL|W_ARTI|TIMEOUT)) == 0L &&
651.  	    !is_floater(uasmon)) you_are("levitating, at will");
652.  	else if (Levitation) you_are("levitating");	/* without control */
653.  	else if (is_flyer(uasmon)) you_can("fly");
654.  	if (Fumbling) enl_msg("You fumble", "", "d", "");
655.  	if (Jumping) you_can("jump");
656.  	if (Wwalking) you_can("walk on water");
657.  	if (passes_walls(uasmon)) you_can("walk through walls");
658.  	if (Breathless) you_can("survive without air");
659.  	else if (Amphibious) you_can("breathe water");
660.  	if (Antimagic) you_are("magic-protected");
661.  	if (Displaced) you_are("displaced");
662.  	if (Clairvoyant) you_are("clairvoyant");
663.  	if (u.ulycn >= LOW_PM) {
664.  		Strcpy(buf, an(mons[u.ulycn].mname));
665.  		you_are(buf);
666.  	}
667.  	if (Luck) {
668.  	    ltmp = abs((int)Luck);
669.  	    Sprintf(buf, "%s%slucky",
670.  		    ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "",
671.  		    Luck < 0 ? "un" : "");
672.  #ifdef WIZARD
673.  	    if (wizard) Sprintf(eos(buf), " (%d)", Luck);
674.  #endif
675.  	    you_are(buf);
676.  	}
677.  #ifdef WIZARD
678.  	 else if (wizard) enl_msg("Your luck ", "is", "was", " zero");
679.  #endif
680.  	if (u.moreluck > 0) you_have("extra luck");
681.  	else if (u.moreluck < 0) you_have("reduced luck");
682.  	if (carrying(LUCKSTONE)) {
683.  	    ltmp = stone_luck(FALSE);
684.  	    if (ltmp <= 0)
685.  		enl_msg("Bad luck ", "does", "did", " not time out for you");
686.  	    if (ltmp >= 0)
687.  		enl_msg("Good luck ", "does", "did", " not time out for you");
688.  	}
689.  
690.  	if (u.ugangr) {
691.  	    Sprintf(buf, " %sangry with you",
692.  		    u.ugangr > 6 ? "extremely " : u.ugangr > 3 ? "very " : "");
693.  #ifdef WIZARD
694.  	    if (wizard) Sprintf(eos(buf), " (%d)", u.ugangr);
695.  #endif
696.  	    enl_msg(u_gname(), " is", " was", buf);
697.  	} else
698.  	    /*
699.  	     * We need to suppress this when the game is over, because death
700.  	     * can change the value calculated by can_pray(), potentially
701.  	     * resulting in a false claim that you could have prayed safely.
702.  	     */
703.  	  if (!final) {
704.  #if 0
705.  	    /* "can [not] safely pray" vs "could [not] have safely prayed" */
706.  	    Sprintf(buf, "%s%ssafely pray%s", can_pray(FALSE) ? "" : "not ",
707.  		    final ? "have " : "", final ? "ed" : "");
708.  #else
709.  	    Sprintf(buf, "%ssafely pray", can_pray(FALSE) ? "" : "not ");
710.  #endif
711.  #ifdef WIZARD
712.  	    if (wizard) Sprintf(eos(buf), " (%d)", u.ublesscnt);
713.  #endif
714.  	    you_can(buf);
715.  	}
716.  
717.      {
718.  	const char *p;
719.  
720.  	buf[0] = '\0';
721.  	if (final < 2) {    /* still in progress, or quit/escaped/ascended */
722.  	    p = "survived after being killed ";
723.  	    switch (u.umortality) {
724.  	    case 0:  p = !final ? (char *)0 : "survived";  break;
725.  	    case 1:  Strcpy(buf, "once");  break;
726.  	    case 2:  Strcpy(buf, "twice");  break;
727.  	    case 3:  Strcpy(buf, "thrice");  break;
728.  	    default: Sprintf(buf, "%d times", u.umortality);
729.  		     break;
730.  	    }
731.  	} else {		/* game ended in character's death */
732.  	    p = "are dead";
733.  	    switch (u.umortality) {
734.  	    case 0:  impossible("dead without dying?");
735.  	    case 1:  break;			/* just "are dead" */
736.  	    default: Sprintf(buf, " (%d%s time!)", u.umortality,
737.  			     ordin(u.umortality));
738.  		     break;
739.  	    }
740.  	}
741.  	if (p) enl_msg(You_, "have been killed ", p, buf);
742.      }
743.  
744.  	display_nhwindow(en_win, TRUE);
745.  	destroy_nhwindow(en_win);
746.  	return;
747.  }
748.  
749.  STATIC_PTR int
750.  wiz_attributes()
751.  {
752.  	if (wizard || discover)
753.  		enlightenment(0);
754.  	else
755.  		pline("Unavailable command '^X'.");
756.  	return 0;
757.  }
758.  
759.  #endif /* OVLB */
760.  #ifdef OVL1
761.  
762.  #ifndef M
763.  # ifndef NHSTDC
764.  #  define M(c)		(0x80 | (c))
765.  # else
766.  #  define M(c)		((c) - 128)
767.  # endif /* NHSTDC */
768.  #endif
769.  #ifndef C
770.  #define C(c)		(0x1f & (c))
771.  #endif
772.  
773.  static const struct func_tab cmdlist[] = {
774.  	{C('d'), FALSE, dokick}, /* "D" is for door!...?  Msg is in dokick.c */
775.  #ifdef WIZARD
776.  	{C('e'), TRUE, wiz_detect},
777.  	{C('f'), TRUE, wiz_map},
778.  	{C('g'), TRUE, wiz_genesis},
779.  	{C('i'), TRUE, wiz_identify},
780.  #endif
781.  	{C('l'), TRUE, doredraw}, /* if number_pad is set */
782.  #ifdef WIZARD
783.  	{C('o'), TRUE, wiz_where},
784.  #endif
785.  	{C('p'), TRUE, doprev_message},
786.  	{C('r'), TRUE, doredraw},
787.  	{C('t'), TRUE, dotele},
788.  #ifdef WIZARD
789.  	{C('v'), TRUE, wiz_level_tele},
790.  	{C('w'), TRUE, wiz_wish},
791.  #endif
792.  	{C('x'), TRUE, wiz_attributes},
793.  #ifdef SUSPEND
794.  	{C('z'), TRUE, dosuspend},
795.  #endif
796.  	{'a', FALSE, doapply},
797.  	{'A', FALSE, doddoremarm},
798.  	{M('a'), TRUE, doorganize},
799.  /*	'b', 'B' : go sw */
800.  	{'c', FALSE, doclose},
801.  	{'C', TRUE, do_mname},
802.  	{M('c'), TRUE, dotalk},
803.  	{'d', FALSE, dodrop},
804.  	{'D', FALSE, doddrop},
805.  	{M('d'), FALSE, dodip},
806.  	{'e', FALSE, doeat},
807.  	{'E', FALSE, doengrave},
808.  #ifdef WEAPON_SKILLS
809.  	{M('e'), TRUE, select_weapon_skill},
810.  #endif /* WEAPON_SKILLS */
811.  /* Soon to be
812.  	{'f', FALSE, dofight, "fighting"},
813.  	{'F', FALSE, doFight, "fighting"},
814.   */
815.  	{M('f'), FALSE, doforce},
816.  /*	'g', 'G' : multiple go */
817.  /*	'h', 'H' : go west */
818.  	{'h', TRUE, dohelp}, /* if number_pad is set */
819.  	{'i', TRUE, ddoinv},
820.  	{'I', TRUE, dotypeinv},		/* Robert Viduya */
821.  	{M('i'), TRUE, doinvoke},
822.  /*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
823.  	{'j', FALSE, dojump}, /* if number_pad is on */
824.  	{M('j'), FALSE, dojump},
825.  	{'k', FALSE, dokick}, /* if number_pad is on */
826.  	{'l', FALSE, doloot}, /* if number_pad is on */
827.  	{M('l'), FALSE, doloot},
828.  /*	'n' prefixes a count if number_pad is on */
829.  	{M('m'), TRUE, domonability},
830.  	{'N', TRUE, ddocall}, /* if number_pad is on */
831.  	{M('n'), TRUE, ddocall},
832.  	{M('N'), TRUE, ddocall},
833.  	{'o', FALSE, doopen},
834.  	{'O', TRUE, doset},
835.  	{M('o'), FALSE, dosacrifice},
836.  	{'p', FALSE, dopay},
837.  	{'P', FALSE, doputon},
838.  	{M('p'), TRUE, dopray},
839.  	{'q', FALSE, dodrink},
840.  	{'Q', TRUE, done2},
841.  #ifdef WEAPON_SKILLS
842.  	{M('q'), TRUE, check_weapon_skills},
843.  #endif /* WEAPON_SKILLS */
844.  	{'r', FALSE, doread},
845.  	{'R', FALSE, doremring},
846.  	{M('r'), FALSE, dorub},
847.  	{'s', TRUE, dosearch, "searching"},
848.  	{'S', TRUE, dosave},
849.  	{M('s'), FALSE, dosit},
850.  	{'t', FALSE, dothrow},
851.  	{'T', FALSE, dotakeoff},
852.  	{M('t'), TRUE, doturn},
853.  /*	'u', 'U' : go ne */
854.  	{'u', FALSE, dountrap}, /* if number_pad is on */
855.  	{M('u'), FALSE, dountrap},
856.  	{'v', TRUE, doversion},
857.  	{'V', TRUE, dohistory},
858.  	{M('v'), TRUE, doextversion},
859.  	{'w', FALSE, dowield},
860.  	{'W', FALSE, dowear},
861.  	{M('w'), FALSE, dowipe},
862.  	{'x', TRUE, dovspell},			/* Mike Stephenson */
863.  	{'X', TRUE, enter_explore_mode},
864.  /*	'y', 'Y' : go nw */
865.  	{'z', FALSE, dozap},
866.  	{'Z', TRUE, docast},
867.  	{'<', FALSE, doup},
868.  	{'>', FALSE, dodown},
869.  	{'/', TRUE, dowhatis},
870.  	{'&', TRUE, dowhatdoes},
871.  	{'?', TRUE, dohelp},
872.  	{M('?'), TRUE, doextlist},
873.  #ifdef SHELL
874.  	{'!', TRUE, dosh},
875.  #endif
876.  	{'.', TRUE, donull, "waiting"},
877.  	{' ', TRUE, donull, "waiting"},
878.  	{',', FALSE, dopickup},
879.  	{':', TRUE, dolook},
880.  	{';', TRUE, doquickwhatis},
881.  	{'^', TRUE, doidtrap},
882.  	{'\\', TRUE, dodiscovered},		/* Robert Viduya */
883.  	{'@', TRUE, dotogglepickup},
884.  	{WEAPON_SYM,  TRUE, doprwep},
885.  	{ARMOR_SYM,  TRUE, doprarm},
886.  	{RING_SYM,  TRUE, doprring},
887.  	{AMULET_SYM, TRUE, dopramulet},
888.  	{TOOL_SYM, TRUE, doprtool},
889.  	{GOLD_SYM, TRUE, doprgold},
890.  	{SPBOOK_SYM, TRUE, dovspell},			/* Mike Stephenson */
891.  	{'#', TRUE, doextcmd},
892.  	{0,0,0,0}
893.  };
894.  
895.  struct ext_func_tab extcmdlist[] = {
896.  	{"adjust", "adjust inventory letters", doorganize, TRUE},
897.  	{"chat", "talk to someone", dotalk, TRUE},	/* converse? */
898.  	{"dip", "dip an object into something", dodip, FALSE},
899.  #ifdef WEAPON_SKILLS
900.  	{"enhance", "advance a weapon skill", select_weapon_skill, TRUE},
901.  #endif /* WEAPON_SKILLS */
902.  	{"force", "force a lock", doforce, FALSE},
903.  	{"invoke", "invoke an object's powers", doinvoke, TRUE},
904.  	{"jump", "jump to a location", dojump, FALSE},
905.  	{"loot", "loot a box on the floor", doloot, FALSE},
906.  	{"monster", "use a monster's special ability", domonability, TRUE},
907.  	{"name", "name an item or type of object", ddocall, TRUE},
908.  	{"offer", "offer a sacrifice to the gods", dosacrifice, FALSE},
909.  	{"pray", "pray to the gods for help", dopray, TRUE},
910.  #ifdef WEAPON_SKILLS
911.  	{"qualifications", "check your weapon skills", check_weapon_skills, TRUE},
912.  #endif /* WEAPON_SKILLS */
913.  	{"rub", "rub a lamp", dorub, FALSE},
914.  	{"sit", "sit down", dosit, FALSE},
915.  	{"turn", "turn undead", doturn, TRUE},
916.  	{"untrap", "untrap something", dountrap, FALSE},
917.  	{"version", "list compile time options for this version of NetHack",
918.  		doextversion, TRUE},
919.  	{"wipe", "wipe off your face", dowipe, FALSE},
920.  	{"?", "get this list of extended commands", doextlist, TRUE},
921.  #if defined(WIZARD)
922.  	/*
923.  	 * There must be a blank entry here for every entry in the table
924.  	 * below.
925.  	 */
926.  	{(char *)0, (char *)0, donull, TRUE},
927.  	{(char *)0, (char *)0, donull, TRUE},
928.  	{(char *)0, (char *)0, donull, TRUE},
929.  	{(char *)0, (char *)0, donull, TRUE},
930.  	{(char *)0, (char *)0, donull, TRUE},
931.  #ifdef DEBUG
932.  	{(char *)0, (char *)0, donull, TRUE},
933.  #endif
934.  	{(char *)0, (char *)0, donull, TRUE},
935.  #endif
936.  	{(char *)0, (char *)0, donull, TRUE}
937.  };
938.  
939.  #if defined(WIZARD)
940.  static const struct ext_func_tab debug_extcmdlist[] = {
941.  	{"light sources", "show mobile light sources", wiz_light_sources, TRUE},
942.  	{"seenv", "show seen vectors", wiz_show_seenv, TRUE},
943.  	{"stats", "show memory statistics", wiz_show_stats, TRUE},
944.  	{"timeout", "look at timeout queue", wiz_timeout_queue, TRUE},
945.  	{"vision", "show vision array", wiz_show_vision, TRUE},
946.  #ifdef DEBUG
947.  	{"wizdebug", "wizard debug command", wiz_debug_cmd, TRUE},
948.  #endif
949.  	{"wmode", "show wall modes", wiz_show_wmodes, TRUE},
950.  	{(char *)0, (char *)0, donull, TRUE}
951.  };
952.  
953.  /*
954.   * Insert debug commands into the extended command list.  This function
955.   * assumes that the last entry will be the help entry.
956.   *
957.   * You must add entries in ext_func_tab every time you add one to the
958.   * debug_extcmdlist().
959.   */
960.  void
961.  add_debug_extended_commands()
962.  {
963.  	int i, j, k, n;
964.  
965.  	/* count the # of help entries */
966.  	for (n = 0; extcmdlist[n].ef_txt[0] != '?'; n++)
967.  	    ;
968.  
969.  	for (i = 0; debug_extcmdlist[i].ef_txt; i++) {
970.  	    for (j = 0; j < n; j++)
971.  		if (strcmp(debug_extcmdlist[i].ef_txt, extcmdlist[j].ef_txt) < 0) break;
972.  
973.  	    /* insert i'th debug entry into extcmdlist[j], pushing down  */
974.  	    for (k = n; k >= j; --k)
975.  		extcmdlist[k+1] = extcmdlist[k];
976.  	    extcmdlist[j] = debug_extcmdlist[i];
977.  	    n++;	/* now an extra entry */
978.  	}
979.  }
980.  
981.  
982.  static const char *template = "%-18s %4ld  %6ld";
983.  static const char *count_str = "                   count  bytes";
984.  static const char *separator = "------------------ -----  ------";
985.  
986.  static void
987.  count_obj(chain, total_count, total_size, top, recurse)
988.  	struct obj *chain;
989.  	long *total_count;
990.  	long *total_size;
991.  	boolean top;
992.  	boolean recurse;
993.  {
994.  	long count, size;
995.  	struct obj *obj;
996.  
997.  	for (count = size = 0, obj = chain; obj; obj = obj->nobj) {
998.  	    if (top) {
999.  		count++;
1000. 		size += sizeof(struct obj) + obj->onamelth;
1001. 	    }
1002. 	    if (recurse && obj->cobj)
1003. 		count_obj(obj->cobj, total_count, total_size, TRUE, TRUE);
1004. 	}
1005. 	*total_count += count;
1006. 	*total_size += size;
1007. }
1008. 
1009. static void
1010. obj_chain(win, src, chain, total_count, total_size)
1011. 	winid win;
1012. 	const char *src;
1013. 	struct obj *chain;
1014. 	long *total_count;
1015. 	long *total_size;
1016. {
1017. 	char buf[BUFSZ];
1018. 	long count = 0, size = 0;
1019. 
1020. 	count_obj(chain, &count, &size, TRUE, FALSE);
1021. 	*total_count += count;
1022. 	*total_size += size;
1023. 	Sprintf(buf, template, src, count, size);
1024. 	putstr(win, 0, buf);
1025. }
1026. 
1027. static void
1028. mon_invent_chain(win, src, chain, total_count, total_size)
1029. 	winid win;
1030. 	const char *src;
1031. 	struct monst *chain;
1032. 	long *total_count;
1033. 	long *total_size;
1034. {
1035. 	char buf[BUFSZ];
1036. 	long count = 0, size = 0;
1037. 	struct monst *mon;
1038. 
1039. 	for (mon = chain; mon; mon = mon->nmon)
1040. 	    count_obj(mon->minvent, &count, &size, TRUE, FALSE);
1041. 	*total_count += count;
1042. 	*total_size += size;
1043. 	Sprintf(buf, template, src, count, size);
1044. 	putstr(win, 0, buf);
1045. }
1046. 
1047. static void
1048. contained(win, src, total_count, total_size)
1049. 	winid win;
1050. 	const char *src;
1051. 	long *total_count;
1052. 	long *total_size;
1053. {
1054. 	char buf[BUFSZ];
1055. 	long count = 0, size = 0;
1056. 	struct monst *mon;
1057. 
1058. 	count_obj(invent, &count, &size, FALSE, TRUE);
1059. 	count_obj(fobj, &count, &size, FALSE, TRUE);
1060. 	count_obj(level.buriedobjlist, &count, &size, FALSE, TRUE);
1061. 	count_obj(migrating_objs, &count, &size, FALSE, TRUE);
1062. 	for (mon = fmon; mon; mon = mon->nmon)
1063. 	    count_obj(mon->minvent, &count, &size, FALSE, TRUE);
1064. 	for (mon = migrating_mons; mon; mon = mon->nmon)
1065. 	    count_obj(mon->minvent, &count, &size, FALSE, TRUE);
1066. 
1067. 	*total_count += count; *total_size += size;
1068. 
1069. 	Sprintf(buf, template, src, count, size);
1070. 	putstr(win, 0, buf);
1071. }
1072. 
1073. static void
1074. mon_chain(win, src, chain, total_count, total_size)
1075. 	winid win;
1076. 	const char *src;
1077. 	struct monst *chain;
1078. 	long *total_count;
1079. 	long *total_size;
1080. {
1081. 	char buf[BUFSZ];
1082. 	long count, size;
1083. 	struct monst *mon;
1084. 
1085. 	for (count = size = 0, mon = chain; mon; mon = mon->nmon) {
1086. 	    count++;
1087. 	    size += sizeof(struct monst) + mon->mxlth + mon->mnamelth;
1088. 	}
1089. 	*total_count += count;
1090. 	*total_size += size;
1091. 	Sprintf(buf, template, src, count, size);
1092. 	putstr(win, 0, buf);
1093. }
1094. 
1095. /*
1096.  * Display memory usage of all monsters and objects on the level.
1097.  */
1098. static int
1099. wiz_show_stats()
1100. {
1101. 	char buf[BUFSZ];
1102. 	winid win;
1103. 	long total_obj_size = 0, total_obj_count = 0;
1104. 	long total_mon_size = 0, total_mon_count = 0;
1105. 
1106. 	win = create_nhwindow(NHW_TEXT);
1107. 	putstr(win, 0, "Current memory statistics:");
1108. 	putstr(win, 0, "");
1109. 	Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj));
1110. 	putstr(win, 0, buf);
1111. 	putstr(win, 0, "");
1112. 	putstr(win, 0, count_str);
1113. 
1114. 	obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size);
1115. 	obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size);
1116. 	obj_chain(win, "buried", level.buriedobjlist,
1117. 				&total_obj_count, &total_obj_size);
1118. 	obj_chain(win, "migrating obj", migrating_objs,
1119. 				&total_obj_count, &total_obj_size);
1120. 	mon_invent_chain(win, "minvent", fmon,
1121. 				&total_obj_count,&total_obj_size);
1122. 	mon_invent_chain(win, "migrating minvent", migrating_mons,
1123. 				&total_obj_count, &total_obj_size);
1124. 
1125. 	contained(win, "contained",
1126. 				&total_obj_count, &total_obj_size);
1127. 
1128. 	putstr(win, 0, separator);
1129. 	Sprintf(buf, template, "Total", total_obj_count, total_obj_size);
1130. 	putstr(win, 0, buf);
1131. 
1132. 	putstr(win, 0, "");
1133. 	putstr(win, 0, "");
1134. 	Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst));
1135. 	putstr(win, 0, buf);
1136. 	putstr(win, 0, "");
1137. 
1138. 	mon_chain(win, "fmon", fmon,
1139. 				&total_mon_count, &total_mon_size);
1140. 	mon_chain(win, "migrating", migrating_mons,
1141. 				&total_mon_count, &total_mon_size);
1142. 
1143. 	putstr(win, 0, separator);
1144. 	Sprintf(buf, template, "Total", total_mon_count, total_mon_size);
1145. 	putstr(win, 0, buf);
1146. 
1147. #ifdef __BORLANDC__
1148. 	show_borlandc_stats(win);
1149. #endif
1150. 
1151. 	display_nhwindow(win, FALSE);
1152. 	destroy_nhwindow(win);
1153. 	return 0;
1154. }
1155. 
1156. void
1157. sanity_check()
1158. {
1159. 	obj_sanity_check();
1160. 	timer_sanity_check();
1161. }
1162. 
1163. #endif /* WIZARD */
1164. 
1165. #define unctrl(c)	((c) <= C('z') ? (0x60 | (c)) : (c))
1166. #define unmeta(c)	(0x7f & (c))
1167. 
1168. 
1169. void
1170. rhack(cmd)
1171. register char *cmd;
1172. {
1173. 	boolean do_walk, do_rush, prefix_seen, bad_command,
1174. 		firsttime = (cmd == 0);
1175. 
1176. 	if (firsttime) {
1177. 		flags.nopick = 0;
1178. 		cmd = parse();
1179. 	}
1180. 	if (*cmd == '\033') {
1181. 		flags.move = FALSE;
1182. 		return;
1183. 	}
1184. #ifdef REDO
1185. 	if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
1186. 		in_doagain = TRUE;
1187. 		stail = 0;
1188. 		rhack((char *)0);	/* read and execute command */
1189. 		in_doagain = FALSE;
1190. 		return;
1191. 	}
1192. 	/* Special case of *cmd == ' ' handled better below */
1193. 	if(!*cmd || *cmd == (char)0377) {
1194. #else
1195. 	if(!*cmd || *cmd == (char)0377 ||
1196. 	   (!flags.rest_on_space && *cmd == ' ')) {
1197. #endif
1198. 		nhbell();
1199. 		flags.move = FALSE;
1200. 		return;		/* probably we just had an interrupt */
1201. 	}
1202. 
1203. 	/* handle most movement commands */
1204. 	do_walk = do_rush = prefix_seen = FALSE;
1205. 	switch (*cmd) {
1206. 	 case 'g':  if (movecmd(cmd[1])) {
1207. 			flags.run = 2;
1208. 			do_rush = TRUE;
1209. 		    } else
1210. 			prefix_seen = TRUE;
1211. 		    break;
1212. 	 case '5':  if (!flags.num_pad) break;	/* else FALLTHRU */
1213. 	 case 'G':  if (movecmd(lowc(cmd[1]))) {
1214. 			flags.run = 3;
1215. 			do_rush = TRUE;
1216. 		    } else
1217. 			prefix_seen = TRUE;
1218. 		    break;
1219. 	 case '-':  if (!flags.num_pad) break;	/* else FALLTHRU */
1220. 	 case 'm':  if (movecmd(cmd[1]) || u.dz) {
1221. 			flags.run = 0;
1222. 			flags.nopick = 1;
1223. 			if (!u.dz) do_walk = TRUE;
1224. 			else cmd[0] = cmd[1];	/* "m<" or "m>" */
1225. 		    } else
1226. 			prefix_seen = TRUE;
1227. 		    break;
1228. 	 case 'M':  if (movecmd(lowc(cmd[1]))) {
1229. 			flags.run = 1;
1230. 			flags.nopick = 1;
1231. 			do_rush = TRUE;
1232. 		    } else
1233. 			prefix_seen = TRUE;
1234. 		    break;
1235. 	 case '0':  if (!flags.num_pad) break;
1236. 		    (void)ddoinv(); /* a convenience borrowed from the PC */
1237. 		    flags.move = FALSE;
1238. 		    multi = 0;
1239. 		    return;
1240. 	 default:   if (movecmd(*cmd)) {	/* ordinary movement */
1241. 			do_walk = TRUE;
1242. 		    } else if (movecmd(flags.num_pad ?
1243. 				       unmeta(*cmd) : lowc(*cmd))) {
1244. 			flags.run = 1;
1245. 			do_rush = TRUE;
1246. 		    } else if (movecmd(unctrl(*cmd))) {
1247. 			flags.run = 3;
1248. 			do_rush = TRUE;
1249. 		    }
1250. 		    break;
1251. 	}
1252. 	if (do_walk) {
1253. 	    if (multi) flags.mv = TRUE;
1254. 	    domove();
1255. 	    return;
1256. 	} else if (do_rush) {
1257. 	    if (firsttime) {
1258. 		if (!multi) multi = max(COLNO,ROWNO);
1259. 		u.last_str_turn = 0;
1260. 	    }
1261. 	    flags.mv = TRUE;
1262. 	    domove();
1263. 	    return;
1264. 	} else if (prefix_seen && cmd[1] == '\033') {	/* <prefix><escape> */
1265. 	    /* don't report "unknown command" for change of heart... */
1266. 	    bad_command = FALSE;
1267. 	} else if (*cmd == ' ' && !flags.rest_on_space) {
1268. 	    bad_command = TRUE;		/* skip cmdlist[] loop */
1269. 
1270. 	/* handle all other commands */
1271. 	} else {
1272. 	    register const struct func_tab *tlist;
1273. 	    int res, NDECL((*func));
1274. 
1275. 	    for (tlist = cmdlist; tlist->f_char; tlist++) {
1276. 		if ((*cmd & 0xff) != (tlist->f_char & 0xff)) continue;
1277. 
1278. 		if (u.uburied && !tlist->can_if_buried) {
1279. 		    You_cant("do that while you are buried!");
1280. 		    res = 0;
1281. 		} else {
1282. 		    /* we discard 'const' because some compilers seem to have
1283. 		       trouble with the pointer passed to set_occupation() */
1284. 		    func = ((struct func_tab *)tlist)->f_funct;
1285. 		    if (tlist->f_text && !occupation && multi)
1286. 			set_occupation(func, tlist->f_text, multi);
1287. 		    res = (*func)();		/* perform the command */
1288. 		}
1289. 		if (!res) {
1290. 		    flags.move = FALSE;
1291. 		    multi = 0;
1292. 		}
1293. 		return;
1294. 	    }
1295. 	    /* if we reach here, cmd wasn't found in cmdlist[] */
1296. 	    bad_command = TRUE;
1297. 	}
1298. 
1299. 	if (bad_command) {
1300. 	    char expcmd[10];
1301. 	    register char *cp = expcmd;
1302. 
1303. 	    while (*cmd && (int)(cp - expcmd) < (int)(sizeof expcmd - 3)) {
1304. 		if (*cmd >= 040 && *cmd < 0177) {
1305. 		    *cp++ = *cmd++;
1306. 		} else if (*cmd & 0200) {
1307. 		    *cp++ = 'M';
1308. 		    *cp++ = '-';
1309. 		    *cp++ = *cmd++ &= ~0200;
1310. 		} else {
1311. 		    *cp++ = '^';
1312. 		    *cp++ = *cmd++ ^ 0100;
1313. 		}
1314. 	    }
1315. 	    *cp = '\0';
1316. 	    Norep("Unknown command '%s'.", expcmd);
1317. 	}
1318. 	/* didn't move */
1319. 	flags.move = FALSE;
1320. 	multi = 0;
1321. 	return;
1322. }
1323. 
1324. int
1325. xytod(x, y)	/* convert an x,y pair into a direction code */
1326. schar x, y;
1327. {
1328. 	register int dd;
1329. 
1330. 	for(dd = 0; dd < 8; dd++)
1331. 	    if(x == xdir[dd] && y == ydir[dd]) return dd;
1332. 
1333. 	return -1;
1334. }
1335. 
1336. void
1337. dtoxy(cc,dd)	/* convert a direction code into an x,y pair */
1338. coord *cc;
1339. register int dd;
1340. {
1341. 	cc->x = xdir[dd];
1342. 	cc->y = ydir[dd];
1343. 	return;
1344. }
1345. 
1346. int
1347. movecmd(sym)	/* also sets u.dz, but returns false for <> */
1348. char sym;
1349. {
1350. 	register const char *dp;
1351. 	register const char *sdp;
1352. 	if(flags.num_pad) sdp = ndir; else sdp = sdir;	/* DICE workaround */
1353. 
1354. 	u.dz = 0;
1355. 	if(!(dp = index(sdp, sym))) return 0;
1356. 	u.dx = xdir[dp-sdp];
1357. 	u.dy = ydir[dp-sdp];
1358. 	u.dz = zdir[dp-sdp];
1359. 	if (u.dx && u.dy && u.umonnum == PM_GRID_BUG) {
1360. 		u.dx = u.dy = 0;
1361. 		return 0;
1362. 	}
1363. 	return !u.dz;
1364. }
1365. 
1366. int
1367. getdir(s)
1368. const char *s;
1369. {
1370. 	char dirsym;
1371. 
1372. #ifdef REDO	
1373. 	if(in_doagain)
1374. 	    dirsym = readchar();
1375. 	else
1376. #endif
1377. 	    dirsym = yn_function (s ? s : "In what direction?",
1378. 					(char *)0, '\0');
1379. #ifdef REDO
1380. 	savech(dirsym);
1381. #endif
1382. 	if(dirsym == '.' || dirsym == 's')
1383. 		u.dx = u.dy = u.dz = 0;
1384. 	else if(!movecmd(dirsym) && !u.dz) {
1385. 		if(!index(quitchars, dirsym))
1386. 			pline("What a strange direction!");
1387. 		return 0;
1388. 	}
1389. 	if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir();
1390. 	return 1;
1391. }
1392. 
1393. #endif /* OVL1 */
1394. #ifdef OVLB
1395. 
1396. void
1397. confdir()
1398. {
1399. 	register int x = (u.umonnum == PM_GRID_BUG) ? 2*rn2(4) : rn2(8);
1400. 	u.dx = xdir[x];
1401. 	u.dy = ydir[x];
1402. 	return;
1403. }
1404. 
1405. #endif /* OVLB */
1406. #ifdef OVL0
1407. 
1408. int
1409. isok(x,y)
1410. register int x, y;
1411. {
1412. 	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
1413. 	return x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1;
1414. }
1415. 
1416. static NEARDATA int last_multi;
1417. 
1418. /*
1419.  * convert a MAP window position into a movecmd
1420.  */
1421. int
1422. click_to_cmd(x, y, mod)
1423.     int x, y, mod;
1424. {
1425.     x -= u.ux;
1426.     y -= u.uy;
1427.     /* convert without using floating point, allowing sloppy clicking */
1428.     if(x > 2*abs(y))
1429. 	x = 1, y = 0;
1430.     else if(y > 2*abs(x))
1431. 	x = 0, y = 1;
1432.     else if(x < -2*abs(y))
1433. 	x = -1, y = 0;
1434.     else if(y < -2*abs(x))
1435. 	x = 0, y = -1;
1436.     else
1437. 	x = sgn(x), y = sgn(y);
1438. 
1439.     if(x == 0 && y == 0)	/* map click on player to "rest" command */
1440. 	return '.';
1441. 
1442.     x = xytod(x, y);
1443.     if(mod == CLICK_1) {
1444. 	return (flags.num_pad ? ndir[x] : sdir[x]);
1445.     } else {
1446. 	return (flags.num_pad ? M(ndir[x]) :
1447. 		(sdir[x] - 'a' + 'A')); /* run command */
1448.     }
1449. }
1450. 
1451. STATIC_OVL char *
1452. parse()
1453. {
1454. #ifdef LINT	/* static char in_line[COLNO]; */
1455. 	char in_line[COLNO];
1456. #else
1457. 	static char in_line[COLNO];
1458. #endif
1459. 	register int foo;
1460. 	boolean prezero = FALSE;
1461. 
1462. 	multi = 0;
1463. 	flags.move = 1;
1464. 	flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
1465. 
1466. 	if (!flags.num_pad || (foo = readchar()) == 'n')
1467. 	    for (;;) {
1468. 		foo = readchar();
1469. 		if (foo >= '0' && foo <= '9') {
1470. 		    multi = 10 * multi + foo - '0';
1471. 		    if (multi < 0 || multi >= LARGEST_INT) multi = LARGEST_INT;
1472. 		    if (multi > 9) {
1473. 			clear_nhwindow(WIN_MESSAGE);
1474. 			Sprintf(in_line, "Count: %d", multi);
1475. 			pline(in_line);
1476. 			mark_synch();
1477. 		    }
1478. 		    last_multi = multi;
1479. 		    if (!multi && foo == '0') prezero = TRUE;
1480. 		} else break;	/* not a digit */
1481. 	    }
1482. 
1483. 	if (foo == '\033') {   /* esc cancels count (TH) */
1484. 	    clear_nhwindow(WIN_MESSAGE);
1485. 	    multi = last_multi = 0;
1486. # ifdef REDO
1487. 	} else if (foo == DOAGAIN || in_doagain) {
1488. 	    multi = last_multi;
1489. 	} else {
1490. 	    last_multi = multi;
1491. 	    savech(0);	/* reset input queue */
1492. 	    savech((char)foo);
1493. # endif
1494. 	}
1495. 
1496. 	if (multi) {
1497. 	    multi--;
1498. 	    save_cm = in_line;
1499. 	} else {
1500. 	    save_cm = (char *)0;
1501. 	}
1502. 	in_line[0] = foo;
1503. 	in_line[1] = '\0';
1504. 	if (foo == 'g' || foo == 'G' || (flags.num_pad && foo == '5') ||
1505. 	    foo == 'm' || foo == 'M') {
1506. 	    foo = readchar();
1507. #ifdef REDO
1508. 	    savech((char)foo);
1509. #endif
1510. 	    in_line[1] = foo;
1511. 	    in_line[2] = 0;
1512. 	}
1513. 	clear_nhwindow(WIN_MESSAGE);
1514. 	if (prezero) in_line[0] = '\033';
1515. 	return(in_line);
1516. }
1517. 
1518. #endif /* OVL0 */
1519. #ifdef OVLB
1520. 
1521. #ifdef UNIX
1522. static
1523. void
1524. end_of_input()
1525. {
1526. 	exit_nhwindows("End of input?");
1527. #ifndef NOSAVEONHANGUP
1528. 	if (!program_state.done_hup++)
1529. 	    (void) dosave0();
1530. #endif
1531. 	clearlocks();
1532. 	terminate(EXIT_SUCCESS);
1533. }
1534. #endif
1535. 
1536. #endif /* OVLB */
1537. #ifdef OVL0
1538. 
1539. char
1540. readchar()
1541. {
1542. 	register int sym;
1543. 	int x, y, mod;
1544. 
1545. #ifdef REDO
1546. 	sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod);
1547. #else
1548. 	sym = Getchar();
1549. #endif
1550. 
1551. #ifdef UNIX
1552. # ifdef NR_OF_EOFS
1553. 	if (sym == EOF) {
1554. 	    register int cnt = NR_OF_EOFS;
1555. 	  /*
1556. 	   * Some SYSV systems seem to return EOFs for various reasons
1557. 	   * (?like when one hits break or for interrupted systemcalls?),
1558. 	   * and we must see several before we quit.
1559. 	   */
1560. 	    do {
1561. 		clearerr(stdin);	/* omit if clearerr is undefined */
1562. 		sym = Getchar();
1563. 	    } while (--cnt && sym == EOF);
1564. 	}
1565. # endif /* NR_OF_EOFS */
1566. 	if (sym == EOF)
1567. 	    end_of_input();
1568. #endif /* UNIX */
1569. 
1570. 	if(sym == 0) /* click event */
1571. 	    sym = click_to_cmd(x, y, mod);
1572. 	return((char) sym);
1573. }
1574. #endif /* OVL0 */
1575. 
1576. /*cmd.c*/

Also on Fandom

Random Wiki