Wikihack
Advertisement

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

Top of file[]

1.    /*	SCCS Id: @(#)end.c	3.4	2003/03/10	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    #define NEED_VARARGS	/* comment line for pre-compiled headers */
6.    
7.    #include "hack.h"
8.    #include "eshk.h"
9.    #ifndef NO_SIGNAL
10.   #include <signal.h>
11.   #endif
12.   #include "dlb.h"
13.   
14.   	/* these probably ought to be generated by makedefs, like LAST_GEM */
15.   #define FIRST_GEM    DILITHIUM_CRYSTAL
16.   #define FIRST_AMULET AMULET_OF_ESP
17.   #define LAST_AMULET  AMULET_OF_YENDOR
18.    
19.   struct valuable_data { long count; int typ; };
20.   
21.   static struct valuable_data
22.   	gems[LAST_GEM+1 - FIRST_GEM + 1], /* 1 extra for glass */
23.   	amulets[LAST_AMULET+1 - FIRST_AMULET];
24.   
25.   static struct val_list { struct valuable_data *list; int size; } valuables[] = {
26.   	{ gems,    sizeof gems / sizeof *gems },
27.   	{ amulets, sizeof amulets / sizeof *amulets },
28.   	{ 0, 0 }
29.   };
30.   
31.   #ifndef NO_SIGNAL
32.   STATIC_PTR void FDECL(done_intr, (int));
33.   # if defined(UNIX) || defined(VMS) || defined (__EMX__)
34.   static void FDECL(done_hangup, (int));
35.   # endif
36.   #endif
37.   STATIC_DCL void FDECL(disclose,(int,BOOLEAN_P));
38.   STATIC_DCL void FDECL(get_valuables, (struct obj *));
39.   STATIC_DCL void FDECL(sort_valuables, (struct valuable_data *,int));
40.   STATIC_DCL void FDECL(artifact_score, (struct obj *,BOOLEAN_P,winid));
41.   STATIC_DCL void FDECL(savelife, (int));
42.   STATIC_DCL void FDECL(list_vanquished, (CHAR_P,BOOLEAN_P));
43.   STATIC_DCL void FDECL(list_genocided, (CHAR_P,BOOLEAN_P));
44.   STATIC_DCL boolean FDECL(should_query_disclose_option, (int,char *));
45.   
46.   #if defined(__BEOS__) || defined(MICRO) || defined(WIN32) || defined(OS2)
47.   extern void FDECL(nethack_exit,(int));
48.   #else
49.   #define nethack_exit exit
50.   #endif
51.   
52.   #define done_stopprint program_state.stopprint
53.   
54.   #ifdef AMIGA
55.   # define NH_abort()	Abort(0)
56.   #else
57.   # ifdef SYSV
58.   # define NH_abort()	(void) abort()
59.   # else
60.   #  ifdef WIN32
61.   # define NH_abort()	win32_abort()
62.   #  else
63.   # define NH_abort()	abort()
64.   #  endif
65.   # endif
66.   #endif
67.   
68.   /*
69.    * The order of these needs to match the macros in hack.h.
70.    */
71.   static NEARDATA const char *deaths[] = {		/* the array of death */
72.   	"died", "choked", "poisoned", "starvation", "drowning",
73.   	"burning", "dissolving under the heat and pressure",
74.   	"crushed", "turned to stone", "turned into slime",
75.   	"genocided", "panic", "trickery",
76.   	"quit", "escaped", "ascended"
77.   };
78.   
79.   static NEARDATA const char *ends[] = {		/* "when you..." */
80.   	"died", "choked", "were poisoned", "starved", "drowned",
81.   	"burned", "dissolved in the lava",
82.   	"were crushed", "turned to stone", "turned into slime",
83.   	"were genocided", "panicked", "were tricked",
84.   	"quit", "escaped", "ascended"
85.   };
86.   
87.   extern const char * const killed_by_prefix[];	/* from topten.c */
88.   

done1[]

89.   /*ARGSUSED*/
90.   void
91.   done1(sig_unused)   /* called as signal() handler, so sent at least one arg */
92.   int sig_unused;
93.   {
94.   #ifndef NO_SIGNAL
95.   	(void) signal(SIGINT,SIG_IGN);
96.   #endif
97.   	if(flags.ignintr) {
98.   #ifndef NO_SIGNAL
99.   		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
100.  #endif
101.  		clear_nhwindow(WIN_MESSAGE);
102.  		curs_on_u();
103.  		wait_synch();
104.  		if(multi > 0) nomul(0);
105.  	} else {
106.  		(void)done2();
107.  	}
108.  }
109.  
110.  

done2[]

111.  /* "#quit" command or keyboard interrupt */
112.  int
113.  done2()
114.  {
115.  	if(yn("Really quit?") == 'n') {
116.  #ifndef NO_SIGNAL
117.  		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
118.  #endif
119.  		clear_nhwindow(WIN_MESSAGE);
120.  		curs_on_u();
121.  		wait_synch();
122.  		if(multi > 0) nomul(0);
123.  		if(multi == 0) {
124.  		    u.uinvulnerable = FALSE;	/* avoid ctrl-C bug -dlc */
125.  		    u.usleep = 0;
126.  		}
127.  		return 0;
128.  	}
129.  #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE))
130.  	if(wizard) {
131.  	    int c;
132.  # ifdef VMS
133.  	    const char *tmp = "Enter debugger?";
134.  # else
135.  #  ifdef LATTICE
136.  	    const char *tmp = "Create SnapShot?";
137.  #  else
138.  	    const char *tmp = "Dump core?";
139.  #  endif
140.  # endif
141.  	    if ((c = ynq(tmp)) == 'y') {
142.  		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
143.  		exit_nhwindows((char *)0);
144.  		NH_abort();
145.  	    } else if (c == 'q') done_stopprint++;
146.  	}
147.  #endif
148.  #ifndef LINT
149.  	done(QUIT);
150.  #endif
151.  	return 0;
152.  }
153.  

