Source:NetHack 3.4.3/src/end.c

From NetHackWiki
(Redirected from End.c)
Jump to: navigation, search

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.

Contents

[edit] 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.

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

[edit] done1

  1. /*ARGSUSED*/
  2. void
  3. done1(sig_unused)   /* called as signal() handler, so sent at least one arg */
  4. int sig_unused;
  5. {
  6. #ifndef NO_SIGNAL
  7. 	(void) signal(SIGINT,SIG_IGN);
  8. #endif
  9. 	if(flags.ignintr) {
  10. #ifndef NO_SIGNAL
  11. 		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
  12. #endif
  13. 		clear_nhwindow(WIN_MESSAGE);
  14. 		curs_on_u();
  15. 		wait_synch();
  16. 		if(multi > 0) nomul(0);
  17. 	} else {
  18. 		(void)done2();
  19. 	}
  20. }
  21.  
  22.  

[edit] done2

  1. /* "#quit" command or keyboard interrupt */
  2. int
  3. done2()
  4. {
  5. 	if(yn("Really quit?") == 'n') {
  6. #ifndef NO_SIGNAL
  7. 		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
  8. #endif
  9. 		clear_nhwindow(WIN_MESSAGE);
  10. 		curs_on_u();
  11. 		wait_synch();
  12. 		if(multi > 0) nomul(0);
  13. 		if(multi == 0) {
  14. 		    u.uinvulnerable = FALSE;	/* avoid ctrl-C bug -dlc */
  15. 		    u.usleep = 0;
  16. 		}
  17. 		return 0;
  18. 	}
  19. #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE))
  20. 	if(wizard) {
  21. 	    int c;
  22. # ifdef VMS
  23. 	    const char *tmp = "Enter debugger?";
  24. # else
  25. #  ifdef LATTICE
  26. 	    const char *tmp = "Create SnapShot?";
  27. #  else
  28. 	    const char *tmp = "Dump core?";
  29. #  endif
  30. # endif
  31. 	    if ((c = ynq(tmp)) == 'y') {
  32. 		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
  33. 		exit_nhwindows((char *)0);
  34. 		NH_abort();
  35. 	    } else if (c == 'q') done_stopprint++;
  36. 	}
  37. #endif
  38. #ifndef LINT
  39. 	done(QUIT);
  40. #endif
  41. 	return 0;
  42. }
  43.  

[edit] done_intr

  1. #ifndef NO_SIGNAL
  2. /*ARGSUSED*/
  3. STATIC_PTR void
  4. done_intr(sig_unused) /* called as signal() handler, so sent at least one arg */
  5. int sig_unused;
  6. {
  7. 	done_stopprint++;
  8. 	(void) signal(SIGINT, SIG_IGN);
  9. # if defined(UNIX) || defined(VMS)
  10. 	(void) signal(SIGQUIT, SIG_IGN);
  11. # endif
  12. 	return;
  13. }
  14.  

[edit] done_hangup

  1. # if defined(UNIX) || defined(VMS) || defined(__EMX__)
  2. static void
  3. done_hangup(sig)	/* signal() handler */
  4. int sig;
  5. {
  6. 	program_state.done_hup++;
  7. 	(void)signal(SIGHUP, SIG_IGN);
  8. 	done_intr(sig);
  9. 	return;
  10. }
  11. # endif
  12. #endif /* NO_SIGNAL */
  13.  

[edit] done_in_by

  1. void
  2. done_in_by(mtmp)
  3. register struct monst *mtmp;
  4. {
  5. 	char buf[BUFSZ];
  6. 	boolean distorted = (boolean)(Hallucination && canspotmon(mtmp));
  7.  
  8. 	You("die...");
  9. 	mark_synch();	/* flush buffered screen output */
  10. 	buf[0] = '\0';
  11. 	killer_format = KILLED_BY_AN;
  12. 	/* "killed by the high priest of Crom" is okay, "killed by the high
  13. 	   priest" alone isn't */
  14. 	if ((mtmp->data->geno & G_UNIQ) != 0 && !(mtmp->data == &mons[PM_HIGH_PRIEST] && !mtmp->ispriest)) {
  15. 	    if (!type_is_pname(mtmp->data))
  16. 		Strcat(buf, "the ");
  17. 	    killer_format = KILLED_BY;
  18. 	}
  19. 	/* _the_ <invisible> <distorted> ghost of Dudley */
  20. 	if (mtmp->data == &mons[PM_GHOST] && mtmp->mnamelth) {
  21. 		Strcat(buf, "the ");
  22. 		killer_format = KILLED_BY;
  23. 	}
  24. 	if (mtmp->minvis)
  25. 		Strcat(buf, "invisible ");
  26. 	if (distorted)
  27. 		Strcat(buf, "hallucinogen-distorted ");
  28.  
  29. 	if(mtmp->data == &mons[PM_GHOST]) {
  30. 		Strcat(buf, "ghost");
  31. 		if (mtmp->mnamelth) Sprintf(eos(buf), " of %s", NAME(mtmp));
  32. 	} else if(mtmp->isshk) {
  33. 		Sprintf(eos(buf), "%s %s, the shopkeeper",
  34. 			(mtmp->female ? "Ms." : "Mr."), shkname(mtmp));
  35. 		killer_format = KILLED_BY;
  36. 	} else if (mtmp->ispriest || mtmp->isminion) {
  37. 		/* m_monnam() suppresses "the" prefix plus "invisible", and
  38. 		   it overrides the effect of Hallucination on priestname() */
  39. 		killer = m_monnam(mtmp);
  40. 		Strcat(buf, killer);
  41. 	} else {
  42. 		Strcat(buf, mtmp->data->mname);
  43. 		if (mtmp->mnamelth)
  44. 		    Sprintf(eos(buf), " called %s", NAME(mtmp));
  45. 	}
  46.  
  47. 	if (multi) Strcat(buf, ", while helpless");
  48. 	killer = buf;
  49. 	if (mtmp->data->mlet == S_WRAITH)
  50. 		u.ugrave_arise = PM_WRAITH;
  51. 	else if (mtmp->data->mlet == S_MUMMY && urace.mummynum != NON_PM)
  52. 		u.ugrave_arise = urace.mummynum;
  53. 	else if (mtmp->data->mlet == S_VAMPIRE && Race_if(PM_HUMAN))
  54. 		u.ugrave_arise = PM_VAMPIRE;
  55. 	else if (mtmp->data == &mons[PM_GHOUL])
  56. 		u.ugrave_arise = PM_GHOUL;
  57. 	if (u.ugrave_arise >= LOW_PM &&
  58. 				(mvitals[u.ugrave_arise].mvflags & G_GENOD))
  59. 		u.ugrave_arise = NON_PM;
  60. 	if (touch_petrifies(mtmp->data))
  61. 		done(STONING);
  62. 	else
  63. 		done(DIED);
  64. 	return;
  65. }
  66.  
  67. #if defined(WIN32)
  68. #define NOTIFY_NETHACK_BUGS
  69. #endif
  70.  

