Source:End.c

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. 1.   /*	SCCS Id: @(#)end.c	3.4	2003/03/10	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.

5.   #define NEED_VARARGS	/* comment line for pre-compiled headers */ 6.    7.    #include "hack.h"  8.    #include "eshk.h"  9.    #ifndef NO_SIGNAL 10.  #include   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.   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.   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.   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.   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.  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_  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.  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_printing */ 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.   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.   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.   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.   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.   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.   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.   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.   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.   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.   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.  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.  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*/