OSDN Git Service

Merge pull request #2178 from Hourier/Remove-Old-Struct-Decleration
[hengbandforosx/hengbandosx.git] / src / monster / monster-update.cpp
1 /*!
2  * @brief モンスター情報のアップデート処理
3  * @date 2020/03/08
4  * @author Hourier
5  */
6
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"
46
47 // Update Monster.
48 struct um_type {
49     monster_type *m_ptr;
50     bool do_disturb;
51     POSITION fy;
52     POSITION fx;
53     bool flag;
54     bool easy;
55     bool in_darkness;
56     bool full;
57 };
58
59 /*!
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
69  */
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)
71 {
72     auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
73     auto *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);
77
78     player_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
79     if (g_ptr->m_idx) {
80         y_ptr->fy = oy;
81         y_ptr->fx = ox;
82         update_monster(player_ptr, g_ptr->m_idx, true);
83     }
84
85     g_ptr->m_idx = m_idx;
86     m_ptr->fy = ny;
87     m_ptr->fx = nx;
88     update_monster(player_ptr, m_idx, true);
89
90     lite_spot(player_ptr, oy, ox);
91     lite_spot(player_ptr, ny, nx);
92     return true;
93 }
94
95 /*!
96  * @brief updateフィールドを更新する
97  * @param player_ptr プレイヤーへの参照ポインタ
98  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
99  */
100 void update_player_type(PlayerType *player_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr)
101 {
102     if (turn_flags_ptr->do_view) {
103         player_ptr->update |= PU_FLOW;
104         player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
105     }
106
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;
109     }
110 }
111
112 /*!
113  * @brief モンスターのフラグを更新する
114  * @param player_ptr プレイヤーへの参照ポインタ
115  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
116  * @param m_ptr モンスターへの参照ポインタ
117  */
118 void update_monster_race_flags(PlayerType *player_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr)
119 {
120     auto *r_ptr = &r_info[m_ptr->r_idx];
121     if (!is_original_ap_and_seen(player_ptr, m_ptr))
122         return;
123
124     if (turn_flags_ptr->did_open_door)
125         r_ptr->r_behavior_flags.set(MonsterBehaviorType::OPEN_DOOR);
126
127     if (turn_flags_ptr->did_bash_door)
128         r_ptr->r_behavior_flags.set(MonsterBehaviorType::BASH_DOOR);
129
130     if (turn_flags_ptr->did_take_item)
131         r_ptr->r_behavior_flags.set(MonsterBehaviorType::TAKE_ITEM);
132
133     if (turn_flags_ptr->did_kill_item)
134         r_ptr->r_behavior_flags.set(MonsterBehaviorType::KILL_ITEM);
135
136     if (turn_flags_ptr->did_move_body)
137         r_ptr->r_behavior_flags.set(MonsterBehaviorType::MOVE_BODY);
138
139     if (turn_flags_ptr->did_pass_wall)
140         r_ptr->r_flags2 |= RF2_PASS_WALL;
141
142     if (turn_flags_ptr->did_kill_wall)
143         r_ptr->r_flags2 |= RF2_KILL_WALL;
144 }
145
146 /*!
147  * @brief モンスターフラグの更新に基づき、モンスター表示を更新する
148  * @param monster_race_idx モンスターID
149  * @param window ウィンドウフラグ
150  * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
151  */
152 void update_player_window(PlayerType *player_ptr, old_race_flags *old_race_flags_ptr)
153 {
154     monster_race *r_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;
162     }
163 }
164
165 static um_type *initialize_um_type(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx, bool full)
166 {
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;
174     um_ptr->full = full;
175     return um_ptr;
176 }
177
178 static POSITION decide_updated_distance(PlayerType *player_ptr, um_type *um_ptr)
179 {
180     if (!um_ptr->full)
181         return um_ptr->m_ptr->cdis;
182
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));
186     if (distance > 255)
187         distance = 255;
188
189     if (!distance)
190         distance = 1;
191
192     um_ptr->m_ptr->cdis = distance;
193     return distance;
194 }
195
196 static void update_smart_stupid_flags(monster_race *r_ptr)
197 {
198     if (r_ptr->r_behavior_flags.has(MonsterBehaviorType::SMART))
199         r_ptr->r_behavior_flags.set(MonsterBehaviorType::SMART);
200
201     if (r_ptr->r_behavior_flags.has(MonsterBehaviorType::STUPID))
202         r_ptr->r_behavior_flags.set(MonsterBehaviorType::STUPID);
203 }
204
205 /*!
206  * @brief WEIRD_MINDフラグ持ちのモンスターを1/10の確率でテレパシーに引っかける
207  * @param player_ptr プレイヤーへの参照ポインタ
208  * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
209  * @param m_idx モンスターID
210  * @return WEIRD_MINDフラグがあるならTRUE
211  */
212 static bool update_weird_telepathy(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
213 {
214     auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
215     if ((r_ptr->flags2 & RF2_WEIRD_MIND) == 0)
216         return false;
217
218     if ((m_idx % 10) != (w_ptr->game_turn % 10))
219         return true;
220
221     um_ptr->flag = true;
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);
226     }
227
228     return true;
229 }
230
231 static void update_telepathy_sight(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
232 {
233     auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
234     if (PlayerClass(player_ptr).samurai_stance_is(SamuraiStanceType::MUSOU)) {
235         um_ptr->flag = true;
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);
239
240         return;
241     }
242
243     if (!player_ptr->telepathy)
244         return;
245
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;
249
250         return;
251     }
252
253     if (update_weird_telepathy(player_ptr, um_ptr, m_idx))
254         return;
255
256     um_ptr->flag = true;
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);
260 }
261
262 static void update_specific_race_telepathy(PlayerType *player_ptr, um_type *um_ptr)
263 {
264     auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
265     if ((player_ptr->esp_animal) && r_ptr->kind_flags.has(MonsterKindType::ANIMAL)) {
266         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::ANIMAL);
270     }
271
272     if ((player_ptr->esp_undead) && r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
273         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::UNDEAD);
277     }
278
279     if ((player_ptr->esp_demon) && r_ptr->kind_flags.has(MonsterKindType::DEMON)) {
280         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::DEMON);
284     }
285
286     if ((player_ptr->esp_orc) && r_ptr->kind_flags.has(MonsterKindType::ORC)) {
287         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::ORC);
291     }
292
293     if ((player_ptr->esp_troll) && r_ptr->kind_flags.has(MonsterKindType::TROLL)) {
294         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::TROLL);
298     }
299
300     if ((player_ptr->esp_giant) && r_ptr->kind_flags.has(MonsterKindType::GIANT)) {
301         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::GIANT);
305     }
306
307     if ((player_ptr->esp_dragon) && r_ptr->kind_flags.has(MonsterKindType::DRAGON)) {
308         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::DRAGON);
312     }
313
314     if ((player_ptr->esp_human) && r_ptr->kind_flags.has(MonsterKindType::HUMAN)) {
315         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::HUMAN);
319     }
320
321     if ((player_ptr->esp_evil) && r_ptr->kind_flags.has(MonsterKindType::EVIL)) {
322         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::EVIL);
326     }
327
328     if ((player_ptr->esp_good) && r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
329         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::GOOD);
333     }
334
335     if ((player_ptr->esp_nonliving) && (r_ptr->kind_flags.has(MonsterKindType::NONLIVING) && r_ptr->kind_flags.has_none_of({ MonsterKindType::DEMON, MonsterKindType::UNDEAD }))) {
336         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::NONLIVING);
340     }
341
342     if ((player_ptr->esp_unique) && r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
343         um_ptr->flag = true;
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_kind_flags.set(MonsterKindType::UNIQUE);
347     }
348 }
349
350 static bool check_cold_blood(PlayerType *player_ptr, um_type *um_ptr, const POSITION distance)
351 {
352     if (distance > player_ptr->see_infra)
353         return false;
354
355     auto *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))
357         return false;
358
359     um_ptr->easy = true;
360     um_ptr->flag = true;
361     return true;
362 }
363
364 static bool check_invisible(PlayerType *player_ptr, um_type *um_ptr)
365 {
366     if (!player_can_see_bold(player_ptr, um_ptr->fy, um_ptr->fx))
367         return false;
368
369     auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
370     if (r_ptr->flags2 & RF2_INVISIBLE) {
371         if (player_ptr->see_inv) {
372             um_ptr->easy = true;
373             um_ptr->flag = true;
374         }
375     } else {
376         um_ptr->easy = true;
377         um_ptr->flag = true;
378     }
379
380     return true;
381 }
382
383 /*!
384  * @brief テレパシー・赤外線視力・可視透明によってモンスターを感知できるかどうかの判定
385  * @param player_ptr プレイヤーへの参照ポインタ
386  * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
387  */
388 static void decide_sight_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
389 {
390     POSITION distance = decide_updated_distance(player_ptr, um_ptr);
391     auto *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
392
393     um_ptr->m_ptr->mflag.reset(MonsterTemporaryFlagType::ESP);
394
395     if (distance > (um_ptr->in_darkness ? MAX_SIGHT / 2 : MAX_SIGHT))
396         return;
397
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);
401     }
402
403     if (!player_has_los_bold(player_ptr, um_ptr->fy, um_ptr->fx) || player_ptr->blind)
404         return;
405
406     auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
407     if (sniper_data && (sniper_data->concent >= CONCENT_RADAR_THRESHOLD)) {
408         um_ptr->easy = true;
409         um_ptr->flag = true;
410     }
411
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)
415         return;
416
417     if (do_invisible)
418         r_ptr->r_flags2 |= RF2_INVISIBLE;
419
420     if (do_cold_blood)
421         r_ptr->r_flags2 |= RF2_COLD_BLOOD;
422 }
423
424 /*!
425  * @brief 壁の向こうにいるモンスターへのテレパシー・赤外線視力による冷血動物以外の透明モンスター・可視透明能力による透明モンスター
426  * 以上を感知する
427  * @param player_ptr プレイヤーへの参照ポインタ
428  * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
429  * @param m_idx フロアのモンスター番号
430  * @details 感知した結果、エルドリッチホラー持ちがいたら精神を破壊する
431  */
432 static void update_invisible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
433 {
434     if (um_ptr->m_ptr->ml)
435         return;
436
437     um_ptr->m_ptr->ml = true;
438     lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
439
440     if (player_ptr->health_who == m_idx)
441         player_ptr->redraw |= PR_HEALTH;
442
443     if (player_ptr->riding == m_idx)
444         player_ptr->redraw |= PR_UHEALTH;
445
446     if (!player_ptr->hallucinated) {
447         auto *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))
451             r_ptr->r_sights++;
452     }
453
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);
456
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);
460     }
461 }
462
463 static void update_visible_monster(PlayerType *player_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
464 {
465     if (!um_ptr->m_ptr->ml)
466         return;
467
468     um_ptr->m_ptr->ml = false;
469     lite_spot(player_ptr, um_ptr->fy, um_ptr->fx);
470
471     if (player_ptr->health_who == m_idx)
472         player_ptr->redraw |= PR_HEALTH;
473
474     if (player_ptr->riding == m_idx)
475         player_ptr->redraw |= PR_UHEALTH;
476
477     if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr)))
478         disturb(player_ptr, true, true);
479 }
480
481 static bool update_clear_monster(PlayerType *player_ptr, um_type *um_ptr)
482 {
483     if (!um_ptr->easy)
484         return false;
485
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);
490     }
491
492     return true;
493 }
494
495 /*!
496  * @brief モンスターの各情報を更新する / This function updates the monster record of the given monster
497  * @param m_idx 更新するモンスター情報のID
498  * @param full プレイヤーとの距離更新を行うならばtrue
499  */
500 void update_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool full)
501 {
502     um_type tmp_um;
503     um_type *um_ptr = initialize_um_type(player_ptr, &tmp_um, m_idx, full);
504     if (disturb_high) {
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;
508     }
509
510     if (um_ptr->m_ptr->mflag2.has(MonsterConstantFlagType::MARK))
511         um_ptr->flag = true;
512
513     decide_sight_invisible_monster(player_ptr, um_ptr, m_idx);
514     if (um_ptr->flag)
515         update_invisible_monster(player_ptr, um_ptr, m_idx);
516     else
517         update_visible_monster(player_ptr, um_ptr, m_idx);
518
519     if (update_clear_monster(player_ptr, um_ptr) || um_ptr->m_ptr->mflag.has_not(MonsterTemporaryFlagType::VIEW))
520         return;
521
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);
525 }
526
527 /*!
528  * @param player_ptr プレイヤーへの参照ポインタ
529  * @brief 単純に生存している全モンスターの更新処理を行う / This function simply updates all the (non-dead) monsters (see above).
530  * @param full 距離更新を行うならtrue
531  * @todo モンスターの感知状況しか更新していないように見える。関数名変更を検討する
532  */
533 void update_monsters(PlayerType *player_ptr, bool full)
534 {
535     auto *floor_ptr = player_ptr->current_floor_ptr;
536     for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
537         auto *m_ptr = &floor_ptr->m_list[i];
538         if (!monster_is_valid(m_ptr))
539             continue;
540
541         update_monster(player_ptr, i, full);
542     }
543 }
544
545 /*!
546  * @brief SMART(適格に攻撃を行う)モンスターの学習状況を更新する / Learn about an "observed" resistance.
547  * @param m_idx 更新を行う「モンスター情報ID
548  * @param what 学習対象ID
549  */
550 void update_smart_learn(PlayerType *player_ptr, MONSTER_IDX m_idx, int what)
551 {
552     auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
553     auto *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)))
555         return;
556
557     switch (what) {
558     case DRS_ACID:
559         if (has_resist_acid(player_ptr))
560             m_ptr->smart.set(MonsterSmartLearnType::RES_ACID);
561
562         if (is_oppose_acid(player_ptr))
563             m_ptr->smart.set(MonsterSmartLearnType::OPP_ACID);
564
565         if (has_immune_acid(player_ptr))
566             m_ptr->smart.set(MonsterSmartLearnType::IMM_ACID);
567
568         break;
569     case DRS_ELEC:
570         if (has_resist_elec(player_ptr))
571             m_ptr->smart.set(MonsterSmartLearnType::RES_ELEC);
572
573         if (is_oppose_elec(player_ptr))
574             m_ptr->smart.set(MonsterSmartLearnType::OPP_ELEC);
575
576         if (has_immune_elec(player_ptr))
577             m_ptr->smart.set(MonsterSmartLearnType::IMM_ELEC);
578
579         break;
580     case DRS_FIRE:
581         if (has_resist_fire(player_ptr))
582             m_ptr->smart.set(MonsterSmartLearnType::RES_FIRE);
583
584         if (is_oppose_fire(player_ptr))
585             m_ptr->smart.set(MonsterSmartLearnType::OPP_FIRE);
586
587         if (has_immune_fire(player_ptr))
588             m_ptr->smart.set(MonsterSmartLearnType::IMM_FIRE);
589
590         break;
591     case DRS_COLD:
592         if (has_resist_cold(player_ptr))
593             m_ptr->smart.set(MonsterSmartLearnType::RES_COLD);
594
595         if (is_oppose_cold(player_ptr))
596             m_ptr->smart.set(MonsterSmartLearnType::OPP_COLD);
597
598         if (has_immune_cold(player_ptr))
599             m_ptr->smart.set(MonsterSmartLearnType::IMM_COLD);
600
601         break;
602     case DRS_POIS:
603         if (has_resist_pois(player_ptr))
604             m_ptr->smart.set(MonsterSmartLearnType::RES_POIS);
605
606         if (is_oppose_pois(player_ptr))
607             m_ptr->smart.set(MonsterSmartLearnType::OPP_POIS);
608
609         break;
610     case DRS_NETH:
611         if (has_resist_neth(player_ptr))
612             m_ptr->smart.set(MonsterSmartLearnType::RES_NETH);
613
614         break;
615     case DRS_LITE:
616         if (has_resist_lite(player_ptr))
617             m_ptr->smart.set(MonsterSmartLearnType::RES_LITE);
618
619         break;
620     case DRS_DARK:
621         if (has_resist_dark(player_ptr))
622             m_ptr->smart.set(MonsterSmartLearnType::RES_DARK);
623
624         break;
625     case DRS_FEAR:
626         if (has_resist_fear(player_ptr))
627             m_ptr->smart.set(MonsterSmartLearnType::RES_FEAR);
628
629         break;
630     case DRS_CONF:
631         if (has_resist_conf(player_ptr))
632             m_ptr->smart.set(MonsterSmartLearnType::RES_CONF);
633
634         break;
635     case DRS_CHAOS:
636         if (has_resist_chaos(player_ptr))
637             m_ptr->smart.set(MonsterSmartLearnType::RES_CHAOS);
638
639         break;
640     case DRS_DISEN:
641         if (has_resist_disen(player_ptr))
642             m_ptr->smart.set(MonsterSmartLearnType::RES_DISEN);
643
644         break;
645     case DRS_BLIND:
646         if (has_resist_blind(player_ptr))
647             m_ptr->smart.set(MonsterSmartLearnType::RES_BLIND);
648
649         break;
650     case DRS_NEXUS:
651         if (has_resist_nexus(player_ptr))
652             m_ptr->smart.set(MonsterSmartLearnType::RES_NEXUS);
653
654         break;
655     case DRS_SOUND:
656         if (has_resist_sound(player_ptr))
657             m_ptr->smart.set(MonsterSmartLearnType::RES_SOUND);
658
659         break;
660     case DRS_SHARD:
661         if (has_resist_shard(player_ptr))
662             m_ptr->smart.set(MonsterSmartLearnType::RES_SHARD);
663
664         break;
665     case DRS_FREE:
666         if (player_ptr->free_act)
667             m_ptr->smart.set(MonsterSmartLearnType::IMM_FREE);
668
669         break;
670     case DRS_MANA:
671         if (!player_ptr->msp)
672             m_ptr->smart.set(MonsterSmartLearnType::IMM_MANA);
673
674         break;
675     case DRS_REFLECT:
676         if (has_reflect(player_ptr))
677             m_ptr->smart.set(MonsterSmartLearnType::IMM_REFLECT);
678
679         break;
680     default:
681         break;
682     }
683 }