From 9bd245c0a8c9997aa2a2e6e98e89cafce6bfb0ce Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Sat, 9 Apr 2016 21:13:15 +0200 Subject: Import new given intermediate tests --- test/ch/epfl/xblast/ArgumentCheckerTest.java | 36 ++ test/ch/epfl/xblast/BlockEnumTests.java | 87 ++++ test/ch/epfl/xblast/BoardTests.java | 217 ++++++++ test/ch/epfl/xblast/CellTest.java | 60 ++- test/ch/epfl/xblast/CellTest05.java | 22 + test/ch/epfl/xblast/DirectionTest.java | 11 + test/ch/epfl/xblast/GameStateTest05.java | 512 +++++++++++++++++++ test/ch/epfl/xblast/GameStateTestUtils.java | 119 +++++ test/ch/epfl/xblast/ListsTests.java | 105 ++++ test/ch/epfl/xblast/SubCellTest.java | 72 ++- test/ch/epfl/xblast/SubCellTest05.java | 27 + test/ch/epfl/xblast/TestEtape4.java | 332 +++++++++++++ test/ch/epfl/xblast/TicksTest.java | 30 ++ test/ch/epfl/xblast/etape6/BonusTest.java | 209 ++++++++ .../ch/epfl/xblast/etape6/DirectionChangeTest.java | 324 ++++++++++++ test/ch/epfl/xblast/etape6/DirectionEvents.java | 98 ++++ test/ch/epfl/xblast/etape6/GameSimulation.java | 143 ++++++ test/ch/epfl/xblast/etape6/LifeTest.java | 176 +++++++ test/ch/epfl/xblast/etape6/RandomTestGame.java | 86 ++++ test/ch/epfl/xblast/etape6/events/Event.java | 8 + .../epfl/xblast/etape6/events/EventSequence.java | 56 +++ test/ch/epfl/xblast/etape6/events/PlayerEvent.java | 52 ++ test/ch/epfl/xblast/etape6/events/PlayerState.java | 80 +++ .../xblast/etape6/generator/EventsGenerator.java | 81 +++ .../etape6/generator/PlayersEventsGenerator.java | 42 ++ test/ch/epfl/xblast/server/BombTest.java | 201 ++++++++ test/ch/epfl/xblast/server/PlayerTest.java | 553 +++++++++++++++++++++ 27 files changed, 3735 insertions(+), 4 deletions(-) create mode 100644 test/ch/epfl/xblast/ArgumentCheckerTest.java create mode 100644 test/ch/epfl/xblast/BlockEnumTests.java create mode 100644 test/ch/epfl/xblast/BoardTests.java create mode 100644 test/ch/epfl/xblast/CellTest05.java create mode 100644 test/ch/epfl/xblast/GameStateTest05.java create mode 100644 test/ch/epfl/xblast/GameStateTestUtils.java create mode 100644 test/ch/epfl/xblast/ListsTests.java create mode 100644 test/ch/epfl/xblast/SubCellTest05.java create mode 100644 test/ch/epfl/xblast/TestEtape4.java create mode 100644 test/ch/epfl/xblast/TicksTest.java create mode 100644 test/ch/epfl/xblast/etape6/BonusTest.java create mode 100644 test/ch/epfl/xblast/etape6/DirectionChangeTest.java create mode 100644 test/ch/epfl/xblast/etape6/DirectionEvents.java create mode 100644 test/ch/epfl/xblast/etape6/GameSimulation.java create mode 100644 test/ch/epfl/xblast/etape6/LifeTest.java create mode 100644 test/ch/epfl/xblast/etape6/RandomTestGame.java create mode 100644 test/ch/epfl/xblast/etape6/events/Event.java create mode 100644 test/ch/epfl/xblast/etape6/events/EventSequence.java create mode 100644 test/ch/epfl/xblast/etape6/events/PlayerEvent.java create mode 100644 test/ch/epfl/xblast/etape6/events/PlayerState.java create mode 100644 test/ch/epfl/xblast/etape6/generator/EventsGenerator.java create mode 100644 test/ch/epfl/xblast/etape6/generator/PlayersEventsGenerator.java create mode 100644 test/ch/epfl/xblast/server/BombTest.java create mode 100644 test/ch/epfl/xblast/server/PlayerTest.java (limited to 'test/ch/epfl') diff --git a/test/ch/epfl/xblast/ArgumentCheckerTest.java b/test/ch/epfl/xblast/ArgumentCheckerTest.java new file mode 100644 index 0000000..b439700 --- /dev/null +++ b/test/ch/epfl/xblast/ArgumentCheckerTest.java @@ -0,0 +1,36 @@ +package ch.epfl.xblast; + +import org.junit.Test; + +import static ch.epfl.xblast.ArgumentChecker.requireNonNegative; +import static org.junit.Assert.assertEquals; + +/** + * @author EPFL + */ +public class ArgumentCheckerTest { + + @Test + public void requireNonNegativeAcceptPositives() { + assertEquals("Zero is accepted", 0, requireNonNegative(0)); + assertEquals("One is accepted", 1, requireNonNegative(1)); + assertEquals("42 is accepted", 42, requireNonNegative(42)); + assertEquals("Max integer is accepted", Integer.MAX_VALUE, requireNonNegative(Integer.MAX_VALUE)); + } + + @Test(expected = IllegalArgumentException.class) + public void requireNonNegativeRejectMinusOne() { + requireNonNegative(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void requireNonNegativeRejectMinus42() { + requireNonNegative(-42); + } + + @Test(expected = IllegalArgumentException.class) + public void requireNonNegativeRejectMinInteger() { + requireNonNegative(Integer.MIN_VALUE); + } + +} diff --git a/test/ch/epfl/xblast/BlockEnumTests.java b/test/ch/epfl/xblast/BlockEnumTests.java new file mode 100644 index 0000000..dcf2939 --- /dev/null +++ b/test/ch/epfl/xblast/BlockEnumTests.java @@ -0,0 +1,87 @@ +package ch.epfl.xblast; + +import org.junit.Test; + +import java.util.NoSuchElementException; + +import static ch.epfl.xblast.server.Block.*; +import static ch.epfl.xblast.server.Bonus.INC_BOMB; +import static ch.epfl.xblast.server.Bonus.INC_RANGE; +import static org.junit.Assert.*; + +/** + * @author EPFL + */ +public class BlockEnumTests { + + @Test + public void isFreeBehaviourIsCorrect() { + assertTrue(FREE.isFree()); + assertFalse(INDESTRUCTIBLE_WALL.isFree()); + assertFalse(DESTRUCTIBLE_WALL.isFree()); + assertFalse(CRUMBLING_WALL.isFree()); + assertFalse(BONUS_BOMB.isFree()); + assertFalse(BONUS_RANGE.isFree()); + } + + @Test + public void canHostPlayerBehaviorIsCorrect() { + assertTrue(FREE.canHostPlayer()); + assertTrue(BONUS_BOMB.canHostPlayer()); + assertTrue(BONUS_RANGE.canHostPlayer()); + assertFalse(INDESTRUCTIBLE_WALL.canHostPlayer()); + assertFalse(DESTRUCTIBLE_WALL.canHostPlayer()); + assertFalse(CRUMBLING_WALL.canHostPlayer()); + } + + @Test + public void castsShadowBehaviourIsCorrect() { + assertTrue(INDESTRUCTIBLE_WALL.castsShadow()); + assertTrue(DESTRUCTIBLE_WALL.castsShadow()); + assertTrue(CRUMBLING_WALL.castsShadow()); + assertFalse(FREE.castsShadow()); + assertFalse(BONUS_BOMB.castsShadow()); + assertFalse(BONUS_RANGE.castsShadow()); + } + + @Test(expected = NoSuchElementException.class) + public void freeBlockThrowsExceptionWhenRetrievingBonus() { + FREE.associatedBonus(); + } + + @Test(expected = NoSuchElementException.class) + public void indestructibleWallBlockThrowsExceptionWhenRetrievingBonus() { + INDESTRUCTIBLE_WALL.associatedBonus(); + } + + @Test(expected = NoSuchElementException.class) + public void destructibleWallBlockThrowsExceptionWhenRetrievingBonus() { + DESTRUCTIBLE_WALL.associatedBonus(); + } + + @Test(expected = NoSuchElementException.class) + public void crumblingWallBlockThrowsExceptionWhenRetrievingBonus() { + CRUMBLING_WALL.associatedBonus(); + } + + @Test + public void bonusBombBlockHasCorrectBonus() { + assertEquals(INC_BOMB, BONUS_BOMB.associatedBonus()); + } + + @Test + public void bonusRangeBlockHasCorrectBonus() { + assertEquals(INC_RANGE, BONUS_RANGE.associatedBonus()); + } + + @Test + public void isBonusBehaviourIsCorrect() { + assertTrue(BONUS_RANGE.isBonus()); + assertTrue(BONUS_BOMB.isBonus()); + assertFalse(FREE.isBonus()); + assertFalse(INDESTRUCTIBLE_WALL.isBonus()); + assertFalse(DESTRUCTIBLE_WALL.isBonus()); + assertFalse(CRUMBLING_WALL.isBonus()); + } + +} diff --git a/test/ch/epfl/xblast/BoardTests.java b/test/ch/epfl/xblast/BoardTests.java new file mode 100644 index 0000000..7add23f --- /dev/null +++ b/test/ch/epfl/xblast/BoardTests.java @@ -0,0 +1,217 @@ +package ch.epfl.xblast; + +import ch.epfl.cs108.Sq; +import ch.epfl.xblast.server.Block; +import ch.epfl.xblast.server.Board; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static ch.epfl.xblast.server.Block.*; +import static org.junit.Assert.*; + +/** + * @author EPFL + */ +public class BoardTests { + + @Test + public void boardClassIsImmutable() { + List> matrix = new ArrayList<>(Cell.COUNT); + + for (int i = 0; i < Cell.COUNT; i++) { + matrix.add(Sq.constant(INDESTRUCTIBLE_WALL)); + } + + Board b = new Board(matrix); + + for (int i = 0; i < Cell.COUNT; i++) { + matrix.set(i, matrix.get(i).limit(1).concat(Sq.constant(FREE))); + } + + for (int y = 0; y < Cell.ROWS; y++) { + for (int x = 0; x < Cell.COLUMNS; x++) { + assertNotEquals(FREE, b.blocksAt(new Cell(x, y)).tail().head()); + } + } + + } + + @Test(expected = IllegalArgumentException.class) + public void emptyListOfBlockSequencesRaisesException() { + new Board(new ArrayList>()); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidNumberOfBlockSequencesRaisesException() { + Sq freeBlockSequence = Sq.constant(FREE); + List> wholeBoardList = new ArrayList<>(Cell.COUNT); + + //Creates a board + for (int k = 0; k < Cell.COUNT - 1; k++) { + wholeBoardList.add(freeBlockSequence); + } + + new Board(wholeBoardList); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidNumberOfRowsRaisesException() { + List freeRow = new ArrayList<>(Collections.nCopies(Cell.COLUMNS, FREE)); + List> matrix = Collections.nCopies(Cell.ROWS + 1, freeRow); + Board.ofRows(new ArrayList<>(matrix)); + } + + @Test(expected = IllegalArgumentException.class) + public void invalidColumnRaisesException() { + List validRow = new ArrayList<>(Collections.nCopies(Cell.COLUMNS, FREE)); + List incompleteRow = new ArrayList<>(validRow); + incompleteRow.remove(FREE); + + List> matrix = new ArrayList<>(Collections.nCopies(Cell.ROWS - 1, validRow)); + + matrix.add(incompleteRow); + Board.ofRows(matrix); + } + + @Test + public void blockAtIsCorrect() { + Block[] blockTypes = Block.values(); + + List> matrix = new ArrayList<>(Collections.nCopies(Cell.ROWS, generateRow(Cell.COLUMNS, blockTypes))); + Board board = Board.ofRows(matrix); + + //Check at every position if the returned block corresponds to what we constructed + for (int y = 0; y < Cell.ROWS; y++) { + for (int x = 0; x < Cell.COLUMNS; x++) { + int index = x % blockTypes.length; + Cell c = new Cell(x, y); + + assertEquals(blockTypes[index], board.blockAt(c)); + } + } + } + + @Test + public void blocksAtIsCorrect() { + Block[] blockTypes = Block.values(); + + List> matrix = Collections.nCopies(Cell.ROWS, generateRow(Cell.COLUMNS, blockTypes)); + + /*Build a board where every block is followed in the sequence by + the next block type as specified by the enumeration order*/ + List> blocks = new ArrayList<>(Cell.COUNT); + for (List l : matrix) { + for (Block b : l) + blocks.add(Sq.repeat(1, b).concat(Sq.repeat(1, blockTypes[(b.ordinal() + 1) % blockTypes.length]))); + } + + Board board = new Board(blocks); + + //Check at every position if the sequence corresponds to what we constructed + for (int y = 0; y < Cell.ROWS; y++) { + for (int x = 0; x < Cell.COLUMNS; x++) { + int index = Math.floorMod(x, blockTypes.length); + Cell c = new Cell(x, y); + Sq blockSequence = board.blocksAt(c); + + assertEquals(blockTypes[index], blockSequence.head()); + assertEquals(blockTypes[(index + 1) % blockTypes.length], blockSequence.tail().head()); + assertTrue(blockSequence.tail().tail().isEmpty()); + } + } + } + + @Test(expected = IllegalArgumentException.class) + public void ofQuadrantNWInvalidColumnsRaisesException() { + List someRow = new ArrayList<>(Collections.nCopies(Cell.COLUMNS / 2 + 1, FREE)); + List> matrix = new ArrayList<>(Collections.nCopies(Cell.ROWS / 2, someRow)); + Board.ofQuadrantNWBlocksWalled(matrix); + } + + @Test(expected = IllegalArgumentException.class) + public void ofQuadrantNWInvalidRowsRaisesException() { + List someRow = new ArrayList<>(Collections.nCopies(Cell.COLUMNS / 2, FREE)); + List> matrix = new ArrayList<>(Collections.nCopies(Cell.ROWS / 2 - 1, someRow)); + Board.ofQuadrantNWBlocksWalled(matrix); + } + + @Test + public void ofQuadrantNWBlocksWalledIsCorrect() { + + List> matrix = Collections.nCopies(Cell.ROWS / 2, generateRow(Cell.COLUMNS / 2, Block.values())); + Board board = Board.ofQuadrantNWBlocksWalled(new ArrayList<>(matrix)); + + boardIsWalled(board); + + for (int y = Cell.ROWS / 2; y >= 1; y--) { + List mirroredRow = Lists.mirrored(matrix.get(y - 1)); + for (int x = 1; x < Cell.COLUMNS - 1; x++) { + // b1 checks the upper half board, whereas b2 checks the lower half board. + // When y = Cell.ROWS / 2, we are checking the middle line, and when y = 1, + // we are checking the line 1 with b1 and the line 13 with b2. + Block b1 = board.blockAt(new Cell(x, y)); + assertEquals(mirroredRow.get(x - 1), b1); + Block b2 = board.blockAt(new Cell(x, Cell.ROWS - 1 - y)); + assertEquals(mirroredRow.get(x - 1), b2); + } + } + } + + @Test(expected = IllegalArgumentException.class) + public void ofInnerBlocksInvalidArgumentRaisesException() { + List> blockList = Collections.nCopies(Cell.ROWS - 2, Collections.emptyList()); + Board.ofInnerBlocksWalled(new ArrayList<>(blockList)); + } + + @Test + public void ofInnerBlocksWalledIsCorrect() { + List aRow = Collections.nCopies(Cell.COLUMNS - 2, CRUMBLING_WALL); + List> matrix = Collections.nCopies(Cell.ROWS - 2, new ArrayList<>(aRow)); + Board board = Board.ofInnerBlocksWalled(new ArrayList<>(matrix)); + + boardIsWalled(board); + + for (int x = 1; x < Cell.COLUMNS - 1; x++) { + for (int y = 1; y < Cell.ROWS - 1; y++) { + Block b = board.blockAt(new Cell(x, y)); + assertEquals(CRUMBLING_WALL, b); + } + } + } + + private void boardIsWalled(Board board) { + for (int x = 0; x < Cell.COLUMNS; x++) { + //Checks the upper row + assertEquals(INDESTRUCTIBLE_WALL, board.blockAt(new Cell(x, 0))); + + //Checks the bottom row + assertEquals(INDESTRUCTIBLE_WALL, board.blockAt(new Cell(x, Cell.ROWS - 1))); + } + + for (int y = 0; y < Cell.ROWS; y++) { + //Checks the left column + assertEquals(INDESTRUCTIBLE_WALL, board.blockAt(new Cell(0, y))); + + //Checks the right column + assertEquals(INDESTRUCTIBLE_WALL, board.blockAt(new Cell(Cell.COLUMNS - 1, y))); + } + + } + + //Generate a row using available block types, consecutively in the order they are declared in the enumeration + private List generateRow(int requiredSize, Block[] blockTypes) { + + List someRow = new ArrayList<>(); + int x; + for (int i = 0; i < requiredSize; i++) { + x = i % blockTypes.length; + someRow.add(blockTypes[x]); + } + + return someRow; + } + +} diff --git a/test/ch/epfl/xblast/CellTest.java b/test/ch/epfl/xblast/CellTest.java index c5d93e8..de3d1e8 100644 --- a/test/ch/epfl/xblast/CellTest.java +++ b/test/ch/epfl/xblast/CellTest.java @@ -2,8 +2,7 @@ package ch.epfl.xblast; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.*; /** * @author EPFL @@ -52,6 +51,18 @@ public class CellTest { } } + @Test + public void equalsCorrect() { + Cell c1 = new Cell(0, 0); + Cell c2 = new Cell(0, 1); + Cell c4 = new Cell(1, 0); + Cell c3 = new Cell(0, 0); + assertFalse(c1.equals(c2)); + assertFalse(c1.equals(c4)); + assertFalse(c4.equals(c2)); + assertTrue(c1.equals(c3)); + } + @Test public void neighborsOfOriginAreCorrect() { Cell c = new Cell(0, 0); @@ -61,6 +72,34 @@ public class CellTest { assertEquals(new Cell(14, 0), c.neighbor(Direction.W)); } + @Test + public void neighborOfCornerCorrect() { + Cell NE = new Cell(14, 0); + Cell NW = new Cell(0, 0); + Cell SE = new Cell(14, 12); + Cell SW = new Cell(0, 12); + + assertEquals(new Cell(0, 12), NW.neighbor(Direction.N)); + assertEquals(new Cell(1, 0), NW.neighbor(Direction.E)); + assertEquals(new Cell(0, 1), NW.neighbor(Direction.S)); + assertEquals(new Cell(14, 0), NW.neighbor(Direction.W)); + + assertEquals(SE, NE.neighbor(Direction.N)); + assertEquals(NW, NE.neighbor(Direction.E)); + assertEquals(new Cell(14, 1), NE.neighbor(Direction.S)); + assertEquals(new Cell(13, 0), NE.neighbor(Direction.W)); + + assertEquals(new Cell(0, 11), SW.neighbor(Direction.N)); + assertEquals(new Cell(1, 12), SW.neighbor(Direction.E)); + assertEquals(NW, SW.neighbor(Direction.S)); + assertEquals(SE, SW.neighbor(Direction.W)); + + assertEquals(new Cell(14, 11), SE.neighbor(Direction.N)); + assertEquals(SW, SE.neighbor(Direction.E)); + assertEquals(NE, SE.neighbor(Direction.S)); + assertEquals(new Cell(13, 12), SE.neighbor(Direction.W)); + } + @Test public void oppositeNeighborOfNeighborIsThis() { for (Cell c : Cell.ROW_MAJOR_ORDER) { @@ -70,4 +109,21 @@ public class CellTest { } } + @Test(expected = UnsupportedOperationException.class) + public void isRowMajorOrderModifiable() { + Cell.ROW_MAJOR_ORDER.set(0, new Cell(1, 0)); + } + + @Test(expected = UnsupportedOperationException.class) + public void isSpiralOrderModifiable() { + Cell.SPIRAL_ORDER.set(0, new Cell(1, 0)); + } + + @Test + public void constantsAreCorrect() { + assertEquals(15, Cell.COLUMNS); + assertEquals(13, Cell.ROWS); + assertEquals(15 * 13, Cell.COUNT); + } + } diff --git a/test/ch/epfl/xblast/CellTest05.java b/test/ch/epfl/xblast/CellTest05.java new file mode 100644 index 0000000..01a58a1 --- /dev/null +++ b/test/ch/epfl/xblast/CellTest05.java @@ -0,0 +1,22 @@ +package ch.epfl.xblast; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author EPFL + */ +public class CellTest05 { + + @Test + public void hashCodeCellsConsistentWithEquals() { + for (Cell c : Cell.ROW_MAJOR_ORDER) { + Cell c1 = new Cell(c.x(), c.y()); + if (c.equals(c1)) { + assertEquals(c.hashCode(), c1.hashCode()); + } + } + } + +} diff --git a/test/ch/epfl/xblast/DirectionTest.java b/test/ch/epfl/xblast/DirectionTest.java index 49cf4be..568a3ef 100644 --- a/test/ch/epfl/xblast/DirectionTest.java +++ b/test/ch/epfl/xblast/DirectionTest.java @@ -16,6 +16,14 @@ public class DirectionTest { assertEquals(d, d.opposite().opposite()); } + @Test + public void oppositeWorksForAll4Directions() { + assertEquals(Direction.S, Direction.N.opposite()); + assertEquals(Direction.W, Direction.E.opposite()); + assertEquals(Direction.N, Direction.S.opposite()); + assertEquals(Direction.E, Direction.W.opposite()); + } + @Test public void oppositeIsTwoStepsAway() { for (Direction d : Direction.values()) @@ -42,6 +50,9 @@ public class DirectionTest { } } + /** + * @author Pacien TRAN-GIRARD (261948) + */ @Test public void oppositeVectorSumIsNil() { for (Direction d : Direction.values()) { diff --git a/test/ch/epfl/xblast/GameStateTest05.java b/test/ch/epfl/xblast/GameStateTest05.java new file mode 100644 index 0000000..3fed463 --- /dev/null +++ b/test/ch/epfl/xblast/GameStateTest05.java @@ -0,0 +1,512 @@ +package ch.epfl.xblast; + +import ch.epfl.cs108.Sq; +import ch.epfl.xblast.server.*; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.*; +import java.util.function.UnaryOperator; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static ch.epfl.xblast.GameStateTestUtils.*; +import static java.util.Collections.*; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; +import static org.junit.Assert.*; + +/** + * @author EPFL + */ +public class GameStateTest05 { + + private static final Cell POS_NW = new Cell(1, 1); + private static final Cell POS_NE = new Cell(-2, 1); + private static final Cell POS_SE = new Cell(-2, -2); + private static final Cell POS_SW = new Cell(1, -2); + private static final Cell POS_CENTER = new Cell(7, 6); + + private static final List CELLS = Arrays.asList(POS_NW, POS_NE, POS_SE, POS_SW); + + private static Board createBoard() { + Block __ = Block.FREE; + Block XX = Block.INDESTRUCTIBLE_WALL; + Block xx = Block.DESTRUCTIBLE_WALL; + return Board.ofQuadrantNWBlocksWalled( + Arrays.asList(Arrays.asList(__, __, __, __, __, xx, __), Arrays.asList(__, XX, xx, XX, xx, XX, xx), + Arrays.asList(__, xx, __, __, __, xx, __), Arrays.asList(xx, XX, __, XX, XX, XX, XX), + Arrays.asList(__, xx, __, xx, __, __, __), Arrays.asList(xx, XX, xx, XX, xx, XX, __))); + } + + private static Board createBoard(Block centralBlock) { + Block __ = Block.FREE; + return Board.ofQuadrantNWBlocksWalled(Arrays.asList(Arrays.asList(__, __, __, __, __, __, __), + Arrays.asList(__, __, __, __, __, __, __), Arrays.asList(__, __, __, __, __, __, __), + Arrays.asList(__, __, __, __, __, __, __), Arrays.asList(__, __, __, __, __, __, __), + Arrays.asList(__, __, __, __, __, __, centralBlock))); + } + + private static List createPlayers(int lives, int maxBombs, int bombRange, Cell p1, Cell p2, Cell p3, + Cell p4) { + return Arrays.asList(new Player(PlayerID.PLAYER_1, lives, p1, maxBombs, bombRange), + new Player(PlayerID.PLAYER_2, lives, p2, maxBombs, bombRange), + new Player(PlayerID.PLAYER_3, lives, p3, maxBombs, bombRange), + new Player(PlayerID.PLAYER_4, lives, p4, maxBombs, bombRange)); + } + + private static List createPlayers() { + return createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW); + } + + private static List createBombs() { + return CELLS.stream().map(c -> new Bomb(PlayerID.PLAYER_1, c, 3, 3)).collect(toList()); + } + + private static List> createBlasts() { + return CELLS.stream().map(Sq::constant).collect(toList()); + } + + private static void bonusDisappearsPlayer(Block block) { + Board board = createBoard(block); + List players = Arrays.asList(new Player(PlayerID.PLAYER_1, 1, POS_CENTER, 1, 3), + new Player(PlayerID.PLAYER_2, 1, POS_NW, 0, 3), new Player(PlayerID.PLAYER_3, 1, POS_SE, 0, 3), + new Player(PlayerID.PLAYER_4, 1, POS_SW, 0, 3)); + + GameState gameState = new GameState(0, board, players, emptyList(), emptyList(), + emptyList()); + assertEquals(block, gameState.board().blockAt(POS_CENTER)); + + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(Block.FREE, gameState.board().blockAt(POS_CENTER)); + } + + private static void bonusDisappearsBlast(Block block) { + Board board = createBoard(block); + List players = Arrays.asList(new Player(PlayerID.PLAYER_1, 1, POS_NE, 1, 3), + new Player(PlayerID.PLAYER_2, 1, POS_NW, 0, 3), new Player(PlayerID.PLAYER_3, 1, POS_SE, 0, 3), + new Player(PlayerID.PLAYER_4, 1, POS_SW, 0, 3)); + + List> blasts = + singletonList(Sq.iterate(POS_CENTER.neighbor(Direction.N), c -> c.neighbor(Direction.S))); + + GameState gameState = new GameState(0, board, players, emptyList(), emptyList(), + blasts); + + assertEquals(block, gameState.board().blockAt(POS_CENTER)); + + for (int i = 0; i < Ticks.EXPLOSION_TICKS; ++i) { + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(block, gameState.board().blockAt(POS_CENTER)); + } + + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(Block.FREE, gameState.board().blockAt(POS_CENTER)); + } + + private static void bonusDisappearsPlayerBeforeBlast(Block block) { + Board board = createBoard(block); + List players = Arrays.asList(new Player(PlayerID.PLAYER_1, 1, POS_CENTER.neighbor(Direction.W), 1, 3), + new Player(PlayerID.PLAYER_2, 1, POS_NW, 0, 3), new Player(PlayerID.PLAYER_3, 1, POS_SE, 0, 3), + new Player(PlayerID.PLAYER_4, 1, POS_SW, 0, 3)); + + List> blasts = + singletonList(Sq.iterate(POS_CENTER.neighbor(Direction.N), c -> c.neighbor(Direction.S))); + + GameState gameState = new GameState(0, board, players, emptyList(), emptyList(), + blasts); + + assertEquals(block, gameState.board().blockAt(POS_CENTER)); + + singletonMap(PlayerID.PLAYER_1, Direction.E); + + for (int i = 0; i <= Ticks.EXPLOSION_TICKS / 2.; ++i) { + gameState = gameState.next(singletonMap(PlayerID.PLAYER_1, Optional.of(Direction.E)), + emptySet()); + assertEquals(block, gameState.board().blockAt(POS_CENTER)); + } + + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(Block.FREE, gameState.board().blockAt(POS_CENTER)); + } + + private static void assertBlastsStoppedBy(Block block) { + Board board = createBoard(block); + List players = createPlayers(); + + // Create blast in direction of the center cell + List> singleBlast = + singletonList(Sq.iterate(POS_CENTER.neighbor(Direction.W), q -> q.neighbor(Direction.E))); + + GameState gameState = new GameState(0, board, players, emptyList(), emptyList(), + singleBlast); + + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(1, gameState.blastedCells().size()); + assertTrue(gameState.blastedCells().contains(POS_CENTER)); + + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(0, gameState.blastedCells().size()); + } + + @Test + public void xAssertEqualsCorrectlyAssert() { + GameState ig1 = new GameState(createBoard(), createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + GameState ig2 = new GameState(createBoard(), createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + GameState ig3 = new GameState(createBoard(), createPlayers(3, 1, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + GameState ig4 = new GameState(createBoard(), createPlayers(2, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + GameState ig5 = new GameState(createBoard(), createPlayers(3, 2, 2, POS_NW, POS_NE, POS_SE, POS_SW)); + GameState ig6 = new GameState(createBoard(), createPlayers(3, 2, 3, POS_NE, POS_NW, POS_SE, POS_SW)); + GameState ig7 = new GameState(createBoard(Block.FREE), createPlayers(3, 2, 3, POS_NE, POS_NW, POS_SE, POS_SW)); + xAssertEquals(ig1, ig2); + xAssertNotEquals(ig1, ig3); + xAssertNotEquals(ig1, ig4); + xAssertNotEquals(ig1, ig5); + xAssertNotEquals(ig1, ig6); + xAssertNotEquals(ig1, ig7); + } + + @Test + public void bombedCellsIsWorking() { + GameState ig1 = new GameState(createBoard(), createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + assertTrue(ig1.bombedCells().isEmpty()); + + GameState ig2 = new GameState(0, createBoard(), createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW), + createBombs(), emptyList(), emptyList()); + assertEquals(new HashSet<>(CELLS), ig2.bombedCells().keySet()); + } + + @Test + public void bombedCellsImmutable() { + List bombs = createBombs(); + GameState ig = new GameState(0, createBoard(), createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW), bombs, + emptyList(), emptyList()); + Map bombedCells1 = ig.bombedCells(); + bombs.remove(0); + Map bombedCells2 = ig.bombedCells(); + assertEquals(bombedCells1, bombedCells2); + } + + @Test + public void blastedCellsIsWorking() { + GameState ig1 = new GameState(createBoard(), createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + assertTrue(ig1.blastedCells().isEmpty()); + + GameState ig2 = new GameState(0, createBoard(), createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW), + emptyList(), emptyList(), createBlasts()); + assertEquals(new HashSet<>(CELLS), ig2.blastedCells()); + } + + @Test + public void blastedCellsImmutable() { + List> blasts = createBlasts(); + GameState ig = new GameState(0, createBoard(), createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW), + emptyList(), emptyList(), blasts); + Set blastedCells1 = ig.blastedCells(); + blasts.remove(0); + Set blastedCells2 = ig.blastedCells(); + assertEquals(blastedCells1, blastedCells2); + } + + @Test + public void newlyDroppedBombed() { + Board board = createBoard(); + List players = createPlayers(); + GameState gameState = new GameState(board, players); + + Player droppingPlayer = players.get(0); + gameState = gameState.next(emptyMap(), singleton(droppingPlayer.id())); + + Map cellBombMap = gameState.bombedCells(); + assertEquals(1, cellBombMap.size()); + + Bomb droppedBomb = cellBombMap.get(droppingPlayer.position().containingCell()); + assertNotNull(droppedBomb); + assertEquals(droppedBomb.range(), droppingPlayer.bombRange()); + assertEquals(Ticks.BOMB_FUSE_TICKS - 1, droppedBomb.fuseLength()); + } + + @Test + public void cannotDropBombWhenDead() { + Board board = createBoard(Block.FREE); + List players = Arrays.asList(new Player(PlayerID.PLAYER_1, 0, POS_NE, 0, 3), + new Player(PlayerID.PLAYER_2, 1, POS_NW, 0, 3), new Player(PlayerID.PLAYER_3, 1, POS_SE, 0, 3), + new Player(PlayerID.PLAYER_4, 1, POS_SW, 0, 3)); + + GameState gameState = new GameState(board, players); + gameState = gameState.next(emptyMap(), singleton(PlayerID.PLAYER_1)); + + assertTrue(gameState.bombedCells().isEmpty()); + } + + @Test + public void cannotDropBombWhenMaxReached() { + Board board = createBoard(Block.FREE); + List players = createPlayers(); + + List existingBombs = new ArrayList<>(); + Player droppingPlayer = players.get(0); + for (int i = 0; i < droppingPlayer.maxBombs(); i++) { + existingBombs.add(new Bomb(droppingPlayer.id(), new Cell(i + 1, POS_CENTER.y()), 10, 3)); + } + + GameState gameState = new GameState(0, board, players, existingBombs, emptyList(), + emptyList()); + gameState = gameState.next(emptyMap(), singleton(droppingPlayer.id())); + + assertEquals(2, gameState.bombedCells().size()); + assertFalse(gameState.bombedCells().containsKey(droppingPlayer.position().containingCell())); + } + + @Test + public void bombToExplosion() { + Board board = createBoard(Block.FREE); // The bomb should live during 2 + // ticks Bomb bomb + Bomb bomb = new Bomb(PlayerID.PLAYER_1, POS_CENTER, 2, 2); + + GameState gameState = new GameState(0, board, createPlayers(), singletonList(bomb), + emptyList(), emptyList()); + + Collection result = gameState.bombedCells().values(); + assertEquals(1, result.size()); + xAssertEquals(bomb, result.iterator().next()); + + gameState = gameState.next(emptyMap(), emptySet()); + result = gameState.bombedCells().values(); + assertEquals(1, result.size()); + xAssertEquals(bombDecreased(bomb), result.iterator().next()); + + gameState = gameState.next(emptyMap(), emptySet()); + result = gameState.bombedCells().values(); + assertEquals(0, result.size()); + + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(singleton(bomb.position()), gameState.blastedCells()); + + gameState = gameState.next(emptyMap(), emptySet()); + + Set centerNeighbors = Stream.of(Direction.values()).map(POS_CENTER::neighbor).collect(toSet()); + + centerNeighbors.add(POS_CENTER); + assertEquals(centerNeighbors, gameState.blastedCells()); + + for (int i = 0; i <= Ticks.EXPLOSION_TICKS - 3; ++i) { + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(centerNeighbors, gameState.blastedCells()); + } + + gameState = gameState.next(emptyMap(), emptySet()); + + centerNeighbors.remove(POS_CENTER); + assertEquals(centerNeighbors, gameState.blastedCells()); + + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(emptySet(), gameState.blastedCells()); + } + + @Test + public void cannotDropBombWhenCellOccupied() { + Board board = createBoard(Block.FREE); + List players = createPlayers(); + + Player droppingPlayer = players.get(0); + Player otherPlayer = players.get(1); + + List existingBombs = + singletonList(new Bomb(otherPlayer.id(), droppingPlayer.position().containingCell(), 3, 3)); + + GameState gameState = new GameState(0, board, players, existingBombs, emptyList(), + emptyList()); + gameState = gameState.next(emptyMap(), singleton(droppingPlayer.id())); + + assertEquals(1, gameState.bombedCells().size()); + assertEquals(otherPlayer.id(), + gameState.bombedCells().get(droppingPlayer.position().containingCell()).ownerId()); + } + + @Test + public void wallCrumblesWhenHit() { + Board board = createBoard(Block.DESTRUCTIBLE_WALL); + List players = createPlayers(); + + Cell centerNeighbor = POS_CENTER.neighbor(Direction.W); + + // Create blast in direction of the center cell + List> singleBlast = + singletonList(Sq.iterate(centerNeighbor, q -> q.neighbor(Direction.E))); + + GameState gameState = new GameState(0, board, players, emptyList(), emptyList(), + singleBlast); + + assertEquals(Block.DESTRUCTIBLE_WALL, gameState.board().blockAt(POS_CENTER)); + for (int i = 0; i < Ticks.WALL_CRUMBLING_TICKS; i++) { + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(Block.CRUMBLING_WALL, gameState.board().blockAt(POS_CENTER)); + } + + gameState = gameState.next(emptyMap(), emptySet()); + + Set possibleBlocks = asSet(Block.BONUS_BOMB, Block.BONUS_RANGE, Block.FREE); + assertTrue(possibleBlocks.contains(gameState.board().blockAt(POS_CENTER))); + } + + @Test + public void bonusBombDisappearsPlayer() { + bonusDisappearsPlayer(Block.BONUS_BOMB); + } + + @Test + public void bonusRangeDisappearsPlayer() { + bonusDisappearsPlayer(Block.BONUS_RANGE); + } + + @Test + public void bonusBombDisappearsBlast() { + bonusDisappearsBlast(Block.BONUS_BOMB); + } + + @Test + public void bonusRangeDisappearsBlast() { + bonusDisappearsBlast(Block.BONUS_RANGE); + } + + /* + * This test is ignored as it uses some feature of step 6 that we do not want to test yet + * Remove Ignore and add test if you want to + */ + @Ignore + public void bonusBombDisappearsPlayerBeforeBlast() { + bonusDisappearsPlayerBeforeBlast(Block.BONUS_BOMB); + } + + @Ignore + public void bonusRangeDisappearsPlayerBeforeBlast() { + bonusDisappearsPlayerBeforeBlast(Block.BONUS_RANGE); + } + + @Test + public void droppedBombConflictNotOnlySamePlayer() { + Board board = createBoard(Block.FREE); + List players = Arrays.asList(new Player(PlayerID.PLAYER_1, 30, POS_CENTER, 10, 3), + new Player(PlayerID.PLAYER_2, 30, POS_CENTER, 10, 3), + new Player(PlayerID.PLAYER_3, 30, POS_CENTER, 10, 3), + new Player(PlayerID.PLAYER_4, 30, POS_CENTER, 10, 3)); + + List bombsDropped = new ArrayList<>(); + Set bombEvents = asSet(PlayerID.values()); + + GameState gameState; + + int fact = IntStream.range(1, players.size() + 1).reduce(1, (x, y) -> x * y); + + for (int i = 1; i <= fact * 100; ++i) { + gameState = new GameState(i - 1, board, players, emptyList(), emptyList(), + emptyList()); + assertEquals(0, gameState.bombedCells().size()); + gameState = gameState.next(emptyMap(), bombEvents); + assertEquals(1, gameState.bombedCells().size()); + bombsDropped.add(gameState.bombedCells().values().iterator().next().ownerId()); + } + + // Remember : in a set all the elements are unique, if the size of the + // given set is 1, then we can be sure that the bombs were dropped in a fair way + assertEquals(1, asSet(PlayerID.values()).stream().map(p -> bombsDropped.stream().filter(p2 -> p2 == p).count()) + .collect(toSet()).size()); + } + + + @Test + public void blastsMoveCorrectly() { + Board board = createBoard(Block.FREE); + List players = createPlayers(); + + // Create a single blast + int blastRange = 5; + Direction blastDirection = Direction.E; + Cell blastStartPosition = POS_CENTER; + + List> singleBlast = + singletonList(Sq.iterate(blastStartPosition, q -> q.neighbor(blastDirection)).limit(blastRange)); + + // Create a game state with a single blast + GameState gameState = new GameState(0, board, players, emptyList(), emptyList(), + singleBlast); + + // The blast should move at each tick + Cell nextExpectedPos = blastStartPosition; + for (int i = 0; i < blastRange; i++) { + assertEquals(1, gameState.blastedCells().size()); + assertTrue(gameState.blastedCells().contains(nextExpectedPos)); + + gameState = gameState.next(emptyMap(), emptySet()); + nextExpectedPos = nextExpectedPos.neighbor(blastDirection); + } + + // Eventually the blast should disappears + assertEquals(0, gameState.blastedCells().size()); + } + + @Test + public void blastsStoppedByWalls() { + Set blockingBlocks = asSet(Block.BONUS_BOMB, Block.BONUS_RANGE, Block.CRUMBLING_WALL, + Block.DESTRUCTIBLE_WALL, Block.INDESTRUCTIBLE_WALL); + + blockingBlocks.forEach(b -> assertBlastsStoppedBy(b)); + } + + @Test + public void completeEvolutionOfExplosion() { + Board board = createBoard(Block.FREE); + int bombRange = 5; + List players = Arrays.asList(new Player(PlayerID.PLAYER_1, 3, POS_CENTER, 1, bombRange), + new Player(PlayerID.PLAYER_2, 3, POS_NW, 0, 3), new Player(PlayerID.PLAYER_3, 3, POS_SE, 0, 3), + new Player(PlayerID.PLAYER_4, 3, POS_SW, 0, 3)); + + GameState gameState = new GameState(0, board, players, emptyList(), emptyList(), + emptyList()); + + // First step : the bomb consumes its fuse length + for (int i = 1; i < Ticks.BOMB_FUSE_TICKS; ++i) { + gameState = gameState.next(emptyMap(), asSet(PlayerID.PLAYER_1)); + assertEquals(1, gameState.bombedCells().size()); + assertEquals(0, gameState.blastedCells().size()); + xAssertEquals(new Bomb(PlayerID.PLAYER_1, POS_CENTER, Ticks.BOMB_FUSE_TICKS - i, bombRange), gameState.bombedCells().values().iterator().next()); + } + + // We create here the successive positions of the blasts + // (for each direction, we store one arm of the explosion at the given tick) + Map>> neigbors = new HashMap<>(); + for (Direction d : Direction.values()) { + UnaryOperator> addToSet = u -> addToSet(u, u.stream().map(c -> c.neighbor(d)).collect(toSet())); + Sq> cells = Sq.iterate(asSet(POS_CENTER), addToSet).limit(bombRange); + + Set maxCells = cells.findFirst(s -> s.size() == bombRange); + cells = cells.concat(Sq.repeat(Ticks.EXPLOSION_TICKS - bombRange, maxCells)); + cells = cells.concat(Sq.repeat(1, removeFromSet(maxCells, cells.head()))); + cells = cells.concat(Sq.repeat(1, removeFromSet(maxCells, cells.tail().head()))); + cells = cells.concat(Sq.repeat(1, removeFromSet(maxCells, cells.tail().tail().head()))); + cells = cells.concat(Sq.repeat(1, removeFromSet(maxCells, cells.tail().tail().tail().head()))); + cells = cells.concat(Sq.repeat(1, removeFromSet(maxCells, cells.tail().tail().tail().tail().head()))); + neigbors.put(d, cells); + } + + gameState = gameState.next(emptyMap(), emptySet()); + + // Second step : the bomb disappears and the blasts appear + for (int i = 0; i < Ticks.EXPLOSION_TICKS + bombRange; ++i) { + gameState = gameState.next(emptyMap(), emptySet()); + assertEquals(0, gameState.bombedCells().size()); + + Set cells = new HashSet<>(); + for (Map.Entry>> entry : neigbors.entrySet()) { + cells.addAll(entry.getValue().head()); + neigbors.put(entry.getKey(), entry.getValue().tail()); + } + assertEquals(cells, gameState.blastedCells()); + } + + assertEquals(0, gameState.bombedCells().size()); + assertEquals(0, gameState.blastedCells().size()); + } + +} diff --git a/test/ch/epfl/xblast/GameStateTestUtils.java b/test/ch/epfl/xblast/GameStateTestUtils.java new file mode 100644 index 0000000..dfced4e --- /dev/null +++ b/test/ch/epfl/xblast/GameStateTestUtils.java @@ -0,0 +1,119 @@ +package ch.epfl.xblast; + +import ch.epfl.cs108.Sq; +import ch.epfl.xblast.server.Board; +import ch.epfl.xblast.server.Bomb; +import ch.epfl.xblast.server.GameState; +import ch.epfl.xblast.server.Player; +import org.junit.Assert; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.stream.IntStream; + +import static org.junit.Assert.*; + +/** + * @author EPFL + */ +public class GameStateTestUtils { + + private static final int SQ_CHECK_COUNT = 1000; + + public static void xAssertEquals(Sq expected, Sq given, BiConsumer equals) { + for (int i = 0; i < SQ_CHECK_COUNT && !expected.isEmpty() && !given.isEmpty(); ++i) { + equals.accept(expected.head(), given.head()); + expected = expected.tail(); + given = given.tail(); + } + assertEquals(expected.isEmpty(), given.isEmpty()); + } + + public static void xAssertEquals(Board expected, Board given) { + Cell.ROW_MAJOR_ORDER.forEach(c -> xAssertEquals(expected.blocksAt(c), given.blocksAt(c), Assert::assertEquals)); + } + + public static void xAssertEquals(Player.LifeState expected, Player.LifeState given) { + assertEquals(expected.state(), given.state()); + assertEquals(expected.lives(), given.lives()); + } + + public static void xAssertEquals(Player.DirectedPosition expected, Player.DirectedPosition given) { + assertEquals(expected.direction(), given.direction()); + assertEquals(expected.position(), given.position()); + } + + public static void xAssertEquals(Player expected, Player given) { + assertEquals(expected.id(), given.id()); + xAssertEquals(expected.lifeStates(), given.lifeStates(), GameStateTestUtils::xAssertEquals); + assertEquals(expected.lives(), given.lives()); + xAssertEquals(expected.directedPositions(), given.directedPositions(), GameStateTestUtils::xAssertEquals); + assertEquals(expected.maxBombs(), given.maxBombs()); + assertEquals(expected.bombRange(), given.bombRange()); + } + + public static void xAssertEquals(List expected, List given, BiConsumer equals) { + assertEquals(expected.size(), given.size()); + IntStream.range(0, expected.size()).forEach(i -> equals.accept(expected.get(i), given.get(i))); + } + + public static void xAssertEquals(Map expected, Map given, BiConsumer equals) { + assertEquals(expected.size(), given.size()); + expected.forEach((k, v) -> { + assertTrue(given.containsKey(k)); // need key hashcode redefinition + equals.accept(v, given.get(k)); + }); + } + + public static void xAssertEquals(Bomb expected, Bomb given) { + assertEquals(expected.ownerId(), given.ownerId()); + assertEquals(expected.position(), given.position()); + xAssertEquals(expected.fuseLengths(), given.fuseLengths(), Assert::assertEquals); + assertEquals(expected.range(), given.range()); + } + + public static void xAssertEquals(GameState expected, GameState given) { + assertEquals(expected.ticks(), given.ticks()); + assertEquals(expected.winner(), given.winner()); + xAssertEquals(expected.board(), given.board()); + xAssertEquals(expected.players(), given.players(), GameStateTestUtils::xAssertEquals); + xAssertEquals(expected.alivePlayers(), given.alivePlayers(), GameStateTestUtils::xAssertEquals); + xAssertEquals(expected.bombedCells(), given.bombedCells(), GameStateTestUtils::xAssertEquals); + assertTrue(expected.blastedCells().containsAll(given.blastedCells())); + } + + public static void xAssertNotEquals(GameState expected, GameState given) { + boolean failing = true; + try { + xAssertEquals(expected, given); + failing = false; + } catch (AssertionError ignored) { + } + if (!failing) { + fail(); + } + } + + public static Bomb bombDecreased(Bomb b) { + return new Bomb(b.ownerId(), b.position(), b.fuseLength() - 1, b.range()); + } + + @SafeVarargs + public static Set asSet(T... t) { + return new HashSet<>(Arrays.asList(t)); + } + + public static Set addToSet(Set to, Set add) { + Set tmp = new HashSet<>(to); + tmp.addAll(add); + return Collections.unmodifiableSet(tmp); + } + + + public static Set removeFromSet(Set from, Set remove) { + Set tmp = new HashSet<>(from); + tmp.removeAll(remove); + return Collections.unmodifiableSet(tmp); + } + +} diff --git a/test/ch/epfl/xblast/ListsTests.java b/test/ch/epfl/xblast/ListsTests.java new file mode 100644 index 0000000..6a81f28 --- /dev/null +++ b/test/ch/epfl/xblast/ListsTests.java @@ -0,0 +1,105 @@ +package ch.epfl.xblast; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +/** + * @author EPFL + */ +public class ListsTests { + + @Test(expected = IllegalArgumentException.class) + public void mirroredThrowsExceptionOnEmptyList() { + Lists.mirrored(Collections.emptyList()); + } + + @Test + public void mirroredBehaviourIsCorrect() { + List aibohp = stringToList("aibohp"); + List detart = stringToList("detart"); + List delev = stringToList("delev"); + List race = stringToList("race"); + + + assertEquals(stringToList("aibohphobia"), Lists.mirrored(aibohp)); + assertEquals(stringToList("detartrated"), Lists.mirrored(detart)); + assertEquals(stringToList("deleveled"), Lists.mirrored(delev)); + assertEquals(stringToList("racecar"), Lists.mirrored(race)); + } + + @Test + public void singletonListMirroredRemainsUnchanged() { + List a = Collections.singletonList('a'); + assertEquals(a, Lists.mirrored(new ArrayList<>(a))); + } + + @Test + public void permutationsOnEmptyListIsCorrect() { + assertEquals(Collections.singletonList(Collections.emptyList()), + Lists.permutations(new ArrayList<>())); + } + + @Test + public void permutationsOnSingleElementIsCorrect() { + assertEquals(Collections.singletonList(Collections.singletonList(1)), + Lists.permutations(new ArrayList<>(Collections.singletonList(1)))); + } + + @Test + public void permutationsOnTwoElementsIsCorrect() { + List l = Arrays.asList(1, 2); + Set> s = new HashSet<>(Arrays.asList( + Arrays.asList(1, 2), + Arrays.asList(2, 1) + ) + ); + + assertEquals(s, new HashSet<>(Lists.permutations(new ArrayList<>(l)))); + } + + @Test + public void permutationsOnMoreElementsIsCorrect() { + List l = Arrays.asList(1, 2, 3, 4); + Set> s = new HashSet<>(Arrays.asList( + Arrays.asList(1, 2, 3, 4), + Arrays.asList(1, 2, 4, 3), + Arrays.asList(1, 3, 2, 4), + Arrays.asList(1, 3, 4, 2), + Arrays.asList(1, 4, 2, 3), + Arrays.asList(1, 4, 3, 2), + Arrays.asList(2, 1, 3, 4), + Arrays.asList(2, 1, 4, 3), + Arrays.asList(2, 3, 1, 4), + Arrays.asList(2, 3, 4, 1), + Arrays.asList(2, 4, 1, 3), + Arrays.asList(2, 4, 3, 1), + Arrays.asList(3, 1, 2, 4), + Arrays.asList(3, 1, 4, 2), + Arrays.asList(3, 2, 1, 4), + Arrays.asList(3, 2, 4, 1), + Arrays.asList(3, 4, 1, 2), + Arrays.asList(3, 4, 2, 1), + Arrays.asList(4, 1, 2, 3), + Arrays.asList(4, 1, 3, 2), + Arrays.asList(4, 2, 1, 3), + Arrays.asList(4, 2, 3, 1), + Arrays.asList(4, 3, 1, 2), + Arrays.asList(4, 3, 2, 1) + ) + ); + + assertEquals(s, new HashSet<>(Lists.permutations(new ArrayList<>(l)))); + } + + private List stringToList(String s) { + List l = new ArrayList<>(); + for (int i = 0; i < s.length(); ++i) { + l.add(s.charAt(i)); + } + return l; + } + +} diff --git a/test/ch/epfl/xblast/SubCellTest.java b/test/ch/epfl/xblast/SubCellTest.java index b3450e1..f4cbc3b 100644 --- a/test/ch/epfl/xblast/SubCellTest.java +++ b/test/ch/epfl/xblast/SubCellTest.java @@ -2,8 +2,7 @@ package ch.epfl.xblast; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * @author EPFL @@ -62,4 +61,73 @@ public class SubCellTest { } } + @Test + public void equalsCorrect() { + SubCell c1 = new SubCell(0, 0); + SubCell c2 = new SubCell(0, 1); + SubCell c4 = new SubCell(1, 0); + SubCell c3 = new SubCell(0, 0); + assertFalse(c1.equals(c2)); + assertFalse(c1.equals(c4)); + assertFalse(c4.equals(c2)); + assertTrue(c1.equals(c3)); + } + + @Test + public void neighborOfCornerCorrect() { + SubCell NE = new SubCell(239, 0); + SubCell NW = new SubCell(0, 0); + SubCell SE = new SubCell(239, 207); + SubCell SW = new SubCell(0, 207); + + assertEquals(new SubCell(0, 207), NW.neighbor(Direction.N)); + assertEquals(new SubCell(1, 0), NW.neighbor(Direction.E)); + assertEquals(new SubCell(0, 1), NW.neighbor(Direction.S)); + assertEquals(new SubCell(239, 0), NW.neighbor(Direction.W)); + + assertEquals(SE, NE.neighbor(Direction.N)); + assertEquals(NW, NE.neighbor(Direction.E)); + assertEquals(new SubCell(239, 1), NE.neighbor(Direction.S)); + assertEquals(new SubCell(238, 0), NE.neighbor(Direction.W)); + + assertEquals(new SubCell(0, 206), SW.neighbor(Direction.N)); + assertEquals(new SubCell(1, 207), SW.neighbor(Direction.E)); + assertEquals(NW, SW.neighbor(Direction.S)); + assertEquals(SE, SW.neighbor(Direction.W)); + + assertEquals(new SubCell(239, 206), SE.neighbor(Direction.N)); + assertEquals(SW, SE.neighbor(Direction.E)); + assertEquals(NE, SE.neighbor(Direction.S)); + assertEquals(new SubCell(238, 207), SE.neighbor(Direction.W)); + } + + @Test + public void distanceToCentralOfSomeSubCellIsCorrect() { + assertEquals(10, new SubCell(0, 10).distanceToCentral()); + assertEquals(5, new SubCell(5, 10).distanceToCentral()); + assertEquals(4, new SubCell(10, 10).distanceToCentral()); + assertEquals(9, new SubCell(15, 10).distanceToCentral()); + assertEquals(11, new SubCell(0, 5).distanceToCentral()); + assertEquals(6, new SubCell(5, 5).distanceToCentral()); + assertEquals(9, new SubCell(10, 15).distanceToCentral()); + } + + @Test + public void isCentralOfFirstCellIsCorrect() { + for (int i = 0; i < 16; ++i) { + for (int j = 0; j < 16; ++j) { + if (i == 8 && j == 8) assertTrue(new SubCell(i, j).isCentral()); + else assertFalse(new SubCell(i, j).isCentral()); + } + } + } + + @Test + public void borderCaseOfContainingCell() { + assertEquals(new Cell(0, 0), new SubCell(15, 15).containingCell()); + assertEquals(new Cell(1, 1), new SubCell(16, 16).containingCell()); + assertEquals(new Cell(0, 1), new SubCell(15, 16).containingCell()); + assertEquals(new Cell(1, 0), new SubCell(16, 15).containingCell()); + } + } diff --git a/test/ch/epfl/xblast/SubCellTest05.java b/test/ch/epfl/xblast/SubCellTest05.java new file mode 100644 index 0000000..dd4386c --- /dev/null +++ b/test/ch/epfl/xblast/SubCellTest05.java @@ -0,0 +1,27 @@ +package ch.epfl.xblast; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author EPFL + */ +public class SubCellTest05 { + + private static final int SUBDIVISIONS = 16; + + @Test + public void hashCodeSubCellsConsistentWithEquals() { + for (int i = 0; i < Cell.COLUMNS * SUBDIVISIONS; i++) { + for (int j = 0; j < Cell.ROWS * SUBDIVISIONS; j++) { + SubCell c1 = new SubCell(i, j); + SubCell c2 = new SubCell(i, j); + if (c1.equals(c2)) { + assertEquals(c1.hashCode(), c2.hashCode()); + } + } + } + } + +} diff --git a/test/ch/epfl/xblast/TestEtape4.java b/test/ch/epfl/xblast/TestEtape4.java new file mode 100644 index 0000000..e1c14cd --- /dev/null +++ b/test/ch/epfl/xblast/TestEtape4.java @@ -0,0 +1,332 @@ +package ch.epfl.xblast; + +import ch.epfl.cs108.Sq; +import ch.epfl.xblast.server.*; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.BiConsumer; + +import static org.junit.Assert.*; + +/** + * @author EPFL + */ +public class TestEtape4 { + + private static final Cell POS_NW = new Cell(1, 1); + private static final Cell POS_NE = new Cell(-2, 1); + private static final Cell POS_SE = new Cell(-2, -2); + private static final Cell POS_SW = new Cell(1, -2); + + private static Board createBoard() { + Block __ = Block.FREE; + Block XX = Block.INDESTRUCTIBLE_WALL; + Block xx = Block.DESTRUCTIBLE_WALL; + return Board.ofQuadrantNWBlocksWalled( + Arrays.asList( + Arrays.asList(__, __, __, __, __, xx, __), + Arrays.asList(__, XX, xx, XX, xx, XX, xx), + Arrays.asList(__, xx, __, __, __, xx, __), + Arrays.asList(xx, XX, __, XX, XX, XX, XX), + Arrays.asList(__, xx, __, xx, __, __, __), + Arrays.asList(xx, XX, xx, XX, xx, XX, __))); + } + + private static List createPlayers(int lives, int maxBombs, int bombRange, Cell p1, Cell p2, Cell p3, Cell p4) { + return Arrays.asList( + new Player(PlayerID.PLAYER_1, lives, p1, maxBombs, bombRange), + new Player(PlayerID.PLAYER_2, lives, p2, maxBombs, bombRange), + new Player(PlayerID.PLAYER_3, lives, p3, maxBombs, bombRange), + new Player(PlayerID.PLAYER_4, lives, p4, maxBombs, bombRange)); + } + + private static GameState createGameState(int tick) { + List players = new ArrayList<>(createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + return new GameState(tick, + createBoard(), + players, + new ArrayList<>(), + new ArrayList<>(), + new ArrayList<>()); + } + + @Test + public void testApplyBombBonus() { + Player p = new Player(PlayerID.PLAYER_1, 3, new Cell(1, 1), 2, 3); + int oldBombs = p.maxBombs(); + Bonus b = Bonus.INC_BOMB; + + p = b.applyTo(p); + assertEquals("Bomb bonus should increase maxBombs by one", oldBombs + 1, p.maxBombs()); + } + + @Test + public void testMaxBomb() { + Player p = new Player(PlayerID.PLAYER_1, 3, new Cell(1, 1), 2, 3); + + Bonus b = Bonus.INC_BOMB; + + p = b.applyTo(p); + for (int i = 0; i < 10; i++) { + p = b.applyTo(p); + } + + assertEquals("Max bombs can't be greater than 9", 9, p.maxBombs()); + } + + @Test + public void testApplyRangeBonus() { + Player p = new Player(PlayerID.PLAYER_1, 3, new Cell(1, 1), 2, 3); + int oldRange = p.bombRange(); + Bonus b = Bonus.INC_RANGE; + + p = b.applyTo(p); + assertEquals("Range bonus should increase range by one", oldRange + 1, p.bombRange()); + } + + @Test + public void testMaxRange() { + Player p = new Player(PlayerID.PLAYER_1, 3, new Cell(1, 1), 2, 3); + Bonus b = Bonus.INC_RANGE; + + p = b.applyTo(p); + for (int i = 0; i < 10; i++) { + p = b.applyTo(p); + } + + assertEquals("Max range can't be greater than 9", 9, p.bombRange()); + } + + @Test + public void testIsBonus() { + for (Block block : Block.values()) { + switch (block) { + case BONUS_BOMB: + case BONUS_RANGE: + assertTrue("isBonus on bonus should be true", block.isBonus()); + break; + default: + assertFalse("isBonus on non bonus should be false", block.isBonus()); + + } + } + } + + /* + // Team 2 is doing those tests + @Test(expected = NoSuchElementException.class) + public void testNonAssociatedBonus() { + + } + + public void testAssociatedBonus() { + + } + + @Test + public void testCanHostPlayerBonus() { + + } + */ + + @Test + public void testTimeEnum() { + assertEquals(Time.S_PER_MIN, 60); + assertEquals(Time.MS_PER_S, 1_000); + assertEquals(Time.US_PER_S, 1_000 * 1_000); + assertEquals(Time.NS_PER_S, 1_000 * 1_000 * 1_000); + } + + @Test(expected = IllegalArgumentException.class) + public void testGameStateNegativeTick() { + new GameState(-1, + createBoard(), + createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW), + new ArrayList<>(), + new ArrayList<>(), + new ArrayList<>()); + } + + private void constructGameState(List players) { + new GameState(0, + createBoard(), + players, + new ArrayList<>(), + new ArrayList<>(), + new ArrayList<>()); + } + + @Test(expected = IllegalArgumentException.class) + public void testGameStateLess4Players() { + List p = new ArrayList<>(createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + p.remove(0); + constructGameState(p); + } + + @Test(expected = IllegalArgumentException.class) + public void testGameStateGreater4Players() { + List p = new ArrayList<>(createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + p.add(new Player(PlayerID.PLAYER_1, 3, new Cell(1, 1), 2, 3)); + constructGameState(p); + } + + @Test(expected = NullPointerException.class) + public void testGameStateNullBoard() { + List p = new ArrayList<>(createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + new GameState(0, + null, + p, + new ArrayList<>(), + new ArrayList<>(), + new ArrayList<>()); + } + + @Test(expected = NullPointerException.class) + public void testGameStateNullPlayers() { + new GameState(0, + createBoard(), + null, + new ArrayList<>(), + new ArrayList<>(), + new ArrayList<>()); + } + + @Test(expected = NullPointerException.class) + public void testGameStateNullBombs() { + List p = new ArrayList<>(createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + new GameState(0, + createBoard(), + p, + null, + new ArrayList<>(), + new ArrayList<>()); + } + + @Test(expected = NullPointerException.class) + public void testGameStateNullExplosions() { + List p = new ArrayList<>(createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + new GameState(0, + createBoard(), + p, + new ArrayList<>(), + null, + new ArrayList<>()); + } + + @Test(expected = NullPointerException.class) + public void testGameStateNullBlasts() { + List p = new ArrayList<>(createPlayers(3, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + new GameState(0, + createBoard(), + p, + new ArrayList<>(), + new ArrayList<>(), + null); + } + + // GameState methods + @Test + public void testIsGameOverDead() { + List players = new ArrayList<>(createPlayers(0, 2, 3, POS_NW, POS_NE, POS_SE, POS_SW)); + players.remove(0); + players.add(new Player(PlayerID.PLAYER_1, 3, new Cell(1, 1), 2, 3)); + GameState game = new GameState(0, + createBoard(), + players, + new ArrayList<>(), + new ArrayList<>(), + new ArrayList<>()); + assertTrue("Game is over, as three players are dead", game.isGameOver()); + } + + @Test + public void testIsGameOverTime() { + GameState game = createGameState(Ticks.TOTAL_TICKS + 1); + assertTrue("Game is over, because of timeout", game.isGameOver()); + } + + @Test + public void testRemainingTime() { + for (int i = 0; i < Ticks.TOTAL_TICKS; i += 10) { + GameState state = createGameState(i); + assertEquals((double) (Ticks.TOTAL_TICKS - i) / Ticks.TICKS_PER_SECOND, state.remainingTime(), 1); + } + } + + @Test + publ