Mercurial > hg > early-roguelike
diff rogue5/potions.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Mon, 24 May 2010 20:10:59 +0000 |
parents | |
children | 696277507a2e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue5/potions.c Mon May 24 20:10:59 2010 +0000 @@ -0,0 +1,375 @@ +/* + * Function(s) for dealing with potions + * + * @(#)potions.c 4.46 (Berkeley) 06/07/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 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 <ctype.h> +#include "rogue.h" + +typedef struct PACT +{ + const int pa_flags; + void (*pa_daemon)(); + const int pa_time; + const char *pa_high, *pa_straight; +} PACT; + +static const 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; + int discardit = FALSE; + int 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) + { + case 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((void(*)())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 + */ +int +is_magic(const 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 + */ +int +turn_see(int turn_off) +{ + THING *mp; + int 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 + */ +int +seen_stairs(void) +{ + THING *tp; + + move(stairs.y, stairs.x); + if (CCHAR( 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, int knowit) +{ + const 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)); +}