OSDN Git Service

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