summaryrefslogtreecommitdiff
path: root/src/melee2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/melee2.c')
-rw-r--r--src/melee2.c7591
1 files changed, 0 insertions, 7591 deletions
diff --git a/src/melee2.c b/src/melee2.c
deleted file mode 100644
index 6ada6bd0..00000000
--- a/src/melee2.c
+++ /dev/null
@@ -1,7591 +0,0 @@
-/* File: melee2.c */
-
-/* Purpose: Monster spells and movement */
-
-/*
-* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
-*
-* This software may be copied and distributed for educational, research, and
-* not for profit purposes provided that this copyright and statement are
-* included in all such copies.
-*/
-
-/*
-* This file has several additions to it by Keldon Jones (keldon@umr.edu)
-* to improve the general quality of the AI (version 0.1.1).
-*/
-
-#include "angband.h"
-
-#define SPEAK_CHANCE 8
-#define GRINDNOISE 20
-
-#define FOLLOW_DISTANCE 6
-
-/*
- * Based on mon_take_hit... all monster attacks on
- * other monsters should use
- */
-bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
-{
- monster_type *m_ptr = &m_list[m_idx], *s_ptr = &m_list[s_idx];
-
- monster_race *r_ptr = race_inf(m_ptr);
-
- s32b div, new_exp, new_exp_frac;
-
- /* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
-
- /* Some mosnters are immune to death */
- if (r_ptr->flags7 & RF7_NO_DEATH) return FALSE;
-
- /* Wake it up */
- m_ptr->csleep = 0;
-
- /* Hurt it */
- m_ptr->hp -= dam;
-
- /* It is dead now... or is it? */
- if (m_ptr->hp < 0)
- {
- if (((r_ptr->flags1 & RF1_UNIQUE) && (m_ptr->status <= MSTATUS_NEUTRAL_P)) ||
- (m_ptr->mflag & MFLAG_QUEST))
- {
- m_ptr->hp = 1;
- }
- else
- {
- char m_name[80];
- s32b dive = s_ptr->level;
-
- if (!dive) dive = 1;
-
- /* Extract monster name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Make a sound */
- if ((r_ptr->flags3 & RF3_DEMON) ||
- (r_ptr->flags3 & RF3_UNDEAD) ||
- (r_ptr->flags2 & RF2_STUPID) ||
- (r_ptr->flags3 & RF3_NONLIVING) ||
- (strchr("Evg", r_ptr->d_char)))
- {
- sound(SOUND_N_KILL);
- }
- else
- {
- sound(SOUND_KILL);
- }
-
- /* Death by Missile/Spell attack */
- if (note)
- {
- cmonster_msg(TERM_L_RED, "%^s%s", m_name, note);
- }
- /* Death by Physical attack -- living monster */
- else if (!m_ptr->ml)
- {
- /* Do nothing */
- }
- /* Death by Physical attack -- non-living monster */
- else if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
- (r_ptr->flags3 & (RF3_NONLIVING)) ||
- (strchr("Evg", r_ptr->d_char)))
- {
- cmonster_msg(TERM_L_RED, "%^s is destroyed.", m_name);
- }
- else
- {
- cmonster_msg(TERM_L_RED, "%^s is killed.", m_name);
- }
-
- dive = r_ptr->mexp * m_ptr->level / dive;
- if (!dive) dive = 1;
-
- /* Monster gains some xp */
- monster_gain_exp(s_idx, dive, FALSE);
-
- /* Monster lore skill allows gaining xp from pets */
- if (get_skill(SKILL_LORE) && (s_ptr->status >= MSTATUS_PET))
- {
- /* Maximum player level */
- div = p_ptr->max_plv;
-
- /* Give some experience for the kill */
- new_exp = ((long)r_ptr->mexp * m_ptr->level) / div;
-
- /* Handle fractional experience */
- new_exp_frac = ((((long)r_ptr->mexp * m_ptr->level) % div)
- * 0x10000L / div) + p_ptr->exp_frac;
-
- /* Keep track of experience */
- if (new_exp_frac >= 0x10000L)
- {
- new_exp++;
- p_ptr->exp_frac = new_exp_frac - 0x10000;
- }
- else
- {
- p_ptr->exp_frac = new_exp_frac;
- }
-
- /*
- * Factor the xp by the skill level
- * Note that a score of 50 in the skill makes the gain be 120% of the exp
- */
- new_exp = new_exp * get_skill_scale(SKILL_LORE, 120) / 100;
-
- /* Gain experience */
- gain_exp(new_exp);
- }
-
- /* When an Unique dies, it stays dead */
- if (r_ptr->flags1 & (RF1_UNIQUE))
- {
- r_ptr->max_num = 0;
- }
-
- /* Generate treasure */
- monster_death(m_idx);
-
- /* Delete the monster */
- delete_monster_idx(m_idx);
-
- /* Not afraid */
- (*fear) = FALSE;
-
- /* Monster is dead */
- return (TRUE);
- }
-
- }
-
-#ifdef ALLOW_FEAR
-
- /* Mega-Hack -- Pain cancels fear */
- if (m_ptr->monfear && (dam > 0))
- {
- int tmp = randint(dam);
-
- /* Cure a little fear */
- if (tmp < m_ptr->monfear)
- {
- /* Reduce fear */
- m_ptr->monfear -= tmp;
- }
-
- /* Cure all the fear */
- else
- {
- /* Cure fear */
- m_ptr->monfear = 0;
-
- /* No more fear */
- (*fear) = FALSE;
- }
- }
-
- /* Sometimes a monster gets scared by damage */
- if (!m_ptr->monfear && !(r_ptr->flags3 & (RF3_NO_FEAR)))
- {
- int percentage;
-
- /* Percentage of fully healthy */
- percentage = (100L * m_ptr->hp) / m_ptr->maxhp;
-
- /*
- * Run (sometimes) if at 10% or less of max hit points,
- * or (usually) when hit for half its current hit points
- */
- if (((percentage <= 10) && (rand_int(10) < percentage)) ||
- ((dam >= m_ptr->hp) && (rand_int(100) < 80)))
- {
- /* Hack -- note fear */
- (*fear) = TRUE;
-
- /* XXX XXX XXX Hack -- Add some timed fear */
- m_ptr->monfear = (randint(10) +
- (((dam >= m_ptr->hp) && (percentage > 7)) ?
- 20 : ((11 - percentage) * 5)));
- }
- }
-
-#endif /* ALLOW_FEAR */
-
- /* Not dead yet */
- return (FALSE);
-}
-
-
-
-
-
-/*
-* And now for Intelligent monster attacks (including spells).
-*
-* Original idea and code by "DRS" (David Reeves Sward).
-* Major modifications by "BEN" (Ben Harrison).
-*
-* Give monsters more intelligent attack/spell selection based on
-* observations of previous attacks on the player, and/or by allowing
-* the monster to "cheat" and know the player status.
-*
-* Maintain an idea of the player status, and use that information
-* to occasionally eliminate "ineffective" spell attacks. We could
-* also eliminate ineffective normal attacks, but there is no reason
-* for the monster to do this, since he gains no benefit.
-* Note that MINDLESS monsters are not allowed to use this code.
-* And non-INTELLIGENT monsters only use it partially effectively.
-*
-* Actually learn what the player resists, and use that information
-* to remove attacks or spells before using them. This will require
-* much less space, if I am not mistaken. Thus, each monster gets a
-* set of 32 bit flags, "smart", build from the various "SM_*" flags.
-*
-* This has the added advantage that attacks and spells are related.
-* The "smart_learn" option means that the monster "learns" the flags
-* that should be set, and "smart_cheat" means that he "knows" them.
-* So "smart_cheat" means that the "smart" field is always up to date,
-* while "smart_learn" means that the "smart" field is slowly learned.
-* Both of them have the same effect on the "choose spell" routine.
-*/
-
-
-
-/*
-* Internal probability routine
-*/
-static bool_ int_outof(monster_race *r_ptr, int prob)
-{
- /* Non-Smart monsters are half as "smart" */
- if (!(r_ptr->flags2 & (RF2_SMART))) prob = prob / 2;
-
- /* Roll the dice */
- return (rand_int(100) < prob);
-}
-
-
-
-/*
- * Remove the "bad" spells from a spell list
- */
-static void remove_bad_spells(int m_idx, u32b *f4p, u32b *f5p, u32b *f6p)
-{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- u32b f4 = (*f4p);
- u32b f5 = (*f5p);
- u32b f6 = (*f6p);
-
- u32b smart = 0L;
-
-
- /* Too stupid to know anything */
- if (r_ptr->flags2 & (RF2_STUPID)) return;
-
-
- /* Must be cheating or learning */
- if (!smart_cheat && !smart_learn) return;
-
-
- /* Update acquired knowledge */
- if (smart_learn)
- {
- /* Hack -- Occasionally forget player status */
- if (m_ptr->smart && (rand_int(100) < 1)) m_ptr->smart = 0L;
-
- /* Use the memorized flags */
- smart = m_ptr->smart;
- }
-
-
- /* Cheat if requested */
- if (smart_cheat)
- {
- /* Know basic info */
- if (p_ptr->resist_acid) smart |= (SM_RES_ACID);
- if (p_ptr->oppose_acid) smart |= (SM_OPP_ACID);
- if (p_ptr->immune_acid) smart |= (SM_IMM_ACID);
- if (p_ptr->resist_elec) smart |= (SM_RES_ELEC);
- if (p_ptr->oppose_elec) smart |= (SM_OPP_ELEC);
- if (p_ptr->immune_elec) smart |= (SM_IMM_ELEC);
- if (p_ptr->resist_fire) smart |= (SM_RES_FIRE);
- if (p_ptr->oppose_fire) smart |= (SM_OPP_FIRE);
- if (p_ptr->immune_fire) smart |= (SM_IMM_FIRE);
- if (p_ptr->resist_cold) smart |= (SM_RES_COLD);
- if (p_ptr->oppose_cold) smart |= (SM_OPP_COLD);
- if (p_ptr->immune_cold) smart |= (SM_IMM_COLD);
-
- /* Know poison info */
- if (p_ptr->resist_pois) smart |= (SM_RES_POIS);
- if (p_ptr->oppose_pois) smart |= (SM_OPP_POIS);
-
- /* Know special resistances */
- if (p_ptr->resist_neth) smart |= (SM_RES_NETH);
- if (p_ptr->resist_lite) smart |= (SM_RES_LITE);
- if (p_ptr->resist_dark) smart |= (SM_RES_DARK);
- if (p_ptr->resist_fear) smart |= (SM_RES_FEAR);
- if (p_ptr->resist_conf) smart |= (SM_RES_CONF);
- if (p_ptr->resist_chaos) smart |= (SM_RES_CHAOS);
- if (p_ptr->resist_disen) smart |= (SM_RES_DISEN);
- if (p_ptr->resist_blind) smart |= (SM_RES_BLIND);
- if (p_ptr->resist_nexus) smart |= (SM_RES_NEXUS);
- if (p_ptr->resist_sound) smart |= (SM_RES_SOUND);
- if (p_ptr->resist_shard) smart |= (SM_RES_SHARD);
- if (p_ptr->reflect) smart |= (SM_IMM_REFLECT);
-
- /* Know bizarre "resistances" */
- if (p_ptr->free_act) smart |= (SM_IMM_FREE);
- if (!p_ptr->msp) smart |= (SM_IMM_MANA);
- }
-
-
- /* Nothing known */
- if (!smart) return;
-
-
- if (smart & (SM_IMM_ACID))
- {
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_ACID);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BA_ACID);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ACID);
- }
- else if ((smart & (SM_OPP_ACID)) && (smart & (SM_RES_ACID)))
- {
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_ACID);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_ACID);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_ACID);
- }
- else if ((smart & (SM_OPP_ACID)) || (smart & (SM_RES_ACID)))
- {
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_ACID);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_ACID);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_ACID);
- }
-
-
- if (smart & (SM_IMM_ELEC))
- {
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_ELEC);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BA_ELEC);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ELEC);
- }
- else if ((smart & (SM_OPP_ELEC)) && (smart & (SM_RES_ELEC)))
- {
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_ELEC);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_ELEC);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_ELEC);
- }
- else if ((smart & (SM_OPP_ELEC)) || (smart & (SM_RES_ELEC)))
- {
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_ELEC);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_ELEC);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_ELEC);
- }
-
-
- if (smart & (SM_IMM_FIRE))
- {
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_FIRE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BA_FIRE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_FIRE);
- }
- else if ((smart & (SM_OPP_FIRE)) && (smart & (SM_RES_FIRE)))
- {
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_FIRE);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_FIRE);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_FIRE);
- }
- else if ((smart & (SM_OPP_FIRE)) || (smart & (SM_RES_FIRE)))
- {
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_FIRE);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_FIRE);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_FIRE);
- }
-
-
- if (smart & (SM_IMM_COLD))
- {
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_COLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BA_COLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_COLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ICEE);
- }
- else if ((smart & (SM_OPP_COLD)) && (smart & (SM_RES_COLD)))
- {
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_COLD);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_COLD);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_COLD);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_ICEE);
- }
- else if ((smart & (SM_OPP_COLD)) || (smart & (SM_RES_COLD)))
- {
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_COLD);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_COLD);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_COLD);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_ICEE);
- }
-
-
- if ((smart & (SM_OPP_POIS)) && (smart & (SM_RES_POIS)))
- {
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_POIS);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_POIS);
- if (int_outof(r_ptr, 40)) f4 &= ~(RF4_BA_NUKE);
- if (int_outof(r_ptr, 40)) f4 &= ~(RF4_BR_NUKE);
- }
- else if ((smart & (SM_OPP_POIS)) || (smart & (SM_RES_POIS)))
- {
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_POIS);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_POIS);
- }
-
-
- if (smart & (SM_RES_NETH))
- {
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_NETH);
- if (int_outof(r_ptr, 50)) f5 &= ~(RF5_BA_NETH);
- if (int_outof(r_ptr, 50)) f5 &= ~(RF5_BO_NETH);
- }
-
- if (smart & (SM_RES_LITE))
- {
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_LITE);
- }
-
- if (smart & (SM_RES_DARK))
- {
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_DARK);
- if (int_outof(r_ptr, 50)) f5 &= ~(RF5_BA_DARK);
- }
-
- if (smart & (SM_RES_FEAR))
- {
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_SCARE);
- }
-
- if (smart & (SM_RES_CONF))
- {
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_CONF);
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_CONF);
- }
-
- if (smart & (SM_RES_CHAOS))
- {
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_CONF);
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_CONF);
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_CHAO);
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BA_CHAO);
- }
-
- if (smart & (SM_RES_DISEN))
- {
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_DISE);
- }
-
- if (smart & (SM_RES_BLIND))
- {
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BLIND);
- }
-
- if (smart & (SM_RES_NEXUS))
- {
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_NEXU);
- if (int_outof(r_ptr, 50)) f6 &= ~(RF6_TELE_LEVEL);
- }
-
- if (smart & (SM_RES_SOUND))
- {
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_SOUN);
- }
-
- if (smart & (SM_RES_SHARD))
- {
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_SHAR);
- if (int_outof(r_ptr, 20)) f4 &= ~(RF4_ROCKET);
- }
-
- if (smart & (SM_IMM_REFLECT))
- {
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_COLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_FIRE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ACID);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ELEC);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_POIS);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_NETH);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_WATE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_MANA);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_PLAS);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ICEE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_MISSILE);
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_ARROW_1);
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_ARROW_2);
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_ARROW_3);
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_ARROW_4);
- }
-
- if (smart & (SM_IMM_FREE))
- {
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_HOLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_SLOW);
- }
-
- if (smart & (SM_IMM_MANA))
- {
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_DRAIN_MANA);
- }
-
- /* XXX XXX XXX No spells left? */
- /* if (!f4 && !f5 && !f6) ... */
-
- (*f4p) = f4;
- (*f5p) = f5;
- (*f6p) = f6;
-}
-
-
-/*
- * Determine if there is a space near the player in which
- * a summoned creature can appear
- */
-static bool_ summon_possible(int y1, int x1)
-{
- int y, x;
-
- /* Start at the player's location, and check 2 grids in each dir */
- for (y = y1 - 2; y <= y1 + 2; y++)
- {
- for (x = x1 - 2; x <= x1 + 2; x++)
- {
- /* Ignore illegal locations */
- if (!in_bounds(y, x)) continue;
-
- /* Only check a circular area */
- if (distance(y1, x1, y, x) > 2) continue;
-
- /* Hack: no summon on glyph of warding */
- if (cave[y][x].feat == FEAT_GLYPH) continue;
- if (cave[y][x].feat == FEAT_MINOR_GLYPH) continue;
-
- /* Nor on the between */
- if (cave[y][x].feat == FEAT_BETWEEN) return (FALSE);
-
- /* ...nor on the Pattern */
- if ((cave[y][x].feat >= FEAT_PATTERN_START)
- && (cave[y][x].feat <= FEAT_PATTERN_XTRA2)) continue;
-
- /* Require empty floor grid in line of sight */
- if (cave_empty_bold(y, x) && los(y1, x1, y, x)) return (TRUE);
- }
- }
-
- return FALSE;
-}
-
-
-
-/*
- * Determine if a bolt spell will hit the player.
- *
- * This is exactly like "projectable", but it will return FALSE if a monster
- * is in the way.
- */
-static bool_ clean_shot(int y1, int x1, int y2, int x2)
-{
- int dist, y, x;
-
- /* Start at the initial location */
- y = y1, x = x1;
-
- /* See "project()" and "projectable()" */
- for (dist = 0; dist <= MAX_RANGE; dist++)
- {
- /* Never pass through walls */
- if (dist && (!cave_sight_bold(y, x) || !cave_floor_bold(y, x))) break;
-
- /* Never pass through monsters */
- if (dist && cave[y][x].m_idx > 0)
- {
- if (is_friend(&m_list[cave[y][x].m_idx]) < 0) break;
- }
-
- /* Check for arrival at "final target" */
- if ((x == x2) && (y == y2)) return (TRUE);
-
- /* Calculate the new location */
- mmove2(&y, &x, y1, x1, y2, x2);
- }
-
- /* Assume obstruction */
- return (FALSE);
-}
-
-
-/*
- * Cast a bolt at the player
- * Stop if we hit a monster
- * Affect monsters and the player
- */
-static void bolt(int m_idx, int typ, int dam_hp)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
-
- /* Target the player with a bolt attack */
- (void)project(m_idx, 0, p_ptr->py, p_ptr->px, dam_hp, typ, flg);
-}
-
-
-/*
- * Return TRUE if a spell is good for hurting the player (directly).
- */
-static bool_ spell_attack(byte spell)
-{
- /* All RF4 spells hurt (except for shriek, multiply, summon animal) */
- if (spell >= 96 + 3 && spell <= 96 + 31) return (TRUE);
-
- /* Various "ball" spells */
- if (spell >= 128 && spell <= 128 + 8) return (TRUE);
-
- /* "Cause wounds" and "bolt" spells */
- if (spell >= 128 + 12 && spell <= 128 + 26) return (TRUE);
-
- /* Hand of Doom */
- if (spell == 160 + 1) return (TRUE);
-
- /* Doesn't hurt */
- return (FALSE);
-}
-
-
-/*
- * Return TRUE if a spell is good for escaping.
- */
-static bool_ spell_escape(byte spell)
-{
- /* Blink or Teleport */
- if (spell == 160 + 4 || spell == 160 + 5) return (TRUE);
-
- /* Teleport the player away */
- if (spell == 160 + 7 || spell == 160 + 8) return (TRUE);
-
- /* Isn't good for escaping */
- return (FALSE);
-}
-
-/*
- * Return TRUE if a spell is good for annoying the player.
- */
-static bool_ spell_annoy(byte spell)
-{
- /* Shriek */
- if (spell == 96 + 0) return (TRUE);
-
- /* Brain smash, et al (added curses) */
- if (spell >= 128 + 9 && spell <= 128 + 14) return (TRUE);
-
- /* Scare, confuse, blind, slow, paralyze */
- if (spell >= 128 + 27 && spell <= 128 + 31) return (TRUE);
-
- /* Teleport to */
- if (spell == 160 + 6) return (TRUE);
-
- /* Darkness, make traps, cause amnesia */
- if (spell >= 160 + 9 && spell <= 160 + 11) return (TRUE);
-
- /* Doesn't annoy */
- return (FALSE);
-}
-
-/*
- * Return TRUE if a spell summons help.
- */
-static bool_ spell_summon(byte spell)
-{
- /* RF4_S_ANIMAL, RF6_S_ANIMALS */
- if (spell == 96 + 2 || spell == 160 + 3) return (TRUE);
- /* All other summon spells */
- if (spell >= 160 + 13 && spell <= 160 + 31) return (TRUE);
-
- /* Doesn't summon */
- return (FALSE);
-}
-
-
-/*
- * Return TRUE if a spell is good in a tactical situation.
- */
-static bool_ spell_tactic(byte spell)
-{
- /* Blink */
- if (spell == 160 + 4) return (TRUE);
-
- /* Not good */
- return (FALSE);
-}
-
-
-/*
- * Return TRUE if a spell hastes.
- */
-static bool_ spell_haste(byte spell)
-{
- /* Haste self */
- if (spell == 160 + 0) return (TRUE);
-
- /* Not a haste spell */
- return (FALSE);
-}
-
-
-/*
- * Return TRUE if a spell is good for healing.
- */
-static bool_ spell_heal(byte spell)
-{
- /* Heal */
- if (spell == 160 + 2) return (TRUE);
-
- /* No healing */
- return (FALSE);
-}
-
-
-/*
- * Have a monster choose a spell from a list of "useful" spells.
- *
- * Note that this list does NOT include spells that will just hit
- * other monsters, and the list is restricted when the monster is
- * "desperate". Should that be the job of this function instead?
- *
- * Stupid monsters will just pick a spell randomly. Smart monsters
- * will choose more "intelligently".
- *
- * Use the helper functions above to put spells into categories.
- *
- * This function may well be an efficiency bottleneck.
- */
-static int choose_attack_spell(int m_idx, byte spells[], byte num)
-{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- byte escape[96], escape_num = 0;
- byte attack[96], attack_num = 0;
- byte summon[96], summon_num = 0;
- byte tactic[96], tactic_num = 0;
- byte annoy[96], annoy_num = 0;
- byte haste[96], haste_num = 0;
- byte heal[96], heal_num = 0;
-
- int i;
-
- /* Stupid monsters choose randomly */
- if (r_ptr->flags2 & (RF2_STUPID))
- {
- /* Pick at random */
- return (spells[rand_int(num)]);
- }
-
- /* Categorize spells */
- for (i = 0; i < num; i++)
- {
- /* Escape spell? */
- if (spell_escape(spells[i])) escape[escape_num++] = spells[i];
-
- /* Attack spell? */
- if (spell_attack(spells[i])) attack[attack_num++] = spells[i];
-
- /* Summon spell? */
- if (spell_summon(spells[i])) summon[summon_num++] = spells[i];
-
- /* Tactical spell? */
- if (spell_tactic(spells[i])) tactic[tactic_num++] = spells[i];
-
- /* Annoyance spell? */
- if (spell_annoy(spells[i])) annoy[annoy_num++] = spells[i];
-
- /* Haste spell? */
- if (spell_haste(spells[i])) haste[haste_num++] = spells[i];
-
- /* Heal spell? */
- if (spell_heal(spells[i])) heal[heal_num++] = spells[i];
- }
-
- /*** Try to pick an appropriate spell type ***/
-
- /* Hurt badly or afraid, attempt to flee */
- if ((m_ptr->hp < m_ptr->maxhp / 3) || m_ptr->monfear)
- {
- /* Choose escape spell if possible */
- if (escape_num) return (escape[rand_int(escape_num)]);
- }
-
- /* Still hurt badly, couldn't flee, attempt to heal */
- if (m_ptr->hp < m_ptr->maxhp / 3)
- {
- /* Choose heal spell if possible */
- if (heal_num) return (heal[rand_int(heal_num)]);
- }
-
- /* Player is close and we have attack spells, blink away */
- if ((distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < 4) && attack_num && (rand_int(100) < 75))
- {
- /* Choose tactical spell */
- if (tactic_num) return (tactic[rand_int(tactic_num)]);
- }
-
- /* We're hurt (not badly), try to heal */
- if ((m_ptr->hp < m_ptr->maxhp * 3 / 4) && (rand_int(100) < 75))
- {
- /* Choose heal spell if possible */
- if (heal_num) return (heal[rand_int(heal_num)]);
- }
-
- /* Summon if possible (sometimes) */
- if (summon_num && (rand_int(100) < 50))
- {
- /* Choose summon spell */
- return (summon[rand_int(summon_num)]);
- }
-
- /* Attack spell (most of the time) */
- if (attack_num && (rand_int(100) < 85))
- {
- /* Choose attack spell */
- return (attack[rand_int(attack_num)]);
- }
-
- /* Try another tactical spell (sometimes) */
- if (tactic_num && (rand_int(100) < 50))
- {
- /* Choose tactic spell */
- return (tactic[rand_int(tactic_num)]);
- }
-
- /* Haste self if we aren't already somewhat hasted (rarely) */
- if (haste_num && (rand_int(100) < (20 + m_ptr->speed - m_ptr->mspeed)))
- {
- /* Choose haste spell */
- return (haste[rand_int(haste_num)]);
- }
-
- /* Annoy player (most of the time) */
- if (annoy_num && (rand_int(100) < 85))
- {
- /* Choose annoyance spell */
- return (annoy[rand_int(annoy_num)]);
- }
-
- /* Choose no spell */
- return (0);
-}
-
-
-/*
- * Cast a breath (or ball) attack at the player
- * Pass over any monsters that may be in the way
- * Affect grids, objects, monsters, and the player
- */
-static void breath(int m_idx, int typ, int dam_hp, int rad)
-{
- int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
-
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Determine the radius of the blast */
- if (rad < 1) rad = (r_ptr->flags2 & (RF2_POWERFUL)) ? 3 : 2;
-
- /* Target the player with a ball attack */
- (void)project(m_idx, rad, p_ptr->py, p_ptr->px, dam_hp, typ, flg);
-}
-
-
-/*
- * Monster casts a breath (or ball) attack at another monster.
- * Pass over any monsters that may be in the way
- * Affect grids, objects, monsters, and the player
- */
-static void monst_breath_monst(int m_idx, int y, int x, int typ, int dam_hp, int rad)
-{
- int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
-
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Determine the radius of the blast */
- if (rad < 1) rad = (r_ptr->flags2 & (RF2_POWERFUL)) ? 3 : 2;
-
- (void)project(m_idx, rad, y, x, dam_hp, typ, flg);
-}
-
-
-/*
- * Monster casts a bolt at another monster
- * Stop if we hit a monster
- * Affect monsters and the player
- */
-static void monst_bolt_monst(int m_idx, int y, int x, int typ, int dam_hp)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
-
- (void)project(m_idx, 0, y, x, dam_hp, typ, flg);
-}
-
-
-void monster_msg(cptr fmt, ...)
-{
- va_list vp;
-
- char buf[1024];
-
- /* Begin the Varargs Stuff */
- va_start(vp, fmt);
-
- /* Format the args, save the length */
- (void)vstrnfmt(buf, 1024, fmt, vp);
-
- /* End the Varargs Stuff */
- va_end(vp);
-
- /* Display */
- if (disturb_other)
- msg_print(buf);
- else
- {
- message_add(MESSAGE_MSG, buf, TERM_WHITE);
- p_ptr->window |= PW_MESSAGE;
- }
-}
-
-void cmonster_msg(char a, cptr fmt, ...)
-{
- va_list vp;
-
- char buf[1024];
-
- /* Begin the Varargs Stuff */
- va_start(vp, fmt);
-
- /* Format the args, save the length */
- (void)vstrnfmt(buf, 1024, fmt, vp);
-
- /* End the Varargs Stuff */
- va_end(vp);
-
- /* Display */
- if (disturb_other)
- cmsg_print(a, buf);
- else
- {
- message_add(MESSAGE_MSG, buf, a);
- p_ptr->window |= PW_MESSAGE;
- }
-}
-
-
-/*
- * Monster tries to 'cast a spell' (or breath, etc)
- * at another monster.
- */
-int monst_spell_monst_spell = -1;
-static bool_ monst_spell_monst(int m_idx)
-{
- int y = 0, x = 0;
- int i = 1, k, t_idx;
- int chance, thrown_spell, count = 0;
- byte spell[96], num = 0;
- char m_name[80], t_name[80];
- char m_poss[80];
- char ddesc[80];
- int rlev; /* monster level */
- monster_type *m_ptr = &m_list[m_idx]; /* Attacker */
- monster_race *r_ptr = race_inf(m_ptr);
- monster_type *t_ptr; /* Putative target */
- monster_race *tr_ptr;
- u32b f4, f5, f6; /* racial spell flags */
- bool_ direct = TRUE;
- bool_ wake_up = FALSE;
-
- /* Extract the blind-ness */
- bool_ blind = (p_ptr->blind ? TRUE : FALSE);
-
- /* Extract the "see-able-ness" */
- bool_ seen = (!blind && m_ptr->ml);
-
- bool_ see_m;
- bool_ see_t;
- bool_ see_either;
- bool_ see_both;
-
- bool_ friendly = FALSE;
-
- if (is_friend(m_ptr) > 0) friendly = TRUE;
-
- /* Cannot cast spells when confused */
- if (m_ptr->confused) return (FALSE);
-
- /* Hack -- Extract the spell probability */
- chance = (r_ptr->freq_inate + r_ptr->freq_spell) / 2;
-
- /* Not allowed to cast spells */
- if ((!chance) && (monst_spell_monst_spell == -1)) return (FALSE);
-
- if ((rand_int(100) >= chance) && (monst_spell_monst_spell == -1)) return (FALSE);
-
- /* Target location */
- if (m_ptr->target > -1)
- {
- if (m_ptr->target > 0)
- {
- i = m_ptr->target;
- }
- else return FALSE;
- }
- else return FALSE;
-
-
- {
- t_idx = i;
- t_ptr = &m_list[t_idx];
- tr_ptr = race_inf(t_ptr);
-
- /* Hack -- no fighting >100 squares from player */
- if (t_ptr->cdis > MAX_RANGE) return FALSE;
-
- /* Monster must be projectable */
- if (!projectable(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) return FALSE;
-
- /* OK -- we-ve got a target */
- y = t_ptr->fy;
- x = t_ptr->fx;
-
- /* Extract the monster level */
- rlev = ((m_ptr->level >= 1) ? m_ptr->level : 1);
-
- /* Extract the racial spell flags */
- f4 = r_ptr->flags4;
- f5 = r_ptr->flags5;
- f6 = r_ptr->flags6;
-
- /* Hack -- allow "desperate" spells */
- if ((r_ptr->flags2 & (RF2_SMART)) &&
- (m_ptr->hp < m_ptr->maxhp / 10) &&
- (rand_int(100) < 50))
- {
- /* Require intelligent spells */
- f4 &= (RF4_INT_MASK);
- f5 &= (RF5_INT_MASK);
- f6 &= (RF6_INT_MASK);
-
- /* No spells left */
- if ((!f4 && !f5 && !f6) && (monst_spell_monst_spell == -1)) return (FALSE);
- }
-
- /* Extract the "inate" spells */
- for (k = 0; k < 32; k++)
- {
- if (f4 & (1L << k)) spell[num++] = k + 32 * 3;
- }
-
- /* Extract the "normal" spells */
- for (k = 0; k < 32; k++)
- {
- if (f5 & (1L << k)) spell[num++] = k + 32 * 4;
- }
-
- /* Extract the "bizarre" spells */
- for (k = 0; k < 32; k++)
- {
- if (f6 & (1L << k)) spell[num++] = k + 32 * 5;
- }
-
- /* No spells left */
- if (!num) return (FALSE);
-
- /* Stop if player is dead or gone */
- if (!alive || death) return (FALSE);
-
- /* Handle "leaving" */
- if (p_ptr->leaving) return (FALSE);
-
- /* Get the monster name (or "it") */
- monster_desc(m_name, m_ptr, 0x00);
-
- /* Get the monster possessive ("his"/"her"/"its") */
- monster_desc(m_poss, m_ptr, 0x22);
-
- /* Get the target's name (or "it") */
- monster_desc(t_name, t_ptr, 0x00);
-
- /* Hack -- Get the "died from" name */
- monster_desc(ddesc, m_ptr, 0x88);
-
- /* Choose a spell to cast */
- thrown_spell = spell[rand_int(num)];
-
- /* Force a spell ? */
- if (monst_spell_monst_spell > -1)
- {
- thrown_spell = monst_spell_monst_spell;
- monst_spell_monst_spell = -1;
- }
-
- see_m = seen;
- see_t = (!blind && t_ptr->ml);
- see_either = (see_m || see_t);
- see_both = (see_m && see_t);
-
- switch (thrown_spell)
- {
- /* RF4_SHRIEK */
- case 96 + 0:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (!see_m) monster_msg("You hear a shriek.");
- else monster_msg("%^s shrieks at %s.", m_name, t_name);
- wake_up = TRUE;
- break;
- }
-
- /* RF4_MULTIPLY */
- case 96 + 1:
- {
- break;
- }
-
- /* RF4_S_ANIMAL */
- case 96 + 2:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons an animal!", m_name);
- for (k = 0; k < 1; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_ANIMAL);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
- break;
- }
-
- /* RF4_ROCKET */
- case 96 + 3:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear an explosion!");
- else if (blind) monster_msg("%^s shoots something.", m_name);
- else monster_msg("%^s fires a rocket at %s.", m_name, t_name);
- monst_breath_monst(m_idx, y, x, GF_ROCKET,
- ((m_ptr->hp / 4) > 800 ? 800 : (m_ptr->hp / 4)), 2);
- break;
- }
-
- /* RF4_ARROW_1 */
- case 96 + 4:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear a strange noise.");
- else if (blind) monster_msg("%^s makes a strange noise.", m_name);
- else monster_msg("%^s fires an arrow at %s.", m_name, t_name);
- sound(SOUND_SHOOT);
- monst_bolt_monst(m_idx, y, x, GF_ARROW, damroll(1, 6));
- break;
- }
-
- /* RF4_ARROW_2 */
- case 96 + 5:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear a strange noise.");
- else if (blind) monster_msg("%^s makes a strange noise.", m_name);
- else monster_msg("%^s fires an arrow at %s.", m_name, t_name);
- sound(SOUND_SHOOT);
- monst_bolt_monst(m_idx, y, x, GF_ARROW, damroll(3, 6));
- break;
- }
-
- /* RF4_ARROW_3 */
- case 96 + 6:
- {
- if (disturb_other) disturb(1, 0);
-
- if (!see_either) monster_msg("You hear a strange noise.");
- else if (blind) monster_msg("%^s makes a strange noise.", m_name);
- else monster_msg("%^s fires a missile at %s.", m_name, t_name);
- sound(SOUND_SHOOT);
- monst_bolt_monst(m_idx, y, x, GF_ARROW, damroll(5, 6));
- break;
- }
-
- /* RF4_ARROW_4 */
- case 96 + 7:
- {
- if (!see_either) monster_msg("You hear a strange noise.");
- else if (disturb_other) disturb(1, 0);
- if (blind) monster_msg("%^s makes a strange noise.", m_name);
- else monster_msg("%^s fires a missile at %s.", m_name, t_name);
- sound(SOUND_SHOOT);
- monst_bolt_monst(m_idx, y, x, GF_ARROW, damroll(7, 6));
- break;
- }
-
- /* RF4_BR_ACID */
- case 96 + 8:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes acid at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_ACID,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_ELEC */
- case 96 + 9:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes lightning at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_ELEC,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_FIRE */
- case 96 + 10:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes fire at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_FIRE,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_COLD */
- case 96 + 11:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes frost at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_COLD,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_POIS */
- case 96 + 12:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes gas at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_POIS,
- ((m_ptr->hp / 3) > 800 ? 800 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_NETH */
- case 96 + 13:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes nether at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_NETHER,
- ((m_ptr->hp / 6) > 550 ? 550 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_LITE */
- case 96 + 14:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes light at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_LITE,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_DARK */
- case 96 + 15:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes darkness at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_DARK,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_CONF */
- case 96 + 16:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes confusion at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_CONFUSION,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_SOUN */
- case 96 + 17:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes sound at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_SOUND,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_CHAO */
- case 96 + 18:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes chaos at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_CHAOS,
- ((m_ptr->hp / 6) > 600 ? 600 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_DISE */
- case 96 + 19:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes disenchantment at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_DISENCHANT,
- ((m_ptr->hp / 6) > 500 ? 500 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_NEXU */
- case 96 + 20:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes nexus at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_NEXUS,
- ((m_ptr->hp / 3) > 250 ? 250 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_TIME */
- case 96 + 21:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes time at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_TIME,
- ((m_ptr->hp / 3) > 150 ? 150 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_INER */
- case 96 + 22:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes inertia at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_INERTIA,
- ((m_ptr->hp / 6) > 200 ? 200 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_GRAV */
- case 96 + 23:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes gravity at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_GRAVITY,
- ((m_ptr->hp / 3) > 200 ? 200 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_SHAR */
- case 96 + 24:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes shards at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_SHARDS,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_PLAS */
- case 96 + 25:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes plasma at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_PLASMA,
- ((m_ptr->hp / 6) > 150 ? 150 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_WALL */
- case 96 + 26:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes force at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_FORCE,
- ((m_ptr->hp / 6) > 200 ? 200 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_MANA */
- case 96 + 27:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes magical energy at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_MANA,
- ((m_ptr->hp / 3) > 250 ? 250 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BA_NUKE */
- case 96 + 28:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear someone mumble.");
- else if (blind) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a ball of radiation at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_NUKE,
- (rlev + damroll(10, 6)), 2);
- break;
- }
-
- /* RF4_BR_NUKE */
- case 96 + 29:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes toxic waste at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_NUKE,
- ((m_ptr->hp / 3) > 800 ? 800 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BA_CHAO */
- case 96 + 30:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear someone mumble frighteningly.");
- else if (blind) monster_msg("%^s mumbles frighteningly.", m_name);
- else monster_msg("%^s invokes a raw Chaos upon %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_CHAOS,
- (rlev * 2) + damroll(10, 10), 4);
- break;
- }
-
- /* RF4_BR_DISI -> Breathe Disintegration */
- case 96 + 31:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg("You hear breathing noise.");
- else if (blind) monster_msg("%^s breathes.", m_name);
- else monster_msg("%^s breathes disintegration at %s.", m_name, t_name);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_DISINTEGRATE,
- ((m_ptr->hp / 3) > 300 ? 300 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF5_BA_ACID */
- case 128 + 0:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg ("You hear someone mumble.");
- else if (blind) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts an acid ball at %s.", m_name, t_name);
- monst_breath_monst(m_idx, y, x, GF_ACID, randint(rlev * 3) + 15, 2);
- break;
- }
-
- /* RF5_BA_ELEC */
- case 128 + 1:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg ("You hear someone mumble.");
- else
- if (blind) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a lightning ball at %s.", m_name, t_name);
- monst_breath_monst(m_idx, y, x, GF_ELEC, randint(rlev * 3 / 2) + 8, 2);
- break;
- }
-
- /* RF5_BA_FIRE */
- case 128 + 2:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg ("You hear someone mumble.");
- else
- if (blind) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a fire ball at %s.", m_name, t_name);
- monst_breath_monst(m_idx, y, x, GF_FIRE, randint(rlev * 7 / 2) + 10, 2);
- break;
- }
-
- /* RF5_BA_COLD */
- case 128 + 3:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg ("You hear someone mumble.");
- else
- if (blind) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a frost ball at %s.", m_name, t_name);
- monst_breath_monst(m_idx, y, x, GF_COLD, randint(rlev * 3 / 2) + 10, 2);
- break;
- }
-
- /* RF5_BA_POIS */
- case 128 + 4:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg ("You hear someone mumble.");
- else
- if (blind) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a stinking cloud at %s.", m_name, t_name);
- monst_breath_monst(m_idx, y, x, GF_POIS, damroll(12, 2), 2);
- break;
- }
-
- /* RF5_BA_NETH */
- case 128 + 5:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg ("You hear someone mumble.");
- else
- if (blind) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a nether ball at %s.", m_name, t_name);
- monst_breath_monst(m_idx, y, x, GF_NETHER, (50 + damroll(10, 10) + rlev), 2);
- break;
- }
-
- /* RF5_BA_WATE */
- case 128 + 6:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg ("You hear someone mumble.");
- else
- if (blind) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s gestures fluidly at %s.", m_name, t_name);
- monster_msg("%^s is engulfed in a whirlpool.", t_name);
- monst_breath_monst(m_idx, y, x, GF_WATER, randint(rlev * 5 / 2) + 50, 4);
- break;
- }
-
- /* RF5_BA_MANA */
- case 128 + 7:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg ("You hear someone mumble powerfully.");
- else
- if (blind) monster_msg("%^s mumbles powerfully.", m_name);
- else monster_msg("%^s invokes a mana storm upon %s.", m_name, t_name);
- monst_breath_monst(m_idx, y, x, GF_MANA, (rlev * 5) + damroll(10, 10), 4);
- break;
- }
-
- /* RF5_BA_DARK */
- case 128 + 8:
- {
- if (disturb_other) disturb(1, 0);
- if (!see_either) monster_msg ("You hear someone mumble powerfully.");
- else
- if (blind) monster_msg("%^s mumbles powerfully.", m_name);
- else monster_msg("%^s invokes a darkness storm upon %s.", m_name, t_name);
- monst_breath_monst(m_idx, y, x, GF_DARK, (rlev * 5) + damroll(10, 10), 4);
- break;
- }
-
- /* RF5_DRAIN_MANA */
- case 128 + 9:
- {
- /* Attack power */
- int r1 = (randint(rlev) / 2) + 1;
-
- if (see_m)
- {
- /* Basic message */
- monster_msg("%^s draws psychic energy from %s.", m_name, t_name);
- }
-
- /* Heal the monster */
- if (m_ptr->hp < m_ptr->maxhp)
- {
- if (!(tr_ptr->flags4 || tr_ptr->flags5 || tr_ptr->flags6))
- {
- if (see_both)
- monster_msg("%^s is unaffected!", t_name);
- }
- else
- {
- /* Heal */
- m_ptr->hp += (6 * r1);
- if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
-
- /* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
-
- /* Special message */
- if (seen)
- {
- monster_msg("%^s appears healthier.", m_name);
- }
- }
- }
-
- wake_up = TRUE;
- break;
- }
-
- /* RF5_MIND_BLAST */
- case 128 + 10:
- {
- if (!direct) break;
-
- if (disturb_other) disturb(1, 0);
-
- if (!seen)
- {
- /* */
- }
- else
- {
- monster_msg("%^s gazes intently at %s.", m_name, t_name);
- }
-
- /* Attempt a saving throw */
- if ((tr_ptr->flags1 & (RF1_UNIQUE)) ||
- (tr_ptr->flags3 & (RF3_NO_CONF)) ||
- (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10))
- {
- /* Memorize a flag */
- if (tr_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) tr_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
- /* No obvious effect */
- if (see_t)
- {
- monster_msg("%^s is unaffected!", t_name);
- }
- }
- else
- {
- bool_ fear;
- monster_msg("%^s is blasted by psionic energy.", t_name);
- t_ptr->confused += rand_int(4) + 4;
-
- mon_take_hit_mon(m_idx, t_idx, damroll(8, 8), &fear, " collapses, a mindless husk.");
- }
-
- wake_up = TRUE;
- break;
- }
-
- /* RF5_BRAIN_SMASH */
- case 128 + 11:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (!seen)
- {
- /* */
- }
- else
- {
- monster_msg("%^s gazes intently at %s.", m_name, t_name);
- }
-
- /* Attempt a saving throw */
- if ((tr_ptr->flags1 & (RF1_UNIQUE)) ||
- (tr_ptr->flags3 & (RF3_NO_CONF)) ||
- (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10))
- {
- /* Memorize a flag */
- if (tr_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) tr_ptr->r_flags3 |= (RF3_NO_CONF);
- }
- /* No obvious effect */
- if (see_t)
- {
- monster_msg("%^s is unaffected!", t_name);
- }
- }
- else
- {
- bool_ fear;
- if (see_t)
- {
- monster_msg("%^s is blasted by psionic energy.", t_name);
- }
- t_ptr->confused += rand_int(4) + 4;
- t_ptr->mspeed -= rand_int(4) + 4;
- t_ptr->stunned += rand_int(4) + 4;
- mon_take_hit_mon(m_idx, t_idx, damroll(12, 15), &fear, " collapses, a mindless husk.");
- }
- wake_up = TRUE;
- break;
- }
-
- /* RF5_CAUSE_1 */
- case 128 + 12:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s points at %s and curses.", m_name, t_name);
- if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
- {
-
- if (see_t) monster_msg("%^s resists!", t_name);
- }
- else
- {
- bool_ fear;
- mon_take_hit_mon(m_idx, t_idx, damroll(3, 8), &fear, " is destroyed.");
- }
- wake_up = TRUE;
- break;
- }
-
- /* RF5_CAUSE_2 */
- case 128 + 13:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s points at %s and curses horribly.", m_name, t_name);
- if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
- {
- if (see_t) monster_msg("%^s resists!", t_name);
- }
- else
- {
- bool_ fear;
- mon_take_hit_mon(m_idx, t_idx, damroll(8, 8), &fear, " is destroyed.");
- }
- wake_up = TRUE;
- break;
- }
-
- /* RF5_CAUSE_3 */
- case 128 + 14:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s points at %s, incanting terribly!", m_name, t_name);
- if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
- {
- if (see_t) monster_msg("%^s resists!", t_name);
- }
- else
- {
- bool_ fear;
- mon_take_hit_mon(m_idx, t_idx, damroll(10, 15), &fear, " is destroyed.");
- }
- wake_up = TRUE;
- break;
- }
-
- /* RF5_CAUSE_4 */
- case 128 + 15:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s points at %s, screaming the word 'DIE!'", m_name, t_name);
- if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
- {
- if (see_t) monster_msg("%^s resists!", t_name);
- }
- else
- {
- bool_ fear;
- mon_take_hit_mon(m_idx, t_idx, damroll(15, 15), &fear, " is destroyed.");
- }
- wake_up = TRUE;
- break;
- }
-
- /* RF5_BO_ACID */
- case 128 + 16:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts an acid bolt at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_ACID,
- damroll(7, 8) + (rlev / 3));
- break;
- }
-
- /* RF5_BO_ELEC */
- case 128 + 17:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a lightning bolt at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_ELEC,
- damroll(4, 8) + (rlev / 3));
- break;
- }
-
- /* RF5_BO_FIRE */
- case 128 + 18:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a fire bolt at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_FIRE,
- damroll(9, 8) + (rlev / 3));
- break;
- }
-
- /* RF5_BO_COLD */
- case 128 + 19:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a frost bolt at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_COLD,
- damroll(6, 8) + (rlev / 3));
- break;
- }
-
- /* RF5_BO_POIS */
- case 128 + 20:
- {
- /* XXX XXX XXX */
- break;
- }
-
- /* RF5_BO_NETH */
- case 128 + 21:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a nether bolt at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_NETHER,
- 30 + damroll(5, 5) + (rlev * 3) / 2);
- break;
- }
-
- /* RF5_BO_WATE */
- case 128 + 22:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a water bolt at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_WATER,
- damroll(10, 10) + (rlev));
- break;
- }
-
- /* RF5_BO_MANA */
- case 128 + 23:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a mana bolt at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_MANA,
- randint(rlev * 7 / 2) + 50);
- break;
- }
-
- /* RF5_BO_PLAS */
- case 128 + 24:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a plasma bolt at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_PLASMA,
- 10 + damroll(8, 7) + (rlev));
- break;
- }
-
- /* RF5_BO_ICEE */
- case 128 + 25:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts an ice bolt at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_ICE,
- damroll(6, 6) + (rlev));
- break;
- }
-
- /* RF5_MISSILE */
- case 128 + 26:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a magic missile at %s.", m_name, t_name);
- monst_bolt_monst(m_idx, y, x, GF_MISSILE,
- damroll(2, 6) + (rlev / 3));
- break;
- }
-
- /* RF5_SCARE */
- case 128 + 27:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles, and you hear scary noises.", m_name);
- else monster_msg("%^s casts a fearful illusion at %s.", m_name, t_name);
- if (tr_ptr->flags3 & RF3_NO_FEAR)
- {
- if (see_t) monster_msg("%^s refuses to be frightened.", t_name);
- }
- else if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
- {
- if (see_t) monster_msg("%^s refuses to be frightened.", t_name);
- }
- else
- {
- if (!(t_ptr->monfear) && see_t) monster_msg("%^s flees in terror!", t_name);
- t_ptr->monfear += rand_int(4) + 4;
- }
- wake_up = TRUE;
- break;
- }
-
- /* RF5_BLIND */
- case 128 + 28:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s casts a spell, burning %s%s eyes.", m_name, t_name,
- (!strcmp(t_name, "it") ? "s" : "'s"));
- if (tr_ptr->flags3 & RF3_NO_CONF) /* Simulate blindness with confusion */
- {
- if (see_t) monster_msg("%^s is unaffected.", t_name);
- }
- else if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
- {
- if (see_t) monster_msg("%^s is unaffected.", t_name);
- }
- else
- {
- if (see_t) monster_msg("%^s is blinded!", t_name);
- t_ptr->confused += 12 + (byte)rand_int(4);
- }
- wake_up = TRUE;
- break;
-
- }
-
- /* RF5_CONF */
- case 128 + 29:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles, and you hear puzzling noises.", m_name);
- else monster_msg("%^s creates a mesmerising illusion in front of %s.", m_name, t_name);
- if (tr_ptr->flags3 & RF3_NO_CONF)
- {
- if (see_t) monster_msg("%^s disbelieves the feeble spell.", t_name);
- }
- else if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
- {
- if (see_t) monster_msg("%^s disbelieves the feeble spell.", t_name);
- }
- else
- {
- if (see_t) monster_msg("%^s seems confused.", t_name);
- t_ptr->confused += 12 + (byte)rand_int(4);
- }
- wake_up = TRUE;
- break;
- }
-
- /* RF5_SLOW */
- case 128 + 30:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (!blind && see_either) monster_msg("%^s drains power from %s%s muscles.", m_name, t_name,
- (!strcmp(t_name, "it") ? "s" : "'s"));
- if (tr_ptr->flags1 & RF1_UNIQUE)
- {
- if (see_t) monster_msg("%^s is unaffected.", t_name);
- }
- else if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
- {
- if (see_t) monster_msg("%^s is unaffected.", t_name);
- }
- else
- {
- t_ptr->mspeed -= 10;
- if (see_t) monster_msg("%^s starts moving slower.", t_name);
- }
- wake_up = TRUE;
- break;
- }
-
- /* RF5_HOLD */
- case 128 + 31:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (!blind && see_m) monster_msg("%^s stares intently at %s.", m_name, t_name);
- if ((tr_ptr->flags1 & RF1_UNIQUE) ||
- (tr_ptr->flags3 & RF3_NO_STUN))
- {
- if (see_t) monster_msg("%^s is unaffected.", t_name);
- }
- else if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
- {
- if (see_t) monster_msg("%^s is unaffected.", t_name);
- }
- else
- {
- t_ptr->stunned += randint(4) + 4;
- if (see_t) monster_msg("%^s is paralyzed!", t_name);
- }
- wake_up = TRUE;
- break;
- }
-
-
- /* RF6_HASTE */
- case 160 + 0:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m)
- {
- monster_msg("%^s mumbles.", m_name);
- }
- else
- {
- monster_msg("%^s concentrates on %s body.", m_name, m_poss);
- }
-
- /* Allow quick speed increases to base+10 */
- if (m_ptr->mspeed < m_ptr->speed + 10)
- {
- if (see_m) monster_msg("%^s starts moving faster.", m_name);
- m_ptr->mspeed += 10;
- }
-
- /* Allow small speed increases to base+20 */
- else if (m_ptr->mspeed < m_ptr->speed + 20)
- {
- if (see_m) monster_msg("%^s starts moving faster.", m_name);
- m_ptr->mspeed += 2;
- }
-
- break;
- }
-
- /* RF6_HAND_DOOM */
- case 160 + 1:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (!see_m) monster_msg("You hear someone invoke the Hand of Doom!");
- else if (!blind) monster_msg("%^s invokes the Hand of Doom on %s.", m_name, t_name);
- else
- monster_msg ("You hear someone invoke the Hand of Doom!");
- if (tr_ptr->flags1 & RF1_UNIQUE)
- {
- if (!blind && see_t) monster_msg("^%s is unaffected!", t_name);
- }
- else
- {
- if (((m_ptr->level) + randint(20)) >
- ((t_ptr->level) + 10 + randint(20)))
- {
- t_ptr->hp = t_ptr->hp
- - (((s32b) ((65 + randint(25)) * (t_ptr->hp))) / 100);
- if (t_ptr->hp < 1) t_ptr->hp = 1;
- }
- else
- {
- if (see_t) monster_msg("%^s resists!", t_name);
- }
- }
-
- wake_up = TRUE;
- break;
- }
-
- /* RF6_HEAL */
- case 160 + 2:
- {
- if (disturb_other) disturb(1, 0);
-
- /* Message */
- if (blind || !see_m)
- {
- monster_msg("%^s mumbles.", m_name);
- }
- else
- {
- monster_msg("%^s concentrates on %s wounds.", m_name, m_poss);
- }
-
- /* Heal some */
- m_ptr->hp += (rlev * 6);
-
- /* Fully healed */
- if (m_ptr->hp >= m_ptr->maxhp)
- {
- /* Fully healed */
- m_ptr->hp = m_ptr->maxhp;
-
- /* Message */
- if (seen)
- {
- monster_msg("%^s looks completely healed!", m_name);
- }
- else
- {
- monster_msg("%^s sounds completely healed!", m_name);
- }
- }
-
- /* Partially healed */
- else
- {
- /* Message */
- if (seen)
- {
- monster_msg("%^s looks healthier.", m_name);
- }
- else
- {
- monster_msg("%^s sounds healthier.", m_name);
- }
- }
-
- /* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
-
- /* Cancel fear */
- if (m_ptr->monfear)
- {
- /* Cancel fear */
- m_ptr->monfear = 0;
-
- /* Message */
- if (see_m) monster_msg("%^s recovers %s courage.", m_name, m_poss);
- }
-
- break;
- }
-
- /* RF6_S_ANIMALS */
- case 160 + 3:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons some animals!", m_name);
- for (k = 0; k < 4; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_ANIMAL);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_BLINK */
- case 160 + 4:
- {
- if (disturb_other) disturb(1, 0);
- if (see_m) monster_msg("%^s blinks away.", m_name);
- teleport_away(m_idx, 10);
- break;
- }
-
- /* RF6_TPORT */
- case 160 + 5:
- {
- if (dungeon_flags2 & DF2_NO_TELEPORT) break; /* No teleport on special levels */
- else
- {
- if (disturb_other) disturb(1, 0);
- if (see_m) monster_msg("%^s teleports away.", m_name);
- teleport_away(m_idx, MAX_SIGHT * 2 + 5);
- break;
- }
- }
-
- /* RF6_TELE_TO */
- case 160 + 6:
- {
- /* Not implemented */
- break;
- }
-
- /* RF6_TELE_AWAY */
- case 160 + 7:
- {
- if (dungeon_flags2 & DF2_NO_TELEPORT) break;
-
- if (!direct) break;
- else
- {
- bool_ resists_tele = FALSE;
- if (disturb_other) disturb(1, 0);
- monster_msg("%^s teleports %s away.", m_name, t_name);
-
-
- if (tr_ptr->flags3 & (RF3_RES_TELE))
- {
- if (tr_ptr->flags1 & (RF1_UNIQUE))
- {
- if (see_t)
- {
- tr_ptr->r_flags3 |= RF3_RES_TELE;
- monster_msg("%^s is unaffected!", t_name);
- }
- resists_tele = TRUE;
- }
- else if (t_ptr->level > randint(100))
- {
- if (see_t)
- {
- tr_ptr->r_flags3 |= RF3_RES_TELE;
- monster_msg("%^s resists!", t_name);
- }
- resists_tele = TRUE;
- }
- }
-
- if (!resists_tele)
- {
- teleport_away(t_idx, MAX_SIGHT * 2 + 5);
- }
- }
-
- break;
- }
-
- /* RF6_TELE_LEVEL */
- case 160 + 8:
- {
- /* Not implemented */
- break;
- }
-
- /* RF6_DARKNESS */
- case 160 + 9:
- {
- if (!direct) break;
- if (disturb_other) disturb(1, 0);
- if (blind) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s gestures in shadow.", m_name);
- if (seen)
- monster_msg("%^s is surrounded by darkness.", t_name);
- (void)project(m_idx, 3, y, x, 0, GF_DARK_WEAK, PROJECT_GRID | PROJECT_KILL);
- /* Lite up the room */
- unlite_room(y, x);
- break;
- }
-
- /* RF6_TRAPS */
- case 160 + 10:
- {
- /* Not implemented */
- break;
- }
-
- /* RF6_FORGET */
- case 160 + 11:
- {
- /* Not implemented */
- break;
- }
-
- /* RF6_ANIM_DEAD */
- case 160 + 12:
- {
- break;
- }
-
- /* RF6_S_BUG */
- case 160 + 13:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically codes some software bugs.", m_name);
- for (k = 0; k < 6; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_BUG, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_BUG);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_RNG */
- case 160 + 14:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically codes some RNGs.", m_name);
- for (k = 0; k < 6; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_RNG, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_RNG);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
- break;
- }
-
-
- /* RF6_S_THUNDERLORD */
- case 160 + 15:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons a Thunderlord!", m_name);
- for (k = 0; k < 1; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_THUNDERLORD, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_THUNDERLORD);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
- break;
- }
-
- /* RF6_SUMMON_KIN */
- case 160 + 16:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons %s %s.",
- m_name, m_poss,
- ((r_ptr->flags1) & RF1_UNIQUE ?
- "minions" : "kin"));
- summon_kin_type = r_ptr->d_char; /* Big hack */
- for (k = 0; k < 6; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_KIN, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_KIN);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
-
-
- break;
- }
-
- /* RF6_S_HI_DEMON */
- case 160 + 17:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons greater demons!", m_name);
- if (blind && count) monster_msg("You hear heavy steps nearby.");
- if (friendly)
- summon_specific_friendly(y, x, rlev, SUMMON_HI_DEMON, TRUE);
- else
- summon_cyber();
- break;
- }
-
- /* RF6_S_MONSTER */
- case 160 + 18:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons help!", m_name);
- for (k = 0; k < 1; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, 0);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_MONSTERS */
- case 160 + 19:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons monsters!", m_name);
- for (k = 0; k < 8; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, 0);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_ANT */
- case 160 + 20:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons ants.", m_name);
- for (k = 0; k < 6; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_ANT, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_ANT);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_SPIDER */
- case 160 + 21:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons spiders.", m_name);
- for (k = 0; k < 6; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_SPIDER, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_SPIDER);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_HOUND */
- case 160 + 22:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons hounds.", m_name);
- for (k = 0; k < 6; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HOUND, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HOUND);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_HYDRA */
- case 160 + 23:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons hydras.", m_name);
- for (k = 0; k < 6; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HYDRA, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HYDRA);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_ANGEL */
- case 160 + 24:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons an angel!", m_name);
- for (k = 0; k < 1; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_ANGEL, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_ANGEL);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_DEMON */
- case 160 + 25:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons a demon!", m_name);
- for (k = 0; k < 1; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_DEMON, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_DEMON);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_UNDEAD */
- case 160 + 26:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons an undead adversary!", m_name);
- for (k = 0; k < 1; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_UNDEAD, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_UNDEAD);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_DRAGON */
- case 160 + 27:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons a dragon!", m_name);
- for (k = 0; k < 1; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_DRAGON, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_DRAGON);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_HI_UNDEAD */
- case 160 + 28:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons greater undead!", m_name);
- for (k = 0; k < 8; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HI_UNDEAD_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HI_UNDEAD);
- }
- if (blind && count)
- {
- monster_msg("You hear many creepy things appear nearby.");
- }
- break;
- }
-
- /* RF6_S_HI_DRAGON */
- case 160 + 29:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons ancient dragons!", m_name);
- for (k = 0; k < 8; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HI_DRAGON_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HI_DRAGON);
- }
- if (blind && count)
- {
- monster_msg("You hear many powerful things appear nearby.");
- }
- break;
- }
-
- /* RF6_S_WRAITH */
- case 160 + 30:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons a wraith!", m_name);
-
-
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_WRAITH);
- }
-
- if (blind && count)
- {
- monster_msg("You hear immortal beings appear nearby.");
- }
- break;
- }
-
- /* RF6_S_UNIQUE */
- case 160 + 31:
- {
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons special opponents!", m_name);
- for (k = 0; k < 8; k++)
- {
- if (!friendly)
- count += summon_specific(y, x, rlev, SUMMON_UNIQUE);
- }
- for (k = 0; k < 8; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HI_UNDEAD_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HI_UNDEAD);
- }
- if (blind && count)
- {
- monster_msg("You hear many powerful things appear nearby.");
- }
- break;
- }
- }
-
- if (wake_up)
- {
- t_ptr->csleep = 0;
- }
-
-
- /* Remember what the monster did, if we saw it */
- if (seen)
- {
- /* Inate spell */
- if (thrown_spell < 32*4)
- {
- r_ptr->r_flags4 |= (1L << (thrown_spell - 32 * 3));
- if (r_ptr->r_cast_inate < MAX_UCHAR) r_ptr->r_cast_inate++;
- }
-
- /* Bolt or Ball */
- else if (thrown_spell < 32*5)
- {
- r_ptr->r_flags5 |= (1L << (thrown_spell - 32 * 4));
- if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++;
- }
-
- /* Special spell */
- else if (thrown_spell < 32*6)
- {
- r_ptr->r_flags6 |= (1L << (thrown_spell - 32 * 5));
- if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++;
- }
- }
-
- /* Always take note of monsters that kill you ---
- * even accidentally */
- if (death && (r_ptr->r_deaths < MAX_SHORT))
- {
- r_ptr->r_deaths++;
- }
-
- /* A spell was cast */
- return (TRUE);
- }
-
- /* No enemy found */
- return (FALSE);
-}
-
-
-void curse_equipment(int chance, int heavy_chance)
-{
- bool_ changed = FALSE;
- u32b o1, o2, o3, o4, esp, o5;
- object_type * o_ptr =
- &p_ptr->inventory[rand_range(INVEN_WIELD, INVEN_TOTAL - 1)];
-
- if (randint(100) > chance) return;
-
- if (!(o_ptr->k_idx)) return;
-
- object_flags(o_ptr, &o1, &o2, &o3, &o4, &o5, &esp);
-
-
- /* Extra, biased saving throw for blessed items */
- if ((o3 & (TR3_BLESSED)) && (randint(888) > chance))
- {
- char o_name[256];
- object_desc(o_name, o_ptr, FALSE, 0);
- msg_format("Your %s resist%s cursing!", o_name,
- ((o_ptr->number > 1) ? "" : "s"));
- /* Hmmm -- can we wear multiple items? If not, this is unnecessary */
- return;
- }
-
- if ((randint(100) <= heavy_chance) &&
- (o_ptr->name1 || o_ptr->name2 || o_ptr->art_name))
- {
- if (!(o3 & TR3_HEAVY_CURSE))
- changed = TRUE;
- o_ptr->art_flags3 |= TR3_HEAVY_CURSE;
- o_ptr->art_flags3 |= TR3_CURSED;
- o_ptr->ident |= IDENT_CURSED;
- }
- else
- {
- if (!(o_ptr->ident & (IDENT_CURSED)))
- changed = TRUE;
- o_ptr->art_flags3 |= TR3_CURSED;
- o_ptr->ident |= IDENT_CURSED;
- }
-
- if (changed)
- {
- msg_print("There is a malignant black aura surrounding you...");
- if (o_ptr->note)
- {
- if (streq(quark_str(o_ptr->note), "uncursed"))
- {
- o_ptr->note = 0;
- }
- }
- }
-}
-
-
-void curse_equipment_dg(int chance, int heavy_chance)
-{
- bool_ changed = FALSE;
- u32b o1, o2, o3, o4, esp, o5;
- object_type * o_ptr =
- &p_ptr->inventory[rand_range(INVEN_WIELD, INVEN_TOTAL - 1)];
-
- if (randint(100) > chance) return;
-
- if (!(o_ptr->k_idx)) return;
-
- object_flags(o_ptr, &o1, &o2, &o3, &o4, &o5, &esp);
-
-
- /* Extra, biased saving throw for blessed items */
- if ((o3 & (TR3_BLESSED)) && (randint(888) > chance))
- {
- char o_name[256];
- object_desc(o_name, o_ptr, FALSE, 0);
- msg_format("Your %s resist%s cursing!", o_name,
- ((o_ptr->number > 1) ? "" : "s"));
- /* Hmmm -- can we wear multiple items? If not, this is unnecessary */
- /* DG -- Yes we can, in the quiver */
- return;
- }
-
- if ((randint(100) <= heavy_chance) &&
- (o_ptr->name1 || o_ptr->name2 || o_ptr->art_name))
- {
- if (!(o3 & TR3_HEAVY_CURSE))
- changed = TRUE;
- o_ptr->art_flags3 |= TR3_HEAVY_CURSE;
- o_ptr->art_flags3 |= TR3_CURSED;
- o_ptr->art_flags4 |= TR4_DG_CURSE;
- o_ptr->ident |= IDENT_CURSED;
- }
- else
- {
- if (!(o_ptr->ident & (IDENT_CURSED)))
- changed = TRUE;
- o_ptr->art_flags3 |= TR3_CURSED;
- o_ptr->art_flags4 |= TR4_DG_CURSE;
- o_ptr->ident |= IDENT_CURSED;
- }
-
- if (changed)
- {
- msg_print("There is a malignant black aura surrounding you...");
- if (o_ptr->note)
- {
- if (streq(quark_str(o_ptr->note), "uncursed"))
- {
- o_ptr->note = 0;
- }
- }
- }
-}
-
-
-/*
- * Creatures can cast spells, shoot missiles, and breathe.
- *
- * Returns "TRUE" if a spell (or whatever) was (successfully) cast.
- *
- * XXX XXX XXX This function could use some work, but remember to
- * keep it as optimized as possible, while retaining generic code.
- *
- * Verify the various "blind-ness" checks in the code.
- *
- * XXX XXX XXX Note that several effects should really not be "seen"
- * if the player is blind. See also "effects.c" for other "mistakes".
- *
- * Perhaps monsters should breathe at locations *near* the player,
- * since this would allow them to inflict "partial" damage.
- *
- * Perhaps smart monsters should decline to use "bolt" spells if
- * there is a monster in the way, unless they wish to kill it.
- *
- * Note that, to allow the use of the "track_target" option at some
- * later time, certain non-optimal things are done in the code below,
- * including explicit checks against the "direct" variable, which is
- * currently always true by the time it is checked, but which should
- * really be set according to an explicit "projectable()" test, and
- * the use of generic "x,y" locations instead of the player location,
- * with those values being initialized with the player location.
- *
- * It will not be possible to "correctly" handle the case in which a
- * monster attempts to attack a location which is thought to contain
- * the player, but which in fact is nowhere near the player, since this
- * might induce all sorts of messages about the attack itself, and about
- * the effects of the attack, which the player might or might not be in
- * a position to observe. Thus, for simplicity, it is probably best to
- * only allow "faulty" attacks by a monster if one of the important grids
- * (probably the initial or final grid) is in fact in view of the player.
- * It may be necessary to actually prevent spell attacks except when the
- * monster actually has line of sight to the player. Note that a monster
- * could be left in a bizarre situation after the player ducked behind a
- * pillar and then teleported away, for example.
- *
- * Note that certain spell attacks do not use the "project()" function
- * but "simulate" it via the "direct" variable, which is always at least
- * as restrictive as the "project()" function. This is necessary to
- * prevent "blindness" attacks and such from bending around walls, etc,
- * and to allow the use of the "track_target" option in the future.
- *
- * Note that this function attempts to optimize the use of spells for the
- * cases in which the monster has no spells, or has spells but cannot use
- * them, or has spells but they will have no "useful" effect. Note that
- * this function has been an efficiency bottleneck in the past.
- *
- * Note the special "MFLAG_NICE" flag, which prevents a monster from using
- * any spell attacks until the player has had a single chance to move.
- */
-bool_ make_attack_spell(int m_idx)
-{
- int k, chance, thrown_spell, rlev, failrate;
- byte spell[96], num = 0;
- u32b f4, f5, f6;
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
- char m_name[80];
- bool_ no_inate = FALSE;
- int x, y;
-
- /* Summon count */
- int count = 0;
-
- /* Extract the blind-ness */
- bool_ blind = (p_ptr->blind ? TRUE : FALSE);
-
- /* Extract the "see-able-ness" */
- bool_ seen = (!blind && m_ptr->ml);
-
- /* Assume "normal" target */
- bool_ normal = TRUE;
-
- /* Assume "projectable" */
- bool_ direct = TRUE;
-
- /* Target location */
- if (m_ptr->target > -1)
- {
- if (!m_ptr->target)
- {
- y = p_ptr->py;
- x = p_ptr->px;
- }
- else
- {
- return (FALSE);
- }
- }
- else return FALSE;
-
- /* Cannot cast spells when confused */
- if (m_ptr->confused) return (FALSE);
-
- /* Cannot cast spells when nice */
- if (m_ptr->mflag & (MFLAG_NICE)) return (FALSE);
- if (is_friend(m_ptr) >= 0) return (FALSE);
-
- /* Cannot attack the player if mortal and player fated to never die by the ... */
- if ((r_ptr->flags7 & RF7_MORTAL) && (p_ptr->no_mortal)) return (FALSE);
-
- /* Hack -- Extract the spell probability */
- chance = (r_ptr->freq_inate + r_ptr->freq_spell) / 2;
-
- /* Not allowed to cast spells */
- if (!chance) return (FALSE);
-
- if (stupid_monsters)
- {
- /* Only do spells occasionally */
- if (rand_int(100) >= chance) return (FALSE);
- }
- else
- {
- if (rand_int(100) >= chance) return (FALSE);
-
- /* Sometimes forbid inate attacks (breaths) */
- if (rand_int(100) >= (chance * 2)) no_inate = TRUE;
- }
-
- /* XXX XXX XXX Handle "track_target" option (?) */
-
-
- /* Hack -- require projectable player */
- if (normal)
- {
- /* Check range */
- if (m_ptr->cdis > MAX_RANGE) return (FALSE);
-
- /* Check path */
- if (!projectable(m_ptr->fy, m_ptr->fx, y, x)) return (FALSE);
- }
-
- /* Extract the monster level */
- rlev = ((m_ptr->level >= 1) ? m_ptr->level : 1);
-
- /* Extract the racial spell flags */
- f4 = r_ptr->flags4;
- f5 = r_ptr->flags5;
- f6 = r_ptr->flags6;
-
- if (!stupid_monsters)
- {
- /* Forbid inate attacks sometimes */
- if (no_inate) f4 = 0L;
- }
-
- /* Hack -- allow "desperate" spells */
- if ((r_ptr->flags2 & (RF2_SMART)) &&
- (m_ptr->hp < m_ptr->maxhp / 10) &&
- (rand_int(100) < 50))
- {
- /* Require intelligent spells */
- f4 &= (RF4_INT_MASK);
- f5 &= (RF5_INT_MASK);
- f6 &= (RF6_INT_MASK);
-
- /* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
- }
-
- /* Remove the "ineffective" spells */
- remove_bad_spells(m_idx, &f4, &f5, &f6);
-
- /* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
-
- if (!stupid_monsters)
- {
- /* Check for a clean bolt shot */
- if ((f4&(RF4_BOLT_MASK) || f5 & (RF5_BOLT_MASK) ||
- f6&(RF6_BOLT_MASK)) &&
- !(r_ptr->flags2 & (RF2_STUPID)) &&
- !clean_shot(m_ptr->fy, m_ptr->fx, y, x))
- {
- /* Remove spells that will only hurt friends */
- f4 &= ~(RF4_BOLT_MASK);
- f5 &= ~(RF5_BOLT_MASK);
- f6 &= ~(RF6_BOLT_MASK);
- }
-
- /* Check for a possible summon */
- if ((f4 & (RF4_SUMMON_MASK) || f5 & (RF5_SUMMON_MASK) ||
- f6 & (RF6_SUMMON_MASK)) &&
- !(r_ptr->flags2 & (RF2_STUPID)) &&
- !(summon_possible(y, x)))
- {
- /* Remove summoning spells */
- f4 &= ~(RF4_SUMMON_MASK);
- f5 &= ~(RF5_SUMMON_MASK);
- f6 &= ~(RF6_SUMMON_MASK);
- }
-
- /* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
- }
-
- /* Extract the "inate" spells */
- for (k = 0; k < 32; k++)
- {
- if (f4 & (1L << k)) spell[num++] = k + 32 * 3;
- }
-
- /* Extract the "normal" spells */
- for (k = 0; k < 32; k++)
- {
- if (f5 & (1L << k)) spell[num++] = k + 32 * 4;
- }
-
- /* Extract the "bizarre" spells */
- for (k = 0; k < 32; k++)
- {
- if (f6 & (1L << k)) spell[num++] = k + 32 * 5;
- }
-
- /* No spells left */
- if (!num) return (FALSE);
-
- /* Stop if player is dead or gone */
- if (!alive || death) return (FALSE);
-
- /* Stop if player is leaving */
- if (p_ptr->leaving) return (FALSE);
-
- /* Get the monster name (or "it") */
- monster_desc(m_name, m_ptr, 0x00);
-
- if (stupid_monsters)
- {
- /* Choose a spell to cast */
- thrown_spell = spell[rand_int(num)];
- }
- else
- {
- thrown_spell = choose_attack_spell(m_idx, spell, num);
-
- /* Abort if no spell was chosen */
- if (!thrown_spell) return (FALSE);
-
- /* Calculate spell failure rate */
- failrate = 25 - (rlev + 3) / 4;
-
- /* Hack -- Stupid monsters will never fail (for jellies and such) */
- if (r_ptr->flags2 & (RF2_STUPID)) failrate = 0;
-
- /* Check for spell failure (inate attacks never fail) */
- if ((thrown_spell >= 128) && (rand_int(100) < failrate))
- {
- /* Message */
- msg_format("%^s tries to cast a spell, but fails.", m_name);
-
- return (TRUE);
- }
- }
-
- /* Can the player disrupt its puny attempts? */
- if ((p_ptr->antimagic_dis >= m_ptr->cdis) && (magik(p_ptr->antimagic)) && (thrown_spell >= 128))
- {
- char m_poss[80];
-
- /* Get monster's possessive noun form ("the Illusionist's") */
- monster_desc(m_poss, m_ptr, 0x06);
-
- msg_format("Your anti-magic field disrupts %s spell.", m_poss);
- }
- else
- {
- char m_poss[80];
- char ddesc[80];
-
- /* Get the monster possessive ("his"/"her"/"its") */
- monster_desc(m_poss, m_ptr, 0x22);
-
- /* Hack -- Get the "died from" name */
- monster_desc(ddesc, m_ptr, 0x88);
-
- /* Cast the spell. */
- switch (thrown_spell)
- {
- /* RF4_SHRIEK */
- case 96 + 0:
- {
- if (!direct) break;
- disturb(1, 0);
- msg_format("%^s makes a high pitched shriek.", m_name);
- aggravate_monsters(m_idx);
- break;
- }
-
- /* RF4_MULTIPLY */
- case 96 + 1:
- {
- break;
- }
-
- /* RF4_S_ANIMAL */
- case 96 + 2:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons an animal!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_ANIMAL);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
- break;
- }
-
- /* RF4_ROCKET */
- case 96 + 3:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s shoots something.", m_name);
- else msg_format("%^s fires a rocket.", m_name);
- breath(m_idx, GF_ROCKET,
- ((m_ptr->hp / 4) > 800 ? 800 : (m_ptr->hp / 4)), 2);
- update_smart_learn(m_idx, DRS_SHARD);
- break;
- }
-
- /* RF4_ARROW_1 */
- case 96 + 4:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s makes a strange noise.", m_name);
- else msg_format("%^s fires an arrow.", m_name);
- bolt(m_idx, GF_ARROW, damroll(1, 6));
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF4_ARROW_2 */
- case 96 + 5:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s makes a strange noise.", m_name);
- else msg_format("%^s fires an arrow!", m_name);
- bolt(m_idx, GF_ARROW, damroll(3, 6));
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF4_ARROW_3 */
- case 96 + 6:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s makes a strange noise.", m_name);
- else msg_format("%^s fires a missile.", m_name);
- bolt(m_idx, GF_ARROW, damroll(5, 6));
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF4_ARROW_4 */
- case 96 + 7:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s makes a strange noise.", m_name);
- else msg_format("%^s fires a missile!", m_name);
- bolt(m_idx, GF_ARROW, damroll(7, 6));
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF4_BR_ACID */
- case 96 + 8:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes acid.", m_name);
- breath(m_idx, GF_ACID,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_ACID);
- break;
- }
-
- /* RF4_BR_ELEC */
- case 96 + 9:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes lightning.", m_name);
- breath(m_idx, GF_ELEC,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_ELEC);
- break;
- }
-
- /* RF4_BR_FIRE */
- case 96 + 10:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes fire.", m_name);
- breath(m_idx, GF_FIRE,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_FIRE);
- break;
- }
-
- /* RF4_BR_COLD */
- case 96 + 11:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes frost.", m_name);
- breath(m_idx, GF_COLD,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_COLD);
- break;
- }
-
- /* RF4_BR_POIS */
- case 96 + 12:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes gas.", m_name);
- breath(m_idx, GF_POIS,
- ((m_ptr->hp / 3) > 800 ? 800 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_POIS);
- break;
- }
-
-
- /* RF4_BR_NETH */
- case 96 + 13:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes nether.", m_name);
- breath(m_idx, GF_NETHER,
- ((m_ptr->hp / 6) > 550 ? 550 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_NETH);
- break;
- }
-
- /* RF4_BR_LITE */
- case 96 + 14:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes light.", m_name);
- breath(m_idx, GF_LITE,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_LITE);
- break;
- }
-
- /* RF4_BR_DARK */
- case 96 + 15:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes darkness.", m_name);
- breath(m_idx, GF_DARK,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_DARK);
- break;
- }
-
- /* RF4_BR_CONF */
- case 96 + 16:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes confusion.", m_name);
- breath(m_idx, GF_CONFUSION,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_CONF);
- break;
- }
-
- /* RF4_BR_SOUN */
- case 96 + 17:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes sound.", m_name);
- breath(m_idx, GF_SOUND,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_SOUND);
- break;
- }
-
- /* RF4_BR_CHAO */
- case 96 + 18:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes chaos.", m_name);
- breath(m_idx, GF_CHAOS,
- ((m_ptr->hp / 6) > 600 ? 600 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_CHAOS);
- break;
- }
-
- /* RF4_BR_DISE */
- case 96 + 19:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes disenchantment.", m_name);
- breath(m_idx, GF_DISENCHANT,
- ((m_ptr->hp / 6) > 500 ? 500 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_DISEN);
- break;
- }
-
- /* RF4_BR_NEXU */
- case 96 + 20:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes nexus.", m_name);
- breath(m_idx, GF_NEXUS,
- ((m_ptr->hp / 3) > 250 ? 250 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_NEXUS);
- break;
- }
-
- /* RF4_BR_TIME */
- case 96 + 21:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes time.", m_name);
- breath(m_idx, GF_TIME,
- ((m_ptr->hp / 3) > 150 ? 150 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_INER */
- case 96 + 22:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes inertia.", m_name);
- breath(m_idx, GF_INERTIA,
- ((m_ptr->hp / 6) > 200 ? 200 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_GRAV */
- case 96 + 23:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes gravity.", m_name);
- breath(m_idx, GF_GRAVITY,
- ((m_ptr->hp / 3) > 200 ? 200 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BR_SHAR */
- case 96 + 24:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes shards.", m_name);
- breath(m_idx, GF_SHARDS,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_SHARD);
- break;
- }
-
- /* RF4_BR_PLAS */
- case 96 + 25:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes plasma.", m_name);
- breath(m_idx, GF_PLASMA,
- ((m_ptr->hp / 6) > 150 ? 150 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_WALL */
- case 96 + 26:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes force.", m_name);
- breath(m_idx, GF_FORCE,
- ((m_ptr->hp / 6) > 200 ? 200 : (m_ptr->hp / 6)), 0);
- break;
- }
-
- /* RF4_BR_MANA */
- case 96 + 27:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes magical energy.", m_name);
- breath(m_idx, GF_MANA,
- ((m_ptr->hp / 3) > 250 ? 250 : (m_ptr->hp / 3)), 0);
- break;
- }
-
- /* RF4_BA_NUKE */
- case 96 + 28:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a ball of radiation.", m_name);
- breath(m_idx, GF_NUKE, (rlev + damroll(10, 6)), 2);
- update_smart_learn(m_idx, DRS_POIS);
- break;
- }
-
- /* RF4_BR_NUKE */
- case 96 + 29:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes toxic waste.", m_name);
- breath(m_idx, GF_NUKE,
- ((m_ptr->hp / 3) > 800 ? 800 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_POIS);
- break;
- }
-
- /* RF4_BA_CHAO */
- case 96 + 30:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles frighteningly.", m_name);
- else msg_format("%^s invokes a raw chaos.", m_name);
- breath(m_idx, GF_CHAOS, (rlev * 2) + damroll(10, 10), 4);
- update_smart_learn(m_idx, DRS_CHAOS);
- break;
- }
-
- /* RF4_BR_DISI -> Disintegration breath! */
- case 96 + 31:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes disintegration.", m_name);
- breath(m_idx, GF_DISINTEGRATE,
- ((m_ptr->hp / 3) > 300 ? 300 : (m_ptr->hp / 3)), 0);
- break;
- }
-
-
-
- /* RF5_BA_ACID */
- case 128 + 0:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts an acid ball.", m_name);
- breath(m_idx, GF_ACID,
- randint(rlev * 3) + 15, 2);
- update_smart_learn(m_idx, DRS_ACID);
- break;
- }
-
- /* RF5_BA_ELEC */
- case 128 + 1:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a lightning ball.", m_name);
- breath(m_idx, GF_ELEC,
- randint(rlev * 3 / 2) + 8, 2);
- update_smart_learn(m_idx, DRS_ELEC);
- break;
- }
-
- /* RF5_BA_FIRE */
- case 128 + 2:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a fire ball.", m_name);
- breath(m_idx, GF_FIRE,
- randint(rlev * 7 / 2) + 10, 2);
- update_smart_learn(m_idx, DRS_FIRE);
- break;
- }
-
- /* RF5_BA_COLD */
- case 128 + 3:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a frost ball.", m_name);
- breath(m_idx, GF_COLD,
- randint(rlev * 3 / 2) + 10, 2);
- update_smart_learn(m_idx, DRS_COLD);
- break;
- }
-
- /* RF5_BA_POIS */
- case 128 + 4:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a stinking cloud.", m_name);
- breath(m_idx, GF_POIS,
- damroll(12, 2), 2);
- update_smart_learn(m_idx, DRS_POIS);
- break;
- }
-
- /* RF5_BA_NETH */
- case 128 + 5:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a nether ball.", m_name);
- breath(m_idx, GF_NETHER,
- (50 + damroll(10, 10) + rlev), 2);
- update_smart_learn(m_idx, DRS_NETH);
- break;
- }
-
- /* RF5_BA_WATE */
- case 128 + 6:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s gestures fluidly.", m_name);
- msg_print("You are engulfed in a whirlpool.");
- breath(m_idx, GF_WATER,
- randint(rlev * 5 / 2) + 50, 4);
- break;
- }
-
- /* RF5_BA_MANA */
- case 128 + 7:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles powerfully.", m_name);
- else msg_format("%^s invokes a mana storm.", m_name);
- breath(m_idx, GF_MANA,
- (rlev * 5) + damroll(10, 10), 4);
- break;
- }
-
- /* RF5_BA_DARK */
- case 128 + 8:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles powerfully.", m_name);
- else msg_format("%^s invokes a darkness storm.", m_name);
- breath(m_idx, GF_DARK,
- (rlev * 5) + damroll(10, 10), 4);
- update_smart_learn(m_idx, DRS_DARK);
- break;
- }
-
- /* RF5_DRAIN_MANA */
- case 128 + 9:
- {
- if (!direct) break;
- if (p_ptr->csp)
- {
- int r1;
-
- /* Disturb if legal */
- disturb(1, 0);
-
- /* Basic message */
- msg_format("%^s draws psychic energy from you!", m_name);
-
- /* Attack power */
- r1 = (randint(rlev) / 2) + 1;
-
- /* Full drain */
- if (r1 >= p_ptr->csp)
- {
- r1 = p_ptr->csp;
- p_ptr->csp = 0;
- p_ptr->csp_frac = 0;
- }
-
- /* Partial drain */
- else
- {
- p_ptr->csp -= r1;
- }
-
- /* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
-
- /* Window stuff */
- p_ptr->window |= (PW_PLAYER);
-
- /* Heal the monster */
- if (m_ptr->hp < m_ptr->maxhp)
- {
- /* Heal */
- m_ptr->hp += (6 * r1);
- if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
-
- /* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
-
- /* Special message */
- if (seen)
- {
- msg_format("%^s appears healthier.", m_name);
- }
- }
- }
- update_smart_learn(m_idx, DRS_MANA);
- break;
- }
-
- /* RF5_MIND_BLAST */
- case 128 + 10:
- {
- if (!direct) break;
- disturb(1, 0);
- if (!seen)
- {
- msg_print("You feel something focusing on your mind.");
- }
- else
- {
- msg_format("%^s gazes deep into your eyes.", m_name);
- }
-
- if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else
- {
- msg_print("Your mind is blasted by psionic energy.");
-
- if (!p_ptr->resist_conf)
- {
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
- }
-
- if ((!p_ptr->resist_chaos) && (randint(3) == 1))
- {
- (void) set_image(p_ptr->image + rand_int(250) + 150);
- }
-
- take_sanity_hit(damroll(8, 8), ddesc);
- }
- break;
- }
-
- /* RF5_BRAIN_SMASH */
- case 128 + 11:
- {
- if (!direct) break;
- disturb(1, 0);
- if (!seen)
- {
- msg_print("You feel something focusing on your mind.");
- }
- else
- {
- msg_format("%^s looks deep into your eyes.", m_name);
- }
-
- if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else
- {
- msg_print("Your mind is blasted by psionic energy.");
- take_sanity_hit(damroll(12, 15), ddesc);
- if (!p_ptr->resist_blind)
- {
- (void)set_blind(p_ptr->blind + 8 + rand_int(8));
- }
- if (!p_ptr->resist_conf)
- {
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
- }
- if (!p_ptr->free_act)
- {
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
- }
- (void)set_slow(p_ptr->slow + rand_int(4) + 4);
-
- while (rand_int(100) > p_ptr->skill_sav)
- (void)do_dec_stat(A_INT, STAT_DEC_NORMAL);
- while (rand_int(100) > p_ptr->skill_sav)
- (void)do_dec_stat(A_WIS, STAT_DEC_NORMAL);
-
- if (!p_ptr->resist_chaos)
- {
- (void) set_image(p_ptr->image + rand_int(250) + 150);
- }
- }
- break;
- }
-
- /* RF5_CAUSE_1 */
- case 128 + 12:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s points at you and curses.", m_name);
- if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else
- {
- curse_equipment(33, 0);
- take_hit(damroll(3, 8), ddesc);
- }
- break;
- }
-
- /* RF5_CAUSE_2 */
- case 128 + 13:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s points at you and curses horribly.", m_name);
- if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else
- {
- curse_equipment(50, 5);
- take_hit(damroll(8, 8), ddesc);
- }
- break;
- }
-
- /* RF5_CAUSE_3 */
- case 128 + 14:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles loudly.", m_name);
- else msg_format("%^s points at you, incanting terribly!", m_name);
- if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else
- {
- curse_equipment(80, 15);
- take_hit(damroll(10, 15), ddesc);
- }
- break;
- }
-
- /* RF5_CAUSE_4 */
- case 128 + 15:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s screams the word 'DIE!'", m_name);
- else msg_format("%^s points at you, screaming the word DIE!", m_name);
- if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else
- {
- take_hit(damroll(15, 15), ddesc);
- (void)set_cut(p_ptr->cut + damroll(10, 10));
- }
- break;
- }
-
- /* RF5_BO_ACID */
- case 128 + 16:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a acid bolt.", m_name);
- bolt(m_idx, GF_ACID, damroll(7, 8) + (rlev / 3));
- update_smart_learn(m_idx, DRS_ACID);
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_BO_ELEC */
- case 128 + 17:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a lightning bolt.", m_name);
- bolt(m_idx, GF_ELEC, damroll(4, 8) + (rlev / 3));
- update_smart_learn(m_idx, DRS_ELEC);
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_BO_FIRE */
- case 128 + 18:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a fire bolt.", m_name);
- bolt(m_idx, GF_FIRE, damroll(9, 8) + (rlev / 3));
- update_smart_learn(m_idx, DRS_FIRE);
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_BO_COLD */
- case 128 + 19:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a frost bolt.", m_name);
- bolt(m_idx, GF_COLD, damroll(6, 8) + (rlev / 3));
- update_smart_learn(m_idx, DRS_COLD);
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_BO_POIS */
- case 128 + 20:
- {
- /* XXX XXX XXX */
- break;
- }
-
- /* RF5_BO_NETH */
- case 128 + 21:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a nether bolt.", m_name);
- bolt(m_idx, GF_NETHER, 30 + damroll(5, 5) + (rlev * 3) / 2);
- update_smart_learn(m_idx, DRS_NETH);
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_BO_WATE */
- case 128 + 22:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a water bolt.", m_name);
- bolt(m_idx, GF_WATER, damroll(10, 10) + (rlev));
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_BO_MANA */
- case 128 + 23:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a mana bolt.", m_name);
- bolt(m_idx, GF_MANA, randint(rlev * 7 / 2) + 50);
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_BO_PLAS */
- case 128 + 24:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a plasma bolt.", m_name);
- bolt(m_idx, GF_PLASMA, 10 + damroll(8, 7) + (rlev));
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_BO_ICEE */
- case 128 + 25:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts an ice bolt.", m_name);
- bolt(m_idx, GF_ICE, damroll(6, 6) + (rlev));
- update_smart_learn(m_idx, DRS_COLD);
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_MISSILE */
- case 128 + 26:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a magic missile.", m_name);
- bolt(m_idx, GF_MISSILE, damroll(2, 6) + (rlev / 3));
- update_smart_learn(m_idx, DRS_REFLECT);
- break;
- }
-
- /* RF5_SCARE */
- case 128 + 27:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles, and you hear scary noises.", m_name);
- else msg_format("%^s casts a fearful illusion.", m_name);
- if (p_ptr->resist_fear)
- {
- msg_print("You refuse to be frightened.");
- }
- else if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You refuse to be frightened.");
- }
- else
- {
- (void)set_afraid(p_ptr->afraid + rand_int(4) + 4);
- }
- update_smart_learn(m_idx, DRS_FEAR);
- break;
- }
-
- /* RF5_BLIND */
- case 128 + 28:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s casts a spell, burning your eyes!", m_name);
- if (p_ptr->resist_blind)
- {
- msg_print("You are unaffected!");
- }
- else if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else
- {
- (void)set_blind(12 + rand_int(4));
- }
- update_smart_learn(m_idx, DRS_BLIND);
- break;
- }
-
- /* RF5_CONF */
- case 128 + 29:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles, and you hear puzzling noises.", m_name);
- else msg_format("%^s creates a mesmerizing illusion.", m_name);
- if (p_ptr->resist_conf)
- {
- msg_print("You disbelieve the feeble spell.");
- }
- else if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You disbelieve the feeble spell.");
- }
- else
- {
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
- }
- update_smart_learn(m_idx, DRS_CONF);
- break;
- }
-
- /* RF5_SLOW */
- case 128 + 30:
- {
- if (!direct) break;
- disturb(1, 0);
- msg_format("%^s drains power from your muscles!", m_name);
- if (p_ptr->free_act)
- {
- msg_print("You are unaffected!");
- }
- else if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else
- {
- (void)set_slow(p_ptr->slow + rand_int(4) + 4);
- }
- update_smart_learn(m_idx, DRS_FREE);
- break;
- }
-
- /* RF5_HOLD */
- case 128 + 31:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s stares deep into your eyes!", m_name);
- if (p_ptr->free_act)
- {
- msg_print("You are unaffected!");
- }
- else if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_format("You resist the effects!");
- }
- else
- {
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
- }
- update_smart_learn(m_idx, DRS_FREE);
- break;
- }
-
-
-
- /* RF6_HASTE */
- case 160 + 0:
- {
- disturb(1, 0);
- if (blind)
- {
- msg_format("%^s mumbles.", m_name);
- }
- else
- {
- msg_format("%^s concentrates on %s body.", m_name, m_poss);
- }
-
- /* Allow quick speed increases to base+10 */
- if (m_ptr->mspeed < m_ptr->speed + 10)
- {
- msg_format("%^s starts moving faster.", m_name);
- m_ptr->mspeed += 10;
- }
-
- /* Allow small speed increases to base+20 */
- else if (m_ptr->mspeed < m_ptr->speed + 20)
- {
- msg_format("%^s starts moving faster.", m_name);
- m_ptr->mspeed += 2;
- }
-
- break;
- }
-
- /* RF6_HAND_DOOM */
- case 160 + 1:
- {
- disturb(1, 0);
- msg_format("%^s invokes the Hand of Doom!", m_name);
- if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_format("You resist the effects!");
- }
- else
- {
- int dummy = (((s32b) ((65 + randint(25)) * (p_ptr->chp))) / 100);
- msg_print("Your feel your life fade away!");
- take_hit(dummy, m_name);
- curse_equipment(100, 20);
-
- if (p_ptr->chp < 1) p_ptr->chp = 1;
- }
- break;
- }
-
- /* RF6_HEAL */
- case 160 + 2:
- {
- disturb(1, 0);
-
- /* Message */
- if (blind)
- {
- msg_format("%^s mumbles.", m_name);
- }
- else
- {
- msg_format("%^s concentrates on %s wounds.", m_name, m_poss);
- }
-
- /* Heal some */
- m_ptr->hp += (rlev * 6);
-
- /* Fully healed */
- if (m_ptr->hp >= m_ptr->maxhp)
- {
- /* Fully healed */
- m_ptr->hp = m_ptr->maxhp;
-
- /* Message */
- if (seen)
- {
- msg_format("%^s looks completely healed!", m_name);
- }
- else
- {
- msg_format("%^s sounds completely healed!", m_name);
- }
- }
-
- /* Partially healed */
- else
- {
- /* Message */
- if (seen)
- {
- msg_format("%^s looks healthier.", m_name);
- }
- else
- {
- msg_format("%^s sounds healthier.", m_name);
- }
- }
-
- /* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
-
- /* Cancel fear */
- if (m_ptr->monfear)
- {
- /* Cancel fear */
- m_ptr->monfear = 0;
-
- /* Message */
- msg_format("%^s recovers %s courage.", m_name, m_poss);
- }
- break;
- }
-
- /* RF6_S_ANIMALS */
- case 160 + 3:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons some animals!", m_name);
- for (k = 0; k < 4; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_ANIMAL);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
- break;
- }
-
- /* RF6_BLINK */
- case 160 + 4:
- {
- disturb(1, 0);
- msg_format("%^s blinks away.", m_name);
- teleport_away(m_idx, 10);
- break;
- }
-
- /* RF6_TPORT */
- case 160 + 5:
- {
- disturb(1, 0);
- msg_format("%^s teleports away.", m_name);
- teleport_away(m_idx, MAX_SIGHT * 2 + 5);
- break;
- }
-
- /* RF6_TELE_TO */
- case 160 + 6:
- {
- if (!direct) break;
- disturb(1, 0);
- msg_format("%^s commands you to return.", m_name);
- teleport_player_to(m_ptr->fy, m_ptr->fx);
- break;
- }
-
- /* RF6_TELE_AWAY */
- case 160 + 7:
- {
- if (!direct) break;
- disturb(1, 0);
- msg_format("%^s teleports you away.", m_name);
- teleport_player(100);
- break;
- }
-
- /* RF6_TELE_LEVEL */
- case 160 + 8:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles strangely.", m_name);
- else msg_format("%^s gestures at your feet.", m_name);
- if (p_ptr->resist_nexus)
- {
- msg_print("You are unaffected!");
- }
- else if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else
- {
- teleport_player_level();
- }
- update_smart_learn(m_idx, DRS_NEXUS);
- break;
- }
-
- /* RF6_DARKNESS */
- case 160 + 9:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s gestures in shadow.", m_name);
- (void)unlite_area(0, 3);
- break;
- }
-
- /* RF6_TRAPS */
- case 160 + 10:
- {
- if (!direct) break;
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles, and then cackles evilly.", m_name);
- else msg_format("%^s casts a spell and cackles evilly.", m_name);
- (void)trap_creation();
- break;
- }
-
- /* RF6_FORGET */
- case 160 + 11:
- {
- if (!direct) break;
- disturb(1, 0);
- msg_format("%^s tries to blank your mind.", m_name);
-
- if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You resist the effects!");
- }
- else if (lose_all_info())
- {
- msg_print("Your memories fade away.");
- }
- break;
- }
-
- /* RF6_ANIM_DEAD */
- case 160 + 12:
- break;
-
- /* RF6_S_BUG */
- case 160 + 13:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically codes some software bugs.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_BUG);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_RNG */
- case 160 + 14:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically codes some RNGs.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_RNG);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_THUNDERLORD */
- case 160 + 15:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons a Thunderlord!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_THUNDERLORD);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
- break;
- }
-
- /* RF6_SUMMON_KIN */
- case 160 + 16:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons %s %s.",
- m_name, m_poss,
- ((r_ptr->flags1) & RF1_UNIQUE ?
- "minions" : "kin"));
- summon_kin_type = r_ptr->d_char; /* Big hack */
-
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_KIN);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
-
- break;
- }
-
- /* RF6_S_HI_DEMON */
- case 160 + 17:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons greater demons!", m_name);
- if (blind && count) msg_print("You hear heavy steps nearby.");
- summon_cyber();
- break;
- }
-
- /* RF6_S_MONSTER */
- case 160 + 18:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons help!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, 0);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_MONSTERS */
- case 160 + 19:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons monsters!", m_name);
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, 0);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_ANT */
- case 160 + 20:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons ants.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_ANT);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_SPIDER */
- case 160 + 21:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons spiders.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_SPIDER);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_HOUND */
- case 160 + 22:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons hounds.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_HOUND);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_HYDRA */
- case 160 + 23:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons hydras.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_HYDRA);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_S_ANGEL */
- case 160 + 24:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons an angel!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_ANGEL);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_DEMON */
- case 160 + 25:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons a demon!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_DEMON);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_UNDEAD */
- case 160 + 26:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons an undead adversary!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_UNDEAD);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_DRAGON */
- case 160 + 27:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons a dragon!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_DRAGON);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
- break;
- }
-
- /* RF6_S_HI_UNDEAD */
- case 160 + 28:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons greater undead!", m_name);
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_HI_UNDEAD);
- }
- if (blind && count)
- {
- msg_print("You hear many creepy things appear nearby.");
- }
- break;
- }
-
- /* RF6_S_HI_DRAGON */
- case 160 + 29:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons ancient dragons!", m_name);
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_HI_DRAGON);
- }
- if (blind && count)
- {
- msg_print("You hear many powerful things appear nearby.");
- }
- break;
- }
-
- /* RF6_S_WRAITH */
- case 160 + 30:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons Wraith!", m_name);
-
-
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_WRAITH);
- }
-
- if (blind && count)
- {
- msg_print("You hear immortal beings appear nearby.");
- }
- break;
- }
-
- /* RF6_S_UNIQUE */
- case 160 + 31:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons special opponents!", m_name);
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_UNIQUE);
- }
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_HI_UNDEAD);
- }
- if (blind && count)
- {
- msg_print("You hear many powerful things appear nearby.");
- }
- break;
- }
- }
- }
-
- /* Remember what the monster did to us */
- if (seen)
- {
- /* Inate spell */
- if (thrown_spell < 32*4)
- {
- r_ptr->r_flags4 |= (1L << (thrown_spell - 32 * 3));
- if (r_ptr->r_cast_inate < MAX_UCHAR) r_ptr->r_cast_inate++;
- }
-
- /* Bolt or Ball */
- else if (thrown_spell < 32*5)
- {
- r_ptr->r_flags5 |= (1L << (thrown_spell - 32 * 4));
- if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++;
- }
-
- /* Special spell */
- else if (thrown_spell < 32*6)
- {
- r_ptr->r_flags6 |= (1L << (thrown_spell - 32 * 5));
- if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++;
- }
- }
-
-
- /* Always take note of monsters that kill you */
- if (death && (r_ptr->r_deaths < MAX_SHORT))
- {
- r_ptr->r_deaths++;
- }
-
- /* A spell was cast */
- return (TRUE);
-}
-
-
-/*
- * Returns whether a given monster will try to run from the player.
- *
- * Monsters will attempt to avoid very powerful players. See below.
- *
- * Because this function is called so often, little details are important
- * for efficiency. Like not using "mod" or "div" when possible. And
- * attempting to check the conditions in an optimal order. Note that
- * "(x << 2) == (x * 4)" if "x" has enough bits to hold the result.
- *
- * Note that this function is responsible for about one to five percent
- * of the processor use in normal conditions...
- */
-static int mon_will_run(int m_idx)
-{
- monster_type *m_ptr = &m_list[m_idx];
-
-#ifdef ALLOW_TERROR
-
- u16b p_lev, m_lev;
- u16b p_chp, p_mhp;
- u16b m_chp, m_mhp;
- u32b p_val, m_val;
-
-#endif
-
- /* Keep monsters from running too far away */
- if (m_ptr->cdis > MAX_SIGHT + 5) return (FALSE);
-
- /* Friends don't run away */
- if (is_friend(m_ptr) >= 0) return (FALSE);
-
- /* All "afraid" monsters will run away */
- if (m_ptr->monfear) return (TRUE);
-
-#ifdef ALLOW_TERROR
-
- /* Nearby monsters will not become terrified */
- if (m_ptr->cdis <= 5) return (FALSE);
-
- /* Examine player power (level) */
- p_lev = p_ptr->lev;
-
- /* Examine monster power (level plus morale) */
- m_lev = m_ptr->level + (m_idx & 0x08) + 25;
-
- /* Optimize extreme cases below */
- if (m_lev > p_lev + 4) return (FALSE);
- if (m_lev + 4 <= p_lev) return (TRUE);
-
- /* Examine player health */
- p_chp = p_ptr->chp;
- p_mhp = p_ptr->mhp;
-
- /* Examine monster health */
- m_chp = m_ptr->hp;
- m_mhp = m_ptr->maxhp;
-
- /* Prepare to optimize the calculation */
- p_val = (p_lev * p_mhp) + (p_chp << 2); /* div p_mhp */
- m_val = (m_lev * m_mhp) + (m_chp << 2); /* div m_mhp */
-
- /* Strong players scare strong monsters */
- if (p_val * m_mhp > m_val * p_mhp) return (TRUE);
-
-#endif
-
- /* Assume no terror */
- return (FALSE);
-}
-
-
-
-
-/*
-* Choose the "best" direction for "flowing"
-*
-* Note that ghosts and rock-eaters are never allowed to "flow",
-* since they should move directly towards the player.
-*
-* Prefer "non-diagonal" directions, but twiddle them a little
-* to angle slightly towards the player's actual location.
-*
-* Allow very perceptive monsters to track old "spoor" left by
-* previous locations occupied by the player. This will tend
-* to have monsters end up either near the player or on a grid
-* recently occupied by the player (and left via "teleport").
-*
-* Note that if "smell" is turned on, all monsters get vicious.
-*
-* Also note that teleporting away from a location will cause
-* the monsters who were chasing you to converge on that location
-* as long as you are still near enough to "annoy" them without
-* being close enough to chase directly. I have no idea what will
-* happen if you combine "smell" with low "aaf" values.
-*/
-
-/*
-* Provide a location to flee to, but give the player a wide berth.
-*
-* A monster may wish to flee to a location that is behind the player,
-* but instead of heading directly for it, the monster should "swerve"
-* around the player so that he has a smaller chance of getting hit.
-*/
-static bool_ get_fear_moves_aux(int m_idx, int *yp, int *xp)
-{
- int y, x, y1, x1, fy, fx, gy = 0, gx = 0;
- int when = 0, score = -1;
- int i;
-
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Monster flowing disabled */
- if (!flow_by_sound) return (FALSE);
-
- /* Monster location */
- fy = m_ptr->fy;
- fx = m_ptr->fx;
-
- /* Desired destination */
- y1 = fy - (*yp);
- x1 = fx - (*xp);
-
- /* The player is not currently near the monster grid */
- if (cave[fy][fx].when < cave[p_ptr->py][p_ptr->px].when)
- {
- /* No reason to attempt flowing */
- return (FALSE);
- }
-
- /* Monster is too far away to use flow information */
- if (cave[fy][fx].cost > MONSTER_FLOW_DEPTH) return (FALSE);
- if (cave[fy][fx].cost > r_ptr->aaf) return (FALSE);
-
- /* Check nearby grids, diagonals first */
- for (i = 7; i >= 0; i--)
- {
- int dis, s;
-
- /* Get the location */
- y = fy + ddy_ddd[i];
- x = fx + ddx_ddd[i];
-
- /* Ignore illegal locations */
- if (cave[y][x].when == 0) continue;
-
- /* Ignore ancient locations */
- if (cave[y][x].when < when) continue;
-
- /* Calculate distance of this grid from our destination */
- dis = distance(y, x, y1, x1);
-
- /* Score this grid */
- s = 5000 / (dis + 3) - 500 / (cave[y][x].cost + 1);
-
- /* No negative scores */
- if (s < 0) s = 0;
-
- /* Ignore lower scores */
- if (s < score) continue;
-
- /* Save the score and time */
- when = cave[y][x].when;
- score = s;
-
- /* Save the location */
- gy = y;
- gx = x;
- }
-
- /* No legal move (?) */
- if (!when) return (FALSE);
-
- /* Find deltas */
- (*yp) = fy - gy;
- (*xp) = fx - gx;
-
- /* Success */
- return (TRUE);
-}
-
-
-/*
-* Choose a "safe" location near a monster for it to run toward.
-*
-* A location is "safe" if it can be reached quickly and the player
-* is not able to fire into it (it isn't a "clean shot"). So, this will
-* cause monsters to "duck" behind walls. Hopefully, monsters will also
-* try to run towards corridor openings if they are in a room.
-*
-* This function may take lots of CPU time if lots of monsters are
-* fleeing.
-*
-* Return TRUE if a safe location is available.
-*/
-static bool_ find_safety(int m_idx, int *yp, int *xp)
-{
- monster_type *m_ptr = &m_list[m_idx];
-
- int fy = m_ptr->fy;
- int fx = m_ptr->fx;
-
- int y, x, d, dis;
- int gy = 0, gx = 0, gdis = 0;
-
- /* Start with adjacent locations, spread further */
- for (d = 1; d < 10; d++)
- {
- /* Check nearby locations */
- for (y = fy - d; y <= fy + d; y++)
- {
- for (x = fx - d; x <= fx + d; x++)
- {
- /* Skip illegal locations */
- if (!in_bounds(y, x)) continue;
-
- /* Skip locations in a wall */
- if (!cave_floor_bold(y, x)) continue;
-
- /* Check distance */
- if (distance(y, x, fy, fx) != d) continue;
-
- /* Check for "availability" (if monsters can flow) */
- if (flow_by_sound)
- {
- /* Ignore grids very far from the player */
- if (cave[y][x].when < cave[p_ptr->py][p_ptr->px].when) continue;
-
- /* Ignore too-distant grids */
- if (cave[y][x].cost > cave[fy][fx].cost + 2 * d) continue;
- }
-
- /* Check for absence of shot */
- if (!projectable(y, x, p_ptr->py, p_ptr->px))
- {
- /* Calculate distance from player */
- dis = distance(y, x, p_ptr->py, p_ptr->px);
-
- /* Remember if further than previous */
- if (dis > gdis)
- {
- gy = y;
- gx = x;
- gdis = dis;
- }
- }
- }
- }
-
- /* Check for success */
- if (gdis > 0)
- {
- /* Good location */
- (*yp) = fy - gy;
- (*xp) = fx - gx;
-
- /* Found safe place */
- return (TRUE);
- }
- }
-
- /* No safe place */
- return (FALSE);
-}
-
-
-/*
- * Choose a good hiding place near a monster for it to run toward.
- *
- * Pack monsters will use this to "ambush" the player and lure him out
- * of corridors into open space so they can swarm him.
- *
- * Return TRUE if a good location is available.
- */
-static bool_ find_hiding(int m_idx, int *yp, int *xp)
-{
- monster_type *m_ptr = &m_list[m_idx];
-
- int fy = m_ptr->fy;
- int fx = m_ptr->fx;
-
- int y, x, d, dis;
- int gy = 0, gx = 0, gdis = 999, min;
-
- /* Closest distance to get */
- min = distance(p_ptr->py, p_ptr->px, fy, fx) * 3 / 4 + 2;
-
- /* Start with adjacent locations, spread further */
- for (d = 1; d < 10; d++)
- {
- /* Check nearby locations */
- for (y = fy - d; y <= fy + d; y++)
- {
- for (x = fx - d; x <= fx + d; x++)
- {
- /* Skip illegal locations */
- if (!in_bounds(y, x)) continue;
-
- /* Skip locations in a wall */
- if (!cave_floor_bold(y, x)) continue;
-
- /* Check distance */
- if (distance(y, x, fy, fx) != d) continue;
-
- /* Check for hidden, available grid */
- if (!player_can_see_bold(y, x) && clean_shot(fy, fx, y, x))
- {
- /* Calculate distance from player */
- dis = distance(y, x, p_ptr->py, p_ptr->px);
-
- /* Remember if closer than previous */
- if (dis < gdis && dis >= min)
- {
- gy = y;
- gx = x;
- gdis = dis;
- }
- }
- }
- }
-
- /* Check for success */
- if (gdis < 999)
- {
- /* Good location */
- (*yp) = fy - gy;
- (*xp) = fx - gx;
-
- /* Found good place */
- return (TRUE);
- }
- }
-
- /* No good place */
- return (FALSE);
-}
-
-
-/* Find an appropriate corpse */
-void find_corpse(monster_type *m_ptr, int *y, int *x)
-{
- int k, last = -1;
-
- for (k = 0; k < max_o_idx; k++)
- {
- object_type *o_ptr = &o_list[k];
- monster_race *rt_ptr, *rt2_ptr;
-
- if (!o_ptr->k_idx) continue;
-
- if (o_ptr->tval != TV_CORPSE) continue;
- if ((o_ptr->sval != SV_CORPSE_CORPSE) && (o_ptr->sval != SV_CORPSE_SKELETON)) continue;
-
- rt_ptr = &r_info[o_ptr->pval2];
-
- /* Cannot incarnate into a higher level monster */
- if (rt_ptr->level > m_ptr->level) continue;
-
- /* Must be in LOS */
- if (!los(m_ptr->fy, m_ptr->fx, o_ptr->iy, o_ptr->ix)) continue;
-
- if (last != -1)
- {
- rt2_ptr = &r_info[o_list[last].pval2];
- if (rt_ptr->level > rt2_ptr->level) last = k;
- else continue;
- }
- else
- {
- last = k;
- }
- }
-
- /* Must be ok now */
- if (last != -1)
- {
- *y = o_list[last].iy;
- *x = o_list[last].ix;
- }
-}
-
-/*
- * Choose target
- */
-static void get_target_monster(int m_idx)
-{
- monster_type *m_ptr = &m_list[m_idx];
- int i, t = -1, d = 9999;
-
- /* Process the monsters (backwards) */
- for (i = m_max - 1; i >= 1; i--)
- {
- /* Access the monster */
- monster_type *t_ptr = &m_list[i];
- /* hack should call the function for ego monsters ... but no_target i not meant to be added by ego and it speeds up the code */
- monster_race *rt_ptr = &r_info[t_ptr->r_idx];
- int dd;
-
- /* Ignore "dead" monsters */
- if (!t_ptr->r_idx) continue;
-
- if (m_idx == i) continue;
-
- /* Cannot be targeted */
- if (rt_ptr->flags7 & RF7_NO_TARGET) continue;
-
- if (is_enemy(m_ptr, t_ptr) && (los(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx) &&
- ((dd = distance(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) < d)))
- {
- t = i;
- d = dd;
- }
- }
- /* Hack */
- if ((is_friend(m_ptr) < 0) && los(m_ptr->fy, m_ptr->fx, p_ptr->py, p_ptr->px) && (distance(m_ptr->fy, m_ptr->fx, p_ptr->py, p_ptr->px) < d)) t = 0;
-
- m_ptr->target = t;
-}
-
-/*
- * Choose "logical" directions for monster movement
- */
-static bool_ get_moves(int m_idx, int *mm)
-{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- int y, ay, x, ax;
-
- int move_val = 0;
-
- int y2 = p_ptr->py;
- int x2 = p_ptr->px;
- bool_ done = FALSE;
-
- /* Oups get nearer */
- if ((is_friend(m_ptr) > 0) && (m_ptr->cdis > p_ptr->pet_follow_distance))
- {
- y2 = p_ptr->py;
- x2 = p_ptr->px;
- }
- /* Use the target */
- else if (!m_ptr->target)
- {
- y2 = p_ptr->py;
- x2 = p_ptr->px;
- }
- else if (m_ptr->target > 0)
- {
- y2 = m_list[m_ptr->target].fy;
- x2 = m_list[m_ptr->target].fx;
- }
-
- /* Hack doppleganger confuses monsters(even pets) */
- if (doppleganger)
- {
- if (magik(70))
- {
- y2 = m_list[doppleganger].fy;
- x2 = m_list[doppleganger].fx;
- }
- }
-
- /* A possessor is not interrested in the player, it only wants a corpse */
- if (r_ptr->flags7 & RF7_POSSESSOR)
- {
- find_corpse(m_ptr, &y2, &x2);
- }
-
- /* Let quests redefine AI */
- if (r_ptr->flags7 & RF7_AI_SPECIAL)
- {
- if (process_hooks_ret(HOOK_MONSTER_AI, "dd", "(d)", m_idx))
- {
- y2 = process_hooks_return[0].num;
- x2 = process_hooks_return[1].num;
- }
- }
-
- if (m_idx == p_ptr->control)
- {
- if ((r_ptr->flags7 & RF7_AI_PLAYER) || magik(85))
- {
- if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < 50)
- {
- y2 = m_ptr->fy + ddy[p_ptr->control_dir];
- x2 = m_ptr->fx + ddx[p_ptr->control_dir];
- }
- }
- }
-
- /* Extract the "pseudo-direction" */
- y = m_ptr->fy - y2;
- x = m_ptr->fx - x2;
-
- /* Tease the player */
- if (r_ptr->flags7 & RF7_AI_ANNOY)
- {
- if (distance(m_ptr->fy, m_ptr->fx, y2, x2) < 4)
- {
- y = -y;
- x = -x;
- }
- }
-
- /* Death orbs .. */
- if (r_ptr->flags2 & RF2_DEATH_ORB)
- {
- if (!los(m_ptr->fy, m_ptr->fx, y2, x2))
- {
- return (FALSE);
- }
- }
-
- if (!stupid_monsters && (is_friend(m_ptr) < 0))
- {
- int tx = x2, ty = y2;
-
- /*
- * Animal packs try to get the player out of corridors
- * (...unless they can move through walls -- TY)
- */
- if ((r_ptr->flags1 & RF1_FRIENDS) &&
- (r_ptr->flags3 & RF3_ANIMAL) &&
- !((r_ptr->flags2 & (RF2_PASS_WALL)) ||
- (r_ptr->flags2 & (RF2_KILL_WALL))))
- {
- int i, room = 0;
-
- /* Count room grids next to player */
- for (i = 0; i < 8; i++)
- {
- /* Check grid */
- if (cave[ty + ddy_ddd[i]][tx + ddx_ddd[i]].info & (CAVE_ROOM))
- {
- /* One more room grid */
- room++;
- }
- }
-
- /* Not in a room and strong player */
- if ((room < 8) && (p_ptr->chp > ((p_ptr->mhp * 3) / 4)))
- {
- /* Find hiding place */
- if (find_hiding(m_idx, &y, &x)) done = TRUE;
- }
- }
-
- /* Monster groups try to surround the player */
- if (!done && (r_ptr->flags1 & RF1_FRIENDS))
- {
- int i;
-
- /* Find an empty square near the target to fill */
- for (i = 0; i < 8; i++)
- {
- /* Pick squares near target (semi-randomly) */
- y2 = ty + ddy_ddd[(m_idx + i) & 7];
- x2 = tx + ddx_ddd[(m_idx + i) & 7];
-
- /* Already there? */
- if ((m_ptr->fy == y2) && (m_ptr->fx == x2))
- {
- /* Attack the target */
- y2 = ty;
- x2 = tx;
-
- break;
- }
-
- /* Ignore filled grids */
- if (!cave_empty_bold(y2, x2)) continue;
-
- /* Try to fill this hole */
- break;
- }
-
- /* Extract the new "pseudo-direction" */
- y = m_ptr->fy - y2;
- x = m_ptr->fx - x2;
-
- /* Done */
- done = TRUE;
- }
- }
-
- /* Apply fear if possible and necessary */
- if ((stupid_monsters) || (is_friend(m_ptr) > 0))
- {
- if (mon_will_run(m_idx))
- {
- /* XXX XXX Not very "smart" */
- y = ( -y), x = ( -x);
- }
- }
- else
- {
- if (!done && mon_will_run(m_idx))
- {
- /* Try to find safe place */
- if (!find_safety(m_idx, &y, &x))
- {
- /* This is not a very "smart" method XXX XXX */
- y = ( -y);
- x = ( -x);
- }
- else
- {
- /* Attempt to avoid the player */
- if (flow_by_sound)
- {
- /* Adjust movement */
- (void)get_fear_moves_aux(m_idx, &y, &x);
- }
- }
- }
- }
-
-
- if (!stupid_monsters)
- {
- /* Check for no move */
- if (!x && !y) return (FALSE);
- }
-
- /* Extract the "absolute distances" */
- ax = ABS(x);
- ay = ABS(y);
-
- /* Do something weird */
- if (y < 0) move_val += 8;
- if (x > 0) move_val += 4;
-
- /* Prevent the diamond maneuvre */
- if (ay > (ax << 1))
- {
- move_val++;
- move_val++;
- }
- else if (ax > (ay << 1))
- {
- move_val++;
- }
-
- /* Extract some directions */
- switch (move_val)
- {
- case 0:
- mm[0] = 9;
- if (ay > ax)
- {
- mm[1] = 8;
- mm[2] = 6;
- mm[3] = 7;
- mm[4] = 3;
- }
- else
- {
- mm[1] = 6;
- mm[2] = 8;
- mm[3] = 3;
- mm[4] = 7;
- }
- break;
- case 1:
- case 9:
- mm[0] = 6;
- if (y < 0)
- {
- mm[1] = 3;
- mm[2] = 9;
- mm[3] = 2;
- mm[4] = 8;
- }
- else
- {
- mm[1] = 9;
- mm[2] = 3;
- mm[3] = 8;
- mm[4] = 2;
- }
- break;
- case 2:
- case 6:
- mm[0] = 8;
- if (x < 0)
- {
- mm[1] = 9;
- mm[2] = 7;
- mm[3] = 6;
- mm[4] = 4;
- }
- else
- {
- mm[1] = 7;
- mm[2] = 9;
- mm[3] = 4;
- mm[4] = 6;
- }
- break;
- case 4:
- mm[0] = 7;
- if (ay > ax)
- {
- mm[1] = 8;
- mm[2] = 4;
- mm[3] = 9;
- mm[4] = 1;
- }
- else
- {
- mm[1] = 4;
- mm[2] = 8;
- mm[3] = 1;
- mm[4] = 9;
- }
- break;
- case 5:
- case 13:
- mm[0] = 4;
- if (y < 0)
- {
- mm[1] = 1;
- mm[2] = 7;
- mm[3] = 2;
- mm[4] = 8;
- }
- else
- {
- mm[1] = 7;
- mm[2] = 1;
- mm[3] = 8;
- mm[4] = 2;
- }
- break;
- case 8:
- mm[0] = 3;
- if (ay > ax)
- {
- mm[1] = 2;
- mm[2] = 6;
- mm[3] = 1;
- mm[4] = 9;
- }
- else
- {
- mm[1] = 6;
- mm[2] = 2;
- mm[3] = 9;
- mm[4] = 1;
- }
- break;
- case 10:
- case 14:
- mm[0] = 2;
- if (x < 0)
- {
- mm[1] = 3;
- mm[2] = 1;
- mm[3] = 6;
- mm[4] = 4;
- }
- else
- {
- mm[1] = 1;
- mm[2] = 3;
- mm[3] = 4;
- mm[4] = 6;
- }
- break;
- case 12:
- mm[0] = 1;
- if (ay > ax)
- {
- mm[1] = 2;
- mm[2] = 4;
- mm[3] = 3;
- mm[4] = 7;
- }
- else
- {
- mm[1] = 4;
- mm[2] = 2;
- mm[3] = 7;
- mm[4] = 3;
- }
- break;
- }
-
-
-
- /* Wants to move... */
- return (TRUE);
-}
-
-
-int check_hit2(int power, int level, int ac)
-{
- int i, k;
-
- /* Percentile dice */
- k = rand_int(100);
-
- /* Hack -- Always miss or hit */
- if (k < 10) return (k < 5);
-
- /* Calculate the "attack quality" */
- i = (power + (level * 3));
-
- /* Power and Level compete against Armor */
- if ((i > 0) && (randint(i) > ((ac * 3) / 4))) return (TRUE);
-
- /* Assume miss */
- return (FALSE);
-}
-
-
-/* Monster attacks monster */
-static bool_ monst_attack_monst(int m_idx, int t_idx)
-{
- monster_type *m_ptr = &m_list[m_idx], *t_ptr = &m_list[t_idx];
- monster_race *r_ptr = race_inf(m_ptr);
- monster_race *tr_ptr = race_inf(t_ptr);
- int ap_cnt;
- int ac, rlev, pt;
- char m_name[80], t_name[80];
- char ddesc[80], temp[80];
- bool_ blinked = FALSE, touched = FALSE;
- bool_ explode = FALSE;
- bool_ fear = FALSE;
- byte y_saver = t_ptr->fy;
- byte x_saver = t_ptr->fx;
-
-
- /* Not allowed to attack */
- if (r_ptr->flags1 & RF1_NEVER_BLOW) return FALSE;
- if (tr_ptr->flags7 & RF7_IM_MELEE) return FALSE;
-
- /* Total armor */
- ac = t_ptr->ac;
-
- /* Extract the effective monster level */
- rlev = ((m_ptr->level >= 1) ? m_ptr->level : 1);
-
- /* Get the monster name (or "it") */
- monster_desc(m_name, m_ptr, 0);
-
- /* Get the monster name (or "it") */
- monster_desc(t_name, t_ptr, 0);
-
- /* Get the "died from" information (i.e. "a kobold") */
- monster_desc(ddesc, m_ptr, 0x88);
-
- /* Assume no blink */
- blinked = FALSE;
-
- if (!(m_ptr->ml || t_ptr->ml))
- {
- monster_msg("You hear noise.");
- }
-
- /* Scan through all four blows */
- for (ap_cnt = 0; ap_cnt < 4; ap_cnt++)
- {
- bool_ visible = FALSE;
- bool_ obvious = FALSE;
-
- int power = 0;
- int damage = 0;
-
- cptr act = NULL;
-
- /* Extract the attack infomation */
- int effect = m_ptr->blow[ap_cnt].effect;
- int method = m_ptr->blow[ap_cnt].method;
- int d_dice = m_ptr->blow[ap_cnt].d_dice;
- int d_side = m_ptr->blow[ap_cnt].d_side;
-
- if (t_ptr == m_ptr) /* Paranoia */
- {
- if (wizard)
- monster_msg("Monster attacking self?");
- break;
- }
-
- /* Stop attacking if the target dies! */
- if (t_ptr->fx != x_saver || t_ptr->fy != y_saver)
- break;
-
- /* Hack -- no more attacks */
- if (!method) break;
-
- if (blinked) /* Stop! */
- {
- /* break; */
- }
-
- /* Extract visibility (before blink) */
- if (m_ptr->ml) visible = TRUE;
-
- /* Extract the attack "power" */
- power = get_attack_power(effect);
-
-
- /* Monster hits*/
- if (!effect || check_hit2(power, rlev, ac))
- {
- /* Always disturbing */
- if (disturb_other) disturb(1, 0);
-
- /* Describe the attack method */
- switch (method)
- {
- case RBM_HIT:
- {
- act = "hits %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_TOUCH:
- {
- act = "touches %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_PUNCH:
- {
- act = "punches %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_KICK:
- {
- act = "kicks %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CLAW:
- {
- act = "claws %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_BITE:
- {
- act = "bites %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_STING:
- {
- act = "stings %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_XXX1:
- {
- act = "XXX1's %s.";
- break;
- }
-
- case RBM_BUTT:
- {
- act = "butts %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CRUSH:
- {
- act = "crushes %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_ENGULF:
- {
- act = "engulfs %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CHARGE:
- {
- act = "charges %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_CRAWL:
- {
- act = "crawls on %s.";
- touched = TRUE;
- break;
- }
-
- case RBM_DROOL:
- {
- act = "drools on %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_SPIT:
- {
- act = "spits on %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_EXPLODE:
- {
- act = "explodes.";
- explode = TRUE;
- touched = FALSE;
- break;
- }
-
- case RBM_GAZE:
- {
- act = "gazes at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_WAIL:
- {
- act = "wails at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_SPORE:
- {
- act = "releases spores at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_XXX4:
- {
- act = "projects XXX4's at %s.";
- touched = FALSE;
- break;
- }
-
- case RBM_BEG:
- {
- act = "begs %s for money.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
-
- case RBM_INSULT:
- {
- act = "insults %s.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
-
- case RBM_MOAN:
- {
- act = "moans at %s.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
-
- case RBM_SHOW:
- {
- act = "sings to %s.";
- touched = FALSE;
- t_ptr->csleep = 0;
- break;
- }
- }
-
- /* Message */
- if (act)
- {
- strfmt(temp, act, t_name);
- if (m_ptr->ml || t_ptr->ml)
- monster_msg("%^s %s", m_name, temp);
-
- }
-
- /* Hack -- assume all attacks are obvious */
- obvious = TRUE;
-
- /* Roll out the damage */
- damage = damroll(d_dice, d_side);
-
- /* Hack need more punch against monsters */
- damage *= 3;
-
- pt = GF_MISSILE;
-
- /* Apply appropriate damage */
- switch (effect)
- {
- case 0:
- {
- damage = 0;
- pt = 0;
- break;
- }
-
- case RBE_HURT:
- case RBE_SANITY:
- {
- damage -= (damage * ((ac < 150) ? ac : 150) / 250);
- break;
- }
-
- case RBE_POISON:
- case RBE_DISEASE:
- {
- pt = GF_POIS;
- break;
- }
-
- case RBE_UN_BONUS:
- case RBE_UN_POWER:
- case RBE_ABOMINATION:
- {
- pt = GF_DISENCHANT;
- break;
- }
-
- case RBE_EAT_FOOD:
- case RBE_EAT_LITE:
- {
- pt = damage = 0;
- break;
- }
-
- case RBE_EAT_ITEM:
- case RBE_EAT_GOLD:
- {
- pt = damage = 0;
- if (randint(2) == 1) blinked = TRUE;
- break;
- }
-
- case RBE_ACID:
- {
- pt = GF_ACID;
- break;
- }
-
- case RBE_ELEC:
- {
- pt = GF_ELEC;
- break;
- }
-
- case RBE_FIRE:
- {
- pt = GF_FIRE;
- break;
- }
-
- case RBE_COLD:
- {
- pt = GF_COLD;
- break;
- }
-
- case RBE_BLIND:
- {
- break;
- }
-
- case RBE_HALLU:
- case RBE_CONFUSE:
- {
- pt = GF_CONFUSION;
- break;
- }
-
- case RBE_TERRIFY:
- {
- pt = GF_TURN_ALL;
- break;
- }
-
- case RBE_PARALYZE:
- {
- pt = GF_OLD_SLEEP; /* sort of close... */
- break;
- }
-
- case RBE_LOSE_STR:
- case RBE_LOSE_INT:
- case RBE_LOSE_WIS:
- case RBE_LOSE_DEX:
- case RBE_LOSE_CON:
- case RBE_LOSE_CHR:
- case RBE_LOSE_ALL:
- case RBE_PARASITE:
- {
- break;
- }
- case RBE_SHATTER:
- {
- if (damage > 23)
- {
- /* Prevent destruction of quest levels and town */
- if (!is_quest(dun_level) && dun_level)
- earthquake(m_ptr->fy, m_ptr->fx, 8);
- }
- break;
- }
- case RBE_EXP_10:
- case RBE_EXP_20:
- case RBE_EXP_40:
- case RBE_EXP_80:
- {
- pt = GF_NETHER;
- break;
- }
- case RBE_TIME:
- {
- pt = GF_TIME;
- break;
- }
- default:
- {
- pt = 0;
- break;
- }
- }
-
- if (pt)
- {
- /* Do damage if not exploding */
- if (!explode)
- {
- project(m_idx, 0, t_ptr->fy, t_ptr->fx,
- (pt == GF_OLD_SLEEP ? m_ptr->level : damage), pt, PROJECT_KILL | PROJECT_STOP);
- }
-
- if (touched)
- {
- /* Aura fire */
- if ((tr_ptr->flags2 & RF2_AURA_FIRE) &&
- !(r_ptr->flags3 & RF3_IM_FIRE))
- {
- if (m_ptr->ml || t_ptr->ml)
- {
- blinked = FALSE;
- monster_msg("%^s is suddenly very hot!", m_name);
- if (t_ptr->ml)
- tr_ptr->r_flags2 |= RF2_AURA_FIRE;
- }
- project(t_idx, 0, m_ptr->fy, m_ptr->fx,
- damroll (1 + ((t_ptr->level) / 26),
- 1 + ((t_ptr->level) / 17)),
- GF_FIRE, PROJECT_KILL | PROJECT_STOP);
- }
-
- /* Aura elec */
- if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) && !(r_ptr->flags3 & (RF3_IM_ELEC)))
- {
- if (m_ptr->ml || t_ptr->ml)
- {
- blinked = FALSE;
- monster_msg("%^s gets zapped!", m_name);
- if (t_ptr->ml)
- tr_ptr->r_flags2 |= RF2_AURA_ELEC;
- }
- project(t_idx, 0, m_ptr->fy, m_ptr->fx,
- damroll (1 + ((t_ptr->level) / 26),
- 1 + ((t_ptr->level) / 17)),
- GF_ELEC, PROJECT_KILL | PROJECT_STOP);
- }
-
- }
- }
- }
-
- /* Monster missed player */
- else
- {
- /* Analyze failed attacks */
- switch (method)
- {
- case RBM_HIT:
- case RBM_TOUCH:
- case RBM_PUNCH:
- case RBM_KICK:
- case RBM_CLAW:
- case RBM_BITE:
- case RBM_STING:
- case RBM_XXX1:
- case RBM_BUTT:
- case RBM_CRUSH:
- case RBM_ENGULF:
- case RBM_CHARGE:
- {
- /* Visible monsters */
- if (m_ptr->ml)
- {
- /* Disturbing */
- disturb(1, 0);
-
- /* Message */
- monster_msg("%^s misses %s.", m_name, t_name);
- }
-
- break;
- }
- }
- }
-
-
- /* Analyze "visible" monsters only */
- if (visible)
- {
- /* Count "obvious" attacks (and ones that cause damage) */
- if (obvious || damage || (r_ptr->r_blows[ap_cnt] > 10))
- {
- /* Count attacks of this type */
- if (r_ptr->r_blows[ap_cnt] < MAX_UCHAR)
- {
- r_ptr->r_blows[ap_cnt]++;
- }
- }
- }
- }
-
- if (explode)
- {
- sound(SOUND_EXPLODE);
- mon_take_hit_mon(m_idx, m_idx, m_ptr->hp + 1, &fear, " explodes into tiny shreds.");
-
- blinked = FALSE;
- }
-
-
- /* Blink away */
- if (blinked)
- {
- if (m_ptr->ml)
- {
- monster_msg("The thief flees laughing!");
- }
- else
- {
- monster_msg("You hear laughter!");
- }
-
- teleport_away(m_idx, MAX_SIGHT * 2 + 5);
- }
-
- return TRUE;
-}
-
-
-/*
- * Hack -- local "player stealth" value (see below)
- */
-static u32b noise = 0L;
-
-/* Determine whether the player is invisible to a monster */
-static bool_ player_invis(monster_type * m_ptr)
-{
- s16b inv, mlv;
- monster_race *r_ptr = race_inf(m_ptr);
-
- inv = p_ptr->invis;
-
- mlv = (s16b) m_ptr->level;
-
- if (r_ptr->flags3 & RF3_NO_SLEEP)
- mlv += 10;
- if (r_ptr->flags3 & RF3_DRAGON)
- mlv += 20;
- if (r_ptr->flags3 & RF3_UNDEAD)
- mlv += 15;
- if (r_ptr->flags3 & RF3_DEMON)
- mlv += 15;
- if (r_ptr->flags3 & RF3_ANIMAL)
- mlv += 15;
- if (r_ptr->flags3 & RF3_ORC)
- mlv -= 15;
- if (r_ptr->flags3 & RF3_TROLL)
- mlv -= 10;
- if (r_ptr->flags2 & RF2_STUPID)
- mlv /= 2;
- if (r_ptr->flags2 & RF2_SMART)
- mlv = (mlv * 5) / 4;
- if (m_ptr->mflag & MFLAG_QUEST)
- inv = 0;
- if (r_ptr->flags2 & RF2_INVISIBLE)
- inv = 0;
- if (m_ptr->mflag & MFLAG_CONTROL)
- inv = 0;
- if (mlv < 1)
- mlv = 1;
- return (inv >= randint(mlv*2));
-}
-
-/*
- * Process a monster
- *
- * The monster is known to be within 100 grids of the player
- *
- * In several cases, we directly update the monster lore
- *
- * Note that a monster is only allowed to "reproduce" if there
- * are a limited number of "reproducing" monsters on the current
- * level. This should prevent the level from being "swamped" by
- * reproducing monsters. It also allows a large mass of mice to
- * prevent a louse from multiplying, but this is a small price to
- * pay for a simple multiplication method.
- *
- * XXX Monster fear is slightly odd, in particular, monsters will
- * fixate on opening a door even if they cannot open it. Actually,
- * the same thing happens to normal monsters when they hit a door
- *
- * XXX XXX XXX In addition, monsters which *cannot* open or bash
- * down a door will still stand there trying to open it...
- *
- * XXX Technically, need to check for monster in the way
- * combined with that monster being in a wall (or door?)
- *
- * A "direction" of "5" means "pick a random direction".
- */
-static void process_monster(int m_idx, bool_ is_frien)
-{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
- cave_type *c_ptr = &cave[m_ptr->fy][m_ptr->fx];
-
- int i, d, oy, ox, ny, nx;
-
- int mm[8];
-
- monster_type *y_ptr;
-
- bool_ do_turn;
- bool_ do_move;
- bool_ do_view;
-
- bool_ did_open_door;
- bool_ did_bash_door;
- bool_ did_take_item;
- bool_ did_kill_item;
- bool_ did_move_body;
- bool_ did_kill_body;
- bool_ did_pass_wall;
- bool_ did_kill_wall;
- bool_ gets_angry = FALSE;
- bool_ inv;
- bool_ xxx = FALSE;
-
- inv = player_invis(m_ptr);
-
- if (r_ptr->flags9 & RF9_DOPPLEGANGER) doppleganger = m_idx;
-
- /* Handle "bleeding" */
- if (m_ptr->bleeding)
- {
- int d = 1 + (m_ptr->maxhp / 50);
- if (d > m_ptr->bleeding) d = m_ptr->bleeding;
-
- /* Exit if the monster dies */
- if (mon_take_hit(m_idx, d, &xxx, " bleeds to death.")) return;
-
- /* Hack -- Recover from bleeding */
- if (m_ptr->bleeding > d)
- {
- /* Recover somewhat */
- m_ptr->bleeding -= d;
- }
-
- /* Fully recover */
- else
- {
- /* Recover fully */
- m_ptr->bleeding = 0;
-
- /* Message if visible */
- if (m_ptr->ml)
- {
- char m_name[80];
-
- /* Get the monster name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Dump a message */
- msg_format("%^s is no longer bleeding.", m_name);
-
- /* Hack -- Update the health bar */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
- }
- }
- }
-
- /* Handle "poisoned" */
- if (m_ptr->poisoned)
- {
- int d = (m_ptr->poisoned) / 10;
- if (d < 1) d = 1;
-
- /* Exit if the monster dies */
- if (mon_take_hit(m_idx, d, &xxx, " dies of poison.")) return;
-
- /* Hack -- Recover from bleeding */
- if (m_ptr->poisoned > d)
- {
- /* Recover somewhat */
- m_ptr->poisoned -= d;
- }
-
- /* Fully recover */
- else
- {
- /* Recover fully */
- m_ptr->poisoned = 0;
-
- /* Message if visible */
- if (m_ptr->ml)
- {
- char m_name[80];
-
- /* Get the monster name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Dump a message */
- msg_format("%^s is no longer poisoned.", m_name);
-
- /* Hack -- Update the health bar */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
- }
- }
- }
-
- /* Handle "sleep" */
- if (m_ptr->csleep)
- {
- u32b notice = 0;
-
- /* Hack -- handle non-aggravation */
- if (!p_ptr->aggravate) notice = rand_int(1024);
-
- /* Hack -- See if monster "notices" player */
- if ((notice * notice * notice) <= noise)
- {
- /* Hack -- amount of "waking" */
- int d = 1;
-
- /* Wake up faster near the player */
- if (m_ptr->cdis < 50) d = (100 / m_ptr->cdis);
-
- /* Hack -- handle aggravation */
- if (p_ptr->aggravate) d = m_ptr->csleep;
-
- /* Still asleep */
- if (m_ptr->csleep > d)
- {
- /* Monster wakes up "a little bit" */
- m_ptr->csleep -= d;
-
- /* Notice the "not waking up" */
- if (m_ptr->ml)
- {
- /* Hack -- Count the ignores */
- if (r_ptr->r_ignore < MAX_UCHAR)
- {
- r_ptr->r_ignore++;
- }
- }
- }
-
- /* Just woke up */
- else
- {
- /* Reset sleep counter */
- m_ptr->csleep = 0;
-
- /* Notice the "waking up" */
- if (m_ptr->ml)
- {
- char m_name[80];
-
- /* Acquire the monster name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Dump a message */
- msg_format("%^s wakes up.", m_name);
-
- /* Hack -- Count the wakings */
- if (r_ptr->r_wake < MAX_UCHAR)
- {
- r_ptr->r_wake++;
- }
- }
- }
- }
-
- /* Still sleeping */
- if (m_ptr->csleep) return;
- }
-
-
- /* Handle "stun" */
- if (m_ptr->stunned)
- {
- int d = 1;
-
- /* Make a "saving throw" against stun */
- if (rand_int(5000) <= m_ptr->level * m_ptr->level)
- {
- /* Recover fully */
- d = m_ptr->stunned;
- }
-
- /* Hack -- Recover from stun */
- if (m_ptr->stunned > d)
- {
- /* Recover somewhat */
- m_ptr->stunned -= d;
- }
-
- /* Fully recover */
- else
- {
- /* Recover fully */
- m_ptr->stunned = 0;
-
- /* Message if visible */
- if (m_ptr->ml)
- {
- char m_name[80];
-
- /* Acquire the monster name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Dump a message */
- msg_format("%^s is no longer stunned.", m_name);
- }
- }
-
- /* Still stunned */
- if (m_ptr->stunned) return;
- }
-
-
- /* Handle confusion */
- if (m_ptr->confused)
- {
- /* Amount of "boldness" */
- int d = randint(m_ptr->level / 10 + 1);
-
- /* Still confused */
- if (m_ptr->confused > d)
- {
- /* Reduce the confusion */
- m_ptr->confused -= d;
- }
-
- /* Recovered */
- else
- {
- /* No longer confused */
- m_ptr->confused = 0;
-
- /* Message if visible */
- if (m_ptr->ml)
- {
- char m_name[80];
-
- /* Acquire the monster name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Dump a message */
- msg_format("%^s is no longer confused.", m_name);
- }
- }
- }
-
- /* No one wants to be your friend if you're aggravating */
- if ((m_ptr->status > MSTATUS_NEUTRAL) && (m_ptr->status < MSTATUS_COMPANION) && (p_ptr->aggravate) && !(r_ptr->flags7 & RF7_PET))
- gets_angry = TRUE;
-
- /* Paranoia... no friendly uniques outside wizard mode -- TY */
- if ((m_ptr->status > MSTATUS_NEUTRAL) && (m_ptr->status < MSTATUS_COMPANION) && !(wizard) &&
- (r_ptr->flags1 & (RF1_UNIQUE)) && !(r_ptr->flags7 & RF7_PET))
- gets_angry = TRUE;
-
- if (gets_angry)
- {
- char m_name[80];
- monster_desc(m_name, m_ptr, 0);
- switch (is_friend(m_ptr))
- {
- case 1:
- msg_format("%^s suddenly becomes hostile!", m_name);
- change_side(m_ptr);
- break;
- }
- }
-
- /* Handle "fear" */
- if (m_ptr->monfear)
- {
- /* Amount of "boldness" */
- int d = randint(m_ptr->level / 10 + 1);
-
- /* Still afraid */
- if (m_ptr->monfear > d)
- {
- /* Reduce the fear */
- m_ptr->monfear -= d;
- }
-
- /* Recover from fear, take note if seen */
- else
- {
- /* No longer afraid */
- m_ptr->monfear = 0;
-
- /* Visual note */
- if (m_ptr->ml)
- {
- char m_name[80];
- char m_poss[80];
-
- /* Acquire the monster name/poss */
- monster_desc(m_name, m_ptr, 0);
- monster_desc(m_poss, m_ptr, 0x22);
-
- /* Dump a message */
- msg_format("%^s recovers %s courage.", m_name, m_poss);
- }
- }
- }
-
- /* Get the origin */
- oy = m_ptr->fy;
- ox = m_ptr->fx;
-
- /* Attempt to "multiply" if able and allowed */
- if ((r_ptr->flags4 & (RF4_MULTIPLY)) && (num_repro < MAX_REPRO))
- {
- if (ai_multiply(m_idx)) return;
- }
-
- if (speak_unique)
- {
- if (randint(SPEAK_CHANCE) == 1)
- {
- if (player_has_los_bold(oy, ox) && (r_ptr->flags2 & RF2_CAN_SPEAK))
- {
- char m_name[80];
- char monmessage[80];
-
- /* Acquire the monster name/poss */
- if (m_ptr->ml)
- monster_desc(m_name, m_ptr, 0);
- else
- strcpy(m_name, "It");
-
- /* xtra_line function by Matt Graham--allow uniques to */
- /* say "unique" things based on their monster index. */
- /* Try for the unique's lines in "monspeak.txt" first. */
- /* 0 is SUCCESS, of course.... */
-
- if (!process_hooks(HOOK_MON_SPEAK, "(d,s)", m_idx, m_name))
- {
- if (get_xtra_line("monspeak.txt", m_ptr, monmessage) != 0)
- {
- /* Get a message from old defaults if new don't work */
-
- if (is_friend(m_ptr) > 0)
- get_rnd_line("speakpet.txt", monmessage);
- else if (m_ptr->monfear)
- get_rnd_line("monfear.txt", monmessage);
- else
- get_rnd_line("bravado.txt", monmessage);
- }
- msg_format("%^s %s", m_name, monmessage);
- }
- }
- }
- }
-
- /* Need a new target ? */
- if ((m_ptr->target == -1) || magik(10)) get_target_monster(m_idx);
-
-
- /* Attempt to cast a spell */
- if (make_attack_spell(m_idx)) return;
-
- /*
- * Attempt to cast a spell at an enemy other than the player
- * (may slow the game a smidgeon, but I haven't noticed.)
- */
- hack_message_pain_may_silent = TRUE;
- if (monst_spell_monst(m_idx))
- {
- hack_message_pain_may_silent = FALSE;
- return;
- }
- hack_message_pain_may_silent = FALSE;
-
-
- /* Hack -- Assume no movement */
- mm[0] = mm[1] = mm[2] = mm[3] = 0;
- mm[4] = mm[5] = mm[6] = mm[7] = 0;
-
- /* Confused -- 100% random */
- if (m_ptr->confused || (inv == TRUE && m_ptr->target == 0))
- {
- /* Try four "random" directions */
- mm[0] = mm[1] = mm[2] = mm[3] = 5;
- }
-
- /* 75% random movement */
- else if ((r_ptr->flags1 & (RF1_RAND_50)) &&
- (r_ptr->flags1 & (RF1_RAND_25)) &&
- (rand_int(100) < 75))
- {
- /* Memorize flags */
- if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_RAND_50);
- if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_RAND_25);
-
- /* Try four "random" directions */
- mm[0] = mm[1] = mm[2] = mm[3] = 5;
- }
-
- /* 50% random movement */
- else if ((r_ptr->flags1 & (RF1_RAND_50)) &&
- (rand_int(100) < 50))
- {
- /* Memorize flags */
- if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_RAND_50);
-
- /* Try four "random" directions */
- mm[0] = mm[1] = mm[2] = mm[3] = 5;
- }
-
- /* 25% random movement */
- else if ((r_ptr->flags1 & (RF1_RAND_25)) &&
- (rand_int(100) < 25))
- {
- /* Memorize flags */
- if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_RAND_25);
-
- /* Try four "random" directions */
- mm[0] = mm[1] = mm[2] = mm[3] = 5;
- }
-
- /* Normal movement */
- else
- {
- if (stupid_monsters)
- {
- /* Logical moves */
- get_moves(m_idx, mm);
- }
- else
- {
- /* Logical moves, may do nothing */
- if (!get_moves(m_idx, mm)) return;
- }
- }
-
- /* Paranoia -- quest code could delete it */
- if (!c_ptr->m_idx) return;
-
- /* Assume nothing */
- do_turn = FALSE;
- do_move = FALSE;
- do_view = FALSE;
-
- /* Assume nothing */
- did_open_door = FALSE;
- did_bash_door = FALSE;
- did_take_item = FALSE;
- did_kill_item = FALSE;
- did_move_body = FALSE;
- did_kill_body = FALSE;
- did_pass_wall = FALSE;
- did_kill_wall = FALSE;
-
-
- /* Take a zero-terminated array of "directions" */
- for (i = 0; mm[i]; i++)
- {
- /* Get the direction */
- d = mm[i];
-
- /* Hack -- allow "randomized" motion */
- if (d == 5) d = ddd[rand_int(8)];
-
- /* Get the destination */
- ny = oy + ddy[d];
- nx = ox + ddx[d];
-
- /* Access that cave grid */
- c_ptr = &cave[ny][nx];
-
- /* Access that cave grid's contents */
- y_ptr = &m_list[c_ptr->m_idx];
-
-
- /* Floor is open? */
- if (cave_floor_bold(ny, nx))
- {
- /* Go ahead and move */
- do_move = TRUE;
- }
-
- /* Floor is trapped? */
- else if (c_ptr->feat == FEAT_MON_TRAP)
- {
- /* Go ahead and move */
- do_move = TRUE;
- }
-
- /* Hack -- check for Glyph of Warding */
- if ((c_ptr->feat == FEAT_GLYPH) &&
- !(r_ptr->flags1 & RF1_NEVER_BLOW))
- {
- /* Assume no move allowed */
- do_move = FALSE;
-
- /* Break the ward */
- if (randint(BREAK_GLYPH) < m_ptr->level)
- {
- /* Describe observable breakage */
- if (c_ptr->info & CAVE_MARK)
- {
- msg_print("The rune of protection is broken!");
- }
-
- /* Forget the rune */
- c_ptr->info &= ~(CAVE_MARK);
-
- /* Break the rune */
- place_floor_convert_glass(ny, nx);
-
- /* Allow movement */
- do_move = TRUE;
- }
- }
-
- /* Hack -- trees are obstacle */
- else if ((cave[ny][nx].feat == FEAT_TREES) && (r_ptr->flags9 & RF9_KILL_TREES))
- {
- do_move = TRUE;
-
- /* Forget the tree */
- c_ptr->info &= ~(CAVE_MARK);
-
- /* Notice */
- cave_set_feat(ny, nx, FEAT_GRASS);
- }
-
- /* Hack -- player 'in' wall */
- else if ((ny == p_ptr->py) && (nx == p_ptr->px))
- {
- do_move = TRUE;
- }
-
- else if (c_ptr->m_idx)
- {
- /* Possibly a monster to attack */
- do_move = TRUE;
- }
-
- /* Permanent wall */
- else if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT)
- {
- /* Nothing */
- }
-
-
- /* Some monsters can fly */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_LEVITATE) && (r_ptr->flags7 & (RF7_CAN_FLY)))
- {
- /* Pass through walls/doors/rubble */
- do_move = TRUE;
- }
-
- /* Some monsters can fly */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_FLY) && (r_ptr->flags7 & (RF7_CAN_FLY)))
- {
- /* Pass through trees/... */
- do_move = TRUE;
- }
-
- /* Monster moves through walls (and doors) */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_PASS) && (r_ptr->flags2 & (RF2_PASS_WALL)))
- {
- /* Pass through walls/doors/rubble */
- do_move = TRUE;
-
- /* Monster went through a wall */
- did_pass_wall = TRUE;
- }
-
- /* Monster destroys walls (and doors) */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_PASS) && (r_ptr->flags2 & (RF2_KILL_WALL)))
- {
- /* Eat through walls/doors/rubble */
- do_move = TRUE;
-
- /* Monster destroyed a wall */
- did_kill_wall = TRUE;
-
- if (randint(GRINDNOISE) == 1)
- {
- msg_print("There is a grinding sound.");
- }
-
- /* Forget the wall */
- c_ptr->info &= ~(CAVE_MARK);
-
- /* Notice */
- cave_set_feat(ny, nx, FEAT_FLOOR);
-
- /* Note changes to viewable region */
- if (player_has_los_bold(ny, nx)) do_view = TRUE;
- }
-
- /* Monster moves through walls (and doors) */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_PASS) && (r_ptr->flags2 & (RF2_PASS_WALL)))
- {
- /* Pass through walls/doors/rubble */
- do_move = TRUE;
-
- /* Monster went through a wall */
- did_pass_wall = TRUE;
- }
-
- /* Monster moves through webs */
- else if ((f_info[c_ptr->feat].flags1 & FF1_WEB) &&
- (r_ptr->flags7 & RF7_SPIDER))
- {
- /* Pass through webs */
- do_move = TRUE;
- }
-
- /* Handle doors and secret doors */
- else if (((c_ptr->feat >= FEAT_DOOR_HEAD) &&
- (c_ptr->feat <= FEAT_DOOR_TAIL)) ||
- (c_ptr->feat == FEAT_SECRET))
- {
- bool_ may_bash = TRUE;
-
- /* Take a turn */
- do_turn = TRUE;
-
- if ((r_ptr->flags2 & (RF2_OPEN_DOOR)) &&
- ((is_friend(m_ptr) <= 0) || p_ptr->pet_open_doors))
- {
- /* Closed doors and secret doors */
- if ((c_ptr->feat == FEAT_DOOR_HEAD) ||
- (c_ptr->feat == FEAT_SECRET))
- {
- /* The door is open */
- did_open_door = TRUE;
-
- /* Do not bash the door */
- may_bash = FALSE;
- }
-
- /* Locked doors (not jammed) */
- else if (c_ptr->feat < FEAT_DOOR_HEAD + 0x08)
- {
- int k;
-
- /* Door power */
- k = ((c_ptr->feat - FEAT_DOOR_HEAD) & 0x07);
-
- /* Try to unlock it XXX XXX XXX */
- if (rand_int(m_ptr->hp / 10) > k)
- {
- /* Unlock the door */
- cave_set_feat(ny, nx, FEAT_DOOR_HEAD + 0x00);
-
- /* Do not bash the door */
- may_bash = FALSE;
- }
- }
- }
-
- /* Stuck doors -- attempt to bash them down if allowed */
- if (may_bash && (r_ptr->flags2 & RF2_BASH_DOOR) &&
- ((is_friend(m_ptr) <= 0) || p_ptr->pet_open_doors))
- {
- int k;
-
- /* Door power */
- k = ((c_ptr->feat - FEAT_DOOR_HEAD) & 0x07);
-
- /* Attempt to Bash XXX XXX XXX */
- if (rand_int(m_ptr->hp / 10) > k)
- {
- /* Message */
- msg_print("You hear a door burst open!");
-
- /* Disturb (sometimes) */
- if (disturb_minor) disturb(0, 0);
-
- /* The door was bashed open */
- did_bash_door = TRUE;
-
- /* Hack -- fall into doorway */
- do_move = TRUE;
- }
- }
-
-
- /* Deal with doors in the way */
- if (did_open_door || did_bash_door)
- {
- /* It's no longer hidden */
- cave[ny][nx].mimic = 0;
-
- /* Break down the door */
- if (did_bash_door && (rand_int(100) < 50))
- {
- cave_set_feat(ny, nx, FEAT_BROKEN);
- }
-
- /* Open the door */
- else
- {
- cave_set_feat(ny, nx, FEAT_OPEN);
- }
-
- /* Handle viewable doors */
- if (player_has_los_bold(ny, nx)) do_view = TRUE;
- }
- }
- else if (do_move && (c_ptr->feat == FEAT_MINOR_GLYPH)
- && !(r_ptr->flags1 & RF1_NEVER_BLOW))
- {
- /* Assume no move allowed */
- do_move = FALSE;
-
- /* Break the ward */
- if (randint(BREAK_MINOR_GLYPH) < m_ptr->level)
- {
- /* Describe observable breakage */
- if (c_ptr->info & CAVE_MARK)
- {
- if (ny == p_ptr->py && nx == p_ptr->px)
- {
- msg_print("The rune explodes!");
- fire_ball(GF_MANA, 0,
- 2 * ((p_ptr->lev / 2) + damroll(7, 7)), 2);
- }
- else
- msg_print("An explosive rune was disarmed.");
- }
-
- /* Forget the rune */
- c_ptr->info &= ~(CAVE_MARK);
-
- /* Break the rune */
- place_floor_convert_glass(ny, nx);
-
- /* Allow movement */
- do_move = TRUE;
- }
- }
-
- /* Hack -- the Between teleport the monsters too */
- else if (cave[ny][nx].feat == FEAT_BETWEEN)
- {
- nx = cave[ny][nx].special & 255;
- ny = cave[ny][nx].special >> 8;
- get_pos_player(10, &ny, &nx);
-
- /* Access that cave grid */
- c_ptr = &cave[ny][nx];
-
- /* Access that cave grid's contents */
- y_ptr = &m_list[c_ptr->m_idx];
-
- if (!(r_ptr->flags3 & RF3_IM_COLD))
- {
- if ((m_ptr->hp - distance(ny, nx, oy, ox)*2) <= 0)
- {
- ny = oy + ddy[d];
- nx = ox + ddx[d];
- do_move = FALSE;
- }
- else
- {
- m_ptr->hp -= distance(ny, nx, oy, ox) * 2;
- do_move = TRUE;
- }
- }
- else
- {
- do_move = TRUE;
- }
- }
-
- /* Execute the inscription -- MEGA HACK -- */
- if ((c_ptr->inscription) && (c_ptr->inscription != INSCRIP_CHASM))
- {
- if (inscription_info[c_ptr->inscription].when & INSCRIP_EXEC_MONST_WALK)
- {
- bool_ t;
- t = execute_inscription(c_ptr->inscription, ny, nx);
- if (!t && do_move)
- {
- /* Hack -- attack the player even if on the inscription */
- if ((ny == p_ptr->py) && (nx == p_ptr->px))
- do_move = TRUE;
- else
- do_move = FALSE;
- }
- }
- }
-
- /* Some monsters never attack */
- if (do_move && (ny == p_ptr->py) && (nx == p_ptr->px) &&
- (r_ptr->flags1 & RF1_NEVER_BLOW))
- {
- /* Do not move */
- do_move = FALSE;
- }
-
- /* The player is in the way. Attack him. */
- if (do_move && (ny == p_ptr->py) && (nx == p_ptr->px))
- {
- /* Do the attack */
- (void)make_attack_normal(m_idx, 1);
-
- /* Do not move */
- do_move = FALSE;
-
- /* Took a turn */
- do_turn = TRUE;
- }
-
- if ((cave[ny][nx].feat >= FEAT_PATTERN_START) &&
- (cave[ny][nx].feat <= FEAT_PATTERN_XTRA2) &&
- do_turn == FALSE)
- {
- do_move = FALSE;
- }
-
-
- /* A monster is in the way */
- if (do_move && c_ptr->m_idx)
- {
- monster_race *z_ptr = race_inf(y_ptr);
- monster_type *m2_ptr = &m_list[c_ptr->m_idx];
-
- /* Assume no movement */
- do_move = FALSE;
-
- /* Kill weaker monsters */
- if ((r_ptr->flags2 & RF2_KILL_BODY) &&
- (r_ptr->mexp > z_ptr->mexp) && (cave_floor_bold(ny, nx)) &&
- /* Friends don't kill friends... */
- !((is_friend(m_ptr) > 0) && (is_friend(m2_ptr) > 0)) &&
- /* Uniques aren't faceless monsters in a crowd */
- !(z_ptr->flags1 & RF1_UNIQUE) &&
- /* Don't wreck quests */
- !(m2_ptr->mflag & (MFLAG_QUEST | MFLAG_QUEST2)) &&
- /* Don't punish summoners for relying on their friends */
- (is_friend(m2_ptr) <= 0))
- {
- /* Allow movement */
- do_move = TRUE;
-
- /* Monster ate another monster */
- did_kill_body = TRUE;
-
- /* XXX XXX XXX Message */
-
- /* Kill the monster */
- delete_monster(ny, nx);
-
- /* Hack -- get the empty monster */
- y_ptr = &m_list[c_ptr->m_idx];
- }
-
- /* Attack 'enemies' */
- else if (is_enemy(m_ptr, m2_ptr) || m_ptr->confused)
- {
- do_move = FALSE;
- /* attack */
- if (m2_ptr->r_idx && (m2_ptr->hp >= 0))
- {
- hack_message_pain_may_silent = TRUE;
- if (monst_attack_monst(m_idx, c_ptr->m_idx))
- {
- hack_message_pain_may_silent = FALSE;
- return;
- }
- hack_message_pain_may_silent = FALSE;
- }
- }
-
- /* Push past weaker monsters (unless leaving a wall) */
- else if ((r_ptr->flags2 & RF2_MOVE_BODY) &&
- (r_ptr->mexp > z_ptr->mexp) && cave_floor_bold(ny, nx) &&
- (cave_floor_bold(m_ptr->fy, m_ptr->fx)))
- {
- /* Allow movement */
- do_move = TRUE;
-
- /* Monster pushed past another monster */
- did_move_body = TRUE;
-
- /* XXX XXX XXX Message */
- }
- }
-
- /*
- * Check if monster can cross terrain
- * This is checked after the normal attacks
- * to allow monsters to attack an enemy,
- * even if it can't enter the terrain.
- */
- if (do_move && !monster_can_cross_terrain(c_ptr->feat, r_ptr))
- {
- /* Assume no move allowed */
- do_move = FALSE;
- }
-
- /* Some monsters never move */
- if (do_move && (r_ptr->flags1 & RF1_NEVER_MOVE))
- {
- /* Hack -- memorize lack of attacks */
- /* if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_NEVER_MOVE); */
-
- /* Do not move */
- do_move = FALSE;
- }
-
-
-
- /* Creature has been allowed move */
- if (do_move)
- {
- s16b this_o_idx, next_o_idx = 0;
-
- /* Take a turn */
- do_turn = TRUE;
-
- /* Hack -- Update the old location */
- cave[oy][ox].m_idx = c_ptr->m_idx;
-
- /* Mega-Hack -- move the old monster, if any */
- if (c_ptr->m_idx)
- {
- /* Move the old monster */
- y_ptr->fy = oy;
- y_ptr->fx = ox;
-
- /* Update the old monster */
- update_mon(c_ptr->m_idx, TRUE);
-
- /* Wake up the moved monster */
- m_list[c_ptr->m_idx].csleep = 0;
-
- /*
- * Update monster light -- I'm too lazy to check flags
- * here, and those ego monster_race functions aren't
- * re-entrant XXX XXX XXX
- */
- p_ptr->update |= (PU_MON_LITE);
- }
-
- /* Hack -- Update the new location */
- c_ptr->m_idx = m_idx;
-
- /* Move the monster */
- m_ptr->fy = ny;
- m_ptr->fx = nx;
-
- /* Update the monster */
- update_mon(m_idx, TRUE);
-
- /* Redraw the old grid */
- lite_spot(oy, ox);
-
- /* Redraw the new grid */
- lite_spot(ny, nx);
-
- /* Execute the inscription -- MEGA HACK -- */
- if (c_ptr->inscription == INSCRIP_CHASM)
- {
- if (inscription_info[c_ptr->inscription].when & INSCRIP_EXEC_MONST_WALK)
- {
- execute_inscription(c_ptr->inscription, ny, nx);
- }
- }
-
- /* Possible disturb */
- if (m_ptr->ml && (disturb_move ||
- ((m_ptr->mflag & (MFLAG_VIEW)) &&
- disturb_near)))
- {
- /* Disturb */
- if ((is_friend(m_ptr) < 0) || disturb_pets)
- disturb(0, 0);
- }
-
- /* Check for monster trap */
- if (c_ptr->feat == FEAT_MON_TRAP)
- {
- if (mon_hit_trap(m_idx)) return;
- }
- else
- {
- /* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
- {
- object_type * o_ptr;
-
- /* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
-
- /* Skip gold */
- if (o_ptr->tval == TV_GOLD) continue;
-
- /* Incarnate ? */
- if ((o_ptr->tval == TV_CORPSE) && (r_ptr->flags7 & RF7_POSSESSOR) &&
- ((o_ptr->sval == SV_CORPSE_CORPSE) || (o_ptr->sval == SV_CORPSE_SKELETON)))
- {
- if (ai_possessor(m_idx, this_o_idx)) return;
- }
-
- /* Take or Kill objects on the floor */
- /* rr9: Pets will no longer pick up/destroy items */
- if ((((r_ptr->flags2 & (RF2_TAKE_ITEM)) &&
- ((is_friend(m_ptr) <= 0) || p_ptr->pet_pickup_items)) ||
- (r_ptr->flags2 & (RF2_KILL_ITEM))) &&
- (is_friend(m_ptr) <= 0))
- {
- u32b f1, f2, f3, f4, f5, esp;
-
- u32b flg3 = 0L;
-
- char m_name[80];
- char o_name[80];
-
- /* Extract some flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Acquire the object name */
- object_desc(o_name, o_ptr, TRUE, 3);
-
- /* Acquire the monster name */
- monster_desc(m_name, m_ptr, 0x04);
-
- /* React to objects that hurt the monster */
- if (f5 & (TR5_KILL_DEMON)) flg3 |= (RF3_DEMON);
- if (f5 & (TR5_KILL_UNDEAD)) flg3 |= (RF3_UNDEAD);
- if (f1 & (TR1_SLAY_DRAGON)) flg3 |= (RF3_DRAGON);
- if (f1 & (TR1_SLAY_TROLL)) flg3 |= (RF3_TROLL);
- if (f1 & (TR1_SLAY_GIANT)) flg3 |= (RF3_GIANT);
- if (f1 & (TR1_SLAY_ORC)) flg3 |= (RF3_ORC);
- if (f1 & (TR1_SLAY_DEMON)) flg3 |= (RF3_DEMON);
- if (f1 & (TR1_SLAY_UNDEAD)) flg3 |= (RF3_UNDEAD);
- if (f1 & (TR1_SLAY_ANIMAL)) flg3 |= (RF3_ANIMAL);
- if (f1 & (TR1_SLAY_EVIL)) flg3 |= (RF3_EVIL);
-
- /* The object cannot be picked up by the monster */
- if (artifact_p(o_ptr) || (r_ptr->flags3 & flg3) ||
- (o_ptr->art_name))
- {
- /* Only give a message for "take_item" */
- if (r_ptr->flags2 & (RF2_TAKE_ITEM))
- {
- /* Take note */
- did_take_item = TRUE;
-
- /* Describe observable situations */
- if (m_ptr->ml && player_has_los_bold(ny, nx))
- {
- /* Dump a message */
- msg_format("%^s tries to pick up %s, but fails.",
- m_name, o_name);
- }
- }
- }
-
- /* Pick up the item */
- else if (r_ptr->flags2 & (RF2_TAKE_ITEM))
- {
- /* Take note */
- did_take_item = TRUE;
-
- /* Describe observable situations */
- if (player_has_los_bold(ny, nx))
- {
- /* Dump a message */
- msg_format("%^s picks up %s.", m_name, o_name);
- }
-
- /* Option */
- if (testing_carry)
- {
- /* Excise the object */
- excise_object_idx(this_o_idx);
-
- /* Forget mark */
- o_ptr->marked = FALSE;
-
- /* Forget location */
- o_ptr->iy = o_ptr->ix = 0;
-
- /* Memorize monster */
- o_ptr->held_m_idx = m_idx;
-
- /* Build a stack */
- o_ptr->next_o_idx = m_ptr->hold_o_idx;
-
- /* Carry object */
- m_ptr->hold_o_idx = this_o_idx;
- }
-
- /* Nope */
- else
- {
- /* Delete the object */
- delete_object_idx(this_o_idx);
- }
- }
-
- /* Destroy the item */
- else
- {
- /* Take note */
- did_kill_item = TRUE;
-
- /* Describe observable situations */
- if (player_has_los_bold(ny, nx))
- {
- /* Dump a message */
- msg_format("%^s crushes %s.", m_name, o_name);
- }
-
- /* Delete the object */
- delete_object_idx(this_o_idx);
- }
- }
- }
- }
-
- /* Update monster light */
- if (r_ptr->flags9 & RF9_HAS_LITE) p_ptr->update |= (PU_MON_LITE);
- }
-
- /* Stop when done */
- if (do_turn) break;
- }
-
-
- /* If we haven't done anything, try casting a spell again */
- if (!do_turn && !do_move && !m_ptr->monfear && !stupid_monsters &&
- (is_friend(m_ptr) < 0))
- {
- /* Cast spell */
- if (make_attack_spell(m_idx)) return;
- }
-
-
- /* Notice changes in view */
- if (do_view)
- {
- /* Update some things */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MONSTERS | PU_MON_LITE);
- }
-
-
- /* Learn things from observable monster */
- if (m_ptr->ml)
- {
- /* Monster opened a door */
- if (did_open_door) r_ptr->r_flags2 |= (RF2_OPEN_DOOR);
-
- /* Monster bashed a door */
- if (did_bash_door) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
-
- /* Monster tried to pick something up */
- if (did_take_item) r_ptr->r_flags2 |= (RF2_TAKE_ITEM);
-
- /* Monster tried to crush something */
- if (did_kill_item) r_ptr->r_flags2 |= (RF2_KILL_ITEM);
-
- /* Monster pushed past another monster */
- if (did_move_body) r_ptr->r_flags2 |= (RF2_MOVE_BODY);
-
- /* Monster ate another monster */
- if (did_kill_body) r_ptr->r_flags2 |= (RF2_KILL_BODY);
-
- /* Monster passed through a wall */
- if (did_pass_wall) r_ptr->r_flags2 |= (RF2_PASS_WALL);
-
- /* Monster destroyed a wall */
- if (did_kill_wall) r_ptr->r_flags2 |= (RF2_KILL_WALL);
- }
-
-
- /* Hack -- get "bold" if out of options */
- if (!do_turn && !do_move && m_ptr->monfear)
- {
- /* No longer afraid */
- m_ptr->monfear = 0;
-
- /* Message if seen */
- if (m_ptr->ml)
- {
- char m_name[80];
-
- /* Acquire the monster name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Dump a message */
- msg_format("%^s turns to fight!", m_name);
- }
-
- /* XXX XXX XXX Actually do something now (?) */
- }
-}
-
-
-void summon_maint(int m_idx)
-{
-
- monster_type *m_ptr = &m_list[m_idx];
-
- /* Can you pay? */
- if ((s32b)(p_ptr->maintain_sum / 10000) > p_ptr->csp)
- {
- char m_name[80];
-
- monster_desc(m_name, m_ptr, 0);
-
- msg_format("You lose control of %s.", m_name);
-
- /* Well, then, I guess I'm dead. */
- delete_monster_idx(m_idx);
- }
- else
- {
- s32b cl, ml, floor, cost;
-
- cl = get_skill_scale(SKILL_SUMMON, 100);
- ml = m_ptr->level * 10000;
-
- /* Floor = 19 * ml / 990 + 8 / 199
- This gives a floor of 0.1 at level 1 and a floor of 2 at level 100
-
- Since ml is multiplied by 10000 already, we multiply the 8/199 too
- */
- floor = ml * 19 / 990 + 80000 / 199;
- cost = (ml / cl - 10000) / 4;
- if(cost < floor)
- cost = floor;
-
- /* Well, then I'll take my wages from you. */
- p_ptr->maintain_sum += cost;
- }
- return;
-}
-
-
-/*
- * Process all the "live" monsters, once per game turn.
- *
- * During each game turn, we scan through the list of all the "live" monsters,
- * (backwards, so we can excise any "freshly dead" monsters), energizing each
- * monster, and allowing fully energized monsters to move, attack, pass, etc.
- *
- * Note that monsters can never move in the monster array (except when the
- * "compact_monsters()" function is called by "dungeon()" or "save_player()").
- *
- * This function is responsible for at least half of the processor time
- * on a normal system with a "normal" amount of monsters and a player doing
- * normal things.
- *
- * When the player is resting, virtually 90% of the processor time is spent
- * in this function, and its children, "process_monster()" and "make_move()".
- *
- * Most of the rest of the time is spent in "update_view()" and "lite_spot()",
- * especially when the player is running.
- *
- * Note the special "MFLAG_BORN" flag, which allows us to ignore "fresh"
- * monsters while they are still being "born". A monster is "fresh" only
- * during the turn in which it is created, and we use the "hack_m_idx" to
- * determine if the monster is yet to be processed during the current turn.
- *
- * Note the special "MFLAG_NICE" flag, which allows the player to get one
- * move before any "nasty" monsters get to use their spell attacks.
- *
- * Note that when the "knowledge" about the currently tracked monster
- * changes (flags, attacks, spells), we induce a redraw of the monster
- * recall window.
- */
-void process_monsters(void)
-{
- int i, e;
- int fx, fy;
-
- bool_ test;
- bool_ is_frien = FALSE;
-
- monster_type *m_ptr;
- monster_race *r_ptr;
-
- int old_monster_race_idx;
-
- u32b old_r_flags1 = 0L;
- u32b old_r_flags2 = 0L;
- u32b old_r_flags3 = 0L;
- u32b old_r_flags4 = 0L;
- u32b old_r_flags5 = 0L;
- u32b old_r_flags6 = 0L;
-
- byte old_r_blows0 = 0;
- byte old_r_blows1 = 0;
- byte old_r_blows2 = 0;
- byte old_r_blows3 = 0;
-
- byte old_r_cast_inate = 0;
- byte old_r_cast_spell = 0;
-
- /* Check the doppleganger */
- if (doppleganger && !(r_info[m_list[doppleganger].r_idx].flags9 & RF9_DOPPLEGANGER))
- doppleganger = 0;
-
- /* Memorize old race */
- old_monster_race_idx = monster_race_idx;
-
- /* Acquire knowledge */
- if (monster_race_idx)
- {
- /* Acquire current monster */
- r_ptr = &r_info[monster_race_idx];
-
- /* Memorize flags */
- old_r_flags1 = r_ptr->r_flags1;
- old_r_flags2 = r_ptr->r_flags2;
- old_r_flags3 = r_ptr->r_flags3;
- old_r_flags4 = r_ptr->r_flags4;
- old_r_flags5 = r_ptr->r_flags5;
- old_r_flags6 = r_ptr->r_flags6;
-
- /* Memorize blows */
- old_r_blows0 = r_ptr->r_blows[0];
- old_r_blows1 = r_ptr->r_blows[1];
- old_r_blows2 = r_ptr->r_blows[2];
- old_r_blows3 = r_ptr->r_blows[3];
-
- /* Memorize castings */
- old_r_cast_inate = r_ptr->r_cast_inate;
- old_r_cast_spell = r_ptr->r_cast_spell;
- }
-
-
- /* Hack -- calculate the "player noise" */
- noise = (1L << (30 - p_ptr->skill_stl));
-
-
- /* Process the monsters (backwards) */
- for (i = m_max - 1; i >= 1; i--)
- {
- /* Access the monster */
- m_ptr = &m_list[i];
-
- /* Handle "leaving" */
- if (p_ptr->leaving) break;
-
- /* Ignore "dead" monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Calculate "upkeep" for friendly monsters */
- if (m_ptr->status == MSTATUS_PET)
- {
- total_friends++;
- total_friend_levels += m_ptr->level;
- }
-
-
- /* Handle "fresh" monsters */
- if (m_ptr->mflag & (MFLAG_BORN))
- {
- /* No longer "fresh" */
- m_ptr->mflag &= ~(MFLAG_BORN);
-
- /* Skip */
- continue;
- }
-
-
- /* Obtain the energy boost */
- e = extract_energy[m_ptr->mspeed];
-
- /* Give this monster some energy */
- m_ptr->energy += e;
-
-
- /* Not enough energy to move */
- if (m_ptr->energy < 100) continue;
-
- /* Use up "some" energy */
- m_ptr->energy -= 100;
-
-
- /* Hack -- Require proximity */
- if (m_ptr->cdis >= 100) continue;
-
-
- /* Access the race */
- r_ptr = race_inf(m_ptr);
-
- /* Access the location */
- fx = m_ptr->fx;
- fy = m_ptr->fy;
-
-
- /* Assume no move */
- test = FALSE;
-
- /* Control monster aint affected by distance */
- if (p_ptr->control == i)
- {
- test = TRUE;
- }
-
- /* No free upkeep on partial summons just because they're out
- * of line of sight. */
- else if (m_ptr->mflag & MFLAG_PARTIAL) test = TRUE;
-
- /* Handle "sensing radius" */
- else if (m_ptr->cdis <= r_ptr->aaf)
- {
- /* We can "sense" the player */
- test = TRUE;
- }
-
- /* Handle "sight" and "aggravation" */
- else if ((m_ptr->cdis <= MAX_SIGHT) &&
- (player_has_los_bold(fy, fx) ||
- p_ptr->aggravate))
- {
- /* We can "see" or "feel" the player */
- test = TRUE;
- }
-
- /* Hack -- Monsters can "smell" the player from far away */
- /* Note that most monsters have "aaf" of "20" or so */
- else if (flow_by_sound &&
- (cave[p_ptr->py][p_ptr->px].when == cave[fy][fx].when) &&
- (cave[fy][fx].cost < MONSTER_FLOW_DEPTH) &&
- (cave[fy][fx].cost < r_ptr->aaf))
- {
- /* We can "smell" the player */
- test = TRUE;
- }
-
- /* Running away wont save them ! */
- if (m_ptr->poisoned || m_ptr->bleeding) test = TRUE;
-
- /* Do nothing */
- if (!test) continue;
-
- /* Save global index */
- hack_m_idx = i;
-
- if (is_friend(m_ptr) > 0) is_frien = TRUE;
-
- /* Process the monster */
- process_monster(i, is_frien);
-
- /* Hack -- notice death or departure */
- if (!alive || death) break;
-
- /* If it's still alive and friendly, charge upkeep. */
- if (m_ptr->mflag & MFLAG_PARTIAL) summon_maint(i);
-
- /* Notice leaving */
- if (p_ptr->leaving) break;
- }
-
- /* Reset global index */
- hack_m_idx = 0;
-
-
- /* Tracking a monster race (the same one we were before) */
- if (monster_race_idx && (monster_race_idx == old_monster_race_idx))
- {
- /* Acquire monster race */
- r_ptr = &r_info[monster_race_idx];
-
- /* Check for knowledge change */
- if ((old_r_flags1 != r_ptr->r_flags1) ||
- (old_r_flags2 != r_ptr->r_flags2) ||
- (old_r_flags3 != r_ptr->r_flags3) ||
- (old_r_flags4 != r_ptr->r_flags4) ||
- (old_r_flags5 != r_ptr->r_flags5) ||
- (old_r_flags6 != r_ptr->r_flags6) ||
- (old_r_blows0 != r_ptr->r_blows[0]) ||
- (old_r_blows1 != r_ptr->r_blows[1]) ||
- (old_r_blows2 != r_ptr->r_blows[2]) ||
- (old_r_blows3 != r_ptr->r_blows[3]) ||
- (old_r_cast_inate != r_ptr->r_cast_inate) ||
- (old_r_cast_spell != r_ptr->r_cast_spell))
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
- }
-}