Source:NetHack 3.1.0/cmd.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to cmd.c from the source code of NetHack 3.1.0.

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

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

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

1.    /*	SCCS Id: @(#)cmd.c	3.1	92/11/25	*/
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.    
8.    /*
9.     * Some systems may have getchar() return EOF for various reasons, and
10.    * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
11.    */
12.   #if defined(SYSV) || defined(DGUX) || defined(HPUX)
13.   #define	NR_OF_EOFS	20
14.   #endif
15.   
16.   #ifdef DUMB	/* stuff commented out in extern.h, but needed here */
17.   extern int NDECL(doapply); /**/
18.   extern int NDECL(dorub); /**/
19.   extern int NDECL(dojump); /**/
20.   extern int NDECL(doextlist); /**/
21.   extern int NDECL(dodrop); /**/
22.   extern int NDECL(doddrop); /**/
23.   extern int NDECL(dodown); /**/
24.   extern int NDECL(doup); /**/
25.   extern int NDECL(donull); /**/
26.   extern int NDECL(dowipe); /**/
27.   extern int NDECL(do_mname); /**/
28.   extern int NDECL(ddocall); /**/
29.   extern int NDECL(dotakeoff); /**/
30.   extern int NDECL(doremring); /**/
31.   extern int NDECL(dowear); /**/
32.   extern int NDECL(doputon); /**/
33.   extern int NDECL(doddoremarm); /**/
34.   extern int NDECL(dokick); /**/
35.   extern int NDECL(dothrow); /**/
36.   extern int NDECL(doeat); /**/
37.   extern int NDECL(done2); /**/
38.   extern int NDECL(doengrave); /**/
39.   extern int NDECL(dopickup); /**/
40.   extern int NDECL(ddoinv); /**/
41.   extern int NDECL(dotypeinv); /**/
42.   extern int NDECL(dolook); /**/
43.   extern int NDECL(doprgold); /**/
44.   extern int NDECL(doprwep); /**/
45.   extern int NDECL(doprarm); /**/
46.   extern int NDECL(doprring); /**/
47.   extern int NDECL(dopramulet); /**/
48.   extern int NDECL(doprtool); /**/
49.   extern int NDECL(dosuspend); /**/
50.   extern int NDECL(doforce); /**/
51.   extern int NDECL(doopen); /**/
52.   extern int NDECL(doclose); /**/
53.   extern int NDECL(dosh); /**/
54.   extern int NDECL(dodiscovered); /**/
55.   extern int NDECL(doset); /**/
56.   extern int NDECL(dotogglepickup); /**/
57.   extern int NDECL(dowhatis); /**/
58.   extern int NDECL(doquickwhatis); /**/
59.   extern int NDECL(dowhatdoes); /**/
60.   extern int NDECL(dohelp); /**/
61.   extern int NDECL(dohistory); /**/
62.   extern int NDECL(doloot); /**/
63.   extern int NDECL(dodrink); /**/
64.   extern int NDECL(dodip); /**/
65.   extern int NDECL(dosacrifice); /**/
66.   extern int NDECL(dopray); /**/
67.   extern int NDECL(doturn); /**/
68.   extern int NDECL(doredraw); /**/
69.   extern int NDECL(doread); /**/
70.   extern int NDECL(dosave); /**/
71.   extern int NDECL(dosearch); /**/
72.   extern int NDECL(doidtrap); /**/
73.   extern int NDECL(dopay); /**/
74.   extern int NDECL(dosit); /**/
75.   extern int NDECL(dotalk); /**/
76.   extern int NDECL(docast); /**/
77.   extern int NDECL(dovspell); /**/
78.   extern int NDECL(dotele); /**/
79.   extern int NDECL(dountrap); /**/
80.   extern int NDECL(doversion); /**/
81.   extern int NDECL(doextversion); /**/
82.   extern int NDECL(dowield); /**/
83.   extern int NDECL(dozap); /**/
84.   extern int NDECL(doorganize); /**/
85.   #endif /* DUMB */
86.   
87.   #ifdef OVL1
88.   static int NDECL((*timed_occ_fn));
89.   #endif /* OVL1 */
90.   
91.   STATIC_PTR int NDECL(doprev_message);
92.   STATIC_PTR int NDECL(timed_occupation);
93.   STATIC_PTR int NDECL(doextcmd);
94.   # ifdef POLYSELF
95.   STATIC_PTR int NDECL(domonability);
96.   # endif
97.   # ifdef WIZARD
98.   STATIC_PTR int NDECL(wiz_wish);
99.   STATIC_PTR int NDECL(wiz_identify);
100.  STATIC_PTR int NDECL(wiz_map);
101.  STATIC_PTR int NDECL(wiz_genesis);
102.  STATIC_PTR int NDECL(wiz_where);
103.  STATIC_PTR int NDECL(wiz_detect);
104.  STATIC_PTR int NDECL(wiz_level_tele);
105.  # endif
106.  # ifdef EXPLORE_MODE
107.  STATIC_PTR int NDECL(enter_explore_mode);
108.  # endif
109.  # if defined(WIZARD) || defined(EXPLORE_MODE)
110.  STATIC_PTR int NDECL(wiz_attributes);
111.  # endif
112.  
113.  #ifdef OVLB
114.  static void FDECL(enlght_line, (const char *,const char *,const char *));
115.  #ifdef UNIX
116.  static void NDECL(end_of_input);
117.  #endif
118.  #endif /* OVLB */
119.  
120.  #ifdef OVL0
121.  static int FDECL(click_to_cmd, (int,int,int));
122.  #endif /* OVL0 */
123.  
124.  STATIC_OVL char *NDECL(parse);
125.  
126.  #ifdef UNIX
127.  extern boolean hu;
128.  #endif
129.  
130.  #ifdef OVL1
131.  
132.  STATIC_PTR int
133.  doprev_message()
134.  {
135.      return nh_doprev_message();
136.  }
137.  
138.  /* Count down by decrementing multi */
139.  STATIC_PTR int
140.  timed_occupation() {
141.  	(*timed_occ_fn)();
142.  	if (multi > 0)
143.  		multi--;
144.  	return multi > 0;
145.  }
146.  
147.  /* If you have moved since initially setting some occupations, they
148.   * now shouldn't be able to restart.
149.   *
150.   * The basic rule is that if you are carrying it, you can continue
151.   * since it is with you.  If you are acting on something at a distance,
152.   * your orientation to it must have changed when you moved.
153.   *
154.   * The exception to this is taking off items, since they can be taken
155.   * off in a number of ways in the intervening time, screwing up ordering.
156.   *
157.   *	Currently:	Take off all armor.
158.   *			Picking Locks / Forcing Chests.
159.   */
160.  void
161.  reset_occupations() {
162.  
163.  	reset_remarm();
164.  	reset_pick();
165.  }
166.  
167.  /* If a time is given, use it to timeout this function, otherwise the
168.   * function times out by its own means.
169.   */
170.  void
171.  set_occupation(fn, txt, xtime)
172.  int NDECL((*fn));
173.  const char *txt;
174.  int xtime;
175.  {
176.  	if (xtime) {
177.  		occupation = timed_occupation;
178.  		timed_occ_fn = fn;
179.  	} else
180.  		occupation = fn;
181.  	occtxt = txt;
182.  	occtime = 0;
183.  	return;
184.  }
185.  
186.  #ifdef REDO
187.  
188.  static char NDECL(popch);
189.  
190.  /* Provide a means to redo the last command.  The flag `in_doagain' is set
191.   * to true while redoing the command.  This flag is tested in commands that
192.   * require additional input (like `throw' which requires a thing and a
193.   * direction), and the input prompt is not shown.  Also, while in_doagain is
194.   * TRUE, no keystrokes can be saved into the saveq.
195.   */
196.  #define BSIZE 20
197.  static char pushq[BSIZE], saveq[BSIZE];
198.  static int NEARDATA phead, NEARDATA ptail, NEARDATA shead, NEARDATA stail;
199.  
200.  static char
201.  popch() {
202.  	/* If occupied, return '\0', letting tgetch know a character should
203.  	 * be read from the keyboard.  If the character read is not the
204.  	 * ABORT character (as checked in pcmain.c), that character will be
205.  	 * pushed back on the pushq.
206.  	 */
207.  	if (occupation) return '\0';
208.  	if (in_doagain) return (shead != stail) ? saveq[stail++] : '\0';
209.  	else		return (phead != ptail) ? pushq[ptail++] : '\0';
210.  }
211.  
212.  char
213.  pgetchar() {		/* curtesy of aeb@cwi.nl */
214.  	register int ch;
215.  
216.  	if(!(ch = popch()))
217.  		ch = nhgetch();
218.  	return(ch);
219.  }
220.  
221.  /* A ch == 0 resets the pushq */
222.  void
223.  pushch(ch)
224.  char ch;
225.  {
226.  	if (!ch)
227.  		phead = ptail = 0;
228.  	if (phead < BSIZE)
229.  		pushq[phead++] = ch;
230.  	return;
231.  }
232.  
233.  /* A ch == 0 resets the saveq.	Only save keystrokes when not
234.   * replaying a previous command.
235.   */
236.  void
237.  savech(ch)
238.  char ch;
239.  {
240.  	if (!in_doagain) {
241.  		if (!ch)
242.  			phead = ptail = shead = stail = 0;
243.  		else if (shead < BSIZE)
244.  			saveq[shead++] = ch;
245.  	}
246.  	return;
247.  }
248.  #endif /* REDO */
249.  
250.  #endif /* OVL1 */
251.  #ifdef OVLB
252.  
253.  STATIC_PTR int
254.  doextcmd()	/* here after # - now read a full-word command */
255.  {
256.  	char buf[BUFSZ];
257.  	register const struct ext_func_tab *efp = extcmdlist;
258.  again:
259.  #ifdef COM_COMPL
260.  	get_ext_cmd(buf);
261.  #else
262.  	getlin("#", buf);
263.  #endif
264.  	clear_nhwindow(WIN_MESSAGE);
265.  	if(buf[0] == '\0' || buf[0] == '\033')
266.  		return 0;
267.  	if(buf[0] == '?') {
268.  		(void) doextlist();
269.  		goto again;
270.  	}
271.  	while(efp->ef_txt) {
272.  		if(!strncmpi(efp->ef_txt, buf,BUFSIZ))
273.  			return (*(efp->ef_funct))();
274.  		efp++;
275.  	}
276.  	pline("%s: unknown extended command.", buf);
277.  	return 0;
278.  }
279.  
280.  int
281.  doextlist()	/* here after #? - now list all full-word commands */
282.  {
283.  	register const struct ext_func_tab *efp;
284.  	char	 buf[BUFSZ];
285.  	winid datawin;
286.  
287.  	datawin = create_nhwindow(NHW_TEXT);
288.  	putstr(datawin, 0, "");
289.  	putstr(datawin, 0, "            Extended Commands List");
290.  	putstr(datawin, 0, "");
291.  #ifdef COM_COMPL
292.  	putstr(datawin, 0, "    Press '#', then type (first letter only):");
293.  #else
294.  	putstr(datawin, 0, "    Press '#', then type:");
295.  #endif
296.  	putstr(datawin, 0, "");
297.  
298.  	for(efp = extcmdlist; efp->ef_txt; efp++) {
299.  		Sprintf(buf, "    %-8s  - %s.", efp->ef_txt, efp->ef_desc);
300.  		putstr(datawin, 0, buf);
301.  	}
302.  	display_nhwindow(datawin, FALSE);
303.  	destroy_nhwindow(datawin);
304.  	return 0;
305.  }
306.  
307.  #ifdef POLYSELF
308.  STATIC_PTR int
309.  domonability()
310.  {
311.  	if (can_breathe(uasmon)) return dobreathe();
312.  	else if (attacktype(uasmon, AT_SPIT)) return dospit();
313.  	else if (u.usym == S_NYMPH) return doremove();
314.  	else if (u.usym == S_UMBER) return doconfuse();
315.  	else if (is_were(uasmon)) return dosummon();
316.  	else if (webmaker(uasmon)) return dospinweb();
317.  	else if (is_hider(uasmon)) return dohide();
318.  	else if(u.umonnum == PM_GREMLIN) {
319.  	    if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
320.  		struct monst *mtmp;
321.  		if ((mtmp = cloneu()) != 0) {
322.  			mtmp->mhpmax = (u.mhmax /= 2);
323.  			You("multiply.");
324.  			dryup(u.ux,u.uy);
325.  		}
326.  	    } else pline("There is no fountain here.");
327.  	}
328.  	else if (u.usym == S_UNICORN) {
329.  	    use_unicorn_horn((struct obj *)0);
330.  	    return 1;
331.  	} else if (u.umonnum == PM_MIND_FLAYER) return domindblast();
332.  	else if (uasmon->msound == MS_SHRIEK) {
333.  	    You("shriek.");
334.  	    aggravate();
335.  	} else if (u.umonnum >= 0)
336.  		pline("Any special ability you may have is purely reflexive.");
337.  	else You("don't have a special ability!");
338.  	return 0;
339.  }
340.  #endif
341.  
342.  #ifdef EXPLORE_MODE
343.  STATIC_PTR int
344.  enter_explore_mode()
345.  {
346.  	if(!discover && !wizard) {
347.  		pline("Beware!  From discovery mode there will be no return to normal game.");
348.  		if (yn("Do you want to enter discovery mode?") == 'y') {
349.  			clear_nhwindow(WIN_MESSAGE);
350.  			You("are now in non-scoring discovery mode.");
351.  			discover = TRUE;
352.  		}
353.  		else {
354.  			clear_nhwindow(WIN_MESSAGE);
355.  			pline("Resuming normal game.");
356.  		}
357.  	}
358.  	return 0;
359.  }
360.  #endif
361.  
362.  #ifdef WIZARD
363.  STATIC_PTR int
364.  wiz_wish()	/* Unlimited wishes for debug mode by Paul Polderman */
365.  {
366.  	if (wizard) {
367.  	    makewish();
368.  	    (void) encumber_msg();
369.  	} else
370.  	    pline("Unavailable command '^W'.");
371.  	return 0;
372.  }
373.  
374.  STATIC_PTR int
375.  wiz_identify()
376.  {
377.  	struct obj *obj;
378.  
379.  	if (!wizard)
380.  		pline("Unavailable command '^I'.");
381.  	else {
382.  		for (obj = invent; obj; obj = obj->nobj)
383.  			if (!objects[obj->otyp].oc_name_known || !obj->known
384.  						|| !obj->dknown || !obj->bknown)
385.  				(void) identify(obj);
386.  	}
387.  	return 0;
388.  }
389.  
390.  STATIC_PTR int
391.  wiz_map()
392.  {
393.  	if (wizard)	do_mapping();
394.  	else		pline("Unavailable command '^F'.");
395.  	return 0;
396.  }
397.  
398.  STATIC_PTR int
399.  wiz_genesis()
400.  {
401.  	if (wizard)	(void) create_particular();
402.  	else		pline("Unavailable command '^G'.");
403.  	return 0;
404.  }
405.  
406.  STATIC_PTR int
407.  wiz_where()
408.  {
409.  	if (wizard) print_dungeon();
410.  	else	    pline("Unavailable command '^O'.");
411.  	return 0;
412.  }
413.  
414.  STATIC_PTR int
415.  wiz_detect()
416.  {
417.  	if(wizard)  (void) findit();
418.  	else	    pline("Unavailable command '^E'.");
419.  	return 0;
420.  }
421.  
422.  STATIC_PTR int
423.  wiz_level_tele()
424.  {
425.  	if (wizard)	level_tele();
426.  	else		pline("Unavailable command '^V'.");
427.  	return 0;
428.  }
429.  
430.  #endif /* WIZARD */
431.  
432.  /* -enlightenment- */
433.  static winid en_win;
434.  static const char
435.  	*You_ = "You ",
436.  	*are  = "are ",  *were  = "were ",
437.  	*have = "have ", *had   = "had ",
438.  	*can  = "can ",  *could = "could ";
439.  
440.  #define enl_msg(prefix,present,past,suffix) \
441.  			enlght_line(prefix, final ? past : present, suffix)
442.  #define you_are(attr)	enl_msg(You_,are,were,attr)
443.  #define you_have(attr)	enl_msg(You_,have,had,attr)
444.  #define you_can(attr)	enl_msg(You_,can,could,attr)
445.  
446.  static void
447.  enlght_line(start, middle, end)
448.  const char *start, *middle, *end;
449.  {
450.  	char buf[BUFSZ];
451.  
452.  	Sprintf(buf, "%s%s%s.", start, middle, end);
453.  	putstr(en_win, 0, buf);
454.  }
455.  
456.  void
457.  enlightenment(final)
458.  boolean final;
459.  {
460.  	int ltmp;
461.  	char buf[BUFSZ];
462.  
463.  	en_win = create_nhwindow(NHW_MENU);
464.  	putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:");
465.  	putstr(en_win, 0, "");
466.  
467.  	/* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
468.  	if (u.ualign.record >= 20)	you_are("piously aligned");
469.  	else if (u.ualign.record > 13)	you_are("devoutly aligned");
470.  	else if (u.ualign.record > 8)	you_are("fervently aligned");
471.  	else if (u.ualign.record > 3)	you_are("stridently aligned");
472.  	else if (u.ualign.record == 3)	you_are("aligned");
473.  	else if (u.ualign.record > 0)	you_are("haltingly aligned");
474.  	else if (u.ualign.record == 0)	you_are("nominally aligned");
475.  	else if (u.ualign.record >= -3)	you_have("strayed");
476.  	else if (u.ualign.record >= -8)	you_have("sinned");
477.  	else you_have("transgressed");
478.  #ifdef WIZARD
479.  	if (wizard) {
480.  		Sprintf(buf, " %d", u.ualign.record);
481.  		enl_msg("Your alignment ", "is", "was", buf);
482.  	}
483.  #endif
484.  
485.  	if (Telepat) you_are("telepathic");
486.  	if (Searching) you_have("automatic searching");
487.  	if (Teleportation) you_can("teleport");
488.  	if (Teleport_control) you_have("teleport control");
489.  	if (See_invisible) enl_msg(You_, "see", "saw", " invisible");
490.  	if (Invisible) you_are("invisible");
491.  	else if (Invis) you_are("invisible to others");
492.  	if (Fast) you_are((Fast & ~INTRINSIC) ? "very fast" : "fast");
493.  	if (Stealth) you_are("stealthy");
494.  	if (Regeneration) enl_msg("You regenerate", "", "d", "");
495.  	if (Hunger) you_have("hunger");
496.  	if (Conflict) enl_msg("You cause", "", "d", " conflict");
497.  	if (Aggravate_monster) enl_msg("You aggravate", "", "d", " monsters");
498.  	if (Poison_resistance) you_are("poison resistant");
499.  	if (Fire_resistance) you_are("fire resistant");
500.  	if (Cold_resistance) you_are("cold resistant");
501.  	if (Shock_resistance) you_are("shock resistant");
502.  	if (Sleep_resistance) you_are("sleep resistant");
503.  	if (Disint_resistance) you_are("disintegration-resistant");
504.  	if (Protection_from_shape_changers)
505.  		you_are("protected from shape changers");
506.  #ifdef POLYSELF
507.  	if (Polymorph) you_are("polymorphing");
508.  	if (Polymorph_control) you_have("polymorph control");
509.  #endif
510.  	if (HHalluc_resistance)
511.  		enl_msg("You resist", "", "ed", " hallucinations");
512.  	if (final) {
513.  		if (Hallucination) you_are("hallucinating");
514.  		if (Stunned) you_are("stunned");
515.  		if (Confusion) you_are("confused");
516.  		if (Sick) you_are("sick");
517.  		if (Blinded) you_are("blinded");
518.  	}
519.  	if (Wounded_legs) {
520.  		Sprintf(buf, "wounded %s", makeplural(body_part(LEG)));
521.  		you_have(buf);
522.  	}
523.  	if (Glib) {
524.  		Sprintf(buf, "slippery %s", makeplural(body_part(FINGER)));
525.  		you_have(buf);
526.  	}
527.  	if (Strangled) you_are("being strangled");
528.  	if (Stoned) you_are("turning to stone");
529.  	if (Lifesaved)
530.  		enl_msg("Your life ", "will be", "would have been", " saved");
531.  	if (Adornment) you_are("adorned");
532.  	if (Warning) you_are("warned");
533.  	if (Protection) you_are("protected");
534.  	if (Reflecting) you_have("reflection");
535.  	if (Levitation) you_are("levitating");
536.  	if (Fumbling) enl_msg("You fumble", "", "d", "");
537.  	if (Jumping) you_can("jump");
538.  	if (Wwalking) you_can("walk on water");
539.  	if (Magical_breathing) you_can("survive without air");
540.  	if (Antimagic) you_are("magic-protected");
541.  	if (Displaced) you_are("displaced");
542.  	if (Clairvoyant) you_are("clairvoyant");
543.  #ifdef POLYSELF
544.  	if (u.ulycn != -1) {	
545.  		Strcpy(buf, an(mons[u.ulycn].mname));
546.  		you_are(buf);
547.  	}
548.  #endif
549.  	if (Luck) {
550.  	    ltmp = abs((int)Luck);
551.  	    Sprintf(buf, "%s%slucky",
552.  		    ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "",
553.  		    Luck < 0 ? "un" : "");
554.  #ifdef WIZARD
555.  	    if (wizard) Sprintf(eos(buf), " (%d)", Luck);
556.  #endif
557.  	    you_are(buf);
558.  	}
559.  #ifdef WIZARD
560.  	 else if (wizard) enl_msg("Your luck ", "is", "was", " zero");
561.  #endif
562.  	ltmp = stone_luck(TRUE);
563.  	if (ltmp > 0) you_have("extra luck");
564.  	else if (ltmp < 0) you_have("reduced luck");
565.  	if (carrying(LUCKSTONE)) {
566.  	    ltmp = stone_luck(FALSE);
567.  	    if (ltmp <= 0)
568.  		enl_msg("Bad luck ", "does", "did", " not time out for you");
569.  	    if (ltmp >= 0)
570.  		enl_msg("Good luck ", "does", "did", " not time out for you");
571.  	}
572.  
573.  	display_nhwindow(en_win, TRUE);
574.  	destroy_nhwindow(en_win);
575.  	return;
576.  }
577.  
578.  #if defined(WIZARD) || defined(EXPLORE_MODE)
579.  STATIC_PTR int
580.  wiz_attributes()
581.  {
582.  	if (wizard || discover)
583.  		enlightenment(FALSE);
584.  	else
585.  		pline("Unavailable command '^X'.");
586.  	return 0;
587.  }
588.  #endif /* WIZARD || EXPLORE_MODE */
589.  
590.  #endif /* OVLB */
591.  #ifdef OVL1
592.  
593.  #ifndef M
594.  # ifndef NHSTDC
595.  #  define M(c)		(0x80 | (c))
596.  # else
597.  #  define M(c)		((c) - 128)
598.  # endif /* NHSTDC */
599.  #endif
600.  #ifndef C
601.  #define C(c)		(0x1f & (c))
602.  #endif
603.  
604.  static const struct func_tab cmdlist[] = {
605.  	{C('d'), dokick},	/* "D" is for door!...? */
606.  #ifdef WIZARD
607.  	{C('e'), wiz_detect},
608.  	{C('f'), wiz_map},
609.  	{C('g'), wiz_genesis},
610.  	{C('i'), wiz_identify},
611.  #endif
612.  	{C('l'), doredraw}, /* if number_pad is set */
613.  #ifdef WIZARD
614.  	{C('o'), wiz_where},
615.  #endif
616.  	{C('p'), doprev_message},
617.  	{C('r'), doredraw},
618.  	{C('t'), dotele},
619.  #ifdef WIZARD
620.  	{C('v'), wiz_level_tele},
621.  	{C('w'), wiz_wish},
622.  #endif
623.  #if defined(WIZARD) || defined(EXPLORE_MODE)
624.  	{C('x'), wiz_attributes},
625.  #endif
626.  #ifdef SUSPEND
627.  	{C('z'), dosuspend},
628.  #endif
629.  	{'a', doapply},
630.  	{'A', doddoremarm},
631.  	{M('a'), doorganize},
632.  /*	'b', 'B' : go sw */
633.  	{'c', doclose},
634.  	{'C', do_mname},
635.  	{M('c'), dotalk},
636.  	{'d', dodrop},
637.  	{'D', doddrop},
638.  	{M('d'), dodip},
639.  	{'e', doeat},
640.  	{'E', doengrave},
641.  /* Soon to be
642.  	{'f', dofight, "fighting"},
643.  	{'F', doFight, "fighting"},
644.   */
645.  	{M('f'), doforce},
646.  /*	'g', 'G' : multiple go */
647.  /*	'h', 'H' : go west */
648.  	{'h', dohelp}, /* if number_pad is set */
649.  	{'i', ddoinv},
650.  	{'I', dotypeinv},		/* Robert Viduya */
651.  	{M('i'), doinvoke},
652.  /*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
653.  	{'j', dojump}, /* if number_pad is on */
654.  	{M('j'), dojump},
655.  	{'k', dokick}, /* if number_pad is on */
656.  	{'l', doloot}, /* if number_pad is on */
657.  	{M('l'), doloot},
658.  /*	'n' prefixes a count if number_pad is on */
659.  #ifdef POLYSELF
660.  	{M('m'), domonability},
661.  #endif /* POLYSELF */
662.  	{'N', ddocall}, /* if number_pad is on */
663.  	{M('N'), ddocall},
664.  	{'o', doopen},
665.  	{'O', doset},
666.  	{M('o'), dosacrifice},
667.  	{'p', dopay},
668.  	{'P', doputon},
669.  	{M('p'), dopray},
670.  	{'q', dodrink},
671.  	{'Q', done2},
672.  	{'r', doread},
673.  	{'R', doremring},
674.  	{M('r'), dorub},
675.  	{'s', dosearch, "searching"},
676.  	{'S', dosave},
677.  	{M('s'), dosit},
678.  	{'t', dothrow},
679.  	{'T', dotakeoff},
680.  	{M('t'), doturn},
681.  /*	'u', 'U' : go ne */
682.  	{'u', dountrap}, /* if number_pad is on */
683.  	{M('u'), dountrap},
684.  	{'v', doversion},
685.  	{'V', dohistory},
686.  	{M('v'), doextversion},
687.  	{'w', dowield},
688.  	{'W', dowear},
689.  	{M('w'), dowipe},
690.  	{'x', dovspell},			/* Mike Stephenson */
691.  #ifdef EXPLORE_MODE
692.  	{'X', enter_explore_mode},
693.  #endif
694.  /*	'y', 'Y' : go nw */
695.  	{'z', dozap},
696.  	{'Z', docast},
697.  	{'<', doup},
698.  	{'>', dodown},
699.  	{'/', dowhatis},
700.  	{'&', dowhatdoes},
701.  	{'?', dohelp},
702.  #ifdef SHELL
703.  	{'!', dosh},
704.  #endif
705.  	{'.', donull, "waiting"},
706.  	{' ', donull, "waiting"},
707.  	{',', dopickup},
708.  	{':', dolook},
709.  	{';', doquickwhatis},
710.  	{'^', doidtrap},
711.  	{'\\', dodiscovered},		/* Robert Viduya */
712.  	{'@', dotogglepickup},
713.  	{WEAPON_SYM,  doprwep},
714.  	{ARMOR_SYM,  doprarm},
715.  	{RING_SYM,  doprring},
716.  	{AMULET_SYM, dopramulet},
717.  	{TOOL_SYM, doprtool},
718.  	{GOLD_SYM, doprgold},
719.  	{SPBOOK_SYM, dovspell},			/* Mike Stephenson */
720.  	{'#', doextcmd},
721.  	{0,0,0}
722.  };
723.  #undef M
724.  
725.  const struct ext_func_tab extcmdlist[] = {
726.  	{"adjust", "adjust inventory letters", doorganize},
727.  	{"chat", "talk to someone", dotalk},	/* converse? */
728.  	{"dip", "dip an object into something", dodip},
729.  	{"force", "force a lock", doforce},
730.  	{"invoke", "invoke an object's powers", doinvoke},
731.  	{"jump", "jump to a location", dojump},
732.  	{"loot", "loot a box on the floor", doloot},
733.  #ifdef POLYSELF
734.  	{"monster", "use a monster's special ability", domonability},
735.  #endif
736.  	{"name", "name an item or type of object", ddocall},
737.  	{"offer", "offer a sacrifice to the gods", dosacrifice},
738.  	{"pray", "pray to the gods for help", dopray},
739.  	{"rub", "rub a lamp", dorub},
740.  	{"sit", "sit down", dosit},
741.  	{"turn", "turn undead", doturn},
742.  	{"untrap", "untrap something", dountrap},
743.  	{"version", "list compile time options for this version of NetHack",
744.  		doextversion},
745.  #ifdef MAC
746.  	{"window", "clean up windows", SanePositions},
747.  #endif
748.  	{"wipe", "wipe off your face", dowipe},
749.  	{"?", "get this list of extended commands", doextlist},
750.  	{NULL, NULL, donull}
751.  };
752.  
753.  #define unctrl(c)	((c) <= C('z') ? (0x60 | (c)) : (c))
754.  #define unmeta(c)	(0x7f & (c))
755.  
756.  
757.  void
758.  rhack(cmd)
759.  register char *cmd;
760.  {
761.  	register const struct func_tab *tlist = cmdlist;
762.  	boolean firsttime = FALSE;
763.  	register int res;
764.  
765.  	if(!cmd) {
766.  		firsttime = TRUE;
767.  		flags.nopick = 0;
768.  		cmd = parse();
769.  	}
770.  	if(*cmd == (char)033) {
771.  		flags.move = 0;
772.  		return;
773.  	}
774.  #ifdef REDO
775.  	if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
776.  		in_doagain = TRUE;
777.  		stail = 0;
778.  		rhack(NULL);	/* read and execute command */
779.  		in_doagain = FALSE;
780.  		return;
781.  	}
782.  	/* Special case of *cmd == ' ' handled better below */
783.  	if(!*cmd || *cmd == (char)0377) {
784.  #else
785.  	if(!*cmd || *cmd == (char)0377 ||
786.  	   (!flags.rest_on_space && *cmd == ' ')) {
787.  #endif
788.  		nhbell();
789.  		flags.move = 0;
790.  		return;		/* probably we just had an interrupt */
791.  	}
792.  	if(movecmd(*cmd)) {
793.  	walk:
794.  		if(multi) flags.mv = 1;
795.  		domove();
796.  		return;
797.  	}
798.  	if(movecmd(flags.num_pad ? unmeta(*cmd) : lowc(*cmd))) {
799.  		flags.run = 1;
800.  	rush:
801.  		if(firsttime){
802.  			if(!multi) multi = COLNO;
803.  			u.last_str_turn = 0;
804.  		}
805.  		flags.mv = 1;
806.  		domove();
807.  		return;
808.  	}
809.  	if(*cmd == 'g' && movecmd(cmd[1])) {
810.  		flags.run = 2;
811.  		goto rush;
812.  	}
813.  	if (((*cmd == 'G' || (flags.num_pad && *cmd == '5')) &&
814.  	    movecmd(lowc(cmd[1]))) || movecmd(unctrl(*cmd))) {
815.  		flags.run = 3;
816.  		goto rush;
817.  	}
818.  	if((*cmd == 'm' || (flags.num_pad && *cmd == '-')) &&
819.  	    movecmd(cmd[1])) {
820.  		flags.run = 0;
821.  		flags.nopick = 1;
822.  		goto walk;
823.  	}
824.  	if(*cmd == 'M' && movecmd(lowc(cmd[1]))) {
825.  		flags.run = 1;
826.  		flags.nopick = 1;
827.  		goto rush;
828.  	}
829.  	if (flags.num_pad && *cmd == '0') {
830.  		(void)ddoinv();	/* A convenience borrowed from the PC */
831.  		flags.move = 0;
832.  		multi = 0;
833.  		return;
834.  	}
835.  	while(tlist->f_char) {
836.  		if((*cmd & 0xff) == (tlist->f_char & 0xff)){
837.  			/* Special case of *cmd == ' ' handled here */
838.  			if (*cmd == ' ' && !flags.rest_on_space)
839.  				break;
840.  
841.  			/* Now control-A can stop lengthy commands */
842.  			/* in the PC version only -- use ^C-N otherwise */
843.  			if (tlist->f_text && !occupation && multi)
844.  #ifdef GCC_WARN
845.  				set_occupation(tlist->f_funct,
846.  						tlist->f_text, multi);
847.  #else
848.  				set_occupation(((struct func_tab *)tlist)->f_funct,
849.  					tlist->f_text, multi);
850.  #endif
851.  			res = (*(tlist->f_funct))();
852.  			if(!res) {
853.  				flags.move = 0;
854.  				multi = 0;
855.  			}
856.  			return;
857.  		}
858.  		tlist++;
859.  	}
860.  	{ char expcmd[10];
861.  	  register char *cp = expcmd;
862.  	  while(*cmd && cp-expcmd < sizeof(expcmd)-2) {
863.  		if(*cmd >= 040 && *cmd < 0177)
864.  			*cp++ = *cmd++;
865.  		else if (*cmd & 0200) {
866.  			*cp++ = 'M';
867.  			*cp++ = '-';
868.  			*cp++ = *cmd++ &=~ 0200;
869.  		}
870.  		else {
871.  			*cp++ = '^';
872.  			*cp++ = *cmd++ ^ 0100;
873.  		}
874.  	  }
875.  	  *cp = 0;
876.  	  Norep("Unknown command '%s'.", expcmd);
877.  	}
878.  	multi = flags.move = 0;
879.  	return;
880.  }
881.  
882.  int
883.  xytod(x, y)	/* convert an x,y pair into a direction code */
884.  schar x, y;
885.  {
886.  	register int dd;
887.  
888.  	for(dd = 0; dd < 8; dd++)
889.  	    if(x == xdir[dd] && y == ydir[dd]) return dd;
890.  
891.  	return -1;
892.  }
893.  
894.  #ifdef WALKIES
895.  void
896.  dtoxy(cc,dd)	/* convert a direction code into an x,y pair */
897.  coord *cc;
898.  register int dd;
899.  {
900.  	cc->x = xdir[dd];
901.  	cc->y = ydir[dd];
902.  	return;
903.  }
904.  #endif /* WALKIES */
905.  
906.  int
907.  movecmd(sym)	/* also sets u.dz, but returns false for <> */
908.  char sym;
909.  {
910.  	register const char *dp;
911.  	register const char *sdp = flags.num_pad ? ndir : sdir;
912.  
913.  	u.dz = 0;
914.  	if(!(dp = index(sdp, sym))) return 0;
915.  	u.dx = xdir[dp-sdp];
916.  	u.dy = ydir[dp-sdp];
917.  	u.dz = zdir[dp-sdp];
918.  #ifdef POLYSELF
919.  	if (u.dx && u.dy && u.umonnum == PM_GRID_BUG) {
920.  		u.dx = u.dy = 0;
921.  		return 0;
922.  	}
923.  #endif
924.  	return !u.dz;
925.  }
926.  
927.  int
928.  getdir(s)
929.  const char *s;
930.  {
931.  	char dirsym;
932.  
933.  #ifdef REDO	
934.  	if(in_doagain)
935.  	    dirsym = readchar();
936.  	else
937.  #endif
938.  	    dirsym = yn_function (s ? s : "In what direction?", NULL, '\0');
939.  #ifdef REDO
940.  	savech(dirsym);
941.  #endif
942.  	if(dirsym == '.' || dirsym == 's')
943.  		u.dx = u.dy = u.dz = 0;
944.  	else if(!movecmd(dirsym) && !u.dz) {
945.  		if(!index(quitchars, dirsym))
946.  			pline("What a strange direction!");
947.  		return 0;
948.  	}
949.  	if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir();
950.  	return 1;
951.  }
952.  
953.  #endif /* OVL1 */
954.  #ifdef OVLB
955.  
956.  void
957.  confdir()
958.  {
959.  	register int x =
960.  #ifdef POLYSELF
961.  		(u.umonnum == PM_GRID_BUG) ? 2*rn2(4) :
962.  #endif
963.  							rn2(8);
964.  	u.dx = xdir[x];
965.  	u.dy = ydir[x];
966.  	return;
967.  }
968.  
969.  #endif /* OVLB */
970.  #ifdef OVL0
971.  
972.  int
973.  isok(x,y)
974.  register int x, y;
975.  {
976.  	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
977.  	return x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1;
978.  }
979.  
980.  static int NEARDATA last_multi;
981.  
982.  /*
983.   * convert a MAP window position into a movecmd
984.   */
985.  static int
986.  click_to_cmd(x, y, mod)
987.      int x, y, mod;
988.  {
989.      x -= u.ux;
990.      y -= u.uy;
991.      /* convert without using floating point, allowing sloppy clicking */
992.      if(x > 2*abs(y))
993.  	x = 1, y = 0;
994.      else if(y > 2*abs(x))
995.  	x = 0, y = 1;
996.      else if(x < -2*abs(y))
997.  	x = -1, y = 0;
998.      else if(y < -2*abs(x))
999.  	x = 0, y = -1;
1000.     else
1001. 	x = sgn(x), y = sgn(y);
1002. 
1003.     if(x == 0 && y == 0)	/* map click on player to "rest" command */
1004. 	return '.';
1005. 
1006.     x = xytod(x, y);
1007.     if(mod == CLICK_1) {
1008. 	return (flags.num_pad ? ndir[x] : sdir[x]);
1009.     } else {
1010. 	return (sdir[x] - 'a' + 'A'); /* run command */
1011.     }
1012. }
1013. 
1014. STATIC_OVL char *
1015. parse()
1016. {
1017. #ifdef LINT	/* static char in_line[COLNO]; */
1018. 	char in_line[COLNO];
1019. #else
1020. 	static char in_line[COLNO];
1021. #endif
1022. 	register int foo;
1023. 	boolean prezero = FALSE;
1024. 
1025. 	multi = 0;
1026. 	flags.move = 1;
1027. 	flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
1028. 
1029. 	if (!flags.num_pad || (foo = readchar()) == 'n')
1030. 	    for (;;) {
1031. 		foo = readchar();
1032. 		if (foo >= '0' && foo <= '9') {
1033. 		    multi = 10 * multi + foo - '0';
1034. 		    if (multi < 0 || multi > LARGEST_INT) multi = LARGEST_INT;
1035. 		    if (multi > 9) {
1036. 			clear_nhwindow(WIN_MESSAGE);
1037. 			Sprintf(in_line, "Count: %d", multi);
1038. 			pline(in_line);
1039. 			mark_synch();
1040. 		    }
1041. 		    last_multi = multi;
1042. 		    if (!multi && foo == '0') prezero = TRUE;
1043. 		} else break;	/* not a digit */
1044. 	    }
1045. 
1046. 	if (foo == '\033') {   /* esc cancels count (TH) */
1047. 	    clear_nhwindow(WIN_MESSAGE);
1048. 	    multi = last_multi = 0;
1049. # ifdef REDO
1050. 	} else if (foo == DOAGAIN || in_doagain) {
1051. 	    multi = last_multi;
1052. 	} else {
1053. 	    last_multi = multi;
1054. 	    savech(0);	/* reset input queue */
1055. 	    savech((char)foo);
1056. # endif
1057. 	}
1058. 
1059. 	if (multi) {
1060. 	    multi--;
1061. 	    save_cm = in_line;
1062. 	} else {
1063. 	    save_cm = NULL;
1064. 	}
1065. 	in_line[0] = foo;
1066. 	in_line[1] = '\0';
1067. 	if (foo == 'g' || foo == 'G' || (flags.num_pad && foo == '5') ||
1068. 	    foo == 'm' || foo == 'M') {
1069. 	    foo = readchar();
1070. #ifdef REDO
1071. 	    savech((char)foo);
1072. #endif
1073. 	    in_line[1] = foo;
1074. 	    in_line[2] = 0;
1075. 	}
1076. 	clear_nhwindow(WIN_MESSAGE);
1077. 	if (prezero) in_line[0] = '\033';
1078. 	return(in_line);
1079. }
1080. 
1081. #endif /* OVL0 */
1082. #ifdef OVLB
1083. 
1084. #ifdef UNIX
1085. static
1086. void
1087. end_of_input()
1088. {
1089. 	exit_nhwindows("End of input?");
1090. #ifndef NOSAVEONHANGUP
1091. 	if(!hu) {
1092. 	    hu = TRUE;
1093. 	    (void) dosave0();
1094. 	}
1095. #endif
1096. 	clearlocks();
1097. 	terminate(0);
1098. }
1099. #endif
1100. 
1101. #endif /* OVLB */
1102. #ifdef OVL0
1103. 
1104. char
1105. readchar()
1106. {
1107. 	register int sym;
1108. 	int x, y, mod;
1109. 
1110. #ifdef REDO
1111. 	sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod);
1112. #else
1113. 	sym = Getchar();
1114. #endif
1115. 
1116. #ifdef UNIX
1117. # ifdef NR_OF_EOFS
1118. 	if (sym == EOF) {
1119. 	    register int cnt = NR_OF_EOFS;
1120. 	  /*
1121. 	   * Some SYSV systems seem to return EOFs for various reasons
1122. 	   * (?like when one hits break or for interrupted systemcalls?),
1123. 	   * and we must see several before we quit.
1124. 	   */
1125. 	    do {
1126. 		clearerr(stdin);	/* omit if clearerr is undefined */
1127. 		sym = Getchar();
1128. 	    } while (--cnt && sym == EOF);
1129. 	}
1130. # endif /* NR_OF_EOFS */
1131. 	if (sym == EOF)
1132. 	    end_of_input();
1133. #endif /* UNIX */
1134. 
1135. 	if(sym == 0) /* click event */
1136. 	    sym = click_to_cmd(x, y, mod);
1137. 	return((char) sym);
1138. }
1139. #endif /* OVL0 */
1140. 
1141. /*cmd.c*/