diff urogue/misc.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 e52a8a7ad4c5
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/urogue/misc.c	Tue Jan 31 19:56:04 2017 -0500
@@ -0,0 +1,1208 @@
+/*
+    misc.c - all sorts of miscellaneous routines
+  
+    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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+    tr_name()
+        print the name of a trap
+*/
+
+char *
+tr_name(char ch, char *trname)
+{
+    const char *s = NULL;
+
+    if (trname == NULL)
+        return(" Your found an error in UltraRogue #100.");
+
+    switch(ch)
+    {
+        case TRAPDOOR:
+            s = "trapdoor.";
+            break;
+        case BEARTRAP:
+            s = "beartrap.";
+            break;
+        case SLEEPTRAP:
+            s = "sleeping gas trap.";
+            break;
+        case ARROWTRAP:
+            s = "arrow trap.";
+            break;
+        case TELTRAP:
+            s = "teleport trap.";
+            break;
+        case DARTTRAP:
+            s = "dart trap.";
+            break;
+        case POOL:
+            s = "shimmering pool.";
+            break;
+        case MAZETRAP:
+            s = "maze entrance.";
+            break;
+        case FIRETRAP:
+            s = "fire trap.";
+            break;
+        case POISONTRAP:
+            s = "poison pool trap.";
+            break;
+        case LAIR:
+            s = "monster lair.";
+            break;
+        case RUSTTRAP:
+            s = "rust trap.";
+            break;
+        default:
+            ;
+    }
+
+    sprintf(trname, "You found a %s.", s);
+
+    return(trname);
+}
+
+/*
+    look()
+        A quick glance all around the player
+*/
+
+void
+look(int wakeup)
+{
+    int     x, y;
+    char   ch, och;
+    int  oldx, oldy;
+    int inpass, horizontal, vertical, do_light = FALSE, do_blank = FALSE;
+    int passcount = 0;
+    struct room *rp;
+    int ey, ex;
+
+    /* Are we moving vertically or horizontally? */
+
+    if (runch == 'h' || runch == 'l')
+        horizontal = TRUE;
+    else
+        horizontal = FALSE;
+
+    if (runch == 'j' || runch == 'k')
+        vertical = TRUE;
+    else
+        vertical = FALSE;
+
+    getyx(cw, oldy, oldx);  /* Save current position */
+
+    /*
+     * Blank out the floor around our last position and check for moving
+     * out of a corridor in a maze.
+    */
+
+    if (oldrp != NULL && (oldrp->r_flags & ISDARK) &&
+        !(oldrp->r_flags & HASFIRE) && off(player, ISBLIND))
+        do_blank = TRUE;
+
+    for (x = player.t_oldpos.x - 1; x <= player.t_oldpos.x + 1; x++)
+        for (y = player.t_oldpos.y - 1; y <= player.t_oldpos.y + 1;
+                y++)
+        {
+            ch = show(y, x);
+
+            if (do_blank && (y != hero.y || x != hero.x) && ch == FLOOR)
+                mvwaddch(cw, y, x, ' ');
+
+            /* Moving out of a corridor? */
+
+            if (levtype == MAZELEV &&
+                (ch != '|' && ch != '-') && /* Not a wall */
+                ((vertical && x != player.t_oldpos.x &&
+                y == player.t_oldpos.y) ||
+                 (horizontal && y != player.t_oldpos.y &&
+                x == player.t_oldpos.x)))
+                do_light = TRUE;    /* Just came to a turn */
+        }
+
+    inpass = ((rp = roomin(hero)) == NULL);    /* Are we in a passage? */
+
+    /* Are we coming out of a wall into a corridor in a maze? */
+    och = show(player.t_oldpos.y, player.t_oldpos.x);
+    ch = show(hero.y, hero.x);
+
+    if (levtype == MAZELEV && (och == '|' || och == '-' ||
+        och == SECRETDOOR) && (ch != '|' && ch != '-' && ch != SECRETDOOR))
+    {
+        do_light = off(player, ISBLIND);    /* Light it up if not blind */
+    }
+
+    /* Look around the player */
+
+    ey = hero.y + 1;
+    ex = hero.x + 1;
+
+    for (x = hero.x - 1; x <= ex; x++)
+        if (x >= 0 && x < COLS)
+            for (y = hero.y - 1; y <= ey; y++)
+            {
+                if (y <= 0 || y >= LINES - 2)
+                    continue;
+
+                if (isalpha(mvwinch(mw, y, x)))
+                {
+                    struct linked_list  *it;
+                    struct thing    *tp;
+
+                    if (wakeup)
+                        it = wake_monster(y, x);
+                    else
+                        it = find_mons(y, x);
+
+                    if (it == NULL)
+                        continue;
+
+                    tp = THINGPTR(it);
+                    tp->t_oldch = CCHAR( mvinch(y, x) );
+
+                    if (isatrap(tp->t_oldch))
+                    {
+                        struct trap *trp = trap_at(y, x);
+
+                        tp->t_oldch = (trp->tr_flags & ISFOUND) ? tp->t_oldch
+                            : trp->tr_show;
+                    }
+
+                    if (tp->t_oldch == FLOOR &&
+                        (rp->r_flags & ISDARK)
+                        && !(rp->r_flags & HASFIRE) &&
+                        off(player, ISBLIND))
+                        tp->t_oldch = ' ';
+                }
+
+                /* Secret doors show as walls */
+
+                if ((ch = show(y, x)) == SECRETDOOR)
+                    ch = secretdoor(y, x);
+
+                /*
+                 * Don't show room walls if he is in a
+                 * passage and check for maze turns
+                */
+
+                if (off(player, ISBLIND))
+                {
+                    if (y == hero.y && x == hero.x || (inpass && (ch == '-' ||
+                        ch == '|')))
+                        continue;
+
+                    /* Are we at a crossroads in a maze? */
+
+                    if (levtype == MAZELEV && (ch != '|' && ch != '-') &&
+                        /* Not a wall */
+                        ((vertical && x != hero.x && y == hero.y) ||
+                         (horizontal && y != hero.y && x == hero.x)))
+                        do_light = TRUE;
+                        /* Just came to a turn */
+                }
+                else if (y != hero.y || x != hero.x)
+                    continue;
+
+                wmove(cw, y, x);
+                waddch(cw, ch);
+
+                if (door_stop && !firstmove && running)
+                {
+                    switch (runch)
+                    {
+                        case 'h':
+                            if (x == ex)
+                                continue;
+                            break;
+                        case 'j':
+                            if (y == hero.y - 1)
+                                continue;
+                            break;
+                        case 'k':
+                            if (y == ey)
+                                continue;
+                            break;
+                        case 'l':
+                            if (x == hero.x - 1)
+                                continue;
+                            break;
+                        case 'y':
+                            if ((x + y) - (hero.x + hero.y) >= 1)
+                                continue;
+                            break;
+                        case 'u':
+                            if ((y - x) - (hero.y - hero.x) >= 1)
+                                continue;
+                            break;
+                        case 'n':
+                            if ((x + y) - (hero.x + hero.y) <= -1)
+                                continue;
+                            break;
+                        case 'b':
+                            if ((y - x) - (hero.y - hero.x) <= -1)
+                                continue;
+                            break;
+                    }
+
+                    switch (ch)
+                    {
+                        case DOOR:
+                            if (x == hero.x || y == hero.y)
+                                running = FALSE;
+                            break;
+                        case PASSAGE:
+                            if (x == hero.x || y == hero.y)
+                                passcount++;
+                            break;
+                        case FLOOR:
+
+                        /*
+                         * Stop by new passages in a
+                         * maze (floor next to us)
+                         */
+                            if ((levtype == MAZELEV) &&
+                                ((horizontal && x == hero.x && y != hero.y) ||
+                                (vertical &&   y == hero.y && x != hero.x)))
+                                running = FALSE;
+
+                        case '|':
+                        case '-':
+                        case ' ':
+                            break;
+
+                        default:
+                            running = FALSE;
+                            break;
+                    }
+                }
+            }
+
+    if (door_stop && !firstmove && passcount > 1)
+        running = FALSE;
+
+    /*
+     * Do we have to light up the area (just stepped into a new
+     * corridor)?
+     */
+
+    if (do_light && wakeup &&   /* wakeup will be true on a normal move */
+        !(rp->r_flags & ISDARK) &&  /* We have some light */
+        !ce(hero, player.t_oldpos)) /* Don't do anything if we didn't move */
+        light(&hero);
+
+    mvwaddch(cw, hero.y, hero.x, PLAYER);
+    wmove(cw, oldy, oldx);
+
+    if (wakeup)
+    {
+        player.t_oldpos = hero; /* Don't change if we didn't move */
+        oldrp = rp;
+    }
+}
+
+/*
+    secret_door()
+        Figure out what a secret door looks like.
+*/
+
+char
+secretdoor(int y, int x)
+{
+    struct room *rp;
+    coord cp;
+
+    cp.x = x;
+    cp.y = y;
+
+    if ((rp = roomin(cp)) != NULL)
+    {
+        if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
+            return ('-');
+        else
+            return ('|');
+    }
+    return ('p');
+}
+
+/*
+    find_obj()
+        find the unclaimed object at y, x
+*/
+
+struct linked_list  *
+find_obj(int y, int x)
+{
+    struct linked_list  *obj, *sobj;
+    struct object   *op;
+
+    sobj = lvl_obj;
+
+    for (obj = sobj; obj != NULL; obj = next(obj))
+    {
+        op = OBJPTR(obj);
+
+        if (op && op->o_pos.y == y && op->o_pos.x == x)
+            return(obj);
+    }
+
+    return(NULL);
+}
+
+/*
+    eat()
+        He wants to eat something, so let him try
+*/
+
+void
+eat(void)
+{
+    struct object   *obj;
+    int amount;
+    float scale = (float) (LINES * COLS) / (25.0F * 80.0F);
+
+    if ((obj = get_object(pack, "eat", FOOD, NULL)) == NULL)
+        return;
+
+    switch (obj->o_which)
+    {
+        case FD_RATION:
+            amount = (int)(scale * (HUNGERTIME + rnd(400) - 200));
+
+            if (rnd(100) > 70)
+            {
+                msg("Yuk, this food tastes awful.");
+                pstats.s_exp++;
+                check_level();
+            }
+            else
+                msg("Yum, that tasted good.");
+            break;
+
+        case FD_FRUIT:
+            amount = (int)(scale * (200 + rnd(HUNGERTIME)));
+            msg("My, that was a yummy %s.", fruit);
+            break;
+
+        case FD_CRAM:
+            amount = (int)(scale * (rnd(HUNGERTIME / 2) + 600));
+            msg("The cram tastes dry in your mouth.");
+            break;
+
+        case FD_CAKES:
+            amount = (int)(scale * ((HUNGERTIME / 3) + rnd(600)));
+            msg("Yum, the honey cakes tasted good.");
+            break;
+
+        case FD_LEMBA:
+            amount = (int)(scale * ((HUNGERTIME / 2) + rnd(900)));
+            quaff(&player, P_HEALING, ISNORMAL);
+            break;
+
+        case FD_MIRUVOR:
+            amount = (int)(scale * ((HUNGERTIME / 3) + rnd(500)));
+            quaff(&player, P_HEALING, ISNORMAL);
+            quaff(&player, P_RESTORE, ISNORMAL);
+            break;
+
+        default:
+            msg("What a strange thing to eat!");
+            amount = (int)(scale * HUNGERTIME);
+    }
+    
+    food_left += amount;
+
+    if (obj->o_flags & ISBLESSED)
+    {
+        food_left += 2 * amount;
+        msg("You have a tingling feeling in your mouth.");
+    }
+    else if (food_left > scale * STOMACHSIZE)
+    {
+        food_left = (int)(scale * STOMACHSIZE);
+        msg("You feel satiated and too full to move.");
+        no_command = HOLDTIME;
+    }
+
+    hungry_state = F_OK;
+    updpack();
+
+    if (obj == cur_weapon)
+        cur_weapon = NULL;
+
+    if (--obj->o_count <= 0) /* Remove this pack entry if last of food */
+        discard_pack(obj);
+}
+
+/*
+ * Used to modify the player's strength it keeps track of the highest it has
+ * been, just in case
+ */
+
+void
+chg_str(int amt, int both, int lost)
+{
+    int           ring_str; /* ring strengths */
+    struct stats *ptr;      /* for speed */
+
+    ptr = &pstats;
+
+    ring_str = ring_value(R_ADDSTR) + (on(player, POWERSTR) ? 10 : 0) +
+        (on(player, SUPERHERO) ? 10 : 0);
+
+    ptr->s_str -= ring_str;
+    ptr->s_str += amt;
+
+    if (ptr->s_str < 3)
+    {
+        ptr->s_str = 3;
+        lost = FALSE;
+    }
+    else if (ptr->s_str > 25)
+        ptr->s_str = 25;
+
+    if (both)
+        max_stats.s_str = ptr->s_str;
+
+    if (lost)
+        lost_str -= amt;
+
+    ptr->s_str += ring_str;
+
+    if (ptr->s_str < 0)
+        ptr->s_str = 0;
+
+    updpack();
+}
+
+/*
+ * Used to modify the player's dexterity it keeps track of the highest it has
+ * been, just in case
+ */
+
+void
+chg_dext(int amt, int both, int lost)
+{
+    int ring_dext;      /* ring strengths   */
+    struct stats *ptr;  /* for speed        */
+
+    ptr = &pstats;
+
+    ring_dext = ring_value(R_ADDHIT) + (on(player, POWERDEXT) ? 10 : 0) +
+        (on(player, SUPERHERO) ? 5 : 0);
+
+    ptr->s_dext -= ring_dext;
+    ptr->s_dext += amt;
+
+    if (ptr->s_dext < 3)
+    {
+        ptr->s_dext = 3;
+        lost = FALSE;
+    }
+    else if (ptr->s_dext > 25)
+        ptr->s_dext = 25;
+
+    if (both)
+        max_stats.s_dext = ptr->s_dext;
+
+    if (lost)
+        lost_dext -= amt;
+
+    ptr->s_dext += ring_dext;
+
+    if (ptr->s_dext < 0)
+        ptr->s_dext = 0;
+}
+
+/*
+    add_haste()
+        add a haste to the player
+*/
+
+void
+add_haste(int blessed)
+{
+    short   hasttime;
+
+    if (blessed)
+        hasttime = 10;
+    else
+        hasttime = 6;
+
+    if (on(player, ISSLOW))    /* Is person slow? */
+    {
+        extinguish_fuse(FUSE_NOSLOW);
+        noslow(NULL);
+
+        if (blessed)
+            hasttime = 4;
+        else
+            return;
+    }
+
+    if (on(player, ISHASTE))
+    {
+        msg("You faint from exhaustion.");
+        no_command += rnd(hasttime);
+        lengthen_fuse(FUSE_NOHASTE, rnd(hasttime) + (roll(1, 4) * hasttime));
+    }
+    else
+    {
+        turn_on(player, ISHASTE);
+        light_fuse(FUSE_NOHASTE, 0, roll(hasttime, hasttime), AFTER);
+    }
+}
+
+/*
+    aggravate()
+        aggravate all the monsters on this level
+*/
+
+void
+aggravate(void)
+{
+    struct linked_list *mi;
+    struct thing *tp;
+
+    for (mi = mlist; mi != NULL; mi = next(mi))
+    {
+        tp = THINGPTR(mi);
+        chase_it(&tp->t_pos, &player);
+    }
+}
+
+/*
+    vowelstr()
+        for printfs: if string starts with a vowel, return "n" for an "an"
+*/
+
+char *
+vowelstr(char *str)
+{
+    switch (*str)
+    {
+        case 'a':
+        case 'A':
+        case 'e':
+        case 'E':
+        case 'i':
+        case 'I':
+        case 'o':
+        case 'O':
+        case 'u':
+        case 'U':
+            return "n";
+        default:
+            return "";
+    }
+}
+
+/*
+    is_object()
+        see if the object is one of the currently used items
+*/
+
+int
+is_current(struct object *obj)
+{
+    if (obj == NULL)
+        return FALSE;
+
+    if (obj == cur_armor || obj == cur_weapon ||
+        obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2] ||
+        obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4] ||
+        obj == cur_ring[LEFT_5] ||
+        obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] ||
+        obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4] ||
+        obj == cur_ring[RIGHT_5]) {
+        msg("That's already in use.");
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*
+    get_dir()
+        set up the direction co_ordinate for use in varios "prefix" commands
+*/
+
+int
+get_dir(void)
+{
+    char *prompt;
+    int   gotit;
+
+    prompt = "Which direction? ";
+    msg(prompt);
+
+    do
+    {
+        gotit = TRUE;
+
+        switch (readchar())
+        {
+            case 'h':
+            case 'H':
+                delta.y = 0;
+                delta.x = -1;
+                break;
+
+            case 'j':
+            case 'J':
+                delta.y = 1;
+                delta.x = 0;
+                break;
+