OSDN Git Service

[Refactor] 無駄な空白、改行の削除、includeのソート
[hengband/hengband.git] / src / monster / monster-update.c
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 "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-flags1.h"
21 #include "monster-race/race-flags2.h"
22 #include "monster-race/race-flags3.h"
23 #include "monster-race/race-flags7.h"
24 #include "monster-race/race-indice-types.h"
25 #include "monster/monster-flag-types.h"
26 #include "monster/monster-info.h"
27 #include "monster/monster-status.h"
28 #include "monster/smart-learn-types.h"
29 #include "player/eldritch-horror.h"
30 #include "player/player-move.h"
31 #include "player/player-status-flags.h"
32 #include "player/special-defense-types.h"
33 #include "status/element-resistance.h"
34 #include "system/floor-type-definition.h"
35 #include "target/projection-path-calculator.h"
36 #include "world/world.h"
37
38 // Update Monster.
39 typedef struct um_type {
40     monster_type *m_ptr;
41     bool do_disturb;
42     POSITION fy;
43     POSITION fx;
44     bool flag;
45     bool easy;
46     bool in_darkness;
47     bool full;
48 } um_type;
49
50 /*!
51  * @brief 騎乗中のモンスター情報を更新する
52  * @param target_ptr プレーヤーへの参照ポインタ
53  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
54  * @param m_idx モンスターID
55  * @param oy 移動前の、モンスターのY座標
56  * @param ox 移動前の、モンスターのX座標
57  * @param ny 移動後の、モンスターのY座標
58  * @param ox 移動後の、モンスターのX座標
59  * @return アイテム等に影響を及ぼしたらTRUE
60  */
61 bool update_riding_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx)
62 {
63     monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
64     grid_type *g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
65     monster_type *y_ptr = &target_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
66     if (turn_flags_ptr->is_riding_mon)
67         return move_player_effect(target_ptr, ny, nx, MPE_DONT_PICKUP);
68
69     target_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
70     if (g_ptr->m_idx) {
71         y_ptr->fy = oy;
72         y_ptr->fx = ox;
73         update_monster(target_ptr, g_ptr->m_idx, TRUE);
74     }
75
76     g_ptr->m_idx = m_idx;
77     m_ptr->fy = ny;
78     m_ptr->fx = nx;
79     update_monster(target_ptr, m_idx, TRUE);
80
81     lite_spot(target_ptr, oy, ox);
82     lite_spot(target_ptr, ny, nx);
83     return TRUE;
84 }
85
86 /*!
87  * @brief updateフィールドを更新する
88  * @param target_ptr プレーヤーへの参照ポインタ
89  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
90  * @return なし
91  */
92 void update_player_type(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr)
93 {
94     if (turn_flags_ptr->do_view) {
95         target_ptr->update |= PU_FLOW;
96         target_ptr->window |= PW_OVERHEAD | PW_DUNGEON;
97     }
98
99     if (turn_flags_ptr->do_move
100         && ((r_ptr->flags7 & (RF7_SELF_LD_MASK | RF7_HAS_DARK_1 | RF7_HAS_DARK_2))
101             || ((r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_HAS_LITE_2)) && !target_ptr->phase_out))) {
102         target_ptr->update |= PU_MON_LITE;
103     }
104 }
105
106 /*!
107  * @brief モンスターのフラグを更新する
108  * @param target_ptr プレーヤーへの参照ポインタ
109  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
110  * @param m_ptr モンスターへの参照ポインタ
111  * @return なし
112  */
113 void update_monster_race_flags(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr)
114 {
115     monster_race *r_ptr = &r_info[m_ptr->r_idx];
116     if (!is_original_ap_and_seen(target_ptr, m_ptr))
117         return;
118
119     if (turn_flags_ptr->did_open_door)
120         r_ptr->r_flags2 |= RF2_OPEN_DOOR;
121
122     if (turn_flags_ptr->did_bash_door)
123         r_ptr->r_flags2 |= RF2_BASH_DOOR;
124
125     if (turn_flags_ptr->did_take_item)
126         r_ptr->r_flags2 |= RF2_TAKE_ITEM;
127
128     if (turn_flags_ptr->did_kill_item)
129         r_ptr->r_flags2 |= RF2_KILL_ITEM;
130
131     if (turn_flags_ptr->did_move_body)
132         r_ptr->r_flags2 |= RF2_MOVE_BODY;
133
134     if (turn_flags_ptr->did_pass_wall)
135         r_ptr->r_flags2 |= RF2_PASS_WALL;
136
137     if (turn_flags_ptr->did_kill_wall)
138         r_ptr->r_flags2 |= RF2_KILL_WALL;
139 }
140
141 /*!
142  * @brief モンスターフラグの更新に基づき、モンスター表示を更新する
143  * @param monster_race_idx モンスターID
144  * @param window ウィンドウフラグ
145  * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
146  * @return なし
147  */
148 void update_player_window(player_type *target_ptr, old_race_flags *old_race_flags_ptr)
149 {
150     monster_race *r_ptr;
151     r_ptr = &r_info[target_ptr->monster_race_idx];
152     if ((old_race_flags_ptr->old_r_flags1 != r_ptr->r_flags1) || (old_race_flags_ptr->old_r_flags2 != r_ptr->r_flags2)
153         || (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) || (old_race_flags_ptr->old_r_flags4 != r_ptr->r_flags4)
154         || (old_race_flags_ptr->old_r_flags5 != r_ptr->r_flags5) || (old_race_flags_ptr->old_r_flags6 != r_ptr->r_flags6)
155         || (old_race_flags_ptr->old_r_flagsr != r_ptr->r_flagsr) || (old_race_flags_ptr->old_r_blows0 != r_ptr->r_blows[0])
156         || (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) || (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2])
157         || (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)) {
158         target_ptr->window |= PW_MONSTER;
159     }
160 }
161
162 static um_type *initialize_um_type(player_type *subject_ptr, um_type *um_ptr, MONSTER_IDX m_idx, bool full)
163 {
164     um_ptr->m_ptr = &subject_ptr->current_floor_ptr->m_list[m_idx];
165     um_ptr->do_disturb = disturb_move;
166     um_ptr->fy = um_ptr->m_ptr->fy;
167     um_ptr->fx = um_ptr->m_ptr->fx;
168     um_ptr->flag = FALSE;
169     um_ptr->easy = FALSE;
170     um_ptr->in_darkness = (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !subject_ptr->see_nocto;
171     um_ptr->full = full;
172     return um_ptr;
173 }
174
175 static POSITION decide_updated_distance(player_type *subject_ptr, um_type *um_ptr)
176 {
177     if (!um_ptr->full)
178         return um_ptr->m_ptr->cdis;
179
180     int dy = (subject_ptr->y > um_ptr->fy) ? (subject_ptr->y - um_ptr->fy) : (um_ptr->fy - subject_ptr->y);
181     int dx = (subject_ptr->x > um_ptr->fx) ? (subject_ptr->x - um_ptr->fx) : (um_ptr->fx - subject_ptr->x);
182     POSITION distance = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
183     if (distance > 255)
184         distance = 255;
185
186     if (!distance)
187         distance = 1;
188
189     um_ptr->m_ptr->cdis = distance;
190     return distance;
191 }
192
193 static void update_smart_stupid_flags(monster_race *r_ptr)
194 {
195     if (r_ptr->flags2 & RF2_SMART)
196         r_ptr->r_flags2 |= RF2_SMART;
197
198     if (r_ptr->flags2 & RF2_STUPID)
199         r_ptr->r_flags2 |= RF2_STUPID;
200 }
201
202 /*!
203  * @brief WEIRD_MINDフラグ持ちのモンスターを1/10の確率でテレパシーに引っかける
204  * @param subject_ptr プレーヤーへの参照ポインタ
205  * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
206  * @param m_idx モンスターID
207  * @return WEIRD_MINDフラグがあるならTRUE
208  */
209 static bool update_weird_telepathy(player_type *subject_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
210 {
211     monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
212     if ((r_ptr->flags2 & RF2_WEIRD_MIND) == 0)
213         return FALSE;
214
215     if ((m_idx % 10) != (current_world_ptr->game_turn % 10))
216         return TRUE;
217
218     um_ptr->flag = TRUE;
219     if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image) {
220         r_ptr->r_flags2 |= RF2_WEIRD_MIND;
221         update_smart_stupid_flags(r_ptr);
222     }
223
224     return TRUE;
225 }
226
227 static void update_telepathy_sight(player_type *subject_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
228 {
229     monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
230     if (subject_ptr->special_defense & KATA_MUSOU) {
231         um_ptr->flag = TRUE;
232         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
233             update_smart_stupid_flags(r_ptr);
234
235         return;
236     }
237
238     if (!subject_ptr->telepathy)
239         return;
240
241     if (r_ptr->flags2 & RF2_EMPTY_MIND) {
242         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
243             r_ptr->r_flags2 |= RF2_EMPTY_MIND;
244
245         return;
246     }
247
248     if (update_weird_telepathy(subject_ptr, um_ptr, m_idx))
249         return;
250
251     um_ptr->flag = TRUE;
252     if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
253         update_smart_stupid_flags(r_ptr);
254 }
255
256 static void update_specific_race_telepathy(player_type *subject_ptr, um_type *um_ptr)
257 {
258     monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
259     if ((subject_ptr->esp_animal) && (r_ptr->flags3 & RF3_ANIMAL)) {
260         um_ptr->flag = TRUE;
261         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
262             r_ptr->r_flags3 |= RF3_ANIMAL;
263     }
264
265     if ((subject_ptr->esp_undead) && (r_ptr->flags3 & RF3_UNDEAD)) {
266         um_ptr->flag = TRUE;
267         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
268             r_ptr->r_flags3 |= RF3_UNDEAD;
269     }
270
271     if ((subject_ptr->esp_demon) && (r_ptr->flags3 & RF3_DEMON)) {
272         um_ptr->flag = TRUE;
273         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
274             r_ptr->r_flags3 |= RF3_DEMON;
275     }
276
277     if ((subject_ptr->esp_orc) && (r_ptr->flags3 & RF3_ORC)) {
278         um_ptr->flag = TRUE;
279         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
280             r_ptr->r_flags3 |= RF3_ORC;
281     }
282
283     if ((subject_ptr->esp_troll) && (r_ptr->flags3 & RF3_TROLL)) {
284         um_ptr->flag = TRUE;
285         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
286             r_ptr->r_flags3 |= RF3_TROLL;
287     }
288
289     if ((subject_ptr->esp_giant) && (r_ptr->flags3 & RF3_GIANT)) {
290         um_ptr->flag = TRUE;
291         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
292             r_ptr->r_flags3 |= RF3_GIANT;
293     }
294
295     if ((subject_ptr->esp_dragon) && (r_ptr->flags3 & RF3_DRAGON)) {
296         um_ptr->flag = TRUE;
297         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
298             r_ptr->r_flags3 |= RF3_DRAGON;
299     }
300
301     if ((subject_ptr->esp_human) && (r_ptr->flags2 & RF2_HUMAN)) {
302         um_ptr->flag = TRUE;
303         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
304             r_ptr->r_flags2 |= RF2_HUMAN;
305     }
306
307     if ((subject_ptr->esp_evil) && (r_ptr->flags3 & RF3_EVIL)) {
308         um_ptr->flag = TRUE;
309         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
310             r_ptr->r_flags3 |= RF3_EVIL;
311     }
312
313     if ((subject_ptr->esp_good) && (r_ptr->flags3 & RF3_GOOD)) {
314         um_ptr->flag = TRUE;
315         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
316             r_ptr->r_flags3 |= RF3_GOOD;
317     }
318
319     if ((subject_ptr->esp_nonliving) && ((r_ptr->flags3 & (RF3_DEMON | RF3_UNDEAD | RF3_NONLIVING)) == RF3_NONLIVING)) {
320         um_ptr->flag = TRUE;
321         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
322             r_ptr->r_flags3 |= RF3_NONLIVING;
323     }
324
325     if ((subject_ptr->esp_unique) && (r_ptr->flags1 & RF1_UNIQUE)) {
326         um_ptr->flag = TRUE;
327         if (is_original_ap(um_ptr->m_ptr) && !subject_ptr->image)
328             r_ptr->r_flags1 |= RF1_UNIQUE;
329     }
330 }
331
332 static bool check_cold_blood(player_type *subject_ptr, um_type *um_ptr, const POSITION distance)
333 {
334     if (distance > subject_ptr->see_infra)
335         return FALSE;
336
337     monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
338     if ((r_ptr->flags2 & (RF2_COLD_BLOOD | RF2_AURA_FIRE)) == RF2_COLD_BLOOD)
339         return FALSE;
340
341     um_ptr->easy = TRUE;
342     um_ptr->flag = TRUE;
343     return TRUE;
344 }
345
346 static bool check_invisible(player_type *subject_ptr, um_type *um_ptr)
347 {
348     if (!player_can_see_bold(subject_ptr, um_ptr->fy, um_ptr->fx))
349         return FALSE;
350
351     monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
352     if (r_ptr->flags2 & RF2_INVISIBLE) {
353         if (subject_ptr->see_inv) {
354             um_ptr->easy = TRUE;
355             um_ptr->flag = TRUE;
356         }
357     } else {
358         um_ptr->easy = TRUE;
359         um_ptr->flag = TRUE;
360     }
361
362     return TRUE;
363 }
364
365 /*!
366  * @brief テレパシー・赤外線視力・可視透明によってモンスターを感知できるかどうかの判定
367  * @param subject_ptr プレーヤーへの参照ポインタ
368  * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
369  * @return なし
370  */
371 static void decide_sight_invisible_monster(player_type *subject_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
372 {
373     POSITION distance = decide_updated_distance(subject_ptr, um_ptr);
374     monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
375     if (distance > (um_ptr->in_darkness ? MAX_SIGHT / 2 : MAX_SIGHT))
376         return;
377
378     if (!um_ptr->in_darkness || (distance <= MAX_SIGHT / 4)) {
379         update_telepathy_sight(subject_ptr, um_ptr, m_idx);
380         update_specific_race_telepathy(subject_ptr, um_ptr);
381     }
382
383     if (!player_has_los_bold(subject_ptr, um_ptr->fy, um_ptr->fx) || subject_ptr->blind)
384         return;
385
386     if (subject_ptr->concent >= CONCENT_RADAR_THRESHOLD) {
387         um_ptr->easy = TRUE;
388         um_ptr->flag = TRUE;
389     }
390
391     bool do_cold_blood = check_cold_blood(subject_ptr, um_ptr, distance);
392     bool do_invisible = check_invisible(subject_ptr, um_ptr);
393     if (!um_ptr->flag || !is_original_ap(um_ptr->m_ptr) || subject_ptr->image)
394         return;
395
396     if (do_invisible)
397         r_ptr->r_flags2 |= RF2_INVISIBLE;
398
399     if (do_cold_blood)
400         r_ptr->r_flags2 |= RF2_COLD_BLOOD;
401 }
402
403 /*!
404  * @brief 壁の向こうにいるモンスターへのテレパシー・赤外線視力による冷血動物以外の透明モンスター・可視透明能力による透明モンスター
405  * 以上を感知する
406  * @param subject_ptr プレーヤーへの参照ポインタ
407  * @param um_ptr モンスター情報アップデート構造体への参照ポインタ
408  * @param m_idx フロアのモンスター番号
409  * @return なし
410  * @details 感知した結果、エルドリッチホラー持ちがいたら精神を破壊する
411  */
412 static void update_invisible_monster(player_type *subject_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
413 {
414     if (um_ptr->m_ptr->ml)
415         return;
416
417     um_ptr->m_ptr->ml = TRUE;
418     lite_spot(subject_ptr, um_ptr->fy, um_ptr->fx);
419
420     if (subject_ptr->health_who == m_idx)
421         subject_ptr->redraw |= PR_HEALTH;
422
423     if (subject_ptr->riding == m_idx)
424         subject_ptr->redraw |= PR_UHEALTH;
425
426     if (!subject_ptr->image) {
427         monster_race *r_ptr = &r_info[um_ptr->m_ptr->r_idx];
428         if ((um_ptr->m_ptr->ap_r_idx == MON_KAGE) && (r_info[MON_KAGE].r_sights < MAX_SHORT))
429             r_info[MON_KAGE].r_sights++;
430         else if (is_original_ap(um_ptr->m_ptr) && (r_ptr->r_sights < MAX_SHORT))
431             r_ptr->r_sights++;
432     }
433
434     if (r_info[um_ptr->m_ptr->ap_r_idx].flags2 & RF2_ELDRITCH_HORROR)
435         sanity_blast(subject_ptr, um_ptr->m_ptr, FALSE);
436
437     if (disturb_near
438         && (projectable(subject_ptr, um_ptr->m_ptr->fy, um_ptr->m_ptr->fx, subject_ptr->y, subject_ptr->x)
439             && projectable(subject_ptr, subject_ptr->y, subject_ptr->x, um_ptr->m_ptr->fy, um_ptr->m_ptr->fx))) {
440         if (disturb_pets || is_hostile(um_ptr->m_ptr))
441             disturb(subject_ptr, TRUE, TRUE);
442     }
443 }
444
445 static void update_visible_monster(player_type *subject_ptr, um_type *um_ptr, MONSTER_IDX m_idx)
446 {
447     if (!um_ptr->m_ptr->ml)
448         return;
449
450     um_ptr->m_ptr->ml = FALSE;
451     lite_spot(subject_ptr, um_ptr->fy, um_ptr->fx);
452
453     if (subject_ptr->health_who == m_idx)
454         subject_ptr->redraw |= PR_HEALTH;
455
456     if (subject_ptr->riding == m_idx)
457         subject_ptr->redraw |= PR_UHEALTH;
458
459     if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr)))
460         disturb(subject_ptr, TRUE, TRUE);
461 }
462
463 static bool update_clear_monster(player_type *subject_ptr, um_type *um_ptr)
464 {
465     if (!um_ptr->easy)
466         return FALSE;
467
468     if (!(um_ptr->m_ptr->mflag & MFLAG_VIEW)) {
469         um_ptr->m_ptr->mflag |= MFLAG_VIEW;
470         if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr)))
471             disturb(subject_ptr, TRUE, TRUE);
472     }
473
474     return TRUE;
475 }
476
477 /*!
478  * @brief モンスターの各情報を更新する / This function updates the monster record of the given monster
479  * @param m_idx 更新するモンスター情報のID
480  * @param full プレイヤーとの距離更新を行うならばtrue
481  * @return なし
482  */
483 void update_monster(player_type *subject_ptr, MONSTER_IDX m_idx, bool full)
484 {
485     um_type tmp_um;
486     um_type *um_ptr = initialize_um_type(subject_ptr, &tmp_um, m_idx, full);
487     if (disturb_high) {
488         monster_race *ap_r_ptr = &r_info[um_ptr->m_ptr->ap_r_idx];
489         if (ap_r_ptr->r_tkills && ap_r_ptr->level >= subject_ptr->lev)
490             um_ptr->do_disturb = TRUE;
491     }
492
493     if (um_ptr->m_ptr->mflag2 & MFLAG2_MARK)
494         um_ptr->flag = TRUE;
495
496     decide_sight_invisible_monster(subject_ptr, um_ptr, m_idx);
497     if (um_ptr->flag)
498         update_invisible_monster(subject_ptr, um_ptr, m_idx);
499     else
500         update_visible_monster(subject_ptr, um_ptr, m_idx);
501
502     if (update_clear_monster(subject_ptr, um_ptr) || ((um_ptr->m_ptr->mflag & MFLAG_VIEW) == 0))
503         return;
504
505     um_ptr->m_ptr->mflag &= ~(MFLAG_VIEW);
506     if (um_ptr->do_disturb && (disturb_pets || is_hostile(um_ptr->m_ptr)))
507         disturb(subject_ptr, TRUE, TRUE);
508 }
509
510 /*!
511  * todo モンスターの感知状況しか更新していないように見える。関数名変更を検討する
512  * @param player_ptr プレーヤーへの参照ポインタ
513  * @brief 単純に生存している全モンスターの更新処理を行う / This function simply updates all the (non-dead) monsters (see above).
514  * @param full 距離更新を行うならtrue
515  * @return なし
516  */
517 void update_monsters(player_type *player_ptr, bool full)
518 {
519     floor_type *floor_ptr = player_ptr->current_floor_ptr;
520     for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
521         monster_type *m_ptr = &floor_ptr->m_list[i];
522         if (!monster_is_valid(m_ptr))
523             continue;
524
525         update_monster(player_ptr, i, full);
526     }
527 }
528
529 /*!
530  * @brief SMART(適格に攻撃を行う)モンスターの学習状況を更新する / Learn about an "observed" resistance.
531  * @param m_idx 更新を行う「モンスター情報ID
532  * @param what 学習対象ID
533  * @return なし
534  */
535 void update_smart_learn(player_type *player_ptr, MONSTER_IDX m_idx, int what)
536 {
537     monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
538     monster_race *r_ptr = &r_info[m_ptr->r_idx];
539     if (!smart_learn || ((r_ptr->flags2 & RF2_STUPID) != 0) || (((r_ptr->flags2 & RF2_SMART) == 0) && (randint0(100) < 50)))
540         return;
541
542     switch (what) {
543     case DRS_ACID:
544         if (has_resist_acid(player_ptr))
545             m_ptr->smart |= SM_RES_ACID;
546
547         if (is_oppose_acid(player_ptr))
548             m_ptr->smart |= SM_OPP_ACID;
549
550         if (has_immune_acid(player_ptr))
551             m_ptr->smart |= SM_IMM_ACID;
552
553         break;
554     case DRS_ELEC:
555         if (has_resist_elec(player_ptr))
556             m_ptr->smart |= SM_RES_ELEC;
557
558         if (is_oppose_elec(player_ptr))
559             m_ptr->smart |= SM_OPP_ELEC;
560
561         if (has_immune_elec(player_ptr))
562             m_ptr->smart |= SM_IMM_ELEC;
563
564         break;
565     case DRS_FIRE:
566         if (has_resist_fire(player_ptr))
567             m_ptr->smart |= SM_RES_FIRE;
568
569         if (is_oppose_fire(player_ptr))
570             m_ptr->smart |= SM_OPP_FIRE;
571
572         if (has_immune_fire(player_ptr))
573             m_ptr->smart |= SM_IMM_FIRE;
574
575         break;
576     case DRS_COLD:
577         if (has_resist_cold(player_ptr))
578             m_ptr->smart |= SM_RES_COLD;
579
580         if (is_oppose_cold(player_ptr))
581             m_ptr->smart |= SM_OPP_COLD;
582
583         if (has_immune_cold(player_ptr))
584             m_ptr->smart |= SM_IMM_COLD;
585
586         break;
587     case DRS_POIS:
588         if (has_resist_pois(player_ptr))
589             m_ptr->smart |= SM_RES_POIS;
590
591         if (is_oppose_pois(player_ptr))
592             m_ptr->smart |= SM_OPP_POIS;
593
594         break;
595     case DRS_NETH:
596         if (has_resist_neth(player_ptr))
597             m_ptr->smart |= SM_RES_NETH;
598
599         break;
600     case DRS_LITE:
601         if (has_resist_lite(player_ptr))
602             m_ptr->smart |= SM_RES_LITE;
603
604         break;
605     case DRS_DARK:
606         if (has_resist_dark(player_ptr))
607             m_ptr->smart |= SM_RES_DARK;
608
609         break;
610     case DRS_FEAR:
611         if (has_resist_fear(player_ptr))
612             m_ptr->smart |= SM_RES_FEAR;
613
614         break;
615     case DRS_CONF:
616         if (has_resist_conf(player_ptr))
617             m_ptr->smart |= SM_RES_CONF;
618
619         break;
620     case DRS_CHAOS:
621         if (has_resist_chaos(player_ptr))
622             m_ptr->smart |= SM_RES_CHAOS;
623
624         break;
625     case DRS_DISEN:
626         if (has_resist_disen(player_ptr))
627             m_ptr->smart |= SM_RES_DISEN;
628
629         break;
630     case DRS_BLIND:
631         if (has_resist_blind(player_ptr))
632             m_ptr->smart |= SM_RES_BLIND;
633
634         break;
635     case DRS_NEXUS:
636         if (has_resist_nexus(player_ptr))
637             m_ptr->smart |= SM_RES_NEXUS;
638
639         break;
640     case DRS_SOUND:
641         if (has_resist_sound(player_ptr))
642             m_ptr->smart |= SM_RES_SOUND;
643
644         break;
645     case DRS_SHARD:
646         if (has_resist_shard(player_ptr))
647             m_ptr->smart |= SM_RES_SHARD;
648
649         break;
650     case DRS_FREE:
651         if (player_ptr->free_act)
652             m_ptr->smart |= SM_IMM_FREE;
653
654         break;
655     case DRS_MANA:
656         if (!player_ptr->msp)
657             m_ptr->smart |= SM_IMM_MANA;
658
659         break;
660     case DRS_REFLECT:
661         if (has_reflect(player_ptr))
662             m_ptr->smart |= SM_IMM_REFLECT;
663
664         break;
665     default:
666         break;
667     }
668 }