5 * @brief プレイヤーから指定の座標がどの方角にあるかを返す /
6 * Convert an adjacent location to a direction.
11 DIRECTION coords_to_dir(POSITION y, POSITION x)
13 DIRECTION d[3][3] = { {7, 4, 1}, {8, 5, 2}, {9, 6, 3} };
18 if (ABS(dx) > 1 || ABS(dy) > 1) return (0);
20 return d[dx + 1][dy + 1];
24 * @brief 始点から終点への直線経路を返す /
25 * Determine the path taken by a projection.
26 * @param gp 経路座標リストを返す参照ポインタ
36 * The projection will always start from the grid (y1,x1), and will travel
37 * towards the grid (y2,x2), touching one grid per unit of distance along
38 * the major axis, and stopping when it enters the destination grid or a
39 * wall grid, or has travelled the maximum legal distance of "range".
41 * Note that "distance" in this function (as in the "update_view()" code)
42 * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
43 * actually has an "octagon of projection" not a "circle of projection".
45 * The path grids are saved into the grid array pointed to by "gp", and
46 * there should be room for at least "range" grids in "gp". Note that
47 * due to the way in which distance is calculated, this function normally
48 * uses fewer than "range" grids for the projection path, so the result
49 * of this function should never be compared directly to "range". Note
50 * that the initial grid (y1,x1) is never saved into the grid array, not
51 * even if the initial grid is also the final grid.
53 * The "flg" flags can be used to modify the behavior of this function.
55 * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
56 * semantics as they do for the "project" function, namely, that the path
57 * will stop as soon as it hits a monster, or that the path will continue
58 * through the destination grid, respectively.
60 * The "PROJECT_JUMP" flag, which for the "project()" function means to
61 * start at a special grid (which makes no sense in this function), means
62 * that the path should be "angled" slightly if needed to avoid any wall
63 * grids, allowing the player to "target" any grid which is in "view".
64 * This flag is non-trivial and has not yet been implemented, but could
65 * perhaps make use of the "vinfo" array (above).
67 * This function returns the number of grids (if any) in the path. This
68 * function will return zero if and only if (y1,x1) and (y2,x2) are equal.
70 * This algorithm is similar to, but slightly different from, the one used
71 * by "update_view_los()", and very different from the one used by "los()".
74 sint project_path(u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flg)
96 /* No path necessary (or allowed) */
97 if ((x1 == x2) && (y1 == y2)) return (0);
125 /* Number of "units" in one "half" grid */
128 /* Number of "units" in one "full" grid */
134 /* Let m = ((dx/dy) * full) = (dx * dx * 2) */
145 /* Advance (X) part 2 */
148 /* Advance (X) part 3 */
155 /* Create the projection path */
159 gp[n++] = GRID(y, x);
161 /* Hack -- Check maximum range */
162 if ((n + (k >> 1)) >= range) break;
164 /* Sometimes stop at destination grid */
165 if (!(flg & (PROJECT_THRU)))
167 if ((x == x2) && (y == y2)) break;
170 if (flg & (PROJECT_DISI))
172 if ((n > 0) && cave_stop_disintegration(y, x)) break;
174 else if (flg & (PROJECT_LOS))
176 if ((n > 0) && !cave_los_bold(y, x)) break;
178 else if (!(flg & (PROJECT_PATH)))
180 /* Always stop at non-initial wall grids */
181 if ((n > 0) && !cave_have_flag_bold(y, x, FF_PROJECT)) break;
184 /* Sometimes stop at non-initial monsters/players */
185 if (flg & (PROJECT_STOP))
188 (player_bold(y, x) || current_floor_ptr->grid_array[y][x].m_idx != 0))
192 if (!in_bounds(y, x)) break;
197 /* Advance (X) part 1 */
200 /* Horizontal change */
203 /* Advance (X) part 2 */
206 /* Advance (X) part 3 */
222 /* Let m = ((dy/dx) * full) = (dy * dy * 2) */
231 /* Vertical change */
234 /* Advance (Y) part 2 */
237 /* Advance (Y) part 3 */
244 /* Create the projection path */
248 gp[n++] = GRID(y, x);
250 /* Hack -- Check maximum range */
251 if ((n + (k >> 1)) >= range) break;
253 /* Sometimes stop at destination grid */
254 if (!(flg & (PROJECT_THRU)))
256 if ((x == x2) && (y == y2)) break;
259 if (flg & (PROJECT_DISI))
261 if ((n > 0) && cave_stop_disintegration(y, x)) break;
263 else if (flg & (PROJECT_LOS))
265 if ((n > 0) && !cave_los_bold(y, x)) break;
267 else if (!(flg & (PROJECT_PATH)))
269 /* Always stop at non-initial wall grids */
270 if ((n > 0) && !cave_have_flag_bold(y, x, FF_PROJECT)) break;
273 /* Sometimes stop at non-initial monsters/players */
274 if (flg & (PROJECT_STOP))
277 (player_bold(y, x) || current_floor_ptr->grid_array[y][x].m_idx != 0))
281 if (!in_bounds(y, x)) break;
286 /* Advance (Y) part 1 */
289 /* Vertical change */
292 /* Advance (Y) part 2 */
295 /* Advance (Y) part 3 */
315 /* Create the projection path */
319 gp[n++] = GRID(y, x);
321 /* Hack -- Check maximum range */
322 if ((n + (n >> 1)) >= range) break;
324 /* Sometimes stop at destination grid */
325 if (!(flg & (PROJECT_THRU)))
327 if ((x == x2) && (y == y2)) break;
330 if (flg & (PROJECT_DISI))
332 if ((n > 0) && cave_stop_disintegration(y, x)) break;
334 else if (flg & (PROJECT_LOS))
336 if ((n > 0) && !cave_los_bold(y, x)) break;
338 else if (!(flg & (PROJECT_PATH)))
340 /* Always stop at non-initial wall grids */
341 if ((n > 0) && !cave_have_flag_bold(y, x, FF_PROJECT)) break;
344 /* Sometimes stop at non-initial monsters/players */
345 if (flg & (PROJECT_STOP))
348 (player_bold(y, x) || current_floor_ptr->grid_array[y][x].m_idx != 0))
352 if (!in_bounds(y, x)) break;
367 * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
368 * at the final destination, assuming no monster gets in the way.
370 * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
372 bool projectable(POSITION y1, POSITION x1, POSITION y2, POSITION x2)
379 /* Check the projection path */
380 grid_n = project_path(grid_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, 0);
383 if (!grid_n) return TRUE;
386 y = GRID_Y(grid_g[grid_n - 1]);
387 x = GRID_X(grid_g[grid_n - 1]);
389 /* May not end in an unrequested grid */
390 if ((y != y2) || (x != x2)) return (FALSE);