mirror of https://github.com/nealey/rogue
366 lines
7.9 KiB
C
366 lines
7.9 KiB
C
/*
|
|
* Function(s) for dealing with potions
|
|
*
|
|
* @(#)ether.c 4.46 (Berkeley) 06/07/83
|
|
*/
|
|
|
|
#include <curses.h>
|
|
#include <ctype.h>
|
|
#include "netprot.h"
|
|
|
|
typedef struct
|
|
{
|
|
int pa_flags;
|
|
void (*pa_daemon)(void);
|
|
int pa_time;
|
|
char *pa_high, *pa_straight;
|
|
} PACT;
|
|
|
|
static PACT P_actions[] =
|
|
{
|
|
{ ISHUH, unconfuse, HUHDURATION, /* P_CONFUSE */
|
|
"what a tripy feeling!",
|
|
"wait, what's going on here. Huh? What? Who?" },
|
|
{ ISHALU, come_down, SEEDURATION, /* P_LSD */
|
|
"Oh, wow! Everything seems so cosmic!",
|
|
"Oh, wow! Everything seems so cosmic!" },
|
|
{ 0, NULL, 0 }, /* P_POISON */
|
|
{ 0, NULL, 0 }, /* P_STRENGTH */
|
|
{ CANSEE, unsee, SEEDURATION, /* P_SEEINVIS */
|
|
Prbuf,
|
|
Prbuf },
|
|
{ 0, NULL, 0 }, /* P_HEALING */
|
|
{ 0, NULL, 0 }, /* P_MFIND */
|
|
{ 0, NULL, 0 }, /* P_TFIND */
|
|
{ 0, NULL, 0 }, /* P_RAISE */
|
|
{ 0, NULL, 0 }, /* P_XHEAL */
|
|
{ 0, NULL, 0 }, /* P_HASTE */
|
|
{ 0, NULL, 0 }, /* P_RESTORE */
|
|
{ ISBLIND, sight, SEEDURATION, /* P_BLIND */
|
|
"oh, bummer! Everything is dark! Help!",
|
|
"a cloak of darkness falls around you" },
|
|
{ ISLEVIT, land, HEALTIME, /* P_LEVIT */
|
|
"oh, wow! You're floating in the air!",
|
|
"you start to float in the air" }
|
|
};
|
|
|
|
/*
|
|
* quaff:
|
|
* Quaff a potion from the pack
|
|
*/
|
|
void
|
|
quaff(void)
|
|
{
|
|
THING *obj, *tp, *mp;
|
|
bool discardit = FALSE;
|
|
bool show, trip;
|
|
|
|
obj = get_item("quaff", POTION);
|
|
/*
|
|
* Make certain that it is somethings that we want to drink
|
|
*/
|
|
if (obj == NULL)
|
|
return;
|
|
if (obj->o_type != POTION)
|
|
{
|
|
if (!Terse)
|
|
msg("yuk! Why would you want to drink that?");
|
|
else
|
|
msg("that's undrinkable");
|
|
return;
|
|
}
|
|
if (obj == Cur_weapon)
|
|
Cur_weapon = NULL;
|
|
|
|
/*
|
|
* Calculate the effect it has on the poor guy.
|
|
*/
|
|
trip = on(Player, ISHALU);
|
|
discardit = (obj->o_count == 1);
|
|
leave_pack(obj, FALSE, FALSE);
|
|
switch (obj->o_which)
|
|
{
|
|
when P_CONFUSE:
|
|
do_pot(P_CONFUSE, !trip);
|
|
when P_POISON:
|
|
Pot_info[P_POISON].oi_know = TRUE;
|
|
if (ISWEARING(R_SUSTSTR))
|
|
msg("you feel momentarily sick");
|
|
else
|
|
{
|
|
chg_str(-(rnd(3) + 1));
|
|
msg("you feel very sick now");
|
|
come_down();
|
|
}
|
|
when P_HEALING:
|
|
Pot_info[P_HEALING].oi_know = TRUE;
|
|
if ((Pstats.s_hpt += roll(Pstats.s_lvl, 4)) > Max_hp)
|
|
Pstats.s_hpt = ++Max_hp;
|
|
sight();
|
|
msg("you begin to feel better");
|
|
when P_STRENGTH:
|
|
Pot_info[P_STRENGTH].oi_know = TRUE;
|
|
chg_str(1);
|
|
msg("you feel stronger, now. What bulging muscles!");
|
|
when P_MFIND:
|
|
Player.t_flags |= SEEMONST;
|
|
fuse(turn_see, TRUE, HUHDURATION, AFTER);
|
|
if (!turn_see(FALSE))
|
|
msg("you have a %s feeling for a moment, then it passes",
|
|
choose_str("normal", "strange"));
|
|
when P_TFIND:
|
|
/*
|
|
* Potion of magic detection. Show the potions and scrolls
|
|
*/
|
|
show = FALSE;
|
|
if (Lvl_obj != NULL)
|
|
{
|
|
wclear(Hw);
|
|
for (tp = Lvl_obj; tp != NULL; tp = next(tp))
|
|
{
|
|
if (is_magic(tp))
|
|
{
|
|
show = TRUE;
|
|
wmove(Hw, tp->o_pos.y, tp->o_pos.x);
|
|
waddch(Hw, MAGIC);
|
|
Pot_info[P_TFIND].oi_know = TRUE;
|
|
}
|
|
}
|
|
for (mp = Mlist; mp != NULL; mp = next(mp))
|
|
{
|
|
for (tp = mp->t_pack; tp != NULL; tp = next(tp))
|
|
{
|
|
if (is_magic(tp))
|
|
{
|
|
show = TRUE;
|
|
wmove(Hw, mp->t_pos.y, mp->t_pos.x);
|
|
waddch(Hw, MAGIC);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (show)
|
|
{
|
|
Pot_info[P_TFIND].oi_know = TRUE;
|
|
show_win("You sense the presence of magic on this level.--More--");
|
|
}
|
|
else
|
|
msg("you have a %s feeling for a moment, then it passes",
|
|
choose_str("normal", "strange"));
|
|
when P_LSD:
|
|
if (!trip)
|
|
{
|
|
if (on(Player, SEEMONST))
|
|
turn_see(FALSE);
|
|
start_daemon(visuals, 0, BEFORE);
|
|
Seenstairs = seen_stairs();
|
|
}
|
|
do_pot(P_LSD, TRUE);
|
|
when P_SEEINVIS:
|
|
sprintf(Prbuf, "this potion tastes like %s juice", Fruit);
|
|
show = on(Player, CANSEE);
|
|
do_pot(P_SEEINVIS, FALSE);
|
|
if (!show)
|
|
invis_on();
|
|
sight();
|
|
when P_RAISE:
|
|
Pot_info[P_RAISE].oi_know = TRUE;
|
|
msg("you suddenly feel much more skillful");
|
|
raise_level();
|
|
when P_XHEAL:
|
|
Pot_info[P_XHEAL].oi_know = TRUE;
|
|
if ((Pstats.s_hpt += roll(Pstats.s_lvl, 8)) > Max_hp)
|
|
{
|
|
if (Pstats.s_hpt > Max_hp + Pstats.s_lvl + 1)
|
|
++Max_hp;
|
|
Pstats.s_hpt = ++Max_hp;
|
|
}
|
|
sight();
|
|
come_down();
|
|
msg("you begin to feel much better");
|
|
when P_HASTE:
|
|
Pot_info[P_HASTE].oi_know = TRUE;
|
|
After = FALSE;
|
|
if (add_haste(TRUE))
|
|
msg("you feel yourself moving much faster");
|
|
when P_RESTORE:
|
|
if (ISRING(LEFT, R_ADDSTR))
|
|
add_str(&Pstats.s_str, -Cur_ring[LEFT]->o_arm);
|
|
if (ISRING(RIGHT, R_ADDSTR))
|
|
add_str(&Pstats.s_str, -Cur_ring[RIGHT]->o_arm);
|
|
if (Pstats.s_str < Max_stats.s_str)
|
|
Pstats.s_str = Max_stats.s_str;
|
|
if (ISRING(LEFT, R_ADDSTR))
|
|
add_str(&Pstats.s_str, Cur_ring[LEFT]->o_arm);
|
|
if (ISRING(RIGHT, R_ADDSTR))
|
|
add_str(&Pstats.s_str, Cur_ring[RIGHT]->o_arm);
|
|
msg("hey, this tastes great. It make you feel warm all over");
|
|
when P_BLIND:
|
|
do_pot(P_BLIND, TRUE);
|
|
when P_LEVIT:
|
|
do_pot(P_LEVIT, TRUE);
|
|
#ifdef MASTER
|
|
otherwise:
|
|
msg("what an odd tasting potion!");
|
|
return;
|
|
#endif
|
|
}
|
|
status();
|
|
/*
|
|
* Throw the item away
|
|
*/
|
|
|
|
call_it(&Pot_info[obj->o_which]);
|
|
|
|
if (discardit)
|
|
discard(obj);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* is_magic:
|
|
* Returns true if an object radiates magic
|
|
*/
|
|
bool
|
|
is_magic(THING *obj)
|
|
{
|
|
switch (obj->o_type)
|
|
{
|
|
case ARMOR:
|
|
return (obj->o_flags&ISPROT) || obj->o_arm != A_class[obj->o_which];
|
|
case WEAPON:
|
|
return obj->o_hplus != 0 || obj->o_dplus != 0;
|
|
case POTION:
|
|
case SCROLL:
|
|
case STICK:
|
|
case RING:
|
|
case AMULET:
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* invis_on:
|
|
* Turn on the ability to see invisible
|
|
*/
|
|
void
|
|
invis_on(void)
|
|
{
|
|
THING *mp;
|
|
|
|
Player.t_flags |= CANSEE;
|
|
for (mp = Mlist; mp != NULL; mp = next(mp))
|
|
if (on(*mp, ISINVIS) && see_monst(mp) && !on(Player, ISHALU))
|
|
mvaddch(mp->t_pos.y, mp->t_pos.x, mp->t_disguise);
|
|
}
|
|
|
|
/*
|
|
* turn_see:
|
|
* Put on or off seeing monsters on this level
|
|
*/
|
|
bool
|
|
turn_see(bool turn_off)
|
|
{
|
|
THING *mp;
|
|
bool can_see, add_new;
|
|
|
|
add_new = FALSE;
|
|
for (mp = Mlist; mp != NULL; mp = next(mp))
|
|
{
|
|
move(mp->t_pos.y, mp->t_pos.x);
|
|
can_see = see_monst(mp);
|
|
if (turn_off)
|
|
{
|
|
if (!can_see)
|
|
addch(mp->t_oldch);
|
|
}
|
|
else
|
|
{
|
|
if (!can_see)
|
|
standout();
|
|
if (!on(Player, ISHALU))
|
|
addch(mp->t_type);
|
|
else
|
|
addch(rnd(26) + 'A');
|
|
if (!can_see)
|
|
{
|
|
standend();
|
|
add_new++;
|
|
}
|
|
}
|
|
}
|
|
if (turn_off)
|
|
Player.t_flags &= ~SEEMONST;
|
|
else
|
|
Player.t_flags |= SEEMONST;
|
|
return add_new;
|
|
}
|
|
|
|
/*
|
|
* seen_stairs:
|
|
* Return TRUE if the player has seen the stairs
|
|
*/
|
|
bool
|
|
seen_stairs(void)
|
|
{
|
|
THING *tp;
|
|
|
|
move(Stairs.y, Stairs.x);
|
|
if (inch() == STAIRS) /* it's on the map */
|
|
return TRUE;
|
|
if (ce(Hero, Stairs)) /* It's under him */
|
|
return TRUE;
|
|
|
|
/*
|
|
* if a monster is on the stairs, this gets hairy
|
|
*/
|
|
if ((tp = moat(Stairs.y, Stairs.x)) != NULL)
|
|
{
|
|
if (see_monst(tp) && on(*tp, ISRUN)) /* if it's visible and awake */
|
|
return TRUE; /* it must have moved there */
|
|
|
|
if (on(Player, SEEMONST) /* if she can detect monster */
|
|
&& tp->t_oldch == STAIRS) /* and there once were stairs */
|
|
return TRUE; /* it must have moved there */
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* raise_level:
|
|
* The guy just magically went up a level.
|
|
*/
|
|
void
|
|
raise_level(void)
|
|
{
|
|
Pstats.s_exp = E_levels[Pstats.s_lvl-1] + 1L;
|
|
check_level();
|
|
}
|
|
|
|
/*
|
|
* do_pot:
|
|
* Do a potion with standard setup. This means it uses a fuse and
|
|
* turns on a flag
|
|
*/
|
|
void
|
|
do_pot(int type, bool knowit)
|
|
{
|
|
PACT *pp;
|
|
int t;
|
|
|
|
pp = &P_actions[type];
|
|
if (!Pot_info[type].oi_know)
|
|
Pot_info[type].oi_know = knowit;
|
|
t = spread(pp->pa_time);
|
|
if (!on(Player, pp->pa_flags))
|
|
{
|
|
Player.t_flags |= pp->pa_flags;
|
|
fuse(pp->pa_daemon, 0, t, AFTER);
|
|
look(FALSE);
|
|
}
|
|
else
|
|
lengthen(pp->pa_daemon, t);
|
|
msg(choose_str(pp->pa_high, pp->pa_straight));
|
|
}
|