OSDN Git Service

[Fix] 荒野のモンスターの召喚が弱くなっている #337 / Wilderness monster's summoning is weaken.
[hengbandforosx/hengbandosx.git] / src / monster-floor / monster-summon.c
index e27e07e..c6c7320 100644 (file)
@@ -1,17 +1,21 @@
 #include "monster-floor/monster-summon.h"
+#include "dungeon/dungeon-flag-types.h"
 #include "dungeon/dungeon.h"
-#include "floor/floor.h"
+#include "floor/wild.h"
 #include "main/sound-definitions-table.h"
+#include "main/sound-of-music.h"
 #include "monster-floor/monster-generator.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-flags1.h"
 #include "monster-race/race-flags7.h"
 #include "monster/monster-info.h"
 #include "monster/monster-list.h"
 #include "monster/monster-util.h"
 #include "mspell/summon-checker.h"
-#include "spell/spells-summon.h"
+#include "spell/summon-types.h"
+#include "system/floor-type-definition.h"
 #include "system/monster-type-definition.h"
 
 /*!
@@ -29,26 +33,23 @@ int summon_specific_who = -1;
 bool summon_unique_okay = FALSE;
 
 /*!
- * todo ここにplayer_typeを追加すると関数ポインタ周りの収拾がつかなくなるので保留
  * @brief モンスターが召喚の基本条件に合っているかをチェックする / Hack -- help decide if a monster race is "okay" to summon
  * @param r_idx チェックするモンスター種族ID
  * @return 召喚対象にできるならばTRUE
  */
-static bool summon_specific_okay(MONRACE_IDX r_idx)
+static bool summon_specific_okay(player_type *player_ptr, MONRACE_IDX r_idx)
 {
     monster_race *r_ptr = &r_info[r_idx];
-    monster_type *m_ptr = &p_ptr->current_floor_ptr->m_list[summon_specific_who];
-    if (!mon_hook_dungeon(r_idx))
+    if (!mon_hook_dungeon(player_ptr, r_idx))
         return FALSE;
 
     if (summon_specific_who > 0) {
-        if (monster_has_hostile_align(p_ptr, m_ptr, 0, 0, r_ptr))
+        monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[summon_specific_who];
+        if (monster_has_hostile_align(player_ptr, m_ptr, 0, 0, r_ptr))
             return FALSE;
     } else if (summon_specific_who < 0) {
-        if (monster_has_hostile_align(p_ptr, NULL, 10, -10, r_ptr)) {
-            if (!one_in_(ABS(p_ptr->align) / 2 + 1))
-                return FALSE;
-        }
+        if (monster_has_hostile_align(player_ptr, NULL, 10, -10, r_ptr) && !one_in_(ABS(player_ptr->align) / 2 + 1))
+            return FALSE;
     }
 
     if (!summon_unique_okay && ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)))
@@ -57,13 +58,49 @@ static bool summon_specific_okay(MONRACE_IDX r_idx)
     if (!summon_specific_type)
         return TRUE;
 
-    if ((summon_specific_who < 0) && ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)) && monster_has_hostile_align(p_ptr, NULL, 10, -10, r_ptr))
+    if ((summon_specific_who < 0) && ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL))
+        && monster_has_hostile_align(player_ptr, NULL, 10, -10, r_ptr))
         return FALSE;
 
-    if ((r_ptr->flags7 & RF7_CHAMELEON) && (d_info[p_ptr->dungeon_idx].flags1 & DF1_CHAMELEON))
+    if ((r_ptr->flags7 & RF7_CHAMELEON) && (d_info[player_ptr->dungeon_idx].flags1 & DF1_CHAMELEON))
         return TRUE;
 