[edit] panic

  1. /*VARARGS1*/
  2. void
  3. panic VA_DECL(const char *, str)
  4. 	VA_START(str);
  5. 	VA_INIT(str, char *);
  6.  
  7. 	if (program_state.panicking++)
  8. 	    NH_abort();	/* avoid loops - this should never happen*/
  9.  
  10. 	if (iflags.window_inited) {
  11. 	    raw_print("\r\nOops...");
  12. 	    wait_synch();	/* make sure all pending output gets flushed */
  13. 	    exit_nhwindows((char *)0);
  14. 	    iflags.window_inited = 0; /* they're gone; force raw_print()ing */
  15. 	}
  16.  
  17. 	raw_print(program_state.gameover ?
  18. 		  "Postgame wrapup disrupted." :
  19. 		  !program_state.something_worth_saving ?
  20. 		  "Program initialization has failed." :
  21. 		  "Suddenly, the dungeon collapses.");
  22. #if defined(WIZARD) && !defined(MICRO)
  23. # if defined(NOTIFY_NETHACK_BUGS)
  24. 	if (!wizard)
  25. 	    raw_printf("Report the following error to \"%s\".",
  26. 			"nethack-bugs@nethack.org");
  27. 	else if (program_state.something_worth_saving)
  28. 	    raw_print("\nError save file being written.\n");
  29. # else
  30. 	if (!wizard)
  31. 	    raw_printf("Report error to \"%s\"%s.",
  32. #  ifdef WIZARD_NAME	/*(KR1ED)*/
  33. 			WIZARD_NAME,
  34. #  else
  35. 			WIZARD,
  36. #  endif
  37. 			!program_state.something_worth_saving ? "" :
  38. 			" and it may be possible to rebuild.");
  39. # endif
  40. 	if (program_state.something_worth_saving) {
  41. 	    set_error_savefile();
  42. 	    (void) dosave0();
  43. 	}
  44. #endif
  45. 	{
  46. 	    char buf[BUFSZ];
  47. 	    Vsprintf(buf,str,VA_ARGS);
  48. 	    raw_print(buf);
  49. 	    paniclog("panic", buf);
  50. 	}
  51. #ifdef WIN32
  52. 	interject(INTERJECT_PANIC);
  53. #endif
  54. #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE) || defined(WIN32))
  55. 	if (wizard)
  56. 	    NH_abort();	/* generate core dump */
  57. #endif
  58. 	VA_END();
  59. 	done(PANICKED);
  60. }
  61.  

[edit] should_query_disclose_option

  1. STATIC_OVL boolean
  2. should_query_disclose_option(category, defquery)
  3. int category;
  4. char *defquery;
  5. {
  6. int idx;
  7. char *dop = index(disclosure_options, category);
  8.  
  9. if (dop && defquery) {
  10. 	idx = dop - disclosure_options;
  11. 	if (idx < 0 || idx > (NUM_DISCLOSURE_OPTIONS - 1)) {
  12. 	    impossible(
  13. 		   "should_query_disclose_option: bad disclosure index %d %c",
  14. 		       idx, category);
  15. 	    *defquery = DISCLOSE_PROMPT_DEFAULT_YES;
  16. 	    return TRUE;
  17. 	}
  18. 	if (flags.end_disclose[idx] == DISCLOSE_YES_WITHOUT_PROMPT) {
  19. 	    *defquery = 'y';
  20. 	    return FALSE;
  21. 	} else if (flags.end_disclose[idx] == DISCLOSE_NO_WITHOUT_PROMPT) {
  22. 	    *defquery = 'n';
  23. 	    return FALSE;
  24. 	} else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_YES) {
  25. 	    *defquery = 'y';
  26. 	    return TRUE;
  27. 	} else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_NO) {
  28. 	    *defquery = 'n';
  29. 	    return TRUE;
  30. 	}
  31. }
  32. if (defquery)
  33. 	impossible("should_query_disclose_option: bad category %c", category);
  34. else
  35. 	impossible("should_query_disclose_option: null defquery");
  36. return TRUE;
  37. }
  38.  

