Mercurial > hg > early-roguelike
view rogue3/rip.c @ 140:856017d63519
xrogue: don't segfault when backstabbing while empty-handed.
The code for backstabbing checked the weapon's properties without
making sure it was not NULL.
author | John "Elwin" Edwards |
---|---|
date | Tue, 05 May 2015 12:12:20 -0400 |
parents | ee250e3646fd |
children | c199a15a2c70 |
line wrap: on
line source
/* * File for the fun ends * Death or a total win * * @(#)rip.c 3.13 (Berkeley) 6/16/81 * * 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. */ #include <stdlib.h> #include <errno.h> #include <time.h> #include <signal.h> #include <ctype.h> #include <sys/types.h> #include <fcntl.h> #include <string.h> #include "curses.h" #include "machdep.h" #include "rogue.h" static char *rip[] = { " __________", " / \\", " / REST \\", " / IN \\", " / PEACE \\", " / \\", " | |", " | |", " | killed by a |", " | |", " | 1980 |", " *| * * * | *", " ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______", 0 }; char *killname(); /* * death: * Do something really fun when he dies */ void death(int monst) { char **dp = rip, *killer; struct tm *lt; time_t date; char buf[80]; /* Don't autosave dead games. It would be a good idea to autosave a game that is between death and scoreboard write, but the restore code can't handle that case yet. */ md_onsignal_default(); time(&date); lt = localtime(&date); clear(); move(8, 0); while (*dp) printw("%s\n", *dp++); mvaddstr(14, 28-(((int)strlen(whoami)+1)/2), whoami); purse -= purse/10; sprintf(buf, "%d Au", purse); mvaddstr(15, 28-(((int)strlen(buf)+1)/2), buf); killer = killname(monst); mvaddstr(17, 28-(((int)strlen(killer)+1)/2), killer); mvaddstr(16, 33, vowelstr(killer)); sprintf(prbuf, "%4d", 1900+lt->tm_year); mvaddstr(18, 26, prbuf); move(LINES-1, 0); draw(stdscr); writelog(purse, 0, monst); score(purse, 0, monst); /* Make sure all the output gets through ssh and anything else that might be in the way. */ printf("[Press return to exit]\n"); fflush(NULL); getchar(); exit(0); } /* * score -- figure score and post it. */ void open_score(void) { #ifdef SCOREFILE char *scorefile = SCOREFILE; if (scoreboard != NULL) { rewind(scoreboard); return; } scoreboard = fopen(scorefile, "r+"); if ((scoreboard == NULL) && (errno == ENOENT)) { scoreboard = fopen(scorefile, "w+"); md_chmod(scorefile,0664); } if (scoreboard == NULL) { fprintf(stderr, "Could not open %s for writing: %s\n", scorefile, strerror(errno)); fflush(stderr); } #else scoreboard = NULL; #endif } /* Same thing, but for the log file. Maybe combine them eventually. */ void open_log(void) { #ifdef LOGFILE logfi = fopen(LOGFILE, "a"); if (logfi == NULL) { fprintf(stderr, "Could not open %s for appending: %s\n", LOGFILE, strerror(errno)); fflush(stderr); } #else logfi == NULL; #endif return; } /* VARARGS2 */ void score(int amount, int flags, int monst) { static struct sc_ent { int sc_score; char sc_name[80]; int sc_flags; int sc_level; char sc_login[8]; int sc_monster; } top_ten[10]; struct sc_ent *scp; int i; struct sc_ent *sc2; FILE *outf; char *killer; int prflags = 0; static char *reason[] = { "killed", "quit", "A total winner", }; char scoreline[100]; int rogue_ver = 0, scorefile_ver = 0; /* * Open file and read list */ if (scoreboard == NULL) return; outf = scoreboard; for (scp = top_ten; scp <= &top_ten[9]; scp++) { scp->sc_score = 0; for (i = 0; i < 80; i++) scp->sc_name[i] = rnd(255); scp->sc_flags = RN; scp->sc_level = RN; scp->sc_monster = RN; scp->sc_login[0] = '\0'; } signal(SIGINT, SIG_DFL); if ((flags != -1) && (flags != 1)) { mvaddstr(LINES-1, 0, "[Press return to continue]"); draw(stdscr); prbuf[0] = 0; get_str(prbuf, stdscr); endwin(); } if (wizard) if (strcmp(prbuf, "names") == 0) prflags = 1; else if (strcmp(prbuf, "edit") == 0) prflags = 2; md_lockfile(outf); encread(scoreline, 100, outf); (void) sscanf(scoreline, "R%d %d\n", &rogue_ver, &scorefile_ver); if ((rogue_ver == 36) && (scorefile_ver == 2)) for(i = 0; i < 10; i++) { encread(&top_ten[i].sc_name, 80, outf); encread(&top_ten[i].sc_login, 8, outf); encread(scoreline, 100, outf); (void) sscanf(scoreline, " %d %d %d %d \n", &top_ten[i].sc_score, &top_ten[i].sc_flags, &top_ten[i].sc_level, &top_ten[i].sc_monster); } /* * Insert her in list if need be */ if (!waswizard) { for (scp = top_ten; scp <= &top_ten[9]; scp++) if (amount > scp->sc_score) break; if (scp <= &top_ten[9]) { for (sc2 = &top_ten[9]; sc2 > scp; sc2--) *sc2 = *(sc2-1); scp->sc_score = amount; strcpy(scp->sc_name, whoami); scp->sc_flags = flags; if (flags == 2) scp->sc_level = max_level; else scp->sc_level = level; scp->sc_monster = monst; strncpy(scp->sc_login, md_getusername(), 8); } } /* * Print the list */ if (flags != -1) printf("\n\n\n"); printf("Top Ten Adventurers:\nRank\tScore\tName\n"); for (scp = top_ten; scp <= &top_ten[9]; scp++) { if (scp->sc_score) { printf("%d\t%d\t%s: %s on level %d", scp - top_ten + 1, scp->sc_score, scp->sc_name, reason[scp->sc_flags], scp->sc_level); if (scp->sc_flags == 0) { printf(" by a"); killer = killname(scp->sc_monster); if (*killer == 'a' || *killer == 'e' || *killer == 'i' || *killer == 'o' || *killer == 'u') putchar('n'); printf(" %s", killer); } if (prflags == 1) { printf(" (%s)", scp->sc_login); putchar('\n'); } else if (prflags == 2) { fflush(stdout); fgets(prbuf,80,stdin); if (prbuf[0] == 'd') { for (sc2 = scp; sc2 < &top_ten[9]; sc2++) *sc2 = *(sc2 + 1); top_ten[9].sc_score = 0; for (i = 0; i < 80; i++) top_ten[9].sc_name[i] = rnd(255); top_ten[9].sc_flags = RN; top_ten[9].sc_level = RN; top_ten[9].sc_monster = RN; scp--; } } else printf(".\n"); } } /* * Update the list file */ rewind(outf); strcpy(scoreline, "R36 2\n"); encwrite(scoreline, 100, outf); for(i = 0; i < 10; i++) { encwrite(&top_ten[i].sc_name, 80, outf); encwrite(&top_ten[i].sc_login, 8, outf); sprintf(scoreline, " %d %d %d %d \n", top_ten[i].sc_score, top_ten[i].sc_flags, top_ten[i].sc_level, top_ten[i].sc_monster); encwrite(scoreline, 100, outf); } md_unlockfile(outf); fclose(outf); } void writelog(int amount, int flags, int monst) { char logmessage[220], ltemp[80]; char *killer; if (waswizard) return; #ifdef LOGFILE sprintf(logmessage, "%d %d %s %d ", time(NULL), amount, whoami, pstats.s_lvl); if (flags == 0) /* died */ { strcat(logmessage, "killed by a"); killer = killname(monst); if (*killer == 'a' || *killer == 'e' || *killer == 'i' || *killer == 'o' || *killer == 'u') strcat(logmessage, "n "); else strcat(logmessage, " "); strcat(logmessage, killer); if (amulet) sprintf(ltemp, " on level %d [max %d] with the Amulet\n", level, max_level); else sprintf(ltemp, " on level %d\n", level); strcat(logmessage, ltemp); } else if (flags == 1) /* quit */ { if (amulet) sprintf(ltemp, "quit on level %d [max %d] with the Amulet\n", level, max_level); else sprintf(ltemp, "quit on level %d\n", level); strcat(logmessage, ltemp); } else if (flags == 2) /* won */ { sprintf(ltemp, "escaped with the Amulet [deepest level: %d]\n", max_level); strcat(logmessage, ltemp); } else return; if (logfi == NULL) return; /* and write it */ md_lockfile(logfi); fprintf(logfi, "%s", logmessage); md_unlockfile(logfi); fclose(logfi); #endif return; } void total_winner() { struct linked_list *item; struct object *obj; int worth = 0; int c; int 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 admitted to the fighters guild.\n"); mvaddstr(LINES - 1, 0, "--Press space to continue--"); refresh(); wait_for(stdscr, ' '); clear(); mvaddstr(0, 0, " Worth Item"); oldpurse = purse; for (c = 'a', item = pack; item != NULL; c++, item = next(item)) { obj = (struct object *) ldata(item); switch (obj->o_type) { case FOOD: worth = 2 * obj->o_count; when WEAPON: switch (obj->o_which) { case MACE: worth = 8; when SWORD: worth = 15; when BOW: worth = 75; when ARROW: worth = 1; when DAGGER: worth = 2; when ROCK: worth = 1; when TWOSWORD: worth = 30; when SLING: worth = 1; when DART: worth = 1; when CROSSBOW: worth = 15; when BOLT: worth = 1; when SPEAR: worth = 2; otherwise: worth = 0; } worth *= (1 + (10 * obj->o_hplus + 10 * obj->o_dplus)); worth *= obj->o_count; obj->o_flags |= ISKNOW; when ARMOR: switch (obj->o_which) { case LEATHER: worth = 5; when RING_MAIL: worth = 30; when STUDDED_LEATHER: worth = 15; when SCALE_MAIL: worth = 3; when CHAIN_MAIL: worth = 75; when SPLINT_MAIL: worth = 80; when BANDED_MAIL: worth = 90; when PLATE_MAIL: worth = 400; otherwise: worth = 0; } if (obj->o_which >= MAXARMORS) break; worth *= (1 + (10 * (a_class[obj->o_which] - obj->o_ac))); obj->o_flags |= ISKNOW; when SCROLL: s_know[obj->o_which] = TRUE; worth = s_magic[obj->o_which].mi_worth; worth *= obj->o_count; when POTION: p_know[obj->o_which] = TRUE; worth = p_magic[obj->o_which].mi_worth; worth *= obj->o_count; when RING: obj->o_flags |= ISKNOW; r_know[obj->o_which] = TRUE; worth = r_magic[obj->o_which].mi_worth; if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM || obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT) if (obj->o_ac > 0) worth += obj->o_ac * 20; else worth = 50; when STICK: obj->o_flags |= ISKNOW; ws_know[obj->o_which] = TRUE; worth = ws_magic[obj->o_which].mi_worth; worth += 20 * obj->o_charges; when AMULET: worth = 1000; } mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE)); purse += worth; } mvprintw(c - 'a' + 1, 0," %5d Gold Peices ", oldpurse); refresh(); writelog(purse, 2, 0); score(purse, 2, 0); printf("[Press return to exit]\n"); fflush(NULL); getchar(); exit(0); } char * killname(int monst) { if (isupper(monst)) return monsters[monst-'A'].m_name; else switch (monst) { case 'a': return "arrow"; case 'd': return "dart"; case 'b': return "bolt"; } return(""); }