2 * @brief モンスター情報のアップデート処理
7 #include "monster/monster-update.h"
8 #include "core/disturbance.h"
9 #include "core/window-redrawer.h"
10 #include "dungeon/dungeon-flag-types.h"
11 #include "floor/geometry.h"
12 #include "game-option/birth-options.h"
13 #include "game-option/disturbance-options.h"
14 #include "grid/grid.h"
15 #include "mind/drs-types.h"
16 #include "monster-race/monster-race.h"
17 #include "monster-race/race-brightness-flags.h"
18 #include "monster-race/race-brightness-mask.h"
19 #include "monster-race/race-flags1.h"
20 #include "monster-race/race-flags2.h"
21 #include "monster-race/race-flags3.h"
22 #include "monster-race/race-flags7.h"
23 #include "monster-race/race-indice-types.h"
24 #include "monster/monster-flag-types.h"
25 #include "monster/monster-info.h"
26 #include "monster/monster-processor-util.h"
27 #include "monster/monster-status.h"
28 #include "monster/smart-learn-types.h"
29 #include "player-base/player-class.h"
30 #include "player-info/samurai-data-type.h"
31 #include "player-info/sniper-data-type.h"
32 #include "player/player-move.h"
33 #include "player/player-status-flags.h"
34 #include "player/special-defense-types.h"
35 #include "status/element-resistance.h"
36 #include "system/angband-system.h"
37 #include "system/dungeon-info.h"
38 #include "system/floor-type-definition.h"
39 #include "system/grid-type-definition.h"
40 #include "system/monster-entity.h"
41 #include "system/monster-race-info.h"
42 #include "system/player-type-definition.h"
43 #include "system/redrawing-flags-updater.h"
44 #include "target/projection-path-calculator.h"
45 #include "timed-effect/player-blindness.h"
46 #include "timed-effect/player-hallucination.h"
47 #include "timed-effect/timed-effects.h"
48 #include "util/bit-flags-calculator.h"
49 #include "world/world.h"
64 * @brief 騎乗中のモンスター情報を更新する
65 * @param player_ptr プレイヤーへの参照ポインタ
66 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
67 * @param m_idx モンスターID
68 * @param oy 移動前の、モンスターのY座標
69 * @param ox 移動前の、モンスターのX座標
70 * @param ny 移動後の、モンスターのY座標
71 * @param ox 移動後の、モンスターのX座標
72 * @return アイテム等に影響を及ぼしたらTRUE
74 bool update_riding_monster(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx)
76 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
77 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[ny][nx];
78 MonsterEntity *y_ptr = &player_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
79 if (turn_flags_ptr->is_riding_mon) {
80 return move_player_effect(player_ptr, ny, nx, MPE_DONT_PICKUP);
83 player_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
87 update_monster(player_ptr, g_ptr->m_idx, true);
93 update_monster(player_ptr, m_idx, true);
95 lite_spot(player_ptr, oy, ox);
96 lite_spot(player_ptr, ny, nx);
101 * @brief マップ及びミニマップの更新フラグをセットする
102 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
104 void update_map_flags(turn_flags *turn_flags_ptr)
106 auto &rfu = RedrawingFlagsUpdater::get_instance();
107 if (!turn_flags_ptr->do_view) {
111 rfu.set_flag(StatusRecalculatingFlag::FLOW);
112 static constexpr auto flags = {
113 SubWindowRedrawingFlag::OVERHEAD,
114 SubWindowRedrawingFlag::DUNGEON,
116 rfu.set_flags(flags);
120 * @brief モンスターの光源フラグに基づいてフロアの光源状態更新フラグをセットする
121 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
122 * @param r_ptr モンスター種族への参照ポインタ
124 void update_lite_flags(turn_flags *turn_flags_ptr, MonsterRaceInfo *r_ptr)
126 using Mbt = MonsterBrightnessType;
127 const auto has_lite = r_ptr->brightness_flags.has_any_of({ Mbt::HAS_LITE_1, Mbt::HAS_LITE_2 });
128 const auto except_has_lite = EnumClassFlagGroup<Mbt>(self_ld_mask).set({ Mbt::HAS_DARK_1, Mbt::HAS_DARK_2 });
129 if (turn_flags_ptr->do_move && (r_ptr->brightness_flags.has_any_of(except_has_lite) || (has_lite && !AngbandSystem::get_instance().is_phase_out()))) {
130 RedrawingFlagsUpdater::get_instance().set_flag(StatusRecalculatingFlag::MONSTER_LITE);
135 * @brief モンスターのフラグを更新する
136 * @param player_ptr プレイヤーへの参照ポインタ
137 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
138 * @param m_ptr モンスターへの参照ポインタ
140 void update_monster_race_flags(PlayerType *player_ptr, turn_flags *turn_flags_ptr, MonsterEntity *m_ptr)
142 auto *r_ptr = &m_ptr->get_monrace();
143 if (!is_original_ap_and_seen(player_ptr, m_ptr)) {
147 if (turn_flags_ptr->did_open_door) {
148 r_ptr->r_behavior_flags.set(MonsterBehaviorType::OPEN_DOOR);
151 if (turn_flags_ptr->did_bash_door) {
152 r_ptr->r_behavior_flags.set(MonsterBehaviorType::BASH_DOOR);
155 if (turn_flags_ptr->did_take_item) {
156 r_ptr->r_behavior_flags.set(MonsterBehaviorType::TAKE_ITEM);
159 if (turn_flags_ptr->did_kill_item) {
160 r_ptr->r_behavior_flags.set(MonsterBehaviorType::KILL_ITEM);
163 if (turn_flags_ptr->did_move_body) {
164 r_ptr->r_behavior_flags.set(MonsterBehaviorType::MOVE_BODY);
167 if (turn_flags_ptr->did_pass_wall) {
168 r_ptr->r_feature_flags.set(MonsterFeatureType::PASS_WALL);
171 if (turn_flags_ptr->did_kill_wall) {
172 r_ptr->r_feature_flags.set(MonsterFeatureType::KILL_WALL);
177 * @brief モンスターフラグの更新に基づき、モンスター表示を更新する
178 * @param monster_race_idx モンスターID
179 * @param window ウィンドウフラグ
180 * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
182 void update_player_window(PlayerType *player_ptr, old_race_flags *old_race_flags_ptr)
184 MonsterRaceInfo *r_ptr;
185 r_ptr = &monraces_info[player_ptr->monster_race_idx];
186 if ((old_race_flags_ptr->old_r_flags1 != r_ptr->r_flags1) || (old_race_flags_ptr->old_r_flags2 != r_ptr->r_flags2) ||
187 (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) || (old_race_flags_ptr->old_r_ability_flags != r_ptr->r_ability_flags) ||
188 (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]) ||
189 (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) || (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2]) ||
190 (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) ||
191 (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) ||
192 (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)) {
193 RedrawingFlagsUpdater::get_instance().set_flag(SubWindowRedrawingFlag::MONSTER_LORE);
197 static um_type *initialize_um_type(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx, bool full)
199 auto &floor = *player_ptr->current_floor_ptr;
200 um_ptr->m_ptr = &floor.m_list[m_idx];
201 um_ptr->do_disturb = disturb_move;
202 um_ptr->fy = um_ptr->m_ptr->fy;
203 um_ptr->fx = um_ptr->m_ptr->fx;
204 um_ptr->flag = false;
205 um_ptr->easy = false;
206 um_ptr->in_darkness = floor.get_dungeon_definition().flags.has(DungeonFeatureType::DARKNESS) && !player_ptr->see_nocto;
211 static POSITION decide_updated_distance(PlayerType *player_ptr, um_type *um_ptr)
214 return um_ptr->m_ptr->cdis;
217 int dy = (player_ptr->y > um_ptr->fy) ? (player_ptr->y - um_ptr->fy) : (um_ptr->fy - player_ptr->y);
218 int dx = (player_ptr->x > um_ptr->fx) ? (player_ptr->x - um_ptr->fx) : (um_ptr->fx - player_ptr->x);
219 POSITION distance = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
220 if (distance > 255) {
228 um_ptr->m_ptr->cdis = distance;
232 static void update_smart_stupid_flags(MonsterRaceInfo *r_ptr)
234 if (r_ptr->behavior_flags.has(MonsterBehaviorType::SMART)) {
235 r_ptr->r_behavior_flags.set(MonsterBehaviorType::SMART);
238 if (r_ptr->behavior_flags.has(MonsterBehaviorType::STUPID)) {
239 r_ptr->r_behavior_flags.set(MonsterBehaviorType::STUPID);
244 * @brief WEIRD_MINDフラグ持ちのモンスターを1/10の確率でテレパシーに引っかける
245 * @param player_ptr プレイヤーへの参照ポインタ
246 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
247 * @param m_idx モンスターID
248 * @return WEIRD_MINDフラグがあるならTRUE
250 static bool update_weird_telepathy(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
252 auto *m_ptr = um_ptr->m_ptr;
253 auto *r_ptr = &m_ptr->get_monrace();
254 if ((r_ptr->flags2 & RF2_WEIRD_MIND) == 0) {
258 if ((m_idx % 10) != (w_ptr->game_turn % 10)) {
263 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
264 if (m_ptr->is_original_ap() && !player_ptr->effects()->hallucination()->is_hallucinated()) {
265 r_ptr->r_flags2 |= RF2_WEIRD_MIND;
266 update_smart_stupid_flags(r_ptr);
272 static void update_telepathy_sight(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
274 auto *m_ptr = um_ptr->m_ptr;
275 auto *r_ptr = &m_ptr->get_monrace();
276 if (PlayerClass(player_ptr).samurai_stance_is(SamuraiStanceType::MUSOU)) {
278 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
279 if (um_ptr->m_ptr->is_original_ap() && !player_ptr->effects()->hallucination()->is_hallucinated()) {
280 update_smart_stupid_flags(r_ptr);
286 if (!player_ptr->telepathy) {
290 auto is_hallucinated = player_ptr->effects()->hallucination()->is_hallucinated();
291 if (r_ptr->flags2 & RF2_EMPTY_MIND) {
292 if (m_ptr->is_original_ap() && !is_hallucinated) {
293 r_ptr->r_flags2 |= RF2_EMPTY_MIND;
299 if (update_weird_telepathy(player_ptr, um_ptr, m_idx)) {
304 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
305 if (m_ptr->is_original_ap() && !is_hallucinated) {
306 update_smart_stupid_flags(r_ptr);
310 static void update_specific_race_telepathy(PlayerType *player_ptr, um_type *um_ptr)
312 auto *m_ptr = um_ptr->m_ptr;
313 auto *r_ptr = &m_ptr->get_monrace();
314 auto is_hallucinated = player_ptr->effects()->hallucination()->is_hallucinated();
315 if ((player_ptr->esp_animal) && r_ptr->kind_flags.has(MonsterKindType::ANIMAL)) {
317 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
318 if (m_ptr->is_original_ap() && !is_hallucinated) {
319 r_ptr->r_kind_flags.set(MonsterKindType::ANIMAL);
323 if ((player_ptr->esp_undead) && r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
325 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
326 if (m_ptr->is_original_ap() && !is_hallucinated) {
327 r_ptr->r_kind_flags.set(MonsterKindType::UNDEAD);
331 if ((player_ptr->esp_demon) && r_ptr->kind_flags.has(MonsterKindType::DEMON)) {
333 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
334 if (m_ptr->is_original_ap() && !is_hallucinated) {
335 r_ptr->r_kind_flags.set(MonsterKindType::DEMON);
339 if ((player_ptr->esp_orc) && r_ptr->kind_flags.has(MonsterKindType::ORC)) {
341 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
342 if (m_ptr->is_original_ap() && !is_hallucinated) {
343 r_ptr->r_kind_flags.set(MonsterKindType::ORC);
347 if ((player_ptr->esp_troll) && r_ptr->kind_flags.has(MonsterKindType::TROLL)) {
349 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
350 if (m_ptr->is_original_ap() && !is_hallucinated) {
351 r_ptr->r_kind_flags.set(MonsterKindType::TROLL);
355 if ((player_ptr->esp_giant) && r_ptr->kind_flags.has(MonsterKindType::GIANT)) {
357 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
358 if (m_ptr->is_original_ap() && !is_hallucinated) {
359 r_ptr->r_kind_flags.set(MonsterKindType::GIANT);
363 if ((player_ptr->esp_dragon) && r_ptr->kind_flags.has(MonsterKindType::DRAGON)) {
365 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
366 if (m_ptr->is_original_ap() && !is_hallucinated) {
367 r_ptr->r_kind_flags.set(MonsterKindType::DRAGON);
371 if ((player_ptr->esp_human) && r_ptr->kind_flags.has(MonsterKindType::HUMAN)) {
373 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
374 if (m_ptr->is_original_ap() && !is_hallucinated) {
375 r_ptr->r_kind_flags.set(MonsterKindType::HUMAN);
379 if ((player_ptr->esp_evil) && r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
381 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
382 if (m_ptr->is_original_ap() && !is_hallucinated) {
383 r_ptr->r_kind_flags.set(MonsterKindType::EVIL);
387 if ((player_ptr->esp_good) && r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
389 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
390 if (m_ptr->is_original_ap() && !is_hallucinated) {
391 r_ptr->r_kind_flags.set(MonsterKindType::GOOD);
395 if ((player_ptr->esp_nonliving) && r_ptr->kind_flags.has(MonsterKindType::NONLIVING) && r_ptr->kind_flags.has_none_of({ MonsterKindType::DEMON, MonsterKindType::UNDEAD })) {
397 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
398 if (m_ptr->is_original_ap() && !is_hallucinated) {
399 r_ptr->r_kind_flags.set(MonsterKindType::NONLIVING);
403 if ((player_ptr->esp_unique) && r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
405 m_ptr->mflag.set(MonsterTemporaryFlagType::ESP);
406 if (m_ptr->is_original_ap() && !is_hallucinated) {
407 r_ptr->r_kind_flags.set(MonsterKindType::UNIQUE);
412 static bool check_cold_blood(PlayerType *player_ptr, um_type *um_ptr, const POSITION distance)
414 if (distance > player_ptr->see_infra) {
418 auto *r_ptr = &um_ptr->m_ptr->get_monrace();
419 if (any_bits(r_ptr->flags2, RF2_COLD_BLOOD) && r_ptr->aura_flags.has_not(MonsterAuraType::FIRE)) {
428 static bool check_invisible(PlayerType *player_ptr, um_type *um_ptr)
430 if (!player_can_see_bold(player_ptr, um_ptr->fy, um_ptr->fx)) {
434 auto *r_ptr = &um_ptr->m_ptr->get_monrace();
435 if (r_ptr->flags2 & RF2_INVISIBLE) {
436 if (player_ptr->see_inv) {
449 * @brief テレパシー・赤外線視力・可視透明によってモンスターを感知できるかどうかの判定
450 * @param player_ptr プレイヤーへの参照ポインタ
451 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
453 static void decide_sight_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
455 POSITION distance = decide_updated_distance(player_ptr, um_ptr);
456 auto *m_ptr = um_ptr->m_ptr;
457 auto *r_ptr = &m_ptr->get_monrace();
459 m_ptr->mflag.reset(MonsterTemporaryFlagType::ESP);
461 if (distance > (um_ptr->in_darkness ? MAX_PLAYER_SIGHT / 2 : MAX_PLAYER_SIGHT)) {
465 if (!um_ptr->in_darkness || (distance <= MAX_PLAYER_SIGHT / 4)) {
466 update_telepathy_sight(player_ptr, um_ptr, m_idx);
467 update_specific_race_telepathy(player_ptr, um_ptr);
470 if (!player_ptr->current_floor_ptr->has_los({ um_ptr->fy, um_ptr->fx }) || player_ptr->effects()->blindness()->is_blind()) {
474 auto sniper_data = PlayerClass(player_ptr).get_specific_data<SniperData>();
475 if (sniper_data && (sniper_data->concent >= CONCENT_RADAR_THRESHOLD)) {
480 bool do_cold_blood = check_cold_blood(player_ptr, um_ptr, distance);
481 bool do_invisible = check_invisible(player_ptr, um_ptr);
482 if (!um_ptr->flag || !m_ptr->is_original_ap() || player_ptr->effects()->hallucination()->is_hallucinated()) {
487 r_ptr->r_flags2 |= RF2_INVISIBLE;
491 r_ptr->r_flags2 |= RF2_COLD_BLOOD;
496 * @brief 壁の向こうにいるモンスターへのテレパシー・赤外線視力による冷血動物以外の透明モンスター・可視透明能力による透明モンスター
498 * @param player_ptr プレイヤーへの参照ポインタ
499 * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
500 * @param m_idx フロアのモンスター番号
501 * @details 感知した結果、エルドリッチホラー持ちがいたら精神を破壊する
503 static void update_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
505 auto *m_ptr = um_ptr->m_ptr;
511 lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
513 auto &rfu = RedrawingFlagsUpdater::get_instance();
514 if (player_ptr->health_who == m_idx) {
515 rfu.set_flag(MainWindowRedrawingFlag::HEALTH);
518 if (player_ptr->riding == m_idx) {
519 rfu.set_flag(MainWindowRedrawingFlag::UHEALTH);
522 if (!player_ptr->effects()->hallucination()->is_hallucinated()) {
523 auto *r_ptr = &m_ptr->get_monrace();
524 if ((m_ptr->ap_r_idx == MonsterRaceId::KAGE) && (monraces_info[MonsterRaceId::KAGE].r_sights < MAX_SHORT)) {
525 monraces_info[MonsterRaceId::KAGE].r_sights++;
526 } else if (m_ptr->is_original_ap() && (r_ptr->r_sights < MAX_SHORT)) {
531 if (w_ptr->is_loading_now && w_ptr->character_dungeon && !AngbandSystem::get_instance().is_phase_out() && m_ptr->get_appearance_monrace().flags2 & RF2_ELDRITCH_HORROR) {
532 m_ptr->mflag.set(MonsterTemporaryFlagType::SANITY_BLAST);
535 const auto projectable_from_monster = projectable(player_ptr, m_ptr->fy, m_ptr->fx, player_ptr->y, player_ptr->x);
536 const auto projectable_from_player = projectable(player_ptr, player_ptr->y, player_ptr->x, m_ptr->fy, m_ptr->fx);
537 if (disturb_near && projectable_from_monster && projectable_from_player) {
538 if (disturb_pets || m_ptr->is_hostile()) {
539 disturb(player_ptr, true, true);
544 static void update_visible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
546 if (!um_ptr->m_ptr->ml) {
550 um_ptr->m_ptr->ml = false;
551 lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
553 auto &rfu = RedrawingFlagsUpdater::get_instance();
554 if (player_ptr->health_who == m_idx) {
555 rfu.set_flag(MainWindowRedrawingFlag::HEALTH);
558 if (player_ptr->riding == m_idx) {
559 rfu.set_flag(MainWindowRedrawingFlag::UHEALTH);
562 if (um_ptr->do_disturb && (disturb_pets || um_ptr->m_ptr->is_hostile())) {
563 disturb(player_ptr, true, true);
567 static bool update_clear_monster(PlayerType *player_ptr, um_type *um_ptr)
573 if (um_ptr->m_ptr->mflag.has_not(MonsterTemporaryFlagType::VIEW)) {
574 um_ptr->m_ptr->mflag.set(MonsterTemporaryFlagType::VIEW);
575 if (um_ptr->do_disturb && (disturb_pets || um_ptr->m_ptr->is_hostile())) {
576 disturb(player_ptr, true, true);
584 * @brief モンスターの各情報を更新する / This function updates the monster record of the given monster
585 * @param m_idx 更新するモンスター情報のID
586 * @param full プレイヤーとの距離更新を行うならばtrue
588 void update_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool full)
591 um_type *um_ptr = initialize_um_type(player_ptr, &tmp_um, m_idx, full);
593 auto *ap_r_ptr = &um_ptr->m_ptr->get_appearance_monrace();
594 if (ap_r_ptr->r_tkills && ap_r_ptr->level >= player_ptr->lev) {
595 um_ptr->do_disturb = true;
599 if (um_ptr->m_ptr->mflag2.has(MonsterConstantFlagType::MARK)) {
603 decide_sight_invisible_monster(player_ptr, um_ptr, m_idx);
605 update_invisible_monster(player_ptr, um_ptr, m_idx);
607 update_visible_monster(player_ptr, um_ptr, m_idx);
610 if (update_clear_monster(player_ptr, um_ptr) || um_ptr->m_ptr->mflag.has_not(MonsterTemporaryFlagType::VIEW)) {
614 um_ptr->m_ptr->mflag.reset(MonsterTemporaryFlagType::VIEW);
615 if (um_ptr->do_disturb && (disturb_pets || um_ptr->m_ptr->is_hostile())) {
616 disturb(player_ptr, true, true);
621 * @param player_ptr プレイヤーへの参照ポインタ
622 * @brief 単純に生存している全モンスターの更新処理を行う / This function simply updates all the (non-dead) monsters (see above).
623 * @param full 距離更新を行うならtrue
624 * @todo モンスターの感知状況しか更新していないように見える。関数名変更を検討する
626 void update_monsters(PlayerType *player_ptr, bool full)
628 auto *floor_ptr = player_ptr->current_floor_ptr;
629 for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
630 auto *m_ptr = &floor_ptr->m_list[i];
631 if (!m_ptr->is_valid()) {
635 update_monster(player_ptr, i, full);
640 * @brief SMART(適格に攻撃を行う)モンスターの学習状況を更新する / Learn about an "observed" resistance.
641 * @param m_idx 更新を行う「モンスター情報ID
644 void update_smart_learn(PlayerType *player_ptr, MONSTER_IDX m_idx, int what)
646 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
647 auto *r_ptr = &m_ptr->get_monrace();
648 if (!smart_learn || (r_ptr->behavior_flags.has(MonsterBehaviorType::STUPID)) || ((r_ptr->behavior_flags.has_not(MonsterBehaviorType::SMART)) && (randint0(100) < 50))) {
654 if (has_resist_acid(player_ptr)) {
655 m_ptr->smart.set(MonsterSmartLearnType::RES_ACID);
658 if (is_oppose_acid(player_ptr)) {
659 m_ptr->smart.set(MonsterSmartLearnType::OPP_ACID);
662 if (has_immune_acid(player_ptr)) {
663 m_ptr->smart.set(MonsterSmartLearnType::IMM_ACID);
668 if (has_resist_elec(player_ptr)) {
669 m_ptr->smart.set(MonsterSmartLearnType::RES_ELEC);
672 if (is_oppose_elec(player_ptr)) {
673 m_ptr->smart.set(MonsterSmartLearnType::OPP_ELEC);
676 if (has_immune_elec(player_ptr)) {
677 m_ptr->smart.set(MonsterSmartLearnType::IMM_ELEC);
682 if (has_resist_fire(player_ptr)) {
683 m_ptr->smart.set(MonsterSmartLearnType::RES_FIRE);
686 if (is_oppose_fire(player_ptr)) {
687 m_ptr->smart.set(MonsterSmartLearnType::OPP_FIRE);
690 if (has_immune_fire(player_ptr)) {
691 m_ptr->smart.set(MonsterSmartLearnType::IMM_FIRE);
696 if (has_resist_cold(player_ptr)) {
697 m_ptr->smart.set(MonsterSmartLearnType::RES_COLD);
700 if (is_oppose_cold(player_ptr)) {
701 m_ptr->smart.set(MonsterSmartLearnType::OPP_COLD);
704 if (has_immune_cold(player_ptr)) {
705 m_ptr->smart.set(MonsterSmartLearnType::IMM_COLD);
710 if (has_resist_pois(player_ptr)) {
711 m_ptr->smart.set(MonsterSmartLearnType::RES_POIS);
714 if (is_oppose_pois(player_ptr)) {
715 m_ptr->smart.set(MonsterSmartLearnType::OPP_POIS);
720 if (has_resist_neth(player_ptr)) {
721 m_ptr->smart.set(MonsterSmartLearnType::RES_NETH);
726 if (has_resist_lite(player_ptr)) {
727 m_ptr->smart.set(MonsterSmartLearnType::RES_LITE);
732 if (has_resist_dark(player_ptr) || has_immune_dark(player_ptr)) {
733 m_ptr->smart.set(MonsterSmartLearnType::RES_DARK);
738 if (has_resist_fear(player_ptr)) {
739 m_ptr->smart.set(MonsterSmartLearnType::RES_FEAR);
744 if (has_resist_conf(player_ptr)) {
745 m_ptr->smart.set(MonsterSmartLearnType::RES_CONF);
750 if (has_resist_chaos(player_ptr)) {
751 m_ptr->smart.set(MonsterSmartLearnType::RES_CHAOS);
756 if (has_resist_disen(player_ptr)) {
757 m_ptr->smart.set(MonsterSmartLearnType::RES_DISEN);
762 if (has_resist_blind(player_ptr)) {
763 m_ptr->smart.set(MonsterSmartLearnType::RES_BLIND);
768 if (has_resist_nexus(player_ptr)) {
769 m_ptr->smart.set(MonsterSmartLearnType::RES_NEXUS);
774 if (has_resist_sound(player_ptr)) {
775 m_ptr->smart.set(MonsterSmartLearnType::RES_SOUND);
780 if (has_resist_shard(player_ptr)) {
781 m_ptr->smart.set(MonsterSmartLearnType::RES_SHARD);
786 if (player_ptr->free_act) {
787 m_ptr->smart.set(MonsterSmartLearnType::IMM_FREE);
792 if (!player_ptr->msp) {
793 m_ptr->smart.set(MonsterSmartLearnType::IMM_MANA);
798 if (has_reflect(player_ptr)) {
799 m_ptr->smart.set(MonsterSmartLearnType::IMM_REFLECT);