From f63c5e1af73f9eefaea26a985b1ab3425df67cdf Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Fri, 8 Apr 2016 15:47:57 +0200 Subject: Make nextPlayers great again --- src/ch/epfl/xblast/server/GameState.java | 200 +++++++++++++++++++++---------- src/ch/epfl/xblast/server/Player.java | 11 +- 2 files changed, 144 insertions(+), 67 deletions(-) (limited to 'src/ch') 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 { * @param speedChangeEvents the speed change events * @return the next player list */ - private static List nextPlayers( - List players0, - Map playerBonuses, - Set bombedCells1, - Board board1, - Set blastedCells1, - Map> speedChangeEvents) { - List players1 = new ArrayList<>(); - - for (Player player0 : players0) { - Optional event = speedChangeEvents.get(player0.id()); - // By default the path won't change - Sq directedPositions1 = player0.directedPositions(); - - // Get the (possibly) requested direction - Direction requestedDirection = null; - if (event != null) { - requestedDirection = event.orElse(null); - } - - // Generate the new Sequence of Directed Positions (kinda ugly right now) - if (!player0.lifeState().canMove() && requestedDirection != null) { // if the player can't movex - directedPositions1 = Player.DirectedPosition.stopped(player0.directedPositions().head()); - } else if (player0.direction().isParallelTo(requestedDirection)) { // if the player want to go to a parallel directionx - Player.DirectedPosition requestedDirectedPosition = new Player.DirectedPosition(player0.position(), requestedDirection); - directedPositions1 = Player.DirectedPosition.moving(requestedDirectedPosition); - } else if (player0.direction().isPerpendicularTo(requestedDirection)) { // if the player want to go to a perpendicular direction - Player.DirectedPosition nextCentralSubCell = player0.directedPositions().findFirst(dp -> dp.position().isCentral()); - Sq toNextCentralSubCell = player0.directedPositions().takeWhile(dp -> !dp.position().isCentral()); - Sq pastNextCentralSubCell = Player.DirectedPosition.moving(new Player.DirectedPosition(nextCentralSubCell.position(), requestedDirection)); - directedPositions1 = toNextCentralSubCell.concat(pastNextCentralSubCell); - } - - // Advance of one SubCell on the player's path - directedPositions1 = directedPositions1.tail(); - - // Check possible collisions and update the Sequence if necessary (kinda ugly right now) - Cell possiblyBlockingCell = directedPositions1.tail().findFirst(dp -> dp.position().isCentral()).position().containingCell(); - if (!board1.blockAt(possiblyBlockingCell).canHostPlayer()) { // if block non-free - Sq actualDirectedPosition = Sq.repeat(1 , player0.directedPositions().head()); - directedPositions1 = actualDirectedPosition.concat(directedPositions1); // won't move for a tick - } else if (bombedCells1.contains(possiblyBlockingCell) && possiblyBlockingCell.equals(player0.position().containingCell()) && player0.position().distanceToCentral() == Board.BOMB_BLOCKING_DISTANCE) { - Sq actualDirectedPosition = Sq.repeat(1 , player0.directedPositions().head()); - directedPositions1 = actualDirectedPosition.concat(directedPositions1); // won't move for a tick - } - - // Apply damages and generate a new LifeState Sequence - Sq lifeStates1; - if (player0.lifeState().state() == Player.LifeState.State.VULNERABLE && blastedCells1.contains(directedPositions1.head().position())) { - lifeStates1 = player0.statesForNextLife(); - } else { - lifeStates1 = player0.lifeStates().tail(); - } - - // Create the new player given the new parameters - Player player1 = new Player(player0.id(), lifeStates1, directedPositions1, player0.maxBombs(), player0.bombRange()); - - // Update the capacities of the player given the possible bonus - if (playerBonuses.containsKey(player0.id())) { - player1 = playerBonuses.get(player0.id()).applyTo(player1); - } - - // Add the newly generated player to the returned list - players1.add(player1); + private static List nextPlayers(List players0, Map playerBonuses, + Set bombedCells1, Board board1, Set blastedCells1, + Map> speedChangeEvents) { + + return players0.stream() + .map(p -> { + Optional speedChangeEvent = speedChangeEvents.get(p.id()); + Direction requestedDirection = speedChangeEvent != null ? speedChangeEvent.orElse(null) : null; + return GameState.nextPlayer(p, playerBonuses.get(p.id()), bombedCells1, board1, blastedCells1, requestedDirection); + }) + .collect(Collectors.toList()); + } + + private static Player nextPlayer(Player players0, Bonus playerBonus, + Set bombedCells1, Board board1, Set blastedCells1, + Direction requestedDirection) { + + Sq directedPositions1 = GameState.nextPath(players0, requestedDirection); + + // Advance of one SubCell on the player's path + directedPositions1 = directedPositions1.tail(); + + //Check possible collisions and update the Sequence if necessary (kinda ugly right now) + directedPositions1 = GameState.handleCollisions(players0, directedPositions1, board1, bombedCells1); + + // Apply damages and generate a new LifeState Sequence + Sq lifeStates1 = GameState.nextLifeState(players0, directedPositions1, blastedCells1); + + // 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) + p1 = playerBonus.applyTo(p1); + + return p1; + } + + /** + * Generate the new Sequence of Directed Positions. + * + * @param player0 + * @param requestedDirection + * @return + */ + private static Sq nextPath(Player player0, Direction requestedDirection) { + if (!player0.lifeState().canMove()) + return Player.DirectedPosition.stopped(player0.directedPositions().head()); + + if (requestedDirection == null) + requestedDirection = player0.direction(); + + if (player0.direction().isParallelTo(requestedDirection)) + return Player.DirectedPosition.moving(new Player.DirectedPosition(player0.position(), requestedDirection)); + + 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); } - return players1; + + return player0.directedPositions(); + } + + /** + * Check possible collisions and update the Sequence if necessary (kinda ugly right now) + * + * @param player0 + * @param projectedPath + * @param board1 + * @param bombedCells1 + * @return + */ + private static Sq handleCollisions(Player player0, + Sq projectedPath, + Board board1, Set bombedCells1) { + + Cell projectedCell = GameState.projectedDirectedPosition(player0, projectedPath).position().containingCell(); + if (GameState.isColliding(player0, projectedCell, board1, bombedCells1)) + return Sq.repeat(1, player0.directedPositions().head()) + .concat(projectedPath); + + return projectedPath; + } + + /** + * @param player0 + * @param projectedPath + * @return + */ + + 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()); + } + + /** + * @param player0 + * @param projectedCell + * @param board1 + * @param bombedCells1 + * @return + */ + private static boolean isColliding(Player player0, Cell projectedCell, Board board1, Set bombedCells1) { + if (!board1.blockAt(projectedCell).canHostPlayer()) + return true; + + if (bombedCells1.contains(projectedCell) && projectedCell.equals(player0.position().containingCell())) + if (player0.position().distanceToCentral() <= Board.BOMB_BLOCKING_DISTANCE) + return true; + + return false; + } + + /** + * Apply damages and generate a new LifeState Sequence + * + * @param player0 + * @param directedPositions1 + * @param blastedCells1 + * @return + */ + private static Sq nextLifeState(Player player0, Sq directedPositions1, + Set blastedCells1) { + + Cell currentCell = directedPositions1.head().position().containingCell(); + + if (player0.isVulnerable() && blastedCells1.contains(currentCell)) + return player0.statesForNextLife(); + else + return player0.lifeStates().tail(); } /** 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 { int newLives = lives() - 1; - if (newLives >= 0) { + if (newLives <= 0) { LifeState dead = new LifeState(newLives, LifeState.State.DEAD); nextLifeState = nextLifeState.concat(Sq.constant(dead)); } else { @@ -259,6 +259,13 @@ public final class Player { return this.lifeStates.head(); } + /** + * @return the vulnerability state of the player + */ + public boolean isVulnerable() { + return this.lifeState().state() == LifeState.State.VULNERABLE; + } + /** * @return the current number of lives of the player */ @@ -270,7 +277,7 @@ public final class Player { * @return true is the player has more than 0 lives */ public boolean isAlive() { - return this.lives() >= 0; + return this.lives() > 0; } /** -- cgit v1.2.3