Mercurial > hg > early-roguelike
view rogue4/rip.c @ 245:e7aab31362af
Rogue V[345], Super-Rogue: Fix violet fungi/venus flytraps.
Violet fungi (renamed venus flytraps in Rogue V5) do an increasing
amount of damage each time they hit. If they miss, you still suffer
the same number of HP. This worked by keeping a counter and printing
new damage strings into monsters[5].m_stats.s_dmg, which is the
"prototype" of that particular monster.
Each individual monster has its own damage string. Apparently these
were once char *, pointing to the same string as the prototype. When
the s_dmg member was changed to be an internal char array, changing the
prototype's damage string no longer had any effect on actual monsters.
As a result, flytraps did no damage on a hit, or only one point in V5.
The mechanism for doing damage on a miss continued to work.
This has been fixed by overwriting the individual monster's damage
string instead of the prototype's. It is now no longer necessary to
reset the damage string when the flytrap is killed. The method for
resetting it when the hero teleports away had to be modified. Comments
referencing the long-unused xstr have been removed.
author | John "Elwin" Edwards |
---|---|
date | Sun, 01 May 2016 19:39:56 -0400 |
parents | 1b73a8641b37 |
children | 23d2e2bf812f |
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 = 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; }