diff options
-rw-r--r-- | src/ch/epfl/xblast/Direction.java | 19 | ||||
-rw-r--r-- | src/ch/epfl/xblast/server/Board.java | 17 | ||||
-rw-r--r-- | src/ch/epfl/xblast/server/GameState.java | 353 | ||||
-rw-r--r-- | src/ch/epfl/xblast/server/Player.java | 22 | ||||
-rw-r--r-- | src/ch/epfl/xblast/server/Ticks.java | 2 | ||||
-rw-r--r-- | src/ch/epfl/xblast/server/debug/GameStatePrinter.java | 78 | ||||
-rw-r--r-- | src/ch/epfl/xblast/server/debug/RandomEventGenerator.java | 50 | ||||
-rw-r--r-- | test/ch/epfl/xblast/server/BoardTest.java | 21 | ||||
-rw-r--r-- | test/ch/epfl/xblast/simulation/RandomSimulation.java | 80 |
9 files changed, 516 insertions, 126 deletions
diff --git a/src/ch/epfl/xblast/Direction.java b/src/ch/epfl/xblast/Direction.java index 030038b..e2df042 100644 --- a/src/ch/epfl/xblast/Direction.java +++ b/src/ch/epfl/xblast/Direction.java | |||
@@ -68,6 +68,25 @@ public enum Direction { | |||
68 | } | 68 | } |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * T(the current and given Directions are perpendicular). | ||
72 | * | ||
73 | * @param that a Direction to compare | ||
74 | * @return T(the current and given Directions are perpendicular) | ||
75 | */ | ||
76 | public boolean isPerpendicularTo(Direction that) { | ||
77 | switch (this) { | ||
78 | case N: | ||
79 | case S: | ||
80 | return that == E || that == W; | ||
81 | case E: | ||
82 | case W: | ||
83 | return that == N || that == S; | ||
84 | default: | ||
85 | return false; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | /** | ||
71 | * Returns the x-coordinate of the normed vector representation of the Direction. | 90 | * Returns the x-coordinate of the normed vector representation of the Direction. |
72 | * | 91 | * |
73 | * @return the x-coordinate | 92 | * @return the x-coordinate |
diff --git a/src/ch/epfl/xblast/server/Board.java b/src/ch/epfl/xblast/server/Board.java index f2a3c89..79259b5 100644 --- a/src/ch/epfl/xblast/server/Board.java +++ b/src/ch/epfl/xblast/server/Board.java | |||
@@ -5,6 +5,7 @@ import ch.epfl.xblast.Cell; | |||
5 | import ch.epfl.xblast.Lists; | 5 | import ch.epfl.xblast.Lists; |
6 | 6 | ||
7 | import java.util.ArrayList; | 7 | import java.util.ArrayList; |
8 | import java.util.Collections; | ||
8 | import java.util.List; | 9 | import java.util.List; |
9 | 10 | ||
10 | /** | 11 | /** |
@@ -15,6 +16,11 @@ import java.util.List; | |||
15 | */ | 16 | */ |
16 | public final class Board { | 17 | public final class Board { |
17 | 18 | ||
19 | /** | ||
20 | * Distance (in SubCells) from a bomb to block a player. | ||
21 | */ | ||
22 | public static final int BOMB_BLOCKING_DISTANCE = 6; | ||
23 | |||
18 | private static final int BLOCKS_LIST_SIZE = 195; | 24 | private static final int BLOCKS_LIST_SIZE = 195; |
19 | private static final int BOARD_ROWS = 13; | 25 | private static final int BOARD_ROWS = 13; |
20 | private static final int BOARD_COLUMNS = 15; | 26 | private static final int BOARD_COLUMNS = 15; |
@@ -44,7 +50,6 @@ public final class Board { | |||
44 | * List containing all the blocks of the board. | 50 | * List containing all the blocks of the board. |
45 | */ | 51 | */ |
46 | private List<Sq<Block>> blocks; | 52 | private List<Sq<Block>> blocks; |
47 | |||
48 | /** | 53 | /** |
49 | * Instantiates a new Board with the given sequence of blocks. | 54 | * Instantiates a new Board with the given sequence of blocks. |
50 | * | 55 | * |
@@ -55,7 +60,7 @@ public final class Board { | |||
55 | if (blocks == null || blocks.size() != BLOCKS_LIST_SIZE) | 60 | if (blocks == null || blocks.size() != BLOCKS_LIST_SIZE) |
56 | throw new IllegalArgumentException(); | 61 | throw new IllegalArgumentException(); |
57 | 62 | ||
58 | this.blocks = blocks; | 63 | this.blocks = new ArrayList<>(blocks); |
59 | } | 64 | } |
60 | 65 | ||
61 | /** | 66 | /** |
@@ -142,12 +147,4 @@ public final class Board { | |||
142 | return this.blocksAt(c).head(); | 147 | return this.blocksAt(c).head(); |
143 | } | 148 | } |
144 | 149 | ||
145 | /** | ||
146 | * Return the blocks of the Board. | ||
147 | * | ||
148 | * @return a list of the Sequences of blocks of the board. | ||
149 | */ | ||
150 | public List<Sq<Block>> getBlocks() { | ||
151 | return blocks; | ||
152 | } | ||
153 | } | 150 | } |
diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 1abe17a..0d381db 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java | |||
@@ -8,6 +8,7 @@ import java.util.function.Function; | |||
8 | import java.util.stream.Collectors; | 8 | import java.util.stream.Collectors; |
9 | import java.util.stream.Stream; | 9 | import java.util.stream.Stream; |
10 | 10 | ||
11 | |||
11 | /** | 12 | /** |
12 | * GameState representing the current game state. | 13 | * GameState representing the current game state. |
13 | * | 14 | * |
@@ -102,12 +103,14 @@ public final class GameState { | |||
102 | private static List<Sq<Cell>> nextBlasts(List<Sq<Cell>> blasts0, Board board0, List<Sq<Sq<Cell>>> explosions0) { | 103 | private static List<Sq<Cell>> nextBlasts(List<Sq<Cell>> blasts0, Board board0, List<Sq<Sq<Cell>>> explosions0) { |
103 | return Stream.concat( | 104 | return Stream.concat( |
104 | blasts0.stream() | 105 | blasts0.stream() |
105 | .filter(blastSeq -> !blastSeq.tail().isEmpty()) | 106 | .filter(b -> !b.tail().isEmpty()) |
106 | .filter(blastSeq -> board0.blockAt(blastSeq.head()).isFree()) | 107 | .filter(b -> board0.blockAt(b.head()).isFree()) |
107 | .map(Sq::tail), | 108 | .map(Sq::tail), |
108 | explosions0.stream() | 109 | explosions0.stream() |
110 | .filter(e -> !e.isEmpty()) | ||
109 | .map(Sq::head) | 111 | .map(Sq::head) |
110 | ).collect(Collectors.toList()); | 112 | .filter(b -> !b.isEmpty())) |
113 | .collect(Collectors.toList()); | ||
111 | } | 114 | } |
112 | 115 | ||
113 | /** | 116 | /** |
@@ -119,29 +122,36 @@ public final class GameState { | |||
119 | * @return the next board | 122 | * @return the next board |
120 | */ | 123 | */ |
121 | private static Board nextBoard(Board board0, Set<Cell> consumedBonuses, Set<Cell> blastedCells1) { | 124 | private static Board nextBoard(Board board0, Set<Cell> consumedBonuses, Set<Cell> blastedCells1) { |
122 | List<Sq<Block>> blocks0 = board0.getBlocks(); | 125 | return new Board(Cell.ROW_MAJOR_ORDER.stream() |
123 | List<Sq<Block>> blocks1 = new ArrayList<>(); | 126 | .map(c -> GameState.nextBlockSeq(c, board0.blocksAt(c), consumedBonuses, blastedCells1)) |
124 | 127 | .collect(Collectors.toList())); | |
125 | int i = 0; | 128 | } |
126 | for (Sq<Block> blockSq : blocks0) { | ||
127 | int cellId = blocks0.get(i).hashCode(); | ||
128 | Block block = blockSq.head(); | ||
129 | if (((HashSet) consumedBonuses).contains(cellId) && block.isBonus()) { | ||
130 | blocks1.add(Sq.constant(Block.FREE)); | ||
131 | } else if (((HashSet) blastedCells1).contains(cellId) && (block == Block.DESTRUCTIBLE_WALL || block.isBonus())) { | ||
132 | if (block == Block.DESTRUCTIBLE_WALL) { | ||
133 | Block bonus = randomBonus(); | ||
134 | blocks1.add(Sq.repeat(Ticks.WALL_CRUMBLING_TICKS, Block.CRUMBLING_WALL).concat(Sq.constant(bonus))); | ||
135 | } else { | ||
136 | blocks1.add(Sq.repeat(Ticks.BONUS_DISAPPEARING_TICKS, block).concat(Sq.constant(Block.FREE))); | ||
137 | } | ||
138 | } else { | ||
139 | blocks1.add(blockSq.tail()); | ||
140 | } | ||
141 | i++; | ||
142 | } | ||
143 | 129 | ||
144 | return new Board(blocks1); | 130 | /** |
131 | * Returns the next Block sequence for the given cell according to the current state and given events. | ||
132 | * | ||
133 | * @param c the Cell | ||
134 | * @param bs0 the previous Block sequence | ||
135 | * @param consumedBonuses the bonus consumption event | ||
136 | * @param blastedCells1 the new Cell blast events | ||
137 | * @return the new Block sequence | ||
138 | */ | ||
139 | private static Sq<Block> nextBlockSeq(Cell c, Sq<Block> bs0, Set<Cell> consumedBonuses, Set<Cell> blastedCells1) { | ||
140 | Block b = bs0.head(); | ||
141 | |||
142 | if (consumedBonuses.contains(c) && b.isBonus()) | ||
143 | return Sq.constant(Block.FREE); | ||
144 | |||
145 | if (blastedCells1.contains(c)) | ||
146 | if (b == Block.DESTRUCTIBLE_WALL) | ||
147 | return Sq.repeat(Ticks.WALL_CRUMBLING_TICKS, Block.CRUMBLING_WALL) | ||
148 | .concat(Sq.constant(GameState.randomBonus())); | ||
149 | |||
150 | else if (b.isBonus()) | ||
151 | return Sq.repeat(Ticks.BONUS_DISAPPEARING_TICKS, b) | ||
152 | .concat(Sq.constant(Block.FREE)); | ||
153 | |||
154 | return bs0.tail(); | ||
145 | } | 155 | } |
146 | 156 | ||
147 | /** | 157 | /** |
@@ -155,15 +165,142 @@ public final class GameState { | |||
155 | * @param speedChangeEvents the speed change events | 165 | * @param speedChangeEvents the speed change events |
156 | * @return the next player list | 166 | * @return the next player list |
157 | */ | 167 | */ |
158 | private static List<Player> nextPlayers( | 168 | private static List<Player> nextPlayers(List<Player> players0, Map<PlayerID, Bonus> playerBonuses, |
159 | List<Player> players0, | 169 | Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1, |
160 | Map<PlayerID, Bonus> playerBonuses, | 170 | Map<PlayerID, Optional<Direction>> speedChangeEvents) { |
161 | Set<Cell> bombedCells1, | 171 | |
162 | Board board1, | 172 | return players0.stream() |
163 | Set<Cell> blastedCells1, | 173 | .map(p -> { |
164 | Map<PlayerID, Optional<Direction>> speedChangeEvents) { | 174 | Optional<Direction> speedChangeEvent = speedChangeEvents.get(p.id()); |
165 | //ToDo | 175 | Direction requestedDirection = speedChangeEvent != null ? speedChangeEvent.orElse(null) : null; |
166 | return players0; | 176 | return GameState.nextPlayer(p, playerBonuses.get(p.id()), bombedCells1, board1, blastedCells1, requestedDirection); |
177 | }) | ||
178 | .collect(Collectors.toList()); | ||
179 | } | ||
180 | |||
181 | private static Player nextPlayer(Player players0, Bonus playerBonus, | ||
182 | Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1, | ||
183 | Direction requestedDirection) { | ||
184 | |||
185 | Sq<Player.DirectedPosition> directedPositions1 = GameState.nextPath(players0, requestedDirection); | ||
186 | |||
187 | // Advance of one SubCell on the player's path | ||
188 | directedPositions1 = directedPositions1.tail(); | ||