OSDN Git Service

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