Source:NetHack 1.3d/cmd.c

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

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. }