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