Source:NetHack 1.4f/cmd.c

Below is the full text to cmd.c from the source code of NetHack 1.4f. To link to a particular line, write [[NetHack 1.4f/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	1.4	87/08/08 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, doturn; 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.  extern 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. 	{GOLD_SYM, 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. 	"turn", "turn undead", doturn, 216. #endif 217. #if defined(KOPS) && defined(KAA) 218. 	"wipe", "wipe your face off", dowipe, 219. #endif 220. 	"?", "get this list of extended commands", doextlist, 221. 	(char *) 0, (char *) 0, donull 222. };  223.   224.  extern char *parse, lowc, unctrl, quitchars[]; 225.  226.  rhack(cmd) 227. register char *cmd; 228. {  229.  	register struct func_tab *tlist = cmdlist; 230. 	boolean firsttime = FALSE; 231. 	register res; 232.  233.  	if(!cmd) { 234. 		firsttime = TRUE; 235. 		flags.nopick = 0; 236. 		cmd = parse; 237. 	}  238.  #ifdef REDO 239. 	if (*cmd == DOAGAIN && !in_doagain && saveq[0]) { 240. 		in_doagain = TRUE; 241. 		stail = 0; 242. 		rhack((char *) 0);	/* read and execute command */ 243. 		in_doagain = FALSE; 244. 		return; 245. 	}  246.   247.  	/* Special case of *cmd == ' ' handled better below */ 248. 	if(!*cmd || *cmd == (char)0377) { 249. #else 250. 	if(!*cmd || *cmd == (char)0377 || (flags.no_rest_on_space && *cmd == ' ')){ 251. #endif 252. 		bell; 253. 		flags.move = 0; 254. 		return(0);	/* probably we just had an interrupt */ 255. 	}  256.  	if(movecmd(*cmd)) { 257. 	walk: 258. 		if(multi) flags.mv = 1; 259. 		domove; 260. 		return; 261. 	}  262.  	if(movecmd(lowc(*cmd))) { 263. 		flags.run = 1; 264. 	rush: 265. 		if(firsttime){ 266. 			if(!multi) multi = COLNO; 267. 			u.last_str_turn = 0; 268. 		}  269.  		flags.mv = 1; 270. #ifdef QUEST 271. 		if(flags.run >= 4) finddir; 272. 		if(firsttime){ 273. 			u.ux0 = u.ux + u.dx; 274. 			u.uy0 = u.uy + u.dy; 275. 		}  276.  #endif 277. 		domove; 278. 		return; 279. 	}  280.  	if((*cmd == 'g' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) { 281. 		flags.run = 2; 282. 		goto rush; 283. 	}  284.  	if(*cmd == 'G' && movecmd(lowc(cmd[1]))) { 285. 		flags.run = 3; 286. 		goto rush; 287. 	}  288.  	if(*cmd == 'm' && movecmd(cmd[1])) { 289. 		flags.run = 0; 290. 		flags.nopick = 1; 291. 		goto walk; 292. 	}  293.  	if(*cmd == 'M' && movecmd(lowc(cmd[1]))) { 294. 		flags.run = 1; 295. 		flags.nopick = 1; 296. 		goto rush; 297. 	}  298.  #ifdef QUEST 299. 	if(*cmd == cmd[1] && (*cmd == 'g' || *cmd == 'G')) { 300. 		flags.run = 4; 301. 		if(*cmd == 'G') flags.run += 2; 302. 		if(cmd[2] == '-') flags.run += 1; 303. 		goto rush; 304. 	}  305.  #endif 306. 	while(tlist->f_char) { 307. 		if(*cmd == tlist->f_char){ 308. #ifdef DGKMOD 309. 			/* Special case of *cmd == ' ' handled here */ 310. 			if (*cmd == ' ' && flags.no_rest_on_space) 311. 				break; 312.  313.  			/* Now control-A can stop lengthy commands */ 314. 			if (tlist->f_text && !occupation && multi) 315. 				set_occupation(tlist->f_funct, tlist->f_text,  316.  					multi); 317. #endif 318. 			res = (*(tlist->f_funct)); 319. 			if(!res) { 320. 				flags.move = 0; 321. 				multi = 0; 322. 			}  323.  			return; 324. 		}  325.  		tlist++; 326. 	}  327.  	{ char expcmd[10]; 328. 	  register char *cp = expcmd; 329. 	  while(*cmd && cp-expcmd < sizeof(expcmd)-2) { 330. 		if(*cmd >= 040 && *cmd < 0177) 331. 			*cp++ = *cmd++; 332. 		else { 333. 			*cp++ = '^'; 334. 			*cp++ = *cmd++ ^ 0100; 335. 		}  336.  	  }  337.  	  *cp++ = 0; 338. 	  pline("Unknown command '%s'.", expcmd); 339. 	}  340.  	multi = flags.move = 0; 341. }  342.   343.  doextcmd	/* here after # - now read a full-word command */ 344. {  345.  	char buf[BUFSZ]; 346. 	register struct ext_func_tab *efp = extcmdlist; 347.  348.  	pline("# "); 349. #ifdef COM_COMPL 350. 	get_ext_cmd(buf); 351. #else 352. 	getlin(buf); 353. #endif 354. 	clrlin; 355. 	if(buf[0] == '\033') 356. 		return(0); 357. 	while(efp->ef_txt) { 358. 		if(!strcmp(efp->ef_txt, buf)) 359. 			return((*(efp->ef_funct))); 360. 		efp++; 361. 	}  362.  	pline("%s: unknown command.", buf); 363. 	return(0); 364. }  365.   366.  doextlist	/* here after #? - now list all full-word commands */ 367. {  368.  	register struct ext_func_tab *efp = extcmdlist; 369. 	char     buf[BUFSZ]; 370.  371.  	set_pager(0); 372. 	if(page_line("") ||  373.  	   page_line("        Extended Command Set:") ||  374.  	   page_line(""))					 goto quit; 375.  376.  	while(efp->ef_txt) { 377.  378.  		(void)sprintf(buf, "    %-8s  - %s.", efp->ef_txt, efp->ef_desc); 379. 		if(page_line(buf)) goto quit; 380. 		efp++; 381. 	}  382.  	set_pager(1); 383. 	return(0); 384. quit: 385. 	set_pager(2); 386. 	return(0); 387. }  388.   389.  char 390. lowc(sym) 391. char sym; 392. {  393.      return( (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym ); 394. }  395.   396.  char 397. unctrl(sym) 398. char sym; 399. {  400.      return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym ); 401. }  402.   403.  /* 'rogue'-like direction commands */ 404. char sdir[] = "hykulnjb><"; 405. schar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 }; 406. schar ydir[10] = {  0,-1,-1,-1, 0, 1, 1, 1, 0, 0 }; 407. schar zdir[10] = {  0, 0, 0, 0, 0, 0, 0, 0, 1,-1 }; 408.  409.  movecmd(sym)	/* also sets u.dz, but returns false for <> */ 410. char sym; 411. {  412.  	register char *dp; 413.  414.  	u.dz = 0; 415. 	if(!(dp = index(sdir, sym))) return(0); 416. 	u.dx = xdir[dp-sdir]; 417. 	u.dy = ydir[dp-sdir]; 418. 	u.dz = zdir[dp-sdir]; 419. 	return(!u.dz); 420. }  421.   422.  getdir(s) 423. boolean s;  424. { 425.  	char dirsym; 426.  427.  #ifdef REDO 428. 	if (!in_doagain) 429. #endif 430. 	    if(s) pline("In what direction?"); 431. 	dirsym = readchar; 432. #ifdef REDO 433. 	savech(dirsym); 434. #endif 435. #ifdef KAA 436. 	if(dirsym == '.' || dirsym == 's') 437. 		u.dx = u.dy = u.dz = 0; 438. 	else 439. #endif 440. 	if(!movecmd(dirsym) && !u.dz) { 441. 		if(!index(quitchars, dirsym)) 442. 			pline("What a strange direction!"); 443. 		return(0); 444. 	}  445.  	if(Confusion && !u.dz) confdir; 446. 	return(1); 447. }  448.   449.  confdir 450. {  451.  	register x = rn2(8); 452. 	u.dx = xdir[x]; 453. 	u.dy = ydir[x]; 454. }  455.   456.  #ifdef QUEST 457. finddir{ 458. register int i, ui = u.di; 459. 	for(i = 0; i <= 8; i++){ 460. 		if(flags.run & 1) ui++; else ui += 7; 461. 		ui %= 8; 462. 		if(i == 8){ 463. 			pline("Not near a wall."); 464. 			flags.move = multi = 0; 465. 			return(0); 466. 		}  467.  		if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui])) 468. 			break; 469. 	}  470.  	for(i = 0; i <= 8; i++){ 471. 		if(flags.run & 1) ui += 7; else ui++; 472. 		ui %= 8; 473. 		if(i == 8){ 474. 			pline("Not near a room."); 475. 			flags.move = multi = 0; 476. 			return(0); 477. 		}  478.  		if(isroom(u.ux+xdir[ui], u.uy+ydir[ui])) 479. 			break; 480. 	}  481.  	u.di = ui; 482. 	u.dx = xdir[ui]; 483. 	u.dy = ydir[ui]; 484. }  485.   486.  isroom(x,y)  register x,y; {		/* what about POOL? */ 487.  	return(isok(x,y) && (levl[x][y].typ == ROOM || 488. 				(levl[x][y].typ >= LDOOR && flags.run >= 6))); 489. }  490.  #endif /* QUEST /**/ 491.  492.  isok(x,y) register x,y; { 493. 	/* x corresponds to curx, so x==1 is the first column. Ach. %% */ 494.  	return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1); 495. }