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"
21 /*! 通常pit生成時のモンスターの構成条件ID / Race index for "monster pit (clone)" */
22 MonsterRaceId vault_aux_race;
24 /*! 単一シンボルpit生成時の指定シンボル / Race index for "monster pit (symbol clone)" */
27 /*! ブレス属性に基づくドラゴンpit生成時条件マスク / Breath mask for "monster pit (dragon)" */
28 EnumClassFlagGroup<MonsterAbilityType> vault_aux_dragon_mask4;
31 * @brief pit/nestの基準となる単種モンスターを決める /
32 * @param player_ptr プレイヤーへの参照ポインタ
34 void vault_prep_clone(PlayerType *player_ptr)
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);
42 * @brief pit/nestの基準となるモンスターシンボルを決める /
43 * @param player_ptr プレイヤーへの参照ポインタ
45 void vault_prep_symbol(PlayerType *player_ptr)
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;
54 * @brief pit/nestの基準となるドラゴンの種類を決める /
55 * @param player_ptr プレイヤーへの参照ポインタ
57 void vault_prep_dragon(PlayerType *player_ptr)
62 vault_aux_dragon_mask4.clear();
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 */
74 vault_aux_dragon_mask4.set(breath_list);
78 vault_aux_dragon_mask4.set(rand_choice(breath_list));
82 * @brief モンスターがクエストの討伐対象に成り得るかを返す / Hook function for quest monsters
83 * @param r_idx モンスターID
84 * @return 討伐対象にできるならTRUEを返す。
86 bool mon_hook_quest(PlayerType *player_ptr, MonsterRaceId r_idx)
91 auto *r_ptr = &monraces_info[r_idx];
92 if (r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_ONLY)) {
96 if (r_ptr->feature_flags.has(MonsterFeatureType::AQUATIC)) {
100 if (r_ptr->misc_flags.has(MonsterMiscType::MULTIPLY)) {
104 if (r_ptr->behavior_flags.has(MonsterBehaviorType::FRIENDLY)) {
112 * @brief モンスターがダンジョンに出現するかどうかを返す
113 * @param r_idx 判定するモンスターの種族ID
114 * @return ダンジョンに出現するならばTRUEを返す
117 * 地上は常にTRUE(荒野の出現は別hookで絞るため)。
118 * 荒野限定(WILD_ONLY)の場合、荒野の山に出るモンスターにのみダンジョンの山に出現を許可する。
119 * その他の場合、山及び火山以外のダンジョンでは全てのモンスターに出現を許可する。
120 * ダンジョンが山の場合は、荒野の山(WILD_MOUNTAIN)に出ない水棲動物(AQUATIC)は許可しない。
121 * ダンジョンが火山の場合は、荒野の火山(WILD_VOLCANO)に出ない水棲動物(AQUATIC)は許可しない。
124 bool mon_hook_dungeon(PlayerType *player_ptr, MonsterRaceId r_idx)
126 const auto &floor = *player_ptr->current_floor_ptr;
127 if (!floor.is_in_underground() && !floor.is_in_quest()) {
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);
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;
145 * @brief モンスターが海洋に出現するかどうかを返す
146 * @param r_idx 判定するモンスターの種族ID
147 * @return 海洋に出現するならばTRUEを返す
149 bool mon_hook_ocean(PlayerType *player_ptr, MonsterRaceId r_idx)
154 auto *r_ptr = &monraces_info[r_idx];
155 return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_OCEAN);
159 * @brief モンスターが海岸に出現するかどうかを返す
160 * @param r_idx 判定するモンスターの種族ID
161 * @return 海岸に出現するならばTRUEを返す
163 bool mon_hook_shore(PlayerType *player_ptr, MonsterRaceId r_idx)
168 auto *r_ptr = &monraces_info[r_idx];
169 return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_SHORE);
173 * @brief モンスターが荒地に出現するかどうかを返す
174 * @param r_idx 判定するモンスターの種族ID
175 * @return 荒地に出現するならばTRUEを返す
177 bool mon_hook_waste(PlayerType *player_ptr, MonsterRaceId r_idx)
182 auto *r_ptr = &monraces_info[r_idx];
183 return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_WASTE, MonsterWildernessType::WILD_ALL });
187 * @brief モンスターが町に出現するかどうかを返す
188 * @param r_idx 判定するモンスターの種族ID
189 * @return 荒地に出現するならばTRUEを返す
191 bool mon_hook_town(PlayerType *player_ptr, MonsterRaceId r_idx)
196 auto *r_ptr = &monraces_info[r_idx];
197 return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_TOWN, MonsterWildernessType::WILD_ALL });
201 * @brief モンスターが森林に出現するかどうかを返す
202 * @param r_idx 判定するモンスターの種族ID
203 * @return 森林に出現するならばTRUEを返す
205 bool mon_hook_wood(PlayerType *player_ptr, MonsterRaceId r_idx)
210 auto *r_ptr = &monraces_info[r_idx];
211 return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_WOOD, MonsterWildernessType::WILD_ALL });
215 * @brief モンスターが火山に出現するかどうかを返す
216 * @param r_idx 判定するモンスターの種族ID
217 * @return 火山に出現するならばTRUEを返す
219 bool mon_hook_volcano(PlayerType *player_ptr, MonsterRaceId r_idx)
224 auto *r_ptr = &monraces_info[r_idx];
225 return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_VOLCANO);
229 * @brief モンスターが山地に出現するかどうかを返す
230 * @param r_idx 判定するモンスターの種族ID
231 * @return 山地に出現するならばTRUEを返す
233 bool mon_hook_mountain(PlayerType *player_ptr, MonsterRaceId r_idx)
238 auto *r_ptr = &monraces_info[r_idx];
239 return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_MOUNTAIN);
243 * @brief モンスターが草原に出現するかどうかを返す
244 * @param r_idx 判定するモンスターの種族ID
245 * @return 森林に出現するならばTRUEを返す
247 bool mon_hook_grass(PlayerType *player_ptr, MonsterRaceId r_idx)
252 auto *r_ptr = &monraces_info[r_idx];
253 return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_GRASS, MonsterWildernessType::WILD_ALL });
257 * @brief モンスターが深い水地形に出現するかどうかを返す
258 * @param r_idx 判定するモンスターの種族ID
259 * @return 深い水地形に出現するならばTRUEを返す
261 bool mon_hook_deep_water(PlayerType *player_ptr, MonsterRaceId r_idx)
263 auto *r_ptr = &monraces_info[r_idx];
264 if (!mon_hook_dungeon(player_ptr, r_idx)) {
268 return r_ptr->feature_flags.has(MonsterFeatureType::AQUATIC);
272 * @brief モンスターが浅い水地形に出現するかどうかを返す
273 * @param r_idx 判定するモンスターの種族ID
274 * @return 浅い水地形に出現するならばTRUEを返す
276 bool mon_hook_shallow_water(PlayerType *player_ptr, MonsterRaceId r_idx)
278 auto *r_ptr = &monraces_info[r_idx];
279 if (!mon_hook_dungeon(player_ptr, r_idx)) {
283 return r_ptr->aura_flags.has_not(MonsterAuraType::FIRE);
287 * @brief モンスターが溶岩地形に出現するかどうかを返す
288 * @param r_idx 判定するモンスターの種族ID
289 * @return 溶岩地形に出現するならばTRUEを返す
291 bool mon_hook_lava(PlayerType *player_ptr, MonsterRaceId r_idx)
293 auto *r_ptr = &monraces_info[r_idx];
294 if (!mon_hook_dungeon(player_ptr, r_idx)) {
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);
302 * @brief モンスターが通常の床地形に出現するかどうかを返す
303 * @param r_idx 判定するモンスターの種族ID
304 * @return 通常の床地形に出現するならばTRUEを返す
306 bool mon_hook_floor(PlayerType *player_ptr, MonsterRaceId r_idx)
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)) {
320 * Helper function for "glass room"
322 bool vault_aux_lite(PlayerType *player_ptr, MonsterRaceId r_idx)
327 auto *r_ptr = &monraces_info[r_idx];
328 if (!vault_monster_okay(player_ptr, r_idx)) {
332 if (r_ptr->ability_flags.has_none_of({ MonsterAbilityType::BR_LITE, MonsterAbilityType::BA_LITE })) {
336 if (r_ptr->feature_flags.has_any_of({ MonsterFeatureType::PASS_WALL, MonsterFeatureType::KILL_WALL })) {
340 if (r_ptr->ability_flags.has(MonsterAbilityType::BR_DISI)) {
348 * Helper function for "glass room"
350 bool vault_aux_shards(PlayerType *player_ptr, MonsterRaceId r_idx)
352 auto *r_ptr = &monraces_info[r_idx];
353 if (!vault_monster_okay(player_ptr, r_idx)) {
357 if (r_ptr->ability_flags.has_not(MonsterAbilityType::BR_SHAR)) {
365 * @brief モンスターがVault生成の最低必要条件を満たしているかを返す /
366 * Helper monster selection function
367 * @param r_idx 確認したいモンスター種族ID
368 * @return Vault生成の最低必要条件を満たしているならTRUEを返す。
370 bool vault_aux_simple(PlayerType *player_ptr, MonsterRaceId r_idx)
375 return vault_monster_okay(player_ptr, r_idx);
379 * @brief モンスターがゼリーnestの生成必要条件を満たしているかを返す /
380 * Helper function for "monster nest (jelly)"
381 * @param r_idx 確認したいモンスター種族ID
382 * @return 生成必要条件を満たしているならTRUEを返す。
384 bool vault_aux_jelly(PlayerType *player_ptr, MonsterRaceId r_idx)
386 const auto &monrace = monraces_info[r_idx];
387 if (!vault_monster_okay(player_ptr, r_idx)) {
391 if (monrace.behavior_flags.has(MonsterBehaviorType::KILL_BODY) && monrace.behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
395 if (monrace.kind_flags.has(MonsterKindType::EVIL)) {
399 return monrace.symbol_char_is_any_of("ijm,");
403 * @brief モンスターが動物nestの生成必要条件を満たしているかを返す /
404 * Helper function for "monster nest (animal)"
405 * @param r_idx 確認したいモンスター種族ID
406 * @return 生成必要条件を満たしているならTRUEを返す。
408 bool vault_aux_animal(PlayerType *player_ptr, MonsterRaceId r_idx)
410 auto *r_ptr = &monraces_info[r_idx];
411 if (!vault_monster_okay(player_ptr, r_idx)) {
415 if (r_ptr->kind_flags.has_not(MonsterKindType::ANIMAL)) {
423 * @brief モンスターがアンデッドnestの生成必要条件を満たしているかを返す /
424 * Helper function for "monster nest (undead)"
425 * @param r_idx 確認したいモンスター種族ID
426 * @return 生成必要条件を満たしているならTRUEを返す。
428 bool vault_aux_undead(PlayerType *player_ptr, MonsterRaceId r_idx)
430 auto *r_ptr = &monraces_info[r_idx];
431 if (!vault_monster_okay(player_ptr, r_idx)) {
435 if (r_ptr->kind_flags.has_not(MonsterKindType::UNDEAD)) {
443 * @brief モンスターが聖堂nestの生成必要条件を満たしているかを返す /
444 * Helper function for "monster nest (chapel)"
445 * @param r_idx 確認したいモンスター種族ID
446 * @return 生成必要条件を満たしているならTRUEを返す。
448 bool vault_aux_chapel_g(PlayerType *player_ptr, MonsterRaceId r_idx)
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,
466 const auto &monrace = monraces_info[r_idx];
467 if (!vault_monster_okay(player_ptr, r_idx)) {
471 if (monrace.kind_flags.has(MonsterKindType::EVIL)) {
475 if ((r_idx == MonsterRaceId::A_GOLD) || (r_idx == MonsterRaceId::A_SILVER)) {
479 if (monrace.symbol_char_is_any_of("A")) {
483 return chapel_list.find(r_idx) != chapel_list.end();
487 * @brief モンスターが犬小屋nestの生成必要条件を満たしているかを返す /
488 * Helper function for "monster nest (kennel)"
489 * @param r_idx 確認したいモンスター種族ID
490 * @return 生成必要条件を満たしているならTRUEを返す。
492 bool vault_aux_kennel(PlayerType *player_ptr, MonsterRaceId r_idx)
494 auto *r_ptr = &monraces_info[r_idx];
495 if (!vault_monster_okay(player_ptr, r_idx)) {
499 return r_ptr->symbol_char_is_any_of("CZ");
503 * @brief モンスターがミミックnestの生成必要条件を満たしているかを返す /
504 * Helper function for "monster nest (mimic)"
505 * @param r_idx 確認したいモンスター種族ID
506 * @return 生成必要条件を満たしているならTRUEを返す。
508 bool vault_aux_mimic(PlayerType *player_ptr, MonsterRaceId r_idx)
510 auto *r_ptr = &monraces_info[r_idx];
511 if (!vault_monster_okay(player_ptr, r_idx)) {
515 return r_ptr->symbol_char_is_any_of("!$&(/=?[\\|][`~>+");
519 * @brief モンスターが単一クローンnestの生成必要条件を満たしているかを返す /
520 * Helper function for "monster nest (clone)"
521 * @param r_idx 確認したいモンスター種族ID
522 * @return 生成必要条件を満たしているならTRUEを返す。
524 bool vault_aux_clone(PlayerType *player_ptr, MonsterRaceId r_idx)
526 if (!vault_monster_okay(player_ptr, r_idx)) {
530 return r_idx == vault_aux_race;
534 * @brief モンスターが邪悪属性シンボルクローンnestの生成必要条件を満たしているかを返す /
535 * Helper function for "monster nest (symbol clone)"
536 * @param r_idx 確認したいモンスター種族ID
537 * @return 生成必要条件を満たしているならTRUEを返す。
539 bool vault_aux_symbol_e(PlayerType *player_ptr, MonsterRaceId r_idx)
541 const auto &monrace = monraces_info[r_idx];
542 if (!vault_monster_okay(player_ptr, r_idx)) {
546 if (monrace.behavior_flags.has(MonsterBehaviorType::KILL_BODY) && monrace.behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
550 if (monrace.kind_flags.has(MonsterKindType::GOOD)) {
554 if (monrace.symbol_definition.character != vault_aux_char) {
562 * @brief モンスターが善良属性シンボルクローンnestの生成必要条件を満たしているかを返す /
563 * Helper function for "monster nest (symbol clone)"
564 * @param r_idx 確認したいモンスター種族ID
565 * @return 生成必要条件を満たしているならTRUEを返す。
567 bool vault_aux_symbol_g(PlayerType *player_ptr, MonsterRaceId r_idx)
569 const auto &monrace = monraces_info[r_idx];
570 if (!vault_monster_okay(player_ptr, r_idx)) {
574 if (monrace.behavior_flags.has(MonsterBehaviorType::KILL_BODY) && monrace.behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
578 if (monrace.kind_flags.has(MonsterKindType::EVIL)) {
582 if (monrace.symbol_definition.character != vault_aux_char) {
590 * @brief モンスターがオークpitの生成必要条件を満たしているかを返す /
591 * Helper function for "monster pit (orc)"
592 * @param r_idx 確認したいモンスター種族ID
593 * @return 生成必要条件を満たしているならTRUEを返す。
595 bool vault_aux_orc(PlayerType *player_ptr, MonsterRaceId r_idx)
597 auto *r_ptr = &monraces_info[r_idx];
598 if (!vault_monster_okay(player_ptr, r_idx)) {
602 if (r_ptr->kind_flags.has_not(MonsterKindType::ORC)) {
606 if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
614 * @brief モンスターがトロルpitの生成必要条件を満たしているかを返す /
615 * Helper function for "monster pit (troll)"
616 * @param r_idx 確認したいモンスター種族ID
617 * @return 生成必要条件を満たしているならTRUEを返す。
619 bool vault_aux_troll(PlayerType *player_ptr, MonsterRaceId r_idx)
621 auto *r_ptr = &monraces_info[r_idx];
622 if (!vault_monster_okay(player_ptr, r_idx)) {
626 if (r_ptr->kind_flags.has_not(MonsterKindType::TROLL)) {
630 if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
638 * @brief モンスターが巨人pitの生成必要条件を満たしているかを返す /
639 * Helper function for "monster pit (giant)"
640 * @param r_idx 確認したいモンスター種族ID
641 * @return 生成必要条件を満たしているならTRUEを返す。
643 bool vault_aux_giant(PlayerType *player_ptr, MonsterRaceId r_idx)
645 auto *r_ptr = &monraces_info[r_idx];
646 if (!vault_monster_okay(player_ptr, r_idx)) {
650 if (r_ptr->kind_flags.has_not(MonsterKindType::GIANT)) {
654 if (r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
658 if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
666 * @brief モンスターがドラゴンpitの生成必要条件を満たしているかを返す /
667 * Helper function for "monster pit (dragon)"
668 * @param r_idx 確認したいモンスター種族ID
669 * @return 生成必要条件を満たしているならTRUEを返す。
671 bool vault_aux_dragon(PlayerType *player_ptr, MonsterRaceId r_idx)
673 auto *r_ptr = &monraces_info[r_idx];
674 if (!vault_monster_okay(player_ptr, r_idx)) {
678 if (r_ptr->kind_flags.has_not(MonsterKindType::DRAGON)) {
682 if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
686 auto flags = RF_ABILITY_BREATH_MASK;
687 flags.reset(vault_aux_dragon_mask4);
689 if (r_ptr->ability_flags.has_any_of(flags) || !r_ptr->ability_flags.has_all_of(vault_aux_dragon_mask4)) {
697 * @brief モンスターが悪魔pitの生成必要条件を満たしているかを返す /
698 * Helper function for "monster pit (demon)"
699 * @param r_idx 確認したいモンスター種族ID
700 * @return 生成必要条件を満たしているならTRUEを返す。
702 bool vault_aux_demon(PlayerType *player_ptr, MonsterRaceId r_idx)
704 auto *r_ptr = &monraces_info[r_idx];
705 if (!vault_monster_okay(player_ptr, r_idx)) {
709 if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
713 if (r_ptr->kind_flags.has_not(MonsterKindType::DEMON)) {
721 * @brief モンスターが狂気pitの生成必要条件を満たしているかを返す /
722 * Helper function for "monster pit (lovecraftian)"
723 * @param r_idx 確認したいモンスター種族ID
724 * @return 生成必要条件を満たしているならTRUEを返す。
726 bool vault_aux_cthulhu(PlayerType *player_ptr, MonsterRaceId r_idx)
728 auto *r_ptr = &monraces_info[r_idx];
729 if (!vault_monster_okay(player_ptr, r_idx)) {
733 if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
737 if (r_ptr->misc_flags.has_not(MonsterMiscType::ELDRITCH_HORROR)) {
745 * @brief モンスターがダークエルフpitの生成必要条件を満たしているかを返す /
746 * Helper function for "monster pit (dark elf)"
747 * @param r_idx 確認したいモンスター種族ID
748 * @return 生成必要条件を満たしているならTRUEを返す。
750 bool vault_aux_dark_elf(PlayerType *player_ptr, MonsterRaceId r_idx)
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,
765 if (!vault_monster_okay(player_ptr, r_idx)) {
769 return dark_elf_list.find(r_idx) != dark_elf_list.end();
773 * @brief バルログが死体を食べられるモンスターかの判定 / Hook function for human corpses
774 * @param r_idx モンスターID
775 * @return 死体を食べられるならTRUEを返す。
777 bool monster_hook_human(PlayerType *player_ptr, MonsterRaceId r_idx)
782 const auto &monrace = monraces_info[r_idx];
783 if (monrace.kind_flags.has(MonsterKindType::UNIQUE)) {
787 return monrace.symbol_char_is_any_of("pht");
791 * @brief 悪夢の元凶となるモンスターかどうかを返す。
792 * @param r_idx 判定対象となるモンスターのID
793 * @return 悪夢の元凶となり得るか否か。
795 bool get_nightmare(PlayerType *player_ptr, MonsterRaceId r_idx)
797 auto *r_ptr = &monraces_info[r_idx];
798 if (r_ptr->misc_flags.has_not(MonsterMiscType::ELDRITCH_HORROR)) {
802 if (r_ptr->level <= player_ptr->lev) {
810 * @brief モンスター種族が釣れる種族かどうかを判定する。
811 * @param r_idx 判定したいモンスター種族のID
812 * @return 釣れる対象ならばTRUEを返す
814 bool monster_is_fishing_target(PlayerType *player_ptr, MonsterRaceId r_idx)
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;
827 * @brief モンスター闘技場に参加できるモンスターの判定
828 * @param r_idx モンスターID
829 * @details 基準はNEVER_MOVE MULTIPLY QUANTUM AQUATIC CHAMELEONのいずれも持たず、
830 * 自爆以外のなんらかのHP攻撃手段を持っていること。
833 bool monster_can_entry_arena(PlayerType *player_ptr, MonsterRaceId r_idx)
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();
850 for (const auto &blow : monrace.blows) {
851 if (blow.effect != RaceBlowEffectType::DR_MANA) {
852 dam += blow.damage_dice.num;
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)) {
864 * モンスターが人形のベースにできるかを返す
865 * @param r_idx チェックしたいモンスター種族のID
866 * @return 人形にできるならTRUEを返す
868 bool item_monster_okay(PlayerType *player_ptr, MonsterRaceId r_idx)
873 auto *r_ptr = &monraces_info[r_idx];
874 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
878 if (r_ptr->misc_flags.has(MonsterMiscType::KAGE)) {
882 if (r_ptr->resistance_flags.has(MonsterResistanceType::RESIST_ALL)) {
886 if (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL)) {
890 if (r_ptr->misc_flags.has(MonsterMiscType::FORCE_DEPTH)) {
894 if (r_ptr->population_flags.has_any_of({ MonsterPopulationType::ONLY_ONE, MonsterPopulationType::BUNBUN_STRIKER })) {
902 * vaultに配置可能なモンスターの条件を指定する / Monster validation
903 * @param r_idx モンスター種別ID
904 * @param Vaultに配置可能であればTRUE
906 * Line 1 -- forbid town monsters
907 * Line 2 -- forbid uniques
908 * Line 3 -- forbid aquatic monsters
910 bool vault_monster_okay(PlayerType *player_ptr, MonsterRaceId r_idx)
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);