Source:NetHack 2.3e/cmd.c
Jump to navigation
Jump to search
Below is the full text to cmd.c from the source code of NetHack 2.3e.
Warning! This is the source code from an old release. For newer releases, see Source code
Screenshots and source code from Hack are used under the CWI license.
1. /* SCCS Id: @(#)cmd.c 2.3 88/01/21 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(), dorub(); 14. 15. #ifdef THEOLOGY 16. int dosacrifice (); 17. #endif; 18. 19. #ifdef WIZARD 20. int wiz_wish(), wiz_identify(), wiz_map(), wiz_detect(), wiz_attributes(); 21. #endif 22. #ifdef NEWCLASS 23. int dosit(), doturn(); 24. #endif 25. #ifdef SPELLS 26. int docast(), dovspell(), doxcribe(); 27. #endif 28. #ifdef SHELL 29. int dosh(); 30. #endif 31. #ifdef SUSPEND 32. int dosuspend(); 33. #endif 34. #ifdef KAA 35. int doremove(), dobreathe(); 36. # ifdef KOPS 37. int dowipe(); 38. # endif 39. #endif 40. 41. int rndobjsym(), rndmonsym(); 42. char *hcolor(), *rndmonnam(), *defmonnam(); 43. 44. extern char *occtxt; 45. extern int (*occupation)(); 46. 47. #ifdef DGKMOD 48. int dotogglepickup(), doMSCversion(); 49. # ifdef DEBUG 50. int dodebug(); 51. # endif 52. 53. static int (*timed_occ_fn)(); 54. 55. /* Count down by decrementing multi */ 56. timed_occupation() { 57. (*timed_occ_fn)(); 58. if (multi > 0) 59. multi--; 60. return (multi > 0); 61. } 62. 63. /* If a time is given, use it to timeout this function, otherwise the 64. * function times out by its own means. 65. */ 66. void 67. set_occupation(fn, txt, time) 68. int (*fn)(); 69. char *txt; 70. { 71. if (time) { 72. occupation = timed_occupation; 73. timed_occ_fn = fn; 74. } else 75. occupation = fn; 76. occtxt = txt; 77. occtime = 0; 78. } 79. #endif /* DGKMOD */ 80. 81. #ifdef REDO 82. /* Provide a means to redo the last command. The flag `in_doagain' is set 83. * to true while redoing the command. This flag is tested in commands that 84. * require additional input (like `throw' which requires a thing and a 85. * direction), and the input prompt is not shown. Also, while in_doagain is 86. * TRUE, no keystrokes can be saved into the saveq. 87. */ 88. #define BSIZE 20 89. static char pushq[BSIZE], saveq[BSIZE]; 90. static int phead, ptail, shead, stail; 91. extern int in_doagain; 92. 93. char 94. popch() { 95. /* If occupied, return 0, letting tgetch know a character should 96. * be read from the keyboard. If the character read is not the 97. * ABORT character (as checked in main.c), that character will be 98. * pushed back on the pushq. 99. */ 100. if (occupation) return(0); 101. if (in_doagain) return ((shead != stail) ? saveq[stail++] : 0); 102. else return ((phead != ptail) ? pushq[ptail++] : 0); 103. } 104. 105. /* A ch == 0 resets the pushq */ 106. void 107. pushch(ch) 108. char ch; 109. { 110. if (!ch) 111. phead = ptail = 0; 112. if (phead < BSIZE) 113. pushq[phead++] = ch; 114. } 115. 116. /* A ch == 0 resets the saveq. Only save keystrokes when not 117. * replaying a previous command. 118. */ 119. void 120. savech(ch) 121. char ch; 122. { 123. if (!in_doagain) { 124. if (!ch) 125. phead = ptail = shead = stail = 0; 126. else if (shead < BSIZE) 127. saveq[shead++] = ch; 128. } 129. } 130. #endif /* REDO */ 131. 132. struct func_tab cmdlist[]={ 133. #if defined(DGKMOD) && defined(DEBUG_DOESNT_WORK) 134. {'\004', /* ^D */ dodebug}, /* generic debug function */ 135. #endif 136. #ifdef WIZARD 137. {'\005', /* ^E */ wiz_detect}, 138. {'\006', /* ^F */ wiz_map}, 139. {'\011', /* ^I */ wiz_identify}, 140. #endif 141. {'\020', /* ^P */ doredotopl}, 142. {'\022', /* ^R */ doredraw}, 143. {'\024', /* ^T */ dotele}, 144. #ifdef WIZARD 145. {'\027', /* ^W */ wiz_wish}, 146. {'\030', /* ^X */ wiz_attributes}, 147. #endif 148. #ifdef SUSPEND 149. {'\032', /* ^Z */ dosuspend}, 150. #endif 151. {'a', doapply}, 152. {'A', doddoremarm}, 153. /* 'b', 'B' : go sw */ 154. {'c', ddocall}, 155. {'C', do_mname}, 156. {'d', dodrop}, 157. {'D', doddrop}, 158. {'e', doeat}, 159. {'E', doengrave}, 160. /* Soon to be 161. {'f', dofight, "fighting"}, 162. {'F', doFight, "fighting"}, 163. */ 164. /* 'g', 'G' : multiple go */ 165. /* 'h', 'H' : go west */ 166. {'I', dotypeinv}, /* Robert Viduya */ 167. {'i', ddoinv}, 168. /* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */ 169. /* 'o', doopen, */ 170. {'O', doset}, 171. {'p', dopay}, 172. {'P', dowearring}, 173. {'q', dodrink}, 174. {'Q', done1}, 175. {'r', doread}, 176. {'R', doremring}, 177. {'s', dosearch, "searching"}, 178. {'S', dosave}, 179. {'t', dothrow}, 180. {'T', doremarm}, 181. /* 'u', 'U' : go ne */ 182. {'v', doversion}, 183. {'w', dowield}, 184. {'W', doweararm}, 185. #ifdef SPELLS 186. {'x', dovspell}, /* Mike Stephenson */ 187. {'X', doxcribe}, /* Mike Stephenson */ 188. #endif 189. /* 'y', 'Y' : go nw */ 190. {'z', dozap}, 191. #ifdef SPELLS 192. {'Z', docast}, 193. #endif 194. {'<', doup}, 195. {'>', dodown}, 196. {'/', dowhatis}, 197. {'?', dohelp}, 198. #ifdef SHELL 199. {'!', dosh}, 200. #endif 201. {'.', donull, "waiting"}, 202. {' ', donull, "waiting"}, 203. {',', dopickup}, 204. {':', dolook}, 205. {'^', doidtrap}, 206. {'\\', dodiscovered}, /* Robert Viduya */ 207. #ifdef DGKMOD 208. {'@', dotogglepickup}, 209. {'V', doMSCversion}, 210. #endif 211. {WEAPON_SYM, doprwep}, 212. {ARMOR_SYM, doprarm}, 213. {RING_SYM, doprring}, 214. {GOLD_SYM, doprgold}, 215. {'#', doextcmd}, 216. {0,0,0} 217. }; 218. 219. struct ext_func_tab extcmdlist[] = { 220. #ifdef KAA 221. "breathe", "breathe fire like a red dragon", dobreathe, 222. #endif 223. #ifdef SPELLS 224. "cast", "cast a spell", docast, 225. #endif 226. "dip", "dip an object into something", dodip, 227. #ifdef PRAYERS 228. #ifdef THEOLOGY 229. "sacrifice", "offer a sacrifice to the gods", dosacrifice, 230. #endif 231. "pray", "pray to the gods for help", dopray, 232. #endif 233. #ifdef KAA 234. "remove", "remove a cursed item", doremove, 235. #endif 236. #ifdef NEWCLASS 237. "rub", "rub a lamp", dorub, 238. "sit", "sit down", dosit, 239. "turn", "turn undead", doturn, 240. #endif 241. #if defined(KOPS) && defined(KAA) 242. "wipe", "wipe your face off", dowipe, 243. #endif 244. "?", "get this list of extended commands", doextlist, 245. (char *) 0, (char *) 0, donull 246. }; 247. 248. extern char *parse(), lowc(), unctrl(), quitchars[]; 249. 250. rhack(cmd) 251. register char *cmd; 252. { 253. register struct func_tab *tlist = cmdlist; 254. boolean firsttime = FALSE; 255. register res; 256. 257. if(!cmd) { 258. firsttime = TRUE; 259. flags.nopick = 0; 260. cmd = parse(); 261. } 262. #ifdef REDO 263. if (*cmd == DOAGAIN && !in_doagain && saveq[0]) { 264. in_doagain = TRUE; 265. stail = 0; 266. rhack((char *) 0); /* read and execute command */ 267. in_doagain = FALSE; 268. return; 269. } 270. 271. /* Special case of *cmd == ' ' handled better below */ 272. if(!*cmd || *cmd == (char)0377) { 273. #else 274. if(!*cmd || *cmd == (char)0377 || (flags.no_rest_on_space && *cmd == ' ')){ 275. #endif 276. bell(); 277. flags.move = 0; 278. return; /* probably we just had an interrupt */ 279. } 280. if(movecmd(*cmd)) { 281. walk: 282. if(multi) flags.mv = 1; 283. domove(); 284. return; 285. } 286. if(movecmd(lowc(*cmd))) { 287. flags.run = 1; 288. rush: 289. if(firsttime){ 290. if(!multi) multi = COLNO; 291. u.last_str_turn = 0; 292. } 293. flags.mv = 1; 294. #ifdef QUEST 295. if(flags.run >= 4) finddir(); 296. if(firsttime){ 297. u.ux0 = u.ux + u.dx; 298. u.uy0 = u.uy + u.dy; 299. } 300. #endif 301. domove(); 302. return; 303. } 304. if((*cmd == 'g' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) { 305. flags.run = 2; 306. goto rush; 307. } 308. if(*cmd == 'G' && movecmd(lowc(cmd[1]))) { 309. flags.run = 3; 310. goto rush; 311. } 312. if(*cmd == 'm' && movecmd(cmd[1])) { 313. flags.run = 0; 314. flags.nopick = 1; 315. goto walk; 316. } 317. if(*cmd == 'M' && movecmd(lowc(cmd[1]))) { 318. flags.run = 1; 319. flags.nopick = 1; 320. goto rush; 321. } 322. #ifdef QUEST 323. if(*cmd == cmd[1] && (*cmd == 'g' || *cmd == 'G')) { 324. flags.run = 4; 325. if(*cmd == 'G') flags.run += 2; 326. if(cmd[2] == '-') flags.run += 1; 327. goto rush; 328. } 329. #endif 330. while(tlist->f_char) { 331. if(*cmd == tlist->f_char){ 332. #ifdef DGKMOD 333. /* Special case of *cmd == ' ' handled here */ 334. if (*cmd == ' ' && flags.no_rest_on_space) 335. break; 336. 337. /* Now control-A can stop lengthy commands */ 338. if (tlist->f_text && !occupation && multi) 339. set_occupation(tlist->f_funct, tlist->f_text, 340. multi); 341. #endif 342. res = (*(tlist->f_funct))(); 343. if(!res) { 344. flags.move = 0; 345. multi = 0; 346. } 347. return; 348. } 349. tlist++; 350. } 351. { char expcmd[10]; 352. register char *cp = expcmd; 353. while(*cmd && cp-expcmd < sizeof(expcmd)-2) { 354. if(*cmd >= 040 && *cmd < 0177) 355. *cp++ = *cmd++; 356. else { 357. *cp++ = '^'; 358. *cp++ = *cmd++ ^ 0100; 359. } 360. } 361. *cp++ = 0; 362. pline("Unknown command '%s'.", expcmd); 363. } 364. multi = flags.move = 0; 365. return; 366. } 367. 368. doextcmd() /* here after # - now read a full-word command */ 369. { 370. char buf[BUFSZ]; 371. register struct ext_func_tab *efp = extcmdlist; 372. 373. pline("# "); 374. #ifdef COM_COMPL 375. get_ext_cmd(buf); 376. #else 377. getlin(buf); 378. #endif 379. clrlin(); 380. if(buf[0] == '\033') 381. return(0); 382. while(efp->ef_txt) { 383. if(!strcmp(efp->ef_txt, buf)) 384. return((*(efp->ef_funct))()); 385. efp++; 386. } 387. pline("%s: unknown command.", buf); 388. return(0); 389. } 390. 391. doextlist() /* here after #? - now list all full-word commands */ 392. { 393. register struct ext_func_tab *efp = extcmdlist; 394. char buf[BUFSZ]; 395. 396. set_pager(0); 397. if(page_line("") || 398. page_line(" Extended Command Set:") || 399. page_line("")) goto quit; 400. 401. while(efp->ef_txt) { 402. 403. (void)sprintf(buf, " %-8s - %s.", efp->ef_txt, efp->ef_desc); 404. if(page_line(buf)) goto quit; 405. efp++; 406. } 407. set_pager(1); 408. return(0); 409. quit: 410. set_pager(2); 411. return(0); 412. } 413. 414. char 415. lowc(sym) 416. char sym; 417. { 418. return( (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym ); 419. } 420. 421. char 422. unctrl(sym) 423. char sym; 424. { 425. return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym ); 426. } 427. 428. /* 'rogue'-like direction commands */ 429. char sdir[] = "hykulnjb><"; 430. schar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 }; 431. schar ydir[10] = { 0,-1,-1,-1, 0, 1, 1, 1, 0, 0 }; 432. schar zdir[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1,-1 }; 433. 434. movecmd(sym) /* also sets u.dz, but returns false for <> */ 435. char sym; 436. { 437. register char *dp; 438. 439. u.dz = 0; 440. if(!(dp = index(sdir, sym))) return(0); 441. u.dx = xdir[dp-sdir]; 442. u.dy = ydir[dp-sdir]; 443. u.dz = zdir[dp-sdir]; 444. return(!u.dz); 445. } 446. 447. getdir(s) 448. boolean s; 449. { 450. char dirsym; 451. 452. #ifdef REDO 453. if (!in_doagain) 454. #endif 455. if(s) pline("In what direction?"); 456. dirsym = readchar(); 457. #ifdef REDO 458. savech(dirsym); 459. #endif 460. #ifdef KAA 461. if(dirsym == '.' || dirsym == 's') 462. u.dx = u.dy = u.dz = 0; 463. else 464. #endif 465. if(!movecmd(dirsym) && !u.dz) { 466. if(!index(quitchars, dirsym)) 467. pline("What a strange direction!"); 468. return(0); 469. } 470. if(Confusion && !u.dz) confdir(); 471. return(1); 472. } 473. 474. confdir() 475. { 476. register x = rn2(8); 477. u.dx = xdir[x]; 478. u.dy = ydir[x]; 479. } 480. 481. #ifdef QUEST 482. finddir(){ 483. register int i, ui = u.di; 484. for(i = 0; i <= 8; i++){ 485. if(flags.run & 1) ui++; else ui += 7; 486. ui %= 8; 487. if(i == 8){ 488. pline("Not near a wall."); 489. flags.move = multi = 0; 490. return(0); 491. } 492. if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui])) 493. break; 494. } 495. for(i = 0; i <= 8; i++){ 496. if(flags.run & 1) ui += 7; else ui++; 497. ui %= 8; 498. if(i == 8){ 499. pline("Not near a room."); 500. flags.move = multi = 0; 501. return(0); 502. } 503. if(isroom(u.ux+xdir[ui], u.uy+ydir[ui])) 504. break; 505. } 506. u.di = ui; 507. u.dx = xdir[ui]; 508. u.dy = ydir[ui]; 509. } 510. 511. isroom(x,y) register x,y; { /* what about POOL? */ 512. return(isok(x,y) && (levl[x][y].typ == ROOM || 513. (levl[x][y].typ >= LDOOR && flags.run >= 6))); 514. } 515. #endif /* QUEST /**/ 516. 517. isok(x,y) register x,y; { 518. /* x corresponds to curx, so x==1 is the first column. Ach. %% */ 519. return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1); 520. } 521. 522. #ifdef WIZARD 523. int wiz_wish() /* Unlimited wishes for wizard mode by Paul Polderman */ 524. { 525. if (!wizard) { 526. pline("Alas! You are not allowed to make a wish."); 527. pline("Nice try though..."); 528. } else 529. makewish(); 530. return(0); 531. } 532. 533. int wiz_identify() 534. { 535. struct obj *obj; 536. 537. if (!wizard) 538. pline("You don't have the proper identity!"); 539. else { 540. for (obj = invent; obj; obj = obj->nobj) 541. if (!objects[obj->otyp].oc_name_known || !obj->known) 542. identify(obj); 543. } 544. return(0); 545. } 546. 547. int wiz_map() 548. { 549. if (wizard) do_mapping(); 550. else pline("If you want a map, you'll have to make one yourself!"); 551. } 552. 553. int wiz_detect() 554. { 555. if(wizard) { 556. if(!findit()) return; 557. } else pline("Don't ask me where anything is, I only work here!"); 558. } 559. 560. int wiz_attributes() 561. { 562. char buf[BUFSZ]; 563. 564. if (!wizard) { 565. pline("Alas! You are not allowed see attributes."); 566. pline("Nice try though..."); 567. return; 568. } 569. 570. set_pager(0); 571. if(page_line("Current Attributes:") || page_line("")) goto quit; 572. 573. if (Adornment) { 574. (void) sprintf(buf, "You are adorned."); 575. if(page_line(buf)) goto quit; 576. } 577. if (Teleportation) { 578. (void) sprintf(buf, "You can teleport."); 579. if(page_line(buf)) goto quit; 580. } 581. if (Regeneration) { 582. (void) sprintf(buf, "You regenerate."); 583. if(page_line(buf)) goto quit; 584. } 585. if (Searching) { 586. (void) sprintf(buf, "You have searching."); 587. if(page_line(buf)) goto quit; 588. } 589. if (See_invisible) { 590. (void) sprintf(buf, "You see invisible."); 591. if(page_line(buf)) goto quit; 592. } 593. if (Stealth) { 594. (void) sprintf(buf, "You have stealth."); 595. if(page_line(buf)) goto quit; 596. } 597. if (Levitation) { 598. (void) sprintf(buf, "You are levitated."); 599. if(page_line(buf)) goto quit; 600. } 601. if (Poison_resistance) { 602. (void) sprintf(buf, "You are poison resistant."); 603. if(page_line(buf)) goto quit; 604. } 605. if (Aggravate_monster) { 606. (void) sprintf(buf, "You aggravate monsters."); 607. if(page_line(buf)) goto quit; 608. } 609. if (Hunger) { 610. (void) sprintf(buf, "You have hunger."); 611. if(page_line(buf)) goto quit; 612. } 613. if (Fire_resistance) { 614. (void) sprintf(buf, "You are fire resistant."); 615. if(page_line(buf)) goto quit; 616. } 617. if (Cold_resistance) { 618. (void) sprintf(buf, "You are cold resistant."); 619. if(page_line(buf)) goto quit; 620. } 621. if (Protection_from_shape_changers) { 622. (void) sprintf(buf, "You are protected from shape changers."); 623. if(page_line(buf)) goto quit; 624. } 625. if (Conflict) { 626. (void) sprintf(buf, "You cause conflict."); 627. if(page_line(buf)) goto quit; 628. } 629. if (Gain_strength) { 630. (void) sprintf(buf, "You have extra strength."); 631. if(page_line(buf)) goto quit; 632. } 633. if (Increase_damage) { 634. (void) sprintf(buf, "You cause extra damage."); 635. if(page_line(buf)) goto quit; 636. } 637. if (Protection) { 638. (void) sprintf(buf, "You are protected."); 639. if(page_line(buf)) goto quit; 640. } 641. if (Warning) { 642. (void) sprintf(buf, "You are warned."); 643. if(page_line(buf)) goto quit; 644. } 645. if (Teleport_control) { 646. (void) sprintf(buf, "You have teleport control."); 647. if(page_line(buf)) goto quit; 648. } 649. if (Polymorph) { 650. (void) sprintf(buf, "You are polymorphing."); 651. if(page_line(buf)) goto quit; 652. } 653. if (Polymorph_control) { 654. (void) sprintf(buf, "You have polymorph control."); 655. if(page_line(buf)) goto quit; 656. } 657. if (Shock_resistance) { 658. (void) sprintf(buf, "You are shock resistant."); 659. if(page_line(buf)) goto quit; 660. } 661. if (Telepat) { 662. (void) sprintf(buf, "You have telepathy."); 663. if(page_line(buf)) goto quit; 664. } 665. if (Fast) { 666. (void) sprintf(buf, "You are fast."); 667. if(page_line(buf)) goto quit; 668. } 669. if (Confusion) { 670. (void) sprintf(buf, "You are confused."); 671. if(page_line(buf)) goto quit; 672. } 673. if (Invisible) { 674. (void) sprintf(buf, "You are invisible."); 675. if(page_line(buf)) goto quit; 676. } 677. if (Glib) { 678. (void) sprintf(buf, "You are glib."); 679. if(page_line(buf)) goto quit; 680. } 681. if (Punished) { 682. (void) sprintf(buf, "You are punished."); 683. if(page_line(buf)) goto quit; 684. } 685. if (Sick) { 686. (void) sprintf(buf, "You are sick."); 687. if(page_line(buf)) goto quit; 688. } 689. if (Blinded) { 690. (void) sprintf(buf, "You are blinded."); 691. if(page_line(buf)) goto quit; 692. } 693. if (Wounded_legs) { 694. (void) sprintf(buf, "You have wounded legs."); 695. if(page_line(buf)) goto quit; 696. } 697. if (Stoned) { 698. (void) sprintf(buf, "You are stoned."); 699. if(page_line(buf)) goto quit; 700. } 701. if (Hallucination) { 702. (void) sprintf(buf, "You are hallucinated."); 703. if(page_line(buf)) goto quit; 704. } 705. if (Blindfolded) { 706. (void) sprintf(buf, "You are blindfolded."); 707. if(page_line(buf)) goto quit; 708. } 709. if (Badged) { 710. (void) sprintf(buf, "You are badged."); 711. if(page_line(buf)) goto quit; 712. } 713. 714. set_pager(1); 715. return(0); 716. quit: 717. set_pager(2); 718. return(0); 719. } 720. #endif /* WIZARD */