OSDN Git Service

[Implement] ウサウサストライカー召喚処理を追加
[hengbandforosx/hengbandosx.git] / src / monster-race / monster-race-hook.cpp
1 #include "monster-race/monster-race-hook.h"
2 #include "dungeon/quest.h"
3 #include "monster-attack/monster-attack-effect.h"
4 #include "monster-attack/monster-attack-table.h"
5 #include "monster-floor/place-monster-types.h"
6 #include "monster-race/monster-race.h"
7 #include "monster-race/race-ability-mask.h"
8 #include "monster-race/race-flags-resistance.h"
9 #include "monster-race/race-flags1.h"
10 #include "monster-race/race-flags2.h"
11 #include "monster-race/race-flags3.h"
12 #include "monster-race/race-flags7.h"
13 #include "monster-race/race-flags8.h"
14 #include "monster-race/race-indice-types.h"
15 #include "monster-race/race-misc-flags.h"
16 #include "monster/monster-list.h"
17 #include "monster/monster-util.h"
18 #include "player/player-status.h"
19 #include "system/dungeon-info.h"
20 #include "system/floor-type-definition.h"
21 #include "system/monster-race-info.h"
22 #include "system/player-type-definition.h"
23 #include "util/bit-flags-calculator.h"
24 #include "util/string-processor.h"
25 #include <set>
26
27 /*! 通常pit生成時のモンスターの構成条件ID / Race index for "monster pit (clone)" */
28 MonsterRaceId vault_aux_race;
29
30 /*! 単一シンボルpit生成時の指定シンボル / Race index for "monster pit (symbol clone)" */
31 char vault_aux_char;
32
33 /*! ブレス属性に基づくドラゴンpit生成時条件マスク / Breath mask for "monster pit (dragon)" */
34 EnumClassFlagGroup<MonsterAbilityType> vault_aux_dragon_mask4;
35
36 /*!
37  * @brief pit/nestの基準となる単種モンスターを決める /
38  * @param player_ptr プレイヤーへの参照ポインタ
39  */
40 void vault_prep_clone(PlayerType *player_ptr)
41 {
42     get_mon_num_prep(player_ptr, vault_aux_simple, nullptr);
43     vault_aux_race = get_mon_num(player_ptr, 0, player_ptr->current_floor_ptr->dun_level + 10, PM_NONE);
44     get_mon_num_prep(player_ptr, nullptr, nullptr);
45 }
46
47 /*!
48  * @brief pit/nestの基準となるモンスターシンボルを決める /
49  * @param player_ptr プレイヤーへの参照ポインタ
50  */
51 void vault_prep_symbol(PlayerType *player_ptr)
52 {
53     get_mon_num_prep(player_ptr, vault_aux_simple, nullptr);
54     MonsterRaceId r_idx = get_mon_num(player_ptr, 0, player_ptr->current_floor_ptr->dun_level + 10, PM_NONE);
55     get_mon_num_prep(player_ptr, nullptr, nullptr);
56     vault_aux_char = monraces_info[r_idx].d_char;
57 }
58
59 /*!
60  * @brief pit/nestの基準となるドラゴンの種類を決める /
61  * @param player_ptr プレイヤーへの参照ポインタ
62  */
63 void vault_prep_dragon(PlayerType *player_ptr)
64 {
65     /* Unused */
66     (void)player_ptr;
67
68     vault_aux_dragon_mask4.clear();
69
70     constexpr static auto breath_list = {
71         MonsterAbilityType::BR_ACID, /* Black */
72         MonsterAbilityType::BR_ELEC, /* Blue */
73         MonsterAbilityType::BR_FIRE, /* Red */
74         MonsterAbilityType::BR_COLD, /* White */
75         MonsterAbilityType::BR_POIS, /* Green */
76     };
77
78     if (one_in_(6)) {
79         /* Multi-hued */
80         vault_aux_dragon_mask4.set(breath_list);
81         return;
82     }
83
84     vault_aux_dragon_mask4.set(rand_choice(breath_list));
85 }
86
87 /*!
88  * @brief モンスターがクエストの討伐対象に成り得るかを返す / Hook function for quest monsters
89  * @param r_idx モンスターID
90  * @return 討伐対象にできるならTRUEを返す。
91  */
92 bool mon_hook_quest(PlayerType *player_ptr, MonsterRaceId r_idx)
93 {
94     /* Unused */
95     (void)player_ptr;
96
97     auto *r_ptr = &monraces_info[r_idx];
98     if (r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_ONLY)) {
99         return false;
100     }
101
102     if (r_ptr->feature_flags.has(MonsterFeatureType::AQUATIC)) {
103         return false;
104     }
105
106     if (r_ptr->misc_flags.has(MonsterMiscType::MULTIPLY)) {
107         return false;
108     }
109
110     if (r_ptr->behavior_flags.has(MonsterBehaviorType::FRIENDLY)) {
111         return false;
112     }
113
114     return true;
115 }
116
117 /*!
118  * @brief モンスターがダンジョンに出現するかどうかを返す
119  * @param r_idx 判定するモンスターの種族ID
120  * @return ダンジョンに出現するならばTRUEを返す
121  * @details
122  * <pre>
123  * 地上は常にTRUE(荒野の出現は別hookで絞るため)。
124  * 荒野限定(WILD_ONLY)の場合、荒野の山に出るモンスターにのみダンジョンの山に出現を許可する。
125  * その他の場合、山及び火山以外のダンジョンでは全てのモンスターに出現を許可する。
126  * ダンジョンが山の場合は、荒野の山(WILD_MOUNTAIN)に出ない水棲動物(AQUATIC)は許可しない。
127  * ダンジョンが火山の場合は、荒野の火山(WILD_VOLCANO)に出ない水棲動物(AQUATIC)は許可しない。
128  * </pre>
129  */
130 bool mon_hook_dungeon(PlayerType *player_ptr, MonsterRaceId r_idx)
131 {
132     const auto &floor = *player_ptr->current_floor_ptr;
133     if (!floor.is_in_dungeon() && !floor.is_in_quest()) {
134         return true;
135     }
136
137     auto *r_ptr = &monraces_info[r_idx];
138     dungeon_type *d_ptr = &floor.get_dungeon_definition();
139     if (r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_ONLY)) {
140         return d_ptr->mon_wilderness_flags.has(MonsterWildernessType::WILD_MOUNTAIN) && r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_MOUNTAIN);
141     }
142
143     auto land = r_ptr->feature_flags.has_not(MonsterFeatureType::AQUATIC);
144     auto is_mountain_monster = d_ptr->mon_wilderness_flags.has_none_of({ MonsterWildernessType::WILD_MOUNTAIN, MonsterWildernessType::WILD_VOLCANO });
145     is_mountain_monster |= d_ptr->mon_wilderness_flags.has(MonsterWildernessType::WILD_MOUNTAIN) && (land || r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_MOUNTAIN));
146     is_mountain_monster |= d_ptr->mon_wilderness_flags.has(MonsterWildernessType::WILD_VOLCANO) && (land || r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_VOLCANO));
147     return is_mountain_monster;
148 }
149
150 /*!
151  * @brief モンスターが海洋に出現するかどうかを返す
152  * @param r_idx 判定するモンスターの種族ID
153  * @return 海洋に出現するならばTRUEを返す
154  */
155 bool mon_hook_ocean(PlayerType *player_ptr, MonsterRaceId r_idx)
156 {
157     /* Unused */
158     (void)player_ptr;
159
160     auto *r_ptr = &monraces_info[r_idx];
161     return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_OCEAN);
162 }
163
164 /*!
165  * @brief モンスターが海岸に出現するかどうかを返す
166  * @param r_idx 判定するモンスターの種族ID
167  * @return 海岸に出現するならばTRUEを返す
168  */
169 bool mon_hook_shore(PlayerType *player_ptr, MonsterRaceId r_idx)
170 {
171     /* Unused */
172     (void)player_ptr;
173
174     auto *r_ptr = &monraces_info[r_idx];
175     return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_SHORE);
176 }
177
178 /*!
179  * @brief モンスターが荒地に出現するかどうかを返す
180  * @param r_idx 判定するモンスターの種族ID
181  * @return 荒地に出現するならばTRUEを返す
182  */
183 bool mon_hook_waste(PlayerType *player_ptr, MonsterRaceId r_idx)
184 {
185     /* Unused */
186     (void)player_ptr;
187
188     auto *r_ptr = &monraces_info[r_idx];
189     return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_WASTE, MonsterWildernessType::WILD_ALL });
190 }
191
192 /*!
193  * @brief モンスターが町に出現するかどうかを返す
194  * @param r_idx 判定するモンスターの種族ID
195  * @return 荒地に出現するならばTRUEを返す
196  */
197 bool mon_hook_town(PlayerType *player_ptr, MonsterRaceId r_idx)
198 {
199     /* Unused */
200     (void)player_ptr;
201
202     auto *r_ptr = &monraces_info[r_idx];
203     return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_TOWN, MonsterWildernessType::WILD_ALL });
204 }
205
206 /*!
207  * @brief モンスターが森林に出現するかどうかを返す
208  * @param r_idx 判定するモンスターの種族ID
209  * @return 森林に出現するならばTRUEを返す
210  */
211 bool mon_hook_wood(PlayerType *player_ptr, MonsterRaceId r_idx)
212 {
213     /* Unused */
214     (void)player_ptr;
215
216     auto *r_ptr = &monraces_info[r_idx];
217     return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_WOOD, MonsterWildernessType::WILD_ALL });
218 }
219
220 /*!
221  * @brief モンスターが火山に出現するかどうかを返す
222  * @param r_idx 判定するモンスターの種族ID
223  * @return 火山に出現するならばTRUEを返す
224  */
225 bool mon_hook_volcano(PlayerType *player_ptr, MonsterRaceId r_idx)
226 {
227     /* Unused */
228     (void)player_ptr;
229
230     auto *r_ptr = &monraces_info[r_idx];
231     return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_VOLCANO);
232 }
233
234 /*!
235  * @brief モンスターが山地に出現するかどうかを返す
236  * @param r_idx 判定するモンスターの種族ID
237  * @return 山地に出現するならばTRUEを返す
238  */
239 bool mon_hook_mountain(PlayerType *player_ptr, MonsterRaceId r_idx)
240 {
241     /* Unused */
242     (void)player_ptr;
243
244     auto *r_ptr = &monraces_info[r_idx];
245     return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_MOUNTAIN);
246 }
247
248 /*!
249  * @brief モンスターが草原に出現するかどうかを返す
250  * @param r_idx 判定するモンスターの種族ID
251  * @return 森林に出現するならばTRUEを返す
252  */
253 bool mon_hook_grass(PlayerType *player_ptr, MonsterRaceId r_idx)
254 {
255     /* Unused */
256     (void)player_ptr;
257
258     auto *r_ptr = &monraces_info[r_idx];
259     return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_GRASS, MonsterWildernessType::WILD_ALL });
260 }
261
262 /*!
263  * @brief モンスターが深い水地形に出現するかどうかを返す
264  * @param r_idx 判定するモンスターの種族ID
265  * @return 深い水地形に出現するならばTRUEを返す
266  */
267 bool mon_hook_deep_water(PlayerType *player_ptr, MonsterRaceId r_idx)
268 {
269     auto *r_ptr = &monraces_info[r_idx];
270     if (!mon_hook_dungeon(player_ptr, r_idx)) {
271         return false;
272     }
273
274     return r_ptr->feature_flags.has(MonsterFeatureType::AQUATIC);
275 }
276
277 /*!
278  * @brief モンスターが浅い水地形に出現するかどうかを返す
279  * @param r_idx 判定するモンスターの種族ID
280  * @return 浅い水地形に出現するならばTRUEを返す
281  */
282 bool mon_hook_shallow_water(PlayerType *player_ptr, MonsterRaceId r_idx)
283 {
284     auto *r_ptr = &monraces_info[r_idx];
285     if (!mon_hook_dungeon(player_ptr, r_idx)) {
286         return false;
287     }
288
289     return r_ptr->aura_flags.has_not(MonsterAuraType::FIRE);
290 }
291
292 /*!
293  * @brief モンスターが溶岩地形に出現するかどうかを返す
294  * @param r_idx 判定するモンスターの種族ID
295  * @return 溶岩地形に出現するならばTRUEを返す
296  */
297 bool mon_hook_lava(PlayerType *player_ptr, MonsterRaceId r_idx)
298 {
299     auto *r_ptr = &monraces_info[r_idx];
300     if (!mon_hook_dungeon(player_ptr, r_idx)) {
301         return false;
302     }
303
304     return (r_ptr->resistance_flags.has_any_of(RFR_EFF_IM_FIRE_MASK) || r_ptr->feature_flags.has(MonsterFeatureType::CAN_FLY)) && r_ptr->aura_flags.has_not(MonsterAuraType::COLD);
305 }
306
307 /*!
308  * @brief モンスターが通常の床地形に出現するかどうかを返す
309  * @param r_idx 判定するモンスターの種族ID
310  * @return 通常の床地形に出現するならばTRUEを返す
311  */
312 bool mon_hook_floor(PlayerType *player_ptr, MonsterRaceId r_idx)
313 {
314     /* Unused */
315     (void)player_ptr;
316
317     auto *r_ptr = &monraces_info[r_idx];
318     if (r_ptr->feature_flags.has_not(MonsterFeatureType::AQUATIC) || r_ptr->feature_flags.has(MonsterFeatureType::CAN_FLY)) {
319         return true;
320     } else {
321         return false;
322     }
323 }
324
325 /*
326  * Helper function for "glass room"
327  */
328 bool vault_aux_lite(PlayerType *player_ptr, MonsterRaceId r_idx)
329 {
330     /* Unused */
331     (void)player_ptr;
332
333     auto *r_ptr = &monraces_info[r_idx];
334     if (!vault_monster_okay(player_ptr, r_idx)) {
335         return false;
336     }
337
338     if (r_ptr->ability_flags.has_none_of({ MonsterAbilityType::BR_LITE, MonsterAbilityType::BA_LITE })) {
339         return false;
340     }
341
342     if (r_ptr->feature_flags.has_any_of({ MonsterFeatureType::PASS_WALL, MonsterFeatureType::KILL_WALL })) {
343         return false;
344     }
345
346     if (r_ptr->ability_flags.has(MonsterAbilityType::BR_DISI)) {
347         return false;
348     }
349
350     return true;
351 }
352
353 /*
354  * Helper function for "glass room"
355  */
356 bool vault_aux_shards(PlayerType *player_ptr, MonsterRaceId r_idx)
357 {
358     auto *r_ptr = &monraces_info[r_idx];
359     if (!vault_monster_okay(player_ptr, r_idx)) {
360         return false;
361     }
362
363     if (r_ptr->ability_flags.has_not(MonsterAbilityType::BR_SHAR)) {
364         return false;
365     }
366
367     return true;
368 }
369
370 /*!
371  * @brief モンスターがVault生成の最低必要条件を満たしているかを返す /
372  * Helper monster selection function
373  * @param r_idx 確認したいモンスター種族ID
374  * @return Vault生成の最低必要条件を満たしているならTRUEを返す。
375  */
376 bool vault_aux_simple(PlayerType *player_ptr, MonsterRaceId r_idx)
377 {
378     /* Unused */
379     (void)player_ptr;
380
381     return vault_monster_okay(player_ptr, r_idx);
382 }
383
384 /*!
385  * @brief モンスターがゼリーnestの生成必要条件を満たしているかを返す /
386  * Helper function for "monster nest (jelly)"
387  * @param r_idx 確認したいモンスター種族ID
388  * @return 生成必要条件を満たしているならTRUEを返す。
389  */
390 bool vault_aux_jelly(PlayerType *player_ptr, MonsterRaceId r_idx)
391 {
392     auto *r_ptr = &monraces_info[r_idx];
393     if (!vault_monster_okay(player_ptr, r_idx)) {
394         return false;
395     }
396
397     if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
398         return false;
399     }
400
401     if (r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
402         return false;
403     }
404
405     if (!angband_strchr("ijm,", r_ptr->d_char)) {
406         return false;
407     }
408
409     return true;
410 }
411
412 /*!
413  * @brief モンスターが動物nestの生成必要条件を満たしているかを返す /
414  * Helper function for "monster nest (animal)"
415  * @param r_idx 確認したいモンスター種族ID
416  * @return 生成必要条件を満たしているならTRUEを返す。
417  */
418 bool vault_aux_animal(PlayerType *player_ptr, MonsterRaceId r_idx)
419 {
420     auto *r_ptr = &monraces_info[r_idx];
421     if (!vault_monster_okay(player_ptr, r_idx)) {
422         return false;
423     }
424
425     if (r_ptr->kind_flags.has_not(MonsterKindType::ANIMAL)) {
426         return false;
427     }
428
429     return true;
430 }
431
432 /*!
433  * @brief モンスターがアンデッドnestの生成必要条件を満たしているかを返す /
434  * Helper function for "monster nest (undead)"
435  * @param r_idx 確認したいモンスター種族ID
436  * @return 生成必要条件を満たしているならTRUEを返す。
437  */
438 bool vault_aux_undead(PlayerType *player_ptr, MonsterRaceId r_idx)
439 {
440     auto *r_ptr = &monraces_info[r_idx];
441     if (!vault_monster_okay(player_ptr, r_idx)) {
442         return false;
443     }
444
445     if (r_ptr->kind_flags.has_not(MonsterKindType::UNDEAD)) {
446         return false;
447     }
448
449     return true;
450 }
451
452 /*!
453  * @brief モンスターが聖堂nestの生成必要条件を満たしているかを返す /
454  * Helper function for "monster nest (chapel)"
455  * @param r_idx 確認したいモンスター種族ID
456  * @return 生成必要条件を満たしているならTRUEを返す。
457  */
458 bool vault_aux_chapel_g(PlayerType *player_ptr, MonsterRaceId r_idx)
459 {
460     static const std::set<MonsterRaceId> chapel_list = {
461         MonsterRaceId::NOV_PRIEST,
462         MonsterRaceId::NOV_PALADIN,
463         MonsterRaceId::NOV_PRIEST_G,
464         MonsterRaceId::NOV_PALADIN_G,
465         MonsterRaceId::PRIEST,
466         MonsterRaceId::JADE_MONK,
467         MonsterRaceId::IVORY_MONK,
468         MonsterRaceId::ULTRA_PALADIN,
469         MonsterRaceId::EBONY_MONK,
470         MonsterRaceId::W_KNIGHT,
471         MonsterRaceId::KNI_TEMPLAR,
472         MonsterRaceId::PALADIN,
473         MonsterRaceId::TOPAZ_MONK,
474     };
475
476     auto *r_ptr = &monraces_info[r_idx];
477     if (!vault_monster_okay(player_ptr, r_idx)) {
478         return false;
479     }
480
481     if (r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
482         return false;
483     }
484
485     if ((r_idx == MonsterRaceId::A_GOLD) || (r_idx == MonsterRaceId::A_SILVER)) {
486         return false;
487     }
488
489     if (r_ptr->d_char == 'A') {
490         return true;
491     }
492
493     return chapel_list.find(r_idx) != chapel_list.end();
494 }
495
496 /*!
497  * @brief モンスターが犬小屋nestの生成必要条件を満たしているかを返す /
498  * Helper function for "monster nest (kennel)"
499  * @param r_idx 確認したいモンスター種族ID
500  * @return 生成必要条件を満たしているならTRUEを返す。
501  */
502 bool vault_aux_kennel(PlayerType *player_ptr, MonsterRaceId r_idx)
503 {
504     auto *r_ptr = &monraces_info[r_idx];
505     if (!vault_monster_okay(player_ptr, r_idx)) {
506         return false;
507     }
508
509     if (!angband_strchr("CZ", r_ptr->d_char)) {
510         return false;
511     }
512
513     return true;
514 }
515
516 /*!
517  * @brief モンスターがミミックnestの生成必要条件を満たしているかを返す /
518  * Helper function for "monster nest (mimic)"
519  * @param r_idx 確認したいモンスター種族ID
520  * @return 生成必要条件を満たしているならTRUEを返す。
521  */
522 bool vault_aux_mimic(PlayerType *player_ptr, MonsterRaceId r_idx)
523 {
524     auto *r_ptr = &monraces_info[r_idx];
525     if (!vault_monster_okay(player_ptr, r_idx)) {
526         return false;
527     }
528
529     if (!angband_strchr("!$&(/=?[\\|][`~>+", r_ptr->d_char)) {
530         return false;
531     }
532
533     return true;
534 }
535
536 /*!
537  * @brief モンスターが単一クローンnestの生成必要条件を満たしているかを返す /
538  * Helper function for "monster nest (clone)"
539  * @param r_idx 確認したいモンスター種族ID
540  * @return 生成必要条件を満たしているならTRUEを返す。
541  */
542 bool vault_aux_clone(PlayerType *player_ptr, MonsterRaceId r_idx)
543 {
544     if (!vault_monster_okay(player_ptr, r_idx)) {
545         return false;
546     }
547
548     return r_idx == vault_aux_race;
549 }
550
551 /*!
552  * @brief モンスターが邪悪属性シンボルクローンnestの生成必要条件を満たしているかを返す /
553  * Helper function for "monster nest (symbol clone)"
554  * @param r_idx 確認したいモンスター種族ID
555  * @return 生成必要条件を満たしているならTRUEを返す。
556  */
557 bool vault_aux_symbol_e(PlayerType *player_ptr, MonsterRaceId r_idx)
558 {
559     auto *r_ptr = &monraces_info[r_idx];
560     if (!vault_monster_okay(player_ptr, r_idx)) {
561         return false;
562     }
563
564     if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
565         return false;
566     }
567
568     if (r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
569         return false;
570     }
571
572     if (r_ptr->d_char != vault_aux_char) {
573         return false;
574     }
575
576     return true;
577 }
578
579 /*!
580  * @brief モンスターが善良属性シンボルクローンnestの生成必要条件を満たしているかを返す /
581  * Helper function for "monster nest (symbol clone)"
582  * @param r_idx 確認したいモンスター種族ID
583  * @return 生成必要条件を満たしているならTRUEを返す。
584  */
585 bool vault_aux_symbol_g(PlayerType *player_ptr, MonsterRaceId r_idx)
586 {
587     auto *r_ptr = &monraces_info[r_idx];
588     if (!vault_monster_okay(player_ptr, r_idx)) {
589         return false;
590     }
591
592     if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
593         return false;
594     }
595
596     if (r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
597         return false;
598     }
599
600     if (r_ptr->d_char != vault_aux_char) {
601         return false;
602     }
603
604     return true;
605 }
606
607 /*!
608  * @brief モンスターがオークpitの生成必要条件を満たしているかを返す /
609  * Helper function for "monster pit (orc)"
610  * @param r_idx 確認したいモンスター種族ID
611  * @return 生成必要条件を満たしているならTRUEを返す。
612  */
613 bool vault_aux_orc(PlayerType *player_ptr, MonsterRaceId r_idx)
614 {
615     auto *r_ptr = &monraces_info[r_idx];
616     if (!vault_monster_okay(player_ptr, r_idx)) {
617         return false;
618     }
619
620     if (r_ptr->kind_flags.has_not(MonsterKindType::ORC)) {
621         return false;
622     }
623
624     if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
625         return false;
626     }
627
628     return true;
629 }
630
631 /*!
632  * @brief モンスターがトロルpitの生成必要条件を満たしているかを返す /
633  * Helper function for "monster pit (troll)"
634  * @param r_idx 確認したいモンスター種族ID
635  * @return 生成必要条件を満たしているならTRUEを返す。
636  */
637 bool vault_aux_troll(PlayerType *player_ptr, MonsterRaceId r_idx)
638 {
639     auto *r_ptr = &monraces_info[r_idx];
640     if (!vault_monster_okay(player_ptr, r_idx)) {
641         return false;
642     }
643
644     if (r_ptr->kind_flags.has_not(MonsterKindType::TROLL)) {
645         return false;
646     }
647
648     if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
649         return false;
650     }
651
652     return true;
653 }
654
655 /*!
656  * @brief モンスターが巨人pitの生成必要条件を満たしているかを返す /
657  * Helper function for "monster pit (giant)"
658  * @param r_idx 確認したいモンスター種族ID
659  * @return 生成必要条件を満たしているならTRUEを返す。
660  */
661 bool vault_aux_giant(PlayerType *player_ptr, MonsterRaceId r_idx)
662 {
663     auto *r_ptr = &monraces_info[r_idx];
664     if (!vault_monster_okay(player_ptr, r_idx)) {
665         return false;
666     }
667
668     if (r_ptr->kind_flags.has_not(MonsterKindType::GIANT)) {
669         return false;
670     }
671
672     if (r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
673         return false;
674     }
675
676     if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
677         return false;
678     }
679
680     return true;
681 }
682
683 /*!
684  * @brief モンスターがドラゴンpitの生成必要条件を満たしているかを返す /
685  * Helper function for "monster pit (dragon)"
686  * @param r_idx 確認したいモンスター種族ID
687  * @return 生成必要条件を満たしているならTRUEを返す。
688  */
689 bool vault_aux_dragon(PlayerType *player_ptr, MonsterRaceId r_idx)
690 {
691     auto *r_ptr = &monraces_info[r_idx];
692     if (!vault_monster_okay(player_ptr, r_idx)) {
693         return false;
694     }
695
696     if (r_ptr->kind_flags.has_not(MonsterKindType::DRAGON)) {
697         return false;
698     }
699
700     if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
701         return false;
702     }
703
704     auto flags = RF_ABILITY_BREATH_MASK;
705     flags.reset(vault_aux_dragon_mask4);
706
707     if (r_ptr->ability_flags.has_any_of(flags) || !r_ptr->ability_flags.has_all_of(vault_aux_dragon_mask4)) {
708         return false;
709     }
710
711     return true;
712 }
713
714 /*!
715  * @brief モンスターが悪魔pitの生成必要条件を満たしているかを返す /
716  * Helper function for "monster pit (demon)"
717  * @param r_idx 確認したいモンスター種族ID
718  * @return 生成必要条件を満たしているならTRUEを返す。
719  */
720 bool vault_aux_demon(PlayerType *player_ptr, MonsterRaceId r_idx)
721 {
722     auto *r_ptr = &monraces_info[r_idx];
723     if (!vault_monster_okay(player_ptr, r_idx)) {
724         return false;
725     }
726
727     if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
728         return false;
729     }
730
731     if (r_ptr->kind_flags.has_not(MonsterKindType::DEMON)) {
732         return false;
733     }
734
735     return true;
736 }
737
738 /*!
739  * @brief モンスターが狂気pitの生成必要条件を満たしているかを返す /
740  * Helper function for "monster pit (lovecraftian)"
741  * @param r_idx 確認したいモンスター種族ID
742  * @return 生成必要条件を満たしているならTRUEを返す。
743  */
744 bool vault_aux_cthulhu(PlayerType *player_ptr, MonsterRaceId r_idx)
745 {
746     auto *r_ptr = &monraces_info[r_idx];
747     if (!vault_monster_okay(player_ptr, r_idx)) {
748         return false;
749     }
750
751     if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
752         return false;
753     }
754
755     if (r_ptr->misc_flags.has_not(MonsterMiscType::ELDRITCH_HORROR)) {
756         return false;
757     }
758
759     return true;
760 }
761
762 /*!
763  * @brief モンスターがダークエルフpitの生成必要条件を満たしているかを返す /
764  * Helper function for "monster pit (dark elf)"
765  * @param r_idx 確認したいモンスター種族ID
766  * @return 生成必要条件を満たしているならTRUEを返す。
767  */
768 bool vault_aux_dark_elf(PlayerType *player_ptr, MonsterRaceId r_idx)
769 {
770     static const std::set<MonsterRaceId> dark_elf_list = {
771         MonsterRaceId::D_ELF,
772         MonsterRaceId::D_ELF_MAGE,
773         MonsterRaceId::D_ELF_WARRIOR,
774         MonsterRaceId::D_ELF_PRIEST,
775         MonsterRaceId::D_ELF_LORD,
776         MonsterRaceId::D_ELF_WARLOCK,
777         MonsterRaceId::D_ELF_DRUID,
778         MonsterRaceId::NIGHTBLADE,
779         MonsterRaceId::D_ELF_SORC,
780         MonsterRaceId::D_ELF_SHADE,
781     };
782
783     if (!vault_monster_okay(player_ptr, r_idx)) {
784         return false;
785     }
786
787     return dark_elf_list.find(r_idx) != dark_elf_list.end();
788 }
789
790 /*!
791  * @brief バルログが死体を食べられるモンスターかの判定 / Hook function for human corpses
792  * @param r_idx モンスターID
793  * @return 死体を食べられるならTRUEを返す。
794  */
795 bool monster_hook_human(PlayerType *player_ptr, MonsterRaceId r_idx)
796 {
797     /* Unused */
798     (void)player_ptr;
799
800     auto *r_ptr = &monraces_info[r_idx];
801     if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
802         return false;
803     }
804
805     if (angband_strchr("pht", r_ptr->d_char)) {
806         return true;
807     }
808
809     return false;
810 }
811
812 /*!
813  * @brief 悪夢の元凶となるモンスターかどうかを返す。
814  * @param r_idx 判定対象となるモンスターのID
815  * @return 悪夢の元凶となり得るか否か。
816  */
817 bool get_nightmare(PlayerType *player_ptr, MonsterRaceId r_idx)
818 {
819     auto *r_ptr = &monraces_info[r_idx];
820     if (r_ptr->misc_flags.has_not(MonsterMiscType::ELDRITCH_HORROR)) {
821         return false;
822     }
823
824     if (r_ptr->level <= player_ptr->lev) {
825         return false;
826     }
827
828     return true;
829 }
830
831 /*!
832  * @brief モンスター種族が釣れる種族かどうかを判定する。
833  * @param r_idx 判定したいモンスター種族のID
834  * @return 釣れる対象ならばTRUEを返す
835  */
836 bool monster_is_fishing_target(PlayerType *player_ptr, MonsterRaceId r_idx)
837 {
838     /* Unused */
839     (void)player_ptr;
840
841     auto *r_ptr = &monraces_info[r_idx];
842     if (r_ptr->feature_flags.has(MonsterFeatureType::AQUATIC) && r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE) && angband_strchr("Jjlw", r_ptr->d_char)) {
843         return true;
844     } else {
845         return false;
846     }
847 }
848
849 /*!
850  * @brief モンスター闘技場に参加できるモンスターの判定
851  * @param r_idx モンスターID
852  * @details 基準はNEVER_MOVE MULTIPLY QUANTUM AQUATIC CHAMELEONのいずれも持たず、
853  * 自爆以外のなんらかのHP攻撃手段を持っていること。
854  * @return 参加できるか否か
855  */
856 bool monster_can_entry_arena(PlayerType *player_ptr, MonsterRaceId r_idx)
857 {
858     /* Unused */
859     (void)player_ptr;
860
861     int dam = 0;
862     const auto &monrace = monraces_info[r_idx];
863     bool unselectable = monrace.behavior_flags.has(MonsterBehaviorType::NEVER_MOVE);
864     unselectable |= monrace.misc_flags.has(MonsterMiscType::MULTIPLY);
865     unselectable |= monrace.kind_flags.has(MonsterKindType::QUANTUM) && monrace.kind_flags.has_not(MonsterKindType::UNIQUE);
866     unselectable |= monrace.feature_flags.has(MonsterFeatureType::AQUATIC);
867     unselectable |= monrace.misc_flags.has(MonsterMiscType::CHAMELEON);
868     unselectable |= monrace.is_explodable();
869     if (unselectable) {
870         return false;
871     }
872
873     for (const auto &blow : monrace.blows) {
874         if (blow.effect != RaceBlowEffectType::DR_MANA) {
875             dam += blow.d_dice;
876         }
877     }
878
879     if (!dam && monrace.ability_flags.has_none_of(RF_ABILITY_BOLT_MASK | RF_ABILITY_BEAM_MASK | RF_ABILITY_BALL_MASK | RF_ABILITY_BREATH_MASK)) {
880         return false;
881     }
882
883     return true;
884 }
885
886 /*!
887  * モンスターが人形のベースにできるかを返す
888  * @param r_idx チェックしたいモンスター種族のID
889  * @return 人形にできるならTRUEを返す
890  */
891 bool item_monster_okay(PlayerType *player_ptr, MonsterRaceId r_idx)
892 {
893     /* Unused */
894     (void)player_ptr;
895
896     auto *r_ptr = &monraces_info[r_idx];
897     if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
898         return false;
899     }
900
901     if (r_ptr->misc_flags.has(MonsterMiscType::KAGE)) {
902         return false;
903     }
904
905     if (r_ptr->resistance_flags.has(MonsterResistanceType::RESIST_ALL)) {
906         return false;
907     }
908
909     if (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL)) {
910         return false;
911     }
912
913     if (r_ptr->misc_flags.has(MonsterMiscType::FORCE_DEPTH)) {
914         return false;
915     }
916
917     if (r_ptr->population_flags.has(MonsterPopulationType::ONLY_ONE)) {
918         return false;
919     }
920
921     return true;
922 }
923
924 /*!
925  * vaultに配置可能なモンスターの条件を指定する / Monster validation
926  * @param r_idx モンスター種別ID
927  * @param Vaultに配置可能であればTRUE
928  * @details
929  * Line 1 -- forbid town monsters
930  * Line 2 -- forbid uniques
931  * Line 3 -- forbid aquatic monsters
932  */
933 bool vault_monster_okay(PlayerType *player_ptr, MonsterRaceId r_idx)
934 {
935     const auto &monrace = monraces_info[r_idx];
936     auto is_valid = mon_hook_dungeon(player_ptr, r_idx);
937     is_valid &= monrace.kind_flags.has_not(MonsterKindType::UNIQUE);
938     is_valid &= monrace.population_flags.has_not(MonsterPopulationType::ONLY_ONE);
939     is_valid &= monrace.resistance_flags.has_not(MonsterResistanceType::RESIST_ALL);
940     is_valid &= monrace.feature_flags.has_not(MonsterFeatureType::AQUATIC);
941     return is_valid;
942 }