OSDN Git Service

Merge pull request #1927 from dis-/feature/fix-special-disturb
[hengbandforosx/hengbandosx.git] / src / mspell / mspell-summon.cpp
1 #include "mspell/mspell-summon.h"
2 #include "core/disturbance.h"
3 #include "effect/effect-characteristics.h"
4 #include "effect/effect-processor.h"
5 #include "floor/cave.h"
6 #include "game-option/birth-options.h"
7 #include "monster-floor/monster-summon.h"
8 #include "monster-floor/place-monster-types.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-flags1.h"
11 #include "monster-race/race-indice-types.h"
12 #include "monster/monster-describer.h"
13 #include "monster/monster-description-types.h"
14 #include "monster/monster-info.h"
15 #include "monster/monster-status.h"
16 #include "mspell/mspell-result.h"
17 #include "mspell/mspell-util.h"
18 #include "mspell/specified-summon.h"
19 #include "spell-kind/spells-launcher.h"
20 #include "effect/attribute-types.h"
21 #include "spell/spells-summon.h"
22 #include "spell/summon-types.h"
23 #include "system/floor-type-definition.h"
24 #include "system/monster-race-definition.h"
25 #include "system/monster-type-definition.h"
26 #include "system/player-type-definition.h"
27 #include "util/bit-flags-calculator.h"
28 #include "view/display-messages.h"
29
30 /* summoning number */
31 constexpr int S_NUM_6 = 6;
32 constexpr int S_NUM_4 = 4;
33
34 /*!
35  * @brief モンスターが召喚呪文を使った際にプレイヤーの連続行動を止める処理 /
36  * @param player_ptr プレイヤーへの参照ポインタ
37  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
38  * @param known モンスターが近くにいる場合TRUE
39  * @param see_either モンスターを視認可能な場合TRUE
40  */
41 static void summon_disturb(PlayerType *player_ptr, int target_type, bool known, bool see_either)
42 {
43     bool mon_to_mon = target_type == MONSTER_TO_MONSTER;
44     bool mon_to_player = target_type == MONSTER_TO_PLAYER;
45     if (mon_to_player || (mon_to_mon && known && see_either)) {
46         disturb(player_ptr, true, true);
47     }
48 }
49
50
51 /*!
52  * @brief 特定条件のモンスター召喚のみPM_ALLOW_UNIQUEを許可する /
53  * @param floor_ptr 現在フロアへの参照ポインタ
54  * @param m_idx モンスターID
55  * @return 召喚可能であればPM_ALLOW_UNIQUEを返す。
56  */
57 static BIT_FLAGS monster_u_mode(floor_type *floor_ptr, MONSTER_IDX m_idx)
58 {
59     BIT_FLAGS u_mode = 0L;
60     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
61     bool pet = is_pet(m_ptr);
62     if (!pet)
63         u_mode |= PM_ALLOW_UNIQUE;
64     return u_mode;
65 }
66
67 /*!
68  * @brief 救援召喚の通常処理。同シンボルのモンスターを召喚する。 /
69  * @param player_ptr プレイヤーへの参照ポインタ
70  * @param y 対象の地点のy座標
71  * @param x 対象の地点のx座標
72  * @param rlev 呪文を唱えるモンスターのレベル
73  * @param m_idx 呪文を唱えるモンスターID
74  * @return 召喚したモンスターの数を返す。
75  */
76 static MONSTER_NUMBER summon_Kin(PlayerType *player_ptr, POSITION y, POSITION x, int rlev, MONSTER_IDX m_idx)
77 {
78     int count = 0;
79     for (int k = 0; k < 4; k++) {
80         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_KIN, PM_ALLOW_GROUP);
81     }
82
83     return count;
84 }
85
86 static void decide_summon_kin_caster(
87     PlayerType *player_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type, concptr m_name, concptr m_poss, const bool known)
88 {
89     floor_type *floor_ptr = player_ptr->current_floor_ptr;
90     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
91     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
92     bool mon_to_mon = target_type == MONSTER_TO_MONSTER;
93     bool mon_to_player = target_type == MONSTER_TO_PLAYER;
94
95     if (m_ptr->r_idx == MON_SERPENT || m_ptr->r_idx == MON_ZOMBI_SERPENT) {
96         mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
97             _("%^sがダンジョンの主を召喚した。", "%^s magically summons guardians of dungeons."),
98             _("%^sがダンジョンの主を召喚した。", "%^s magically summons guardians of dungeons."));
99
100         monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
101         return;
102     }
103
104     summon_disturb(player_ptr, target_type, known, see_either);
105
106     if (player_ptr->blind) {
107         if (mon_to_player)
108             msg_format(_("%^sが何かをつぶやいた。", "%^s mumbles."), m_name);
109     } else if (mon_to_player || (mon_to_mon && known && see_either)) {
110         monster_race *r_ptr = &r_info[m_ptr->r_idx];
111 #ifdef JP
112         (void)m_poss;
113 #endif
114         _(msg_format("%sが魔法で%sを召喚した。", m_name, ((r_ptr->flags1 & RF1_UNIQUE) ? "手下" : "仲間")),
115             msg_format("%^s magically summons %s %s.", m_name, m_poss, ((r_ptr->flags1 & RF1_UNIQUE) ? "minions" : "kin")));
116     }
117
118     if (mon_to_mon && known && !see_either)
119         floor_ptr->monster_noise = true;
120 }
121
122 /*!
123  * @brief RF6_S_KINの処理。救援召喚。使用するモンスターの種類により、実処理に分岐させる。 /
124  * @param player_ptr プレイヤーへの参照ポインタ
125  * @param y 対象の地点のy座標
126  * @param x 対象の地点のx座標
127  * @param m_idx 呪文を唱えるモンスターID
128  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
129  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
130  *
131  * プレイヤーが対象ならラーニング可。
132  */
133 MonsterSpellResult spell_RF6_S_KIN(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
134 {
135     floor_type *floor_ptr = player_ptr->current_floor_ptr;
136     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
137     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
138     GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN], m_poss[80];
139     monster_name(player_ptr, m_idx, m_name);
140     monster_name(player_ptr, t_idx, t_name);
141     monster_desc(player_ptr, m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
142     
143     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
144     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
145
146     summon_disturb(player_ptr, target_type, known, see_either);
147
148     decide_summon_kin_caster(player_ptr, m_idx, t_idx, target_type, m_name, m_poss, known);
149     int count = 0;
150     switch (m_ptr->r_idx) {
151     case MON_MENELDOR:
152     case MON_GWAIHIR:
153     case MON_THORONDOR:
154         count += summon_EAGLE(player_ptr, y, x, rlev, m_idx);
155         break;
156     case MON_BULLGATES:
157         count += summon_EDGE(player_ptr, y, x, rlev, m_idx);
158         break;
159     case MON_SERPENT:
160     case MON_ZOMBI_SERPENT:
161         count += summon_guardian(player_ptr, y, x, rlev, m_idx, t_idx, target_type);
162         break;
163     case MON_TIAMAT:
164         count += summon_HIGHEST_DRAGON(player_ptr, y, x, m_idx);
165         break;
166     case MON_CALDARM:
167         count += summon_LOCKE_CLONE(player_ptr, y, x, m_idx);
168         break;
169     case MON_LOUSY:
170         count += summon_LOUSE(player_ptr, y, x, rlev, m_idx);
171         break;
172     case MON_VAIF:
173         count += summon_MOAI(player_ptr, y, x, rlev, m_idx);
174         break;
175     case MON_DEMON_SLAYER_SENIOR:
176         count += summon_DEMON_SLAYER(player_ptr, y, x, m_idx);
177         break;
178     case MON_ALDUIN:
179         count += summon_HIGHEST_DRAGON(player_ptr, y, x, m_idx);
180         break;
181     case MON_MIRAAK:
182         count += summon_APOCRYPHA(player_ptr, y, x, m_idx);
183         break;
184     case MON_IMHOTEP:
185         count += summon_PYRAMID(player_ptr, y, x, rlev, m_idx);
186         break;
187     case MON_JOBZ:
188         count += summon_EYE_PHORN(player_ptr, y, x, rlev, m_idx);
189         break;
190     case MON_QUEEN_VESPOID:
191         count += summon_VESPOID(player_ptr, y, x, rlev, m_idx);
192         break;
193     case MON_YENDOR_WIZARD_1:
194         count += summon_YENDER_WIZARD(player_ptr, y, x, m_idx);
195         break;
196     case MON_LEE_QIEZI:
197         msg_print(_("しかし、誰も来てくれなかった…。", "However, no one answered the call..."));
198         break;
199     case MON_THUNDERS:
200         count += summon_THUNDERS(player_ptr, y, x, rlev, m_idx);
201         break;
202     case MON_OOTSUKI:
203         count += summon_PLASMA(player_ptr, y, x, rlev, m_idx);
204         break;
205     default:
206         count += summon_Kin(player_ptr, y, x, rlev, m_idx);
207         break;
208     }
209
210     if (player_ptr->blind && count && (target_type == MONSTER_TO_PLAYER))
211         msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
212
213     if (known && !see_monster(player_ptr, t_idx) && count && (target_type == MONSTER_TO_MONSTER))
214         floor_ptr->monster_noise = true;
215
216     auto res = MonsterSpellResult::make_valid();
217     res.learnable = target_type == MONSTER_TO_PLAYER;
218
219     return res;
220 }
221
222 /*!
223  * @brief RF6_S_CYBERの処理。サイバー・デーモン召喚。 /
224  * @param player_ptr プレイヤーへの参照ポインタ
225  * @param y 対象の地点のy座標
226  * @param x 対象の地点のx座標
227  * @param m_idx 呪文を唱えるモンスターID
228  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
229  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
230  *
231  * プレイヤーが対象ならラーニング可。
232  */
233 MonsterSpellResult spell_RF6_S_CYBER(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
234 {
235     floor_type *floor_ptr = player_ptr->current_floor_ptr;
236     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
237     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
238     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
239     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
240     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
241     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
242     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
243         _("%^sがサイバーデーモンを召喚した!", "%^s magically summons Cyberdemons!"),
244         _("%^sがサイバーデーモンを召喚した!", "%^s magically summons Cyberdemons!"));
245
246     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
247     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
248
249     int count = 0;
250     if (is_friendly(m_ptr) && mon_to_mon) {
251         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_CYBER, (PM_ALLOW_GROUP));
252     } else {
253         count += summon_cyber(player_ptr, m_idx, y, x);
254     }
255
256     if (player_ptr->blind && count && mon_to_player)
257         msg_print(_("重厚な足音が近くで聞こえる。", "You hear heavy steps nearby."));
258
259     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
260         floor_ptr->monster_noise = true;
261
262     auto res = MonsterSpellResult::make_valid();
263     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
264
265     return res;
266 }
267
268 /*!
269  * @brief RF6_S_MONSTERの処理。モンスター一体召喚。 /
270  * @param player_ptr プレイヤーへの参照ポインタ
271  * @param y 対象の地点のy座標
272  * @param x 対象の地点のx座標
273  * @param m_idx 呪文を唱えるモンスターID
274  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
275  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
276  *
277  * プレイヤーが対象ならラーニング可。
278  */
279 MonsterSpellResult spell_RF6_S_MONSTER(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
280 {
281     floor_type *floor_ptr = player_ptr->current_floor_ptr;
282     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
283     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
284     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
285     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
286     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
287
288     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."), _("%^sが魔法で仲間を召喚した!", "%^s magically summons help!"),
289         _("%^sが魔法で仲間を召喚した!", "%^s magically summons help!"));
290
291     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
292     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
293
294     int count = 0;
295     for (int k = 0; k < 1; k++) {
296         if (mon_to_player)
297             count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_NONE, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
298
299         if (mon_to_mon)
300             count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_NONE, (monster_u_mode(floor_ptr, m_idx)));
301     }
302
303     if (player_ptr->blind && count && mon_to_player)
304         msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
305
306     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
307         floor_ptr->monster_noise = true;
308
309     auto res = MonsterSpellResult::make_valid();
310     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
311
312     return res;
313 }
314
315 /*!
316  * @brief RF6_S_MONSTERSの処理。モンスター複数召喚。 /
317  * @param player_ptr プレイヤーへの参照ポインタ
318  * @param y 対象の地点のy座標
319  * @param x 対象の地点のx座標
320  * @param m_idx 呪文を唱えるモンスターID
321  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
322  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
323  *
324  * プレイヤーが対象ならラーニング可。
325  */
326 MonsterSpellResult spell_RF6_S_MONSTERS(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
327 {
328     floor_type *floor_ptr = player_ptr->current_floor_ptr;
329     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
330     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
331     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
332     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
333     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
334
335     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
336         _("%^sが魔法でモンスターを召喚した!", "%^s magically summons monsters!"), _("%^sが魔法でモンスターを召喚した!", "%^s magically summons monsters!"));
337
338     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
339     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
340
341     int count = 0;
342     for (auto k = 0; k < S_NUM_6; k++) {
343         if (mon_to_player)
344             count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_NONE, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
345
346         if (mon_to_mon)
347             count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_NONE, (PM_ALLOW_GROUP | monster_u_mode(floor_ptr, m_idx)));
348     }
349
350     if (player_ptr->blind && count && mon_to_player)
351         msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
352
353     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
354         floor_ptr->monster_noise = true;
355
356     auto res = MonsterSpellResult::make_valid();
357     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
358
359     return res;
360 }
361
362 /*!
363  * @brief RF6_S_ANTの処理。アリ召喚。 /
364  * @param player_ptr プレイヤーへの参照ポインタ
365  * @param y 対象の地点のy座標
366  * @param x 対象の地点のx座標
367  * @param m_idx 呪文を唱えるモンスターID
368  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
369  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
370  *
371  * プレイヤーが対象ならラーニング可。
372  */
373 MonsterSpellResult spell_RF6_S_ANT(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
374 {
375     floor_type *floor_ptr = player_ptr->current_floor_ptr;
376     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
377     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
378     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
379     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
380     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
381
382     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."), _("%^sが魔法でアリを召喚した。", "%^s magically summons ants."),
383         _("%^sが魔法でアリを召喚した。", "%^s magically summons ants."));
384
385     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
386     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
387
388     int count = 0;
389     for (auto k = 0; k < S_NUM_6; k++) {
390         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_ANT, PM_ALLOW_GROUP);
391     }
392
393     if (player_ptr->blind && count && mon_to_player)
394         msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
395
396     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
397         floor_ptr->monster_noise = true;
398
399     auto res = MonsterSpellResult::make_valid();
400     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
401
402     return res;
403 }
404
405 /*!
406  * @brief RF6_S_SPIDERの処理。クモ召喚。 /
407  * @param player_ptr プレイヤーへの参照ポインタ
408  * @param y 対象の地点のy座標
409  * @param x 対象の地点のx座標
410  * @param m_idx 呪文を唱えるモンスターID
411  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
412  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
413  *
414  * プレイヤーが対象ならラーニング可。
415  */
416 MonsterSpellResult spell_RF6_S_SPIDER(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
417 {
418     floor_type *floor_ptr = player_ptr->current_floor_ptr;
419     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
420     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
421     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
422     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
423     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
424
425     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."), _("%^sが魔法でクモを召喚した。", "%^s magically summons spiders."),
426         _("%^sが魔法でクモを召喚した。", "%^s magically summons spiders."));
427
428     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
429     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
430
431     int count = 0;
432     for (auto k = 0; k < S_NUM_6; k++) {
433         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_SPIDER, PM_ALLOW_GROUP);
434     }
435
436     if (player_ptr->blind && count && mon_to_player)
437         msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
438
439     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
440         floor_ptr->monster_noise = true;
441
442     auto res = MonsterSpellResult::make_valid();
443     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
444
445     return res;
446 }
447
448 /*!
449  * @brief RF6_S_HOUNDの処理。ハウンド召喚。 /
450  * @param player_ptr プレイヤーへの参照ポインタ
451  * @param y 対象の地点のy座標
452  * @param x 対象の地点のx座標
453  * @param m_idx 呪文を唱えるモンスターID
454  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
455  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
456  *
457  * プレイヤーが対象ならラーニング可。
458  */
459 MonsterSpellResult spell_RF6_S_HOUND(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
460 {
461     floor_type *floor_ptr = player_ptr->current_floor_ptr;
462     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
463     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
464     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
465     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
466     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
467
468     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
469         _("%^sが魔法でハウンドを召喚した。", "%^s magically summons hounds."), _("%^sが魔法でハウンドを召喚した。", "%^s magically summons hounds."));
470
471     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
472     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
473
474     int count = 0;
475     for (auto k = 0; k < S_NUM_4; k++) {
476         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HOUND, PM_ALLOW_GROUP);
477     }
478
479     if (player_ptr->blind && count && mon_to_player)
480         msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
481
482     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
483         floor_ptr->monster_noise = true;
484
485     auto res = MonsterSpellResult::make_valid();
486     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
487
488     return res;
489 }
490
491 /*!
492  * @brief RF6_S_HYDRAの処理。ヒドラ召喚。 /
493  * @param player_ptr プレイヤーへの参照ポインタ
494  * @param y 対象の地点のy座標
495  * @param x 対象の地点のx座標
496  * @param m_idx 呪文を唱えるモンスターID
497  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
498  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
499  *
500  * プレイヤーが対象ならラーニング可。
501  */
502 MonsterSpellResult spell_RF6_S_HYDRA(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
503 {
504     floor_type *floor_ptr = player_ptr->current_floor_ptr;
505     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
506     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
507     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
508     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
509     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
510
511     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
512         _("%^sが魔法でヒドラを召喚した。", "%^s magically summons hydras."), _("%^sが魔法でヒドラを召喚した。", "%^s magically summons hydras."));
513
514     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
515     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
516
517     int count = 0;
518     for (auto k = 0; k < S_NUM_4; k++) {
519         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HYDRA, PM_ALLOW_GROUP);
520     }
521
522     if (player_ptr->blind && count && mon_to_player)
523         msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
524
525     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
526         floor_ptr->monster_noise = true;
527
528     auto res = MonsterSpellResult::make_valid();
529     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
530
531     return res;
532 }
533
534 /*!
535  * @brief RF6_S_ANGELの処理。天使一体召喚。 /
536  * @param player_ptr プレイヤーへの参照ポインタ
537  * @param y 対象の地点のy座標
538  * @param x 対象の地点のx座標
539  * @param m_idx 呪文を唱えるモンスターID
540  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
541  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
542  *
543  * プレイヤーが対象ならラーニング可。
544  */
545 MonsterSpellResult spell_RF6_S_ANGEL(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
546 {
547     floor_type *floor_ptr = player_ptr->current_floor_ptr;
548     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
549     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
550     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
551     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
552
553     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
554         _("%^sが魔法で天使を召喚した!", "%^s magically summons an angel!"), _("%^sが魔法で天使を召喚した!", "%^s magically summons an angel!"));
555
556     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
557     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
558
559     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
560     monster_race *r_ptr = &r_info[m_ptr->r_idx];
561     int num = 1;
562     if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
563         num += r_ptr->level / 40;
564     }
565
566     int count = 0;
567     for (int k = 0; k < num; k++) {
568         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_ANGEL, PM_ALLOW_GROUP);
569     }
570
571     if (count < 2) {
572         if (player_ptr->blind && count)
573             msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
574     } else {
575         if (player_ptr->blind)
576             msg_print(_("多くのものが間近に現れた音がする。", "You hear many things appear nearby."));
577     }
578
579     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
580         floor_ptr->monster_noise = true;
581
582     auto res = MonsterSpellResult::make_valid();
583     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
584
585     return res;
586 }
587
588 /*!
589  * @brief RF6_S_DEMONの処理。デーモン一体召喚。 /
590  * @param player_ptr プレイヤーへの参照ポインタ
591  * @param y 対象の地点のy座標
592  * @param x 対象の地点のx座標
593  * @param m_idx 呪文を唱えるモンスターID
594  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
595  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
596  *
597  * プレイヤーが対象ならラーニング可。
598  */
599 MonsterSpellResult spell_RF6_S_DEMON(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
600 {
601     floor_type *floor_ptr = player_ptr->current_floor_ptr;
602     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
603     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
604     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
605     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
606
607     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
608         _("%^sは魔法で混沌の宮廷から悪魔を召喚した!", "%^s magically summons a demon from the Courts of Chaos!"),
609         _("%^sは魔法で混沌の宮廷から悪魔を召喚した!", "%^s magically summons a demon from the Courts of Chaos!"));
610
611     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
612     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
613
614     int count = 0;
615     for (int k = 0; k < 1; k++) {
616         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_DEMON, PM_ALLOW_GROUP);
617     }
618
619     if (player_ptr->blind && count)
620         msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
621
622     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
623         floor_ptr->monster_noise = true;
624
625     auto res = MonsterSpellResult::make_valid();
626     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
627
628     return res;
629 }
630
631 /*!
632  * @brief RF6_S_UNDEADの処理。アンデッド一体召喚。 /
633  * @param player_ptr プレイヤーへの参照ポインタ
634  * @param y 対象の地点のy座標
635  * @param x 対象の地点のx座標
636  * @param m_idx 呪文を唱えるモンスターID
637  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
638  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
639  *
640  * プレイヤーが対象ならラーニング可。
641  */
642 MonsterSpellResult spell_RF6_S_UNDEAD(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
643 {
644     floor_type *floor_ptr = player_ptr->current_floor_ptr;
645     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
646     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
647     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
648     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
649
650     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
651         _("%^sが魔法でアンデッドの強敵を召喚した!", "%^s magically summons an undead adversary!"),
652         _("%sが魔法でアンデッドを召喚した。", "%^s magically summons undead."));
653
654     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
655     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
656
657     int count = 0;
658     for (int k = 0; k < 1; k++) {
659         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_UNDEAD, PM_ALLOW_GROUP);
660     }
661
662     if (player_ptr->blind && count)
663         msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
664
665     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
666         floor_ptr->monster_noise = true;
667
668     auto res = MonsterSpellResult::make_valid();
669     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
670
671     return res;
672 }
673
674 /*!
675  * @brief RF6_S_DRAGONの処理。ドラゴン一体召喚。 /
676  * @param player_ptr プレイヤーへの参照ポインタ
677  * @param y 対象の地点のy座標
678  * @param x 対象の地点のx座標
679  * @param m_idx 呪文を唱えるモンスターID
680  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
681  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
682  *
683  * プレイヤーが対象ならラーニング可。
684  */
685 MonsterSpellResult spell_RF6_S_DRAGON(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
686 {
687     floor_type *floor_ptr = player_ptr->current_floor_ptr;
688     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
689     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
690     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
691     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
692     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
693
694     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
695         _("%^sが魔法でドラゴンを召喚した!", "%^s magically summons a dragon!"), _("%^sが魔法でドラゴンを召喚した!", "%^s magically summons a dragon!"));
696
697     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
698     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
699
700     int count = 0;
701     if (mon_to_player)
702         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_DRAGON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
703
704     if (mon_to_mon)
705         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_DRAGON, (PM_ALLOW_GROUP | monster_u_mode(floor_ptr, m_idx)));
706
707     if (player_ptr->blind && count)
708         msg_print(_("何かが間近に現れた音がする。", "You hear something appear nearby."));
709
710     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
711         floor_ptr->monster_noise = true;
712
713     auto res = MonsterSpellResult::make_valid();
714     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
715
716     return res;
717 }
718
719 /*!
720  * @brief RF6_S_HI_UNDEADの処理。強力なアンデッド召喚。 /
721  * @param player_ptr プレイヤーへの参照ポインタ
722  * @param y 対象の地点のy座標
723  * @param x 対象の地点のx座標
724  * @param m_idx 呪文を唱えるモンスターID
725  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
726  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
727  *
728  * プレイヤーが対象ならラーニング可。
729  */
730 MonsterSpellResult spell_RF6_S_HI_UNDEAD(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
731 {
732     floor_type *floor_ptr = player_ptr->current_floor_ptr;
733     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
734     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
735     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
736     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
737     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
738     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
739
740     GAME_TEXT m_name[MAX_NLEN];
741     monster_name(player_ptr, m_idx, m_name);
742     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
743
744     int count = 0;
745     if (((m_ptr->r_idx == MON_MORGOTH) || (m_ptr->r_idx == MON_SAURON) || (m_ptr->r_idx == MON_ANGMAR)) && ((r_info[MON_NAZGUL].cur_num + 2) < r_info[MON_NAZGUL].max_num) && mon_to_player) {
746         count += summon_NAZGUL(player_ptr, y, x, m_idx);
747     } else {
748         mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
749             _("%^sが魔法で強力なアンデッドを召喚した!", "%^s magically summons greater undead!"),
750             _("%sが魔法でアンデッドを召喚した。", "%^s magically summons undead."));
751
752         monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
753
754         for (auto k = 0; k < S_NUM_6; k++) {
755             if (mon_to_player)
756                 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HI_UNDEAD, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
757
758             if (mon_to_mon)
759                 count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HI_UNDEAD, (PM_ALLOW_GROUP | monster_u_mode(floor_ptr, m_idx)));
760         }
761     }
762
763     if (player_ptr->blind && count && mon_to_player) {
764         msg_print(_("間近で何か多くのものが這い回る音が聞こえる。", "You hear many creepy things appear nearby."));
765     }
766
767     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
768         floor_ptr->monster_noise = true;
769
770     auto res = MonsterSpellResult::make_valid();
771     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
772
773     return res;
774 }
775
776 /*!
777  * @brief RF6_S_HI_DRAGONの処理。古代ドラゴン召喚。 /
778  * @param player_ptr プレイヤーへの参照ポインタ
779  * @param y 対象の地点のy座標
780  * @param x 対象の地点のx座標
781  * @param m_idx 呪文を唱えるモンスターID
782  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
783  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
784  *
785  * プレイヤーが対象ならラーニング可。
786  */
787 MonsterSpellResult spell_RF6_S_HI_DRAGON(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
788 {
789     floor_type *floor_ptr = player_ptr->current_floor_ptr;
790     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
791     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
792     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
793     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
794     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
795
796     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
797         _("%^sが魔法で古代ドラゴンを召喚した!", "%^s magically summons ancient dragons!"),
798         _("%^sが魔法で古代ドラゴンを召喚した!", "%^s magically summons ancient dragons!"));
799
800     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
801     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
802
803     int count = 0;
804     for (auto k = 0; k < S_NUM_4; k++) {
805         if (mon_to_player)
806             count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HI_DRAGON, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
807
808         if (mon_to_mon)
809             count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_HI_DRAGON, (PM_ALLOW_GROUP | monster_u_mode(floor_ptr, m_idx)));
810     }
811
812     if (player_ptr->blind && count && mon_to_player) {
813         msg_print(_("多くの力強いものが間近に現れた音が聞こえる。", "You hear many powerful things appear nearby."));
814     }
815
816     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
817         floor_ptr->monster_noise = true;
818
819     auto res = MonsterSpellResult::make_valid();
820     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
821
822     return res;
823 }
824
825 /*!
826  * @brief RF6_S_AMBERITESの処理。アンバーの王族召喚。 /
827  * @param player_ptr プレイヤーへの参照ポインタ
828  * @param y 対象の地点のy座標
829  * @param x 対象の地点のx座標
830  * @param m_idx 呪文を唱えるモンスターID
831  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
832  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
833  *
834  * プレイヤーが対象ならラーニング可。
835  */
836 MonsterSpellResult spell_RF6_S_AMBERITES(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
837 {
838     floor_type *floor_ptr = player_ptr->current_floor_ptr;
839     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
840     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
841     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
842     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
843     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
844
845     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
846         _("%^sがアンバーの王族を召喚した!", "%^s magically summons Lords of Amber!"),
847         _("%^sがアンバーの王族を召喚した!", "%^s magically summons Lords of Amber!"));
848
849     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
850     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
851
852     int count = 0;
853     for (auto k = 0; k < S_NUM_4; k++) {
854         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_AMBERITES, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
855     }
856
857     if (player_ptr->blind && count && mon_to_player) {
858         msg_print(_("不死の者が近くに現れるのが聞こえた。", "You hear immortal beings appear nearby."));
859     }
860
861     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
862         floor_ptr->monster_noise = true;
863
864     auto res = MonsterSpellResult::make_valid();
865     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
866
867     return res;
868 }
869
870 /*!
871  * @brief RF6_S_UNIQUEの処理。ユニーク・モンスター召喚。 /
872  * @param player_ptr プレイヤーへの参照ポインタ
873  * @param y 対象の地点のy座標
874  * @param x 対象の地点のx座標
875  * @param m_idx 呪文を唱えるモンスターID
876  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
877  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
878  *
879  * プレイヤーが対象ならラーニング可。
880  */
881 MonsterSpellResult spell_RF6_S_UNIQUE(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE)
882 {
883     floor_type *floor_ptr = player_ptr->current_floor_ptr;
884     DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
885     bool mon_to_mon = (TARGET_TYPE == MONSTER_TO_MONSTER);
886     bool mon_to_player = (TARGET_TYPE == MONSTER_TO_PLAYER);
887     bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
888     bool known = monster_near_player(floor_ptr, m_idx, t_idx);
889
890     mspell_cast_msg_blind msg(_("%^sが何かをつぶやいた。", "%^s mumbles."),
891         _("%^sが魔法で特別な強敵を召喚した!", "%^s magically summons special opponents!"),
892         _("%^sが魔法で特別な強敵を召喚した!", "%^s magically summons special opponents!"));
893
894     monspell_message(player_ptr, m_idx, t_idx, msg, TARGET_TYPE);
895     summon_disturb(player_ptr, TARGET_TYPE, known, see_either);
896
897     monster_type *m_ptr = &floor_ptr->m_list[m_idx];
898     bool uniques_are_summoned = false;
899     int count = 0;
900     for (auto k = 0; k < S_NUM_4; k++) {
901         count += summon_specific(player_ptr, m_idx, y, x, rlev, SUMMON_UNIQUE, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
902     }
903
904     if (count)
905         uniques_are_summoned = true;
906
907     summon_type non_unique_type = SUMMON_HI_UNDEAD;
908     if ((m_ptr->sub_align & (SUB_ALIGN_GOOD | SUB_ALIGN_EVIL)) == (SUB_ALIGN_GOOD | SUB_ALIGN_EVIL))
909         non_unique_type = SUMMON_NONE;
910     else if (m_ptr->sub_align & SUB_ALIGN_GOOD)
911         non_unique_type = SUMMON_ANGEL;
912
913     for (auto k = count; k < S_NUM_4; k++) {
914         count += summon_specific(player_ptr, m_idx, y, x, rlev, non_unique_type, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE));
915     }
916
917     if (player_ptr->blind && count && mon_to_player) {
918         msg_format(_("多くの%sが間近に現れた音が聞こえる。", "You hear many %s appear nearby."),
919             uniques_are_summoned ? _("力強いもの", "powerful things") : _("もの", "things"));
920     }
921
922     if (monster_near_player(floor_ptr, m_idx, t_idx) && !see_monster(player_ptr, t_idx) && count && mon_to_mon)
923         floor_ptr->monster_noise = true;
924
925     auto res = MonsterSpellResult::make_valid();
926     res.learnable = TARGET_TYPE == MONSTER_TO_PLAYER;
927
928     return res;
929 }