From 6bbef8efd0748d7ebd71c8e17b90ac7f407e4575 Mon Sep 17 00:00:00 2001 From: pacien Date: Sat, 3 Feb 2018 20:58:28 +0100 Subject: Fix path finder incorrect behaviour Signed-off-by: pacien --- .../java/fr/umlv/java/wallj/board/PathFinder.java | 4 +-- .../fr/umlv/java/wallj/board/PathFinderTest.java | 39 +++++++++++++--------- src/test/resources/maps/wall.txt | 7 ++++ 3 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 src/test/resources/maps/wall.txt 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 { private static List findPath(Node start, T target, BiFunction heuristic) { Map, NodeSearchData> searchData = new HashMap<>(); - TreeSet> discovered = new TreeSet<>(Comparator.comparingDouble(n -> searchData.get(n).estimatedCost)); + Queue> discovered = new PriorityQueue<>(Comparator.comparingDouble(n -> searchData.get(n).estimatedCost)); Set> visited = new HashSet<>(); searchData.put(start, new NodeSearchData<>(null, 0, heuristic.apply(start.val, target))); @@ -65,7 +65,7 @@ public class PathFinder { Node current; while (!discovered.isEmpty()) { - current = discovered.pollFirst(); + current = discovered.poll(); if (target.equals(current.val)) return buildPath(searchData, current); for (Map.Entry, Integer> neighborEntry : current.neighbors.entrySet()) { 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; * @author Pacien TRAN-GIRARD */ final class PathFinderTest { - private Path getResourcePath(String str) throws URISyntaxException { return Paths.get(getClass().getResource(str).toURI()); } @@ -35,29 +34,37 @@ final class PathFinderTest { return true; } - @Test - void testFailImpossibleFindPath() throws URISyntaxException, IOException { - Board board = BoardParser.parse(getResourcePath("/maps/island.txt")); + private void testValidPath(Board board, TileVec2 origin, TileVec2 target) { PathFinder pathFinder = new PathFinder(board); + List path = pathFinder.findPath(origin, target); - Assertions.assertThrows(IllegalArgumentException.class, () -> { - pathFinder.findPath(TileVec2.of(7, 3), TileVec2.of(16, 5)); // into a wall - }); + Assertions.assertEquals(path.get(0), origin); + Assertions.assertEquals(path.get(path.size() - 1), target); + Assertions.assertTrue(isPathConnected(path)); + Assertions.assertTrue(path.stream().allMatch(v -> board.getBlockTypeAt(v).isTraversable())); } @Test void testFindPath() throws URISyntaxException, IOException { + testValidPath( + BoardParser.parse(getResourcePath("/maps/wall.txt")), + TileVec2.of(4, 3), + TileVec2.of(6, 3)); + + testValidPath( + BoardParser.parse(getResourcePath("/maps/island.txt")), + TileVec2.of(7, 3), + TileVec2.of(33, 4)); + } + + + @Test + void testFailImpossibleFindPath() throws URISyntaxException, IOException { Board board = BoardParser.parse(getResourcePath("/maps/island.txt")); PathFinder pathFinder = new PathFinder(board); - TileVec2 origin = TileVec2.of(7, 3); - TileVec2 target = TileVec2.of(33, 4); - List path = pathFinder.findPath(origin, target); - - Assertions.assertEquals(path.get(0), origin); - Assertions.assertEquals(path.get(path.size() - 1), target); - Assertions.assertTrue(isPathConnected(path)); - Assertions.assertTrue(path.stream().allMatch(v -> board.getBlockTypeAt(v).isTraversable())); + Assertions.assertThrows(IllegalArgumentException.class, () -> { + pathFinder.findPath(TileVec2.of(7, 3), TileVec2.of(16, 5)); // into a wall + }); } - } 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 @@ +WWWWWWWWWWW +W W +W W W +W W W +W W W +W W +WWWWWWWWWWW \ No newline at end of file -- cgit v1.2.3 From 75cc8b9be15b33935fa8965aed808836ef3b3e5a Mon Sep 17 00:00:00 2001 From: pacien Date: Sat, 3 Feb 2018 22:36:39 +0100 Subject: Add max bomb placement restriction Signed-off-by: pacien --- src/main/java/fr/umlv/java/wallj/block/RobotBlock.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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..e4e0aad 100644 --- a/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java +++ b/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java @@ -23,10 +23,12 @@ import java.util.List; */ public class RobotBlock extends Block { private static final float SPEED = 10f; // px/ms + private static final int MAX_BOMB_PLACEMENTS = 3; private Vec2 pos; private PathFinder pathFinder; private Deque path = new LinkedList<>(); + private int droppedBombCount = 0; RobotBlock(Vec2 pos) { super(BlockType.ROBOT); @@ -62,10 +64,17 @@ public class RobotBlock extends Block { return Events.findFirst(events, BombSetupOrder.class) .map(event -> isOnBomb(stage) ? Collections.singletonList(new BombTimerIncrEvent(getTile())) : - Collections.singletonList(new BlockCreateEvent(BlockType.BOMB, getTile()))) + dropBomb(event)) .orElse(Collections.emptyList()); } + private List dropBomb(BombSetupOrder order) { + if (droppedBombCount >= MAX_BOMB_PLACEMENTS) return Collections.emptyList(); + + droppedBombCount++; + return Collections.singletonList(new BlockCreateEvent(BlockType.BOMB, getTile())); + } + private void updatePath(Board board, TileVec2 target) { if (!board.inside(target) || !board.getBlockTypeAt(target).isTraversable()) return; if (pathFinder == null) pathFinder = new PathFinder(board); -- cgit v1.2.3 From e8675bbf9b2841bb209ca8ae11eaaf379b78470c Mon Sep 17 00:00:00 2001 From: pacien Date: Sat, 3 Feb 2018 22:40:02 +0100 Subject: Add SimulationStartOrder Signed-off-by: pacien --- .../java/fr/umlv/java/wallj/event/SimulationStartOrder.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/fr/umlv/java/wallj/event/SimulationStartOrder.java 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 @@ +package fr.umlv.java.wallj.event; + +/** + * Signals the beginning of the physics simulation. + * + * @author Pacien TRAN-GIRARD + */ +public final class SimulationStartOrder implements InputEvent { + // void +} -- cgit v1.2.3 From 30f734d6b8602410e7d57d2f9f9bd4814df9fefe Mon Sep 17 00:00:00 2001 From: pacien Date: Sat, 3 Feb 2018 22:44:09 +0100 Subject: Add simulation starting condition check Signed-off-by: pacien --- src/main/java/fr/umlv/java/wallj/block/RobotBlock.java | 3 +-- src/main/java/fr/umlv/java/wallj/context/Stage.java | 13 ++++++++++++- 2 files changed, 13 insertions(+), 3 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 e4e0aad..4d7745b 100644 --- a/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java +++ b/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java @@ -23,7 +23,6 @@ import java.util.List; */ public class RobotBlock extends Block { private static final float SPEED = 10f; // px/ms - private static final int MAX_BOMB_PLACEMENTS = 3; private Vec2 pos; private PathFinder pathFinder; @@ -69,7 +68,7 @@ public class RobotBlock extends Block { } private List dropBomb(BombSetupOrder order) { - if (droppedBombCount >= MAX_BOMB_PLACEMENTS) return Collections.emptyList(); + if (droppedBombCount >= Stage.BOMB_PLACEMENTS) return Collections.emptyList(); droppedBombCount++; return Collections.singletonList(new BlockCreateEvent(BlockType.BOMB, getTile())); 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.*; * @author Pacien TRAN-GIRARD */ public class Stage implements Updateable { + public static final int BOMB_PLACEMENTS = 3; private static final int VELOCITY_TICK_PER_MS = 6; private static final int POSITION_TICK_PER_MS = 2; @@ -60,7 +61,17 @@ public class Stage implements Updateable { * @implNote TODO: profile this and consider a garbage block counter */ public boolean isCleared() { - return blocks.stream().noneMatch(block -> block.getType() == BlockType.GARBAGE); + return blocks.stream() + .noneMatch(block -> block.getType() == BlockType.GARBAGE); + } + + /** + * @return T(the physics simulation can start, i.e. the player has placed all their bombs) + */ + public boolean isReady() { + return blocks.stream() + .filter(block -> block.getType() == BlockType.BOMB) + .count() == BOMB_PLACEMENTS; } /** -- cgit v1.2.3 From 745b3c798de97785dd92e1a3db83cfdb2801ee87 Mon Sep 17 00:00:00 2001 From: pacien Date: Sat, 3 Feb 2018 22:46:20 +0100 Subject: Add note Signed-off-by: pacien --- src/main/java/fr/umlv/java/wallj/block/RobotBlock.java | 3 +++ 1 file changed, 3 insertions(+) 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 4d7745b..f81f423 100644 --- a/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java +++ b/src/main/java/fr/umlv/java/wallj/block/RobotBlock.java @@ -93,6 +93,9 @@ public class RobotBlock extends Block { graphicsContext.paintCircle(Color.BLUE, getPos(), TileVec2.TILE_DIM / 2); } + /** + * @implNote TODO: profile this and consider a mapping (pos: block) for faster lookup in Stage + */ private boolean isOnBomb(Stage stage) { return stage.getBlocks().stream() .anyMatch(block -> Objects.equals(block.getType(), BlockType.BOMB) && -- cgit v1.2.3