done_intr[]

154.  #ifndef NO_SIGNAL
155.  /*ARGSUSED*/
156.  STATIC_PTR void
157.  done_intr(sig_unused) /* called as signal() handler, so sent at least one arg */
158.  int sig_unused;
159.  {
160.  	done_stopprint++;
161.  	(void) signal(SIGINT, SIG_IGN);
162.  # if defined(UNIX) || defined(VMS)
163.  	(void) signal(SIGQUIT, SIG_IGN);
164.  # endif
165.  	return;
166.  }
167.  

done_hangup[]

168.  # if defined(UNIX) || defined(VMS) || defined(__EMX__)
169.  static void
170.  done_hangup(sig)	/* signal() handler */
171.  int sig;
172.  {
173.  	program_state.done_hup++;
174.  	(void)signal(SIGHUP, SIG_IGN);
175.  	done_intr(sig);
176.  	return;
177.  }
178.  # endif
179.  #endif /* NO_SIGNAL */
180.  

done_in_by[]

181.  void
182.  done_in_by(mtmp)
183.  register struct monst *mtmp;
184.  {
185.  	char buf[BUFSZ];
186.  	boolean distorted = (boolean)(Hallucination && canspotmon(mtmp));
187.  
188.  	You("die...");
189.  	mark_synch();	/* flush buffered screen output */
190.  	buf[0] = '\0';
191.  	killer_format = KILLED_BY_AN;
192.  	/* "killed by the high priest of Crom" is okay, "killed by the high
193.  	   priest" alone isn't */
194.  	if ((mtmp->data->geno & G_UNIQ) != 0 && !(mtmp->data == &mons[PM_HIGH_PRIEST] && !mtmp->ispriest)) {
195.  	    if (!type_is_pname(mtmp->data))
196.  		Strcat(buf, "the ");
197.  	    killer_format = KILLED_BY;
198.  	}
199.  	/* _the_ <invisible> <distorted> ghost of Dudley */
200.  	if (mtmp->data == &mons[PM_GHOST] && mtmp->mnamelth) {
201.  		Strcat(buf, "the ");
202.  		killer_format = KILLED_BY;
203.  	}
204.  	if (mtmp->minvis)
205.  		Strcat(buf, "invisible ");
206.  	if (distorted)
207.  		Strcat(buf, "hallucinogen-distorted ");
208.  
209.  	if(mtmp->data == &mons[PM_GHOST]) {
210.  		Strcat(buf, "ghost");
211.  		if (mtmp->mnamelth) Sprintf(eos(buf), " of %s", NAME(mtmp));
212.  	} else if(mtmp->isshk) {
213.  		Sprintf(eos(buf), "%s %s, the shopkeeper",
214.  			(mtmp->female ? "Ms." : "Mr."), shkname(mtmp));
215.  		killer_format = KILLED_BY;
216.  	} else if (mtmp->ispriest || mtmp->isminion) {
217.  		/* m_monnam() suppresses "the" prefix plus "invisible", and
218.  		   it overrides the effect of Hallucination on priestname() */
219.  		killer = m_monnam(mtmp);
220.  		Strcat(buf, killer);
221.  	} else {
222.  		Strcat(buf, mtmp->data->mname);
223.  		if (mtmp->mnamelth)
224.  		    Sprintf(eos(buf), " called %s", NAME(mtmp));
225.  	}
226.  
227.  	if (multi) Strcat(buf, ", while helpless");
228.  	killer = buf;
229.  	if (mtmp->data->mlet == S_WRAITH)
230.  		u.ugrave_arise = PM_WRAITH;
231.  	else if (mtmp->data->mlet == S_MUMMY && urace.mummynum != NON_PM)
232.  		u.ugrave_arise = urace.mummynum;
233.  	else if (mtmp->data->mlet == S_VAMPIRE && Race_if(PM_HUMAN))
234.  		u.ugrave_arise = PM_VAMPIRE;
235.  	else if (mtmp->data == &mons[PM_GHOUL])
236.  		u.ugrave_arise = PM_GHOUL;
237.  	if (u.ugrave_arise >= LOW_PM &&
238.  				(mvitals[u.ugrave_arise].mvflags & G_GENOD))
239.  		u.ugrave_arise = NON_PM;
240.  	if (touch_petrifies(mtmp->data))
241.  		done(STONING);
242.  	else
243.  		done(DIED);
244.  	return;
245.  }
246.  
247.  #if defined(WIN32)
248.  #define NOTIFY_NETHACK_BUGS
249.  #endif
250.  

panic[]

