Difference between revisions of "Source:NetHack 3.4.3/src/end.c"

From NetHackWiki
Jump to navigation Jump to search
(Automated source code upload)
 
m (Add headers.)
Line 1: Line 1:
 +
Below is the full text to src/end.c from NetHack 3.4.3. To link to a particular line, write [[end.c#line123|<nowiki>[[end.c#line123]]</nowiki>]], for example.
 +
 +
== Top of file ==
  
Below is the full text to src/end.c from NetHack 3.4.3. To link to a particular line, write [[end.c#line123|<nowiki>[[end.c#line123]]</nowiki>]], for example.
 
 
  <span id="line1">1.    /* SCCS Id: @(#)end.c 3.4 2003/03/10 */</span>
 
  <span id="line1">1.    /* SCCS Id: @(#)end.c 3.4 2003/03/10 */</span>
 
  <span id="line2">2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */</span>
 
  <span id="line2">2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */</span>
Line 92: Line 94:
 
  <span id="line87">87.  extern const char * const killed_by_prefix[]; /* from topten.c */</span>
 
  <span id="line87">87.  extern const char * const killed_by_prefix[]; /* from topten.c */</span>
 
  <span id="line88">88.  </span>
 
  <span id="line88">88.  </span>
 +
 +
== done1 ==
 +
 
  <span id="line89">89.  /*ARGSUSED*/</span>
 
  <span id="line89">89.  /*ARGSUSED*/</span>
 
  <span id="line90">90.  void</span>
 
  <span id="line90">90.  void</span>
Line 114: Line 119:
 
  <span id="line109">109.  </span>
 
  <span id="line109">109.  </span>
 
  <span id="line110">110.  </span>
 
  <span id="line110">110.  </span>
 +
 +
== done2 ==
 +
 
  <span id="line111">111.  /* "#quit" command or keyboard interrupt */</span>
 
  <span id="line111">111.  /* "#quit" command or keyboard interrupt */</span>
 
  <span id="line112">112.  int</span>
 
  <span id="line112">112.  int</span>
Line 157: Line 165:
 
  <span id="line152">152.  }</span>
 
  <span id="line152">152.  }</span>
 
  <span id="line153">153.  </span>
 
  <span id="line153">153.  </span>
 +
 +
== done_intr ==
 +
 
  <span id="line154">154.  #ifndef NO_SIGNAL</span>
 
  <span id="line154">154.  #ifndef NO_SIGNAL</span>
 
  <span id="line155">155.  /*ARGSUSED*/</span>
 
  <span id="line155">155.  /*ARGSUSED*/</span>
Line 171: Line 182:
 
  <span id="line166">166.  }</span>
 
  <span id="line166">166.  }</span>
 
  <span id="line167">167.  </span>
 
  <span id="line167">167.  </span>
 +
 +
== done_hangup ==
 +
 
  <span id="line168">168.  # if defined(UNIX) || defined(VMS) || defined(__EMX__)</span>
 
  <span id="line168">168.  # if defined(UNIX) || defined(VMS) || defined(__EMX__)</span>
 
  <span id="line169">169.  static void</span>
 
  <span id="line169">169.  static void</span>
Line 184: Line 198:
 
  <span id="line179">179.  #endif /* NO_SIGNAL */</span>
 
  <span id="line179">179.  #endif /* NO_SIGNAL */</span>
 
  <span id="line180">180.  </span>
 
  <span id="line180">180.  </span>
 +
 +
== done_in_by ==
 +
 
  <span id="line181">181.  void</span>
 
  <span id="line181">181.  void</span>
 
  <span id="line182">182.  done_in_by(mtmp)</span>
 
  <span id="line182">182.  done_in_by(mtmp)</span>
Line 254: Line 271:
 
  <span id="line249">249.  #endif</span>
 
  <span id="line249">249.  #endif</span>
 
  <span id="line250">250.  </span>
 
  <span id="line250">250.  </span>
 +
 +
== panic ==
 +
 
  <span id="line251">251.  /*VARARGS1*/</span>
 
  <span id="line251">251.  /*VARARGS1*/</span>
 
  <span id="line252">252.  void</span>
 
  <span id="line252">252.  void</span>
Line 315: Line 335:
 
  <span id="line310">310.  }</span>
 
  <span id="line310">310.  }</span>
 
  <span id="line311">311.  </span>
 
  <span id="line311">311.  </span>
 +
 +
== should_query_disclose_option ==
 +
 
  <span id="line312">312.  STATIC_OVL boolean</span>
 
  <span id="line312">312.  STATIC_OVL boolean</span>
 
  <span id="line313">313.  should_query_disclose_option(category, defquery)</span>
 
  <span id="line313">313.  should_query_disclose_option(category, defquery)</span>
Line 353: Line 376:
 
  <span id="line348">348.  }</span>
 
  <span id="line348">348.  }</span>
 
  <span id="line349">349.  </span>
 
  <span id="line349">349.  </span>
 +
 +
== disclose ==
 +
 
  <span id="line350">350.  STATIC_OVL void</span>
 
  <span id="line350">350.  STATIC_OVL void</span>
 
  <span id="line351">351.  disclose(how,taken)</span>
 
  <span id="line351">351.  disclose(how,taken)</span>
