OSDN Git Service

[Refactor] #2886 再描画フラグの分かりにくい単語や名詞でない単語を分かりやすい名詞にした
[hengbandforosx/hengbandosx.git] / src / effect / effect-monster.cpp
index adf7d35..4620fbe 100644 (file)
 #include "core/player-redraw-types.h"
 #include "core/stuff-handler.h"
 #include "core/window-redrawer.h"
+#include "effect/attribute-types.h"
 #include "effect/effect-characteristics.h"
 #include "effect/effect-monster-switcher.h"
 #include "effect/effect-monster-util.h"
+#include "effect/spells-effect-util.h"
 #include "floor/cave.h"
 #include "floor/floor-object.h"
 #include "game-option/play-record-options.h"
 #include "monster-race/race-flags3.h"
 #include "monster-race/race-flags7.h"
 #include "monster-race/race-indice-types.h"
+#include "monster-race/race-resistance-mask.h"
 #include "monster/monster-damage.h"
 #include "monster/monster-describer.h"
 #include "monster/monster-description-types.h"
 #include "monster/monster-info.h"
+#include "monster/monster-pain-describer.h"
 #include "monster/monster-status-setter.h"
 #include "monster/monster-status.h"
 #include "monster/monster-update.h"
 #include "spell-kind/blood-curse.h"
 #include "spell-kind/spells-polymorph.h"
 #include "spell-kind/spells-teleport.h"
-#include "spell/spell-types.h"
-#include "spells-effect-util.h"
 #include "sv-definition/sv-other-types.h"
+#include "system/baseitem-info.h"
 #include "system/floor-type-definition.h"
 #include "system/grid-type-definition.h"
-#include "system/monster-race-definition.h"
-#include "system/monster-type-definition.h"
-#include "system/object-type-definition.h"
+#include "system/item-entity.h"
+#include "system/monster-entity.h"
+#include "system/monster-race-info.h"
 #include "system/player-type-definition.h"
 #include "util/bit-flags-calculator.h"
+#include "util/string-processor.h"
 #include "view/display-messages.h"
+#include <algorithm>
 
 /*!
  * @brief ビーム/ボルト/ボール系魔法によるモンスターへの効果があるかないかを判定する
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @return 効果が何もないならFALSE、何かあるならTRUE
  */
