Mercurial > hg > early-roguelike
diff urogue/potions.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 | 0250220d8cdd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/urogue/potions.c Tue Jan 31 19:56:04 2017 -0500 @@ -0,0 +1,1516 @@ +/* + potions.c - Functions for dealing with potions + + 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 "rogue.h" + +/* + quaff - drink a potion (or effect a potion-like spell) + + quaffer: who does it + which: which P_POTION (-1 means ask from pack) + flags: ISBLESSED, ISCURSED +*/ + +void +quaff(struct thing *quaffer, int which, int flags) +{ + struct object *obj; + struct thing *th; + struct stats *curp = &(quaffer->t_stats); + struct stats *maxp = &(quaffer->maxstats); + int blessed = flags & ISBLESSED; + int cursed = flags & ISCURSED; + int is_potion = (which < 0 ? TRUE : FALSE); + + struct linked_list *item, *titem; + char buf[2 * LINELEN]; + + if (quaffer != &player) + { + monquaff(quaffer, which, flags); + return; + } + + if (is_potion) /* A regular potion */ + { + if ((item = get_item("quaff", POTION)) == NULL) + return; + + obj = OBJPTR(item); + + if (obj->o_type != POTION) + { + msg("You can't drink that!"); + return; + } + + /* Calculate its effect */ + + flags = obj->o_flags; + cursed = obj->o_flags & ISCURSED; + blessed = obj->o_flags & ISBLESSED; + which = obj->o_which; + + /* remove it from the pack */ + + rem_pack(obj); + discard(item); + updpack(); + } + + switch(which) + { + case P_CLEAR: + if (cursed) + { + if (off(player, ISCLEAR)) + { + msg("Wait, what's going on here. Huh? What? Who?"); + + 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); + } + else + msg("You feel dizzy for a moment, but it passes."); + } + else + { + if (blessed) /* Make player immune for the whole game */ + { + extinguish_fuse(FUSE_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)) + { + light_fuse(FUSE_UNCLRHEAD, 0, CLRDURATION, AFTER); + msg("A faint blue aura surrounds your head."); + } + else /* If have fuse lengthen, else permanently clear */ + { + if (find_slot(FUSE_UNCLRHEAD,FUSE) == NULL) + msg("Your blue aura continues to glow strongly."); + else + { + lengthen_fuse(FUSE_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_fuse(FUSE_UNCONFUSE); + unconfuse(NULL); + } + } + break; + + case P_HEALING: + if (cursed) + { + if (player.t_ctype != C_PALADIN + && !(player.t_ctype == C_NINJA + && curp->s_lvl > 12) + && !save(VS_POISON)) + { + feel_message(); + curp->s_hpt /= 2; + curp->s_power /= 2; + + if ((curp->s_hpt -= 1) <= 0) + { + death(D_POISON); + return; + } + } + else + msg("You feel momentarily sick."); + } + else + { + int nsides = (blessed ? 8 : 4); + int hpt_gain = roll(curp->s_lvl, nsides); + int power_gain = roll(curp->s_lvl, nsides); + + if (blessed && on(player, ISHUH)) + { + extinguish_fuse(FUSE_UNCONFUSE); + unconfuse(NULL); + } + + curp->s_hpt = min(curp->s_hpt + hpt_gain, maxp->s_hpt); + + if (is_potion) /* Do not bump power or maximums if spell */ + { + know_items[TYP_POTION][P_HEALING] = TRUE; + curp->s_power = min(curp->s_power + power_gain, maxp->s_power); + + if (maxp->s_hpt == curp->s_hpt) + maxp->s_hpt = curp->s_hpt += roll(1, nsides); + + if (maxp->s_power == curp->s_power) + maxp->s_power = curp->s_power += roll(1, nsides); + } + + msg("You begin to feel %sbetter.", blessed ? "much " : ""); + + if (off(player, PERMBLIND)) + sight(NULL); + } + break; + + case P_GAINABIL: + { + int ctype; + + if (!is_potion || pstats.s_arm <= 0) + feel_message(); + else + { + if (blessed) /* add to all attributes */ + { + add_intelligence(FALSE); + add_dexterity(FALSE); + add_strength(FALSE); + add_wisdom(FALSE); + add_const(FALSE); + } + else + { + if (rnd(100) < 70) + /* probably change own ability */ + ctype = player.t_ctype; + else + switch(rnd(4)) + { + case 0: ctype = C_FIGHTER; break; + case 1: ctype = C_MAGICIAN; break; + case 2: ctype = C_CLERIC; break; + case 3: ctype = C_THIEF; break; + } + switch (ctype) + { + case C_FIGHTER:add_strength(cursed); break; + case C_PALADIN:add_strength(cursed); break; + case C_RANGER:add_strength(cursed); break; + case C_MAGICIAN:add_intelligence(cursed); break; + case C_ILLUSION:add_intelligence(cursed); break; + case C_CLERIC:add_wisdom(cursed); break; + case C_DRUID:add_wisdom(cursed); break; + case C_THIEF:add_dexterity(cursed); break; + case C_ASSASIN:add_dexterity(cursed); break; + case C_NINJA:add_dexterity(cursed); break; + default: msg("You're a strange type!"); break; + } + } + + if (rnd(100) < 10) + add_const(cursed); + + if (rnd(100) < 60) + curp->s_arm += (cursed ? 1 : -1); + + if (!cursed) + know_items[TYP_POTION][P_GAINABIL] = TRUE; + } + } + break; + + case P_MONSTDET: + + /* + * Potion of monster detection, if there are monsters, + * detect them + */ + + if (is_potion) + know_items[TYP_POTION][P_MONSTDET] = TRUE; + + if (cursed) + { + int nm = roll(3, 6); + int i; + char ch; + struct room *rp; + coord pos; + + msg("You begin to sense the presence of monsters."); + wclear(hw); + + for (i = 1; i < nm; i++) + { + rp = &rooms[rnd_room()]; + rnd_pos(rp, &pos); + + if (rnd(2)) + ch = 'a' + ucrnd(26); + else + ch = 'A' + ucrnd(26); + + mvwaddch(hw, pos.y, pos.x, ch); + } + waddstr(cw, morestr); + overlay(hw, cw); + wrefresh(cw); + wait_for(' '); + msg(""); + } + else if (mlist != NULL) + { + msg("You begin to sense the presence of monsters."); + waddstr(cw, morestr); + overlay(mw, cw); + wrefresh(cw); + wait_for(' '); + msg(""); + + if (blessed) + turn_on(player, BLESSMONS); + } + else + nothing_message(flags); + break; + + case P_TREASDET: + + /* Potion of magic detection. Show the potions and scrolls */ + + if (cursed) + { + int nm = roll(3, 3); + int i; + char ch; + struct room *rp; + coord pos; + + msg("You sense the presence of magic on this level."); + wclear(hw); + + for (i = 1; i < nm; i++) + { + rp = &rooms[rnd_room()]; + rnd_pos(rp, &pos); + + if (rnd(9) == 0) + ch = BMAGIC; + else if (rnd(9) == 0) + ch = CMAGIC; + else + ch = MAGIC; + + mvwaddch(hw, pos.y, pos.x, ch); + } + waddstr(cw, morestr); + + overlay(hw, cw); + wrefresh(cw); + wait_for(' '); + msg(""); + + if (is_potion) + know_items[TYP_POTION][P_TREASDET] = TRUE; + + break; + } + + if (blessed) + turn_on(player, BLESSMAGIC); + + if (lvl_obj != NULL) + { + struct linked_list *mobj; + struct object *tp; + int showit; + + showit = FALSE; + wclear(hw); + + for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) + { + tp = OBJPTR(mobj); + + if (is_magic(tp)) + { + char mag_type = MAGIC; + + if (blessed) + if (tp->o_flags & ISCURSED) + mag_type = CMAGIC; + else if (tp->o_flags & ISBLESSED) + mag_type = BMAGIC; + + showit = TRUE; + mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, mag_type); + } + } + + for (titem = mlist; titem != NULL; titem = next(titem)) + { + struct linked_list *pitem; + + th = THINGPTR(titem); + + for (pitem = th->t_pack; pitem != NULL; pitem = next(pitem)) + { + if (is_magic(OBJPTR(pitem))) + { + showit = TRUE; + mvwaddch(hw, th->t_pos.y, th->t_pos.x,MAGIC); + } + } + } + + if (showit) + { + msg("You sense the presence of magic on this level."); + + if (is_potion) + know_items[TYP_POTION][P_TREASDET] = TRUE; + + waddstr(cw, morestr); + overlay(hw, cw); + wrefresh(cw); + wait_for(' '); + msg(""); + break; + } + } + nothing_message(flags); + break; + + case P_SEEINVIS: + if (cursed) + { + if (off(player, ISBLIND) && !is_wearing(R_SEEINVIS)) + { + msg("A cloak of darkness falls around you."); + turn_on(player, ISBLIND); + light_fuse(FUSE_SIGHT, 0, SEEDURATION, AFTER); + look(FALSE); + } + else + msg("Your eyes stop tingling for a moment."); + } + else if (off(player, PERMBLIND)) + { + if (is_potion) + know_items[TYP_POTION][P_SEEINVIS] = TRUE; + + if (off(player, CANSEE)) + { + turn_on(player, CANSEE); + msg("Your eyes begin to tingle."); + light_fuse(FUSE_UNSEE, 0, blessed ? SEEDURATION * 3 : SEEDURATION, AFTER); + light(&hero); + } + else if (find_slot(FUSE_UNSEE,FUSE) != NULL) + { + nothing_message(ISNORMAL); + lengthen_fuse(FUSE_UNSEE, blessed ? SEEDURATION * 3 : SEEDURATION); + } + sight(NULL); + } + break; + + case P_PHASE: + + if (cursed) + { + msg("You can't move."); + no_command = HOLDTIME; + } + else + { + short duration = (blessed ? 3 : 1); + + if (is_potion) + know_items[TYP_POTION][P_PHASE] = TRUE; + + if (on(player, CANINWALL)) + lengthen_fuse(FUSE_UNPHASE, duration * PHASEDURATION); + else + { + light_fuse(FUSE_UNPHASE, 0, duration * PHASEDURATION, AFTER); + turn_on(player, CANINWALL); + } + msg("You feel %slight-headed!", blessed ? "very " : ""); + } + break; + + case P_RAISELEVEL: + + if (cursed || (!is_potion && pstats.s_lvl > 20)) + lower_level(D_POTION); + else + { + msg("You suddenly feel %smore skillful.", blessed ? "much " : ""); + know_items[TYP_POTION][P_RAISELEVEL] = TRUE; + raise_level(); + + if (blessed) + raise_level(); + } + break; + + case P_HASTE: + if (cursed) /* Slow player down */ + { + if (on(player, ISHASTE)) + { + extinguish_fuse(FUSE_NOHASTE); + nohaste(NULL); + } + else + { + msg("You feel yourself moving %sslower.", + on(player, ISSLOW) ? "even " : ""); + + if (on(player, ISSLOW)) + lengthen_fuse(FUSE_NOSLOW, rnd(4) + 4); + else if (!is_wearing(R_FREEDOM)) + { + turn_on(player, ISSLOW); + player.t_turn = TRUE; + light_fuse(FUSE_NOSLOW, 0, rnd(4) + 4, AFTER); + } + } + } + else + { + if (off(player, ISSLOW)) + msg("You feel yourself moving %sfaster.", + blessed ? "much " : ""); + + add_haste(blessed); + + if (is_potion) + know_items[TYP_POTION][P_HASTE] = TRUE; + } + break; + + case P_RESTORE: + { + int i; + + msg("You are surrounded by an orange mist."); + + if (is_potion) + know_items[TYP_POTION][P_RESTORE] = TRUE; + + if (lost_str) + { + for (i = 0; i < lost_str; i++) + extinguish_fuse(FUSE_RES_STRENGTH); + + lost_str = 0; + } + res_strength(NULL); + + if (lost_dext) + { + for (i = 0; i < lost_dext; i++) + extinguish_fuse(FUSE_UNITCH); + + lost_dext = 0; + } + + res_dexterity(); + res_wisdom(); + res_intelligence(); + curp->s_const = maxp->s_const; + } + break; + + case P_INVIS: + + if (cursed) + { + msg("You feel very noticable."); + quaff(&player, P_SHIELD, ISCURSED); + } + else if (off(player, ISINVIS)) + { + turn_on(player, ISINVIS); + + if (on(player, ISDISGUISE)) + { + turn_off(player, ISDISGUISE); + extinguish_fuse(FUSE_UNDISGUISE); + msg("Your skin feels itchy for a moment."); + } + msg("You have a tingling feeling all over your body."); + light_fuse(FUSE_APPEAR, 0, blessed ? WANDERTIME * 3 : WANDERTIME, AFTER); + PLAYER = IPLAYER; + light(&hero); + + if (is_potion) + know_items[TYP_POTION][P_INVIS] = TRUE; + } + else + lengthen_fuse(FUSE_APPEAR, blessed ? WANDERTIME * 3 : WANDERTIME); + + break; + + case P_SMELL: + + if (cursed) + { + if (on(player, CANSCENT)) + { + turn_off(player, CANSCENT); + extinguish_fuse(FUSE_UNSCENT); + msg("You no longer smell monsters around you."); + } + else if (on(player, ISUNSMELL)) + { + lengthen_fuse(FUSE_UNSCENT, PHASEDURATION); + msg("You feel your nose tingle."); + } + else + { + turn_on(player, ISUNSMELL); + light_fuse(FUSE_SCENT, 0, PHASEDURATION, AFTER); + msg("You can't smell anything now."); + } + } + else + { + short duration = (blessed ? 3 : 1); + + if (is_potion) + know_items[TYP_POTION][P_SMELL] = TRUE; + + if (on(player, CANSCENT)) + lengthen_fuse(FUSE_UNSCENT, duration * PHASEDURATION); + else + { + light_fuse(FUSE_UNSCENT, 0, duration * PHASEDURATION, AFTER); + turn_on(player, CANSCENT); + } + msg("You begin to smell monsters all around you."); + } + break; + + case P_HEAR: + + if (cursed) + { + if (on(player, CANHEAR)) + { + turn_off(player, CANHEAR); + extinguish_fuse(FUSE_HEAR); + msg("You no longer hear monsters around you."); + }