Mercurial > hg > early-roguelike
view rogue4/rip.c @ 252:3d4252fa2ed3
Use more portable random seed generation.
The new function md_random_seed() has replaced time() + getpid() and
similar methods. Putting everything in mdport.c slightly reduces the
warnings and workarounds.
author | John "Elwin" Edwards |
---|---|
date | Sat, 28 Jan 2017 15:49:41 -0500 |
parents | 23d2e2bf812f |
children | d3968e9cb98d |
line wrap: on
line source
/* * File for the fun ends * Death or a total win * * @(#)rip.c 4.28 (Berkeley) 4/12/82 * * Rogue: Exploring the Dungeons of Doom * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman * All rights reserved. * * See the file LICENSE.TXT for full copyright and licensing information. */ #include <curses.h> #include <time.h> #include <signal.h> #include <sys/types.h> #include <string.h> #include <stdlib.h> #include "rogue.h" char *killname(char monst, bool doart); static char *rip[] = { " __________", " / \\", " / REST \\", " / IN \\", " / PEACE \\", " / \\", " | |", " | |", " | killed by a |", " | |", " | 1980 |", " *| * * * | *", " ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______", 0 }; /* * score: * Figure score and post it. */ /* VARARGS2 */ void score(int amount, int flags, char monst) { register struct sc_ent *scp; register int i; register struct sc_ent *sc2; register FILE *outf; register int prflags = 0; register void (*fp)(int); register int uid; char scoreline[MAXSTR + 100]; static struct sc_ent { char sc_name[MAXSTR]; unsigned int sc_flags; unsigned int sc_uid; unsigned short sc_monster; unsigned short sc_score; unsigned short sc_level; } top_ten[10]; static char *reason[] = { "killed", "quit", "A total winner", }; void endit(); start_score(); if (fd >= 0) outf = md_fdopen(fd, "wb"); else return; for (scp = top_ten; scp <= &top_ten[9]; scp++) { scp->sc_score = 0; for (i = 0; i < MAXSTR; i++) scp->sc_name[i] = rnd(255); scp->sc_flags = RN; scp->sc_level = RN; scp->sc_monster = RN; scp->sc_uid = RN; } signal(SIGINT, SIG_DFL); if (flags != -1 #ifdef WIZARD || wizard #endif ) { mvaddstr(LINES - 1, 0 , "[Press return to continue]"); refresh(); wgetnstr(stdscr,prbuf,80); move(LINES - 1, 0); clrtoeol(); refresh(); endwin(); } #ifdef WIZARD if (wizard) if (strcmp(prbuf, "names") == 0) prflags = 1; else if (strcmp(prbuf, "edit") == 0) prflags = 2; #endif for(i=0; i<10; i++) { encread((char *) &top_ten[i].sc_name, MAXSTR, fd); scoreline[0] = '\0'; encread((char *) scoreline, 100, fd); sscanf(scoreline, "%d %d %hd %hd %hd", &top_ten[i].sc_flags, &top_ten[i].sc_uid, &top_ten[i].sc_monster, &top_ten[i].sc_score, &top_ten[i].sc_level); } /* * Insert her in list if need be */ sc2 = NULL; if (!noscore) { uid = md_getuid(); for (scp = top_ten; scp <= &top_ten[9]; scp++) if (amount > scp->sc_score) break; #ifdef LIMIT_TOPTEN else if (flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2) scp = &top_ten[9] + 1; /* only one score per nowin uid */ #endif if (scp <= &top_ten[9]) { #ifdef LIMIT_TOPTEN if (flags != 2) for (sc2 = scp; sc2 <= &top_ten[9]; sc2++) { if (sc2->sc_uid == uid && sc2->sc_flags != 2) break; } else #endif sc2 = &top_ten[9]; while (sc2 > scp) { *sc2 = sc2[-1]; sc2--; } scp->sc_score = amount; strncpy(scp->sc_name, whoami, MAXSTR); scp->sc_flags = flags; if (flags == 2) scp->sc_level = max_level; else scp->sc_level = level; scp->sc_monster = monst; scp->sc_uid = uid; sc2 = scp; } } /* * Print the list */ printf("Top Ten Rogueists:\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 %s", killname((char) scp->sc_monster, TRUE)); if (prflags == 1) { char *name; name = md_getusername(scp->sc_uid); if (name == NULL) printf(" (%d)", scp->sc_uid); else printf(" (%s)", name); 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 < MAXSTR; 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"); } else break; } fseek(outf, 0L, 0); /* * Update the list file */ if (sc2 != NULL) { if (lock_sc()) { int i; fp = signal(SIGINT, SIG_IGN); for(i=0; i<10; i++) { encwrite((char *) &top_ten[i].sc_name, MAXSTR, outf); sprintf(scoreline," %d %d %hd %hd %hd \n", top_ten[i].sc_flags, top_ten[i].sc_uid, top_ten[i].sc_monster, top_ten[i].sc_score, top_ten[i].sc_level); encwrite((char *) scoreline, 100, outf); } unlock_sc(); signal(SIGINT, fp); } } fclose(outf); } void writelog(int amount, int flags, char monst) { FILE *logfi; char logmessage[220], ltemp[80]; char *killer; if (noscore) return; #ifdef LOGFILE if (lfd >= 0) logfi = md_fdopen(lfd, "a"); else return; if (logfi == NULL) return; /* otherwise writing should work */ sprintf(logmessage, "%d %d %s %d ", time(NULL), amount, whoami, pstats.s_lvl); if (flags == 0) /* died */ { strcat(logmessage, "killed by "); killer = killname(monst, TRUE); 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 { fclose(logfi); return; } /* then write */ fprintf(logfi, "%s", logmessage); fclose(logfi); #endif return; } /* * death: * Do something really fun when he dies */ void death(char monst) { register char **dp = rip, *killer; register struct tm *lt; time_t date; char buf[MAXSTR]; struct tm *localtime(); signal(SIGINT, SIG_IGN); purse -= purse / 10; signal(SIGINT, leave); 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, "%d Au", purse); mvaddstr(15, 28-((strlen(buf)+1)/2), buf); killer = killname(monst, FALSE); mvaddstr(17, 28-((strlen(killer)+1)/2), killer); if (monst == 's') mvaddch(16, 32, ' '); else mvaddstr(16, 33, vowelstr(killer)); sprintf(prbuf, "%2d", 1900+lt->tm_year); mvaddstr(18, 26, prbuf); move(LINES-1, 0); refresh(); writelog(purse, 0, monst); score(purse, 0, monst); /* Make sure the output gets through */ printf("[Press return to exit]\n"); fflush(NULL); getchar(); exit(0); } /* * total_winner: * Code for a winner */ void total_winner(void) { register THING *obj; register int worth = 0; register char c; register 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(' '); clear(); mvaddstr(0, 0, " Worth Item"); oldpurse = purse; for (c = 'a', obj = pack; obj != NULL; c++, obj = next(obj)) { 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 CROSSBOW: worth = 30; when ARROW: worth = 1; when DAGGER: worth = 2; when TWOSWORD: worth = 75; when DART: worth = 1; when BOW: worth = 15; when BOLT: worth = 1; when SPEAR: worth = 5; } worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count; obj->o_flags |= ISKNOW; when ARMOR: switch (obj->o_which) { case LEATHER: worth = 20; when RING_MAIL: worth = 25; when STUDDED_LEATHER: worth = 20; when SCALE_MAIL: worth = 30; when CHAIN_MAIL: worth = 75; when SPLINT_MAIL: worth = 80; when BANDED_MAIL: worth = 90; when PLATE_MAIL: worth = 150; } worth += (9 - obj->o_ac) * 100; worth += (10 * (a_class[obj->o_which] - obj->o_ac)); obj->o_flags |= ISKNOW; when SCROLL: worth = s_magic[obj->o_which].mi_worth; worth *= obj->o_count; if (!s_know[obj->o_which]) worth /= 2; s_know[obj->o_which] = TRUE; when POTION: worth = p_magic[obj->o_which].mi_worth; worth *= obj->o_count; if (!p_know[obj->o_which]) worth /= 2; p_know[obj->o_which] = TRUE; when RING: 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 * 100; else worth = 10; if (!(obj->o_flags & ISKNOW)) worth /= 2; obj->o_flags |= ISKNOW; r_know[obj->o_which] = TRUE; when STICK: worth = ws_magic[obj->o_which].mi_worth; worth += 20 * obj->o_charges; if (!(obj->o_flags & ISKNOW)) worth /= 2; obj->o_flags |= ISKNOW; ws_know[obj->o_which] = TRUE; when AMULET: worth = 1000; } if (worth < 0) worth = 0; mvprintw(c - 'a' + 1, 0, "%c) %5d %s", c, worth, inv_name(obj, FALSE)); purse += worth; } mvprintw(c - 'a' + 1, 0," %5d Gold Pieces ", oldpurse); refresh(); writelog(purse, 2, 0); score(purse, 2, 0); printf("[Press return to exit]\n"); fflush(NULL); getchar(); exit(0); } /* * killname: * Convert a code to a monster name */ char * killname(char monst, bool doart) { register const char *sp; register bool article; sp = prbuf; article = TRUE; switch (monst) { case 'a': sp = "arrow"; when 'b': sp = "bolt"; when 'd': sp = "dart"; when 's': sp = "starvation"; article = FALSE; otherwise: if (monst >= 'A' && monst <= 'Z') sp = monsters[monst-'A'].m_name; else { sp = "God"; article = FALSE; } } if (doart && article) sprintf(prbuf, "a%s ", vowelstr(sp)); else prbuf[0] = '\0'; strcat(prbuf, sp); return prbuf; }