OSDN Git Service

[Refactor] #2204 HIT_POINTエイリアスをintに揃えた
[hengbandforosx/hengbandosx.git] / src / monster / monster-damage.cpp
index e4849b5..a77763e 100644 (file)
@@ -4,11 +4,12 @@
  * @author Hourier
  */
 
-#include "monster/monster-damage.h"
+#include <algorithm>
+
+#include "avatar/avatar-changer.h"
 #include "core/player-redraw-types.h"
 #include "core/speed-table.h"
 #include "core/stuff-handler.h"
-#include "dungeon/dungeon.h"
 #include "game-option/birth-options.h"
 #include "game-option/play-record-options.h"
 #include "io/files-util.h"
 #include "monster-floor/place-monster-types.h"
 #include "monster-race/monster-race-hook.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-ability-mask.h"
 #include "monster-race/race-flags1.h"
 #include "monster-race/race-flags2.h"
 #include "monster-race/race-flags3.h"
 #include "monster-race/race-flags7.h"
 #include "monster-race/race-flags8.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-status-setter.h"
 #include "monster/monster-status.h"
 #include "object-enchant/object-curse.h"
-#include "player-info/avatar.h"
 #include "player/player-status.h"
 #include "player/special-defense-types.h"
 #include "spell-kind/spells-random.h"
 #include "util/bit-flags-calculator.h"
 #include "view/display-messages.h"
 #include "world/world.h"
-#include <algorithm>
 
 /*
  * @brief コンストラクタ
- * @param target_ptr プレーヤーへの参照ポインタ
+ * @param player_ptr プレイヤーへの参照ポインタ
  * @param m_idx ダメージを与えたモンスターのID
  * @param dam 与えたダメージ量
  * @param fear ダメージによってモンスターが恐慌状態に陥ったならばtrue
+ * @param attribute 与えたダメージの種類 (単一属性)
  * @param note モンスターが倒された際の特別なメッセージ述語
  */
-MonsterDamageProcessor::MonsterDamageProcessor(player_type *target_ptr, MONSTER_IDX m_idx, HIT_POINT dam, bool *fear)
-    : target_ptr(target_ptr)
+MonsterDamageProcessor::MonsterDamageProcessor(PlayerType *player_ptr, MONSTER_IDX m_idx, int dam, bool *fear, AttributeType attribute)
+    : player_ptr(player_ptr)
     , m_idx(m_idx)
     , dam(dam)
     , fear(fear)
 {
+    this->attribute_flags.clear();
+    this->attribute_flags.set((AttributeType)attribute);
+}
+
+/*
+ * @brief コンストラクタ
+ * @param player_ptr プレイヤーへの参照ポインタ
+ * @param m_idx ダメージを与えたモンスターのID
+ * @param dam 与えたダメージ量
+ * @param fear ダメージによってモンスターが恐慌状態に陥ったならばtrue
+ * @param attribute_flags 与えたダメージの種類 (複数属性)
+ * @param note モンスターが倒された際の特別なメッセージ述語
+ */
+MonsterDamageProcessor::MonsterDamageProcessor(PlayerType *player_ptr, MONSTER_IDX m_idx, int dam, bool *fear, AttributeFlags attribute_flags)
+    : player_ptr(player_ptr)
+    , m_idx(m_idx)
+    , dam(dam)
+    , fear(fear)
+    , attribute_flags(attribute_flags)
+{
 }
 
 /*!
@@ -71,12 +91,8 @@ MonsterDamageProcessor::MonsterDamageProcessor(player_type *target_ptr, MONSTER_
  */
 bool MonsterDamageProcessor::mon_take_hit(concptr note)
 {
-    auto *m_ptr = &this->target_ptr->current_floor_ptr->m_list[this->m_idx];
-    auto innocent = true;
-    auto thief = false;
-
-    monster_type exp_mon;
-    (void)COPY(&exp_mon, m_ptr, monster_type);
+    auto *m_ptr = &this->player_ptr->current_floor_ptr->m_list[this->m_idx];
+    auto exp_mon = *m_ptr;
 
     auto exp_dam = (m_ptr->hp > this->dam) ? this->dam : m_ptr->hp;
 
@@ -91,215 +107,75 @@ bool MonsterDamageProcessor::mon_take_hit(concptr note)
         m_ptr->dealt_damage = m_ptr->max_maxhp * 100;
     }
 