[edit] disclose

  1. STATIC_OVL void
  2. disclose(how,taken)
  3. int how;
  4. boolean taken;
  5. {
  6. 	char	c = 0, defquery;
  7. 	char	qbuf[QBUFSZ];
  8. 	boolean ask;
  9.  
  10. 	if (invent) {
  11. 	    if(taken)
  12. 		Sprintf(qbuf,"Do you want to see what you had when you %s?",
  13. 			(how == QUIT) ? "quit" : "died");
  14. 	    else
  15. 		Strcpy(qbuf,"Do you want your possessions identified?");
  16.  
  17. 	    ask = should_query_disclose_option('i', &defquery);
  18. 	    if (!done_stopprint) {
  19. 		c = ask ? yn_function(qbuf, ynqchars, defquery) : defquery;
  20. 		if (c == 'y') {
  21. 			struct obj *obj;
  22.  
  23. 			for (obj = invent; obj; obj = obj->nobj) {
  24. 			    makeknown(obj->otyp);
  25. 			    obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
  26. 			}
  27. 			(void) display_inventory((char *)0, TRUE);
  28. 			container_contents(invent, TRUE, TRUE);
  29. 		}
  30. 		if (c == 'q')  done_stopprint++;
  31. 	    }
  32. 	}
  33.  
  34. 	ask = should_query_disclose_option('a', &defquery);
  35. 	if (!done_stopprint) {
  36. 	    c = ask ? yn_function("Do you want to see your attributes?",
  37. 				  ynqchars, defquery) : defquery;
  38. 	    if (c == 'y')
  39. 		enlightenment(how >= PANICKED ? 1 : 2); /* final */
  40. 	    if (c == 'q') done_stopprint++;
  41. 	}
  42.  
  43. 	ask = should_query_disclose_option('v', &defquery);
  44. 	if (!done_stopprint)
  45. 	    list_vanquished(defquery, ask);
  46.  
  47. 	ask = should_query_disclose_option('g', &defquery);
  48. 	if (!done_stopprint)
  49. 	    list_genocided(defquery, ask);
  50.  
  51. 	ask = should_query_disclose_option('c', &defquery);
  52. 	if (!done_stopprint) {
  53. 	    c = ask ? yn_function("Do you want to see your conduct?",
  54. 				  ynqchars, defquery) : defquery;
  55. 	    if (c == 'y')
  56. 		show_conduct(how >= PANICKED ? 1 : 2);
  57. 	    if (c == 'q') done_stopprint++;
  58. 	}
  59. }
  60.  

[edit] savelife

  1. /* try to get the player back in a viable state after being killed */
  2. STATIC_OVL void
  3. savelife(how)
  4. int how;
  5. {
  6. 	u.uswldtim = 0;
  7. 	u.uhp = u.uhpmax;
  8. 	if (u.uhunger < 500) {
  9. 	    u.uhunger = 500;
  10. 	    newuhs(FALSE);
  11. 	}
  12. 	/* cure impending doom of sickness hero won't have time to fix */
  13. 	if ((Sick & TIMEOUT) == 1) {
  14. 	    u.usick_type = 0;
  15. 	    Sick = 0;
  16. 	}
  17. 	if (how == CHOKING) init_uhunger();
  18. 	nomovemsg = "You survived that attempt on your life.";
  19. 	flags.move = 0;
  20. 	if(multi > 0) multi = 0; else multi = -1;
  21. 	if(u.utrap && u.utraptype == TT_LAVA) u.utrap = 0;
  22. 	flags.botl = 1;
  23. 	u.ugrave_arise = NON_PM;
  24. 	HUnchanging = 0L;
  25. 	curs_on_u();
  26. }
  27.  

[edit] get_valuables

  1. /*
  2. * Get valuables from the given list.  Revised code: the list always remains
  3. * intact.
  4. */
  5. STATIC_OVL void
  6. get_valuables(list)
  7. struct obj *list;	/* inventory or container contents */
  8. {
  9. register struct obj *obj;
  10. register int i;
  11.  
  12. /* find amulets and gems, ignoring all artifacts */
  13. for (obj = list; obj; obj = obj->nobj)
  14. 	if (Has_contents(obj)) {
  15. 	    get_valuables(obj->cobj);
  16. 	} else if (obj->oartifact) {
  17. 	    continue;
  18. 	} else if (obj->oclass == AMULET_CLASS) {
  19. 	    i = obj->otyp - FIRST_AMULET;
  20. 	    if (!amulets[i].count) {
  21. 		amulets[i].count = obj->quan;
  22. 		amulets[i].typ = obj->otyp;
  23. 	    } else amulets[i].count += obj->quan; /* always adds one */
  24. 	} else if (obj->oclass == GEM_CLASS && obj->otyp < LUCKSTONE) {
  25. 	    i = min(obj->otyp, LAST_GEM + 1) - FIRST_GEM;
  26. 	    if (!gems[i].count) {
  27. 		gems[i].count = obj->quan;
  28. 		gems[i].typ = obj->otyp;
  29. 	    } else gems[i].count += obj->quan;
  30. 	}
  31. return;
  32. }
  33.  

[edit] sort_valuables

  1. /*
  2. *  Sort collected valuables, most frequent to least.  We could just
  3. *  as easily use qsort, but we don't care about efficiency here.
  4. */
  5. STATIC_OVL void
  6. sort_valuables(list, size)
  7. struct valuable_data list[];
  8. int size;		/* max value is less than 20 */
  9. {
  10. register int i, j;
  11. struct valuable_data ltmp;
  12.  
  13. /* move greater quantities to the front of the list */
  14. for (i = 1; i < size; i++) {
  15. 	if (list[i].count == 0) continue;	/* empty slot */
  16. 	ltmp = list[i]; /* structure copy */
  17. 	for (j = i; j > 0; --j)
  18. 	    if (list[j-1].count >= ltmp.count) break;
  19. 	    else {
  20. 		list[j] = list[j-1];
  21. 	    }
  22. 	list[j] = ltmp;
  23. }
  24. return;
  25. }
  26.  

