OSDN Git Service

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