Source:NetHack 3.4.0/end.c

Below is the full text to end.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/end.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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