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));
+}