[edit] artifact_score

  1. /* called twice; first to calculate total, then to list relevant items */
  2. STATIC_OVL void
  3. artifact_score(list, counting, endwin)
  4. struct obj *list;
  5. boolean counting;	/* true => add up points; false => display them */
  6. winid endwin;
  7. {
  8. char pbuf[BUFSZ];
  9. struct obj *otmp;
  10. long value, points;
  11. short dummy;	/* object type returned by artifact_name() */
  12.  
  13. for (otmp = list; otmp; otmp = otmp->nobj) {
  14. 	if (otmp->oartifact ||
  15. 			otmp->otyp == BELL_OF_OPENING ||
  16. 			otmp->otyp == SPE_BOOK_OF_THE_DEAD ||
  17. 			otmp->otyp == CANDELABRUM_OF_INVOCATION) {
  18. 	    value = arti_cost(otmp);	/* zorkmid value */
  19. 	    points = value * 5 / 2;	/* score value */
  20. 	    if (counting) {
  21. 		u.urexp += points;
  22. 	    } else {
  23. 		makeknown(otmp->otyp);
  24. 		otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
  25. 		/* assumes artifacts don't have quan > 1 */
  26. 		Sprintf(pbuf, "%s%s (worth %ld %s and %ld points)",
  27. 			the_unique_obj(otmp) ? "The " : "",
  28. 			otmp->oartifact ? artifact_name(xname(otmp), &dummy) :
  29. 				OBJ_NAME(objects[otmp->otyp]),
  30. 			value, currency(value), points);
  31. 		putstr(endwin, 0, pbuf);
  32. 	    }
  33. 	}
  34. 	if (Has_contents(otmp))
  35. 	    artifact_score(otmp->cobj, counting, endwin);
  36. }
  37. }
  38.  

