OSDN Git Service

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