diff options
author | Adam NAILI | 2018-02-03 23:20:03 +0100 |
---|---|---|
committer | Adam NAILI | 2018-02-03 23:20:03 +0100 |
commit | 78bfc15d36b94058b1f896ec7c8d753e2e487a1d (patch) | |
tree | f2c66df5838b11fad91a834b8b3c0cdc67d3369b | |
parent | c4fa546ef067317bd5e22cdad40792cbd33035d7 (diff) | |
parent | 745b3c798de97785dd92e1a3db83cfdb2801ee87 (diff) | |
download | wallj-78bfc15d36b94058b1f896ec7c8d753e2e487a1d.tar.gz |
Merge branch 'master' of https://github.com/pacien/upem-java-wallj
6 files changed, 66 insertions, 20 deletions
diff --git a/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java b/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java index da7f3cf..f81f423 100644 --- a/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java +++ b/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java | |||
@@ -27,6 +27,7 @@ public class RobotBlock extends Block { | |||
27 | private Vec2 pos; | 27 | private Vec2 pos; |
28 | private PathFinder pathFinder; | 28 | private PathFinder pathFinder; |
29 | private Deque<TileVec2> path = new LinkedList<>(); | 29 | private Deque<TileVec2> path = new LinkedList<>(); |
30 | private int droppedBombCount = 0; | ||
30 | 31 | ||
31 | RobotBlock(Vec2 pos) { | 32 | RobotBlock(Vec2 pos) { |
32 | super(BlockType.ROBOT); | 33 | super(BlockType.ROBOT); |
@@ -62,10 +63,17 @@ public class RobotBlock extends Block { | |||
62 | return Events.findFirst(events, BombSetupOrder.class) | 63 | return Events.findFirst(events, BombSetupOrder.class) |
63 | .map(event -> isOnBomb(stage) ? | 64 | .map(event -> isOnBomb(stage) ? |
64 | Collections.<Event>singletonList(new BombTimerIncrEvent(getTile())) : | 65 | Collections.<Event>singletonList(new BombTimerIncrEvent(getTile())) : |
65 | Collections.<Event>singletonList(new BlockCreateEvent(BlockType.BOMB, getTile()))) | 66 | dropBomb(event)) |
66 | .orElse(Collections.emptyList()); | 67 | .orElse(Collections.emptyList()); |
67 | } | 68 | } |
68 | 69 | ||
70 | private List<Event> dropBomb(BombSetupOrder order) { | ||
71 | if (droppedBombCount >= Stage.BOMB_PLACEMENTS) return Collections.emptyList(); | ||
72 | |||
73 | droppedBombCount++; | ||
74 | return Collections.singletonList(new BlockCreateEvent(BlockType.BOMB, getTile())); | ||
75 | } | ||
76 | |||
69 | private void updatePath(Board board, TileVec2 target) { | 77 | private void updatePath(Board board, TileVec2 target) { |
70 | if (!board.inside(target) || !board.getBlockTypeAt(target).isTraversable()) return; | 78 | if (!board.inside(target) || !board.getBlockTypeAt(target).isTraversable()) return; |
71 | if (pathFinder == null) pathFinder = new PathFinder(board); | 79 | if (pathFinder == null) pathFinder = new PathFinder(board); |
@@ -85,6 +93,9 @@ public class RobotBlock extends Block { | |||
85 | graphicsContext.paintCircle(Color.BLUE, getPos(), TileVec2.TILE_DIM / 2); | 93 | graphicsContext.paintCircle(Color.BLUE, getPos(), TileVec2.TILE_DIM / 2); |
86 | } | 94 | } |
87 | 95 | ||
96 | /** | ||
97 | * @implNote TODO: profile this and consider a mapping (pos: block) for faster lookup in Stage | ||
98 | */ | ||
88 | private boolean isOnBomb(Stage stage) { | 99 | private boolean isOnBomb(Stage stage) { |
89 | return stage.getBlocks().stream() | 100 | return stage.getBlocks().stream() |
90 | .anyMatch(block -> Objects.equals(block.getType(), BlockType.BOMB) && | 101 | .anyMatch(block -> Objects.equals(block.getType(), BlockType.BOMB) && |
diff --git a/src/main/java/fr/umlv/java/wallj/board/PathFinder.java b/src/main/java/fr/umlv/java/wallj/board/PathFinder.java index c530d83..dfd1fa6 100644 --- a/src/main/java/fr/umlv/java/wallj/board/PathFinder.java +++ b/src/main/java/fr/umlv/java/wallj/board/PathFinder.java | |||
@@ -57,7 +57,7 @@ public class PathFinder { | |||
57 | 57 | ||
58 | private static <T> List<T> findPath(Node<T> start, T target, BiFunction<T, T, Double> heuristic) { | 58 | private static <T> List<T> findPath(Node<T> start, T target, BiFunction<T, T, Double> heuristic) { |
59 | Map<Node<T>, NodeSearchData<T>> searchData = new HashMap<>(); | 59 | Map<Node<T>, NodeSearchData<T>> searchData = new HashMap<>(); |
60 | TreeSet<Node<T>> discovered = new TreeSet<>(Comparator.comparingDouble(n -> searchData.get(n).estimatedCost)); | 60 | Queue<Node<T>> discovered = new PriorityQueue<>(Comparator.comparingDouble(n -> searchData.get(n).estimatedCost)); |
61 | Set<Node<T>> visited = new HashSet<>(); | 61 | Set<Node<T>> visited = new HashSet<>(); |
62 | 62 | ||
63 | searchData.put(start, new NodeSearchData<>(null, 0, heuristic.apply(start.val, target))); | 63 | searchData.put(start, new NodeSearchData<>(null, 0, heuristic.apply(start.val, target))); |
@@ -65,7 +65,7 @@ public class PathFinder { | |||
65 | 65 | ||
66 | Node<T> current; | 66 | Node<T> current; |
67 | while (!discovered.isEmpty()) { | 67 | while (!discovered.isEmpty()) { |
68 | current = discovered.pollFirst(); | 68 | current = discovered.poll(); |
69 | if (target.equals(current.val)) return buildPath(searchData, current); | 69 | if (target.equals(current.val)) return buildPath(searchData, current); |
70 | 70 | ||
71 | for (Map.Entry<Node<T>, Integer> neighborEntry : current.neighbors.entrySet()) { | 71 | for (Map.Entry<Node<T>, Integer> neighborEntry : current.neighbors.entrySet()) { |
diff --git a/src/main/java/fr/umlv/java/wallj/context/Stage.java b/src/main/java/fr/umlv/java/wallj/context/Stage.java index 49aa196..9737583 100644 --- a/src/main/java/fr/umlv/java/wallj/context/Stage.java +++ b/src/main/java/fr/umlv/java/wallj/context/Stage.java | |||
@@ -17,6 +17,7 @@ import java.util.*; | |||
17 | * @author Pacien TRAN-GIRARD | 17 | * @author Pacien TRAN-GIRARD |
18 | */ | 18 | */ |
19 | public class Stage implements Updateable { | 19 | public class Stage implements Updateable { |
20 | public static final int BOMB_PLACEMENTS = 3; | ||
20 | private static final int VELOCITY_TICK_PER_MS = 6; | 21 | private static final int VELOCITY_TICK_PER_MS = 6; |
21 | private static final int POSITION_TICK_PER_MS = 2; | 22 | private static final int POSITION_TICK_PER_MS = 2; |
22 | 23 | ||
@@ -60,7 +61,17 @@ public class Stage implements Updateable { | |||
60 | * @implNote TODO: profile this and consider a garbage block counter | 61 | * @implNote TODO: profile this and consider a garbage block counter |
61 | */ | 62 | */ |
62 | public boolean isCleared() { | 63 | public boolean isCleared() { |
63 | return blocks.stream().noneMatch(block -> block.getType() == BlockType.GARBAGE); | 64 | return blocks.stream() |
65 | .noneMatch(block -> block.getType() == BlockType.GARBAGE); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * @return T(the physics simulation can start, i.e. the player has placed all their bombs) | ||
70 | */ | ||
71 | public boolean isReady() { | ||
72 | return blocks.stream() | ||
73 | .filter(block -> block.getType() == BlockType.BOMB) | ||
74 | .count() == BOMB_PLACEMENTS; | ||
64 | } | 75 | } |
65 | 76 | ||
66 | /** | 77 | /** |
diff --git a/src/main/java/fr/umlv/java/wallj/event/SimulationStartOrder.java b/src/main/java/fr/umlv/java/wallj/event/SimulationStartOrder.java new file mode 100644 index 0000000..a268ed0 --- /dev/null +++ b/src/main/java/fr/umlv/java/wallj/event/SimulationStartOrder.java | |||
@@ -0,0 +1,10 @@ | |||
1 | package fr.umlv.java.wallj.event; | ||
2 | |||
3 | /** | ||
4 | * Signals the beginning of the physics simulation. | ||
5 | * | ||
6 | * @author Pacien TRAN-GIRARD | ||
7 | */ | ||
8 | public final class SimulationStartOrder implements InputEvent { | ||
9 | // void | ||
10 | } | ||
diff --git a/src/test/java/fr/umlv/java/wallj/board/PathFinderTest.java b/src/test/java/fr/umlv/java/wallj/board/PathFinderTest.java index be615b7..ddacf71 100644 --- a/src/test/java/fr/umlv/java/wallj/board/PathFinderTest.java +++ b/src/test/java/fr/umlv/java/wallj/board/PathFinderTest.java | |||
@@ -14,7 +14,6 @@ import java.util.List; | |||
14 | * @author Pacien TRAN-GIRARD | 14 | * @author Pacien TRAN-GIRARD |
15 | */ | 15 | */ |
16 | final class PathFinderTest { | 16 | final class PathFinderTest { |
17 | |||
18 | private Path getResourcePath(String str) throws URISyntaxException { | 17 | private Path getResourcePath(String str) throws URISyntaxException { |
19 | return Paths.get(getClass().getResource(str).toURI()); | 18 | return Paths.get(getClass().getResource(str).toURI()); |
20 | } | 19 | } |
@@ -35,29 +34,37 @@ final class PathFinderTest { | |||
35 | return true; | 34 | return true; |
36 | } | 35 | } |
37 | 36 | ||
38 | @Test | 37 | private void testValidPath(Board board, TileVec2 origin, TileVec2 target) { |
39 | void testFailImpossibleFindPath() throws URISyntaxException, IOException { | ||
40 | Board board = BoardParser.parse(getResourcePath("/maps/island.txt")); | ||
41 | PathFinder pathFinder = new PathFinder(board); | 38 | PathFinder pathFinder = new PathFinder(board); |
39 | List<TileVec2> path = pathFinder.findPath(origin, target); | ||
42 | 40 | ||
43 | Assertions.assertThrows(IllegalArgumentException.class, () -> { | 41 | Assertions.assertEquals(path.get(0), origin); |
44 | pathFinder.findPath(TileVec2.of(7, 3), TileVec2.of(16, 5)); // into a wall | 42 | Assertions.assertEquals(path.get(path.size() - 1), target); |
45 | }); | 43 | Assertions.assertTrue(isPathConnected(path)); |
44 | Assertions.assertTrue(path.stream().allMatch(v -> board.getBlockTypeAt(v).isTraversable())); | ||
46 | } | 45 | } |
47 | 46 | ||
48 | @Test | 47 | @Test |
49 | void testFindPath() throws URISyntaxException, IOException { | 48 | void testFindPath() throws URISyntaxException, IOException { |
49 | testValidPath( | ||
50 | BoardParser.parse(getResourcePath("/maps/wall.txt")), | ||
51 | TileVec2.of(4, 3), | ||
52 | TileVec2.of(6, 3)); | ||
53 | |||
54 | testValidPath( | ||
55 | BoardParser.parse(getResourcePath("/maps/island.txt")), | ||
56 | TileVec2.of(7, 3), | ||
57 | TileVec2.of(33, 4)); | ||
58 | } | ||
59 | |||
60 | |||
61 | @Test | ||
62 | void testFailImpossibleFindPath() throws URISyntaxException, IOException { | ||
50 | Board board = BoardParser.parse(getResourcePath("/maps/island.txt")); | 63 | Board board = BoardParser.parse(getResourcePath("/maps/island.txt")); |
51 | PathFinder pathFinder = new PathFinder(board); | 64 | PathFinder pathFinder = new PathFinder(board); |
52 | 65 | ||
53 | TileVec2 origin = TileVec2.of(7, 3); | 66 | Assertions.assertThrows(IllegalArgumentException.class, () -> { |
54 | TileVec2 target = TileVec2.of(33, 4); | 67 | pathFinder.findPath(TileVec2.of(7, 3), TileVec2.of(16, 5)); // into a wall |
55 | List<TileVec2> path = pathFinder.findPath(origin, target); | 68 | }); |
56 | |||
57 | Assertions.assertEquals(path.get(0), origin); | ||
58 | Assertions.assertEquals(path.get(path.size() - 1), target); | ||
59 | Assertions.assertTrue(isPathConnected(path)); | ||
60 | Assertions.assertTrue(path.stream().allMatch(v -> board.getBlockTypeAt(v).isTraversable())); | ||
61 | } | 69 | } |
62 | |||
63 | } | 70 | } |
diff --git a/src/test/resources/maps/wall.txt b/src/test/resources/maps/wall.txt new file mode 100644 index 0000000..97a5874 --- /dev/null +++ b/src/test/resources/maps/wall.txt | |||
@@ -0,0 +1,7 @@ | |||
1 | WWWWWWWWWWW | ||
2 | W W | ||
3 | W W W | ||
4 | W W W | ||
5 | W W W | ||
6 | W W | ||
7 | WWWWWWWWWWW \ No newline at end of file | ||