Source:NetHack 2.2a/cmd.c
Jump to navigation
Jump to search
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
Screenshots and source code from Hack are used under the CWI license.
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 */