-    if (current_world_ptr->wizard) {
+    if (w_ptr->wizard) {
         msg_format(_("合計%d/%dのダメージを与えた。", "You do %d (out of %d) damage."), m_ptr->dealt_damage, m_ptr->maxhp);
     }
 
-    auto *r_ptr = &r_info[m_ptr->r_idx];
-    if (m_ptr->hp < 0) {
-        this->death_special_flag_monster();
-        if (r_ptr->r_akills < MAX_SHORT) {
-            r_ptr->r_akills++;
-        }
-
-        this->increase_kill_numbers();
-        GAME_TEXT m_name[MAX_NLEN];
-        monster_desc(this->target_ptr, m_name, m_ptr, MD_TRUE_NAME);
-        this->death_amberites(m_name);
-        this->dying_scream(m_name);
-        this->change_virtue_non_beginner();
-        if (r_ptr->flags1 & RF1_UNIQUE) {
-            if (r_ptr->flags3 & (RF3_EVIL | RF3_GOOD))
-                chg_virtue(this->target_ptr, V_HARMONY, 2);
-
-            if (r_ptr->flags3 & RF3_GOOD) {
-                chg_virtue(this->target_ptr, V_UNLIFE, 2);
-                chg_virtue(this->target_ptr, V_VITALITY, -2);
-            }
-
-            if (one_in_(3))
-                chg_virtue(this->target_ptr, V_INDIVIDUALISM, -1);
-        }
-
-        if (m_ptr->r_idx == MON_BEGGAR || m_ptr->r_idx == MON_LEPER) {
-            chg_virtue(this->target_ptr, V_COMPASSION, -1);
-        }
-
-        auto *floor_ptr = this->target_ptr->current_floor_ptr;
-        if ((r_ptr->flags3 & RF3_GOOD) && ((r_ptr->level) / 10 + (3 * floor_ptr->dun_level) >= randint1(100)))
-            chg_virtue(this->target_ptr, V_UNLIFE, 1);
-
-        if (any_bits(r_ptr->flags3, RF3_ANGEL)) {
-            if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
-                chg_virtue(this->target_ptr, V_FAITH, -2);
-            } else if ((r_ptr->level) / 10 + (3 * floor_ptr->dun_level) >= randint1(100)) {
-                auto change_value = any_bits(r_ptr->flags3, RF3_GOOD) ? -1 : 1;
-                chg_virtue(this->target_ptr, V_FAITH, change_value);
-            }
-        } else if (any_bits(r_ptr->flags3, RF3_DEMON)) {
-            if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
-                chg_virtue(this->target_ptr, V_FAITH, 2);
-            } else if ((r_ptr->level) / 10 + (3 * floor_ptr->dun_level) >= randint1(100)) {
-                chg_virtue(this->target_ptr, V_FAITH, 1);
-            }
-        }
-
-        if (any_bits(r_ptr->flags3, RF3_UNDEAD) && any_bits(r_ptr->flags1, RF1_UNIQUE)) {
-            chg_virtue(this->target_ptr, V_VITALITY, 2);
-        }
-
-        if (r_ptr->r_deaths > 0) {
-            if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
-                chg_virtue(this->target_ptr, V_HONOUR, 10);
-            } else if ((r_ptr->level) / 10 + (2 * this->target_ptr->current_floor_ptr->dun_level) >= randint1(100)) {
-                chg_virtue(this->target_ptr, V_HONOUR, 1);
-            }
-        }
-
-        if (any_bits(r_ptr->flags2, RF2_MULTIPLY) && (r_ptr->r_akills > 1000) && one_in_(10)) {
-            chg_virtue(this->target_ptr, V_VALOUR, -1);
-        }
-
-        for (auto i = 0; i < MAX_NUM_BLOWS; i++) {
-            if (r_ptr->blow[i].d_dice != 0) {
-                innocent = false;
-            }
-            
-            if ((r_ptr->blow[i].effect == RBE_EAT_ITEM) || (r_ptr->blow[i].effect == RBE_EAT_GOLD)) {
-                thief = true;
-            }
-        }
-
-        if (r_ptr->level > 0) {
-            innocent = false;
-        }
-
-        if (thief) {
-            if (any_bits(r_ptr->flags1, RF1_UNIQUE)) {
-                chg_virtue(this->target_ptr, V_JUSTICE, 3);
-            } else if (1 + ((r_ptr->level) / 10 + (2 * this->target_ptr->current_floor_ptr->dun_level)) >= randint1(100)) {
-                chg_virtue(this->target_ptr, V_JUSTICE, 1);
-            }
-        } else if (innocent) {
-            chg_virtue(this->target_ptr, V_JUSTICE, -1);
-        }
-
-        auto magic_ability_flags = r_ptr->ability_flags;
-        magic_ability_flags.reset(RF_ABILITY_NOMAGIC_MASK);
-        if (any_bits(r_ptr->flags3, RF3_ANIMAL) && none_bits(r_ptr->flags3, RF3_EVIL) && magic_ability_flags.none()) {
-            if (one_in_(4)) {
-                chg_virtue(this->target_ptr, V_NATURE, -1);
-            }
-        }
-
-        if (any_bits(r_ptr->flags1, RF1_UNIQUE) && record_destroy_uniq) {
-            char note_buf[160];
-            sprintf(note_buf, "%s%s", r_ptr->name.c_str(), m_ptr->mflag2.has(MFLAG2::CLONED) ? _("(クローン)", "(Clone)") : "");
-            exe_write_diary(this->target_ptr, DIARY_UNIQUE, 0, note_buf);
-        }
-
-        sound(SOUND_KILL);
-        if (note != nullptr) {
-            msg_format("%^s%s", m_name, note);
-        } else if (!m_ptr->ml) {
-#ifdef JP
-            if (is_echizen(this->target_ptr))
-                msg_format("せっかくだから%sを殺した。", m_name);
-            else
-                msg_format("%sを殺した。", m_name);
-#else
-            msg_format("You have killed %s.", m_name);
-#endif
-        } else if (!monster_living(m_ptr->r_idx)) {
-            bool explode = false;
-            for (auto i = 0; i < 4; i++) {
-                if (r_ptr->blow[i].method == RBM_EXPLODE) {
-                    explode = true;
-                }
-            }
-
-            if (explode) {
-                msg_format(_("%sは爆発して粉々になった。", "%^s explodes into tiny shreds."), m_name);
-            } else {
-#ifdef JP
-                if (is_echizen(this->target_ptr))
-                    msg_format("せっかくだから%sを倒した。", m_name);
-                else
-                    msg_format("%sを倒した。", m_name);
-#else
-                msg_format("You have destroyed %s.", m_name);
-#endif
-            }
-        } else {
-#ifdef JP
-            if (is_echizen(this->target_ptr))
-                msg_format("せっかくだから%sを葬り去った。", m_name);
-            else
-                msg_format("%sを葬り去った。", m_name);
-#else
-            msg_format("You have slain %s.", m_name);
-#endif
-        }
-
-        if (any_bits(r_ptr->flags1, RF1_UNIQUE) && m_ptr->mflag2.has_not(MFLAG2::CLONED) && !vanilla_town) {
-            for (auto i = 0; i < MAX_BOUNTY; i++) {
-                if ((current_world_ptr->bounty_r_idx[i] == m_ptr->r_idx) && m_ptr->mflag2.has_not(MFLAG2::CHAMELEON)) {
-                    msg_format(_("%sの首には賞金がかかっている。", "There is a price on %s's head."), m_name);
-                    break;
-                }
-            }
-        }
-
-        monster_death(this->target_ptr, this->m_idx, true);
-        this->summon_special_unique();
-        this->get_exp_from_mon(&exp_mon, exp_mon.max_maxhp * 2);
-        *this->fear = false;
+    if (this->process_dead_exp_virtue(note, &exp_mon)) {
         return true;
     }
 