251.  /*VARARGS1*/
252.  void
253.  panic VA_DECL(const char *, str)
254.  	VA_START(str);
255.  	VA_INIT(str, char *);
256.  
257.  	if (program_state.panicking++)
258.  	    NH_abort();	/* avoid loops - this should never happen*/
259.  
260.  	if (iflags.window_inited) {
261.  	    raw_print("\r\nOops...");
262.  	    wait_synch();	/* make sure all pending output gets flushed */
263.  	    exit_nhwindows((char *)0);
264.  	    iflags.window_inited = 0; /* they're gone; force raw_print()ing */
265.  	}
266.  
267.  	raw_print(program_state.gameover ?
268.  		  "Postgame wrapup disrupted." :
269.  		  !program_state.something_worth_saving ?
270.  		  "Program initialization has failed." :
271.  		  "Suddenly, the dungeon collapses.");
272.  #if defined(WIZARD) && !defined(MICRO)
273.  # if defined(NOTIFY_NETHACK_BUGS)
274.  	if (!wizard)
275.  	    raw_printf("Report the following error to \"%s\".",
276.  			"nethack-bugs@nethack.org");
277.  	else if (program_state.something_worth_saving)
278.  	    raw_print("\nError save file being written.\n");
279.  # else
280.  	if (!wizard)
281.  	    raw_printf("Report error to \"%s\"%s.",
282.  #  ifdef WIZARD_NAME	/*(KR1ED)*/
283.  			WIZARD_NAME,
284.  #  else
285.  			WIZARD,
286.  #  endif
287.  			!program_state.something_worth_saving ? "" :
288.  			" and it may be possible to rebuild.");
289.  # endif
290.  	if (program_state.something_worth_saving) {
291.  	    set_error_savefile();
292.  	    (void) dosave0();
293.  	}
294.  #endif
295.  	{
296.  	    char buf[BUFSZ];
297.  	    Vsprintf(buf,str,VA_ARGS);
298.  	    raw_print(buf);
299.  	    paniclog("panic", buf);
300.  	}
301.  #ifdef WIN32
302.  	interject(INTERJECT_PANIC);
303.  #endif
304.  #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE) || defined(WIN32))
305.  	if (wizard)
306.  	    NH_abort();	/* generate core dump */
307.  #endif
308.  	VA_END();
309.  	done(PANICKED);
310.  }
311.  

should_query_disclose_option[]

312.  STATIC_OVL boolean
313.  should_query_disclose_option(category, defquery)
314.  int category;
315.  char *defquery;
316.  {
317.      int idx;
318.      char *dop = index(disclosure_options, category);
319.  
320.      if (dop && defquery) {
321.  	idx = dop - disclosure_options;
322.  	if (idx < 0 || idx > (NUM_DISCLOSURE_OPTIONS - 1)) {
323.  	    impossible(
324.  		   "should_query_disclose_option: bad disclosure index %d %c",
325.  		       idx, category);
326.  	    *defquery = DISCLOSE_PROMPT_DEFAULT_YES;
327.  	    return TRUE;
328.  	}
329.  	if (flags.end_disclose[idx] == DISCLOSE_YES_WITHOUT_PROMPT) {
330.  	    *defquery = 'y';
331.  	    return FALSE;
332.  	} else if (flags.end_disclose[idx] == DISCLOSE_NO_WITHOUT_PROMPT) {
333.  	    *defquery = 'n';
334.  	    return FALSE;
335.  	} else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_YES) {
336.  	    *defquery = 'y';
337.  	    return TRUE;
338.  	} else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_NO) {
339.  	    *defquery = 'n';
340.  	    return TRUE;
341.  	}
342.      }
343.      if (defquery)
344.  	impossible("should_query_disclose_option: bad category %c", category);
345.      else
346.  	impossible("should_query_disclose_option: null defquery");
347.      return TRUE;
348.  }
349.  

disclose[]

350.  STATIC_OVL void
351.  disclose(how,taken)
352.  int how;
353.  boolean taken;
354.  {
355.  	char	c = 0, defquery;
356.  	char	qbuf[QBUFSZ];
357.  	boolean ask;
358.  
359.  	if (invent) {
360.  	    if(taken)
361.  		Sprintf(qbuf,"Do you want to see what you had when you %s?",
362.  			(how == QUIT) ? "quit" : "died");
363.  	    else
364.  		Strcpy(qbuf,"Do you want your possessions identified?");
365.  
366.  	    ask = should_query_disclose_option('i', &defquery);
367.  	    if (!done_stopprint) {
368.  		c = ask ? yn_function(qbuf, ynqchars, defquery) : defquery;
369.  		if (c == 'y') {
370.  			struct obj *obj;
371.  
372.  			for (obj = invent; obj; obj = obj->nobj) {
373.  			    makeknown(obj->otyp);
374.  			    obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
375.  			}
376.  			(void) display_inventory((char *)0, TRUE);
377.  			container_contents(invent, TRUE, TRUE);
378.  		}
379.  		if (c == 'q')  done_stopprint++;
380.  	    }
381.  	}
382.  
383.  	ask = should_query_disclose_option('a', &defquery);
384.  	if (!done_stopprint) {
385.  	    c = ask ? yn_function("Do you want to see your attributes?",
386.  				  ynqchars, defquery) : defquery;
387.  	    if (c == 'y')
388.  		enlightenment(how >= PANICKED ? 1 : 2); /* final */
389.  	    if (c == 'q') done_stopprint++;
390.  	}
391.  
392.  	ask = should_query_disclose_option('v', &defquery);
393.  	if (!done_stopprint)
394.  	    list_vanquished(defquery, ask);
395.  
396.  	ask = should_query_disclose_option('g', &defquery);
397.  	if (!done_stopprint)
398.  	    list_genocided(defquery, ask);
399.  
400.  	ask = should_query_disclose_option('c', &defquery);
401.  	if (!done_stopprint) {
402.  	    c = ask ? yn_function("Do you want to see your conduct?",
403.  				  ynqchars, defquery) : defquery;
404.  	    if (c == 'y')
405.  		show_conduct(how >= PANICKED ? 1 : 2);
406.  	    if (c == 'q') done_stopprint++;
407.  	}
408.  }
409.  

savelife[]

410.  /* try to get the player back in a viable state after being killed */
411.  STATIC_OVL void
412.  savelife(how)
413.  int how;
414.  {
415.  	u.uswldtim = 0;
416.  	u.uhp = u.uhpmax;
417.  	if (u.uhunger < 500) {
418.  	    u.uhunger = 500;
419.  	    newuhs(FALSE);
420.  	}
421.  	/* cure impending doom of sickness hero won't have time to fix */
422.  	if ((Sick & TIMEOUT) == 1) {
423.  	    u.usick_type = 0;
424.  	    Sick = 0;
425.  	}
426.  	if (how == CHOKING) init_uhunger();
427.  	nomovemsg = "You survived that attempt on your life.";
428.  	flags.move = 0;
429.  	if(multi > 0) multi = 0; else multi = -1;
430.  	if(u.utrap && u.utraptype == TT_LAVA) u.utrap = 0;
431.  	flags.botl = 1;
432.  	u.ugrave_arise = NON_PM;
433.  	HUnchanging = 0L;
434.  	curs_on_u();
435.  }
436.  

