diff options
Diffstat (limited to 'src/ch')
-rw-r--r-- | src/ch/epfl/xblast/server/GameState.java | 200 | ||||
-rw-r--r-- | src/ch/epfl/xblast/server/Player.java | 11 |
2 files changed, 144 insertions, 67 deletions
diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index e75da1d..0d381db 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java | |||
@@ -165,72 +165,142 @@ public final class GameState { | |||
165 | * @param speedChangeEvents the speed change events | 165 | * @param speedChangeEvents the speed change events |
166 | * @return the next player list | 166 | * @return the next player list |
167 | */ | 167 | */ |
168 | private static List<Player> nextPlayers( | 168 | private static List<Player> nextPlayers(List<Player> players0, Map<PlayerID, Bonus> playerBonuses, |
169 | List<Player> players0, | 169 | Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1, |
170 | Map<PlayerID, Bonus> playerBonuses, | 170 | Map<PlayerID, Optional<Direction>> speedChangeEvents) { |
171 | Set<Cell> bombedCells1, | 171 | |
172 | Board board1, | 172 | return players0.stream() |
173 | Set<Cell> blastedCells1, | 173 | .map(p -> { |
174 | Map<PlayerID, Optional<Direction>> speedChangeEvents) { | 174 | Optional<Direction> speedChangeEvent = speedChangeEvents.get(p.id()); |
175 | List<Player> players1 = new ArrayList<>(); | 175 | Direction requestedDirection = speedChangeEvent != null ? speedChangeEvent.orElse(null) : null; |
176 | 176 | return GameState.nextPlayer(p, playerBonuses.get(p.id()), bombedCells1, board1, blastedCells1, requestedDirection); | |
177 | for (Player player0 : players0) { | 177 | }) |
178 | Optional<Direction> event = speedChangeEvents.get(player0.id()); | 178 | .collect(Collectors.toList()); |
179 | // By default the path won't change | 179 | } |
180 | Sq<Player.DirectedPosition> directedPositions1 = player0.directedPositions(); | 180 | |
181 | 181 | private static Player nextPlayer(Player players0, Bonus playerBonus, | |
182 | // Get the (possibly) requested direction | 182 | Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1, |
183 | Direction requestedDirection = null; | 183 | Direction requestedDirection) { |
184 | if (event != null) { | 184 | |
185 | requestedDirection = event.orElse(null); | 185 | Sq<Player.DirectedPosition> directedPositions1 = GameState.nextPath(players0, requestedDirection); |
186 | } | 186 | |
187 | 187 | // Advance of one SubCell on the player's path | |
188 | // Generate the new Sequence of Directed Positions (kinda ugly right now) | 188 | directedPositions1 = directedPositions1.tail(); |
189 | if (!player0.lifeState().canMove() && requestedDirection != null) { // if the player can't movex | 189 | |
190 | directedPositions1 = Player.DirectedPosition.stopped(player0.directedPositions().head()); | 190 | //Check possible collisions and update the Sequence if necessary (kinda ugly right now) |
191 | } else if (player0.direction().isParallelTo(requestedDirection)) { // if the player want to go to a parallel directionx | 191 | directedPositions1 = GameState.handleCollisions(players0, directedPositions1, board1, bombedCells1); |
192 | Player.DirectedPosition requestedDirectedPosition = new Player.DirectedPosition(player0.position(), requestedDirection); | 192 | |
193 | directedPositions1 = Player.DirectedPosition.moving(requestedDirectedPosition); | 193 | // Apply damages and generate a new LifeState Sequence |
194 | } else if (player0.direction().isPerpendicularTo(requestedDirection)) { // if the player want to go to a perpendicular direction | 194 | Sq<Player.LifeState> lifeStates1 = GameState.nextLifeState(players0, directedPositions1, blastedCells1); |
195 | Player.DirectedPosition nextCentralSubCell = player0.directedPositions().findFirst(dp -> dp.position().isCentral()); | 195 | |
196 | Sq<Player.DirectedPosition> toNextCentralSubCell = player0.directedPositions().takeWhile(dp -> !dp.position().isCentral()); | 196 | // Create the new player given the new parameters |
197 | Sq<Player.DirectedPosition> pastNextCentralSubCell = Player.DirectedPosition.moving(new Player.DirectedPosition(nextCentralSubCell.position(), requestedDirection)); | 197 | Player p1 = new Player(players0.id(), lifeStates1, directedPositions1, players0.maxBombs(), players0.bombRange()); |
198 | directedPositions1 = toNextCentralSubCell.concat(pastNextCentralSubCell); | 198 | |
199 | } | 199 | // Update the capacities of the player given the possible bonus |
200 | 200 | if (playerBonus != null) | |
201 | // Advance of one SubCell on the player's path | 201 | p1 = playerBonus.applyTo(p1); |
202 | directedPositions1 = directedPositions1.tail(); | 202 | |
203 | 203 | return p1; | |
204 | // Check possible collisions and update the Sequence if necessary (kinda ugly right now) | 204 | } |
205 | Cell possiblyBlockingCell = directedPositions1.tail().findFirst(dp -> dp.position().isCentral()).position().containingCell(); | 205 | |
206 | if (!board1.blockAt(possiblyBlockingCell).canHostPlayer()) { // if block non-free | 206 | /** |
207 | Sq<Player.DirectedPosition> actualDirectedPosition = Sq.repeat(1 , player0.directedPositions().head()); | 207 | * Generate the new Sequence of Directed Positions. |
208 | directedPositions1 = actualDirectedPosition.concat(directedPositions1); // won't move for a tick | 208 | * |
209 | } else if (bombedCells1.contains(possiblyBlockingCell) && possiblyBlockingCell.equals(player0.position().containingCell()) && player0.position().distanceToCentral() == Board.BOMB_BLOCKING_DISTANCE) { | 209 | * @param player0 |
210 | Sq<Player.DirectedPosition> actualDirectedPosition = Sq.repeat(1 , player0.directedPositions().head()); | 210 | * @param requestedDirection |
211 | directedPositions1 = actualDirectedPosition.concat(directedPositions1); // won't move for a tick | 211 | * @return |
212 | } | 212 | */ |
213 | 213 | private static Sq<Player.DirectedPosition> nextPath(Player player0, Direction requestedDirection) { | |
214 | // Apply damages and generate a new LifeState Sequence | 214 | if (!player0.lifeState().canMove()) |
215 | Sq<Player.LifeState> lifeStates1; | 215 | return Player.DirectedPosition.stopped(player0.directedPositions().head()); |
216 | if (player0.lifeState().state() == Player.LifeState.State.VULNERABLE && blastedCells1.contains(directedPositions1.head().position())) { | 216 | |
217 | lifeStates1 = player0.statesForNextLife(); | 217 | if (requestedDirection == null) |
218 | } else { | 218 | requestedDirection = player0.direction(); |
219 | lifeStates1 = player0.lifeStates().tail(); | 219 | |
220 | } | 220 | if (player0.direction().isParallelTo(requestedDirection)) |
221 | 221 | return Player.DirectedPosition.moving(new Player.DirectedPosition(player0.position(), requestedDirection)); | |
222 | // Create the new player given the new parameters | 222 | |
223 | Player player1 = new Player(player0.id(), lifeStates1, directedPositions1, player0.maxBombs(), player0.bombRange()); | 223 | if (player0.direction().isPerpendicularTo(requestedDirection)) { |
224 | 224 | Player.DirectedPosition nextCentralSubCell = GameState.projectedDirectedPosition(player0, player0.directedPositions()); | |
225 | // Update the capacities of the player given the possible bonus | 225 | Sq<Player.DirectedPosition> toNextCentralSubCell = player0.directedPositions().takeWhile(dp -> !dp.position().isCentral()); |
226 | if (playerBonuses.containsKey(player0.id())) { | 226 | Player.DirectedPosition centralSubCellDirectedPosition = new Player.DirectedPosition(nextCentralSubCell.position(), requestedDirection); |
227 | player1 = playerBonuses.get(player0.id()).applyTo(player1); | 227 | Sq<Player.DirectedPosition> pastNextCentralSubCell = Player.DirectedPosition.moving(centralSubCellDirectedPosition); |
228 | } | 228 | return toNextCentralSubCell.concat(pastNextCentralSubCell); |
229 | |||
230 | // Add the newly generated player to the returned list | ||
231 | players1.add(player1); | ||
232 | } | 229 | } |
233 | return players1; | 230 | |
231 | return player0.directedPositions(); | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * Check possible collisions and update the Sequence if necessary (kinda ugly right now) | ||
236 | * | ||
237 | * @param player0 | ||
238 | * @param projectedPath | ||
239 | * @param board1 | ||
240 | * @param bombedCells1 | ||
241 | * @return | ||
242 | */ | ||
243 | private static Sq<Player.DirectedPosition> handleCollisions(Player player0, | ||
244 | Sq<Player.DirectedPosition> projectedPath, | ||
245 | Board board1, Set<Cell> bombedCells1) { | ||
246 | |||
247 | Cell projectedCell = GameState.projectedDirectedPosition(player0, projectedPath).position().containingCell(); | ||
248 | if (GameState.isColliding(player0, projectedCell, board1, bombedCells1)) | ||
249 | return Sq.repeat(1, player0.directedPositions().head()) | ||
250 | .concat(projectedPath); | ||
251 | |||
252 | return projectedPath; | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * @param player0 | ||
257 | * @param projectedPath | ||
258 | * @return | ||
259 | */ | ||
260 | |||
261 | private static Player.DirectedPosition projectedDirectedPosition(Player player0, Sq<Player.DirectedPosition> projectedPath) { | ||
262 | if (!player0.lifeState().canMove()) | ||
263 | return new Player.DirectedPosition(player0.position(), player0.direction()); | ||
264 | |||
265 | return projectedPath.tail() | ||
266 | .findFirst(directedPos -> directedPos.position().isCentral()); | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * @param player0 | ||
271 | * @param projectedCell | ||
272 | * @param board1 | ||
273 | * @param bombedCells1 | ||
274 | * @return | ||
275 | */ | ||
276 | private static boolean isColliding(Player player0, Cell projectedCell, Board board1, Set<Cell> bombedCells1) { | ||
277 | if (!board1.blockAt(projectedCell).canHostPlayer()) | ||
278 | return true; | ||
279 | |||
280 | if (bombedCells1.contains(projectedCell) && projectedCell.equals(player0.position().containingCell())) | ||
281 | if (player0.position().distanceToCentral() <= Board.BOMB_BLOCKING_DISTANCE) | ||
282 | return true; | ||
283 | |||
284 | return false; | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * Apply damages and generate a new LifeState Sequence | ||
289 | * | ||
290 | * @param player0 | ||
291 | * @param directedPositions1 | ||
292 | * @param blastedCells1 | ||
293 | * @return | ||
294 | */ | ||
295 | private static Sq<Player.LifeState> nextLifeState(Player player0, Sq<Player.DirectedPosition> directedPositions1, | ||
296 | Set<Cell> blastedCells1) { | ||
297 | |||
298 | Cell currentCell = directedPositions1.head().position().containingCell(); | ||
299 | |||
300 | if (player0.isVulnerable() && blastedCells1.contains(currentCell)) | ||
301 | return player0.statesForNextLife(); | ||
302 | else | ||
303 | return player0.lifeStates().tail(); | ||
234 | } | 304 | } |
235 | 305 | ||
236 | /** | 306 | /** |
diff --git a/src/ch/epfl/xblast/server/Player.java b/src/ch/epfl/xblast/server/Player.java index d2f7b88..fdc4715 100644 --- a/src/ch/epfl/xblast/server/Player.java +++ b/src/ch/epfl/xblast/server/Player.java | |||
@@ -238,7 +238,7 @@ public final class Player { | |||
238 | 238 | ||
239 | int newLives = lives() - 1; | 239 | int newLives = lives() - 1; |
240 | 240 | ||
241 | if (newLives >= 0) { | 241 | if (newLives <= 0) { |
242 | LifeState dead = new LifeState(newLives, LifeState.State.DEAD); | 242 | LifeState dead = new LifeState(newLives, LifeState.State.DEAD); |
243 | nextLifeState = nextLifeState.concat(Sq.constant(dead)); | 243 | nextLifeState = nextLifeState.concat(Sq.constant(dead)); |
244 | } else { | 244 | } else { |
@@ -260,6 +260,13 @@ public final class Player { | |||
260 | } | 260 | } |
261 | 261 | ||
262 | /** | 262 | /** |
263 | * @return the vulnerability state of the player | ||
264 | */ | ||
265 | public boolean isVulnerable() { | ||
266 | return this.lifeState().state() == LifeState.State.VULNERABLE; | ||
267 | } | ||
268 | |||
269 | /** | ||
263 | * @return the current number of lives of the player | 270 | * @return the current number of lives of the player |