OSDN Git Service

Merge pull request #674 from iks3/fix-monomane-damage-zero
[hengbandforosx/hengbandosx.git] / src / mspell / mspell-status.cpp
1 /*!
2  * @brief プレーヤーのステータスを下げるか、モンスター自身のステータスを上げるスペル類の処理
3  * @date 2020/05/16
4  * @author Hourier
5  * @todo やや過密気味。モンスター自身のステータスとプレーヤーのステータスで分けてもいいかもしれない.
6  */
7
8 #include "mspell/mspell-status.h"
9 #include "blue-magic/blue-magic-checker.h"
10 #include "core/disturbance.h"
11 #include "core/player-redraw-types.h"
12 #include "effect/effect-processor.h"
13 #include "mind/drs-types.h"
14 #include "monster-race/monster-race.h"
15 #include "monster-race/race-flags1.h"
16 #include "monster-race/race-flags3.h"
17 #include "monster-race/race-indice-types.h"
18 #include "monster/monster-describer.h"
19 #include "monster/monster-description-types.h"
20 #include "monster/monster-info.h"
21 #include "monster/monster-status-setter.h"
22 #include "monster/monster-status.h"
23 #include "monster/monster-update.h"
24 #include "mspell/mspell-checker.h"
25 #include "mspell/mspell-damage-calculator.h"
26 #include "mspell/mspell-util.h"
27 #include "mspell/mspell.h"
28 #include "player/player-personalities-types.h"
29 #include "player/player-status-flags.h"
30 #include "spell/spell-types.h"
31 #include "status/bad-status-setter.h"
32 #include "status/base-status.h"
33 #include "system/floor-type-definition.h"
34 #include "view/display-messages.h"
35
36 /*!
37  * @brief 状態異常呪文のメッセージ処理関数。 /
38  * @param target_ptr プレーヤーへの参照ポインタ
39  * @param m_idx 呪文を唱えるモンスターID
40  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
41  * @param msg1 対プレイヤーなら盲目時メッセージ。対モンスターなら通常時メッセージ。
42  * @param msg2 対プレイヤーなら非盲目時メッセージ。対モンスターなら耐性有メッセージ。
43  * @param msg3 対プレイヤーなら耐性有メッセージ。対モンスターなら抵抗時メッセージ。
44  * @param msg4 対プレイヤーなら抵抗時メッセージ。対モンスターなら成功時メッセージ。
45  * @param resist 耐性の有無を判別するフラグ
46  * @param saving_throw 抵抗に成功したか判別するフラグ
47  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
48  */
49 void spell_badstatus_message(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, concptr msg1, concptr msg2, concptr msg3, concptr msg4, bool resist,
50     bool saving_throw, int TARGET_TYPE)
51 {
52     floor_type *floor_ptr = target_ptr->current_floor_ptr;
53     bool see_either = see_monster(target_ptr, m_idx) || see_monster(target_ptr, t_idx);
54     bool see_t = see_monster(target_ptr, t_idx);
55     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
56     GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN];
57     monster_name(target_ptr, m_idx, m_name);
58     monster_name(target_ptr, t_idx, t_name);
59
60     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
61         disturb(target_ptr, TRUE, TRUE);
62         if (target_ptr->blind)
63             msg_format(msg1, m_name);
64         else
65             msg_format(msg2, m_name);
66
67         if (resist) {
68             msg_print(msg3);
69         } else if (saving_throw) {
70             msg_print(msg4);
71         }
72
73         return;
74     }
75
76     if (TARGET_TYPE != MONSTER_TO_MONSTER)
77         return;
78
79     if (known) {
80         if (see_either) {
81             msg_format(msg1, m_name, t_name);
82         } else {
83             floor_ptr->monster_noise = TRUE;
84         }
85     }
86
87     if (resist) {
88         if (see_t)
89             msg_format(msg2, t_name);
90     } else if (saving_throw) {
91         if (see_t)
92             msg_format(msg3, t_name);
93     } else {
94         if (see_t)
95             msg_format(msg4, t_name);
96     }
97
98     set_monster_csleep(target_ptr, t_idx, 0);
99 }
100
101 /*!
102  * @brief RF5_DRAIN_MANAの処理。魔力吸収。 /
103  * @param target_ptr プレーヤーへの参照ポインタ
104  * @param y 対象の地点のy座標
105  * @param x 対象の地点のx座標
106  * @param m_idx 呪文を唱えるモンスターID
107  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
108  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
109  *
110  * プレイヤーに当たったらラーニング可。
111  */
112 MonsterSpellResult spell_RF5_DRAIN_MANA(player_type *target_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
113 {
114     GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN];
115     monster_name(target_ptr, m_idx, m_name);
116     monster_name(target_ptr, t_idx, t_name);
117
118     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
119         disturb(target_ptr, TRUE, TRUE);
120     } else if (TARGET_TYPE == MONSTER_TO_MONSTER && see_monster(target_ptr, m_idx)) {
121         /* Basic message */
122         msg_format(_("%^sは精神エネルギーを%sから吸いとった。", "%^s draws psychic energy from %s."), m_name, t_name);
123     }
124
125     const auto dam = monspell_damage(target_ptr, (MS_DRAIN_MANA), m_idx, DAM_ROLL);
126     const auto proj_res = breath(target_ptr, y, x, m_idx, GF_DRAIN_MANA, dam, 0, FALSE, MS_DRAIN_MANA, TARGET_TYPE);
127     if (TARGET_TYPE == MONSTER_TO_PLAYER)
128         update_smart_learn(target_ptr, m_idx, DRS_MANA);
129
130     auto res = MonsterSpellResult::make_valid();
131     res.learnable = proj_res.affected_player;
132
133     return res;
134 }
135
136 /*!
137  * @brief RF5_MIND_BLASTの処理。精神攻撃。 /
138  * @param target_ptr プレーヤーへの参照ポインタ
139  * @param y 対象の地点のy座標
140  * @param x 対象の地点のx座標
141  * @param m_idx 呪文を唱えるモンスターID
142  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
143  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
144  *
145  * プレイヤーに当たったらラーニング可。
146  */
147 MonsterSpellResult spell_RF5_MIND_BLAST(player_type *target_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
148 {
149     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
150     bool seen = (!target_ptr->blind && m_ptr->ml);
151     GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN];
152     monster_name(target_ptr, m_idx, m_name);
153     monster_name(target_ptr, t_idx, t_name);
154
155     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
156         disturb(target_ptr, TRUE, TRUE);
157         if (!seen)
158             msg_print(_("何かがあなたの精神に念を放っているようだ。", "You feel something focusing on your mind."));
159         else
160             msg_format(_("%^sがあなたの瞳をじっとにらんでいる。", "%^s gazes deep into your eyes."), m_name);
161     } else if (TARGET_TYPE == MONSTER_TO_MONSTER && see_monster(target_ptr, m_idx)) {
162         msg_format(_("%^sは%sをじっと睨んだ。", "%^s gazes intently at %s."), m_name, t_name);
163     }
164
165     const auto dam = monspell_damage(target_ptr, (MS_MIND_BLAST), m_idx, DAM_ROLL);
166     const auto proj_res = breath(target_ptr, y, x, m_idx, GF_MIND_BLAST, dam, 0, FALSE, MS_MIND_BLAST, TARGET_TYPE);
167
168     auto res = MonsterSpellResult::make_valid(dam);
169     res.learnable = proj_res.affected_player;
170
171     return res;
172 }
173
174 /*!
175  * @brief RF5_BRAIN_SMASHの処理。脳攻撃。 /
176  * @param target_ptr プレーヤーへの参照ポインタ
177  * @param y 対象の地点のy座標
178  * @param x 対象の地点のx座標
179  * @param m_idx 呪文を唱えるモンスターID
180  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
181  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
182  *
183  * プレイヤーに当たったらラーニング可。
184  */
185 MonsterSpellResult spell_RF5_BRAIN_SMASH(player_type *target_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
186 {
187     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
188     bool seen = (!target_ptr->blind && m_ptr->ml);
189     GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN];
190     monster_name(target_ptr, m_idx, m_name);
191     monster_name(target_ptr, t_idx, t_name);
192
193     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
194         disturb(target_ptr, TRUE, TRUE);
195         if (!seen)
196             msg_print(_("何かがあなたの精神に念を放っているようだ。", "You feel something focusing on your mind."));
197         else
198             msg_format(_("%^sがあなたの瞳をじっとにらんでいる。", "%^s gazes deep into your eyes."), m_name);
199     } else if (TARGET_TYPE == MONSTER_TO_MONSTER && see_monster(target_ptr, m_idx)) {
200         msg_format(_("%^sは%sをじっと睨んだ。", "%^s gazes intently at %s."), m_name, t_name);
201     }
202
203     const auto dam = monspell_damage(target_ptr, (MS_BRAIN_SMASH), m_idx, DAM_ROLL);
204     const auto proj_res = breath(target_ptr, y, x, m_idx, GF_BRAIN_SMASH, dam, 0, FALSE, MS_BRAIN_SMASH, TARGET_TYPE);
205
206     auto res = MonsterSpellResult::make_valid(dam);
207     res.learnable = proj_res.affected_player;
208
209     return res;
210 }
211
212 /*!
213  * @brief RF5_SCAREの処理。恐怖。 /
214  * @param m_idx 呪文を唱えるモンスターID
215  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
216  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
217  *
218  * プレイヤーが対象ならラーニング可。
219  */
220 MonsterSpellResult spell_RF5_SCARE(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_idx, int TARGET_TYPE)
221 {
222     auto res = MonsterSpellResult::make_valid();
223     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
224
225     floor_type *floor_ptr = target_ptr->current_floor_ptr;
226     monster_type *t_ptr = &floor_ptr->m_list[t_idx];
227     monster_race *tr_ptr = &r_info[t_ptr->r_idx];
228     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
229     bool resist, saving_throw;
230
231     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
232         resist = (has_resist_fear(target_ptr) != 0);
233         saving_throw = (randint0(100 + rlev / 2) < target_ptr->skill_sav);
234         spell_badstatus_message(target_ptr, m_idx, t_idx, _("%^sが何かをつぶやくと、恐ろしげな音が聞こえた。", "%^s mumbles, and you hear scary noises."),
235             _("%^sが恐ろしげな幻覚を作り出した。", "%^s casts a fearful illusion."), _("しかし恐怖に侵されなかった。", "You refuse to be frightened."),
236             _("しかし恐怖に侵されなかった。", "You refuse to be frightened."), resist, saving_throw, TARGET_TYPE);
237
238         if (!resist && !saving_throw) {
239             (void)set_afraid(target_ptr, target_ptr->afraid + randint0(4) + 4);
240         }
241
242         update_smart_learn(target_ptr, m_idx, DRS_FEAR);
243         return res;
244     }
245
246     if (TARGET_TYPE != MONSTER_TO_MONSTER)
247         return res;
248
249     resist = ((tr_ptr->flags3 & RF3_NO_FEAR) != 0);
250     saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
251
252     spell_badstatus_message(target_ptr, m_idx, t_idx, _("%^sが恐ろしげな幻覚を作り出した。", "%^s casts a fearful illusion in front of %s."),
253         _("%^sは恐怖を感じない。", "%^s refuses to be frightened."), _("%^sは恐怖を感じない。", "%^s refuses to be frightened."),
254         _("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), resist, saving_throw, TARGET_TYPE);
255
256     if (!resist && !saving_throw) {
257         set_monster_monfear(target_ptr, t_idx, monster_fear_remaining(t_ptr) + randint0(4) + 4);
258     }
259
260     return res;
261 }
262
263 /*!
264  * @brief RF5_BLINDの処理。盲目。 /
265  * @param m_idx 呪文を唱えるモンスターID
266  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
267  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
268  *
269  * プレイヤーが対象ならラーニング可。
270  */
271 MonsterSpellResult spell_RF5_BLIND(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_idx, int TARGET_TYPE)
272 {
273     auto res = MonsterSpellResult::make_valid();
274     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
275
276     floor_type *floor_ptr = target_ptr->current_floor_ptr;
277     monster_type *t_ptr = &floor_ptr->m_list[t_idx];
278     monster_race *tr_ptr = &r_info[t_ptr->r_idx];
279     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
280     bool resist, saving_throw;
281
282     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
283         resist = (has_resist_blind(target_ptr) != 0);
284         saving_throw = (randint0(100 + rlev / 2) < target_ptr->skill_sav);
285         spell_badstatus_message(target_ptr, m_idx, t_idx, _("%^sが何かをつぶやいた。", "%^s mumbles."),
286             _("%^sが呪文を唱えてあなたの目をくらました!", "%^s casts a spell, burning your eyes!"), _("しかし効果がなかった!", "You are unaffected!"),
287             _("しかし効力を跳ね返した!", "You resist the effects!"), resist, saving_throw, TARGET_TYPE);
288
289         if (!resist && !saving_throw) {
290             (void)set_blind(target_ptr, 12 + randint0(4));
291         }
292
293         update_smart_learn(target_ptr, m_idx, DRS_BLIND);
294         return res;
295     }
296
297     if (TARGET_TYPE != MONSTER_TO_MONSTER)
298         return res;
299
300     concptr msg1;
301     GAME_TEXT t_name[MAX_NLEN];
302     monster_name(target_ptr, t_idx, t_name);
303
304     if (streq(t_name, "it")) {
305         msg1 = _("%sは呪文を唱えて%sの目を焼き付かせた。", "%^s casts a spell, burning %ss eyes.");
306     } else {
307         msg1 = _("%sは呪文を唱えて%sの目を焼き付かせた。", "%^s casts a spell, burning %s's eyes.");
308     }
309
310     resist = ((tr_ptr->flags3 & RF3_NO_CONF) != 0);
311     saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
312
313     spell_badstatus_message(target_ptr, m_idx, t_idx, msg1, _("%^sには効果がなかった。", "%^s is unaffected."),
314         _("%^sには効果がなかった。", "%^s is unaffected."), _("%^sは目が見えなくなった! ", "%^s is blinded!"), resist, saving_throw, TARGET_TYPE);
315
316     if (!resist && !saving_throw) {
317         (void)set_monster_confused(target_ptr, t_idx, monster_confused_remaining(t_ptr) + 12 + randint0(4));
318     }
319
320     return res;
321 }
322
323 /*!
324  * @brief RF5_CONFの処理。混乱。/
325  * @param m_idx 呪文を唱えるモンスターID
326  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
327  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
328  *
329  * プレイヤーが対象ならラーニング可。
330  */
331 MonsterSpellResult spell_RF5_CONF(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_idx, int TARGET_TYPE)
332 {
333     auto res = MonsterSpellResult::make_valid();
334     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
335
336     floor_type *floor_ptr = target_ptr->current_floor_ptr;
337     monster_type *t_ptr = &floor_ptr->m_list[t_idx];
338     monster_race *tr_ptr = &r_info[t_ptr->r_idx];
339     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
340     bool resist, saving_throw;
341
342     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
343         resist = (has_resist_conf(target_ptr) != 0);
344         saving_throw = (randint0(100 + rlev / 2) < target_ptr->skill_sav);
345         spell_badstatus_message(target_ptr, m_idx, t_idx, _("%^sが何かをつぶやくと、頭を悩ます音がした。", "%^s mumbles, and you hear puzzling noises."),
346             _("%^sが誘惑的な幻覚を作り出した。", "%^s creates a mesmerising illusion."),
347             _("しかし幻覚にはだまされなかった。", "You disbelieve the feeble spell."),
348             _("しかし幻覚にはだまされなかった。", "You disbelieve the feeble spell."), resist, saving_throw, TARGET_TYPE);
349
350         if (!resist && !saving_throw) {
351             (void)set_confused(target_ptr, target_ptr->confused + randint0(4) + 4);
352         }
353
354         update_smart_learn(target_ptr, m_idx, DRS_CONF);
355         return res;
356     }
357
358     if (TARGET_TYPE != MONSTER_TO_MONSTER)
359         return res;
360
361     resist = ((tr_ptr->flags3 & RF3_NO_CONF) != 0);
362     saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
363
364     spell_badstatus_message(target_ptr, m_idx, t_idx, _("%^sが%sの前に幻惑的な幻をつくり出した。", "%^s casts a mesmerizing illusion in front of %s."),
365         _("%^sは惑わされなかった。", "%^s disbelieves the feeble spell."), _("%^sは惑わされなかった。", "%^s disbelieves the feeble spell."),
366         _("%^sは混乱したようだ。", "%^s seems confused."), resist, saving_throw, TARGET_TYPE);
367
368     if (!resist && !saving_throw) {
369         (void)set_monster_confused(target_ptr, t_idx, monster_confused_remaining(t_ptr) + 12 + randint0(4));
370     }
371
372     return res;
373 }
374
375 /*!
376  * @brief RF5_HOLDの処理。麻痺。 /
377  * @param m_idx 呪文を唱えるモンスターID
378  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
379  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
380  *
381  * プレイヤーが対象ならラーニング可。
382  */
383 MonsterSpellResult spell_RF5_HOLD(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_idx, int TARGET_TYPE)
384 {
385     auto res = MonsterSpellResult::make_valid();
386     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
387
388     floor_type *floor_ptr = target_ptr->current_floor_ptr;
389     monster_type *t_ptr = &floor_ptr->m_list[t_idx];
390     monster_race *tr_ptr = &r_info[t_ptr->r_idx];
391     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
392     bool resist, saving_throw;
393
394     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
395         resist = (target_ptr->free_act != 0);
396         saving_throw = (randint0(100 + rlev / 2) < target_ptr->skill_sav);
397         spell_badstatus_message(target_ptr, m_idx, t_idx, _("%^sが何かをつぶやいた。", "%^s mumbles."),
398             _("%^sがあなたの目をじっと見つめた!", "%^s stares deep into your eyes!"), _("しかし効果がなかった!", "You are unaffected!"),
399             _("しかし効力を跳ね返した!", "You resist the effects!"), (bool)resist, saving_throw, TARGET_TYPE);
400
401         if (!resist && !saving_throw) {
402             (void)set_paralyzed(target_ptr, target_ptr->paralyzed + randint0(4) + 4);
403         }
404
405         update_smart_learn(target_ptr, m_idx, DRS_FREE);
406         return res;
407     }
408
409     if (TARGET_TYPE != MONSTER_TO_MONSTER)
410         return res;
411
412     resist = ((tr_ptr->flags1 & RF1_UNIQUE) != 0 || (tr_ptr->flags3 & RF3_NO_STUN) != 0);
413     saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
414
415     spell_badstatus_message(target_ptr, m_idx, t_idx, _("%^sは%sをじっと見つめた。", "%^s stares intently at %s."),
416         _("%^sには効果がなかった。", "%^s is unaffected."), _("%^sには効果がなかった。", "%^s is unaffected."), _("%^sは麻痺した!", "%^s is paralyzed!"),
417         (bool)resist, saving_throw, TARGET_TYPE);
418
419     if (!resist && !saving_throw) {
420         (void)set_monster_stunned(target_ptr, t_idx, monster_stunned_remaining(t_ptr) + randint1(4) + 4);
421     }
422
423     return res;
424 }
425
426 /*!
427  * @brief RF6_HASTEの処理。加速。 /
428  * @param target_ptr プレーヤーへの参照ポインタ
429  * @param m_idx 呪文を唱えるモンスターID
430  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
431  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
432  *
433  * ラーニング不可。
434  */
435 MonsterSpellResult spell_RF6_HASTE(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
436 {
437     bool see_m = see_monster(target_ptr, m_idx);
438     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
439     GAME_TEXT m_name[MAX_NLEN];
440     monster_name(target_ptr, m_idx, m_name);
441     char m_poss[10];
442     monster_desc(target_ptr, m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
443
444     monspell_message_base(target_ptr, m_idx, t_idx, _("%^sが何かをつぶやいた。", "%^s mumbles."),
445         _("%^sが自分の体に念を送った。", format("%%^s concentrates on %s body.", m_poss)),
446         _("%^sが自分の体に念を送った。", format("%%^s concentrates on %s body.", m_poss)),
447         _("%^sが自分の体に念を送った。", format("%%^s concentrates on %s body.", m_poss)), target_ptr->blind > 0, TARGET_TYPE);
448
449     if (set_monster_fast(target_ptr, m_idx, monster_fast_remaining(m_ptr) + 100)) {
450         if (TARGET_TYPE == MONSTER_TO_PLAYER || (TARGET_TYPE == MONSTER_TO_MONSTER && see_m))
451             msg_format(_("%^sの動きが速くなった。", "%^s starts moving faster."), m_name);
452     }
453
454     return MonsterSpellResult::make_valid();
455 }
456
457 /*!
458  * @brief RF5_SLOWの処理。減速。 /
459  * @param m_idx 呪文を唱えるモンスターID
460  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
461  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
462  *
463  * プレイヤーが対象ならラーニング可。
464  */
465 MonsterSpellResult spell_RF5_SLOW(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_idx, int TARGET_TYPE)
466 {
467     auto res = MonsterSpellResult::make_valid();
468     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
469
470     floor_type *floor_ptr = target_ptr->current_floor_ptr;
471     monster_type *t_ptr = &floor_ptr->m_list[t_idx];
472     monster_race *tr_ptr = &r_info[t_ptr->r_idx];
473     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
474     bool resist, saving_throw;
475
476     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
477         resist = (has_resist_conf(target_ptr) != 0);
478         saving_throw = (randint0(100 + rlev / 2) < target_ptr->skill_sav);
479         spell_badstatus_message(target_ptr, m_idx, t_idx, _("%^sがあなたの筋力を吸い取ろうとした!", "%^s drains power from your muscles!"),
480             _("%^sがあなたの筋力を吸い取ろうとした!", "%^s drains power from your muscles!"), _("しかし効果がなかった!", "You are unaffected!"),
481             _("しかし効力を跳ね返した!", "You resist the effects!"), resist, saving_throw, TARGET_TYPE);
482
483         if (!resist && !saving_throw) {
484             (void)set_slow(target_ptr, target_ptr->slow + randint0(4) + 4, FALSE);
485         }
486
487         update_smart_learn(target_ptr, m_idx, DRS_FREE);
488         return res;
489     }
490
491     if (TARGET_TYPE != MONSTER_TO_MONSTER)
492         return res;
493
494     concptr msg1;
495     GAME_TEXT t_name[MAX_NLEN];
496     monster_name(target_ptr, t_idx, t_name);
497
498     if (streq(t_name, "it")) {
499         msg1 = _("%sが%sの筋肉から力を吸いとった。", "%^s drains power from %ss muscles.");
500     } else {
501         msg1 = _("%sが%sの筋肉から力を吸いとった。", "%^s drains power from %s's muscles.");
502     }
503
504     resist = ((tr_ptr->flags1 & RF1_UNIQUE) != 0);
505     saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
506
507     spell_badstatus_message(target_ptr, m_idx, t_idx, msg1, _("%^sには効果がなかった。", "%^s is unaffected."),
508         _("%^sには効果がなかった。", "%^s is unaffected."), _("%sの動きが遅くなった。", "%^s starts moving slower."), resist, saving_throw, TARGET_TYPE);
509
510     if (!resist && !saving_throw) {
511         set_monster_slow(target_ptr, t_idx, monster_slow_remaining(t_ptr) + 50);
512     }
513
514     return res;
515 }
516
517 /*!
518  * @brief RF6_HEALの処理。治癒。 /
519  * @param target_ptr プレーヤーへの参照ポインタ
520  * @param m_idx 呪文を唱えるモンスターID
521  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
522  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
523  *
524  * ラーニング不可。
525  */
526 MonsterSpellResult spell_RF6_HEAL(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
527 {
528     const auto res = MonsterSpellResult::make_valid();
529
530     floor_type *floor_ptr = target_ptr->current_floor_ptr;
531     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
532     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
533     bool seen = (!target_ptr->blind && m_ptr->ml);
534     GAME_TEXT m_name[MAX_NLEN];
535     monster_name(target_ptr, m_idx, m_name);
536     char m_poss[10];
537     monster_desc(target_ptr, m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
538
539     disturb(target_ptr, TRUE, TRUE);
540
541     monspell_message_base(target_ptr, m_idx, t_idx, _("%^sが何かをつぶやいた。", "%^s mumbles."),
542         _("%^sは自分の傷に念を集中した。", format("%%^s concentrates on %s wounds.", m_poss)),
543         _("%^sが自分の傷に集中した。", format("%%^s concentrates on %s wounds.", m_poss)),
544         _("%^sは自分の傷に念を集中した。", format("%%^s concentrates on %s wounds.", m_poss)), target_ptr->blind > 0, TARGET_TYPE);
545
546     m_ptr->hp += (rlev * 6);
547     if (m_ptr->hp >= m_ptr->maxhp) {
548         /* Fully healed */
549         m_ptr->hp = m_ptr->maxhp;
550
551         monspell_message_base(target_ptr, m_idx, t_idx, _("%^sは完全に治ったようだ!", "%^s sounds completely healed!"),
552             _("%^sは完全に治ったようだ!", "%^s sounds completely healed!"), _("%^sは完全に治った!", "%^s looks completely healed!"),
553             _("%^sは完全に治った!", "%^s looks completely healed!"), !seen, TARGET_TYPE);
554     } else {
555         monspell_message_base(target_ptr, m_idx, t_idx, _("%^sは体力を回復したようだ。", "%^s sounds healthier."),
556             _("%^sは体力を回復したようだ。", "%^s sounds healthier."), _("%^sは体力を回復したようだ。", "%^s looks healthier."),
557             _("%^sは体力を回復したようだ。", "%^s looks healthier."), !seen, TARGET_TYPE);
558     }
559
560     if (target_ptr->health_who == m_idx)
561         target_ptr->redraw |= (PR_HEALTH);
562     if (target_ptr->riding == m_idx)
563         target_ptr->redraw |= (PR_UHEALTH);
564
565     if (!monster_fear_remaining(m_ptr))
566         return res;
567
568     (void)set_monster_monfear(target_ptr, m_idx, 0);
569
570     if (see_monster(target_ptr, m_idx))
571         msg_format(_("%^sは勇気を取り戻した。", format("%%^s recovers %s courage.", m_poss)), m_name);
572
573     return res;
574 }
575
576 /*!
577  * @brief RF6_INVULNERの処理。無敵。 /
578  * @param target_ptr プレーヤーへの参照ポインタ
579  * @param m_idx 呪文を唱えるモンスターID
580  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
581  * @param TARGET_TYPE プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
582  *
583  * ラーニング不可。
584  */
585 MonsterSpellResult spell_RF6_INVULNER(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
586 {
587     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
588     bool seen = (!target_ptr->blind && m_ptr->ml);
589
590     monspell_message_base(target_ptr, m_idx, t_idx, _("%^sが何かを力強くつぶやいた。", "%^s mumbles powerfully."),
591         _("%^sが何かを力強くつぶやいた。", "%^s mumbles powerfully."), _("%sは無傷の球の呪文を唱えた。", "%^s casts a Globe of Invulnerability."),
592         _("%sは無傷の球の呪文を唱えた。", "%^s casts a Globe of Invulnerability."), !seen, TARGET_TYPE);
593
594     MONRACE_IDX r_idx = m_ptr->r_idx;
595     if ((r_idx == MON_MARIO) || r_idx == MON_LUIGI) {
596         GAME_TEXT m_name[MAX_NLEN];
597         monster_desc(target_ptr, m_name, m_ptr, MD_NONE);
598         msg_format(_("%sはスターを取った!", "%^s got a star!"), m_name);
599     }
600
601     if (!monster_invulner_remaining(m_ptr))
602         (void)set_monster_invulner(target_ptr, m_idx, randint1(4) + 4, FALSE);
603
604     return MonsterSpellResult::make_valid();
605 }
606
607 /*!
608  * @brief RF6_FORGETの処理。記憶消去。 /
609  * @param target_ptr プレーヤーへの参照ポインタ
610  * @param m_idx 呪文を唱えるモンスターID
611  *
612  * ラーニング可。
613  */
614 MonsterSpellResult spell_RF6_FORGET(player_type *target_ptr, MONSTER_IDX m_idx)
615 {
616     DEPTH rlev = monster_level_idx(target_ptr->current_floor_ptr, m_idx);
617     GAME_TEXT m_name[MAX_NLEN];
618     monster_name(target_ptr, m_idx, m_name);
619
620     disturb(target_ptr, TRUE, TRUE);
621
622     msg_format(_("%^sがあなたの記憶を消去しようとしている。", "%^s tries to blank your mind."), m_name);
623
624     if (randint0(100 + rlev / 2) < target_ptr->skill_sav) {
625         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
626     } else if (lose_all_info(target_ptr)) {
627         msg_print(_("記憶が薄れてしまった。", "Your memories fade away."));
628     }
629
630     auto res = MonsterSpellResult::make_valid();
631     res.learnable = true;
632
633     return res;
634 }