/* * death.c: code executed when player dies * * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke * * This software may be copied and distributed for educational, research, and * not for profit purposes provided that this copyright and statement are * included in all such copies. */ /* * some incorrectly define NULL as integer constant, so load this before * local includes */ #include #include #include "config.h" #include "constant.h" #include "types.h" #include "externs.h" #ifdef Pyramid #include #else #include #endif #include #include "config.h" #ifndef USG /* only needed for Berkeley UNIX */ #include #include #include #else #ifdef __MINT__ #include #endif #include #endif #ifdef MSDOS #include #else #if !defined(ATARIST_MWC) && !defined(MAC) #ifndef VMS #include #else #include #endif #endif #endif #ifdef linux #include #endif #ifdef USG #ifndef ATARIST_MWC #include #include #endif #else #include #endif #if defined(USG) || defined(VMS) #ifndef L_SET #define L_SET 0 #endif #endif #ifndef VMS #ifndef MAC #if defined(ultrix) || defined(USG) void perror(); void exit(); #endif #endif #endif #ifndef MAC #ifdef SYS_V struct passwd *getpwuid(); #endif #endif /* Lets do all prototypes correctly.... -CWS */ #ifndef NO_LINT_ARGS #ifdef __STDC__ static void date(char *); static char *center_string(char *, const char *); static void print_tomb(void); static void kingly(void); #else static void date(); static char *center_string(); static void print_tomb(); static void kingly(); #endif #endif #ifndef MAC char *getlogin(); #endif #if !defined(time_t) #define time_t long #endif static void date(day) char *day; { register char *tmp; time_t c; c = time((time_t *)0); tmp = ctime(&c); tmp[10] = '\0'; (void)strcpy(day, tmp); } /* Centers a string within a 31 character string -JWT- */ static char * center_string(centered_str, in_str) char *centered_str; const char *in_str; { register int i, j; i = strlen(in_str); j = 15 - i / 2; (void)sprintf(centered_str, "%*s%s%*s", j, "", in_str, 31 - i - j, ""); return centered_str; } /* Not touched for Mac port */ void display_scores(from, to) int from, to; { register int i = 0, j, k, l; int fd; high_scores score; /* MAX_SAVE_HISCORES scores, 2 lines per score */ char list[2 * MAX_SAVE_HISCORES][128]; char hugebuffer[10000]; char string[100]; vtype tmp_str; if (to < 0) to = 20; if (to > MAX_SAVE_HISCORES) to = MAX_SAVE_HISCORES; #ifdef SET_UID if (1 > (fd = my_topen(ANGBAND_TOP, O_RDONLY | O_CREAT, 0644))) { #else if (1 > (fd = my_topen(ANGBAND_TOP, O_RDONLY | O_CREAT, 0666))) { #endif (void)sprintf(string, "Error opening score file \"%s\"\n", ANGBAND_TOP); prt(string, 0, 0); return; } while (0 < read(fd, (char *)&score, sizeof(high_scores))) { if (score.uid != -1 && getpwuid(score.uid) != NULL) (void)sprintf(hugebuffer, "%3d) %-7ld %s the %s %s (Level %d), played by %s", i / 2 + 1, (long)score.points, score.name, race[score.prace].trace, class[score.pclass].title, (int)score.lev, getpwuid(score.uid)->pw_name); else (void)sprintf(hugebuffer, "%3d) %-7ld %s the %s %s (Level %d)", i / 2 + 1, (long)score.points, score.name, race[score.prace].trace, class[score.pclass].title, (int)score.lev); strncpy(list[i], hugebuffer, 127); (void)sprintf(hugebuffer, " Killed by %s on Dungeon Level %d.", score.died_from, score.dun_level); strncpy(list[i + 1], hugebuffer, 127); i += 2; if (i >= (MAX_SAVE_HISCORES * 2)) break; } signal(SIGTSTP, SIG_IGN); k = from * 2; do { if (k > 0) { sprintf(tmp_str, "\t\tAngband Hall of Fame (from position %d)", (k / 2) + 1); put_buffer(tmp_str, 0, 0); } else { put_buffer("\t\tAngband Hall of Fame ", 0, 0); } put_buffer(" Score", 1, 0); l = 0; for (j = k; j < i && j < (to * 2) && j < (k + 20); j++, l++) put_buffer(list[j], l + 2, 0); k += 20; if (!look_line(23)) { /* What happens upon dying. -RAK- */ msg_print(NULL); clear_screen(); flush(); /* flush all input */ nosignals(); /* Can't interrupt or suspend. */ (void)save_char(); /* Save the memory at least. */ restore_term(); exit(0); } clear_screen(); } while (k < (to * 2) && k < i); } /* Pauses for user response before returning -RAK- */ int look_line(prt_line) int prt_line; { prt("[Press ESC to quit, any other key to continue.]", prt_line, 17); if (inkey() == ESCAPE) { erase_line(prt_line, 0); return 0; } else { erase_line(prt_line, 0); return 1; } } /* Prints the gravestone of the character -RAK- */ static void print_tomb() { vtype str, tmp_str; register int i; char day[11]; register const char *p; FILE *fp; if (stricmp(died_from, "Interrupting") && !wizard) { sprintf(str, "%s/%d", ANGBAND_BONES, dun_level); if ((fp = my_tfopen(str, "r")) == NULL && (dun_level > 1)) { if ((fp = my_tfopen(str, "w")) != NULL) { #ifndef __MINT__ #ifdef SET_UID (void)fchmod(fileno(fp), 0644); #else (void)fchmod(fileno(fp), 0666); #endif #endif fprintf(fp, "%s\n%d\n%d\n%d", py.misc.name, py.misc.mhp, py.misc.prace, py.misc.pclass); if (fp) fclose(fp); } } else { if (fp) fclose(fp); } } clear_screen(); put_buffer("_______________________", 1, 15); put_buffer("/", 2, 14); put_buffer("\\ ___", 2, 38); put_buffer("/", 3, 13); put_buffer("\\ ___ / \\ ___", 3, 39); put_buffer("/ RIP \\ \\ : : / \\", 4, 12); put_buffer("/", 5, 11); put_buffer("\\ : _;,,,;_ : :", 5, 41); (void)sprintf(str, "/%s\\,;_ _;,,,;_", center_string(tmp_str, py.misc.name)); put_buffer(str, 6, 10); put_buffer("| the | ___", 7, 9); if (!total_winner) p = title_string(); else p = "Magnificent"; (void)sprintf(str, "| %s | / \\", center_string(tmp_str, p)); put_buffer(str, 8, 9); put_buffer("|", 9, 9); put_buffer("| : :", 9, 43); if (!total_winner) p = class[py.misc.pclass].title; else if (py.misc.male) p = "*King*"; else p = "*Queen*"; (void)sprintf(str, "| %s | _;,,,;_ ____", center_string(tmp_str, p)); put_buffer(str, 10, 9); (void)sprintf(str, "Level : %d", (int)py.misc.lev); (void)sprintf(str, "| %s | / \\", center_string(tmp_str, str)); put_buffer(str, 11, 9); (void)sprintf(str, "%ld Exp", (long)py.misc.exp); (void)sprintf(str, "| %s | : :", center_string(tmp_str, str)); put_buffer(str, 12, 9); (void)sprintf(str, "%ld Au", (long)py.misc.au); (void)sprintf(str, "| %s | : :", center_string(tmp_str, str)); put_buffer(str, 13, 9); (void)sprintf(str, "Died on Level : %d", dun_level); (void)sprintf(str, "| %s | _;,,,,;_", center_string(tmp_str, str)); put_buffer(str, 14, 9); put_buffer("| killed by |", 15, 9); p = died_from; i = strlen(p); died_from[i] = '.'; /* add a trailing period */ died_from[i + 1] = '\0'; (void)sprintf(str, "| %s |", center_string(tmp_str, p)); put_buffer(str, 16, 9); died_from[i] = '\0'; /* strip off the period */ date(day); (void)sprintf(str, "| %s |", center_string(tmp_str, day)); put_buffer(str, 17, 9); put_buffer("*| * * * * * * | *", 18, 8); put_buffer("________)/\\\\_)_/___(\\/___(//_\\)/_\\//__\\\\(/_|_)_______", 19, 0); flush(); put_buffer("(ESC to abort, return to print on screen, or file name)", 23, 0); put_buffer("Character record?", 22, 0); if (get_string(str, 22, 18, 60)) { for (i = 0; i < INVEN_ARRAY_SIZE; i++) { inven_type *i_ptr = &inventory[i]; if (i_ptr && i_ptr->tval != TV_NOTHING) { known1(i_ptr); known2(i_ptr); } } calc_bonuses(); clear_screen(); display_char(); put_buffer("Type ESC to skip the inventory:", 23, 0); if (inkey() != ESCAPE) { clear_screen(); msg_print("You are using:"); (void)show_equip(TRUE, 0); msg_print(NULL); if (inven_ctr) { msg_print("You are carrying:"); clear_from(1); (void)show_inven(0, inven_ctr - 1, TRUE, 0, 0); msg_print(NULL); } msg_print ("You have stored at your house:"); clear_from (1); { /* show home's inventory... */ store_type *s_ptr = &store[7]; /* home */ int ii = 0, j = 0; vtype t1, t2; while ( ii store_ctr) { j = 0; sprintf(t2, "(page %d)", (ii==0?1:2)); prt(t2, 1, 3); while ((iistore_ctr) && (j<12)){ known1(&s_ptr->store_inven[ii].sitem); known2(&s_ptr->store_inven[ii].sitem); objdes(t1, &s_ptr->store_inven[ii].sitem, TRUE); sprintf(t2, "%c) %s", 'a'+j, t1); prt(t2, j+2, 4); j++; ii++; } /* items 1-12, 13-24 loop */ if (ii < s_ptr->store_ctr) { /* if we're done, skip this */ msg_print(NULL); msg_print("Home inventory:"); clear_from (1); } } /* outer while loop */ msg_print(NULL); } /* scope block of display-home inventory code -CFT */ } } } /* Calculates the total number of points earned -JWT- */ long total_points() { return (py.misc.max_exp + (100 * py.misc.max_dlv)); } /* Enters a players name on a hi-score table... SM */ static int top_twenty() { register int i, j, k; high_scores scores[MAX_SAVE_HISCORES], myscore; clear_screen(); if (wizard || to_be_wizard) { display_scores(0, 10); (void)save_char(); restore_term(); exit(0); } if (!total_winner && !stricmp(died_from, "Interrupting")) { msg_print("Score not registered due to interruption."); display_scores(0, 10); (void)save_char(); restore_term(); exit(0); } if (!total_winner && !stricmp(died_from, "Quitting")) { msg_print("Score not registered due to quitting."); display_scores(0, 10); (void)save_char(); restore_term(); exit(0); } myscore.points = total_points(); myscore.dun_level = dun_level; myscore.lev = py.misc.lev; myscore.max_lev = py.misc.max_dlv; myscore.mhp = py.misc.mhp; myscore.chp = py.misc.chp; myscore.uid = player_uid; /* First character of sex, lower case */ myscore.sex = py.misc.male; myscore.prace = py.misc.prace; myscore.pclass = py.misc.pclass; (void)strcpy(myscore.name, py.misc.name); (void)strncpy(myscore.died_from, died_from, strlen(died_from)); myscore.died_from[strlen(died_from)] = '\0'; /* Get rid of '.' at end of death description */ /* First, get a lock on the high score file so no-one else tries */ /* to write to it while we are using it */ /* added sys_v call to lockf - cba */ #ifdef USG if (lockf(highscore_fd, F_LOCK, 0) != 0) #else if (0 != flock(highscore_fd, LOCK_EX)) #endif { perror("Error gaining lock for score file"); exit_game(); } /* Check to see if this score is a high one and where it goes */ i = 0; #ifndef BSD4_3 (void)lseek(highscore_fd, (long)0, L_SET); #else (void)lseek(highscore_fd, (off_t) 0, L_SET); #endif while ((i < MAX_SAVE_HISCORES) && (0 != read(highscore_fd, (char *)&scores[i], sizeof(high_scores)))) { i++; } j = 0; while (j < i && (scores[j].points >= myscore.points)) { j++; } /* i is now how many scores we have, and j is where we put this score */ /* If its the first score, or it gets appended to the file */ if (!i || (i == j && j < MAX_SAVE_HISCORES)) { (void)lseek(highscore_fd, (long)(j * sizeof(high_scores)), L_SET); (void)write(highscore_fd, (char *)&myscore, sizeof(high_scores)); } else if (j < i) { /* If it gets inserted in the middle */ /* Bump all the scores up one place */ for (k = MY_MIN(i, (MAX_SAVE_HISCORES - 1)); k > j; k--) { (void)lseek(highscore_fd, (long)(k * sizeof(high_scores)), L_SET); (void)write(highscore_fd, (char *)&scores[k - 1], sizeof(high_scores)); } /* Write out your score */ (void)lseek(highscore_fd, (long)(j * sizeof(high_scores)), L_SET); (void)write(highscore_fd, (char *)&myscore, sizeof(high_scores)); } /* added usg lockf call - cba */ #ifdef USG lockf(highscore_fd, F_ULOCK, 0); #else (void)flock(highscore_fd, LOCK_UN); #endif (void)close(highscore_fd); if (j < 10) { display_scores(0, 10); } else if (j > (i - 5)) { display_scores(i - 9, i + 1); } else display_scores(j - 5, j + 5); return (0); } /* Enters a players name on the hi-score table SM */ void delete_entry(which) int which; { register int i; high_scores scores[MAX_SAVE_HISCORES]; /* added usg lockf call - cba */ #ifdef USG if (lockf(highscore_fd, F_LOCK, 0) != 0) #else if (0 != flock(highscore_fd, LOCK_EX)) #endif { perror("Error gaining lock for score file"); exit_game(); } /* Check to see if this score is a high one and where it goes */ i = 0; (void)lseek(highscore_fd, (off_t) 0, L_SET); while ((i < MAX_SAVE_HISCORES) && (0 != read(highscore_fd, (char *)&scores[i], sizeof(high_scores)))) i++; if (i >= which) { #if defined(sun) || defined(ultrix) || defined(NeXT) ftruncate(highscore_fd, 0); #endif /* If its the first score, or it gets appended to the file */ lseek(highscore_fd, 0, L_SET); if (which > 0) write(highscore_fd, (char *)&scores[0], (which - 1) * sizeof(high_scores)); if (i > which) write(highscore_fd, (char *)&scores[which], (i - which) * sizeof(high_scores)); } else { puts(" The high score table does not have that many entries!"); } /* added usg lockf call - cba */ #ifdef USG lockf(highscore_fd, F_ULOCK, 0); #else (void)flock(highscore_fd, LOCK_UN); #endif (void)close(highscore_fd); if (which < 10) { display_scores(0, 10); } else if (which > (i - 10)) { display_scores(i - 10, i); } else display_scores(which - 5, which + 5); } /* Change the player into a King! -RAK- */ static void kingly() { register struct misc *p_ptr; register const char *p; /* Change the character attributes. */ dun_level = 0; (void)strcpy(died_from, "Ripe Old Age"); p_ptr = &py.misc; (void)restore_level(); p_ptr->lev += MAX_PLAYER_LEVEL; p_ptr->au += 250000L; p_ptr->max_exp += 5000000L; p_ptr->exp = p_ptr->max_exp; /* Let the player know that he did good. */ clear_screen(); put_buffer("#", 1, 34); put_buffer("#####", 2, 32); put_buffer("#", 3, 34); put_buffer(",,, $$$ ,,,", 4, 28); put_buffer(",,=$ \"$$$$$\" $=,,", 5, 24); put_buffer(",$$ $$$ $$,", 6, 22); put_buffer("*> <*> <*", 7, 22); put_buffer("$$ $$$ $$", 8, 22); put_buffer("\"$$ $$$ $$\"", 9, 22); put_buffer("\"$$ $$$ $$\"", 10, 23); p = "*#########*#########*"; put_buffer(p, 11, 24); put_buffer(p, 12, 24); put_buffer("Veni, Vidi, Vici!", 15, 26); put_buffer("I came, I saw, I conquered!", 16, 21); if (p_ptr->male) put_buffer("All Hail the Mighty King!", 17, 22); else put_buffer("All Hail the Mighty Queen!", 17, 22); flush(); pause_line(23); } /* Handles the gravestone end top-twenty routines -RAK- */ void exit_game() { register int i; #ifdef MAC /* Prevent strange things from happening */ enablefilemenu(FALSE); #endif /* What happens upon dying. -RAK- */ msg_print(NULL); flush(); /* flush all input */ nosignals(); /* Can't interrupt or suspend. */ if (turn >= 0) { if (total_winner) kingly(); print_tomb(); if (!wizard && !to_be_wizard) top_twenty(); else msg_print("Score not registered."); } i = log_index; (void)save_char(); /* Save the memory at least. */ if (i > 0) display_scores(0, 10); erase_line(23, 0); restore_term(); exit(0); }