Mercurial > hg > early-roguelike
diff xrogue/rip.c @ 133:e6179860cb76
Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 21 Apr 2015 08:55:20 -0400 |
parents | |
children | ce0cf824c192 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xrogue/rip.c Tue Apr 21 08:55:20 2015 -0400 @@ -0,0 +1,763 @@ +/* + rip.c - File for the fun ends Death or a total win + + XRogue: Expeditions into the Dungeons of Doom + Copyright (C) 1991 Robert Pietkivitch + All rights reserved. + + Based on "Advanced Rogue" + Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T + All rights reserved. + + Based on "Rogue: Exploring the Dungeons of Doom" + Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + All rights reserved. + + See the file LICENSE.TXT for full copyright and licensing information. +*/ + +#define REALLIFE 1 /* Print out machine and logname */ +#define EDITSCORE 2 /* Edit the current score file */ +#define ADDSCORE 3 /* Add a new score */ + +#include <curses.h> +#include <time.h> +#include <signal.h> +#include <ctype.h> +#include <sys/types.h> +#include <fcntl.h> +#include "mach_dep.h" +#include "network.h" +#include "rogue.h" + +/* Network machines (for mutual score keeping) */ +struct network Network[] = { + { "", "" }, +}; + +static char *rip[] = { +" ___________", +" / \\", +" / \\", +" / R. I. P. \\", +" / \\", +" / \\", +" | |", +" | |", +" | killed by |", +" | |", +" | |", +" | |", +" *| * * * |*", +" _________)|//\\\\///\\///\\//\\//\\/|(_________", +NULL +}; + +char *killname(); + +/*UNUSED*/ +void +byebye(sig) +int sig; +{ + NOOP(sig); + exit_game(EXIT_ENDWIN); +} + + +/* + * death: + * Do something really fun when he dies + */ + +death(monst) +register short monst; +{ + register char **dp = rip, *killer; + register struct tm *lt; + time_t date; + char buf[LINELEN]; + struct tm *localtime(); + + time(&date); + lt = localtime(&date); + clear(); + move(8, 0); + while (*dp) + printw("%s\n", *dp++); + mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami); + sprintf(buf, "%lu Points", pstats.s_exp ); + mvaddstr(15, 28-((strlen(buf)+1)/2), buf); + killer = killname(monst); + mvaddstr(17, 28-((strlen(killer)+1)/2), killer); + mvaddstr(18, 25, (sprintf(prbuf, "%4d", 1900+lt->tm_year), prbuf)); + move(lines-1, 0); + refresh(); + score(pstats.s_exp, KILLED, monst); + exit_game(EXIT_ENDWIN); +} + +char * +killname(monst) +register short monst; +{ + static char mons_name[LINELEN/2]; + int i; + + if (monst > NUMMONST) return("a strange monster"); + + if (monst >= 0) { + switch (monsters[monst].m_name[0]) { + case 'a': + case 'e': + case 'i': + case 'o': + case 'u': + sprintf(mons_name, "an %s", monsters[monst].m_name); + break; + default: + sprintf(mons_name, "a %s", monsters[monst].m_name); + } + return(mons_name); + } + for (i = 0; i< DEATHNUM; i++) { + if (deaths[i].reason == monst) + break; + } + if (i >= DEATHNUM) + return ("strange death"); + return (deaths[i].name); +} + +/* + * score -- figure score and post it. + */ + +/* VARARGS2 */ +score(amount, flags, monst) +unsigned long amount; +int flags; +short monst; +{ + struct sc_ent top_ten[NUMSCORE]; + register struct sc_ent *scp; + register int i; + register struct sc_ent *sc2; + register FILE *outf; + register char *killer; + register int prflags = 0; + short upquest=0, wintype=0, uplevel=0, uptype=0; /* For network updating */ + char upsystem[SYSLEN], uplogin[LOGLEN]; + char *thissys; /* Holds the name of this system */ + +#define REASONLEN 3 + static char *reason[] = { + "killed", + "quit", + "A total winner", + "somehow left", + }; + char *packend; + + memset(top_ten,0,sizeof(top_ten)); + + signal(SIGINT, byebye); + if (level == 0 && max_level == 0) + amount = 0; /*don't count if quit early */ + if (flags != WINNER && flags != SCOREIT && flags != UPDATE) { + if (flags == CHICKEN) { + packend = "when you quit"; + amount = amount / 100; + } + else + packend = "at your untimely demise"; + mvaddstr(lines - 1, 0, retstr); + refresh(); + getstr(prbuf); + showpack(packend); + } + purse = 0; /* Steal all the gold */ + + /* + * Open file and read list + */ + + if ((outf = fopen(score_file, "rb+")) == NULL) + { + if ((outf = fopen(score_file, "wb+")) == NULL) + { + mvprintw(lines - 1, 0, "Unable to open or create score file: %s",score_file); + refresh(); + return; + } + } + + thissys = md_gethostname(); + + /* + * If this is a SCOREIT optin (rogue -s), don't call byebye. The + * endwin() calls in byebye() will and this results in a core dump. + */ + if (flags == SCOREIT) signal(SIGINT, SIG_DFL); + else signal(SIGINT, byebye); + + if (flags != SCOREIT && flags != UPDATE) + { + mvaddstr(lines - 1, 0, retstr); + refresh(); + fflush(stdout); + getstr(prbuf); + } + + /* Check for special options */ + if (strcmp(prbuf, "names") == 0) + prflags = REALLIFE; + else if (wizard) { + if (strcmp(prbuf, "edit") == 0) prflags = EDITSCORE; + else if (strcmp(prbuf, "add") == 0) { + prflags = ADDSCORE; + waswizard = FALSE; /* We want the new score recorded */ + } + } + + /* Read the score and convert it to a compatible format */ + + fseek(outf, 0, SEEK_SET); + rs_read_scorefile(outf, top_ten, NUMSCORE); + + /* Get some values if this is an update */ + if (flags == UPDATE) { + int errcheck, errors = 0; + + upquest = (short) netread(&errcheck, sizeof(short), stdin); + if (errcheck) errors++; + + if (fread(whoami, 1, NAMELEN, stdin) != NAMELEN) errors++; + + wintype = (short) netread(&errcheck, sizeof(short), stdin); + if (errcheck) errors++; + + uplevel = (short) netread(&errcheck, sizeof(short), stdin); + if (errcheck) errors++; + + uptype = (short) netread(&errcheck, sizeof(short), stdin); + if (errcheck) errors++; + + if (fread(upsystem, 1, SYSLEN, stdin) != SYSLEN) + errors++; + if (fread(uplogin, 1, LOGLEN, stdin) != LOGLEN) + errors++; + + if (errors) { + fclose(outf); + return; + } + } + + /* + * Insert player in list if need be + */ + if (!waswizard) { + char *login= NULL; + + if (flags != UPDATE) { + login = md_getusername(); + + if ((login == NULL) || (*login == 0)) + login = "another rogue fiend"; + } + + if (flags == UPDATE) + (void) update(top_ten, amount, upquest, whoami, wintype, + uplevel, monst, uptype, upsystem, uplogin); + else { + if (prflags == ADDSCORE) { /* Overlay characteristic by new ones */ + char buffer[LINELEN]; + + clear(); + mvaddstr(1, 0, "Score: "); + mvaddstr(2, 0, "Quest (number): "); + mvaddstr(3, 0, "Name: "); + mvaddstr(4, 0, "System: "); + mvaddstr(5, 0, "Login: "); + mvaddstr(6, 0, "Level: "); + mvaddstr(7, 0, "Char type: "); + mvaddstr(8, 0, "Result: "); + + /* Get the score */ + move(1, 7); + get_str(buffer, stdscr); + amount = atol(buffer); + + /* Get the character's quest -- must be a number */ + move(2, 16); + get_str(buffer, stdscr); + quest_item = atoi(buffer); + + /* Get the character's name */ + move(3, 6); + get_str(buffer, stdscr); + strncpy(whoami, buffer, NAMELEN); + + /* Get the system */ + move(4, 8); + get_str(buffer, stdscr); + strncpy(thissys, buffer, SYSLEN); + + /* Get the login */ + move(5, 7); + get_str(buffer, stdscr); + strncpy(login, buffer, LOGLEN); + + /* Get the level */ + move(6, 7); + get_str(buffer, stdscr); + level = max_level = (short) atoi(buffer); + + /* Get the character type */ + move(7, 11); + get_str(buffer, stdscr); + for (i=0; i<NUM_CHARTYPES; i++) { + if (EQSTR(buffer, char_class[i].name, strlen(buffer))) + break; + } + player.t_ctype = i; + + /* Get the win type */ + move(8, 8); + get_str(buffer, stdscr); + switch (buffer[0]) { + case 'W': + case 'w': + case 'T': + case 't': + flags = WINNER; + break; + + case 'Q': + case 'q': + flags = CHICKEN; + break; + + case 'k': + case 'K': + default: + flags = KILLED; + break; + } + + /* Get the monster if player was killed */ + if (flags == KILLED) { + mvaddstr(9, 0, "Death type: "); + get_str(buffer, stdscr); + if (buffer[0] == 'M' || buffer[0] == 'm') + do { + monst = makemonster(TRUE, "choose"); + } while (monst < 0); /* Force a choice */ + else monst = getdeath(); + } + } + + if (update(top_ten, amount, (short) quest_item, whoami, flags, + (flags == WINNER) ? (short) max_level : (short) level, + monst, player.t_ctype, thissys, login) + ) { + /* Send this update to the other systems in the network */ + int i, j; + char cmd[256]; /* Command for remote execution */ + FILE *rmf, *popen(); /* For input to remote command */ + + for (i=0; Network[i].system[0] != 0; i++) + if (Network[i].system[0] != '!' && + strcmp(Network[i].system, thissys)) { + sprintf(cmd, NETCOMMAND, + Network[i].system, Network[i].rogue); + + /* Execute the command */ + if ((rmf=popen(cmd, "w")) != NULL) { + unsigned long temp; /* Temporary value */ + + /* Write out the parameters */ + (void) netwrite((unsigned long) amount, + sizeof(unsigned long), rmf); + + (void) netwrite((unsigned long) monst, + sizeof(short), rmf); + + (void) netwrite((unsigned long) quest_item, + sizeof(short), rmf); + + (void) fwrite(whoami, 1, strlen(whoami), rmf); + for (j=strlen(whoami); j<NAMELEN; j++) + putc('\0', rmf); + + (void) netwrite((unsigned long) flags, + sizeof(short), rmf); + + temp = (unsigned long) + (flags==WINNER ? max_level : level); + (void) netwrite(temp, sizeof(short), rmf); + + (void) netwrite((unsigned long) player.t_ctype, + sizeof(short), rmf); + + (void) fwrite(thissys, 1, + strlen(thissys), rmf); + for (j=strlen(thissys); j<SYSLEN; j++) + putc('\0', rmf); + + (void) fwrite(login, 1, strlen(login), rmf); + for (j=strlen(login); j<LOGLEN; j++) + putc('\0', rmf); + + /* Close off the command */ + (void) pclose(rmf); + } + } + } + } + } + + /* + * SCOREIT -- rogue -s option. Never started curses if this option. + * UPDATE -- network scoring update. Never started curses if this option. + * EDITSCORE -- want to delete or change a score. + */ +/* if (flags != SCOREIT && flags != UPDATE && prflags != EDITSCORE) + endwin(); */ + + if (flags != UPDATE) { + if (flags != SCOREIT) { + clear(); + refresh(); + endwin(); + } + /* + * Print the list + */ + printf("\nTop %d Adventurers:\nRank Score\tName\n", + NUMSCORE); + for (scp = top_ten; scp < &top_ten[NUMSCORE]; scp++) { + char *class; + + if (scp->sc_score != 0) { + class = char_class[scp->sc_ctype].name; + + /* Make sure we have an in-bound reason */ + if (scp->sc_flags > REASONLEN) scp->sc_flags = REASONLEN; + + printf("%3d %10lu\t%s (%s)", scp - top_ten + 1, + scp->sc_score, scp->sc_name, class); + + if (prflags == REALLIFE) printf(" [in real life %.*s!%.*s]", + SYSLEN, scp->sc_system, LOGLEN, scp->sc_login); + + printf(":\n\t\t%s on level %d", reason[scp->sc_flags], + scp->sc_level); + + switch (scp->sc_flags) { + case KILLED: + printf(" by"); + killer = killname(scp->sc_monster); + printf(" %s", killer); + break; + + case WINNER: + printf(" with the %s", + rel_magic[scp->sc_quest].mi_name); + break; + } + + if (prflags == EDITSCORE) + { + fflush(stdout); + getstr(prbuf); + printf("\n"); + if (prbuf[0] == 'd') { + for (sc2 = scp; sc2 < &top_ten[NUMSCORE-1]; sc2++) + *sc2 = *(sc2 + 1); + top_ten[NUMSCORE-1].sc_score = 0; + for (i = 0; i < NAMELEN; i++) + top_ten[NUMSCORE-1].sc_name[i] = rnd(255); + top_ten[NUMSCORE-1].sc_flags = RN; + top_ten[NUMSCORE-1].sc_level = RN; + top_ten[NUMSCORE-1].sc_monster = RN; + scp--; + } + else if (prbuf[0] == 'e') { + printf("Death type: "); + getstr(prbuf); + if (prbuf[0] == 'M' || prbuf[0] == 'm') + do { + scp->sc_monster = + makemonster(TRUE, "choose"); + } while (scp->sc_monster < 0); /* Force a choice */ + else scp->sc_monster = getdeath(); + clear(); + refresh(); + } + } + else printf("\n"); + } + } +/* if (prflags == EDITSCORE) endwin();*/ /* End editing windowing */ + } + fseek(outf, 0L, SEEK_SET); + + if (flags != SCOREIT) + rs_write_scorefile(outf,top_ten,NUMSCORE); + fclose(outf); +} + +/* + * showpack: + * Display the contents of the hero's pack + */ + +showpack(howso) +char *howso; +{ + reg char *iname; + reg int cnt, packnum; + reg struct linked_list *item; + reg struct object *obj; + + idenpack(); + cnt = 1; + clear(); + mvprintw(0, 0, "Contents of your pack %s:\n",howso); + packnum = 'a'; + for (item = pack; item != NULL; item = next(item)) { + obj = OBJPTR(item); + iname = inv_name(obj, FALSE); + mvprintw(cnt, 0, "%c) %s\n",packnum++,iname); + if (++cnt >= lines - 2 && + next(item) != NULL) { + cnt = 1; + mvaddstr(lines - 1, 0, morestr); + refresh(); + wait_for(' '); + clear(); + } + } + mvprintw(cnt + 1,0,"--- %ld Gold Pieces ---",purse); + refresh(); +} + +total_winner() +{ + register struct linked_list *item; + register struct object *obj; + register long worth; + register char c; + register long oldpurse; + + clear(); + standout(); + addstr(" \n"); + addstr(" @ @ @ @ @ @@@ @ @ \n"); + addstr(" @ @ @@ @@ @ @ @ @ \n"); + addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n"); + addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n"); + addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n"); + addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n"); + addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n"); + addstr(" \n"); + addstr(" Congratulations, you have made it to the light of day! \n"); + standend(); + addstr("\nYou have joined the elite ranks of those who have escaped the\n"); + addstr("Dungeons of Doom alive. You journey home and sell all your loot at\n"); + addstr("a great profit and are appointed "); + switch (player.t_ctype) { + case C_FIGHTER: addstr("Leader of the Fighter's Guild.\n"); + when C_RANGER: addstr("King of the Northern Land.\n"); + when C_PALADIN: addstr("King of the Southern Land.\n"); + when C_MAGICIAN:addstr("High Wizard of the Sorcerer's Guild.\n"); + when C_CLERIC: addstr("Bishop of the Monastery.\n"); + when C_THIEF: addstr("Leader of the Thief's Guild.\n"); + when C_MONK: addstr("Master of the Temple.\n"); + when C_ASSASSIN: addstr("Leader of the Assassin's Guild.\n"); + when C_DRUID: addstr("High Priest of the Monastery.\n"); + otherwise: addstr("Town Drunk in the Tavern.\n"); + } + mvaddstr(lines - 1, 0, spacemsg); + refresh(); + wait_for(' '); + clear(); + mvaddstr(0, 0, " Worth Item"); + oldpurse = purse; + for (c = 'a', item = pack; item != NULL; c++, item = next(item)) + { + obj = OBJPTR(item); + worth = get_worth(obj); + if (obj->o_group == 0) + worth *= obj->o_count; + whatis(item); + mvprintw(c-'a'+1, 0, "%c) %6ld %s", c, worth, inv_name(obj, FALSE)); + purse += worth; + } + mvprintw(c - 'a' + 1, 0," %5ld Gold Pieces ", oldpurse); + refresh(); + score(pstats.s_exp + (long) purse, WINNER, '\0'); + exit_game(EXIT_ENDWIN); +} + + +void +delete_score(top_ten, idx) +struct sc_ent top_ten[NUMSCORE]; +int idx; +{ + for(;idx < NUMSCORE-1;idx++) + top_ten[idx] = top_ten[idx+1]; + + top_ten[NUMSCORE-1].sc_score = 0L; +} + +int +insert_score(top_ten, sc) +struct sc_ent top_ten[NUMSCORE]; +struct sc_ent *sc;