diff xrogue/potions.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children ce0cf824c192
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/potions.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1058 @@
+/*
+    potions.c - Functions for dealing with potions
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    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 <curses.h>
+#include "rogue.h"
+
+/*
+ * add_abil is an array of functions used to change attributes.  It must be
+ * ordered according to the attribute definitions in rogue.h.
+ */
+
+int (*add_abil[NUMABILITIES])() = {
+    add_intelligence, add_strength, add_wisdom, add_dexterity,
+    add_constitution, add_charisma
+};
+
+/*
+ * res_abil is an array of functions used to change attributes.  It must be
+ * ordered according to the attribute definitions in rogue.h.
+ */
+
+int (*res_abil[NUMABILITIES])() = {
+    res_intelligence, res_strength, res_wisdom, res_dexterity,
+    res_constitution, res_charisma
+};
+
+/*
+ * Increase player's constitution
+ */
+
+int
+add_constitution(change)
+int change;
+{
+    /* Do the potion */
+    if (change < 0) {
+        msg("You feel less healthy now.");
+        pstats.s_const += change;
+        if (pstats.s_const < 1) {
+        pstats.s_hpt = -1;
+        msg("You collapse!  --More--");
+        wait_for(' ');
+            death(D_CONSTITUTION);
+    }
+    }
+    else {
+        msg("You feel healthier now.");
+        pstats.s_const = min(pstats.s_const + change, MAXATT);
+    }
+
+    /* Adjust the maximum */
+    if (max_stats.s_const < pstats.s_const)
+        max_stats.s_const = pstats.s_const;
+
+    return(0);
+}
+
+/*
+ * Increase player's charisma
+ */
+
+int
+add_charisma(change)
+int change;
+{
+    /* Do the potion */
+    if (change < 0) msg("You feel less attractive now.");
+    else msg("You feel more attractive now.");
+
+    pstats.s_charisma += change;
+    if (pstats.s_charisma > MAXATT) pstats.s_charisma = MAXATT;
+    else if (pstats.s_charisma < 3) pstats.s_charisma = 3;
+
+    /* Adjust the maximum */
+    if (max_stats.s_charisma < pstats.s_charisma)
+        max_stats.s_charisma = pstats.s_charisma;
+
+    return(0);
+}
+
+/*
+ * Increase player's dexterity
+ */
+
+int
+add_dexterity(change)
+int change;
+{
+    int ring_str;       /* Value of ring strengths */
+
+    /* Undo any ring changes */
+    ring_str = ring_value(R_ADDHIT);
+    pstats.s_dext -= ring_str;
+
+    /* Now do the potion */
+    if (change < 0) msg("You feel less dextrous now.");
+    else msg("You feel more dextrous now.  Watch those hands!");
+
+    pstats.s_dext += change;
+    if (pstats.s_dext > MAXATT) pstats.s_dext = MAXATT;
+    else if (pstats.s_dext < 3) pstats.s_dext = 3;
+
+    /* Adjust the maximum */
+    if (max_stats.s_dext < pstats.s_dext)
+        max_stats.s_dext = pstats.s_dext;
+
+    /* Now put back the ring changes */
+    if (ring_str)
+        pstats.s_dext += ring_str;
+
+    return(0);
+}
+
+/*
+ * add_haste:
+ *      add a haste to the player
+ */
+
+add_haste(blessed)
+bool blessed;
+{
+    int hasttime;
+
+    if (player.t_ctype == C_MONK) { /* monks cannot be slowed or hasted */
+        msg(nothing);
+        return;
+    }
+
+    if (blessed) hasttime = HASTETIME*2;
+    else hasttime = HASTETIME;
+
+    if (on(player, ISSLOW)) { /* Is person slow? */
+        extinguish(noslow);
+        noslow();
+
+        if (blessed) hasttime = HASTETIME/2;
+        else return;
+    }
+
+    if (on(player, ISHASTE)) {
+        msg("You faint from exhaustion.");
+        player.t_no_move += movement(&player) * rnd(hasttime);
+        player.t_action = A_FREEZE;
+        lengthen(nohaste, roll(hasttime,hasttime));
+    }
+    else {
+        msg("You feel yourself moving %sfaster.", blessed ? "much " : "");
+        turn_on(player, ISHASTE);
+        fuse(nohaste, (VOID *)NULL, roll(hasttime, hasttime), AFTER);
+    }
+}
+
+/*
+ * Increase player's intelligence
+ */
+
+int
+add_intelligence(change)
+int change;
+{
+    int ring_str;       /* Value of ring strengths */
+
+    /* Undo any ring changes */
+    ring_str = ring_value(R_ADDINTEL);
+    pstats.s_intel -= ring_str;
+
+    /* Now do the potion */
+    if (change < 0) msg("You feel slightly less intelligent now.");
+    else msg("You feel more intelligent now.  What a mind!");
+
+    pstats.s_intel += change;
+    if (pstats.s_intel > MAXATT) pstats.s_intel = MAXATT;
+    else if (pstats.s_intel < 3) pstats.s_intel = 3;
+
+    /* Adjust the maximum */
+    if (max_stats.s_intel < pstats.s_intel)
+            max_stats.s_intel = pstats.s_intel;
+
+    /* Now put back the ring changes */
+    if (ring_str)
+        pstats.s_intel += ring_str;
+
+    return(0);
+}
+
+/*
+ * this routine makes the hero move slower 
+ */
+
+add_slow()
+{
+    /* monks cannot be slowed or hasted */
+    if (player.t_ctype == C_MONK || ISWEARING(R_FREEDOM)) { 
+        msg(nothing);
+        return;
+    }
+
+    if (on(player, ISHASTE)) { /* Already sped up */
+        extinguish(nohaste);
+        nohaste();
+    }
+    else {
+        msg("You feel yourself moving %sslower.",
+                on(player, ISSLOW) ? "even " : "");
+        if (on(player, ISSLOW))
+            lengthen(noslow, roll(HASTETIME,HASTETIME));
+        else {
+            turn_on(player, ISSLOW);
+            fuse(noslow, (VOID *)NULL, roll(HASTETIME,HASTETIME), AFTER);
+        }
+    }
+}
+
+/*
+ * Increase player's strength
+ */
+
+int
+add_strength(change)
+int change;
+{
+
+    if (change < 0) {
+        msg("You feel slightly weaker now.");
+        chg_str(change);
+    }
+    else {
+        msg("You feel stronger now.  What bulging muscles!");
+        chg_str(change);
+    }
+    return(0);
+}
+
+/*
+ * Increase player's wisdom
+ */
+
+int
+add_wisdom(change)
+int change;
+{
+    int ring_str;       /* Value of ring strengths */
+
+    /* Undo any ring changes */
+    ring_str = ring_value(R_ADDWISDOM);
+    pstats.s_wisdom -= ring_str;
+
+    /* Now do the potion */
+    if (change < 0) msg("You feel slightly less wise now.");
+    else msg("You feel wiser now.  What a sage!");
+
+    pstats.s_wisdom += change;
+    if (pstats.s_wisdom > MAXATT) pstats.s_wisdom = MAXATT;
+    else if (pstats.s_wisdom < 3) pstats.s_wisdom = 3;
+
+    /* Adjust the maximum */
+    if (max_stats.s_wisdom < pstats.s_wisdom)
+        max_stats.s_wisdom = pstats.s_wisdom;
+
+    /* Now put back the ring changes */
+    if (ring_str)
+        pstats.s_wisdom += ring_str;
+
+    return(0);
+}
+
+quaff(which, kind, flags, is_potion)
+int which;
+int kind;
+int flags;
+bool is_potion;
+{
+    register struct object *obj;
+    register struct linked_list *item, *titem;
+    register struct thing *th;
+    bool cursed, blessed;
+
+    blessed = FALSE;
+    cursed = FALSE;
+    item = NULL;
+
+    if (which < 0) {    /* figure out which ourselves */
+        /* This is a potion.  */
+        if (player.t_action != C_QUAFF) {
+            int units;
+
+            item = get_item(pack, "quaff", QUAFFABLE, FALSE, FALSE);
+
+            /*
+             * Make certain that it is somethings that we want to drink
+             */
+            if (item == NULL)
+                return;
+
+            /* How long does it take to quaff? */
+            units = usage_time(item);
+            if (units < 0) return;
+
+            player.t_using = item;      /* Remember what it is */
+            player.t_no_move = units * movement(&player);
+            if ((OBJPTR(item))->o_type == POTION) player.t_action = C_QUAFF;
+            else player.t_action = C_USE;
+            return;
+        }
+
+        /* We have waited our time, let's quaff the potion */
+        item = player.t_using;
+        player.t_using = NULL;
+        player.t_action = A_NIL;
+
+        obj = OBJPTR(item);
+        /* remove it from the pack */
+        inpack--;
+        detach(pack, item);
+
+        flags = obj->o_flags;
+        which = obj->o_which;
+        kind = obj->o_kind;
+    }
+    cursed = flags & ISCURSED;
+    blessed = flags & ISBLESSED;
+
+    switch(which) {
+        case P_CLEAR:
+            if (cursed) {
+                confus_player();
+            }
+            else {
+                if (blessed) {  /* Make player immune for the whole game */
+                    extinguish(unclrhead);  /* If we have a fuse, put it out */
+                    msg("A strong blue aura surrounds your head.");
+                }
+                else {  /* Just light a fuse for how long player is safe */
+                    if (off(player, ISCLEAR)) {
+                        fuse(unclrhead, (VOID *)NULL, CLRDURATION, AFTER);
+                        msg("A faint blue aura surrounds your head.");
+                    }
+                    else {  /* If we have a fuse lengthen it, else we
+                             * are permanently clear.
+                             */
+                        if (find_slot(unclrhead) == 0)
+                            msg("Your blue aura continues to glow strongly.");
+                        else {
+                            lengthen(unclrhead, CLRDURATION);
+                            msg("Your blue aura brightens for a moment.");
+                        }
+                    }
+                }
+                turn_on(player, ISCLEAR);
+                /* If player is confused, unconfuse him */
+                if (on(player, ISHUH)) {
+                    extinguish(unconfuse);
+                    unconfuse();
+                }
+            }
+        when P_HEALING:
+            if (cursed) {
+                msg("You feel worse now.");
+                pstats.s_hpt -= roll(pstats.s_lvl, char_class[player.t_ctype].hit_pts);
+                if (pstats.s_hpt < 1) {
+            pstats.s_hpt = -1;
+            msg("You're life passes before your eyes..  --More--");
+            wait_for(' ');
+                    death(D_POTION);
+        }
+            }
+            else {
+                if (blessed) {
+                    pstats.s_hpt += roll(pstats.s_lvl+1, char_class[player.t_ctype].hit_pts);
+                    if (pstats.s_hpt > max_stats.s_hpt) {
+                        pstats.s_hpt = ++max_stats.s_hpt;
+                        pstats.s_hpt = ++max_stats.s_hpt;
+            }
+                    if (on(player, ISHUH)) {
+                        extinguish(unconfuse);
+                        unconfuse();
+                    }
+                }
+                else {
+                    pstats.s_hpt += roll(pstats.s_lvl+1, char_class[player.t_ctype].hit_pts/2);
+                    if (pstats.s_hpt > max_stats.s_hpt)
+                        pstats.s_hpt = ++max_stats.s_hpt;
+                }
+                msg("You begin to feel %sbetter.",
+                        blessed ? "much " : "");
+                sight();
+                if (is_potion) p_know[P_HEALING] = TRUE;
+            }
+        when P_ABIL:
+            /* If it is cursed, we take a point away */
+            if (cursed) {
+                if (ISWEARING(R_SUSABILITY)) {
+                    msg(nothing);
+                    break;
+                }
+                else (*add_abil[kind])(-1);
+            }
+
+            /* Otherwise we add points */
+            else (*add_abil[kind])(blessed ? 3 : 1);
+
+            if (is_potion) p_know[P_ABIL] = TRUE;
+        when P_MFIND:
+            /*
+             * Potion of monster detection, if there are monters, detect them
+             */
+            if (mlist != NULL)
+            {
+                register struct thing *tp;
+                register struct linked_list *item;
+
+                wclear(hw);
+                for (item=mlist; item!=NULL; item=next(item)) {
+                    tp = THINGPTR(item);
+                    if (on(*tp, NODETECT))
+                        continue;
+                    if (off(*tp, ISRUN))/* turn off only on sleeping ones */
+                        turn_off(*tp, CANSURPRISE);
+                    mvwaddch(hw, tp->t_pos.y, tp->t_pos.x, 
+                             monsters[tp->t_index].m_appear);
+                }
+                rmmsg();
+                overlay(hw,cw);
+                draw(cw);
+                msg("You begin to sense the presence of monsters.");
+                if (is_potion) p_know[P_MFIND] = TRUE;
+            }
+            else
+                msg("You have a strange feeling for a moment, then it passes.");
+        when P_TFIND:
+            /*
+             * Potion of magic detection.  Show the potions and scrolls
+             */
+            {
+                register struct linked_list *mobj;
+                register struct object *tp;
+                bool show;
+
+                show = FALSE;
+                wclear(hw);
+                for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) {
+                    tp = OBJPTR(mobj);
+                    if (is_magic(tp)) {
+                        char mag_type=MAGIC;
+
+                        /* Mark cursed items or bad weapons */
+                        if ((tp->o_flags & ISCURSED) ||
+                            (tp->o_type == WEAPON &&
+                             (tp->o_hplus < 0 || tp->o_dplus < 0)))
+                                mag_type = CMAGIC;
+                        else if ((tp->o_flags & ISBLESSED) ||
+                                 (tp->o_type == WEAPON &&
+                                  (tp->o_hplus > 0 || tp->o_dplus > 0)))
+                                        mag_type = BMAGIC;
+                        show = TRUE;
+                        mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, mag_type);
+                    }
+                }
+                for (titem = mlist; titem != NULL; titem = next(titem)) {
+                    register struct linked_list *pitem;
+
+                    th = THINGPTR(titem);
+                    if (on(*th, NODETECT)) continue;
+                    for(pitem = th->t_pack; pitem != NULL; pitem = next(pitem)){
+                        tp = OBJPTR(pitem);
+                        if (is_magic(tp)) {
+                            char mag_type=MAGIC;
+
+                            /* Mark cursed items or bad weapons */
+                            if ((tp->o_flags & ISCURSED) ||
+                                (tp->o_type == WEAPON &&
+                                 (tp->o_hplus < 0 || tp->o_dplus < 0)))
+                                    mag_type = CMAGIC;
+                            else if ((tp->o_flags & ISBLESSED) ||
+                                     (tp->o_type == WEAPON &&
+                                      (tp->o_hplus > 0 || tp->o_dplus > 0)))
+                                            mag_type = BMAGIC;
+                            show = TRUE;
+                            mvwaddch(hw, th->t_pos.y, th->t_pos.x, mag_type);
+                        }
+                    }
+                }
+                if (show) {
+                    if (is_potion) p_know[P_TFIND] = TRUE;
+                    rmmsg();
+                    overlay(hw,cw);
+                    draw(cw);
+                    msg("You sense the presence of magic on this level.");
+                    break;
+                }
+                else
+                    msg("You have a strange feeling for a moment, then it passes.");
+            }
+        when P_SEEINVIS:
+            if (cursed) {
+                if (!find_slot(sight))
+                {
+                    msg("A cloak of darkness falls around you.");
+                    turn_on(player, ISBLIND);
+                    fuse(sight, (VOID *)NULL, SEEDURATION, AFTER);
+                    light(&hero);
+                }
+                else
+                    msg("The darkness around you thickens. ");
+                    lengthen(sight, SEEDURATION);
+            }
+            else {
+                if (off(player, CANSEE)) {
+                    turn_on(player, CANSEE);
+                    msg("Your eyes begin to tingle.");
+                    fuse(unsee, (VOID *)NULL, blessed ? SEEDURATION*3 :SEEDURATION, AFTER);
+                    light(&hero);
+                }
+                else if (find_slot(unsee) != 0) {
+                    msg("You eyes continue to tingle.");
+                    lengthen(unsee, blessed ? SEEDURATION*3 : SEEDURATION);
+        }
+                sight();
+            }
+        when P_PHASE:
+            if (cursed) {
+                msg("You can't move.");
+                player.t_no_move = movement(&player) * FREEZETIME;
+                player.t_action = A_FREEZE;
+            }
+            else {
+                int duration;
+
+                if (blessed) duration = 3;
+                else duration = 1;
+
+                if (on(player, CANINWALL))
+                    lengthen(unphase, duration*PHASEDURATION);
+                else {
+                    fuse(unphase, (VOID *)NULL, duration*PHASEDURATION, AFTER);
+                    turn_on(player, CANINWALL);
+                }
+                msg("You feel %slight-headed!",
+                    blessed ? "very " : "");
+            }
+        when P_FLY: {
+            int duration;
+            bool say_message;
+
+            say_message = TRUE;
+
+            if (blessed) duration = 3;
+            else duration = 1;
+
+            if (on(player, ISFLY)) {
+                if (find_slot(land))
+                    lengthen(land, duration*FLYTIME);
+                else {
+                    msg("Nothing happens.");    /* Flying by cloak */
+                    say_message = FALSE;
+                }
+            }
+            else {
+                fuse(land, (VOID *)NULL, duration*FLYTIME, AFTER);
+                turn_on(player, ISFLY);
+            }
+            if (say_message) {
+                if (is_potion) p_know[P_FLY] = TRUE;
+                msg("You feel %slighter than air!", blessed ? "much " : "");
+            }
+        }
+        when P_RAISE:
+            if (cursed) lower_level(D_POTION);
+            else {
+                msg("You suddenly feel %smore skillful",
+                        blessed ? "much " : "");
+                p_know[P_RAISE] = TRUE;
+                raise_level();
+                do_panic(NULL);         /* this startles them */
+                if (blessed) raise_level();
+            }
+        when P_HASTE:
+            if (cursed) {       /* Slow player down */
+                add_slow();
+            }
+            else {
+                add_haste(blessed);
+                if (is_potion) p_know[P_HASTE] = TRUE;
+            }
+        when P_RESTORE: {
+            register int i, howmuch, strength_tally;
+
+            msg("Hey, this tastes great.  It make you feel %swarm all over.",
+                blessed ? "really " : "");
+            howmuch = blessed ? 3 : 1;
+
+            for (i=0; i<NUMABILITIES; i++) {
+                if (i == A_STRENGTH) {
+                    if (lost_str) {
+                        if (lost_str > howmuch) {
+                            lost_str -= howmuch;
+
+                            /*
+                             * Save the lost strength.  We have to set
+                             * temporarilty set it to 0 so that res_strength
+                             * will not restore it.
+                             */
+                            strength_tally = lost_str;
+                            lost_str = 0;
+                            res_strength(howmuch);
+                            lost_str = strength_tally;
+                        }
+                        else {
+                        lost_str = 0;
+                            extinguish(res_strength);
+                            res_strength(howmuch);
+                        }
+                    }
+                    else res_strength(howmuch);
+                }