From fa66073ed8bb68b144c3e7397ef95ce0d8442ae8 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Fri, 25 Mar 2016 16:30:39 +0100 Subject: Import given random event generator debugging utility --- .../xblast/server/debug/RandomEventGenerator.java | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/ch/epfl/xblast/server/debug/RandomEventGenerator.java (limited to 'src') diff --git a/src/ch/epfl/xblast/server/debug/RandomEventGenerator.java b/src/ch/epfl/xblast/server/debug/RandomEventGenerator.java new file mode 100644 index 0000000..60a9c62 --- /dev/null +++ b/src/ch/epfl/xblast/server/debug/RandomEventGenerator.java @@ -0,0 +1,50 @@ +package ch.epfl.xblast.server.debug; + +import ch.epfl.xblast.Direction; +import ch.epfl.xblast.PlayerID; + +import java.util.*; + +/** + * Random event generator debugging utility. + * + * @author EPFL + */ +public final class RandomEventGenerator { + + private static final List> possibleSpeeds = + Arrays.asList( + Optional.empty(), + Optional.of(Direction.N), + Optional.of(Direction.E), + Optional.of(Direction.S), + Optional.of(Direction.W)); + + private final Random rng; + private final int speedChangeProb, bombProb; + + public RandomEventGenerator(long seed, int speedChangeProb, int bombProb) { + this.rng = new Random(seed); + this.speedChangeProb = speedChangeProb; + this.bombProb = bombProb; + } + + public Map> randomSpeedChangeEvents() { + Map> events = new EnumMap<>(PlayerID.class); + for (PlayerID pId : PlayerID.values()) { + if (rng.nextInt(speedChangeProb) == 0) + events.put(pId, possibleSpeeds.get(rng.nextInt(possibleSpeeds.size()))); + } + return Collections.unmodifiableMap(events); + } + + public Set randomBombDropEvents() { + Set events = EnumSet.noneOf(PlayerID.class); + for (PlayerID pID : PlayerID.values()) { + if (rng.nextInt(bombProb) == 0) + events.add(pID); + } + return Collections.unmodifiableSet(events); + } + +} -- cgit v1.2.3 From 552d82f34ee4b60785164bc40d6dd5b5d8923609 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Sat, 26 Mar 2016 13:44:46 +0100 Subject: Implement random event live simulation --- src/ch/epfl/xblast/server/GameState.java | 12 ++++++++++++ src/ch/epfl/xblast/server/Player.java | 11 +++++++++++ src/ch/epfl/xblast/server/debug/GameStatePrinter.java | 15 +++++++++++---- 3 files changed, 34 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 1abe17a..4b00c3e 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -477,4 +477,16 @@ public final class GameState { .collect(Collectors.toList()); } + @Override + public String toString() { + return "GameState{" + + "ticks=" + ticks + + ", board=" + board + + ", players=" + players + + ", bombs=" + bombs + + ", explosions=" + explosions + + ", blasts=" + blasts + + '}'; + } + } diff --git a/src/ch/epfl/xblast/server/Player.java b/src/ch/epfl/xblast/server/Player.java index 094d395..d2f7b88 100644 --- a/src/ch/epfl/xblast/server/Player.java +++ b/src/ch/epfl/xblast/server/Player.java @@ -329,4 +329,15 @@ public final class Player { return new Bomb(this.id(), this.position().containingCell(), Ticks.BOMB_FUSE_TICKS, this.bombRange()); } + @Override + public String toString() { + return "Player{" + + "id=" + id + + ", lifeStates=" + lifeStates + + ", directedPos=" + directedPos + + ", maxBombs=" + maxBombs + + ", bombRange=" + bombRange + + '}'; + } + } diff --git a/src/ch/epfl/xblast/server/debug/GameStatePrinter.java b/src/ch/epfl/xblast/server/debug/GameStatePrinter.java index ea8b360..d4d91e5 100644 --- a/src/ch/epfl/xblast/server/debug/GameStatePrinter.java +++ b/src/ch/epfl/xblast/server/debug/GameStatePrinter.java @@ -12,6 +12,7 @@ import java.util.List; * Game state printer utility class that outputs the board to the terminal. * * @author EPFL + * @author Pacien TRAN-GIRARD (261948) */ public final class GameStatePrinter { @@ -19,9 +20,15 @@ public final class GameStatePrinter { } public static void printGameState(GameState s) { - List ps = s.alivePlayers(); - Board board = s.board(); + printStats(s); + printBoard(s.board(), s.alivePlayers()); + } + + private static void printStats(GameState s) { + System.out.println(s); + } + private static void printBoard(Board b, List ps) { for (int y = 0; y < Cell.ROWS; ++y) { xLoop: for (int x = 0; x < Cell.COLUMNS; ++x) { @@ -32,8 +39,8 @@ public final class GameStatePrinter { continue xLoop; } } - Block b = board.blockAt(c); - System.out.print(stringForBlock(b)); + Block block = b.blockAt(c); + System.out.print(stringForBlock(block)); } System.out.println(); } -- cgit v1.2.3 From 5e2797946a3d63de9142d79b241788e2284f8eab Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Sat, 26 Mar 2016 13:45:30 +0100 Subject: Implement simulation terminal output coloring --- .../epfl/xblast/server/debug/GameStatePrinter.java | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/debug/GameStatePrinter.java b/src/ch/epfl/xblast/server/debug/GameStatePrinter.java index d4d91e5..a846421 100644 --- a/src/ch/epfl/xblast/server/debug/GameStatePrinter.java +++ b/src/ch/epfl/xblast/server/debug/GameStatePrinter.java @@ -16,6 +16,25 @@ import java.util.List; */ public final class GameStatePrinter { + private enum ANSIColor { + + BLACK(0), RED(1), GREEN(2), YELLOW(3), BLUE(4), MAGENTA(5), CYAN(6), WHITE(7); + + private static final String CSI = "\u001b["; + private static final String END = "m"; + private static final int SET_COMMAND = 4; + + private final int code; + + ANSIColor(int code) { + this.code = code; + } + + public String coloredText(String t) { + return String.format("%s%d%d%s%s%s%s", CSI, SET_COMMAND, this.code, END, t, CSI, END); + } + } + private GameStatePrinter() { } @@ -63,7 +82,7 @@ public final class GameStatePrinter { b.append('<'); break; } - return b.toString(); + return ANSIColor.CYAN.coloredText(b.toString()); } private static String stringForBlock(Block b) { @@ -71,15 +90,15 @@ public final class GameStatePrinter { case FREE: return " "; case INDESTRUCTIBLE_WALL: - return "##"; + return ANSIColor.BLACK.coloredText("##"); case DESTRUCTIBLE_WALL: - return "??"; + return ANSIColor.BLACK.coloredText("??"); case CRUMBLING_WALL: - return "¿¿"; + return ANSIColor.BLACK.coloredText("¿¿"); case BONUS_BOMB: - return "+b"; + return ANSIColor.GREEN.coloredText("+b"); case BONUS_RANGE: - return "+r"; + return ANSIColor.GREEN.coloredText("+r"); default: throw new Error(); } -- cgit v1.2.3 From a5f3aa729dfad19f3979b01f0a6f9916ac968698 Mon Sep 17 00:00:00 2001 From: Timothée Floure Date: Thu, 31 Mar 2016 12:54:35 +0200 Subject: Fix encapsulation failure in Board class --- src/ch/epfl/xblast/server/Board.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/Board.java b/src/ch/epfl/xblast/server/Board.java index f2a3c89..d7ca706 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; import ch.epfl.xblast.Lists; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -55,7 +56,7 @@ public final class Board { if (blocks == null || blocks.size() != BLOCKS_LIST_SIZE) throw new IllegalArgumentException(); - this.blocks = blocks; + this.blocks = new ArrayList<>(blocks); } /** @@ -148,6 +149,7 @@ public final class Board { * @return a list of the Sequences of blocks of the board. */ public List> getBlocks() { - return blocks; + List> immutableBlocks = Collections.unmodifiableList(new ArrayList<>(blocks)); + return immutableBlocks; } } -- cgit v1.2.3 From 54cd144e8a070e4b89baa86361db95280939d001 Mon Sep 17 00:00:00 2001 From: Timothée Floure Date: Thu, 31 Mar 2016 13:07:11 +0200 Subject: Remove (useless ?) cast to HasSet in GameState/nextBoard --- src/ch/epfl/xblast/server/GameState.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 4b00c3e..32edf5d 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -126,9 +126,9 @@ public final class GameState { for (Sq blockSq : blocks0) { int cellId = blocks0.get(i).hashCode(); Block block = blockSq.head(); - if (((HashSet) consumedBonuses).contains(cellId) && block.isBonus()) { + if (( consumedBonuses).contains(cellId) && block.isBonus()) { blocks1.add(Sq.constant(Block.FREE)); - } else if (((HashSet) blastedCells1).contains(cellId) && (block == Block.DESTRUCTIBLE_WALL || block.isBonus())) { + } else if ((blastedCells1).contains(cellId) && (block == Block.DESTRUCTIBLE_WALL || block.isBonus())) { if (block == Block.DESTRUCTIBLE_WALL) { Block bonus = randomBonus(); blocks1.add(Sq.repeat(Ticks.WALL_CRUMBLING_TICKS, Block.CRUMBLING_WALL).concat(Sq.constant(bonus))); -- cgit v1.2.3 From 7309447c8ddc269eaa014dcb9c2f62716053b632 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Thu, 31 Mar 2016 13:35:36 +0200 Subject: Fix wrong method call for empty set enum creation --- src/ch/epfl/xblast/server/GameState.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 32edf5d..f4d021c 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -456,12 +456,13 @@ public final class GameState { * @return the conflict-free set of bomb drop events */ private Set discardConflictingBombDropEvents(Set bombDropEvents) { - return EnumSet.copyOf( - this.mapTopPriorityPlayerCells( - this.alivePlayers().stream() - .filter(bombDropEvents::contains) - .collect(Collectors.toList()) - ).values()); + Map bombDropMap = this.mapTopPriorityPlayerCells( + this.alivePlayers().stream() + .filter(bombDropEvents::contains) + .collect(Collectors.toList()) + ); + + return bombDropMap.isEmpty() ? EnumSet.noneOf(PlayerID.class) : EnumSet.copyOf(bombDropMap.values()); } /** -- cgit v1.2.3 From 4d75a239dbffb6bd73d261c2cd5804d6e77834b4 Mon Sep 17 00:00:00 2001 From: Timothée Floure Date: Tue, 5 Apr 2016 01:04:06 +0200 Subject: Implement nextPlayer() for GameState --- src/ch/epfl/xblast/server/GameState.java | 81 ++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index f4d021c..035493d 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; import java.util.stream.Collectors; import java.util.stream.Stream; + /** * GameState representing the current game state. * @@ -126,9 +127,9 @@ public final class GameState { for (Sq blockSq : blocks0) { int cellId = blocks0.get(i).hashCode(); Block block = blockSq.head(); - if (( consumedBonuses).contains(cellId) && block.isBonus()) { + if (consumedBonuses.contains(cellId) && block.isBonus()) { blocks1.add(Sq.constant(Block.FREE)); - } else if ((blastedCells1).contains(cellId) && (block == Block.DESTRUCTIBLE_WALL || block.isBonus())) { + } else if (blastedCells1.contains(cellId) && (block == Block.DESTRUCTIBLE_WALL || block.isBonus())) { if (block == Block.DESTRUCTIBLE_WALL) { Block bonus = randomBonus(); blocks1.add(Sq.repeat(Ticks.WALL_CRUMBLING_TICKS, Block.CRUMBLING_WALL).concat(Sq.constant(bonus))); @@ -162,8 +163,68 @@ public final class GameState { Board board1, Set blastedCells1, Map> speedChangeEvents) { - //ToDo - return players0; + List players1 = new ArrayList<>(); + + for (Player player0 : players0) { + Optional event = speedChangeEvents.get(player0.id()); + Sq directedPositions1; + + // Get the requested direction + Direction requestedDirection = null; + if (event != null) { + requestedDirection = event.orElse(null); + } + + // Generate the new Sequence of Directed Positions (kinda ugly right now) + if (requestedDirection == null || !player0.lifeState().canMove()) { + // The player does not move + directedPositions1 = Player.DirectedPosition.stopped(player0.directedPositions().head()); + } else if (player0.direction() == requestedDirection.opposite() || player0.direction() == requestedDirection) { + // The player keep its actual position or go to the opposite direction + Player.DirectedPosition requestedDirectedPosition = new Player.DirectedPosition(player0.position(), requestedDirection); + directedPositions1 = Sq.constant(requestedDirectedPosition); + } else { + // The player go to a perpendicular position. + 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 newly computed path + directedPositions1 = directedPositions1.tail(); + + // Check possible collisions and update the Sequence if necessary (kinda ugly right now) + Cell possiblyWalledCell = directedPositions1.tail().findFirst(dp -> dp.position().isCentral()).position().containingCell(); + if (!board1.blockAt(possiblyWalledCell).canHostPlayer()) { // if block non-free + Sq actualDirectedPosition = Sq.repeat(1 , player0.directedPositions().head()); + directedPositions1 = actualDirectedPosition.concat(directedPositions1); // won't move for a tick + } + if (bombedCells1.contains(player0.position().containingCell()) && player0.position().distanceToCentral() <= 6) { // Magic number ! 10 lashes for Fnux. + 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); + } + return players1; } /** @@ -174,7 +235,7 @@ public final class GameState { */ private static List>> nextExplosions(List>> explosions0) { List>> explosions1 = new ArrayList<>(); - for (Sq> explosion : explosions0) { + for (Sq> explosion : explosions0) { if (!explosion.tail().isEmpty()) { explosions1.add(explosion.tail()); } @@ -203,9 +264,9 @@ public final class GameState { for (Player player : players0) { if (bombDropEvents.contains(player.id()) && player.isAlive() && !containingBombCells.contains(player.position().containingCell())) { - Bomb newBomb = new Bomb(player.id(), player.position().containingCell(), Ticks.BOMB_FUSE_TICKS, player.bombRange()); - containingBombCells.add(newBomb.position()); - bombs1.add(newBomb); + Bomb newBomb = new Bomb(player.id(), player.position().containingCell(), Ticks.BOMB_FUSE_TICKS, player.bombRange()); + containingBombCells.add(newBomb.position()); + bombs1.add(newBomb); } } return bombs1; @@ -458,8 +519,8 @@ public final class GameState { private Set discardConflictingBombDropEvents(Set bombDropEvents) { Map bombDropMap = this.mapTopPriorityPlayerCells( this.alivePlayers().stream() - .filter(bombDropEvents::contains) - .collect(Collectors.toList()) + .filter(bombDropEvents::contains) + .collect(Collectors.toList()) ); return bombDropMap.isEmpty() ? EnumSet.noneOf(PlayerID.class) : EnumSet.copyOf(bombDropMap.values()); -- cgit v1.2.3 From 0ce2048d2c34efb6335722a8d09c37afca78c583 Mon Sep 17 00:00:00 2001 From: Timothée Floure Date: Tue, 5 Apr 2016 09:37:10 +0200 Subject: GameState: Fix movement in nextPlayer() --- src/ch/epfl/xblast/Direction.java | 19 +++++++++++++++++++ src/ch/epfl/xblast/server/GameState.java | 18 ++++++++---------- 2 files changed, 27 insertions(+), 10 deletions(-) (limited to 'src') 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 @@ -67,6 +67,25 @@ public enum Direction { return that == this || that == this.opposite(); } + /** + * T(the current and given Directions are perpendicular). + * + * @param that a Direction to compare + * @return T(the current and given Directions are perpendicular) + */ + public boolean isPerpendicularTo(Direction that) { + switch (this) { + case N: + case S: + return that == E || that == W; + case E: + case W: + return that == N || that == S; + default: + return false; + } + } + /** * Returns the x-coordinate of the normed vector representation of the Direction. * diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 035493d..d648cef 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -167,31 +167,29 @@ public final class GameState { for (Player player0 : players0) { Optional event = speedChangeEvents.get(player0.id()); - Sq directedPositions1; + // By default the path won't change + Sq directedPositions1 = player0.directedPositions(); - // Get the requested direction + // 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 (requestedDirection == null || !player0.lifeState().canMove()) { - // The player does not move + if (!player0.lifeState().canMove() && requestedDirection != null) { // if the player can't movex directedPositions1 = Player.DirectedPosition.stopped(player0.directedPositions().head()); - } else if (player0.direction() == requestedDirection.opposite() || player0.direction() == requestedDirection) { - // The player keep its actual position or go to the opposite direction + } 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 = Sq.constant(requestedDirectedPosition); - } else { - // The player go to a perpendicular position. + 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 newly computed path + // 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) -- cgit v1.2.3 From 873a3084a9993f9dcf8d575563a6a018ed85dbb6 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Wed, 6 Apr 2016 22:48:59 +0200 Subject: Optimize nextExplosions --- src/ch/epfl/xblast/server/GameState.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index d648cef..77e91f2 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -232,13 +232,10 @@ public final class GameState { * @return the next explosion state */ private static List>> nextExplosions(List>> explosions0) { - List>> explosions1 = new ArrayList<>(); - for (Sq> explosion : explosions0) { - if (!explosion.tail().isEmpty()) { - explosions1.add(explosion.tail()); - } - } - return explosions1; + return explosions0.stream() + .map(Sq::tail) + .filter(s -> !s.isEmpty()) + .collect(Collectors.toList()); } /** -- cgit v1.2.3 From f8effdde28b9d92ce28b3ef5fbd3acf0644d2191 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Wed, 6 Apr 2016 22:51:52 +0200 Subject: Remove player number magic value --- src/ch/epfl/xblast/server/GameState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 77e91f2..c58a911 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -290,7 +290,7 @@ public final class GameState { this.ticks = ArgumentChecker.requireNonNegative(ticks); this.board = Objects.requireNonNull(board); - if (players.size() != 4) throw new IllegalArgumentException(); + if (players.size() != PlayerID.values().length) throw new IllegalArgumentException(); this.players = players; this.bombs = Objects.requireNonNull(bombs); -- cgit v1.2.3 From a33c9df30d209e8ba24b51507ffdeab17008dbe8 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Wed, 6 Apr 2016 23:06:07 +0200 Subject: Make newlyDroppedBombs more readable --- src/ch/epfl/xblast/server/GameState.java | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index c58a911..3495af1 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -240,30 +240,27 @@ public final class GameState { /** * Computes and returns the list of newly dropped bombs by players according to the given player states and events. + * Given bomb drop events must be conflict-free. * * @param players0 the previous player states * @param bombDropEvents the bomb drop events * @param bombs0 the previous bomb state * @return the newly dropped bombs */ - private static List newlyDroppedBombs( - List players0, - Set bombDropEvents, - List bombs0) { + private static List newlyDroppedBombs(List players0, Set bombDropEvents, List bombs0) { + Set bombedCells = GameState.bombedCells(bombs0).keySet(); + List bombs1 = new ArrayList<>(); - Set containingBombCells = new HashSet<>(); - for (Bomb bomb : bombs0) { - containingBombCells.add(bomb.position()); - } + for (Player p : GameState.alivePlayers(players0)) { + if (!bombDropEvents.contains(p.id())) continue; + if (bombedCells.contains(p.position().containingCell())) continue; - for (Player player : players0) { - if (bombDropEvents.contains(player.id()) && player.isAlive() && !containingBombCells.contains(player.position().containingCell())) { - Bomb newBomb = new Bomb(player.id(), player.position().containingCell(), Ticks.BOMB_FUSE_TICKS, player.bombRange()); - containingBombCells.add(newBomb.position()); - bombs1.add(newBomb); - } + Bomb b = new Bomb(p.id(), p.position().containingCell(), Ticks.BOMB_FUSE_TICKS, p.bombRange()); + bombedCells.add(b.position()); + bombs1.add(b); } + return bombs1; } -- cgit v1.2.3 From 7bf9f6e6195fa5c021871bd025cf8f4582a61fec Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Wed, 6 Apr 2016 23:51:09 +0200 Subject: Complete GameStatePrinter with bombs and blasts --- .../epfl/xblast/server/debug/GameStatePrinter.java | 49 ++++++++++++---------- 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/debug/GameStatePrinter.java b/src/ch/epfl/xblast/server/debug/GameStatePrinter.java index a846421..d81c6b9 100644 --- a/src/ch/epfl/xblast/server/debug/GameStatePrinter.java +++ b/src/ch/epfl/xblast/server/debug/GameStatePrinter.java @@ -1,12 +1,13 @@ package ch.epfl.xblast.server.debug; import ch.epfl.xblast.Cell; -import ch.epfl.xblast.server.Block; -import ch.epfl.xblast.server.Board; -import ch.epfl.xblast.server.GameState; -import ch.epfl.xblast.server.Player; +import ch.epfl.xblast.server.*; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; /** * Game state printer utility class that outputs the board to the terminal. @@ -17,7 +18,6 @@ import java.util.List; public final class GameStatePrinter { private enum ANSIColor { - BLACK(0), RED(1), GREEN(2), YELLOW(3), BLUE(4), MAGENTA(5), CYAN(6), WHITE(7); private static final String CSI = "\u001b["; @@ -40,31 +40,38 @@ public final class GameStatePrinter { public static void printGameState(GameState s) { printStats(s); - printBoard(s.board(), s.alivePlayers()); + printBoard(s.board(), s.alivePlayers(), s.bombedCells(), s.blastedCells()); } private static void printStats(GameState s) { System.out.println(s); } - private static void printBoard(Board b, List ps) { + private static void printBoard(Board b, List ps, Map bc, Set blastedCells) { + Map playerMap = ps.stream() + .collect(Collectors.toMap(p -> p.position().containingCell(), Function.identity())); + for (int y = 0; y < Cell.ROWS; ++y) { - xLoop: - for (int x = 0; x < Cell.COLUMNS; ++x) { - Cell c = new Cell(x, y); - for (Player p : ps) { - if (p.position().containingCell().equals(c)) { - System.out.print(stringForPlayer(p)); - continue xLoop; - } - } - Block block = b.blockAt(c); - System.out.print(stringForBlock(block)); - } + for (int x = 0; x < Cell.COLUMNS; ++x) + System.out.print(GameStatePrinter.stringForCellContent(new Cell(x, y), b, bc, playerMap, blastedCells)); + System.out.println(); } } + private static String stringForCellContent(Cell c, Board b, Map bc, Map p, Set blastedCells) { + if (bc.containsKey(c)) + return ANSIColor.RED.coloredText("@@"); + + if (p.containsKey(c)) + return GameStatePrinter.stringForPlayer(p.get(c)); + + if (blastedCells.contains(c)) + return ANSIColor.MAGENTA.coloredText("**"); + + return GameStatePrinter.stringForBlock(b.blockAt(c)); + } + private static String stringForPlayer(Player p) { StringBuilder b = new StringBuilder(); b.append(p.id().ordinal() + 1); @@ -87,8 +94,6 @@ public final class GameStatePrinter { private static String stringForBlock(Block b) { switch (b) { - case FREE: - return " "; case INDESTRUCTIBLE_WALL: return ANSIColor.BLACK.coloredText("##"); case DESTRUCTIBLE_WALL: @@ -100,7 +105,7 @@ public final class GameStatePrinter { case BONUS_RANGE: return ANSIColor.GREEN.coloredText("+r"); default: - throw new Error(); + return " "; } } -- cgit v1.2.3 From 182b0806bfa7d13ff3e79a99b876122fe9cd1219 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Thu, 7 Apr 2016 15:23:50 +0200 Subject: Fix bomb drop event filtering --- src/ch/epfl/xblast/server/GameState.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 3495af1..36709e9 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -248,8 +248,7 @@ public final class GameState { * @return the newly dropped bombs */ private static List newlyDroppedBombs(List players0, Set bombDropEvents, List bombs0) { - Set bombedCells = GameState.bombedCells(bombs0).keySet(); - + HashSet bombedCells = new HashSet<>(GameState.bombedCells(bombs0).keySet()); List bombs1 = new ArrayList<>(); for (Player p : GameState.alivePlayers(players0)) { @@ -511,7 +510,7 @@ public final class GameState { private Set discardConflictingBombDropEvents(Set bombDropEvents) { Map bombDropMap = this.mapTopPriorityPlayerCells( this.alivePlayers().stream() - .filter(bombDropEvents::contains) + .filter(p -> bombDropEvents.contains(p.id())) .collect(Collectors.toList()) ); -- cgit v1.2.3 From 552085b0fc886d93680bde42af14d1e161b33380 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Thu, 7 Apr 2016 16:14:59 +0200 Subject: Make nextBoard great again --- src/ch/epfl/xblast/server/Board.java | 9 ------ src/ch/epfl/xblast/server/GameState.java | 51 ++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/Board.java b/src/ch/epfl/xblast/server/Board.java index d7ca706..bff3ea8 100644 --- a/src/ch/epfl/xblast/server/Board.java +++ b/src/ch/epfl/xblast/server/Board.java @@ -143,13 +143,4 @@ public final class Board { return this.blocksAt(c).head(); } - /** - * Return the blocks of the Board. - * - * @return a list of the Sequences of blocks of the board. - */ - public List> getBlocks() { - List> immutableBlocks = Collections.unmodifiableList(new ArrayList<>(blocks)); - return immutableBlocks; - } } diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 36709e9..10b648b 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -120,29 +120,36 @@ public final class GameState { * @return the next board */ private static Board nextBoard(Board board0, Set consumedBonuses, Set blastedCells1) { - List> blocks0 = board0.getBlocks(); - List> blocks1 = new ArrayList<>(); - - int i = 0; - for (Sq blockSq : blocks0) { - int cellId = blocks0.get(i).hashCode(); - Block block = blockSq.head(); - if (consumedBonuses.contains(cellId) && block.isBonus()) { - blocks1.add(Sq.constant(Block.FREE)); - } else if (blastedCells1.contains(cellId) && (block == Block.DESTRUCTIBLE_WALL || block.isBonus())) { - if (block == Block.DESTRUCTIBLE_WALL) { - Block bonus = randomBonus(); - blocks1.add(Sq.repeat(Ticks.WALL_CRUMBLING_TICKS, Block.CRUMBLING_WALL).concat(Sq.constant(bonus))); - } else { - blocks1.add(Sq.repeat(Ticks.BONUS_DISAPPEARING_TICKS, block).concat(Sq.constant(Block.FREE))); - } - } else { - blocks1.add(blockSq.tail()); - } - i++; - } + return new Board(Cell.ROW_MAJOR_ORDER.stream() + .map(c -> GameState.nextBlockSeq(c, board0.blocksAt(c), consumedBonuses, blastedCells1)) + .collect(Collectors.toList())); + } + + /** + * Returns the next Block sequence for the given cell according to the current state and given events. + * + * @param c the Cell + * @param bs0 the previous Block sequence + * @param consumedBonuses the bonus consumption event + * @param blastedCells1 the new Cell blast events + * @return the new Block sequence + */ + private static Sq nextBlockSeq(Cell c, Sq bs0, Set consumedBonuses, Set blastedCells1) { + Block b = bs0.head(); + + if (consumedBonuses.contains(c) && b.isBonus()) + return Sq.constant(Block.FREE); + + if (blastedCells1.contains(c)) + if (b == Block.DESTRUCTIBLE_WALL) + return Sq.repeat(Ticks.WALL_CRUMBLING_TICKS, Block.CRUMBLING_WALL) + .concat(Sq.constant(GameState.randomBonus())); + + else if (b.isBonus()) + return Sq.repeat(Ticks.BONUS_DISAPPEARING_TICKS, b) + .concat(Sq.constant(Block.FREE)); - return new Board(blocks1); + return bs0.tail(); } /** -- cgit v1.2.3 From 8ce0ed0c2f2837641cc7de8c328a9182f8825f22 Mon Sep 17 00:00:00 2001 From: Timothée Floure Date: Thu, 7 Apr 2016 18:27:16 +0200 Subject: Fix nextPlayer blocking bombs + remove magic number for BOMB_BLOCKING_DISTANCE --- src/ch/epfl/xblast/server/Board.java | 6 +++++- src/ch/epfl/xblast/server/GameState.java | 7 +++---- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/Board.java b/src/ch/epfl/xblast/server/Board.java index bff3ea8..79259b5 100644 --- a/src/ch/epfl/xblast/server/Board.java +++ b/src/ch/epfl/xblast/server/Board.java @@ -16,6 +16,11 @@ import java.util.List; */ public final class Board { + /** + * Distance (in SubCells) from a bomb to block a player. + */ + public static final int BOMB_BLOCKING_DISTANCE = 6; + private static final int BLOCKS_LIST_SIZE = 195; private static final int BOARD_ROWS = 13; private static final int BOARD_COLUMNS = 15; @@ -45,7 +50,6 @@ public final class Board { * List containing all the blocks of the board. */ private List> blocks; - /** * Instantiates a new Board with the given sequence of blocks. * diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 10b648b..c9a23ac 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -200,12 +200,11 @@ public final class GameState { directedPositions1 = directedPositions1.tail(); // Check possible collisions and update the Sequence if necessary (kinda ugly right now) - Cell possiblyWalledCell = directedPositions1.tail().findFirst(dp -> dp.position().isCentral()).position().containingCell(); - if (!board1.blockAt(possiblyWalledCell).canHostPlayer()) { // if block non-free + 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 - } - if (bombedCells1.contains(player0.position().containingCell()) && player0.position().distanceToCentral() <= 6) { // Magic number ! 10 lashes for Fnux. + } 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 } -- cgit v1.2.3 From 3f322fd077aae6323ac162d5b6af5b1cfeda7d67 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Thu, 7 Apr 2016 22:12:35 +0200 Subject: Make explosions great again --- src/ch/epfl/xblast/server/GameState.java | 52 ++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index c9a23ac..31bb902 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -244,6 +244,33 @@ public final class GameState { .collect(Collectors.toList()); } + /** + * Returns a list of exploding bombs (reached by a blast or consumed fuse). + * + * @param bombs the list of bombs + * @param blastedCells the set of blasted cells + * @return the list of exploding bombs + */ + private static List explodingBombs(List bombs, Set blastedCells) { + return bombs.stream() + .filter(b -> blastedCells.contains(b.position()) || b.fuseLength() == 0) + .collect(Collectors.toList()); + } + + /** + * Computes the consumption of the bombs. + * + * @param bombs0 the list of bombs + * @param explodingBombs the list of exploding bombs + * @return the new bombs states + */ + private static List nextBombs(List bombs0, List explodingBombs) { + return bombs0.stream() + .filter(b -> !explodingBombs.contains(b)) + .map(b -> new Bomb(b.ownerId(), b.position(), b.fuseLengths().tail(), b.range())) + .collect(Collectors.toList()); + } + /** * Computes and returns the list of newly dropped bombs by players according to the given player states and events. * Given bomb drop events must be conflict-free. @@ -255,7 +282,7 @@ public final class GameState { */ private static List newlyDroppedBombs(List players0, Set bombDropEvents, List bombs0) { HashSet bombedCells = new HashSet<>(GameState.bombedCells(bombs0).keySet()); - List bombs1 = new ArrayList<>(); + List bombs1 = new ArrayList<>(bombs0); for (Player p : GameState.alivePlayers(players0)) { if (!bombDropEvents.contains(p.id())) continue; @@ -409,23 +436,23 @@ public final class GameState { // 4.1. existing bombs evolution Set blastedCells0 = this.blastedCells(); - List explodingBombs = this.filterExplodingBombs(this.bombs, blastedCells0); - List bombs = this.bombs.stream().filter(b -> !explodingBombs.contains(b)).collect(Collectors.toList()); + List explodingBombs = GameState.explodingBombs(this.bombs, blastedCells0); + List existingBombs = GameState.nextBombs(this.bombs, explodingBombs); // 4.2. subsequent explosions addition explodingBombs.forEach(b -> explosions1.addAll(b.explosion())); // 4.3. newly dropped bombs addition Set topPriorityBombDropEvents = discardConflictingBombDropEvents(bombDropEvents); - bombs.addAll(GameState.newlyDroppedBombs(this.players, topPriorityBombDropEvents, this.bombs)); + List bombs1 = GameState.newlyDroppedBombs(this.players, topPriorityBombDropEvents, existingBombs); // 5. players evolution Map playerBonuses = mapPlayersToBonuses(consumedBonuses); - Set bombedCells1 = GameState.bombedCells(bombs).keySet(); + Set bombedCells1 = GameState.bombedCells(bombs1).keySet(); List players1 = GameState.nextPlayers( this.players, playerBonuses, bombedCells1, board1, blastedCells1, speedChangeEvents); - return new GameState(this.ticks, board1, players1, bombs, explosions1, blasts1); + return new GameState(this.ticks, board1, players1, bombs1, explosions1, blasts1); } /** @@ -523,19 +550,6 @@ public final class GameState { return bombDropMap.isEmpty() ? EnumSet.noneOf(PlayerID.class) : EnumSet.copyOf(bombDropMap.values()); } - /** - * Returns a list of exploding bombs (reached by a blast or consumed fuse). - * - * @param bombs the list of bombs - * @param blastedCells the set of blasted cells - * @return the list of exploding bombs - */ - private List filterExplodingBombs(List bombs, Set blastedCells) { - return bombs.stream() - .filter(b -> blastedCells.contains(b.position()) || b.fuseLength() == 0) - .collect(Collectors.toList()); - } - @Override public String toString() { return "GameState{" + -- cgit v1.2.3 From 3dd23622d97b9fdd75c22554250a793a95b08a55 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Thu, 7 Apr 2016 22:27:18 +0200 Subject: Make indestructible walls great again --- src/ch/epfl/xblast/server/GameState.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 31bb902..c51afe7 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -104,11 +104,12 @@ public final class GameState { return Stream.concat( blasts0.stream() .filter(blastSeq -> !blastSeq.tail().isEmpty()) - .filter(blastSeq -> board0.blockAt(blastSeq.head()).isFree()) .map(Sq::tail), explosions0.stream() .map(Sq::head) - ).collect(Collectors.toList()); + ) + .filter(blastSeq -> board0.blockAt(blastSeq.head()).isFree()) + .collect(Collectors.toList()); } /** -- cgit v1.2.3 From 492ca4fe5b9b193948274419d6361c2829eb10bf Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Fri, 8 Apr 2016 11:35:08 +0200 Subject: Make player collisions great again --- src/ch/epfl/xblast/server/GameState.java | 48 +++++++++++++++------- .../epfl/xblast/server/debug/GameStatePrinter.java | 29 +++++++------ 2 files changed, 47 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index c51afe7..4ed1af5 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -473,13 +473,29 @@ public final class GameState { * @return the highest priority player */ private PlayerID resolveConflict(List claimants) { - if (claimants == null || claimants.isEmpty()) throw new IllegalArgumentException(); + if (claimants == null || claimants.isEmpty()) return null; - return this.currentPlayerPriorityOrder() - .stream() + return this.currentPlayerPriorityOrder().stream() .filter(claimants::contains) - .findFirst() - .get(); + .findFirst().get(); + } + + /** + * Resolves a conflict according to the current priority order. + * + * @param claimants the list of claimants + * @return the highest priority player + */ + public Player resolvePlayerConflict(List claimants) { + if (claimants == null || claimants.isEmpty()) return null; + + Map claimantsMap = claimants.stream() + .collect(Collectors.toMap(Player::id, Function.identity())); + + List claimantsIDs = claimants.stream() + .map(Player::id).collect(Collectors.toList()); + + return claimantsMap.get(this.resolveConflict(claimantsIDs)); } /** @@ -488,11 +504,11 @@ public final class GameState { * @param players a list of players to map * @return the location->player mapping */ - private Map> mapPlayersCells(List players) { + public Map> mapPlayersCells(List players) { return players.stream() .collect( Collectors.groupingBy(p -> p.position().containingCell(), - Collectors.mapping(Player::id, Collectors.toList()))); + Collectors.mapping(Function.identity(), Collectors.toList()))); } /** @@ -502,11 +518,11 @@ public final class GameState { * @param players a list of players to map * @return the location->top-priority player mapping */ - private Map mapTopPriorityPlayerCells(List players) { + private Map mapTopPriorityPlayerCells(List players) { return this.mapPlayersCells(players).entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, - e -> resolveConflict(e.getValue()))); + e -> resolvePlayerConflict(e.getValue()))); } /** @@ -519,7 +535,9 @@ public final class GameState { this.alivePlayers().stream() .filter(p -> p.position().isCentral()) .filter(p -> this.board.blockAt(p.position().containingCell()).isBonus()) - .collect(Collectors.toList())); + .collect(Collectors.toList())) + .entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().id())); } /** @@ -542,13 +560,13 @@ public final class GameState { * @return the conflict-free set of bomb drop events */ private Set discardConflictingBombDropEvents(Set bombDropEvents) { - Map bombDropMap = this.mapTopPriorityPlayerCells( + return this.mapTopPriorityPlayerCells( this.alivePlayers().stream() .filter(p -> bombDropEvents.contains(p.id())) - .collect(Collectors.toList()) - ); - - return bombDropMap.isEmpty() ? EnumSet.noneOf(PlayerID.class) : EnumSet.copyOf(bombDropMap.values()); + .collect(Collectors.toList())) + .values().stream() + .map(Player::id) + .collect(Collectors.toSet()); } @Override diff --git a/src/ch/epfl/xblast/server/debug/GameStatePrinter.java b/src/ch/epfl/xblast/server/debug/GameStatePrinter.java index d81c6b9..575b09a 100644 --- a/src/ch/epfl/xblast/server/debug/GameStatePrinter.java +++ b/src/ch/epfl/xblast/server/debug/GameStatePrinter.java @@ -1,13 +1,12 @@ package ch.epfl.xblast.server.debug; import ch.epfl.xblast.Cell; -import ch.epfl.xblast.server.*; +import ch.epfl.xblast.server.Block; +import ch.epfl.xblast.server.GameState; +import ch.epfl.xblast.server.Player; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; /** * Game state printer utility class that outputs the board to the terminal. @@ -40,36 +39,36 @@ public final class GameStatePrinter { public static void printGameState(GameState s) { printStats(s); - printBoard(s.board(), s.alivePlayers(), s.bombedCells(), s.blastedCells()); + printBoard(s); } private static void printStats(GameState s) { System.out.println(s); } - private static void printBoard(Board b, List ps, Map bc, Set blastedCells) { - Map playerMap = ps.stream() - .collect(Collectors.toMap(p -> p.position().containingCell(), Function.identity())); + private static void printBoard(GameState s) { + Map> playerMap = s.mapPlayersCells(s.alivePlayers()); for (int y = 0; y < Cell.ROWS; ++y) { for (int x = 0; x < Cell.COLUMNS; ++x) - System.out.print(GameStatePrinter.stringForCellContent(new Cell(x, y), b, bc, playerMap, blastedCells)); + System.out.print(GameStatePrinter.stringForCellContent(s, new Cell(x, y), playerMap)); System.out.println(); } } - private static String stringForCellContent(Cell c, Board b, Map bc, Map p, Set blastedCells) { - if (bc.containsKey(c)) + private static String stringForCellContent(GameState s, Cell c, Map> pl) { + if (s.bombedCells().containsKey(c)) return ANSIColor.RED.coloredText("@@"); - if (p.containsKey(c)) - return GameStatePrinter.stringForPlayer(p.get(c)); + Player p = s.resolvePlayerConflict(pl.get(c)); + if (p != null) + return GameStatePrinter.stringForPlayer(p); - if (blastedCells.contains(c)) + if (s.blastedCells().contains(c)) return ANSIColor.MAGENTA.coloredText("**"); - return GameStatePrinter.stringForBlock(b.blockAt(c)); + return GameStatePrinter.stringForBlock(s.board().blockAt(c)); } private static String stringForPlayer(Player p) { -- cgit v1.2.3 From 22b615543b70fd011f8e5e7ed9d8ae82654e5b0c Mon Sep 17 00:00:00 2001 From: Timothée Floure Date: Fri, 8 Apr 2016 11:48:47 +0200 Subject: Fix game duration --- src/ch/epfl/xblast/server/GameState.java | 2 +- src/ch/epfl/xblast/server/Ticks.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 4ed1af5..3df5ebd 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -453,7 +453,7 @@ public final class GameState { List players1 = GameState.nextPlayers( this.players, playerBonuses, bombedCells1, board1, blastedCells1, speedChangeEvents); - return new GameState(this.ticks, board1, players1, bombs1, explosions1, blasts1); + return new GameState(this.ticks + 1, board1, players1, bombs1, explosions1, blasts1); } /** diff --git a/src/ch/epfl/xblast/server/Ticks.java b/src/ch/epfl/xblast/server/Ticks.java index 3517491..b880dd7 100644 --- a/src/ch/epfl/xblast/server/Ticks.java +++ b/src/ch/epfl/xblast/server/Ticks.java @@ -53,7 +53,7 @@ public interface Ticks { /** * Duration of a game (in seconds). */ - int GAME_DURATION = 2; + int GAME_DURATION = 120; /** * Total number of ticks during a game. -- cgit v1.2.3 From 936267c0e4cd775c13cb72cc3df5c0e8f6765284 Mon Sep 17 00:00:00 2001 From: Timothée Floure Date: Fri, 8 Apr 2016 13:15:25 +0200 Subject: Fix nextBlast & crumbling walls --- src/ch/epfl/xblast/server/GameState.java | 46 +++++++++++++++++++------------- src/ch/epfl/xblast/server/Ticks.java | 1 - 2 files changed, 28 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 3df5ebd..a313eab 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -101,15 +101,20 @@ public final class GameState { * @return the position of the explosion's particles for the next state. */ private static List> nextBlasts(List> blasts0, Board board0, List>> explosions0) { - return Stream.concat( - blasts0.stream() - .filter(blastSeq -> !blastSeq.tail().isEmpty()) - .map(Sq::tail), - explosions0.stream() - .map(Sq::head) - ) - .filter(blastSeq -> board0.blockAt(blastSeq.head()).isFree()) - .collect(Collectors.toList()); + List> nextBlasts = new ArrayList<>(); + for(Sq blast : blasts0){ + Sq t = blast.tail(); + if(!t.isEmpty() && board0.blockAt(blast.head()).isFree()) + nextBlasts.add(t); + } + for(Sq> explosion : explosions0){ + if(explosion.isEmpty()) + continue; + Sq b = explosion.head(); + if(!b.isEmpty()) + nextBlasts.add(b); + } + return nextBlasts; } /** @@ -185,9 +190,9 @@ public final class GameState { } // Generate the new Sequence of Directed Positions (kinda ugly right now) - if (!player0.lifeState().canMove() && requestedDirection != null) { // if the player can't movex + if (!player0.lifeState().canMove() && requestedDirection != null) { // if the player can't move directedPositions1 = Player.DirectedPosition.stopped(player0.directedPositions().head()); - } else if (player0.direction().isParallelTo(requestedDirection)) { // if the player want to go to a parallel directionx + } else if (player0.direction().isParallelTo(requestedDirection)) { // if the player want to go to a parallel direction 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 @@ -201,18 +206,23 @@ public final class GameState { 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()); + if (player0.lifeState().canMove()) { + 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 + } + } else { + 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())) { + if (player0.lifeState().state() == Player.LifeState.State.VULNERABLE && blastedCells1.contains(directedPositions1.head().position().containingCell())) { lifeStates1 = player0.statesForNextLife(); } else { lifeStates1 = player0.lifeStates().tail(); diff --git a/src/ch/epfl/xblast/server/Ticks.java b/src/ch/epfl/xblast/server/Ticks.java index b880dd7..a4c3e74 100644 --- a/src/ch/epfl/xblast/server/Ticks.java +++ b/src/ch/epfl/xblast/server/Ticks.java @@ -34,7 +34,6 @@ public interface Ticks { * Duration of crumbling of a wall (in ticks). */ int WALL_CRUMBLING_TICKS = EXPLOSION_TICKS; - /** * Duration of the presence of a bonus (in ticks). */ -- cgit v1.2.3 From ba298420d7890412c42b671e387602c3fc240730 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Fri, 8 Apr 2016 13:16:59 +0200 Subject: Make shadows great again --- src/ch/epfl/xblast/server/GameState.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 3df5ebd..288aeb8 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java @@ -104,11 +104,10 @@ public final class GameState { return Stream.concat( blasts0.stream() .filter(blastSeq -> !blastSeq.tail().isEmpty()) + .filter(blastSeq -> board0.blockAt(blastSeq.head()).isFree()) .map(Sq::tail), explosions0.stream() - .map(Sq::head) - ) - .filter(blastSeq -> board0.blockAt(blastSeq.head()).isFree()) + .map(Sq::head)) .collect(Collectors.toList()); } -- cgit v1.2.3 From 95348e4ca6fa0e0a1bd88bb2a9061c3154d5beb1 Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Fri, 8 Apr 2016 13:26:25 +0200 Subject: Reformat code --- src/ch/epfl/xblast/server/Ticks.java | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ch/epfl/xblast/server/Ticks.java b/src/ch/epfl/xblast/server/Ticks.java index a4c3e74..b880dd7 100644 --- a/src/ch/epfl/xblast/server/Ticks.java +++ b/src/ch/epfl/xblast/server/Ticks.java @@ -34,6 +34,7 @@ public interface Ticks { * Duration of crumbling of a wall (in ticks). */ int WALL_CRUMBLING_TICKS = EXPLOSION_TICKS; + /** * Duration of the presence of a bonus (in ticks). */ -- cgit v1.2.3 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') 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 = speedCha