[edit] done

  1. /* Be careful not to call panic from here! */
  2. void
  3. done(how)
  4. int how;
  5. {
  6. 	boolean taken;
  7. 	char kilbuf[BUFSZ], pbuf[BUFSZ];
  8. 	winid endwin = WIN_ERR;
  9. 	boolean bones_ok, have_windows = iflags.window_inited;
  10. 	struct obj *corpse = (struct obj *)0;
  11. 	long umoney;
  12.  
  13. 	if (how == TRICKED) {
  14. 	    if (killer) {
  15. 		paniclog("trickery", killer);
  16. 		killer = 0;
  17. 	    }
  18. #ifdef WIZARD
  19. 	    if (wizard) {
  20. 		You("are a very tricky wizard, it seems.");
  21. 		return;
  22. 	    }
  23. #endif
  24. 	}
  25.  
  26. 	/* kilbuf: used to copy killer in case it comes from something like
  27. 	 *	xname(), which would otherwise get overwritten when we call
  28. 	 *	xname() when listing possessions
  29. 	 * pbuf: holds Sprintf'd output for raw_print and putstr
  30. 	 */
  31. 	if (how == ASCENDED || (!killer && how == GENOCIDED))
  32. 		killer_format = NO_KILLER_PREFIX;
  33. 	/* Avoid killed by "a" burning or "a" starvation */
  34. 	if (!killer && (how == STARVING || how == BURNING))
  35. 		killer_format = KILLED_BY;
  36. 	Strcpy(kilbuf, (!killer || how >= PANICKED ? deaths[how] : killer));
  37. 	killer = kilbuf;
  38.  
  39. 	if (how < PANICKED) u.umortality++;
  40. 	if (Lifesaved && (how <= GENOCIDED)) {
  41. 		pline("But wait...");
  42. 		makeknown(AMULET_OF_LIFE_SAVING);
  43. 		Your("medallion %s!",
  44. 		      !Blind ? "begins to glow" : "feels warm");
  45. 		if (how == CHOKING) You("vomit ...");
  46. 		You_feel("much better!");
  47. 		pline_The("medallion crumbles to dust!");
  48. 		if (uamul) useup(uamul);
  49.  
  50. 		(void) adjattrib(A_CON, -1, TRUE);
  51. 		if(u.uhpmax <= 0) u.uhpmax = 10;	/* arbitrary */
  52. 		savelife(how);
  53. 		if (how == GENOCIDED)
  54. 			pline("Unfortunately you are still genocided...");
  55. 		else {
  56. 			killer = 0;
  57. 			killer_format = 0;
  58. 			return;
  59. 		}
  60. 	}
  61. 	if ((
  62. #ifdef WIZARD
  63. 			wizard ||
  64. #endif
  65. 			discover) && (how <= GENOCIDED)) {
  66. 		if(yn("Die?") == 'y') goto die;
  67. 		pline("OK, so you don't %s.",
  68. 			(how == CHOKING) ? "choke" : "die");
  69. 		if(u.uhpmax <= 0) u.uhpmax = u.ulevel * 8;	/* arbitrary */
  70. 		savelife(how);
  71. 		killer = 0;
  72. 		killer_format = 0;
  73. 		return;
  74. 	}
  75.  
  76. /*
  77. *	The game is now over...
  78. */
  79.  
  80. die:
  81. 	program_state.gameover = 1;
  82. 	/* in case of a subsequent panic(), there's no point trying to save */
  83. 	program_state.something_worth_saving = 0;
  84. 	/* render vision subsystem inoperative */
  85. 	iflags.vision_inited = 0;
  86. 	/* might have been killed while using a disposable item, so make sure
  87. 	   it's gone prior to inventory disclosure and creation of bones data */
  88. 	inven_inuse(TRUE);
  89.  
  90. 	/* Sometimes you die on the first move.  Life's not fair.
  91. 	 * On those rare occasions you get hosed immediately, go out
  92. 	 * smiling... :-)  -3.
  93. 	 */
  94. 	if (moves <= 1 && how < PANICKED)	/* You die... --More-- */
  95. 	    pline("Do not pass go.  Do not collect 200 %s.", currency(200L));
  96.  
  97. 	if (have_windows) wait_synch();	/* flush screen output */
  98. #ifndef NO_SIGNAL
  99. 	(void) signal(SIGINT, (SIG_RET_TYPE) done_intr);
  100. # if defined(UNIX) || defined(VMS) || defined (__EMX__)
  101. 	(void) signal(SIGQUIT, (SIG_RET_TYPE) done_intr);
  102. 	(void) signal(SIGHUP, (SIG_RET_TYPE) done_hangup);
  103. # endif
  104. #endif /* NO_SIGNAL */
  105.  
  106. 	bones_ok = (how < GENOCIDED) && can_make_bones();
  107.  
  108. 	if (how == TURNED_SLIME)
  109. 	    u.ugrave_arise = PM_GREEN_SLIME;
  110.  
  111. 	if (bones_ok && u.ugrave_arise < LOW_PM) {
  112. 	    /* corpse gets burnt up too */
  113. 	    if (how == BURNING)
  114. 		u.ugrave_arise = (NON_PM - 2);	/* leave no corpse */
  115. 	    else if (how == STONING)
  116. 		u.ugrave_arise = (NON_PM - 1);	/* statue instead of corpse */
  117. 	    else if (u.ugrave_arise == NON_PM &&
  118. 		     !(mvitals[u.umonnum].mvflags & G_NOCORPSE)) {
  119. 		int mnum = u.umonnum;
  120.  
  121. 		if (!Upolyd) {
  122. 		    /* Base corpse on race when not poly'd since original
  123. 		     * u.umonnum is based on role, and all role monsters
  124. 		     * are human.
  125. 		     */
  126. 		    mnum = (flags.female && urace.femalenum != NON_PM) ?
  127. 			urace.femalenum : urace.malenum;
  128. 		}
  129. 		corpse = mk_named_object(CORPSE, &mons[mnum],
  130. 				       u.ux, u.uy, plname);
  131. 		Sprintf(pbuf, "%s, %s%s", plname,
  132. 			killer_format == NO_KILLER_PREFIX ? "" :
  133. 			killed_by_prefix[how],
  134. 			killer_format == KILLED_BY_AN ? an(killer) : killer);
  135. 		make_grave(u.ux, u.uy, pbuf);
  136. 	    }
  137. 	}
  138.  
  139. 	if (how == QUIT) {
  140. 		killer_format = NO_KILLER_PREFIX;
  141. 		if (u.uhp < 1) {
  142. 			how = DIED;
  143. 			u.umortality++;	/* skipped above when how==QUIT */
  144. 			/* note that killer is pointing at kilbuf */
  145. 			Strcpy(kilbuf, "quit while already on Charon's boat");
  146. 		}
  147. 	}
  148. 	if (how == ESCAPED || how == PANICKED)
  149. 		killer_format = NO_KILLER_PREFIX;
  150.  
  151. 	if (how != PANICKED) {
  152. 	    /* these affect score and/or bones, but avoid them during panic */
  153. 	    taken = paybill((how == ESCAPED) ? -1 : (how != QUIT));
  154. 	    paygd();
  155. 	    clearpriests();
  156. 	} else	taken = FALSE;	/* lint; assert( !bones_ok ); */
  157.  
  158. 	clearlocks();
  159.  
  160. 	if (have_windows) display_nhwindow(WIN_MESSAGE, FALSE);
  161.  
  162. 	if (strcmp(flags.end_disclose, "none") && how != PANICKED)
  163. 		disclose(how, taken);
  164. 	/* finish_paybill should be called after disclosure but before bones */
  165. 	if (bones_ok && taken) finish_paybill();
  166.  
  167. 	/* calculate score, before creating bones [container gold] */
  168. 	{
  169. 	    long tmp;
  170. 	    int deepest = deepest_lev_reached(FALSE);
  171.  
  172. #ifndef GOLDOBJ
  173. 	    umoney = u.ugold;
  174. 	    tmp = u.ugold0;
  175. #else
  176. 	    umoney = money_cnt(invent);
  177. 	    tmp = u.umoney0;
  178. #endif
  179. 	    umoney += hidden_gold();	/* accumulate gold from containers */
  180. 	    tmp = umoney - tmp;		/* net gain */
  181.  
  182. 	    if (tmp < 0L)
  183. 		tmp = 0L;
  184. 	    if (how < PANICKED)
  185. 		tmp -= tmp / 10L;
  186. 	    u.urexp += tmp;
  187. 	    u.urexp += 50L * (long)(deepest - 1);
  188. 	    if (deepest > 20)
  189. 		u.urexp += 1000L * (long)((deepest > 30) ? 10 : deepest - 20);
  190. 	    if (how == ASCENDED) u.urexp *= 2L;
  191. 	}
  192.  
  193. 	if (bones_ok) {
  194. #ifdef WIZARD
  195. 	    if (!wizard || yn("Save bones?") == 'y')
  196. #endif
  197. 		savebones(corpse);
  198. 	    /* corpse may be invalid pointer now so
  199. 		ensure that it isn't used again */
  200. 	    corpse = (struct obj *)0;
  201. 	}
  202.  
  203. 	/* update gold for the rip output, which can't use hidden_gold()
  204. 	   (containers will be gone by then if bones just got saved...) */
  205. #ifndef GOLDOBJ
  206. 	u.ugold = umoney;
  207. #else
  208. 	done_money = umoney;
  209. #endif
  210.  
  211. 	/* clean up unneeded windows */
  212. 	if (have_windows) {
  213. 	    wait_synch();
  214. 	    display_nhwindow(WIN_MESSAGE, TRUE);
  215. 	    destroy_nhwindow(WIN_MAP);
  216. 	    destroy_nhwindow(WIN_STATUS);
  217. 	    destroy_nhwindow(WIN_MESSAGE);
  218. 	    WIN_MESSAGE = WIN_STATUS = WIN_MAP = WIN_ERR;
  219.  
  220. 	    if(!done_stopprint || flags.tombstone)
  221. 		endwin = create_nhwindow(NHW_TEXT);
  222.  
  223. 	    if (how < GENOCIDED && flags.tombstone && endwin != WIN_ERR)
  224. 		outrip(endwin, how);
  225. 	} else
  226. 	    done_stopprint = 1; /* just avoid any more output */
  227.  
  228. /* changing kilbuf really changes killer. we do it this way because
  229. killer is declared a (const char *)
  230. */
  231. 	if (u.uhave.amulet) Strcat(kilbuf, " (with the Amulet)");
  232. 	else if (how == ESCAPED) {
  233. 	    if (Is_astralevel(&u.uz))	/* offered Amulet to wrong deity */
  234. 		Strcat(kilbuf, " (in celestial disgrace)");
  235. 	    else if (carrying(FAKE_AMULET_OF_YENDOR))
  236. 		Strcat(kilbuf, " (with a fake Amulet)");
  237. 		/* don't bother counting to see whether it should be plural */
  238. 	}
  239.  
  240. 	if (!done_stopprint) {
  241. 	    Sprintf(pbuf, "%s %s the %s...", Goodbye(), plname,
  242. 		   how != ASCENDED ?
  243. 		      (const char *) ((flags.female && urole.name.f) ?
  244. 		         urole.name.f : urole.name.m) :
  245. 		      (const char *) (flags.female ? "Demigoddess" : "Demigod"));
  246. 	    putstr(endwin, 0, pbuf);
  247. 	    putstr(endwin, 0, "");
  248. 	}
  249.  
  250. 	if (how == ESCAPED || how == ASCENDED) {
  251. 	    register struct monst *mtmp;
  252. 	    register struct obj *otmp;
  253. 	    register struct val_list *val;
  254. 	    register int i;
  255.  
  256. 	    for (val = valuables; val->list; val++)
  257. 		for (i = 0; i < val->size; i++) {
  258. 		    val->list[i].count = 0L;
  259. 		}
  260. 	    get_valuables(invent);
  261.  
  262. 	    /* add points for collected valuables */
  263. 	    for (val = valuables; val->list; val++)
  264. 		for (i = 0; i < val->size; i++)
  265. 		    if (val->list[i].count != 0L)
  266. 			u.urexp += val->list[i].count
  267. 				  * (long)objects[val->list[i].typ].oc_cost;
  268.  
  269. 	    /* count the points for artifacts */
  270. 	    artifact_score(invent, TRUE, endwin);
  271.  
  272. 	    keepdogs(TRUE);
  273. 	    viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
  274. 	    mtmp = mydogs;
  275. 	    if (!done_stopprint) Strcpy(pbuf, "You");
  276. 	    if (mtmp) {
  277. 		while (mtmp) {
  278. 		    if (!done_stopprint)
  279. 			Sprintf(eos(pbuf), " and %s", mon_nam(mtmp));
  280. 		    if (mtmp->mtame)
  281. 			u.urexp += mtmp->mhp;
  282. 		    mtmp = mtmp->nmon;
  283. 		}
  284. 		if (!done_stopprint) putstr(endwin, 0, pbuf);
  285. 		pbuf[0] = '\0';
  286. 	    } else {
  287. 		if (!done_stopprint) Strcat(pbuf, " ");
  288. 	    }
  289. 	    if (!done_stopprint) {
  290. 		Sprintf(eos(pbuf), "%s with %ld point%s,",
  291. 			how==ASCENDED ? "went to your reward" :
  292. 					"escaped from the dungeon",
  293. 			u.urexp, plur(u.urexp));
  294. 		putstr(endwin, 0, pbuf);
  295. 	    }
  296.  
  297. 	    if (!done_stopprint)
  298. 		artifact_score(invent, FALSE, endwin);	/* list artifacts */
  299.  
  300. 	    /* list valuables here */
  301. 	    for (val = valuables; val->list; val++) {
  302. 		sort_valuables(val->list, val->size);
  303. 		for (i = 0; i < val->size && !done_stopprint; i++) {
  304. 		    int typ = val->list[i].typ;
  305. 		    long count = val->list[i].count;
  306.  
  307. 		    if (count == 0L) continue;
  308. 		    if (objects[typ].oc_class != GEM_CLASS || typ <= LAST_GEM) {
  309. 			otmp = mksobj(typ, FALSE, FALSE);
  310. 			makeknown(otmp->otyp);
  311. 			otmp->known = 1;	/* for fake amulets */
  312. 			otmp->dknown = 1;	/* seen it (blindness fix) */
  313. 			otmp->onamelth = 0;
  314. 			otmp->quan = count;
  315. 			Sprintf(pbuf, "%8ld %s (worth %ld %s),",
  316. 				count, xname(otmp),
  317. 				count * (long)objects[typ].oc_cost, currency(2L));
  318. 			obfree(otmp, (struct obj *)0);
  319. 		    } else {
  320. 			Sprintf(pbuf,
  321. 				"%8ld worthless piece%s of colored glass,",
  322. 				count, plur(count));
  323. 		    }
  324. 		    putstr(endwin, 0, pbuf);
  325. 		}
  326. 	    }
  327.  
  328. 	} else if (!done_stopprint) {
  329. 	    /* did not escape or ascend */
  330. 	    if (u.uz.dnum == 0 && u.uz.dlevel <= 0) {
  331. 		/* level teleported out of the dungeon; `how' is DIED,
  332. 		   due to falling or to "arriving at heaven prematurely" */
  333. 		Sprintf(pbuf, "You %s beyond the confines of the dungeon",
  334. 			(u.uz.dlevel < 0) ? "passed away" : ends[how]);
  335. 	    } else {
  336. 		/* more conventional demise */
  337. 		const char *where = dungeons[u.uz.dnum].dname;
  338.  
  339. 		if (Is_astralevel(&u.uz)) where = "The Astral Plane";
  340. 		Sprintf(pbuf, "You %s in %s", ends[how], where);
  341. 		if (!In_endgame(&u.uz) && !Is_knox(&u.uz))
  342. 		    Sprintf(eos(pbuf), " on dungeon level %d",
  343. 			    In_quest(&u.uz) ? dunlev(&u.uz) : depth(&u.uz));
  344. 	    }
  345.  
  346. 	    Sprintf(eos(pbuf), " with %ld point%s,",
  347. 		    u.urexp, plur(u.urexp));
  348. 	    putstr(endwin, 0, pbuf);
  349. 	}
  350.  
  351. 	if (!done_stopprint) {
  352. 	    Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.",
  353. 		    umoney, plur(umoney), moves, plur(moves));
  354. 	    putstr(endwin, 0, pbuf);
  355. 	}
  356. 	if (!done_stopprint) {
  357. 	    Sprintf(pbuf,
  358. 	     "You were level %d with a maximum of %d hit point%s when you %s.",
  359. 		    u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]);
  360. 	    putstr(endwin, 0, pbuf);
  361. 	    putstr(endwin, 0, "");
  362. 	}
  363. 	if (!done_stopprint)
  364. 	    display_nhwindow(endwin, TRUE);
  365. 	if (endwin != WIN_ERR)
  366. 	    destroy_nhwindow(endwin);
  367.  
  368. 	/* "So when I die, the first thing I will see in Heaven is a
  369. 	 * score list?" */
  370. 	if (flags.toptenwin) {
  371. 	    topten(how);
  372. 	    if (have_windows)
  373. 		exit_nhwindows((char *)0);
  374. 	} else {
  375. 	    if (have_windows)
  376. 		exit_nhwindows((char *)0);
  377. 	    topten(how);
  378. 	}
  379.  
  380. 	if(done_stopprint) { raw_print(""); raw_print(""); }
  381. 	terminate(EXIT_SUCCESS);
  382. }
  383.  
  384.  

