1 /* NetHack 3.6 end.c $NHDT-Date: 1448241780 2015/11/23 01:23:00 $ $NHDT-Branch: master $:$NHDT-Revision: 1.108 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #define NEED_VARARGS /* comment line for pre-compiled headers */
16 /* add b to long a, convert wraparound to max value */
17 #define nowrap_add(a, b) (a = ((a + b) < 0 ? LONG_MAX : (a + b)))
19 /* these probably ought to be generated by makedefs, like LAST_GEM */
20 #define FIRST_GEM DILITHIUM_CRYSTAL
21 #define FIRST_AMULET AMULET_OF_ESP
22 #define LAST_AMULET AMULET_OF_YENDOR
24 struct valuable_data {
29 static struct valuable_data
30 gems[LAST_GEM + 1 - FIRST_GEM + 1], /* 1 extra for glass */
31 amulets[LAST_AMULET + 1 - FIRST_AMULET];
33 static struct val_list {
34 struct valuable_data *list;
36 } valuables[] = { { gems, sizeof gems / sizeof *gems },
37 { amulets, sizeof amulets / sizeof *amulets },
41 STATIC_PTR void FDECL(done_intr, (int));
42 #if defined(UNIX) || defined(VMS) || defined(__EMX__)
43 static void FDECL(done_hangup, (int));
46 STATIC_DCL void FDECL(disclose, (int, BOOLEAN_P));
47 STATIC_DCL void FDECL(get_valuables, (struct obj *));
48 STATIC_DCL void FDECL(sort_valuables, (struct valuable_data *, int));
49 STATIC_DCL void FDECL(artifact_score, (struct obj *, BOOLEAN_P, winid));
50 STATIC_DCL void FDECL(really_done, (int)) NORETURN;
51 STATIC_DCL boolean FDECL(odds_and_ends, (struct obj *, int));
52 STATIC_DCL void FDECL(savelife, (int));
53 STATIC_DCL void FDECL(list_vanquished, (CHAR_P, BOOLEAN_P));
54 STATIC_DCL void FDECL(list_genocided, (CHAR_P, BOOLEAN_P));
55 STATIC_DCL boolean FDECL(should_query_disclose_option, (int, char *));
56 STATIC_DCL int NDECL(num_extinct);
58 #if defined(__BEOS__) || defined(MICRO) || defined(WIN32) || defined(OS2)
59 extern void FDECL(nethack_exit, (int));
61 #define nethack_exit exit
64 #define done_stopprint program_state.stopprint
67 #define NH_abort NH_abort_
71 #define NH_abort_() Abort(0)
74 #define NH_abort_() (void) abort()
77 #define NH_abort_() win32_abort()
79 #define NH_abort_() abort()
86 #ifdef PANICTRACE_LIBC
90 /* What do we try and in what order? Tradeoffs:
91 * libc: +no external programs required
92 * -requires newish libc/glibc
94 * gdb: +gives more detailed information
95 * +works on more OS versions
96 * -requires -g, which may preclude -O on some compilers
99 #define SYSOPT_PANICTRACE_GDB sysopt.panictrace_gdb
100 #ifdef PANICTRACE_LIBC
101 #define SYSOPT_PANICTRACE_LIBC sysopt.panictrace_libc
103 #define SYSOPT_PANICTRACE_LIBC 0
106 #define SYSOPT_PANICTRACE_GDB (nh_getenv("NETHACK_USE_GDB") == 0 ? 0 : 2)
107 #ifdef PANICTRACE_LIBC
108 #define SYSOPT_PANICTRACE_LIBC 1
110 #define SYSOPT_PANICTRACE_LIBC 0
114 static void NDECL(NH_abort);
116 static void FDECL(panictrace_handler, (int));
118 static boolean NDECL(NH_panictrace_libc);
119 static boolean NDECL(NH_panictrace_gdb);
123 void panictrace_handler(
124 sig_unused) /* called as signal() handler, so sent at least one arg */
125 int sig_unused UNUSED;
127 #define SIG_MSG "\nSignal received.\n"
128 (void) write(2, SIG_MSG, sizeof(SIG_MSG) - 1);
133 panictrace_setsignals(set)
136 #define SETSIGNAL(sig) \
137 (void) signal(sig, set ? (SIG_RET_TYPE) panictrace_handler : SIG_DFL);
157 SETSIGNAL(SIGSTKFLT);
167 #endif /* NO_SIGNAL */
172 int gdb_prio = SYSOPT_PANICTRACE_GDB;
173 int libc_prio = SYSOPT_PANICTRACE_LIBC;
174 static boolean aborting = FALSE;
181 if (gdb_prio == libc_prio && gdb_prio > 0)
184 if (gdb_prio > libc_prio) {
185 NH_panictrace_gdb() || (libc_prio && NH_panictrace_libc());
187 NH_panictrace_libc() || (gdb_prio && NH_panictrace_gdb());
191 /* overload otherwise unused priority for debug mode: 1 = show
192 traceback and exit; 2 = show traceback and stay in debugger */
193 /* if (wizard && gdb_prio == 1) gdb_prio = 2; */
194 vms_traceback(gdb_prio);
195 (void) libc_prio; /* half-hearted attempt at lint suppression */
200 panictrace_setsignals(FALSE);
208 #ifdef PANICTRACE_LIBC
213 raw_print("Generating more information you may report:\n");
214 count = backtrace(bt, SIZE(bt));
215 info = backtrace_symbols(bt, count);
216 for (x = 0; x < count; x++) {
217 raw_printf("[%lu] %s", (unsigned long) x, info[x]);
219 /* free(info); -- Don't risk it. */
223 #endif /* !PANICTRACE_LIBC */
227 * fooPATH file system path for foo
228 * fooVAR (possibly const) variable containing fooPATH
230 #ifdef PANICTRACE_GDB
232 #define GDBVAR sysopt.gdbpath
233 #define GREPVAR sysopt.greppath
235 #define GDBVAR GDBPATH
236 #define GREPVAR GREPPATH
238 #endif /* PANICTRACE_GDB */
243 #ifdef PANICTRACE_GDB
244 /* A (more) generic method to get a stack trace - invoke
246 char *gdbpath = GDBVAR;
247 char *greppath = GREPVAR;
251 if (gdbpath == NULL || gdbpath[0] == 0)
253 if (greppath == NULL || greppath[0] == 0)
256 sprintf(buf, "%s -n -q %s %d 2>&1 | %s '^#'", gdbpath, ARGV0, getpid(),
258 gdb = popen(buf, "w");
260 raw_print("Generating more information you may report:\n");
261 fprintf(gdb, "bt\nquit\ny");
271 #endif /* !PANICTRACE_GDB */
273 #endif /* PANICTRACE */
275 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\8eg
\82í
\82È
\82¢*/
277 * The order of these needs to match the macros in hack.h.
279 static NEARDATA const char *deaths[] = {
280 /* the array of death */
281 "died", "choked", "poisoned", "starvation", "drowning", "burning",
282 "dissolving under the heat and pressure", "crushed", "turned to stone",
283 "turned into slime", "genocided", "panic", "trickery", "quit",
284 "escaped", "ascended"
288 static NEARDATA const char *ends[] = {
291 "died", "choked", "were poisoned",
292 "starved", "drowned", "burned",
293 "dissolved in the lava",
294 "were crushed", "turned to stone",
295 "turned into slime", "were genocided",
296 "panicked", "were tricked", "quit",
297 "escaped", "ascended"
298 #else /*JP:
\8dÅ
\8cã
\82É
\81u
\8eE
\82³
\82ê
\82½
\81v
\92Ç
\89Á */
299 "
\8e\80\82ñ
\82¾", "
\92\82\91§
\82µ
\82½", "
\93Å
\82É
\82¨
\82©
\82³
\82ê
\82½",
300 "
\89ì
\8e\80\82µ
\82½", "
\93M
\8e\80\82µ
\82½", "
\8fÄ
\8e\80\82µ
\82½",
301 "
\97n
\8aâ
\82É
\97n
\82¯
\82½",
302 "
\89\9f\82µ
\92×
\82³
\82ê
\82½", "
\90Î
\82É
\82È
\82Á
\82½",
303 "
\82Ç
\82ë
\82Ç
\82ë
\82É
\97n
\82¯
\82½", "
\8bs
\8eE
\82³
\82ê
\82½",
304 "
\83p
\83j
\83b
\83N
\82É
\82¨
\82¿
\82¢
\82Á
\82½", "
\8aï
\96
\82È
\8fo
\97\88\8e\96\82É
\89ï
\82Á
\82½", "
\94²
\82¯
\82½",
305 "
\92E
\8fo
\82µ
\82½", "
\8f¸
\93V
\82µ
\82½", "
\8eE
\82³
\82ê
\82½"
309 static boolean Schroedingers_cat = FALSE;
313 done1(sig_unused) /* called as signal() handler, so sent at least one arg */
314 int sig_unused UNUSED;
317 (void) signal(SIGINT, SIG_IGN);
321 (void) signal(SIGINT, (SIG_RET_TYPE) done1);
323 clear_nhwindow(WIN_MESSAGE);
333 /* "#quit" command or keyboard interrupt */
338 if (!paranoid_query(ParanoidQuit, "Really quit?")) {
340 if (!paranoid_query(ParanoidQuit, "
\96{
\93\96\82É
\82â
\82ß
\82é
\81H")) {
342 (void) signal(SIGINT, (SIG_RET_TYPE) done1);
344 clear_nhwindow(WIN_MESSAGE);
350 u.uinvulnerable = FALSE; /* avoid ctrl-C bug -dlc */
355 #if (defined(UNIX) || defined(VMS) || defined(LATTICE))
359 extern int debuggable; /* sys/vms/vmsmisc.c, vmsunix.c */
361 c = !debuggable ? 'n' : ynq("Enter debugger?");
364 c = ynq("Create SnapShot?");
366 c = ynq("Dump core?");
371 (void) signal(SIGINT, (SIG_RET_TYPE) done1);
373 exit_nhwindows((char *) 0);
388 done_intr(sig_unused) /* called as signal() handler, so sent at least 1 arg */
389 int sig_unused UNUSED;
392 (void) signal(SIGINT, SIG_IGN);
393 #if defined(UNIX) || defined(VMS)
394 (void) signal(SIGQUIT, SIG_IGN);
399 #if defined(UNIX) || defined(VMS) || defined(__EMX__)
400 /* signal() handler */
405 program_state.done_hup++;
406 sethanguphandler((void FDECL((*), (int) )) SIG_IGN);
411 #endif /* NO_SIGNAL */
414 done_in_by(mtmp, how)
419 struct permonst *mptr = mtmp->data,
420 *champtr = ((mtmp->cham >= LOW_PM)
423 boolean distorted = (boolean) (Hallucination && canspotmon(mtmp)),
424 mimicker = (mtmp->m_ap_type == M_AP_MONSTER),
425 imitator = (mptr != champtr || mimicker);
428 You((how == STONING) ? "turn to stone..." : "die...");
430 You((how == STONING) ? "
\90Î
\82É
\82È
\82Á
\82½
\81D
\81D
\81D" : "
\8e\80\82É
\82Ü
\82µ
\82½
\81D
\81D
\81D");
431 mark_synch(); /* flush buffered screen output */
433 killer.format = KILLED_BY_AN;
434 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82É
\82Í
\8aÖ
\8cW
\82È
\82¢
\82Ì
\82Å
\82Ü
\82Æ
\82ß
\82Ä
\83R
\83\81\83\93\83g
\83A
\83E
\83g */
435 /* "killed by the high priest of Crom" is okay,
436 "killed by the high priest" alone isn't */
437 if ((mptr->geno & G_UNIQ) != 0 && !(imitator && !mimicker)
438 && !(mptr == &mons[PM_HIGH_PRIEST] && !mtmp->ispriest)) {
439 if (!type_is_pname(mptr))
441 killer.format = KILLED_BY;
443 /* _the_ <invisible> <distorted> ghost of Dudley */
444 if (mptr == &mons[PM_GHOST] && has_mname(mtmp)) {
446 killer.format = KILLED_BY;
451 Strcat(buf, "invisible ");
453 Strcat(buf, "
\93§
\96¾
\82È");
456 Strcat(buf, "hallucinogen-distorted ");
458 Strcat(buf, "
\8c¶
\8ao
\82Å
\98c
\82ñ
\82¾");
462 const char *realnm = champtr->mname, *fakenm = mptr->mname;
463 boolean alt = is_vampshifter(mtmp);
466 /* realnm is already correct because champtr==mptr;
467 set up fake mptr for type_is_pname/the_unique_pm */
468 mptr = &mons[mtmp->mappearance];
469 fakenm = mptr->mname;
471 } else if (alt && strstri(realnm, "vampire")
472 && !strcmp(fakenm, "vampire bat")) {
473 /* special case: use "vampire in bat form" in preference
474 to redundant looking "vampire in vampire bat form" */
477 } else if (alt && strstri(realnm, "
\8bz
\8c\8c\8bS")
478 && !strcmp(fakenm, "
\8bz
\8c\8c\82±
\82¤
\82à
\82è")) {
479 /*
\81u
\8bz
\8c\8c\82±
\82¤
\82à
\82è
\82Ì
\8ep
\82Ì
\8bz
\8c\8c\8bS
\81v
\82Í
\8fç
\92·
\82È
\82Ì
\82Å
480 \81u
\82±
\82¤
\82à
\82è
\82Ì
\8ep
\82Ì
\8bz
\8c\8c\8bS
\81v
\82Ì
\8c`
\82É
\82·
\82é */
481 fakenm = "
\82±
\82¤
\82à
\82è";
485 /* for the alternate format, always suppress any article;
486 pname and the_unique should also have s_suffix() applied,
487 but vampires don't take on any shapes which warrant that */
488 if (alt || type_is_pname(mptr)) /* no article */
489 Strcpy(shape, fakenm);
490 else if (the_unique_pm(mptr)) /* "the"; don't use the() here */
491 Sprintf(shape, "the %s", fakenm);
493 Strcpy(shape, an(fakenm));
494 #else /*JP:
\93ú
\96{
\8cê
\82Å
\82Í
\83V
\83\93\83v
\83\8b*/
495 Strcpy(shape, fakenm);
497 /* omit "called" to avoid excessive verbosity */
500 alt ? "%s in %s form"
501 : mimicker ? "%s disguised as %s"
506 alt ? "%s
\82Ì
\8ep
\82Ì%s"
507 : mimicker ? "%s
\82Ì
\82Ó
\82è
\82ð
\82µ
\82Ä
\82¢
\82é%s"
508 : "%s
\82Ì
\82Ü
\82Ë
\82ð
\82µ
\82Ä
\82¢
\82é%s",
511 mptr = mtmp->data; /* reset for mimicker case */
512 } else if (mptr == &mons[PM_GHOST]) {
514 Strcat(buf, "ghost");
516 Sprintf(eos(buf), " of %s", MNAME(mtmp));
519 Sprintf(eos(buf), "%s
\82Ì
\97H
\97ì", MNAME(mtmp));
521 Strcat(buf, "
\97H
\97ì");
523 } else if (mtmp->isshk) {
525 const char *shknm = shkname(mtmp),
526 *honorific = shkname_is_pname(mtmp) ? ""
527 : mtmp->female ? "Ms. " : "Mr. ";
529 Sprintf(eos(buf), "%s%s, the shopkeeper", honorific, shknm);
531 Sprintf(eos(buf), "%s
\82Æ
\82¢
\82¤
\96¼
\82Ì
\93X
\8eå", shkname(mtmp));
533 killer.format = KILLED_BY;
534 } else if (mtmp->ispriest || mtmp->isminion) {
535 /* m_monnam() suppresses "the" prefix plus "invisible", and
536 it overrides the effect of Hallucination on priestname() */
537 Strcat(buf, m_monnam(mtmp));
540 Strcat(buf, mptr->mname);
542 Sprintf(eos(buf), " called %s", MNAME(mtmp));
544 Strcat(buf, mptr->mname);
548 Strcpy(killer.name, buf);
549 if (mptr->mlet == S_WRAITH)
550 u.ugrave_arise = PM_WRAITH;
551 else if (mptr->mlet == S_MUMMY && urace.mummynum != NON_PM)
552 u.ugrave_arise = urace.mummynum;
553 else if (mptr->mlet == S_VAMPIRE && Race_if(PM_HUMAN))
554 u.ugrave_arise = PM_VAMPIRE;
555 else if (mptr == &mons[PM_GHOUL])
556 u.ugrave_arise = PM_GHOUL;
557 /* this could happen if a high-end vampire kills the hero
558 when ordinary vampires are genocided; ditto for wraiths */
559 if (u.ugrave_arise >= LOW_PM
560 && (mvitals[u.ugrave_arise].mvflags & G_GENOD))
561 u.ugrave_arise = NON_PM;
566 topten.c
\82Ì killed_by_prefix
\82ð
\8eQ
\8fÆ
\82Ì
\82±
\82Æ
\81B
567 STONING
\82Ì
\8fê
\8d\87\82Í "
\90Î
\89»
\82µ
\82½"
\82ª
\95â
\82í
\82ê
\82é
\81B
569 Strcat(buf, "
\82Ì
\8dU
\8c\82\82Å");
573 DIED
\82Ì
\8fê
\8d\87\82Í
\92Ê
\8fí "
\8e\80\82ñ
\82¾"
\82ª
\95â
\82í
\82ê
\82é
\82ª
\81A
574 \89ö
\95¨
\82É
\82æ
\82é
\8fê
\8d\87\82Í "
\82É
\8eE
\82³
\82ê
\82½"
\82ð
\95â
\82¤
\81B
576 killer.format = KILLED_SUFFIX;
584 #if defined(WIN32) && !defined(SYSCF)
585 #define NOTIFY_NETHACK_BUGS
590 VA_DECL(const char *, str)
593 VA_INIT(str, char *);
595 if (program_state.panicking++)
596 NH_abort(); /* avoid loops - this should never happen*/
598 if (iflags.window_inited) {
599 raw_print("\r\nOops...");
600 wait_synch(); /* make sure all pending output gets flushed */
601 exit_nhwindows((char *) 0);
602 iflags.window_inited = 0; /* they're gone; force raw_print()ing */
605 raw_print(program_state.gameover
607 ? "Postgame wrapup disrupted."
609 ? "
\83Q
\81[
\83\80\8fI
\97¹
\8e\9e\82Ì
\8f\88\97\9d\82ª
\95ö
\89ó
\82µ
\82½
\81D"
610 : !program_state.something_worth_saving
612 ? "Program initialization has failed."
614 ? "
\83v
\83\8d\83O
\83\89\83\80\82Ì
\8f\89\8aú
\89»
\82É
\8e¸
\94s
\82µ
\82½
\81D"
616 : "Suddenly, the dungeon collapses.");
618 : "
\93Ë
\91R
\96À
\8b{
\82ª
\95ö
\82ê
\82½
\81D");
620 #if defined(NOTIFY_NETHACK_BUGS)
622 raw_printf("Report the following error to \"%s\" or at \"%s\".",
623 DEVTEAM_EMAIL, DEVTEAM_URL);
624 else if (program_state.something_worth_saving)
625 raw_print("\nError save file being written.\n");
629 const char *maybe_rebuild = !program_state.something_worth_saving
631 : "\nand it may be possible to rebuild.";
633 const char *maybe_rebuild = !program_state.something_worth_saving
635 : "\n
\95\9c\8b\8c\82Å
\82«
\82é
\89Â
\94\
\90«
\82ª
\82 \82è
\82Ü
\82·
\81D";
639 raw_printf("To report this error, %s%s", sysopt.support,
641 else if (sysopt.fmtd_wizard_list) /* formatted SYSCF WIZARDS */
642 raw_printf("To report this error, contact %s%s",
643 sysopt.fmtd_wizard_list, maybe_rebuild);
646 raw_printf("Report error to \"%s\"%s", WIZARD_NAME,
649 raw_printf("\"%s\"
\82É
\83G
\83\89\81[
\82ð
\95ñ
\8d\90\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81D%s", WIZARD_NAME,
654 /* XXX can we move this above the prints? Then we'd be able to
655 * suppress "it may be possible to rebuild" based on dosave0()
656 * or say it's NOT possible to rebuild. */
657 if (program_state.something_worth_saving) {
658 set_error_savefile();
660 /* os/win port specific recover instructions */
662 raw_printf("%s", sysopt.recover);
669 Vsprintf(buf, str, VA_ARGS);
671 paniclog("panic", buf);
674 interject(INTERJECT_PANIC);
676 #if defined(UNIX) || defined(VMS) || defined(LATTICE) || defined(WIN32)
678 NH_abort(); /* generate core dump */
681 really_done(PANICKED);
685 should_query_disclose_option(category, defquery)
693 if ((dop = index(disclosure_options, category)) != 0) {
694 idx = (int) (dop - disclosure_options);
695 if (idx < 0 || idx >= NUM_DISCLOSURE_OPTIONS) {
697 "should_query_disclose_option: bad disclosure index %d %c",
699 *defquery = DISCLOSE_PROMPT_DEFAULT_YES;
702 if (flags.end_disclose[idx] == DISCLOSE_YES_WITHOUT_PROMPT) {
705 } else if (flags.end_disclose[idx] == DISCLOSE_NO_WITHOUT_PROMPT) {
708 } else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_YES) {
716 impossible("should_query_disclose_option: bad category %c", category);
725 char c = '\0', defquery;
729 if (invent && !done_stopprint) {
732 Sprintf(qbuf, "Do you want to see what you had when you %s?",
733 (how == QUIT) ? "quit" : "died");
735 Sprintf(qbuf,"%s
\82Æ
\82«
\89½
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82½
\82©
\8c©
\82Ü
\82·
\82©
\81H",
736 (how == QUIT) ? "
\82â
\82ß
\82½" : "
\8e\80\82ñ
\82¾");
740 Strcpy(qbuf, "Do you want your possessions identified?");
742 Strcpy(qbuf,"
\8e\9d\82¿
\95¨
\82ð
\8e¯
\95Ê
\82µ
\82Ü
\82·
\82©
\81H");
744 ask = should_query_disclose_option('i', &defquery);
745 c = ask ? yn_function(qbuf, ynqchars, defquery) : defquery;
749 for (obj = invent; obj; obj = obj->nobj) {
750 makeknown(obj->otyp);
751 obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
752 if (Is_container(obj) || obj->otyp == STATUE)
753 obj->cknown = obj->lknown = 1;
755 (void) display_inventory((char *) 0, TRUE);
756 container_contents(invent, TRUE, TRUE, FALSE);
762 if (!done_stopprint) {
763 ask = should_query_disclose_option('a', &defquery);
765 c = ask ? yn_function("Do you want to see your attributes?", ynqchars,
769 c = ask ? yn_function("
\91®
\90«
\82ð
\8c©
\82Ü
\82·
\82©
\81H", ynqchars,
774 enlightenment((BASICENLIGHTENMENT | MAGICENLIGHTENMENT),
775 (how >= PANICKED) ? ENL_GAMEOVERALIVE
781 if (!done_stopprint) {
782 ask = should_query_disclose_option('v', &defquery);
783 list_vanquished(defquery, ask);
786 if (!done_stopprint) {
787 ask = should_query_disclose_option('g', &defquery);
788 list_genocided(defquery, ask);
791 if (!done_stopprint) {
792 ask = should_query_disclose_option('c', &defquery);
794 c = ask ? yn_function("Do you want to see your conduct?", ynqchars,
798 c = ask ? yn_function("
\82Ç
\82¤
\82¢
\82¤
\8ds
\93®
\82ð
\82Æ
\82Á
\82½
\82©
\8c©
\82Ü
\82·
\82©
\81H", ynqchars,
803 show_conduct((how >= PANICKED) ? 1 : 2);
808 if (!done_stopprint) {
809 ask = should_query_disclose_option('o', &defquery);
811 c = ask ? yn_function("Do you want to see the dungeon overview?",
815 c = ask ? yn_function("
\96À
\8b{
\82Ì
\8aT
\97v
\82ð
\8c©
\82Ü
\82·
\82©
\81H",
820 show_overview((how >= PANICKED) ? 1 : 2, how);
826 /* try to get the player back in a viable state after being killed */
831 int uhpmin = max(2 * u.ulevel, 10);
833 if (u.uhpmax < uhpmin)
837 if (u.uhunger < 500) {
841 /* cure impending doom of sickness hero won't have time to fix */
842 if ((Sick & TIMEOUT) == 1L) {
844 set_itimeout(&Sick, 0L);
849 nomovemsg = "You survived that attempt on your life.";
851 nomovemsg = "
\82 \82È
\82½
\82Í
\90¶
\82«
\82È
\82ª
\82ç
\82¦
\82½
\81D";
857 if (u.utrap && u.utraptype == TT_LAVA)
860 u.ugrave_arise = NON_PM;
866 * Get valuables from the given list. Revised code: the list always remains
871 struct obj *list; /* inventory or container contents */
873 register struct obj *obj;
876 /* find amulets and gems, ignoring all artifacts */
877 for (obj = list; obj; obj = obj->nobj)
878 if (Has_contents(obj)) {
879 get_valuables(obj->cobj);
880 } else if (obj->oartifact) {
882 } else if (obj->oclass == AMULET_CLASS) {
883 i = obj->otyp - FIRST_AMULET;
884 if (!amulets[i].count) {
885 amulets[i].count = obj->quan;
886 amulets[i].typ = obj->otyp;
888 amulets[i].count += obj->quan; /* always adds one */
889 } else if (obj->oclass == GEM_CLASS && obj->otyp < LUCKSTONE) {
890 i = min(obj->otyp, LAST_GEM + 1) - FIRST_GEM;
891 if (!gems[i].count) {
892 gems[i].count = obj->quan;
893 gems[i].typ = obj->otyp;
895 gems[i].count += obj->quan;
901 * Sort collected valuables, most frequent to least. We could just
902 * as easily use qsort, but we don't care about efficiency here.
905 sort_valuables(list, size)
906 struct valuable_data list[];
907 int size; /* max value is less than 20 */
910 struct valuable_data ltmp;
912 /* move greater quantities to the front of the list */
913 for (i = 1; i < size; i++) {
914 if (list[i].count == 0)
915 continue; /* empty slot */
916 ltmp = list[i]; /* structure copy */
917 for (j = i; j > 0; --j)
918 if (list[j - 1].count >= ltmp.count)
921 list[j] = list[j - 1];
931 odds_and_ends(list, what)
936 for (otmp = list; otmp; otmp = otmp->nobj) {
938 case CAT_CHECK: /* Schroedinger's Cat */
939 /* Ascending is deterministic */
940 if (SchroedingersBox(otmp))
944 if (Has_contents(otmp))
945 return odds_and_ends(otmp->cobj, what);
950 /* called twice; first to calculate total, then to list relevant items */
952 artifact_score(list, counting, endwin)
954 boolean counting; /* true => add up points; false => display them */
960 short dummy; /* object type returned by artifact_name() */
962 for (otmp = list; otmp; otmp = otmp->nobj) {
963 if (otmp->oartifact || otmp->otyp == BELL_OF_OPENING
964 || otmp->otyp == SPE_BOOK_OF_THE_DEAD
965 || otmp->otyp == CANDELABRUM_OF_INVOCATION) {
966 value = arti_cost(otmp); /* zorkmid value */
967 points = value * 5 / 2; /* score value */
969 nowrap_add(u.urexp, points);
971 makeknown(otmp->otyp);
972 otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
973 /* assumes artifacts don't have quan > 1 */
975 Sprintf(pbuf, "%s%s (worth %ld %s and %ld points)",
976 the_unique_obj(otmp) ? "The " : "",
977 otmp->oartifact ? artifact_name(xname(otmp), &dummy)
978 : OBJ_NAME(objects[otmp->otyp]),
979 value, currency(value), points);
981 Sprintf(pbuf, "%s(%ld%s
\81C%ld
\83|
\83C
\83\93\83g
\82Ì
\89¿
\92l)
\81C",
982 otmp->oartifact ? artifact_name(xname(otmp), &dummy)
983 : OBJ_NAME(objects[otmp->otyp]),
984 value, currency(value), points);
986 putstr(endwin, 0, pbuf);
989 if (Has_contents(otmp))
990 artifact_score(otmp->cobj, counting, endwin);
994 /* Be careful not to call panic from here! */
999 if (how == TRICKED) {
1000 if (killer.name[0]) {
1001 paniclog("trickery", killer.name);
1006 You("are a very tricky wizard, it seems.");
1008 You("
\82Æ
\82Ä
\82à
\88µ
\82¢
\82É
\82
\82¢wizard
\82Ì
\82æ
\82¤
\82¾
\81D");
1013 if (how == ASCENDED || (!killer.name[0] && how == GENOCIDED))
1014 killer.format = NO_KILLER_PREFIX;
1015 /* Avoid killed by "a" burning or "a" starvation */
1016 if (!killer.name[0] && (how == STARVING || how == BURNING))
1017 killer.format = KILLED_BY;
1018 if (!killer.name[0] || how >= PANICKED)
1020 Strcpy(killer.name, deaths[how]);
1022 Strcpy(killer.name, ends[how]);
1026 if (Lifesaved && (how <= GENOCIDED)) {
1028 pline("But wait...");
1030 pline("
\82¿
\82å
\82Á
\82Æ
\82Ü
\82Á
\82½
\81D
\81D
\81D");
1031 makeknown(AMULET_OF_LIFE_SAVING);
1033 Your("medallion %s!", !Blind ? "begins to glow" : "feels warm");
1035 Your("
\96\82\8f\9c\82¯
\82Í%s
\81I", !Blind ? "
\8bP
\82«
\82Í
\82¶
\82ß
\82½" : "
\92g
\82©
\82
\82È
\82è
\82Í
\82¶
\82ß
\82½");
1040 You("
\93f
\82¢
\82½
\81D
\81D
\81D");
1042 You_feel("much better!");
1044 You("
\8bC
\95ª
\82ª
\82æ
\82
\82È
\82Á
\82½
\81I");
1046 pline_The("medallion crumbles to dust!");
1048 pline("
\96\82\8f\9c\82¯
\82Í
\82±
\82È
\82²
\82È
\82É
\82
\82¾
\82¯
\82½
\81I");
1052 (void) adjattrib(A_CON, -1, TRUE);
1054 if (how == GENOCIDED) {
1056 pline("Unfortunately you are still genocided...");
1058 pline("
\8ec
\94O
\82È
\82ª
\82ç
\81C
\82 \82È
\82½
\82Í
\8bs
\8eE
\82³
\82ê
\82½
\82Ü
\82Ü
\82¾
\81D
\81D
\81D");
1065 if ((wizard || discover) && (how <= GENOCIDED) &&
1067 !paranoid_query(ParanoidDie, "Die?")) {
1069 !paranoid_query(ParanoidDie, "
\8e\80\82ñ
\82Å
\82Ý
\82é
\81H")) {
1071 pline("OK, so you don't %s.", (how == CHOKING) ? "choke" : "die");
1073 You("
\8e\80\82È
\82È
\82©
\82Á
\82½
\81D");
1082 /* separated from done() in order to specify the __noreturn__ attribute */
1089 winid endwin = WIN_ERR;
1090 boolean bones_ok, have_windows = iflags.window_inited;
1091 struct obj *corpse = (struct obj *) 0;
1097 * The game is now over...
1099 program_state.gameover = 1;
1100 /* in case of a subsequent panic(), there's no point trying to save */
1101 program_state.something_worth_saving = 0;
1102 /* render vision subsystem inoperative */
1103 iflags.vision_inited = 0;
1105 /* might have been killed while using a disposable item, so make sure
1106 it's gone prior to inventory disclosure and creation of bones data */
1108 /* maybe not on object lists; if an active light source, would cause
1109 big trouble (`obj_is_local' panic) for savebones() -> savelev() */
1110 if (thrownobj && thrownobj->where == OBJ_FREE)
1111 dealloc_obj(thrownobj);
1112 if (kickedobj && kickedobj->where == OBJ_FREE)
1113 dealloc_obj(kickedobj);
1115 /* remember time of death here instead of having bones, rip, and
1116 topten figure it out separately and possibly getting different
1117 time or even day if player is slow responding to --More-- */
1118 urealtime.finish_time = endtime = getnow();
1119 urealtime.realtime += (long) (endtime - urealtime.start_timing);
1121 /* Sometimes you die on the first move. Life's not fair.
1122 * On those rare occasions you get hosed immediately, go out
1123 * smiling... :-) -3.
1125 if (moves <= 1 && how < PANICKED) /* You die... --More-- */
1127 pline("Do not pass go. Do not collect 200 %s.", currency(200L));
1129 pline("
\92\8d\88Ó
\88ê
\95b
\81C
\89ö
\89ä
\88ê
\90¶
\81C
\8e\80\96S
\88ê
\95à
\81D");
1132 wait_synch(); /* flush screen output */
1134 (void) signal(SIGINT, (SIG_RET_TYPE) done_intr);
1135 #if defined(UNIX) || defined(VMS) || defined(__EMX__)
1136 (void) signal(SIGQUIT, (SIG_RET_TYPE) done_intr);
1137 sethanguphandler(done_hangup);
1139 #endif /* NO_SIGNAL */
1141 bones_ok = (how < GENOCIDED) && can_make_bones();
1143 if (bones_ok && launch_in_progress())
1144 force_launch_placement();
1146 /* maintain ugrave_arise even for !bones_ok */
1147 if (how == PANICKED)
1148 u.ugrave_arise = (NON_PM - 3); /* no corpse, no grave */
1149 else if (how == BURNING || how == DISSOLVED) /* corpse burns up too */
1150 u.ugrave_arise = (NON_PM - 2); /* leave no corpse */
1151 else if (how == STONING)
1152 u.ugrave_arise = (NON_PM - 1); /* statue instead of corpse */
1153 else if (how == TURNED_SLIME)
1154 u.ugrave_arise = PM_GREEN_SLIME;
1156 /* if pets will contribute to score, populate mydogs list now
1157 (bones creation isn't a factor, but pline() messaging is) */
1158 if (how == ESCAPED || how == ASCENDED)
1162 killer.format = NO_KILLER_PREFIX;
1165 u.umortality++; /* skipped above when how==QUIT */
1167 Strcpy(killer.name, "quit while already on Charon's boat");
1169 Strcpy(killer.name, "
\8eO
\93r
\82Ì
\90ì
\82Ì
\93n
\82µ
\91D
\82É
\8fæ
\82Á
\82Ä
\82¢
\82é
\8aÔ
\82É
\94²
\82¯
\82½");
1172 if (how == ESCAPED || how == PANICKED)
1173 killer.format = NO_KILLER_PREFIX;
1175 if (how != PANICKED) {
1176 /* these affect score and/or bones, but avoid them during panic */
1177 taken = paybill((how == ESCAPED) ? -1 : (how != QUIT));
1181 taken = FALSE; /* lint; assert( !bones_ok ); */
1186 display_nhwindow(WIN_MESSAGE, FALSE);
1188 if (strcmp(flags.end_disclose, "none") && how != PANICKED)
1189 disclose(how, taken);
1191 /* finish_paybill should be called after disclosure but before bones */
1192 if (bones_ok && taken)
1195 /* grave creation should be after disclosure so it doesn't have
1196 this grave in the current level's features for #overview */
1197 if (bones_ok && u.ugrave_arise == NON_PM
1198 && !(mvitals[u.umonnum].mvflags & G_NOCORPSE)) {
1199 int mnum = u.umonnum;
1202 /* Base corpse on race when not poly'd since original
1203 * u.umonnum is based on role, and all role monsters
1206 mnum = (flags.female && urace.femalenum != NON_PM)
1210 corpse = mk_named_object(CORPSE, &mons[mnum], u.ux, u.uy, plname);
1212 Sprintf(pbuf, "%s, ", plname);
1214 Sprintf(pbuf, "%s
\82Ì
\95æ
\81C", plname);
1215 formatkiller(eos(pbuf), sizeof pbuf - strlen(pbuf), how);
1216 make_grave(u.ux, u.uy, pbuf);
1218 pbuf[0] = '\0'; /* clear grave text; also lint suppression */
1220 /* calculate score, before creating bones [container gold] */
1222 int deepest = deepest_lev_reached(FALSE);
1224 umoney = money_cnt(invent);
1226 umoney += hidden_gold(); /* accumulate gold from containers */
1227 tmp = umoney - tmp; /* net gain */
1233 tmp += 50L * (long) (deepest - 1);
1235 tmp += 1000L * (long) ((deepest > 30) ? 10 : deepest - 20);
1236 nowrap_add(u.urexp, tmp);
1238 /* ascension gives a score bonus iff offering to original deity */
1239 if (how == ASCENDED && u.ualign.type == u.ualignbase[A_ORIGINAL]) {
1240 /* retaining original alignment: score *= 2;
1241 converting, then using helm-of-OA to switch back: *= 1.5 */
1242 tmp = (u.ualignbase[A_CURRENT] == u.ualignbase[A_ORIGINAL])
1245 nowrap_add(u.urexp, tmp);
1249 if (u.ugrave_arise >= LOW_PM && u.ugrave_arise != PM_GREEN_SLIME) {
1250 /* give this feedback even if bones aren't going to be created,
1251 so that its presence or absence doesn't tip off the player to
1252 new bones or their lack; it might be a lie if makemon fails */
1254 Your("body rises from the dead as %s...",
1256 Your("
\91Ì
\82Í%s
\82Æ
\82µ
\82Ä
\8e\80\91Ì
\82©
\82ç
\91h
\82Á
\82½
\81D
\81D
\81D",
1257 an(mons[u.ugrave_arise].mname));
1258 display_nhwindow(WIN_MESSAGE, FALSE);
1263 if (!wizard || paranoid_query(ParanoidBones, "Save bones?"))
1265 if (!wizard || paranoid_query(ParanoidBones, "
\8d\9c\82ð
\82¤
\82ß
\82é
\81H"))
1266 savebones(how, endtime, corpse);
1267 /* corpse may be invalid pointer now so
1268 ensure that it isn't used again */
1269 corpse = (struct obj *) 0;
1272 /* update gold for the rip output, which can't use hidden_gold()
1273 (containers will be gone by then if bones just got saved...) */
1274 done_money = umoney;
1276 /* clean up unneeded windows */
1279 free_pickinv_cache(); /* extra persistent window if perm_invent */
1280 if (WIN_INVEN != WIN_ERR)
1281 destroy_nhwindow(WIN_INVEN), WIN_INVEN = WIN_ERR;
1282 display_nhwindow(WIN_MESSAGE, TRUE);
1283 destroy_nhwindow(WIN_MAP), WIN_MAP = WIN_ERR;
1284 #ifndef STATUS_VIA_WINDOWPORT
1285 destroy_nhwindow(WIN_STATUS), WIN_STATUS = WIN_ERR;
1287 destroy_nhwindow(WIN_MESSAGE), WIN_MESSAGE = WIN_ERR;
1289 if (!done_stopprint || flags.tombstone)
1290 endwin = create_nhwindow(NHW_TEXT);
1292 if (how < GENOCIDED && flags.tombstone && endwin != WIN_ERR)
1293 outrip(endwin, how, endtime);
1295 done_stopprint = 1; /* just avoid any more output */
1297 if (u.uhave.amulet) {
1299 Strcat(killer.name, " (with the Amulet)");
1301 Strcat(killer.name, "
\96\82\8f\9c\82¯
\82ð
\8eè
\82É");
1302 } else if (how == ESCAPED) {
1303 if (Is_astralevel(&u.uz)) /* offered Amulet to wrong deity */
1305 Strcat(killer.name, " (in celestial disgrace)");
1307 Strcat(killer.name, "
\93V
\8fã
\82Å
\92p
\90J
\82ð
\8eó
\82¯
\92E
\8fo
\82µ
\82½");
1308 else if (carrying(FAKE_AMULET_OF_YENDOR))
1310 Strcat(killer.name, " (with a fake Amulet)");
1312 Strcat(killer.name, "
\8bU
\95¨
\82Ì
\96\82\8f\9c\82¯
\82ð
\92Í
\82Ü
\82³
\82ê
\92E
\8fo
\82µ
\82½");
1313 /* don't bother counting to see whether it should be plural */
1316 if (!done_stopprint) {
1318 Sprintf(pbuf, "%s %s the %s...", Goodbye(), plname,
1320 ? (const char *) ((flags.female && urole.name.f)
1323 : (const char *) (flags.female ? "Demigoddess" : "Demigod"));
1325 Sprintf(pbuf, "%s%s
\82Ì%s
\81D
\81D
\81D", Goodbye(),
1327 ? (const char *) ((flags.female && urole.name.f)
1330 : (const char *) (flags.female ? "
\8f\97\90_" : "
\90_"),
1333 putstr(endwin, 0, pbuf);
1334 putstr(endwin, 0, "");
1337 if (how == ESCAPED || how == ASCENDED) {
1340 register struct val_list *val;
1343 for (val = valuables; val->list; val++)
1344 for (i = 0; i < val->size; i++) {
1345 val->list[i].count = 0L;
1347 get_valuables(invent);
1349 /* add points for collected valuables */
1350 for (val = valuables; val->list; val++)
1351 for (i = 0; i < val->size; i++)
1352 if (val->list[i].count != 0L) {
1353 tmp = val->list[i].count
1354 * (long) objects[val->list[i].typ].oc_cost;
1355 nowrap_add(u.urexp, tmp);
1358 /* count the points for artifacts */
1359 artifact_score(invent, TRUE, endwin);
1361 viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
1363 if (!done_stopprint)
1365 Strcpy(pbuf, "You");
1367 Strcpy(pbuf, "
\82 \82È
\82½");
1368 if (!Schroedingers_cat) /* check here in case disclosure was off */
1369 Schroedingers_cat = odds_and_ends(invent, CAT_CHECK);
1370 if (Schroedingers_cat) {
1371 int mhp, m_lev = adj_lev(&mons[PM_HOUSECAT]);
1373 nowrap_add(u.urexp, mhp);
1374 if (!done_stopprint)
1376 Strcat(eos(pbuf), " and Schroedinger's cat");
1378 Strcat(eos(pbuf), "
\82Æ
\83V
\83\85\83\8c\83f
\83B
\83\93\83K
\81[
\82Ì
\94L");
1382 if (!done_stopprint)
1384 Sprintf(eos(pbuf), " and %s", mon_nam(mtmp));
1386 Sprintf(eos(pbuf), "
\82Æ%s", mon_nam(mtmp));
1388 nowrap_add(u.urexp, mtmp->mhp);
1392 if (!done_stopprint)
1393 Strcat(pbuf, "
\82Í");
1395 if (!done_stopprint)
1396 putstr(endwin, 0, pbuf);
1399 if (!done_stopprint)
1403 Strcat(pbuf, "
\82Í");
1405 if (!done_stopprint) {
1407 Sprintf(eos(pbuf), "%s with %ld point%s,",
1408 how == ASCENDED ? "went to your reward"
1409 : "escaped from the dungeon",
1410 u.urexp, plur(u.urexp));
1412 Sprintf(eos(pbuf), "%ld
\83|
\83C
\83\93\83g
\83}
\81[
\83N
\82µ%s
\81D",
1414 how==ASCENDED ? "
\8f¸
\93V
\82µ
\82½" : "
\96À
\8b{
\82©
\82ç
\92E
\8fo
\82µ
\82½");
1416 putstr(endwin, 0, pbuf);
1419 if (!done_stopprint)
1420 artifact_score(invent, FALSE, endwin); /* list artifacts */
1422 /* list valuables here */
1423 for (val = valuables; val->list; val++) {
1424 sort_valuables(val->list, val->size);
1425 for (i = 0; i < val->size && !done_stopprint; i++) {
1426 int typ = val->list[i].typ;
1427 long count = val->list[i].count;
1431 if (objects[typ].oc_class != GEM_CLASS || typ <= LAST_GEM) {
1432 otmp = mksobj(typ, FALSE, FALSE);
1433 makeknown(otmp->otyp);
1434 otmp->known = 1; /* for fake amulets */
1435 otmp->dknown = 1; /* seen it (blindness fix) */
1436 if (has_oname(otmp))
1440 Sprintf(pbuf, "%8ld %s (worth %ld %s),", count,
1441 xname(otmp), count * (long) objects[typ].oc_cost,
1444 Sprintf(pbuf, "%ld
\8cÂ
\82Ì%s(%ld%s
\82Ì
\89¿
\92l)
\81C", count,
1445 xname(otmp), count * (long) objects[typ].oc_cost,
1448 obfree(otmp, (struct obj *) 0);
1451 Sprintf(pbuf, "%8ld worthless piece%s of colored glass,",
1452 count, plur(count));
1454 Sprintf(pbuf, "%ld
\8cÂ
\82Ì
\89¿
\92l
\82Ì
\82È
\82¢
\90F
\82Â
\82«
\83K
\83\89\83X
\81C",
1458 putstr(endwin, 0, pbuf);
1462 } else if (!done_stopprint) {
1463 /* did not escape or ascend */
1464 if (u.uz.dnum == 0 && u.uz.dlevel <= 0) {
1465 /* level teleported out of the dungeon; `how' is DIED,
1466 due to falling or to "arriving at heaven prematurely" */
1468 Sprintf(pbuf, "You %s beyond the confines of the dungeon",
1469 (u.uz.dlevel < 0) ? "passed away" : ends[how]);
1471 Sprintf(pbuf, "
\96À
\8b{
\82Ì
\97Ì
\88æ
\82ð
\89z
\82¦%s
\81D",
1472 (u.uz.dlevel < 0) ? "
\8fÁ
\82¦
\82³
\82Á
\82½" : ends[how]);
1475 /* more conventional demise */
1476 const char *where = dungeons[u.uz.dnum].dname;
1478 if (Is_astralevel(&u.uz))
1480 where = "The Astral Plane";
1482 where = "
\90¸
\97ì
\8aE
\82É
\82Ä";
1484 Sprintf(pbuf, "You %s in %s", ends[how], where);
1486 Sprintf(pbuf, "
\82 \82È
\82½
\82Í%s", where);
1487 if (!In_endgame(&u.uz) && !Is_knox(&u.uz))
1489 Sprintf(eos(pbuf), " on dungeon level %d",
1490 In_quest(&u.uz) ? dunlev(&u.uz) : depth(&u.uz));
1492 Sprintf(eos(pbuf), "
\82Ì
\92n
\89º%d
\8aK
\82Å",
1493 In_quest(&u.uz) ? dunlev(&u.uz) : depth(&u.uz));
1498 Sprintf(eos(pbuf), " with %ld point%s,", u.urexp, plur(u.urexp));
1500 Sprintf(eos(pbuf), " %ld
\83|
\83C
\83\93\83g
\82ð
\83}
\81[
\83N
\82µ
\81C", u.urexp);
1501 putstr(endwin, 0, pbuf);
1504 if (!done_stopprint) {
1506 Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.", umoney,
1507 plur(umoney), moves, plur(moves));
1509 Sprintf(pbuf, "%ld
\96\87\82Ì
\8bà
\89Ý
\82ð
\8e\9d\82Á
\82Ä
\81C%ld
\95à
\93®
\82¢
\82½
\81D",
1512 putstr(endwin, 0, pbuf);
1514 if (!done_stopprint) {
1517 "You were level %d with a maximum of %d hit point%s when you %s.",
1518 u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]);
1521 "%s
\82Æ
\82«
\81C
\82 \82È
\82½
\82Í
\83\8c\83x
\83\8b%u
\82Å
\81C
\8dÅ
\91å
\91Ì
\97Í
\82Í%d
\82Å
\82 \82Á
\82½
\81D",
1522 ends[how],u.ulevel, u.uhpmax);
1524 putstr(endwin, 0, pbuf);
1525 putstr(endwin, 0, "");
1527 if (!done_stopprint)
1528 display_nhwindow(endwin, TRUE);
1529 if (endwin != WIN_ERR)
1530 destroy_nhwindow(endwin);
1532 /* "So when I die, the first thing I will see in Heaven is a
1534 if (have_windows && !iflags.toptenwin)
1535 exit_nhwindows((char *) 0), have_windows = FALSE;
1536 topten(how, endtime);
1538 exit_nhwindows((char *) 0);
1540 if (done_stopprint) {
1544 terminate(EXIT_SUCCESS);
1548 container_contents(list, identified, all_containers, reportempty)
1550 boolean identified, all_containers, reportempty;
1552 register struct obj *box, *obj;
1553 struct obj **oarray;
1557 boolean cat, deadcat;
1559 for (box = list; box; box = box->nobj) {
1560 if (Is_container(box) || box->otyp == STATUE) {
1561 box->cknown = 1; /* we're looking at the contents now */
1564 cat = deadcat = FALSE;
1565 if (SchroedingersBox(box) && !Schroedingers_cat) {
1566 /* Schroedinger's Cat? */
1567 cat = odds_and_ends(box, CAT_CHECK);
1569 Schroedingers_cat = TRUE;
1574 if (box->otyp == BAG_OF_TRICKS) {
1575 continue; /* wrong type of container */
1576 } else if (box->cobj) {
1577 winid tmpwin = create_nhwindow(NHW_MENU);
1579 /* count the number of items */
1580 for (n = 0, obj = box->cobj; obj; obj = obj->nobj)
1582 /* Make a temporary array to store the objects sorted */
1583 oarray = objarr_init(n);
1585 /* Add objects to the array */
1587 invlet = flags.inv_order;
1589 for (obj = box->cobj; obj; obj = obj->nobj) {
1590 if (!flags.sortpack || obj->oclass == *invlet) {
1593 (flags.sortloot == 'f' || flags.sortloot == 'l'));
1596 if (flags.sortpack) {
1602 Sprintf(buf, "Contents of %s:", the(xname(box)));
1604 Sprintf(buf, "%s
\82Ì
\92\86\90g
\81F", the(xname(box)));
1605 putstr(tmpwin, 0, buf);
1606 putstr(tmpwin, 0, "");
1607 for (i = 0; i < n; i++) {
1610 makeknown(obj->otyp);
1611 obj->known = obj->bknown = obj->dknown = obj->rknown =
1613 if (Is_container(obj) || obj->otyp == STATUE)
1614 obj->cknown = obj->lknown = 1;
1616 putstr(tmpwin, 0, doname(obj));
1621 putstr(tmpwin, 0, "Schroedinger's cat");
1623 putstr(tmpwin, 0, "
\83V
\83\85\83\8c\83f
\83B
\83\93\83K
\81[
\82Ì
\94L");
1626 putstr(tmpwin, 0, "Schroedinger's dead cat");
1628 putstr(tmpwin, 0, "
\83V
\83\85\83\8c\83f
\83B
\83\93\83K
\81[
\82Ì
\94L
\82Ì
\8e\80\91Ì");
1629 display_nhwindow(tmpwin, TRUE);
1630 destroy_nhwindow(tmpwin);
1632 container_contents(box->cobj, identified, TRUE,
1634 } else if (cat || deadcat) {
1636 pline("%s Schroedinger's %scat!", Tobjnam(box, "contain"),
1637 deadcat ? "dead " : "");
1639 pline("%s
\82É
\82Í
\83V
\83\85\83\8c\83f
\83B
\83\93\83K
\81[
\82Ì
\94L%s
\82ª
\93ü
\82Á
\82Ä
\82¢
\82½
\81I", xname(box),
1640 deadcat ? "
\82Ì
\8e\80\91Ì" : "");
1642 display_nhwindow(WIN_MESSAGE, FALSE);
1643 } else if (reportempty) {
1645 pline("%s is empty.", upstart(thesimpleoname(box)));
1647 pline("%s
\82Í
\8bó
\82Á
\82Û
\82¾
\81D", xname(box));
1648 display_nhwindow(WIN_MESSAGE, FALSE);
1651 if (!all_containers)
1656 /* should be called with either EXIT_SUCCESS or EXIT_FAILURE */
1661 program_state.in_moveloop = 0; /* won't be returning to normal play */
1663 getreturn("to exit");
1665 /* don't bother to try to release memory if we're in panic mode, to
1666 avoid trouble in case that happens to be due to memory problems */
1667 if (!program_state.panicking) {
1674 * This is liable to draw a warning if compiled with gcc, but it's
1675 * more important to flag panic() -> really_done() -> terminate()
1676 * as __noreturn__ then to avoid the warning.
1678 /* don't call exit() if already executing within an exit handler;
1679 that would cancel any other pending user-mode handlers */
1680 if (program_state.exiting)
1683 program_state.exiting = 1;
1685 jputchar('\0'); /* reset terminal */
1687 nethack_exit(status);
1690 /* #vanquished command */
1694 list_vanquished('a', FALSE);
1699 list_vanquished(defquery, ask)
1703 register int i, lev;
1704 int ntypes = 0, max_lev = 0, nkilled;
1705 long total_killed = 0L;
1710 /* get totals first */
1711 for (i = LOW_PM; i < NUMMONS; i++) {
1712 if (mvitals[i].died)
1714 total_killed += (long) mvitals[i].died;
1715 if (mons[i].mlevel > max_lev)
1716 max_lev = mons[i].mlevel;
1719 /* vanquished creatures list;
1720 * includes all dead monsters, not just those killed by the player
1724 c = ask ? yn_function(
1725 "Do you want an account of creatures vanquished?",
1729 c = ask ? yn_function(
1730 "
\93|
\82µ
\82½
\93G
\82Ì
\88ê
\97\97\82ð
\8c©
\82Ü
\82·
\82©
\81H",
1736 if (c == 'y' || c == 'a') {
1737 klwin = create_nhwindow(NHW_MENU);
1739 putstr(klwin, 0, "Vanquished creatures:");
1741 putstr(klwin, 0, "
\93|
\82µ
\82½
\93G
\81F");
1742 putstr(klwin, 0, "");
1744 /* countdown by monster "toughness" */
1745 for (lev = max_lev; lev >= 0; lev--)
1746 for (i = LOW_PM; i < NUMMONS; i++)
1747 if (mons[i].mlevel == lev
1748 && (nkilled = mvitals[i].died) > 0) {
1749 if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST) {
1751 Sprintf(buf, "%s%s",
1752 !type_is_pname(&mons[i]) ? "The " : "",
1755 Sprintf(buf, "%s", mons[i].mname);
1761 Sprintf(eos(buf), " (twice)");
1764 Sprintf(eos(buf), " (thrice)");
1767 Sprintf(eos(buf), " (%d times)", nkilled);
1771 Sprintf(eos(buf)," (%d
\89ñ)", nkilled);
1775 /* trolls or undead might have come back,
1776 but we don't keep track of that */
1778 Strcpy(buf, an(mons[i].mname));
1781 Sprintf(buf, "%d %s", nkilled,
1782 makeplural(mons[i].mname));
1784 Sprintf(buf, "%d
\91Ì
\82Ì%s", nkilled,
1788 putstr(klwin, 0, buf);
1791 * if (Hallucination)
1792 * putstr(klwin, 0, "and a partridge in a pear tree");
1795 putstr(klwin, 0, "");
1797 Sprintf(buf, "%ld creatures vanquished.", total_killed);
1799 Sprintf(buf, "%ld
\95C
\82Ì
\93G
\82ð
\93|
\82µ
\82½
\81D", total_killed);
1800 putstr(klwin, 0, buf);
1802 display_nhwindow(klwin, TRUE);
1803 destroy_nhwindow(klwin);
1805 } else if (defquery == 'a') {
1806 /* #dovanquished rather than final disclosure, so pline() is ok */
1808 pline("No monsters have been vanquished.");
1810 pline("
\93|
\82µ
\82½
\93G
\82Í
\82¢
\82È
\82©
\82Á
\82½
\81D");
1814 /* number of monster species which have been genocided */
1820 for (i = LOW_PM; i < NUMMONS; ++i)
1821 if (mvitals[i].mvflags & G_GENOD)
1832 for (i = LOW_PM; i < NUMMONS; ++i)
1833 if (!(mvitals[i].mvflags & G_GENOD) && (mvitals[i].mvflags & G_GONE)
1834 && !(mons[i].geno & G_UNIQ))
1841 list_genocided(defquery, ask)
1846 int ngenocided, nextinct;
1851 ngenocided = num_genocides();
1852 nextinct = num_extinct();
1854 /* genocided or extinct species list */
1855 if (ngenocided != 0 || nextinct != 0) {
1857 Sprintf(buf, "Do you want a list of %sspecies%s%s?",
1858 (nextinct && !ngenocided) ? "extinct " : "",
1859 (ngenocided) ? " genocided" : "",
1860 (nextinct && ngenocided) ? " and extinct" : "");
1862 Sprintf(buf, "%s%s%s
\82µ
\82½
\8eí
\82Ì
\88ê
\97\97\82ð
\8c©
\82Ü
\82·
\82©
\81H",
1863 (nextinct && !ngenocided) ? "
\90â
\96Å" : "",
1864 (ngenocided) ? "
\8bs
\8eE" : "",
1865 (nextinct && ngenocided) ? "
\82¨
\82æ
\82Ñ
\90â
\96Å" : "");
1867 c = ask ? yn_function(buf, ynqchars, defquery) : defquery;
1871 klwin = create_nhwindow(NHW_MENU);
1873 Sprintf(buf, "%s%s species:",
1874 (ngenocided) ? "Genocided" : "Extinct",
1875 (nextinct && ngenocided) ? " or extinct" : "");
1877 Sprintf(buf, "%s%s
\82µ
\82½
\8eí:",
1878 (ngenocided) ? "
\8bs
\8eE" : "
\90â
\96Å",
1879 (nextinct && ngenocided) ? "
\82Ü
\82½
\82Í
\90â
\96Å" : "");
1881 putstr(klwin, 0, buf);
1882 putstr(klwin, 0, "");
1884 for (i = LOW_PM; i < NUMMONS; i++)
1885 if (mvitals[i].mvflags & G_GONE && !(mons[i].geno & G_UNIQ)) {
1886 if ((mons[i].geno & G_UNIQ) && i != PM_HIGH_PRIEST)
1888 Sprintf(buf, "%s%s",
1889 !type_is_pname(&mons[i]) ? "" : "the ",
1892 Sprintf(buf, "%s", mons[i].mname);
1895 Strcpy(buf, makeplural(mons[i].mname));
1896 if (!(mvitals[i].mvflags & G_GENOD))
1898 Strcat(buf, " (extinct)");
1900 Strcat(buf, "(
\90â
\96Å)");
1901 putstr(klwin, 0, buf);
1904 putstr(klwin, 0, "");
1905 if (ngenocided > 0) {
1907 Sprintf(buf, "%d species genocided.", ngenocided);
1909 Sprintf(buf, "%d
\8eí
\97Þ
\82Ì
\8eí
\82ð
\8bs
\8eE
\82µ
\82½
\81D", ngenocided);
1910 putstr(klwin, 0, buf);
1914 Sprintf(buf, "%d species extinct.", nextinct);
1916 Sprintf(buf, "%d
\8eí
\97Þ
\82Ì
\8eí
\82ð
\90â
\96Å
\82³
\82¹
\82½
\81D", nextinct);
1917 putstr(klwin, 0, buf);
1920 display_nhwindow(klwin, TRUE);
1921 destroy_nhwindow(klwin);
1926 /* set a delayed killer, ensure non-delayed killer is cleared out */
1928 delayed_killer(id, format, killername)
1931 const char *killername;
1933 struct kinfo *k = find_delayed_killer(id);
1935 if (k == (struct kinfo *) 0) {
1936 /* no match, add a new delayed killer to the list */
1937 k = (struct kinfo *) alloc(sizeof(struct kinfo));
1939 k->next = killer.next;
1944 Strcpy(k->name, killername ? killername : "");
1949 find_delayed_killer(id)
1954 for (k = killer.next; k != (struct kinfo *) 0; k = k->next) {
1962 dealloc_killer(kptr)
1965 struct kinfo *prev = &killer, *k;
1967 if (kptr == (struct kinfo *) 0)
1969 for (k = killer.next; k != (struct kinfo *) 0; k = k->next) {
1975 if (k == (struct kinfo *) 0) {
1976 impossible("dealloc_killer not on list");
1978 prev->next = k->next;
1979 free((genericptr_t) k);
1984 save_killers(fd, mode)
1990 if (perform_bwrite(mode)) {
1991 for (kptr = &killer; kptr != (struct kinfo *) 0; kptr = kptr->next) {
1992 bwrite(fd, (genericptr_t) kptr, sizeof(struct kinfo));
1995 if (release_data(mode)) {
1996 while (killer.next) {
1997 kptr = killer.next->next;
1998 free((genericptr_t) killer.next);
2010 for (kptr = &killer; kptr != (struct kinfo *) 0; kptr = kptr->next) {
2011 mread(fd, (genericptr_t) kptr, sizeof(struct kinfo));
2013 kptr->next = (struct kinfo *) alloc(sizeof(struct kinfo));
2025 while (*p && isspace((uchar) *p))
2029 while (*p && !isspace((uchar) *p))
2041 out += strlen(out); /* eos() */
2042 while (*in && isspace((uchar) *in))
2044 while (*in && !isspace((uchar) *in))
2051 build_english_list(in)
2055 int len = (int) strlen(p), words = wordcount(p);
2057 /* +3: " or " - " "; +(words - 1): (N-1)*(", " - " ") */
2059 len += 3 + (words - 1);
2060 out = (char *) alloc(len + 1);
2061 *out = '\0'; /* bel_copy1() appends */
2065 impossible("no words in list");
2073 /* "first or second" */
2077 /* "first, second, or third */
2081 } while (--words > 1);