OSDN Git Service

[Refactor] ブレスのコピペを低減
authorSlimebreath6078 <slimebreath6078@yahoo.co.jp>
Thu, 24 Mar 2022 14:59:05 +0000 (23:59 +0900)
committerSlimebreath6078 <slimebreath6078@yahoo.co.jp>
Wed, 30 Mar 2022 10:48:46 +0000 (19:48 +0900)
概ねは共通化できるものの、メッセージ処理などが少し違うためボルトなどとは別のデータの格納の仕方にした

src/mspell/assign-monster-spell.cpp
src/mspell/mspell-attack/mspell-breath.cpp
src/mspell/mspell-attack/mspell-breath.h

index 6f7984c..8e1ff99 100644 (file)
@@ -10,7 +10,7 @@
 #include "monster/monster-status.h"
 #include "mspell/mspell-attack/mspell-ball.h"
 #include "mspell/mspell-attack/mspell-bolt.h"
-#include "mspell/mspell-breath.h"
+#include "mspell/mspell-attack/mspell-breath.h"
 #include "mspell/mspell-curse.h"
 #include "mspell/mspell-dispel.h"
 #include "mspell/mspell-floor.h"
@@ -35,30 +35,32 @@ static MonsterSpellResult monspell_to_player_impl(PlayerType *player_ptr, Monste
     case MonsterAbilityType::XXX2: break;   /* RF4_XXX2 */
     case MonsterAbilityType::XXX3: break;   /* RF4_XXX3 */
     case MonsterAbilityType::XXX4: break;   /* RF4_XXX4 */
-    case MonsterAbilityType::BR_ACID: return spell_RF4_BREATH(player_ptr, AttributeType::ACID, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ACID */
-    case MonsterAbilityType::BR_ELEC: return spell_RF4_BREATH(player_ptr, AttributeType::ELEC, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ELEC */
-    case MonsterAbilityType::BR_FIRE: return spell_RF4_BREATH(player_ptr, AttributeType::FIRE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_FIRE */
-    case MonsterAbilityType::BR_COLD: return spell_RF4_BREATH(player_ptr, AttributeType::COLD, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_COLD */
-    case MonsterAbilityType::BR_POIS: return spell_RF4_BREATH(player_ptr, AttributeType::POIS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_POIS */
-    case MonsterAbilityType::BR_NETH: return spell_RF4_BREATH(player_ptr, AttributeType::NETHER, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_NETH */
-    case MonsterAbilityType::BR_LITE: return spell_RF4_BREATH(player_ptr, AttributeType::LITE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_LITE */
-    case MonsterAbilityType::BR_DARK: return spell_RF4_BREATH(player_ptr, AttributeType::DARK, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_DARK */
-    case MonsterAbilityType::BR_CONF: return spell_RF4_BREATH(player_ptr, AttributeType::CONFUSION, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_CONF */
-    case MonsterAbilityType::BR_SOUN: return spell_RF4_BREATH(player_ptr, AttributeType::SOUND, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_SOUN */
-    case MonsterAbilityType::BR_CHAO: return spell_RF4_BREATH(player_ptr, AttributeType::CHAOS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_CHAO */
-    case MonsterAbilityType::BR_DISE: return spell_RF4_BREATH(player_ptr, AttributeType::DISENCHANT, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_DISE */
-    case MonsterAbilityType::BR_NEXU: return spell_RF4_BREATH(player_ptr, AttributeType::NEXUS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_NEXU */
-    case MonsterAbilityType::BR_TIME: return spell_RF4_BREATH(player_ptr, AttributeType::TIME, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_TIME */
-    case MonsterAbilityType::BR_INER: return spell_RF4_BREATH(player_ptr, AttributeType::INERTIAL, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_BR_INER */
-    case MonsterAbilityType::BR_GRAV: return spell_RF4_BREATH(player_ptr, AttributeType::GRAVITY, y, x, m_idx, 0, MONSTER_TO_PLAYER);  /* RF4_BR_GRAV */
-    case MonsterAbilityType::BR_SHAR: return spell_RF4_BREATH(player_ptr, AttributeType::SHARDS, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_SHAR */
-    case MonsterAbilityType::BR_PLAS: return spell_RF4_BREATH(player_ptr, AttributeType::PLASMA, y, x, m_idx, 0, MONSTER_TO_PLAYER);   /* RF4_BR_PLAS */
-    case MonsterAbilityType::BR_FORC: return spell_RF4_BREATH(player_ptr, AttributeType::FORCE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_WALL */
-    case MonsterAbilityType::BR_MANA: return spell_RF4_BREATH(player_ptr, AttributeType::MANA, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_MANA */
-    case MonsterAbilityType::BR_NUKE: return spell_RF4_BREATH(player_ptr, AttributeType::NUKE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_NUKE */
-    case MonsterAbilityType::BR_DISI: return spell_RF4_BREATH(player_ptr, AttributeType::DISINTEGRATE, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_DISI */
-    case MonsterAbilityType::BR_VOID: return spell_RF4_BREATH(player_ptr, AttributeType::VOID_MAGIC, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_VOID */
-    case MonsterAbilityType::BR_ABYSS: return spell_RF4_BREATH(player_ptr, AttributeType::ABYSS, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ABYSS */
+
+    case MonsterAbilityType::BR_ACID:
+    case MonsterAbilityType::BR_ELEC:
+    case MonsterAbilityType::BR_FIRE:
+    case MonsterAbilityType::BR_COLD:
+    case MonsterAbilityType::BR_POIS:
+    case MonsterAbilityType::BR_NETH:
+    case MonsterAbilityType::BR_LITE:
+    case MonsterAbilityType::BR_DARK:
+    case MonsterAbilityType::BR_CONF:
+    case MonsterAbilityType::BR_SOUN:
+    case MonsterAbilityType::BR_CHAO:
+    case MonsterAbilityType::BR_DISE:
+    case MonsterAbilityType::BR_NEXU:
+    case MonsterAbilityType::BR_TIME:
+    case MonsterAbilityType::BR_INER:
+    case MonsterAbilityType::BR_GRAV:
+    case MonsterAbilityType::BR_SHAR:
+    case MonsterAbilityType::BR_PLAS:
+    case MonsterAbilityType::BR_FORC:
+    case MonsterAbilityType::BR_MANA:
+    case MonsterAbilityType::BR_NUKE:
+    case MonsterAbilityType::BR_DISI:
+    case MonsterAbilityType::BR_VOID:
+    case MonsterAbilityType::BR_ABYSS:
+     return spell_RF4_BREATH(player_ptr, ms_type, y, x, m_idx, 0, MONSTER_TO_PLAYER); /* RF4_BR_ABYSS */
     
     case MonsterAbilityType::BA_ACID:
     case MonsterAbilityType::BA_ELEC:
@@ -162,30 +164,32 @@ static MonsterSpellResult monspell_to_monster_impl(
     case MonsterAbilityType::XXX2: break;   /* RF4_XXX2 */
     case MonsterAbilityType::XXX3: break;   /* RF4_XXX3 */
     case MonsterAbilityType::XXX4: break;   /* RF4_XXX4 */
-    case MonsterAbilityType::BR_ACID: return spell_RF4_BREATH(player_ptr, AttributeType::ACID, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ACID */
-    case MonsterAbilityType::BR_ELEC: return spell_RF4_BREATH(player_ptr, AttributeType::ELEC, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ELEC */
-    case MonsterAbilityType::BR_FIRE: return spell_RF4_BREATH(player_ptr, AttributeType::FIRE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_FIRE */
-    case MonsterAbilityType::BR_COLD: return spell_RF4_BREATH(player_ptr, AttributeType::COLD, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_COLD */
-    case MonsterAbilityType::BR_POIS: return spell_RF4_BREATH(player_ptr, AttributeType::POIS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_POIS */
-    case MonsterAbilityType::BR_NETH: return spell_RF4_BREATH(player_ptr, AttributeType::NETHER, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_NETH */
-    case MonsterAbilityType::BR_LITE: return spell_RF4_BREATH(player_ptr, AttributeType::LITE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_LITE */
-    case MonsterAbilityType::BR_DARK: return spell_RF4_BREATH(player_ptr, AttributeType::DARK, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_DARK */
-    case MonsterAbilityType::BR_CONF: return spell_RF4_BREATH(player_ptr, AttributeType::CONFUSION, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_CONF */
-    case MonsterAbilityType::BR_SOUN: return spell_RF4_BREATH(player_ptr, AttributeType::SOUND, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_SOUN */
-    case MonsterAbilityType::BR_CHAO: return spell_RF4_BREATH(player_ptr, AttributeType::CHAOS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_CHAO */
-    case MonsterAbilityType::BR_DISE: return spell_RF4_BREATH(player_ptr, AttributeType::DISENCHANT, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_DISE */
-    case MonsterAbilityType::BR_NEXU: return spell_RF4_BREATH(player_ptr, AttributeType::NEXUS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_NEXU */
-    case MonsterAbilityType::BR_TIME: return spell_RF4_BREATH(player_ptr, AttributeType::TIME, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_TIME */
-    case MonsterAbilityType::BR_INER: return spell_RF4_BREATH(player_ptr, AttributeType::INERTIAL, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_INER */
-    case MonsterAbilityType::BR_GRAV: return spell_RF4_BREATH(player_ptr, AttributeType::GRAVITY, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_GRAV */
-    case MonsterAbilityType::BR_SHAR: return spell_RF4_BREATH(player_ptr, AttributeType::SHARDS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_SHAR */
-    case MonsterAbilityType::BR_PLAS: return spell_RF4_BREATH(player_ptr, AttributeType::PLASMA, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);  /* RF4_BR_PLAS */
-    case MonsterAbilityType::BR_FORC: return spell_RF4_BREATH(player_ptr, AttributeType::FORCE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER);   /* RF4_BR_WALL */
-    case MonsterAbilityType::BR_MANA: return spell_RF4_BREATH(player_ptr, AttributeType::MANA, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_MANA */
-    case MonsterAbilityType::BR_NUKE: return spell_RF4_BREATH(player_ptr, AttributeType::NUKE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_NUKE */
-    case MonsterAbilityType::BR_DISI: return spell_RF4_BREATH(player_ptr, AttributeType::DISINTEGRATE, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_DISI */
-    case MonsterAbilityType::BR_VOID: return spell_RF4_BREATH(player_ptr, AttributeType::VOID_MAGIC, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_VOID */
-    case MonsterAbilityType::BR_ABYSS: return spell_RF4_BREATH(player_ptr, AttributeType::ABYSS, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ABYSS */
+
+    case MonsterAbilityType::BR_ACID:
+    case MonsterAbilityType::BR_ELEC:
+    case MonsterAbilityType::BR_FIRE:
+    case MonsterAbilityType::BR_COLD:
+    case MonsterAbilityType::BR_POIS:
+    case MonsterAbilityType::BR_NETH:
+    case MonsterAbilityType::BR_LITE:
+    case MonsterAbilityType::BR_DARK:
+    case MonsterAbilityType::BR_CONF:
+    case MonsterAbilityType::BR_SOUN:
+    case MonsterAbilityType::BR_CHAO:
+    case MonsterAbilityType::BR_DISE:
+    case MonsterAbilityType::BR_NEXU:
+    case MonsterAbilityType::BR_TIME:
+    case MonsterAbilityType::BR_INER:
+    case MonsterAbilityType::BR_GRAV:
+    case MonsterAbilityType::BR_SHAR:
+    case MonsterAbilityType::BR_PLAS:
+    case MonsterAbilityType::BR_FORC:
+    case MonsterAbilityType::BR_MANA:
+    case MonsterAbilityType::BR_NUKE:
+    case MonsterAbilityType::BR_DISI:
+    case MonsterAbilityType::BR_VOID:
+    case MonsterAbilityType::BR_ABYSS:
+    return spell_RF4_BREATH(player_ptr, ms_type, y, x, m_idx, t_idx, MONSTER_TO_MONSTER); /* RF4_BR_ABYSS */
     
     case MonsterAbilityType::BA_ACID:
     case MonsterAbilityType::BA_ELEC:
index 43e05e5..5d7f9bd 100644 (file)
@@ -1,4 +1,4 @@
-#include "mspell/mspell-breath.h"
+#include "mspell/mspell-attack/mspell-breath.h"
 #include "core/disturbance.h"
 #include "effect/attribute-types.h"
 #include "effect/effect-processor.h"
@@ -11,6 +11,7 @@
 #include "monster/monster-update.h"
 #include "mspell/mspell-checker.h"
 #include "mspell/mspell-damage-calculator.h"
+#include "mspell/mspell-data.h"
 #include "mspell/mspell-result.h"
 #include "mspell/mspell-util.h"
 #include "system/floor-type-definition.h"
@@ -45,166 +46,18 @@ static bool spell_RF4_BREATH_special_message(MonsterRaceId r_idx, AttributeType
     return false;
 }
 
-/*!
- * @brief RF4_BR_*の処理。各種ブレス。 /
- * @param player_ptr プレイヤーへの参照ポインタ
- * @param GF_TYPE ブレスの属性
- * @param y 対象の地点のy座標
- * @param x 対象の地点のx座標
- * @param m_idx 呪文を唱えるモンスターID
- * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
- * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
- *
- * プレイヤーに当たったらラーニング可。
- */
-MonsterSpellResult spell_RF4_BREATH(PlayerType *player_ptr, AttributeType GF_TYPE, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
+static void message_breath(PlayerType *player_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type, std::string_view type_s, AttributeType GF_TYPE)
 {
-    int dam, drs_type = 0;
-    concptr type_s;
-    bool smart_learn_aux = true;
     auto *floor_ptr = player_ptr->current_floor_ptr;
     auto *m_ptr = &floor_ptr->m_list[m_idx];
-    bool known = monster_near_player(floor_ptr, m_idx, t_idx);
-    bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
-    bool mon_to_mon = (target_type == MONSTER_TO_MONSTER);
-    bool mon_to_player = (target_type == MONSTER_TO_PLAYER);
+    auto see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
+    auto known = monster_near_player(floor_ptr, m_idx, t_idx);
+    auto mon_to_mon = (target_type == MONSTER_TO_MONSTER);
+    auto mon_to_player = (target_type == MONSTER_TO_PLAYER);
     GAME_TEXT m_name[MAX_NLEN], t_name[MAX_NLEN];
     monster_name(player_ptr, m_idx, m_name);
     monster_name(player_ptr, t_idx, t_name);
 
-    switch (GF_TYPE) {
-    case AttributeType::ACID:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_ACID, m_idx, DAM_ROLL);
-        type_s = _("酸", "acid");
-        drs_type = DRS_ACID;
-        break;
-    case AttributeType::ELEC:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_ELEC, m_idx, DAM_ROLL);
-        type_s = _("稲妻", "lightning");
-        drs_type = DRS_ELEC;
-        break;
-    case AttributeType::FIRE:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_FIRE, m_idx, DAM_ROLL);
-        type_s = _("火炎", "fire");
-        drs_type = DRS_FIRE;
-        break;
-    case AttributeType::COLD:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_COLD, m_idx, DAM_ROLL);
-        type_s = _("冷気", "frost");
-        drs_type = DRS_COLD;
-        break;
-    case AttributeType::POIS:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_POIS, m_idx, DAM_ROLL);
-        type_s = _("ガス", "gas");
-        drs_type = DRS_POIS;
-        break;
-    case AttributeType::NETHER:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_NETH, m_idx, DAM_ROLL);
-        type_s = _("地獄", "nether");
-        drs_type = DRS_NETH;
-        break;
-    case AttributeType::LITE:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_LITE, m_idx, DAM_ROLL);
-        type_s = _("閃光", "light");
-        drs_type = DRS_LITE;
-        break;
-    case AttributeType::DARK:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_DARK, m_idx, DAM_ROLL);
-        type_s = _("暗黒", "darkness");
-        drs_type = DRS_DARK;
-        break;
-    case AttributeType::CONFUSION:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_CONF, m_idx, DAM_ROLL);
-        type_s = _("混乱", "confusion");
-        drs_type = DRS_CONF;
-        break;
-    case AttributeType::SOUND:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_SOUN, m_idx, DAM_ROLL);
-        type_s = _("轟音", "sound");
-        drs_type = DRS_SOUND;
-        break;
-    case AttributeType::CHAOS:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_CHAO, m_idx, DAM_ROLL);
-        type_s = _("カオス", "chaos");
-        drs_type = DRS_CHAOS;
-        break;
-    case AttributeType::DISENCHANT:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_DISE, m_idx, DAM_ROLL);
-        type_s = _("劣化", "disenchantment");
-        drs_type = DRS_DISEN;
-        break;
-    case AttributeType::NEXUS:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_NEXU, m_idx, DAM_ROLL);
-        type_s = _("因果混乱", "nexus");
-        drs_type = DRS_NEXUS;
-        break;
-    case AttributeType::TIME:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_TIME, m_idx, DAM_ROLL);
-        type_s = _("時間逆転", "time");
-        smart_learn_aux = false;
-        break;
-    case AttributeType::INERTIAL:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_INER, m_idx, DAM_ROLL);
-        type_s = _("遅鈍", "inertia");
-        smart_learn_aux = false;
-        break;
-    case AttributeType::GRAVITY:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_GRAV, m_idx, DAM_ROLL);
-        type_s = _("重力", "gravity");
-        smart_learn_aux = false;
-        break;
-    case AttributeType::SHARDS:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_SHAR, m_idx, DAM_ROLL);
-        type_s = _("破片", "shards");
-        drs_type = DRS_SHARD;
-        break;
-    case AttributeType::PLASMA:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_PLAS, m_idx, DAM_ROLL);
-        type_s = _("プラズマ", "plasma");
-        smart_learn_aux = false;
-        break;
-    case AttributeType::FORCE:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_FORC, m_idx, DAM_ROLL);
-        type_s = _("フォース", "force");
-        smart_learn_aux = false;
-        break;
-    case AttributeType::MANA:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_MANA, m_idx, DAM_ROLL);
-        type_s = _("魔力", "mana");
-        smart_learn_aux = false;
-        break;
-    case AttributeType::NUKE:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_NUKE, m_idx, DAM_ROLL);
-        type_s = _("放射性廃棄物", "toxic waste");
-        drs_type = DRS_POIS;
-        break;
-    case AttributeType::DISINTEGRATE:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_DISI, m_idx, DAM_ROLL);
-        type_s = _("分解", "disintegration");
-        smart_learn_aux = false;
-        break;
-    case AttributeType::VOID_MAGIC:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_VOID, m_idx, DAM_ROLL);
-        type_s = _("虚無", "void");
-        smart_learn_aux = false;
-        break;
-    case AttributeType::ABYSS:
-        dam = monspell_damage(player_ptr, MonsterAbilityType::BR_ABYSS, m_idx, DAM_ROLL);
-        type_s = _("深淵", "disintegration");
-        smart_learn_aux = false;
-        break;
-    default:
-        /* Do not reach here */
-        dam = 0;
-        type_s = _("不明", "Unknown");
-        smart_learn_aux = false;
-        break;
-    }
-
-    if (mon_to_player || (mon_to_mon && known && see_either)) {
-        disturb(player_ptr, true, true);
-    }
-
     if (!spell_RF4_BREATH_special_message(m_ptr->r_idx, GF_TYPE, m_name)) {
         if (player_ptr->blind) {
             if (mon_to_player || (mon_to_mon && known && see_either)) {
@@ -212,9 +65,9 @@ MonsterSpellResult spell_RF4_BREATH(PlayerType *player_ptr, AttributeType GF_TYP
             }
         } else {
             if (mon_to_player) {
-                msg_format(_("%^sが%^sのブレスを吐いた。", "%^s breathes %^s."), m_name, type_s);
+                msg_format(_("%^sが%^sのブレスを吐いた。", "%^s breathes %^s."), m_name, type_s.data());
             } else if (mon_to_mon && known && see_either) {
-                _(msg_format("%^sが%^sに%^sのブレスを吐いた。", m_name, t_name, type_s), msg_format("%^s breathes %^s at %^s.", m_name, type_s, t_name));
+                _(msg_format("%^sが%^sに%^sのブレスを吐いた。", m_name, t_name, type_s.data()), msg_format("%^s breathes %^s at %^s.", m_name, type_s.data(), t_name));
             }
         }
     }
@@ -226,10 +79,88 @@ MonsterSpellResult spell_RF4_BREATH(PlayerType *player_ptr, AttributeType GF_TYP
     if (known || see_either) {
         sound(SOUND_BREATH);
     }
+}
+
+static std::pair<MonsterAbilityType, MSpellData> make_breath_elemental(MonsterAbilityType ms_type, AttributeType GF_TYPE, std::string_view type_s)
+{
+    return { ms_type, { [type_s, GF_TYPE](auto *player_ptr, auto m_idx, auto t_idx, int target_type) {
+                           message_breath(player_ptr, m_idx, t_idx, target_type, type_s, GF_TYPE);
+                           return false;
+                       },
+                          GF_TYPE } };
+};
+
+static std::pair<MonsterAbilityType, MSpellData> make_breath_elemental(MonsterAbilityType ms_type, AttributeType GF_TYPE, std::string_view type_s, MSpellDrsData drs)
+{
+    return { ms_type, { [type_s, GF_TYPE](auto *player_ptr, auto m_idx, auto t_idx, int target_type) {
+                           message_breath(player_ptr, m_idx, t_idx, target_type, type_s, GF_TYPE);
+                           return false;
+                       },
+                          GF_TYPE, drs } };
+};
+
+const std::unordered_map<MonsterAbilityType, MSpellData> breath_list = {
+    make_breath_elemental(MonsterAbilityType::BR_ACID, AttributeType::ACID, _("酸", "acid"), DRS_ACID),
+    make_breath_elemental(MonsterAbilityType::BR_ELEC, AttributeType::ELEC, _("稲妻", "lightning"), DRS_ELEC),
+    make_breath_elemental(MonsterAbilityType::BR_FIRE, AttributeType::FIRE, _("火炎", "fire"), DRS_FIRE),
+    make_breath_elemental(MonsterAbilityType::BR_COLD, AttributeType::COLD, _("冷気", "frost"), DRS_COLD),
+    make_breath_elemental(MonsterAbilityType::BR_POIS, AttributeType::POIS, _("ガス", "gas"), DRS_POIS),
+    make_breath_elemental(MonsterAbilityType::BR_NETH, AttributeType::NETHER, _("地獄", "nether"), DRS_NETH),
+    make_breath_elemental(MonsterAbilityType::BR_LITE, AttributeType::LITE, _("閃光", "light"), DRS_LITE),
+    make_breath_elemental(MonsterAbilityType::BR_DARK, AttributeType::DARK, _("暗黒", "darkness"), DRS_DARK),
+    make_breath_elemental(MonsterAbilityType::BR_CONF, AttributeType::CONFUSION, _("混乱", "confusion"), DRS_CONF),
+    make_breath_elemental(MonsterAbilityType::BR_SOUN, AttributeType::SOUND, _("轟音", "sound"), DRS_SOUND),
+    make_breath_elemental(MonsterAbilityType::BR_CHAO, AttributeType::CHAOS, _("カオス", "chaos"), DRS_CHAOS),
+    make_breath_elemental(MonsterAbilityType::BR_DISE, AttributeType::DISENCHANT, _("劣化", "disenchantment"), DRS_DISEN),
+    make_breath_elemental(MonsterAbilityType::BR_NEXU, AttributeType::NEXUS, _("因果混乱", "nexus"), DRS_NEXUS),
+    make_breath_elemental(MonsterAbilityType::BR_TIME, AttributeType::TIME, _("時間逆転", "time")),
+    make_breath_elemental(MonsterAbilityType::BR_INER, AttributeType::INERTIAL, _("遅鈍", "inertia")),
+    make_breath_elemental(MonsterAbilityType::BR_SHAR, AttributeType::SHARDS, _("破片", "shards"), DRS_SHARD),
+    make_breath_elemental(MonsterAbilityType::BR_PLAS, AttributeType::PLASMA, _("プラズマ", "plasma")),
+    make_breath_elemental(MonsterAbilityType::BR_FORC, AttributeType::FORCE, _("フォース", "force")),
+    make_breath_elemental(MonsterAbilityType::BR_MANA, AttributeType::MANA, _("魔力", "mana")),
+    make_breath_elemental(MonsterAbilityType::BR_NUKE, AttributeType::NUKE, _("放射性廃棄物", "toxic waste"), DRS_POIS),
+    make_breath_elemental(MonsterAbilityType::BR_DISE, AttributeType::DISINTEGRATE, _("分解", "disintegration")),
+    make_breath_elemental(MonsterAbilityType::BR_VOID, AttributeType::VOID_MAGIC, _("虚無", "void")),
+    make_breath_elemental(MonsterAbilityType::BR_ABYSS, AttributeType::ABYSS, _("深淵", "abyss")),
+};
+
+/*!
+ * @brief RF4_BR_*の処理。各種ブレス。 /
+ * @param player_ptr プレイヤーへの参照ポインタ
+ * @param GF_TYPE ブレスの属性
+ * @param y 対象の地点のy座標
+ * @param x 対象の地点のx座標
+ * @param m_idx 呪文を唱えるモンスターID
+ * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
+ * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
+ *
+ * プレイヤーに当たったらラーニング可。
+ */
+MonsterSpellResult spell_RF4_BREATH(PlayerType *player_ptr, MonsterAbilityType ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
+{
+    auto dam = 0;
+    auto mon_to_player = (target_type == MONSTER_TO_PLAYER);
+    std::unique_ptr<MSpellData> data;
+
+    if (breath_list.find(ms_type) != breath_list.end()) {
+        dam = monspell_damage(player_ptr, ms_type, m_idx, DAM_ROLL);
+        data = std::make_unique<MSpellData>(breath_list.at(ms_type));
+    } else {
+        dam = 0;
+        data = std::make_unique<MSpellData>([](auto *player_ptr, auto m_idx, auto t_idx, int target_type) {
+            message_breath(player_ptr, m_idx, t_idx, target_type, _("不明", "Unknown"), AttributeType::NONE);
+            return false;
+        },
+            AttributeType::NONE);
+    }
+
+    data->msg.output(player_ptr, m_idx, t_idx, target_type);
+
+    const auto proj_res = breath(player_ptr, y, x, m_idx, data->type, dam, 0, target_type);
 
-    const auto proj_res = breath(player_ptr, y, x, m_idx, GF_TYPE, dam, 0, target_type);
-    if (smart_learn_aux && mon_to_player) {
-        update_smart_learn(player_ptr, m_idx, drs_type);
+    if (mon_to_player) {
+        data->drs.execute(player_ptr, m_idx);
     }
 
     auto res = MonsterSpellResult::make_valid(dam);
index a411364..1afd775 100644 (file)
@@ -1,9 +1,11 @@
 #pragma once
 
-#include "effect/attribute-types.h"
 #include "system/angband.h"
 
+#include "effect/attribute-types.h"
+#include "mspell/mspell-attack/abstract-mspell.h"
+
 struct MonsterSpellResult;
 
 class PlayerType;
-MonsterSpellResult spell_RF4_BREATH(PlayerType *player_ptr, AttributeType GF_TYPE, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type);
+MonsterSpellResult spell_RF4_BREATH(PlayerType *player_ptr, MonsterAbilityType ms_type, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type);