-static process_result is_affective(player_type *player_ptr, effect_monster_type *em_ptr)
+static ProcessResult is_affective(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (!em_ptr->g_ptr->m_idx)
-        return PROCESS_FALSE;
-    if (em_ptr->who && (em_ptr->g_ptr->m_idx == em_ptr->who))
-        return PROCESS_FALSE;
-    if (sukekaku && ((em_ptr->m_ptr->r_idx == MON_SUKE) || (em_ptr->m_ptr->r_idx == MON_KAKU)))
-        return PROCESS_FALSE;
-    if (em_ptr->m_ptr->hp < 0)
-        return PROCESS_FALSE;
-    if (em_ptr->who || em_ptr->g_ptr->m_idx != player_ptr->riding)
-        return PROCESS_TRUE;
-
-    switch (em_ptr->effect_type) {
-    case GF_OLD_HEAL:
-    case GF_OLD_SPEED:
-    case GF_STAR_HEAL:
-        return PROCESS_TRUE;
-    case GF_OLD_SLOW:
-    case GF_OLD_SLEEP:
-    case GF_OLD_CLONE:
-    case GF_OLD_CONF:
-    case GF_OLD_POLY:
-    case GF_GENOCIDE:
-    case GF_E_GENOCIDE:
-        return PROCESS_CONTINUE;
+    if (!em_ptr->g_ptr->m_idx) {
+        return ProcessResult::PROCESS_FALSE;
+    }
+    if (em_ptr->who && (em_ptr->g_ptr->m_idx == em_ptr->who)) {
+        return ProcessResult::PROCESS_FALSE;
+    }
+    if (sukekaku && ((em_ptr->m_ptr->r_idx == MonsterRaceId::SUKE) || (em_ptr->m_ptr->r_idx == MonsterRaceId::KAKU))) {
+        return ProcessResult::PROCESS_FALSE;
+    }
+    if (em_ptr->m_ptr->hp < 0) {
+        return ProcessResult::PROCESS_FALSE;
+    }
+    if (em_ptr->who || em_ptr->g_ptr->m_idx != player_ptr->riding) {
+        return ProcessResult::PROCESS_TRUE;
+    }
+
+    switch (em_ptr->attribute) {
+    case AttributeType::OLD_HEAL:
+    case AttributeType::OLD_SPEED:
+    case AttributeType::STAR_HEAL:
+        return ProcessResult::PROCESS_TRUE;
+    case AttributeType::OLD_SLOW:
+    case AttributeType::OLD_SLEEP:
+    case AttributeType::OLD_CLONE:
+    case AttributeType::OLD_CONF:
+    case AttributeType::OLD_POLY:
+    case AttributeType::GENOCIDE:
+    case AttributeType::E_GENOCIDE:
+        return ProcessResult::PROCESS_CONTINUE;
     default:
         break;
     }
 
-    return PROCESS_FALSE;
+    return ProcessResult::PROCESS_FALSE;
 }
 
 /*!
  * @brief 魔法の効果やモンスター種別(MAKE/FEMALE/なし)に応じて表示するメッセージを変更する
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void make_description_of_affecred_monster(player_type *player_ptr, effect_monster_type *em_ptr)
+static void make_description_of_affecred_monster(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
     em_ptr->dam = (em_ptr->dam + em_ptr->r) / (em_ptr->r + 1);
-    monster_desc(player_ptr, em_ptr->m_name, em_ptr->m_ptr, 0);
-    monster_desc(player_ptr, em_ptr->m_poss, em_ptr->m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
+    angband_strcpy(em_ptr->m_name, monster_desc(player_ptr, em_ptr->m_ptr, 0).data(), sizeof(em_ptr->m_name));
+    angband_strcpy(em_ptr->m_poss, monster_desc(player_ptr, em_ptr->m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE).data(), sizeof(em_ptr->m_poss));
 }
 
 /*!
  * @brief モンスターへの効果属性による耐性及び効果を処理する( / Proccess affecting to monster by effect.
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @return 完全な耐性が発動したらCONTINUE、そうでないなら効果処理の結果
  * @details
  * 完全な耐性を持っていたら、一部属性を除いて影響は及ぼさない
- * 射撃属性 (デバッグ用)であれば貫通する
+ * デバッグ属性、モンスター打撃、モンスター射撃であれば貫通する
  */
-static process_result exe_affect_monster_by_effect(player_type *player_ptr, effect_monster_type *em_ptr)
+static ProcessResult exe_affect_monster_by_effect(PlayerType *player_ptr, effect_monster_type *em_ptr, std::optional<CapturedMonsterType *> cap_mon_ptr)
 {
-    process_result result = is_affective(player_ptr, em_ptr);
-    if (result != PROCESS_TRUE) {
-        if (result == PROCESS_CONTINUE) {
+    const std::vector<AttributeType> effect_arrtibute = {
+        AttributeType::OLD_CLONE,
+        AttributeType::STAR_HEAL,
+        AttributeType::OLD_HEAL,
+        AttributeType::OLD_SPEED,
+        AttributeType::CAPTURE,
+        AttributeType::PHOTO,
+    };
+    const auto check = [em_ptr](const AttributeType attribute) {
+        return em_ptr->attribute == attribute;
+    };
+
+    ProcessResult result = is_affective(player_ptr, em_ptr);
+    if (result != ProcessResult::PROCESS_TRUE) {
+        if (result == ProcessResult::PROCESS_CONTINUE) {
             em_ptr->note = _("には効果がなかった。", " is unaffected.");
             em_ptr->dam = 0;
         }
         return result;
     }
 
-    if (none_bits(em_ptr->r_ptr->flagsr, RFR_RES_ALL) || em_ptr->effect_type == GF_OLD_CLONE || em_ptr->effect_type == GF_STAR_HEAL
-        || em_ptr->effect_type == GF_OLD_HEAL || em_ptr->effect_type == GF_OLD_SPEED || em_ptr->effect_type == GF_CAPTURE || em_ptr->effect_type == GF_PHOTO)
-        return switch_effects_monster(player_ptr, em_ptr);
+    bool do_effect = em_ptr->r_ptr->resistance_flags.has_not(MonsterResistanceType::RESIST_ALL);
+    do_effect |= std::any_of(effect_arrtibute.cbegin(), effect_arrtibute.cend(), check);
+
+    if (do_effect) {
+        return switch_effects_monster(player_ptr, em_ptr, cap_mon_ptr);
+    }
 
-    if (any_bits(em_ptr->r_ptr->flagsr, RFR_RES_ALL) && (em_ptr->effect_type == GF_ARROW))
+    bool ignore_res_all = (em_ptr->attribute == AttributeType::DEBUG);
+    ignore_res_all |= (em_ptr->attribute == AttributeType::MONSTER_MELEE);
+    ignore_res_all |= (em_ptr->attribute == AttributeType::MONSTER_SHOOT);
+
+    if (em_ptr->r_ptr->resistance_flags.has(MonsterResistanceType::RESIST_ALL) && ignore_res_all) {
         return switch_effects_monster(player_ptr, em_ptr);
+    }
 
     em_ptr->note = _("には完全な耐性がある!", " is immune.");
     em_ptr->dam = 0;
-    if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr))
-        em_ptr->r_ptr->r_flagsr |= (RFR_RES_ALL);
+    if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
+        em_ptr->r_ptr->r_resistance_flags.set(MonsterResistanceType::RESIST_ALL);
+    }
 
-    if (em_ptr->effect_type == GF_LITE_WEAK || em_ptr->effect_type == GF_KILL_WALL)
+    if (em_ptr->attribute == AttributeType::LITE_WEAK || em_ptr->attribute == AttributeType::KILL_WALL) {
         em_ptr->skipped = true;
+    }
 
-    return PROCESS_CONTINUE;
+    return ProcessResult::PROCESS_CONTINUE;
 }
 
 /*!
  * @brief ペットの死亡を処理する
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void effect_damage_killed_pet(player_type *player_ptr, effect_monster_type *em_ptr)
+static void effect_damage_killed_pet(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    bool sad = is_pet(em_ptr->m_ptr) && !(em_ptr->m_ptr->ml);
+    bool sad = em_ptr->m_ptr->is_pet() && !(em_ptr->m_ptr->ml);
     if (em_ptr->known && em_ptr->note) {
-        monster_desc(player_ptr, em_ptr->m_name, em_ptr->m_ptr, MD_TRUE_NAME);
-        if (em_ptr->see_s_msg)
-            msg_format("%^s%s", em_ptr->m_name, em_ptr->note);
-        else
+        angband_strcpy(em_ptr->m_name, monster_desc(player_ptr, em_ptr->m_ptr, MD_TRUE_NAME).data(), sizeof(em_ptr->m_name));
+        if (em_ptr->see_s_msg) {
+            msg_format("%s^%s", em_ptr->m_name, em_ptr->note);
+        } else {
             player_ptr->current_floor_ptr->monster_noise = true;
+        }
     }
 
-    if (em_ptr->who > 0)
+    if (em_ptr->who > 0) {
         monster_gain_exp(player_ptr, em_ptr->who, em_ptr->m_ptr->r_idx);
+    }
 
-    monster_death(player_ptr, em_ptr->g_ptr->m_idx, false);
+    monster_death(player_ptr, em_ptr->g_ptr->m_idx, false, em_ptr->attribute);
     delete_monster_idx(player_ptr, em_ptr->g_ptr->m_idx);
-    if (sad)
+    if (sad) {
         msg_print(_("少し悲しい気分がした。", "You feel sad for a moment."));
+    }
 }
 
 /*!
  * @brief モンスターの睡眠を処理する
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void effect_damage_makes_sleep(player_type *player_ptr, effect_monster_type *em_ptr)
+static void effect_damage_makes_sleep(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (em_ptr->note && em_ptr->seen_msg)
-        msg_format("%^s%s", em_ptr->m_name, em_ptr->note);
-    else if (em_ptr->see_s_msg)
-        message_pain(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam);
-    else
+    if (em_ptr->note && em_ptr->seen_msg) {
+        msg_format("%s^%s", em_ptr->m_name, em_ptr->note);
+    } else if (em_ptr->see_s_msg) {
+        const auto pain_message = MonsterPainDescriber(player_ptr, em_ptr->g_ptr->m_idx).describe(em_ptr->dam);
+        if (!pain_message.empty()) {
+            msg_print(pain_message);
+        }
+    } else {
         player_ptr->current_floor_ptr->monster_noise = true;
+    }
 
-    if (em_ptr->do_sleep)
+    if (em_ptr->do_sleep) {
         (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep);
+    }
 }
 
 /*!
@@ -193,44 +233,49 @@ static void effect_damage_makes_sleep(player_type *player_ptr, effect_monster_ty
  * @details
  * モンスターIDがプレイヤー(0)の場合は処理しない。
  */
