*/
#include "angband.h"
+#include "util.h"
+
+#include "floor.h"
+#include "dungeon.h"
+#include "grid.h"
#include "object-curse.h"
-#include "projection.h"
#include "quest.h"
#include "realm-hex.h"
+#include "player-move.h"
+#include "player-status.h"
+#include "monster.h"
+#include "monster-spell.h"
+#include "spells.h"
+#include "world.h"
+#include "realm-song.h"
+#include "view-mainwindow.h"
+#include "player-race.h"
+#include "player-class.h"
+#define DO_SPELL_NONE 0
+#define DO_SPELL_BR_LITE 1
+#define DO_SPELL_BR_DISI 2
+#define DO_SPELL_BA_LITE 3
-/*!
- * @brief モンスターがプレイヤーの弱点をついた選択を取るかどうかの判定 /
- * Internal probability routine
- * @param r_ptr モンスター種族の構造体参照ポインタ
- * @param prob 基本確率(%)
- * @return 適した選択を取るならばTRUEを返す。
- */
+ /*!
+ * @brief モンスターがプレイヤーの弱点をついた選択を取るかどうかの判定 /
+ * Internal probability routine
+ * @param r_ptr モンスター種族の構造体参照ポインタ
+ * @param prob 基本確率(%)
+ * @return 適した選択を取るならばTRUEを返す。
+ */
static bool int_outof(monster_race *r_ptr, PERCENTAGE prob)
{
/* Non-Smart monsters are half as "smart" */
* @param f6p モンスター魔法のフラグリスト3
* @return なし
*/
-static void remove_bad_spells(MONSTER_IDX m_idx, u32b *f4p, u32b *f5p, u32b *f6p)
+static void remove_bad_spells(MONSTER_IDX m_idx, player_type *target_ptr, u32b *f4p, u32b *f5p, u32b *f6p)
{
- monster_type *m_ptr = &m_list[m_idx];
+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
monster_race *r_ptr = &r_info[m_ptr->r_idx];
u32b f4 = (*f4p);
u32b smart = 0L;
-
/* Too stupid to know anything */
if (r_ptr->flags2 & RF2_STUPID) return;
/* Cheat if requested */
if (smart_cheat)
{
- /* Know basic info */
- if (p_ptr->resist_acid) smart |= (SM_RES_ACID);
- if (IS_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 (IS_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 (IS_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 (IS_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 (IS_OPPOSE_POIS()) smart |= (SM_OPP_POIS);
+ /* Know element info */
+ if (target_ptr->resist_acid) smart |= (SM_RES_ACID);
+ if (is_oppose_acid(target_ptr)) smart |= (SM_OPP_ACID);
+ if (target_ptr->immune_acid) smart |= (SM_IMM_ACID);
+ if (target_ptr->resist_elec) smart |= (SM_RES_ELEC);
+ if (is_oppose_elec(target_ptr)) smart |= (SM_OPP_ELEC);
+ if (target_ptr->immune_elec) smart |= (SM_IMM_ELEC);
+ if (target_ptr->resist_fire) smart |= (SM_RES_FIRE);
+ if (is_oppose_fire(target_ptr)) smart |= (SM_OPP_FIRE);
+ if (target_ptr->immune_fire) smart |= (SM_IMM_FIRE);
+ if (target_ptr->resist_cold) smart |= (SM_RES_COLD);
+ if (is_oppose_cold(target_ptr)) smart |= (SM_OPP_COLD);
+ if (target_ptr->immune_cold) smart |= (SM_IMM_COLD);
+ if (target_ptr->resist_pois) smart |= (SM_RES_POIS);
+ if (is_oppose_pois(target_ptr)) 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);
+ if (target_ptr->resist_neth) smart |= (SM_RES_NETH);
+ if (target_ptr->resist_lite) smart |= (SM_RES_LITE);
+ if (target_ptr->resist_dark) smart |= (SM_RES_DARK);
+ if (target_ptr->resist_fear) smart |= (SM_RES_FEAR);
+ if (target_ptr->resist_conf) smart |= (SM_RES_CONF);
+ if (target_ptr->resist_chaos) smart |= (SM_RES_CHAOS);
+ if (target_ptr->resist_disen) smart |= (SM_RES_DISEN);
+ if (target_ptr->resist_blind) smart |= (SM_RES_BLIND);
+ if (target_ptr->resist_nexus) smart |= (SM_RES_NEXUS);
+ if (target_ptr->resist_sound) smart |= (SM_RES_SOUND);
+ if (target_ptr->resist_shard) smart |= (SM_RES_SHARD);
+ if (target_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);
+ if (target_ptr->free_act) smart |= (SM_IMM_FREE);
+ if (!target_ptr->msp) smart |= (SM_IMM_MANA);
}
-
- /* Nothing known */
if (!smart) return;
-
if (smart & SM_IMM_ACID)
{
f4 &= ~(RF4_BR_ACID);
if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_ELEC);
}
-
if (smart & (SM_IMM_FIRE))
{
f4 &= ~(RF4_BR_FIRE);
if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_FIRE);
}
-
if (smart & (SM_IMM_COLD))
{
f4 &= ~(RF4_BR_COLD);
if (int_outof(r_ptr, 20)) 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, 30)) f5 &= ~(RF5_BA_POIS);
}
-
if (smart & (SM_RES_NETH))
{
- if (prace_is_(RACE_SPECTRE))
+ if (PRACE_IS_(target_ptr, RACE_SPECTRE))
{
f4 &= ~(RF4_BR_NETH);
f5 &= ~(RF5_BA_NETH);
if (smart & (SM_RES_DARK))
{
- if (prace_is_(RACE_VAMPIRE))
+ if (PRACE_IS_(target_ptr, RACE_VAMPIRE))
{
f4 &= ~(RF4_BR_DARK);
f5 &= ~(RF5_BA_DARK);
/*!
* @brief モンスターにとって所定の地点が召還に相応しい地点かどうかを返す。 /
* Determine if there is a space near the player in which a summoned creature can appear
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param y1 判定を行いたいマスのY座標
* @param x1 判定を行いたいマスのX座標
* @return 召還に相応しいならばTRUEを返す
*/
-bool summon_possible(POSITION y1, POSITION x1)
+bool summon_possible(player_type *target_ptr, POSITION y1, POSITION x1)
{
POSITION y, x;
/* Start at the player's location, and check 2 grids in each dir */
+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
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;
+ if (!in_bounds(floor_ptr, y, x)) continue;
/* Only check a circular area */
- if (distance(y1, x1, y, x)>2) continue;
+ if (distance(y1, x1, y, x) > 2) continue;
/* ...nor on the Pattern */
- if (pattern_tile(y, x)) continue;
+ if (pattern_tile(floor_ptr, y, x)) continue;
/* Require empty floor grid in line of projection */
- if (cave_empty_bold(y, x) && projectable(y1, x1, y, x) && projectable(y, x, y1, x1)) return (TRUE);
+ if (is_cave_empty_bold(target_ptr, y, x) && projectable(target_ptr, y1, x1, y, x) && projectable(target_ptr, y, x, y1, x1)) return TRUE;
}
}
/*!
* @brief モンスターにとって死者復活を行うべき状態かどうかを返す /
* Determine if there is a space near the player in which a summoned creature can appear
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param m_ptr 判定を行いたいモンスターの構造体参照ポインタ
* @return 死者復活が有効な状態ならばTRUEを返す。
*/
-bool raise_possible(monster_type *m_ptr)
+bool raise_possible(player_type *target_ptr, monster_type *m_ptr)
{
- POSITION xx, yy;
POSITION y = m_ptr->fy;
POSITION x = m_ptr->fx;
- OBJECT_IDX this_o_idx, next_o_idx = 0;
- cave_type *c_ptr;
-
- for (xx = x - 5; xx <= x + 5; xx++)
+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
+ for (POSITION xx = x - 5; xx <= x + 5; xx++)
{
- for (yy = y - 5; yy <= y + 5; yy++)
+ grid_type *g_ptr;
+ for (POSITION yy = y - 5; yy <= y + 5; yy++)
{
if (distance(y, x, yy, xx) > 5) continue;
- if (!los(y, x, yy, xx)) continue;
- if (!projectable(y, x, yy, xx)) continue;
+ if (!los(target_ptr, y, x, yy, xx)) continue;
+ if (!projectable(target_ptr, y, x, yy, xx)) continue;
- c_ptr = &cave[yy][xx];
+ g_ptr = &floor_ptr->grid_array[yy][xx];
/* Scan the pile of objects */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+ OBJECT_IDX this_o_idx, next_o_idx = 0;
+ for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
{
- object_type *o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
+ object_type *o_ptr = &floor_ptr->o_list[this_o_idx];
next_o_idx = o_ptr->next_o_idx;
/* Known to be worthless? */
}
}
}
+
return FALSE;
}
-
/*!
* @brief モンスターにとってボルト型魔法が有効な状態かを返す /
* Determine if a bolt spell will hit the player.
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param y1 ボルト魔法発射地点のY座標
* @param x1 ボルト魔法発射地点のX座標
* @param y2 ボルト魔法目標地点のY座標
* no equally friendly monster is\n
* between the attacker and target.\n
*/
-bool clean_shot(POSITION y1, POSITION x1, POSITION y2, POSITION x2, bool is_friend)
+bool clean_shot(player_type *target_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2, bool is_friend)
{
- /* Must be the same as projectable() */
-
- int i;
- POSITION y, x;
-
- int grid_n = 0;
- u16b grid_g[512];
-
/* Check the projection path */
- grid_n = project_path(grid_g, MAX_RANGE, y1, x1, y2, x2, 0);
+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
+ u16b grid_g[512];
+ int grid_n = grid_n = project_path(target_ptr, grid_g, MAX_RANGE, y1, x1, y2, x2, 0);
/* No grid is ever projectable from itself */
- if (!grid_n) return (FALSE);
+ if (!grid_n) return FALSE;
/* Final grid */
- y = GRID_Y(grid_g[grid_n-1]);
- x = GRID_X(grid_g[grid_n-1]);
+ POSITION y = GRID_Y(grid_g[grid_n - 1]);
+ POSITION x = GRID_X(grid_g[grid_n - 1]);
/* May not end in an unrequested grid */
- if ((y != y2) || (x != x2)) return (FALSE);
+ if ((y != y2) || (x != x2)) return FALSE;
- for (i = 0; i < grid_n; i++)
+ for (int i = 0; i < grid_n; i++)
{
y = GRID_Y(grid_g[i]);
x = GRID_X(grid_g[i]);
- if ((cave[y][x].m_idx > 0) && !((y == y2) && (x == x2)))
+ if ((floor_ptr->grid_array[y][x].m_idx > 0) && !((y == y2) && (x == x2)))
{
- monster_type *m_ptr = &m_list[cave[y][x].m_idx];
+ monster_type *m_ptr = &floor_ptr->m_list[floor_ptr->grid_array[y][x].m_idx];
if (is_friend == is_pet(m_ptr))
{
- return (FALSE);
+ return FALSE;
}
}
+
/* Pets may not shoot through the character - TNB */
- if (player_bold(y, x))
- {
- if (is_friend) return (FALSE);
- }
+ if (player_bold(target_ptr, y, x) && is_friend) return FALSE;
}
- return (TRUE);
+ return TRUE;
}
+
/*!
* @brief モンスターのボルト型魔法処理 /
* Cast a bolt at the player Stop if we hit a monster Affect monsters and the player
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param m_idx モンスターのID
* @param y 目標のY座標
* @param x 目標のX座標
* @param target_type モンスターからモンスターへ撃つならMONSTER_TO_MONSTER、モンスターからプレイヤーならMONSTER_TO_PLAYER
* @return なし
*/
-void bolt(MONSTER_IDX m_idx, POSITION y, POSITION x, EFFECT_ID typ, int dam_hp, int monspell, int target_type)
- {
- BIT_FLAGS flg = 0;
- bool learnable = spell_learnable(m_idx);
-
- switch (target_type)
- {
- case MONSTER_TO_MONSTER:
- flg = PROJECT_STOP | PROJECT_KILL;
- break;
- case MONSTER_TO_PLAYER:
- flg = PROJECT_STOP | PROJECT_KILL | PROJECT_PLAYER;
- break;
- }
- if (typ != GF_ARROW) flg |= PROJECT_REFLECTABLE;
+void bolt(player_type *target_ptr, MONSTER_IDX m_idx, POSITION y, POSITION x, EFFECT_ID typ, int dam_hp, int monspell, int target_type)
+{
+ BIT_FLAGS flg = 0;
+ switch (target_type)
+ {
+ case MONSTER_TO_MONSTER:
+ flg = PROJECT_STOP | PROJECT_KILL;
+ break;
+ case MONSTER_TO_PLAYER:
+ flg = PROJECT_STOP | PROJECT_KILL | PROJECT_PLAYER;
+ break;
+ }
/* Target the player with a bolt attack */
- (void)project(m_idx, 0, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
+ if (typ != GF_ARROW) flg |= PROJECT_REFLECTABLE;
+ bool learnable = spell_learnable(target_ptr, m_idx);
+ (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
}
+
/*!
* @brief モンスターのビーム型魔法処理 /
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param m_idx モンスターのID
* @param y 目標のY座標
* @param x 目標のX座標
* @param target_type モンスターからモンスターへ撃つならMONSTER_TO_MONSTER、モンスターからプレイヤーならMONSTER_TO_PLAYER
* @return なし
*/
-void beam(MONSTER_IDX m_idx, POSITION y, POSITION x, EFFECT_ID typ, int dam_hp, int monspell, int target_type)
+void beam(player_type *target_ptr, MONSTER_IDX m_idx, POSITION y, POSITION x, EFFECT_ID typ, int dam_hp, int monspell, int target_type)
{
- BIT_FLAGS flg = 0;
- bool learnable = spell_learnable(m_idx);
-
- switch (target_type)
- {
- case MONSTER_TO_MONSTER:
- flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_THRU;
- break;
- case MONSTER_TO_PLAYER:
- flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_THRU | PROJECT_PLAYER;
- break;
- }
+ BIT_FLAGS flg = 0;
+ switch (target_type)
+ {
+ case MONSTER_TO_MONSTER:
+ flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_THRU;
+ break;
+ case MONSTER_TO_PLAYER:
+ flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_THRU | PROJECT_PLAYER;
+ break;
+ }
/* Target the player with a bolt attack */
- (void)project(m_idx, 0, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
+ bool learnable = spell_learnable(target_ptr, m_idx);
+ (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
}
/*!
* @brief モンスターのボール型&ブレス型魔法処理 /
* 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
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param y 目標地点のY座標
* @param x 目標地点のX座標
* @param m_idx モンスターのID
* @param typ 効果属性ID
* @param dam_hp 威力
* @param rad 半径
- * @param breath
+ * @param breath
* @param monspell モンスター魔法のID
* @param target_type モンスターからモンスターへ撃つならMONSTER_TO_MONSTER、モンスターからプレイヤーならMONSTER_TO_PLAYER
* @return なし
*/
-void breath(POSITION y, POSITION x, MONSTER_IDX m_idx, EFFECT_ID typ, int dam_hp, POSITION rad, bool breath, int monspell, int target_type)
+void breath(player_type *target_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, EFFECT_ID typ, int dam_hp, POSITION rad, bool breath, int monspell, int target_type)
{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
- bool learnable = spell_learnable(m_idx);
+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
BIT_FLAGS flg = 0x00;
-
- switch (target_type)
- {
- case MONSTER_TO_MONSTER:
- flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
- break;
- case MONSTER_TO_PLAYER:
- flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_PLAYER;
- break;
- }
+ switch (target_type)
+ {
+ case MONSTER_TO_MONSTER:
+ flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
+ break;
+ case MONSTER_TO_PLAYER:
+ flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_PLAYER;
+ break;
+ }
/* Determine the radius of the blast */
if ((rad < 1) && breath) rad = (r_ptr->flags2 & (RF2_POWERFUL)) ? 3 : 2;
}
/* Target the player with a ball attack */
- (void)project(m_idx, rad, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
+ bool learnable = spell_learnable(target_ptr, m_idx);
+ (void)project(target_ptr, m_idx, rad, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
}
-
-
/*!
* @brief ID値が正しいモンスター魔法IDかどうかを返す /
* 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 and dispel) */
- if (spell < 128 && spell > 98) return (TRUE);
+ if (spell < 128 && spell > 98) return TRUE;
/* Various "ball" spells */
- if (spell >= 128 && spell <= 128 + 8) return (TRUE);
+ if (spell >= 128 && spell <= 128 + 8) return TRUE;
/* "Cause wounds" and "bolt" spells */
- if (spell >= 128 + 12 && spell < 128 + 27) return (TRUE);
+ if (spell >= 128 + 12 && spell < 128 + 27) return TRUE;
/* Hand of Doom */
- if (spell == 160 + 1) return (TRUE);
+ if (spell == 160 + 1) return TRUE;
/* Psycho-Spear */
- if (spell == 160 + 11) return (TRUE);
+ if (spell == 160 + 11) return TRUE;
/* Doesn't hurt */
- return (FALSE);
+ return FALSE;
}
static bool spell_escape(byte spell)
{
/* Blink or Teleport */
- if (spell == 160 + 4 || spell == 160 + 5) return (TRUE);
+ if (spell == 160 + 4 || spell == 160 + 5) return TRUE;
/* Teleport the player away */
- if (spell == 160 + 9 || spell == 160 + 10) return (TRUE);
+ if (spell == 160 + 9 || spell == 160 + 10) return TRUE;
/* Isn't good for escaping */
- return (FALSE);
+ return FALSE;
}
+
/*!
* @brief ID値が妨害目的に適したモンスター魔法IDかどうかを返す /
* Return TRUE if a spell is good for annoying the player.
static bool spell_annoy(byte spell)
{
/* Shriek */
- if (spell == 96 + 0) return (TRUE);
+ if (spell == 96 + 0) return TRUE;
/* Brain smash, et al (added curses) */
- if (spell >= 128 + 9 && spell <= 128 + 14) return (TRUE);
+ if (spell >= 128 + 9 && spell <= 128 + 14) return TRUE;
/* Scare, confuse, blind, slow, paralyze */
- if (spell >= 128 + 27 && spell <= 128 + 31) return (TRUE);
+ if (spell >= 128 + 27 && spell <= 128 + 31) return TRUE;
/* Teleport to */
- if (spell == 160 + 8) return (TRUE);
+ if (spell == 160 + 8) return TRUE;
/* Teleport level */
- if (spell == 160 + 10) return (TRUE);
+ if (spell == 160 + 10) return TRUE;
/* Darkness, make traps, cause amnesia */
- if (spell >= 160 + 12 && spell <= 160 + 14) return (TRUE);
+ if (spell >= 160 + 12 && spell <= 160 + 14) return TRUE;
/* Doesn't annoy */
- return (FALSE);
+ return FALSE;
}
+
/*!
* @brief ID値が召喚型のモンスター魔法IDかどうかを返す /
* Return TRUE if a spell is good for annoying the player.
static bool spell_summon(byte spell)
{
/* All summon spells */
- if (spell >= 160 + 16) return (TRUE);
+ if (spell >= 160 + 16) return TRUE;
/* Doesn't summon */
- return (FALSE);
+ return FALSE;
}
static bool spell_raise(byte spell)
{
/* All raise-dead spells */
- if (spell == 160 + 15) return (TRUE);
+ if (spell == 160 + 15) return TRUE;
/* Doesn't summon */
- return (FALSE);
+ return FALSE;
}
+
/*!
* @brief ID値が戦術的なモンスター魔法IDかどうかを返す /
* Return TRUE if a spell is good in a tactical situation.
static bool spell_tactic(byte spell)
{
/* Blink */
- if (spell == 160 + 4) return (TRUE);
+ if (spell == 160 + 4) return TRUE;
/* Not good */
- return (FALSE);
+ return FALSE;
}
+
/*!
* @brief ID値が無敵化するモンスター魔法IDかどうかを返す /
* Return TRUE if a spell makes invulnerable.
static bool spell_invulner(byte spell)
{
/* Invulnerability */
- if (spell == 160 + 3) return (TRUE);
+ if (spell == 160 + 3) return TRUE;
/* No invulnerability */
- return (FALSE);
+ return FALSE;
}
+
/*!
* @brief ID値が加速するモンスター魔法IDかどうかを返す /
* Return TRUE if a spell hastes.
static bool spell_haste(byte spell)
{
/* Haste self */
- if (spell == 160 + 0) return (TRUE);
+ if (spell == 160 + 0) return TRUE;
/* Not a haste spell */
- return (FALSE);
+ return FALSE;
}
*/
static bool spell_world(byte spell)
{
- if (spell == 160 + 6) return (TRUE);
- return (FALSE);
+ if (spell == 160 + 6) return TRUE;
+ return FALSE;
}
/*!
* @brief ID値が特別効果のモンスター魔法IDかどうかを返す /
* Return TRUE if a spell special.
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param spell 判定対象のID
* @return 特別効果魔法のIDならばTRUEを返す。
*/
-static bool spell_special(byte spell)
+static bool spell_special(player_type *target_ptr, byte spell)
{
- if (p_ptr->inside_battle) return FALSE;
- if (spell == 160 + 7) return (TRUE);
- return (FALSE);
+ if (target_ptr->phase_out) return FALSE;
+ if (spell == 160 + 7) return TRUE;
+ return FALSE;
}
static bool spell_psy_spe(byte spell)
{
/* world */
- if (spell == 160 + 11) return (TRUE);
+ if (spell == 160 + 11) return TRUE;
/* Not a haste spell */
- return (FALSE);
+ return FALSE;
}
static bool spell_heal(byte spell)
{
/* Heal */
- if (spell == 160 + 2) return (TRUE);
+ if (spell == 160 + 2) return TRUE;
/* No healing */
- return (FALSE);
+ return FALSE;
}
static bool spell_dispel(byte spell)
{
/* Dispel */
- if (spell == 96 + 2) return (TRUE);
+ if (spell == 96 + 2) return TRUE;
/* No dispel */
- return (FALSE);
+ return FALSE;
}
* @param m_idx モンスターの構造体配列ID
* @return 魔力消去をかけるべきならTRUEを返す。
*/
-bool dispel_check(MONSTER_IDX m_idx)
+bool dispel_check(player_type *creature_ptr, MONSTER_IDX m_idx)
{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
-
/* Invulnabilty (including the song) */
- if (IS_INVULN()) return (TRUE);
+ if (IS_INVULN(creature_ptr)) return TRUE;
/* Wraith form */
- if (p_ptr->wraith_form) return (TRUE);
+ if (creature_ptr->wraith_form) return TRUE;
/* Shield */
- if (p_ptr->shield) return (TRUE);
+ if (creature_ptr->shield) return TRUE;
/* Magic defence */
- if (p_ptr->magicdef) return (TRUE);
+ if (creature_ptr->magicdef) return TRUE;
/* Multi Shadow */
- if (p_ptr->multishadow) return (TRUE);
+ if (creature_ptr->multishadow) return TRUE;
/* Robe of dust */
- if (p_ptr->dustrobe) return (TRUE);
+ if (creature_ptr->dustrobe) return TRUE;
/* Berserk Strength */
- if (p_ptr->shero && (p_ptr->pclass != CLASS_BERSERKER)) return (TRUE);
+ if (creature_ptr->shero && (creature_ptr->pclass != CLASS_BERSERKER)) return TRUE;
/* Demon Lord */
- if (p_ptr->mimic_form == MIMIC_DEMON_LORD) return (TRUE);
+ if (creature_ptr->mimic_form == MIMIC_DEMON_LORD) return TRUE;
/* Elemental resistances */
+ monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[m_idx];
+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
if (r_ptr->flags4 & RF4_BR_ACID)
{
- if (!p_ptr->immune_acid && (p_ptr->oppose_acid || music_singing(MUSIC_RESIST))) return (TRUE);
- if (p_ptr->special_defense & DEFENSE_ACID) return (TRUE);
+ if (!creature_ptr->immune_acid && (creature_ptr->oppose_acid || music_singing(creature_ptr, MUSIC_RESIST))) return TRUE;
+ if (creature_ptr->special_defense & DEFENSE_ACID) return TRUE;
}
if (r_ptr->flags4 & RF4_BR_FIRE)
{
- if (!((p_ptr->prace == RACE_DEMON) && p_ptr->lev > 44))
+ if (!((creature_ptr->prace == RACE_DEMON) && creature_ptr->lev > 44))
{
- if (!p_ptr->immune_fire && (p_ptr->oppose_fire || music_singing(MUSIC_RESIST))) return (TRUE);
- if (p_ptr->special_defense & DEFENSE_FIRE) return (TRUE);
+ if (!creature_ptr->immune_fire && (creature_ptr->oppose_fire || music_singing(creature_ptr, MUSIC_RESIST))) return TRUE;
+ if (creature_ptr->special_defense & DEFENSE_FIRE) return TRUE;
}
}
if (r_ptr->flags4 & RF4_BR_ELEC)
{
- if (!p_ptr->immune_elec && (p_ptr->oppose_elec || music_singing(MUSIC_RESIST))) return (TRUE);
- if (p_ptr->special_defense & DEFENSE_ELEC) return (TRUE);
+ if (!creature_ptr->immune_elec && (creature_ptr->oppose_elec || music_singing(creature_ptr, MUSIC_RESIST))) return TRUE;
+ if (creature_ptr->special_defense & DEFENSE_ELEC) return TRUE;
}
if (r_ptr->flags4 & RF4_BR_COLD)
{
- if (!p_ptr->immune_cold && (p_ptr->oppose_cold || music_singing(MUSIC_RESIST))) return (TRUE);
- if (p_ptr->special_defense & DEFENSE_COLD) return (TRUE);
+ if (!creature_ptr->immune_cold && (creature_ptr->oppose_cold || music_singing(creature_ptr, MUSIC_RESIST))) return TRUE;
+ if (creature_ptr->special_defense & DEFENSE_COLD) return TRUE;
}
if (r_ptr->flags4 & (RF4_BR_POIS | RF4_BR_NUKE))
{
- if (!((p_ptr->pclass == CLASS_NINJA) && p_ptr->lev > 44))
+ if (!((creature_ptr->pclass == CLASS_NINJA) && creature_ptr->lev > 44))
{
- if (p_ptr->oppose_pois || music_singing(MUSIC_RESIST)) return (TRUE);
- if (p_ptr->special_defense & DEFENSE_POIS) return (TRUE);
+ if (creature_ptr->oppose_pois || music_singing(creature_ptr, MUSIC_RESIST)) return TRUE;
+ if (creature_ptr->special_defense & DEFENSE_POIS) return TRUE;
}
}
/* Ultimate resistance */
- if (p_ptr->ult_res) return (TRUE);
+ if (creature_ptr->ult_res) return TRUE;
/* Potion of Neo Tsuyosi special */
- if (p_ptr->tsuyoshi) return (TRUE);
+ if (creature_ptr->tsuyoshi) return TRUE;
/* Elemental Brands */
- if ((p_ptr->special_attack & ATTACK_ACID) && !(r_ptr->flagsr & RFR_EFF_IM_ACID_MASK)) return (TRUE);
- if ((p_ptr->special_attack & ATTACK_FIRE) && !(r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK)) return (TRUE);
- if ((p_ptr->special_attack & ATTACK_ELEC) && !(r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK)) return (TRUE);
- if ((p_ptr->special_attack & ATTACK_COLD) && !(r_ptr->flagsr & RFR_EFF_IM_COLD_MASK)) return (TRUE);
- if ((p_ptr->special_attack & ATTACK_POIS) && !(r_ptr->flagsr & RFR_EFF_IM_POIS_MASK)) return (TRUE);
+ if ((creature_ptr->special_attack & ATTACK_ACID) && !(r_ptr->flagsr & RFR_EFF_IM_ACID_MASK)) return TRUE;
+ if ((creature_ptr->special_attack & ATTACK_FIRE) && !(r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK)) return TRUE;
+ if ((creature_ptr->special_attack & ATTACK_ELEC) && !(r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK)) return TRUE;
+ if ((creature_ptr->special_attack & ATTACK_COLD) && !(r_ptr->flagsr & RFR_EFF_IM_COLD_MASK)) return TRUE;
+ if ((creature_ptr->special_attack & ATTACK_POIS) && !(r_ptr->flagsr & RFR_EFF_IM_POIS_MASK)) return TRUE;
- /* Speed */
- if (p_ptr->pspeed < 145)
+ if (creature_ptr->pspeed < 145)
{
- if (IS_FAST()) return (TRUE);
+ if (IS_FAST(creature_ptr)) return TRUE;
}
/* Light speed */
- if (p_ptr->lightspeed && (m_ptr->mspeed < 136)) return (TRUE);
+ if (creature_ptr->lightspeed && (m_ptr->mspeed < 136)) return TRUE;
- if (p_ptr->riding && (m_list[p_ptr->riding].mspeed < 135))
+ if (creature_ptr->riding && (creature_ptr->current_floor_ptr->m_list[creature_ptr->riding].mspeed < 135))
{
- if (MON_FAST(&m_list[p_ptr->riding])) return (TRUE);
+ if (MON_FAST(&creature_ptr->current_floor_ptr->m_list[creature_ptr->riding])) return TRUE;
}
/* No need to cast dispel spell */
- return (FALSE);
+ return FALSE;
}
/*!
+ * todo 長過ぎる。切り分けが必要
* @brief モンスターの魔法選択ルーチン
* Have a monster choose a spell from a list of "useful" spells.
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param m_idx モンスターの構造体配列ID
* @param spells 候補魔法IDをまとめた配列
* @param num spellsの長さ
*\n
* This function may well be an efficiency bottleneck.\n
*/
-static int choose_attack_spell(MONSTER_IDX m_idx, byte spells[], byte num)
+static int choose_attack_spell(player_type *target_ptr, MONSTER_IDX m_idx, byte spells[], byte num)
{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
-
byte escape[96], escape_num = 0;
byte attack[96], attack_num = 0;
byte summon[96], summon_num = 0;
byte heal[96], heal_num = 0;
byte dispel[96], dispel_num = 0;
- int i;
-
/* Stupid monsters choose randomly */
- if (r_ptr->flags2 & (RF2_STUPID))
- {
- /* Pick at random */
- return (spells[randint0(num)]);
- }
+ monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
+ if (r_ptr->flags2 & (RF2_STUPID)) return (spells[randint0(num)]);
/* Categorize spells */
- for (i = 0; i < num; i++)
+ for (int i = 0; i < num; i++)
{
/* Escape spell? */
if (spell_escape(spells[i])) escape[escape_num++] = spells[i];
if (spell_world(spells[i])) world[world_num++] = spells[i];
/* Special spell? */
- if (spell_special(spells[i])) special[special_num++] = spells[i];
+ if (spell_special(target_ptr, spells[i])) special[special_num++] = spells[i];
/* Psycho-spear spell? */
if (spell_psy_spe(spells[i])) psy_spe[psy_spe_num++] = spells[i];
/*** Try to pick an appropriate spell type ***/
/* world */
- if (world_num && (randint0(100) < 15) && !world_monster)
+ if (world_num && (randint0(100) < 15) && !current_world_ptr->timewalk_m_idx)
{
/* Choose haste spell */
return (world[randint0(world_num)]);
if (special_num)
{
bool success = FALSE;
- switch(m_ptr->r_idx)
+ switch (m_ptr->r_idx)
{
- case MON_BANOR:
- case MON_LUPART:
- if ((m_ptr->hp < m_ptr->maxhp / 2) && r_info[MON_BANOR].max_num && r_info[MON_LUPART].max_num) success = TRUE;
- break;
- default: break;
+ case MON_BANOR:
+ case MON_LUPART:
+ if ((m_ptr->hp < m_ptr->maxhp / 2) && r_info[MON_BANOR].max_num && r_info[MON_LUPART].max_num) success = TRUE;
+ break;
+ default: break;
}
+
if (success) return (special[randint0(special_num)]);
}
bool success = FALSE;
switch (m_ptr->r_idx)
{
- case MON_OHMU:
- case MON_BANOR:
- case MON_LUPART:
- break;
- case MON_BANORLUPART:
- if (randint0(100) < 70) success = TRUE;
- break;
- case MON_ROLENTO:
- if (randint0(100) < 40) success = TRUE;
- break;
- default:
- if (randint0(100) < 50) success = TRUE;
- break;
+ case MON_OHMU:
+ case MON_BANOR:
+ case MON_LUPART:
+ break;
+ case MON_BANORLUPART:
+ if (randint0(100) < 70) success = TRUE;
+ break;
+ case MON_ROLENTO:
+ if (randint0(100) < 40) success = TRUE;
+ break;
+ default:
+ if (randint0(100) < 50) success = TRUE;
+ break;
}
if (success) return (special[randint0(special_num)]);
}
/* Player is close and we have attack spells, blink away */
- if ((distance(p_ptr->y, p_ptr->x, m_ptr->fy, m_ptr->fx) < 4) && (attack_num || (r_ptr->a_ability_flags2 & RF6_TRAPS)) && (randint0(100) < 75) && !world_monster)
+ if ((distance(target_ptr->y, target_ptr->x, m_ptr->fy, m_ptr->fx) < 4) && (attack_num || (r_ptr->a_ability_flags2 & RF6_TRAPS)) && (randint0(100) < 75) && !current_world_ptr->timewalk_m_idx)
{
/* Choose tactical spell */
if (tactic_num) return (tactic[randint0(tactic_num)]);
if (dispel_num && one_in_(2))
{
/* Choose dispel spell if possible */
- if (dispel_check(m_idx))
+ if (dispel_check(target_ptr, m_idx))
{
return (dispel[randint0(dispel_num)]);
}
}
/* Attack spell (most of the time) */
- if (IS_INVULN())
+ if (IS_INVULN(target_ptr))
{
if (psy_spe_num && (randint0(100) < 50))
{
}
/* Try another tactical spell (sometimes) */
- if (tactic_num && (randint0(100) < 50) && !world_monster)
+ if (tactic_num && (randint0(100) < 50) && !current_world_ptr->timewalk_m_idx)
{
/* Choose tactic spell */
return (tactic[randint0(tactic_num)]);
}
/* Choose no spell */
- return (0);
+ return 0;
}
{
if ((1L << (spell - 32 * 3)) & RF4_NOMAGIC_MASK) return TRUE;
}
- else if (spell < 32 * 5) /* Set RF5 */
+
+ if (spell < 32 * 5) /* Set RF5 */
{
if ((1L << (spell - 32 * 4)) & RF5_NOMAGIC_MASK) return TRUE;
}
- else if (spell < 32 * 6) /* Set RF6 */
+
+ if (spell < 32 * 6) /* Set RF6 */
{
if ((1L << (spell - 32 * 5)) & RF6_NOMAGIC_MASK) return TRUE;
}
/*!
* @brief モンスターがプレイヤーにダメージを与えるための最適な座標を算出する /
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param m_ptr 技能を使用するモンスター構造体の参照ポインタ
* @param yp 最適な目標地点のY座標を返す参照ポインタ
* @param xp 最適な目標地点のX座標を返す参照ポインタ
* @param path_check 射線を判定するための関数ポインタ
* @return 有効な座標があった場合TRUEを返す
*/
-static bool adjacent_grid_check(monster_type *m_ptr, POSITION *yp, POSITION *xp,
- int f_flag, bool (*path_check)(POSITION, POSITION, POSITION, POSITION))
+static bool adjacent_grid_check(player_type *target_ptr, monster_type *m_ptr, POSITION *yp, POSITION *xp,
+ int f_flag, bool(*path_check)(player_type *, POSITION, POSITION, POSITION, POSITION))
{
- int i;
- int tonari;
- static int tonari_y[4][8] = {{-1, -1, -1, 0, 0, 1, 1, 1},
- {-1, -1, -1, 0, 0, 1, 1, 1},
- { 1, 1, 1, 0, 0, -1, -1, -1},
- { 1, 1, 1, 0, 0, -1, -1, -1}};
- static int tonari_x[4][8] = {{-1, 0, 1, -1, 1, -1, 0, 1},
- { 1, 0, -1, 1, -1, 1, 0, -1},
- {-1, 0, 1, -1, 1, -1, 0, 1},
- { 1, 0, -1, 1, -1, 1, 0, -1}};
-
- if (m_ptr->fy < p_ptr->y && m_ptr->fx < p_ptr->x) tonari = 0;
- else if (m_ptr->fy < p_ptr->y) tonari = 1;
- else if (m_ptr->fx < p_ptr->x) tonari = 2;
- else tonari = 3;
-
- for (i = 0; i < 8; i++)
- {
- int next_x = *xp + tonari_x[tonari][i];
- int next_y = *yp + tonari_y[tonari][i];
- cave_type *c_ptr;
+ static int tonari_y[4][8] = { {-1, -1, -1, 0, 0, 1, 1, 1},
+ {-1, -1, -1, 0, 0, 1, 1, 1},
+ { 1, 1, 1, 0, 0, -1, -1, -1},
+ { 1, 1, 1, 0, 0, -1, -1, -1} };
+ static int tonari_x[4][8] = { {-1, 0, 1, -1, 1, -1, 0, 1},
+ { 1, 0, -1, 1, -1, 1, 0, -1},
+ {-1, 0, 1, -1, 1, -1, 0, 1},
+ { 1, 0, -1, 1, -1, 1, 0, -1} };
+
+ int next;
+ if (m_ptr->fy < target_ptr->y && m_ptr->fx < target_ptr->x) next = 0;
+ else if (m_ptr->fy < target_ptr->y) next = 1;
+ else if (m_ptr->fx < target_ptr->x) next = 2;
+ else next = 3;
+
+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
+ for (int i = 0; i < 8; i++)
+ {
+ int next_x = *xp + tonari_x[next][i];
+ int next_y = *yp + tonari_y[next][i];
+ grid_type *g_ptr;
/* Access the next grid */
- c_ptr = &cave[next_y][next_x];
+ g_ptr = &floor_ptr->grid_array[next_y][next_x];
/* Skip this feature */
- if (!cave_have_flag_grid(c_ptr, f_flag)) continue;
+ if (!cave_have_flag_grid(g_ptr, f_flag)) continue;
- if (path_check(m_ptr->fy, m_ptr->fx, next_y, next_x))
+ if (path_check(target_ptr, m_ptr->fy, m_ptr->fx, next_y, next_x))
{
*yp = next_y;
*xp = next_x;
return FALSE;
}
-#define DO_SPELL_NONE 0
-#define DO_SPELL_BR_LITE 1
-#define DO_SPELL_BR_DISI 2
-#define DO_SPELL_BA_LITE 3
/*!
+ * todo メインルーチンの割に長過ぎる。要分割
* @brief モンスターの特殊技能メインルーチン /
* Creatures can cast spells, shoot missiles, and breathe.
+ * @param target_ptr プレーヤーへの参照ポインタ
* @param m_idx モンスター構造体配列のID
* @return 実際に特殊技能を利用したらTRUEを返す
* @details
* Note the special "MFLAG_NICE" flag, which prevents a monster from using\n
* any spell attacks until the player has had a single chance to move.\n
*/
-bool make_attack_spell(MONSTER_IDX m_idx)
+bool make_attack_spell(MONSTER_IDX m_idx, player_type *target_ptr)
{
- int k;
- SPELL_IDX thrown_spell = 0;
- DEPTH rlev;
- PERCENTAGE failrate;
- byte spell[96], num = 0;
- BIT_FLAGS f4, f5, f6;
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
- GAME_TEXT m_name[MAX_NLEN];
-#ifndef JP
+#ifdef JP
+#else
+
char m_poss[80];
#endif
- bool no_inate = FALSE;
- bool do_spell = DO_SPELL_NONE;
- int dam = 0;
-
- POSITION x = p_ptr->x;
- POSITION y = p_ptr->y;
-
- /* Target location for lite breath */
- POSITION x_br_lite = 0;
- POSITION y_br_lite = 0;
-
/* Extract the "see-able-ness" */
- bool seen = (!p_ptr->blind && m_ptr->ml);
- bool maneable = player_has_los_bold(m_ptr->fy, m_ptr->fx);
-
- /* Check "projectable" */
- bool direct;
-
- bool in_no_magic_dungeon = (d_info[dungeon_type].flags1 & DF1_NO_MAGIC) && dun_level
- && (!p_ptr->inside_quest || is_fixed_quest_idx(p_ptr->inside_quest));
-
- bool can_use_lite_area = FALSE;
-
- bool can_remember;
+ floor_type *floor_ptr = target_ptr->current_floor_ptr;
+ monster_type *m_ptr = &floor_ptr->m_list[m_idx];
+ monster_race *r_ptr = &r_info[m_ptr->r_idx];
/* Cannot cast spells when confused */
if (MON_CONFUSED(m_ptr))
{
reset_target(m_ptr);
- return (FALSE);
+ return FALSE;
}
/* Cannot cast spells when nice */
- if (m_ptr->mflag & MFLAG_NICE) return (FALSE);
- if (!is_hostile(m_ptr)) return (FALSE);
+ if (m_ptr->mflag & MFLAG_NICE) return FALSE;
+ if (!is_hostile(m_ptr)) return FALSE;
/* Sometimes forbid inate attacks (breaths) */
+ bool no_inate = FALSE;
if (randint0(100) >= (r_ptr->freq_spell * 2)) no_inate = TRUE;
- /* Handle "track_target" option (?) */
-
-
/* Extract the racial spell flags */
- f4 = r_ptr->flags4;
- f5 = r_ptr->a_ability_flags1;
- f6 = r_ptr->a_ability_flags2;
+ BIT_FLAGS f4 = r_ptr->flags4;
+ BIT_FLAGS f5 = r_ptr->a_ability_flags1;
+ BIT_FLAGS f6 = r_ptr->a_ability_flags2;
/*** require projectable player ***/
/* Check range */
- if ((m_ptr->cdis > MAX_RANGE) && !m_ptr->target_y) return (FALSE);
+ if ((m_ptr->cdis > MAX_RANGE) && !m_ptr->target_y) return FALSE;
/* Check path for lite breath */
+ POSITION x = target_ptr->x;
+ POSITION y = target_ptr->y;
+ POSITION x_br_lite = 0;
+ POSITION y_br_lite = 0;
if (f4 & RF4_BR_LITE)
{
y_br_lite = y;
x_br_lite = x;
- if (los(m_ptr->fy, m_ptr->fx, y_br_lite, x_br_lite))
+ if (los(target_ptr, m_ptr->fy, m_ptr->fx, y_br_lite, x_br_lite))
{
- feature_type *f_ptr = &f_info[cave[y_br_lite][x_br_lite].feat];
+ feature_type *f_ptr = &f_info[floor_ptr->grid_array[y_br_lite][x_br_lite].feat];
if (!have_flag(f_ptr->flags, FF_LOS))
{
}
/* Check path to next grid */
- else if (!adjacent_grid_check(m_ptr, &y_br_lite, &x_br_lite, FF_LOS, los)) f4 &= ~(RF4_BR_LITE);
+ else if (!adjacent_grid_check(target_ptr, m_ptr, &y_br_lite, &x_br_lite, FF_LOS, los)) f4 &= ~(RF4_BR_LITE);
/* Don't breath lite to the wall if impossible */
if (!(f4 & RF4_BR_LITE))
}
/* Check path */
- if (projectable(m_ptr->fy, m_ptr->fx, y, x))
+ bool do_spell = DO_SPELL_NONE;
+ if (projectable(target_ptr, m_ptr->fy, m_ptr->fx, y, x))
{
- feature_type *f_ptr = &f_info[cave[y][x].feat];
+ feature_type *f_ptr = &f_info[floor_ptr->grid_array[y][x].feat];
if (!have_flag(f_ptr->flags, FF_PROJECT))
{
{
bool success = FALSE;
- if ((f4 & RF4_BR_DISI) && (m_ptr->cdis < MAX_RANGE/2) &&
- in_disintegration_range(m_ptr->fy, m_ptr->fx, y, x) &&
- (one_in_(10) || (projectable(y, x, m_ptr->fy, m_ptr->fx) && one_in_(2))))
+ if ((f4 & RF4_BR_DISI) && (m_ptr->cdis < MAX_RANGE / 2) &&
+ in_disintegration_range(floor_ptr, m_ptr->fy, m_ptr->fx, y, x) &&
+ (one_in_(10) || (projectable(target_ptr, y, x, m_ptr->fy, m_ptr->fx) && one_in_(2))))
{
do_spell = DO_SPELL_BR_DISI;
success = TRUE;
}
- else if ((f4 & RF4_BR_LITE) && (m_ptr->cdis < MAX_RANGE/2) &&
- los(m_ptr->fy, m_ptr->fx, y, x) && one_in_(5))
+ else if ((f4 & RF4_BR_LITE) && (m_ptr->cdis < MAX_RANGE / 2) &&
+ los(target_ptr, m_ptr->fy, m_ptr->fx, y, x) && one_in_(5))
{
do_spell = DO_SPELL_BR_LITE;
success = TRUE;
else if ((f5 & RF5_BA_LITE) && (m_ptr->cdis <= MAX_RANGE))
{
POSITION by = y, bx = x;
- get_project_point(m_ptr->fy, m_ptr->fx, &by, &bx, 0L);
- if ((distance(by, bx, y, x) <= 3) && los(by, bx, y, x) && one_in_(5))
+ get_project_point(target_ptr, m_ptr->fy, m_ptr->fx, &by, &bx, 0L);
+ if ((distance(by, bx, y, x) <= 3) && los(target_ptr, by, bx, y, x) && one_in_(5))
{
do_spell = DO_SPELL_BA_LITE;
success = TRUE;
}
}
- if (!success) success = adjacent_grid_check(m_ptr, &y, &x, FF_PROJECT, projectable);
+ if (!success) success = adjacent_grid_check(target_ptr, m_ptr, &y, &x, FF_PROJECT, projectable);
if (!success)
{
success = TRUE;
}
- if (y_br_lite && x_br_lite && (m_ptr->cdis < MAX_RANGE/2) && one_in_(5))
+ if (y_br_lite && x_br_lite && (m_ptr->cdis < MAX_RANGE / 2) && one_in_(5))
{
if (!success)
{
reset_target(m_ptr);
- rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
+ DEPTH rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
/* Forbid inate attacks sometimes */
if (no_inate)
f6 &= ~(RF6_NOMAGIC_MASK);
}
+ bool can_use_lite_area = FALSE;
if (f6 & RF6_DARKNESS)
{
- if ((p_ptr->pclass == CLASS_NINJA) &&
- !(r_ptr->flags3 & (RF3_UNDEAD | RF3_HURT_LITE)) &&
- !(r_ptr->flags7 & RF7_DARK_MASK))
+ if ((target_ptr->pclass == CLASS_NINJA) &&
+ !(r_ptr->flags3 & (RF3_UNDEAD | RF3_HURT_LITE)) &&
+ !(r_ptr->flags7 & RF7_DARK_MASK))
can_use_lite_area = TRUE;
if (!(r_ptr->flags2 & RF2_STUPID))
{
- if (d_info[dungeon_type].flags1 & DF1_DARKNESS) f6 &= ~(RF6_DARKNESS);
- else if ((p_ptr->pclass == CLASS_NINJA) && !can_use_lite_area) f6 &= ~(RF6_DARKNESS);
+ if (d_info[target_ptr->dungeon_idx].flags1 & DF1_DARKNESS) f6 &= ~(RF6_DARKNESS);
+ else if ((target_ptr->pclass == CLASS_NINJA) && !can_use_lite_area) f6 &= ~(RF6_DARKNESS);
}
}
+ bool in_no_magic_dungeon = (d_info[target_ptr->dungeon_idx].flags1 & DF1_NO_MAGIC) && floor_ptr->dun_level
+ && (!floor_ptr->inside_quest || is_fixed_quest_idx(floor_ptr->inside_quest));
if (in_no_magic_dungeon && !(r_ptr->flags2 & RF2_STUPID))
{
f4 &= (RF4_NOMAGIC_MASK);
}
/* Hack -- decline "teleport level" in some case */
- if ((f6 & RF6_TELE_LEVEL) && TELE_LEVEL_IS_INEFF(0))
+ if ((f6 & RF6_TELE_LEVEL) && is_teleport_level_ineffective(target_ptr, 0))
{
f6 &= ~(RF6_TELE_LEVEL);
}
}
/* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
+ if (!f4 && !f5 && !f6) return FALSE;
/* Remove the "ineffective" spells */
- remove_bad_spells(m_idx, &f4, &f5, &f6);
+ remove_bad_spells(m_idx, target_ptr, &f4, &f5, &f6);
- if (p_ptr->inside_arena || p_ptr->inside_battle)
+ if (floor_ptr->inside_arena || target_ptr->phase_out)
{
f4 &= ~(RF4_SUMMON_MASK);
f5 &= ~(RF5_SUMMON_MASK);
}
/* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
+ if (!f4 && !f5 && !f6) return FALSE;
if (!(r_ptr->flags2 & RF2_STUPID))
{
- if (!p_ptr->csp) f5 &= ~(RF5_DRAIN_MANA);
+ if (!target_ptr->csp) f5 &= ~(RF5_DRAIN_MANA);
/* Check for a clean bolt shot */
if (((f4 & RF4_BOLT_MASK) ||
- (f5 & RF5_BOLT_MASK) ||
- (f6 & RF6_BOLT_MASK)) &&
- !clean_shot(m_ptr->fy, m_ptr->fx, p_ptr->y, p_ptr->x, FALSE))
+ (f5 & RF5_BOLT_MASK) ||
+ (f6 & RF6_BOLT_MASK)) &&
+ !clean_shot(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x, FALSE))
{
/* Remove spells that will only hurt friends */
f4 &= ~(RF4_BOLT_MASK);
/* Check for a possible summon */
if (((f4 & RF4_SUMMON_MASK) ||
- (f5 & RF5_SUMMON_MASK) ||
- (f6 & RF6_SUMMON_MASK)) &&
- !(summon_possible(y, x)))
+ (f5 & RF5_SUMMON_MASK) ||
+ (f6 & RF6_SUMMON_MASK)) &&
+ !(summon_possible(target_ptr, y, x)))
{
/* Remove summoning spells */
f4 &= ~(RF4_SUMMON_MASK);
}
/* Check for a possible raise dead */
- if ((f6 & RF6_RAISE_DEAD) && !raise_possible(m_ptr))
+ if ((f6 & RF6_RAISE_DEAD) && !raise_possible(target_ptr, m_ptr))
{
/* Remove raise dead spell */
f6 &= ~(RF6_RAISE_DEAD);
/* Special moves restriction */
if (f6 & RF6_SPECIAL)
{
- if ((m_ptr->r_idx == MON_ROLENTO) && !summon_possible(y, x))
+ if ((m_ptr->r_idx == MON_ROLENTO) && !summon_possible(target_ptr, y, x))
{
f6 &= ~(RF6_SPECIAL);
}
}
/* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
+ if (!f4 && !f5 && !f6) return FALSE;
}
/* Extract the "inate" spells */
- for (k = 0; k < 32; k++)
+ byte spell[96], num = 0;
+ for (int k = 0; k < 32; k++)
{
- if (f4 & (1L << k)) spell[num++] = k + RF4_SPELL_START;
+ if (f4 & (1L << k)) spell[num++] = k + RF4_SPELL_START;
}
/* Extract the "normal" spells */
- for (k = 0; k < 32; k++)
+ for (int k = 0; k < 32; k++)
{
- if (f5 & (1L << k)) spell[num++] = k + RF5_SPELL_START;
+ if (f5 & (1L << k)) spell[num++] = k + RF5_SPELL_START;
}
/* Extract the "bizarre" spells */
- for (k = 0; k < 32; k++)
+ for (int k = 0; k < 32; k++)
{
- if (f6 & (1L << k)) spell[num++] = k + RF6_SPELL_START;
+ if (f6 & (1L << k)) spell[num++] = k + RF6_SPELL_START;
}
/* No spells left */
- if (!num) return (FALSE);
+ if (!num) return FALSE;
/* Stop if player is dead or gone */
- if (!p_ptr->playing || p_ptr->is_dead) return (FALSE);
+ if (!target_ptr->playing || target_ptr->is_dead) return FALSE;
/* Stop if player is leaving */
- if (p_ptr->leaving) return (FALSE);
+ if (target_ptr->leaving) return FALSE;
/* Get the monster name (or "it") */
- monster_desc(m_name, m_ptr, 0x00);
+ GAME_TEXT m_name[MAX_NLEN];
+ monster_desc(target_ptr, m_name, m_ptr, 0x00);
+
+#ifdef JP
+#else
-#ifndef JP
/* Get the monster possessive ("his"/"her"/"its") */
monster_desc(m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
#endif
+ SPELL_IDX thrown_spell = 0;
switch (do_spell)
{
case DO_SPELL_NONE:
+ {
+ int attempt = 10;
+ while (attempt--)
{
- int attempt = 10;
- while (attempt--)
- {
- thrown_spell = choose_attack_spell(m_idx, spell, num);
- if (thrown_spell) break;
- }
+ thrown_spell = choose_attack_spell(target_ptr, m_idx, spell, num);
+ if (thrown_spell) break;
}
- break;
+ }
+
+ break;
case DO_SPELL_BR_LITE:
- thrown_spell = 96+14; /* RF4_BR_LITE */
+ thrown_spell = 96 + 14; /* RF4_BR_LITE */
break;
case DO_SPELL_BR_DISI:
- thrown_spell = 96+31; /* RF4_BR_DISI */
+ thrown_spell = 96 + 31; /* RF4_BR_DISI */
break;
case DO_SPELL_BA_LITE:
- thrown_spell = 128+20; /* RF5_BA_LITE */
+ thrown_spell = 128 + 20; /* RF5_BA_LITE */
break;
default:
- return FALSE; /* Paranoia */
+ return FALSE;
}
/* Abort if no spell was chosen */
- if (!thrown_spell) return (FALSE);
+ if (!thrown_spell) return FALSE;
/* Calculate spell failure rate */
- failrate = 25 - (rlev + 3) / 4;
+ PERCENTAGE 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 (!spell_is_inate(thrown_spell)
- && (in_no_magic_dungeon || (MON_STUNNED(m_ptr) && one_in_(2)) || (randint0(100) < failrate)))
+ && (in_no_magic_dungeon || (MON_STUNNED(m_ptr) && one_in_(2)) || (randint0(100) < failrate)))
{
- disturb(TRUE, TRUE);
+ disturb(target_ptr, TRUE, TRUE);
msg_format(_("%^sは呪文を唱えようとしたが失敗した。", "%^s tries to cast a spell, but fails."), m_name);
- return (TRUE);
+ return TRUE;
}
/* Hex: Anti Magic Barrier */
- if (!spell_is_inate(thrown_spell) && magic_barrier(m_idx))
+ if (!spell_is_inate(thrown_spell) && magic_barrier(target_ptr, m_idx))
{
msg_format(_("反魔法バリアが%^sの呪文をかき消した。", "Anti magic barrier cancels the spell which %^s casts."), m_name);
- return (TRUE);
+ return TRUE;
}
/* Projectable? */
- direct = player_bold(y, x);
-
- can_remember = is_original_ap_and_seen(m_ptr);
-
- if (!direct)
- {
- switch (thrown_spell)
- {
- case 96 + 2: /* RF4_DISPEL */
- case 96 + 4: /* RF4_SHOOT */
- case 128 + 9: /* RF5_DRAIN_MANA */
- case 128 + 10: /* RF5_MIND_BLAST */
- case 128 + 11: /* RF5_BRAIN_SMASH */
- case 128 + 12: /* RF5_CAUSE_1 */
- case 128 + 13: /* RF5_CAUSE_2 */
- case 128 + 14: /* RF5_CAUSE_3 */
- case 128 + 15: /* RF5_CAUSE_4 */
- case 128 + 16: /* RF5_BO_ACID */
- case 128 + 17: /* RF5_BO_ELEC */
- case 128 + 18: /* RF5_BO_FIRE */
- case 128 + 19: /* RF5_BO_COLD */
- case 128 + 21: /* RF5_BO_NETH */
- case 128 + 22: /* RF5_BO_WATE */
- case 128 + 23: /* RF5_BO_MANA */
- case 128 + 24: /* RF5_BO_PLAS */
- case 128 + 25: /* RF5_BO_ICEE */
- case 128 + 26: /* RF5_MISSILE */
- case 128 + 27: /* RF5_SCARE */
- case 128 + 28: /* RF5_BLIND */
- case 128 + 29: /* RF5_CONF */
- case 128 + 30: /* RF5_SLOW */
- case 128 + 31: /* RF5_HOLD */
- case 160 + 1: /* RF6_HAND_DOOM */
- case 160 + 8: /* RF6_TELE_TO */
- case 160 + 9: /* RF6_TELE_AWAY */
- case 160 + 10: /* RF6_TELE_LEVEL */
- case 160 + 11: /* RF6_PSY_SPEAR */
- case 160 + 12: /* RF6_DARKNESS */
- case 160 + 14: /* RF6_FORGET */
- return (FALSE);
- }
- }
-
- /* Cast the spell. */
- dam = monspell_to_player(thrown_spell, y, x, m_idx);
- if (dam < 0) return FALSE;
-
- if ((p_ptr->action == ACTION_LEARN) && thrown_spell > 175)
- {
- learn_spell(thrown_spell - 96);
- }
-
- if (seen && maneable && !world_monster && (p_ptr->pclass == CLASS_IMITATOR))
+ bool direct = player_bold(target_ptr, y, x);
+ bool can_remember = is_original_ap_and_seen(target_ptr, m_ptr);
+ if (!direct)
+ {
+ switch (thrown_spell)
+ {
+ case 96 + 2: /* RF4_DISPEL */
+ case 96 + 4: /* RF4_SHOOT */
+ case 128 + 9: /* RF5_DRAIN_MANA */
+ case 128 + 10: /* RF5_MIND_BLAST */
+ case 128 + 11: /* RF5_BRAIN_SMASH */
+ case 128 + 12: /* RF5_CAUSE_1 */
+ case 128 + 13: /* RF5_CAUSE_2 */
+ case 128 + 14: /* RF5_CAUSE_3 */
+ case 128 + 15: /* RF5_CAUSE_4 */
+ case 128 + 16: /* RF5_BO_ACID */
+ case 128 + 17: /* RF5_BO_ELEC */
+ case 128 + 18: /* RF5_BO_FIRE */
+ case 128 + 19: /* RF5_BO_COLD */
+ case 128 + 21: /* RF5_BO_NETH */
+ case 128 + 22: /* RF5_BO_WATE */
+ case 128 + 23: /* RF5_BO_MANA */
+ case 128 + 24: /* RF5_BO_PLAS */
+ case 128 + 25: /* RF5_BO_ICEE */
+ case 128 + 26: /* RF5_MISSILE */
+ case 128 + 27: /* RF5_SCARE */
+ case 128 + 28: /* RF5_BLIND */
+ case 128 + 29: /* RF5_CONF */
+ case 128 + 30: /* RF5_SLOW */
+ case 128 + 31: /* RF5_HOLD */
+ case 160 + 1: /* RF6_HAND_DOOM */
+ case 160 + 8: /* RF6_TELE_TO */
+ case 160 + 9: /* RF6_TELE_AWAY */
+ case 160 + 10: /* RF6_TELE_LEVEL */
+ case 160 + 11: /* RF6_PSY_SPEAR */
+ case 160 + 12: /* RF6_DARKNESS */
+ case 160 + 14: /* RF6_FORGET */
+ return FALSE;
+ }
+ }
+
+ /* Cast the spell. */
+ int dam = monspell_to_player(thrown_spell, target_ptr, y, x, m_idx);
+ if (dam < 0) return FALSE;
+
+ if ((target_ptr->action == ACTION_LEARN) && thrown_spell > 175)
+ {
+ learn_spell(target_ptr, thrown_spell - 96);
+ }
+
+ bool seen = (!target_ptr->blind && m_ptr->ml);
+ bool maneable = player_has_los_bold(target_ptr, m_ptr->fy, m_ptr->fx);
+ if (seen && maneable && !current_world_ptr->timewalk_m_idx && (target_ptr->pclass == CLASS_IMITATOR))
{
if (thrown_spell != 167) /* Not RF6_SPECIAL */
{
- if (p_ptr->mane_num == MAX_MANE)
+ if (target_ptr->mane_num == MAX_MANE)
{
int i;
- p_ptr->mane_num--;
- for (i = 0;i < p_ptr->mane_num;i++)
+ target_ptr->mane_num--;
+ for (i = 0; i < target_ptr->mane_num; i++)
{
- p_ptr->mane_spell[i] = p_ptr->mane_spell[i+1];
- p_ptr->mane_dam[i] = p_ptr->mane_dam[i+1];
+ target_ptr->mane_spell[i] = target_ptr->mane_spell[i + 1];
+ target_ptr->mane_dam[i] = target_ptr->mane_dam[i + 1];
}
}
- p_ptr->mane_spell[p_ptr->mane_num] = thrown_spell - 96;
- p_ptr->mane_dam[p_ptr->mane_num] = dam;
- p_ptr->mane_num++;
- new_mane = TRUE;
+ target_ptr->mane_spell[target_ptr->mane_num] = thrown_spell - 96;
+ target_ptr->mane_dam[target_ptr->mane_num] = dam;
+ target_ptr->mane_num++;
+ target_ptr->new_mane = TRUE;
- p_ptr->redraw |= (PR_IMITATION);
+ target_ptr->redraw |= (PR_IMITATION);
}
}
}
}
-
/* Always take note of monsters that kill you */
- if (p_ptr->is_dead && (r_ptr->r_deaths < MAX_SHORT) && !p_ptr->inside_arena)
+ if (target_ptr->is_dead && (r_ptr->r_deaths < MAX_SHORT) && !floor_ptr->inside_arena)
{
r_ptr->r_deaths++; /* Ignore appearance difference */
}
/* A spell was cast */
- return (TRUE);
+ return TRUE;
}