OSDN Git Service

Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband
[hengband/hengband.git] / src / monster-floor / monster-summon.c
1 #include "monster-floor/monster-summon.h"
2 #include "dungeon/dungeon-flag-types.h"
3 #include "dungeon/dungeon.h"
4 #include "main/sound-definitions-table.h"
5 #include "main/sound-of-music.h"
6 #include "monster-floor/monster-generator.h"
7 #include "monster-floor/place-monster-types.h"
8 #include "monster-race/monster-race-hook.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-flags1.h"
11 #include "monster-race/race-flags7.h"
12 #include "monster/monster-info.h"
13 #include "monster/monster-list.h"
14 #include "monster/monster-util.h"
15 #include "mspell/summon-checker.h"
16 #include "spell/summon-types.h"
17 #include "system/floor-type-definition.h"
18 #include "system/monster-type-definition.h"
19
20 /*!
21  * @var summon_specific_who
22  * @brief 召喚を行ったプレイヤーあるいはモンスターのIDを示すグローバル変数 / Hack -- the index of the summoning monster
23  * @todo summon_specific_who グローバル変数の除去と関数引数への代替を行う
24  */
25 int summon_specific_who = -1;
26
27 /*!
28  * @var summon_unique_okay
29  * @brief 召喚対象にユニークを含めるかを示すグローバル変数 / summoning unique enable
30  * @todo summon_unique_okay グローバル変数の除去と関数引数への代替を行う
31  */
32 bool summon_unique_okay = FALSE;
33
34 /*!
35  * @brief モンスターが召喚の基本条件に合っているかをチェックする / Hack -- help decide if a monster race is "okay" to summon
36  * @param r_idx チェックするモンスター種族ID
37  * @return 召喚対象にできるならばTRUE
38  */
39 static bool summon_specific_okay(player_type *player_ptr, MONRACE_IDX r_idx)
40 {
41     monster_race *r_ptr = &r_info[r_idx];
42     monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[summon_specific_who];
43     if (!mon_hook_dungeon(player_ptr, r_idx))
44         return FALSE;
45
46     if (summon_specific_who > 0) {
47         if (monster_has_hostile_align(player_ptr, m_ptr, 0, 0, r_ptr))
48             return FALSE;
49     } else if (summon_specific_who < 0) {
50         if (monster_has_hostile_align(player_ptr, NULL, 10, -10, r_ptr)) {
51             if (!one_in_(ABS(player_ptr->align) / 2 + 1))
52                 return FALSE;
53         }
54     }
55
56     if (!summon_unique_okay && ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)))
57         return FALSE;
58
59     if (!summon_specific_type)
60         return TRUE;
61
62     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))
63         return FALSE;
64
65     if ((r_ptr->flags7 & RF7_CHAMELEON) && (d_info[player_ptr->dungeon_idx].flags1 & DF1_CHAMELEON))
66         return TRUE;
67
68     return (check_summon_specific(player_ptr, m_ptr->r_idx, r_idx));
69 }
70
71 /*!
72  * @brief モンスター死亡時に召喚されうるモンスターかどうかの判定
73  * @param type モンスター種族ID
74  * @return 召喚されうるならばTRUE (あやしい影として生成されない)
75  */
76 static bool is_dead_summoning(summon_type type)
77 {
78     bool summoning = type == SUMMON_BLUE_HORROR;
79     summoning |= type == SUMMON_DAWN;
80     summoning |= type == SUMMON_TOTEM_MOAI;
81     return summoning;
82 }
83
84 /*!
85  * @brief モンスターを召喚により配置する / Place a monster (of the specified "type") near the given location. Return TRUE if a monster was actually summoned.
86  * @param player_ptr プレーヤーへの参照ポインタ
87  * @param who 召喚主のモンスター情報ID
88  * @param y1 目標地点y座標
89  * @param x1 目標地点x座標
90  * @param lev 相当生成階
91  * @param type 召喚種別
92  * @param mode 生成オプション
93  * @return 召喚できたらtrueを返す
94  */
95 bool summon_specific(player_type *player_ptr, MONSTER_IDX who, POSITION y1, POSITION x1, DEPTH lev, summon_type type, BIT_FLAGS mode)
96 {
97     floor_type *floor_ptr = player_ptr->current_floor_ptr;
98     if (floor_ptr->inside_arena)
99         return FALSE;
100
101     POSITION x, y;
102     if (!mon_scatter(player_ptr, 0, &y, &x, y1, x1, 2))
103         return FALSE;
104
105     summon_specific_who = who;
106     summon_specific_type = type;
107     summon_unique_okay = (mode & PM_ALLOW_UNIQUE) ? TRUE : FALSE;
108     get_mon_num_prep(player_ptr, summon_specific_okay, get_monster_hook2(player_ptr, y, x));
109
110     MONRACE_IDX r_idx = get_mon_num(player_ptr, (floor_ptr->dun_level + lev) / 2 + 5, 0);
111     if (!r_idx) {
112         summon_specific_type = 0;
113         return FALSE;
114     }
115
116     if (is_dead_summoning(type))
117         mode |= PM_NO_KAGE;
118
119     if (!place_monster_aux(player_ptr, who, y, x, r_idx, mode)) {
120         summon_specific_type = 0;
121         return FALSE;
122     }
123
124     summon_specific_type = 0;
125     sound(SOUND_SUMMON);
126     return TRUE;
127 }
128
129 /*!
130  * @brief 特定モンスター種族を召喚により生成する / A "dangerous" function, creates a pet of the specified type
131  * @param player_ptr プレーヤーへの参照ポインタ
132  * @param who 召喚主のモンスター情報ID
133  * @param oy 目標地点y座標
134  * @param ox 目標地点x座標
135  * @param r_idx 生成するモンスター種族ID
136  * @param mode 生成オプション
137  * @return 召喚できたらtrueを返す
138  */
139 bool summon_named_creature(player_type *player_ptr, MONSTER_IDX who, POSITION oy, POSITION ox, MONRACE_IDX r_idx, BIT_FLAGS mode)
140 {
141     if (r_idx >= max_r_idx)
142         return FALSE;
143
144     POSITION x, y;
145     if (player_ptr->current_floor_ptr->inside_arena)
146         return FALSE;
147
148     if (!mon_scatter(player_ptr, r_idx, &y, &x, oy, ox, 2))
149         return FALSE;
150
151     return place_monster_aux(player_ptr, who, y, x, r_idx, (mode | PM_NO_KAGE));
152 }