diff arogue5/potions.c @ 63:0ed67132cf10

Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 09 Aug 2012 22:58:48 +0000
parents
children c49f7927b0fa
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/potions.c	Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,698 @@
+/*
+ * Function(s) for dealing with potions
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985 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.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+
+
+
+/*
+ * Increase player's constitution
+ */
+
+add_const(cursed)
+bool cursed;
+{
+    /* Do the potion */
+    if (cursed) {
+	msg("You feel less healthy now.");
+	pstats.s_const--;
+	if (pstats.s_const <= 0)
+	    death(D_CONSTITUTION);
+    }
+    else {
+	msg("You feel healthier now.");
+	pstats.s_const = min(pstats.s_const + 1, 25);
+    }
+
+    /* Adjust the maximum */
+    if (max_stats.s_const < pstats.s_const)
+	max_stats.s_const = pstats.s_const;
+}
+
+/*
+ * Increase player's dexterity
+ */
+
+add_dexterity(cursed)
+bool cursed;
+{
+    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 (cursed) {
+	msg("You feel less dextrous now.");
+	pstats.s_dext--;
+    }
+    else {
+	msg("You feel more dextrous now.  Watch those hands!");
+	pstats.s_dext = min(pstats.s_dext + 1, 25);
+    }
+
+    /* 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 (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.");
+	no_command += rnd(hasttime);
+	lengthen(nohaste, roll(hasttime,hasttime));
+    }
+    else {
+	turn_on(player, ISHASTE);
+	fuse(nohaste, 0, roll(hasttime, hasttime), AFTER);
+    }
+}
+
+/*
+ * Increase player's intelligence
+ */
+add_intelligence(cursed)
+bool cursed;
+{
+    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 (cursed) {
+	msg("You feel slightly less intelligent now.");
+	pstats.s_intel--;
+    }
+    else {
+	msg("You feel more intelligent now.  What a mind!");
+	pstats.s_intel = min(pstats.s_intel + 1, 25);
+    }
+
+    /* 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()
+{
+    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);
+	    player.t_turn = TRUE;
+	    fuse(noslow, 0, roll(HASTETIME,HASTETIME), AFTER);
+	}
+    }
+}
+
+/*
+ * Increase player's strength
+ */
+
+add_strength(cursed)
+bool cursed;
+{
+
+    if (cursed) {
+	msg("You feel slightly weaker now.");
+	chg_str(-1);
+    }
+    else {
+	msg("You feel stronger now.  What bulging muscles!");
+	chg_str(1);
+    }
+}
+
+/*
+ * Increase player's wisdom
+ */
+
+add_wisdom(cursed)
+bool cursed;
+{
+    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 (cursed) {
+	msg("You feel slightly less wise now.");
+	pstats.s_wisdom--;
+    }
+    else {
+	msg("You feel wiser now.  What a sage!");
+	pstats.s_wisdom = min(pstats.s_wisdom + 1, 25);
+    }
+
+    /* 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;
+}
+
+
+/* 
+ * Lower a level of experience 
+ */
+
+lower_level(who)
+short who;
+{
+    int fewer, nsides = 0;
+
+    if (--pstats.s_lvl == 0)
+	death(who);		/* All levels gone */
+    msg("You suddenly feel less skillful.");
+    pstats.s_exp /= 2;
+    switch (player.t_ctype) {
+	case C_FIGHTER:	nsides = HIT_FIGHTER;
+	when C_MAGICIAN:nsides = HIT_MAGICIAN;
+	when C_CLERIC:	nsides = HIT_CLERIC;
+	when C_THIEF:	nsides = HIT_THIEF;
+    }
+    fewer = max(1, roll(1,nsides) + const_bonus());
+    pstats.s_hpt -= fewer;
+    max_stats.s_hpt -= fewer;
+    if (pstats.s_hpt < 1)
+	pstats.s_hpt = 1;
+    if (max_stats.s_hpt < 1)
+	death(who);
+}
+
+quaff(which, flag, is_potion)
+int which;
+int flag;
+bool is_potion;
+{
+    register struct object *obj = NULL;
+    register struct linked_list *item, *titem;
+    register struct thing *th;
+    bool cursed, blessed;
+    char buf[LINELEN];
+
+    blessed = FALSE;
+    cursed = FALSE;
+    item = NULL;
+
+    if (which < 0) {	/* figure out which ourselves */
+	item = get_item(pack, "quaff", POTION);
+	/*
+	 * Make certain that it is somethings that we want to drink
+	 */
+	if (item == NULL)
+	    return;
+
+	obj = OBJPTR(item);
+	/* remove it from the pack */
+	inpack--;
+	detach(pack, item);
+
+	/*
+	 * Calculate the effect it has on the poor guy.
+	 */
+	cursed = (obj->o_flags & ISCURSED) != 0;
+	blessed = (obj->o_flags & ISBLESSED) != 0;
+
+	which = obj->o_which;
+    }
+    else {
+	cursed = flag & ISCURSED;
+	blessed = flag & ISBLESSED;
+    }
+
+    switch(which)
+    {
+	case P_CLEAR:
+	    if (cursed) {
+		if (off(player, ISCLEAR))
+		{
+		    msg("Wait, what's going on here. Huh? What? Who?");
+		    if (find_slot(unconfuse))
+			lengthen(unconfuse, rnd(8)+HUHDURATION);
+		    else
+			fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
+		    turn_on(player, ISHUH);
+		}
+		else msg("You feel dizzy for a moment, but it quickly passes.");
+	    }
+	    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) == FALSE)
+			    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) {
+		if (!save(VS_POISON, &player, 0)) {
+		    msg("You feel very sick now.");
+		    pstats.s_hpt /= 2;
+		    pstats.s_const--;
+		    if (pstats.s_const <= 0 || pstats.s_hpt <= 0) 
+			death(D_POISON);
+		}
+		else msg("You feel momentarily sick.");
+	    }
+	    else {
+		if (blessed) {
+		    if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_stats.s_hpt)
+			pstats.s_hpt = ++max_stats.s_hpt;
+		    if (on(player, ISHUH)) {
+			extinguish(unconfuse);
+			unconfuse();
+		    }
+		}
+		else {
+		    if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > 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:
+	    {
+		int ctype;
+
+		/*
+		 * if blessed then fix all attributes
+		 */
+		if (blessed) {
+		    add_intelligence(FALSE);
+		    add_dexterity(FALSE);
+		    add_strength(FALSE);
+		    add_wisdom(FALSE);
+		    add_const(FALSE);
+		}
+		/* probably will be own ability */
+		else {
+		    if (rnd(100) < 70) 
+			ctype = player.t_ctype;
+		    else do {
+			ctype = rnd(4);
+			} while (ctype == player.t_ctype);
+
+		    /* Small chance of doing constitution instead */
+		    if (rnd(100) < 10) 
+			add_const(cursed);
+		    else switch (ctype) {
+			case C_FIGHTER: add_strength(cursed);
+			when C_MAGICIAN: add_intelligence(cursed);
+			when C_CLERIC:	add_wisdom(cursed);
+			when C_THIEF:	add_dexterity(cursed);
+			otherwise:	msg("You're a strange type!");
+		    }
+		}
+		if (is_potion) p_know[P_ABIL] = TRUE;
+	    }
+	when P_MFIND:
+	    /*
+	     * Potion of monster detection, if there are monters, detect them
+	     */
+	    if (mlist != NULL)
+	    {
+		msg("You begin to sense the presence of monsters.");
+		waddstr(cw, morestr);
+		overlay(mw, cw);
+		draw(cw);
+		wait_for(cw,' ');
+		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
+	     */
+	    if (lvl_obj != NULL)
+	    {
+		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);
+		    }
+		    if (is_potion) p_know[P_TFIND] = TRUE;
+		}
+		for (titem = mlist; titem != NULL; titem = next(titem)) {
+		    register struct linked_list *pitem;
+
+		    th = THINGPTR(titem);
+		    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 (is_potion) p_know[P_TFIND] = TRUE;
+		    }
+		}
+		if (show) {
+		    msg("You sense the presence of magic on this level.");
+		    waddstr(cw, morestr);
+		    overlay(hw,cw);
+		    draw(cw);
+		    wait_for(cw,' ');
+		    msg("");
+		    break;
+		}
+	    }
+	    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) != FALSE)
+		    lengthen(unsee, blessed ? SEEDURATION*3 : SEEDURATION);
+		sight();
+	    }
+	when P_PHASE:
+	    if (cursed) {
+		msg("You can't move.");
+		no_command = FREEZETIME;
+	    }
+	    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) 
+		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(TRUE);
+		if (blessed) raise_level(TRUE);
+	    }
+	when P_HASTE:
+	    if (cursed) {	/* Slow player down */
+		add_slow();
+	    }
+	    else {
+		if (off(player, ISSLOW))
+		    msg("You feel yourself moving %sfaster.",
+			blessed ? "much " : "");
+		add_haste(blessed);
+		if (is_potion) p_know[P_HASTE] = TRUE;
+	    }
+	when P_RESTORE: {
+	    register int i;
+
+	    msg("Hey, this tastes great.  It make you feel warm all over.");
+	    if (lost_str) {
+		extinguish(res_strength);
+		lost_str = 0;
+	    }
+	    for (i=0; i<lost_dext; i++)
+		extinguish(un_itch);
+	    lost_dext = 0;
+	    res_strength();
+	    res_wisdom();
+	    res_dexterity(0);
+	    res_intelligence();
+	    pstats.s_const = max_stats.s_const;
+	}
+	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 */
+	    }
+
+	otherwise:
+	    msg("What an odd tasting potion!");
+	    return;
+    }
+    status(FALSE);
+    if (is_potion && p_know[which] && p_guess[which])
+    {
+	free(p_guess[which]);
+	p_guess[which] = NULL;
+    }
+    else if (is_potion && 
+	     !p_know[which] && 
+	     askme &&
+	     (obj->o_flags & ISKNOW) == 0 &&
+	     (obj->o_flags & ISPOST) == 0 &&
+	     p_guess[which] == NULL)
+    {
+	msg(terse ? "Call it: " : "What do you want to call it? ");
+	if (get_str(buf, cw) == NORM)
+	{
+	    p_guess[which] = new((unsigned int) strlen(buf) + 1);
+	    strcpy(p_guess[which], buf);
+	}
+    }
+    if (item != NULL) o_discard(item);
+    updpack(TRUE);
+}
+
+
+/*
+ * res_dexterity:
+ *	Restore player's dexterity
+ *	if called with zero the restore fully
+ */
+
+res_dexterity(howmuch)
+int howmuch;
+{
+    short save_max;
+    int ring_str;
+
+    /* Discount the ring value */
+    ring_str = ring_value(R_ADDHIT);
+    pstats.s_dext -= ring_str;
+
+    if (pstats.s_dext < max_stats.s_dext ) {
+	if (howmuch == 0)
+	    pstats.s_dext = max_stats.s_dext;
+	else
+	    pstats.s_dext = min(pstats.s_dext+howmuch, max_stats.s_dext);
+    }
+
+    /* Redo the rings */
+    if (ring_str) {
+	save_max = max_stats.s_dext;
+	pstats.s_dext += ring_str;
+	max_stats.s_dext = save_max;
+    }
+}
+
+
+/*
+ * res_intelligence:
+ *	Restore player's intelligence
+ */
+
+res_intelligence()
+{
+    short save_max;
+    int ring_str;
+
+    /* Discount the ring value */
+    ring_str = ring_value(R_ADDINTEL);
+    pstats.s_intel -= ring_str;
+
+    if (pstats.s_intel < max_stats.s_intel ) pstats.s_intel = max_stats.s_intel;
+
+    /* Redo the rings */
+    if (ring_str) {
+	save_max = max_stats.s_intel;
+	pstats.s_intel += ring_str;
+	max_stats.s_intel = save_max;
+    }
+}
+
+/*
+ * res_wisdom:
+ *	Restore player's wisdom
+ */
+
+res_wisdom()
+{
+    short save_max;
+    int ring_str;
+
+    /* Discount the ring value */
+    ring_str = ring_value(R_ADDWISDOM);
+    pstats.s_wisdom -= ring_str;
+
+    if (pstats.s_wisdom < max_stats.s_wisdom )
+	pstats.s_wisdom = max_stats.s_wisdom;
+
+    /* Redo the rings */
+    if (ring_str) {
+	save_max = max_stats.s_wisdom;
+	pstats.s_wisdom += ring_str;
+	max_stats.s_wisdom = save_max;
+    }
+}