OSDN Git Service

[Fix] 青魔道師の一貫性のないラーニング判定を修正
authortaotao54321 <taotao54321@gmail.com>
Thu, 18 Feb 2021 16:21:00 +0000 (01:21 +0900)
committertaotao54321 <taotao54321@gmail.com>
Fri, 19 Feb 2021 15:06:20 +0000 (00:06 +0900)
例えばプラズマボルトで朦朧としたのにラーニングが成功したりしていた。
`learn_spell()` があちこちで呼ばれており、判定に一貫性がなくなっていた。

`learn_spell()` の呼び出しを `make_attack_spell()` 内に一本化して修正。
ただし、モンスター特技「暗闇」は特定条件下でライトエリアになる関係上、やむを得
ず特技処理内にラーニングも含めることとした。

また、従来のコードで曖昧だった仕様について以下のように定めた:

* ラーニングを行うためには、モンスターが特技を使う前の時点でプレイヤーがモンス
  ターを視認できていなければならない。
* 分身による回避はラーニングの可否に影響しない。

12 files changed:
src/blue-magic/blue-magic-checker.c
src/blue-magic/blue-magic-checker.h
src/effect/effect-player-curse.c
src/effect/effect-player-resist-hurt.c
src/effect/effect-player-spirit.c
src/mspell/mspell-attack.c
src/mspell/mspell-checker.c
src/mspell/mspell-dispel.c
src/mspell/mspell-floor.c
src/mspell/mspell-learn-checker.c
src/mspell/mspell-status.c
src/player/player-damage.c

index f698ee1..379a463 100644 (file)
 #include "main/sound-definitions-table.h"
 #include "main/sound-of-music.h"
 #include "mind/mind-blue-mage.h"
-#include "monster-race/race-flags4.h"
 #include "monster-race/race-flags-ability1.h"
 #include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-flags4.h"
 #include "mspell/monster-power-table.h"
 #include "mspell/mspell-mask-definitions.h"
