OSDN Git Service

[Refactor] #40577 Moved projectable() from floor.c/h to projection-path-calculator.c/h
[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/special-defense-types.h"
32 #include "status/element-resistance.h"
33 #include "system/floor-type-definition.h"
34 #include "target/projection-path-calculator.h"
35
36 /*!
37  * @brief 騎乗中のモンスター情報を更新する
38  * @param target_ptr プレーヤーへの参照ポインタ
39  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
40  * @param m_idx モンスターID
41  * @param oy 移動前の、モンスターのY座標
42  * @param ox 移動前の、モンスターのX座標
43  * @param ny 移動後の、モンスターのY座標
44  * @param ox 移動後の、モンスターのX座標
45  * @return アイテム等に影響を及ぼしたらTRUE
46  */
47 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)
48 {
49         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
50         grid_type *g_ptr;
51         g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
52         monster_type *y_ptr;
53         y_ptr = &target_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
54         if (turn_flags_ptr->is_riding_mon)
55                 return move_player_effect(target_ptr, ny, nx, MPE_DONT_PICKUP);
56
57         target_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
58         if (g_ptr->m_idx)
59         {
60                 y_ptr->fy = oy;
61                 y_ptr->fx = ox;
62                 update_monster(target_ptr, g_ptr->m_idx, TRUE);
63         }
64
65         g_ptr->m_idx = m_idx;
66         m_ptr->fy = ny;
67         m_ptr->fx = nx;
68         update_monster(target_ptr, m_idx, TRUE);
69
70         lite_spot(target_ptr, oy, ox);
71         lite_spot(target_ptr, ny, nx);
72         return TRUE;
73 }
74
75
76 /*!
77  * @brief updateフィールドを更新する
78  * @param target_ptr プレーヤーへの参照ポインタ
79  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
80  * @return なし
81  */
82 void update_player_type(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr)
83 {
84         if (turn_flags_ptr->do_view)
85         {
86                 target_ptr->update |= (PU_FLOW);
87                 target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
88         }
89
90         if (turn_flags_ptr->do_move && ((r_ptr->flags7 & (RF7_SELF_LD_MASK | RF7_HAS_DARK_1 | RF7_HAS_DARK_2))
91                 || ((r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_HAS_LITE_2)) && !target_ptr->phase_out)))
92         {
93                 target_ptr->update |= (PU_MON_LITE);
94         }
95 }
96
97
98 /*!
99  * @brief モンスターのフラグを更新する
100  * @param target_ptr プレーヤーへの参照ポインタ
101  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
102  * @param m_ptr モンスターへの参照ポインタ
103  * @return なし
104  */
105 void update_monster_race_flags(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr)
106 {
107         monster_race *r_ptr = &r_info[m_ptr->r_idx];
108         if (!is_original_ap_and_seen(target_ptr, m_ptr)) return;
109
110         if (turn_flags_ptr->did_open_door) r_ptr->r_flags2 |= (RF2_OPEN_DOOR);
111         if (turn_flags_ptr->did_bash_door) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
112         if (turn_flags_ptr->did_take_item) r_ptr->r_flags2 |= (RF2_TAKE_ITEM);
113         if (turn_flags_ptr->did_kill_item) r_ptr->r_flags2 |= (RF2_KILL_ITEM);
114         if (turn_flags_ptr->did_move_body) r_ptr->r_flags2 |= (RF2_MOVE_BODY);
115         if (turn_flags_ptr->did_pass_wall) r_ptr->r_flags2 |= (RF2_PASS_WALL);
116         if (turn_flags_ptr->did_kill_wall) r_ptr->r_flags2 |= (RF2_KILL_WALL);
117 }
118
119
120 /*!
121  * @brief モンスターフラグの更新に基づき、モンスター表示を更新する
122  * @param monster_race_idx モンスターID
123  * @param window ウィンドウフラグ
124  * @param old_race_flags_ptr モンスターフラグへの参照ポインタ
125  * @return なし
126  */
127 void update_player_window(player_type *target_ptr, old_race_flags *old_race_flags_ptr)
128 {
129         monster_race *r_ptr;
130         r_ptr = &r_info[target_ptr->monster_race_idx];
131         if ((old_race_flags_ptr->old_r_flags1 != r_ptr->r_flags1) ||
132                 (old_race_flags_ptr->old_r_flags2 != r_ptr->r_flags2) ||
133                 (old_race_flags_ptr->old_r_flags3 != r_ptr->r_flags3) ||
134                 (old_race_flags_ptr->old_r_flags4 != r_ptr->r_flags4) ||
135                 (old_race_flags_ptr->old_r_flags5 != r_ptr->r_flags5) ||
136                 (old_race_flags_ptr->old_r_flags6 != r_ptr->r_flags6) ||
137                 (old_race_flags_ptr->old_r_flagsr != r_ptr->r_flagsr) ||
138                 (old_race_flags_ptr->old_r_blows0 != r_ptr->r_blows[0]) ||
139                 (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) ||
140                 (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2]) ||
141                 (old_race_flags_ptr->old_r_blows3 != r_ptr->r_blows[3]) ||
142                 (old_race_flags_ptr->old_r_cast_spell != r_ptr->r_cast_spell))
143         {
144                 target_ptr->window |= (PW_MONSTER);
145         }
146 }
147
148 /*!
149  * @brief モンスターの各情報を更新する / This function updates the monster record of the given monster
150  * @param m_idx 更新するモンスター情報のID
151  * @param full プレイヤーとの距離更新を行うならばtrue
152  * @return なし
153  */
154 void update_monster(player_type *subject_ptr, MONSTER_IDX m_idx, bool full)
155 {
156     monster_type *m_ptr = &subject_ptr->current_floor_ptr->m_list[m_idx];
157     monster_race *r_ptr = &r_info[m_ptr->r_idx];
158
159     bool do_disturb = disturb_move;
160
161     POSITION fy = m_ptr->fy;
162     POSITION fx = m_ptr->fx;
163
164     bool flag = FALSE;
165     bool easy = FALSE;
166     bool in_darkness = (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !subject_ptr->see_nocto;
167     if (disturb_high) {
168         monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
169         if (ap_r_ptr->r_tkills && ap_r_ptr->level >= subject_ptr->lev)
170             do_disturb = TRUE;
171     }
172
173     POSITION distance;
174     if (full) {
175         int dy = (subject_ptr->y > fy) ? (subject_ptr->y - fy) : (fy - subject_ptr->y);
176         int dx = (subject_ptr->x > fx) ? (subject_ptr->x - fx) : (fx - subject_ptr->x);
177
178         distance = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
179         if (distance > 255)
180             distance = 255;
181         if (!distance)
182             distance = 1;
183
184         m_ptr->cdis = distance;
185     } else {
186         distance = m_ptr->cdis;
187     }
188
189     if (m_ptr->mflag2 & (MFLAG2_MARK))
190         flag = TRUE;
191
192     if (distance <= (in_darkness ? MAX_SIGHT / 2 : MAX_SIGHT)) {
193         if (!in_darkness || (distance <= MAX_SIGHT / 4)) {
194             if (subject_ptr->special_defense & KATA_MUSOU) {
195                 flag = TRUE;
196                 if (is_original_ap(m_ptr) && !subject_ptr->image) {
197                     if (r_ptr->flags2 & (RF2_SMART))
198                         r_ptr->r_flags2 |= (RF2_SMART);
199                     if (r_ptr->flags2 & (RF2_STUPID))
200                         r_ptr->r_flags2 |= (RF2_STUPID);
201                 }
202             } else if (subject_ptr->telepathy) {
203                 if (r_ptr->flags2 & (RF2_EMPTY_MIND)) {
204                     if (is_original_ap(m_ptr) && !subject_ptr->image)
205                         r_ptr->r_flags2 |= (RF2_EMPTY_MIND);
206                 } else if (r_ptr->flags2 & (RF2_WEIRD_MIND)) {
207                     if ((m_idx % 10) == 5) {
208                         flag = TRUE;
209                         if (is_original_ap(m_ptr) && !subject_ptr->image) {
210                             r_ptr->r_flags2 |= (RF2_WEIRD_MIND);
211                             if (r_ptr->flags2 & (RF2_SMART))
212                                 r_ptr->r_flags2 |= (RF2_SMART);
213                             if (r_ptr->flags2 & (RF2_STUPID))
214                                 r_ptr->r_flags2 |= (RF2_STUPID);
215                         }
216                     }
217                 } else {
218                     flag = TRUE;
219                     if (is_original_ap(m_ptr) && !subject_ptr->image) {
220                         if (r_ptr->flags2 & (RF2_SMART))
221                             r_ptr->r_flags2 |= (RF2_SMART);
222                         if (r_ptr->flags2 & (RF2_STUPID))
223                             r_ptr->r_flags2 |= (RF2_STUPID);
224                     }
225                 }
226             }
227
228             if ((subject_ptr->esp_animal) && (r_ptr->flags3 & (RF3_ANIMAL))) {
229                 flag = TRUE;
230                 if (is_original_ap(m_ptr) && !subject_ptr->image)
231                     r_ptr->r_flags3 |= (RF3_ANIMAL);
232             }
233
234             if ((subject_ptr->esp_undead) && (r_ptr->flags3 & (RF3_UNDEAD))) {
235                 flag = TRUE;
236                 if (is_original_ap(m_ptr) && !subject_ptr->image)
237                     r_ptr->r_flags3 |= (RF3_UNDEAD);
238             }
239
240             if ((subject_ptr->esp_demon) && (r_ptr->flags3 & (RF3_DEMON))) {
241                 flag = TRUE;
242                 if (is_original_ap(m_ptr) && !subject_ptr->image)
243                     r_ptr->r_flags3 |= (RF3_DEMON);
244             }
245
246             if ((subject_ptr->esp_orc) && (r_ptr->flags3 & (RF3_ORC))) {
247                 flag = TRUE;
248                 if (is_original_ap(m_ptr) && !subject_ptr->image)
249                     r_ptr->r_flags3 |= (RF3_ORC);
250             }
251
252             if ((subject_ptr->esp_troll) && (r_ptr->flags3 & (RF3_TROLL))) {
253                 flag = TRUE;
254                 if (is_original_ap(m_ptr) && !subject_ptr->image)
255                     r_ptr->r_flags3 |= (RF3_TROLL);
256             }
257
258             if ((subject_ptr->esp_giant) && (r_ptr->flags3 & (RF3_GIANT))) {
259                 flag = TRUE;
260                 if (is_original_ap(m_ptr) && !subject_ptr->image)
261                     r_ptr->r_flags3 |= (RF3_GIANT);
262             }
263
264             if ((subject_ptr->esp_dragon) && (r_ptr->flags3 & (RF3_DRAGON))) {
265                 flag = TRUE;
266                 if (is_original_ap(m_ptr) && !subject_ptr->image)
267                     r_ptr->r_flags3 |= (RF3_DRAGON);
268             }
269
270             if ((subject_ptr->esp_human) && (r_ptr->flags2 & (RF2_HUMAN))) {
271                 flag = TRUE;
272                 if (is_original_ap(m_ptr) && !subject_ptr->image)
273                     r_ptr->r_flags2 |= (RF2_HUMAN);
274             }
275
276             if ((subject_ptr->esp_evil) && (r_ptr->flags3 & (RF3_EVIL))) {
277                 flag = TRUE;
278                 if (is_original_ap(m_ptr) && !subject_ptr->image)
279                     r_ptr->r_flags3 |= (RF3_EVIL);
280             }
281
282             if ((subject_ptr->esp_good) && (r_ptr->flags3 & (RF3_GOOD))) {
283                 flag = TRUE;
284                 if (is_original_ap(m_ptr) && !subject_ptr->image)
285                     r_ptr->r_flags3 |= (RF3_GOOD);
286             }
287
288             if ((subject_ptr->esp_nonliving) && ((r_ptr->flags3 & (RF3_DEMON | RF3_UNDEAD | RF3_NONLIVING)) == RF3_NONLIVING)) {
289                 flag = TRUE;
290                 if (is_original_ap(m_ptr) && !subject_ptr->image)
291                     r_ptr->r_flags3 |= (RF3_NONLIVING);
292             }
293
294             if ((subject_ptr->esp_unique) && (r_ptr->flags1 & (RF1_UNIQUE))) {
295                 flag = TRUE;
296                 if (is_original_ap(m_ptr) && !subject_ptr->image)
297                     r_ptr->r_flags1 |= (RF1_UNIQUE);
298             }
299         }
300
301         if (player_has_los_bold(subject_ptr, fy, fx) && !subject_ptr->blind) {
302             bool do_invisible = FALSE;
303             bool do_cold_blood = FALSE;
304
305             if (subject_ptr->concent >= CONCENT_RADAR_THRESHOLD) {
306                 easy = flag = TRUE;
307             }
308
309             if (distance <= subject_ptr->see_infra) {
310                 if ((r_ptr->flags2 & (RF2_COLD_BLOOD | RF2_AURA_FIRE)) == RF2_COLD_BLOOD) {
311                     do_cold_blood = TRUE;
312                 } else {
313                     easy = flag = TRUE;
314                 }
315             }
316
317             if (player_can_see_bold(subject_ptr, fy, fx)) {
318                 if (r_ptr->flags2 & (RF2_INVISIBLE)) {
319                     do_invisible = TRUE;
320                     if (subject_ptr->see_inv) {
321                         easy = flag = TRUE;
322                     }
323                 } else {
324                     easy = flag = TRUE;
325                 }
326             }
327
328             if (flag) {
329                 if (is_original_ap(m_ptr) && !subject_ptr->image) {
330                     if (do_invisible)
331                         r_ptr->r_flags2 |= (RF2_INVISIBLE);
332                     if (do_cold_blood)
333                         r_ptr->r_flags2 |= (RF2_COLD_BLOOD);
334                 }
335             }
336         }
337     }
338
339     /* The monster is now visible */
340     if (flag) {
341         if (!m_ptr->ml) {
342             m_ptr->ml = TRUE;
343             lite_spot(subject_ptr, fy, fx);
344
345             if (subject_ptr->health_who == m_idx)
346                 subject_ptr->redraw |= (PR_HEALTH);
347             if (subject_ptr->riding == m_idx)
348                 subject_ptr->redraw |= (PR_UHEALTH);
349
350             if (!subject_ptr->image) {
351                 if ((m_ptr->ap_r_idx == MON_KAGE) && (r_info[MON_KAGE].r_sights < MAX_SHORT))
352                     r_info[MON_KAGE].r_sights++;
353                 else if (is_original_ap(m_ptr) && (r_ptr->r_sights < MAX_SHORT))
354                     r_ptr->r_sights++;
355             }
356
357             if (r_info[m_ptr->ap_r_idx].flags2 & RF2_ELDRITCH_HORROR) {
358                 sanity_blast(subject_ptr, m_ptr, FALSE);
359             }
360
361             if (disturb_near
362                 && (projectable(subject_ptr, m_ptr->fy, m_ptr->fx, subject_ptr->y, subject_ptr->x)
363                     && projectable(subject_ptr, subject_ptr->y, subject_ptr->x, m_ptr->fy, m_ptr->fx))) {
364                 if (disturb_pets || is_hostile(m_ptr))
365                     disturb(subject_ptr, TRUE, TRUE);
366             }
367         }
368     }
369
370     /* The monster is not visible */
371     else {
372         if (m_ptr->ml) {
373             m_ptr->ml = FALSE;
374             lite_spot(subject_ptr, fy, fx);
375
376             if (subject_ptr->health_who == m_idx)
377                 subject_ptr->redraw |= (PR_HEALTH);
378             if (subject_ptr->riding == m_idx)
379                 subject_ptr->redraw |= (PR_UHEALTH);
380             if (do_disturb) {
381                 if (disturb_pets || is_hostile(m_ptr))
382                     disturb(subject_ptr, TRUE, TRUE);
383             }
384         }
385     }
386
387     /* The monster is now easily visible */
388     if (easy) {
389         if (!(m_ptr->mflag & (MFLAG_VIEW))) {
390             m_ptr->mflag |= (MFLAG_VIEW);
391             if (do_disturb) {
392                 if (disturb_pets || is_hostile(m_ptr))
393                     disturb(subject_ptr, TRUE, TRUE);
394             }
395         }
396
397         return;
398     }
399
400     /* The monster is not easily visible */
401     /* Change */
402     if (!(m_ptr->mflag & (MFLAG_VIEW)))
403         return;
404
405     /* Mark as not easily visible */
406     m_ptr->mflag &= ~(MFLAG_VIEW);
407
408     if (do_disturb) {
409         if (disturb_pets || is_hostile(m_ptr))
410             disturb(subject_ptr, TRUE, TRUE);
411     }
412 }
413
414 /*!
415  * @param player_ptr プレーヤーへの参照ポインタ
416  * @brief 単純に生存している全モンスターの更新処理を行う / This function simply updates all the (non-dead) monsters (see above).
417  * @param full 距離更新を行うならtrue
418  * @return なし
419  */
420 void update_monsters(player_type *player_ptr, bool full)
421 {
422     floor_type *floor_ptr = player_ptr->current_floor_ptr;
423     for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
424         monster_type *m_ptr = &floor_ptr->m_list[i];
425         if (!monster_is_valid(m_ptr))
426             continue;
427         update_monster(player_ptr, i, full);
428     }
429 }
430
431 /*!
432  * @brief SMART(適格に攻撃を行う)モンスターの学習状況を更新する / Learn about an "observed" resistance.
433  * @param m_idx 更新を行う「モンスター情報ID
434  * @param what 学習対象ID
435  * @return なし
436  */
437 void update_smart_learn(player_type *player_ptr, MONSTER_IDX m_idx, int what)
438 {
439     monster_type *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
440     monster_race *r_ptr = &r_info[m_ptr->r_idx];
441
442     if (!smart_learn)
443         return;
444     if (r_ptr->flags2 & (RF2_STUPID))
445         return;
446     if (!(r_ptr->flags2 & (RF2_SMART)) && (randint0(100) < 50))
447         return;
448
449     switch (what) {
450     case DRS_ACID:
451         if (player_ptr->resist_acid)
452             m_ptr->smart |= (SM_RES_ACID);
453         if (is_oppose_acid(player_ptr))
454             m_ptr->smart |= (SM_OPP_ACID);
455         if (player_ptr->immune_acid)
456             m_ptr->smart |= (SM_IMM_ACID);
457         break;
458
459     case DRS_ELEC:
460         if (player_ptr->resist_elec)
461             m_ptr->smart |= (SM_RES_ELEC);
462         if (is_oppose_elec(player_ptr))
463             m_ptr->smart |= (SM_OPP_ELEC);
464         if (player_ptr->immune_elec)
465             m_ptr->smart |= (SM_IMM_ELEC);
466         break;
467
468     case DRS_FIRE:
469         if (player_ptr->resist_fire)
470             m_ptr->smart |= (SM_RES_FIRE);
471         if (is_oppose_fire(player_ptr))
472             m_ptr->smart |= (SM_OPP_FIRE);
473         if (player_ptr->immune_fire)
474             m_ptr->smart |= (SM_IMM_FIRE);
475         break;
476
477     case DRS_COLD:
478         if (player_ptr->resist_cold)
479             m_ptr->smart |= (SM_RES_COLD);
480         if (is_oppose_cold(player_ptr))
481             m_ptr->smart |= (SM_OPP_COLD);
482         if (player_ptr->immune_cold)
483             m_ptr->smart |= (SM_IMM_COLD);
484         break;
485
486     case DRS_POIS:
487         if (player_ptr->resist_pois)
488             m_ptr->smart |= (SM_RES_POIS);
489         if (is_oppose_pois(player_ptr))
490             m_ptr->smart |= (SM_OPP_POIS);
491         break;
492
493     case DRS_NETH:
494         if (player_ptr->resist_neth)
495             m_ptr->smart |= (SM_RES_NETH);
496         break;
497
498     case DRS_LITE:
499         if (player_ptr->resist_lite)
500             m_ptr->smart |= (SM_RES_LITE);
501         break;
502
503     case DRS_DARK:
504         if (player_ptr->resist_dark)
505             m_ptr->smart |= (SM_RES_DARK);
506         break;
507
508     case DRS_FEAR:
509         if (player_ptr->resist_fear)
510             m_ptr->smart |= (SM_RES_FEAR);
511         break;
512
513     case DRS_CONF:
514         if (player_ptr->resist_conf)
515             m_ptr->smart |= (SM_RES_CONF);
516         break;
517
518     case DRS_CHAOS:
519         if (player_ptr->resist_chaos)
520             m_ptr->smart |= (SM_RES_CHAOS);
521         break;
522
523     case DRS_DISEN:
524         if (player_ptr->resist_disen)
525             m_ptr->smart |= (SM_RES_DISEN);
526         break;
527
528     case DRS_BLIND:
529         if (player_ptr->resist_blind)
530             m_ptr->smart |= (SM_RES_BLIND);
531         break;
532
533     case DRS_NEXUS:
534         if (player_ptr->resist_nexus)
535             m_ptr->smart |= (SM_RES_NEXUS);
536         break;
537
538     case DRS_SOUND:
539         if (player_ptr->resist_sound)
540             m_ptr->smart |= (SM_RES_SOUND);
541         break;
542
543     case DRS_SHARD:
544         if (player_ptr->resist_shard)
545             m_ptr->smart |= (SM_RES_SHARD);
546         break;
547
548     case DRS_FREE:
549         if (player_ptr->free_act)
550             m_ptr->smart |= (SM_IMM_FREE);
551         break;
552
553     case DRS_MANA:
554         if (!player_ptr->msp)
555             m_ptr->smart |= (SM_IMM_MANA);
556         break;
557
558     case DRS_REFLECT:
559         if (player_ptr->reflect)
560             m_ptr->smart |= (SM_IMM_REFLECT);
561         break;
562     }
563 }