OSDN Git Service

[Feature] 元素使いの領域選択時に説明文と確認を出す
[hengbandforosx/hengbandosx.git] / src / mind / mind-elementalist.cpp
1 /*!
2  * @brief 元素使いの魔法系統
3  */
4
5 #include "mind-elementalist.h"
6 #include "action/action-limited.h"
7 #include "cmd-action/cmd-spell.h"
8 #include "cmd-action/cmd-mind.h"
9 #include "cmd-io/cmd-gameoption.h"
10 #include "core/asking-player.h"
11 #include "core/hp-mp-processor.h"
12 #include "core/player-redraw-types.h"
13 #include "core/stuff-handler.h"
14 #include "core/window-redrawer.h"
15 #include "effect/effect-characteristics.h"
16 #include "effect/effect-monster-util.h"
17 #include "effect/effect-processor.h"
18 #include "effect/spells-effect-util.h"
19 #include "floor/cave.h"
20 #include "floor/floor-util.h"
21 #include "game-option/disturbance-options.h"
22 #include "game-option/input-options.h"
23 #include "game-option/text-display-options.h"
24 #include "io/command-repeater.h"
25 #include "io/input-key-acceptor.h"
26 #include "io/input-key-requester.h"
27 #include "main/sound-definitions-table.h"
28 #include "main/sound-of-music.h"
29 #include "mind/mind-explanations-table.h"
30 #include "monster/monster-describer.h"
31 #include "monster-race/monster-race.h"
32 #include "monster-race/race-flags3.h"
33 #include "monster-race/race-flags-resistance.h"
34 #include "mind/mind-mindcrafter.h"
35 #include "player/player-status-table.h"
36 #include "player-info/avatar.h"
37 #include "player-status/player-status-base.h"
38 #include "racial/racial-util.h"
39 #include "spell-kind/earthquake.h"
40 #include "spell-kind/spells-charm.h"
41 #include "spell-kind/spells-detection.h"
42 #include "spell-kind/spells-genocide.h"
43 #include "spell-kind/spells-launcher.h"
44 #include "spell-kind/spells-lite.h"
45 #include "spell-kind/magic-item-recharger.h"
46 #include "spell-kind/spells-beam.h"
47 #include "spell-kind/spells-sight.h"
48 #include "spell-kind/spells-world.h"
49 #include "status/bad-status-setter.h"
50 #include "status/base-status.h"
51 #include "system/game-option-types.h"
52 #include "util/bit-flags-calculator.h"
53 #include "util/buffer-shaper.h"
54 #include "util/int-char-converter.h"
55 #include "target/target-getter.h"
56 #include "term/screen-processor.h"
57 #include "term/term-color-types.h"
58 #include "view/display-messages.h"
59 #include <string>
60 #include <array>
61 #include <unordered_map>
62
63 /*!
64  * @brief 元素魔法呪文のID定義
65  */
66 enum class ElementSpells {
67     BOLT_1ST = 0,
68     MON_DETECT = 1,
69     PERCEPT = 2,
70     CURE = 3,
71     BOLT_2ND = 4,
72     MAG_DETECT = 5,
73     BEAM_1ST = 6,
74     BALL_1ST = 7,
75     BREATH_2ND = 8,
76     ANNIHILATE = 9,
77     BOLT_3RD = 10,
78     WAVE_1ST = 11,
79     BALL_2ND = 12,
80     BURST_1ST = 13,
81     STORM_2ND = 14,
82     BREATH_1ST = 15,
83     STORM_3ND = 16,
84     MAX
85 };
86
87 /*!
88  * @brief 元素魔法タイプ構造体
89  */
90 struct element_type {
91     std::string_view title; //!< 領域名
92     std::array<spells_type, 3> type; //!< 属性タイプリスト
93     std::array<std::string_view, 3> name; //!< 属性名リスト
94 };
95
96 /*!
97  * @brief 元素魔法難易度構造体
98  */
99 struct element_power {
100     int elem; //!< 使用属性番号
101     mind_type info; //!< 難易度構造体
102 };
103
104 using element_type_list = const std::unordered_map<ElementRealm, element_type>;
105 using element_power_list = const std::unordered_map<ElementSpells, element_power>;
106 using element_tip_list = const std::unordered_map<ElementSpells, std::string_view>;
107 using element_text_list = const std::unordered_map<ElementRealm, std::string_view>;
108
109 // clang-format off
110 /*!
111  * @brief 元素魔法タイプ定義
112  */
113 static element_type_list element_types = {
114     {
115         ElementRealm::FIRE, {
116             _("炎", "Fire"),
117             { GF_FIRE, GF_PLASMA, GF_HOLY_FIRE },
118             { _("火炎", "Fire"), _("プラズマ", "Plasma"), _("聖気", "Holy Fire") },
119         }
120     },
121     {
122         ElementRealm::ICE, {
123             _("氷", "Ice"),
124             { GF_COLD, GF_INERTIAL, GF_TIME },
125             { _("冷気", "Ice"), _("遅鈍", "Inertial"), _("時間逆転", "Time Stream") },
126         }
127     },
128     {
129         ElementRealm::SKY, {
130             _("空", "Sky"),
131             { GF_ELEC, GF_LITE, GF_MANA },
132             { _("電撃", "Lightning"), _("光", "Light"), _("魔力", "Mana") },
133         }
134     },
135     {
136         ElementRealm::SEA, {
137             _("海", "Sea"),
138             { GF_ACID, GF_WATER, GF_DISINTEGRATE },
139             { _("酸", "Acid"), _("水", "Water"), _("分解", "Disintegrate") },
140         }
141     },
142     {
143         ElementRealm::DARKNESS, {
144             _("闇", "Darkness"),
145             { GF_DARK, GF_NETHER, GF_HELL_FIRE },
146             { _("暗黒", "Darkness"), _("地獄", "Nether"), _("業火", "Hell Fire") },
147         }
148     },
149     {
150         ElementRealm::CHAOS, {
151             _("混沌", "Chaos"),
152             { GF_CONFUSION, GF_NEXUS, GF_CHAOS },
153             { _("混乱", "Confusion"), _("因果混乱", "Nexus"), _("カオス", "Chaos") },
154         }
155     },
156     {
157         ElementRealm::EARTH, {
158             _("地", "Earth"),
159             { GF_SHARDS, GF_FORCE, GF_METEOR },
160             { _("破片", "Shard"), _("フォース", "Force"), _("隕石", "Meteo") },
161         }
162     },
163     {
164         ElementRealm::DEATH, {
165             _("瘴気", "Death"),
166             { GF_POIS, GF_HYPODYNAMIA, GF_DISENCHANT },
167             { _("毒", "Poison"), _("吸血", "Drain Life"), _("劣化", "Disenchant") },
168         }
169     },
170 };
171
172 /*!
173  * @brief 元素魔法呪文定義
174  */
175 static element_power_list element_powers = {
176     { ElementSpells::BOLT_1ST,   { 0, {  1,  1,  15, _("%sの矢", "%s Bolt") }}},
177     { ElementSpells::MON_DETECT, { 0, {  2,  1,  20, _("モンスター感知", "Detect Monsters") }}},
178     { ElementSpells::PERCEPT,    { 0, {  5,  5,  50, _("擬似鑑定", "Psychometry") }}},
179     { ElementSpells::CURE,       { 0, {  6,  5,  35, _("傷の治癒", "Cure Wounds") }}},
180     { ElementSpells::BOLT_2ND,   { 1, {  8,  6,  35, _("%sの矢", "%s Bolt") }}},
181     { ElementSpells::MAG_DETECT, { 0, { 10,  8,  60, _("魔法感知", "Detect Magical Objs") }}},
182     { ElementSpells::BEAM_1ST,   { 0, { 15, 10,  45, _("%sの鞭", "%s Whip") }}},
183     { ElementSpells::BALL_1ST,   { 0, { 18, 15,  70, _("%sの球", "%s Ball") }}},
184     { ElementSpells::BREATH_2ND, { 1, { 21, 20,  70, _("%sのブレス", "Breath of %s") }}},
185     { ElementSpells::ANNIHILATE, { 0, { 24, 20,  75, _("モンスター消滅", "Annihilation") }}},
186     { ElementSpells::BOLT_3RD,   { 2, { 25, 15,  60, _("%sの矢", "%s Bolt") }}},
187     { ElementSpells::WAVE_1ST,   { 0, { 28, 30,  75, _("元素の波動", "Elemental Wave") }}},
188     { ElementSpells::BALL_2ND,   { 1, { 28, 22,  75, _("%sの球", "%s Ball") }}},
189     { ElementSpells::BURST_1ST,  { 0, { 33, 35,  75, _("精気乱射", "%s Blast") }}},
190     { ElementSpells::STORM_2ND,  { 1, { 35, 30,  75, _("%sの嵐", "%s Storm") }}},
191     { ElementSpells::BREATH_1ST, { 0, { 42, 48,  75, _("%sのブレス", "Breath of %s") }}},
192     { ElementSpells::STORM_3ND,  { 2, { 45, 60,  80, _("%sの嵐", "%s Storm") }}},
193 };
194
195 /*!
196  * @brief 元素魔法呪文説明文定義
197  */
198 static element_tip_list element_tips = {
199     { ElementSpells::BOLT_1ST,
200     _("弱い%sの矢を放つ。", "Fire a weak bolt of %s.") },
201     { ElementSpells::MON_DETECT,
202     _("近くの全てのモンスターを感知する。", "Detects monsters.") },
203     { ElementSpells::PERCEPT,
204     _("アイテムの雰囲気を知る。", "Gives feeling of an item.") },
205     { ElementSpells::CURE,
206     _("怪我と体力を少し回復させる。", "Heals HP and wounds a bit.") },
207     { ElementSpells::BOLT_2ND,
208     _("%sの矢を放つ。", "Fire a bolt of %s.") },
209     { ElementSpells::MAG_DETECT,
210     _("近くの魔法のアイテムを感知する。", "Detects magic devices.") },
211     { ElementSpells::BEAM_1ST,
212     _("高威力で射程が短い%sのビームを放つ。", "Fire a short and strong beam of %s.") },
213     { ElementSpells::BALL_1ST,
214     _("%sの球を放つ。",  "Fire a ball of %s.") },
215     { ElementSpells::BREATH_2ND,
216     _("%sのブレスを吐く。", "Fire a breath of %s.") },
217     { ElementSpells::ANNIHILATE,
218     _("%s耐性のないモンスターを1体抹殺する。", "Erase a monster unless it resists %s.") },
219     { ElementSpells::BOLT_3RD,
220     _("%sの矢を放つ。", "Fire a bolt of %s.") },
221     { ElementSpells::WAVE_1ST,
222     _("視界内の全ての敵に%sによるダメージを与える。", "Inflict all monsters with %s damage.") },
223     { ElementSpells::BALL_2ND,
224     _("%sの球を放つ。",  "Fire a ball of %s.") },
225     { ElementSpells::BURST_1ST,
226     _("ランダムな方向に%sの矢を放つ。", "Fire some bolts of %s toward random direction.") },
227     { ElementSpells::STORM_2ND,
228     _("%sの巨大な球を放つ。", "Fire a large ball of %s.") },
229     { ElementSpells::BREATH_1ST,
230     _("%sのブレスを吐く。", "Fire a breath of %s.") },
231     { ElementSpells::STORM_3ND,
232     _("%sの巨大な球を放つ。", "Fire a large ball of %s.") },
233 };
234
235 /*!
236  * @brief 元素魔法選択時説明文定義
237  */
238 static element_text_list element_texts = {
239     { ElementRealm::FIRE,
240     _("炎系統は巨大なエネルギーで灼熱を生み出し、全ての敵を燃やし尽くそうとします。",
241         "Great energy of Fire system will be able to burn out all of your enemies.")},
242     { ElementRealm::ICE,
243     _("氷系統の魔法はその冷たさで敵の動きを奪い尽くし、魂すらも止めてしまうでしょう。",
244         "Ice system will be freeze your enemies even their souls.")},
245     { ElementRealm::SKY,
246     _("空系統は大いなる天空のエネルギーを駆使して敵の全てを撃滅できます。",
247         "Sky system can terminate all of your enemies powerfully with enery of the great sky.")},
248     { ElementRealm::SEA,
249     _("海系統はその敵の全てを溶かし、大いなる海へと返してしまいます。",
250         "Sea system melts all of your enemies and returns them to the great oscean.")},
251     { ElementRealm::DARKNESS,
252     _("闇系統は恐るべき力を常闇から引き出し、敵を地獄へと叩き落とすでしょう。",
253         "Dark system buries all of your enemies by scary power from dark hell.")},
254     { ElementRealm::CHAOS,
255     _("混沌系統は敵の意識も条理も捻じ曲げ、その存在をあの世に送ってしまいます。",
256         "Chaos system twists and wraps your enemies even their souls and kill all of them resultly.")},
257     { ElementRealm::EARTH,
258     _("地系統は偉大なる大地の力を呼び出して、数多の敵のことごとくを粉砕しようとします。",
259         "Earth system smash all of your enemies massively using its huge powers.")},
260     { ElementRealm::DEATH,
261     _("瘴気系統は全ての生ける者にとって途轍もない毒です。",
262         "Death system is doomed poison for all of living your ememies.")},
263 };
264
265 // clang-format on
266
267 /*!
268  * @brief 元素魔法の領域名を返す
269  * @param realm_idx 領域番号
270  * @return 領域名
271  */
272 concptr get_element_title(int realm_idx)
273 {
274     auto realm = static_cast<ElementRealm>(realm_idx);
275     return element_types.at(realm).title.data();
276 }
277
278 /*!
279  * @brief 元素魔法領域の属性リストを返す
280  * @param realm_idx 領域番号
281  * @return 領域で使用できる属性リスト
282  */
283 static std::array<spells_type, 3> get_element_types(int realm_idx)
284 {
285     auto realm = static_cast<ElementRealm>(realm_idx);
286     return element_types.at(realm).type;
287 }
288
289 /*!
290  * @brief 元素魔法領域のn番目の属性を返す
291  * @param realm_idx 領域番号
292  * @param n 属性の何番目か
293  * @return 属性タイプ
294  */
295 spells_type get_element_type(int realm_idx, int n)
296 {
297     return get_element_types(realm_idx)[n];
298 }
299
300 /*!
301  * @brief 元素魔法領域の属性名リストを返す
302  * @param realm_idx 領域番号
303  * @return 領域で使用できる属性の名称リスト
304  */
305 static std::array<std::string_view, 3> get_element_names(int realm_idx)
306 {
307     auto realm = static_cast<ElementRealm>(realm_idx);
308     return element_types.at(realm).name;
309 }
310
311 /*!
312  * @brief 元素魔法領域のn番目の属性名を返す
313  * @param realm_idx 領域番号
314  * @param n 属性の何番目か
315  * @return 属性名
316  */
317 concptr get_element_name(int realm_idx, int n)
318 {
319     return get_element_names(realm_idx)[n].data();
320 }
321
322 /*!
323  * @brief 元素魔法の説明文を取得
324  * @param caster_ptr プレイヤー情報への参照ポインタ
325  * @param spell_idx 呪文番号
326  * @return 説明文
327  */
328 static concptr get_element_tip(player_type *caster_ptr, int spell_idx)
329 {
330     auto realm = static_cast<ElementRealm>(caster_ptr->realm1);
331     auto spell = static_cast<ElementSpells>(spell_idx);
332     auto elem = element_powers.at(spell).elem;
333     return format(element_tips.at(spell).data(), element_types.at(realm).name[elem].data());
334 }
335
336 /*!
337  * @brief 元素魔法の説明文を取得
338  * @param caster_ptr プレイヤー情報への参照ポインタ
339  * @param spell_idx 呪文番号
340  * @return 説明文
341  */
342 static int get_elemental_elem(player_type *caster_ptr, int spell_idx)
343 {
344     (void)caster_ptr;
345     auto spell = static_cast<ElementSpells>(spell_idx);
346     return element_powers.at(spell).elem;
347 }
348
349 /*!
350  * @brief 元素魔法呪文の難易度データを取得
351  * @param caster_ptr プレイヤー情報への参照ポインタ
352  * @param spell_idx 呪文番号
353  * @return 説明文
354  */
355 static mind_type get_elemental_info(player_type *caster_ptr, int spell_idx)
356 {
357     (void)caster_ptr;
358     auto spell = static_cast<ElementSpells>(spell_idx);
359     return element_powers.at(spell).info;
360 }
361
362 /*!
363  * @brief 元素魔法呪文の効果表示文字列を取得
364  * @param caster_ptr プレイヤー情報への参照ポインタ
365  * @param spell_idx 呪文番号
366  * @param p バッファ
367  * @return なし(pを更新)
368  */
369 void get_element_effect_info(player_type *caster_ptr, int spell_idx, char *p)
370 {
371     PLAYER_LEVEL plev = caster_ptr->lev;
372     auto spell = static_cast<ElementSpells>(spell_idx);
373     int dam = 0;
374
375     switch (spell) {
376     case ElementSpells::BOLT_1ST:
377         sprintf(p, " %s%dd%d", KWD_DAM, 3 + ((plev - 1) / 5), 4);
378         break;
379     case ElementSpells::CURE:
380         sprintf(p, " %s%dd%d", KWD_HEAL, 2, 8);
381         break;
382     case ElementSpells::BOLT_2ND:
383         sprintf(p, " %s%dd%d", KWD_DAM, 8 + ((plev - 5) / 4), 8);
384         break;
385     case ElementSpells::BEAM_1ST:
386         sprintf(p, " %s%d", KWD_DAM, (50 + plev * 2));
387         break;
388     case ElementSpells::BALL_1ST:
389         sprintf(p, " %s%d", KWD_DAM, 55 + plev);
390         break;
391     case ElementSpells::BREATH_2ND:
392         dam = p_ptr->chp / 2;
393         sprintf(p, " %s%d", KWD_DAM, (dam > 120) ? 120 : dam);
394         break;
395     case ElementSpells::ANNIHILATE:
396         sprintf(p, " %s%d", _("効力:", "pow "), 50 + plev);
397         break;
398     case ElementSpells::BOLT_3RD:
399         sprintf(p, " %s%dd%d", KWD_DAM, 12 + ((plev - 5) / 4), 8);
400         break;
401     case ElementSpells::WAVE_1ST:
402         sprintf(p, " %sd%d", KWD_DAM, plev * 4);
403         break;
404     case ElementSpells::BALL_2ND:
405         sprintf(p, " %s%d", KWD_DAM, 75 + plev);
406         break;
407     case ElementSpells::BURST_1ST:
408         sprintf(p, " %s%dd%d", KWD_DAM, 6 + plev / 8, 8);
409         break;
410     case ElementSpells::STORM_2ND:
411         sprintf(p, " %s%d", KWD_DAM, 120 + plev * 2);
412         break;
413     case ElementSpells::BREATH_1ST:
414         sprintf(p, " %s%d", KWD_DAM, p_ptr->chp * 2 / 3);
415         break;
416     case ElementSpells::STORM_3ND:
417         sprintf(p, " %s%d", KWD_DAM, 300 + plev * 5);
418         break;
419     default:
420         p[0] = '\0';
421         break;
422     }
423 }
424
425 /*!
426  * @brief 元素魔法呪文を実行する
427  * @param caster_ptr プレイヤー情報への参照ポインタ
428  * @param spell_idx 呪文番号
429  * @return 実行したらTRUE、キャンセルならFALSE
430  */
431 static bool cast_element_spell(player_type *caster_ptr, SPELL_IDX spell_idx)
432 {
433     auto spell = static_cast<ElementSpells>(spell_idx);
434     auto types = get_element_types(caster_ptr->realm1);
435     DIRECTION dir;
436     PLAYER_LEVEL plev = caster_ptr->lev;
437     HIT_POINT dam;
438     POSITION y, x;
439     int num;
440
441     switch (spell) {
442     case ElementSpells::BOLT_1ST:
443         if (!get_aim_dir(caster_ptr, &dir))
444             return FALSE;
445         dam = damroll(3 + ((plev - 1) / 5), 4);
446         (void)fire_bolt(caster_ptr, types[0], dir, dam);
447         break;
448     case ElementSpells::MON_DETECT:
449         (void)detect_monsters_normal(caster_ptr, DETECT_RAD_DEFAULT);
450         (void)detect_monsters_invis(caster_ptr, DETECT_RAD_DEFAULT);
451         break;
452     case ElementSpells::PERCEPT:
453         return psychometry(caster_ptr);
454     case ElementSpells::CURE:
455         (void)hp_player(caster_ptr, damroll(2, 8));
456         (void)set_cut(caster_ptr, caster_ptr->cut - 10);
457         break;
458     case ElementSpells::BOLT_2ND:
459         if (!get_aim_dir(caster_ptr, &dir))
460             return FALSE;
461         dam = damroll(8 + ((plev - 5) / 4), 8);
462         if (fire_bolt_or_beam(caster_ptr, plev, types[1], dir, dam)) {
463             if (types[1] == GF_HYPODYNAMIA) {
464                 (void)hp_player(caster_ptr, dam / 2);
465             }
466         }
467         break;
468     case ElementSpells::MAG_DETECT:
469         (void)detect_objects_magic(caster_ptr, DETECT_RAD_DEFAULT);
470         break;
471     case ElementSpells::BEAM_1ST:
472         project_length = 2;
473         if (!get_aim_dir(caster_ptr, &dir))
474             return FALSE;
475         (void)fire_beam(caster_ptr, types[0], dir, 50 + plev * 2);
476         project_length = 0;
477         break;
478     case ElementSpells::BALL_1ST:
479         if (!get_aim_dir(caster_ptr, &dir))
480             return FALSE;
481         dam = 55 + plev;
482         (void)fire_ball(caster_ptr, types[0], dir, dam, 2);
483         break;
484     case ElementSpells::BREATH_2ND:
485         if (!get_aim_dir(caster_ptr, &dir))
486             return FALSE;
487         dam = caster_ptr->chp / 2;
488         if (fire_breath(caster_ptr, types[1], dir, dam, 3)) {
489             if (types[1] == GF_HYPODYNAMIA) {
490                 (void)hp_player(caster_ptr, dam / 2);
491             }
492         }
493         break;
494     case ElementSpells::ANNIHILATE:
495         if (!get_aim_dir(caster_ptr, &dir))
496             return FALSE;
497         fire_ball_hide(caster_ptr, GF_E_GENOCIDE, dir, plev + 50, 0);
498         break;
499     case ElementSpells::BOLT_3RD:
500         if (!get_aim_dir(caster_ptr, &dir))
501             return FALSE;
502         dam = damroll(12 + ((plev - 5) / 4), 8);
503         fire_bolt_or_beam(caster_ptr, plev, types[2], dir, dam);
504         break;
505     case ElementSpells::WAVE_1ST:
506         dam = randint1(plev * 4);
507         project_all_los(caster_ptr, types[0], dam);
508         break;
509     case ElementSpells::BALL_2ND:
510         if (!get_aim_dir(caster_ptr, &dir))
511             return FALSE;
512         dam = 75 + plev;
513         if (fire_ball(caster_ptr, types[1], dir, dam, 2)) {
514             if (types[1] == GF_HYPODYNAMIA) {
515                 (void)hp_player(caster_ptr, dam / 2);
516             }
517         }
518         break;
519     case ElementSpells::BURST_1ST:
520         y = caster_ptr->y;
521         x = caster_ptr->x;
522         num = damroll(5, 3);
523         for (int k = 0; k < num; k++) {
524             int attempts = 1000;
525             while (attempts--) {
526                 scatter(caster_ptr, &y, &x, caster_ptr->y, caster_ptr->x, 4, PROJECT_NONE);
527                 if (!player_bold(caster_ptr, y, x))
528                     break;
529             }
530             project(caster_ptr, 0, 0, y, x, damroll(6 + plev / 8, 10), types[0], (PROJECT_BEAM | PROJECT_THRU | PROJECT_GRID | PROJECT_KILL), -1);
531         }
532         break;
533     case ElementSpells::STORM_2ND:
534         if (!get_aim_dir(caster_ptr, &dir))
535             return FALSE;
536         dam = 125 + plev * 2;
537         if (fire_ball(caster_ptr, types[1], dir, dam, 4)) {
538             if (types[1] == GF_HYPODYNAMIA) {
539                 (void)hp_player(caster_ptr, dam / 2);
540             }
541         }
542         break;
543     case ElementSpells::BREATH_1ST:
544         if (!get_aim_dir(caster_ptr, &dir))
545             return FALSE;
546         dam = caster_ptr->chp * 2 / 3;
547         (void)fire_breath(caster_ptr, types[0], dir, dam, 3);
548         break;
549     case ElementSpells::STORM_3ND:
550         if (!get_aim_dir(caster_ptr, &dir))
551             return FALSE;
552         dam = 300 + plev * 5;
553         (void)fire_ball(caster_ptr, types[2], dir, dam, 5);
554         break;
555     default:
556         return FALSE;
557     }
558
559     return TRUE;
560 }
561
562 /*!
563  * @brief 元素魔法呪文の失敗率を計算
564  * @param caster_ptr プレイヤー情報への参照ポインタ
565  * @param spell_idx 呪文番号
566  * @return 失敗率
567  */
568 static PERCENTAGE decide_element_chance(player_type *caster_ptr, mind_type spell)
569 {
570     PERCENTAGE chance = spell.fail;
571
572     chance -= 3 * (caster_ptr->lev - spell.min_lev);
573     chance += caster_ptr->to_m_chance;
574     chance -= 3 * (adj_mag_stat[caster_ptr->stat_index[A_WIS]] - 1);
575     
576     PERCENTAGE minfail = adj_mag_fail[caster_ptr->stat_index[A_WIS]];
577     if (chance < minfail)
578         chance = minfail;
579
580     if (caster_ptr->stun > 50)
581         chance += 25;
582     else if (caster_ptr->stun)
583         chance += 15;
584
585     if (heavy_armor(caster_ptr))
586         chance += 5;
587
588     if (caster_ptr->icky_wield[0])
589         chance += 5;
590
591     if (caster_ptr->icky_wield[1])
592         chance += 5;
593
594     if (chance > 95)
595         chance = 95;
596
597     return chance;
598 }
599
600 /*!
601  * @brief 元素魔法呪文の消費MPを計算
602  * @param caster_ptr プレイヤー情報への参照ポインタ
603  * @param spell_idx 呪文番号
604  * @return 消費MP
605  */
606 static MANA_POINT decide_element_mana_cost(player_type *caster_ptr, mind_type spell)
607 {
608     (void)caster_ptr;
609     return spell.mana_cost;
610 }
611
612 /*!
613  * @brief 元素魔法呪文を選択して取得
614  * @param caster_ptr プレイヤー情報への参照ポインタ
615  * @param sn 呪文番号
616  * @param only_browse 閲覧モードかどうか
617  * @return 選んだらTRUE、選ばなかったらFALSE
618  */
619 bool get_element_power(player_type *caster_ptr, SPELL_IDX *sn, bool only_browse)
620 {
621     SPELL_IDX i;
622     int num = 0;
623     TERM_LEN y = 1;
624     TERM_LEN x = 10;
625     PLAYER_LEVEL plev = caster_ptr->lev;
626     int ask = TRUE;
627     char choice;
628     char out_val[160];
629     char comment[80];
630     COMMAND_CODE code;
631     bool flag, redraw;
632     int menu_line = (use_menu ? 1 : 0);
633
634     *sn = -1;
635     if (repeat_pull(&code)) {
636         *sn = (SPELL_IDX)code;
637         if (get_elemental_info(caster_ptr, *sn).min_lev <= plev)
638             return TRUE;
639     }
640
641     concptr p = _("元素魔法", "magic");
642     flag = FALSE;
643     redraw = FALSE;
644
645     for (i = 0; i < static_cast<SPELL_IDX>(ElementSpells::MAX); i++) {
646         if (get_elemental_info(caster_ptr, i).min_lev <= plev)
647             num++;
648     }
649
650     if (only_browse)
651         (void)strnfmt(out_val, 78, 
652             _("(%^s %c-%c, '*'で一覧, ESC) どの%sについて知りますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "),
653             p, I2A(0), I2A(num - 1), p);
654     else
655         (void)strnfmt(out_val, 78, 
656             _("(%^s %c-%c, '*'で一覧, ESC) どの%sを使いますか?", "(%^ss %c-%c, *=List, ESC=exit) Use which %s? "),
657             p, I2A(0), I2A(num - 1), p);
658
659     if (use_menu && !only_browse)
660         screen_save();
661
662     int elem;
663     mind_type spell;
664     choice = (always_show_list || use_menu) ? ESCAPE : 1;
665     while (!flag) {
666         if (choice == ESCAPE)
667             choice = ' ';
668         else if (!get_com(out_val, &choice, TRUE))
669             break;
670
671         if (use_menu && choice != ' ') {
672             switch (choice) {
673             case '0':
674                 if (!only_browse)
675                     screen_load();
676                 return FALSE;
677             case '8':
678             case 'k':
679             case 'K':
680                 menu_line += (num - 1);
681                 break;
682             case '2':
683             case 'j':
684             case 'J':
685                 menu_line++;
686                 break;
687             case 'x':
688             case 'X':
689             case '\r':
690             case '\n':
691                 i = menu_line - 1;
692                 ask = FALSE;
693                 break;
694             }
695
696             if (menu_line > num)
697                 menu_line -= num;
698         }
699
700         int spell_max = static_cast<int>(ElementSpells::MAX);
701         if ((choice == ' ') || (choice == '*') || (choice == '?') || (use_menu && ask)) {
702             if (!redraw || use_menu) {
703                 char desc[80];
704                 char name[80];
705                 redraw = TRUE;
706                 if (!only_browse && !use_menu)
707                     screen_save();
708
709                 prt("", y, x);
710                 put_str(_("名前", "Name"), y, x + 5);
711                 put_str(_("Lv   MP   失率 効果", "Lv   MP   Fail Info"), y, x + 35);
712                 for (i = 0; i < spell_max; i++) {
713                     elem = get_elemental_elem(caster_ptr, i);
714                     spell = get_elemental_info(caster_ptr, i);
715
716                     if (spell.min_lev > plev)
717                         break;
718
719                     PERCENTAGE chance = decide_element_chance(caster_ptr, spell);
720                     int mana_cost = decide_element_mana_cost(caster_ptr, spell);
721                     get_element_effect_info(caster_ptr, i, comment);
722
723                     if (use_menu) {
724                         if (i == (menu_line - 1))
725                             strcpy(desc, _("  》 ", "  >  "));
726                         else
727                             strcpy(desc, "     ");
728                     } else
729                         sprintf(desc, "  %c) ", I2A(i));
730
731                     concptr s = get_element_name(caster_ptr->realm1, elem);
732                     sprintf(name, spell.name, s);
733                     strcat(desc,
734                         format("%-30s%2d %4d %3d%%%s", name, spell.min_lev, mana_cost, chance, comment));
735                     prt(desc, y + i + 1, x);
736                 }
737
738                 prt("", y + i + 1, x);
739             } else if (!only_browse) {
740                 redraw = FALSE;
741                 screen_load();
742             }
743
744             continue;
745         }
746
747         if (!use_menu) {
748             ask = isupper(choice);
749             if (ask)
750                 choice = (char)tolower(choice);
751
752             i = (islower(choice) ? A2I(choice) : -1);
753         }
754
755         if ((i < 0) || (i >= num)) {
756             bell();
757             continue;
758         }
759
760         spell = get_elemental_info(caster_ptr, i);
761         if (ask) {
762             char tmp_val[160];
763             (void)strnfmt(tmp_val, 78, _("%sを使いますか?", "Use %s? "), spell.name);
764             if (!get_check(tmp_val))
765                 continue;
766         }
767
768         flag = TRUE;
769     }
770
771     if (redraw && !only_browse)
772         screen_load();
773
774     set_bits(caster_ptr->window_flags, PW_SPELL);
775     handle_stuff(caster_ptr);
776     if (!flag)
777         return FALSE;
778
779     *sn = i;
780     repeat_push((COMMAND_CODE)i);
781     return TRUE;
782 }
783
784 /*!
785  * @brief 元素魔法呪文をMPがなくても挑戦するか確認する
786  * @param caster_ptr プレイヤー情報への参照ポインタ
787  * @param mana_cost 消費MP
788  * @return 詠唱するならTRUE、しないならFALSE
789  */
790 static bool check_element_mp_sufficiency(player_type *caster_ptr, int mana_cost)
791 {
792     if (mana_cost <= caster_ptr->csp)
793         return TRUE;
794
795     msg_print(_("MPが足りません。", "You do not have enough mana to use this power."));
796     if (!over_exert)
797         return FALSE;
798
799     return get_check(_("それでも挑戦しますか? ", "Attempt it anyway? "));
800 }
801
802 /*!
803  * @brief 元素魔法呪文の詠唱を試み、成功なら詠唱し、失敗ならファンブルする
804  * @param caster_ptr プレイヤー情報への参照ポインタ
805  * @param spell_idx 呪文番号
806  * @param chance 失敗率
807  * @return 詠唱して実行したらTRUE、されなかったらFALSE
808  */
809 static bool try_cast_element_spell(player_type *caster_ptr, SPELL_IDX spell_idx, PERCENTAGE chance)
810 {
811     if (randint0(100) >= chance) {
812         sound(SOUND_ZAP);
813         return cast_element_spell(caster_ptr, spell_idx);
814     }
815
816     if (flush_failure)
817         flush();
818
819     msg_format(_("魔力の集中に失敗した!", "You failed to concentrate hard enough for Mana!"));
820     sound(SOUND_FAIL);
821
822     if (randint1(100) < chance / 2) {
823         int plev = caster_ptr->lev;
824         msg_print(_("元素の力が制御できない氾流となって解放された!",
825             "Elemental power unleashes its power in an uncontrollable storm!"));
826         project(caster_ptr, PROJECT_WHO_UNCTRL_POWER, 2 + plev / 10, caster_ptr->y, caster_ptr->x, plev * 2,
827             get_element_types(caster_ptr->realm1)[0],
828             PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM, -1);
829         caster_ptr->csp = MAX(0, caster_ptr->csp - plev * MAX(1, plev / 10));
830     }
831
832     return TRUE;
833 }
834
835 /*!
836  * @brief 元素魔法コマンドのメインルーチン
837  * @param caster_ptr プレイヤー情報への参照ポインタ
838  * @return なし
839  */
840 void do_cmd_element(player_type *caster_ptr)
841 {
842     SPELL_IDX i;
843     if (cmd_limit_confused(caster_ptr) || !get_element_power(caster_ptr, &i, FALSE))
844         return;
845
846     mind_type spell = get_elemental_info(caster_ptr, i);
847     PERCENTAGE chance = decide_element_chance(caster_ptr, spell);
848     int mana_cost = decide_element_mana_cost(caster_ptr, spell);
849
850     if (!check_element_mp_sufficiency(caster_ptr, mana_cost))
851         return;
852
853     if (!try_cast_element_spell(caster_ptr, i, chance))
854         return;
855
856     if (mana_cost <= caster_ptr->csp) {
857         caster_ptr->csp -= mana_cost;
858     } else {
859         int oops = mana_cost;
860         caster_ptr->csp = 0;
861         caster_ptr->csp_frac = 0;
862         msg_print(_("精神を集中しすぎて気を失ってしまった!", "You faint from the effort!"));
863         (void)set_paralyzed(caster_ptr, caster_ptr->paralyzed + randint1(5 * oops + 1));
864         chg_virtue(caster_ptr, V_KNOWLEDGE, -10);
865         if (randint0(100) < 50) {
866             bool perm = (randint0(100) < 25);
867             msg_print(_("体を悪くしてしまった!", "You have damaged your health!"));
868             (void)dec_stat(caster_ptr, A_CON, 15 + randint1(10), perm);
869         }
870     }
871
872     take_turn(caster_ptr, 100);
873     set_bits(caster_ptr->redraw, PR_MANA);
874     set_bits(caster_ptr->window_flags, PW_PLAYER | PW_SPELL);
875 }
876
877 /*!
878  * @brief 現在プレイヤーが使用可能な元素魔法の一覧表示
879  * @param caster_ptr プレイヤー情報への参照ポインタ
880  * @return なし
881  */
882 void do_cmd_element_browse(player_type *caster_ptr)
883 {
884     SPELL_IDX n = 0;
885     char temp[62 * 5];
886
887     screen_save();
888     while (TRUE) {
889         if (!get_element_power(caster_ptr, &n, TRUE)) {
890             screen_load();
891             return;
892         }
893
894         term_erase(12, 21, 255);
895         term_erase(12, 20, 255);
896         term_erase(12, 19, 255);
897         term_erase(12, 18, 255);
898         term_erase(12, 17, 255);
899         term_erase(12, 16, 255);
900         shape_buffer(get_element_tip(caster_ptr, n), 62, temp, sizeof(temp));
901         for (int j = 0, line = 17; temp[j]; j += (1 + strlen(&temp[j]))) {
902             prt(&temp[j], line, 15);
903             line++;
904         }
905
906         prt(_("何かキーを押して下さい。", "Hit any key."), 0, 0);
907         (void)inkey();
908     }
909 }
910
911
912 /*!
913  * @brief 元素魔法の単体抹殺の効果を発動する 
914  * @param caster_ptr プレイヤー情報への参照ポインタ
915  * @param em_ptr 魔法効果情報への参照ポインタ
916  * @return 効果処理を続けるかどうか
917  */
918 process_result effect_monster_elemental_genocide(player_type *caster_ptr, effect_monster_type *em_ptr)
919 {
920     auto types = get_element_types(caster_ptr->realm1);
921     char m_name[160];
922
923     monster_desc(caster_ptr, m_name, em_ptr->m_ptr, 0);
924     msg_format(_("%sが%sを包み込んだ。", "The %s surrounds %s."), types[0], m_name);
925
926     auto realm = static_cast<ElementRealm>(caster_ptr->realm1);
927     switch (realm) {
928     case ElementRealm::FIRE:
929         if (any_bits(em_ptr->r_ptr->r_flagsr, RFR_IM_FIRE))
930             return PROCESS_CONTINUE;
931         break;
932     case ElementRealm::ICE:
933         if (any_bits(em_ptr->r_ptr->r_flagsr, RFR_IM_COLD))
934             return PROCESS_CONTINUE;
935         break;
936     case ElementRealm::SKY:
937         if (any_bits(em_ptr->r_ptr->r_flagsr, RFR_IM_ELEC))
938             return PROCESS_CONTINUE;
939         break;
940     case ElementRealm::SEA:
941         if (any_bits(em_ptr->r_ptr->r_flagsr, RFR_IM_ACID))
942             return PROCESS_CONTINUE;
943         break;
944     case ElementRealm::DARKNESS:
945         if (any_bits(em_ptr->r_ptr->r_flagsr, RFR_RES_DARK) || any_bits(em_ptr->r_ptr->r_flags3, RF3_HURT_LITE))
946             return PROCESS_CONTINUE;
947         break;
948     case ElementRealm::CHAOS:
949         if (any_bits(em_ptr->r_ptr->r_flags3, RF3_NO_CONF))
950             return PROCESS_CONTINUE;
951         break;
952     case ElementRealm::EARTH:
953         if (any_bits(em_ptr->r_ptr->r_flagsr, RFR_RES_SHAR))
954             return PROCESS_CONTINUE;
955         break;
956     case ElementRealm::DEATH:
957         if (any_bits(em_ptr->r_ptr->r_flagsr, RFR_IM_POIS))
958             return PROCESS_CONTINUE;
959         break;
960     default:
961         return PROCESS_CONTINUE;
962     }
963
964     if (em_ptr->seen)
965         em_ptr->obvious = TRUE;
966
967     if (genocide_aux(caster_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, !em_ptr->who, (em_ptr->r_ptr->level + 1) / 2, _("モンスター消滅", "Genocide One"))) {
968         if (em_ptr->seen_msg)
969             msg_format(_("%sは消滅した!", "%^s disappeared!"), em_ptr->m_name);
970         chg_virtue(caster_ptr, V_VITALITY, -1);
971         return PROCESS_TRUE;
972     }
973
974     em_ptr->skipped = TRUE;
975     return PROCESS_CONTINUE;
976 }
977
978 /*!
979  * @brief 元素領域とレベルの条件に見合うかチェックする
980  * @param caster_ptr プレイヤー情報への参照ポインタ
981  * @param realm 領域
982  * @param lev プレイヤーレベル
983  * @return 見合うならTRUE、そうでなければFALSE
984  * @detail
985  * レベルに応じて取得する耐性などの判定に使用する
986  */
987 bool has_element_resist(player_type *creature_ptr, ElementRealm realm, PLAYER_LEVEL lev)
988 {
989     auto prealm = static_cast<ElementRealm>(creature_ptr->realm1);
990     return (prealm == realm && creature_ptr->lev >= lev);
991 }
992
993 /*!
994  * @brief 領域選択時のカーソル表示(シンボル+領域名)
995  * @param i 位置
996  * @param n 最後尾の位置
997  * @param color 表示色
998  * @return なし
999  */
1000 static void display_realm_cursor(int i, int n, term_color_type color)
1001 {
1002     char cur[80];
1003     char sym;
1004     concptr name;
1005     if (i == n) {
1006         sym = '*';
1007         name = _("ランダム", "Random");
1008     } else {
1009         sym = I2A(i);
1010         name = element_types.at(static_cast<ElementRealm>(i + 1)).title.data();
1011     }
1012     sprintf(cur, "%c) %s", sym, name);
1013
1014     c_put_str(color, cur, 12 + (i / 5), 2 + 15 * (i % 5));
1015 }
1016
1017 /*!
1018  * @brief 領域選択時の移動キー処理
1019  * @param cs 現在位置
1020  * @param n 最後尾の位置
1021  * @param c 入力キー
1022  * @return 新しい位置
1023  */
1024 static int interpret_realm_select_key(int cs, int n, char c)
1025 {
1026     if (c == 'Q')
1027         quit(NULL);
1028
1029     if (c == '8')
1030         if (cs >= 5)
1031             return cs - 5;
1032
1033     if (c == '4')
1034         if (cs > 0)
1035             return cs - 1;
1036
1037     if (c == '6')
1038         if (cs < n)
1039             return cs + 1;
1040
1041     if (c == '2')
1042         if (cs + 5 <= n)
1043             return cs + 5;
1044
1045     return cs;
1046 }
1047
1048 /*!
1049  * @brief 領域選択ループ処理
1050  * @param creature_ptr プレイヤー情報への参照ポインタ
1051  * @param n 最後尾の位置
1052  * @return 領域番号
1053  */
1054 static int get_element_realm(player_type *creature_ptr, int is, int n)
1055 {
1056     int cs = MAX(0, is);
1057     int os = cs;
1058     int k;
1059
1060     char buf[80];
1061     sprintf(buf, _("領域を選んで下さい(%c-%c) ('='初期オプション設定): ", "Choose a realm (%c-%c) ('=' for options): "), I2A(0), I2A(n - 1));
1062
1063     while (TRUE) {
1064         display_realm_cursor(os, n, TERM_WHITE);
1065         display_realm_cursor(cs, n, TERM_YELLOW);
1066         put_str(buf, 10, 10);
1067         os = cs;
1068
1069         char c = inkey();
1070         cs = interpret_realm_select_key(cs, n, c);
1071
1072         if (c == 'S')
1073             return 255;
1074
1075         if (c == ' ' || c == '\r' || c == '\n') {
1076             if (cs == n) {
1077                 display_realm_cursor(cs, n, TERM_WHITE);
1078                 cs = randint0(n - 1);
1079                 display_realm_cursor(cs, n, TERM_YELLOW);
1080             }
1081             break;
1082         }
1083
1084         if (c == '*') {
1085             display_realm_cursor(cs, n, TERM_WHITE);
1086             cs = randint0(n - 1);
1087             display_realm_cursor(cs, n, TERM_YELLOW);
1088             break;
1089         }
1090
1091         k = islower(c) ? A2I(c) : -1;
1092         if (k >= 0 && k < n) {
1093             cs = k;
1094             continue;
1095         }
1096
1097         k = isupper(c) ? (26 + c - 'A') : -1;
1098         if (k >= 26 && k < n) {
1099             cs = k;
1100             continue;
1101         }
1102
1103         if (c == '=') {
1104             screen_save();
1105             do_cmd_options_aux(creature_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score"));
1106             screen_load();
1107         } else if (c != '2' && c != '4' && c != '6' && c != '8')
1108             bell();
1109     }
1110
1111     return (cs + 1);
1112 }
1113
1114 /*!
1115  * @brief 領域選択
1116  * @param creature_ptr プレイヤー情報への参照ポインタ
1117  * @return 領域番号
1118  */
1119 byte select_element_realm(player_type *creature_ptr)
1120 {
1121     clear_from(10);
1122
1123     int realm_max = static_cast<int>(ElementRealm::MAX);
1124     int realm_idx = 1;
1125     int row = 16;
1126     while (1) {
1127         put_str(
1128             _("注意:元素系統の選択によりあなたが習得する呪文のタイプが決まります。", "Note: The system of element will determine which spells you can learn."),
1129             23, 5);
1130
1131         for (int i = 0; i < realm_max; i++) {
1132             display_realm_cursor(i, realm_max - 1, TERM_WHITE);
1133         }
1134
1135         realm_idx = get_element_realm(creature_ptr, realm_idx - 1, realm_max - 1);
1136         if (realm_idx == 255)
1137             break;
1138
1139         auto realm = static_cast<ElementRealm>(realm_idx);
1140         char temp[80 * 5];
1141         shape_buffer(element_texts.at(realm).data(), 74, temp, sizeof(temp));
1142         concptr t = temp;
1143         for (int i = 0; i < 5; i++) {
1144             if (t[0] == 0)
1145                 break;
1146             prt(t, row + i, 3);
1147             t += strlen(t) + 1;
1148         }
1149
1150         if (get_check_strict(creature_ptr, _("よろしいですか?", "Are you sure? "), CHECK_DEFAULT_Y))
1151             break;
1152
1153         clear_from(row);
1154     }
1155
1156     clear_from(10);
1157     return (byte)realm_idx;
1158 }
1159
1160 /*!
1161  * @brief クラスパワー情報を追加
1162  * @param creature_ptr プレイヤー情報への参照ポインタ
1163  * @param rc_ptr レイシャルパワー情報への参照ポインタ
1164  * @return なし
1165  */
1166 void switch_element_racial(player_type *creature_ptr, rc_type *rc_ptr)
1167 {
1168     auto realm = static_cast<ElementRealm>(creature_ptr->realm1);
1169     switch (realm) {
1170     case ElementRealm::FIRE:
1171         strcpy(rc_ptr->power_desc[rc_ptr->num].racial_name, _("ライト・エリア", "Light area"));
1172         rc_ptr->power_desc[rc_ptr->num].min_level = 3;
1173         rc_ptr->power_desc[rc_ptr->num].cost = 5;
1174         rc_ptr->power_desc[rc_ptr->num].stat = A_WIS;
1175         rc_ptr->power_desc[rc_ptr->num].fail = 10;
1176         rc_ptr->power_desc[rc_ptr->num++].number = -4;
1177         break;
1178     case ElementRealm::ICE:
1179         strcpy(rc_ptr->power_desc[rc_ptr->num].racial_name, _("フリーズ・モンスター", "Sleep monster"));
1180         rc_ptr->power_desc[rc_ptr->num].min_level = 10;
1181         rc_ptr->power_desc[rc_ptr->num].cost = 10;
1182         rc_ptr->power_desc[rc_ptr->num].stat = A_WIS;
1183         rc_ptr->power_desc[rc_ptr->num].fail = 15;
1184         rc_ptr->power_desc[rc_ptr->num++].number = -4;
1185         break;
1186     case ElementRealm::SKY:
1187         strcpy(rc_ptr->power_desc[rc_ptr->num].racial_name, _("魔力充填", "Recharging"));
1188         rc_ptr->power_desc[rc_ptr->num].min_level = 20;
1189         rc_ptr->power_desc[rc_ptr->num].cost = 15;
1190         rc_ptr->power_desc[rc_ptr->num].stat = A_WIS;
1191         rc_ptr->power_desc[rc_ptr->num].fail = 25;
1192         rc_ptr->power_desc[rc_ptr->num++].number = -4;
1193         break;
1194     case ElementRealm::SEA:
1195         strcpy(rc_ptr->power_desc[rc_ptr->num].racial_name, _("岩石溶解", "Stone to mud"));
1196         rc_ptr->power_desc[rc_ptr->num].min_level = 5;
1197         rc_ptr->power_desc[rc_ptr->num].cost = 5;
1198         rc_ptr->power_desc[rc_ptr->num].stat = A_WIS;
1199         rc_ptr->power_desc[rc_ptr->num].fail = 10;
1200         rc_ptr->power_desc[rc_ptr->num++].number = -4;
1201         break;
1202     case ElementRealm::DARKNESS:
1203         strcpy(rc_ptr->power_desc[rc_ptr->num].racial_name, _("アンデッド従属", "Enslave undead"));
1204         rc_ptr->power_desc[rc_ptr->num].min_level = 10;
1205         rc_ptr->power_desc[rc_ptr->num].cost = 10;
1206         rc_ptr->power_desc[rc_ptr->num].stat = A_WIS;
1207         rc_ptr->power_desc[rc_ptr->num].fail = 20;
1208         rc_ptr->power_desc[rc_ptr->num++].number = -4;
1209         break;
1210     case ElementRealm::CHAOS:
1211         strcpy(rc_ptr->power_desc[rc_ptr->num].racial_name, _("現実変容", "Alter reality"));
1212         rc_ptr->power_desc[rc_ptr->num].min_level = 35;
1213         rc_ptr->power_desc[rc_ptr->num].cost = 30;
1214         rc_ptr->power_desc[rc_ptr->num].stat = A_WIS;
1215         rc_ptr->power_desc[rc_ptr->num].fail = 40;
1216         rc_ptr->power_desc[rc_ptr->num++].number = -4;
1217         break;
1218     case ElementRealm::EARTH:
1219         strcpy(rc_ptr->power_desc[rc_ptr->num].racial_name, _("地震", "Earthquake"));
1220         rc_ptr->power_desc[rc_ptr->num].min_level = 25;
1221         rc_ptr->power_desc[rc_ptr->num].cost = 15;
1222         rc_ptr->power_desc[rc_ptr->num].stat = A_WIS;
1223         rc_ptr->power_desc[rc_ptr->num].fail = 20;
1224         rc_ptr->power_desc[rc_ptr->num++].number = -4;
1225         break;
1226     case ElementRealm::DEATH:
1227         strcpy(rc_ptr->power_desc[rc_ptr->num].racial_name, _("害虫駆除", "Pesticide"));
1228         rc_ptr->power_desc[rc_ptr->num].min_level = 5;
1229         rc_ptr->power_desc[rc_ptr->num].cost = 3;
1230         rc_ptr->power_desc[rc_ptr->num].stat = A_WIS;
1231         rc_ptr->power_desc[rc_ptr->num].fail = 20;
1232         rc_ptr->power_desc[rc_ptr->num++].number = -4;
1233         break;
1234     default:
1235         break;
1236     }
1237 }
1238
1239 /*!
1240  * @brief クラスパワーを実行
1241  * @param creature_ptr プレイヤー情報への参照ポインタ
1242  * @return 実行したらTRUE、しなかったらFALSE
1243  */
1244 bool switch_element_execution(player_type *creature_ptr)
1245 {
1246     auto realm = static_cast<ElementRealm>(creature_ptr->realm1);
1247     PLAYER_LEVEL plev = creature_ptr->lev;
1248     DIRECTION dir;
1249
1250     switch (realm) {
1251     case ElementRealm::FIRE:
1252         (void)lite_area(creature_ptr, damroll(2, plev / 2), plev / 10);
1253         break;
1254     case ElementRealm::ICE:
1255         if (!get_aim_dir(creature_ptr, &dir))
1256             return FALSE;
1257         (void)project_hook(creature_ptr, GF_OLD_SLEEP, dir, (plev * 2), PROJECT_STOP | PROJECT_KILL | PROJECT_REFLECTABLE);
1258         break;
1259     case ElementRealm::SKY:
1260         (void)recharge(creature_ptr, 120);
1261         break;
1262     case ElementRealm::SEA:
1263         if (!get_aim_dir(creature_ptr, &dir))
1264             return FALSE;
1265         (void)wall_to_mud(creature_ptr, dir, plev * 3 / 2);
1266         break;
1267     case ElementRealm::DARKNESS:
1268         if (!get_aim_dir(creature_ptr, &dir))
1269             return FALSE;
1270         (void)control_one_undead(creature_ptr, dir, plev * 3 / 2);
1271         break;
1272     case ElementRealm::CHAOS:
1273         reserve_alter_reality(creature_ptr, randint0(21) + 15);
1274         break;
1275     case ElementRealm::EARTH:
1276         (void)earthquake(creature_ptr, creature_ptr->y, creature_ptr->x, 10, 0);
1277         break;
1278     case ElementRealm::DEATH:
1279         (void)dispel_monsters(creature_ptr, plev / 2);
1280         break;
1281     default:
1282         return FALSE;
1283     }
1284
1285     return TRUE;
1286 }