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