OSDN Git Service

Merge pull request #1192 from hengband/feature/3.0.0Alpha26
[hengbandforosx/hengbandosx.git] / src / player / player-view.cpp
1 #include "core/player-update-types.h"
2 #include "floor/cave.h"
3 #include "floor/line-of-sight.h"
4 #include "game-option/map-screen-options.h"
5 #include "grid/grid.h"
6 #include "player/player-view.h"
7 #include "system/floor-type-definition.h"
8 #include "system/player-type-definition.h"
9 #include "util/point-2d.h"
10
11 #include <vector>
12
13 /*
14  * Helper function for "update_view()" below
15  *
16  * We are checking the "viewability" of grid (y,x) by the player.
17  *
18  * This function assumes that (y,x) is legal (i.e. on the map).
19  *
20  * Grid (y1,x1) is on the "diagonal" between (subject_ptr->y,subject_ptr->x) and (y,x)
21  * Grid (y2,x2) is "adjacent", also between (subject_ptr->y,subject_ptr->x) and (y,x).
22  *
23  * Note that we are using the "CAVE_XTRA" field for marking grids as
24  * "easily viewable".  This bit is cleared at the end of "update_view()".
25  *
26  * This function adds (y,x) to the "viewable set" if necessary.
27  *
28  * This function now returns "TRUE" if vision is "blocked" by grid (y,x).
29  */
30 static bool update_view_aux(player_type *subject_ptr, POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
31 {
32     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
33     grid_type *g1_c_ptr;
34     grid_type *g2_c_ptr;
35     g1_c_ptr = &floor_ptr->grid_array[y1][x1];
36     g2_c_ptr = &floor_ptr->grid_array[y2][x2];
37     bool f1 = (cave_los_grid(g1_c_ptr));
38     bool f2 = (cave_los_grid(g2_c_ptr));
39     if (!f1 && !f2)
40         return true;
41
42     bool v1 = (f1 && (g1_c_ptr->info & CAVE_VIEW));
43     bool v2 = (f2 && (g2_c_ptr->info & CAVE_VIEW));
44     if (!v1 && !v2)
45         return true;
46
47     grid_type *g_ptr;
48     g_ptr = &floor_ptr->grid_array[y][x];
49     bool wall = (!cave_los_grid(g_ptr));
50     bool z1 = (v1 && (g1_c_ptr->info & CAVE_XTRA));
51     bool z2 = (v2 && (g2_c_ptr->info & CAVE_XTRA));
52     if (z1 && z2) {
53         g_ptr->info |= CAVE_XTRA;
54         cave_view_hack(floor_ptr, g_ptr, y, x);
55         return wall;
56     }
57
58     if (z1) {
59         cave_view_hack(floor_ptr, g_ptr, y, x);
60         return wall;
61     }
62
63     if (v1 && v2) {
64         cave_view_hack(floor_ptr, g_ptr, y, x);
65         return wall;
66     }
67
68     if (wall) {
69         cave_view_hack(floor_ptr, g_ptr, y, x);
70         return wall;
71     }
72
73     if (los(subject_ptr, subject_ptr->y, subject_ptr->x, y, x)) {
74         cave_view_hack(floor_ptr, g_ptr, y, x);
75         return wall;
76     }
77
78     return true;
79 }
80
81 /*
82  * Calculate the viewable space
83  *
84  *  1: Process the player
85  *  1a: The player is always (easily) viewable
86  *  2: Process the diagonals
87  *  2a: The diagonals are (easily) viewable up to the first wall
88  *  2b: But never go more than 2/3 of the "full" distance
89  *  3: Process the main axes
90  *  3a: The main axes are (easily) viewable up to the first wall
91  *  3b: But never go more than the "full" distance
92  *  4: Process sequential "strips" in each of the eight octants
93  *  4a: Each strip runs along the previous strip
94  *  4b: The main axes are "previous" to the first strip
95  *  4c: Process both "sides" of each "direction" of each strip
96  *  4c1: Each side aborts as soon as possible
97  *  4c2: Each side tells the next strip how far it has to check
98  */
99 void update_view(player_type *subject_ptr)
100 {
101     // 前回プレイヤーから見えていた座標たちを格納する配列。
102     std::vector<Pos2D> points;
103
104     int n, m, d, k, z;
105     POSITION y, x;
106
107     int se, sw, ne, nw, es, en, ws, wn;
108
109     int full, over;
110
111     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
112     POSITION y_max = floor_ptr->height - 1;
113     POSITION x_max = floor_ptr->width - 1;
114
115     grid_type *g_ptr;
116     if (view_reduce_view && !floor_ptr->dun_level) {
117         full = MAX_SIGHT / 2;
118         over = MAX_SIGHT * 3 / 4;
119     } else {
120         full = MAX_SIGHT;
121         over = MAX_SIGHT * 3 / 2;
122     }
123
124     for (n = 0; n < floor_ptr->view_n; n++) {
125         y = floor_ptr->view_y[n];
126         x = floor_ptr->view_x[n];
127         g_ptr = &floor_ptr->grid_array[y][x];
128         g_ptr->info &= ~(CAVE_VIEW);
129         g_ptr->info |= CAVE_TEMP;
130
131         points.emplace_back(y, x);
132     }
133
134     floor_ptr->view_n = 0;
135     y = subject_ptr->y;
136     x = subject_ptr->x;
137     g_ptr = &floor_ptr->grid_array[y][x];
138     g_ptr->info |= CAVE_XTRA;
139     cave_view_hack(floor_ptr, g_ptr, y, x);
140
141     z = full * 2 / 3;
142     for (d = 1; d <= z; d++) {
143         g_ptr = &floor_ptr->grid_array[y + d][x + d];
144         g_ptr->info |= CAVE_XTRA;
145         cave_view_hack(floor_ptr, g_ptr, y + d, x + d);
146         if (!cave_los_grid(g_ptr))
147             break;
148     }
149
150     for (d = 1; d <= z; d++) {
151         g_ptr = &floor_ptr->grid_array[y + d][x - d];
152         g_ptr->info |= CAVE_XTRA;
153         cave_view_hack(floor_ptr, g_ptr, y + d, x - d);
154         if (!cave_los_grid(g_ptr))
155             break;
156     }
157
158     for (d = 1; d <= z; d++) {
159         g_ptr = &floor_ptr->grid_array[y - d][x + d];
160         g_ptr->info |= CAVE_XTRA;
161         cave_view_hack(floor_ptr, g_ptr, y - d, x + d);
162         if (!cave_los_grid(g_ptr))
163             break;
164     }
165
166     for (d = 1; d <= z; d++) {
167         g_ptr = &floor_ptr->grid_array[y - d][x - d];
168         g_ptr->info |= CAVE_XTRA;
169         cave_view_hack(floor_ptr, g_ptr, y - d, x - d);
170         if (!cave_los_grid(g_ptr))
171             break;
172     }
173
174     for (d = 1; d <= full; d++) {
175         g_ptr = &floor_ptr->grid_array[y + d][x];
176         g_ptr->info |= CAVE_XTRA;
177         cave_view_hack(floor_ptr, g_ptr, y + d, x);
178         if (!cave_los_grid(g_ptr))
179             break;
180     }
181
182     se = sw = d;
183     for (d = 1; d <= full; d++) {
184         g_ptr = &floor_ptr->grid_array[y - d][x];
185         g_ptr->info |= CAVE_XTRA;
186         cave_view_hack(floor_ptr, g_ptr, y - d, x);
187         if (!cave_los_grid(g_ptr))
188             break;
189     }
190
191     ne = nw = d;
192     for (d = 1; d <= full; d++) {
193         g_ptr = &floor_ptr->grid_array[y][x + d];
194         g_ptr->info |= CAVE_XTRA;
195         cave_view_hack(floor_ptr, g_ptr, y, x + d);
196         if (!cave_los_grid(g_ptr))
197             break;
198     }
199
200     es = en = d;
201     for (d = 1; d <= full; d++) {
202         g_ptr = &floor_ptr->grid_array[y][x - d];
203         g_ptr->info |= CAVE_XTRA;
204         cave_view_hack(floor_ptr, g_ptr, y, x - d);
205         if (!cave_los_grid(g_ptr))
206             break;
207     }
208
209     ws = wn = d;
210     for (n = 1; n <= over / 2; n++) {
211         POSITION ypn, ymn, xpn, xmn;
212         z = over - n - n;
213         if (z > full - n)
214             z = full - n;
215
216         while ((z + n + (n >> 1)) > full)
217             z--;
218
219         ypn = y + n;
220         ymn = y - n;
221         xpn = x + n;
222         xmn = x - n;
223         if (ypn < y_max) {
224             m = MIN(z, y_max - ypn);
225             if ((xpn <= x_max) && (n < se)) {
226                 for (k = n, d = 1; d <= m; d++) {
227                     if (update_view_aux(subject_ptr, ypn + d, xpn, ypn + d - 1, xpn - 1, ypn + d - 1, xpn)) {
228                         if (n + d >= se)
229                             break;
230                     } else
231                         k = n + d;
232                 }
233
234                 se = k + 1;
235             }
236
237             if ((xmn >= 0) && (n < sw)) {
238                 for (k = n, d = 1; d <= m; d++) {
239                     if (update_view_aux(subject_ptr, ypn + d, xmn, ypn + d - 1, xmn + 1, ypn + d - 1, xmn)) {
240                         if (n + d >= sw)
241                             break;
242                     } else
243                         k = n + d;
244                 }
245
246                 sw = k + 1;
247             }
248         }
249
250         if (ymn > 0) {
251             m = MIN(z, ymn);
252             if ((xpn <= x_max) && (n < ne)) {
253                 for (k = n, d = 1; d <= m; d++) {
254                     if (update_view_aux(subject_ptr, ymn - d, xpn, ymn - d + 1, xpn - 1, ymn - d + 1, xpn)) {
255                         if (n + d >= ne)
256                             break;
257                     } else
258                         k = n + d;
259                 }
260
261                 ne = k + 1;
262             }
263
264             if ((xmn >= 0) && (n < nw)) {
265                 for (k = n, d = 1; d <= m; d++) {
266                     if (update_view_aux(subject_ptr, ymn - d, xmn, ymn - d + 1, xmn + 1, ymn - d + 1, xmn)) {
267                         if (n + d >= nw)
268                             break;
269                     } else
270                         k = n + d;
271                 }
272
273                 nw = k + 1;
274             }
275         }
276
277         if (xpn < x_max) {
278             m = MIN(z, x_max - xpn);
279             if ((ypn <= x_max) && (n < es)) {
280                 for (k = n, d = 1; d <= m; d++) {
281                     if (update_view_aux(subject_ptr, ypn, xpn + d, ypn - 1, xpn + d - 1, ypn, xpn + d - 1)) {
282                         if (n + d >= es)
283                             break;
284                     } else
285                         k = n + d;
286                 }
287
288                 es = k + 1;
289             }
290
291             if ((ymn >= 0) && (n < en)) {
292                 for (k = n, d = 1; d <= m; d++) {
293                     if (update_view_aux(subject_ptr, ymn, xpn + d, ymn + 1, xpn + d - 1, ymn, xpn + d - 1)) {
294                         if (n + d >= en)
295                             break;
296                     } else
297                         k = n + d;
298                 }
299
300                 en = k + 1;
301             }
302         }
303
304         if (xmn > 0) {
305             m = MIN(z, xmn);
306             if ((ypn <= y_max) && (n < ws)) {
307                 for (k = n, d = 1; d <= m; d++) {
308                     if (update_view_aux(subject_ptr, ypn, xmn - d, ypn - 1, xmn - d + 1, ypn, xmn - d + 1)) {
309                         if (n + d >= ws)
310                             break;
311                     } else
312                         k = n + d;
313                 }
314
315                 ws = k + 1;
316             }
317
318             if ((ymn >= 0) && (n < wn)) {
319                 for (k = n, d = 1; d <= m; d++) {
320                     if (update_view_aux(subject_ptr, ymn, xmn - d, ymn + 1, xmn - d + 1, ymn, xmn - d + 1)) {
321                         if (n + d >= wn)
322                             break;
323                     } else
324                         k = n + d;
325                 }
326
327                 wn = k + 1;
328             }
329         }
330     }
331
332     for (n = 0; n < floor_ptr->view_n; n++) {
333         y = floor_ptr->view_y[n];
334         x = floor_ptr->view_x[n];
335         g_ptr = &floor_ptr->grid_array[y][x];
336         g_ptr->info &= ~(CAVE_XTRA);
337         if (g_ptr->info & CAVE_TEMP)
338             continue;
339
340         cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
341     }
342
343     for (const auto &[py, px] : points) {
344         g_ptr = &floor_ptr->grid_array[py][px];
345         g_ptr->info &= ~(CAVE_TEMP);
346         if (g_ptr->info & CAVE_VIEW)
347             continue;
348
349         cave_redraw_later(floor_ptr, g_ptr, py, px);
350     }
351
352     subject_ptr->update |= PU_DELAY_VIS;
353 }