get_valuables[]

437.  /*
438.   * Get valuables from the given list.  Revised code: the list always remains
439.   * intact.
440.   */
441.  STATIC_OVL void
442.  get_valuables(list)
443.  struct obj *list;	/* inventory or container contents */
444.  {
445.      register struct obj *obj;
446.      register int i;
447.  
448.      /* find amulets and gems, ignoring all artifacts */
449.      for (obj = list; obj; obj = obj->nobj)
450.  	if (Has_contents(obj)) {
451.  	    get_valuables(obj->cobj);
452.  	} else if (obj->oartifact) {
453.  	    continue;
454.  	} else if (obj->oclass == AMULET_CLASS) {
455.  	    i = obj->otyp - FIRST_AMULET;
456.  	    if (!amulets[i].count) {
457.  		amulets[i].count = obj->quan;
458.  		amulets[i].typ = obj->otyp;
459.  	    } else amulets[i].count += obj->quan; /* always adds one */
460.  	} else if (obj->oclass == GEM_CLASS && obj->otyp < LUCKSTONE) {
461.  	    i = min(obj->otyp, LAST_GEM + 1) - FIRST_GEM;
462.  	    if (!gems[i].count) {
463.  		gems[i].count = obj->quan;
464.  		gems[i].typ = obj->otyp;
465.  	    } else gems[i].count += obj->quan;
466.  	}
467.      return;
468.  }
469.  

sort_valuables[]

470.  /*
471.   *  Sort collected valuables, most frequent to least.  We could just
472.   *  as easily use qsort, but we don't care about efficiency here.
473.   */
474.  STATIC_OVL void
475.  sort_valuables(list, size)
476.  struct valuable_data list[];
477.  int size;		/* max value is less than 20 */
478.  {
479.      register int i, j;
480.      struct valuable_data ltmp;
481.  
482.      /* move greater quantities to the front of the list */
483.      for (i = 1; i < size; i++) {
484.  	if (list[i].count == 0) continue;	/* empty slot */
485.  	ltmp = list[i]; /* structure copy */
486.  	for (j = i; j > 0; --j)
487.  	    if (list[j-1].count >= ltmp.count) break;
488.  	    else {
489.  		list[j] = list[j-1];
490.  	    }
491.  	list[j] = ltmp;
492.      }
493.      return;
494.  }
495.  

artifact_score[]

496.  /* called twice; first to calculate total, then to list relevant items */
497.  STATIC_OVL void
498.  artifact_score(list, counting, endwin)
499.  struct obj *list;
500.  boolean counting;	/* true => add up points; false => display them */
501.  winid endwin;
502.  {
503.      char pbuf[BUFSZ];
504.      struct obj *otmp;
505.      long value, points;
506.      short dummy;	/* object type returned by artifact_name() */
507.  
508.      for (otmp = list; otmp; otmp = otmp->nobj) {
509.  	if (otmp->oartifact ||
510.  			otmp->otyp == BELL_OF_OPENING ||
511.  			otmp->otyp == SPE_BOOK_OF_THE_DEAD ||
512.  			otmp->otyp == CANDELABRUM_OF_INVOCATION) {
513.  	    value = arti_cost(otmp);	/* zorkmid value */
514.  	    points = value * 5 / 2;	/* score value */
515.  	    if (counting) {
516.  		u.urexp += points;
517.  	    } else {
518.  		makeknown(otmp->otyp);
519.  		otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
520.  		/* assumes artifacts don't have quan > 1 */
521.  		Sprintf(pbuf, "%s%s (worth %ld %s and %ld points)",
522.  			the_unique_obj(otmp) ? "The " : "",
523.  			otmp->oartifact ? artifact_name(xname(otmp), &dummy) :
524.  				OBJ_NAME(objects[otmp->otyp]),
525.  			value, currency(value), points);
526.  		putstr(endwin, 0, pbuf);
527.  	    }
528.  	}
529.  	if (Has_contents(otmp))
530.  	    artifact_score(otmp->cobj, counting, endwin);
531.      }
532.  }
533.  

done[]

