Source:NetHack 3.1.0/cmd.c
Jump to navigation
Jump to search
Below is the full text to cmd.c from the source code of NetHack 3.1.0.
Warning! This is the source code from an old release. For newer releases, see Source code
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
1. /* SCCS Id: @(#)cmd.c 3.1 92/11/25 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "func_tab.h" 7. 8. /* 9. * Some systems may have getchar() return EOF for various reasons, and 10. * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs. 11. */ 12. #if defined(SYSV) || defined(DGUX) || defined(HPUX) 13. #define NR_OF_EOFS 20 14. #endif 15. 16. #ifdef DUMB /* stuff commented out in extern.h, but needed here */ 17. extern int NDECL(doapply); /**/ 18. extern int NDECL(dorub); /**/ 19. extern int NDECL(dojump); /**/ 20. extern int NDECL(doextlist); /**/ 21. extern int NDECL(dodrop); /**/ 22. extern int NDECL(doddrop); /**/ 23. extern int NDECL(dodown); /**/ 24. extern int NDECL(doup); /**/ 25. extern int NDECL(donull); /**/ 26. extern int NDECL(dowipe); /**/ 27. extern int NDECL(do_mname); /**/ 28. extern int NDECL(ddocall); /**/ 29. extern int NDECL(dotakeoff); /**/ 30. extern int NDECL(doremring); /**/ 31. extern int NDECL(dowear); /**/ 32. extern int NDECL(doputon); /**/ 33. extern int NDECL(doddoremarm); /**/ 34. extern int NDECL(dokick); /**/ 35. extern int NDECL(dothrow); /**/ 36. extern int NDECL(doeat); /**/ 37. extern int NDECL(done2); /**/ 38. extern int NDECL(doengrave); /**/ 39. extern int NDECL(dopickup); /**/ 40. extern int NDECL(ddoinv); /**/ 41. extern int NDECL(dotypeinv); /**/ 42. extern int NDECL(dolook); /**/ 43. extern int NDECL(doprgold); /**/ 44. extern int NDECL(doprwep); /**/ 45. extern int NDECL(doprarm); /**/ 46. extern int NDECL(doprring); /**/ 47. extern int NDECL(dopramulet); /**/ 48. extern int NDECL(doprtool); /**/ 49. extern int NDECL(dosuspend); /**/ 50. extern int NDECL(doforce); /**/ 51. extern int NDECL(doopen); /**/ 52. extern int NDECL(doclose); /**/ 53. extern int NDECL(dosh); /**/ 54. extern int NDECL(dodiscovered); /**/ 55. extern int NDECL(doset); /**/ 56. extern int NDECL(dotogglepickup); /**/ 57. extern int NDECL(dowhatis); /**/ 58. extern int NDECL(doquickwhatis); /**/ 59. extern int NDECL(dowhatdoes); /**/ 60. extern int NDECL(dohelp); /**/ 61. extern int NDECL(dohistory); /**/ 62. extern int NDECL(doloot); /**/ 63. extern int NDECL(dodrink); /**/ 64. extern int NDECL(dodip); /**/ 65. extern int NDECL(dosacrifice); /**/ 66. extern int NDECL(dopray); /**/ 67. extern int NDECL(doturn); /**/ 68. extern int NDECL(doredraw); /**/ 69. extern int NDECL(doread); /**/ 70. extern int NDECL(dosave); /**/ 71. extern int NDECL(dosearch); /**/ 72. extern int NDECL(doidtrap); /**/ 73. extern int NDECL(dopay); /**/ 74. extern int NDECL(dosit); /**/ 75. extern int NDECL(dotalk); /**/ 76. extern int NDECL(docast); /**/ 77. extern int NDECL(dovspell); /**/ 78. extern int NDECL(dotele); /**/ 79. extern int NDECL(dountrap); /**/ 80. extern int NDECL(doversion); /**/ 81. extern int NDECL(doextversion); /**/ 82. extern int NDECL(dowield); /**/ 83. extern int NDECL(dozap); /**/ 84. extern int NDECL(doorganize); /**/ 85. #endif /* DUMB */ 86. 87. #ifdef OVL1 88. static int NDECL((*timed_occ_fn)); 89. #endif /* OVL1 */ 90. 91. STATIC_PTR int NDECL(doprev_message); 92. STATIC_PTR int NDECL(timed_occupation); 93. STATIC_PTR int NDECL(doextcmd); 94. # ifdef POLYSELF 95. STATIC_PTR int NDECL(domonability); 96. # endif 97. # ifdef WIZARD 98. STATIC_PTR int NDECL(wiz_wish); 99. STATIC_PTR int NDECL(wiz_identify); 100. STATIC_PTR int NDECL(wiz_map); 101. STATIC_PTR int NDECL(wiz_genesis); 102. STATIC_PTR int NDECL(wiz_where); 103. STATIC_PTR int NDECL(wiz_detect); 104. STATIC_PTR int NDECL(wiz_level_tele); 105. # endif 106. # ifdef EXPLORE_MODE 107. STATIC_PTR int NDECL(enter_explore_mode); 108. # endif 109. # if defined(WIZARD) || defined(EXPLORE_MODE) 110. STATIC_PTR int NDECL(wiz_attributes); 111. # endif 112. 113. #ifdef OVLB 114. static void FDECL(enlght_line, (const char *,const char *,const char *)); 115. #ifdef UNIX 116. static void NDECL(end_of_input); 117. #endif 118. #endif /* OVLB */ 119. 120. #ifdef OVL0 121. static int FDECL(click_to_cmd, (int,int,int)); 122. #endif /* OVL0 */ 123. 124. STATIC_OVL char *NDECL(parse); 125. 126. #ifdef UNIX 127. extern boolean hu; 128. #endif 129. 130. #ifdef OVL1 131. 132. STATIC_PTR int 133. doprev_message() 134. { 135. return nh_doprev_message(); 136. } 137. 138. /* Count down by decrementing multi */ 139. STATIC_PTR int 140. timed_occupation() { 141. (*timed_occ_fn)(); 142. if (multi > 0) 143. multi--; 144. return multi > 0; 145. } 146. 147. /* If you have moved since initially setting some occupations, they 148. * now shouldn't be able to restart. 149. * 150. * The basic rule is that if you are carrying it, you can continue 151. * since it is with you. If you are acting on something at a distance, 152. * your orientation to it must have changed when you moved. 153. * 154. * The exception to this is taking off items, since they can be taken 155. * off in a number of ways in the intervening time, screwing up ordering. 156. * 157. * Currently: Take off all armor. 158. * Picking Locks / Forcing Chests. 159. */ 160. void 161. reset_occupations() { 162. 163. reset_remarm(); 164. reset_pick(); 165. } 166. 167. /* If a time is given, use it to timeout this function, otherwise the 168. * function times out by its own means. 169. */ 170. void 171. set_occupation(fn, txt, xtime) 172. int NDECL((*fn)); 173. const char *txt; 174. int xtime; 175. { 176. if (xtime) { 177. occupation = timed_occupation; 178. timed_occ_fn = fn; 179. } else 180. occupation = fn; 181. occtxt = txt; 182. occtime = 0; 183. return; 184. } 185. 186. #ifdef REDO 187. 188. static char NDECL(popch); 189. 190. /* Provide a means to redo the last command. The flag `in_doagain' is set 191. * to true while redoing the command. This flag is tested in commands that 192. * require additional input (like `throw' which requires a thing and a 193. * direction), and the input prompt is not shown. Also, while in_doagain is 194. * TRUE, no keystrokes can be saved into the saveq. 195. */ 196. #define BSIZE 20 197. static char pushq[BSIZE], saveq[BSIZE]; 198. static int NEARDATA phead, NEARDATA ptail, NEARDATA shead, NEARDATA stail; 199. 200. static char 201. popch() { 202. /* If occupied, return '\0', letting tgetch know a character should 203. * be read from the keyboard. If the character read is not the 204. * ABORT character (as checked in pcmain.c), that character will be 205. * pushed back on the pushq. 206. */ 207. if (occupation) return '\0'; 208. if (in_doagain) return (shead != stail) ? saveq[stail++] : '\0'; 209. else return (phead != ptail) ? pushq[ptail++] : '\0'; 210. } 211. 212. char 213. pgetchar() { /* curtesy of aeb@cwi.nl */ 214. register int ch; 215. 216. if(!(ch = popch())) 217. ch = nhgetch(); 218. return(ch); 219. } 220. 221. /* A ch == 0 resets the pushq */ 222. void 223. pushch(ch) 224. char ch; 225. { 226. if (!ch) 227. phead = ptail = 0; 228. if (phead < BSIZE) 229. pushq[phead++] = ch; 230. return; 231. } 232. 233. /* A ch == 0 resets the saveq. Only save keystrokes when not 234. * replaying a previous command. 235. */ 236. void 237. savech(ch) 238. char ch; 239. { 240. if (!in_doagain) { 241. if (!ch) 242. phead = ptail = shead = stail = 0; 243. else if (shead < BSIZE) 244. saveq[shead++] = ch; 245. } 246. return; 247. } 248. #endif /* REDO */ 249. 250. #endif /* OVL1 */ 251. #ifdef OVLB 252. 253. STATIC_PTR int 254. doextcmd() /* here after # - now read a full-word command */ 255. { 256. char buf[BUFSZ]; 257. register const struct ext_func_tab *efp = extcmdlist; 258. again: 259. #ifdef COM_COMPL 260. get_ext_cmd(buf); 261. #else 262. getlin("#", buf); 263. #endif 264. clear_nhwindow(WIN_MESSAGE); 265. if(buf[0] == '\0' || buf[0] == '\033') 266. return 0; 267. if(buf[0] == '?') { 268. (void) doextlist(); 269. goto again; 270. } 271. while(efp->ef_txt) { 272. if(!strncmpi(efp->ef_txt, buf,BUFSIZ)) 273. return (*(efp->ef_funct))(); 274. efp++; 275. } 276. pline("%s: unknown extended command.", buf); 277. return 0; 278. } 279. 280. int 281. doextlist() /* here after #? - now list all full-word commands */ 282. { 283. register const struct ext_func_tab *efp; 284. char buf[BUFSZ]; 285. winid datawin; 286. 287. datawin = create_nhwindow(NHW_TEXT); 288. putstr(datawin, 0, ""); 289. putstr(datawin, 0, " Extended Commands List"); 290. putstr(datawin, 0, ""); 291. #ifdef COM_COMPL 292. putstr(datawin, 0, " Press '#', then type (first letter only):"); 293. #else 294. putstr(datawin, 0, " Press '#', then type:"); 295. #endif 296. putstr(datawin, 0, ""); 297. 298. for(efp = extcmdlist; efp->ef_txt; efp++) { 299. Sprintf(buf, " %-8s - %s.", efp->ef_txt, efp->ef_desc); 300. putstr(datawin, 0, buf); 301. } 302. display_nhwindow(datawin, FALSE); 303. destroy_nhwindow(datawin); 304. return 0; 305. } 306. 307. #ifdef POLYSELF 308. STATIC_PTR int 309. domonability() 310. { 311. if (can_breathe(uasmon)) return dobreathe(); 312. else if (attacktype(uasmon, AT_SPIT)) return dospit(); 313. else if (u.usym == S_NYMPH) return doremove(); 314. else if (u.usym == S_UMBER) return doconfuse(); 315. else if (is_were(uasmon)) return dosummon(); 316. else if (webmaker(uasmon)) return dospinweb(); 317. else if (is_hider(uasmon)) return dohide(); 318. else if(u.umonnum == PM_GREMLIN) { 319. if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 320. struct monst *mtmp; 321. if ((mtmp = cloneu()) != 0) { 322. mtmp->mhpmax = (u.mhmax /= 2); 323. You("multiply."); 324. dryup(u.ux,u.uy); 325. } 326. } else pline("There is no fountain here."); 327. } 328. else if (u.usym == S_UNICORN) { 329. use_unicorn_horn((struct obj *)0); 330. return 1; 331. } else if (u.umonnum == PM_MIND_FLAYER) return domindblast(); 332. else if (uasmon->msound == MS_SHRIEK) { 333. You("shriek."); 334. aggravate(); 335. } else if (u.umonnum >= 0) 336. pline("Any special ability you may have is purely reflexive."); 337. else You("don't have a special ability!"); 338. return 0; 339. } 340. #endif 341. 342. #ifdef EXPLORE_MODE 343. STATIC_PTR int 344. enter_explore_mode() 345. { 346. if(!discover && !wizard) { 347. pline("Beware! From discovery mode there will be no return to normal game."); 348. if (yn("Do you want to enter discovery mode?") == 'y') { 349. clear_nhwindow(WIN_MESSAGE); 350. You("are now in non-scoring discovery mode."); 351. discover = TRUE; 352. } 353. else { 354. clear_nhwindow(WIN_MESSAGE); 355. pline("Resuming normal game."); 356. } 357. } 358. return 0; 359. } 360. #endif 361. 362. #ifdef WIZARD 363. STATIC_PTR int 364. wiz_wish() /* Unlimited wishes for debug mode by Paul Polderman */ 365. { 366. if (wizard) { 367. makewish(); 368. (void) encumber_msg(); 369. } else 370. pline("Unavailable command '^W'."); 371. return 0; 372. } 373. 374. STATIC_PTR int 375. wiz_identify() 376. { 377. struct obj *obj; 378. 379. if (!wizard) 380. pline("Unavailable command '^I'."); 381. else { 382. for (obj = invent; obj; obj = obj->nobj) 383. if (!objects[obj->otyp].oc_name_known || !obj->known 384. || !obj->dknown || !obj->bknown) 385. (void) identify(obj); 386. } 387. return 0; 388. } 389. 390. STATIC_PTR int 391. wiz_map() 392. { 393. if (wizard) do_mapping(); 394. else pline("Unavailable command '^F'."); 395. return 0; 396. } 397. 398. STATIC_PTR int 399. wiz_genesis() 400. { 401. if (wizard) (void) create_particular(); 402. else pline("Unavailable command '^G'."); 403. return 0; 404. } 405. 406. STATIC_PTR int 407. wiz_where() 408. { 409. if (wizard) print_dungeon(); 410. else pline("Unavailable command '^O'."); 411. return 0; 412. } 413. 414. STATIC_PTR int 415. wiz_detect() 416. { 417. if(wizard) (void) findit(); 418. else pline("Unavailable command '^E'."); 419. return 0; 420. } 421. 422. STATIC_PTR int 423. wiz_level_tele() 424. { 425. if (wizard) level_tele(); 426. else pline("Unavailable command '^V'."); 427. return 0; 428. } 429. 430. #endif /* WIZARD */ 431. 432. /* -enlightenment- */ 433. static winid en_win; 434. static const char 435. *You_ = "You ", 436. *are = "are ", *were = "were ", 437. *have = "have ", *had = "had ", 438. *can = "can ", *could = "could "; 439. 440. #define enl_msg(prefix,present,past,suffix) \ 441. enlght_line(prefix, final ? past : present, suffix) 442. #define you_are(attr) enl_msg(You_,are,were,attr) 443. #define you_have(attr) enl_msg(You_,have,had,attr) 444. #define you_can(attr) enl_msg(You_,can,could,attr) 445. 446. static void 447. enlght_line(start, middle, end) 448. const char *start, *middle, *end; 449. { 450. char buf[BUFSZ]; 451. 452. Sprintf(buf, "%s%s%s.", start, middle, end); 453. putstr(en_win, 0, buf); 454. } 455. 456. void 457. enlightenment(final) 458. boolean final; 459. { 460. int ltmp; 461. char buf[BUFSZ]; 462. 463. en_win = create_nhwindow(NHW_MENU); 464. putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:"); 465. putstr(en_win, 0, ""); 466. 467. /* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */ 468. if (u.ualign.record >= 20) you_are("piously aligned"); 469. else if (u.ualign.record > 13) you_are("devoutly aligned"); 470. else if (u.ualign.record > 8) you_are("fervently aligned"); 471. else if (u.ualign.record > 3) you_are("stridently aligned"); 472. else if (u.ualign.record == 3) you_are("aligned"); 473. else if (u.ualign.record > 0) you_are("haltingly aligned"); 474. else if (u.ualign.record == 0) you_are("nominally aligned"); 475. else if (u.ualign.record >= -3) you_have("strayed"); 476. else if (u.ualign.record >= -8) you_have("sinned"); 477. else you_have("transgressed"); 478. #ifdef WIZARD 479. if (wizard) { 480. Sprintf(buf, " %d", u.ualign.record); 481. enl_msg("Your alignment ", "is", "was", buf); 482. } 483. #endif 484. 485. if (Telepat) you_are("telepathic"); 486. if (Searching) you_have("automatic searching"); 487. if (Teleportation) you_can("teleport"); 488. if (Teleport_control) you_have("teleport control"); 489. if (See_invisible) enl_msg(You_, "see", "saw", " invisible"); 490. if (Invisible) you_are("invisible"); 491. else if (Invis) you_are("invisible to others"); 492. if (Fast) you_are((Fast & ~INTRINSIC) ? "very fast" : "fast"); 493. if (Stealth) you_are("stealthy"); 494. if (Regeneration) enl_msg("You regenerate", "", "d", ""); 495. if (Hunger) you_have("hunger"); 496. if (Conflict) enl_msg("You cause", "", "d", " conflict"); 497. if (Aggravate_monster) enl_msg("You aggravate", "", "d", " monsters"); 498. if (Poison_resistance) you_are("poison resistant"); 499. if (Fire_resistance) you_are("fire resistant"); 500. if (Cold_resistance) you_are("cold resistant"); 501. if (Shock_resistance) you_are("shock resistant"); 502. if (Sleep_resistance) you_are("sleep resistant"); 503. if (Disint_resistance) you_are("disintegration-resistant"); 504. if (Protection_from_shape_changers) 505. you_are("protected from shape changers"); 506. #ifdef POLYSELF 507. if (Polymorph) you_are("polymorphing"); 508. if (Polymorph_control) you_have("polymorph control"); 509. #endif 510. if (HHalluc_resistance) 511. enl_msg("You resist", "", "ed", " hallucinations"); 512. if (final) { 513. if (Hallucination) you_are("hallucinating"); 514. if (Stunned) you_are("stunned"); 515. if (Confusion) you_are("confused"); 516. if (Sick) you_are("sick"); 517. if (Blinded) you_are("blinded"); 518. } 519. if (Wounded_legs) { 520. Sprintf(buf, "wounded %s", makeplural(body_part(LEG))); 521. you_have(buf); 522. } 523. if (Glib) { 524. Sprintf(buf, "slippery %s", makeplural(body_part(FINGER))); 525. you_have(buf); 526. } 527. if (Strangled) you_are("being strangled"); 528. if (Stoned) you_are("turning to stone"); 529. if (Lifesaved) 530. enl_msg("Your life ", "will be", "would have been", " saved"); 531. if (Adornment) you_are("adorned"); 532. if (Warning) you_are("warned"); 533. if (Protection) you_are("protected"); 534. if (Reflecting) you_have("reflection"); 535. if (Levitation) you_are("levitating"); 536. if (Fumbling) enl_msg("You fumble", "", "d", ""); 537. if (Jumping) you_can("jump"); 538. if (Wwalking) you_can("walk on water"); 539. if (Magical_breathing) you_can("survive without air"); 540. if (Antimagic) you_are("magic-protected"); 541. if (Displaced) you_are("displaced"); 542. if (Clairvoyant) you_are("clairvoyant"); 543. #ifdef POLYSELF 544. if (u.ulycn != -1) { 545. Strcpy(buf, an(mons[u.ulycn].mname)); 546. you_are(buf); 547. } 548. #endif 549. if (Luck) { 550. ltmp = abs((int)Luck); 551. Sprintf(buf, "%s%slucky", 552. ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "", 553. Luck < 0 ? "un" : ""); 554. #ifdef WIZARD 555. if (wizard) Sprintf(eos(buf), " (%d)", Luck); 556. #endif 557. you_are(buf); 558. } 559. #ifdef WIZARD 560. else if (wizard) enl_msg("Your luck ", "is", "was", " zero"); 561. #endif 562. ltmp = stone_luck(TRUE); 563. if (ltmp > 0) you_have("extra luck"); 564. else if (ltmp < 0) you_have("reduced luck"); 565. if (carrying(LUCKSTONE)) { 566. ltmp = stone_luck(FALSE); 567. if (ltmp <= 0) 568. enl_msg("Bad luck ", "does", "did", " not time out for you"); 569. if (ltmp >= 0) 570. enl_msg("Good luck ", "does", "did", " not time out for you"); 571. } 572. 573. display_nhwindow(en_win, TRUE); 574. destroy_nhwindow(en_win); 575. return; 576. } 577. 578. #if defined(WIZARD) || defined(EXPLORE_MODE) 579. STATIC_PTR int 580. wiz_attributes() 581. { 582. if (wizard || discover) 583. enlightenment(FALSE); 584. else 585. pline("Unavailable command '^X'."); 586. return 0; 587. } 588. #endif /* WIZARD || EXPLORE_MODE */ 589. 590. #endif /* OVLB */ 591. #ifdef OVL1 592. 593. #ifndef M 594. # ifndef NHSTDC 595. # define M(c) (0x80 | (c)) 596. # else 597. # define M(c) ((c) - 128) 598. # endif /* NHSTDC */ 599. #endif 600. #ifndef C 601. #define C(c) (0x1f & (c)) 602. #endif 603. 604. static const struct func_tab cmdlist[] = { 605. {C('d'), dokick}, /* "D" is for door!...? */ 606. #ifdef WIZARD 607. {C('e'), wiz_detect}, 608. {C('f'), wiz_map}, 609. {C('g'), wiz_genesis}, 610. {C('i'), wiz_identify}, 611. #endif 612. {C('l'), doredraw}, /* if number_pad is set */ 613. #ifdef WIZARD 614. {C('o'), wiz_where}, 615. #endif 616. {C('p'), doprev_message}, 617. {C('r'), doredraw}, 618. {C('t'), dotele}, 619. #ifdef WIZARD 620. {C('v'), wiz_level_tele}, 621. {C('w'), wiz_wish}, 622. #endif 623. #if defined(WIZARD) || defined(EXPLORE_MODE) 624. {C('x'), wiz_attributes}, 625. #endif 626. #ifdef SUSPEND 627. {C('z'), dosuspend}, 628. #endif 629. {'a', doapply}, 630. {'A', doddoremarm}, 631. {M('a'), doorganize}, 632. /* 'b', 'B' : go sw */ 633. {'c', doclose}, 634. {'C', do_mname}, 635. {M('c'), dotalk}, 636. {'d', dodrop}, 637. {'D', doddrop}, 638. {M('d'), dodip}, 639. {'e', doeat}, 640. {'E', doengrave}, 641. /* Soon to be 642. {'f', dofight, "fighting"}, 643. {'F', doFight, "fighting"}, 644. */ 645. {M('f'), doforce}, 646. /* 'g', 'G' : multiple go */ 647. /* 'h', 'H' : go west */ 648. {'h', dohelp}, /* if number_pad is set */ 649. {'i', ddoinv}, 650. {'I', dotypeinv}, /* Robert Viduya */ 651. {M('i'), doinvoke}, 652. /* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */ 653. {'j', dojump}, /* if number_pad is on */ 654. {M('j'), dojump}, 655. {'k', dokick}, /* if number_pad is on */ 656. {'l', doloot}, /* if number_pad is on */ 657. {M('l'), doloot}, 658. /* 'n' prefixes a count if number_pad is on */ 659. #ifdef POLYSELF 660. {M('m'), domonability}, 661. #endif /* POLYSELF */ 662. {'N', ddocall}, /* if number_pad is on */ 663. {M('N'), ddocall}, 664. {'o', doopen}, 665. {'O', doset}, 666. {M('o'), dosacrifice}, 667. {'p', dopay}, 668. {'P', doputon}, 669. {M('p'), dopray}, 670. {'q', dodrink}, 671. {'Q', done2}, 672. {'r', doread}, 673. {'R', doremring}, 674. {M('r'), dorub}, 675. {'s', dosearch, "searching"}, 676. {'S', dosave}, 677. {M('s'), dosit}, 678. {'t', dothrow}, 679. {'T', dotakeoff}, 680. {M('t'), doturn}, 681. /* 'u', 'U' : go ne */ 682. {'u', dountrap}, /* if number_pad is on */ 683. {M('u'), dountrap}, 684. {'v', doversion}, 685. {'V', dohistory}, 686. {M('v'), doextversion}, 687. {'w', dowield}, 688. {'W', dowear}, 689. {M('w'), dowipe}, 690. {'x', dovspell}, /* Mike Stephenson */ 691. #ifdef EXPLORE_MODE 692. {'X', enter_explore_mode}, 693. #endif 694. /* 'y', 'Y' : go nw */ 695. {'z', dozap}, 696. {'Z', docast}, 697. {'<', doup}, 698. {'>', dodown}, 699. {'/', dowhatis}, 700. {'&', dowhatdoes}, 701. {'?', dohelp}, 702. #ifdef SHELL 703. {'!', dosh}, 704. #endif 705. {'.', donull, "waiting"}, 706. {' ', donull, "waiting"}, 707. {',', dopickup}, 708. {':', dolook}, 709. {';', doquickwhatis}, 710. {'^', doidtrap}, 711. {'\\', dodiscovered}, /* Robert Viduya */ 712. {'@', dotogglepickup}, 713. {WEAPON_SYM, doprwep}, 714. {ARMOR_SYM, doprarm}, 715. {RING_SYM, doprring}, 716. {AMULET_SYM, dopramulet}, 717. {TOOL_SYM, doprtool}, 718. {GOLD_SYM, doprgold}, 719. {SPBOOK_SYM, dovspell}, /* Mike Stephenson */ 720. {'#', doextcmd}, 721. {0,0,0} 722. }; 723. #undef M 724. 725. const struct ext_func_tab extcmdlist[] = { 726. {"adjust", "adjust inventory letters", doorganize}, 727. {"chat", "talk to someone", dotalk}, /* converse? */ 728. {"dip", "dip an object into something", dodip}, 729. {"force", "force a lock", doforce}, 730. {"invoke", "invoke an object's powers", doinvoke}, 731. {"jump", "jump to a location", dojump}, 732. {"loot", "loot a box on the floor", doloot}, 733. #ifdef POLYSELF 734. {"monster", "use a monster's special ability", domonability}, 735. #endif 736. {"name", "name an item or type of object", ddocall}, 737. {"offer", "offer a sacrifice to the gods", dosacrifice}, 738. {"pray", "pray to the gods for help", dopray}, 739. {"rub", "rub a lamp", dorub}, 740. {"sit", "sit down", dosit}, 741. {"turn", "turn undead", doturn}, 742. {"untrap", "untrap something", dountrap}, 743. {"version", "list compile time options for this version of NetHack", 744. doextversion}, 745. #ifdef MAC 746. {"window", "clean up windows", SanePositions}, 747. #endif 748. {"wipe", "wipe off your face", dowipe}, 749. {"?", "get this list of extended commands", doextlist}, 750. {NULL, NULL, donull} 751. }; 752. 753. #define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c)) 754. #define unmeta(c) (0x7f & (c)) 755. 756. 757. void 758. rhack(cmd) 759. register char *cmd; 760. { 761. register const struct func_tab *tlist = cmdlist; 762. boolean firsttime = FALSE; 763. register int res; 764. 765. if(!cmd) { 766. firsttime = TRUE; 767. flags.nopick = 0; 768. cmd = parse(); 769. } 770. if(*cmd == (char)033) { 771. flags.move = 0; 772. return; 773. } 774. #ifdef REDO 775. if (*cmd == DOAGAIN && !in_doagain && saveq[0]) { 776. in_doagain = TRUE; 777. stail = 0; 778. rhack(NULL); /* read and execute command */ 779. in_doagain = FALSE; 780. return; 781. } 782. /* Special case of *cmd == ' ' handled better below */ 783. if(!*cmd || *cmd == (char)0377) { 784. #else 785. if(!*cmd || *cmd == (char)0377 || 786. (!flags.rest_on_space && *cmd == ' ')) { 787. #endif 788. nhbell(); 789. flags.move = 0; 790. return; /* probably we just had an interrupt */ 791. } 792. if(movecmd(*cmd)) { 793. walk: 794. if(multi) flags.mv = 1; 795. domove(); 796. return; 797. } 798. if(movecmd(flags.num_pad ? unmeta(*cmd) : lowc(*cmd))) { 799. flags.run = 1; 800. rush: 801. if(firsttime){ 802. if(!multi) multi = COLNO; 803. u.last_str_turn = 0; 804. } 805. flags.mv = 1; 806. domove(); 807. return; 808. } 809. if(*cmd == 'g' && movecmd(cmd[1])) { 810. flags.run = 2; 811. goto rush; 812. } 813. if (((*cmd == 'G' || (flags.num_pad && *cmd == '5')) && 814. movecmd(lowc(cmd[1]))) || movecmd(unctrl(*cmd))) { 815. flags.run = 3; 816. goto rush; 817. } 818. if((*cmd == 'm' || (flags.num_pad && *cmd == '-')) && 819. movecmd(cmd[1])) { 820. flags.run = 0; 821. flags.nopick = 1; 822. goto walk; 823. } 824. if(*cmd == 'M' && movecmd(lowc(cmd[1]))) { 825. flags.run = 1; 826. flags.nopick = 1; 827. goto rush; 828. } 829. if (flags.num_pad && *cmd == '0') { 830. (void)ddoinv(); /* A convenience borrowed from the PC */ 831. flags.move = 0; 832. multi = 0; 833. return; 834. } 835. while(tlist->f_char) { 836. if((*cmd & 0xff) == (tlist->f_char & 0xff)){ 837. /* Special case of *cmd == ' ' handled here */ 838. if (*cmd == ' ' && !flags.rest_on_space) 839. break; 840. 841. /* Now control-A can stop lengthy commands */ 842. /* in the PC version only -- use ^C-N otherwise */ 843. if (tlist->f_text && !occupation && multi) 844. #ifdef GCC_WARN 845. set_occupation(tlist->f_funct, 846. tlist->f_text, multi); 847. #else 848. set_occupation(((struct func_tab *)tlist)->f_funct, 849. tlist->f_text, multi); 850. #endif 851. res = (*(tlist->f_funct))(); 852. if(!res) { 853. flags.move = 0; 854. multi = 0; 855. } 856. return; 857. } 858. tlist++; 859. } 860. { char expcmd[10]; 861. register char *cp = expcmd; 862. while(*cmd && cp-expcmd < sizeof(expcmd)-2) { 863. if(*cmd >= 040 && *cmd < 0177) 864. *cp++ = *cmd++; 865. else if (*cmd & 0200) { 866. *cp++ = 'M'; 867. *cp++ = '-'; 868. *cp++ = *cmd++ &=~ 0200; 869. } 870. else { 871. *cp++ = '^'; 872. *cp++ = *cmd++ ^ 0100; 873. } 874. } 875. *cp = 0; 876. Norep("Unknown command '%s'.", expcmd); 877. } 878. multi = flags.move = 0; 879. return; 880. } 881. 882. int 883. xytod(x, y) /* convert an x,y pair into a direction code */ 884. schar x, y; 885. { 886. register int dd; 887. 888. for(dd = 0; dd < 8; dd++) 889. if(x == xdir[dd] && y == ydir[dd]) return dd; 890. 891. return -1; 892. } 893. 894. #ifdef WALKIES 895. void 896. dtoxy(cc,dd) /* convert a direction code into an x,y pair */ 897. coord *cc; 898. register int dd; 899. { 900. cc->x = xdir[dd]; 901. cc->y = ydir[dd]; 902. return; 903. } 904. #endif /* WALKIES */ 905. 906. int 907. movecmd(sym) /* also sets u.dz, but returns false for <> */ 908. char sym; 909. { 910. register const char *dp; 911. register const char *sdp = flags.num_pad ? ndir : sdir; 912. 913. u.dz = 0; 914. if(!(dp = index(sdp, sym))) return 0; 915. u.dx = xdir[dp-sdp]; 916. u.dy = ydir[dp-sdp]; 917. u.dz = zdir[dp-sdp]; 918. #ifdef POLYSELF 919. if (u.dx && u.dy && u.umonnum == PM_GRID_BUG) { 920. u.dx = u.dy = 0; 921. return 0; 922. } 923. #endif 924. return !u.dz; 925. } 926. 927. int 928. getdir(s) 929. const char *s; 930. { 931. char dirsym; 932. 933. #ifdef REDO 934. if(in_doagain) 935. dirsym = readchar(); 936. else 937. #endif 938. dirsym = yn_function (s ? s : "In what direction?", NULL, '\0'); 939. #ifdef REDO 940. savech(dirsym); 941. #endif 942. if(dirsym == '.' || dirsym == 's') 943. u.dx = u.dy = u.dz = 0; 944. else if(!movecmd(dirsym) && !u.dz) { 945. if(!index(quitchars, dirsym)) 946. pline("What a strange direction!"); 947. return 0; 948. } 949. if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir(); 950. return 1; 951. } 952. 953. #endif /* OVL1 */ 954. #ifdef OVLB 955. 956. void 957. confdir() 958. { 959. register int x = 960. #ifdef POLYSELF 961. (u.umonnum == PM_GRID_BUG) ? 2*rn2(4) : 962. #endif 963. rn2(8); 964. u.dx = xdir[x]; 965. u.dy = ydir[x]; 966. return; 967. } 968. 969. #endif /* OVLB */ 970. #ifdef OVL0 971. 972. int 973. isok(x,y) 974. register int x, y; 975. { 976. /* x corresponds to curx, so x==1 is the first column. Ach. %% */ 977. return x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1; 978. } 979. 980. static int NEARDATA last_multi; 981. 982. /* 983. * convert a MAP window position into a movecmd 984. */ 985. static int 986. click_to_cmd(x, y, mod) 987. int x, y, mod; 988. { 989. x -= u.ux; 990. y -= u.uy; 991. /* convert without using floating point, allowing sloppy clicking */ 992. if(x > 2*abs(y)) 993. x = 1, y = 0; 994. else if(y > 2*abs(x)) 995. x = 0, y = 1; 996. else if(x < -2*abs(y)) 997. x = -1, y = 0; 998. else if(y < -2*abs(x)) 999. x = 0, y = -1; 1000. else 1001. x = sgn(x), y = sgn(y); 1002. 1003. if(x == 0 && y == 0) /* map click on player to "rest" command */ 1004. return '.'; 1005. 1006. x = xytod(x, y); 1007. if(mod == CLICK_1) { 1008. return (flags.num_pad ? ndir[x] : sdir[x]); 1009. } else { 1010. return (sdir[x] - 'a' + 'A'); /* run command */ 1011. } 1012. } 1013. 1014. STATIC_OVL char * 1015. parse() 1016. { 1017. #ifdef LINT /* static char in_line[COLNO]; */ 1018. char in_line[COLNO]; 1019. #else 1020. static char in_line[COLNO]; 1021. #endif 1022. register int foo; 1023. boolean prezero = FALSE; 1024. 1025. multi = 0; 1026. flags.move = 1; 1027. flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */ 1028. 1029. if (!flags.num_pad || (foo = readchar()) == 'n') 1030. for (;;) { 1031. foo = readchar(); 1032. if (foo >= '0' && foo <= '9') { 1033. multi = 10 * multi + foo - '0'; 1034. if (multi < 0 || multi > LARGEST_INT) multi = LARGEST_INT; 1035. if (multi > 9) { 1036. clear_nhwindow(WIN_MESSAGE); 1037. Sprintf(in_line, "Count: %d", multi); 1038. pline(in_line); 1039. mark_synch(); 1040. } 1041. last_multi = multi; 1042. if (!multi && foo == '0') prezero = TRUE; 1043. } else break; /* not a digit */ 1044. } 1045. 1046. if (foo == '\033') { /* esc cancels count (TH) */ 1047. clear_nhwindow(WIN_MESSAGE); 1048. multi = last_multi = 0; 1049. # ifdef REDO 1050. } else if (foo == DOAGAIN || in_doagain) { 1051. multi = last_multi; 1052. } else { 1053. last_multi = multi; 1054. savech(0); /* reset input queue */ 1055. savech((char)foo); 1056. # endif 1057. } 1058. 1059. if (multi) { 1060. multi--; 1061. save_cm = in_line; 1062. } else { 1063. save_cm = NULL; 1064. } 1065. in_line[0] = foo; 1066. in_line[1] = '\0'; 1067. if (foo == 'g' || foo == 'G' || (flags.num_pad && foo == '5') || 1068. foo == 'm' || foo == 'M') { 1069. foo = readchar(); 1070. #ifdef REDO 1071. savech((char)foo); 1072. #endif 1073. in_line[1] = foo; 1074. in_line[2] = 0; 1075. } 1076. clear_nhwindow(WIN_MESSAGE); 1077. if (prezero) in_line[0] = '\033'; 1078. return(in_line); 1079. } 1080. 1081. #endif /* OVL0 */ 1082. #ifdef OVLB 1083. 1084. #ifdef UNIX 1085. static 1086. void 1087. end_of_input() 1088. { 1089. exit_nhwindows("End of input?"); 1090. #ifndef NOSAVEONHANGUP 1091. if(!hu) { 1092. hu = TRUE; 1093. (void) dosave0(); 1094. } 1095. #endif 1096. clearlocks(); 1097. terminate(0); 1098. } 1099. #endif 1100. 1101. #endif /* OVLB */ 1102. #ifdef OVL0 1103. 1104. char 1105. readchar() 1106. { 1107. register int sym; 1108. int x, y, mod; 1109. 1110. #ifdef REDO 1111. sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod); 1112. #else 1113. sym = Getchar(); 1114. #endif 1115. 1116. #ifdef UNIX 1117. # ifdef NR_OF_EOFS 1118. if (sym == EOF) { 1119. register int cnt = NR_OF_EOFS; 1120. /* 1121. * Some SYSV systems seem to return EOFs for various reasons 1122. * (?like when one hits break or for interrupted systemcalls?), 1123. * and we must see several before we quit. 1124. */ 1125. do { 1126. clearerr(stdin); /* omit if clearerr is undefined */ 1127. sym = Getchar(); 1128. } while (--cnt && sym == EOF); 1129. } 1130. # endif /* NR_OF_EOFS */ 1131. if (sym == EOF) 1132. end_of_input(); 1133. #endif /* UNIX */ 1134. 1135. if(sym == 0) /* click event */ 1136. sym = click_to_cmd(x, y, mod); 1137. return((char) sym); 1138. } 1139. #endif /* OVL0 */ 1140. 1141. /*cmd.c*/