[edit] container_contents

  1. void
  2. container_contents(list, identified, all_containers)
  3. struct obj *list;
  4. boolean identified, all_containers;
  5. {
  6. 	register struct obj *box, *obj;
  7. 	char buf[BUFSZ];
  8.  
  9. 	for (box = list; box; box = box->nobj) {
  10. 	    if (Is_container(box) || box->otyp == STATUE) {
  11. 		if (box->otyp == BAG_OF_TRICKS) {
  12. 		    continue;	/* wrong type of container */
  13. 		} else if (box->cobj) {
  14. 		    winid tmpwin = create_nhwindow(NHW_MENU);
  15. 		    Sprintf(buf, "Contents of %s:", the(xname(box)));
  16. 		    putstr(tmpwin, 0, buf);
  17. 		    putstr(tmpwin, 0, "");
  18. 		    for (obj = box->cobj; obj; obj = obj->nobj) {
  19. 			if (identified) {
  20. 			    makeknown(obj->otyp);
  21. 			    obj->known = obj->bknown =
  22. 			    obj->dknown = obj->rknown = 1;
  23. 			}
  24. 			putstr(tmpwin, 0, doname(obj));
  25. 		    }
  26. 		    display_nhwindow(tmpwin, TRUE);
  27. 		    destroy_nhwindow(tmpwin);
  28. 		    if (all_containers)
  29. 			container_contents(box->cobj, identified, TRUE);
  30. 		} else {
  31. 		    pline("%s empty.", Tobjnam(box, "are"));
  32. 		    display_nhwindow(WIN_MESSAGE, FALSE);
  33. 		}
  34. 	    }
  35. 	    if (!all_containers)
  36. 		break;
  37. 	}
  38. }
  39.  
  40.  