534.  /* Be careful not to call panic from here! */
535.  void
536.  done(how)
537.  int how;
538.  {
539.  	boolean taken;
540.  	char kilbuf[BUFSZ], pbuf[BUFSZ];
541.  	winid endwin = WIN_ERR;
542.  	boolean bones_ok, have_windows = iflags.window_inited;
543.  	struct obj *corpse = (struct obj *)0;
544.  	long umoney;
545.  
546.  	if (how == TRICKED) {
547.  	    if (killer) {
548.  		paniclog("trickery", killer);
549.  		killer = 0;
550.  	    }
551.  #ifdef WIZARD
552.  	    if (wizard) {
553.  		You("are a very tricky wizard, it seems.");
554.  		return;
555.  	    }
556.  #endif
557.  	}
558.  
559.  	/* kilbuf: used to copy killer in case it comes from something like
560.  	 *	xname(), which would otherwise get overwritten when we call
561.  	 *	xname() when listing possessions
562.  	 * pbuf: holds Sprintf'd output for raw_print and putstr
563.  	 */
564.  	if (how == ASCENDED || (!killer && how == GENOCIDED))
565.  		killer_format = NO_KILLER_PREFIX;
566.  	/* Avoid killed by "a" burning or "a" starvation */
567.  	if (!killer && (how == STARVING || how == BURNING))
568.  		killer_format = KILLED_BY;
569.  	Strcpy(kilbuf, (!killer || how >= PANICKED ? deaths[how] : killer));
570.  	killer = kilbuf;
571.  
572.  	if (how < PANICKED) u.umortality++;
573.  	if (Lifesaved && (how <= GENOCIDED)) {
574.  		pline("But wait...");
575.  		makeknown(AMULET_OF_LIFE_SAVING);
576.  		Your("medallion %s!",
577.  		      !Blind ? "begins to glow" : "feels warm");
578.  		if (how == CHOKING) You("vomit ...");
579.  		You_feel("much better!");
580.  		pline_The("medallion crumbles to dust!");
581.  		if (uamul) useup(uamul);
582.  
583.  		(void) adjattrib(A_CON, -1, TRUE);
584.  		if(u.uhpmax <= 0) u.uhpmax = 10;	/* arbitrary */
585.  		savelife(how);
586.  		if (how == GENOCIDED)
587.  			pline("Unfortunately you are still genocided...");
588.  		else {
589.  			killer = 0;
590.  			killer_format = 0;
591.  			return;
592.  		}
593.  	}
594.  	if ((
595.  #ifdef WIZARD
596.  			wizard ||
597.  #endif
598.  			discover) && (how <= GENOCIDED)) {
599.  		if(yn("Die?") == 'y') goto die;
600.  		pline("OK, so you don't %s.",
601.  			(how == CHOKING) ? "choke" : "die");
602.  		if(u.uhpmax <= 0) u.uhpmax = u.ulevel * 8;	/* arbitrary */
603.  		savelife(how);
604.  		killer = 0;
605.  		killer_format = 0;
606.  		return;
607.  	}
608.  
609.      /*
610.       *	The game is now over...
611.       */
612.  
613.  die:
614.  	program_state.gameover = 1;
615.  	/* in case of a subsequent panic(), there's no point trying to save */
616.  	program_state.something_worth_saving = 0;
617.  	/* render vision subsystem inoperative */
618.  	iflags.vision_inited = 0;
619.  	/* might have been killed while using a disposable item, so make sure
620.  	   it's gone prior to inventory disclosure and creation of bones data */
621.  	inven_inuse(TRUE);
622.  
623.  	/* Sometimes you die on the first move.  Life's not fair.
624.  	 * On those rare occasions you get hosed immediately, go out
625.  	 * smiling... :-)  -3.
626.  	 */
627.  	if (moves <= 1 && how < PANICKED)	/* You die... --More-- */
628.  	    pline("Do not pass go.  Do not collect 200 %s.", currency(200L));
629.  
630.  	if (have_windows) wait_synch();	/* flush screen output */
631.  #ifndef NO_SIGNAL
632.  	(void) signal(SIGINT, (SIG_RET_TYPE) done_intr);
633.  # if defined(UNIX) || defined(VMS) || defined (__EMX__)
634.  	(void) signal(SIGQUIT, (SIG_RET_TYPE) done_intr);
635.  	(void) signal(SIGHUP, (SIG_RET_TYPE) done_hangup);
636.  # endif
637.  #endif /* NO_SIGNAL */
638.  
639.  	bones_ok = (how < GENOCIDED) && can_make_bones();
640.  
641.  	if (how == TURNED_SLIME)
642.  	    u.ugrave_arise = PM_GREEN_SLIME;
643.  
644.  	if (bones_ok && u.ugrave_arise < LOW_PM) {
645.  	    /* corpse gets burnt up too */
646.  	    if (how == BURNING)
647.  		u.ugrave_arise = (NON_PM - 2);	/* leave no corpse */
648.  	    else if (how == STONING)
649.  		u.ugrave_arise = (NON_PM - 1);	/* statue instead of corpse */
650.  	    else if (u.ugrave_arise == NON_PM &&
651.  		     !(mvitals[u.umonnum].mvflags & G_NOCORPSE)) {
652.  		int mnum = u.umonnum;
653.  
654.  		if (!Upolyd) {
655.  		    /* Base corpse on race when not poly'd since original
656.  		     * u.umonnum is based on role, and all role monsters
657.  		     * are human.
658.  		     */
659.  		    mnum = (flags.female && urace.femalenum != NON_PM) ?
660.  			urace.femalenum : urace.malenum;
661.  		}
662.  		corpse = mk_named_object(CORPSE, &mons[mnum],
663.  				       u.ux, u.uy, plname);
664.  		Sprintf(pbuf, "%s, %s%s", plname,
665.  			killer_format == NO_KILLER_PREFIX ? "" :
666.  			killed_by_prefix[how],
667.  			killer_format == KILLED_BY_AN ? an(killer) : killer);
668.  		make_grave(u.ux, u.uy, pbuf);
669.  	    }
670.  	}
671.  
672.  	if (how == QUIT) {
673.  		killer_format = NO_KILLER_PREFIX;
674.  		if (u.uhp < 1) {
675.  			how = DIED;
676.  			u.umortality++;	/* skipped above when how==QUIT */
677.  			/* note that killer is pointing at kilbuf */
678.  			Strcpy(kilbuf, "quit while already on Charon's boat");
679.  		}
680.  	}
681.  	if (how == ESCAPED || how == PANICKED)
682.  		killer_format = NO_KILLER_PREFIX;
683.  
684.  	if (how != PANICKED) {
685.  	    /* these affect score and/or bones, but avoid them during panic */
686.  	    taken = paybill((how == ESCAPED) ? -1 : (how != QUIT));
687.  	    paygd();
688.  	    clearpriests();
689.  	} else	taken = FALSE;	/* lint; assert( !bones_ok ); */
690.  
691.  	clearlocks();
692.  
693.  	if (have_windows) display_nhwindow(WIN_MESSAGE, FALSE);
694.  
695.  	if (strcmp(flags.end_disclose, "none") && how != PANICKED)
696.  		disclose(how, taken);
697.  	/* finish_paybill should be called after disclosure but before bones */
698.  	if (bones_ok && taken) finish_paybill();
699.  
700.  	/* calculate score, before creating bones [container gold] */
701.  	{
702.  	    long tmp;
703.  	    int deepest = deepest_lev_reached(FALSE);
704.  
705.  #ifndef GOLDOBJ
706.  	    umoney = u.ugold;
707.  	    tmp = u.ugold0;
708.  #else
709.  	    umoney = money_cnt(invent);
710.  	    tmp = u.umoney0;
711.  #endif
712.  	    umoney += hidden_gold();	/* accumulate gold from containers */
713.  	    tmp = umoney - tmp;		/* net gain */
714.  
715.  	    if (tmp < 0L)
716.  		tmp = 0L;
717.  	    if (how < PANICKED)
718.  		tmp -= tmp / 10L;
719.  	    u.urexp += tmp;
720.  	    u.urexp += 50L * (long)(deepest - 1);
721.  	    if (deepest > 20)
722.  		u.urexp += 1000L * (long)((deepest > 30) ? 10 : deepest - 20);
723.  	    if (how == ASCENDED) u.urexp *= 2L;
724.  	}
725.  
726.  	if (bones_ok) {
727.  #ifdef WIZARD
728.  	    if (!wizard || yn("Save bones?") == 'y')
729.  #endif
730.  		savebones(corpse);
731.  	    /* corpse may be invalid pointer now so
732.  		ensure that it isn't used again */
733.  	    corpse = (struct obj *)0;
734.  	}
735.  
736.  	/* update gold for the rip output, which can't use hidden_gold()
737.  	   (containers will be gone by then if bones just got saved...) */
738.  #ifndef GOLDOBJ
739.  	u.ugold = umoney;
740.  #else
741.  	done_money = umoney;
742.  #endif
743.  
744.  	/* clean up unneeded windows */
745.  	if (have_windows) {
746.  	    wait_synch();
747.  	    display_nhwindow(WIN_MESSAGE, TRUE);
748.  	    destroy_nhwindow(WIN_MAP);
749.  	    destroy_nhwindow(WIN_STATUS);
750.  	    destroy_nhwindow(WIN_MESSAGE);
751.  	    WIN_MESSAGE = WIN_STATUS = WIN_MAP = WIN_ERR;
752.  
753.  	    if(!done_stopprint || flags.tombstone)
754.  		endwin = create_nhwindow(NHW_TEXT);
755.  
756.  	    if (how < GENOCIDED && flags.tombstone && endwin != WIN_ERR)
757.  		outrip(endwin, how);
758.  	} else
759.  	    done_stopprint = 1; /* just avoid any more output */
760.  
761.  /* changing kilbuf really changes killer. we do it this way because
762.     killer is declared a (const char *)
763.  */
764.  	if (u.uhave.amulet) Strcat(kilbuf, " (with the Amulet)");
765.  	else if (how == ESCAPED) {
766.  	    if (Is_astralevel(&u.uz))	/* offered Amulet to wrong deity */
767.  		Strcat(kilbuf, " (in celestial disgrace)");
768.  	    else if (carrying(FAKE_AMULET_OF_YENDOR))
769.  		Strcat(kilbuf, " (with a fake Amulet)");
770.  		/* don't bother counting to see whether it should be plural */
771.  	}
772.  
773.  	if (!done_stopprint) {
774.  	    Sprintf(pbuf, "%s %s the %s...", Goodbye(), plname,
775.  		   how != ASCENDED ?
776.  		      (const char *) ((flags.female && urole.name.f) ?
777.  		         urole.name.f : urole.name.m) :
778.  		      (const char *) (flags.female ? "Demigoddess" : "Demigod"));
779.  	    putstr(endwin, 0, pbuf);
780.  	    putstr(endwin, 0, "");
781.  	}
782.  
783.  	if (how == ESCAPED || how == ASCENDED) {
784.  	    register struct monst *mtmp;
785.  	    register struct obj *otmp;
786.  	    register struct val_list *val;
787.  	    register int i;
788.  
789.  	    for (val = valuables; val->list; val++)
790.  		for (i = 0; i < val->size; i++) {
791.  		    val->list[i].count = 0L;
792.  		}
793.  	    get_valuables(invent);
794.  
795.  	    /* add points for collected valuables */
796.  	    for (val = valuables; val->list; val++)
797.  		for (i = 0; i < val->size; i++)
798.  		    if (val->list[i].count != 0L)
799.  			u.urexp += val->list[i].count
800.  				  * (long)objects[val->list[i].typ].oc_cost;
801.  
802.  	    /* count the points for artifacts */
803.  	    artifact_score(invent, TRUE, endwin);
804.  
805.  	    keepdogs(TRUE);
806.  	    viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
807.  	    mtmp = mydogs;
808.  	    if (!done_stopprint) Strcpy(pbuf, "You");
809.  	    if (mtmp) {
810.  		while (mtmp) {
811.  		    if (!done_stopprint)
812.  			Sprintf(eos(pbuf), " and %s", mon_nam(mtmp));
813.  		    if (mtmp->mtame)
814.  			u.urexp += mtmp->mhp;
815.  		    mtmp = mtmp->nmon;
816.  		}
817.  		if (!done_stopprint) putstr(endwin, 0, pbuf);
818.  		pbuf[0] = '\0';
819.  	    } else {
820.  		if (!done_stopprint) Strcat(pbuf, " ");
821.  	    }
822.  	    if (!done_stopprint) {
823.  		Sprintf(eos(pbuf), "%s with %ld point%s,",
824.  			how==ASCENDED ? "went to your reward" :
825.  					"escaped from the dungeon",
826.  			u.urexp, plur(u.urexp));
827.  		putstr(endwin, 0, pbuf);
828.  	    }
829.  
830.  	    if (!done_stopprint)
831.  		artifact_score(invent, FALSE, endwin);	/* list artifacts */
832.  
833.  	    /* list valuables here */
834.  	    for (val = valuables; val->list; val++) {
835.  		sort_valuables(val->list, val->size);
836.  		for (i = 0; i < val->size && !done_stopprint; i++) {
837.  		    int typ = val->list[i].typ;
838.  		    long count = val->list[i].count;
839.  
840.  		    if (count == 0L) continue;
841.  		    if (objects[typ].oc_class != GEM_CLASS || typ <= LAST_GEM) {
842.  			otmp = mksobj(typ, FALSE, FALSE);
843.  			makeknown(otmp->otyp);
844.  			otmp->known = 1;	/* for fake amulets */
845.  			otmp->dknown = 1;	/* seen it (blindness fix) */
846.  			otmp->onamelth = 0;
847.  			otmp->quan = count;
848.  			Sprintf(pbuf, "%8ld %s (worth %ld %s),",
849.  				count, xname(otmp),
850.  				count * (long)objects[typ].oc_cost, currency(2L));
851.  			obfree(otmp, (struct obj *)0);
852.  		    } else {
853.  			Sprintf(pbuf,
854.  				"%8ld worthless piece%s of colored glass,",
855.  				count, plur(count));
856.  		    }
857.  		    putstr(endwin, 0, pbuf);
858.  		}
859.  	    }
860.  
861.  	} else if (!done_stopprint) {
862.  	    /* did not escape or ascend */
863.  	    if (u.uz.dnum == 0 && u.uz.dlevel <= 0) {
864.  		/* level teleported out of the dungeon; `how' is DIED,
865.  		   due to falling or to "arriving at heaven prematurely" */
866.  		Sprintf(pbuf, "You %s beyond the confines of the dungeon",
867.  			(u.uz.dlevel < 0) ? "passed away" : ends[how]);
868.  	    } else {
869.  		/* more conventional demise */
870.  		const char *where = dungeons[u.uz.dnum].dname;
871.  
872.  		if (Is_astralevel(&u.uz)) where = "The Astral Plane";
873.  		Sprintf(pbuf, "You %s in %s", ends[how], where);
874.  		if (!In_endgame(&u.uz) && !Is_knox(&u.uz))
875.  		    Sprintf(eos(pbuf), " on dungeon level %d",
876.  			    In_quest(&u.uz) ? dunlev(&u.uz) : depth(&u.uz));
877.  	    }
878.  
879.  	    Sprintf(eos(pbuf), " with %ld point%s,",
880.  		    u.urexp, plur(u.urexp));
881.  	    putstr(endwin, 0, pbuf);
882.  	}
883.  
884.  	if (!done_stopprint) {
885.  	    Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.",
886.  		    umoney, plur(umoney), moves, plur(moves));
887.  	    putstr(endwin, 0, pbuf);
888.  	}
889.  	if (!done_stopprint) {
890.  	    Sprintf(pbuf,
891.  	     "You were level %d with a maximum of %d hit point%s when you %s.",
892.  		    u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]);
893.  	    putstr(endwin, 0, pbuf);
894.  	    putstr(endwin, 0, "");
895.  	}
896.  	if (!done_stopprint)
897.  	    display_nhwindow(endwin, TRUE);
898.  	if (endwin != WIN_ERR)
899.  	    destroy_nhwindow(endwin);
900.  
901.  	/* "So when I die, the first thing I will see in Heaven is a
902.  	 * score list?" */
903.  	if (flags.toptenwin) {
904.  	    topten(how);
905.  	    if (have_windows)
906.  		exit_nhwindows((char *)0);
907.  	} else {
908.  	    if (have_windows)
909.  		exit_nhwindows((char *)0);
910.  	    topten(how);
911.  	}
912.  
913.  	if(done_stopprint) { raw_print(""); raw_print(""); }
914.  	terminate(EXIT_SUCCESS);
915.  }
916.  
917.  

