OSDN Git Service

[Refactor] #40577 Separated set_asxy() from projection_path()
[hengbandforosx/hengbandosx.git] / src / target / projection-path-calculator.c
1 #include "target/projection-path-calculator.h"
2 #include "effect/effect-characteristics.h"
3 #include "floor/cave.h"
4 #include "grid/feature-flag-types.h"
5 #include "grid/grid.h"
6 #include "system/floor-type-definition.h"
7
8 typedef struct projection_path_type {
9     POSITION y1;
10     POSITION x1;
11     POSITION y2;
12     POSITION x2;
13     POSITION y;
14     POSITION x;
15     POSITION ay;
16     POSITION ax;
17     POSITION sy;
18     POSITION sx;
19     int frac;
20     int m;
21     int half;
22     int full;
23     int n;
24     int k;
25 } projection_path_type;
26
27 /*
28  * @brief Convert a "location" (Y, X) into a "grid" (G)
29  * @param y Y\8dÀ\95W
30  * @param x X\8dÀ\95W
31  * return \8co\98H\8dÀ\95W
32  */
33 static u16b location_to_grid(POSITION y, POSITION x) { return 256 * y + x; }
34
35 static projection_path_type *initialize_projection_path_type(projection_path_type *pp_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
36 {
37     pp_ptr->y1 = y1;
38     pp_ptr->x1 = x1;
39     pp_ptr->y2 = y2;
40     pp_ptr->x2 = x2;
41     return pp_ptr;
42 }
43
44 static void set_asxy(projection_path_type *pp_ptr)
45 {
46     if (pp_ptr->y2 < pp_ptr->y1) {
47         pp_ptr->ay = pp_ptr->y1 - pp_ptr->y2;
48         pp_ptr->sy = -1;
49     } else {
50         pp_ptr->ay = pp_ptr->y2 - pp_ptr->y1;
51         pp_ptr->sy = 1;
52     }
53
54     if (pp_ptr->x2 < pp_ptr->x1) {
55         pp_ptr->ax = pp_ptr->x1 - pp_ptr->x2;
56         pp_ptr->sx = -1;
57     } else {
58         pp_ptr->ax = pp_ptr->x2 - pp_ptr->x1;
59         pp_ptr->sx = 1;
60     }
61 }
62
63 /*!
64  * @brief \8en\93_\82©\82ç\8fI\93_\82Ö\82Ì\92¼\90ü\8co\98H\82ð\95Ô\82· /
65  * Determine the path taken by a projection.
66  * @param player_ptr \83v\83\8c\81[\83\84\81[\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
67  * @param gp \8co\98H\8dÀ\95W\83\8a\83X\83g\82ð\95Ô\82·\8eQ\8fÆ\83|\83C\83\93\83^
68  * @param range \8b\97\97£
69  * @param y1 \8en\93_Y\8dÀ\95W
70  * @param x1 \8en\93_X\8dÀ\95W
71  * @param y2 \8fI\93_Y\8dÀ\95W
72  * @param x2 \8fI\93_X\8dÀ\95W
73  * @param flg \83t\83\89\83OID
74  * @return \83\8a\83X\83g\82Ì\92·\82³
75  */
76 int projection_path(player_type *player_ptr, u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flg)
77 {
78     if ((x1 == x2) && (y1 == y2))
79         return 0;
80
81     projection_path_type tmp_projection_path;
82     projection_path_type *pp_ptr = initialize_projection_path_type(&tmp_projection_path, y1, x1, y2, x2);
83     set_asxy(pp_ptr);
84     pp_ptr->half = pp_ptr->ay * pp_ptr->ax;
85     pp_ptr->full = pp_ptr->half << 1;
86     pp_ptr->n = 0;
87     pp_ptr->k = 0;
88
89     /* Vertical */
90     if (pp_ptr->ay > pp_ptr->ax) {
91         pp_ptr->m = pp_ptr->ax * pp_ptr->ax * 2;
92         pp_ptr->y = y1 + pp_ptr->sy;
93         pp_ptr->x = x1;
94         pp_ptr->frac = pp_ptr->m;
95         if (pp_ptr->frac > pp_ptr->half) {
96             pp_ptr->x += pp_ptr->sx;
97             pp_ptr->frac -= pp_ptr->full;
98             pp_ptr->k++;
99         }
100
101         floor_type *floor_ptr = player_ptr->current_floor_ptr;
102         while (TRUE) {
103             gp[pp_ptr->n++] = location_to_grid(pp_ptr->y, pp_ptr->x);
104             if ((pp_ptr->n + (pp_ptr->k >> 1)) >= range)
105                 break;
106
107             if (!(flg & PROJECT_THRU)) {
108                 if ((pp_ptr->x == x2) && (pp_ptr->y == y2))
109                     break;
110             }
111
112             if (flg & PROJECT_DISI) {
113                 if ((pp_ptr->n > 0) && cave_stop_disintegration(floor_ptr, pp_ptr->y, pp_ptr->x))
114                     break;
115             } else if (flg & PROJECT_LOS) {
116                 if ((pp_ptr->n > 0) && !cave_los_bold(floor_ptr, pp_ptr->y, pp_ptr->x))
117                     break;
118             } else if (!(flg & PROJECT_PATH)) {
119                 if ((pp_ptr->n > 0) && !cave_have_flag_bold(floor_ptr, pp_ptr->y, pp_ptr->x, FF_PROJECT))
120                     break;
121             }
122
123             if (flg & PROJECT_STOP) {
124                 if ((pp_ptr->n > 0) && (player_bold(player_ptr, pp_ptr->y, pp_ptr->x) || floor_ptr->grid_array[pp_ptr->y][pp_ptr->x].m_idx != 0))
125                     break;
126             }
127
128             if (!in_bounds(floor_ptr, pp_ptr->y, pp_ptr->x))
129                 break;
130
131             if (pp_ptr->m) {
132                 pp_ptr->frac += pp_ptr->m;
133                 if (pp_ptr->frac > pp_ptr->half) {
134                     pp_ptr->x += pp_ptr->sx;
135                     pp_ptr->frac -= pp_ptr->full;
136                     pp_ptr->k++;
137                 }
138             }
139
140             pp_ptr->y += pp_ptr->sy;
141         }
142
143         return pp_ptr->n;
144     }
145
146     /* Horizontal */
147     if (pp_ptr->ax > pp_ptr->ay) {
148         pp_ptr->m = pp_ptr->ay * pp_ptr->ay * 2;
149         pp_ptr->y = y1;
150         pp_ptr->x = x1 + pp_ptr->sx;
151         pp_ptr->frac = pp_ptr->m;
152         if (pp_ptr->frac > pp_ptr->half) {
153             pp_ptr->y += pp_ptr->sy;
154             pp_ptr->frac -= pp_ptr->full;
155             pp_ptr->k++;
156         }
157
158         floor_type *floor_ptr = player_ptr->current_floor_ptr;
159         while (TRUE) {
160             gp[pp_ptr->n++] = location_to_grid(pp_ptr->y, pp_ptr->x);
161             if ((pp_ptr->n + (pp_ptr->k >> 1)) >= range)
162                 break;
163
164             if (!(flg & (PROJECT_THRU))) {
165                 if ((pp_ptr->x == x2) && (pp_ptr->y == y2))
166                     break;
167             }
168
169             if (flg & (PROJECT_DISI)) {
170                 if ((pp_ptr->n > 0) && cave_stop_disintegration(floor_ptr, pp_ptr->y, pp_ptr->x))
171                     break;
172             } else if (flg & (PROJECT_LOS)) {
173                 if ((pp_ptr->n > 0) && !cave_los_bold(floor_ptr, pp_ptr->y, pp_ptr->x))
174                     break;
175             } else if (!(flg & (PROJECT_PATH))) {
176                 if ((pp_ptr->n > 0) && !cave_have_flag_bold(floor_ptr, pp_ptr->y, pp_ptr->x, FF_PROJECT))
177                     break;
178             }
179
180             if (flg & (PROJECT_STOP)) {
181                 if ((pp_ptr->n > 0) && (player_bold(player_ptr, pp_ptr->y, pp_ptr->x) || floor_ptr->grid_array[pp_ptr->y][pp_ptr->x].m_idx != 0))
182                     break;
183             }
184
185             if (!in_bounds(floor_ptr, pp_ptr->y, pp_ptr->x))
186                 break;
187
188             if (pp_ptr->m) {
189                 pp_ptr->frac += pp_ptr->m;
190                 if (pp_ptr->frac > pp_ptr->half) {
191                     pp_ptr->y += pp_ptr->sy;
192                     pp_ptr->frac -= pp_ptr->full;
193                     pp_ptr->k++;
194                 }
195             }
196
197             pp_ptr->x += pp_ptr->sx;
198         }
199
200         return pp_ptr->n;
201     }
202
203     pp_ptr->y = y1 + pp_ptr->sy;
204     pp_ptr->x = x1 + pp_ptr->sx;
205
206     floor_type *floor_ptr = player_ptr->current_floor_ptr;
207     while (TRUE) {
208         gp[pp_ptr->n++] = location_to_grid(pp_ptr->y, pp_ptr->x);
209         if ((pp_ptr->n + (pp_ptr->n >> 1)) >= range)
210             break;
211
212         if (!(flg & PROJECT_THRU)) {
213             if ((pp_ptr->x == x2) && (pp_ptr->y == y2))
214                 break;
215         }
216
217         if (flg & PROJECT_DISI) {
218             if ((pp_ptr->n > 0) && cave_stop_disintegration(floor_ptr, pp_ptr->y, pp_ptr->x))
219                 break;
220         } else if (flg & PROJECT_LOS) {
221             if ((pp_ptr->n > 0) && !cave_los_bold(floor_ptr, pp_ptr->y, pp_ptr->x))
222                 break;
223         } else if (!(flg & PROJECT_PATH)) {
224             if ((pp_ptr->n > 0) && !cave_have_flag_bold(floor_ptr, pp_ptr->y, pp_ptr->x, FF_PROJECT))
225                 break;
226         }
227
228         if (flg & PROJECT_STOP) {
229             if ((pp_ptr->n > 0) && (player_bold(player_ptr, pp_ptr->y, pp_ptr->x) || floor_ptr->grid_array[pp_ptr->y][pp_ptr->x].m_idx != 0))
230                 break;
231         }
232
233         if (!in_bounds(floor_ptr, pp_ptr->y, pp_ptr->x))
234             break;
235
236         pp_ptr->y += pp_ptr->sy;
237         pp_ptr->x += pp_ptr->sx;
238     }
239
240     return pp_ptr->n;
241 }