OSDN Git Service

Merge pull request #1363 from backwardsEric/Pakuman-English
[hengbandforosx/hengbandosx.git] / src / monster-floor / monster-lite.cpp
1 #include "monster-floor/monster-lite.h"
2 #include "core/player-update-types.h"
3 #include "dungeon/dungeon-flag-types.h"
4 #include "dungeon/dungeon.h"
5 #include "floor/cave.h"
6 #include "grid/feature-flag-types.h"
7 #include "grid/grid.h"
8 #include "monster-floor/monster-lite-util.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-flags7.h"
11 #include "monster/monster-status.h"
12 #include "player/special-defense-types.h"
13 #include "system/floor-type-definition.h"
14 #include "system/grid-type-definition.h"
15 #include "system/monster-race-definition.h"
16 #include "system/monster-type-definition.h"
17 #include "system/player-type-definition.h"
18 #include "util/point-2d.h"
19 #include "view/display-messages.h"
20 #include "world/world.h"
21 #include <vector>
22
23 /*!
24  * @brief モンスターによる光量状態更新 / Add a square to the changes array
25  * @param subject_ptr 主観となるクリーチャーの参照ポインタ
26  * @param points 座標たちを記録する配列
27  * @param y Y座標
28  * @param x X座標
29  */
30 static void update_monster_lite(
31     player_type *const subject_ptr, std::vector<Pos2D> &points, const POSITION y, const POSITION x, const monster_lite_type *const ml_ptr)
32 {
33     grid_type *g_ptr;
34     int dpf, d;
35     POSITION midpoint;
36     g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
37     if ((g_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW)
38         return;
39
40     if (!feat_supports_los(g_ptr->feat)) {
41         if (((y < subject_ptr->y) && (y > ml_ptr->mon_fy)) || ((y > subject_ptr->y) && (y < ml_ptr->mon_fy))) {
42             dpf = subject_ptr->y - ml_ptr->mon_fy;
43             d = y - ml_ptr->mon_fy;
44             midpoint = ml_ptr->mon_fx + ((subject_ptr->x - ml_ptr->mon_fx) * ABS(d)) / ABS(dpf);
45             if (x < midpoint) {
46                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x + 1))
47                     return;
48             } else if (x > midpoint) {
49                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x - 1))
50                     return;
51             } else if (ml_ptr->mon_invis)
52                 return;
53         }
54
55         if (((x < subject_ptr->x) && (x > ml_ptr->mon_fx)) || ((x > subject_ptr->x) && (x < ml_ptr->mon_fx))) {
56             dpf = subject_ptr->x - ml_ptr->mon_fx;
57             d = x - ml_ptr->mon_fx;
58             midpoint = ml_ptr->mon_fy + ((subject_ptr->y - ml_ptr->mon_fy) * ABS(d)) / ABS(dpf);
59             if (y < midpoint) {
60                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y + 1, x))
61                     return;
62             } else if (y > midpoint) {
63                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y - 1, x))
64                     return;
65             } else if (ml_ptr->mon_invis)
66                 return;
67         }
68     }
69
70     if (!(g_ptr->info & CAVE_MNDK)) {
71         points.emplace_back(y, x);
72     } else {
73         g_ptr->info &= ~(CAVE_MNDK);
74     }
75
76     g_ptr->info |= CAVE_MNLT;
77 }
78
79 /*
80  * Add a square to the changes array
81  */
82 static void update_monster_dark(
83     player_type *const subject_ptr, std::vector<Pos2D> &points, const POSITION y, const POSITION x, const monster_lite_type *const ml_ptr)
84 {
85     grid_type *g_ptr;
86     int midpoint, dpf, d;
87     g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
88     if ((g_ptr->info & (CAVE_LITE | CAVE_MNLT | CAVE_MNDK | CAVE_VIEW)) != CAVE_VIEW)
89         return;
90
91     if (!feat_supports_los(g_ptr->feat) && !g_ptr->cave_has_flag(FF_PROJECT)) {
92         if (((y < subject_ptr->y) && (y > ml_ptr->mon_fy)) || ((y > subject_ptr->y) && (y < ml_ptr->mon_fy))) {
93             dpf = subject_ptr->y - ml_ptr->mon_fy;
94             d = y - ml_ptr->mon_fy;
95             midpoint = ml_ptr->mon_fx + ((subject_ptr->x - ml_ptr->mon_fx) * ABS(d)) / ABS(dpf);
96             if (x < midpoint) {
97                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x + 1) && !cave_has_flag_bold(subject_ptr->current_floor_ptr, y, x + 1, FF_PROJECT))
98                     return;
99             } else if (x > midpoint) {
100                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x - 1) && !cave_has_flag_bold(subject_ptr->current_floor_ptr, y, x - 1, FF_PROJECT))
101                     return;
102             } else if (ml_ptr->mon_invis)
103                 return;
104         }
105
106         if (((x < subject_ptr->x) && (x > ml_ptr->mon_fx)) || ((x > subject_ptr->x) && (x < ml_ptr->mon_fx))) {
107             dpf = subject_ptr->x - ml_ptr->mon_fx;
108             d = x - ml_ptr->mon_fx;
109             midpoint = ml_ptr->mon_fy + ((subject_ptr->y - ml_ptr->mon_fy) * ABS(d)) / ABS(dpf);
110             if (y < midpoint) {
111                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y + 1, x) && !cave_has_flag_bold(subject_ptr->current_floor_ptr, y + 1, x, FF_PROJECT))
112                     return;
113             } else if (y > midpoint) {
114                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y - 1, x) && !cave_has_flag_bold(subject_ptr->current_floor_ptr, y - 1, x, FF_PROJECT))
115                     return;
116             } else if (ml_ptr->mon_invis)
117                 return;
118         }
119     }
120
121     points.emplace_back(y, x);
122     g_ptr->info |= CAVE_MNDK;
123 }
124
125 /*!
126  * @brief Update squares illuminated or darkened by monsters.
127  * The CAVE_TEMP and CAVE_XTRA flag are used to store the state during the
128  * updating.  Only squares in view of the player, whos state
129  * changes are drawn via lite_spot().
130  * @todo player-status からのみ呼ばれている。しかしあちらは行数が酷いので要調整
131  */
132 void update_mon_lite(player_type *subject_ptr)
133 {
134     // 座標たちを記録する配列。
135     std::vector<Pos2D> points;
136
137     void (*add_mon_lite)(player_type *, std::vector<Pos2D> &, const POSITION, const POSITION, const monster_lite_type *);
138     int dis_lim = (d_info[subject_ptr->dungeon_idx].flags.has(DF::DARKNESS) && !subject_ptr->see_nocto) ? (MAX_SIGHT / 2 + 1) : (MAX_SIGHT + 3);
139     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
140     for (int i = 0; i < floor_ptr->mon_lite_n; i++) {
141         grid_type *g_ptr;
142         g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
143         g_ptr->info |= (g_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
144         g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
145     }
146
147     if (!current_world_ptr->timewalk_m_idx) {
148         monster_type *m_ptr;
149         monster_race *r_ptr;
150         for (int i = 1; i < floor_ptr->m_max; i++) {
151             m_ptr = &floor_ptr->m_list[i];
152             r_ptr = &r_info[m_ptr->r_idx];
153             if (!monster_is_valid(m_ptr) || (m_ptr->cdis > dis_lim))
154                 continue;
155
156             int rad = 0;
157             if (r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_SELF_LITE_1))
158                 rad++;
159
160             if (r_ptr->flags7 & (RF7_HAS_LITE_2 | RF7_SELF_LITE_2))
161                 rad += 2;
162
163             if (r_ptr->flags7 & (RF7_HAS_DARK_1 | RF7_SELF_DARK_1))
164                 rad--;
165
166             if (r_ptr->flags7 & (RF7_HAS_DARK_2 | RF7_SELF_DARK_2))
167                 rad -= 2;
168
169             if (!rad)
170                 continue;
171
172             feature_flag_type f_flag;
173             if (rad > 0) {
174                 if (!(r_ptr->flags7 & (RF7_SELF_LITE_1 | RF7_SELF_LITE_2))
175                     && (monster_csleep_remaining(m_ptr) || (!floor_ptr->dun_level && is_daytime()) || subject_ptr->phase_out))
176                     continue;
177
178                 if (d_info[subject_ptr->dungeon_idx].flags.has(DF::DARKNESS))
179                     rad = 1;
180
181                 add_mon_lite = update_monster_lite;
182                 f_flag = FF_LOS;
183             } else {
184                 if (!(r_ptr->flags7 & (RF7_SELF_DARK_1 | RF7_SELF_DARK_2)) && (monster_csleep_remaining(m_ptr) || (!floor_ptr->dun_level && !is_daytime())))
185                     continue;
186
187                 add_mon_lite = update_monster_dark;
188                 f_flag = FF_PROJECT;
189                 rad = -rad;
190             }
191
192             monster_lite_type tmp_ml;
193             monster_lite_type *ml_ptr = initialize_monster_lite_type(floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].info, &tmp_ml, m_ptr);
194             add_mon_lite(subject_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx, ml_ptr);
195             add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx, ml_ptr);
196             add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx, ml_ptr);
197             add_mon_lite(subject_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx + 1, ml_ptr);
198             add_mon_lite(subject_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx - 1, ml_ptr);
199             add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 1, ml_ptr);
200             add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 1, ml_ptr);
201             add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 1, ml_ptr);
202             add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 1, ml_ptr);
203             if (rad < 2)
204                 continue;
205
206             grid_type *g_ptr;
207             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx, f_flag)) {
208                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx + 1, ml_ptr);
209                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx, ml_ptr);
210                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx - 1, ml_ptr);
211                 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy + 2][ml_ptr->mon_fx];
212                 if ((rad == 3) && g_ptr->cave_has_flag(f_flag)) {
213                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 3, ml_ptr->mon_fx + 1, ml_ptr);
214                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 3, ml_ptr->mon_fx, ml_ptr);
215                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 3, ml_ptr->mon_fx - 1, ml_ptr);
216                 }
217             }
218
219             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx, f_flag)) {
220                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx + 1, ml_ptr);
221                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx, ml_ptr);
222                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx - 1, ml_ptr);
223                 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy - 2][ml_ptr->mon_fx];
224                 if ((rad == 3) && g_ptr->cave_has_flag(f_flag)) {
225                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 3, ml_ptr->mon_fx + 1, ml_ptr);
226                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 3, ml_ptr->mon_fx, ml_ptr);
227                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 3, ml_ptr->mon_fx - 1, ml_ptr);
228                 }
229             }
230
231             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx + 1, f_flag)) {
232                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 2, ml_ptr);
233                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx + 2, ml_ptr);
234                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 2, ml_ptr);
235                 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy][ml_ptr->mon_fx + 2];
236                 if ((rad == 3) && g_ptr->cave_has_flag(f_flag)) {
237                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 3, ml_ptr);
238                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx + 3, ml_ptr);
239                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 3, ml_ptr);
240                 }
241             }
242
243             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx - 1, f_flag)) {
244                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 2, ml_ptr);
245                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx - 2, ml_ptr);
246                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 2, ml_ptr);
247                 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy][ml_ptr->mon_fx - 2];
248                 if ((rad == 3) && g_ptr->cave_has_flag(f_flag)) {
249                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 3, ml_ptr);
250                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy, ml_ptr->mon_fx - 3, ml_ptr);
251                     add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 3, ml_ptr);
252                 }
253             }
254
255             if (rad != 3)
256                 continue;
257
258             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 1, f_flag))
259                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx + 2, ml_ptr);
260
261             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 1, f_flag))
262                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy + 2, ml_ptr->mon_fx - 2, ml_ptr);
263
264             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 1, f_flag))
265                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx + 2, ml_ptr);
266
267             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 1, f_flag))
268                 add_mon_lite(subject_ptr, points, ml_ptr->mon_fy - 2, ml_ptr->mon_fx - 2, ml_ptr);
269         }
270     }
271
272     const auto end_temp = size(points);
273     for (int i = 0; i < floor_ptr->mon_lite_n; i++) {
274         POSITION fx = floor_ptr->mon_lite_x[i];
275         POSITION fy = floor_ptr->mon_lite_y[i];
276         grid_type *g_ptr;
277         g_ptr = &floor_ptr->grid_array[fy][fx];
278         if (g_ptr->info & CAVE_TEMP) {
279             if ((g_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW)
280                 cave_note_and_redraw_later(floor_ptr, fy, fx);
281         } else if ((g_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW)
282             cave_note_and_redraw_later(floor_ptr, fy, fx);
283
284         points.emplace_back(fy, fx);
285     }
286
287     floor_ptr->mon_lite_n = 0;
288     for (size_t i = 0; i < end_temp; i++) {
289         const auto [fy, fx] = points[i];
290
291         grid_type *const g_ptr = &floor_ptr->grid_array[fy][fx];
292         if (g_ptr->info & CAVE_MNLT) {
293             if ((g_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW)
294                 cave_note_and_redraw_later(floor_ptr, fy, fx);
295         } else if ((g_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW)
296             cave_note_and_redraw_later(floor_ptr, fy, fx);
297
298         floor_ptr->mon_lite_x[floor_ptr->mon_lite_n] = fx;
299         floor_ptr->mon_lite_y[floor_ptr->mon_lite_n] = fy;
300         floor_ptr->mon_lite_n++;
301     }
302
303     for (size_t i = end_temp; i < size(points); i++) {
304         const auto [y, x] = points[i];
305         floor_ptr->grid_array[y][x].info &= ~(CAVE_TEMP | CAVE_XTRA);
306     }
307
308     subject_ptr->update |= PU_DELAY_VIS;
309     subject_ptr->monlite = (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_MNLT) != 0;
310     if (!(subject_ptr->special_defense & NINJA_S_STEALTH)) {
311         subject_ptr->old_monlite = subject_ptr->monlite;
312         return;
313     }
314
315     if (subject_ptr->old_monlite == subject_ptr->monlite) {
316         subject_ptr->old_monlite = subject_ptr->monlite;
317         return;
318     }
319
320     if (subject_ptr->monlite)
321         msg_print(_("影の覆いが薄れた気がする。", "Your mantle of shadow becomes thin."));
322     else
323         msg_print(_("影の覆いが濃くなった!", "Your mantle of shadow is restored to its original darkness."));
324
325     subject_ptr->old_monlite = subject_ptr->monlite;
326 }
327
328 /*!
329  * @brief 画面切り替え等でモンスターの灯りを消去する
330  * @param floor_ptr 現在フロアへの参照ポインタ
331  */
332 void clear_mon_lite(floor_type *floor_ptr)
333 {
334     for (int i = 0; i < floor_ptr->mon_lite_n; i++) {
335         grid_type *g_ptr;
336         g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
337         g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
338     }
339
340     floor_ptr->mon_lite_n = 0;
341 }