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 "timed-effect/player-hallucination.h"
45 #include "timed-effect/timed-effects.h"
46 #include "util/bit-flags-calculator.h"
47 #include "world/world.h"
62 * @brief 騎乗中のモンスター情報を更新する
63 * @param player_ptr プレイヤーへの参照ポインタ
64 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
65 * @param m_idx モンスターID
66 * @param oy 移動前の、モンスターのY座標
67 * @param ox 移動前の、モンスターのX座標
68 * @param ny 移動後の、モンスターのY座標
69 * @param ox 移動後の、モンスターのX座標
70 * @return アイテム等に影響を及ぼしたらTRUE
72 bool update_riding_monster(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx)
74 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
75 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[ny][nx];
76 monster_type *y_ptr = &player_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
77 if (turn_flags_ptr->is_riding_mon) {
78 return move_player_effect(player_ptr, ny, nx, MPE_DONT_PICKUP);
81 player_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
85 update_monster(player_ptr, g_ptr->m_idx, true);
91 update_monster(player_ptr, m_idx, true);
93 lite_spot(player_ptr, oy, ox);
94 lite_spot(player_ptr, ny, nx);
99 * @brief updateフィールドを更新する
100 * @param player_ptr プレイヤーへの参照ポインタ
101 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
103 void update_player_type(PlayerType *player_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr)
105 if (turn_flags_ptr->do_view) {
106 player_ptr->update |= PU_FLOW;
107 player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
110 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))) {
111 player_ptr->update |= PU_MON_LITE;
116 * @brief モンスターのフラグを更新する
117 * @param player_ptr プレイヤーへの参照ポインタ
118 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
119 * @param m_ptr モンスターへの参照ポインタ
121 void update_monster_race_flags(PlayerType *player_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr)
123 auto *r_ptr = &r_info[m_ptr->r_idx];
124 if (!is_original_ap_and_seen(player_ptr, m_ptr)) {
128 if (turn_flags_ptr->did_open_door) {
129 r_ptr->r_behavior_flags.set(MonsterBehaviorType::OPEN_DOOR);
132 if (turn_flags_ptr->did_bash_door) {
133 r_ptr->r_behavior_flags.set(MonsterBehaviorType::BASH_DOOR);
136 if (turn_flags_ptr->did_take_item) {
137 r_ptr->r_behavior_flags.set(MonsterBehaviorType::TAKE_ITEM);
140 if (turn_flags_ptr->did_kill_item) {
141 r_ptr->r_behavior_flags.set(MonsterBehaviorType::KILL_ITEM);
144 if (turn_flags_ptr->did_move_body) {
145 r_ptr->r_behavior_flags.set(MonsterBehaviorType::MOVE_BODY);
148 if (turn_flags_ptr->did_pass_wall) {
149 r_ptr->r_flags2 |= RF2_PASS_WALL;
152 if (turn_flags_ptr->did_kill_wall) {
153 r_ptr->r_flags2 |= RF2_KILL_WALL;
158 * @brief モンスターフラグの更新に基づき、モンスター表示を更新する
159 * @param monster_race_idx モンスターID
160 * @param window ウィンドウフラグ
161 * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
163 void update_player_window(PlayerType *player_ptr, old_race_flags *old_race_flags_ptr)
166 r_ptr = &r_info[player_ptr->monster_race_idx];
167 if ((old_race_flags_ptr->old_r_flags1 != r_ptr->r_flags1) || (old_race_flags_ptr->old_r_flags2 != r_ptr->r_flags2) ||
168 (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) || (old_race_flags_ptr->old_r_ability_flags != r_ptr->r_ability_flags) ||
169 (old_race_flags_ptr->old_r_resistance_flags != r_ptr->r_resistance_flags) || (old_race_flags_ptr->old_r_blows0 != r_ptr->r_blows[0]) ||
170 (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) || (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2]) ||
171 (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) ||
172 (old_race_flags_ptr->old_r_behavior_flags != r_ptr->r_behavior_flags) || (old_race_flags_ptr->old_r_kind_flags != r_ptr->r_kind_flags)) {
173 player_ptr->window_flags |= PW_MONSTER;
177 static um_type *initialize_um_type(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx, bool full)
179 um_ptr->m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
180 um_ptr->do_disturb = disturb_move;
181 um_ptr->fy = um_ptr->m_ptr->fy;
182 um_ptr->fx = um_ptr->m_ptr->fx;
183 um_ptr->flag = false;
184 um_ptr->easy = false;
185 um_ptr->in_darkness = d_info[player_ptr->dungeon_idx].flags.has(DungeonFeatureType::DARKNESS) && !player_ptr->see_nocto;
190 static POSITION decide_updated_distance(PlayerType *player_ptr, um_type *um_ptr)
193 return um_ptr->m_ptr->cdis;
196 int dy = (player_ptr->y > um_ptr->fy) ? (player_ptr->y - um_ptr->fy) : (um_ptr->fy - player_ptr->y);
197 int dx = (player_ptr->x > um_ptr->fx) ? (player_ptr->x - um_ptr->fx) : (um_ptr->fx - player_ptr->x);
198 POSITION distance = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
199 if (distance > 255) {
207 um_ptr->m_ptr->cdis = distance;
211 static void update_smart_stupid_flags(monster_race *r_ptr)
213 if (r_ptr->r_behavior_flags.has(MonsterBehaviorType::SMART)) {
214 r_ptr->r_behavior_flags.set(MonsterBehaviorType::SMART);
217 if (r_ptr->r_behavior_flags.has(MonsterBehaviorType::STUPID)) {
218 r_ptr->r_behavior_flags.set(MonsterBehaviorType::STUPID);
223 * @brief WEIRD_MINDフラグ持ちのモンスターを1/10の確率でテレパシーに引っかける
224 * @param player_ptr プレイヤーへの参照ポインタ
225 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
226 * @param m_idx モンスターID
227 * @return WEIRD_MINDフラグがあるならTRUE
229 static bool update_weird_telepathy(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
231 auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
232 if ((r_ptr->flags2 & RF2_WEIRD_MIND) == 0) {
236 if ((m_idx % 10) != (w_ptr->game_turn % 10)) {
241 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
242 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->effects()->hallucination()->is_hallucinated()) {
243 r_ptr->r_flags2 |= RF2_WEIRD_MIND;
244 update_smart_stupid_flags(r_ptr);
250 static void update_telepathy_sight(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
252 auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
253 if (PlayerClass(player_ptr).samurai_stance_is(SamuraiStanceType::MUSOU)) {
255 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
256 if (is_original_ap(um_ptr->m_ptr) && !player_ptr->effects()->hallucination()->is_hallucinated()) {
257 update_smart_stupid_flags(r_ptr);
263 if (!player_ptr->telepathy) {
267 auto is_hallucinated = player_ptr->effects()->hallucination()->is_hallucinated();
268 if (r_ptr->flags2 & RF2_EMPTY_MIND) {
269 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
270 r_ptr->r_flags2 |= RF2_EMPTY_MIND;
276 if (update_weird_telepathy(player_ptr, um_ptr, m_idx)) {
281 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
282 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
283 update_smart_stupid_flags(r_ptr);
287 static void update_specific_race_telepathy(PlayerType *player_ptr, um_type *um_ptr)
289 auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
290 auto is_hallucinated = player_ptr->effects()->hallucination()->is_hallucinated();
291 if ((player_ptr->esp_animal) && r_ptr->kind_flags.has(MonsterKindType::ANIMAL)) {
293 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
294 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
295 r_ptr->r_kind_flags.set(MonsterKindType::ANIMAL);
299 if ((player_ptr->esp_undead) && r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
301 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
302 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
303 r_ptr->r_kind_flags.set(MonsterKindType::UNDEAD);
307 if ((player_ptr->esp_demon) && r_ptr->kind_flags.has(MonsterKindType::DEMON)) {
309 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
310 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
311 r_ptr->r_kind_flags.set(MonsterKindType::DEMON);
315 if ((player_ptr->esp_orc) && r_ptr->kind_flags.has(MonsterKindType::ORC)) {
317 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
318 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
319 r_ptr->r_kind_flags.set(MonsterKindType::ORC);
323 if ((player_ptr->esp_troll) && r_ptr->kind_flags.has(MonsterKindType::TROLL)) {
325 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
326 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
327 r_ptr->r_kind_flags.set(MonsterKindType::TROLL);
331 if ((player_ptr->esp_giant) && r_ptr->kind_flags.has(MonsterKindType::GIANT)) {
333 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
334 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
335 r_ptr->r_kind_flags.set(MonsterKindType::GIANT);
339 if ((player_ptr->esp_dragon) && r_ptr->kind_flags.has(MonsterKindType::DRAGON)) {
341 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
342 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
343 r_ptr->r_kind_flags.set(MonsterKindType::DRAGON);
347 if ((player_ptr->esp_human) && r_ptr->kind_flags.has(MonsterKindType::HUMAN)) {
349 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
350 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
351 r_ptr->r_kind_flags.set(MonsterKindType::HUMAN);
355 if ((player_ptr->esp_evil) && r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
357 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
358 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
359 r_ptr->r_kind_flags.set(MonsterKindType::EVIL);
363 if ((player_ptr->esp_good) && r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
365 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
366 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
367 r_ptr->r_kind_flags.set(MonsterKindType::GOOD);
371 if ((player_ptr->esp_nonliving) && (r_ptr->kind_flags.has(MonsterKindType::NONLIVING) && r_ptr->kind_flags.has_none_of({ MonsterKindType::DEMON, MonsterKindType::UNDEAD }))) {
373 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
374 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
375 r_ptr->r_kind_flags.set(MonsterKindType::NONLIVING);
379 if ((player_ptr->esp_unique) && r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
381 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
382 if (is_original_ap(um_ptr->m_ptr) && !is_hallucinated) {
383 r_ptr->r_kind_flags.set(MonsterKindType::UNIQUE);
388 static bool check_cold_blood(PlayerType *player_ptr, um_type *um_ptr, const POSITION distance)
390 if (distance > player_ptr->see_infra) {
394 auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
395 if (any_bits(r_ptr->flags2, RF2_COLD_BLOOD) && r_ptr->aura_flags.has_not(MonsterAuraType::FIRE)) {
404 static bool check_invisible(PlayerType *player_ptr, um_type *um_ptr)
406 if (!player_can_see_bold(player_ptr, um_ptr->fy, um_ptr->fx)) {
410 auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
411 if (r_ptr->flags2 & RF2_INVISIBLE) {
412 if (player_ptr->see_inv) {
425 * @brief テレパシー・赤外線視力・可視透明によってモンスターを感知できるかどうかの判定
426 * @param player_ptr プレイヤーへの参照ポインタ
427 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
429 static void decide_sight_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
431 POSITION distance = decide_updated_distance(player_ptr, um_ptr);
432 auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
434 um_ptr->m_ptr->mflag.reset(MonsterTemporaryFlagType::ESP);
436 if (distance > (um_ptr->in_darkness ? MAX_SIGHT / 2 : MAX_SIGHT)) {
440 if (!um_ptr->in_darkness || (distance <= MAX_SIGHT / 4)) {
441 update_telepathy_sight(player_ptr, um_ptr, m_idx);
442 update_specific_race_telepathy(player_ptr, um_ptr);
445 if (!player_has_los_bold(player_ptr, um_ptr->fy, um_ptr->fx) || player_ptr->blind) {
449 auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
450 if (sniper_data && (sniper_data->concent >= CONCENT_RADAR_THRESHOLD)) {
455 bool do_cold_blood = check_cold_blood(player_ptr, um_ptr, distance);
456 bool do_invisible = check_invisible(player_ptr, um_ptr);
457 if (!um_ptr->flag || !is_original_ap(um_ptr->m_ptr) || player_ptr->effects()->hallucination()->is_hallucinated()) {
462 r_ptr->r_flags2 |= RF2_INVISIBLE;
466 r_ptr->r_flags2 |= RF2_COLD_BLOOD;
471 * @brief 壁の向こうにいるモンスターへのテレパシー・赤外線視力による冷血動物以外の透明モンスター・可視透明能力による透明モンスター
473 * @param player_ptr プレイヤーへの参照ポインタ
474 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
475 * @param m_idx フロアのモンスター番号
476 * @details 感知した結果、エルドリッチホラー持ちがいたら精神を破壊する
478 static void update_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
480 if (um_ptr->m_ptr->ml) {
484 um_ptr->m_ptr->ml = true;
485 lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
487 if (player_ptr->health_who == m_idx) {
488 player_ptr->redraw |= PR_HEALTH;
491 if (player_ptr->riding == m_idx) {
492 player_ptr->redraw |= PR_UHEALTH;
495 if (!player_ptr->effects()->hallucination()->is_hallucinated()) {
496 auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
497 if ((um_ptr->m_ptr->ap_r_idx == MonsterRaceId::KAGE) && (r_info[MonsterRaceId::KAGE].r_sights < MAX_SHORT)) {
498 r_info[MonsterRaceId::KAGE].r_sights++;
499 } else if (is_original_ap(um_ptr->m_ptr) && (r_ptr->r_sights < MAX_SHORT)) {
504 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) {
505 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::SANITY_BLAST);
508 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))) {
509 if (disturb_pets || is_hostile(um_ptr->m_ptr)) {
510 disturb(player_ptr, true, true);
515 static void update_visible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
517 if (!um_ptr->m_ptr->ml) {
521 um_ptr->m_ptr->ml = false;
522 lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
524 if (player_ptr->health_who == m_idx) {
525 player_ptr->redraw |= PR_HEALTH;
528 if (player_ptr->riding == m_idx) {
529 player_ptr->redraw |= PR_UHEALTH;
532 if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr))) {
533 disturb(player_ptr, true, true);
537 static bool update_clear_monster(PlayerType *player_ptr, um_type *um_ptr)
543 if (um_ptr->m_ptr->mflag.has_not(MonsterTemporaryFlagType::VIEW)) {
544 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::VIEW);
545 if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr))) {
546 disturb(player_ptr, true, true);
554 * @brief モンスターの各情報を更新する / This function updates the monster record of the given monster
555 * @param m_idx 更新するモンスター情報のID
556 * @param full プレイヤーとの距離更新を行うならばtrue
558 void update_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool full)
561 um_type *um_ptr = initialize_um_type(player_ptr, &tmp_um, m_idx, full);
563 monster_race *ap_r_ptr = &r_info[um_ptr->m_ptr->ap_r_idx];
564 if (ap_r_ptr->r_tkills && ap_r_ptr->level >= player_ptr->lev) {
565 um_ptr->do_disturb = true;
569 if (um_ptr->m_ptr->mflag2.has(MonsterConstantFlagType::MARK)) {
573 decide_sight_invisible_monster(player_ptr, um_ptr, m_idx);
575 update_invisible_monster(player_ptr, um_ptr, m_idx);
577 update_visible_monster(player_ptr, um_ptr, m_idx);
580 if (update_clear_monster(player_ptr, um_ptr) || um_ptr->m_ptr->mflag.has_not(MonsterTemporaryFlagType::VIEW)) {
584 um_ptr->m_ptr->mflag.reset(MonsterTemporaryFlagType::VIEW);
585 if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr))) {
586 disturb(player_ptr, true, true);
591 * @param player_ptr プレイヤーへの参照ポインタ
592 * @brief 単純に生存している全モンスターの更新処理を行う / This function simply updates all the (non-dead) monsters (see above).
593 * @param full 距離更新を行うならtrue
594 * @todo モンスターの感知状況しか更新していないように見える。関数名変更を検討する
596 void update_monsters(PlayerType *player_ptr, bool full)
598 auto *floor_ptr = player_ptr->current_floor_ptr;
599 for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
600 auto *m_ptr = &floor_ptr->m_list[i];
601 if (!monster_is_valid(m_ptr)) {
605 update_monster(player_ptr, i, full);
610 * @brief SMART(適格に攻撃を行う)モンスターの学習状況を更新する / Learn about an "observed" resistance.
611 * @param m_idx 更新を行う「モンスター情報ID
614 void update_smart_learn(PlayerType *player_ptr, MONSTER_IDX m_idx, int what)
616 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
617 auto *r_ptr = &r_info[m_ptr->r_idx];
618 if (!smart_learn || (r_ptr->behavior_flags.has(MonsterBehaviorType::STUPID)) || ((r_ptr->behavior_flags.has_not(MonsterBehaviorType::SMART)) && (randint0(100) < 50))) {
624 if (has_resist_acid(player_ptr)) {
625 m_ptr->smart.set(MonsterSmartLearnType::RES_ACID);
628 if (is_oppose_acid(player_ptr)) {
629 m_ptr->smart.set(MonsterSmartLearnType::OPP_ACID);
632 if (has_immune_acid(player_ptr)) {
633 m_ptr->smart.set(MonsterSmartLearnType::IMM_ACID);
638 if (has_resist_elec(player_ptr)) {
639 m_ptr->smart.set(MonsterSmartLearnType::RES_ELEC);
642 if (is_oppose_elec(player_ptr)) {
643 m_ptr->smart.set(MonsterSmartLearnType::OPP_ELEC);
646 if (has_immune_elec(player_ptr)) {
647 m_ptr->smart.set(MonsterSmartLearnType::IMM_ELEC);
652 if (has_resist_fire(player_ptr)) {
653 m_ptr->smart.set(MonsterSmartLearnType::RES_FIRE);
656 if (is_oppose_fire(player_ptr)) {
657 m_ptr->smart.set(MonsterSmartLearnType::OPP_FIRE);
660 if (has_immune_fire(player_ptr)) {
661 m_ptr->smart.set(MonsterSmartLearnType::IMM_FIRE);
666 if (has_resist_cold(player_ptr)) {
667 m_ptr->smart.set(MonsterSmartLearnType::RES_COLD);
670 if (is_oppose_cold(player_ptr)) {
671 m_ptr->smart.set(MonsterSmartLearnType::OPP_COLD);
674 if (has_immune_cold(player_ptr)) {
675 m_ptr->smart.set(MonsterSmartLearnType::IMM_COLD);
680 if (has_resist_pois(player_ptr)) {
681 m_ptr->smart.set(MonsterSmartLearnType::RES_POIS);
684 if (is_oppose_pois(player_ptr)) {
685 m_ptr->smart.set(MonsterSmartLearnType::OPP_POIS);
690 if (has_resist_neth(player_ptr)) {
691 m_ptr->smart.set(MonsterSmartLearnType::RES_NETH);
696 if (has_resist_lite(player_ptr)) {
697 m_ptr->smart.set(MonsterSmartLearnType::RES_LITE);
702 if (has_resist_dark(player_ptr)) {
703 m_ptr->smart.set(MonsterSmartLearnType::RES_DARK);
708 if (has_resist_fear(player_ptr)) {
709 m_ptr->smart.set(MonsterSmartLearnType::RES_FEAR);
714 if (has_resist_conf(player_ptr)) {
715 m_ptr->smart.set(MonsterSmartLearnType::RES_CONF);
720 if (has_resist_chaos(player_ptr)) {
721 m_ptr->smart.set(MonsterSmartLearnType::RES_CHAOS);
726 if (has_resist_disen(player_ptr)) {
727 m_ptr->smart.set(MonsterSmartLearnType::RES_DISEN);
732 if (has_resist_blind(player_ptr)) {
733 m_ptr->smart.set(MonsterSmartLearnType::RES_BLIND);
738 if (has_resist_nexus(player_ptr)) {
739 m_ptr->smart.set(MonsterSmartLearnType::RES_NEXUS);
744 if (has_resist_sound(player_ptr)) {
745 m_ptr->smart.set(MonsterSmartLearnType::RES_SOUND);
750 if (has_resist_shard(player_ptr)) {
751 m_ptr->smart.set(MonsterSmartLearnType::RES_SHARD);
756 if (player_ptr->free_act) {
757 m_ptr->smart.set(MonsterSmartLearnType::IMM_FREE);
762 if (!player_ptr->msp) {
763 m_ptr->smart.set(MonsterSmartLearnType::IMM_MANA);
768 if (has_reflect(player_ptr)) {
769 m_ptr->smart.set(MonsterSmartLearnType::IMM_REFLECT);