-    return (check_summon_specific(p_ptr, m_ptr->r_idx, r_idx));
+    if (summon_specific_who > 0) {
+        monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[summon_specific_who];
+        return check_summon_specific(player_ptr, m_ptr->r_idx, r_idx);
+    } else {
+        return check_summon_specific(player_ptr, 0, r_idx);
+    }
+}
+
+/*!
+ * @brief モンスター死亡時に召喚されうるモンスターかどうかの判定
+ * @param type モンスター種族ID
+ * @return 召喚されうるならばTRUE (あやしい影として生成されない)
+ */
+static bool is_dead_summoning(summon_type type)
+{
+    bool summoning = type == SUMMON_BLUE_HORROR;
+    summoning |= type == SUMMON_DAWN;
+    summoning |= type == SUMMON_TOTEM_MOAI;
+    return summoning;
+}
+
+/*!
+ * @brief 荒野のレベルを含めた階層レベルを返す
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @return 階層レベル
+ * @detail
+ * ダンジョン及びクエストはdun_level>0となる。
+ * 荒野はdun_level==0なので、その場合荒野レベルを返す。
+ */
+DEPTH get_dungeon_or_wilderness_level(player_type *player_ptr)
+{
+    floor_type *floor_ptr = player_ptr->current_floor_ptr;
+    if (floor_ptr->dun_level > 0)
+        return floor_ptr->dun_level;
+
+    return wilderness[player_ptr->wilderness_y][player_ptr->wilderness_x].level;
 }
 
 /*!
@@ -77,7 +114,7 @@ static bool summon_specific_okay(MONRACE_IDX r_idx)
  * @param mode 生成オプション
  * @return 召喚できたらtrueを返す
  */
-bool summon_specific(player_type *player_ptr, MONSTER_IDX who, POSITION y1, POSITION x1, DEPTH lev, int type, BIT_FLAGS mode)
+bool summon_specific(player_type *player_ptr, MONSTER_IDX who, POSITION y1, POSITION x1, DEPTH lev, summon_type type, BIT_FLAGS mode)
 {
     floor_type *floor_ptr = player_ptr->current_floor_ptr;
     if (floor_ptr->inside_arena)
@@ -89,16 +126,17 @@ bool summon_specific(player_type *player_ptr, MONSTER_IDX who, POSITION y1, POSI
 
     summon_specific_who = who;
     summon_specific_type = type;
-    summon_unique_okay = (mode & PM_ALLOW_UNIQUE) ? TRUE : FALSE;
+    summon_unique_okay = (mode & PM_ALLOW_UNIQUE) != 0;
     get_mon_num_prep(player_ptr, summon_specific_okay, get_monster_hook2(player_ptr, y, x));
 
-    MONRACE_IDX r_idx = get_mon_num(player_ptr, (floor_ptr->dun_level + lev) / 2 + 5, 0);
+    DEPTH dlev = get_dungeon_or_wilderness_level(player_ptr);
+    MONRACE_IDX r_idx = get_mon_num(player_ptr, 0, (dlev + lev) / 2 + 5, 0);
     if (!r_idx) {
         summon_specific_type = 0;
         return FALSE;
     }
 
-    if ((type == SUMMON_BLUE_HORROR) || (type == SUMMON_DAWN))
+    if (is_dead_summoning(type))
         mode |= PM_NO_KAGE;
 
     if (!place_monster_aux(player_ptr, who, y, x, r_idx, mode)) {
@@ -127,10 +165,7 @@ bool summon_named_creature(player_type *player_ptr, MONSTER_IDX who, POSITION oy
         return FALSE;
 
     POSITION x, y;
-    if (player_ptr->current_floor_ptr->inside_arena)
-        return FALSE;
-
-    if (!mon_scatter(player_ptr, r_idx, &y, &x, oy, ox, 2))
+    if (player_ptr->current_floor_ptr->inside_arena || !mon_scatter(player_ptr, r_idx, &y, &x, oy, ox, 2))
         return FALSE;
 
     return place_monster_aux(player_ptr, who, y, x, r_idx, (mode | PM_NO_KAGE));