diff rogue4/fight.c @ 12:9535a08ddc39

Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
author edwarj4
date Sat, 24 Oct 2009 16:52:52 +0000
parents
children 1b73a8641b37
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/fight.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,738 @@
+/*
+ * All the fighting gets done here
+ *
+ * @(#)fight.c	4.30 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 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 <string.h>
+#include "rogue.h"
+
+long e_levels[] = {
+    10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L,
+    40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L, 0L
+};
+
+/*
+ * fight:
+ *	The player attacks the monster.
+ */
+fight(mp, mn, weap, thrown)
+register coord *mp;
+char mn;
+register THING *weap;
+bool thrown;
+{
+    register THING *tp;
+    register bool did_hit = TRUE;
+    register const char *mname;
+
+    /*
+     * Find the monster we want to fight
+     */
+#ifdef WIZARD
+    if ((tp = moat(mp->y, mp->x)) == NULL)
+	debug("Fight what @ %d,%d", mp->y, mp->x);
+#else
+    tp = moat(mp->y, mp->x);
+#endif
+    /*
+     * Since we are fighting, things are not quiet so no healing takes
+     * place.
+     */
+    count = quiet = 0;
+    runto(mp, &hero);
+    /*
+     * Let him know it was really a mimic (if it was one).
+     */
+    if (tp->t_type == 'M' && tp->t_disguise != 'M' && !on(player, ISBLIND))
+    {
+	tp->t_disguise = 'M';
+	if (!thrown)
+	    return FALSE;
+	msg("wait! That's a mimic!");
+    }
+    did_hit = FALSE;
+    if (on(player, ISBLIND))
+	mname = "it";
+    else
+	mname = monsters[mn-'A'].m_name;
+    if (roll_em(&player, tp, weap, thrown))
+    {
+	did_hit = FALSE;
+	if (thrown)
+	    thunk(weap, mname);
+	else
+	    hit(NULL, mname);
+	if (on(player, CANHUH))
+	{
+	    did_hit = TRUE;
+	    tp->t_flags |= ISHUH;
+	    player.t_flags &= ~CANHUH;
+	    msg("your hands stop glowing red");
+	}
+	if (tp->t_stats.s_hpt <= 0)
+	    killed(tp, TRUE);
+	else if (did_hit && !on(player, ISBLIND))
+	    msg("the %s appears confused", mname);
+	did_hit = TRUE;
+    }
+    else
+	if (thrown)
+	    bounce(weap, mname);
+	else
+	    miss(NULL, mname);
+    return did_hit;
+}
+
+/*
+ * attack:
+ *	The monster attacks the player
+ */
+attack(mp)
+register THING *mp;
+{
+    register const char *mname;
+
+    /*
+     * Since this is an attack, stop running and any healing that was
+     * going on at the time.
+     */
+    running = FALSE;
+    count = quiet = 0;
+    if (mp->t_type == 'M' && !on(player, ISBLIND))
+	mp->t_disguise = 'M';
+    if (on(player, ISBLIND))
+	mname = "it";
+    else
+	mname = monsters[mp->t_type-'A'].m_name;
+    if (roll_em(mp, &player, NULL, FALSE))
+    {
+	if (mp->t_type != 'E')
+	    hit(mname, NULL);
+	if (pstats.s_hpt <= 0)
+	    death(mp->t_type);	/* Bye bye life ... */
+	if (!on(*mp, ISCANC))
+	    switch (mp->t_type)
+	    {
+		case 'R':
+		    /*
+		     * If a rust monster hits, you lose armor, unless
+		     * that armor is leather or there is a magic ring
+		     */
+		    if (cur_armor != NULL && cur_armor->o_ac < 9
+			&& cur_armor->o_which != LEATHER)
+			    if (ISWEARING(R_SUSTARM))
+				msg("The rust vanishes instantly");
+			    else
+			    {
+				cur_armor->o_ac++;
+				if (!terse)
+				    msg("your armor appears to be weaker now. Oh my!");
+				else
+				    msg("your armor weakens");
+			    }
+		when 'E':
+		    /*
+		     * The gaze of the floating eye hypnotizes you
+		     */
+		    if (on(player, ISBLIND))
+			break;
+		    player.t_flags &= ~ISRUN;
+		    if (!no_command)
+		    {
+			addmsg("you are transfixed");
+			if (!terse)
+			    addmsg(" by the gaze of the floating eye");
+			endmsg();
+		    }
+		    no_command += rnd(2) + 2;
+		when 'A':
+		    /*
+		     * Ants have poisonous bites
+		     */
+		    if (!save(VS_POISON))
+			if (!ISWEARING(R_SUSTSTR))
+			{
+			    chg_str(-1);
+			    if (!terse)
+				msg("you feel a sting in your arm and now feel weaker");
+			    else
+				msg("a sting has weakened you");
+			}
+			else
+			    if (!terse)
+				msg("a sting momentarily weakens you");
+			    else
+				msg("sting has no effect");
+		when 'W':
+		case 'V':
+		    /*
+		     * Wraiths might drain energy levels, and Vampires
+		     * can steal max_hp
+		     */
+		    if (rnd(100) < (mp->t_type == 'W' ? 15 : 30))
+		    {
+			register int fewer;
+
+			if (mp->t_type == 'W')
+			{
+			    if (pstats.s_exp == 0)
+				death('W');		/* All levels gone */
+			    if (--pstats.s_lvl == 0)
+			    {
+				pstats.s_exp = 0;
+				pstats.s_lvl = 1;
+			    }
+			    else
+				pstats.s_exp = e_levels[pstats.s_lvl-1]+1;
+			    fewer = roll(1, 10);
+			}
+			else
+			    fewer = roll(1, 5);
+			pstats.s_hpt -= fewer;
+			max_hp -= fewer;
+			if (pstats.s_hpt < 1)
+			    pstats.s_hpt = 1;
+			if (max_hp < 1)
+			    death(mp->t_type);
+			msg("you suddenly feel weaker");
+		    }
+		when 'F':
+		    /*
+		     * Violet fungi stops the poor guy from moving
+		     */
+		    player.t_flags |= ISHELD;
+		    sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit);
+		when 'L':
+		{
+		    /*
+		     * Leperachaun steals some gold
+		     */
+		    register long lastpurse;
+
+		    lastpurse = purse;
+		    purse -= GOLDCALC;
+		    if (!save(VS_MAGIC))
+			purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
+		    if (purse < 0)
+			purse = 0;
+		    remove_monster(&mp->t_pos, mp, FALSE);
+			mp = NULL;
+		    if (purse != lastpurse)
+			msg("your purse feels lighter");
+		}
+		when 'N':
+		{
+		    register THING *obj, *steal;
+		    register int nobj;
+
+		    /*
+		     * Nymph's steal a magic item, look through the pack
+		     * and pick out one we like.
+		     */
+		    steal = NULL;
+		    for (nobj = 0, obj = pack; obj != NULL; obj = next(obj))
+			if (obj != cur_armor && obj != cur_weapon
+			    && obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]
+			    && is_magic(obj) && rnd(++nobj) == 0)
+				steal = obj;
+		    if (steal != NULL)
+		    {
+			remove_monster(&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
+			mp = NULL;
+			inpack--;
+			if (steal->o_count > 1 && steal->o_group == 0)
+			{
+			    register int oc;
+
+			    oc = steal->o_count--;
+			    steal->o_count = 1;
+			    msg("she stole %s!", inv_name(steal, TRUE));
+			    steal->o_count = oc;
+			}
+			else
+			{
+			    detach(pack, steal);
+			    msg("she stole %s!", inv_name(steal, TRUE));
+			    discard(steal);
+			}
+		    }
+		}
+		otherwise:
+		    break;
+	    }
+    }
+    else if (mp->t_type != 'E')
+    {
+	if (mp->t_type == 'F')
+	{
+	    pstats.s_hpt -= fung_hit;
+	    if (pstats.s_hpt <= 0)
+		death(mp->t_type);	/* Bye bye life ... */
+	}
+	miss(mname, NULL);
+    }
+    if (fight_flush)
+	flush_type();
+    count = 0;
+    status();
+
+	if (mp == NULL)
+		return(-1);
+	else
+		return(0);
+}
+
+/*
+ * swing:
+ *	Returns true if the swing hits
+ */
+swing(at_lvl, op_arm, wplus)
+int at_lvl, op_arm, wplus;
+{
+    register int res = rnd(20);
+    register int need = (20 - at_lvl) - op_arm;
+
+    return (res + wplus >= need);
+}
+
+/*
+ * check_level:
+ *	Check to see if the guy has gone up a level.
+ */
+check_level()
+{
+    register int i, add, olevel;
+
+    for (i = 0; e_levels[i] != 0; i++)
+	if (e_levels[i] > pstats.s_exp)
+	    break;
+    i++;
+    olevel = pstats.s_lvl;
+    pstats.s_lvl = i;
+    if (i > olevel)
+    {
+	add = roll(i - olevel, 10);
+	max_hp += add;
+	if ((pstats.s_hpt += add) > max_hp)
+	    pstats.s_hpt = max_hp;
+	msg("welcome to level %d", i);
+    }
+}
+
+/*
+ * roll_em:
+ *	Roll several attacks
+ */
+roll_em(thatt, thdef, weap, hurl)
+THING *thatt, *thdef, *weap;
+bool hurl;
+{
+    register struct stats *att, *def;
+    register char *cp;
+    register int ndice, nsides, def_arm;
+    register bool did_hit = FALSE;
+    register int hplus;
+    register int dplus;
+    register int damage;
+
+    att = &thatt->t_stats;
+    def = &thdef->t_stats;
+    if (weap == NULL)
+    {
+	cp = att->s_dmg;
+	dplus = 0;
+	hplus = 0;
+    }
+    else
+    {
+	hplus = (weap == NULL ? 0 : weap->o_hplus);
+	dplus = (weap == NULL ? 0 : weap->o_dplus);
+	if (weap == cur_weapon)
+	{
+	    if (ISRING(LEFT, R_ADDDAM))
+		dplus += cur_ring[LEFT]->o_ac;
+	    else if (ISRING(LEFT, R_ADDHIT))
+		hplus += cur_ring[LEFT]->o_ac;
+	    if (ISRING(RIGHT, R_ADDDAM))
+		dplus += cur_ring[RIGHT]->o_ac;
+	    else if (ISRING(RIGHT, R_ADDHIT))
+		hplus += cur_ring[RIGHT]->o_ac;
+	}
+	if (hurl)
+	    if ((weap->