container_contents[]

918.  void
919.  container_contents(list, identified, all_containers)
920.  struct obj *list;
921.  boolean identified, all_containers;
922.  {
923.  	register struct obj *box, *obj;
924.  	char buf[BUFSZ];
925.  
926.  	for (box = list; box; box = box->nobj) {
927.  	    if (Is_container(box) || box->otyp == STATUE) {
928.  		if (box->otyp == BAG_OF_TRICKS) {
929.  		    continue;	/* wrong type of container */
930.  		} else if (box->cobj) {
931.  		    winid tmpwin = create_nhwindow(NHW_MENU);
932.  		    Sprintf(buf, "Contents of %s:", the(xname(box)));
933.  		    putstr(tmpwin, 0, buf);
934.  		    putstr(tmpwin, 0, "");
935.  		    for (obj = box->cobj; obj; obj = obj->nobj) {
936.  			if (identified) {
937.  			    makeknown(obj->otyp);
938.  			    obj->known = obj->bknown =
939.  			    obj->dknown = obj->rknown = 1;
940.  			}
941.  			putstr(tmpwin, 0, doname(obj));
942.  		    }
943.  		    display_nhwindow(tmpwin, TRUE);
944.  		    destroy_nhwindow(tmpwin);
945.  		    if (all_containers)
946.  			container_contents(box->cobj, identified, TRUE);
947.  		} else {
948.  		    pline("%s empty.", Tobjnam(box, "are"));
949.  		    display_nhwindow(WIN_MESSAGE, FALSE);
950.  		}
951.  	    }
952.  	    if (!all_containers)
953.  		break;
954.  	}
955.  }
956.  
957.  

