2 #include "projection.h"
5 * @brief 始点から終点への経路を返す /
6 * Determine the path taken by a projection.
7 * @param gp 経路座標リストを返す参照ポインタ
17 * The projection will always start from the grid (y1,x1), and will travel
18 * towards the grid (y2,x2), touching one grid per unit of distance along
19 * the major axis, and stopping when it enters the destination grid or a
20 * wall grid, or has travelled the maximum legal distance of "range".
22 * Note that "distance" in this function (as in the "update_view()" code)
23 * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
24 * actually has an "octagon of projection" not a "circle of projection".
26 * The path grids are saved into the grid array pointed to by "gp", and
27 * there should be room for at least "range" grids in "gp". Note that
28 * due to the way in which distance is calculated, this function normally
29 * uses fewer than "range" grids for the projection path, so the result
30 * of this function should never be compared directly to "range". Note
31 * that the initial grid (y1,x1) is never saved into the grid array, not
32 * even if the initial grid is also the final grid.
34 * The "flg" flags can be used to modify the behavior of this function.
36 * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
37 * semantics as they do for the "project" function, namely, that the path
38 * will stop as soon as it hits a monster, or that the path will continue
39 * through the destination grid, respectively.
41 * The "PROJECT_JUMP" flag, which for the "project()" function means to
42 * start at a special grid (which makes no sense in this function), means
43 * that the path should be "angled" slightly if needed to avoid any wall
44 * grids, allowing the player to "target" any grid which is in "view".
45 * This flag is non-trivial and has not yet been implemented, but could
46 * perhaps make use of the "vinfo" array (above).
48 * This function returns the number of grids (if any) in the path. This
49 * function will return zero if and only if (y1,x1) and (y2,x2) are equal.
51 * This algorithm is similar to, but slightly different from, the one used
52 * by "update_view_los()", and very different from the one used by "los()".
55 sint project_path(u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flg)
77 /* No path necessary (or allowed) */
78 if ((x1 == x2) && (y1 == y2)) return (0);
106 /* Number of "units" in one "half" grid */
109 /* Number of "units" in one "full" grid */
115 /* Let m = ((dx/dy) * full) = (dx * dx * 2) */
126 /* Advance (X) part 2 */
129 /* Advance (X) part 3 */
136 /* Create the projection path */
140 gp[n++] = GRID(y, x);
142 /* Hack -- Check maximum range */
143 if ((n + (k >> 1)) >= range) break;
145 /* Sometimes stop at destination grid */
146 if (!(flg & (PROJECT_THRU)))
148 if ((x == x2) && (y == y2)) break;
151 if (flg & (PROJECT_DISI))
153 if ((n > 0) && cave_stop_disintegration(y, x)) break;
155 else if (flg & (PROJECT_LOS))
157 if ((n > 0) && !cave_los_bold(y, x)) break;
159 else if (!(flg & (PROJECT_PATH)))
161 /* Always stop at non-initial wall grids */
162 if ((n > 0) && !cave_have_flag_bold(y, x, FF_PROJECT)) break;
165 /* Sometimes stop at non-initial monsters/players */
166 if (flg & (PROJECT_STOP))
169 (player_bold(y, x) || current_floor_ptr->grid_array[y][x].m_idx != 0))
173 if (!in_bounds(y, x)) break;
178 /* Advance (X) part 1 */
181 /* Horizontal change */
184 /* Advance (X) part 2 */
187 /* Advance (X) part 3 */
203 /* Let m = ((dy/dx) * full) = (dy * dy * 2) */
212 /* Vertical change */
215 /* Advance (Y) part 2 */
218 /* Advance (Y) part 3 */
225 /* Create the projection path */
229 gp[n++] = GRID(y, x);
231 /* Hack -- Check maximum range */
232 if ((n + (k >> 1)) >= range) break;
234 /* Sometimes stop at destination grid */
235 if (!(flg & (PROJECT_THRU)))
237 if ((x == x2) && (y == y2)) break;
240 if (flg & (PROJECT_DISI))
242 if ((n > 0) && cave_stop_disintegration(y, x)) break;
244 else if (flg & (PROJECT_LOS))
246 if ((n > 0) && !cave_los_bold(y, x)) break;
248 else if (!(flg & (PROJECT_PATH)))
250 /* Always stop at non-initial wall grids */
251 if ((n > 0) && !cave_have_flag_bold(y, x, FF_PROJECT)) break;
254 /* Sometimes stop at non-initial monsters/players */
255 if (flg & (PROJECT_STOP))
258 (player_bold(y, x) || current_floor_ptr->grid_array[y][x].m_idx != 0))
262 if (!in_bounds(y, x)) break;
267 /* Advance (Y) part 1 */
270 /* Vertical change */
273 /* Advance (Y) part 2 */
276 /* Advance (Y) part 3 */
296 /* Create the projection path */
300 gp[n++] = GRID(y, x);
302 /* Hack -- Check maximum range */
303 if ((n + (n >> 1)) >= range) break;
305 /* Sometimes stop at destination grid */
306 if (!(flg & (PROJECT_THRU)))
308 if ((x == x2) && (y == y2)) break;
311 if (flg & (PROJECT_DISI))
313 if ((n > 0) && cave_stop_disintegration(y, x)) break;
315 else if (flg & (PROJECT_LOS))
317 if ((n > 0) && !cave_los_bold(y, x)) break;
319 else if (!(flg & (PROJECT_PATH)))
321 /* Always stop at non-initial wall grids */
322 if ((n > 0) && !cave_have_flag_bold(y, x, FF_PROJECT)) break;
325 /* Sometimes stop at non-initial monsters/players */
326 if (flg & (PROJECT_STOP))
329 (player_bold(y, x) || current_floor_ptr->grid_array[y][x].m_idx != 0))
333 if (!in_bounds(y, x)) break;