diff arogue7/potions.c @ 125:adfa37e67084

Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Fri, 08 May 2015 15:24:40 -0400
parents
children b786053d2f37
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/potions.c	Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,980 @@
+/*
+ * potions.c  -  Function(s) for dealing with potions
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985, 1986 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.
+ */
+
+/*
+ * Function(s) for dealing with potions
+ */
+
+#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.
+ */
+
+void (*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.
+ */
+
+void (*res_abil[NUMABILITIES])() = {
+    res_intelligence, res_strength, res_wisdom, res_dexterity,
+    res_constitution, res_charisma
+};
+
+/*
+ * Increase player's constitution
+ */
+
+void
+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 <= 0)
+	    death(D_CONSTITUTION);
+    }
+    else {
+	msg("You feel healthier now.");
+	pstats.s_const = min(pstats.s_const + change, 25);
+    }
+
+    /* Adjust the maximum */
+    if (max_stats.s_const < pstats.s_const)
+	max_stats.s_const = pstats.s_const;
+}
+
+/*
+ * Increase player's charisma
+ */
+
+void
+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 > 25) pstats.s_charisma = 25;
+    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;
+}
+
+/*
+ * Increase player's dexterity
+ */
+
+void
+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 > 25) pstats.s_dext = 25;
+    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;
+}
+
+/*
+ * 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, 0, roll(hasttime, hasttime), AFTER);
+    }
+}
+
+/*
+ * Increase player's intelligence
+ */
+void
+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 > 25) pstats.s_intel = 25;
+    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;
+}
+
+/*
+ * 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, 0, roll(HASTETIME,HASTETIME), AFTER);
+	}
+    }
+}
+
+/*
+ * Increase player's strength
+ */
+
+void
+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);
+    }
+}
+
+/*
+ * Increase player's wisdom
+ */
+
+void
+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 > 25) pstats.s_wisdom = 25;
+    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;
+}
+
+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, 0, 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 <= 0) 
+		    death(D_POISON);
+	    }
+	    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;
+		    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;
+
+		msg("You begin to sense the presence of monsters.");
+		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);
+		}
+		waddstr(msgw, morestr);
+		clearok(msgw, FALSE);
+		draw(msgw);
+		overlay(hw, cw);
+		draw(cw);
+		wait_for(' ');
+		msg("");
+		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;
+		    msg("You sense the presence of magic on this level.");
+		    waddstr(msgw, morestr);
+		    clearok(msgw, FALSE);
+		    draw(msgw);
+		    overlay(hw,cw);
+		    draw(cw);
+		    wait_for(' ');
+		    msg("");
+		    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, 0, SEEDURATION, AFTER);
+		    light(&hero);
+		}
+		else
+		    lengthen(sight, SEEDURATION);
+	    }
+	    else {
+		if (off(player, CANSEE)) {
+		    turn_on(player, CANSEE);
+		    msg("Your eyes begin to tingle.");
+		    fuse(unsee, 0, blessed ? SEEDURATION*3 :SEEDURATION, AFTER);
+		    light(&hero);
+		}
+		else if (find_slot(unsee) != 0)
+		    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, 0, 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, 0, 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();
+		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 ? 2 : 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);
+		}
+		else res_abil[i](howmuch);
+	    }
+	}
+	when P_INVIS:
+	    if (off(player, ISINVIS)) {
+		turn_on(player, ISINVIS);
+		msg("You have a tingling feeling all over your body");
+		fuse(appear, 0, blessed ? GONETIME*3 : GONETIME, AFTER);
+		PLAYER = IPLAYER;
+		light(&hero);
+	    }
+	    else {
+		if (find_slot(appear)) {
+		    msg("Your tingling feeling surges.");
+		    lengthen(appear, blessed ? GONETIME*3 : GONETIME);
+		}
+		else msg("Nothing happens.");	/* Using cloak */
+	    }
+
+	when P_FFIND:
+	    {
+		register struct linked_list *nitem;
+		register struct object *nobj;
+		bool show;
+
+		show = FALSE;
+		wclear(hw);
+		for (nitem = lvl_obj; nitem != NULL; nitem = next(nitem)) {
+		    nobj = OBJPTR(nitem);
+		    if (nobj->o_type == FOOD) {
+			show = TRUE;
+			mvwaddch(hw, nobj->o_pos.y, nobj->o_pos.x, FOOD);
+		    }
+		}
+		for (nitem = mlist; nitem != NULL; nitem = next(nitem)) {
+		    register struct linked_list *pitem;
+		    register struct thing *th;
+
+		    th = THINGPTR(nitem);
+		    if (on(*th, NODETECT)) continue;
+		    for(pitem = th->t_pack; pitem != NULL; pitem = next(pitem)){
+			nobj = OBJPTR(pitem);
+			if (nobj->o_type == FOOD) {
+			    show = TRUE;
+			    mvwaddch(hw, th->t_pos.y, th->t_pos.x, FOOD);
+			}
+		    }
+		}
+		if (show) {
+		    if (is_potion) p_know[P_FFIND] = TRUE;
+		    msg("Your nose tingles.");
+		    msg("You sense the presence of food on this level.");
+		    waddstr(msgw, morestr);
+		    clearok(msgw, FALSE);
+		    draw(msgw);
+		    overlay(hw,cw);
+		    draw(cw);
+		    wait_for(' ');
+		    msg("");
+		}
+		else
+	            msg("You have a strange feeling for a moment, then it passes.");
+	    }
+
+	when P_SKILL:
+	    if (cursed) {
+		msg("You feel less skillful.");