Source:NetHack 1.4f/cmd.c
Revision as of 00:48, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 1.4f/cmd.c moved to Source:NetHack 1.4f/cmd.c: Robot: moved page)
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
Screenshots and source code from Hack are used under the CWI license.
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. }