-    if (monster_fear_remaining(m_ptr) && (this->dam > 0)) {
-        auto fear_remining = monster_fear_remaining(m_ptr) - randint1(this->dam);
-        if (set_monster_monfear(this->target_ptr, this->m_idx, fear_remining)) {
-            *this->fear = false;
-        }
-    }
-
-    // 恐怖の更なる加算.
-    if (!monster_fear_remaining(m_ptr) && none_bits(r_ptr->flags3, RF3_NO_FEAR)) {
-        int percentage = (100L * m_ptr->hp) / m_ptr->maxhp;
-        if ((randint1(10) >= percentage) || ((this->dam >= m_ptr->hp) && (randint0(100) < 80))) {
-            *this->fear = true;
-            (void)set_monster_monfear(
-                this->target_ptr, this->m_idx, (randint1(10) + (((this->dam >= m_ptr->hp) && (percentage > 7)) ? 20 : ((11 - percentage) * 5))));
-        }
-    }
-
+    this->add_monster_fear();
     return false;
 }
 
 bool MonsterDamageProcessor::genocide_chaos_patron()
 {
-    auto *m_ptr = &this->target_ptr->current_floor_ptr->m_list[this->m_idx];
+    auto *m_ptr = &this->player_ptr->current_floor_ptr->m_list[this->m_idx];
     if (!monster_is_valid(m_ptr)) {
         this->m_idx = 0;
     }
 
     this->set_redraw();
-    (void)set_monster_csleep(this->target_ptr, this->m_idx, 0);
-    if (this->target_ptr->special_defense & NINJA_S_STEALTH) {
-        set_superstealth(this->target_ptr, false);
-    }
+    (void)set_monster_csleep(this->player_ptr, this->m_idx, 0);
+    set_superstealth(this->player_ptr, false);
 
     return this->m_idx == 0;
 }
 