Line 413: Line 439:
 
  <span id="line408">408.  }</span>
 
  <span id="line408">408.  }</span>
 
  <span id="line409">409.  </span>
 
  <span id="line409">409.  </span>
 +
 +
== savelife ==
 +
 
  <span id="line410">410.  /* try to get the player back in a viable state after being killed */</span>
 
  <span id="line410">410.  /* try to get the player back in a viable state after being killed */</span>
 
  <span id="line411">411.  STATIC_OVL void</span>
 
  <span id="line411">411.  STATIC_OVL void</span>
Line 440: Line 469:
 
  <span id="line435">435.  }</span>
 
  <span id="line435">435.  }</span>
 
  <span id="line436">436.  </span>
 
  <span id="line436">436.  </span>
 +
 +
== get_valuables ==
 +
 
  <span id="line437">437.  /*</span>
 
  <span id="line437">437.  /*</span>
 
  <span id="line438">438.  * Get valuables from the given list.  Revised code: the list always remains</span>
 
  <span id="line438">438.  * Get valuables from the given list.  Revised code: the list always remains</span>
Line 473: Line 505:
 
  <span id="line468">468.  }</span>
 
  <span id="line468">468.  }</span>
 
  <span id="line469">469.  </span>
 
  <span id="line469">469.  </span>
 +
 +
== sort_valuables ==
 +
 
  <span id="line470">470.  /*</span>
 
  <span id="line470">470.  /*</span>
 
  <span id="line471">471.  *  Sort collected valuables, most frequent to least.  We could just</span>
 
  <span id="line471">471.  *  Sort collected valuables, most frequent to least.  We could just</span>
Line 499: Line 534:
 
  <span id="line494">494.  }</span>
 
  <span id="line494">494.  }</span>
 
  <span id="line495">495.  </span>
 
  <span id="line495">495.  </span>
 +
 +
== artifact_score ==
 +
 
  <span id="line496">496.  /* called twice; first to calculate total, then to list relevant items */</span>
 
  <span id="line496">496.  /* called twice; first to calculate total, then to list relevant items */</span>
 
  <span id="line497">497.  STATIC_OVL void</span>
 
  <span id="line497">497.  STATIC_OVL void</span>
Line 537: Line 575:
 
  <span id="line532">532.  }</span>
 
  <span id="line532">532.  }</span>
 
  <span id="line533">533.  </span>
 
  <span id="line533">533.  </span>
 +
 +
== done ==
 +
 
  <span id="line534">534.  /* Be careful not to call panic from here! */</span>
 
  <span id="line534">534.  /* Be careful not to call panic from here! */</span>
 
  <span id="line535">535.  void</span>
 
  <span id="line535">535.  void</span>
Line 921: Line 962:
 
  <span id="line916">916.  </span>
 
  <span id="line916">916.  </span>
 
  <span id="line917">917.  </span>
 
  <span id="line917">917.  </span>
 +
 +
== container_contents ==
 +
 
  <span id="line918">918.  void</span>
 
  <span id="line918">918.  void</span>
 
  <span id="line919">919.  container_contents(list, identified, all_containers)</span>
 
  <span id="line919">919.  container_contents(list, identified, all_containers)</span>
Line 961: Line 1,005:
 
  <span id="line956">956.  </span>
 
  <span id="line956">956.  </span>
 
  <span id="line957">957.  </span>
 
  <span id="line957">957.  </span>
 +
 +
== terminate ==
 +
 
  <span id="line958">958.  /* should be called with either EXIT_SUCCESS or EXIT_FAILURE */</span>
 
  <span id="line958">958.  /* should be called with either EXIT_SUCCESS or EXIT_FAILURE */</span>
 
  <span id="line959">959.  void</span>
 
  <span id="line959">959.  void</span>
Line 979: Line 1,026:
 
  <span id="line974">974.  }</span>
 
  <span id="line974">974.  }</span>
 
  <span id="line975">975.  </span>
 
  <span id="line975">975.  </span>
 +
 +
== list_vanquished ==
 +
 
  <span id="line976">976.  STATIC_OVL void</span>
 
  <span id="line976">976.  STATIC_OVL void</span>
 
  <span id="line977">977.  list_vanquished(defquery, ask)</span>
 
  <span id="line977">977.  list_vanquished(defquery, ask)</span>
Line 1,053: Line 1,103:
 
  <span id="line1048">1048. }</span>
 
  <span id="line1048">1048. }</span>
 
  <span id="line1049">1049. </span>
 
  <span id="line1049">1049. </span>
 +
 +
== num_genocides ==
 +
 
  <span id="line1050">1050. /* number of monster species which have been genocided */</span>
 
  <span id="line1050">1050. /* number of monster species which have been genocided */</span>
 
  <span id="line1051">1051. int</span>
 
  <span id="line1051">1051. int</span>
Line 1,065: Line 1,118:
 
  <span id="line1060">1060. }</span>
 
  <span id="line1060">1060. }</span>
 
  <span id="line1061">1061. </span>
 
  <span id="line1061">1061. </span>
 +
 +
== list_genocided ==
 +
 
  <span id="line1062">1062. STATIC_OVL void</span>
 
  <span id="line1062">1062. STATIC_OVL void</span>
 
  <span id="line1063">1063. list_genocided(defquery, ask)</span>
 
  <span id="line1063">1063. list_genocided(defquery, ask)</span>

Revision as of 22:03, 23 August 2006

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.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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*/