Source:NetHack 1.3d/cmd.c

From NetHackWiki
Jump to: navigation, search

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

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

Screenshots and source code from Hack are used under the CWI license.

1.    /*	SCCS Id: @(#)cmd.c	1.3	87/07/14
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* cmd.c - version 1.0.3 */
4.    
5.    #include	"hack.h"
6.    #include	"func_tab.h"
7.    
8.    int doredraw(),doredotopl(),dodrop(),dodrink(),doread(),dosearch(),dopickup(),
9.    doversion(),doweararm(),dowearring(),doremarm(),doddoremarm(),doremring(),
10.   dopay(),doapply(),dosave(),dowield(),ddoinv(),dozap(),ddocall(),dowhatis(),
11.   doengrave(),dotele(),dohelp(),doeat(),doddrop(),do_mname(),doidtrap(),
12.   doprwep(),doprarm(),doprring(),doprgold(),dodiscovered(),dotypeinv(),dolook(),
13.   doset(),doup(), dodown(), done1(), donull(), dothrow(), doextcmd(), dodip(),
14.   dopray(), doextlist();
15.   #ifdef NEWCLASS
16.   int dosit();
17.   #endif
18.   #ifdef SPELLS
19.   int docast(), dovspell(), doxcribe();
20.   #endif
21.   #ifdef SHELL
22.   int dosh();
23.   #endif
24.   #ifdef SUSPEND
25.   int dosuspend();
26.   #endif
27.   #ifdef KAA
28.   int doremove(), dobreathe();
29.   # ifdef KOPS
30.   int dowipe();
31.   # endif
32.   #endif
33.   
34.   int rndobjsym(), rndmonsym();
35.   char *hcolor(), *rndmonnam(), *defmonnam();
36.   
37.   extern char *occtxt;
38.   extern int (*occupation)();
39.   
40.   # ifdef DGKMOD
41.   int dotogglepickup(), doMSCversion();
42.   # ifdef DEBUG
43.   int dodebug();
44.   # endif
45.   
46.   static int (*timed_occ_fn)();
47.   
48.   /* Count down by decrementing multi */
49.   timed_occupation() {
50.   	(*timed_occ_fn)();
51.   	if (multi > 0)
52.   		multi--;
53.   	return (multi > 0);
54.   }
55.   
56.   /* If a time is given, use it to timeout this function, otherwise the
57.    * function times out by its own means.
58.    */
59.   void
60.   set_occupation(fn, txt, time)
61.   int (*fn)();
62.   char *txt;
63.   {
64.   	if (time) {
65.   		occupation = timed_occupation;
66.   		timed_occ_fn = fn;
67.   	} else
68.   		occupation = fn;
69.   	occtxt = txt;
70.   	occtime = 0;
71.   }
72.   #endif /* DGKMOD */
73.   
74.   #ifdef REDO
75.   /* Provide a means to redo the last command.  The flag `in_doagain' is set
76.    * to true while redoing the command.  This flag is tested in commands that
77.    * require additional input (like `throw' which requires a thing and a
78.    * direction), and the input prompt is not shown.  Also, while in_doagain is
79.    * TRUE, no keystrokes can be saved into the saveq.
80.    */
81.   #define BSIZE 20
82.   static char pushq[BSIZE], saveq[BSIZE];
83.   static int phead, ptail, shead, stail;
84.   int in_doagain;
85.   
86.   char
87.   popch() {
88.   	/* If occupied, return 0, letting tgetch know a character should
89.   	 * be read from the keyboard.  If the character read is not the
90.   	 * ABORT character (as checked in main.c), that character will be
91.   	 * pushed back on the pushq.
92.   	 */
93.   	if (occupation) return(0);
94.   	if (in_doagain) return ((shead != stail) ? saveq[stail++] : 0);
95.   	else		return ((phead != ptail) ? pushq[ptail++] : 0);
96.   }
97.   
98.   /* A ch == 0 resets the pushq */
99.   void
100.  pushch(ch)
101.  char ch;
102.  {
103.  	if (!ch)
104.  		phead = ptail = 0;
105.  	if (phead < BSIZE)
106.  		pushq[phead++] = ch;
107.  }
108.  
109.  /* A ch == 0 resets the saveq.  Only save keystrokes when not
110.   * replaying a previous command.
111.   */
112.  void
113.  savech(ch)
114.  char ch;
115.  {
116.  	if (!in_doagain) {
117.  		if (!ch)
118.  			phead = ptail = shead = stail = 0;
119.  		else if (shead < BSIZE)
120.  			saveq[shead++] = ch;
121.  	}
122.  }
123.  # endif /* REDO */
124.  
125.  struct func_tab cmdlist[]={
126.  	{'\020', doredotopl},
127.  	{'\022', doredraw},
128.  	{'\024', dotele},
129.  #ifdef SUSPEND
130.  	{'\032', dosuspend},
131.  #endif
132.  	{'a', doapply},
133.  	{'A', doddoremarm},
134.  /*	'b', 'B' : go sw */
135.  	{'c', ddocall},
136.  	{'C', do_mname},
137.  	{'d', dodrop},
138.  	{'D', doddrop},
139.  	{'e', doeat},
140.  	{'E', doengrave},
141.  /* Soon to be
142.  	{'f', dofight, "fighting"},
143.  	{'F', doFight, "fighting"},
144.   */
145.  /*	'g', 'G' : multiple go */
146.  /*	'h', 'H' : go west */
147.  	{'I', dotypeinv},		/* Robert Viduya */
148.  	{'i', ddoinv},
149.  /*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
150.  /*	'o', doopen,	*/
151.  	{'O', doset},
152.  	{'p', dopay},
153.  	{'P', dowearring},
154.  	{'q', dodrink},
155.  	{'Q', done1},
156.  	{'r', doread},
157.  	{'R', doremring},
158.  	{'s', dosearch, "searching"},
159.  	{'S', dosave},
160.  	{'t', dothrow},
161.  	{'T', doremarm},
162.  /*	'u', 'U' : go ne */
163.  	{'v', doversion},
164.  	{'w', dowield},
165.  	{'W', doweararm},
166.  #ifdef SPELLS
167.  	{'x', dovspell},			/* Mike Stephenson */
168.  	{'X', doxcribe},			/* Mike Stephenson */ 
169.  #endif
170.  /*	'y', 'Y' : go nw */
171.  	{'z', dozap},
172.  /*	'Z' : UNUSED */
173.  	{'<', doup},
174.  	{'>', dodown},
175.  	{'/', dowhatis},
176.  	{'?', dohelp},
177.  #ifdef SHELL
178.  	{'!', dosh},
179.  #endif
180.  	{'.', donull, "waiting"},
181.  	{' ', donull, "waiting"},
182.  	{',', dopickup},
183.  	{':', dolook},
184.  	{'^', doidtrap},
185.  	{'\\', dodiscovered},		/* Robert Viduya */
186.  #ifdef DGKMOD
187.  	{'@', dotogglepickup},
188.  	{'V', doMSCversion},
189.  # ifdef DEBUG_DOESNT_WORK
190.  	{'\004', dodebug},	/* generic debug function */
191.  # endif
192.  #endif
193.  	{WEAPON_SYM,  doprwep},
194.  	{ARMOR_SYM,  doprarm},
195.  	{RING_SYM,  doprring},
196.  	{'$', doprgold},
197.  	{'#', doextcmd},
198.  	{0,0,0}
199.  };
200.  
201.  struct ext_func_tab extcmdlist[] = {
202.  #ifdef KAA
203.  	"breathe", "breathe like a dragon", dobreathe,
204.  #endif
205.  #ifdef SPELLS
206.  	"cast", "cast a spell", docast,
207.  #endif
208.  	"dip", "dip an object into something", dodip,
209.  	"pray", "pray to the gods for help", dopray,
210.  #ifdef KAA
211.  	"remove", "remove a cursed item", doremove,
212.  #endif
213.  #ifdef NEWCLASS
214.  	"sit", "sit down", dosit,
215.  #endif
216.  #if defined(KOPS) && defined(KAA)
217.  	"wipe", "wipe your face off", dowipe,
218.  #endif
219.  	"?", "get this list of extended commands", doextlist,
220.  	(char *) 0, (char *) 0, donull
221.  };
222.  
223.  extern char *parse(), lowc(), unctrl(), quitchars[];
224.  
225.  rhack(cmd)
226.  register char *cmd;
227.  {
228.  	register struct func_tab *tlist = cmdlist;
229.  	boolean firsttime = FALSE;
230.  	register res;
231.  
232.  	if(!cmd) {
233.  		firsttime = TRUE;
234.  		flags.nopick = 0;
235.  		cmd = parse();
236.  	}
237.  #ifdef REDO
238.  	if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
239.  		in_doagain = TRUE;
240.  		stail = 0;
241.  		rhack((char *) 0);	/* read and execute command */
242.  		in_doagain = FALSE;
243.  		return;
244.  	}
245.  
246.  	/* Special case of *cmd == ' ' handled better below */
247.  	if(!*cmd || *cmd == 0377) {
248.  #else
249.  	if(!*cmd || *cmd == 0377 || (flags.no_rest_on_space && *cmd == ' ')){
250.  #endif
251.  		bell();
252.  		flags.move = 0;
253.  		return(0);	/* probably we just had an interrupt */
254.  	}
255.  	if(movecmd(*cmd)) {
256.  	walk:
257.  		if(multi) flags.mv = 1;
258.  		domove();
259.  		return;
260.  	}
261.  	if(movecmd(lowc(*cmd))) {
262.  		flags.run = 1;
263.  	rush:
264.  		if(firsttime){
265.  			if(!multi) multi = COLNO;
266.  			u.last_str_turn = 0;
267.  		}
268.  		flags.mv = 1;
269.  #ifdef QUEST
270.  		if(flags.run >= 4) finddir();
271.  		if(firsttime){
272.  			u.ux0 = u.ux + u.dx;
273.  			u.uy0 = u.uy + u.dy;
274.  		}
275.  #endif
276.  		domove();
277.  		return;
278.  	}
279.  	if((*cmd == 'g' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
280.  		flags.run = 2;
281.  		goto rush;
282.  	}
283.  	if(*cmd == 'G' && movecmd(lowc(cmd[1]))) {
284.  		flags.run = 3;
285.  		goto rush;
286.  	}
287.  	if(*cmd == 'm' && movecmd(cmd[1])) {
288.  		flags.run = 0;
289.  		flags.nopick = 1;
290.  		goto walk;
291.  	}
292.  	if(*cmd == 'M' && movecmd(lowc(cmd[1]))) {
293.  		flags.run = 1;
294.  		flags.nopick = 1;
295.  		goto rush;
296.  	}
297.  #ifdef QUEST
298.  	if(*cmd == cmd[1] && (*cmd == 'g' || *cmd == 'G')) {
299.  		flags.run = 4;
300.  		if(*cmd == 'G') flags.run += 2;
301.  		if(cmd[2] == '-') flags.run += 1;
302.  		goto rush;
303.  	}
304.  #endif
305.  	while(tlist->f_char) {
306.  		if(*cmd == tlist->f_char){
307.  #ifdef DGKMOD
308.  			/* Special case of *cmd == ' ' handled here */
309.  			if (*cmd == ' ' && flags.no_rest_on_space)
310.  				break;
311.  
312.  			/* Now control-A can stop lengthy commands */
313.  			if (tlist->f_text && !occupation && multi)
314.  				set_occupation(tlist->f_funct, tlist->f_text,
315.  					multi);
316.  #endif
317.  			res = (*(tlist->f_funct))();
318.  			if(!res) {
319.  				flags.move = 0;
320.  				multi = 0;
321.  			}
322.  			return;
323.  		}
324.  		tlist++;
325.  	}
326.  	{ char expcmd[10];
327.  	  register char *cp = expcmd;
328.  	  while(*cmd && cp-expcmd < sizeof(expcmd)-2) {
329.  		if(*cmd >= 040 && *cmd < 0177)
330.  			*cp++ = *cmd++;
331.  		else {
332.  			*cp++ = '^';
333.  			*cp++ = *cmd++ ^ 0100;
334.  		}
335.  	  }
336.  	  *cp++ = 0;
337.  	  pline("Unknown command '%s'.", expcmd);
338.  	}
339.  	multi = flags.move = 0;
340.  }
341.  
342.  doextcmd()	/* here after # - now read a full-word command */
343.  {
344.  	char buf[BUFSZ];
345.  	register struct ext_func_tab *efp = extcmdlist;
346.  
347.  	pline("# ");
348.  	getlin(buf);
349.  	clrlin();
350.  	if(buf[0] == '\033')
351.  		return(0);
352.  	while(efp->ef_txt) {
353.  		if(!strcmp(efp->ef_txt, buf))
354.  			return((*(efp->ef_funct))());
355.  		efp++;
356.  	}
357.  	pline("%s: unknown command.", buf);
358.  	return(0);
359.  }
360.  
361.  doextlist()	/* here after #? - now list all full-word commands */
362.  {
363.  	register struct ext_func_tab *efp = extcmdlist;
364.  	char     buf[BUFSZ];
365.  
366.  	set_pager(0);
367.  	if(page_line("") ||
368.  	   page_line("        Extended Command Set:") ||
369.  	   page_line(""))					 goto quit;
370.  
371.  	while(efp->ef_txt) {
372.  
373.  		(void)sprintf(buf, "    %-8s  - %s.", efp->ef_txt, efp->ef_desc);
374.  		if(page_line(buf)) goto quit;
375.  		efp++;
376.  	}
377.  	set_pager(1);
378.  	return(0);
379.  quit:
380.  	set_pager(2);
381.  	return(0);
382.  }
383.  
384.  char
385.  lowc(sym)
386.  char sym;
387.  {
388.      return( (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym );
389.  }
390.  
391.  char
392.  unctrl(sym)
393.  char sym;
394.  {
395.      return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym );
396.  }
397.  
398.  /* 'rogue'-like direction commands */
399.  char sdir[] = "hykulnjb><";
400.  schar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 };
401.  schar ydir[10] = {  0,-1,-1,-1, 0, 1, 1, 1, 0, 0 };
402.  schar zdir[10] = {  0, 0, 0, 0, 0, 0, 0, 0, 1,-1 };
403.  
404.  movecmd(sym)	/* also sets u.dz, but returns false for <> */
405.  char sym;
406.  {
407.  	register char *dp;
408.  
409.  	u.dz = 0;
410.  	if(!(dp = index(sdir, sym))) return(0);
411.  	u.dx = xdir[dp-sdir];
412.  	u.dy = ydir[dp-sdir];
413.  	u.dz = zdir[dp-sdir];
414.  	return(!u.dz);
415.  }
416.  
417.  getdir(s)
418.  boolean s;
419.  {
420.  	char dirsym;
421.  
422.  #ifdef REDO
423.  	if (!in_doagain)
424.  #endif
425.  	    if(s) pline("In what direction?");
426.  	dirsym = readchar();
427.  #ifdef REDO
428.  	savech(dirsym);
429.  #endif
430.  #ifdef KAA
431.  	if(dirsym == '.' || dirsym == 's')
432.  		u.dx = u.dy = u.dz = 0;
433.  	else
434.  #endif
435.  	if(!movecmd(dirsym) && !u.dz) {
436.  		if(!index(quitchars, dirsym))
437.  			pline("What a strange direction!");
438.  		return(0);
439.  	}
440.  	if(Confusion && !u.dz) confdir();
441.  	return(1);
442.  }
443.  
444.  confdir()
445.  {
446.  	register x = rn2(8);
447.  	u.dx = xdir[x];
448.  	u.dy = ydir[x];
449.  }
450.  
451.  #ifdef QUEST
452.  finddir(){
453.  register int i, ui = u.di;
454.  	for(i = 0; i <= 8; i++){
455.  		if(flags.run & 1) ui++; else ui += 7;
456.  		ui %= 8;
457.  		if(i == 8){
458.  			pline("Not near a wall.");
459.  			flags.move = multi = 0;
460.  			return(0);
461.  		}
462.  		if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
463.  			break;
464.  	}
465.  	for(i = 0; i <= 8; i++){
466.  		if(flags.run & 1) ui += 7; else ui++;
467.  		ui %= 8;
468.  		if(i == 8){
469.  			pline("Not near a room.");
470.  			flags.move = multi = 0;
471.  			return(0);
472.  		}
473.  		if(isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
474.  			break;
475.  	}
476.  	u.di = ui;
477.  	u.dx = xdir[ui];
478.  	u.dy = ydir[ui];
479.  }
480.  
481.  isroom(x,y)  register x,y; {		/* what about POOL? */
482.  	return(isok(x,y) && (levl[x][y].typ == ROOM ||
483.  				(levl[x][y].typ >= LDOOR && flags.run >= 6)));
484.  }
485.  #endif /* QUEST /**/
486.  
487.  isok(x,y) register x,y; {
488.  	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
489.  	return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1);
490.  }