-static bool deal_effect_damage_from_monster(player_type *player_ptr, effect_monster_type *em_ptr)
+static bool deal_effect_damage_from_monster(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (em_ptr->who <= 0)
+    if (em_ptr->who <= 0) {
         return false;
+    }
 
-    if (player_ptr->health_who == em_ptr->g_ptr->m_idx)
+    if (player_ptr->health_who == em_ptr->g_ptr->m_idx) {
         player_ptr->redraw |= (PR_HEALTH);
-    if (player_ptr->riding == em_ptr->g_ptr->m_idx)
+    }
+    if (player_ptr->riding == em_ptr->g_ptr->m_idx) {
         player_ptr->redraw |= (PR_UHEALTH);
+    }
 
     (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, 0);
     em_ptr->m_ptr->hp -= em_ptr->dam;
-    if (em_ptr->m_ptr->hp < 0)
+    if (em_ptr->m_ptr->hp < 0) {
         effect_damage_killed_pet(player_ptr, em_ptr);
-    else
+    } else {
         effect_damage_makes_sleep(player_ptr, em_ptr);
+    }
 
     return true;
 }
 
 /*!
  * @brief 不潔な病人の治療処理
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @return 大賞モンスターが不潔な病人だった場合はTRUE、それ以外はFALSE
  */
