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"
27 /*! 通常pit生成時のモンスターの構成条件ID / Race index for "monster pit (clone)" */
28 MonsterRaceId vault_aux_race;
30 /*! 単一シンボルpit生成時の指定シンボル / Race index for "monster pit (symbol clone)" */
33 /*! ブレス属性に基づくドラゴンpit生成時条件マスク / Breath mask for "monster pit (dragon)" */
34 EnumClassFlagGroup<MonsterAbilityType> vault_aux_dragon_mask4;
37 * @brief pit/nestの基準となる単種モンスターを決める /
38 * @param player_ptr プレイヤーへの参照ポインタ
40 void vault_prep_clone(PlayerType *player_ptr)
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);
48 * @brief pit/nestの基準となるモンスターシンボルを決める /
49 * @param player_ptr プレイヤーへの参照ポインタ
51 void vault_prep_symbol(PlayerType *player_ptr)
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;
60 * @brief pit/nestの基準となるドラゴンの種類を決める /
61 * @param player_ptr プレイヤーへの参照ポインタ
63 void vault_prep_dragon(PlayerType *player_ptr)
68 vault_aux_dragon_mask4.clear();
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 */
80 vault_aux_dragon_mask4.set(breath_list);
84 vault_aux_dragon_mask4.set(rand_choice(breath_list));
88 * @brief モンスターがクエストの討伐対象に成り得るかを返す / Hook function for quest monsters
89 * @param r_idx モンスターID
90 * @return 討伐対象にできるならTRUEを返す。
92 bool mon_hook_quest(PlayerType *player_ptr, MonsterRaceId r_idx)
97 auto *r_ptr = &monraces_info[r_idx];
98 if (r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_ONLY)) {
102 if (r_ptr->feature_flags.has(MonsterFeatureType::AQUATIC)) {
106 if (r_ptr->misc_flags.has(MonsterMiscType::MULTIPLY)) {
110 if (r_ptr->behavior_flags.has(MonsterBehaviorType::FRIENDLY)) {
118 * @brief モンスターがダンジョンに出現するかどうかを返す
119 * @param r_idx 判定するモンスターの種族ID
120 * @return ダンジョンに出現するならばTRUEを返す
123 * 地上は常にTRUE(荒野の出現は別hookで絞るため)。
124 * 荒野限定(WILD_ONLY)の場合、荒野の山に出るモンスターにのみダンジョンの山に出現を許可する。
125 * その他の場合、山及び火山以外のダンジョンでは全てのモンスターに出現を許可する。
126 * ダンジョンが山の場合は、荒野の山(WILD_MOUNTAIN)に出ない水棲動物(AQUATIC)は許可しない。
127 * ダンジョンが火山の場合は、荒野の火山(WILD_VOLCANO)に出ない水棲動物(AQUATIC)は許可しない。
130 bool mon_hook_dungeon(PlayerType *player_ptr, MonsterRaceId r_idx)
132 const auto &floor = *player_ptr->current_floor_ptr;
133 if (!floor.is_in_dungeon() && !floor.is_in_quest()) {
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);
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;
151 * @brief モンスターが海洋に出現するかどうかを返す
152 * @param r_idx 判定するモンスターの種族ID
153 * @return 海洋に出現するならばTRUEを返す
155 bool mon_hook_ocean(PlayerType *player_ptr, MonsterRaceId r_idx)
160 auto *r_ptr = &monraces_info[r_idx];
161 return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_OCEAN);
165 * @brief モンスターが海岸に出現するかどうかを返す
166 * @param r_idx 判定するモンスターの種族ID
167 * @return 海岸に出現するならばTRUEを返す
169 bool mon_hook_shore(PlayerType *player_ptr, MonsterRaceId r_idx)
174 auto *r_ptr = &monraces_info[r_idx];
175 return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_SHORE);
179 * @brief モンスターが荒地に出現するかどうかを返す
180 * @param r_idx 判定するモンスターの種族ID
181 * @return 荒地に出現するならばTRUEを返す
183 bool mon_hook_waste(PlayerType *player_ptr, MonsterRaceId r_idx)
188 auto *r_ptr = &monraces_info[r_idx];
189 return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_WASTE, MonsterWildernessType::WILD_ALL });
193 * @brief モンスターが町に出現するかどうかを返す
194 * @param r_idx 判定するモンスターの種族ID
195 * @return 荒地に出現するならばTRUEを返す
197 bool mon_hook_town(PlayerType *player_ptr, MonsterRaceId r_idx)
202 auto *r_ptr = &monraces_info[r_idx];
203 return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_TOWN, MonsterWildernessType::WILD_ALL });
207 * @brief モンスターが森林に出現するかどうかを返す
208 * @param r_idx 判定するモンスターの種族ID
209 * @return 森林に出現するならばTRUEを返す
211 bool mon_hook_wood(PlayerType *player_ptr, MonsterRaceId r_idx)
216 auto *r_ptr = &monraces_info[r_idx];
217 return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_WOOD, MonsterWildernessType::WILD_ALL });
221 * @brief モンスターが火山に出現するかどうかを返す
222 * @param r_idx 判定するモンスターの種族ID
223 * @return 火山に出現するならばTRUEを返す
225 bool mon_hook_volcano(PlayerType *player_ptr, MonsterRaceId r_idx)
230 auto *r_ptr = &monraces_info[r_idx];
231 return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_VOLCANO);
235 * @brief モンスターが山地に出現するかどうかを返す
236 * @param r_idx 判定するモンスターの種族ID
237 * @return 山地に出現するならばTRUEを返す
239 bool mon_hook_mountain(PlayerType *player_ptr, MonsterRaceId r_idx)
244 auto *r_ptr = &monraces_info[r_idx];
245 return r_ptr->wilderness_flags.has(MonsterWildernessType::WILD_MOUNTAIN);
249 * @brief モンスターが草原に出現するかどうかを返す
250 * @param r_idx 判定するモンスターの種族ID
251 * @return 森林に出現するならばTRUEを返す
253 bool mon_hook_grass(PlayerType *player_ptr, MonsterRaceId r_idx)
258 auto *r_ptr = &monraces_info[r_idx];
259 return r_ptr->wilderness_flags.has_any_of({ MonsterWildernessType::WILD_GRASS, MonsterWildernessType::WILD_ALL });
263 * @brief モンスターが深い水地形に出現するかどうかを返す
264 * @param r_idx 判定するモンスターの種族ID
265 * @return 深い水地形に出現するならばTRUEを返す
267 bool mon_hook_deep_water(PlayerType *player_ptr, MonsterRaceId r_idx)
269 auto *r_ptr = &monraces_info[r_idx];
270 if (!mon_hook_dungeon(player_ptr, r_idx)) {
274 return r_ptr->feature_flags.has(MonsterFeatureType::AQUATIC);
278 * @brief モンスターが浅い水地形に出現するかどうかを返す
279 * @param r_idx 判定するモンスターの種族ID
280 * @return 浅い水地形に出現するならばTRUEを返す
282 bool mon_hook_shallow_water(PlayerType *player_ptr, MonsterRaceId r_idx)
284 auto *r_ptr = &monraces_info[r_idx];
285 if (!mon_hook_dungeon(player_ptr, r_idx)) {
289 return r_ptr->aura_flags.has_not(MonsterAuraType::FIRE);
293 * @brief モンスターが溶岩地形に出現するかどうかを返す
294 * @param r_idx 判定するモンスターの種族ID
295 * @return 溶岩地形に出現するならばTRUEを返す
297 bool mon_hook_lava(PlayerType *player_ptr, MonsterRaceId r_idx)
299 auto *r_ptr = &monraces_info[r_idx];
300 if (!mon_hook_dungeon(player_ptr, r_idx)) {
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);
308 * @brief モンスターが通常の床地形に出現するかどうかを返す
309 * @param r_idx 判定するモンスターの種族ID
310 * @return 通常の床地形に出現するならばTRUEを返す
312 bool mon_hook_floor(PlayerType *player_ptr, MonsterRaceId r_idx)
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)) {
326 * Helper function for "glass room"
328 bool vault_aux_lite(PlayerType *player_ptr, MonsterRaceId r_idx)
333 auto *r_ptr = &monraces_info[r_idx];
334 if (!vault_monster_okay(player_ptr, r_idx)) {
338 if (r_ptr->ability_flags.has_none_of({ MonsterAbilityType::BR_LITE, MonsterAbilityType::BA_LITE })) {
342 if (r_ptr->feature_flags.has_any_of({ MonsterFeatureType::PASS_WALL, MonsterFeatureType::KILL_WALL })) {
346 if (r_ptr->ability_flags.has(MonsterAbilityType::BR_DISI)) {
354 * Helper function for "glass room"
356 bool vault_aux_shards(PlayerType *player_ptr, MonsterRaceId r_idx)
358 auto *r_ptr = &monraces_info[r_idx];
359 if (!vault_monster_okay(player_ptr, r_idx)) {
363 if (r_ptr->ability_flags.has_not(MonsterAbilityType::BR_SHAR)) {
371 * @brief モンスターがVault生成の最低必要条件を満たしているかを返す /
372 * Helper monster selection function
373 * @param r_idx 確認したいモンスター種族ID
374 * @return Vault生成の最低必要条件を満たしているならTRUEを返す。
376 bool vault_aux_simple(PlayerType *player_ptr, MonsterRaceId r_idx)
381 return vault_monster_okay(player_ptr, r_idx);
385 * @brief モンスターがゼリーnestの生成必要条件を満たしているかを返す /
386 * Helper function for "monster nest (jelly)"
387 * @param r_idx 確認したいモンスター種族ID
388 * @return 生成必要条件を満たしているならTRUEを返す。
390 bool vault_aux_jelly(PlayerType *player_ptr, MonsterRaceId r_idx)
392 auto *r_ptr = &monraces_info[r_idx];
393 if (!vault_monster_okay(player_ptr, r_idx)) {
397 if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
401 if (r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
405 if (!angband_strchr("ijm,", r_ptr->d_char)) {
413 * @brief モンスターが動物nestの生成必要条件を満たしているかを返す /
414 * Helper function for "monster nest (animal)"
415 * @param r_idx 確認したいモンスター種族ID
416 * @return 生成必要条件を満たしているならTRUEを返す。
418 bool vault_aux_animal(PlayerType *player_ptr, MonsterRaceId r_idx)
420 auto *r_ptr = &monraces_info[r_idx];
421 if (!vault_monster_okay(player_ptr, r_idx)) {
425 if (r_ptr->kind_flags.has_not(MonsterKindType::ANIMAL)) {
433 * @brief モンスターがアンデッドnestの生成必要条件を満たしているかを返す /
434 * Helper function for "monster nest (undead)"
435 * @param r_idx 確認したいモンスター種族ID
436 * @return 生成必要条件を満たしているならTRUEを返す。
438 bool vault_aux_undead(PlayerType *player_ptr, MonsterRaceId r_idx)
440 auto *r_ptr = &monraces_info[r_idx];
441 if (!vault_monster_okay(player_ptr, r_idx)) {
445 if (r_ptr->kind_flags.has_not(MonsterKindType::UNDEAD)) {
453 * @brief モンスターが聖堂nestの生成必要条件を満たしているかを返す /
454 * Helper function for "monster nest (chapel)"
455 * @param r_idx 確認したいモンスター種族ID
456 * @return 生成必要条件を満たしているならTRUEを返す。
458 bool vault_aux_chapel_g(PlayerType *player_ptr, MonsterRaceId r_idx)
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,
476 auto *r_ptr = &monraces_info[r_idx];
477 if (!vault_monster_okay(player_ptr, r_idx)) {
481 if (r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
485 if ((r_idx == MonsterRaceId::A_GOLD) || (r_idx == MonsterRaceId::A_SILVER)) {
489 if (r_ptr->d_char == 'A') {
493 return chapel_list.find(r_idx) != chapel_list.end();
497 * @brief モンスターが犬小屋nestの生成必要条件を満たしているかを返す /
498 * Helper function for "monster nest (kennel)"
499 * @param r_idx 確認したいモンスター種族ID
500 * @return 生成必要条件を満たしているならTRUEを返す。
502 bool vault_aux_kennel(PlayerType *player_ptr, MonsterRaceId r_idx)
504 auto *r_ptr = &monraces_info[r_idx];
505 if (!vault_monster_okay(player_ptr, r_idx)) {
509 if (!angband_strchr("CZ", r_ptr->d_char)) {
517 * @brief モンスターがミミックnestの生成必要条件を満たしているかを返す /
518 * Helper function for "monster nest (mimic)"
519 * @param r_idx 確認したいモンスター種族ID
520 * @return 生成必要条件を満たしているならTRUEを返す。
522 bool vault_aux_mimic(PlayerType *player_ptr, MonsterRaceId r_idx)
524 auto *r_ptr = &monraces_info[r_idx];
525 if (!vault_monster_okay(player_ptr, r_idx)) {
529 if (!angband_strchr("!$&(/=?[\\|][`~>+", r_ptr->d_char)) {
537 * @brief モンスターが単一クローンnestの生成必要条件を満たしているかを返す /
538 * Helper function for "monster nest (clone)"
539 * @param r_idx 確認したいモンスター種族ID
540 * @return 生成必要条件を満たしているならTRUEを返す。
542 bool vault_aux_clone(PlayerType *player_ptr, MonsterRaceId r_idx)
544 if (!vault_monster_okay(player_ptr, r_idx)) {
548 return r_idx == vault_aux_race;
552 * @brief モンスターが邪悪属性シンボルクローンnestの生成必要条件を満たしているかを返す /
553 * Helper function for "monster nest (symbol clone)"
554 * @param r_idx 確認したいモンスター種族ID
555 * @return 生成必要条件を満たしているならTRUEを返す。
557 bool vault_aux_symbol_e(PlayerType *player_ptr, MonsterRaceId r_idx)
559 auto *r_ptr = &monraces_info[r_idx];
560 if (!vault_monster_okay(player_ptr, r_idx)) {
564 if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
568 if (r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
572 if (r_ptr->d_char != vault_aux_char) {
580 * @brief モンスターが善良属性シンボルクローンnestの生成必要条件を満たしているかを返す /
581 * Helper function for "monster nest (symbol clone)"
582 * @param r_idx 確認したいモンスター種族ID
583 * @return 生成必要条件を満たしているならTRUEを返す。
585 bool vault_aux_symbol_g(PlayerType *player_ptr, MonsterRaceId r_idx)
587 auto *r_ptr = &monraces_info[r_idx];
588 if (!vault_monster_okay(player_ptr, r_idx)) {
592 if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
596 if (r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
600 if (r_ptr->d_char != vault_aux_char) {
608 * @brief モンスターがオークpitの生成必要条件を満たしているかを返す /
609 * Helper function for "monster pit (orc)"
610 * @param r_idx 確認したいモンスター種族ID
611 * @return 生成必要条件を満たしているならTRUEを返す。
613 bool vault_aux_orc(PlayerType *player_ptr, MonsterRaceId r_idx)
615 auto *r_ptr = &monraces_info[r_idx];
616 if (!vault_monster_okay(player_ptr, r_idx)) {
620 if (r_ptr->kind_flags.has_not(MonsterKindType::ORC)) {
624 if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
632 * @brief モンスターがトロルpitの生成必要条件を満たしているかを返す /
633 * Helper function for "monster pit (troll)"
634 * @param r_idx 確認したいモンスター種族ID
635 * @return 生成必要条件を満たしているならTRUEを返す。
637 bool vault_aux_troll(PlayerType *player_ptr, MonsterRaceId r_idx)
639 auto *r_ptr = &monraces_info[r_idx];
640 if (!vault_monster_okay(player_ptr, r_idx)) {
644 if (r_ptr->kind_flags.has_not(MonsterKindType::TROLL)) {
648 if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
656 * @brief モンスターが巨人pitの生成必要条件を満たしているかを返す /
657 * Helper function for "monster pit (giant)"
658 * @param r_idx 確認したいモンスター種族ID
659 * @return 生成必要条件を満たしているならTRUEを返す。
661 bool vault_aux_giant(PlayerType *player_ptr, MonsterRaceId r_idx)
663 auto *r_ptr = &monraces_info[r_idx];
664 if (!vault_monster_okay(player_ptr, r_idx)) {
668 if (r_ptr->kind_flags.has_not(MonsterKindType::GIANT)) {
672 if (r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
676 if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
684 * @brief モンスターがドラゴンpitの生成必要条件を満たしているかを返す /
685 * Helper function for "monster pit (dragon)"
686 * @param r_idx 確認したいモンスター種族ID
687 * @return 生成必要条件を満たしているならTRUEを返す。
689 bool vault_aux_dragon(PlayerType *player_ptr, MonsterRaceId r_idx)
691 auto *r_ptr = &monraces_info[r_idx];
692 if (!vault_monster_okay(player_ptr, r_idx)) {
696 if (r_ptr->kind_flags.has_not(MonsterKindType::DRAGON)) {
700 if (r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
704 auto flags = RF_ABILITY_BREATH_MASK;
705 flags.reset(vault_aux_dragon_mask4);
707 if (r_ptr->ability_flags.has_any_of(flags) || !r_ptr->ability_flags.has_all_of(vault_aux_dragon_mask4)) {
715 * @brief モンスターが悪魔pitの生成必要条件を満たしているかを返す /
716 * Helper function for "monster pit (demon)"
717 * @param r_idx 確認したいモンスター種族ID
718 * @return 生成必要条件を満たしているならTRUEを返す。
720 bool vault_aux_demon(PlayerType *player_ptr, MonsterRaceId r_idx)
722 auto *r_ptr = &monraces_info[r_idx];
723 if (!vault_monster_okay(player_ptr, r_idx)) {
727 if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
731 if (r_ptr->kind_flags.has_not(MonsterKindType::DEMON)) {
739 * @brief モンスターが狂気pitの生成必要条件を満たしているかを返す /
740 * Helper function for "monster pit (lovecraftian)"
741 * @param r_idx 確認したいモンスター種族ID
742 * @return 生成必要条件を満たしているならTRUEを返す。
744 bool vault_aux_cthulhu(PlayerType *player_ptr, MonsterRaceId r_idx)
746 auto *r_ptr = &monraces_info[r_idx];
747 if (!vault_monster_okay(player_ptr, r_idx)) {
751 if (r_ptr->behavior_flags.has(MonsterBehaviorType::KILL_BODY) && r_ptr->behavior_flags.has_not(MonsterBehaviorType::NEVER_BLOW)) {
755 if (r_ptr->misc_flags.has_not(MonsterMiscType::ELDRITCH_HORROR)) {
763 * @brief モンスターがダークエルフpitの生成必要条件を満たしているかを返す /
764 * Helper function for "monster pit (dark elf)"
765 * @param r_idx 確認したいモンスター種族ID
766 * @return 生成必要条件を満たしているならTRUEを返す。
768 bool vault_aux_dark_elf(PlayerType *player_ptr, MonsterRaceId r_idx)
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,
783 if (!vault_monster_okay(player_ptr, r_idx)) {
787 return dark_elf_list.find(r_idx) != dark_elf_list.end();
791 * @brief バルログが死体を食べられるモンスターかの判定 / Hook function for human corpses
792 * @param r_idx モンスターID
793 * @return 死体を食べられるならTRUEを返す。
795 bool monster_hook_human(PlayerType *player_ptr, MonsterRaceId r_idx)
800 auto *r_ptr = &monraces_info[r_idx];
801 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
805 if (angband_strchr("pht", r_ptr->d_char)) {
813 * @brief 悪夢の元凶となるモンスターかどうかを返す。
814 * @param r_idx 判定対象となるモンスターのID
815 * @return 悪夢の元凶となり得るか否か。
817 bool get_nightmare(PlayerType *player_ptr, MonsterRaceId r_idx)
819 auto *r_ptr = &monraces_info[r_idx];
820 if (r_ptr->misc_flags.has_not(MonsterMiscType::ELDRITCH_HORROR)) {
824 if (r_ptr->level <= player_ptr->lev) {
832 * @brief モンスター種族が釣れる種族かどうかを判定する。
833 * @param r_idx 判定したいモンスター種族のID
834 * @return 釣れる対象ならばTRUEを返す
836 bool monster_is_fishing_target(PlayerType *player_ptr, MonsterRaceId r_idx)
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)) {
850 * @brief モンスター闘技場に参加できるモンスターの判定
851 * @param r_idx モンスターID
852 * @details 基準はNEVER_MOVE MULTIPLY QUANTUM AQUATIC CHAMELEONのいずれも持たず、
853 * 自爆以外のなんらかのHP攻撃手段を持っていること。
856 bool monster_can_entry_arena(PlayerType *player_ptr, MonsterRaceId r_idx)
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();
873 for (const auto &blow : monrace.blows) {
874 if (blow.effect != RaceBlowEffectType::DR_MANA) {
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)) {
887 * モンスターが人形のベースにできるかを返す
888 * @param r_idx チェックしたいモンスター種族のID
889 * @return 人形にできるならTRUEを返す
891 bool item_monster_okay(PlayerType *player_ptr, MonsterRaceId r_idx)
896 auto *r_ptr = &monraces_info[r_idx];
897 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
901 if (r_ptr->misc_flags.has(MonsterMiscType::KAGE)) {
905 if (r_ptr->resistance_flags.has(MonsterResistanceType::RESIST_ALL)) {
909 if (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL)) {
913 if (r_ptr->misc_flags.has(MonsterMiscType::FORCE_DEPTH)) {
917 if (r_ptr->population_flags.has(MonsterPopulationType::ONLY_ONE)) {
925 * vaultに配置可能なモンスターの条件を指定する / Monster validation
926 * @param r_idx モンスター種別ID
927 * @param Vaultに配置可能であればTRUE
929 * Line 1 -- forbid town monsters
930 * Line 2 -- forbid uniques
931 * Line 3 -- forbid aquatic monsters
933 bool vault_monster_okay(PlayerType *player_ptr, MonsterRaceId r_idx)
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);