OSDN Git Service

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