Source:NetHack 3.2.0/cmd.c
(Redirected from NetHack 3.2.0/cmd.c)
Jump to navigation
Jump to search
Below is the full text to cmd.c from the source code of NetHack 3.2.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.2 95/08/12 */ 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. /* #define DEBUG /* uncomment for debugging */ 8. 9. /* 10. * Some systems may have getchar() return EOF for various reasons, and 11. * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs. 12. */ 13. #if defined(SYSV) || defined(DGUX) || defined(HPUX) 14. #define NR_OF_EOFS 20 15. #endif 16. 17. #ifdef DEBUG 18. /* 19. * only one "wiz_debug_cmd" routine should be available (in whatever 20. * module you are trying to debug) or things are going to get rather 21. * hard to link :-) 22. */ 23. extern void NDECL(wiz_debug_cmd); 24. #endif 25. 26. #ifdef DUMB /* stuff commented out in extern.h, but needed here */ 27. extern int NDECL(doapply); /**/ 28. extern int NDECL(dorub); /**/ 29. extern int NDECL(dojump); /**/ 30. extern int NDECL(doextlist); /**/ 31. extern int NDECL(dodrop); /**/ 32. extern int NDECL(doddrop); /**/ 33. extern int NDECL(dodown); /**/ 34. extern int NDECL(doup); /**/ 35. extern int NDECL(donull); /**/ 36. extern int NDECL(dowipe); /**/ 37. extern int NDECL(do_mname); /**/ 38. extern int NDECL(ddocall); /**/ 39. extern int NDECL(dotakeoff); /**/ 40. extern int NDECL(doremring); /**/ 41. extern int NDECL(dowear); /**/ 42. extern int NDECL(doputon); /**/ 43. extern int NDECL(doddoremarm); /**/ 44. extern int NDECL(dokick); /**/ 45. extern int NDECL(dothrow); /**/ 46. extern int NDECL(doeat); /**/ 47. extern int NDECL(done2); /**/ 48. extern int NDECL(doengrave); /**/ 49. extern int NDECL(dopickup); /**/ 50. extern int NDECL(ddoinv); /**/ 51. extern int NDECL(dotypeinv); /**/ 52. extern int NDECL(dolook); /**/ 53. extern int NDECL(doprgold); /**/ 54. extern int NDECL(doprwep); /**/ 55. extern int NDECL(doprarm); /**/ 56. extern int NDECL(doprring); /**/ 57. extern int NDECL(dopramulet); /**/ 58. extern int NDECL(doprtool); /**/ 59. extern int NDECL(dosuspend); /**/ 60. extern int NDECL(doforce); /**/ 61. extern int NDECL(doopen); /**/ 62. extern int NDECL(doclose); /**/ 63. extern int NDECL(dosh); /**/ 64. extern int NDECL(dodiscovered); /**/ 65. extern int NDECL(doset); /**/ 66. extern int NDECL(dotogglepickup); /**/ 67. extern int NDECL(dowhatis); /**/ 68. extern int NDECL(doquickwhatis); /**/ 69. extern int NDECL(dowhatdoes); /**/ 70. extern int NDECL(dohelp); /**/ 71. extern int NDECL(dohistory); /**/ 72. extern int NDECL(doloot); /**/ 73. extern int NDECL(dodrink); /**/ 74. extern int NDECL(dodip); /**/ 75. extern int NDECL(dosacrifice); /**/ 76. extern int NDECL(dopray); /**/ 77. extern int NDECL(doturn); /**/ 78. extern int NDECL(doredraw); /**/ 79. extern int NDECL(doread); /**/ 80. extern int NDECL(dosave); /**/ 81. extern int NDECL(dosearch); /**/ 82. extern int NDECL(doidtrap); /**/ 83. extern int NDECL(dopay); /**/ 84. extern int NDECL(dosit); /**/ 85. extern int NDECL(dotalk); /**/ 86. extern int NDECL(docast); /**/ 87. extern int NDECL(dovspell); /**/ 88. extern int NDECL(dotele); /**/ 89. extern int NDECL(dountrap); /**/ 90. extern int NDECL(doversion); /**/ 91. extern int NDECL(doextversion); /**/ 92. extern int NDECL(dowield); /**/ 93. extern int NDECL(dozap); /**/ 94. extern int NDECL(doorganize); /**/ 95. #endif /* DUMB */ 96. 97. #ifdef OVL1 98. static int NDECL((*timed_occ_fn)); 99. #endif /* OVL1 */ 100. 101. STATIC_PTR int NDECL(doprev_message); 102. STATIC_PTR int NDECL(timed_occupation); 103. STATIC_PTR int NDECL(doextcmd); 104. STATIC_PTR int NDECL(domonability); 105. # ifdef WIZARD 106. STATIC_PTR int NDECL(wiz_wish); 107. STATIC_PTR int NDECL(wiz_identify); 108. STATIC_PTR int NDECL(wiz_map); 109. STATIC_PTR int NDECL(wiz_genesis); 110. STATIC_PTR int NDECL(wiz_where); 111. STATIC_PTR int NDECL(wiz_detect); 112. STATIC_PTR int NDECL(wiz_level_tele); 113. STATIC_PTR int NDECL(wiz_show_seenv); 114. STATIC_PTR int NDECL(wiz_show_vision); 115. STATIC_PTR int NDECL(wiz_show_wmodes); 116. #ifdef __BORLANDC__ 117. extern void FDECL(show_borlandc_stats, (winid)); 118. #endif 119. static void FDECL(count_obj, (struct obj *, long *, long *, BOOLEAN_P, BOOLEAN_P)); 120. static void FDECL(obj_chain, (winid, const char *, struct obj *, long *, long *)); 121. static void FDECL(mon_invent_chain, (winid, const char *, struct monst *, long *, long *)); 122. static void FDECL(mon_chain, (winid, const char *, struct monst *, long *, long *)); 123. static void FDECL(contained, (winid, const char *, long *, long *)); 124. STATIC_PTR int NDECL(wiz_show_stats); 125. # endif 126. STATIC_PTR int NDECL(enter_explore_mode); 127. STATIC_PTR int NDECL(wiz_attributes); 128. 129. #ifdef OVLB 130. static void FDECL(enlght_line, (const char *,const char *,const char *)); 131. #ifdef UNIX 132. static void NDECL(end_of_input); 133. #endif 134. #endif /* OVLB */ 135. 136. STATIC_DCL char *NDECL(parse); 137. 138. #ifdef OVL1 139. 140. STATIC_PTR int 141. doprev_message() 142. { 143. return nh_doprev_message(); 144. } 145. 146. /* Count down by decrementing multi */ 147. STATIC_PTR int 148. timed_occupation() { 149. (*timed_occ_fn)(); 150. if (multi > 0) 151. multi--; 152. return multi > 0; 153. } 154. 155. /* If you have moved since initially setting some occupations, they 156. * now shouldn't be able to restart. 157. * 158. * The basic rule is that if you are carrying it, you can continue 159. * since it is with you. If you are acting on something at a distance, 160. * your orientation to it must have changed when you moved. 161. * 162. * The exception to this is taking off items, since they can be taken 163. * off in a number of ways in the intervening time, screwing up ordering. 164. * 165. * Currently: Take off all armor. 166. * Picking Locks / Forcing Chests. 167. */ 168. void 169. reset_occupations() { 170. 171. reset_remarm(); 172. reset_pick(); 173. } 174. 175. /* If a time is given, use it to timeout this function, otherwise the 176. * function times out by its own means. 177. */ 178. void 179. set_occupation(fn, txt, xtime) 180. int NDECL((*fn)); 181. const char *txt; 182. int xtime; 183. { 184. if (xtime) { 185. occupation = timed_occupation; 186. timed_occ_fn = fn; 187. } else 188. occupation = fn; 189. occtxt = txt; 190. occtime = 0; 191. return; 192. } 193. 194. #ifdef REDO 195. 196. static char NDECL(popch); 197. 198. /* Provide a means to redo the last command. The flag `in_doagain' is set 199. * to true while redoing the command. This flag is tested in commands that 200. * require additional input (like `throw' which requires a thing and a 201. * direction), and the input prompt is not shown. Also, while in_doagain is 202. * TRUE, no keystrokes can be saved into the saveq. 203. */ 204. #define BSIZE 20 205. static char pushq[BSIZE], saveq[BSIZE]; 206. static NEARDATA int phead, ptail, shead, stail; 207. 208. static char 209. popch() { 210. /* If occupied, return '\0', letting tgetch know a character should 211. * be read from the keyboard. If the character read is not the 212. * ABORT character (as checked in pcmain.c), that character will be 213. * pushed back on the pushq. 214. */ 215. if (occupation) return '\0'; 216. if (in_doagain) return(char)((shead != stail) ? saveq[stail++] : '\0'); 217. else return(char)((phead != ptail) ? pushq[ptail++] : '\0'); 218. } 219. 220. char 221. pgetchar() { /* curtesy of aeb@cwi.nl */ 222. register int ch; 223. 224. if(!(ch = popch())) 225. ch = nhgetch(); 226. return((char)ch); 227. } 228. 229. /* A ch == 0 resets the pushq */ 230. void 231. pushch(ch) 232. char ch; 233. { 234. if (!ch) 235. phead = ptail = 0; 236. if (phead < BSIZE) 237. pushq[phead++] = ch; 238. return; 239. } 240. 241. /* A ch == 0 resets the saveq. Only save keystrokes when not 242. * replaying a previous command. 243. */ 244. void 245. savech(ch) 246. char ch; 247. { 248. if (!in_doagain) { 249. if (!ch) 250. phead = ptail = shead = stail = 0; 251. else if (shead < BSIZE) 252. saveq[shead++] = ch; 253. } 254. return; 255. } 256. #endif /* REDO */ 257. 258. #endif /* OVL1 */ 259. #ifdef OVLB 260. 261. STATIC_PTR int 262. doextcmd() /* here after # - now read a full-word command */ 263. { 264. int idx, retval; 265. 266. /* keep repeating until we don't run help or quit */ 267. do { 268. idx = get_ext_cmd(); 269. if (idx < 0) return 0; /* quit */ 270. 271. retval = (*extcmdlist[idx].ef_funct)(); 272. } while (extcmdlist[idx].ef_funct == doextlist); 273. 274. return retval; 275. } 276. 277. int 278. doextlist() /* here after #? - now list all full-word commands */ 279. { 280. register const struct ext_func_tab *efp; 281. char buf[BUFSZ]; 282. winid datawin; 283. 284. datawin = create_nhwindow(NHW_TEXT); 285. putstr(datawin, 0, ""); 286. putstr(datawin, 0, " Extended Commands List"); 287. putstr(datawin, 0, ""); 288. putstr(datawin, 0, " Press '#', then type:"); 289. putstr(datawin, 0, ""); 290. 291. for(efp = extcmdlist; efp->ef_txt; efp++) { 292. Sprintf(buf, " %-14s - %s.", efp->ef_txt, efp->ef_desc); 293. putstr(datawin, 0, buf); 294. } 295. display_nhwindow(datawin, FALSE); 296. destroy_nhwindow(datawin); 297. return 0; 298. } 299. 300. STATIC_PTR int 301. domonability() 302. { 303. if (can_breathe(uasmon)) return dobreathe(); 304. else if (attacktype(uasmon, AT_SPIT)) return dospit(); 305. else if (u.usym == S_NYMPH) return doremove(); 306. else if (u.usym == S_UMBER) return doconfuse(); 307. else if (is_were(uasmon)) return dosummon(); 308. else if (webmaker(uasmon)) return dospinweb(); 309. else if (is_hider(uasmon)) return dohide(); 310. else if(u.umonnum == PM_GREMLIN) { 311. if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 312. struct monst *mtmp; 313. if ((mtmp = cloneu()) != 0) { 314. mtmp->mhpmax = (u.mhmax /= 2); 315. You("multiply."); 316. dryup(u.ux,u.uy); 317. } 318. } else pline("There is no fountain here."); 319. } 320. else if (u.usym == S_UNICORN) { 321. use_unicorn_horn((struct obj *)0); 322. return 1; 323. } else if (u.umonnum == PM_MIND_FLAYER) return domindblast(); 324. else if (uasmon->msound == MS_SHRIEK) { 325. You("shriek."); 326. if(u.uburied) 327. pline("Unfortunately sound does not carry well through rock."); 328. else aggravate(); 329. } else if (Upolyd) 330. pline("Any special ability you may have is purely reflexive."); 331. else You("don't have a special ability!"); 332. return 0; 333. } 334. 335. STATIC_PTR int 336. enter_explore_mode() 337. { 338. if(!discover && !wizard) { 339. pline("Beware! From explore mode there will be no return to normal game."); 340. if (yn("Do you want to enter explore mode?") == 'y') { 341. clear_nhwindow(WIN_MESSAGE); 342. You("are now in non-scoring explore mode."); 343. discover = TRUE; 344. } 345. else { 346. clear_nhwindow(WIN_MESSAGE); 347. pline("Resuming normal game."); 348. } 349. } 350. return 0; 351. } 352. 353. #ifdef WIZARD 354. STATIC_PTR int 355. wiz_wish() /* Unlimited wishes for debug mode by Paul Polderman */ 356. { 357. if (wizard) { 358. boolean save_verbose = flags.verbose; 359. 360. flags.verbose = FALSE; 361. makewish(); 362. flags.verbose = save_verbose; 363. (void) encumber_msg(); 364. } else 365. pline("Unavailable command '^W'."); 366. return 0; 367. } 368. 369. STATIC_PTR int 370. wiz_identify() 371. { 372. if (wizard) identify_pack(0); 373. else pline("Unavailable command '^I'."); 374. return 0; 375. } 376. 377. STATIC_PTR int 378. wiz_map() 379. { 380. if (wizard) do_mapping(); 381. else pline("Unavailable command '^F'."); 382. return 0; 383. } 384. 385. STATIC_PTR int 386. wiz_genesis() 387. { 388. if (wizard) (void) create_particular(); 389. else pline("Unavailable command '^G'."); 390. return 0; 391. } 392. 393. STATIC_PTR int 394. wiz_where() 395. { 396. if (wizard) print_dungeon(); 397. else pline("Unavailable command '^O'."); 398. return 0; 399. } 400. 401. STATIC_PTR int 402. wiz_detect() 403. { 404. if(wizard) (void) findit(); 405. else pline("Unavailable command '^E'."); 406. return 0; 407. } 408. 409. STATIC_PTR int 410. wiz_level_tele() 411. { 412. if (wizard) level_tele(); 413. else pline("Unavailable command '^V'."); 414. return 0; 415. } 416. 417. STATIC_PTR int 418. wiz_show_seenv() 419. { 420. winid win; 421. int x, y, v, startx, stopx, curx; 422. char row[COLNO+1]; 423. 424. win = create_nhwindow(NHW_TEXT); 425. /* 426. * Each seenv description takes up 2 characters, so center 427. * the seenv display around the hero. 428. */ 429. startx = max(1, u.ux-(COLNO/4)); 430. stopx = min(startx+(COLNO/2), COLNO); 431. /* can't have a line exactly 80 chars long */ 432. if (stopx - startx == COLNO/2) startx++; 433. 434. for (y = 0; y < ROWNO; y++) { 435. for (x = startx, curx = 0; x < stopx; x++, curx += 2) { 436. if (x == u.ux && y == u.uy) { 437. row[curx] = row[curx+1] = '@'; 438. } else { 439. v = levl[x][y].seenv & 0xff; 440. if (v == 0) 441. row[curx] = row[curx+1] = ' '; 442. else 443. Sprintf(&row[curx], "%02x", v); 444. } 445. } 446. /* remove trailing spaces */ 447. for (x = curx-1; x >= 0; x--) 448. if (row[x] != ' ') break; 449. row[x+1] = '\0'; 450. 451. putstr(win, 0, row); 452. } 453. display_nhwindow(win, TRUE); 454. destroy_nhwindow(win); 455. return 0; 456. } 457. 458. STATIC_PTR int 459. wiz_show_vision() 460. { 461. winid win; 462. int x, y, v; 463. char row[COLNO+1]; 464. 465. win = create_nhwindow(NHW_TEXT); 466. Sprintf(row, "Flags: 0x%x could see, 0x%x in sight, 0x%x temp lit", 467. COULD_SEE, IN_SIGHT, TEMP_LIT); 468. putstr(win, 0, row); 469. putstr(win, 0, ""); 470. for (y = 0; y < ROWNO; y++) { 471. for (x = 1; x < COLNO; x++) { 472. if (x == u.ux && y == u.uy) 473. row[x] = '@'; 474. else { 475. v = viz_array[y][x]; /* data access should be hidden */ 476. if (v == 0) 477. row[x] = ' '; 478. else 479. row[x] = '0' + viz_array[y][x]; 480. } 481. } 482. /* remove trailing spaces */ 483. for (x = COLNO-1; x >= 1; x--) 484. if (row[x] != ' ') break; 485. row[x+1] = '\0'; 486. 487. putstr(win, 0, &row[1]); 488. } 489. display_nhwindow(win, TRUE); 490. destroy_nhwindow(win); 491. return 0; 492. } 493. 494. STATIC_PTR int 495. wiz_show_wmodes() 496. { 497. winid win; 498. int x,y; 499. char row[COLNO+1]; 500. struct rm *lev; 501. 502. win = create_nhwindow(NHW_TEXT); 503. for (y = 0; y < ROWNO; y++) { 504. for (x = 0; x < COLNO; x++) { 505. lev = &levl[x][y]; 506. if (x == u.ux && y == u.uy) 507. row[x] = '@'; 508. if (IS_WALL(lev->typ) || lev->typ == SDOOR) 509. row[x] = '0' + (lev->wall_info & WM_MASK); 510. else if (lev->typ == CORR) 511. row[x] = '#'; 512. else if (IS_ROOM(lev->typ) || IS_DOOR(lev->typ)) 513. row[x] = '.'; 514. else 515. row[x] = 'x'; 516. } 517. row[COLNO] = '\0'; 518. putstr(win, 0, row); 519. } 520. display_nhwindow(win, TRUE); 521. destroy_nhwindow(win); 522. return 0; 523. } 524. 525. #endif /* WIZARD */ 526. 527. /* -enlightenment- */ 528. static winid en_win; 529. static const char 530. *You_ = "You ", 531. *are = "are ", *were = "were ", 532. *have = "have ", *had = "had ", 533. *can = "can ", *could = "could "; 534. 535. #define enl_msg(prefix,present,past,suffix) \ 536. enlght_line(prefix, final ? past : present, suffix) 537. #define you_are(attr) enl_msg(You_,are,were,attr) 538. #define you_have(attr) enl_msg(You_,have,had,attr) 539. #define you_can(attr) enl_msg(You_,can,could,attr) 540. 541. static void 542. enlght_line(start, middle, end) 543. const char *start, *middle, *end; 544. { 545. char buf[BUFSZ]; 546. 547. Sprintf(buf, "%s%s%s.", start, middle, end); 548. putstr(en_win, 0, buf); 549. } 550. 551. void 552. enlightenment(final) 553. int final; /* 0 => still in progress; 1 => over, survived; 2 => dead */ 554. { 555. int ltmp; 556. char buf[BUFSZ]; 557. 558. en_win = create_nhwindow(NHW_MENU); 559. putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:"); 560. putstr(en_win, 0, ""); 561. 562. #ifdef ELBERETH 563. if (u.uevent.uhand_of_elbereth) { 564. static const char *hofe_titles[3] = { 565. "the Hand of Elbereth", 566. "the Envoy of Balance", 567. "the Glory of Arioch" 568. }; 569. you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1]); 570. } 571. #endif 572. 573. /* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */ 574. if (u.ualign.record >= 20) you_are("piously aligned"); 575. else if (u.ualign.record > 13) you_are("devoutly aligned"); 576. else if (u.ualign.record > 8) you_are("fervently aligned"); 577. else if (u.ualign.record > 3) you_are("stridently aligned"); 578. else if (u.ualign.record == 3) you_are("aligned"); 579. else if (u.ualign.record > 0) you_are("haltingly aligned"); 580. else if (u.ualign.record == 0) you_are("nominally aligned"); 581. else if (u.ualign.record >= -3) you_have("strayed"); 582. else if (u.ualign.record >= -8) you_have("sinned"); 583. else you_have("transgressed"); 584. #ifdef WIZARD 585. if (wizard) { 586. Sprintf(buf, " %d", u.ualign.record); 587. enl_msg("Your alignment ", "is", "was", buf); 588. } 589. #endif 590. 591. if (Telepat) you_are("telepathic"); 592. if (Searching) you_have("automatic searching"); 593. if (Teleportation) you_can("teleport"); 594. if (Teleport_control) you_have("teleport control"); 595. if (See_invisible) enl_msg(You_, "see", "saw", " invisible"); 596. if (Invisible) you_are("invisible"); 597. else if (Invis) you_are("invisible to others"); 598. /* ordinarily "visible" is redundant; this is a special case for 599. the situation when invisibility would be an expected attribute */ 600. else if ((HInvis & I_BLOCKED) != 0L && 601. ((HInvis & ~I_BLOCKED) != 0L || pm_invisible(uasmon))) 602. you_are("visible"); 603. if (Fast) you_are((Fast & ~INTRINSIC) ? "very fast" : "fast"); 604. if (Stealth) you_are("stealthy"); 605. if (Regeneration) enl_msg("You regenerate", "", "d", ""); 606. if (Hunger) enl_msg("You hunger", "", "ed", " rapidly"); 607. if (Conflict) enl_msg("You cause", "", "d", " conflict"); 608. if (Aggravate_monster) enl_msg("You aggravate", "", "d", " monsters"); 609. if (Poison_resistance) you_are("poison resistant"); 610. if (Fire_resistance) you_are("fire resistant"); 611. if (Cold_resistance) you_are("cold resistant"); 612. if (Shock_resistance) you_are("shock resistant"); 613. if (Sleep_resistance) you_are("sleep resistant"); 614. if (Disint_resistance) you_are("disintegration-resistant"); 615. if (Protection_from_shape_changers) 616. you_are("protected from shape changers"); 617. if (Polymorph) you_are("polymorphing"); 618. if (Polymorph_control) you_have("polymorph control"); 619. if (HHalluc_resistance) 620. enl_msg("You resist", "", "ed", " hallucinations"); 621. if (final) { 622. if (Hallucination) you_are("hallucinating"); 623. if (Stunned) you_are("stunned"); 624. if (Confusion) you_are("confused"); 625. if (Sick) { 626. if (u.usick_type & SICK_VOMITABLE) 627. you_are("sick from food poisoning"); 628. if (u.usick_type & SICK_NONVOMITABLE) 629. you_are("sick from illness"); 630. } 631. if (Blinded) you_are("blinded"); 632. } 633. if (Wounded_legs) { 634. Sprintf(buf, "wounded %s", makeplural(body_part(LEG))); 635. you_have(buf); 636. } 637. if (Glib) { 638. Sprintf(buf, "slippery %s", makeplural(body_part(FINGER))); 639. you_have(buf); 640. } 641. if (Strangled) you_are((u.uburied) ? "buried" : "being strangled"); 642. if (Stoned) you_are("turning to stone"); 643. if (Lifesaved) 644. enl_msg("Your life ", "will be", "would have been", " saved"); 645. if (Adornment) you_are("adorned"); 646. if (Warning) you_are("warned"); 647. if (Protection) you_are("protected"); 648. if (Reflecting) you_have("reflection"); 649. if ((HLevitation & (I_SPECIAL|W_ARTI)) != 0L && 650. (HLevitation & ~(I_SPECIAL|W_ARTI|TIMEOUT)) == 0L && 651. !is_floater(uasmon)) you_are("levitating, at will"); 652. else if (Levitation) you_are("levitating"); /* without control */ 653. else if (is_flyer(uasmon)) you_can("fly"); 654. if (Fumbling) enl_msg("You fumble", "", "d", ""); 655. if (Jumping) you_can("jump"); 656. if (Wwalking) you_can("walk on water"); 657. if (passes_walls(uasmon)) you_can("walk through walls"); 658. if (Breathless) you_can("survive without air"); 659. else if (Amphibious) you_can("breathe water"); 660. if (Antimagic) you_are("magic-protected"); 661. if (Displaced) you_are("displaced"); 662. if (Clairvoyant) you_are("clairvoyant"); 663. if (u.ulycn >= LOW_PM) { 664. Strcpy(buf, an(mons[u.ulycn].mname)); 665. you_are(buf); 666. } 667. if (Luck) { 668. ltmp = abs((int)Luck); 669. Sprintf(buf, "%s%slucky", 670. ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "", 671. Luck < 0 ? "un" : ""); 672. #ifdef WIZARD 673. if (wizard) Sprintf(eos(buf), " (%d)", Luck); 674. #endif 675. you_are(buf); 676. } 677. #ifdef WIZARD 678. else if (wizard) enl_msg("Your luck ", "is", "was", " zero"); 679. #endif 680. if (u.moreluck > 0) you_have("extra luck"); 681. else if (u.moreluck < 0) you_have("reduced luck"); 682. if (carrying(LUCKSTONE)) { 683. ltmp = stone_luck(FALSE); 684. if (ltmp <= 0) 685. enl_msg("Bad luck ", "does", "did", " not time out for you"); 686. if (ltmp >= 0) 687. enl_msg("Good luck ", "does", "did", " not time out for you"); 688. } 689. 690. if (u.ugangr) { 691. Sprintf(buf, " %sangry with you", 692. u.ugangr > 6 ? "extremely " : u.ugangr > 3 ? "very " : ""); 693. #ifdef WIZARD 694. if (wizard) Sprintf(eos(buf), " (%d)", u.ugangr); 695. #endif 696. enl_msg(u_gname(), " is", " was", buf); 697. } else 698. /* 699. * We need to suppress this when the game is over, because death 700. * can change the value calculated by can_pray(), potentially 701. * resulting in a false claim that you could have prayed safely. 702. */ 703. if (!final) { 704. #if 0 705. /* "can [not] safely pray" vs "could [not] have safely prayed" */ 706. Sprintf(buf, "%s%ssafely pray%s", can_pray(FALSE) ? "" : "not ", 707. final ? "have " : "", final ? "ed" : ""); 708. #else 709. Sprintf(buf, "%ssafely pray", can_pray(FALSE) ? "" : "not "); 710. #endif 711. #ifdef WIZARD 712. if (wizard) Sprintf(eos(buf), " (%d)", u.ublesscnt); 713. #endif 714. you_can(buf); 715. } 716. 717. { 718. const char *p; 719. 720. buf[0] = '\0'; 721. if (final < 2) { /* still in progress, or quit/escaped/ascended */ 722. p = "survived after being killed "; 723. switch (u.umortality) { 724. case 0: p = !final ? (char *)0 : "survived"; break; 725. case 1: Strcpy(buf, "once"); break; 726. case 2: Strcpy(buf, "twice"); break; 727. case 3: Strcpy(buf, "thrice"); break; 728. default: Sprintf(buf, "%d times", u.umortality); 729. break; 730. } 731. } else { /* game ended in character's death */ 732. p = "are dead"; 733. switch (u.umortality) { 734. case 0: impossible("dead without dying?"); 735. case 1: break; /* just "are dead" */ 736. default: Sprintf(buf, " (%d%s time!)", u.umortality, 737. ordin(u.umortality)); 738. break; 739. } 740. } 741. if (p) enl_msg(You_, "have been killed ", p, buf); 742. } 743. 744. display_nhwindow(en_win, TRUE); 745. destroy_nhwindow(en_win); 746. return; 747. } 748. 749. STATIC_PTR int 750. wiz_attributes() 751. { 752. if (wizard || discover) 753. enlightenment(0); 754. else 755. pline("Unavailable command '^X'."); 756. return 0; 757. } 758. 759. #endif /* OVLB */ 760. #ifdef OVL1 761. 762. #ifndef M 763. # ifndef NHSTDC 764. # define M(c) (0x80 | (c)) 765. # else 766. # define M(c) ((c) - 128) 767. # endif /* NHSTDC */ 768. #endif 769. #ifndef C 770. #define C(c) (0x1f & (c)) 771. #endif 772. 773. static const struct func_tab cmdlist[] = { 774. {C('d'), FALSE, dokick}, /* "D" is for door!...? Msg is in dokick.c */ 775. #ifdef WIZARD 776. {C('e'), TRUE, wiz_detect}, 777. {C('f'), TRUE, wiz_map}, 778. {C('g'), TRUE, wiz_genesis}, 779. {C('i'), TRUE, wiz_identify}, 780. #endif 781. {C('l'), TRUE, doredraw}, /* if number_pad is set */ 782. #ifdef WIZARD 783. {C('o'), TRUE, wiz_where}, 784. #endif 785. {C('p'), TRUE, doprev_message}, 786. {C('r'), TRUE, doredraw}, 787. {C('t'), TRUE, dotele}, 788. #ifdef WIZARD 789. {C('v'), TRUE, wiz_level_tele}, 790. {C('w'), TRUE, wiz_wish}, 791. #endif 792. {C('x'), TRUE, wiz_attributes}, 793. #ifdef SUSPEND 794. {C('z'), TRUE, dosuspend}, 795. #endif 796. {'a', FALSE, doapply}, 797. {'A', FALSE, doddoremarm}, 798. {M('a'), TRUE, doorganize}, 799. /* 'b', 'B' : go sw */ 800. {'c', FALSE, doclose}, 801. {'C', TRUE, do_mname}, 802. {M('c'), TRUE, dotalk}, 803. {'d', FALSE, dodrop}, 804. {'D', FALSE, doddrop}, 805. {M('d'), FALSE, dodip}, 806. {'e', FALSE, doeat}, 807. {'E', FALSE, doengrave}, 808. #ifdef WEAPON_SKILLS 809. {M('e'), TRUE, select_weapon_skill}, 810. #endif /* WEAPON_SKILLS */ 811. /* Soon to be 812. {'f', FALSE, dofight, "fighting"}, 813. {'F', FALSE, doFight, "fighting"}, 814. */ 815. {M('f'), FALSE, doforce}, 816. /* 'g', 'G' : multiple go */ 817. /* 'h', 'H' : go west */ 818. {'h', TRUE, dohelp}, /* if number_pad is set */ 819. {'i', TRUE, ddoinv}, 820. {'I', TRUE, dotypeinv}, /* Robert Viduya */ 821. {M('i'), TRUE, doinvoke}, 822. /* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */ 823. {'j', FALSE, dojump}, /* if number_pad is on */ 824. {M('j'), FALSE, dojump}, 825. {'k', FALSE, dokick}, /* if number_pad is on */ 826. {'l', FALSE, doloot}, /* if number_pad is on */ 827. {M('l'), FALSE, doloot}, 828. /* 'n' prefixes a count if number_pad is on */ 829. {M('m'), TRUE, domonability}, 830. {'N', TRUE, ddocall}, /* if number_pad is on */ 831. {M('n'), TRUE, ddocall}, 832. {M('N'), TRUE, ddocall}, 833. {'o', FALSE, doopen}, 834. {'O', TRUE, doset}, 835. {M('o'), FALSE, dosacrifice}, 836. {'p', FALSE, dopay}, 837. {'P', FALSE, doputon}, 838. {M('p'), TRUE, dopray}, 839. {'q', FALSE, dodrink}, 840. {'Q', TRUE, done2}, 841. #ifdef WEAPON_SKILLS 842. {M('q'), TRUE, check_weapon_skills}, 843. #endif /* WEAPON_SKILLS */ 844. {'r', FALSE, doread}, 845. {'R', FALSE, doremring}, 846. {M('r'), FALSE, dorub}, 847. {'s', TRUE, dosearch, "searching"}, 848. {'S', TRUE, dosave}, 849. {M('s'), FALSE, dosit}, 850. {'t', FALSE, dothrow}, 851. {'T', FALSE, dotakeoff}, 852. {M('t'), TRUE, doturn}, 853. /* 'u', 'U' : go ne */ 854. {'u', FALSE, dountrap}, /* if number_pad is on */ 855. {M('u'), FALSE, dountrap}, 856. {'v', TRUE, doversion}, 857. {'V', TRUE, dohistory}, 858. {M('v'), TRUE, doextversion}, 859. {'w', FALSE, dowield}, 860. {'W', FALSE, dowear}, 861. {M('w'), FALSE, dowipe}, 862. {'x', TRUE, dovspell}, /* Mike Stephenson */ 863. {'X', TRUE, enter_explore_mode}, 864. /* 'y', 'Y' : go nw */ 865. {'z', FALSE, dozap}, 866. {'Z', TRUE, docast}, 867. {'<', FALSE, doup}, 868. {'>', FALSE, dodown}, 869. {'/', TRUE, dowhatis}, 870. {'&', TRUE, dowhatdoes}, 871. {'?', TRUE, dohelp}, 872. {M('?'), TRUE, doextlist}, 873. #ifdef SHELL 874. {'!', TRUE, dosh}, 875. #endif 876. {'.', TRUE, donull, "waiting"}, 877. {' ', TRUE, donull, "waiting"}, 878. {',', FALSE, dopickup}, 879. {':', TRUE, dolook}, 880. {';', TRUE, doquickwhatis}, 881. {'^', TRUE, doidtrap}, 882. {'\\', TRUE, dodiscovered}, /* Robert Viduya */ 883. {'@', TRUE, dotogglepickup}, 884. {WEAPON_SYM, TRUE, doprwep}, 885. {ARMOR_SYM, TRUE, doprarm}, 886. {RING_SYM, TRUE, doprring}, 887. {AMULET_SYM, TRUE, dopramulet}, 888. {TOOL_SYM, TRUE, doprtool}, 889. {GOLD_SYM, TRUE, doprgold}, 890. {SPBOOK_SYM, TRUE, dovspell}, /* Mike Stephenson */ 891. {'#', TRUE, doextcmd}, 892. {0,0,0,0} 893. }; 894. 895. struct ext_func_tab extcmdlist[] = { 896. {"adjust", "adjust inventory letters", doorganize, TRUE}, 897. {"chat", "talk to someone", dotalk, TRUE}, /* converse? */ 898. {"dip", "dip an object into something", dodip, FALSE}, 899. #ifdef WEAPON_SKILLS 900. {"enhance", "advance a weapon skill", select_weapon_skill, TRUE}, 901. #endif /* WEAPON_SKILLS */ 902. {"force", "force a lock", doforce, FALSE}, 903. {"invoke", "invoke an object's powers", doinvoke, TRUE}, 904. {"jump", "jump to a location", dojump, FALSE}, 905. {"loot", "loot a box on the floor", doloot, FALSE}, 906. {"monster", "use a monster's special ability", domonability, TRUE}, 907. {"name", "name an item or type of object", ddocall, TRUE}, 908. {"offer", "offer a sacrifice to the gods", dosacrifice, FALSE}, 909. {"pray", "pray to the gods for help", dopray, TRUE}, 910. #ifdef WEAPON_SKILLS 911. {"qualifications", "check your weapon skills", check_weapon_skills, TRUE}, 912. #endif /* WEAPON_SKILLS */ 913. {"rub", "rub a lamp", dorub, FALSE}, 914. {"sit", "sit down", dosit, FALSE}, 915. {"turn", "turn undead", doturn, TRUE}, 916. {"untrap", "untrap something", dountrap, FALSE}, 917. {"version", "list compile time options for this version of NetHack", 918. doextversion, TRUE}, 919. {"wipe", "wipe off your face", dowipe, FALSE}, 920. {"?", "get this list of extended commands", doextlist, TRUE}, 921. #if defined(WIZARD) 922. /* 923. * There must be a blank entry here for every entry in the table 924. * below. 925. */ 926. {(char *)0, (char *)0, donull, TRUE}, 927. {(char *)0, (char *)0, donull, TRUE}, 928. {(char *)0, (char *)0, donull, TRUE}, 929. {(char *)0, (char *)0, donull, TRUE}, 930. {(char *)0, (char *)0, donull, TRUE}, 931. #ifdef DEBUG 932. {(char *)0, (char *)0, donull, TRUE}, 933. #endif 934. {(char *)0, (char *)0, donull, TRUE}, 935. #endif 936. {(char *)0, (char *)0, donull, TRUE} 937. }; 938. 939. #if defined(WIZARD) 940. static const struct ext_func_tab debug_extcmdlist[] = { 941. {"light sources", "show mobile light sources", wiz_light_sources, TRUE}, 942. {"seenv", "show seen vectors", wiz_show_seenv, TRUE}, 943. {"stats", "show memory statistics", wiz_show_stats, TRUE}, 944. {"timeout", "look at timeout queue", wiz_timeout_queue, TRUE}, 945. {"vision", "show vision array", wiz_show_vision, TRUE}, 946. #ifdef DEBUG 947. {"wizdebug", "wizard debug command", wiz_debug_cmd, TRUE}, 948. #endif 949. {"wmode", "show wall modes", wiz_show_wmodes, TRUE}, 950. {(char *)0, (char *)0, donull, TRUE} 951. }; 952. 953. /* 954. * Insert debug commands into the extended command list. This function 955. * assumes that the last entry will be the help entry. 956. * 957. * You must add entries in ext_func_tab every time you add one to the 958. * debug_extcmdlist(). 959. */ 960. void 961. add_debug_extended_commands() 962. { 963. int i, j, k, n; 964. 965. /* count the # of help entries */ 966. for (n = 0; extcmdlist[n].ef_txt[0] != '?'; n++) 967. ; 968. 969. for (i = 0; debug_extcmdlist[i].ef_txt; i++) { 970. for (j = 0; j < n; j++) 971. if (strcmp(debug_extcmdlist[i].ef_txt, extcmdlist[j].ef_txt) < 0) break; 972. 973. /* insert i'th debug entry into extcmdlist[j], pushing down */ 974. for (k = n; k >= j; --k) 975. extcmdlist[k+1] = extcmdlist[k]; 976. extcmdlist[j] = debug_extcmdlist[i]; 977. n++; /* now an extra entry */ 978. } 979. } 980. 981. 982. static const char *template = "%-18s %4ld %6ld"; 983. static const char *count_str = " count bytes"; 984. static const char *separator = "------------------ ----- ------"; 985. 986. static void 987. count_obj(chain, total_count, total_size, top, recurse) 988. struct obj *chain; 989. long *total_count; 990. long *total_size; 991. boolean top; 992. boolean recurse; 993. { 994. long count, size; 995. struct obj *obj; 996. 997. for (count = size = 0, obj = chain; obj; obj = obj->nobj) { 998. if (top) { 999. count++; 1000. size += sizeof(struct obj) + obj->onamelth; 1001. } 1002. if (recurse && obj->cobj) 1003. count_obj(obj->cobj, total_count, total_size, TRUE, TRUE); 1004. } 1005. *total_count += count; 1006. *total_size += size; 1007. } 1008. 1009. static void 1010. obj_chain(win, src, chain, total_count, total_size) 1011. winid win; 1012. const char *src; 1013. struct obj *chain; 1014. long *total_count; 1015. long *total_size; 1016. { 1017. char buf[BUFSZ]; 1018. long count = 0, size = 0; 1019. 1020. count_obj(chain, &count, &size, TRUE, FALSE); 1021. *total_count += count; 1022. *total_size += size; 1023. Sprintf(buf, template, src, count, size); 1024. putstr(win, 0, buf); 1025. } 1026. 1027. static void 1028. mon_invent_chain(win, src, chain, total_count, total_size) 1029. winid win; 1030. const char *src; 1031. struct monst *chain; 1032. long *total_count; 1033. long *total_size; 1034. { 1035. char buf[BUFSZ]; 1036. long count = 0, size = 0; 1037. struct monst *mon; 1038. 1039. for (mon = chain; mon; mon = mon->nmon) 1040. count_obj(mon->minvent, &count, &size, TRUE, FALSE); 1041. *total_count += count; 1042. *total_size += size; 1043. Sprintf(buf, template, src, count, size); 1044. putstr(win, 0, buf); 1045. } 1046. 1047. static void 1048. contained(win, src, total_count, total_size) 1049. winid win; 1050. const char *src; 1051. long *total_count; 1052. long *total_size; 1053. { 1054. char buf[BUFSZ]; 1055. long count = 0, size = 0; 1056. struct monst *mon; 1057. 1058. count_obj(invent, &count, &size, FALSE, TRUE); 1059. count_obj(fobj, &count, &size, FALSE, TRUE); 1060. count_obj(level.buriedobjlist, &count, &size, FALSE, TRUE); 1061. count_obj(migrating_objs, &count, &size, FALSE, TRUE); 1062. for (mon = fmon; mon; mon = mon->nmon) 1063. count_obj(mon->minvent, &count, &size, FALSE, TRUE); 1064. for (mon = migrating_mons; mon; mon = mon->nmon) 1065. count_obj(mon->minvent, &count, &size, FALSE, TRUE); 1066. 1067. *total_count += count; *total_size += size; 1068. 1069. Sprintf(buf, template, src, count, size); 1070. putstr(win, 0, buf); 1071. } 1072. 1073. static void 1074. mon_chain(win, src, chain, total_count, total_size) 1075. winid win; 1076. const char *src; 1077. struct monst *chain; 1078. long *total_count; 1079. long *total_size; 1080. { 1081. char buf[BUFSZ]; 1082. long count, size; 1083. struct monst *mon; 1084. 1085. for (count = size = 0, mon = chain; mon; mon = mon->nmon) { 1086. count++; 1087. size += sizeof(struct monst) + mon->mxlth + mon->mnamelth; 1088. } 1089. *total_count += count; 1090. *total_size += size; 1091. Sprintf(buf, template, src, count, size); 1092. putstr(win, 0, buf); 1093. } 1094. 1095. /* 1096. * Display memory usage of all monsters and objects on the level. 1097. */ 1098. static int 1099. wiz_show_stats() 1100. { 1101. char buf[BUFSZ]; 1102. winid win; 1103. long total_obj_size = 0, total_obj_count = 0; 1104. long total_mon_size = 0, total_mon_count = 0; 1105. 1106. win = create_nhwindow(NHW_TEXT); 1107. putstr(win, 0, "Current memory statistics:"); 1108. putstr(win, 0, ""); 1109. Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj)); 1110. putstr(win, 0, buf); 1111. putstr(win, 0, ""); 1112. putstr(win, 0, count_str); 1113. 1114. obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size); 1115. obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size); 1116. obj_chain(win, "buried", level.buriedobjlist, 1117. &total_obj_count, &total_obj_size); 1118. obj_chain(win, "migrating obj", migrating_objs, 1119. &total_obj_count, &total_obj_size); 1120. mon_invent_chain(win, "minvent", fmon, 1121. &total_obj_count,&total_obj_size); 1122. mon_invent_chain(win, "migrating minvent", migrating_mons, 1123. &total_obj_count, &total_obj_size); 1124. 1125. contained(win, "contained", 1126. &total_obj_count, &total_obj_size); 1127. 1128. putstr(win, 0, separator); 1129. Sprintf(buf, template, "Total", total_obj_count, total_obj_size); 1130. putstr(win, 0, buf); 1131. 1132. putstr(win, 0, ""); 1133. putstr(win, 0, ""); 1134. Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst)); 1135. putstr(win, 0, buf); 1136. putstr(win, 0, ""); 1137. 1138. mon_chain(win, "fmon", fmon, 1139. &total_mon_count, &total_mon_size); 1140. mon_chain(win, "migrating", migrating_mons, 1141. &total_mon_count, &total_mon_size); 1142. 1143. putstr(win, 0, separator); 1144. Sprintf(buf, template, "Total", total_mon_count, total_mon_size); 1145. putstr(win, 0, buf); 1146. 1147. #ifdef __BORLANDC__ 1148. show_borlandc_stats(win); 1149. #endif 1150. 1151. display_nhwindow(win, FALSE); 1152. destroy_nhwindow(win); 1153. return 0; 1154. } 1155. 1156. void 1157. sanity_check() 1158. { 1159. obj_sanity_check(); 1160. timer_sanity_check(); 1161. } 1162. 1163. #endif /* WIZARD */ 1164. 1165. #define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c)) 1166. #define unmeta(c) (0x7f & (c)) 1167. 1168. 1169. void 1170. rhack(cmd) 1171. register char *cmd; 1172. { 1173. boolean do_walk, do_rush, prefix_seen, bad_command, 1174. firsttime = (cmd == 0); 1175. 1176. if (firsttime) { 1177. flags.nopick = 0; 1178. cmd = parse(); 1179. } 1180. if (*cmd == '\033') { 1181. flags.move = FALSE; 1182. return; 1183. } 1184. #ifdef REDO 1185. if (*cmd == DOAGAIN && !in_doagain && saveq[0]) { 1186. in_doagain = TRUE; 1187. stail = 0; 1188. rhack((char *)0); /* read and execute command */ 1189. in_doagain = FALSE; 1190. return; 1191. } 1192. /* Special case of *cmd == ' ' handled better below */ 1193. if(!*cmd || *cmd == (char)0377) { 1194. #else 1195. if(!*cmd || *cmd == (char)0377 || 1196. (!flags.rest_on_space && *cmd == ' ')) { 1197. #endif 1198. nhbell(); 1199. flags.move = FALSE; 1200. return; /* probably we just had an interrupt */ 1201. } 1202. 1203. /* handle most movement commands */ 1204. do_walk = do_rush = prefix_seen = FALSE; 1205. switch (*cmd) { 1206. case 'g': if (movecmd(cmd[1])) { 1207. flags.run = 2; 1208. do_rush = TRUE; 1209. } else 1210. prefix_seen = TRUE; 1211. break; 1212. case '5': if (!flags.num_pad) break; /* else FALLTHRU */ 1213. case 'G': if (movecmd(lowc(cmd[1]))) { 1214. flags.run = 3; 1215. do_rush = TRUE; 1216. } else 1217. prefix_seen = TRUE; 1218. break; 1219. case '-': if (!flags.num_pad) break; /* else FALLTHRU */ 1220. case 'm': if (movecmd(cmd[1]) || u.dz) { 1221. flags.run = 0; 1222. flags.nopick = 1; 1223. if (!u.dz) do_walk = TRUE; 1224. else cmd[0] = cmd[1]; /* "m<" or "m>" */ 1225. } else 1226. prefix_seen = TRUE; 1227. break; 1228. case 'M': if (movecmd(lowc(cmd[1]))) { 1229. flags.run = 1; 1230. flags.nopick = 1; 1231. do_rush = TRUE; 1232. } else 1233. prefix_seen = TRUE; 1234. break; 1235. case '0': if (!flags.num_pad) break; 1236. (void)ddoinv(); /* a convenience borrowed from the PC */ 1237. flags.move = FALSE; 1238. multi = 0; 1239. return; 1240. default: if (movecmd(*cmd)) { /* ordinary movement */ 1241. do_walk = TRUE; 1242. } else if (movecmd(flags.num_pad ? 1243. unmeta(*cmd) : lowc(*cmd))) { 1244. flags.run = 1; 1245. do_rush = TRUE; 1246. } else if (movecmd(unctrl(*cmd))) { 1247. flags.run = 3; 1248. do_rush = TRUE; 1249. } 1250. break; 1251. } 1252. if (do_walk) { 1253. if (multi) flags.mv = TRUE; 1254. domove(); 1255. return; 1256. } else if (do_rush) { 1257. if (firsttime) { 1258. if (!multi) multi = max(COLNO,ROWNO); 1259. u.last_str_turn = 0; 1260. } 1261. flags.mv = TRUE; 1262. domove(); 1263. return; 1264. } else if (prefix_seen && cmd[1] == '\033') { /* <prefix><escape> */ 1265. /* don't report "unknown command" for change of heart... */ 1266. bad_command = FALSE; 1267. } else if (*cmd == ' ' && !flags.rest_on_space) { 1268. bad_command = TRUE; /* skip cmdlist[] loop */ 1269. 1270. /* handle all other commands */ 1271. } else { 1272. register const struct func_tab *tlist; 1273. int res, NDECL((*func)); 1274. 1275. for (tlist = cmdlist; tlist->f_char; tlist++) { 1276. if ((*cmd & 0xff) != (tlist->f_char & 0xff)) continue; 1277. 1278. if (u.uburied && !tlist->can_if_buried) { 1279. You_cant("do that while you are buried!"); 1280. res = 0; 1281. } else { 1282. /* we discard 'const' because some compilers seem to have 1283. trouble with the pointer passed to set_occupation() */ 1284. func = ((struct func_tab *)tlist)->f_funct; 1285. if (tlist->f_text && !occupation && multi) 1286. set_occupation(func, tlist->f_text, multi); 1287. res = (*func)(); /* perform the command */ 1288. } 1289. if (!res) { 1290. flags.move = FALSE; 1291. multi = 0; 1292. } 1293. return; 1294. } 1295. /* if we reach here, cmd wasn't found in cmdlist[] */ 1296. bad_command = TRUE; 1297. } 1298. 1299. if (bad_command) { 1300. char expcmd[10]; 1301. register char *cp = expcmd; 1302. 1303. while (*cmd && (int)(cp - expcmd) < (int)(sizeof expcmd - 3)) { 1304. if (*cmd >= 040 && *cmd < 0177) { 1305. *cp++ = *cmd++; 1306. } else if (*cmd & 0200) { 1307. *cp++ = 'M'; 1308. *cp++ = '-'; 1309. *cp++ = *cmd++ &= ~0200; 1310. } else { 1311. *cp++ = '^'; 1312. *cp++ = *cmd++ ^ 0100; 1313. } 1314. } 1315. *cp = '\0'; 1316. Norep("Unknown command '%s'.", expcmd); 1317. } 1318. /* didn't move */ 1319. flags.move = FALSE; 1320. multi = 0; 1321. return; 1322. } 1323. 1324. int 1325. xytod(x, y) /* convert an x,y pair into a direction code */ 1326. schar x, y; 1327. { 1328. register int dd; 1329. 1330. for(dd = 0; dd < 8; dd++) 1331. if(x == xdir[dd] && y == ydir[dd]) return dd; 1332. 1333. return -1; 1334. } 1335. 1336. void 1337. dtoxy(cc,dd) /* convert a direction code into an x,y pair */ 1338. coord *cc; 1339. register int dd; 1340. { 1341. cc->x = xdir[dd]; 1342. cc->y = ydir[dd]; 1343. return; 1344. } 1345. 1346. int 1347. movecmd(sym) /* also sets u.dz, but returns false for <> */ 1348. char sym; 1349. { 1350. register const char *dp; 1351. register const char *sdp; 1352. if(flags.num_pad) sdp = ndir; else sdp = sdir; /* DICE workaround */ 1353. 1354. u.dz = 0; 1355. if(!(dp = index(sdp, sym))) return 0; 1356. u.dx = xdir[dp-sdp]; 1357. u.dy = ydir[dp-sdp]; 1358. u.dz = zdir[dp-sdp]; 1359. if (u.dx && u.dy && u.umonnum == PM_GRID_BUG) { 1360. u.dx = u.dy = 0; 1361. return 0; 1362. } 1363. return !u.dz; 1364. } 1365. 1366. int 1367. getdir(s) 1368. const char *s; 1369. { 1370. char dirsym; 1371. 1372. #ifdef REDO 1373. if(in_doagain) 1374. dirsym = readchar(); 1375. else 1376. #endif 1377. dirsym = yn_function (s ? s : "In what direction?", 1378. (char *)0, '\0'); 1379. #ifdef REDO 1380. savech(dirsym); 1381. #endif 1382. if(dirsym == '.' || dirsym == 's') 1383. u.dx = u.dy = u.dz = 0; 1384. else if(!movecmd(dirsym) && !u.dz) { 1385. if(!index(quitchars, dirsym)) 1386. pline("What a strange direction!"); 1387. return 0; 1388. } 1389. if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir(); 1390. return 1; 1391. } 1392. 1393. #endif /* OVL1 */ 1394. #ifdef OVLB 1395. 1396. void 1397. confdir() 1398. { 1399. register int x = (u.umonnum == PM_GRID_BUG) ? 2*rn2(4) : rn2(8); 1400. u.dx = xdir[x]; 1401. u.dy = ydir[x]; 1402. return; 1403. } 1404. 1405. #endif /* OVLB */ 1406. #ifdef OVL0 1407. 1408. int 1409. isok(x,y) 1410. register int x, y; 1411. { 1412. /* x corresponds to curx, so x==1 is the first column. Ach. %% */ 1413. return x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1; 1414. } 1415. 1416. static NEARDATA int last_multi; 1417. 1418. /* 1419. * convert a MAP window position into a movecmd 1420. */ 1421. int 1422. click_to_cmd(x, y, mod) 1423. int x, y, mod; 1424. { 1425. x -= u.ux; 1426. y -= u.uy; 1427. /* convert without using floating point, allowing sloppy clicking */ 1428. if(x > 2*abs(y)) 1429. x = 1, y = 0; 1430. else if(y > 2*abs(x)) 1431. x = 0, y = 1; 1432. else if(x < -2*abs(y)) 1433. x = -1, y = 0; 1434. else if(y < -2*abs(x)) 1435. x = 0, y = -1; 1436. else 1437. x = sgn(x), y = sgn(y); 1438. 1439. if(x == 0 && y == 0) /* map click on player to "rest" command */ 1440. return '.'; 1441. 1442. x = xytod(x, y); 1443. if(mod == CLICK_1) { 1444. return (flags.num_pad ? ndir[x] : sdir[x]); 1445. } else { 1446. return (flags.num_pad ? M(ndir[x]) : 1447. (sdir[x] - 'a' + 'A')); /* run command */ 1448. } 1449. } 1450. 1451. STATIC_OVL char * 1452. parse() 1453. { 1454. #ifdef LINT /* static char in_line[COLNO]; */ 1455. char in_line[COLNO]; 1456. #else 1457. static char in_line[COLNO]; 1458. #endif 1459. register int foo; 1460. boolean prezero = FALSE; 1461. 1462. multi = 0; 1463. flags.move = 1; 1464. flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */ 1465. 1466. if (!flags.num_pad || (foo = readchar()) == 'n') 1467. for (;;) { 1468. foo = readchar(); 1469. if (foo >= '0' && foo <= '9') { 1470. multi = 10 * multi + foo - '0'; 1471. if (multi < 0 || multi >= LARGEST_INT) multi = LARGEST_INT; 1472. if (multi > 9) { 1473. clear_nhwindow(WIN_MESSAGE); 1474. Sprintf(in_line, "Count: %d", multi); 1475. pline(in_line); 1476. mark_synch(); 1477. } 1478. last_multi = multi; 1479. if (!multi && foo == '0') prezero = TRUE; 1480. } else break; /* not a digit */ 1481. } 1482. 1483. if (foo == '\033') { /* esc cancels count (TH) */ 1484. clear_nhwindow(WIN_MESSAGE); 1485. multi = last_multi = 0; 1486. # ifdef REDO 1487. } else if (foo == DOAGAIN || in_doagain) { 1488. multi = last_multi; 1489. } else { 1490. last_multi = multi; 1491. savech(0); /* reset input queue */ 1492. savech((char)foo); 1493. # endif 1494. } 1495. 1496. if (multi) { 1497. multi--; 1498. save_cm = in_line; 1499. } else { 1500. save_cm = (char *)0; 1501. } 1502. in_line[0] = foo; 1503. in_line[1] = '\0'; 1504. if (foo == 'g' || foo == 'G' || (flags.num_pad && foo == '5') || 1505. foo == 'm' || foo == 'M') { 1506. foo = readchar(); 1507. #ifdef REDO 1508. savech((char)foo); 1509. #endif 1510. in_line[1] = foo; 1511. in_line[2] = 0; 1512. } 1513. clear_nhwindow(WIN_MESSAGE); 1514. if (prezero) in_line[0] = '\033'; 1515. return(in_line); 1516. } 1517. 1518. #endif /* OVL0 */ 1519. #ifdef OVLB 1520. 1521. #ifdef UNIX 1522. static 1523. void 1524. end_of_input() 1525. { 1526. exit_nhwindows("End of input?"); 1527. #ifndef NOSAVEONHANGUP 1528. if (!program_state.done_hup++) 1529. (void) dosave0(); 1530. #endif 1531. clearlocks(); 1532. terminate(EXIT_SUCCESS); 1533. } 1534. #endif 1535. 1536. #endif /* OVLB */ 1537. #ifdef OVL0 1538. 1539. char 1540. readchar() 1541. { 1542. register int sym; 1543. int x, y, mod; 1544. 1545. #ifdef REDO 1546. sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod); 1547. #else 1548. sym = Getchar(); 1549. #endif 1550. 1551. #ifdef UNIX 1552. # ifdef NR_OF_EOFS 1553. if (sym == EOF) { 1554. register int cnt = NR_OF_EOFS; 1555. /* 1556. * Some SYSV systems seem to return EOFs for various reasons 1557. * (?like when one hits break or for interrupted systemcalls?), 1558. * and we must see several before we quit. 1559. */ 1560. do { 1561. clearerr(stdin); /* omit if clearerr is undefined */ 1562. sym = Getchar(); 1563. } while (--cnt && sym == EOF); 1564. } 1565. # endif /* NR_OF_EOFS */ 1566. if (sym == EOF) 1567. end_of_input(); 1568. #endif /* UNIX */ 1569. 1570. if(sym == 0) /* click event */ 1571. sym = click_to_cmd(x, y, mod); 1572. return((char) sym); 1573. } 1574. #endif /* OVL0 */ 1575. 1576. /*cmd.c*/