Source:NetHack 2.2a/cmd.c

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

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

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