terminate[]

958.  /* should be called with either EXIT_SUCCESS or EXIT_FAILURE */
959.  void
960.  terminate(status)
961.  int status;
962.  {
963.  #ifdef MAC
964.  	getreturn("to exit");
965.  #endif
966.  	/* don't bother to try to release memory if we're in panic mode, to
967.  	   avoid trouble in case that happens to be due to memory problems */
968.  	if (!program_state.panicking) {
969.  	    freedynamicdata();
970.  	    dlb_cleanup();
971.  	}
972.  
973.  	nethack_exit(status);
974.  }
975.  

list_vanquished[]

976.  STATIC_OVL void
977.  list_vanquished(defquery, ask)
978.  char defquery;
979.  boolean ask;
980.  {
981.      register int i, lev;
982.      int ntypes = 0, max_lev = 0, nkilled;
983.      long total_killed = 0L;
984.      char c;
985.      winid klwin;
986.      char buf[BUFSZ];
987.  
988.      /* get totals first */
989.      for (i = LOW_PM; i < NUMMONS; i++) {
990.  	if (mvitals[i].died) ntypes++;
991.  	total_killed += (long)mvitals[i].died;
992.  	if (mons[i].mlevel > max_lev) max_lev = mons[i].mlevel;
993.      }
994.  
995.      /* vanquished creatures list;
996.       * includes all dead monsters, not just those killed by the player
997.       */
998.      if (ntypes != 0) {
999.  	c = ask ? yn_function("Do you want an account of creatures vanquished?",
1000. 			      ynqchars, defquery) : defquery;
1001. 	if (c == 'q') done_stopprint++;
1002. 	if (c == 'y') {
1003. 	    klwin = create_nhwindow(NHW_MENU);
1004. 	    putstr(klwin, 0, "Vanquished creatures:");
1005. 	    putstr(klwin, 0, "");
1006. 
1007. 	    /* countdown by monster "toughness" */
1008. 	    for (lev = max_lev; lev >= 0; lev--)
1009. 	      for (i = LOW_PM; i < NUMMONS; i++)
1010. 		if (mons[i].mlevel == lev && (nkilled = mvitals[i].died) > 0) {
1011. 		    if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) {
1012. 			Sprintf(buf, "%s%s",
1013. 				!type_is_pname(&mons[i]) ? "The " : "",
1014. 				mons[i].mname);
1015. 			if (nkilled > 1) {
1016. 			    switch (nkilled) {
1017. 				case 2:  Sprintf(eos(buf)," (twice)");  break;
1018. 				case 3:  Sprintf(eos(buf)," (thrice)");  break;
1019. 				default: Sprintf(eos(buf)," (%d time%s)",
1020. 						 nkilled, plur(nkilled));
1021. 					 break;
1022. 			    }
1023. 			}
1024. 		    } else {
1025. 			/* trolls or undead might have come back,
1026. 			   but we don't keep track of that */
1027. 			if (nkilled == 1)
1028. 			    Strcpy(buf, an(mons[i].mname));
1029. 			else
1030. 			    Sprintf(buf, "%d %s",
1031. 				    nkilled, makeplural(mons[i].mname));
1032. 		    }
1033. 		    putstr(klwin, 0, buf);
1034. 		}
1035. 	    /*
1036. 	     * if (Hallucination)
1037. 	     *     putstr(klwin, 0, "and a partridge in a pear tree");
1038. 	     */
1039. 	    if (ntypes > 1) {
1040. 		putstr(klwin, 0, "");
1041. 		Sprintf(buf, "%ld creatures vanquished.", total_killed);
1042. 		putstr(klwin, 0, buf);
1043. 	    }
1044. 	    display_nhwindow(klwin, TRUE);
1045. 	    destroy_nhwindow(klwin);
1046. 	}
1047.     }
1048. }
1049. 

