1 #include "floor/line-of-sight.h"
2 #include "floor/cave.h"
3 #include "system/floor-type-definition.h"
4 #include "system/player-type-definition.h"
7 * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
8 * @param player_ptr プレイヤーへの参照ポインタ
13 * @return LOSが通っているならTRUEを返す。
15 * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall,\n
16 * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu.\n
18 * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
20 * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
21 * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line\n
22 * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
24 * We assume that the "mathematical corner" of a non-floor tile does not\n
25 * block line of sight.\n
27 * Because this function uses (short) ints for all calculations, overflow may\n
28 * occur if dx and dy exceed 90.\n
30 * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
31 * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
32 * we can use integer arithmetic.\n
34 * We travel from start to finish along the longer axis, starting at the border\n
35 * between the first and second tiles, where the y offset = .5 * slope, taking\n
36 * into account the scale factor. See below.\n
38 * Also note that this function and the "move towards target" code do NOT\n
39 * share the same properties. Thus, you can see someone, target them, and\n
40 * then fire a bolt at them, but the bolt may hit a wall, not them. However\n,
41 * by clever choice of target locations, you can sometimes throw a "curve".\n
43 * Note that "line of sight" is not "reflexive" in all cases.\n
45 * Use the "projectable()" routine to test "spell/missile line of sight".\n
47 * Use the "update_view()" function to determine player line-of-sight.\n
49 bool los(PlayerType *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
51 POSITION dy = y2 - y1;
52 POSITION dx = x2 - x1;
53 POSITION ay = std::abs(dy);
54 POSITION ax = std::abs(dx);
55 if ((ax < 2) && (ay < 2)) {
59 /* Directly South/North */
60 auto *floor_ptr = player_ptr->current_floor_ptr;
63 /* South -- check for walls */
65 for (ty = y1 + 1; ty < y2; ty++) {
66 if (!cave_los_bold(floor_ptr, ty, x1)) {
72 /* North -- check for walls */
74 for (ty = y1 - 1; ty > y2; ty--) {
75 if (!cave_los_bold(floor_ptr, ty, x1)) {
85 /* Directly East/West */
87 /* East -- check for walls */
89 for (tx = x1 + 1; tx < x2; tx++) {
90 if (!cave_los_bold(floor_ptr, y1, tx)) {
96 /* West -- check for walls */
98 for (tx = x1 - 1; tx > x2; tx--) {
99 if (!cave_los_bold(floor_ptr, y1, tx)) {
108 POSITION sx = (dx < 0) ? -1 : 1;
109 POSITION sy = (dy < 0) ? -1 : 1;
113 if (cave_los_bold(floor_ptr, y1 + sy, x1)) {
117 } else if (ay == 1) {
119 if (cave_los_bold(floor_ptr, y1, x1 + sx)) {
125 POSITION f2 = (ax * ay);
126 POSITION f1 = f2 << 1;
140 /* Note (below) the case (qy == f2), where */
141 /* the LOS exactly meets the corner of a tile. */
143 if (!cave_los_bold(floor_ptr, ty, tx)) {
156 if (!cave_los_bold(floor_ptr, ty, tx)) {
172 /* Travel vertically */
173 POSITION qx = ax * ax;
183 /* Note (below) the case (qx == f2), where */
184 /* the LOS exactly meets the corner of a tile. */
186 if (!cave_los_bold(floor_ptr, ty, tx)) {
199 if (!cave_los_bold(floor_ptr, ty, tx)) {