OSDN Git Service

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