num_genocides[]

1050. /* number of monster species which have been genocided */
1051. int
1052. num_genocides()
1053. {
1054.     int i, n = 0;
1055. 
1056.     for (i = LOW_PM; i < NUMMONS; ++i)
1057. 	if (mvitals[i].mvflags & G_GENOD) ++n;
1058. 
1059.     return n;
1060. }
1061. 

list_genocided[]

1062. STATIC_OVL void
1063. list_genocided(defquery, ask)
1064. char defquery;
1065. boolean ask;
1066. {
1067.     register int i;
1068.     int ngenocided;
1069.     char c;
1070.     winid klwin;
1071.     char buf[BUFSZ];
1072. 
1073.     ngenocided = num_genocides();
1074. 
1075.     /* genocided species list */
1076.     if (ngenocided != 0) {
1077. 	c = ask ? yn_function("Do you want a list of species genocided?",
1078. 			      ynqchars, defquery) : defquery;
1079. 	if (c == 'q') done_stopprint++;
1080. 	if (c == 'y') {
1081. 	    klwin = create_nhwindow(NHW_MENU);
1082. 	    putstr(klwin, 0, "Genocided species:");
1083. 	    putstr(klwin, 0, "");
1084. 
1085. 	    for (i = LOW_PM; i < NUMMONS; i++)
1086. 		if (mvitals[i].mvflags & G_GENOD) {
1087. 		    if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST)
1088. 			Sprintf(buf, "%s%s",
1089. 				!type_is_pname(&mons[i]) ? "" : "the ",
1090. 				mons[i].mname);
1091. 		    else
1092. 			Strcpy(buf, makeplural(mons[i].mname));
1093. 		    putstr(klwin, 0, buf);
1094. 		}
1095. 
1096. 	    putstr(klwin, 0, "");
1097. 	    Sprintf(buf, "%d species genocided.", ngenocided);
1098. 	    putstr(klwin, 0, buf);
1099. 
1100. 	    display_nhwindow(klwin, TRUE);
1101. 	    destroy_nhwindow(klwin);
1102. 	}
1103.     }
1104. }
1105. 
1106. /*end.c*/
Advertisement