+bool MonsterDamageProcessor::process_dead_exp_virtue(concptr note, monster_type *exp_mon)
+{
+    auto *m_ptr = &this->player_ptr->current_floor_ptr->m_list[this->m_idx];
+    auto *r_ptr = real_r_ptr(m_ptr);
+    if (m_ptr->hp >= 0) {
+        return false;
+    }
+
+    this->death_special_flag_monster();
+    if (r_ptr->r_akills < MAX_SHORT) {
+        r_ptr->r_akills++;
+    }
+
+    this->increase_kill_numbers();
+    GAME_TEXT m_name[MAX_NLEN];
+    monster_desc(this->player_ptr, m_name, m_ptr, MD_TRUE_NAME);
+    this->death_amberites(m_name);
+    this->dying_scream(m_name);
+    AvatarChanger ac(player_ptr, m_ptr);
+    ac.change_virtue();
+    if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) && record_destroy_uniq) {
+        char note_buf[160];
+        sprintf(note_buf, "%s%s", r_ptr->name.c_str(), m_ptr->mflag2.has(MonsterConstantFlagType::CLONED) ? _("(クローン)", "(Clone)") : "");
+        exe_write_diary(this->player_ptr, DIARY_UNIQUE, 0, note_buf);
+    }
+
+    sound(SOUND_KILL);
+    this->show_kill_message(note, m_name);
+    this->show_bounty_message(m_name);
+    monster_death(this->player_ptr, this->m_idx, true, this->attribute_flags);
+    this->summon_special_unique();
+    this->get_exp_from_mon(exp_mon, exp_mon->max_maxhp * 2);
+    *this->fear = false;
+    return true;
+}
+
 /*
  * @brief たぬき、カメレオン、ナズグル、ユニークの死亡時処理
  * @param m_ptr ダメージを与えたモンスターの構造体参照ポインタ
  */
 void MonsterDamageProcessor::death_special_flag_monster()
 {
-    auto *m_ptr = &this->target_ptr->current_floor_ptr->m_list[this->m_idx];
+    auto *m_ptr = &this->player_ptr->current_floor_ptr->m_list[this->m_idx];
     auto r_idx = m_ptr->r_idx;
     auto *r_ptr = &r_info[r_idx];
     if (any_bits(r_info[r_idx].flags7, RF7_TANUKI)) {
@@ -310,14 +186,15 @@ void MonsterDamageProcessor::death_special_flag_monster()
         }
     }
 
