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 "floor/cave.h"
14 #include "floor/geometry.h"
15 #include "game-option/birth-options.h"
16 #include "game-option/disturbance-options.h"
17 #include "grid/grid.h"
18 #include "mind/drs-types.h"
19 #include "monster-race/monster-race.h"
20 #include "monster-race/race-brightness-flags.h"
21 #include "monster-race/race-brightness-mask.h"
22 #include "monster-race/race-flags1.h"
23 #include "monster-race/race-flags2.h"
24 #include "monster-race/race-flags3.h"
25 #include "monster-race/race-flags7.h"
26 #include "monster-race/race-indice-types.h"
27 #include "monster/monster-flag-types.h"
28 #include "monster/monster-info.h"
29 #include "monster/monster-processor-util.h"
30 #include "monster/monster-status.h"
31 #include "monster/smart-learn-types.h"
32 #include "player-base/player-class.h"
33 #include "player-info/samurai-data-type.h"
34 #include "player-info/sniper-data-type.h"
35 #include "player/player-move.h"
36 #include "player/player-status-flags.h"
37 #include "player/special-defense-types.h"
38 #include "status/element-resistance.h"
39 #include "system/dungeon-info.h"
40 #include "system/floor-type-definition.h"
41 #include "system/grid-type-definition.h"
42 #include "system/monster-entity.h"
43 #include "system/monster-race-info.h"
44 #include "system/player-type-definition.h"
45 #include "target/projection-path-calculator.h"
46 #include "timed-effect/player-blindness.h"
47 #include "timed-effect/player-hallucination.h"
48 #include "timed-effect/timed-effects.h"
49 #include "util/bit-flags-calculator.h"
50 #include "world/world.h"
65 * @brief 騎乗中のモンスター情報を更新する
66 * @param player_ptr プレイヤーへの参照ポインタ
67 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
68 * @param m_idx モンスターID
69 * @param oy 移動前の、モンスターのY座標
70 * @param ox 移動前の、モンスターのX座標
71 * @param ny 移動後の、モンスターのY座標
72 * @param ox 移動後の、モンスターのX座標
73 * @return アイテム等に影響を及ぼしたらTRUE
75 bool update_riding_monster(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx)
77 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
78 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[ny][nx];
79 MonsterEntity *y_ptr = &player_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
80 if (turn_flags_ptr->is_riding_mon) {
81 return move_player_effect(player_ptr, ny, nx, MPE_DONT_PICKUP);
84 player_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
88 update_monster(player_ptr, g_ptr->m_idx, true);
94 update_monster(player_ptr, m_idx, true);
96 lite_spot(player_ptr, oy, ox);
97 lite_spot(player_ptr, ny, nx);
102 * @brief updateフィールドを更新する
103 * @param player_ptr プレイヤーへの参照ポインタ
104 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
106 void update_player_type(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MonsterRaceInfo *r_ptr)
108 auto except_has_lite = EnumClassFlagGroup<MonsterBrightnessType>(self_ld_mask).set({ MonsterBrightnessType::HAS_DARK_1, MonsterBrightnessType::HAS_DARK_2 });
109 if (turn_flags_ptr->do_view) {
110 player_ptr->update |= PU_FLOW;
111 player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
114 if (turn_flags_ptr->do_move && (r_ptr->brightness_flags.has_any_of(except_has_lite) || (r_ptr->brightness_flags.has_any_of({ MonsterBrightnessType::HAS_LITE_1, MonsterBrightnessType::HAS_LITE_2 }) && !player_ptr->phase_out))) {
115 player_ptr->update |= PU_MONSTER_LITE;
120 * @brief モンスターのフラグを更新する
121 * @param player_ptr プレイヤーへの参照ポインタ
122 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
123 * @param m_ptr モンスターへの参照ポインタ
125 void update_monster_race_flags(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MonsterEntity *m_ptr)
127 auto *r_ptr = &monraces_info[m_ptr->r_idx];
128 if (!is_original_ap_and_seen(player_ptr, m_ptr)) {
132 if (turn_flags_ptr->did_open_door) {
133 r_ptr->r_behavior_flags.set(MonsterBehaviorType::OPEN_DOOR);
136 if (turn_flags_ptr->did_bash_door) {
137 r_ptr->r_behavior_flags.set(MonsterBehaviorType::BASH_DOOR);
140 if (turn_flags_ptr->did_take_item) {
141 r_ptr->r_behavior_flags.set(MonsterBehaviorType::TAKE_ITEM);
144 if (turn_flags_ptr->did_kill_item) {
145 r_ptr->r_behavior_flags.set(MonsterBehaviorType::KILL_ITEM);
148 if (turn_flags_ptr->did_move_body) {
149 r_ptr->r_behavior_flags.set(MonsterBehaviorType::MOVE_BODY);
152 if (turn_flags_ptr->did_pass_wall) {
153 r_ptr->r_feature_flags.set(MonsterFeatureType::PASS_WALL);
156 if (turn_flags_ptr->did_kill_wall) {
157 r_ptr->r_feature_flags.set(MonsterFeatureType::KILL_WALL);
162 * @brief モンスターフラグの更新に基づき、モンスター表示を更新する
163 * @param monster_race_idx モンスターID
164 * @param window ウィンドウフラグ
165 * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
167 void update_player_window(PlayerType *player_ptr, old_race_flags *old_race_flags_ptr)
169 MonsterRaceInfo *r_ptr;
170 r_ptr = &monraces_info[player_ptr->monster_race_idx];
171 if ((old_race_flags_ptr->old_r_flags1 != r_ptr->r_flags1) || (old_race_flags_ptr->old_r_flags2 != r_ptr->r_flags2) ||
172 (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) || (old_race_flags_ptr->old_r_ability_flags != r_ptr->r_ability_flags) ||
173 (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]) ||
174 (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) || (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2]) ||
175 (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) ||
176 (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) ||
177 (old_race_flags_ptr->old_r_drop_flags != r_ptr->r_drop_flags) || (old_race_flags_ptr->old_r_feature_flags != r_ptr->r_feature_flags)) {
178 player_ptr->window_flags |= PW_MONSTER_LORE;
182 static um_type *initialize_um_type(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx, bool full)
184 um_ptr->m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
185 um_ptr->do_disturb = disturb_move;
186 um_ptr->fy = um_ptr->m_ptr->fy;
187 um_ptr->fx = um_ptr->m_ptr->fx;
188 um_ptr->flag = false;
189 um_ptr->easy = false;
190 um_ptr->in_darkness = dungeons_info[player_ptr->dungeon_idx].flags.has(DungeonFeatureType::DARKNESS) && !player_ptr->see_nocto;
195 static POSITION decide_updated_distance(PlayerType *player_ptr, um_type *um_ptr)
198 return um_ptr->m_ptr->cdis;
201 int dy = (player_ptr->y > um_ptr->fy) ? (player_ptr->y - um_ptr->fy) : (um_ptr->fy - player_ptr->y);
202 int dx = (player_ptr->x > um_ptr->fx) ? (player_ptr->x - um_ptr->fx) : (um_ptr->fx - player_ptr->x);
203 POSITION distance = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
204 if (distance > 255) {
212 um_ptr->m_ptr->cdis = distance;
216 static void update_smart_stupid_flags(MonsterRaceInfo *r_ptr)
218 if (r_ptr->r_behavior_flags.has(MonsterBehaviorType::SMART)) {
219 r_ptr->r_behavior_flags.set(MonsterBehaviorType::SMART);
222 if (r_ptr->r_behavior_flags.has(MonsterBehaviorType::STUPID)) {
223 r_ptr->r_behavior_flags.set(MonsterBehaviorType::STUPID);
228 * @brief WEIRD_MINDフラグ持ちのモンスターを1/10の確率でテレパシーに引っかける
229 * @param player_ptr プレイヤーへの参照ポインタ
230 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
231 * @param m_idx モンスターID
232 * @return WEIRD_MINDフラグがあるならTRUE
234 static bool update_weird_telepathy(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
236 auto *m_ptr = um_ptr->m_ptr;
237 auto *r_ptr = &monraces_info[m_ptr->r_idx];
238 if ((r_ptr->flags2 & RF2_WEIRD_MIND) == 0) {
242 if ((m_idx % 10) != (w_ptr->game_turn % 10)) {
247 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
248 if (m_ptr->is_original_ap() && !player_ptr->effects()->hallucination()->is_hallucinated()) {
249 r_ptr->r_flags2 |= RF2_WEIRD_MIND;
250 update_smart_stupid_flags(r_ptr);
256 static void update_telepathy_sight(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
258 auto *m_ptr = um_ptr->m_ptr;
259 auto *r_ptr = &monraces_info[m_ptr->r_idx];
260 if (PlayerClass(player_ptr).samurai_stance_is(SamuraiStanceType::MUSOU)) {
262 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
263 if (um_ptr->m_ptr->is_original_ap() && !player_ptr->effects()->hallucination()->is_hallucinated()) {
264 update_smart_stupid_flags(r_ptr);
270 if (!player_ptr->telepathy) {
274 auto is_hallucinated = player_ptr->effects()->hallucination()->is_hallucinated();
275 if (r_ptr->flags2 & RF2_EMPTY_MIND) {
276 if (m_ptr->is_original_ap() && !is_hallucinated) {
277 r_ptr->r_flags2 |= RF2_EMPTY_MIND;
283 if (update_weird_telepathy(player_ptr, um_ptr, m_idx)) {
288 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
289 if (m_ptr->is_original_ap() && !is_hallucinated) {
290 update_smart_stupid_flags(r_ptr);
294 static void update_specific_race_telepathy(PlayerType *player_ptr, um_type *um_ptr)
296 auto *m_ptr = um_ptr->m_ptr;
297 auto *r_ptr = &monraces_info[m_ptr->r_idx];
298 auto is_hallucinated = player_ptr->effects()->hallucination()->is_hallucinated();
299 if ((player_ptr->esp_animal) && r_ptr->kind_flags.has(MonsterKindType::ANIMAL)) {
301 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
302 if (m_ptr->is_original_ap() && !is_hallucinated) {
303 r_ptr->r_kind_flags.set(MonsterKindType::ANIMAL);
307 if ((player_ptr->esp_undead) && r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
309 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
310 if (m_ptr->is_original_ap() && !is_hallucinated) {
311 r_ptr->r_kind_flags.set(MonsterKindType::UNDEAD);
315 if ((player_ptr->esp_demon) && r_ptr->kind_flags.has(MonsterKindType::DEMON)) {
317 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
318 if (m_ptr->is_original_ap() && !is_hallucinated) {
319 r_ptr->r_kind_flags.set(MonsterKindType::DEMON);
323 if ((player_ptr->esp_orc) && r_ptr->kind_flags.has(MonsterKindType::ORC)) {
325 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
326 if (m_ptr->is_original_ap() && !is_hallucinated) {
327 r_ptr->r_kind_flags.set(MonsterKindType::ORC);
331 if ((player_ptr->esp_troll) && r_ptr->kind_flags.has(MonsterKindType::TROLL)) {
333 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
334 if (m_ptr->is_original_ap() && !is_hallucinated) {
335 r_ptr->r_kind_flags.set(MonsterKindType::TROLL);
339 if ((player_ptr->esp_giant) && r_ptr->kind_flags.has(MonsterKindType::GIANT)) {
341 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
342 if (m_ptr->is_original_ap() && !is_hallucinated) {
343 r_ptr->r_kind_flags.set(MonsterKindType::GIANT);
347 if ((player_ptr->esp_dragon) && r_ptr->kind_flags.has(MonsterKindType::DRAGON)) {
349 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
350 if (m_ptr->is_original_ap() && !is_hallucinated) {
351 r_ptr->r_kind_flags.set(MonsterKindType::DRAGON);
355 if ((player_ptr->esp_human) && r_ptr->kind_flags.has(MonsterKindType::HUMAN)) {
357 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
358 if (m_ptr->is_original_ap() && !is_hallucinated) {
359 r_ptr->r_kind_flags.set(MonsterKindType::HUMAN);
363 if ((player_ptr->esp_evil) && r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
365 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
366 if (m_ptr->is_original_ap() && !is_hallucinated) {
367 r_ptr->r_kind_flags.set(MonsterKindType::EVIL);
371 if ((player_ptr->esp_good) && r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
373 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
374 if (m_ptr->is_original_ap() && !is_hallucinated) {
375 r_ptr->r_kind_flags.set(MonsterKindType::GOOD);
379 if ((player_ptr->esp_nonliving) && (r_ptr->kind_flags.has(MonsterKindType::NONLIVING) && r_ptr->kind_flags.has_none_of({ MonsterKindType::DEMON, MonsterKindType::UNDEAD }))) {
381 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
382 if (m_ptr->is_original_ap() && !is_hallucinated) {
383 r_ptr->r_kind_flags.set(MonsterKindType::NONLIVING);
387 if ((player_ptr->esp_unique) && r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
389 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
390 if (m_ptr->is_original_ap() && !is_hallucinated) {
391 r_ptr->r_kind_flags.set(MonsterKindType::UNIQUE);
396 static bool check_cold_blood(PlayerType *player_ptr, um_type *um_ptr, const POSITION distance)
398 if (distance > player_ptr->see_infra) {
402 auto *r_ptr = &monraces_info[um_ptr->m_ptr->r_idx];
403 if (any_bits(r_ptr->flags2, RF2_COLD_BLOOD) && r_ptr->aura_flags.has_not(MonsterAuraType::FIRE)) {
412 static bool check_invisible(PlayerType *player_ptr, um_type *um_ptr)
414 if (!player_can_see_bold(player_ptr, um_ptr->fy, um_ptr->fx)) {
418 auto *r_ptr = &monraces_info[um_ptr->m_ptr->r_idx];
419 if (r_ptr->flags2 & RF2_INVISIBLE) {
420 if (player_ptr->see_inv) {
433 * @brief テレパシー・赤外線視力・可視透明によってモンスターを感知できるかどうかの判定
434 * @param player_ptr プレイヤーへの参照ポインタ
435 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
437 static void decide_sight_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
439 POSITION distance = decide_updated_distance(player_ptr, um_ptr);
440 auto *m_ptr = um_ptr->m_ptr;
441 auto *r_ptr = &monraces_info[m_ptr->r_idx];
443 m_ptr->mflag.reset(MonsterTemporaryFlagType::ESP);
445 if (distance > (um_ptr->in_darkness ? MAX_PLAYER_SIGHT / 2 : MAX_PLAYER_SIGHT)) {
449 if (!um_ptr->in_darkness || (distance <= MAX_PLAYER_SIGHT / 4)) {
450 update_telepathy_sight(player_ptr, um_ptr, m_idx);
451 update_specific_race_telepathy(player_ptr, um_ptr);
454 if (!player_has_los_bold(player_ptr, um_ptr->fy, um_ptr->fx) || player_ptr->effects()->blindness()->is_blind()) {
458 auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
459 if (sniper_data && (sniper_data->concent >= CONCENT_RADAR_THRESHOLD)) {
464 bool do_cold_blood = check_cold_blood(player_ptr, um_ptr, distance);
465 bool do_invisible = check_invisible(player_ptr, um_ptr);
466 if (!um_ptr->flag || !m_ptr->is_original_ap() || player_ptr->effects()->hallucination()->is_hallucinated()) {
471 r_ptr->r_flags2 |= RF2_INVISIBLE;
475 r_ptr->r_flags2 |= RF2_COLD_BLOOD;
480 * @brief 壁の向こうにいるモンスターへのテレパシー・赤外線視力による冷血動物以外の透明モンスター・可視透明能力による透明モンスター
482 * @param player_ptr プレイヤーへの参照ポインタ
483 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
484 * @param m_idx フロアのモンスター番号
485 * @details 感知した結果、エルドリッチホラー持ちがいたら精神を破壊する
487 static void update_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
489 auto *m_ptr = um_ptr->m_ptr;
495 lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
497 if (player_ptr->health_who == m_idx) {
498 player_ptr->redraw |= PR_HEALTH;
501 if (player_ptr->riding == m_idx) {
502 player_ptr->redraw |= PR_UHEALTH;
505 if (!player_ptr->effects()->hallucination()->is_hallucinated()) {
506 auto *r_ptr = &monraces_info[m_ptr->r_idx];
507 if ((m_ptr->ap_r_idx == MonsterRaceId::KAGE) && (monraces_info[MonsterRaceId::KAGE].r_sights < MAX_SHORT)) {
508 monraces_info[MonsterRaceId::KAGE].r_sights++;
509 } else if (m_ptr->is_original_ap() && (r_ptr->r_sights < MAX_SHORT)) {
514 if (w_ptr->is_loading_now && w_ptr->character_dungeon && !player_ptr->phase_out && monraces_info[m_ptr->ap_r_idx].flags2 & RF2_ELDRITCH_HORROR) {
515 m_ptr->mflag.set(MonsterTemporaryFlagType::SANITY_BLAST);
518 const auto projectable_from_monster = projectable(player_ptr, m_ptr->fy, m_ptr->fx, player_ptr->y, player_ptr->x);
519 const auto projectable_from_player = projectable(player_ptr, player_ptr->y, player_ptr->x, m_ptr->fy, m_ptr->fx);
520 if (disturb_near && projectable_from_monster && projectable_from_player) {
521 if (disturb_pets || m_ptr->is_hostile()) {
522 disturb(player_ptr, true, true);
527 static void update_visible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
529 if (!um_ptr->m_ptr->ml) {
533 um_ptr->m_ptr->ml = false;
534 lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
536 if (player_ptr->health_who == m_idx) {
537 player_ptr->redraw |= PR_HEALTH;
540 if (player_ptr->riding == m_idx) {
541 player_ptr->redraw |= PR_UHEALTH;
544 if (um_ptr->do_disturb && (disturb_pets || um_ptr->m_ptr->is_hostile())) {
545 disturb(player_ptr, true, true);
549 static bool update_clear_monster(PlayerType *player_ptr, um_type *um_ptr)
555 if (um_ptr->m_ptr->mflag.has_not(MonsterTemporaryFlagType::VIEW)) {
556 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::VIEW);
557 if (um_ptr->do_disturb && (disturb_pets || um_ptr->m_ptr->is_hostile())) {
558 disturb(player_ptr, true, true);
566 * @brief モンスターの各情報を更新する / This function updates the monster record of the given monster
567 * @param m_idx 更新するモンスター情報のID
568 * @param full プレイヤーとの距離更新を行うならばtrue
570 void update_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool full)
573 um_type *um_ptr = initialize_um_type(player_ptr, &tmp_um, m_idx, full);
575 MonsterRaceInfo *ap_r_ptr = &monraces_info[um_ptr->m_ptr->ap_r_idx];
576 if (ap_r_ptr->r_tkills && ap_r_ptr->level >= player_ptr->lev) {
577 um_ptr->do_disturb = true;
581 if (um_ptr->m_ptr->mflag2.has(MonsterConstantFlagType::MARK)) {
585 decide_sight_invisible_monster(player_ptr, um_ptr, m_idx);
587 update_invisible_monster(player_ptr, um_ptr, m_idx);
589 update_visible_monster(player_ptr, um_ptr, m_idx);
592 if (update_clear_monster(player_ptr, um_ptr) || um_ptr->m_ptr->mflag.has_not(MonsterTemporaryFlagType::VIEW)) {
596 um_ptr->m_ptr->mflag.reset(MonsterTemporaryFlagType::VIEW);
597 if (um_ptr->do_disturb && (disturb_pets || um_ptr->m_ptr->is_hostile())) {
598 disturb(player_ptr, true, true);
603 * @param player_ptr プレイヤーへの参照ポインタ
604 * @brief 単純に生存している全モンスターの更新処理を行う / This function simply updates all the (non-dead) monsters (see above).
605 * @param full 距離更新を行うならtrue
606 * @todo モンスターの感知状況しか更新していないように見える。関数名変更を検討する
608 void update_monsters(PlayerType *player_ptr, bool full)
610 auto *floor_ptr = player_ptr->current_floor_ptr;
611 for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
612 auto *m_ptr = &floor_ptr->m_list[i];
613 if (!m_ptr->is_valid()) {
617 update_monster(player_ptr, i, full);
622 * @brief SMART(適格に攻撃を行う)モンスターの学習状況を更新する / Learn about an "observed" resistance.
623 * @param m_idx 更新を行う「モンスター情報ID
626 void update_smart_learn(PlayerType *player_ptr, MONSTER_IDX m_idx, int what)
628 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
629 auto *r_ptr = &monraces_info[m_ptr->r_idx];
630 if (!smart_learn || (r_ptr->behavior_flags.has(MonsterBehaviorType::STUPID)) || ((r_ptr->behavior_flags.has_not(MonsterBehaviorType::SMART)) && (randint0(100) < 50))) {
636 if (has_resist_acid(player_ptr)) {
637 m_ptr->smart.set(MonsterSmartLearnType::RES_ACID);
640 if (is_oppose_acid(player_ptr)) {
641 m_ptr->smart.set(MonsterSmartLearnType::OPP_ACID);
644 if (has_immune_acid(player_ptr)) {
645 m_ptr->smart.set(MonsterSmartLearnType::IMM_ACID);
650 if (has_resist_elec(player_ptr)) {
651 m_ptr->smart.set(MonsterSmartLearnType::RES_ELEC);
654 if (is_oppose_elec(player_ptr)) {
655 m_ptr->smart.set(MonsterSmartLearnType::OPP_ELEC);
658 if (has_immune_elec(player_ptr)) {
659 m_ptr->smart.set(MonsterSmartLearnType::IMM_ELEC);
664 if (has_resist_fire(player_ptr)) {
665 m_ptr->smart.set(MonsterSmartLearnType::RES_FIRE);
668 if (is_oppose_fire(player_ptr)) {
669 m_ptr->smart.set(MonsterSmartLearnType::OPP_FIRE);
672 if (has_immune_fire(player_ptr)) {
673 m_ptr->smart.set(MonsterSmartLearnType::IMM_FIRE);
678 if (has_resist_cold(player_ptr)) {
679 m_ptr->smart.set(MonsterSmartLearnType::RES_COLD);
682 if (is_oppose_cold(player_ptr)) {
683 m_ptr->smart.set(MonsterSmartLearnType::OPP_COLD);
686 if (has_immune_cold(player_ptr)) {
687 m_ptr->smart.set(MonsterSmartLearnType::IMM_COLD);
692 if (has_resist_pois(player_ptr)) {
693 m_ptr->smart.set(MonsterSmartLearnType::RES_POIS);
696 if (is_oppose_pois(player_ptr)) {
697 m_ptr->smart.set(MonsterSmartLearnType::OPP_POIS);
702 if (has_resist_neth(player_ptr)) {
703 m_ptr->smart.set(MonsterSmartLearnType::RES_NETH);
708 if (has_resist_lite(player_ptr)) {
709 m_ptr->smart.set(MonsterSmartLearnType::RES_LITE);
714 if (has_resist_dark(player_ptr) || has_immune_dark(player_ptr)) {
715 m_ptr->smart.set(MonsterSmartLearnType::RES_DARK);
720 if (has_resist_fear(player_ptr)) {
721 m_ptr->smart.set(MonsterSmartLearnType::RES_FEAR);
726 if (has_resist_conf(player_ptr)) {
727 m_ptr->smart.set(MonsterSmartLearnType::RES_CONF);
732 if (has_resist_chaos(player_ptr)) {
733 m_ptr->smart.set(MonsterSmartLearnType::RES_CHAOS);
738 if (has_resist_disen(player_ptr)) {
739 m_ptr->smart.set(MonsterSmartLearnType::RES_DISEN);
744 if (has_resist_blind(player_ptr)) {
745 m_ptr->smart.set(MonsterSmartLearnType::RES_BLIND);
750 if (has_resist_nexus(player_ptr)) {
751 m_ptr->smart.set(MonsterSmartLearnType::RES_NEXUS);
756 if (has_resist_sound(player_ptr)) {
757 m_ptr->smart.set(MonsterSmartLearnType::RES_SOUND);
762 if (has_resist_shard(player_ptr)) {
763 m_ptr->smart.set(MonsterSmartLearnType::RES_SHARD);
768 if (player_ptr->free_act) {
769 m_ptr->smart.set(MonsterSmartLearnType::IMM_FREE);
774 if (!player_ptr->msp) {
775 m_ptr->smart.set(MonsterSmartLearnType::IMM_MANA);
780 if (has_reflect(player_ptr)) {
781 m_ptr->smart.set(MonsterSmartLearnType::IMM_REFLECT);