-static bool heal_leaper(player_type *player_ptr, effect_monster_type *em_ptr)
+static bool heal_leaper(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (!em_ptr->heal_leper)
+    if (!em_ptr->heal_leper) {
         return false;
+    }
 
-    if (em_ptr->seen_msg)
+    if (em_ptr->seen_msg) {
         msg_print(_("不潔な病人は病気が治った!", "The Mangy looking leper is healed!"));
+    }
 
-    if (record_named_pet && is_pet(em_ptr->m_ptr) && em_ptr->m_ptr->nickname) {
-        char m2_name[MAX_NLEN];
-        monster_desc(player_ptr, m2_name, em_ptr->m_ptr, MD_INDEF_VISIBLE);
-        exe_write_diary(player_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_HEAL_LEPER, m2_name);
+    if (record_named_pet && em_ptr->m_ptr->is_named_pet()) {
+        const auto m2_name = monster_desc(player_ptr, em_ptr->m_ptr, MD_INDEF_VISIBLE);
+        exe_write_diary(player_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_HEAL_LEPER, m2_name.data());
     }
 
     delete_monster_idx(player_ptr, em_ptr->g_ptr->m_idx);
@@ -239,33 +284,40 @@ static bool heal_leaper(player_type *player_ptr, effect_monster_type *em_ptr)
 
 /*!
  * @brief プレイヤー起因の効果によるダメージを処理 / Deal damages from player and fear by them.
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @return モンスターが死んだらTRUE、生きていたらFALSE
  * @details
  * em_ptr->do_fearによる恐怖メッセージもここで表示。
  */
-static bool deal_effect_damage_from_player(player_type *player_ptr, effect_monster_type *em_ptr)
+static bool deal_effect_damage_from_player(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
     bool fear = false;
-    MonsterDamageProcessor mdp(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, &fear);
-    if (mdp.mon_take_hit(em_ptr->note_dies))
+    MonsterDamageProcessor mdp(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, &fear, em_ptr->attribute);
+    if (mdp.mon_take_hit(em_ptr->note_dies)) {
         return true;
+    }
 
-    if (em_ptr->do_sleep)
+    if (em_ptr->do_sleep) {
         anger_monster(player_ptr, em_ptr->m_ptr);
+    }
 
-    if (em_ptr->note && em_ptr->seen)
-        msg_format(_("%s%s", "%^s%s"), em_ptr->m_name, em_ptr->note);
-    else if (em_ptr->known && (em_ptr->dam || !em_ptr->do_fear))
-        message_pain(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam);
+    if (em_ptr->note && em_ptr->seen) {
+        msg_format(_("%s%s", "%s^%s"), em_ptr->m_name, em_ptr->note);
+    } else if (em_ptr->known && (em_ptr->dam || !em_ptr->do_fear)) {
+        const auto pain_message = MonsterPainDescriber(player_ptr, em_ptr->g_ptr->m_idx).describe(em_ptr->dam);
+        if (!pain_message.empty()) {
+            msg_print(pain_message);
+        }
+    }
 
-    if (((em_ptr->dam > 0) || em_ptr->get_angry) && !em_ptr->do_sleep)
+    if (((em_ptr->dam > 0) || em_ptr->get_angry) && !em_ptr->do_sleep) {
         anger_monster(player_ptr, em_ptr->m_ptr);
+    }
 
     if ((fear || em_ptr->do_fear) && em_ptr->seen) {
         sound(SOUND_FLEE);
-        msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), em_ptr->m_name);
+        msg_format(_("%s^は恐怖して逃げ出した!", "%s^ flees in terror!"), em_ptr->m_name);
     }
 
     return false;
@@ -273,7 +325,7 @@ static bool deal_effect_damage_from_player(player_type *player_ptr, effect_monst
 
 /*!
  * @brief モンスターに効果のダメージを与える / Deal effect damage to monster.
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @details
  * 以下のいずれかの処理を行う。
@@ -282,74 +334,85 @@ static bool deal_effect_damage_from_player(player_type *player_ptr, effect_monst
  * 3.プレイヤーによる効果ダメージの処理
  * 4.睡眠する処理
  */
-static void deal_effect_damage_to_monster(player_type *player_ptr, effect_monster_type *em_ptr)
+static void deal_effect_damage_to_monster(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (em_ptr->effect_type == GF_DRAIN_MANA)
+    if (em_ptr->attribute == AttributeType::DRAIN_MANA) {
         return;
+    }
 
     // モンスターによる効果
-    if (deal_effect_damage_from_monster(player_ptr, em_ptr))
+    if (deal_effect_damage_from_monster(player_ptr, em_ptr)) {
         return;
+    }
 
-    //プレイヤーによる効果
-    if (heal_leaper(player_ptr, em_ptr))
+    // プレイヤーによる効果
+    if (heal_leaper(player_ptr, em_ptr)) {
         return;
-    if (deal_effect_damage_from_player(player_ptr, em_ptr))
+    }
+    if (deal_effect_damage_from_player(player_ptr, em_ptr)) {
         return;
+    }
 
-    if (em_ptr->do_sleep)
+    if (em_ptr->do_sleep) {
         (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_sleep);
+    }
 }
 
 /*!
  * @brief プレイヤーが眠っている敵に効果を及ぼした場合の徳の変化
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void effect_makes_change_virtues(player_type *player_ptr, effect_monster_type *em_ptr)
+static void effect_makes_change_virtues(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if ((em_ptr->who > 0) || !em_ptr->slept)
+    if ((em_ptr->who > 0) || !em_ptr->slept) {
         return;
+    }
 
-    if (!(em_ptr->r_ptr->flags3 & RF3_EVIL) || one_in_(5))
-        chg_virtue(player_ptr, V_COMPASSION, -1);
-    if (!(em_ptr->r_ptr->flags3 & RF3_EVIL) || one_in_(5))
-        chg_virtue(player_ptr, V_HONOUR, -1);
+    if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL) || one_in_(5)) {
+        chg_virtue(player_ptr, Virtue::COMPASSION, -1);
+    }
+    if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL) || one_in_(5)) {
+        chg_virtue(player_ptr, Virtue::HONOUR, -1);
+    }
 }
 
 /*!
  * @brief 魔法効果に対する強制処理(変身の強制解除、死なない処理)
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void affected_monster_prevents_bad_status(player_type *player_ptr, effect_monster_type *em_ptr)
+static void affected_monster_prevents_bad_status(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) || (em_ptr->r_ptr->flags1 & RF1_QUESTOR) || (player_ptr->riding && (em_ptr->g_ptr->m_idx == player_ptr->riding)))
+    if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR) || (player_ptr->riding && (em_ptr->g_ptr->m_idx == player_ptr->riding))) {
         em_ptr->do_polymorph = false;
+    }
 
-    if (((em_ptr->r_ptr->flags1 & (RF1_UNIQUE | RF1_QUESTOR)) || (em_ptr->r_ptr->flags7 & RF7_NAZGUL)) && !player_ptr->phase_out && (em_ptr->who > 0)
-        && (em_ptr->dam > em_ptr->m_ptr->hp))
+    if ((em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR) || (em_ptr->r_ptr->population_flags.has(MonsterPopulationType::NAZGUL))) && !player_ptr->phase_out && (em_ptr->who > 0) && (em_ptr->dam > em_ptr->m_ptr->hp)) {
         em_ptr->dam = em_ptr->m_ptr->hp;
+    }
 }
 
 /*!
  * @brief モンスターの朦朧値を蓄積させる
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @param stun_damage 朦朧値
  */
-static void effect_damage_piles_stun(player_type *player_ptr, effect_monster_type *em_ptr)
+static void effect_damage_piles_stun(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if ((em_ptr->do_stun == 0) || (em_ptr->r_ptr->flagsr & (RFR_RES_SOUN | RFR_RES_WALL)) || (em_ptr->r_ptr->flags3 & RF3_NO_STUN))
+    if ((em_ptr->do_stun == 0) || em_ptr->r_ptr->resistance_flags.has_any_of({ MonsterResistanceType::RESIST_SOUND, MonsterResistanceType::RESIST_FORCE }) || (em_ptr->r_ptr->flags3 & RF3_NO_STUN)) {
         return;
+    }
 
-    if (em_ptr->seen)
+    if (em_ptr->seen) {
         em_ptr->obvious = true;
+    }
 
     int turns = 0;
-    if (monster_stunned_remaining(em_ptr->m_ptr)) {
+    if (em_ptr->m_ptr->get_remaining_stun()) {
         em_ptr->note = _("はひどくもうろうとした。", " is more dazed.");
-        turns = monster_stunned_remaining(em_ptr->m_ptr) + (em_ptr->do_stun / 2);
+        turns = em_ptr->m_ptr->get_remaining_stun() + (em_ptr->do_stun / 2);
     } else {
         em_ptr->note = _("はもうろうとした。", " is dazed.");
         turns = em_ptr->do_stun;
@@ -361,22 +424,24 @@ static void effect_damage_piles_stun(player_type *player_ptr, effect_monster_typ
 
 /*!
  * @brief モンスターの混乱値を蓄積させる
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @param stun_damage 混乱値
  */
-static void effect_damage_piles_confusion(player_type *player_ptr, effect_monster_type *em_ptr)
+static void effect_damage_piles_confusion(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if ((em_ptr->do_conf == 0) || (em_ptr->r_ptr->flags3 & RF3_NO_CONF) || (em_ptr->r_ptr->flagsr & RFR_EFF_RES_CHAO_MASK))
+    if ((em_ptr->do_conf == 0) || (em_ptr->r_ptr->flags3 & RF3_NO_CONF) || em_ptr->r_ptr->resistance_flags.has_any_of(RFR_EFF_RESIST_CHAOS_MASK)) {
         return;
+    }
 
-    if (em_ptr->seen)
+    if (em_ptr->seen) {
         em_ptr->obvious = true;
+    }
 
     int turns = 0;
-    if (monster_confused_remaining(em_ptr->m_ptr)) {
+    if (em_ptr->m_ptr->is_confused()) {
         em_ptr->note = _("はさらに混乱したようだ。", " looks more confused.");
-        turns = monster_confused_remaining(em_ptr->m_ptr) + (em_ptr->do_conf / 2);
+        turns = em_ptr->m_ptr->get_remaining_confusion() + (em_ptr->do_conf / 2);
     } else {
         em_ptr->note = _("は混乱したようだ。", " looks confused.");
         turns = em_ptr->do_conf;
@@ -388,18 +453,19 @@ static void effect_damage_piles_confusion(player_type *player_ptr, effect_monste
 
 /*!
  * @brief モンスターの恐怖値を蓄積させる
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @param stun_damage 恐怖値
  * @details
  * 打撃ダメージによる恐怖もあるため、メッセージは後で表示。
  */
-static void effect_damage_piles_fear(player_type *player_ptr, effect_monster_type *em_ptr)
+static void effect_damage_piles_fear(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (em_ptr->do_fear == 0 || any_bits(em_ptr->r_ptr->flags3, RF3_NO_FEAR))
+    if (em_ptr->do_fear == 0 || any_bits(em_ptr->r_ptr->flags3, RF3_NO_FEAR)) {
         return;
+    }
 
-    (void)set_monster_monfear(player_ptr, em_ptr->g_ptr->m_idx, monster_fear_remaining(em_ptr->m_ptr) + em_ptr->do_fear);
+    (void)set_monster_monfear(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->m_ptr->get_remaining_fear() + em_ptr->do_fear);
     em_ptr->get_angry = true;
 }
 
@@ -409,20 +475,24 @@ static void effect_damage_piles_fear(player_type *player_ptr, effect_monster_typ
  */
 static void effect_damage_makes_weak(effect_monster_type *em_ptr)
 {
-    if (em_ptr->do_time == 0)
+    if (em_ptr->do_time == 0) {
         return;
+    }
 
-    if (em_ptr->seen)
+    if (em_ptr->seen) {
         em_ptr->obvious = true;
+    }
 
-    if (em_ptr->do_time >= em_ptr->m_ptr->maxhp)
+    if (em_ptr->do_time >= em_ptr->m_ptr->maxhp) {
         em_ptr->do_time = em_ptr->m_ptr->maxhp - 1;
+    }
 
     if (em_ptr->do_time) {
         em_ptr->note = _("は弱くなったようだ。", " seems weakened.");
         em_ptr->m_ptr->maxhp -= em_ptr->do_time;
-        if ((em_ptr->m_ptr->hp - em_ptr->dam) > em_ptr->m_ptr->maxhp)
+        if ((em_ptr->m_ptr->hp - em_ptr->dam) > em_ptr->m_ptr->maxhp) {
             em_ptr->dam = em_ptr->m_ptr->hp - em_ptr->m_ptr->maxhp;
+        }
     }
 
     em_ptr->get_angry = true;
@@ -430,45 +500,50 @@ static void effect_damage_makes_weak(effect_monster_type *em_ptr)
 
 /*!
  * @brief モンスターを変身させる
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void effect_damage_makes_polymorph(player_type *player_ptr, effect_monster_type *em_ptr)
+static void effect_damage_makes_polymorph(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (!em_ptr->do_polymorph || (randint1(90) <= em_ptr->r_ptr->level))
+    if (!em_ptr->do_polymorph || (randint1(90) <= em_ptr->r_ptr->level)) {
         return;
+    }
 
     if (polymorph_monster(player_ptr, em_ptr->y, em_ptr->x)) {
-        if (em_ptr->seen)
+        if (em_ptr->seen) {
             em_ptr->obvious = true;
+        }
 
         em_ptr->note = _("が変身した!", " changes!");
         em_ptr->dam = 0;
     }
 
     em_ptr->m_ptr = &player_ptr->current_floor_ptr->m_list[em_ptr->g_ptr->m_idx];
-    em_ptr->r_ptr = &r_info[em_ptr->m_ptr->r_idx];
+    em_ptr->r_ptr = &monraces_info[em_ptr->m_ptr->r_idx];
 }
 
 /*!
  * @brief モンスターをテレポートさせる
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void effect_damage_makes_teleport(player_type *player_ptr, effect_monster_type *em_ptr)
+static void effect_damage_makes_teleport(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (em_ptr->do_dist == 0)
+    if (em_ptr->do_dist == 0) {
         return;
+    }
 
-    if (em_ptr->seen)
+    if (em_ptr->seen) {
         em_ptr->obvious = true;
+    }
 
     em_ptr->note = _("が消え去った!", " disappears!");
 
-    if (!em_ptr->who)
-        chg_virtue(player_ptr, V_VALOUR, -1);
+    if (!em_ptr->who) {
+        chg_virtue(player_ptr, Virtue::VALOUR, -1);
+    }
 
-    teleport_flags tflag = static_cast<teleport_flags>((!em_ptr->who ? TELEPORT_DEC_VALOUR : TELEPORT_SPONTANEOUS) | TELEPORT_PASSIVE);
+    teleport_flags tflag = i2enum<teleport_flags>((!em_ptr->who ? TELEPORT_DEC_VALOUR : TELEPORT_SPONTANEOUS) | TELEPORT_PASSIVE);
     teleport_away(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->do_dist, tflag);
 
     em_ptr->y = em_ptr->m_ptr->fy;
@@ -478,7 +553,7 @@ static void effect_damage_makes_teleport(player_type *player_ptr, effect_monster
 
 /*!
  * @brief モンスターへのダメージに応じたメッセージを表示させ、異常状態を与える
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @details
  * 以下の判定と処理を行う。
@@ -486,16 +561,17 @@ static void effect_damage_makes_teleport(player_type *player_ptr, effect_monster
  * 2.ダメージ量が現HPを上回る場合
  * 3.通常時(デバフをかける)
  */
-static void effect_damage_gives_bad_status(player_type *player_ptr, effect_monster_type *em_ptr)
+static void effect_damage_gives_bad_status(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
     int tmp_damage = em_ptr->dam;
-    em_ptr->dam = mon_damage_mod(player_ptr, em_ptr->m_ptr, em_ptr->dam, (bool)(em_ptr->effect_type == GF_PSY_SPEAR));
-    if ((tmp_damage > 0) && (em_ptr->dam == 0) && em_ptr->seen)
+    em_ptr->dam = mon_damage_mod(player_ptr, em_ptr->m_ptr, em_ptr->dam, (bool)(em_ptr->attribute == AttributeType::PSY_SPEAR));
+    if ((tmp_damage > 0) && (em_ptr->dam == 0) && em_ptr->seen) {
         em_ptr->note = _("はダメージを受けていない。", " is unharmed.");
+    }
 
-    if (em_ptr->dam > em_ptr->m_ptr->hp)
+    if (em_ptr->dam > em_ptr->m_ptr->hp) {
         em_ptr->note = em_ptr->note_dies;
-    else {
+    else {
         effect_damage_piles_stun(player_ptr, em_ptr);
         effect_damage_piles_confusion(player_ptr, em_ptr);
         effect_damage_piles_fear(player_ptr, em_ptr);
@@ -507,7 +583,7 @@ static void effect_damage_gives_bad_status(player_type *player_ptr, effect_monst
 
 /*!
  * @brief 効果によるモンスターへのダメージと付随効果を処理する
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @details
  * 以下の処理を行う。
@@ -517,25 +593,27 @@ static void effect_damage_gives_bad_status(player_type *player_ptr, effect_monst
  * 4.ダメージ処理及び恐怖メッセージ
  * 5.悪魔領域血の呪いによる事後処理
  */
-static void exe_affect_monster_by_damage(player_type *player_ptr, effect_monster_type *em_ptr)
+static void exe_affect_monster_by_damage(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
     effect_makes_change_virtues(player_ptr, em_ptr);
     affected_monster_prevents_bad_status(player_ptr, em_ptr);
     effect_damage_gives_bad_status(player_ptr, em_ptr);
     deal_effect_damage_to_monster(player_ptr, em_ptr);
-    if ((em_ptr->effect_type == GF_BLOOD_CURSE) && one_in_(4))
+    if ((em_ptr->attribute == AttributeType::BLOOD_CURSE) && one_in_(4)) {
         blood_curse_to_enemy(player_ptr, em_ptr->who);
+    }
 }
 
 /*!
  * @brief モンスター闘技場にいる場合の画面更新処理
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void update_phase_out_stat(player_type *player_ptr, effect_monster_type *em_ptr)
+static void update_phase_out_stat(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (!player_ptr->phase_out)
+    if (!player_ptr->phase_out) {
         return;
+    }
 
     player_ptr->health_who = em_ptr->g_ptr->m_idx;
     player_ptr->redraw |= (PR_HEALTH);
@@ -544,56 +622,64 @@ static void update_phase_out_stat(player_type *player_ptr, effect_monster_type *
 
 /*!
  * @brief 魔法効果がペットに及んだ時の処理
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void postprocess_by_effected_pet(player_type *player_ptr, effect_monster_type *em_ptr)
+static void postprocess_by_effected_pet(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if ((em_ptr->dam <= 0) || is_pet(em_ptr->m_ptr) || is_friendly(em_ptr->m_ptr))
+    auto *m_ptr = em_ptr->m_ptr;
+    if ((em_ptr->dam <= 0) || m_ptr->is_pet() || m_ptr->is_friendly()) {
         return;
+    }
 
     if (em_ptr->who == 0) {
-        if (!(em_ptr->flag & PROJECT_NO_HANGEKI))
-            set_target(em_ptr->m_ptr, monster_target_y, monster_target_x);
+        if (!(em_ptr->flag & PROJECT_NO_HANGEKI)) {
+            set_target(m_ptr, monster_target_y, monster_target_x);
+        }
 
         return;
     }
 
-    if ((em_ptr->who > 0) && is_pet(em_ptr->m_caster_ptr) && !player_bold(player_ptr, em_ptr->m_ptr->target_y, em_ptr->m_ptr->target_x))
-        set_target(em_ptr->m_ptr, em_ptr->m_caster_ptr->fy, em_ptr->m_caster_ptr->fx);
+    const auto &m_caster_ref = *em_ptr->m_caster_ptr;
+    if ((em_ptr->who > 0) && m_caster_ref.is_pet() && !player_bold(player_ptr, m_ptr->target_y, m_ptr->target_x)) {
+        set_target(m_ptr, m_caster_ref.fy, m_caster_ref.fx);
+    }
 }
 
 /*!
  * @brief 魔法効果が騎乗モンスターに及んだ時の処理
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void postprocess_by_riding_pet_effected(player_type *player_ptr, effect_monster_type *em_ptr)
+static void postprocess_by_riding_pet_effected(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (!player_ptr->riding || (player_ptr->riding != em_ptr->g_ptr->m_idx) || (em_ptr->dam <= 0))
+    if (!player_ptr->riding || (player_ptr->riding != em_ptr->g_ptr->m_idx) || (em_ptr->dam <= 0)) {
         return;
+    }
 
-    if (em_ptr->m_ptr->hp > (em_ptr->m_ptr->maxhp / 3))
+    if (em_ptr->m_ptr->hp > (em_ptr->m_ptr->maxhp / 3)) {
         em_ptr->dam = (em_ptr->dam + 1) / 2;
+    }
 
     rakubadam_m = (em_ptr->dam > 200) ? 200 : em_ptr->dam;
 }
 
 /*!
  * @brief 写真を撮った時の処理
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  * @details 写真のフラッシュは弱閃光属性
  */
-static void postprocess_by_taking_photo(player_type *player_ptr, effect_monster_type *em_ptr)
+static void postprocess_by_taking_photo(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
-    if (em_ptr->photo == 0)
+    if (em_ptr->photo == 0) {
         return;
+    }
 
-    object_type *q_ptr;
-    object_type forge;
+    ItemEntity *q_ptr;
+    ItemEntity forge;
     q_ptr = &forge;
-    q_ptr->prep(lookup_kind(TV_STATUE, SV_PHOTO));
+    q_ptr->prep(lookup_baseitem_id({ ItemKindType::STATUE, SV_PHOTO }));
     q_ptr->pval = em_ptr->photo;
     q_ptr->ident |= (IDENT_FULL_KNOWN);
     (void)drop_near(player_ptr, q_ptr, -1, player_ptr->y, player_ptr->x);
@@ -601,10 +687,10 @@ static void postprocess_by_taking_photo(player_type *player_ptr, effect_monster_
 
 /*!
  * @brief モンスター効果の後処理 (ペット関係、記念撮影、グローバル変数更新)
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param em_ptr モンスター効果構造体への参照ポインタ
  */
-static void exe_affect_monster_postprocess(player_type *player_ptr, effect_monster_type *em_ptr)
+static void exe_affect_monster_postprocess(PlayerType *player_ptr, effect_monster_type *em_ptr)
 {
     postprocess_by_effected_pet(player_ptr, em_ptr);
     postprocess_by_riding_pet_effected(player_ptr, em_ptr);
@@ -616,13 +702,13 @@ static void exe_affect_monster_postprocess(player_type *player_ptr, effect_monst
 
 /*!
  * @brief 汎用的なビーム/ボルト/ボール系によるモンスターへの効果処理 / Handle a beam/bolt/ball causing damage to a monster.
- * @param player_ptr ã\83\97ã\83¬ã\83¼ヤーへの参照ポインタ
+ * @param player_ptr ã\83\97ã\83¬ã\82¤ヤーへの参照ポインタ
  * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player")
  * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
  * @param y 目標y座標 / Target y location (or location to travel "towards")
  * @param x 目標x座標 / Target x location (or location to travel "towards")
  * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player)
- * @param effect_type 効果属性 / Type of damage to apply to monsters (and objects)
+ * @param attribute 効果属性 / Type of damage to apply to monsters (and objects)
  * @param flag 効果フラグ
  * @param see_s_msg TRUEならばメッセージを表示する
  * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE
@@ -633,32 +719,38 @@ static void exe_affect_monster_postprocess(player_type *player_ptr, effect_monst
  * 3.ペット及び撮影による事後効果
  */
 bool affect_monster(
-    player_type *player_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID effect_type, BIT_FLAGS flag, bool see_s_msg)
+    PlayerType *player_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, int dam, AttributeType attribute, BIT_FLAGS flag, bool see_s_msg, std::optional<CapturedMonsterType *> cap_mon_ptr)
 {
     effect_monster_type tmp_effect;
-    effect_monster_type *em_ptr = initialize_effect_monster(player_ptr, &tmp_effect, who, r, y, x, dam, effect_type, flag, see_s_msg);
+    effect_monster_type *em_ptr = initialize_effect_monster(player_ptr, &tmp_effect, who, r, y, x, dam, attribute, flag, see_s_msg);
 
     make_description_of_affecred_monster(player_ptr, em_ptr);
 
-    if (player_ptr->riding && (em_ptr->g_ptr->m_idx == player_ptr->riding))
+    if (player_ptr->riding && (em_ptr->g_ptr->m_idx == player_ptr->riding)) {
         disturb(player_ptr, true, true);
+    }
 
-    process_result result = exe_affect_monster_by_effect(player_ptr, em_ptr);
-    if (result != PROCESS_CONTINUE)
-        return (bool)result;
+    ProcessResult result = exe_affect_monster_by_effect(player_ptr, em_ptr, cap_mon_ptr);
+    if (result != ProcessResult::PROCESS_CONTINUE) {
+        return result == ProcessResult::PROCESS_TRUE;
+    }
 
-    if (em_ptr->skipped)
+    if (em_ptr->skipped) {
         return false;
+    }
 
     exe_affect_monster_by_damage(player_ptr, em_ptr);
 
     update_phase_out_stat(player_ptr, em_ptr);
-    if (em_ptr->m_ptr->r_idx)
+    const auto monster_is_valid = MonsterRace(em_ptr->m_ptr->r_idx).is_valid();
+    if (monster_is_valid) {
         update_monster(player_ptr, em_ptr->g_ptr->m_idx, false);
+    }
 
     lite_spot(player_ptr, em_ptr->y, em_ptr->x);
-    if ((player_ptr->monster_race_idx == em_ptr->m_ptr->r_idx) && (em_ptr->seen || !em_ptr->m_ptr->r_idx))
-        player_ptr->window_flags |= (PW_MONSTER);
+    if ((player_ptr->monster_race_idx == em_ptr->m_ptr->r_idx) && (em_ptr->seen || !monster_is_valid)) {
+        player_ptr->window_flags |= (PW_MONSTER_LORE);
+    }
 
     exe_affect_monster_postprocess(player_ptr, em_ptr);
     return em_ptr->obvious;