+#include "mspell/mspell-type.h"
 #include "player/attack-defense-types.h"
 #include "status/experience.h"
 #include "view/display-messages.h"
 
 /*!
+ * @brief モンスター特技がラーニング可能かどうかを返す
+ * @param ms_type モンスター特技ID
+ */
+bool monster_spell_is_learnable(const int monspell)
+{
+    switch (monspell) {
+    case MS_DISPEL:
+    case MS_ROCKET:
+    case MS_SHOOT:
+    case MS_BR_ACID:
+    case MS_BR_ELEC:
+    case MS_BR_FIRE:
+    case MS_BR_COLD:
+    case MS_BR_POIS:
+    case MS_BR_NETHER:
+    case MS_BR_LITE:
+    case MS_BR_DARK:
+    case MS_BR_CONF:
+    case MS_BR_SOUND:
+    case MS_BR_CHAOS:
+    case MS_BR_DISEN:
+    case MS_BR_NEXUS:
+    case MS_BR_TIME:
+    case MS_BR_INERTIA:
+    case MS_BR_GRAVITY:
+    case MS_BR_SHARDS:
+    case MS_BR_PLASMA:
+    case MS_BR_FORCE:
+    case MS_BR_MANA:
+    case MS_BALL_NUKE:
+    case MS_BR_NUKE:
+    case MS_BALL_CHAOS:
+    case MS_BR_DISI:
+    case MS_BALL_ACID:
+    case MS_BALL_ELEC:
+    case MS_BALL_FIRE:
+    case MS_BALL_COLD:
+    case MS_BALL_POIS:
+    case MS_BALL_NETHER:
+    case MS_BALL_WATER:
+    case MS_BALL_MANA:
+    case MS_BALL_DARK:
+    case MS_DRAIN_MANA:
+    case MS_MIND_BLAST:
+    case MS_BRAIN_SMASH:
+    case MS_CAUSE_1:
+    case MS_CAUSE_2:
+    case MS_CAUSE_3:
+    case MS_CAUSE_4:
+    case MS_BOLT_ACID:
+    case MS_BOLT_ELEC:
+    case MS_BOLT_FIRE:
+    case MS_BOLT_COLD:
+    case MS_STARBURST:
+    case MS_BOLT_NETHER:
+    case MS_BOLT_WATER:
+    case MS_BOLT_MANA:
+    case MS_BOLT_PLASMA:
+    case MS_BOLT_ICE:
+    case MS_MAGIC_MISSILE:
+    case MS_SCARE:
+    case MS_BLIND:
+    case MS_CONF:
+    case MS_SLOW:
+    case MS_SLEEP:
+    case MS_HAND_DOOM:
+    case MS_TELE_TO:
+    case MS_TELE_AWAY:
+    case MS_PSY_SPEAR:
+    case MS_DARKNESS:
+    case MS_MAKE_TRAP:
+    case MS_FORGET:
+    case MS_S_KIN:
+    case MS_S_CYBER:
+    case MS_S_MONSTER:
+    case MS_S_MONSTERS:
+    case MS_S_ANT:
+    case MS_S_SPIDER:
+    case MS_S_HOUND:
+    case MS_S_HYDRA:
+    case MS_S_ANGEL:
+    case MS_S_DEMON:
+    case MS_S_UNDEAD:
+    case MS_S_DRAGON:
+    case MS_S_HI_UNDEAD:
+    case MS_S_HI_DRAGON:
+    case MS_S_AMBERITE:
+    case MS_S_UNIQUE:
+        return TRUE;
+    default:
+        return FALSE;
+    }
+}
+
+/*!
  * @brief 青魔法のラーニング判定と成功した場合のラーニング処理
  * @param monspell ラーニングを試みるモンスター攻撃のID
  * @return なし
index 1604b4d..917c1a4 100644 (file)
@@ -3,5 +3,7 @@
 #include "system/angband.h"
 
 typedef enum blue_magic_type blue_magic_type;
+
+bool monster_spell_is_learnable(int monspell);
 void learn_spell(player_type *learner_ptr, int monspell);
 void set_rf_masks(BIT_FLAGS *f4, BIT_FLAGS *f5, BIT_FLAGS *f6, blue_magic_type mode);
index 6483f77..5364507 100644 (file)
@@ -12,7 +12,6 @@ void effect_player_curse_1(player_type *target_ptr, effect_player_type *ep_ptr)
 {
     if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) {
         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
-        learn_spell(target_ptr, ep_ptr->monspell);
     } else {
         if (!check_multishadow(target_ptr))
             curse_equipment(target_ptr, 15, 0);
@@ -24,7 +23,6 @@ void effect_player_curse_2(player_type *target_ptr, effect_player_type *ep_ptr)
 {
     if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) {
         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
-        learn_spell(target_ptr, ep_ptr->monspell);
     } else {
         if (!check_multishadow(target_ptr))
             curse_equipment(target_ptr, 25, MIN(ep_ptr->rlev / 2 - 15, 5));
@@ -36,7 +34,6 @@ void effect_player_curse_3(player_type *target_ptr, effect_player_type *ep_ptr)
 {
     if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) {
         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
-        learn_spell(target_ptr, ep_ptr->monspell);
     } else {
         if (!check_multishadow(target_ptr))
             curse_equipment(target_ptr, 33, MIN(ep_ptr->rlev / 2 - 15, 15));
@@ -48,7 +45,6 @@ void effect_player_curse_4(player_type *target_ptr, effect_player_type *ep_ptr)
 {
     if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !(ep_ptr->m_ptr->r_idx == MON_KENSHIROU) && !check_multishadow(target_ptr)) {
         msg_print(_("しかし秘孔を跳ね返した!", "You resist the effects!"));
-        learn_spell(target_ptr, ep_ptr->monspell);
     } else {
         ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell);
         if (!check_multishadow(target_ptr))
index 1dc9d21..c3b55e7 100644 (file)
@@ -160,7 +160,6 @@ void effect_player_nether(player_type *target_ptr, effect_player_type *ep_ptr)
 
     msg_print(_("気分がよくなった。", "You feel invigorated!"));
     hp_player(target_ptr, ep_ptr->dam / 4);
-    learn_spell(target_ptr, ep_ptr->monspell);
 }
 
 void effect_player_water(player_type *target_ptr, effect_player_type *ep_ptr)
@@ -577,7 +576,6 @@ void effect_player_hand_doom(player_type *target_ptr, effect_player_type *ep_ptr
 {
     if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) {
         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
-        learn_spell(target_ptr, ep_ptr->monspell);
     } else {
         if (!check_multishadow(target_ptr)) {
             msg_print(_("あなたは命が薄まっていくように感じた!", "You feel your life fade away!"));
index b1dcc0d..878f4e5 100644 (file)
@@ -36,7 +36,6 @@ void effect_player_drain_mana(player_type *target_ptr, effect_player_type *ep_pt
         target_ptr->csp -= ep_ptr->dam;
     }
 
-    learn_spell(target_ptr, ep_ptr->monspell);
     target_ptr->redraw |= (PR_MANA);
     target_ptr->window_flags |= (PW_PLAYER | PW_SPELL);
 
@@ -65,7 +64,6 @@ void effect_player_mind_blast(player_type *target_ptr, effect_player_type *ep_pt
 {
     if ((randint0(100 + ep_ptr->rlev / 2) < MAX(5, target_ptr->skill_sav)) && !check_multishadow(target_ptr)) {
         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
-        learn_spell(target_ptr, ep_ptr->monspell);
         return;
     }
 
@@ -97,7 +95,6 @@ void effect_player_brain_smash(player_type *target_ptr, effect_player_type *ep_p
 {
     if ((randint0(100 + ep_ptr->rlev / 2) < MAX(5, target_ptr->skill_sav)) && !check_multishadow(target_ptr)) {
         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
-        learn_spell(target_ptr, ep_ptr->monspell);
         return;
     }
 
index 44083ce..590cb56 100644 (file)
@@ -21,6 +21,7 @@
 #include "mspell/improper-mspell-remover.h"
 #include "mspell/mspell-attack-util.h"
 #include "mspell/mspell-checker.h"
+#include "mspell/mspell-learn-checker.h"
 #include "mspell/mspell-lite.h"
 #include "mspell/mspell-mask-definitions.h"
 #include "mspell/mspell-selector.h"
@@ -367,15 +368,24 @@ bool make_attack_spell(player_type *target_ptr, MONSTER_IDX m_idx)
     if (!check_thrown_mspell(target_ptr, msa_ptr))
         return FALSE;
 
+    // 特技使用前の時点でプレイヤーがモンスターを視認できているかチェック(ラーニングの必要条件)。
+    const bool player_could_see_monster = spell_learnable(target_ptr, m_idx);
+
     // 特技を使う。
     msa_ptr->dam = monspell_to_player(target_ptr, msa_ptr->thrown_spell, msa_ptr->y, msa_ptr->x, m_idx);
     if (msa_ptr->dam < 0)
         return FALSE;
 
-    // 召喚を行う特技の場合、ラーニング処理。
-    // TODO: 全てのラーニング処理をここに集約する。
-    if ((target_ptr->action == ACTION_LEARN) && msa_ptr->thrown_spell >= RF4_SPELL_START + MS_S_KIN)
-        learn_spell(target_ptr, msa_ptr->thrown_spell - RF4_SPELL_START);
+    // 条件を満たしていればラーニングを試みる。
+    if (player_could_see_monster) {
+        const int monspell = msa_ptr->thrown_spell - RF4_SPELL_START;
+        // XXX: 「暗闇」は特定条件下でライトエリアになる関係上、やむを得ずラー
+        // ニング処理を特技処理に含めた。よって二重ラーニングを行わないようここ
+        // では除外する。
+        const bool try_learn = monster_spell_is_learnable(monspell) && monspell != MS_DARKNESS;
+        if (try_learn)
+            learn_spell(target_ptr, monspell);
+    }
 
     check_mspell_imitation(target_ptr, msa_ptr);
     remember_mspell(msa_ptr);
index 6d28f3e..0a9b2a1 100644 (file)
@@ -203,8 +203,7 @@ void bolt(player_type *target_ptr, MONSTER_IDX m_idx, POSITION y, POSITION x, EF
     if (typ != GF_ARROW)
         flg |= PROJECT_REFLECTABLE;
 
-    bool learnable = spell_learnable(target_ptr, m_idx);
-    (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
+    (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, monspell);
 }
 
 /*!
@@ -231,8 +230,7 @@ void beam(player_type *target_ptr, MONSTER_IDX m_idx, POSITION y, POSITION x, EF
         break;
     }
 
-    bool learnable = spell_learnable(target_ptr, m_idx);
-    (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
+    (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, monspell);
 }
 
 /*!
@@ -287,8 +285,7 @@ void breath(
         break;
     }
 
-    bool learnable = spell_learnable(target_ptr, m_idx);
-    (void)project(target_ptr, m_idx, rad, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
+    (void)project(target_ptr, m_idx, rad, y, x, dam_hp, typ, flg, monspell);
 }
 
 /*!
index b24362f..63fd150 100644 (file)
 #include "status/temporary-resistance.h"
 #include "view/display-messages.h"
 
-#include "status/buff-setter.h"
 #include "core/speed-table.h"
 #include "monster/monster-status-setter.h"
 #include "player/attack-defense-types.h"
 #include "player/player-race.h"
+#include "status/buff-setter.h"
 
 /*!
  * @brief プレイヤーに魔力消去効果を与える。
@@ -129,7 +129,6 @@ void spell_RF4_DISPEL(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_
                 msg_print(_("弱い者いじめは止めるんだ!", ""));
         }
 
-        learn_spell(target_ptr, MS_DISPEL);
         return;
     }
 
index 9dd1893..fe26e4f 100644 (file)
@@ -155,7 +155,6 @@ void spell_RF6_TELE_TO(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_IDX t
 
     if (TARGET_TYPE == MONSTER_TO_PLAYER) {
         teleport_player_to(target_ptr, m_ptr->fy, m_ptr->fx, TELEPORT_PASSIVE);
-        learn_spell(target_ptr, MS_TELE_TO);
         return;
     }
 
@@ -223,7 +222,6 @@ void spell_RF6_TELE_AWAY(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_IDX
                 msg_print(_("弱い者いじめは止めるんだ!", ""));
         }
 
-        learn_spell(target_ptr, MS_TELE_AWAY);
         teleport_player_away(m_idx, target_ptr, 100, FALSE);
         return;
     }
@@ -292,7 +290,6 @@ void spell_RF6_TELE_LEVEL(player_type *target_ptr, MONSTER_IDX m_idx, MONSTER_ID
             teleport_level(target_ptr, 0);
         }
 
-        learn_spell(target_ptr, MS_TELE_LEVEL);
         update_smart_learn(target_ptr, m_idx, DRS_NEXUS);
         return;
     }
@@ -358,6 +355,7 @@ void spell_RF6_DARKNESS(player_type *target_ptr, POSITION y, POSITION x, MONSTER
         if (can_use_lite_area) {
             (void)lite_area(target_ptr, 0, 3);
         } else {
+            // XXX: ラーニング条件が特技IDのみから決まらないため、やむを得ずここでラーニング処理を行う。
             learn_spell(target_ptr, MS_DARKNESS);
             (void)unlite_area(target_ptr, 0, 3);
         }
@@ -392,7 +390,6 @@ void spell_RF6_TRAPS(player_type *target_ptr, POSITION y, POSITION x, MONSTER_ID
     else
         msg_format(_("%^sが呪文を唱えて邪悪に微笑んだ。", "%^s casts a spell and cackles evilly."), m_name);
 
-    learn_spell(target_ptr, MS_MAKE_TRAP);
     (void)trap_creation(target_ptr, y, x);
 }
 
index cf8c356..4e5e50f 100644 (file)
@@ -9,6 +9,8 @@
  * @param target_ptr プレーヤーへの参照ポインタ
  * @param m_idx モンスターID
  * @return プレイヤーが青魔法で学習できるならTRUE、そうでなければFALSEを返す。
+ *
+ * モンスターが特技を使う前にプレイヤーがモンスターを視認できているかどうかの判定用。
  */
 bool spell_learnable(player_type *target_ptr, MONSTER_IDX m_idx)
 {
index 9c36245..d063214 100644 (file)
@@ -11,9 +11,9 @@
 #include "core/player-redraw-types.h"
 #include "mind/drs-types.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-indice-types.h"
 #include "monster-race/race-flags1.h"
 #include "monster-race/race-flags3.h"
+#include "monster-race/race-indice-types.h"
 #include "monster/monster-describer.h"
 #include "monster/monster-description-types.h"
 #include "monster/monster-info.h"
@@ -221,7 +221,6 @@ void spell_RF5_SCARE(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_i
             (void)set_afraid(target_ptr, target_ptr->afraid + randint0(4) + 4);
         }
 
-        learn_spell(target_ptr, MS_SCARE);
         update_smart_learn(target_ptr, m_idx, DRS_FEAR);
         return;
     }
