From a74846aced2635ebe7c51cc56b6d22eb4c33c69c Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Sun, 10 Apr 2016 11:07:32 +0200 Subject: Fix and refactor player path evolution --- src/ch/epfl/xblast/server/GameState.java | 140 ++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 48 deletions(-) (limited to 'src/ch') 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 { .collect(Collectors.toList()); } - private static Player nextPlayer(Player players0, Bonus playerBonus, + /** + * Computes and returns the next State of a Player from the given events. + * + * @param player0 the Player + * @param playerBonus the optional Bonus to apply to the Player + * @param bombedCells1 the Set of bombed Cells + * @param board1 the updated Board + * @param blastedCells1 the Set of blasted Cells + * @param requestedDirection the Player's new requested Direction + * @return the next state of the Player + */ + private static Player nextPlayer(Player player0, Bonus playerBonus, Set bombedCells1, Board board1, Set blastedCells1, Direction requestedDirection) { - Sq directedPositions1 = GameState.nextPath(players0, requestedDirection); + // 1. Compute the new path + Sq path1 = GameState.nextPath(player0, requestedDirection); - // Advance of one SubCell on the player's path - directedPositions1 = directedPositions1.tail(); + // 2. Check possible collisions and update the Sequence if necessary + Sq directedPos1 = GameState.handleCollisions(player0, path1, board1, bombedCells1); - //Check possible collisions and update the Sequence if necessary (kinda ugly right now) - directedPositions1 = GameState.handleCollisions(players0, directedPositions1, board1, bombedCells1); + // 3. Apply damages and generate a new LifeState Sequence + Sq lifeStates1 = GameState.nextLifeState(player0, directedPos1, blastedCells1); - // Apply damages and generate a new LifeState Sequence - Sq lifeStates1 = GameState.nextLifeState(players0, directedPositions1, blastedCells1); + // 4. Create the new player given the new parameters + Player p1 = new Player(player0.id(), lifeStates1, directedPos1, player0.maxBombs(), player0.bombRange()); - // Create the new player given the new parameters - Player p1 = new Player(players0.id(), lifeStates1, directedPositions1, players0.maxBombs(), players0.bombRange()); - - // Update the capacities of the player given the possible bonus - if (playerBonus != null) + // 5. Update the capacities of the player given the possible bonus + if (!Objects.isNull(playerBonus)) p1 = playerBonus.applyTo(p1); return p1; } /** - * Generate the new Sequence of Directed Positions. + * Returns the next Direction of the Player according to the constraints. * - * @param player0 the Player - * @param requestedDirection the requested Direction - * @return the path + * @param p0 the Player + * @param requestedDir the requested new Direction + * @return the next Direction */ - private static Sq nextPath(Player player0, Direction requestedDirection) { - if (!player0.lifeState().canMove()) - return Player.DirectedPosition.stopped(player0.directedPositions().head()); + private static Direction nextDirection(Player p0, Direction requestedDir) { + return !Objects.isNull(requestedDir) ? requestedDir : p0.direction(); + } - if (requestedDirection == null) - requestedDirection = player0.direction(); + /** + * Generates the new Sequence of DirectedPositions. + * + * @param p0 the Player + * @param requestedDir the new requested Direction + * @return the next path + */ + private static Sq nextPath(Player p0, Direction requestedDir) { + Sq path1 = GameState.newPath( + Player.DirectedPosition.moving(p0.directedPositions().head()), + GameState.nextDirection(p0, requestedDir)); - if (player0.direction().isParallelTo(requestedDirection)) - return Player.DirectedPosition.moving(new Player.DirectedPosition(player0.position(), requestedDirection)); + return p0.lifeState().canMove() ? path1.tail() : path1; + } - if (player0.direction().isPerpendicularTo(requestedDirection)) { - Player.DirectedPosition nextCentralSubCell = GameState.projectedDirectedPosition(player0, player0.directedPositions()); - Sq toNextCentralSubCell = player0.directedPositions().takeWhile(dp -> !dp.position().isCentral()); - Player.DirectedPosition centralSubCellDirectedPosition = new Player.DirectedPosition(nextCentralSubCell.position(), requestedDirection); - Sq pastNextCentralSubCell = Player.DirectedPosition.moving(centralSubCellDirectedPosition); - return toNextCentralSubCell.concat(pastNextCentralSubCell); - } + /** + * Computes the new path to follow according to the Player's wishes and the Board constraints. + * + * @param p0 the current path + * @param newDir the new requested Direction + * @return the new path + */ + private static Sq newPath(Sq p0, Direction newDir) { + if (p0.head().direction().isPerpendicularTo(newDir)) + return GameState.pivotPath(p0, newDir); + else + return Player.DirectedPosition.moving(new Player.DirectedPosition(p0.head().position(), newDir)); + } - return player0.directedPositions(); + /** + * Builds and returns a pivot path reaching the next pivot SubCell and then rotating to the given Direction. + * + * @param p0 the initial path + * @param newDir the new Direction to follow when possible + * @return the pivot path + */ + private static Sq pivotPath(Sq p0, Direction newDir) { + SubCell nextCentral = GameState.nextCentralPosition(p0); + + return GameState + .pathToNextCentralPosition(p0) + .concat(Player.DirectedPosition.moving(new Player.DirectedPosition(nextCentral, newDir))); + } + + /** + * Returns the path to the next central SubCell. + * + * @param p the path to follow + * @return the truncated path + */ + private static Sq pathToNextCentralPosition(Sq p) { + return p.tail() + .takeWhile(dp -> dp.position().isCentral()); + } + + /** + * Searches for and returns the next central SubCell reachable following the given path. + * + * @param p the path to follow + * @return the next central SubCell + */ + private static SubCell nextCentralPosition(Sq p) { + return p.tail() + .findFirst(dp -> dp.position().isCentral()) + .position(); } /** @@ -254,7 +313,7 @@ public final class GameState { Sq projectedPath, Board board1, Set bombedCells1) { - Cell projectedCell = GameState.projectedDirectedPosition(player0, projectedPath).position().containingCell(); + Cell projectedCell = GameState.nextCentralPosition(projectedPath).containingCell(); if (GameState.isColliding(player0, projectedCell, board1, bombedCells1)) return Sq.repeat(1, player0.directedPositions().head()) .concat(projectedPath); @@ -262,21 +321,6 @@ public final class GameState { return projectedPath; } - /** - * Computes a projection of the next DirectedPosition. - * - * @param player0 the Player - * @param projectedPath the projected path - * @return the projected next DirectedPosition - */ - private static Player.DirectedPosition projectedDirectedPosition(Player player0, Sq projectedPath) { - if (!player0.lifeState().canMove()) - return new Player.DirectedPosition(player0.position(), player0.direction()); - - return projectedPath.tail() - .findFirst(directedPos -> directedPos.position().isCentral()); - } - /** * Returns T(the player is colliding with an object). * -- cgit v1.2.3