diff urogue/rip.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children 911f0aa6e758
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/urogue/rip.c	Tue Jan 31 19:56:04 2017 -0500
@@ -0,0 +1,661 @@
+/*
+    rip.c - File for the fun ends Death or a total win
+       
+    UltraRogue: The Ultimate Adventure in the Dungeons of Doom
+    Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
+    All rights reserved.
+
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
+    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.
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include "rogue.h"
+
+static struct sc_ent
+{
+    int sc_lvl;
+    long    sc_score;
+    char    sc_name[76];
+    long    sc_gold;
+    int sc_flags;
+    int sc_level;
+    int   sc_artifacts;
+    int   sc_monster;
+} top_ten[10];
+
+
+static const char *rip[] =
+{
+    "                       __________",
+    "                      /          \\",
+    "                     /    REST    \\",
+    "                    /      IN      \\",
+    "                   /     PEACE      \\",
+    "                  /                  \\",
+    "                  |                  |",
+    "                  |                  |",
+    "                  |    killed by     |",
+    "                  |                  |",
+    "                  |       1993       |",
+    "                 *|     *  *  *      | *",
+    "       ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
+    0
+};
+
+/*
+    death()
+        Do something really fun when he dies
+*/
+
+void
+death(int monst)
+{
+    char **dp = (char **) rip, *killer;
+    struct tm   *lt;
+    time_t  date;
+    char    buf[80];
+	int c;
+
+    if (is_wearing(R_RESURRECT) || rnd(wizard ? 3 : 67) == 0)
+    {
+        int die = TRUE;
+
+        if (resurrect-- == 0)
+            msg("You've run out of lives.");
+        else if (!save_resurrect(ring_value(R_RESURRECT)))
+            msg("Your attempt to return from the grave fails.");
+        else
+        {
+            struct linked_list  *item;
+            struct linked_list  *next_item;
+            struct object   *obj;
+            int rm, flags;
+            coord   pos;
+
+            die = FALSE;
+            msg("You feel a sudden warmth and then nothingness.");
+            teleport();
+
+            if (ring_value(R_RESURRECT) > 1 && rnd(10))
+            {
+                pstats.s_hpt = 2 * pstats.s_const;
+                pstats.s_const = max(pstats.s_const - 1, 3);
+            }
+            else
+            {
+                for (item = pack; item != NULL; item = next_item)
+                {
+                    obj = OBJPTR(item);
+
+                    if (obj->o_flags & ISOWNED || obj->o_flags & ISPROT)
+                    {
+                        next_item = next(item);
+                        continue;
+                    }
+
+                    flags = obj->o_flags;
+                    obj->o_flags &= ~ISCURSED;
+                    dropcheck(obj);
+                    obj->o_flags = flags;
+                    next_item = next(item);
+                    rem_pack(obj);
+
+                    if (obj->o_type == ARTIFACT)
+                        has_artifact &= ~(1 << obj->o_which);
+
+                    do
+                    {
+                        rm = rnd_room();
+                        rnd_pos(&rooms[rm], &pos);
+                    }
+                    while(winat(pos.y, pos.x) != FLOOR);
+
+                    obj->o_pos = pos;
+                    add_obj(item, obj->o_pos.y, obj->o_pos.x);
+                }
+
+                pstats.s_hpt = pstats.s_const;
+                pstats.s_const = max(pstats.s_const - roll(2, 2), 3);
+            }
+
+            chg_str(roll(1, 4), TRUE, FALSE);
+            pstats.s_lvl = max(pstats.s_lvl, 1);
+            no_command += 2 + rnd(4);
+
+            if (on(player, ISHUH))
+                lengthen_fuse(FUSE_UNCONFUSE, rnd(8) + HUHDURATION);
+            else
+                light_fuse(FUSE_UNCONFUSE, 0, rnd(8) + HUHDURATION, AFTER);
+
+            turn_on(player, ISHUH);
+            light(&hero);
+        }
+
+        if (die)
+        {
+            wmove(cw, mpos, 0);
+            waddstr(cw, morestr);
+            wrefresh(cw);
+            wait_for(' ');
+        }
+        else
+            return;
+    }
+
+    time(&date);
+    lt = localtime(&date);
+    clear();
+    wclear(cw);
+    move(8, 0);
+
+    while (*dp)
+        printw("%s\n", *dp++);
+
+    mvaddstr(14, 28 - ((int)(strlen(whoami) + 1) / 2), whoami);
+    sprintf(buf, "%d+%ld Points", pstats.s_lvl, pstats.s_exp);
+    mvaddstr(15, 28 - ((int)(strlen(buf) + 1) / 2), buf);
+    killer = killname(monst,buf);
+    mvaddstr(17, 28 - ((int)(strlen(killer) + 1) / 2), killer);
+    mvaddstr(18, 28, (sprintf(prbuf, "%2d", lt->tm_year), prbuf));
+    move(LINES - 1, 0);
+
+    mvaddstr(LINES - 1, 0, retstr);
+
+    while ((c = readcharw(stdscr)) != '\n' && c != '\r')
+        continue;
+    idenpack();
+    wrefresh(cw);
+    refresh();
+
+    score(pstats.s_exp, pstats.s_lvl, KILLED, monst);
+    byebye();
+}
+
+/*
+    score()
+        figure score and post it.
+*/
+
+void
+score(long amount, int lvl, int flags, int monst) /*ARGSUSED*/
+{
+    struct sc_ent   *scp=NULL, *sc2=NULL;
+    int i;
+    char    *killer;
+    char buf[1024];
+
+    static const char *reason[] =
+    {
+        "killed",
+        "quit",
+        "a winner",
+        "a total winner"
+    };
+
+    char    *packend;
+
+    if (flags != WINNER && flags != TOTAL && flags != SCOREIT)
+    {
+        if (flags == CHICKEN)
+            packend = "when you quit";
+        else
+            packend = "at your untimely demise";
+
+        noecho();
+        nl();
+        refresh();
+        showpack(packend);
+    }
+
+    /* Open file and read list */
+
+    if (fd_score == NULL)
+    {
+        printf("No score file opened\n");
+        return;
+    }
+
+    for (scp = top_ten; scp < &top_ten[10]; scp++)
+    {
+        scp->sc_lvl = 0L;
+        scp->sc_score = 0L;
+
+        for (i = 0; i < 76; i++)
+            scp->sc_name[i] = ucrnd(255);
+
+        scp->sc_gold = 0L;
+        scp->sc_flags = rnd(10);
+        scp->sc_level = rnd(10);
+        scp->sc_monster = srnd(10);
+        scp->sc_artifacts = 0;
+    }
+
+    if (flags != SCOREIT)
+    {
+        mvaddstr(LINES - 1, 0, retstr);
+        refresh();
+        fflush(stdout);
+        wait_for('\n');
+    }
+
+    fseek(fd_score, 0L, SEEK_SET);
+    fread(top_ten, sizeof(top_ten), 1, fd_score);
+
+    /* Insert player in list if need be */
+
+    if (!waswizard)
+    {
+        for (scp = top_ten; scp < &top_ten[10]; scp++)
+        {
+            if (lvl > scp->sc_lvl)
+                break;
+
+            if (lvl == scp->sc_lvl && amount > scp->sc_score)
+                break;
+        }
+
+        if (scp < &top_ten[10])
+        {
+            if (flags == WINNER)
+                sc2 = &top_ten[9]; /* LAST WINNER ALWAYS MAKES IT */
+
+            while (sc2 > scp)
+            {
+                *sc2 = sc2[-1];
+                sc2--;
+            }
+            
+			scp->sc_lvl = lvl;
+			scp->sc_gold = purse;
+            scp->sc_score = amount;
+            strcpy(scp->sc_name, whoami);
+			strcat(scp->sc_name,", ");
+			strcat(scp->sc_name, which_class(player.t_ctype));
+            scp->sc_flags = flags;
+			
+            if (flags == WINNER)
+                scp->sc_level = max_level;
+            else
+                scp->sc_level = level;
+				
+            scp->sc_monster = monst;
+	    scp->sc_artifacts = has_artifact;
+
+            sc2 = scp;
+        }
+    }
+
+    if (flags != SCOREIT)
+    {
+        clear();
+        refresh();
+        endwin();
+    }
+
+    /* Print the list */
+
+    printf("\nTop Ten Adventurers:\n%4s %15s %10s %s\n",
+	    "Rank", "Score", "Gold", "Name");
+
+    for (scp = top_ten; scp < &top_ten[10]; scp++)
+    {
+        if (scp->sc_score)
+        {
+		    char lev[20];
+			
+			sprintf(lev, "%ld+%ld", scp->sc_lvl, scp->sc_score);
+            printf("%4d %15s %10ld %s:", scp - top_ten + 1, 
+			       lev,
+                   scp->sc_gold,
+                   scp->sc_name);
+
+            if (scp->sc_artifacts)
+            {
+                char  thangs[80];
+                int   n;
+                int   first = TRUE;
+
+                thangs[0] = '\0';
+
+                for (n = 0; n <= maxartifact; n++)
+                {
+                    if (scp->sc_artifacts & (1 << n))
+                    {
+                        if (strlen(thangs))
+                            strcat(thangs, ", ");
+
+                        if (first)
+                        {
+                            strcat(thangs, "retrieved ");
+                            first = FALSE;
+                        }
+
+                        if (45 - strlen(thangs) < strlen(arts[n].ar_name))
+                        {
+                            printf("%s\n%32s", thangs," ");
+                            thangs[0] = '\0';
+                        }
+                        strcat(thangs, arts[n].ar_name);
+                    }
+                }
+
+                if (strlen(thangs))
+                    printf("%s,", thangs);
+
+                printf("\n%32s"," ");
+            }
+
+            printf("%s on level %d",reason[scp->sc_flags],scp->sc_level);
+
+            if (scp->sc_flags == 0)
+            {
+                printf(" by \n%32s"," ");
+                killer = killname(scp->sc_monster, buf);
+                printf(" %s", killer);
+            }
+
+            putchar('\n');
+        }
+    }
+
+    if (sc2 != NULL)
+    {
+        fseek(fd_score, 0L, SEEK_SET);
+        /* Update the list file */
+        fwrite(top_ten, sizeof(top_ten), 1, fd_score);
+    }
+
+    fclose(fd_score);
+}
+
+void
+total_winner(void)
+{
+    struct linked_list  *item;
+    struct object   *obj;
+    int worth, oldpurse;
+    char    c;
+    struct linked_list  *bag = NULL;
+
+    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 \n");
+    addstr("escaped the Dungeons of Doom alive.  You journey home \n");
+    addstr("and sell all your loot at a great profit.\n");
+    addstr("The White Council approves the recommendation of\n");
+
+    if (player.t_ctype == C_FIGHTER)
+        addstr("the fighters guild and appoints you Lord Protector\n");
+    else if (player.t_ctype == C_ASSASIN)
+        addstr("the assassins guild and appoints you Master Murderer\n");
+    else if (player.t_ctype == C_NINJA)
+        addstr("the ninja guild and appoints you Master of the Wind\n");
+    else if (player.t_ctype == C_ILLUSION)
+        addstr("the illusionists guild and appoints you Master Wizard\n");
+    else if (player.t_ctype == C_MAGICIAN)
+        addstr("the magicians guild and appoints you Master Wizard\n");
+    else if (player.t_ctype == C_CLERIC)
+        addstr("the temple priests and appoints you Master of the Flowers\n");
+    else if (player.t_ctype == C_DRUID)
+        addstr("the temple priests and appoints you Master of the Flowers\n");
+    else if (player.t_ctype == C_RANGER)
+        addstr("the rangers guild and appoints you Master Ranger\n");
+    else if (player.t_ctype == C_PALADIN)
+        addstr("the paladins guild and appoints you Master Paladin\n");
+    else if (player.t_ctype == C_THIEF)
+    {
+        addstr("the thieves guild under protest and appoints you\n");
+        addstr("Master of the Highways\n");
+    }
+
+    addstr("of the Land Between the Mountains.\n");
+    mvaddstr(LINES - 1, 0, spacemsg);
+    refresh();
+    wait_for(' ');
+    clear();
+    idenpack();
+    oldpurse = purse;
+    mvaddstr(0, 0, "   Worth  Item");
+
+    for (c = 'a', item = pack; item != NULL; c++, item = next(item))
+    {
+        obj = OBJPTR(item);
+        worth = get_worth(obj);
+        purse += worth;
+
+        if (obj->o_type == ARTIFACT && obj->o_which == TR_PURSE)
+            bag = obj->o_bag;
+
+        mvprintw(c - 'a' + 1, 0, "%c) %8d  %s", c,
+             worth, inv_name(obj, UPPERCASE));
+    }
+
+    if (bag != NULL)
+    {
+        mvaddstr(LINES - 1, 0, morestr);
+        refresh();
+        wait_for(' ');
+        clear();
+        mvprintw(0, 0, "Contents of the Magic Purse of Yendor:\n");
+
+        for (c = 'a', item = bag; item != NULL; c++, item = next(item))
+        {
+            obj = OBJPTR(item);
+            worth = get_worth(obj);
+            whatis(item);
+            purse += worth;
+            mvprintw(c - 'a' + 1, 0, "%c) %8d %s\n", c,
+                 worth, inv_name(obj, UPPERCASE));
+        }
+    }
+
+    mvprintw(c - 'a' + 1, 0, "   %6d  Gold Pieces          ", oldpurse);
+    refresh();
+
+    if (has_artifact == 255)
+        score(pstats.s_exp, pstats.s_lvl, TOTAL, 0);
+    else
+        score(pstats.s_exp, pstats.s_lvl, WINNER, 0);
+
+    byebye();
+}
+
+char *
+killname(int monst, char *buf)
+{
+    if (buf == NULL)
+        return("A bug in UltraRogue #102");
+
+    if (monst >= 0)
+    {
+        switch (monsters[monst].m_name[0])
+        {
+            case 'a':
+            case 'e':
+            case 'i':
+            case 'o':
+            case 'u':
+                sprintf(buf, "an %s", monsters[monst].m_name);
+                break;
+            default:
+                sprintf(buf, "a %s", monsters[monst].m_name);
+        }
+
+        return(buf);
+    }
+    else
+        switch(monst)
+        {
+            case D_ARROW:
+                strcpy(buf, "an arrow"); break;
+            case D_DART:
+                strcpy(buf, "a dart"); break;
+            case D_BOLT:
+                strcpy(buf, "a bolt"); break;
+            case D_POISON:
+                strcpy(buf, "poison"); break;
+            case D_POTION:
+                strcpy(buf, "a cursed potion"); break;
+            case D_PETRIFY:
+                strcpy(buf, "petrification"); break;
+            case D_SUFFOCATION:
+                strcpy(buf, "suffocation"); break;
+            case D_INFESTATION:
+                strcpy(buf, "a parasite"); break;
+            case D_DROWN:
+                strcpy(buf, "drowning"); break;
+            case D_FALL:
+                strcpy(buf, "falling"); break;
+            case D_FIRE:
+                strcpy(buf, "slow boiling in oil"); break;
+            case D_SPELLFUMBLE:
+                strcpy(buf, "a botched spell"); break;
+            case D_DRAINLIFE:
+                strcpy(buf, "a drain life spell"); break;
+            case D_ARTIFACT:
+                strcpy(buf, "an artifact of the gods"); break;
+            case D_GODWRATH:
+                strcpy(buf, "divine retribution"); break;
+            case D_CLUMSY:
+                strcpy(buf, "excessive clumsyness"); break;
+            default:
+                strcpy(buf, "stupidity"); break;
+        }
+
+    return(buf);
+}
+
+/*
+    showpack()
+        Display the contents of the hero's pack
+*/
+
+void
+showpack(char *howso)
+{
+    char    *iname;
+    unsigned int worth;
+    int cnt, ch, oldpurse;
+    struct linked_list  *item;
+    struct object   *obj;
+    struct linked_list  *bag = NULL;
+
+    cnt = 1;
+    clear();
+    mvprintw(0, 0, "Contents of your pack %s:\n", howso);
+    ch = 0;
+    oldpurse = purse;
+    purse = 0;
+
+    for (item = pack; item != NULL; item = next(item))
+    {
+        obj = OBJPTR(item);
+        worth = get_worth(obj);
+        whatis(item);
+        purse += worth;
+
+        if (obj->o_type == ARTIFACT && obj->o_which == TR_PURSE)
+            bag = obj->o_bag;
+
+        iname = inv_name(obj, UPPERCASE);
+        mvprintw(cnt, 0, "%d) %s\n", ch, iname);
+        ch += 1;
+
+        if (++cnt > LINES - 5 && next(item) != NULL)
+        {
+            cnt = 1;
+            mvaddstr(LINES - 1, 0, morestr);
+            refresh();
+            wait_for(' ');
+            clear();
+        }
+    }
+
+    if (bag != NULL)
+    {
+        mvaddstr(LINES - 1, 0, morestr);
+        refresh();
+        wait_for(' ');
+        clear();
+        cnt = 1;
+        ch = 0;
+
+        mvprintw(0, 0, "Contents of the Magic Purse of Yendor %s:\n", howso);
+
+        for (item = bag; item != NULL; item = next(item))
+        {
+            obj = OBJPTR(item);
+            worth = get_worth(obj);
+            whatis(item);
+            purse += worth;
+            mvprintw(cnt, 0, "%d) %s\n", ch, inv_name(obj, UPPERCASE));
+            ch += 1;
+
+            if (++cnt > LINES - 5 && next(item) != NULL)
+            {
+                cnt = 1;
+                mvaddstr(LINES - 1, 0, morestr);
+                refresh();
+                wait_for(' ');
+                clear();
+            }
+        }
+    }
+
+    mvprintw(cnt + 1, 0, "Carrying %d gold pieces", oldpurse);
+    mvprintw(cnt + 2, 0, "Carrying objects worth %d gold pieces", purse);
+    purse += oldpurse;
+    refresh();
+}
+
+void
+byebye(void)
+{
+    endwin();
+    printf("\n");
+    exit(0);
+}
+
+/*
+    save_resurrect()
+        chance of resurrection according to modifed D&D probabilities
+*/
+
+int
+save_resurrect(int bonus)
+{
+    int need, adjust;
+
+    adjust = pstats.s_const + bonus - luck;
+
+    if (adjust > 17)
+        return(TRUE);
+    else if (adjust < 14)
+        need = 5 * (adjust + 5);
+    else
+        need = 90 + 2 * (adjust - 13);
+
+    return(roll(1, 100) < need);
+}