@@ -266,7 +265,6 @@ void spell_RF5_BLIND(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_i
             (void)set_blind(target_ptr, 12 + randint0(4));
         }
 
-        learn_spell(target_ptr, MS_BLIND);
         update_smart_learn(target_ptr, m_idx, DRS_BLIND);
         return;
     }
@@ -321,7 +319,6 @@ void spell_RF5_CONF(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_id
             (void)set_confused(target_ptr, target_ptr->confused + randint0(4) + 4);
         }
 
-        learn_spell(target_ptr, MS_CONF);
         update_smart_learn(target_ptr, m_idx, DRS_CONF);
         return;
     }
@@ -366,7 +363,6 @@ void spell_RF5_HOLD(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_id
             (void)set_paralyzed(target_ptr, target_ptr->paralyzed + randint0(4) + 4);
         }
 
-        learn_spell(target_ptr, MS_SLEEP);
         update_smart_learn(target_ptr, m_idx, DRS_FREE);
         return;
     }
@@ -438,7 +434,6 @@ void spell_RF5_SLOW(MONSTER_IDX m_idx, player_type *target_ptr, MONSTER_IDX t_id
             (void)set_slow(target_ptr, target_ptr->slow + randint0(4) + 4, FALSE);
         }
 
-        learn_spell(target_ptr, MS_SLOW);
         update_smart_learn(target_ptr, m_idx, DRS_FREE);
         return;
     }
