diff arogue7/effects.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/effects.c	Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,699 @@
+/*
+ * effects.c  -  functions for dealing with appllying effects to monsters
+ *
+ * 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.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+
+/*
+ * effect:
+ *	Check for effects of one thing hitting another thing.  Return
+ *	the reason code if the defender is killed.  Otherwise return 0.
+ */
+effect(att, def, weap, thrown, see_att, see_def)
+register struct thing *att, *def;
+struct object *weap;
+bool thrown;
+register bool see_att, see_def;
+{
+    register bool att_player, def_player;
+    char attname[LINELEN+1], defname[LINELEN+1];
+
+    /* See if the attacker or defender is the player */
+    att_player = (att == &player);
+    def_player = (def == &player);
+
+    /*
+     * If the player could see the attacker or defender, they can't
+     * surprise anymore (don't bother checking if they could).
+     */
+    if (see_att) turn_off(*att, CANSURPRISE);
+    if (see_def) turn_off(*def, CANSURPRISE);
+
+    /* What are the attacker and defender names? */
+    if (att_player) strcpy(attname, "you");
+    else {
+	if (see_att) strcpy(attname, monster_name(att));
+	else strcpy(attname, "something");
+    }
+
+    if (def_player) strcpy(defname, "you");
+    else {
+	if (see_def) strcpy(defname, monster_name(def));
+	else strcpy(defname, "something");
+    }
+
+    /*
+     * See what happens to the attacker first.  We can skip this
+     * whole section, however, if the defender is the player.
+     * Nothing happens (yet) to anyone just for hitting the player.
+     */
+    if (!def_player) {
+	if (!thrown) {	/* Some things require a direct hit. */
+	    /*
+	     * If the attacker hits a rusting monster, The weapon
+	     * may be damaged
+	     */
+	    if (on(*def, CANRUST)	&& weap				&&
+		weap->o_type != RELIC	&& (weap->o_flags & ISMETAL)	&&
+		!(weap->o_flags & ISPROT)) {
+		    if ((weap->o_hplus < 1 && weap->o_dplus < 1) ||
+			roll(1,20) < weap->o_hplus+weap->o_dplus+10) {
+			    if (rnd(100) < 50) weap->o_hplus--;
+			    else               weap->o_dplus--;
+			    if (att_player)
+				msg(terse ? "Your %s weakens!"
+					  : "Your %s appears to be weaker now!",
+				    weaps[weap->o_which].w_name);
+		    }
+	    }
+	}
+		
+	/* If the attacker hit something that shrieks, wake the dungeon */
+	if (on(*def, CANSHRIEK)) {
+	    turn_off(*def, CANSHRIEK);
+	    if (see_def)
+		msg("%s emits a piercing shriek.", prname(defname, TRUE));
+	    else msg("You hear a piercing shriek.");
+	    aggravate(TRUE, TRUE);
+	}
+
+	/*
+	 * does the creature explode when hit?
+	 */
+	if (on(*def, CANEXPLODE)) {
+	    if (see_def) msg("%s explodes!", prname(defname, TRUE));
+	    else msg("You hear a tremendous explosion!");
+	    explode(def);
+	    if (pstats.s_hpt <= 0)
+	        death(def->t_index);
+	}
+    }
+
+    /*
+     * Now let's see what happens to the defender.  Start out with
+     * the things that everyone can do.  Then exit if the attacker
+     * is the player.
+     */
+    if (!thrown) {
+	/* 
+	 * Can the player confuse? 
+	 */
+	if (on(*att, CANHUH) && att_player) {
+	    msg("Your hands stop glowing red.");
+	    if (off(*def, ISCLEAR) && 
+	       (off(*def, ISUNIQUE) || !save(VS_MAGIC, def, 0))) {
+		if (see_def) msg("%s appears confused.", prname(defname, TRUE));
+		turn_on(*def, ISHUH);
+	    }
+	    turn_off(*att, CANHUH);
+	}
+
+	/* Return now if the attacker is the player. */
+	if (att_player) return(0);
+
+	/*
+	 * Some monsters may take half your hit points
+	 */
+	if (on(*att, CANSUCK) && !save(VS_MAGIC, def, 0)) {
+	    if (def->t_stats.s_hpt == 1) return(att->t_index); /* Killed! */
+	    else {
+	        def->t_stats.s_hpt /= 2;
+	        if (def_player)
+		    msg("You feel your life force being drawn from you.");
+	    }
+	}
+
+	/*
+	 * If a hugging monster hits, it may SQUEEEEEEEZE.
+	 */
+	if (on(*att, CANHUG)) {
+	    if (roll(1,20) >= 18 || roll(1,20) >= 18) {
+		if (def_player)
+		    msg("%s squeezes you against itself.",
+				prname(attname, TRUE));
+		else if (see_att)
+		    msg("%s squeezes hard.", prname(attname, TRUE));
+
+		if ((def->t_stats.s_hpt -= roll(2,8)) <= 0)
+		    return(att->t_index);
+	    }
+	}
+
+	/*
+	 * Some monsters have poisonous bites.
+	 */
+	if (on(*att, CANPOISON) && !save(VS_POISON, def, 0)) {
+	    if (def_player) {
+		if (ISWEARING(R_SUSABILITY))
+		    msg(terse ? "Sting has no effect"
+			      : "A sting momentarily weakens you");
+		else {
+		    chg_str(-1);
+		    msg(terse ? "A sting has weakened you" :
+		    "You feel a sting in your arm and now feel weaker");
+		}
+	    }
+	    else {
+		/* Subtract a strength point and see if it kills it */
+		if (--def->t_stats.s_str <= 0) return(D_STRENGTH);
+	    }
+	}
+
+	/*
+	 * Turning to stone:
+	 */
+	if (on(*att, TOUCHSTONE)) {
+	    if (def_player) turn_off(*att, TOUCHSTONE);
+	    if (on(*def, CANINWALL)) {
+		if (def_player)
+		    msg("%s's touch has no effect.", prname(attname, TRUE));
+	    }
+	    else {
+		if (!save(VS_PETRIFICATION, def, 0) && rnd(100) < 10) {
+		    if (def_player) {
+			msg("Your body begins to solidify.");
+			msg("You are turned to stone !!! --More--");
+			wait_for(' ');
+			return(D_PETRIFY);
+		    }
+		    else {
+			/* The monster got stoned! */
+			turn_on(*def, ISSTONE);
+			turn_off(*def, ISRUN);
+			turn_off(*def, ISINVIS);
+			turn_off(*def, ISDISGUISE);
+			if (see_def)
+			    msg("%s turns to stone.", prname(defname, TRUE));
+			else if (cansee(unc(def->t_pos)))
+			    msg("A new statue appears!");
+		    }
+		}
+		else if (def->t_action != A_FREEZE) {
+		    if (def_player)
+			msg("%s's touch stiffens your limbs.",
+					prname(attname, TRUE));
+		    else if (see_def)
+			msg("%s appears to freeze.", prname(defname, TRUE));
+
+		    def->t_no_move += movement(def) * STONETIME;
+		    def->t_action = A_FREEZE;
+		}
+	    }
+	}
+
+	/*
+	 * Wraiths might drain energy levels
+	 */
+	if ((on(*att, CANDRAIN) || on(*att, DOUBLEDRAIN)) && 
+	    !save(VS_POISON, def, 3-(att->t_stats.s_lvl/5))) {
+	    if (def_player) {
+		lower_level(att->t_index);
+		if (on(*att, DOUBLEDRAIN)) lower_level(att->t_index);
+		turn_on(*att, DIDDRAIN);  
+	    }
+	    else {
+		def->t_stats.s_hpt -= roll(1, 8);
+		def->t_stats.s_lvl--;
+		if (on(*att, DOUBLEDRAIN)) {
+		    def->t_stats.s_hpt -= roll(1, 8);
+		    def->t_stats.s_lvl--;
+		}
+		if (see_def)
+		    msg("%s appears less skillfull.", prname(defname, TRUE));
+
+		/* Did it kill it? */
+		if (def->t_stats.s_hpt <= 0 ||
+		    def->t_stats.s_lvl <= 0)
+		    return(att->t_index);
+	    }
+	}
+
+	/*
+	 * Paralyzation:
+	 */
+	if (on(*att, CANPARALYZE) && def->t_action != A_FREEZE) {
+	    if (def_player) turn_off(*att, CANPARALYZE);
+	    if (!save(VS_PARALYZATION, def, 0)) {
+		if (on(*def, CANINWALL)) {
+		    if (def_player)
+			msg("%s's touch has no effect.", prname(attname, TRUE));
+		}
+		else {
+		    if (def_player)
+			msg("%s's touch paralyzes you.", prname(attname, TRUE));
+		    else if (see_def)
+			msg("%s appears to freeze.", prname(defname, TRUE));
+
+		    def->t_no_move += movement(def) * FREEZETIME;
+		    def->t_action = A_FREEZE;
+		}
+	    }
+	}
+
+	/*
+	 * Painful wounds make the defendant faint
+	 */
+	 if (on(*att, CANPAIN) && def->t_action != A_FREEZE) {
+	    if (def_player) turn_off(*att, CANPAIN);
+	    if (!ISWEARING(R_ALERT) && !save(VS_POISON, def, 0)) {
+		    if (def_player)
+			msg("You faint from the painful wound");
+		    else if (see_def)
+			msg("%s appears to faint.", prname(defname, TRUE));
+
+		    def->t_no_move += movement(def) * PAINTIME;
+		    def->t_action = A_FREEZE;
+	    }
+	}
+
+	/*
+	 * Some things currently affect only the player.  Let's make
+	 * a check here so we don't have to check for each thing.
+	 */
+	if (def_player) {
+	/*
+	 * Stinking monsters make the defender weaker (to hit).  For now
+	 * this will only affect the player.  We may later add the HASSTINK
+	 * effect to monsters, too.
+	 */
+	    if (on(*att, CANSTINK)) {
+		turn_off(*att, CANSTINK);
+		if (!save(VS_POISON, def, 0)) {
+		    msg("The stench of %s sickens you.",
+				prname(attname, FALSE));
+		    if (on(player, HASSTINK)) lengthen(unstink, STINKTIME);
+		    else {
+			turn_on(player, HASSTINK);
+			fuse(unstink, 0, STINKTIME, AFTER);
+		    }
+		}
+	    }