OSDN Git Service

Merge pull request #716 from sikabane-works/release/3.0.0Alpha16
[hengbandforosx/hengbandosx.git] / src / mspell / assign-monster-spell.cpp
1 /*!
2  * @brief モンスターのスペル振り分け処理 / Spell launch by a monster
3  * @date 2014/07/14
4  * @author Habu
5  */
6
7 #include "mspell/assign-monster-spell.h"
8 #include "blue-magic/blue-magic-checker.h"
9 #include "mspell/mspell-ball.h"
10 #include "mspell/mspell-bolt.h"
11 #include "mspell/mspell-breath.h"
12 #include "mspell/mspell-curse.h"
13 #include "mspell/mspell-dispel.h"
14 #include "mspell/mspell-floor.h"
15 #include "mspell/mspell-learn-checker.h"
16 #include "mspell/mspell-particularity.h"
17 #include "mspell/mspell-special.h"
18 #include "mspell/mspell-status.h"
19 #include "mspell/mspell-summon.h"
20 #include "mspell/mspell-type.h"
21 #include "mspell/mspell-util.h"
22 #include "mspell/mspell.h"
23 #include "spell/spell-types.h"
24
25 /*!
26  * @brief SPELL_IDX を monster_spell_type に変換する。
27  */
28 static int spell_idx_to_monster_spell_type(const SPELL_IDX idx)
29 {
30     return idx - RF4_SPELL_START;
31 }
32
33 static MonsterSpellResult monspell_to_player_impl(player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx)
34 {
35     // clang-format off
36     switch (ms_type) {
37     case RF4_SPELL_START + 0:  return spell_RF4_SHRIEK(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF4_SHRIEK */
38     case RF4_SPELL_START + 1:  break;   /* RF4_XXX1 */
39     case RF4_SPELL_START + 2:  return spell_RF4_DISPEL(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF4_DISPEL */
40     case RF4_SPELL_START + 3:  return spell_RF4_ROCKET(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_ROCKET */
41     case RF4_SPELL_START + 4:  return spell_RF4_SHOOT(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_SHOOT */
42     case RF4_SPELL_START + 5:  break;   /* RF4_XXX2 */
43     case RF4_SPELL_START + 6:  break;   /* RF4_XXX3 */
44     case RF4_SPELL_START + 7:  break;   /* RF4_XXX4 */
45     case RF4_SPELL_START + 8:  return spell_RF4_BREATH(target_ptr, GF_ACID, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ACID */
46     case RF4_SPELL_START + 9:  return spell_RF4_BREATH(target_ptr, GF_ELEC, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ELEC */
47     case RF4_SPELL_START + 10: return spell_RF4_BREATH(target_ptr, GF_FIRE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_FIRE */
48     case RF4_SPELL_START + 11: return spell_RF4_BREATH(target_ptr, GF_COLD, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_COLD */
49     case RF4_SPELL_START + 12: return spell_RF4_BREATH(target_ptr, GF_POIS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_POIS */
50     case RF4_SPELL_START + 13: return spell_RF4_BREATH(target_ptr, GF_NETHER, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_NETH */
51     case RF4_SPELL_START + 14: return spell_RF4_BREATH(target_ptr, GF_LITE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_LITE */
52     case RF4_SPELL_START + 15: return spell_RF4_BREATH(target_ptr, GF_DARK, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_DARK */
53     case RF4_SPELL_START + 16: return spell_RF4_BREATH(target_ptr, GF_CONFUSION, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_CONF */
54     case RF4_SPELL_START + 17: return spell_RF4_BREATH(target_ptr, GF_SOUND, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_SOUN */
55     case RF4_SPELL_START + 18: return spell_RF4_BREATH(target_ptr, GF_CHAOS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_CHAO */
56     case RF4_SPELL_START + 19: return spell_RF4_BREATH(target_ptr, GF_DISENCHANT, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_DISE */
57     case RF4_SPELL_START + 20: return spell_RF4_BREATH(target_ptr, GF_NEXUS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_NEXU */
58     case RF4_SPELL_START + 21: return spell_RF4_BREATH(target_ptr, GF_TIME, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_TIME */
59     case RF4_SPELL_START + 22: return spell_RF4_BREATH(target_ptr, GF_INERTIAL, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_BR_INER */
60     case RF4_SPELL_START + 23: return spell_RF4_BREATH(target_ptr, GF_GRAVITY, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_BR_GRAV */
61     case RF4_SPELL_START + 24: return spell_RF4_BREATH(target_ptr, GF_SHARDS, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_SHAR */
62     case RF4_SPELL_START + 25: return spell_RF4_BREATH(target_ptr, GF_PLASMA, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_PLAS */
63     case RF4_SPELL_START + 26: return spell_RF4_BREATH(target_ptr, GF_FORCE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_WALL */
64     case RF4_SPELL_START + 27: return spell_RF4_BREATH(target_ptr, GF_MANA, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_MANA */
65     case RF4_SPELL_START + 28: return spell_RF4_BA_NUKE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BA_NUKE */
66     case RF4_SPELL_START + 29: return spell_RF4_BREATH(target_ptr, GF_NUKE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_NUKE */
67     case RF4_SPELL_START + 30: return spell_RF4_BA_CHAO(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BA_CHAO */
68     case RF4_SPELL_START + 31: return spell_RF4_BREATH(target_ptr, GF_DISINTEGRATE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_DISI */
69     case RF5_SPELL_START + 0:  return spell_RF5_BA_ACID(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_ACID */
70     case RF5_SPELL_START + 1:  return spell_RF5_BA_ELEC(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_ELEC */
71     case RF5_SPELL_START + 2:  return spell_RF5_BA_FIRE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_FIRE */
72     case RF5_SPELL_START + 3:  return spell_RF5_BA_COLD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_COLD */
73     case RF5_SPELL_START + 4:  return spell_RF5_BA_POIS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_POIS */
74     case RF5_SPELL_START + 5:  return spell_RF5_BA_NETH(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_NETH */
75     case RF5_SPELL_START + 6:  return spell_RF5_BA_WATE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_WATE */
76     case RF5_SPELL_START + 7:  return spell_RF5_BA_MANA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_MANA */
77     case RF5_SPELL_START + 8:  return spell_RF5_BA_DARK(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_DARK */
78     case RF5_SPELL_START + 9:  return spell_RF5_DRAIN_MANA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF5_DRAIN_MANA */
79     case RF5_SPELL_START + 10: return spell_RF5_MIND_BLAST(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF5_MIND_BLAST */
80     case RF5_SPELL_START + 11: return spell_RF5_BRAIN_SMASH(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_MIND_BLAST */
81     case RF5_SPELL_START + 12: return spell_RF5_CAUSE_1(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_1 */
82     case RF5_SPELL_START + 13: return spell_RF5_CAUSE_2(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_2 */
83     case RF5_SPELL_START + 14: return spell_RF5_CAUSE_3(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_3 */
84     case RF5_SPELL_START + 15: return spell_RF5_CAUSE_4(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_CAUSE_4 */
85     case RF5_SPELL_START + 16: return spell_RF5_BO_ACID(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_ACID */
86     case RF5_SPELL_START + 17: return spell_RF5_BO_ELEC(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_ELEC */
87     case RF5_SPELL_START + 18: return spell_RF5_BO_FIRE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_FIRE */
88     case RF5_SPELL_START + 19: return spell_RF5_BO_COLD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_COLD */
89     case RF5_SPELL_START + 20: return spell_RF5_BA_LITE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BA_LITE */
90     case RF5_SPELL_START + 21: return spell_RF5_BO_NETH(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_NETH */
91     case RF5_SPELL_START + 22: return spell_RF5_BO_WATE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_WATE */
92     case RF5_SPELL_START + 23: return spell_RF5_BO_MANA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_MANA */
93     case RF5_SPELL_START + 24: return spell_RF5_BO_PLAS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_PLAS */
94     case RF5_SPELL_START + 25: return spell_RF5_BO_ICEE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_BO_ICEE */
95     case RF5_SPELL_START + 26: return spell_RF5_MISSILE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF5_MISSILE */
96     case RF5_SPELL_START + 27: return spell_RF5_SCARE(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_SCARE */
97     case RF5_SPELL_START + 28: return spell_RF5_BLIND(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_BLIND */
98     case RF5_SPELL_START + 29: return spell_RF5_CONF(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_CONF */
99     case RF5_SPELL_START + 30: return spell_RF5_SLOW(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_SLOW */
100     case RF5_SPELL_START + 31: return spell_RF5_HOLD(m_idx, target_ptr, 0, MONSTER_TO_PLAYER); /* RF5_HOLD */
101     case RF6_SPELL_START + 0:  return spell_RF6_HASTE(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HASTE */
102     case RF6_SPELL_START + 1:  return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HAND_DOOM */
103     case RF6_SPELL_START + 2:  return spell_RF6_HEAL(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_HEAL */
104     case RF6_SPELL_START + 3:  return spell_RF6_INVULNER(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_INVULNER */
105     case RF6_SPELL_START + 4:  return spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_PLAYER, FALSE); /* RF6_BLINK */
106     case RF6_SPELL_START + 5:  return spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_PLAYER); /* RF6_TPORT */
107     case RF6_SPELL_START + 6:  return spell_RF6_WORLD(target_ptr, m_idx); /* RF6_WORLD */
108     case RF6_SPELL_START + 7:  return spell_RF6_SPECIAL(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF6_SPECIAL */
109     case RF6_SPELL_START + 8:  return spell_RF6_TELE_TO(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_TELE_TO */
110     case RF6_SPELL_START + 9:  return spell_RF6_TELE_AWAY(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_TELE_AWAY */
111     case RF6_SPELL_START + 10: return spell_RF6_TELE_LEVEL(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_TELE_LEVEL */
112     case RF6_SPELL_START + 11: return spell_RF6_PSY_SPEAR(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_PSY_SPEAR */
113     case RF6_SPELL_START + 12: return spell_RF6_DARKNESS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_DARKNESS */
114     case RF6_SPELL_START + 13: return spell_RF6_TRAPS(target_ptr, y, x, m_idx); /* RF6_TRAPS */
115     case RF6_SPELL_START + 14: return spell_RF6_FORGET(target_ptr, m_idx); /* RF6_FORGET */
116     case RF6_SPELL_START + 15: return spell_RF6_RAISE_DEAD(target_ptr, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_RAISE_DEAD */
117     case RF6_SPELL_START + 16: return spell_RF6_S_KIN(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_KIN */
118     case RF6_SPELL_START + 17: return spell_RF6_S_CYBER(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_CYBER */
119     case RF6_SPELL_START + 18: return spell_RF6_S_MONSTER(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_MONSTER */
120     case RF6_SPELL_START + 19: return spell_RF6_S_MONSTERS(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_MONSTER */
121     case RF6_SPELL_START + 20: return spell_RF6_S_ANT(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_ANT */
122     case RF6_SPELL_START + 21: return spell_RF6_S_SPIDER(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_SPIDER */
123     case RF6_SPELL_START + 22: return spell_RF6_S_HOUND(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HOUND */
124     case RF6_SPELL_START + 23: return spell_RF6_S_HYDRA(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HYDRA */
125     case RF6_SPELL_START + 24: return spell_RF6_S_ANGEL(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_ANGEL */
126     case RF6_SPELL_START + 25: return spell_RF6_S_DEMON(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_DEMON */
127     case RF6_SPELL_START + 26: return spell_RF6_S_UNDEAD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_UNDEAD */
128     case RF6_SPELL_START + 27: return spell_RF6_S_DRAGON(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_DRAGON */
129     case RF6_SPELL_START + 28: return spell_RF6_S_HI_UNDEAD(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HI_UNDEAD */
130     case RF6_SPELL_START + 29: return spell_RF6_S_HI_DRAGON(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_HI_DRAGON */
131     case RF6_SPELL_START + 30: return spell_RF6_S_AMBERITES(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_AMBERITES */
132     case RF6_SPELL_START + 31: return spell_RF6_S_UNIQUE(target_ptr, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF6_S_UNIQUE */
133     default: break;
134     }
135     // clang-format on
136
137     return MonsterSpellResult::make_invalid();
138 }
139
140 static MonsterSpellResult monspell_to_monster_impl(
141     player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell)
142 {
143     // clang-format off
144     switch (ms_type) {
145     case RF4_SPELL_START + 0:  return spell_RF4_SHRIEK(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF4_SHRIEK */
146     case RF4_SPELL_START + 1:  break;   /* RF4_XXX1 */
147     case RF4_SPELL_START + 2:  return spell_RF4_DISPEL(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF4_DISPEL */
148     case RF4_SPELL_START + 3:  return spell_RF4_ROCKET(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_ROCKET */
149     case RF4_SPELL_START + 4:  return spell_RF4_SHOOT(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_SHOOT */
150     case RF4_SPELL_START + 5:  break;   /* RF4_XXX2 */
151     case RF4_SPELL_START + 6:  break;   /* RF4_XXX3 */
152     case RF4_SPELL_START + 7:  break;   /* RF4_XXX4 */
153     case RF4_SPELL_START + 8:  return spell_RF4_BREATH(target_ptr, GF_ACID, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ACID */
154     case RF4_SPELL_START + 9:  return spell_RF4_BREATH(target_ptr, GF_ELEC, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ELEC */
155     case RF4_SPELL_START + 10: return spell_RF4_BREATH(target_ptr, GF_FIRE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_FIRE */
156     case RF4_SPELL_START + 11: return spell_RF4_BREATH(target_ptr, GF_COLD, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_COLD */
157     case RF4_SPELL_START + 12: return spell_RF4_BREATH(target_ptr, GF_POIS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_POIS */
158     case RF4_SPELL_START + 13: return spell_RF4_BREATH(target_ptr, GF_NETHER, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_NETH */
159     case RF4_SPELL_START + 14: return spell_RF4_BREATH(target_ptr, GF_LITE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_LITE */
160     case RF4_SPELL_START + 15: return spell_RF4_BREATH(target_ptr, GF_DARK, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_DARK */
161     case RF4_SPELL_START + 16: return spell_RF4_BREATH(target_ptr, GF_CONFUSION, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_CONF */
162     case RF4_SPELL_START + 17: return spell_RF4_BREATH(target_ptr, GF_SOUND, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_SOUN */
163     case RF4_SPELL_START + 18: return spell_RF4_BREATH(target_ptr, GF_CHAOS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_CHAO */
164     case RF4_SPELL_START + 19: return spell_RF4_BREATH(target_ptr, GF_DISENCHANT, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_DISE */
165     case RF4_SPELL_START + 20: return spell_RF4_BREATH(target_ptr, GF_NEXUS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_NEXU */
166     case RF4_SPELL_START + 21: return spell_RF4_BREATH(target_ptr, GF_TIME, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_TIME */
167     case RF4_SPELL_START + 22: return spell_RF4_BREATH(target_ptr, GF_INERTIAL, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_INER */
168     case RF4_SPELL_START + 23: return spell_RF4_BREATH(target_ptr, GF_GRAVITY, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_GRAV */
169     case RF4_SPELL_START + 24: return spell_RF4_BREATH(target_ptr, GF_SHARDS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_SHAR */
170     case RF4_SPELL_START + 25: return spell_RF4_BREATH(target_ptr, GF_PLASMA, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_PLAS */
171     case RF4_SPELL_START + 26: return spell_RF4_BREATH(target_ptr, GF_FORCE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_WALL */
172     case RF4_SPELL_START + 27: return spell_RF4_BREATH(target_ptr, GF_MANA, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_MANA */
173     case RF4_SPELL_START + 28: return spell_RF4_BA_NUKE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BA_NUKE */
174     case RF4_SPELL_START + 29: return spell_RF4_BREATH(target_ptr, GF_NUKE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_NUKE */
175     case RF4_SPELL_START + 30: return spell_RF4_BA_CHAO(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BA_CHAO */
176     case RF4_SPELL_START + 31: return spell_RF4_BREATH(target_ptr, GF_DISINTEGRATE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_DISI */
177     case RF5_SPELL_START + 0:  return spell_RF5_BA_ACID(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_ACID */
178     case RF5_SPELL_START + 1:  return spell_RF5_BA_ELEC(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_ELEC */
179     case RF5_SPELL_START + 2:  return spell_RF5_BA_FIRE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_FIRE */
180     case RF5_SPELL_START + 3:  return spell_RF5_BA_COLD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_COLD */
181     case RF5_SPELL_START + 4:  return spell_RF5_BA_POIS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_POIS */
182     case RF5_SPELL_START + 5:  return spell_RF5_BA_NETH(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_NETH */
183     case RF5_SPELL_START + 6:  return spell_RF5_BA_WATE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_WATE */
184     case RF5_SPELL_START + 7:  return spell_RF5_BA_MANA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_MANA */
185     case RF5_SPELL_START + 8:  return spell_RF5_BA_DARK(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_DARK */
186     case RF5_SPELL_START + 9:  return spell_RF5_DRAIN_MANA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_DRAIN_MANA */
187     case RF5_SPELL_START + 10: return spell_RF5_MIND_BLAST(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_MIND_BLAST */
188     case RF5_SPELL_START + 11: return spell_RF5_BRAIN_SMASH(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BRAIN_SMASH */
189     case RF5_SPELL_START + 12: return spell_RF5_CAUSE_1(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_1 */
190     case RF5_SPELL_START + 13: return spell_RF5_CAUSE_2(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_2 */
191     case RF5_SPELL_START + 14: return spell_RF5_CAUSE_3(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_3 */
192     case RF5_SPELL_START + 15: return spell_RF5_CAUSE_4(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_CAUSE_4 */
193     case RF5_SPELL_START + 16: return spell_RF5_BO_ACID(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_ACID */
194     case RF5_SPELL_START + 17: return spell_RF5_BO_ELEC(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_ELEC */
195     case RF5_SPELL_START + 18: return spell_RF5_BO_FIRE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_FIRE */
196     case RF5_SPELL_START + 19: return spell_RF5_BO_COLD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_COLD */
197     case RF5_SPELL_START + 20: return spell_RF5_BA_LITE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BA_LITE */
198     case RF5_SPELL_START + 21: return spell_RF5_BO_NETH(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_NETH */
199     case RF5_SPELL_START + 22: return spell_RF5_BO_WATE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_WATE */
200     case RF5_SPELL_START + 23: return spell_RF5_BO_MANA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_MANA */
201     case RF5_SPELL_START + 24: return spell_RF5_BO_PLAS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_PLAS */
202     case RF5_SPELL_START + 25: return spell_RF5_BO_ICEE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_BO_ICEE */
203     case RF5_SPELL_START + 26: return spell_RF5_MISSILE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF5_MISSILE */
204     case RF5_SPELL_START + 27: return spell_RF5_SCARE(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_SCARE */
205     case RF5_SPELL_START + 28: return spell_RF5_BLIND(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_BLIND */
206     case RF5_SPELL_START + 29: return spell_RF5_CONF(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_CONF */
207     case RF5_SPELL_START + 30: return spell_RF5_SLOW(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_SLOW */
208     case RF5_SPELL_START + 31: return spell_RF5_HOLD(m_idx, target_ptr, t_idx, MONSTER_TO_MONSTER); /* RF5_HOLD */
209     case RF6_SPELL_START + 0:  return spell_RF6_HASTE(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HASTE */
210     case RF6_SPELL_START + 1:  return spell_RF6_HAND_DOOM(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HAND_DOOM */
211     case RF6_SPELL_START + 2:  return spell_RF6_HEAL(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_HEAL */
212     case RF6_SPELL_START + 3:  return spell_RF6_INVULNER(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_INVULNER */
213     case RF6_SPELL_START + 4:  return spell_RF6_BLINK(target_ptr, m_idx, MONSTER_TO_MONSTER, is_special_spell); /* RF6_BLINK */
214     case RF6_SPELL_START + 5:  return spell_RF6_TPORT(target_ptr, m_idx, MONSTER_TO_MONSTER); /* RF6_TPORT */
215     case RF6_SPELL_START + 6:  break; /* RF6_WORLD */
216     case RF6_SPELL_START + 7:  return spell_RF6_SPECIAL(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF6_SPECIAL */
217     case RF6_SPELL_START + 8:  return spell_RF6_TELE_TO(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_TELE_TO */
218     case RF6_SPELL_START + 9:  return spell_RF6_TELE_AWAY(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_TELE_AWAY */
219     case RF6_SPELL_START + 10: return spell_RF6_TELE_LEVEL(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_TELE_LEVEL */
220     case RF6_SPELL_START + 11: return spell_RF6_PSY_SPEAR(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_PSY_SPEAR */
221     case RF6_SPELL_START + 12: return spell_RF6_DARKNESS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_DARKNESS */
222     case RF6_SPELL_START + 13: break; /* RF6_TRAPS */
223     case RF6_SPELL_START + 14: break; /* RF6_FORGET */
224     case RF6_SPELL_START + 15: return spell_RF6_RAISE_DEAD(target_ptr, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_RAISE_DEAD */
225     case RF6_SPELL_START + 16: return spell_RF6_S_KIN(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_KIN */
226     case RF6_SPELL_START + 17: return spell_RF6_S_CYBER(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_CYBER */
227     case RF6_SPELL_START + 18: return spell_RF6_S_MONSTER(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_MONSTER */
228     case RF6_SPELL_START + 19: return spell_RF6_S_MONSTERS(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_MONSTER */
229     case RF6_SPELL_START + 20: return spell_RF6_S_ANT(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_ANT */
230     case RF6_SPELL_START + 21: return spell_RF6_S_SPIDER(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_SPIDER */
231     case RF6_SPELL_START + 22: return spell_RF6_S_HOUND(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HOUND */
232     case RF6_SPELL_START + 23: return spell_RF6_S_HYDRA(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HYDRA */
233     case RF6_SPELL_START + 24: return spell_RF6_S_ANGEL(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_ANGEL */
234     case RF6_SPELL_START + 25: return spell_RF6_S_DEMON(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_DEMON */
235     case RF6_SPELL_START + 26: return spell_RF6_S_UNDEAD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_UNDEAD */
236     case RF6_SPELL_START + 27: return spell_RF6_S_DRAGON(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_DRAGON */
237     case RF6_SPELL_START + 28: return spell_RF6_S_HI_UNDEAD(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HI_UNDEAD */
238     case RF6_SPELL_START + 29: return spell_RF6_S_HI_DRAGON(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_HI_DRAGON */
239     case RF6_SPELL_START + 30: return spell_RF6_S_AMBERITES(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_AMBERITES */
240     case RF6_SPELL_START + 31: return spell_RF6_S_UNIQUE(target_ptr, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF6_S_UNIQUE */
241     default: break;
242     }
243     // clang-format on
244
245     return MonsterSpellResult::make_invalid();
246 }
247
248 /*!
249  * @brief モンスターからプレイヤーへの魔法使用。ラーニング処理も行う。
250  * @param ms_type モンスター魔法ID (monster_spell_typeのenum値とは異なる)
251  * @param y 対象の地点のy座標
252  * @param x 対象の地点のx座標
253  * @param m_idx 呪文を唱えるモンスターID
254  */
255 MonsterSpellResult monspell_to_player(player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx)
256 {
257     // 特技使用前の時点でプレイヤーがモンスターを視認できているかチェック(ラーニングの必要条件)。
258     const bool player_could_see_monster = spell_learnable(target_ptr, m_idx);
259
260     auto res = monspell_to_player_impl(target_ptr, ms_type, y, x, m_idx);
261     if (!player_could_see_monster)
262         res.learnable = false;
263
264     // 条件を満たしていればラーニングを試みる。
265     if (res.valid && res.learnable) {
266         const auto monspell = spell_idx_to_monster_spell_type(ms_type);
267         learn_spell(target_ptr, monspell);
268     }
269
270     return res;
271 }
272
273 /*!
274  * @brief モンスターからモンスターへの魔法使用。ラーニング処理も行う。
275  * @param target_ptr プレーヤーへの参照ポインタ (monster_spell_typeのenum値とは異なる)
276  * @param ms_type モンスター魔法ID
277  * @param y 対象の地点のy座標
278  * @param x 対象の地点のx座標
279  * @param m_idx 呪文を唱えるモンスターID
280  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
281  * @param is_special_spell 特殊な行動である時TRUE
282  * @todo モンスターからモンスターへの呪文なのにplayer_typeが引数になり得るのは間違っている……
283  */
284 MonsterSpellResult monspell_to_monster(
285     player_type *target_ptr, SPELL_IDX ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, bool is_special_spell)
286 {
287     // 特技使用前の時点でプレイヤーがモンスターを視認できているかチェック(ラーニングの必要条件)。
288     const bool player_could_see_monster = spell_learnable(target_ptr, m_idx);
289
290     auto res = monspell_to_monster_impl(target_ptr, ms_type, y, x, m_idx, t_idx, is_special_spell);
291     if (!player_could_see_monster)
292         res.learnable = false;
293
294     // 条件を満たしていればラーニングを試みる。
295     if (res.valid && res.learnable) {
296         const auto monspell = spell_idx_to_monster_spell_type(ms_type);
297         learn_spell(target_ptr, monspell);
298     }
299
300     return res;
301 }