@@ -568,6 +563,4 @@ void spell_RF6_FORGET(player_type *target_ptr, MONSTER_IDX m_idx)
     } else if (lose_all_info(target_ptr)) {
         msg_print(_("記憶が薄れてしまった。", "Your memories fade away."));
     }
-
-    learn_spell(target_ptr, MS_FORGET);
 }
index 3489ef3..2c86c5e 100644 (file)
@@ -140,10 +140,8 @@ HIT_POINT acid_dam(player_type *creature_ptr, HIT_POINT dam, concptr kb_str, int
     int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
     bool double_resist = is_oppose_acid(creature_ptr);
     dam = dam * calc_acid_damage_rate(creature_ptr) / 100;
-    if (dam <= 0) {
-        learn_spell(creature_ptr, monspell);
+    if (dam <= 0)
         return 0;
-    }
 
     if (aura || !check_multishadow(creature_ptr)) {
         if ((!(double_resist || has_resist_acid(creature_ptr))) && one_in_(HURT_CHANCE))
@@ -177,10 +175,8 @@ HIT_POINT elec_dam(player_type *creature_ptr, HIT_POINT dam, concptr kb_str, int
 
     dam = dam * calc_elec_damage_rate(creature_ptr) / 100;
 
-    if (dam <= 0) {
-        learn_spell(creature_ptr, monspell);
+    if (dam <= 0)
         return 0;
-    }
 
     if (aura || !check_multishadow(creature_ptr)) {
         if ((!(double_resist || has_resist_elec(creature_ptr))) && one_in_(HURT_CHANCE))
@@ -210,10 +206,8 @@ HIT_POINT fire_dam(player_type *creature_ptr, HIT_POINT dam, concptr kb_str, int
     bool double_resist = is_oppose_fire(creature_ptr);
 
     /* Totally immune */
-    if (has_immune_fire(creature_ptr) || (dam <= 0)) {
-        learn_spell(creature_ptr, monspell);
+    if (has_immune_fire(creature_ptr) || (dam <= 0))
         return 0;
-    }
 
     dam = dam * calc_fire_damage_rate(creature_ptr) / 100;
     if (aura || !check_multishadow(creature_ptr)) {
@@ -242,10 +236,8 @@ HIT_POINT cold_dam(player_type *creature_ptr, HIT_POINT dam, concptr kb_str, int
 {
     int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
     bool double_resist = is_oppose_cold(creature_ptr);
-    if (has_immune_cold(creature_ptr) || (dam <= 0)) {
-        learn_spell(creature_ptr, monspell);
+    if (has_immune_cold(creature_ptr) || (dam <= 0))
         return 0;
-    }
 
     dam = dam * calc_cold_damage_rate(creature_ptr) / 100;
     if (aura || !check_multishadow(creature_ptr)) {
@@ -295,9 +287,6 @@ int take_hit(player_type *creature_ptr, int damage_type, HIT_POINT damage, concp
         }
     }
 
-    if (monspell >= 0)
-        learn_spell(creature_ptr, monspell);
-
     if ((damage_type != DAMAGE_USELIFE) && (damage_type != DAMAGE_LOSELIFE)) {
         if (is_invuln(creature_ptr) && (damage < 9000)) {
             if (damage_type == DAMAGE_FORCE) {