[edit] terminate

  1. /* should be called with either EXIT_SUCCESS or EXIT_FAILURE */
  2. void
  3. terminate(status)
  4. int status;
  5. {
  6. #ifdef MAC
  7. 	getreturn("to exit");
  8. #endif
  9. 	/* don't bother to try to release memory if we're in panic mode, to
  10. 	   avoid trouble in case that happens to be due to memory problems */
  11. 	if (!program_state.panicking) {
  12. 	    freedynamicdata();
  13. 	    dlb_cleanup();
  14. 	}
  15.  
  16. 	nethack_exit(status);
  17. }
  18.  

[edit] list_vanquished

  1. STATIC_OVL void
  2. list_vanquished(defquery, ask)
  3. char defquery;
  4. boolean ask;
  5. {
  6. register int i, lev;
  7. int ntypes = 0, max_lev = 0, nkilled;
  8. long total_killed = 0L;
  9. char c;
  10. winid klwin;
  11. char buf[BUFSZ];
  12.  
  13. /* get totals first */
  14. for (i = LOW_PM; i < NUMMONS; i++) {
  15. 	if (mvitals[i].died) ntypes++;
  16. 	total_killed += (long)mvitals[i].died;
  17. 	if (mons[i].mlevel > max_lev) max_lev = mons[i].mlevel;
  18. }
  19.  
  20. /* vanquished creatures list;
  21. * includes all dead monsters, not just those killed by the player
  22. */
  23. if (ntypes != 0) {
  24. 	c = ask ? yn_function("Do you want an account of creatures vanquished?",
  25. 			      ynqchars, defquery) : defquery;
  26. 	if (c == 'q') done_stopprint++;
  27. 	if (c == 'y') {
  28. 	    klwin = create_nhwindow(NHW_MENU);
  29. 	    putstr(klwin, 0, "Vanquished creatures:");
  30. 	    putstr(klwin, 0, "");
  31.  
  32. 	    /* countdown by monster "toughness" */
  33. 	    for (lev = max_lev; lev >= 0; lev--)
  34. 	      for (i = LOW_PM; i < NUMMONS; i++)
  35. 		if (mons[i].mlevel == lev && (nkilled = mvitals[i].died) > 0) {
  36. 		    if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) {
  37. 			Sprintf(buf, "%s%s",
  38. 				!type_is_pname(&mons[i]) ? "The " : "",
  39. 				mons[i].mname);
  40. 			if (nkilled > 1) {
  41. 			    switch (nkilled) {
  42. 				case 2:  Sprintf(eos(buf)," (twice)");  break;
  43. 				case 3:  Sprintf(eos(buf)," (thrice)");  break;
  44. 				default: Sprintf(eos(buf)," (%d time%s)",
  45. 						 nkilled, plur(nkilled));
  46. 					 break;
  47. 			    }
  48. 			}
  49. 		    } else {
  50. 			/* trolls or undead might have come back,
  51. 			   but we don't keep track of that */
  52. 			if (nkilled == 1)
  53. 			    Strcpy(buf, an(mons[i].mname));
  54. 			else
  55. 			    Sprintf(buf, "%d %s",
  56. 				    nkilled, makeplural(mons[i].mname));
  57. 		    }
  58. 		    putstr(klwin, 0, buf);
  59. 		}
  60. 	    /*
  61. 	     * if (Hallucination)
  62. 	     *     putstr(klwin, 0, "and a partridge in a pear tree");
  63. 	     */
  64. 	    if (ntypes > 1) {
  65. 		putstr(klwin, 0, "");
  66. 		Sprintf(buf, "%ld creatures vanquished.", total_killed);
  67. 		putstr(klwin, 0, buf);
  68. 	    }
  69. 	    display_nhwindow(klwin, TRUE);
  70. 	    destroy_nhwindow(klwin);
  71. 	}
  72. }
  73. }
  74.  

