diff options
Diffstat (limited to 'src/ch')
-rw-r--r-- | src/ch/epfl/xblast/server/GameState.java | 140 |
1 files changed, 92 insertions, 48 deletions
diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index f3547dc..df0cc24 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java | |||
@@ -188,57 +188,116 @@ public final class GameState { | |||
188 | .collect(Collectors.toList()); | 188 | .collect(Collectors.toList()); |
189 | } | 189 | } |
190 | 190 | ||
191 | private static Player nextPlayer(Player players0, Bonus playerBonus, | 191 | /** |
192 | * Computes and returns the next State of a Player from the given events. | ||
193 | * | ||
194 | * @param player0 the Player | ||
195 | * @param playerBonus the optional Bonus to apply to the Player | ||
196 | * @param bombedCells1 the Set of bombed Cells | ||
197 | * @param board1 the updated Board | ||
198 | * @param blastedCells1 the Set of blasted Cells | ||
199 | * @param requestedDirection the Player's new requested Direction | ||
200 | * @return the next state of the Player | ||
201 | */ | ||
202 | private static Player nextPlayer(Player player0, Bonus playerBonus, | ||
192 | Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1, | 203 | Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1, |
193 | Direction requestedDirection) { | 204 | Direction requestedDirection) { |
194 | 205 | ||
195 | Sq<Player.DirectedPosition> directedPositions1 = GameState.nextPath(players0, requestedDirection); | 206 | // 1. Compute the new path |
207 | Sq<Player.DirectedPosition> path1 = GameState.nextPath(player0, requestedDirection); | ||
196 | 208 | ||
197 | // Advance of one SubCell on the player's path | 209 | // 2. Check possible collisions and update the Sequence if necessary |
198 | directedPositions1 = directedPositions1.tail(); | 210 | Sq<Player.DirectedPosition> directedPos1 = GameState.handleCollisions(player0, path1, board1, bombedCells1); |
199 | 211 | ||
200 | //Check possible collisions and update the Sequence if necessary (kinda ugly right now) | 212 | // 3. Apply damages and generate a new LifeState Sequence |
201 | directedPositions1 = GameState.handleCollisions(players0, directedPositions1, board1, bombedCells1); | 213 | Sq<Player.LifeState> lifeStates1 = GameState.nextLifeState(player0, directedPos1, blastedCells1); |
202 | 214 | ||
203 | // Apply damages and generate a new LifeState Sequence | 215 | // 4. Create the new player given the new parameters |
204 | Sq<Player.LifeState> lifeStates1 = GameState.nextLifeState(players0, directedPositions1, blastedCells1); | 216 | Player p1 = new Player(player0.id(), lifeStates1, directedPos1, player0.maxBombs(), player0.bombRange()); |
205 | 217 | ||
206 | // Create the new player given the new parameters | 218 | // 5. Update the capacities of the player given the possible bonus |
207 | Player p1 = new Player(players0.id(), lifeStates1, directedPositions1, players0.maxBombs(), players0.bombRange()); | 219 | if (!Objects.isNull(playerBonus)) |
208 | |||
209 | // Update the capacities of the player given the possible bonus | ||
210 | if (playerBonus != null) | ||
211 | p1 = playerBonus.applyTo(p1); | 220 | p1 = playerBonus.applyTo(p1); |
212 | 221 | ||
213 | return p1; | 222 | return p1; |
214 | } | 223 | } |
215 | 224 | ||
216 | /** | 225 | /** |
217 | * Generate the new Sequence of Directed Positions. | 226 | * Returns the next Direction of the Player according to the constraints. |
218 | * | 227 | * |
219 | * @param player0 the Player | 228 | * @param p0 the Player |
220 | * @param requestedDirection the requested Direction | 229 | * @param requestedDir the requested new Direction |
221 | * @return the path | 230 | * @return the next Direction |
222 | */ | 231 | */ |
223 | private static Sq<Player.DirectedPosition> nextPath(Player player0, Direction requestedDirection) { | 232 | private static Direction nextDirection(Player p0, Direction requestedDir) { |
224 | if (!player0.lifeState().canMove()) | 233 | return !Objects.isNull(requestedDir) ? requestedDir : p0.direction(); |
225 | return Player.DirectedPosition.stopped(player0.directedPositions().head()); | 234 | } |
226 | 235 | ||
227 | if (requestedDirection == null) | 236 | /** |
228 | requestedDirection = player0.direction(); | 237 | * Generates the new Sequence of DirectedPositions. |
238 | * | ||
239 | * @param p0 the Player | ||
240 | * @param requestedDir the new requested Direction | ||
241 | * @return the next path | ||
242 | */ | ||
243 | private static Sq<Player.DirectedPosition> nextPath(Player p0, Direction requestedDir) { | ||
244 | Sq<Player.DirectedPosition> path1 = GameState.newPath( | ||
245 | Player.DirectedPosition.moving(p0.directedPositions().head()), | ||
246 | GameState.nextDirection(p0, requestedDir)); | ||
229 | 247 | ||
230 | if (player0.direction().isParallelTo(requestedDirection)) | 248 | return p0.lifeState().canMove() ? path1.tail() : path1; |
231 | return Player.DirectedPosition.moving(new Player.DirectedPosition(player0.position(), requestedDirection)); | 249 | } |
232 | 250 | ||
233 | if (player0.direction().isPerpendicularTo(requestedDirection)) { | 251 | /** |
234 | Player.DirectedPosition nextCentralSubCell = GameState.projectedDirectedPosition(player0, player0.directedPositions()); | 252 | * Computes the new path to follow according to the Player's wishes and the Board constraints. |
235 | Sq<Player.DirectedPosition> toNextCentralSubCell = player0.directedPositions().takeWhile(dp -> !dp.position().isCentral()); | 253 | * |
236 | Player.DirectedPosition centralSubCellDirectedPosition = new Player.DirectedPosition(nextCentralSubCell.position(), requestedDirection); | 254 | * @param p0 the current path |
237 | Sq<Player.DirectedPosition> pastNextCentralSubCell = Player.DirectedPosition.moving(centralSubCellDirectedPosition); | 255 | * @param newDir the new requested Direction |
238 | return toNextCentralSubCell.concat(pastNextCentralSubCell); | 256 | * @return the new path |
239 | } | 257 | */ |
258 | private static Sq<Player.DirectedPosition> newPath(Sq<Player.DirectedPosition> p0, Direction newDir) { | ||
259 | if (p0.head().direction().isPerpendicularTo(newDir)) | ||
260 | return GameState.pivotPath(p0, newDir); | ||
261 | else | ||
262 | return Player.DirectedPosition.moving(new Player.DirectedPosition(p0.head().position(), newDir)); | ||
263 | } | ||
240 | 264 | ||
241 | return player0.directedPositions(); | 265 | /** |
266 | * Builds and returns a pivot path reaching the next pivot SubCell and then rotating to the given Direction. | ||
267 | * | ||
268 | * @param p0 the initial path | ||
269 | * @param newDir the new Direction to follow when possible | ||
270 | * @return the pivot path | ||
271 | */ | ||
272 | private static Sq<Player.DirectedPosition> pivotPath(Sq<Player.DirectedPosition> p0, Direction newDir) { | ||
273 | SubCell nextCentral = GameState.nextCentralPosition(p0); | ||
274 | |||
275 | return GameState | ||
276 | .pathToNextCentralPosition(p0) | ||
277 | .concat(Player.DirectedPosition.moving(new Player.DirectedPosition(nextCentral, newDir))); | ||
278 | } | ||
279 | |||
280 | /** | ||
281 | * Returns the path to the next central SubCell. | ||
282 | * | ||
283 | * @param p the path to follow | ||
284 | * @return the truncated path | ||
285 | */ | ||
286 | private static Sq<Player.DirectedPosition> pathToNextCentralPosition(Sq<Player.DirectedPosition> p) { | ||
287 | return p.tail() | ||
288 | .takeWhile(dp -> dp.position().isCentral()); | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * Searches for and returns the next central SubCell reachable following the given path. | ||
293 | * | ||
294 | * @param p the path to follow | ||
295 | * @return the next central SubCell | ||
296 | */ | ||
297 | private static SubCell nextCentralPosition(Sq<Player.DirectedPosition> p) { | ||
298 | return p.tail() | ||
299 | .findFirst(dp -> dp.position().isCentral()) | ||
300 | .position(); | ||
242 | } | 301 | } |
243 | 302 | ||
244 | /** | 303 | /** |
@@ -254,7 +313,7 @@ public final class GameState { | |||
254 | Sq<Player.DirectedPosition> projectedPath, | 313 | Sq<Player.DirectedPosition> projectedPath, |
255 | Board board1, Set<Cell> bombedCells1) { | 314 | Board board1, Set<Cell> bombedCells1) { |
256 | 315 | ||
257 | Cell projectedCell = GameState.projectedDirectedPosition(player0, projectedPath).position().containingCell(); | 316 | Cell projectedCell = GameState.nextCentralPosition(projectedPath).containingCell(); |
258 | if (GameState.isColliding(player0, projectedCell, board1, bombedCells1)) | 317 | if (GameState.isColliding(player0, projectedCell, board1, bombedCells1)) |
259 | return Sq.repeat(1, player0.directedPositions().head()) | 318 | return Sq.repeat(1, player0.directedPositions().head()) |
260 | .concat(projectedPath); | 319 | .concat(projectedPath); |
@@ -263,21 +322,6 @@ public final class GameState { | |||
263 | } | 322 | } |
264 | 323 | ||
265 | /** | 324 | /** |
266 | * Computes a projection of the next DirectedPosition. | ||
267 | * | ||
268 | * @param player0 the Player | ||
269 | * @param projectedPath the projected path | ||
270 | * @return the projected next DirectedPosition | ||
271 | */ | ||
272 | private static Player.DirectedPosition projectedDirectedPosition(Player player0, Sq<Player.DirectedPosition> projectedPath) { | ||
273 | if (!player0.lifeState().canMove()) | ||
274 | return new Player.DirectedPosition(player0.position(), player0.direction()); | ||
275 | |||
276 | return projectedPath.tail() | ||
277 | .findFirst(directedPos -> directedPos.position().isCentral()); | ||
278 | } | ||
279 | |||
280 | /** | ||
281 | * Returns T(the player is colliding with an object). | 325 | * Returns T(the player is colliding with an object). |
282 | * | 326 | * |
283 | * @param player0 the Player | 327 | * @param player0 the Player |