1 #include "monster/monster-util.h"
2 #include "dungeon/dungeon.h"
3 #include "dungeon/quest.h"
4 #include "floor/floor.h"
6 #include "floor/wild.h"
7 #include "monster-race/monster-race.h"
8 #include "monster-race/race-flags-ability1.h"
9 #include "monster-race/race-flags-ability2.h"
10 #include "monster-race/race-flags1.h"
11 #include "monster-race/race-flags4.h"
12 #include "monster-race/race-flags7.h"
13 #include "monster-race/monster-race-hook.h"
14 #include "monster-race/race-indice-types.h"
15 #include "mspell/mspell-mask-definitions.h"
16 #include "spell/spells-summon.h"
17 #include "system/alloc-entries.h"
18 #include "system/floor-type-definition.h"
19 #include "util/bit-flags-calculator.h"
21 MONSTER_IDX hack_m_idx = 0; /* Hack -- see "process_monsters()" */
22 MONSTER_IDX hack_m_idx_ii = 0;
25 * @var chameleon_change_m_idx
26 * @brief カメレオンの変身先モンスターIDを受け渡すためのグローバル変数
27 * @todo 変数渡しの問題などもあるができればchameleon_change_m_idxのグローバル変数を除去し、関数引き渡しに移行すること
29 int chameleon_change_m_idx = 0;
32 * @var summon_specific_type
33 * @brief 召喚条件を指定するグローバル変数 / Hack -- the "type" of the current "summon specific"
34 * @todo summon_specific_typeグローバル変数の除去と関数引数への代替を行う
36 int summon_specific_type = 0;
38 static monsterrace_hook_type get_mon_num_hook;
39 static monsterrace_hook_type get_mon_num2_hook;
42 * todo ここには本来floor_type*を追加したいが、monster.hにfloor.hの参照を追加するとコンパイルエラーが出るので保留
43 * @brief 指定されたモンスター種族がダンジョンの制限にかかるかどうかをチェックする / Some dungeon types restrict the possible monsters.
44 * @param player_ptr プレーヤーへの参照ポインタ
45 * @param r_idx チェックするモンスター種族ID
46 * @return 召喚条件が一致するならtrue / Return TRUE is the monster is OK and FALSE otherwise
48 static bool restrict_monster_to_dungeon(player_type *player_ptr, MONRACE_IDX r_idx)
50 DUNGEON_IDX d_idx = player_ptr->dungeon_idx;
51 dungeon_type *d_ptr = &d_info[d_idx];
52 monster_race *r_ptr = &r_info[r_idx];
54 if (d_ptr->flags1 & DF1_CHAMELEON) {
55 if (chameleon_change_m_idx)
59 if (d_ptr->flags1 & DF1_NO_MAGIC) {
60 if (r_idx != MON_CHAMELEON && r_ptr->freq_spell && !(r_ptr->flags4 & RF4_NOMAGIC_MASK) && !(r_ptr->a_ability_flags1 & RF5_NOMAGIC_MASK)
61 && !(r_ptr->a_ability_flags2 & RF6_NOMAGIC_MASK))
65 if (d_ptr->flags1 & DF1_NO_MELEE) {
66 if (r_idx == MON_CHAMELEON)
68 if (!(r_ptr->flags4 & (RF4_BOLT_MASK | RF4_BEAM_MASK | RF4_BALL_MASK))
69 && !(r_ptr->a_ability_flags1
70 & (RF5_BOLT_MASK | RF5_BEAM_MASK | RF5_BALL_MASK | RF5_CAUSE_1 | RF5_CAUSE_2 | RF5_CAUSE_3 | RF5_CAUSE_4 | RF5_MIND_BLAST | RF5_BRAIN_SMASH))
71 && !(r_ptr->a_ability_flags2 & (RF6_BOLT_MASK | RF6_BEAM_MASK | RF6_BALL_MASK)))
75 floor_type *floor_ptr = player_ptr->current_floor_ptr;
76 if (d_ptr->flags1 & DF1_BEGINNER) {
77 if (r_ptr->level > floor_ptr->dun_level)
81 if (d_ptr->special_div >= 64)
83 if (summon_specific_type && !(d_ptr->flags1 & DF1_CHAMELEON))
87 switch (d_ptr->mode) {
88 case DUNGEON_MODE_AND: {
90 if ((d_ptr->mflags1 & r_ptr->flags1) != d_ptr->mflags1)
95 if ((d_ptr->mflags2 & r_ptr->flags2) != d_ptr->mflags2)
100 if ((d_ptr->mflags3 & r_ptr->flags3) != d_ptr->mflags3)
104 if (d_ptr->mflags4) {
105 if ((d_ptr->mflags4 & r_ptr->flags4) != d_ptr->mflags4)
109 if (d_ptr->m_a_ability_flags1) {
110 if ((d_ptr->m_a_ability_flags1 & r_ptr->a_ability_flags1) != d_ptr->m_a_ability_flags1)
114 if (d_ptr->m_a_ability_flags2) {
115 if ((d_ptr->m_a_ability_flags2 & r_ptr->a_ability_flags2) != d_ptr->m_a_ability_flags2)
119 if (d_ptr->mflags7) {
120 if ((d_ptr->mflags7 & r_ptr->flags7) != d_ptr->mflags7)
124 if (d_ptr->mflags8) {
125 if ((d_ptr->mflags8 & r_ptr->flags8) != d_ptr->mflags8)
129 if (d_ptr->mflags9) {
130 if ((d_ptr->mflags9 & r_ptr->flags9) != d_ptr->mflags9)
134 if (d_ptr->mflagsr) {
135 if ((d_ptr->mflagsr & r_ptr->flagsr) != d_ptr->mflagsr)
139 for (a = 0; a < 5; a++)
140 if (d_ptr->r_char[a] && (d_ptr->r_char[a] != r_ptr->d_char))
145 case DUNGEON_MODE_NAND: {
146 if (d_ptr->mflags1) {
147 if ((d_ptr->mflags1 & r_ptr->flags1) != d_ptr->mflags1)
151 if (d_ptr->mflags2) {
152 if ((d_ptr->mflags2 & r_ptr->flags2) != d_ptr->mflags2)
156 if (d_ptr->mflags3) {
157 if ((d_ptr->mflags3 & r_ptr->flags3) != d_ptr->mflags3)
161 if (d_ptr->mflags4) {
162 if ((d_ptr->mflags4 & r_ptr->flags4) != d_ptr->mflags4)
166 if (d_ptr->m_a_ability_flags1) {
167 if ((d_ptr->m_a_ability_flags1 & r_ptr->a_ability_flags1) != d_ptr->m_a_ability_flags1)
171 if (d_ptr->m_a_ability_flags2) {
172 if ((d_ptr->m_a_ability_flags2 & r_ptr->a_ability_flags2) != d_ptr->m_a_ability_flags2)
176 if (d_ptr->mflags7) {
177 if ((d_ptr->mflags7 & r_ptr->flags7) != d_ptr->mflags7)
181 if (d_ptr->mflags8) {
182 if ((d_ptr->mflags8 & r_ptr->flags8) != d_ptr->mflags8)
186 if (d_ptr->mflags9) {
187 if ((d_ptr->mflags9 & r_ptr->flags9) != d_ptr->mflags9)
191 if (d_ptr->mflagsr) {
192 if ((d_ptr->mflagsr & r_ptr->flagsr) != d_ptr->mflagsr)
196 for (a = 0; a < 5; a++)
197 if (d_ptr->r_char[a] && (d_ptr->r_char[a] != r_ptr->d_char))
202 case DUNGEON_MODE_OR: {
203 if (r_ptr->flags1 & d_ptr->mflags1)
205 if (r_ptr->flags2 & d_ptr->mflags2)
207 if (r_ptr->flags3 & d_ptr->mflags3)
209 if (r_ptr->flags4 & d_ptr->mflags4)
211 if (r_ptr->a_ability_flags1 & d_ptr->m_a_ability_flags1)
213 if (r_ptr->a_ability_flags2 & d_ptr->m_a_ability_flags2)
215 if (r_ptr->flags7 & d_ptr->mflags7)
217 if (r_ptr->flags8 & d_ptr->mflags8)
219 if (r_ptr->flags9 & d_ptr->mflags9)
221 if (r_ptr->flagsr & d_ptr->mflagsr)
223 for (a = 0; a < 5; a++)
224 if (d_ptr->r_char[a] == r_ptr->d_char)
229 case DUNGEON_MODE_NOR: {
230 if (r_ptr->flags1 & d_ptr->mflags1)
232 if (r_ptr->flags2 & d_ptr->mflags2)
234 if (r_ptr->flags3 & d_ptr->mflags3)
236 if (r_ptr->flags4 & d_ptr->mflags4)
238 if (r_ptr->a_ability_flags1 & d_ptr->m_a_ability_flags1)
240 if (r_ptr->a_ability_flags2 & d_ptr->m_a_ability_flags2)
242 if (r_ptr->flags7 & d_ptr->mflags7)
244 if (r_ptr->flags8 & d_ptr->mflags8)
246 if (r_ptr->flags9 & d_ptr->mflags9)
248 if (r_ptr->flagsr & d_ptr->mflagsr)
250 for (a = 0; a < 5; a++)
251 if (d_ptr->r_char[a] == r_ptr->d_char)
262 * @brief プレイヤーの現在の広域マップ座標から得た地勢を元にモンスターの生成条件関数を返す
263 * @param player_ptr プレーヤーへの参照ポインタ
264 * @return 地勢にあったモンスターの生成条件関数
266 monsterrace_hook_type get_monster_hook(player_type *player_ptr)
268 if ((player_ptr->current_floor_ptr->dun_level > 0) || (player_ptr->current_floor_ptr->inside_quest > 0))
269 return (monsterrace_hook_type)mon_hook_dungeon;
271 switch (wilderness[player_ptr->wilderness_y][player_ptr->wilderness_x].terrain) {
273 return (monsterrace_hook_type)mon_hook_town;
274 case TERRAIN_DEEP_WATER:
275 return (monsterrace_hook_type)mon_hook_ocean;
276 case TERRAIN_SHALLOW_WATER:
278 return (monsterrace_hook_type)mon_hook_shore;
281 return (monsterrace_hook_type)mon_hook_waste;
283 return (monsterrace_hook_type)mon_hook_grass;
285 return (monsterrace_hook_type)mon_hook_wood;
286 case TERRAIN_SHALLOW_LAVA:
287 case TERRAIN_DEEP_LAVA:
288 return (monsterrace_hook_type)mon_hook_volcano;
289 case TERRAIN_MOUNTAIN:
290 return (monsterrace_hook_type)mon_hook_mountain;
292 return (monsterrace_hook_type)mon_hook_dungeon;
297 * @brief 指定された広域マップ座標の地勢を元にモンスターの生成条件関数を返す
298 * @return 地勢にあったモンスターの生成条件関数
300 monsterrace_hook_type get_monster_hook2(player_type *player_ptr, POSITION y, POSITION x)
302 feature_type *f_ptr = &f_info[player_ptr->current_floor_ptr->grid_array[y][x].feat];
303 if (have_flag(f_ptr->flags, FF_WATER)) {
304 if (have_flag(f_ptr->flags, FF_DEEP)) {
305 return (monsterrace_hook_type)mon_hook_deep_water;
307 return (monsterrace_hook_type)mon_hook_shallow_water;
311 if (have_flag(f_ptr->flags, FF_LAVA)) {
312 return (monsterrace_hook_type)mon_hook_lava;
315 return (monsterrace_hook_type)mon_hook_floor;
319 * @brief モンスター生成制限関数最大2つから / Apply a "monster restriction function" to the "monster allocation table"
320 * @param player_ptr プレーヤーへの参照ポインタ
321 * @param monster_hook 制限関数1
322 * @param monster_hook2 制限関数2
325 errr get_mon_num_prep(player_type *player_ptr, monsterrace_hook_type monster_hook, monsterrace_hook_type monster_hook2)
327 /* Todo: Check the hooks for non-changes */
328 get_mon_num_hook = monster_hook;
329 get_mon_num2_hook = monster_hook2;
331 floor_type *floor_ptr = player_ptr->current_floor_ptr;
332 for (int i = 0; i < alloc_race_size; i++) {
334 alloc_entry *entry = &alloc_race_table[i];
336 r_ptr = &r_info[entry->index];
338 if ((get_mon_num_hook && !((*get_mon_num_hook)(player_ptr, entry->index))) || (get_mon_num2_hook && !((*get_mon_num2_hook)(player_ptr, entry->index))))
341 if (!player_ptr->phase_out && !chameleon_change_m_idx && summon_specific_type != SUMMON_GUARDIANS) {
342 if (r_ptr->flags1 & RF1_QUESTOR)
345 if (r_ptr->flags7 & RF7_GUARDIAN)
348 if ((r_ptr->flags1 & (RF1_FORCE_DEPTH)) && (r_ptr->level > floor_ptr->dun_level))
352 entry->prob2 = entry->prob1;
353 if (floor_ptr->dun_level && (!floor_ptr->inside_quest || is_fixed_quest_idx(floor_ptr->inside_quest))
354 && !restrict_monster_to_dungeon(player_ptr, entry->index) && !player_ptr->phase_out) {
355 int hoge = entry->prob2 * d_info[player_ptr->dungeon_idx].special_div;
356 entry->prob2 = hoge / 64;
357 if (randint0(64) < (hoge & 0x3f))