Mercurial > hg > early-roguelike
diff arogue5/rip.c @ 63:0ed67132cf10
Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Thu, 09 Aug 2012 22:58:48 +0000 |
parents | |
children | 7aff18a8d508 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arogue5/rip.c Thu Aug 09 22:58:48 2012 +0000 @@ -0,0 +1,768 @@ +/* + * File for the fun ends + * Death or a total win + * + * 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. + */ + +/* Print flags for scoring */ +#define REALLIFE 1 /* Print out machine and logname */ +#define EDITSCORE 2 /* Edit the current score file */ +#define ADDSCORE 3 /* Add a new score */ + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include "curses.h" +#include <time.h> +#include <signal.h> +#include <ctype.h> +#include <sys/types.h> +#include "network.h" +#include "rogue.h" +#include "mach_dep.h" + +/* + * If you change this structure, change the compatibility routines + * scoreout() and scorein() to reflect the change. Also update SCORELEN. + */ + +struct sc_ent { + unsigned long sc_score; + char sc_name[LINELEN]; + char sc_system[SYSLEN]; + char sc_login[LOGLEN]; + short sc_flgs; + short sc_level; + short sc_ctype; + short sc_monster; + short sc_quest; +}; + +#define SCORELEN \ + (sizeof(unsigned long) + LINELEN + SYSLEN + LOGLEN + 5*sizeof(short)) + +static char *rip[] = { +" __________", +" / \\", +" / REST \\", +" / IN \\", +" / PEACE \\", +" / \\", +" | |", +" | |", +" | killed by |", +" | |", +" | 1984 |", +" *| * * * | *", +" ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______", + 0 +}; + +char *killname(); + + + + + +void +byebye(sig) +int sig; +{ + NOOP(sig); + if (!isendwin()) { + clear(); + endwin(); + } + printf("\n"); + exit(0); +} + + +/* + * 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[80]; + 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, 26, (sprintf(prbuf, "%4d", 1900+lt->tm_year), prbuf)); + move(LINES-1, 0); + refresh(); + score(pstats.s_exp, KILLED, monst); + exit(0); +} + +char * +killname(monst) +register short monst; +{ + static char mons_name[LINELEN]; + 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; +short monst; +{ + static 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; + register int fd; + 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 */ + char *compatstr=NULL; /* Holds scores for writing compatible score files */ +#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 (flags != WINNER && flags != SCOREIT && flags != UPDATE) { + if (flags == CHICKEN) + packend = "when you quit"; + else + packend = "at your untimely demise"; + mvaddstr(LINES - 1, 0, retstr); + refresh(); + wgetnstr(cw,prbuf,80); + showpack(packend); + } + purse = 0; /* Steal all the gold */ + + /* + * Open file and read list + */ + + if ((fd = open(score_file, O_RDWR | O_CREAT, 0666)) < 0) + { + printf("\nCannot open score_file.\n"); + return; + } + outf = (FILE *) fdopen(fd, "w"); + + /* Get this system's name */ + thissys = md_gethostname(); + + for (scp = top_ten; scp <= &top_ten[NUMSCORE-1]; scp++) + { + scp->sc_score = 0L; + for (i = 0; i < 80; i++) + scp->sc_name[i] = rnd(255); + scp->sc_quest= RN; + scp->sc_flgs = RN; + scp->sc_level = RN; + scp->sc_monster = RN; + scp->sc_ctype = 0; + strncpy(scp->sc_system, thissys, SYSLEN); + scp->sc_login[0] = '\0'; + } + + /* + * If this is a SCOREIT optin (rogue -s), don't call byebye. The + * endwin() call in byebye() will result 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); + wgetnstr(stdscr,prbuf,80); + } + + /* Check for special options */ + if (strcmp(prbuf, "names") == 0) + prflags = REALLIFE; +#ifdef WIZARD + 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 */ + } + } +#endif + + /* Read the score and convert it to a compatible format */ + scorein(top_ten, fd); /* Convert it */ + + /* 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, LINELEN, stdin) != LINELEN) 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); + free(compatstr); + return; + } + } + + /* + * Insert player in list if need be + */ + if (!waswizard) { + char *login = NULL; + + if (flags != UPDATE) { + login = md_getusername(); + } + + if (flags == UPDATE) + (void) update(top_ten, amount, upquest, whoami, wintype, + uplevel, monst, uptype, upsystem, uplogin); + else { +#ifdef WIZARD + if (prflags == ADDSCORE) { /* Overlay characteristic by new ones */ + char buffer[80]; + int atoi(); + + 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, LINELEN); + + /* 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); + switch (buffer[0]) { + case 'F': + case 'f': + default: + player.t_ctype = C_FIGHTER; + break; + + case 'C': + case 'c': + player.t_ctype = C_CLERIC; + break; + + case 'M': + case 'm': + player.t_ctype = C_MAGICIAN; + break; + + case 'T': + case 't': + player.t_ctype = C_THIEF; + break; + } + + /* 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') + monst = makemonster(FALSE); + else monst = getdeath(); + } + } +#endif + + if (update(top_ten, amount, (short) quest_item, whoami, flags, + (flags == WINNER) ? (short) max_level : (short) level, + monst, player.t_ctype, thissys, login) +#ifdef NUMNET + && fork() == 0 /* Spin off network process */ +#endif + ) { +#ifdef NUMNET + /* 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; i<NUMNET; i++) + if (Network[i].system[0] != '!' && + strcmp(Network[i].system, thissys)) { + sprintf(cmd, + "usend -s -d%s -uNoLogin -!'%s -u' - 2>/dev/null", + 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<LINELEN; 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); + } + } + _exit(0); /* Exit network process */ +#endif + } + } + } + + /* + * 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-1]; scp++) { + char *class; + + if (scp->sc_score != 0) { + switch (scp->sc_ctype) { + case C_FIGHTER: class = "fighter"; + when C_MAGICIAN: class = "magician"; + when C_CLERIC: class = "cleric"; + when C_THIEF: class = "thief"; + otherwise: class = "unknown"; + } + + /* Make sure we have an in-bound reason */ + if (scp->sc_flgs > REASONLEN) scp->sc_flgs = 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_flgs], + scp->sc_level); + + switch (scp->sc_flgs) { + 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); + fgets(prbuf,80,stdin); + 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 < 80; i++) + top_ten[NUMSCORE-1].sc_name[i] = rnd(255); + top_ten[NUMSCORE-1].sc_flgs = RN; + top_ten[NUMSCORE-1].sc_level = RN; + top_ten[NUMSCORE-1].sc_monster = RN; + scp--; + } + else if (prbuf[0] == 'e') { + printf("Death type: "); + fgets(prbuf,80,stdin); + if (prbuf[0] == 'M' || prbuf[0] == 'm') + scp->sc_monster = makemonster(FALSE); + else scp->sc_monster = getdeath(); + clear(); + refresh(); + } + } + else printf("\n"); + } + } + if ((flags != SCOREIT) && (flags != UPDATE)) { + printf("\n[Press return to exit]"); + fflush(stdout); + fgets(prbuf,80,stdin); + } +/* if (prflags == EDITSCORE) endwin(); */ /* End editing windowing */ + } + fseek(outf, 0L, 0); + /* + * Update the list file + */ + scoreout(top_ten, outf); + fclose(outf); +} + +/* + * scorein: + * Convert a character string that has been translated from a + * score file by scoreout() back to a score file structure. + */ +scorein(scores, fd) +struct sc_ent scores[]; +int fd; +{ + int i; + char scoreline[100]; + + for(i = 0; i < NUMSCORE; i++) + { + encread((char *) &scores[i].sc_name, LINELEN, fd); + encread((char *) &scores[i].sc_system, SYSLEN, fd); + encread((char *) &scores[i].sc_login, LINELEN, fd); + encread((char *) scoreline, 100, fd); + sscanf(scoreline, " %lu %d %d %d %d %d \n", + &scores[i].sc_score, &scores[i].sc_flgs, + &scores[i].sc_level, &scores[i].sc_ctype, + &scores[i].sc_monster, &scores[i].sc_quest); + } +} + +/* + * scoreout: + * Convert a score file structure to a character string. We do + * this for compatibility sake since some machines write out fields in + * different orders. + */ +scoreout(scores, outf) +struct sc_ent scores[]; +FILE *outf; +{ + int i; + char scoreline[100]; + + for(i = 0; i < NUMSCORE; i++) { + memset(scoreline,0,100); + encwrite((char *) scores[i].sc_name, LINELEN, outf); + encwrite((char *) scores[i].sc_system, SYSLEN, outf); + encwrite((char *) scores[i].sc_login, LINELEN, outf); + sprintf(scoreline, " %lu %d %d %d %d %d \n", + scores[i].sc_score, scores[i].sc_flgs, + scores[i].sc_level, scores[i].sc_ctype, + scores[i].sc_monster,scores[i].sc_quest); + encwrite((char *) scoreline, 100, 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(stdscr,' '); + clear(); + } + } + mvprintw(cnt + 1,0,"--- %d Gold Pieces ---",purse); + refresh(); +} + +total_winner() +{ + register struct linked_list *item; + register struct object *obj; + register int worth; + register char c; + register int oldpurse; + + clear(); + standout(); + addstr(" \n"); + addstr(" @ @ @ @ @ @@@ @ @ \n"); + addstr(" @ @ @@ @@ @ @ @ @ \n"); + addstr(" @ @ @@@ @ @ @ @ @ @@@ @@@@ @@@ @ @@@ @ \n"); + addstr(" @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ \n"); + addstr(" @ @ @ @ @ @ @ @@@@ @ @ @@@@@ @ @ @ \n"); + addstr(" @ @ @ @ @ @@ @ @ @ @ @ @ @ @ @ @ \n"); + addstr(" @@@ @@@ @@ @ @ @ @@@@ @@@@ @@@ @@@ @@ @ \n");