2 * @brief モンスター情報のアップデート処理
7 #include "monster/monster-update.h"
8 #include "core/disturbance.h"
9 #include "core/player-redraw-types.h"
10 #include "core/player-update-types.h"
11 #include "core/window-redrawer.h"
12 #include "dungeon/dungeon-flag-types.h"
13 #include "dungeon/dungeon.h"
14 #include "floor/cave.h"
15 #include "floor/geometry.h"
16 #include "game-option/birth-options.h"
17 #include "game-option/disturbance-options.h"
18 #include "grid/grid.h"
19 #include "mind/drs-types.h"
20 #include "monster-race/monster-race.h"
21 #include "monster-race/race-flags1.h"
22 #include "monster-race/race-flags2.h"
23 #include "monster-race/race-flags3.h"
24 #include "monster-race/race-flags7.h"
25 #include "monster-race/race-indice-types.h"
26 #include "monster/monster-flag-types.h"
27 #include "monster/monster-info.h"
28 #include "monster/monster-processor-util.h"
29 #include "monster/monster-status.h"
30 #include "monster/smart-learn-types.h"
31 #include "player-base/player-class.h"
32 #include "player-info/samurai-data-type.h"
33 #include "player-info/sniper-data-type.h"
34 #include "player/player-move.h"
35 #include "player/player-status-flags.h"
36 #include "player/special-defense-types.h"
37 #include "status/element-resistance.h"
38 #include "system/floor-type-definition.h"
39 #include "system/grid-type-definition.h"
40 #include "system/monster-race-definition.h"
41 #include "system/monster-type-definition.h"
42 #include "system/player-type-definition.h"
43 #include "target/projection-path-calculator.h"
44 #include "util/bit-flags-calculator.h"
45 #include "world/world.h"
48 typedef struct um_type {
60 * @brief 騎乗中のモンスター情報を更新する
61 * @param player_ptr プレイヤーへの参照ポインタ
62 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
63 * @param m_idx モンスターID
64 * @param oy 移動前の、モンスターのY座標
65 * @param ox 移動前の、モンスターのX座標
66 * @param ny 移動後の、モンスターのY座標
67 * @param ox 移動後の、モンスターのX座標
68 * @return アイテム等に影響を及ぼしたらTRUE
70 bool update_riding_monster(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx)
72 monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
73 grid_type *g_ptr = &player_ptr->current_floor_ptr->grid_array[ny][nx];
74 monster_type *y_ptr = &player_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
75 if (turn_flags_ptr->is_riding_mon)
76 return move_player_effect(player_ptr, ny, nx, MPE_DONT_PICKUP);
78 player_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
82 update_monster(player_ptr, g_ptr->m_idx, true);
88 update_monster(player_ptr, m_idx, true);
90 lite_spot(player_ptr, oy, ox);
91 lite_spot(player_ptr, ny, nx);
96 * @brief updateフィールドを更新する
97 * @param player_ptr プレイヤーへの参照ポインタ
98 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
100 void update_player_type(PlayerType *player_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr)
102 if (turn_flags_ptr->do_view) {
103 player_ptr->update |= PU_FLOW;
104 player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
107 if (turn_flags_ptr->do_move && ((r_ptr->flags7 & (RF7_SELF_LD_MASK | RF7_HAS_DARK_1 | RF7_HAS_DARK_2)) || ((r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_HAS_LITE_2)) && !player_ptr->phase_out))) {
108 player_ptr->update |= PU_MON_LITE;
113 * @brief モンスターのフラグを更新する
114 * @param player_ptr プレイヤーへの参照ポインタ
115 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
116 * @param m_ptr モンスターへの参照ポインタ
118 void update_monster_race_flags(PlayerType *player_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr)
120 monster_race *r_ptr = &r_info[m_ptr->r_idx];
121 if (!is_original_ap_and_seen(player_ptr, m_ptr))
124 if (turn_flags_ptr->did_open_door)
125 r_ptr->r_behavior_flags.set(MonsterBehaviorType::OPEN_DOOR);
127 if (turn_flags_ptr->did_bash_door)
128 r_ptr->r_behavior_flags.set(MonsterBehaviorType::BASH_DOOR);
130 if (turn_flags_ptr->did_take_item)
131 r_ptr->r_behavior_flags.set(MonsterBehaviorType::TAKE_ITEM);
133 if (turn_flags_ptr->did_kill_item)
134 r_ptr->r_behavior_flags.set(MonsterBehaviorType::KILL_ITEM);
136 if (turn_flags_ptr->did_move_body)
137 r_ptr->r_behavior_flags.set(MonsterBehaviorType::MOVE_BODY);
139 if (turn_flags_ptr->did_pass_wall)
140 r_ptr->r_flags2 |= RF2_PASS_WALL;
142 if (turn_flags_ptr->did_kill_wall)
143 r_ptr->r_flags2 |= RF2_KILL_WALL;
147 * @brief モンスターフラグの更新に基づき、モンスター表示を更新する
148 * @param monster_race_idx モンスターID
149 * @param window ウィンドウフラグ
150 * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
152 void update_player_window(PlayerType *player_ptr, old_race_flags *old_race_flags_ptr)
155 r_ptr = &r_info[player_ptr->monster_race_idx];
156 if ((old_race_flags_ptr->old_r_flags1 != r_ptr->r_flags1) || (old_race_flags_ptr->old_r_flags2 != r_ptr->r_flags2) ||
157 (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) || (old_race_flags_ptr->old_r_ability_flags != r_ptr->r_ability_flags) ||
158 (old_race_flags_ptr->old_r_flagsr != r_ptr->r_flagsr) || (old_race_flags_ptr->old_r_blows0 != r_ptr->r_blows[0]) ||
159 (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) || (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2]) ||
160 (old_race_flags_ptr->old_r_blows3 != r_ptr->r_blows[3]) || (old_race_flags_ptr->old_r_cast_spell != r_ptr->r_cast_spell)) {
161 player_ptr->window_flags |= PW_MONSTER;
165 static um_type *initialize_um_type(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx, bool full)
167 um_ptr->m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
168 um_ptr->do_disturb = disturb_move;
169 um_ptr->fy = um_ptr->m_ptr->fy;
170 um_ptr->fx = um_ptr->m_ptr->fx;
171 um_ptr->flag = false;
172 um_ptr->easy = false;
173 um_ptr->in_darkness = d_info[player_ptr->dungeon_idx].flags.has(DungeonFeatureType::DARKNESS) && !player_ptr->see_nocto;
178 static POSITION decide_updated_distance(PlayerType *player_ptr, um_type *um_ptr)
181 return um_ptr->m_ptr->cdis;
183 int dy = (player_ptr->y > um_ptr->fy) ? (player_ptr->y - um_ptr->fy) : (um_ptr->fy - player_ptr->y);
184 int dx = (player_ptr->x > um_ptr->fx) ? (player_ptr->x - um_ptr->fx) : (um_ptr->fx - player_ptr->x);
185 POSITION distance = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
192 um_ptr->m_ptr->cdis = distance;
196 static void update_smart_stupid_flags(monster_race *r_ptr)
198 if (r_ptr->r_behavior_flags.has(MonsterBehaviorType::SMART))
199 r_ptr->r_behavior_flags.set(MonsterBehaviorType::SMART);
201 if (r_ptr->r_behavior_flags.has(MonsterBehaviorType::STUPID))
202 r_ptr->r_behavior_flags.set(MonsterBehaviorType::STUPID);
206 * @brief WEIRD_MINDフラグ持ちのモンスターを1/10の確率でテレパシーに引っかける
207 * @param player_ptr プレイヤーへの参照ポインタ
208 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
209 * @param m_idx モンスターID
210 * @return WEIRD_MINDフラグがあるならTRUE
212 static bool update_weird_telepathy(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
214 monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
215 if ((r_ptr->flags2 & RF2_WEIRD_MIND) == 0)
218 if ((m_idx % 10) != (w_ptr->game_turn % 10))
222 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
223 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated) {
224 r_ptr->r_flags2 |= RF2_WEIRD_MIND;
225 update_smart_stupid_flags(r_ptr);
231 static void update_telepathy_sight(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
233 monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
234 if (PlayerClass(player_ptr).samurai_stance_is(SamuraiStanceType::MUSOU)) {
236 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
237 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
238 update_smart_stupid_flags(r_ptr);
243 if (!player_ptr->telepathy)
246 if (r_ptr->flags2 & RF2_EMPTY_MIND) {
247 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
248 r_ptr->r_flags2 |= RF2_EMPTY_MIND;
253 if (update_weird_telepathy(player_ptr, um_ptr, m_idx))
257 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
258 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
259 update_smart_stupid_flags(r_ptr);
262 static void update_specific_race_telepathy(PlayerType *player_ptr, um_type *um_ptr)
264 monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
265 if ((player_ptr->esp_animal) && (r_ptr->flags3 & RF3_ANIMAL)) {
267 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
268 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
269 r_ptr->r_flags3 |= RF3_ANIMAL;
272 if ((player_ptr->esp_undead) && (r_ptr->flags3 & RF3_UNDEAD)) {
274 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
275 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
276 r_ptr->r_flags3 |= RF3_UNDEAD;
279 if ((player_ptr->esp_demon) && (r_ptr->flags3 & RF3_DEMON)) {
281 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
282 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
283 r_ptr->r_flags3 |= RF3_DEMON;
286 if ((player_ptr->esp_orc) && (r_ptr->flags3 & RF3_ORC)) {
288 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
289 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
290 r_ptr->r_flags3 |= RF3_ORC;
293 if ((player_ptr->esp_troll) && (r_ptr->flags3 & RF3_TROLL)) {
295 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
296 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
297 r_ptr->r_flags3 |= RF3_TROLL;
300 if ((player_ptr->esp_giant) && (r_ptr->flags3 & RF3_GIANT)) {
302 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
303 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
304 r_ptr->r_flags3 |= RF3_GIANT;
307 if ((player_ptr->esp_dragon) && (r_ptr->flags3 & RF3_DRAGON)) {
309 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
310 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
311 r_ptr->r_flags3 |= RF3_DRAGON;
314 if ((player_ptr->esp_human) && (r_ptr->flags2 & RF2_HUMAN)) {
316 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
317 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
318 r_ptr->r_flags2 |= RF2_HUMAN;
321 if ((player_ptr->esp_evil) && (r_ptr->flags3 & RF3_EVIL)) {
323 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
324 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
325 r_ptr->r_flags3 |= RF3_EVIL;
328 if ((player_ptr->esp_good) && (r_ptr->flags3 & RF3_GOOD)) {
330 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
331 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
332 r_ptr->r_flags3 |= RF3_GOOD;
335 if ((player_ptr->esp_nonliving) && ((r_ptr->flags3 & (RF3_DEMON | RF3_UNDEAD | RF3_NONLIVING)) == RF3_NONLIVING)) {
337 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
338 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
339 r_ptr->r_flags3 |= RF3_NONLIVING;
342 if ((player_ptr->esp_unique) && (r_ptr->flags1 & RF1_UNIQUE)) {
344 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
345 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->hallucinated)
346 r_ptr->r_flags1 |= RF1_UNIQUE;
350 static bool check_cold_blood(PlayerType *player_ptr, um_type *um_ptr, const POSITION distance)
352 if (distance > player_ptr->see_infra)
355 monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
356 if (any_bits(r_ptr->flags2, RF2_COLD_BLOOD) && r_ptr->aura_flags.has_not(MonsterAuraType::FIRE))
364 static bool check_invisible(PlayerType *player_ptr, um_type *um_ptr)
366 if (!player_can_see_bold(player_ptr, um_ptr->fy, um_ptr->fx))
369 monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
370 if (r_ptr->flags2 & RF2_INVISIBLE) {
371 if (player_ptr->see_inv) {
384 * @brief テレパシー・赤外線視力・可視透明によってモンスターを感知できるかどうかの判定
385 * @param player_ptr プレイヤーへの参照ポインタ
386 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
388 static void decide_sight_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
390 POSITION distance = decide_updated_distance(player_ptr, um_ptr);
391 monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
393 um_ptr->m_ptr->mflag.reset(MonsterTemporaryFlagType::ESP);
395 if (distance > (um_ptr->in_darkness ? MAX_SIGHT / 2 : MAX_SIGHT))
398 if (!um_ptr->in_darkness || (distance <= MAX_SIGHT / 4)) {
399 update_telepathy_sight(player_ptr, um_ptr, m_idx);
400 update_specific_race_telepathy(player_ptr, um_ptr);
403 if (!player_has_los_bold(player_ptr, um_ptr->fy, um_ptr->fx) || player_ptr->blind)
406 auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
407 if (sniper_data && (sniper_data->concent >= CONCENT_RADAR_THRESHOLD)) {
412 bool do_cold_blood = check_cold_blood(player_ptr, um_ptr, distance);
413 bool do_invisible = check_invisible(player_ptr, um_ptr);
414 if (!um_ptr->flag || !is_original_ap(um_ptr->m_ptr) || player_ptr->hallucinated)
418 r_ptr->r_flags2 |= RF2_INVISIBLE;
421 r_ptr->r_flags2 |= RF2_COLD_BLOOD;
425 * @brief 壁の向こうにいるモンスターへのテレパシー・赤外線視力による冷血動物以外の透明モンスター・可視透明能力による透明モンスター
427 * @param player_ptr プレイヤーへの参照ポインタ
428 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
429 * @param m_idx フロアのモンスター番号
430 * @details 感知した結果、エルドリッチホラー持ちがいたら精神を破壊する
432 static void update_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
434 if (um_ptr->m_ptr->ml)
437 um_ptr->m_ptr->ml = true;
438 lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
440 if (player_ptr->health_who == m_idx)
441 player_ptr->redraw |= PR_HEALTH;
443 if (player_ptr->riding == m_idx)
444 player_ptr->redraw |= PR_UHEALTH;
446 if (!player_ptr->hallucinated) {
447 monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
448 if ((um_ptr->m_ptr->ap_r_idx == MON_KAGE) && (r_info[MON_KAGE].r_sights < MAX_SHORT))
449 r_info[MON_KAGE].r_sights++;
450 else if (is_original_ap(um_ptr->m_ptr) && (r_ptr->r_sights < MAX_SHORT))
454 if (w_ptr->is_loading_now && w_ptr->character_dungeon && !player_ptr->phase_out && r_info[um_ptr->m_ptr->ap_r_idx].flags2 & RF2_ELDRITCH_HORROR)
455 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::SANITY_BLAST);
457 if (disturb_near && (projectable(player_ptr, um_ptr->m_ptr->fy, um_ptr->m_ptr->fx, player_ptr->y, player_ptr->x) && projectable(player_ptr, player_ptr->y, player_ptr->x, um_ptr->m_ptr->fy, um_ptr->m_ptr->fx))) {
458 if (disturb_pets || is_hostile(um_ptr->m_ptr))
459 disturb(player_ptr, true, true);
463 static void update_visible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
465 if (!um_ptr->m_ptr->ml)
468 um_ptr->m_ptr->ml = false;
469 lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
471 if (player_ptr->health_who == m_idx)
472 player_ptr->redraw |= PR_HEALTH;
474 if (player_ptr->riding == m_idx)
475 player_ptr->redraw |= PR_UHEALTH;
477 if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr)))
478 disturb(player_ptr, true, true);
481 static bool update_clear_monster(PlayerType *player_ptr, um_type *um_ptr)
486 if (um_ptr->m_ptr->mflag.has_not(MonsterTemporaryFlagType::VIEW)) {
487 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::VIEW);
488 if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr)))
489 disturb(player_ptr, true, true);
496 * @brief モンスターの各情報を更新する / This function updates the monster record of the given monster
497 * @param m_idx 更新するモンスター情報のID
498 * @param full プレイヤーとの距離更新を行うならばtrue
500 void update_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool full)
503 um_type *um_ptr = initialize_um_type(player_ptr, &tmp_um, m_idx, full);
505 monster_race *ap_r_ptr = &r_info[um_ptr->m_ptr->ap_r_idx];
506 if (ap_r_ptr->r_tkills && ap_r_ptr->level >= player_ptr->lev)
507 um_ptr->do_disturb = true;
510 if (um_ptr->m_ptr->mflag2.has(MonsterConstantFlagType::MARK))
513 decide_sight_invisible_monster(player_ptr, um_ptr, m_idx);
515 update_invisible_monster(player_ptr, um_ptr, m_idx);
517 update_visible_monster(player_ptr, um_ptr, m_idx);
519 if (update_clear_monster(player_ptr, um_ptr) || um_ptr->m_ptr->mflag.has_not(MonsterTemporaryFlagType::VIEW))
522 um_ptr->m_ptr->mflag.reset(MonsterTemporaryFlagType::VIEW);
523 if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr)))
524 disturb(player_ptr, true, true);
528 * @param player_ptr プレイヤーへの参照ポインタ
529 * @brief 単純に生存している全モンスターの更新処理を行う / This function simply updates all the (non-dead) monsters (see above).
530 * @param full 距離更新を行うならtrue
531 * @todo モンスターの感知状況しか更新していないように見える。関数名変更を検討する
533 void update_monsters(PlayerType *player_ptr, bool full)
535 floor_type *floor_ptr = player_ptr->current_floor_ptr;
536 for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
537 monster_type *m_ptr = &floor_ptr->m_list[i];
538 if (!monster_is_valid(m_ptr))
541 update_monster(player_ptr, i, full);
546 * @brief SMART(適格に攻撃を行う)モンスターの学習状況を更新する / Learn about an "observed" resistance.
547 * @param m_idx 更新を行う「モンスター情報ID
550 void update_smart_learn(PlayerType *player_ptr, MONSTER_IDX m_idx, int what)
552 monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
553 monster_race *r_ptr = &r_info[m_ptr->r_idx];
554 if (!smart_learn || (r_ptr->behavior_flags.has(MonsterBehaviorType::STUPID)) || ((r_ptr->behavior_flags.has_not(MonsterBehaviorType::SMART)) && (randint0(100) < 50)))
559 if (has_resist_acid(player_ptr))
560 m_ptr->smart.set(MonsterSmartLearnType::RES_ACID);
562 if (is_oppose_acid(player_ptr))
563 m_ptr->smart.set(MonsterSmartLearnType::OPP_ACID);
565 if (has_immune_acid(player_ptr))
566 m_ptr->smart.set(MonsterSmartLearnType::IMM_ACID);
570 if (has_resist_elec(player_ptr))
571 m_ptr->smart.set(MonsterSmartLearnType::RES_ELEC);
573 if (is_oppose_elec(player_ptr))
574 m_ptr->smart.set(MonsterSmartLearnType::OPP_ELEC);
576 if (has_immune_elec(player_ptr))
577 m_ptr->smart.set(MonsterSmartLearnType::IMM_ELEC);
581 if (has_resist_fire(player_ptr))
582 m_ptr->smart.set(MonsterSmartLearnType::RES_FIRE);
584 if (is_oppose_fire(player_ptr))
585 m_ptr->smart.set(MonsterSmartLearnType::OPP_FIRE);
587 if (has_immune_fire(player_ptr))
588 m_ptr->smart.set(MonsterSmartLearnType::IMM_FIRE);
592 if (has_resist_cold(player_ptr))
593 m_ptr->smart.set(MonsterSmartLearnType::RES_COLD);
595 if (is_oppose_cold(player_ptr))
596 m_ptr->smart.set(MonsterSmartLearnType::OPP_COLD);
598 if (has_immune_cold(player_ptr))
599 m_ptr->smart.set(MonsterSmartLearnType::IMM_COLD);
603 if (has_resist_pois(player_ptr))
604 m_ptr->smart.set(MonsterSmartLearnType::RES_POIS);
606 if (is_oppose_pois(player_ptr))
607 m_ptr->smart.set(MonsterSmartLearnType::OPP_POIS);
611 if (has_resist_neth(player_ptr))
612 m_ptr->smart.set(MonsterSmartLearnType::RES_NETH);
616 if (has_resist_lite(player_ptr))
617 m_ptr->smart.set(MonsterSmartLearnType::RES_LITE);
621 if (has_resist_dark(player_ptr))
622 m_ptr->smart.set(MonsterSmartLearnType::RES_DARK);
626 if (has_resist_fear(player_ptr))
627 m_ptr->smart.set(MonsterSmartLearnType::RES_FEAR);
631 if (has_resist_conf(player_ptr))
632 m_ptr->smart.set(MonsterSmartLearnType::RES_CONF);
636 if (has_resist_chaos(player_ptr))
637 m_ptr->smart.set(MonsterSmartLearnType::RES_CHAOS);
641 if (has_resist_disen(player_ptr))
642 m_ptr->smart.set(MonsterSmartLearnType::RES_DISEN);
646 if (has_resist_blind(player_ptr))
647 m_ptr->smart.set(MonsterSmartLearnType::RES_BLIND);
651 if (has_resist_nexus(player_ptr))
652 m_ptr->smart.set(MonsterSmartLearnType::RES_NEXUS);
656 if (has_resist_sound(player_ptr))
657 m_ptr->smart.set(MonsterSmartLearnType::RES_SOUND);
661 if (has_resist_shard(player_ptr))
662 m_ptr->smart.set(MonsterSmartLearnType::RES_SHARD);
666 if (player_ptr->free_act)
667 m_ptr->smart.set(MonsterSmartLearnType::IMM_FREE);
671 if (!player_ptr->msp)
672 m_ptr->smart.set(MonsterSmartLearnType::IMM_MANA);
676 if (has_reflect(player_ptr))
677 m_ptr->smart.set(MonsterSmartLearnType::IMM_REFLECT);