fr.arakne.utils.maps.sight.BattlefieldSight   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 17
c 1
b 0
f 0
dl 0
loc 109
ccs 9
cts 9
cp 1
rs 10
wmc 6

6 Methods

Rating   Name   Duplication   Size   Complexity  
A from(C) 0 2 1
A BattlefieldSight(DofusMap) 0 3 1
A between(CoordinateCell,CoordinateCell) 0 2 1
A from(CoordinateCell) 0 2 1
A between(C,C) 0 2 1
A getCellByCoordinates(int,int) 0 4 1
1
/*
2
 * This file is part of ArakneUtils.
3
 *
4
 * ArakneUtils is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * ArakneUtils is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with ArakneUtils.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2020 Vincent Quatrevieux
18
 */
19
20
package fr.arakne.utils.maps.sight;
21
22
import fr.arakne.utils.maps.BattlefieldCell;
23
import fr.arakne.utils.maps.CoordinateCell;
24
import fr.arakne.utils.maps.DofusMap;
25
import org.checkerframework.checker.index.qual.Positive;
26
import org.checkerframework.checker.nullness.qual.NonNull;
27
28
/**
29
 * Utility class for compute line of sights
30
 * Note: The used algorithm is not exactly same as the client's one, some differences can occurs
31
 *
32
 * Algorithm :
33
 * - Get coordinates of the two cells
34
 * - "draw" a line between the cells :
35
 * - Compute the vector between those cells
36
 * - Creates the function : Y = ySlope * X + yAtZero with
37
 * - For each X between the cells compute the related Y using the function
38
 * - Increments Y cell by cell to reach the computed Y
39
 * - Check the cell line of sight value
40
 * - If the sight is blocked, return false
41
 *
42
 * @param <C> The battlefield cell type
43
 */
44
public final class BattlefieldSight<C extends @NonNull BattlefieldCell> {
45
    private final DofusMap<C> battlefield;
46
    private final @Positive int width; // store map width for optimisation
47
48 1
    public BattlefieldSight(DofusMap<C> battlefield) {
49 1
        this.battlefield = battlefield;
50 1
        this.width = battlefield.dimensions().width();
51 1
    }
52
53
    /**
54
     * Check the line of sight between those two cells
55
     *
56
     * This is equivalent to {@code sight.from(source).isFree(target)}
57
     *
58
     * Usage:
59
     * <pre>{@code
60
     * final BattlefieldSight<FightCell> sight = new BattlefieldSight<>(map);
61
     *
62
     * if (!sight.between(fighter.cell(), target.cell())) {
63
     *     throw new Exception("Target is no reachable");
64
     * }
65
     * }</pre>
66
     *
67
     * @param source The source cell
68
     * @param target The target cell
69
     *
70
     * @return true if target is not blocked
71
     *
72
     * @see CellSight#isFree(BattlefieldCell)
73
     */
74
    public boolean between(C source, C target) {
75 1
        return between(source.coordinate(), target.coordinate());
76
    }
77
78
    /**
79
     * Check the line of sight between those two cells
80
     *
81
     * This is equivalent to {@code sight.from(source).isFree(target)}
82
     *
83
     * Usage:
84
     * <pre>{@code
85
     * final BattlefieldSight<FightCell> sight = new BattlefieldSight<>(map);
86
     * final CoordinateCell<FightCell> from = new CoordinateCell<>(fighter.cell());
87
     * final CoordinateCell<FightCell> to = new CoordinateCell<>(target.cell());
88
     *
89
     * if (!sight.between(from, to)) {
90
     *     throw new Exception("Target is no reachable");
91
     * }
92
     * }</pre>
93
     *
94
     * @param source The source cell
95
     * @param target The target cell
96
     *
97
     * @return true if target is not blocked
98
     *
99
     * @see CellSight#isFree(CoordinateCell)
100
     */
101
    public boolean between(CoordinateCell<C> source, CoordinateCell<C> target) {
102 1
        return from(source).isFree(target);
103
    }
104
105
    /**
106
     * Get the line of sight of a cell
107
     *
108
     * Usage:
109
     * <pre>{@code
110
     * final BattlefieldSight<FightCell> sight = new BattlefieldSight<>(map);
111
     * final CoordinateCell<FightCell> current = new CoordinateCell<>(fighter.cell());
112
     *
113
     * sight.from(current).to(target.cell()).forEachRemaining(cell -> {
114
     *     // Iterator on line of sight
115
     * });
116
     * }</pre>
117
     *
118
     * @param cell The cell to check
119
     *
120
     * @return The line of sight instance
121
     */
122
    public CellSight<C> from(CoordinateCell<C> cell) {
123 1
        return new CellSight<>(this, cell);
124
    }
125
126
    /**
127
     * Get the line of sight of a cell
128
     *
129
     * Usage:
130
     * <pre>{@code
131
     * final BattlefieldSight<FightCell> sight = new BattlefieldSight<>(map);
132
     *
133
     * sight.from(fighter.cell()).to(target.cell()).forEachRemaining(cell -> {
134
     *     // Iterator on line of sight
135
     * });
136
     * }</pre>
137
     *
138
     * @param cell The cell to check
139
     *
140
     * @return The line of sight instance
141
     */
142
    public CellSight<C> from(C cell) {
143 1
        return new CellSight<>(this, cell.coordinate());
144
    }
145
146
    /**
147
     * Get a cell by its coordinates
148
     */
149
    @SuppressWarnings("argument") // Consider x and y as safe
150
    C getCellByCoordinates(int x, int y) {
151
        // https://github.com/Emudofus/Dofus/blob/1.29/ank/battlefield/utils/Pathfinding.as#L550
152 1
        return battlefield.get(x * width + y * (width - 1));
153
    }
154
}
155