OSDN Git Service

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