OSDN Git Service

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