[edit] num_genocides

  1. /* number of monster species which have been genocided */
  2. int
  3. num_genocides()
  4. {
  5. int i, n = 0;
  6.  
  7. for (i = LOW_PM; i < NUMMONS; ++i)
  8. 	if (mvitals[i].mvflags & G_GENOD) ++n;
  9.  
  10. return n;
  11. }
  12.  

[edit] list_genocided

  1. STATIC_OVL void
  2. list_genocided(defquery, ask)
  3. char defquery;
  4. boolean ask;
  5. {
  6. register int i;
  7. int ngenocided;
  8. char c;
  9. winid klwin;
  10. char buf[BUFSZ];
  11.  
  12. ngenocided = num_genocides();
  13.  
  14. /* genocided species list */
  15. if (ngenocided != 0) {
  16. 	c = ask ? yn_function("Do you want a list of species genocided?",
  17. 			      ynqchars, defquery) : defquery;
  18. 	if (c == 'q') done_stopprint++;
  19. 	if (c == 'y') {
  20. 	    klwin = create_nhwindow(NHW_MENU);
  21. 	    putstr(klwin, 0, "Genocided species:");
  22. 	    putstr(klwin, 0, "");
  23.  
  24. 	    for (i = LOW_PM; i < NUMMONS; i++)
  25. 		if (mvitals[i].mvflags & G_GENOD) {
  26. 		    if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST)
  27. 			Sprintf(buf, "%s%s",
  28. 				!type_is_pname(&mons[i]) ? "" : "the ",
  29. 				mons[i].mname);
  30. 		    else
  31. 			Strcpy(buf, makeplural(mons[i].mname));
  32. 		    putstr(klwin, 0, buf);
  33. 		}
  34.  
  35. 	    putstr(klwin, 0, "");
  36. 	    Sprintf(buf, "%d species genocided.", ngenocided);
  37. 	    putstr(klwin, 0, buf);
  38.  
  39. 	    display_nhwindow(klwin, TRUE);
  40. 	    destroy_nhwindow(klwin);
  41. 	}
  42. }
  43. }
  44.  
  45. /*end.c*/
Personal tools
Namespaces

Variants
Actions
Navigation
Contributing
Toolbox