-    if (m_ptr->mflag2.has(MFLAG2::CHAMELEON)) {
+    if (m_ptr->mflag2.has(MonsterConstantFlagType::CHAMELEON)) {
         r_ptr = real_r_ptr(m_ptr);
+        r_idx = real_r_idx(m_ptr);
         if (r_ptr->r_sights < MAX_SHORT) {
             r_ptr->r_sights++;
         }
     }
 
-    if (m_ptr->mflag2.has(MFLAG2::CLONED)) {
+    if (m_ptr->mflag2.has(MonsterConstantFlagType::CLONED)) {
         return;
     }
 
@@ -326,7 +203,7 @@ void MonsterDamageProcessor::death_special_flag_monster()
         return;
     }
 
-    if (none_bits(r_ptr->flags1, RF1_UNIQUE)) {
+    if (r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
         return;
     }
 
@@ -340,15 +217,15 @@ void MonsterDamageProcessor::death_special_flag_monster()
 void MonsterDamageProcessor::death_unique_monster(monster_race_type r_idx)
 {
     r_info[r_idx].max_num = 0;
-    std::vector<monster_race_type> combined_uniques;
-    if (!check_combined_unique(r_idx, &combined_uniques)) {
+    std::vector<monster_race_type> combined_unique_vec;
+    if (!check_combined_unique(r_idx, &combined_unique_vec)) {
         return;
     }
 
-    std::vector<std::tuple<monster_race_type, monster_race_type, monster_race_type>> uniques;
+    combined_uniques uniques;
     const int one_unit = 3;
-    for (auto i = 0U; i < combined_uniques.size(); i += one_unit) {
-        auto unique = std::make_tuple(combined_uniques[i], combined_uniques[i + 1], combined_uniques[i + 2]);
+    for (auto i = 0U; i < combined_unique_vec.size(); i += one_unit) {
+        auto unique = std::make_tuple(combined_unique_vec[i], combined_unique_vec[i + 1], combined_unique_vec[i + 2]);
         uniques.push_back(unique);
     }
 
@@ -361,13 +238,13 @@ void MonsterDamageProcessor::death_unique_monster(monster_race_type r_idx)
  * @param united_uniques 分裂/合体を行う特殊ユニーク
  * @details 合体後、合体前1、合体前2 の順にpush_backすること
  */
-bool MonsterDamageProcessor::check_combined_unique(const monster_race_type r_idx, std::vector<monster_race_type> *combined_uniques)
+bool MonsterDamageProcessor::check_combined_unique(const monster_race_type r_idx, std::vector<monster_race_type> *combined_unique_vec)
 {
-    combined_uniques->push_back(MON_BANORLUPART);
-    combined_uniques->push_back(MON_BANOR);
-    combined_uniques->push_back(MON_LUPART);
+    combined_unique_vec->push_back(MON_BANORLUPART);
+    combined_unique_vec->push_back(MON_BANOR);
+    combined_unique_vec->push_back(MON_LUPART);
 
-    for (const auto &unique : *combined_uniques) {
+    for (const auto &unique : *combined_unique_vec) {
         if (r_idx == unique) {
             return true;
         }
@@ -381,8 +258,7 @@ bool MonsterDamageProcessor::check_combined_unique(const monster_race_type r_idx
  * @param m_ptr ダメージを与えたモンスターの構造体参照ポインタ
  * @uniques 分裂/合体を行う特殊ユニークのリスト
  */
-void MonsterDamageProcessor::death_combined_uniques(
-    const monster_race_type r_idx, std::vector<std::tuple<monster_race_type, monster_race_type, monster_race_type>> *combined_uniques)
+void MonsterDamageProcessor::death_combined_uniques(const monster_race_type r_idx, combined_uniques *combined_uniques)
 {
     for (const auto &unique : *combined_uniques) {
         auto united = (monster_race_type)0;
@@ -422,32 +298,32 @@ void MonsterDamageProcessor::death_combined_uniques(
 
 void MonsterDamageProcessor::increase_kill_numbers()
 {
-    auto *m_ptr = &this->target_ptr->current_floor_ptr->m_list[this->m_idx];
-    auto *r_ptr = &r_info[m_ptr->r_idx];
-    if (((m_ptr->ml == 0) || this->target_ptr->image) && none_bits(r_ptr->flags1, RF1_UNIQUE)) {
+    auto *m_ptr = &this->player_ptr->current_floor_ptr->m_list[this->m_idx];
+    auto *r_ptr = real_r_ptr(m_ptr);
+    if (((m_ptr->ml == 0) || this->player_ptr->hallucinated) && r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
         return;
     }
 
-    if (m_ptr->mflag2.has(MFLAG2::KAGE) && (r_info[MON_KAGE].r_pkills < MAX_SHORT)) {
+    if (m_ptr->mflag2.has(MonsterConstantFlagType::KAGE) && (r_info[MON_KAGE].r_pkills < MAX_SHORT)) {
         r_info[MON_KAGE].r_pkills++;
     } else if (r_ptr->r_pkills < MAX_SHORT) {
         r_ptr->r_pkills++;
     }
 
-    if (m_ptr->mflag2.has(MFLAG2::KAGE) && (r_info[MON_KAGE].r_tkills < MAX_SHORT)) {
+    if (m_ptr->mflag2.has(MonsterConstantFlagType::KAGE) && (r_info[MON_KAGE].r_tkills < MAX_SHORT)) {
         r_info[MON_KAGE].r_tkills++;
     } else if (r_ptr->r_tkills < MAX_SHORT) {
         r_ptr->r_tkills++;
     }
 
-    monster_race_track(this->target_ptr, m_ptr->ap_r_idx);
+    monster_race_track(this->player_ptr, m_ptr->ap_r_idx);
 }
 
 void MonsterDamageProcessor::death_amberites(GAME_TEXT *m_name)
 {
-    auto *m_ptr = &this->target_ptr->current_floor_ptr->m_list[this->m_idx];
-    auto *r_ptr = &r_info[m_ptr->r_idx];
-    if (none_bits(r_ptr->flags3, RF3_AMBERITE) || one_in_(2)) {
+    auto *m_ptr = &this->player_ptr->current_floor_ptr->m_list[this->m_idx];
+    auto *r_ptr = real_r_ptr(m_ptr);
+    if (r_ptr->kind_flags.has_not(MonsterKindType::AMBERITE) || one_in_(2)) {
         return;
     }
 
@@ -455,16 +331,16 @@ void MonsterDamageProcessor::death_amberites(GAME_TEXT *m_name)
     auto stop_ty = false;
     auto count = 0;
     msg_format(_("%^sは恐ろしい血の呪いをあなたにかけた!", "%^s puts a terrible blood curse on you!"), m_name);
-    curse_equipment(this->target_ptr, 100, 50);
+    curse_equipment(this->player_ptr, 100, 50);
     do {
-        stop_ty = activate_ty_curse(this->target_ptr, stop_ty, &count);
+        stop_ty = activate_ty_curse(this->player_ptr, stop_ty, &count);
     } while (--curses);
 }
 
 void MonsterDamageProcessor::dying_scream(GAME_TEXT *m_name)
 {
-    auto *m_ptr = &this->target_ptr->current_floor_ptr->m_list[this->m_idx];
-    auto *r_ptr = &r_info[m_ptr->r_idx];
+    auto *m_ptr = &this->player_ptr->current_floor_ptr->m_list[this->m_idx];
+    auto *r_ptr = real_r_ptr(m_ptr);
     if (none_bits(r_ptr->flags2, RF2_CAN_SPEAK)) {
         return;
     }
@@ -476,34 +352,66 @@ void MonsterDamageProcessor::dying_scream(GAME_TEXT *m_name)
 
 #ifdef WORLD_SCORE
     if (m_ptr->r_idx == MON_SERPENT) {
-        screen_dump = make_screen_dump(this->target_ptr);
+        screen_dump = make_screen_dump(this->player_ptr);
     }
 #endif
 }
 
-void MonsterDamageProcessor::change_virtue_non_beginner()
+void MonsterDamageProcessor::show_kill_message(concptr note, GAME_TEXT *m_name)
 {
-    auto *floor_ptr = this->target_ptr->current_floor_ptr;
+    auto *floor_ptr = this->player_ptr->current_floor_ptr;
     auto *m_ptr = &floor_ptr->m_list[this->m_idx];
-    auto *r_ptr = &r_info[m_ptr->r_idx];
-    if (d_info[this->target_ptr->dungeon_idx].flags.has(DF::BEGINNER)) {
+    auto *r_ptr = real_r_ptr(m_ptr);
+    if (note != nullptr) {
+        msg_format("%^s%s", m_name, note);
         return;
     }
 
-    if ((floor_ptr->dun_level == 0) && !this->target_ptr->ambush_flag && !floor_ptr->inside_arena) {
-        chg_virtue(this->target_ptr, V_VALOUR, -1);
-    } else if (r_ptr->level > floor_ptr->dun_level) {
-        if (randint1(10) <= (r_ptr->level - floor_ptr->dun_level)) {
-            chg_virtue(this->target_ptr, V_VALOUR, 1);
+    if (!m_ptr->ml) {
+        auto mes = is_echizen(this->player_ptr) ? _("せっかくだから%sを殺した。", "Because it's time, you have killed %s.")
+                                                : _("%sを殺した。", "You have killed %s.");
+        msg_format(mes, m_name);
+        return;
+    }
+
+    if (monster_living(m_ptr->r_idx)) {
+        auto mes = is_echizen(this->player_ptr) ? _("せっかくだから%sを殺した。", "Because it's time, you have slain %s.")
+                                                : _("%sを殺した。", "You have slain %s.");
+        msg_format(mes, m_name);
+        return;
+    }
+
+    auto explode = false;
+    for (auto i = 0; i < 4; i++) {
+        if (r_ptr->blow[i].method == RaceBlowMethodType::EXPLODE) {
+            explode = true;
         }
     }
 
-    if (r_ptr->level > 60) {
-        chg_virtue(this->target_ptr, V_VALOUR, 1);
+    if (explode) {
+        msg_format(_("%sは爆発して粉々になった。", "%^s explodes into tiny shreds."), m_name);
+        return;
+    }
+
+    auto mes = is_echizen(this->player_ptr) ? _("せっかくだから%sを殺した。", "Because it's time, you have destroyed %s.")
+                                            : _("%sを殺した。", "You have destroyed %s.");
+    msg_format(mes, m_name);
+}
+
+void MonsterDamageProcessor::show_bounty_message(GAME_TEXT *m_name)
+{
+    auto *floor_ptr = this->player_ptr->current_floor_ptr;
+    auto *m_ptr = &floor_ptr->m_list[this->m_idx];
+    auto *r_ptr = real_r_ptr(m_ptr);
+    if (r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE) || m_ptr->mflag2.has(MonsterConstantFlagType::CLONED) || vanilla_town) {
+        return;
     }
 
-    if (r_ptr->level >= 2 * (this->target_ptr->lev + 1)) {
-        chg_virtue(this->target_ptr, V_VALOUR, 2);
+    for (auto i = 0; i < MAX_BOUNTY; i++) {
+        if ((w_ptr->bounty_r_idx[i] == m_ptr->r_idx) && m_ptr->mflag2.has_not(MonsterConstantFlagType::CHAMELEON)) {
+            msg_format(_("%sの首には賞金がかかっている。", "There is a price on %s's head."), m_name);
+            break;
+        }
     }
 }
 
@@ -519,10 +427,10 @@ void MonsterDamageProcessor::change_virtue_non_beginner()
  * experience point of a monster later.
  * </pre>
  */
-void MonsterDamageProcessor::get_exp_from_mon(monster_type *m_ptr, HIT_POINT exp_dam)
+void MonsterDamageProcessor::get_exp_from_mon(monster_type *m_ptr, int exp_dam)
 {
     auto *r_ptr = &r_info[m_ptr->r_idx];
-    if (!monster_is_valid(m_ptr) || is_pet(m_ptr) || this->target_ptr->phase_out) {
+    if (!monster_is_valid(m_ptr) || is_pet(m_ptr) || this->player_ptr->phase_out) {
         return;
     }
 
@@ -531,17 +439,17 @@ void MonsterDamageProcessor::get_exp_from_mon(monster_type *m_ptr, HIT_POINT exp
      * - Varying speed effects
      * - Get a fraction in proportion of damage point
      */
-    auto new_exp = r_ptr->level * SPEED_TO_ENERGY(m_ptr->mspeed) * exp_dam;
+    auto new_exp = r_ptr->level * speed_to_energy(m_ptr->mspeed) * exp_dam;
     auto new_exp_frac = 0U;
     auto div_h = 0;
-    auto div_l = (uint)((this->target_ptr->max_plv + 2) * SPEED_TO_ENERGY(r_ptr->speed));
+    auto div_l = (uint)((this->player_ptr->max_plv + 2) * speed_to_energy(r_ptr->speed));
 
     /* Use (average maxhp * 2) as a denominator */
     auto compensation = any_bits(r_ptr->flags1, RF1_FORCE_MAXHP) ? r_ptr->hside * 2 : r_ptr->hside + 1;
     s64b_mul(&div_h, &div_l, 0, r_ptr->hdice * (ironman_nightmare ? 2 : 1) * compensation);
 
     /* Special penalty in the wilderness */
-    if (!this->target_ptr->current_floor_ptr->dun_level && (none_bits(r_ptr->flags8, RF8_WILD_ONLY) || none_bits(r_ptr->flags1, RF1_UNIQUE))) {
+    if (!this->player_ptr->current_floor_ptr->dun_level && (none_bits(r_ptr->flags8, RF8_WILD_ONLY) || r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE))) {
         s64b_mul(&div_h, &div_l, 0, 5);
     }
 
@@ -576,17 +484,17 @@ void MonsterDamageProcessor::get_exp_from_mon(monster_type *m_ptr, HIT_POINT exp
     }
 
     s64b_mul(&new_exp, &new_exp_frac, 0, r_ptr->mexp);
-    gain_exp_64(this->target_ptr, new_exp, new_exp_frac);
+    gain_exp_64(this->player_ptr, new_exp, new_exp_frac);
 }
 
 void MonsterDamageProcessor::set_redraw()
 {
-    if (this->target_ptr->health_who == this->m_idx) {
-        this->target_ptr->redraw |= PR_HEALTH;
+    if (this->player_ptr->health_who == this->m_idx) {
+        this->player_ptr->redraw |= PR_HEALTH;
     }
 
-    if (this->target_ptr->riding == this->m_idx) {
-        this->target_ptr->redraw |= PR_UHEALTH;
+    if (this->player_ptr->riding == this->m_idx) {
+        this->player_ptr->redraw |= PR_UHEALTH;
     }
 }
 
@@ -596,12 +504,11 @@ void MonsterDamageProcessor::set_redraw()
  */
 void MonsterDamageProcessor::summon_special_unique()
 {
-    auto *m_ptr = &this->target_ptr->current_floor_ptr->m_list[this->m_idx];
-    auto *r_ptr = &r_info[m_ptr->r_idx];
+    auto *m_ptr = &this->player_ptr->current_floor_ptr->m_list[this->m_idx];
     bool is_special_summon = m_ptr->r_idx == MON_IKETA;
     is_special_summon |= m_ptr->r_idx == MON_DOPPIO;
-    if (!is_special_summon || this->target_ptr->current_floor_ptr->inside_arena || this->target_ptr->phase_out) {
-        delete_monster_idx(this->target_ptr, this->m_idx);
+    if (!is_special_summon || this->player_ptr->current_floor_ptr->inside_arena || this->player_ptr->phase_out) {
+        delete_monster_idx(this->player_ptr, this->m_idx);
         return;
     }
 
@@ -629,8 +536,34 @@ void MonsterDamageProcessor::summon_special_unique()
         break;
     }
 
-    delete_monster_idx(this->target_ptr, this->m_idx);
-    if (summon_named_creature(this->target_ptr, 0, dummy_y, dummy_x, new_unique_idx, mode)) {
+    delete_monster_idx(this->player_ptr, this->m_idx);
+    if (summon_named_creature(this->player_ptr, 0, dummy_y, dummy_x, new_unique_idx, mode)) {
         msg_print(mes);
     }
 }
+
+void MonsterDamageProcessor::add_monster_fear()
+{
+    auto *m_ptr = &this->player_ptr->current_floor_ptr->m_list[this->m_idx];
+    if (monster_fear_remaining(m_ptr) && (this->dam > 0)) {
+        auto fear_remining = monster_fear_remaining(m_ptr) - randint1(this->dam);
+        if (set_monster_monfear(this->player_ptr, this->m_idx, fear_remining)) {
+            *this->fear = false;
+        }
+    }
+
+    auto *r_ptr = &r_info[m_ptr->r_idx];
+    if (monster_fear_remaining(m_ptr) || any_bits(r_ptr->flags3, RF3_NO_FEAR)) {
+        return;
+    }
+
+    int percentage = (100L * m_ptr->hp) / m_ptr->maxhp;
+    if ((randint1(10) < percentage) && ((this->dam < m_ptr->hp) || (randint0(100) >= 80))) {
+        return;
+    }
+
+    *this->fear = true;
+    auto fear_condition = (this->dam >= m_ptr->hp) && (percentage > 7);
+    auto fear_value = randint1(10) + (fear_condition ? 20 : (11 - percentage) * 5);
+    (void)set_monster_monfear(this->player_ptr, this->m_idx, fear_value);
+}