Source:NetHack 3.2.0/end.c
(Redirected from NetHack 3.2.0/end.c)
Jump to navigation
Jump to search
Below is the full text to end.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: @(#)end.c 3.2 95/11/29 */ 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. STATIC_PTR void FDECL(done_intr, (int)); 15. static void FDECL(disclose,(int,BOOLEAN_P)); 16. static void FDECL(get_valuables, (struct obj *)); 17. static void FDECL(sort_valuables, (struct obj **,int)); 18. static void FDECL(savelife, (int)); 19. static void NDECL(list_vanquished); 20. static void NDECL(list_genocided); 21. #if defined(UNIX) || defined(VMS) 22. static void FDECL(done_hangup, (int)); 23. #endif 24. 25. 26. #define done_stopprint program_state.stopprint 27. 28. #ifdef AMIGA 29. void NDECL(clear_icon); 30. # define NH_abort() Abort(0) 31. #else 32. # ifdef SYSV 33. # define NH_abort() (void) abort() 34. # else 35. # define NH_abort() abort() 36. # endif 37. #endif 38. 39. /* 40. * The order of these needs to match the macros in hack.h. 41. */ 42. static NEARDATA const char *deaths[] = { /* the array of death */ 43. "died", "choked", "poisoned", "starvation", "drowning", 44. "burning", "dissolving under the heat and pressure", 45. "crushed", "turned to stone", "genocided", 46. "panic", "trickery", 47. "quit", "escaped", "ascended" 48. }; 49. 50. static NEARDATA const char *ends[] = { /* "when you..." */ 51. "died", "choked", "were poisoned", "starved", "drowned", 52. "burned", "dissolved in the lava", 53. "were crushed", "turned to stone", "were genocided", 54. "panicked", "were tricked", 55. "quit", "escaped", "ascended" 56. }; 57. 58. /* these probably ought to be generated by makedefs, like LAST_GEM */ 59. #define FIRST_GEM DILITHIUM_CRYSTAL 60. #define FIRST_AMULET AMULET_OF_ESP 61. #define LAST_AMULET AMULET_OF_YENDOR 62. 63. static struct obj *gems[LAST_GEM+1 - FIRST_GEM + 1], /* 1 extra for glass */ 64. *amulets[LAST_AMULET+1 - FIRST_AMULET]; 65. 66. static struct val_list { struct obj **list; int size; } valuables[] = { 67. { gems, sizeof gems / sizeof *gems }, 68. { amulets, sizeof amulets / sizeof *amulets }, 69. { 0, 0 } 70. }; 71. 72. /*ARGSUSED*/ 73. void 74. done1(sig_unused) /* called as signal() handler, so sent at least one arg */ 75. int sig_unused; 76. { 77. #ifndef NO_SIGNAL 78. (void) signal(SIGINT,SIG_IGN); 79. #endif 80. if(flags.ignintr) { 81. #ifndef NO_SIGNAL 82. (void) signal(SIGINT, (SIG_RET_TYPE) done1); 83. #endif 84. clear_nhwindow(WIN_MESSAGE); 85. curs_on_u(); 86. wait_synch(); 87. if(multi > 0) nomul(0); 88. } else { 89. (void)done2(); 90. } 91. } 92. 93. int 94. done2() 95. { 96. if(yn("Really quit?") == 'n') { 97. #ifndef NO_SIGNAL 98. (void) signal(SIGINT, (SIG_RET_TYPE) done1); 99. #endif 100. clear_nhwindow(WIN_MESSAGE); 101. curs_on_u(); 102. wait_synch(); 103. if(multi > 0) nomul(0); 104. if(multi == 0) { 105. u.uinvulnerable = FALSE; /* avoid ctrl-C bug -dlc */ 106. u.usleep = 0; 107. } 108. return 0; 109. } 110. #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE)) 111. if(wizard) { 112. int c; 113. # ifdef VMS 114. const char *tmp = "Enter debugger?"; 115. # else 116. # ifdef LATTICE 117. const char *tmp = "Create SnapShot?"; 118. # else 119. const char *tmp = "Dump core?"; 120. # endif 121. # endif 122. if ((c = ynq(tmp)) == 'y') { 123. (void) signal(SIGINT, (SIG_RET_TYPE) done1); 124. exit_nhwindows((char *)0); 125. NH_abort(); 126. } else if (c == 'q') done_stopprint++; 127. } 128. #endif 129. #ifndef LINT 130. done(QUIT); 131. #endif 132. return 0; 133. } 134. 135. /*ARGSUSED*/ 136. STATIC_PTR void 137. done_intr(sig_unused) /* called as signal() handler, so sent at least one arg */ 138. int sig_unused; 139. { 140. done_stopprint++; 141. #ifndef NO_SIGNAL 142. (void) signal(SIGINT, SIG_IGN); 143. # if defined(UNIX) || defined(VMS) 144. (void) signal(SIGQUIT, SIG_IGN); 145. # endif 146. #endif /* NO_SIGNAL */ 147. return; 148. } 149. 150. #if defined(UNIX) || defined(VMS) 151. static void 152. done_hangup(sig) /* signal() handler */ 153. int sig; 154. { 155. program_state.done_hup++; 156. (void)signal(SIGHUP, SIG_IGN); 157. done_intr(sig); 158. return; 159. } 160. #endif 161. 162. void 163. done_in_by(mtmp) 164. register struct monst *mtmp; 165. { 166. char buf[BUFSZ]; 167. boolean distorted = (boolean)(Hallucination && canspotmon(mtmp)); 168. 169. You("die..."); 170. mark_synch(); /* flush buffered screen output */ 171. buf[0] = '\0'; 172. if ((mtmp->data->geno & G_UNIQ) != 0) { 173. if (!type_is_pname(mtmp->data)) 174. Strcat(buf, "the "); 175. killer_format = KILLED_BY; 176. } 177. if (mtmp->minvis && !(mtmp->ispriest || mtmp->isminion)) 178. Strcat(buf, "invisible "); 179. if (distorted) 180. Strcat(buf, "hallucinogen-distorted "); 181. 182. if(mtmp->data == &mons[PM_GHOST]) { 183. register char *gn = (char *) mtmp->mextra; 184. if (!distorted && !mtmp->minvis && *gn) { 185. Strcat(buf, "the "); 186. killer_format = KILLED_BY; 187. } 188. Sprintf(eos(buf), (*gn ? "ghost of %s" : "ghost%s"), gn); 189. } else if(mtmp->isshk) { 190. Sprintf(eos(buf), "%s %s, the shopkeeper", 191. (mtmp->female ? "Ms." : "Mr."), shkname(mtmp)); 192. killer_format = KILLED_BY; 193. } else if (mtmp->ispriest || mtmp->isminion) { 194. killer = priestname(mtmp); 195. if (!strncmp(killer, "the ", 4)) Strcat(buf, killer+4); 196. else Strcat(buf, killer); 197. } else Strcat(buf, mtmp->data->mname); 198. if (mtmp->mnamelth) Sprintf(eos(buf), " called %s", NAME(mtmp)); 199. killer = buf; 200. if (mtmp->data->mlet == S_WRAITH) 201. u.ugrave_arise = PM_WRAITH; 202. else if (mtmp->data->mlet == S_MUMMY) 203. u.ugrave_arise = Role_is('E') ? PM_ELF_MUMMY : PM_HUMAN_MUMMY; 204. else if (mtmp->data->mlet == S_VAMPIRE && !Role_is('E')) 205. u.ugrave_arise = PM_VAMPIRE; 206. if (u.ugrave_arise >= LOW_PM && 207. (mvitals[u.ugrave_arise].mvflags & G_GENOD)) 208. u.ugrave_arise = NON_PM; 209. if (mtmp->data->mlet == S_COCKATRICE) 210. done(STONING); 211. else 212. done(DIED); 213. return; 214. } 215. 216. /*VARARGS1*/ 217. void 218. panic VA_DECL(const char *, str) 219. VA_START(str); 220. VA_INIT(str, char *); 221. 222. if (program_state.panicking++) 223. NH_abort(); /* avoid loops - this should never happen*/ 224. 225. if (flags.window_inited) { 226. raw_print("\r\nOops..."); 227. wait_synch(); /* make sure all pending output gets flushed */ 228. exit_nhwindows((char *)0); 229. flags.window_inited = 0; /* they're gone; force raw_print()ing */ 230. } 231. 232. raw_print(!program_state.something_worth_saving ? 233. "Program initialization has failed." : 234. "Suddenly, the dungeon collapses."); 235. #if defined(WIZARD) && !defined(MICRO) 236. if (!wizard) 237. raw_printf("Report error to \"%s\"%s.", 238. # ifdef WIZARD_NAME /*(KR1ED)*/ 239. WIZARD_NAME, 240. # else 241. WIZARD, 242. # endif 243. !program_state.something_worth_saving ? "" : 244. " and it may be possible to rebuild."); 245. if (program_state.something_worth_saving) { 246. set_error_savefile(); 247. (void) dosave0(); 248. } 249. #endif 250. { 251. char buf[BUFSZ]; 252. Vsprintf(buf,str,VA_ARGS); 253. raw_print(buf); 254. } 255. #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE)) 256. if (wizard) 257. NH_abort(); /* generate core dump */ 258. #endif 259. VA_END(); 260. done(PANICKED); 261. } 262. 263. static void 264. disclose(how,taken) 265. int how; 266. boolean taken; 267. { 268. char c; 269. char qbuf[QBUFSZ]; 270. 271. if (invent && !done_stopprint && 272. (!flags.end_disclose[0] || index(flags.end_disclose, 'i'))) { 273. if(taken) 274. Sprintf(qbuf,"Do you want to see what you had when you %s?", 275. (how == QUIT) ? "quit" : "died"); 276. else 277. Strcpy(qbuf,"Do you want your possessions identified?"); 278. if ((c = yn_function(qbuf, ynqchars, 'y')) == 'y') { 279. /* New dump format by maartenj@cs.vu.nl */ 280. struct obj *obj; 281. 282. for (obj = invent; obj; obj = obj->nobj) { 283. makeknown(obj->otyp); 284. obj->known = obj->bknown = obj->dknown = obj->rknown = 1; 285. } 286. (void) display_inventory((char *)0, TRUE); 287. container_contents(invent, TRUE, TRUE); 288. } 289. if (c == 'q') done_stopprint++; 290. } 291. 292. if (!done_stopprint && 293. (!flags.end_disclose[0] || index(flags.end_disclose, 'a'))) { 294. c = yn_function("Do you want to see your attributes?",ynqchars,'y'); 295. if (c == 'y') enlightenment(how >= PANICKED ? 1 : 2); /* final */ 296. if (c == 'q') done_stopprint++; 297. } 298. 299. if (!done_stopprint && 300. (!flags.end_disclose[0] || index(flags.end_disclose, 'v'))) { 301. list_vanquished(); 302. } 303. 304. if (!done_stopprint && 305. (!flags.end_disclose[0] || index(flags.end_disclose, 'g'))) { 306. list_genocided(); 307. } 308. } 309. 310. /* try to get the player back in a viable state after being killed */ 311. static void 312. savelife(how) 313. int how; 314. { 315. u.uswldtim = 0; 316. u.uhp = u.uhpmax; 317. if (u.uhunger < 500) { 318. u.uhunger = 500; 319. newuhs(FALSE); 320. } 321. if (how == CHOKING) init_uhunger(); 322. nomovemsg = "You survived that attempt on your life."; 323. flags.move = 0; 324. if(multi > 0) multi = 0; else multi = -1; 325. if(u.utrap && u.utraptype == TT_LAVA) u.utrap = 0; 326. flags.botl = 1; 327. u.ugrave_arise = NON_PM; 328. curs_on_u(); 329. } 330. 331. /* 332. * Get valuables from the given list. NOTE: The list is destroyed as it is 333. * processed, so don't expect to use it again! [Revised code: the list 334. * remains intact, but object quanties for some elements are altered.] 335. */ 336. static void 337. get_valuables(list) 338. struct obj *list; /* inventory or container contents */ 339. { 340. register struct obj *obj; 341. register int i; 342. 343. /* find amulets and gems; artifact amulets are treated as ordinary ones */ 344. for (obj = list; obj; obj = obj->nobj) 345. if (Has_contents(obj)) { 346. get_valuables(obj->cobj); 347. } else if (obj->oclass == AMULET_CLASS) { 348. i = obj->otyp - FIRST_AMULET; 349. if (!amulets[i]) amulets[i] = obj; 350. else amulets[i]->quan += obj->quan; /*(always adds one)*/ 351. } else if (obj->oclass == GEM_CLASS && obj->otyp < LUCKSTONE) { 352. i = min(obj->otyp, LAST_GEM + 1) - FIRST_GEM; 353. if (!gems[i]) gems[i] = obj; 354. else gems[i]->quan += obj->quan; 355. } 356. return; 357. } 358. 359. /* 360. * Sort collected valuables, most frequent to least. We could just 361. * as easily use qsort, but we don't care about efficiency here. 362. */ 363. static void 364. sort_valuables(list, size) 365. struct obj *list[]; 366. int size; /* max value is less than 20 */ 367. { 368. register int i, j; 369. register struct obj *obj; 370. 371. /* move greater quantities to the front of the list */ 372. for (i = 1; i < size; i++) { 373. if ((obj = list[i]) == 0) continue; /* empty slot */ 374. for (j = i; j > 0; --j) 375. if (list[j-1] && list[j-1]->quan >= obj->quan) break; 376. else list[j] = list[j-1]; 377. list[j] = obj; 378. } 379. return; 380. } 381. 382. /* Be careful not to call panic from here! */ 383. void 384. done(how) 385. int how; 386. { 387. boolean taken; 388. char kilbuf[BUFSZ], pbuf[BUFSZ]; 389. winid endwin = WIN_ERR; 390. boolean bones_ok, have_windows = flags.window_inited; 391. 392. /* kilbuf: used to copy killer in case it comes from something like 393. * xname(), which would otherwise get overwritten when we call 394. * xname() when listing possessions 395. * pbuf: holds Sprintf'd output for raw_print and putstr 396. */ 397. if (how == ASCENDED) 398. killer_format = NO_KILLER_PREFIX; 399. /* Avoid killed by "a" burning or "a" starvation */ 400. if (!killer && (how == STARVING || how == BURNING)) 401. killer_format = KILLED_BY; 402. Strcpy(kilbuf, (!killer || how >= PANICKED ? deaths[how] : killer)); 403. killer = kilbuf; 404. #ifdef WIZARD 405. if (wizard && how == TRICKED) { 406. You("are a very tricky wizard, it seems."); 407. return; 408. } 409. #endif 410. if (how < PANICKED) u.umortality++; 411. if (Lifesaved && how <= GENOCIDED) { 412. pline("But wait..."); 413. makeknown(AMULET_OF_LIFE_SAVING); 414. Your("medallion %s!", 415. !Blind ? "begins to glow" : "feels warm"); 416. if (how == CHOKING) You("vomit ..."); 417. You_feel("much better!"); 418. pline_The("medallion crumbles to dust!"); 419. useup(uamul); 420. 421. (void) adjattrib(A_CON, -1, TRUE); 422. if(u.uhpmax <= 0) u.uhpmax = 10; /* arbitrary */ 423. savelife(how); 424. if (how == GENOCIDED) 425. pline("Unfortunately you are still genocided..."); 426. else { 427. killer = 0; 428. killer_format = 0; 429. return; 430. } 431. } 432. if ((wizard || discover) && how <= GENOCIDED) { 433. if(yn("Die?") == 'y') goto die; 434. pline("OK, so you don't %s.", 435. (how == CHOKING) ? "choke" : "die"); 436. if(u.uhpmax <= 0) u.uhpmax = u.ulevel * 8; /* arbitrary */ 437. savelife(how); 438. killer = 0; 439. killer_format = 0; 440. return; 441. } 442. 443. /* Sometimes you die on the first move. Life's not fair. 444. * On those rare occasions you get hosed immediately, go out 445. * smiling... :-) -3. 446. */ 447. if (moves <= 1 && how < PANICKED) 448. /* You die... --More-- */ 449. pline("Do not pass go. Do not collect 200 zorkmids."); 450. 451. die: 452. if (have_windows) wait_synch(); /* flush screen output */ 453. #ifndef NO_SIGNAL 454. (void) signal(SIGINT, (SIG_RET_TYPE) done_intr); 455. # if defined(UNIX) || defined(VMS) 456. (void) signal(SIGQUIT, (SIG_RET_TYPE) done_intr); 457. (void) signal(SIGHUP, (SIG_RET_TYPE) done_hangup); 458. # endif 459. #endif /* NO_SIGNAL */ 460. 461. bones_ok = (how < GENOCIDED) && can_make_bones(); 462. 463. if (bones_ok && u.ugrave_arise < LOW_PM) { 464. if (how == BURNING) /* corpse gets burnt up too */ 465. u.ugrave_arise = (NON_PM - 2); /* leave no corpse */ 466. else if (how == STONING) 467. u.ugrave_arise = (NON_PM - 1); /* statue instead of corpse */ 468. else if (u.ugrave_arise == NON_PM) 469. (void) mk_named_object(CORPSE, Upolyd ? uasmon : player_mon(), 470. u.ux, u.uy, plname); 471. } 472. 473. if (how == QUIT) { 474. killer_format = NO_KILLER_PREFIX; 475. if (u.uhp < 1) { 476. how = DIED; 477. /* note that killer is pointing at kilbuf */ 478. Strcpy(kilbuf, "quit while already on Charon's boat"); 479. } 480. } 481. if (how == ESCAPED || how == PANICKED) 482. killer_format = NO_KILLER_PREFIX; 483. 484. if (how != PANICKED) { 485. /* these affect score and/or bones, but avoid them during panic */ 486. taken = paybill(how != QUIT); 487. paygd(); 488. clearpriests(); 489. } else taken = FALSE; /* lint; assert( !bones_ok ); */ 490. 491. clearlocks(); 492. #ifdef AMIGA 493. clear_icon(); 494. #endif 495. if (have_windows) display_nhwindow(WIN_MESSAGE, FALSE); 496. 497. if (strcmp(flags.end_disclose, "none") && how != PANICKED) 498. disclose(how, taken); 499. /* finish_paybill should be called after disclosure but before bones */ 500. if (bones_ok && taken) finish_paybill(); 501. 502. /* calculate score, before creating bones [container gold] */ 503. { 504. long tmp; 505. int deepest = deepest_lev_reached(FALSE); 506. 507. u.ugold += hidden_gold(); /* accumulate gold from containers */ 508. tmp = u.ugold - u.ugold0; 509. if (tmp < 0L) 510. tmp = 0L; 511. if (how < PANICKED) 512. tmp -= tmp / 10L; 513. u.urexp += tmp; 514. u.urexp += 50L * (long)(deepest - 1); 515. if (deepest > 20) 516. u.urexp += 1000L * (long)((deepest > 30) ? 10 : deepest - 20); 517. if (how == ASCENDED) u.urexp *= 2L; 518. } 519. 520. if (bones_ok) { 521. #ifdef WIZARD 522. if (!wizard || yn("Save bones?") == 'y') 523. #endif 524. savebones(); 525. } 526. 527. /* clean up unneeded windows */ 528. if (have_windows) { 529. destroy_nhwindow(WIN_MAP); 530. destroy_nhwindow(WIN_STATUS); 531. destroy_nhwindow(WIN_MESSAGE); 532. 533. if(!done_stopprint || flags.tombstone) 534. endwin = create_nhwindow(NHW_TEXT); 535. 536. if(how < GENOCIDED && flags.tombstone) outrip(endwin, how); 537. } else 538. done_stopprint = 1; /* just avoid any more output */ 539. 540. /* changing kilbuf really changes killer. we do it this way because 541. killer is declared a (const char *) 542. */ 543. if (u.uhave.amulet) Strcat(kilbuf, " (with the Amulet)"); 544. if (!done_stopprint) { 545. Sprintf(pbuf, "%s %s the %s...", 546. Role_is('S') ? "Sayonara" : 547. #ifdef TOURIST 548. Role_is('T') ? "Aloha" : 549. #endif 550. "Goodbye", plname, 551. how != ASCENDED ? (const char *) pl_character : 552. (const char *) (flags.female ? "Demigoddess" : "Demigod")); 553. putstr(endwin, 0, pbuf); 554. putstr(endwin, 0, ""); 555. } 556. 557. if (how == ESCAPED || how == ASCENDED) { 558. register struct monst *mtmp; 559. register struct obj *otmp; 560. register struct val_list *val; 561. register int i; 562. 563. /* 564. * Collecting valuables renders `invent' invalid, but from 565. * this point on, it won't be used again. 566. */ 567. for (val = valuables; val->list; val++) 568. for (i = 0; i < val->size; i++) val->list[i] = (struct obj *)0; 569. get_valuables(invent); 570. 571. /* add points for collected valuables */ 572. for (val = valuables; val->list; val++) 573. for (i = 0; i < val->size; i++) 574. if ((otmp = val->list[i]) != 0) 575. u.urexp += otmp->quan 576. * (long)objects[otmp->otyp].oc_cost; 577. 578. keepdogs(TRUE); 579. viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */ 580. mtmp = mydogs; 581. if (!done_stopprint) Strcpy(pbuf, "You"); 582. if (mtmp) { 583. while (mtmp) { 584. if (!done_stopprint) 585. Sprintf(eos(pbuf), " and %s", mon_nam(mtmp)); 586. if (mtmp->mtame) 587. u.urexp += mtmp->mhp; 588. mtmp = mtmp->nmon; 589. } 590. if (!done_stopprint) putstr(endwin, 0, pbuf); 591. pbuf[0] = '\0'; 592. } else { 593. if (!done_stopprint) Strcat(pbuf, " "); 594. } 595. if (!done_stopprint) { 596. Sprintf(eos(pbuf), "%s with %ld point%s,", 597. how==ASCENDED ? "went to your reward" : 598. "escaped from the dungeon", 599. u.urexp, plur(u.urexp)); 600. putstr(endwin, 0, pbuf); 601. } 602. 603. /* list valuables here */ 604. for (val = valuables; val->list; val++) { 605. sort_valuables(val->list, val->size); 606. for (i = 0; i < val->size && !done_stopprint; i++) { 607. if ((otmp = val->list[i]) == 0) continue; 608. if (otmp->oclass != GEM_CLASS || otmp->otyp <= LAST_GEM) { 609. makeknown(otmp->otyp); 610. otmp->known = 1; /* for fake amulets */ 611. otmp->onamelth = 0; 612. Sprintf(pbuf, "%8ld %s (worth %ld zorkmids),", 613. otmp->quan, xname(otmp), 614. otmp->quan * (long)objects[otmp->otyp].oc_cost); 615. } else { 616. Sprintf(pbuf, 617. "%8ld worthless piece%s of colored glass,", 618. otmp->quan, plur(otmp->quan)); 619. } 620. putstr(endwin, 0, pbuf); 621. } 622. } 623. 624. } else if (!done_stopprint) { 625. /* did not escape or ascend */ 626. const char *where = dungeons[u.uz.dnum].dname; 627. if (Is_astralevel(&u.uz)) where = "The Astral Plane"; 628. Sprintf(pbuf, "You %s in %s", ends[how], where); 629. if (!In_endgame(&u.uz) && !Is_knox(&u.uz)) 630. Sprintf(eos(pbuf), " on dungeon level %d", 631. In_quest(&u.uz) ? dunlev(&u.uz) : depth(&u.uz)); 632. Sprintf(eos(pbuf), " with %ld point%s,", 633. u.urexp, plur(u.urexp)); 634. putstr(endwin, 0, pbuf); 635. } 636. 637. if (!done_stopprint) { 638. Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.", 639. u.ugold, plur(u.ugold), moves, plur(moves)); 640. putstr(endwin, 0, pbuf); 641. } 642. if (!done_stopprint) { 643. Sprintf(pbuf, 644. "You were level %d with a maximum of %d hit point%s when you %s.", 645. u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]); 646. putstr(endwin, 0, pbuf); 647. putstr(endwin, 0, ""); 648. } 649. if (!done_stopprint) 650. display_nhwindow(endwin, TRUE); 651. if (endwin != WIN_ERR) 652. destroy_nhwindow(endwin); 653. 654. /* "So when I die, the first thing I will see in Heaven is a 655. * score list?" */ 656. if (flags.toptenwin) { 657. topten(how); 658. if (have_windows) 659. exit_nhwindows((char *)0); 660. } else { 661. if (have_windows) 662. exit_nhwindows((char *)0); 663. topten(how); 664. } 665. 666. if(done_stopprint) { raw_print(""); raw_print(""); } 667. terminate(EXIT_SUCCESS); 668. } 669. 670. 671. void 672. container_contents(list, identified, all_containers) 673. struct obj *list; 674. boolean identified, all_containers; 675. { 676. register struct obj *box, *obj; 677. char buf[BUFSZ]; 678. 679. for (box = list; box; box = box->nobj) { 680. if (Is_container(box) && box->otyp != BAG_OF_TRICKS) { 681. if (box->cobj) { 682. winid tmpwin = create_nhwindow(NHW_MENU); 683. Sprintf(buf, "Contents of %s:", the(xname(box))); 684. putstr(tmpwin, 0, buf); 685. putstr(tmpwin, 0, ""); 686. for (obj = box->cobj; obj; obj = obj->nobj) { 687. if (identified) { 688. makeknown(obj->otyp); 689. obj->known = obj->bknown = 690. obj->dknown = obj->rknown = 1; 691. } 692. putstr(tmpwin, 0, doname(obj)); 693. } 694. display_nhwindow(tmpwin, TRUE); 695. destroy_nhwindow(tmpwin); 696. if (all_containers) 697. container_contents(box->cobj, identified, TRUE); 698. } else { 699. pline("%s is empty.", The(xname(box))); 700. display_nhwindow(WIN_MESSAGE, FALSE); 701. } 702. } 703. if (!all_containers) 704. break; 705. } 706. } 707. 708. 709. /* should be called with either EXIT_SUCCESS or EXIT_FAILURE */ 710. void 711. terminate(status) 712. int status; 713. { 714. #ifdef MAC 715. getreturn("to exit"); 716. #endif 717. 718. /* don't bother to try to release memory if we're in panic mode, to 719. avoid trouble in case that happens to be due to memory problems */ 720. if (!program_state.panicking) { 721. freedynamicdata(); 722. dlb_cleanup(); 723. } 724. 725. exit(status); 726. } 727. 728. static void 729. list_vanquished() 730. { 731. register int i, lev; 732. int ntypes = 0, max_lev = 0, nkilled; 733. long total_killed = 0L; 734. char c; 735. winid klwin; 736. char buf[BUFSZ]; 737. 738. /* get totals first */ 739. for (i = LOW_PM; i < NUMMONS; i++) { 740. if (mvitals[i].died) ntypes++; 741. total_killed += (long)mvitals[i].died; 742. if (mons[i].mlevel > max_lev) max_lev = mons[i].mlevel; 743. } 744. 745. /* vanquished creatures list; 746. * includes all dead monsters, not just those killed by the player 747. */ 748. if (ntypes != 0) { 749. c = yn_function("Do you want an account of creatures vanquished?", 750. ynqchars, 'n'); 751. if (c == 'q') done_stopprint++; 752. if (c == 'y') { 753. klwin = create_nhwindow(NHW_MENU); 754. putstr(klwin, 0, "Vanquished creatures:"); 755. putstr(klwin, 0, ""); 756. 757. /* countdown by monster "toughness" */ 758. for (lev = max_lev; lev >= 0; lev--) 759. for (i = LOW_PM; i < NUMMONS; i++) 760. if (mons[i].mlevel == lev && (nkilled = mvitals[i].died) > 0) { 761. if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) { 762. Sprintf(buf, "%s%s", 763. !type_is_pname(&mons[i]) ? "The " : "", 764. mons[i].mname); 765. if (nkilled > 1) 766. Sprintf(eos(buf)," (%d time%s)", 767. nkilled, plur(nkilled)); 768. } else { 769. /* trolls or undead might have come back, 770. but we don't keep track of that */ 771. if (nkilled == 1) 772. Strcpy(buf, an(mons[i].mname)); 773. else 774. Sprintf(buf, "%d %s", 775. nkilled, makeplural(mons[i].mname)); 776. } 777. putstr(klwin, 0, buf); 778. } 779. /* 780. * if (Hallucination) 781. * putstr(klwin, 0, "and a partridge in a pear tree"); 782. */ 783. if (ntypes > 1) { 784. putstr(klwin, 0, ""); 785. Sprintf(buf, "%ld creatures vanquished.", total_killed); 786. putstr(klwin, 0, buf); 787. } 788. display_nhwindow(klwin, TRUE); 789. destroy_nhwindow(klwin); 790. } 791. } 792. } 793. 794. static void 795. list_genocided() 796. { 797. register int i; 798. int ngenocided = 0; 799. char c; 800. winid klwin; 801. char buf[BUFSZ]; 802. 803. /* get totals first */ 804. for (i = LOW_PM; i < NUMMONS; i++) { 805. if (mvitals[i].mvflags & G_GENOD) ngenocided++; 806. } 807. 808. /* genocided species list */ 809. if (ngenocided != 0) { 810. c = yn_function("Do you want a list of species genocided?", 811. ynqchars, 'n'); 812. if (c == 'q') done_stopprint++; 813. if (c == 'y') { 814. klwin = create_nhwindow(NHW_MENU); 815. putstr(klwin, 0, "Genocided species:"); 816. putstr(klwin, 0, ""); 817. 818. for (i = LOW_PM; i < NUMMONS; i++) 819. if (mvitals[i].mvflags & G_GENOD) { 820. if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) 821. Sprintf(buf, "%s%s", 822. !type_is_pname(&mons[i]) ? "" : "the ", 823. mons[i].mname); 824. else 825. Strcpy(buf, makeplural(mons[i].mname)); 826. putstr(klwin, 0, buf); 827. } 828. 829. putstr(klwin, 0, ""); 830. Sprintf(buf, "%d species genocided.", ngenocided); 831. putstr(klwin, 0, buf); 832. 833. display_nhwindow(klwin, TRUE); 834. destroy_nhwindow(klwin); 835. } 836. } 837. } 838. 839. /*end.c*/