Source:SLASH'EM 0.0.7E7F2/end.c
Revision as of 19:03, 7 March 2008 by Kernigh bot (talk | contribs) (SLASH'EM 0.0.7E7F2/end.c moved to Source:SLASH'EM 0.0.7E7F2/end.c: Robot: moved page)
Below is the full text to end.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/end.c#line123]], for example.
The latest source code for vanilla NetHack is at 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: @(#)end.c 3.4 2003/03/10 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #define NEED_VARARGS /* comment line for pre-compiled headers */ 6. 7. #include "hack.h" 8. #include "eshk.h" 9. #ifndef NO_SIGNAL 10. #include <signal.h> 11. #endif 12. #include "dlb.h" 13. 14. /* these probably ought to be generated by makedefs, like LAST_GEM */ 15. #define FIRST_GEM DILITHIUM_CRYSTAL 16. #define FIRST_AMULET AMULET_OF_ESP 17. #define LAST_AMULET AMULET_OF_YENDOR 18. 19. struct valuable_data { long count; int typ; }; 20. 21. static struct valuable_data 22. gems[LAST_GEM+1 - FIRST_GEM + 1], /* 1 extra for glass */ 23. amulets[LAST_AMULET+1 - FIRST_AMULET]; 24. 25. static struct val_list { struct valuable_data *list; int size; } valuables[] = { 26. { gems, sizeof gems / sizeof *gems }, 27. { amulets, sizeof amulets / sizeof *amulets }, 28. { 0, 0 } 29. }; 30. 31. #ifndef NO_SIGNAL 32. STATIC_PTR void FDECL(done_intr, (int)); 33. # if defined(UNIX) || defined(VMS) || defined (__EMX__) 34. static void FDECL(done_hangup, (int)); 35. # endif 36. #endif 37. STATIC_DCL void FDECL(disclose,(int,BOOLEAN_P)); 38. STATIC_DCL void FDECL(get_valuables, (struct obj *)); 39. STATIC_DCL void FDECL(sort_valuables, (struct valuable_data *,int)); 40. STATIC_DCL void FDECL(artifact_score, (struct obj *,BOOLEAN_P,winid)); 41. STATIC_DCL void FDECL(savelife, (int)); 42. STATIC_DCL boolean FDECL(list_vanquished, (CHAR_P, BOOLEAN_P)); 43. STATIC_DCL void FDECL(list_genocided, (CHAR_P, BOOLEAN_P)); 44. STATIC_DCL boolean FDECL(should_query_disclose_option, (int,char *)); 45. 46. #if defined(__BEOS__) || defined(MICRO) || defined(WIN32) || defined(OS2) 47. extern void FDECL(nethack_exit,(int)); 48. #else 49. #define nethack_exit exit 50. #endif 51. 52. #define done_stopprint program_state.stopprint 53. 54. #ifdef AMIGA 55. # define NH_abort() Abort(0) 56. #else 57. # ifdef SYSV 58. # define NH_abort() (void) abort() 59. # else 60. # ifdef WIN32 61. # define NH_abort() win32_abort() 62. # else 63. # define NH_abort() abort() 64. # endif 65. # endif 66. #endif 67. 68. /* 69. * The order of these needs to match the macros in hack.h. 70. */ 71. static NEARDATA const char *deaths[] = { /* the array of death */ 72. "died", "betrayed", "choked", "poisoned", "starvation", "drowning", 73. "burning", "dissolving under the heat and pressure", 74. "crushed", "turned to stone", "turned into slime", 75. "genocided", "panic", "trickery", 76. "quit", "escaped", "ascended" 77. }; 78. 79. static NEARDATA const char *ends[] = { /* "when you..." */ 80. "died", "were betrayed", "choked", "were poisoned", "starved", 81. "drowned", "burned", "dissolved in the lava", 82. "were crushed", "turned to stone", "turned into slime", 83. "were genocided", "panicked", "were tricked", 84. "quit", "escaped", "ascended" 85. }; 86. 87. /*ARGSUSED*/ 88. void 89. done1(sig_unused) /* called as signal() handler, so sent at least one arg */ 90. int sig_unused; 91. { 92. #if defined(MAC_MPW) 93. # pragma unused ( sig_unused ) 94. #endif 95. #ifndef NO_SIGNAL 96. (void) signal(SIGINT,SIG_IGN); 97. #endif 98. if(flags.ignintr) { 99. #ifndef NO_SIGNAL 100. (void) signal(SIGINT, (SIG_RET_TYPE) done1); 101. #endif 102. clear_nhwindow(WIN_MESSAGE); 103. curs_on_u(); 104. wait_synch(); 105. if(multi > 0) nomul(0); 106. } else { 107. (void)done2(); 108. } 109. } 110. 111. extern const char * const killed_by_prefix[]; /* from topten.c */ 112. 113. /* "#quit" command or keyboard interrupt */ 114. int 115. done2() 116. { 117. if(yn("Really quit?") == 'n') { 118. #ifndef NO_SIGNAL 119. (void) signal(SIGINT, (SIG_RET_TYPE) done1); 120. #endif 121. clear_nhwindow(WIN_MESSAGE); 122. curs_on_u(); 123. wait_synch(); 124. if(multi > 0) nomul(0); 125. if(multi == 0) { 126. u.uinvulnerable = FALSE; /* avoid ctrl-C bug -dlc */ 127. u.usleep = 0; 128. } 129. return 0; 130. } 131. #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE)) 132. if(wizard) { 133. int c; 134. # ifdef VMS 135. const char *tmp = "Enter debugger?"; 136. # else 137. # ifdef LATTICE 138. const char *tmp = "Create SnapShot?"; 139. # else 140. const char *tmp = "Dump core?"; 141. # endif 142. # endif 143. if ((c = ynq(tmp)) == 'y') { 144. (void) signal(SIGINT, (SIG_RET_TYPE) done1); 145. exit_nhwindows((char *)0); 146. NH_abort(); 147. } else if (c == 'q') done_stopprint++; 148. } 149. #endif 150. #ifndef LINT 151. done(QUIT); 152. #endif 153. return 0; 154. } 155. 156. #ifndef NO_SIGNAL 157. /*ARGSUSED*/ 158. STATIC_PTR void 159. done_intr(sig_unused) /* called as signal() handler, so sent at least one arg */ 160. int sig_unused; 161. { 162. #if defined(MAC_MPW) 163. # pragma unused ( sig_unused ) 164. #endif 165. done_stopprint++; 166. (void) signal(SIGINT, SIG_IGN); 167. # if defined(UNIX) || defined(VMS) 168. (void) signal(SIGQUIT, SIG_IGN); 169. # endif 170. return; 171. } 172. 173. # if defined(UNIX) || defined(VMS) || defined(__EMX__) 174. static void 175. done_hangup(sig) /* signal() handler */ 176. int sig; 177. { 178. program_state.done_hup++; 179. (void)signal(SIGHUP, SIG_IGN); 180. done_intr(sig); 181. return; 182. } 183. # endif 184. #endif /* NO_SIGNAL */ 185. 186. void 187. done_in_by(mtmp) 188. register struct monst *mtmp; 189. { 190. char buf[BUFSZ]; 191. boolean distorted = (boolean)(Hallucination && canspotmon(mtmp)); 192. 193. You("die..."); 194. /* for those wand o'death, touch o'death, poisoned spike times... */ 195. if (Instant_Death) 196. You("were hosed!"); 197. mark_synch(); /* flush buffered screen output */ 198. buf[0] = '\0'; 199. killer_format = KILLED_BY_AN; 200. if (!Blind || Blind_telepat) { 201. /* "killed by the high priest of Crom" is okay, "killed by the high 202. priest" alone isn't */ 203. if ((mtmp->data->geno & G_UNIQ) != 0 && !(mtmp->data == &mons[PM_HIGH_PRIEST] && !mtmp->ispriest)) { 204. if (!type_is_pname(mtmp->data)) 205. Strcat(buf, "the "); 206. killer_format = KILLED_BY; 207. } 208. /* _the_ <invisible> <distorted> ghost of Dudley */ 209. if (mtmp->data == &mons[PM_GHOST] && mtmp->mnamelth) { 210. Strcat(buf, "the "); 211. killer_format = KILLED_BY; 212. } 213. if (mtmp->minvis) 214. Strcat(buf, "invisible "); 215. if (distorted) 216. Strcat(buf, "hallucinogen-distorted "); 217. 218. if(mtmp->data == &mons[PM_GHOST]) { 219. Strcat(buf, "ghost"); 220. if (mtmp->mnamelth) Sprintf(eos(buf), " of %s", NAME(mtmp)); 221. } else if(mtmp->isshk) { 222. Sprintf(eos(buf), "%s %s, the shopkeeper", 223. (mtmp->female ? "Ms." : "Mr."), shkname(mtmp)); 224. killer_format = KILLED_BY; 225. } else if (mtmp->ispriest || mtmp->isminion) { 226. /* m_monnam() suppresses "the" prefix plus "invisible", and 227. it overrides the effect of Hallucination on priestname() */ 228. killer = m_monnam(mtmp); 229. Strcat(buf, killer); 230. } else { 231. Strcat(buf, mtmp->data->mname); 232. if (mtmp->mnamelth) 233. Sprintf(eos(buf), " called %s", NAME(mtmp)); 234. } 235. 236. if (multi) Strcat(buf,", while helpless"); 237. } else { 238. killer_format = KILLED_BY; 239. Strcat(buf,"something while blind"); 240. if (multi) Strcat(buf," and helpless"); 241. } 242. 243. killer = buf; 244. if (mtmp->data->mlet == S_WRAITH) 245. u.ugrave_arise = PM_WRAITH; 246. else if (mtmp->data->mlet == S_MUMMY && urace.mummynum != NON_PM) 247. u.ugrave_arise = urace.mummynum; 248. else if (is_vampire(mtmp->data) && Race_if(PM_HUMAN) 249. && mtmp->data != &mons[PM_FIRE_VAMPIRE] 250. && mtmp->data != &mons[PM_STAR_VAMPIRE]) 251. u.ugrave_arise = PM_VAMPIRE; 252. else if (mtmp->data == &mons[PM_GHOUL]) 253. u.ugrave_arise = PM_GHOUL; 254. if (u.ugrave_arise >= LOW_PM && 255. (mvitals[u.ugrave_arise].mvflags & G_GENOD)) 256. u.ugrave_arise = NON_PM; 257. if (touch_petrifies(mtmp->data)) 258. done(STONING); 259. else if (mtmp->mtraitor) 260. done(BETRAYED); 261. else 262. done(DIED); 263. return; 264. } 265. 266. #if defined(WIN32) 267. #define NOTIFY_NETHACK_BUGS 268. #endif 269. 270. /*VARARGS1*/ 271. void 272. panic VA_DECL(const char *, str) 273. VA_START(str); 274. VA_INIT(str, char *); 275. 276. if (program_state.panicking++) 277. NH_abort(); /* avoid loops - this should never happen*/ 278. 279. if (iflags.window_inited) { 280. raw_print("\r\nOops..."); 281. wait_synch(); /* make sure all pending output gets flushed */ 282. exit_nhwindows((char *)0); 283. iflags.window_inited = 0; /* they're gone; force raw_print()ing */ 284. } 285. 286. raw_print(program_state.gameover ? 287. "Postgame wrapup disrupted." : 288. !program_state.something_worth_saving ? 289. "Program initialization has failed." : 290. "Suddenly, the dungeon collapses."); 291. #if defined(WIZARD) && !defined(MICRO) 292. # if defined(NOTIFY_NETHACK_BUGS) 293. if (!wizard) 294. raw_printf("Report the following error to \"%s\".", 295. "slashem-discuss@lists.sourceforge.net"); 296. else if (program_state.something_worth_saving) 297. raw_print("\nError save file being written.\n"); 298. # else 299. if (!wizard) 300. raw_printf("Report error to \"%s\"%s.", 301. # ifdef WIZARD_NAME /*(KR1ED)*/ 302. WIZARD_NAME, 303. # else 304. WIZARD, 305. # endif 306. !program_state.something_worth_saving ? "" : 307. " and it may be possible to rebuild."); 308. # endif 309. if (program_state.something_worth_saving) { 310. set_error_savefile(); 311. (void) dosave0(); 312. } 313. #endif 314. { 315. char buf[BUFSZ]; 316. Vsprintf(buf,str,VA_ARGS); 317. raw_print(buf); 318. paniclog("panic", buf); 319. } 320. #ifdef WIN32 321. interject(INTERJECT_PANIC); 322. #endif 323. #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE) || defined(WIN32)) 324. if (wizard) 325. NH_abort(); /* generate core dump */ 326. #endif 327. VA_END(); 328. done(PANICKED); 329. } 330. 331. STATIC_OVL boolean 332. should_query_disclose_option(category, defquery) 333. int category; 334. char *defquery; 335. { 336. int idx; 337. char *dop = index(disclosure_options, category); 338. 339. if (dop && defquery) { 340. idx = dop - disclosure_options; 341. if (idx < 0 || idx > (NUM_DISCLOSURE_OPTIONS - 1)) { 342. impossible( 343. "should_query_disclose_option: bad disclosure index %d %c", 344. idx, category); 345. *defquery = DISCLOSE_PROMPT_DEFAULT_YES; 346. return TRUE; 347. } 348. if (flags.end_disclose[idx] == DISCLOSE_YES_WITHOUT_PROMPT) { 349. *defquery = 'y'; 350. return FALSE; 351. } else if (flags.end_disclose[idx] == DISCLOSE_NO_WITHOUT_PROMPT) { 352. *defquery = 'n'; 353. return FALSE; 354. } else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_YES) { 355. *defquery = 'y'; 356. return TRUE; 357. } else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_NO) { 358. *defquery = 'n'; 359. return TRUE; 360. } 361. } 362. if (defquery) 363. impossible("should_query_disclose_option: bad category %c", category); 364. else 365. impossible("should_query_disclose_option: null defquery"); 366. return TRUE; 367. } 368. 369. STATIC_OVL void 370. disclose(how,taken) 371. int how; 372. boolean taken; 373. { 374. char c = 0, defquery; 375. char qbuf[QBUFSZ]; 376. boolean ask; 377. boolean hallu=FALSE; 378. 379. if (invent) { 380. if(taken) 381. Sprintf(qbuf,"Do you want to see what you had when you %s?", 382. (how == QUIT) ? "quit" : "died"); 383. else 384. Strcpy(qbuf,"Do you want your possessions identified?"); 385. 386. ask = should_query_disclose_option('i', &defquery); 387. if (!done_stopprint) { 388. c = ask ? yn_function(qbuf, ynqchars, defquery) : defquery; 389. if (c == 'y') { 390. struct obj *obj; 391. 392. if (Hallucination) { 393. make_hallucinated(0L, FALSE, 0L); 394. hallu = TRUE; 395. } 396. for (obj = invent; obj; obj = obj->nobj) { 397. makeknown(obj->otyp); 398. obj->known = obj->bknown = obj->dknown = obj->rknown = 1; 399. } 400. (void) display_inventory((char *)0, TRUE); 401. container_contents(invent, TRUE, TRUE); 402. } 403. if (c == 'q') done_stopprint++; 404. } 405. } 406. if (hallu) make_hallucinated(20L, FALSE, 0L); 407. 408. ask = should_query_disclose_option('a', &defquery); 409. if (!done_stopprint) { 410. c = ask ? yn_function("Do you want to see your attributes?", 411. ynqchars, defquery) : defquery; 412. if (c == 'y') 413. enlightenment(how >= PANICKED ? 1 : 2); /* final */ 414. if (c == 'q') done_stopprint++; 415. } 416. 417. ask = should_query_disclose_option('v', &defquery); 418. if (!done_stopprint) 419. list_vanquished(defquery, ask); 420. 421. ask = should_query_disclose_option('g', &defquery); 422. if (!done_stopprint) 423. list_genocided(defquery, ask); 424. 425. ask = should_query_disclose_option('c', &defquery); 426. if (!done_stopprint) { 427. c = ask ? yn_function("Do you want to see your conduct?", 428. ynqchars, defquery) : defquery; 429. if (c == 'y') 430. show_conduct(how >= PANICKED ? 1 : 2); 431. if (c == 'q') done_stopprint++; 432. } 433. } 434. 435. /* try to get the player back in a viable state after being killed */ 436. STATIC_OVL void 437. savelife(how) 438. int how; 439. { 440. u.uswldtim = 0; 441. u.uhp = u.uhpmax; 442. if (u.uhunger < 500) { 443. u.uhunger = 500; 444. newuhs(FALSE); 445. } 446. /* cure impending doom of sickness hero won't have time to fix */ 447. if ((Sick & TIMEOUT) == 1) { 448. u.usick_type = 0; 449. Sick = 0; 450. } 451. if (how == CHOKING) init_uhunger(); 452. nomovemsg = "You survived that attempt on your life."; 453. flags.move = 0; 454. if(multi > 0) multi = 0; else multi = -1; 455. if(u.utrap && u.utraptype == TT_LAVA) u.utrap = 0; 456. flags.botl = 1; 457. u.ugrave_arise = NON_PM; 458. HUnchanging = 0L; 459. curs_on_u(); 460. } 461. 462. /* 463. * Get valuables from the given list. Revised code: the list always remains 464. * intact. 465. */ 466. STATIC_OVL void 467. get_valuables(list) 468. struct obj *list; /* inventory or container contents */ 469. { 470. register struct obj *obj; 471. register int i; 472. 473. /* find amulets and gems, ignoring all artifacts */ 474. for (obj = list; obj; obj = obj->nobj) 475. if (Has_contents(obj)) { 476. get_valuables(obj->cobj); 477. } else if (obj->oartifact) { 478. continue; 479. } else if (obj->oclass == AMULET_CLASS) { 480. i = obj->otyp - FIRST_AMULET; 481. if (!amulets[i].count) { 482. amulets[i].count = obj->quan; 483. amulets[i].typ = obj->otyp; 484. } else amulets[i].count += obj->quan; /* always adds one */ 485. } else if (obj->oclass == GEM_CLASS && obj->otyp < LUCKSTONE) { 486. i = min(obj->otyp, LAST_GEM + 1) - FIRST_GEM; 487. if (!gems[i].count) { 488. gems[i].count = obj->quan; 489. gems[i].typ = obj->otyp; 490. } else gems[i].count += obj->quan; 491. } 492. return; 493. } 494. 495. /* 496. * Sort collected valuables, most frequent to least. We could just 497. * as easily use qsort, but we don't care about efficiency here. 498. */ 499. STATIC_OVL void 500. sort_valuables(list, size) 501. struct valuable_data list[]; 502. int size; /* max value is less than 20 */ 503. { 504. register int i, j; 505. struct valuable_data ltmp; 506. 507. /* move greater quantities to the front of the list */ 508. for (i = 1; i < size; i++) { 509. if (list[i].count == 0) continue; /* empty slot */ 510. ltmp = list[i]; /* structure copy */ 511. for (j = i; j > 0; --j) 512. if (list[j-1].count >= ltmp.count) break; 513. else { 514. list[j] = list[j-1]; 515. } 516. list[j] = ltmp; 517. } 518. return; 519. } 520. 521. /* called twice; first to calculate total, then to list relevant items */ 522. STATIC_OVL void 523. artifact_score(list, counting, endwin) 524. struct obj *list; 525. boolean counting; /* true => add up points; false => display them */ 526. winid endwin; 527. { 528. char pbuf[BUFSZ]; 529. struct obj *otmp; 530. long value, points; 531. short dummy; /* object type returned by artifact_name() */ 532. 533. for (otmp = list; otmp; otmp = otmp->nobj) { 534. if (otmp->oartifact || 535. otmp->otyp == BELL_OF_OPENING || 536. otmp->otyp == SPE_BOOK_OF_THE_DEAD || 537. otmp->otyp == CANDELABRUM_OF_INVOCATION) { 538. value = arti_cost(otmp); /* zorkmid value */ 539. points = value * 5 / 2; /* score value */ 540. if (counting) { 541. u.urexp += points; 542. } else { 543. makeknown(otmp->otyp); 544. otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1; 545. /* assumes artifacts don't have quan > 1 */ 546. Sprintf(pbuf, "%s%s (worth %ld %s and %ld points)", 547. the_unique_obj(otmp) ? "The " : "", 548. otmp->oartifact ? artifact_name(xname(otmp), &dummy) : 549. OBJ_NAME(objects[otmp->otyp]), 550. value, currency(value), points); 551. putstr(endwin, 0, pbuf); 552. } 553. } 554. if (Has_contents(otmp)) 555. artifact_score(otmp->cobj, counting, endwin); 556. } 557. } 558. 559. /* Be careful not to call panic from here! */ 560. void 561. done(how) 562. int how; 563. { 564. boolean taken; 565. char kilbuf[BUFSZ], pbuf[BUFSZ]; 566. winid endwin = WIN_ERR; 567. boolean bones_ok, have_windows = iflags.window_inited; 568. struct obj *corpse = (struct obj *)0; 569. long umoney; 570. 571. if (how == TRICKED) { 572. if (killer) { 573. paniclog("trickery", killer); 574. killer = 0; 575. } 576. #ifdef WIZARD 577. if (wizard) { 578. You("are a very tricky wizard, it seems."); 579. return; 580. } 581. #endif 582. } 583. 584. /* kilbuf: used to copy killer in case it comes from something like 585. * xname(), which would otherwise get overwritten when we call 586. * xname() when listing possessions 587. * pbuf: holds Sprintf'd output for raw_print and putstr 588. */ 589. if (how == ASCENDED || (!killer && how == GENOCIDED)) 590. killer_format = NO_KILLER_PREFIX; 591. /* Avoid killed by "a" burning or "a" starvation */ 592. if (!killer && (how == STARVING || how == BURNING)) 593. killer_format = KILLED_BY; 594. Strcpy(kilbuf, (!killer || how >= PANICKED ? deaths[how] : killer)); 595. killer = kilbuf; 596. 597. if (how < PANICKED) u.umortality++; 598. if (how == STONING && uamul && uamul->otyp == AMULET_VERSUS_STONE) { 599. pline("But wait..."); 600. makeknown(AMULET_VERSUS_STONE); 601. Your("medallion %s%s!", 602. !Blind ? "begins to glow" : "feels warm", 603. uamul->cursed ? " and disintegrates" : ""); 604. /* blessed -> uncursed -> cursed -> gone */ 605. if (uamul->cursed) 606. useup(uamul); 607. else if (uamul->blessed) 608. unbless(uamul); 609. else 610. curse(uamul); 611. 612. uunstone(); 613. (void) adjattrib(A_CON, -1, TRUE); 614. if(u.uhpmax <= 0) u.uhpmax = 1; 615. savelife(how); 616. killer = 0; 617. killer_format = 0; 618. return; 619. } 620. if (Lifesaved && (how <= GENOCIDED)) { 621. pline("But wait..."); 622. makeknown(AMULET_OF_LIFE_SAVING); 623. Your("medallion %s!", 624. !Blind ? "begins to glow" : "feels warm"); 625. if (how == CHOKING) You("vomit ..."); 626. You_feel("much better!"); 627. pline_The("medallion crumbles to dust!"); 628. /* KMH -- Bullet-proofing */ 629. if (uamul) 630. useup(uamul); 631. 632. (void) adjattrib(A_CON, -1, TRUE); 633. if(u.uhpmax <= 0) u.uhpmax = 10; /* arbitrary */ 634. savelife(how); 635. if (how == GENOCIDED) 636. pline("Unfortunately you are still genocided..."); 637. else { 638. killer = 0; 639. killer_format = 0; 640. return; 641. } 642. } 643. if (( 644. #ifdef WIZARD 645. wizard || 646. #endif 647. discover) && (how <= GENOCIDED || how == TURNED_SLIME)) { 648. if(yn("Die?") == 'y') goto die; 649. pline("OK, so you don't %s.", 650. (how == CHOKING) ? "choke" : "die"); 651. if(u.uhpmax <= 0) u.uhpmax = u.ulevel * 8; /* arbitrary */ 652. savelife(how); 653. killer = 0; 654. killer_format = 0; 655. return; 656. } 657. 658. /* 659. * The game is now over... 660. */ 661. 662. die: 663. program_state.gameover = 1; 664. /* in case of a subsequent panic(), there's no point trying to save */ 665. program_state.something_worth_saving = 0; 666. /* render vision subsystem inoperative */ 667. iflags.vision_inited = 0; 668. /* might have been killed while using a disposable item, so make sure 669. it's gone prior to inventory disclosure and creation of bones data */ 670. inven_inuse(TRUE); 671. 672. /* Sometimes you die on the first move. Life's not fair. 673. * On those rare occasions you get hosed immediately, go out 674. * smiling... :-) -3. 675. */ 676. if (moves <= 1 && how < PANICKED) /* You die... --More-- */ 677. pline("Do not pass go. Do not collect 200 %s.", currency(200L)); 678. 679. if (have_windows) wait_synch(); /* flush screen output */ 680. #ifndef NO_SIGNAL 681. (void) signal(SIGINT, (SIG_RET_TYPE) done_intr); 682. # if defined(UNIX) || defined(VMS) || defined (__EMX__) 683. (void) signal(SIGQUIT, (SIG_RET_TYPE) done_intr); 684. (void) signal(SIGHUP, (SIG_RET_TYPE) done_hangup); 685. # endif 686. #endif /* NO_SIGNAL */ 687. 688. #ifdef ALLEG_FX 689. if(iflags.usealleg && (how < PANICKED)) 690. fade_to_black(); 691. #endif 692. 693. bones_ok = (how < GENOCIDED) && can_make_bones(); 694. 695. if (how == TURNED_SLIME) 696. u.ugrave_arise = PM_GREEN_SLIME; 697. 698. if (bones_ok && u.ugrave_arise < LOW_PM) { 699. /* corpse gets burnt up too */ 700. if (how == BURNING) 701. u.ugrave_arise = (NON_PM - 2); /* leave no corpse */ 702. else if (how == STONING) 703. u.ugrave_arise = (NON_PM - 1); /* statue instead of corpse */ 704. else if (u.ugrave_arise == NON_PM && 705. !(mvitals[u.umonnum].mvflags & G_NOCORPSE)) { 706. int mnum = u.umonnum; 707. 708. if (!Upolyd) { 709. /* Base corpse on race when not poly'd since original 710. * u.umonnum is based on role, and all role monsters 711. * are human. 712. */ 713. mnum = undead_to_corpse( 714. (flags.female && urace.femalenum != NON_PM) ? 715. urace.femalenum : urace.malenum); 716. } 717. corpse = mk_named_object(CORPSE, &mons[mnum], 718. u.ux, u.uy, plname); 719. Sprintf(pbuf, "%s, %s%s", plname, 720. killer_format == NO_KILLER_PREFIX ? "" : 721. killed_by_prefix[how], 722. killer_format == KILLED_BY_AN ? an(killer) : killer); 723. make_grave(u.ux, u.uy, pbuf); 724. } 725. } 726. if (how == TURNED_SLIME) killer_format = NO_KILLER_PREFIX; 727. if (how == QUIT) { 728. killer_format = NO_KILLER_PREFIX; 729. if (u.uhp < 1) { 730. how = DIED; 731. u.umortality++; /* skipped above when how==QUIT */ 732. /* note that killer is pointing at kilbuf */ 733. Strcpy(kilbuf, "quit while already on Charon's boat"); 734. } 735. } 736. if (how == ESCAPED || how == PANICKED) 737. killer_format = NO_KILLER_PREFIX; 738. 739. if (how != PANICKED) { 740. /* these affect score and/or bones, but avoid them during panic */ 741. taken = paybill((how == ESCAPED) ? -1 : (how != QUIT)); 742. paygd(); 743. clearpriests(); 744. } else taken = FALSE; /* lint; assert( !bones_ok ); */ 745. 746. clearlocks(); 747. 748. if (have_windows) display_nhwindow(WIN_MESSAGE, FALSE); 749. 750. if (strcmp(flags.end_disclose, "none") && how != PANICKED) 751. disclose(how, taken); 752. /* finish_paybill should be called after disclosure but before bones */ 753. if (bones_ok && taken) finish_paybill(); 754. 755. /* calculate score, before creating bones [container gold] */ 756. { 757. long tmp; 758. int deepest = deepest_lev_reached(FALSE); 759. 760. #ifndef GOLDOBJ 761. umoney = u.ugold; 762. tmp = u.ugold0; 763. #else 764. umoney = money_cnt(invent); 765. tmp = u.umoney0; 766. #endif 767. umoney += hidden_gold(); /* accumulate gold from containers */ 768. tmp = umoney - tmp; /* net gain */ 769. 770. if (tmp < 0L) 771. tmp = 0L; 772. if (how < PANICKED) 773. tmp -= tmp / 10L; 774. u.urexp += tmp; 775. u.urexp += 50L * (long)(deepest - 1); 776. if (deepest > 20) 777. u.urexp += 1000L * (long)((deepest > 30) ? 10 : deepest - 20); 778. if (how == ASCENDED) u.urexp *= 2L; 779. } 780. 781. if (bones_ok) { 782. #ifdef WIZARD 783. /* KMH -- We need the "Save bones?" prompt for testing! */ 784. if (!wizard || yn("Save bones?") == 'y') 785. #endif 786. savebones(corpse); 787. /* corpse may be invalid pointer now so 788. ensure that it isn't used again */ 789. corpse = (struct obj *)0; 790. } 791. 792. /* update gold for the rip output, which can't use hidden_gold() 793. (containers will be gone by then if bones just got saved...) */ 794. #ifndef GOLDOBJ 795. u.ugold = umoney; 796. #else 797. done_money = umoney; 798. #endif 799. 800. /* clean up unneeded windows */ 801. if (have_windows) { 802. wait_synch(); 803. display_nhwindow(WIN_MESSAGE, TRUE); 804. destroy_nhwindow(WIN_MAP); 805. destroy_nhwindow(WIN_STATUS); 806. destroy_nhwindow(WIN_MESSAGE); 807. WIN_MESSAGE = WIN_STATUS = WIN_MAP = WIN_ERR; 808. 809. if(!done_stopprint || flags.tombstone) 810. endwin = create_nhwindow(NHW_TEXT); 811. 812. if (how < GENOCIDED && flags.tombstone && endwin != WIN_ERR) 813. outrip(endwin, how); 814. } else 815. done_stopprint = 1; /* just avoid any more output */ 816. 817. /* changing kilbuf really changes killer. we do it this way because 818. killer is declared a (const char *) 819. */ 820. if (u.uhave.amulet) Strcat(kilbuf, " (with the Amulet)"); 821. else if (how == ESCAPED) { 822. if (Is_astralevel(&u.uz)) /* offered Amulet to wrong deity */ 823. Strcat(kilbuf, " (in celestial disgrace)"); 824. else if (carrying(FAKE_AMULET_OF_YENDOR)) 825. Strcat(kilbuf, " (with a fake Amulet)"); 826. /* don't bother counting to see whether it should be plural */ 827. } 828. 829. if (!done_stopprint) { 830. Sprintf(pbuf, "%s %s the %s...", Goodbye(), plname, 831. how != ASCENDED ? 832. (const char *) ((flags.female && urole.name.f) ? 833. urole.name.f : urole.name.m) : 834. (const char *) (flags.female ? "Demigoddess" : "Demigod")); 835. putstr(endwin, 0, pbuf); 836. putstr(endwin, 0, ""); 837. } 838. 839. if (how == ESCAPED || how == ASCENDED) { 840. register struct monst *mtmp; 841. register struct obj *otmp; 842. register struct val_list *val; 843. register int i; 844. 845. for (val = valuables; val->list; val++) 846. for (i = 0; i < val->size; i++) { 847. val->list[i].count = 0L; 848. } 849. get_valuables(invent); 850. 851. /* add points for collected valuables */ 852. for (val = valuables; val->list; val++) 853. for (i = 0; i < val->size; i++) 854. if (val->list[i].count != 0L) 855. u.urexp += val->list[i].count 856. * (long)objects[val->list[i].typ].oc_cost; 857. 858. /* count the points for artifacts */ 859. artifact_score(invent, TRUE, endwin); 860. 861. keepdogs(TRUE); 862. viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */ 863. mtmp = mydogs; 864. if (!done_stopprint) Strcpy(pbuf, "You"); 865. if (mtmp) { 866. while (mtmp) { 867. if (!done_stopprint) 868. Sprintf(eos(pbuf), " and %s", mon_nam(mtmp)); 869. if (mtmp->mtame) 870. u.urexp += mtmp->mhp; 871. mtmp = mtmp->nmon; 872. } 873. if (!done_stopprint) putstr(endwin, 0, pbuf); 874. pbuf[0] = '\0'; 875. } else { 876. if (!done_stopprint) Strcat(pbuf, " "); 877. } 878. if (!done_stopprint) { 879. Sprintf(eos(pbuf), "%s with %ld point%s,", 880. how==ASCENDED ? "went to your reward" : 881. "escaped from the dungeon", 882. u.urexp, plur(u.urexp)); 883. putstr(endwin, 0, pbuf); 884. } 885. 886. if (!done_stopprint) 887. artifact_score(invent, FALSE, endwin); /* list artifacts */ 888. 889. /* list valuables here */ 890. for (val = valuables; val->list; val++) { 891. sort_valuables(val->list, val->size); 892. for (i = 0; i < val->size && !done_stopprint; i++) { 893. int typ = val->list[i].typ; 894. long count = val->list[i].count; 895. 896. if (count == 0L) continue; 897. if (objects[typ].oc_class != GEM_CLASS || typ <= LAST_GEM) { 898. otmp = mksobj(typ, FALSE, FALSE); 899. makeknown(otmp->otyp); 900. otmp->known = 1; /* for fake amulets */ 901. otmp->dknown = 1; /* seen it (blindness fix) */ 902. otmp->onamelth = 0; 903. otmp->quan = count; 904. Sprintf(pbuf, "%8ld %s (worth %ld %s),", 905. count, xname(otmp), 906. count * (long)objects[typ].oc_cost, currency(2L)); 907. obfree(otmp, (struct obj *)0); 908. } else { 909. Sprintf(pbuf, 910. "%8ld worthless piece%s of colored glass,", 911. count, plur(count)); 912. } 913. putstr(endwin, 0, pbuf); 914. } 915. } 916. 917. } else if (!done_stopprint) { 918. /* did not escape or ascend */ 919. if (u.uz.dnum == 0 && u.uz.dlevel <= 0) { 920. /* level teleported out of the dungeon; `how' is DIED, 921. due to falling or to "arriving at heaven prematurely" */ 922. Sprintf(pbuf, "You %s beyond the confines of the dungeon", 923. (u.uz.dlevel < 0) ? "passed away" : ends[how]); 924. } else { 925. /* more conventional demise */ 926. const char *where = dungeons[u.uz.dnum].dname; 927. 928. if (Is_astralevel(&u.uz)) where = "The Astral Plane"; 929. Sprintf(pbuf, "You %s in %s", ends[how], where); 930. if (!In_endgame(&u.uz) && !Is_knox(&u.uz)) 931. Sprintf(eos(pbuf), " on dungeon level %d", 932. In_quest(&u.uz) ? dunlev(&u.uz) : depth(&u.uz)); 933. } 934. 935. Sprintf(eos(pbuf), " with %ld point%s,", 936. u.urexp, plur(u.urexp)); 937. putstr(endwin, 0, pbuf); 938. } 939. 940. if (!done_stopprint) { 941. Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.", 942. umoney, plur(umoney), moves, plur(moves)); 943. putstr(endwin, 0, pbuf); 944. } 945. if (!done_stopprint) { 946. Sprintf(pbuf, 947. "You were level %d with a maximum of %d hit point%s when you %s.", 948. u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]); 949. putstr(endwin, 0, pbuf); 950. putstr(endwin, 0, ""); 951. } 952. if (!done_stopprint) 953. display_nhwindow(endwin, TRUE); 954. if (endwin != WIN_ERR) 955. destroy_nhwindow(endwin); 956. 957. /* "So when I die, the first thing I will see in Heaven is a 958. * score list?" */ 959. if (flags.toptenwin) { 960. topten(how); 961. if (have_windows) 962. exit_nhwindows((char *)0); 963. } else { 964. if (have_windows) 965. exit_nhwindows((char *)0); 966. topten(how); 967. } 968. 969. if(done_stopprint) { raw_print(""); raw_print(""); } 970. terminate(EXIT_SUCCESS); 971. } 972. 973. 974. void 975. container_contents(list, identified, all_containers) 976. struct obj *list; 977. boolean identified, all_containers; 978. { 979. register struct obj *box, *obj; 980. char buf[BUFSZ]; 981. 982. for (box = list; box; box = box->nobj) { 983. if (Is_container(box) || box->otyp == STATUE) { 984. if (box->otyp == BAG_OF_TRICKS) { 985. continue; /* wrong type of container */ 986. } else if (box->cobj) { 987. winid tmpwin = create_nhwindow(NHW_MENU); 988. Sprintf(buf, "Contents of %s:", the(xname(box))); 989. putstr(tmpwin, 0, buf); 990. putstr(tmpwin, 0, ""); 991. for (obj = box->cobj; obj; obj = obj->nobj) { 992. if (identified) { 993. makeknown(obj->otyp); 994. obj->known = obj->bknown = 995. obj->dknown = obj->rknown = 1; 996. } 997. putstr(tmpwin, 0, doname(obj)); 998. } 999. display_nhwindow(tmpwin, TRUE); 1000. destroy_nhwindow(tmpwin); 1001. if (all_containers) 1002. container_contents(box->cobj, identified, TRUE); 1003. } else { 1004. pline("%s empty.", Tobjnam(box, "are")); 1005. display_nhwindow(WIN_MESSAGE, FALSE); 1006. } 1007. } 1008. if (!all_containers) 1009. break; 1010. } 1011. } 1012. 1013. /* should be called with either EXIT_SUCCESS or EXIT_FAILURE */ 1014. void 1015. terminate(status) 1016. int status; 1017. { 1018. #ifdef MAC 1019. getreturn("to exit"); 1020. #endif 1021. /* don't bother to try to release memory if we're in panic mode, to 1022. avoid trouble in case that happens to be due to memory problems */ 1023. if (!program_state.panicking) { 1024. freedynamicdata(); 1025. dlb_cleanup(); 1026. } 1027. 1028. nethack_exit(status); 1029. } 1030. 1031. STATIC_OVL boolean 1032. list_vanquished(defquery, ask) 1033. char defquery; 1034. boolean ask; 1035. { 1036. register int i, lev; 1037. int ntypes = 0, max_lev = 0, nkilled; 1038. long total_killed = 0L; 1039. char c; 1040. winid klwin; 1041. char buf[BUFSZ]; 1042. 1043. /* get totals first */ 1044. for (i = LOW_PM; i < NUMMONS; i++) { 1045. if (mvitals[i].died) ntypes++; 1046. total_killed += (long)mvitals[i].died; 1047. if (mons[i].mlevel > max_lev) max_lev = mons[i].mlevel; 1048. } 1049. 1050. /* vanquished creatures list; 1051. * includes all dead monsters, not just those killed by the player 1052. */ 1053. if (ntypes != 0) { 1054. c = ask ? yn_function("Do you want an account of creatures vanquished?", 1055. ynqchars, defquery) : defquery; 1056. if (c == 'q') done_stopprint++; 1057. if (c == 'y') { 1058. klwin = create_nhwindow(NHW_MENU); 1059. putstr(klwin, 0, "Vanquished creatures:"); 1060. putstr(klwin, 0, ""); 1061. 1062. /* countdown by monster "toughness" */ 1063. for (lev = max_lev; lev >= 0; lev--) 1064. for (i = LOW_PM; i < NUMMONS; i++) 1065. if (mons[i].mlevel == lev && (nkilled = mvitals[i].died) > 0) { 1066. if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) { 1067. Sprintf(buf, "%s%s", 1068. !type_is_pname(&mons[i]) ? "The " : "", 1069. mons[i].mname); 1070. if (nkilled > 1) { 1071. switch (nkilled) { 1072. case 2: Sprintf(eos(buf)," (twice)"); break; 1073. case 3: Sprintf(eos(buf)," (thrice)"); break; 1074. default: Sprintf(eos(buf)," (%d time%s)", 1075. nkilled, plur(nkilled)); 1076. break; 1077. } 1078. } 1079. } else { 1080. /* trolls or undead might have come back, 1081. but we don't keep track of that */ 1082. if (nkilled == 1) 1083. Strcpy(buf, an(mons[i].mname)); 1084. else 1085. Sprintf(buf, "%d %s", 1086. nkilled, makeplural(mons[i].mname)); 1087. } 1088. putstr(klwin, 0, buf); 1089. } 1090. /* 1091. * if (Hallucination) 1092. * putstr(klwin, 0, "and a partridge in a pear tree"); 1093. */ 1094. if (ntypes > 1) { 1095. putstr(klwin, 0, ""); 1096. Sprintf(buf, "%ld creatures vanquished.", total_killed); 1097. putstr(klwin, 0, buf); 1098. } 1099. display_nhwindow(klwin, TRUE); 1100. destroy_nhwindow(klwin); 1101. } 1102. } 1103. return (boolean) (total_killed); 1104. } 1105. 1106. int 1107. dolistvanq() 1108. { 1109. if (!list_vanquished('y', FALSE)) 1110. pline("No monsters have yet been killed."); 1111. return(0); 1112. } 1113. 1114. /* number of monster species which have been genocided */ 1115. int 1116. num_genocides() 1117. { 1118. int i, n = 0; 1119. 1120. for (i = LOW_PM; i < NUMMONS; ++i) 1121. if (mvitals[i].mvflags & G_GENOD) ++n; 1122. 1123. return n; 1124. } 1125. 1126. STATIC_OVL void 1127. list_genocided(defquery, ask) 1128. char defquery; 1129. boolean ask; 1130. { 1131. register int i; 1132. int ngenocided; 1133. char c; 1134. winid klwin; 1135. char buf[BUFSZ]; 1136. 1137. ngenocided = num_genocides(); 1138. 1139. /* genocided species list */ 1140. if (ngenocided != 0) { 1141. c = ask ? yn_function("Do you want a list of species genocided?", 1142. ynqchars, defquery) : defquery; 1143. if (c == 'q') done_stopprint++; 1144. if (c == 'y') { 1145. klwin = create_nhwindow(NHW_MENU); 1146. putstr(klwin, 0, "Genocided species:"); 1147. putstr(klwin, 0, ""); 1148. 1149. for (i = LOW_PM; i < NUMMONS; i++) 1150. if (mvitals[i].mvflags & G_GENOD) { 1151. if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) 1152. Sprintf(buf, "%s%s", 1153. !type_is_pname(&mons[i]) ? "" : "the ", 1154. mons[i].mname); 1155. else 1156. Strcpy(buf, makeplural(mons[i].mname)); 1157. putstr(klwin, 0, buf); 1158. } 1159. 1160. putstr(klwin, 0, ""); 1161. Sprintf(buf, "%d species genocided.", ngenocided); 1162. putstr(klwin, 0, buf); 1163. 1164. display_nhwindow(klwin, TRUE); 1165. destroy_nhwindow(klwin); 1166. } 1167. } 1168. } 1169. 1170. /*end.c*/