aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ch/epfl/xblast/Direction.java19
-rw-r--r--src/ch/epfl/xblast/server/Board.java17
-rw-r--r--src/ch/epfl/xblast/server/GameState.java353
-rw-r--r--src/ch/epfl/xblast/server/Player.java22
-rw-r--r--src/ch/epfl/xblast/server/Ticks.java2
-rw-r--r--src/ch/epfl/xblast/server/debug/GameStatePrinter.java78
-rw-r--r--src/ch/epfl/xblast/server/debug/RandomEventGenerator.java50
-rw-r--r--test/ch/epfl/xblast/server/BoardTest.java21
-rw-r--r--test/ch/epfl/xblast/simulation/RandomSimulation.java80
9 files changed, 516 insertions, 126 deletions
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
@@ -68,6 +68,25 @@ public enum Direction {
68 } 68 }
69 69
70 /** 70 /**
71 * T(the current and given Directions are perpendicular).
72 *
73 * @param that a Direction to compare
74 * @return T(the current and given Directions are perpendicular)
75 */
76 public boolean isPerpendicularTo(Direction that) {
77 switch (this) {
78 case N:
79 case S:
80 return that == E || that == W;
81 case E:
82 case W:
83 return that == N || that == S;
84 default:
85 return false;
86 }
87 }
88
89 /**
71 * Returns the x-coordinate of the normed vector representation of the Direction. 90 * Returns the x-coordinate of the normed vector representation of the Direction.
72 * 91 *
73 * @return the x-coordinate 92 * @return the x-coordinate
diff --git a/src/ch/epfl/xblast/server/Board.java b/src/ch/epfl/xblast/server/Board.java
index f2a3c89..79259b5 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;
5import ch.epfl.xblast.Lists; 5import ch.epfl.xblast.Lists;
6 6
7import java.util.ArrayList; 7import java.util.ArrayList;
8import java.util.Collections;
8import java.util.List; 9import java.util.List;
9 10
10/** 11/**
@@ -15,6 +16,11 @@ import java.util.List;
15 */ 16 */
16public final class Board { 17public final class Board {
17 18
19 /**
20 * Distance (in SubCells) from a bomb to block a player.
21 */
22 public static final int BOMB_BLOCKING_DISTANCE = 6;
23
18 private static final int BLOCKS_LIST_SIZE = 195; 24 private static final int BLOCKS_LIST_SIZE = 195;
19 private static final int BOARD_ROWS = 13; 25 private static final int BOARD_ROWS = 13;
20 private static final int BOARD_COLUMNS = 15; 26 private static final int BOARD_COLUMNS = 15;
@@ -44,7 +50,6 @@ public final class Board {
44 * List containing all the blocks of the board. 50 * List containing all the blocks of the board.
45 */ 51 */
46 private List<Sq<Block>> blocks; 52 private List<Sq<Block>> blocks;
47
48 /** 53 /**
49 * Instantiates a new Board with the given sequence of blocks. 54 * Instantiates a new Board with the given sequence of blocks.
50 * 55 *
@@ -55,7 +60,7 @@ public final class Board {
55 if (blocks == null || blocks.size() != BLOCKS_LIST_SIZE) 60 if (blocks == null || blocks.size() != BLOCKS_LIST_SIZE)
56 throw new IllegalArgumentException(); 61 throw new IllegalArgumentException();
57 62
58 this.blocks = blocks; 63 this.blocks = new ArrayList<>(blocks);
59 } 64 }
60 65
61 /** 66 /**
@@ -142,12 +147,4 @@ public final class Board {
142 return this.blocksAt(c).head(); 147 return this.blocksAt(c).head();
143 } 148 }
144 149
145 /**
146 * Return the blocks of the Board.
147 *
148 * @return a list of the Sequences of blocks of the board.
149 */
150 public List<Sq<Block>> getBlocks() {
151 return blocks;
152 }
153} 150}
diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java
index 1abe17a..0d381db 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;
8import java.util.stream.Collectors; 8import java.util.stream.Collectors;
9import java.util.stream.Stream; 9import java.util.stream.Stream;
10 10
11
11/** 12/**
12 * GameState representing the current game state. 13 * GameState representing the current game state.
13 * 14 *
@@ -102,12 +103,14 @@ public final class GameState {
102 private static List<Sq<Cell>> nextBlasts(List<Sq<Cell>> blasts0, Board board0, List<Sq<Sq<Cell>>> explosions0) { 103 private static List<Sq<Cell>> nextBlasts(List<Sq<Cell>> blasts0, Board board0, List<Sq<Sq<Cell>>> explosions0) {
103 return Stream.concat( 104 return Stream.concat(
104 blasts0.stream() 105 blasts0.stream()
105 .filter(blastSeq -> !blastSeq.tail().isEmpty()) 106 .filter(b -> !b.tail().isEmpty())
106 .filter(blastSeq -> board0.blockAt(blastSeq.head()).isFree()) 107 .filter(b -> board0.blockAt(b.head()).isFree())
107 .map(Sq::tail), 108 .map(Sq::tail),
108 explosions0.stream() 109 explosions0.stream()
110 .filter(e -> !e.isEmpty())
109 .map(Sq::head) 111 .map(Sq::head)
110 ).collect(Collectors.toList()); 112 .filter(b -> !b.isEmpty()))
113 .collect(Collectors.toList());
111 } 114 }
112 115
113 /** 116 /**
@@ -119,29 +122,36 @@ public final class GameState {
119 * @return the next board 122 * @return the next board
120 */ 123 */
121 private static Board nextBoard(Board board0, Set<Cell> consumedBonuses, Set<Cell> blastedCells1) { 124 private static Board nextBoard(Board board0, Set<Cell> consumedBonuses, Set<Cell> blastedCells1) {
122 List<Sq<Block>> blocks0 = board0.getBlocks(); 125 return new Board(Cell.ROW_MAJOR_ORDER.stream()
123 List<Sq<Block>> blocks1 = new ArrayList<>(); 126 .map(c -> GameState.nextBlockSeq(c, board0.blocksAt(c), consumedBonuses, blastedCells1))
124 127 .collect(Collectors.toList()));
125 int i = 0; 128 }
126 for (Sq<Block> blockSq : blocks0) {
127 int cellId = blocks0.get(i).hashCode();
128 Block block = blockSq.head();
129 if (((HashSet) consumedBonuses).contains(cellId) && block.isBonus()) {
130 blocks1.add(Sq.constant(Block.FREE));
131 } else if (((HashSet) blastedCells1).contains(cellId) && (block == Block.DESTRUCTIBLE_WALL || block.isBonus())) {
132 if (block == Block.DESTRUCTIBLE_WALL) {
133 Block bonus = randomBonus();
134 blocks1.add(Sq.repeat(Ticks.WALL_CRUMBLING_TICKS, Block.CRUMBLING_WALL).concat(Sq.constant(bonus)));
135 } else {
136 blocks1.add(Sq.repeat(Ticks.BONUS_DISAPPEARING_TICKS, block).concat(Sq.constant(Block.FREE)));
137 }
138 } else {
139 blocks1.add(blockSq.tail());
140 }
141 i++;
142 }
143 129
144 return new Board(blocks1); 130 /**
131 * Returns the next Block sequence for the given cell according to the current state and given events.
132 *
133 * @param c the Cell
134 * @param bs0 the previous Block sequence
135 * @param consumedBonuses the bonus consumption event
136 * @param blastedCells1 the new Cell blast events
137 * @return the new Block sequence
138 */
139 private static Sq<Block> nextBlockSeq(Cell c, Sq<Block> bs0, Set<Cell> consumedBonuses, Set<Cell> blastedCells1) {
140 Block b = bs0.head();
141
142 if (consumedBonuses.contains(c) && b.isBonus())
143 return Sq.constant(Block.FREE);
144
145 if (blastedCells1.contains(c))
146 if (b == Block.DESTRUCTIBLE_WALL)
147 return Sq.repeat(Ticks.WALL_CRUMBLING_TICKS, Block.CRUMBLING_WALL)
148 .concat(Sq.constant(GameState.randomBonus()));
149
150 else if (b.isBonus())
151 return Sq.repeat(Ticks.BONUS_DISAPPEARING_TICKS, b)
152 .concat(Sq.constant(Block.FREE));
153
154 return bs0.tail();
145 } 155 }
146 156
147 /** 157 /**
@@ -155,15 +165,142 @@ public final class GameState {
155 * @param speedChangeEvents the speed change events 165 * @param speedChangeEvents the speed change events
156 * @return the next player list 166 * @return the next player list
157 */ 167 */
158 private static List<Player> nextPlayers( 168 private static List<Player> nextPlayers(List<Player> players0, Map<PlayerID, Bonus> playerBonuses,
159 List<Player> players0, 169 Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1,
160 Map<PlayerID, Bonus> playerBonuses, 170 Map<PlayerID, Optional<Direction>> speedChangeEvents) {
161 Set<Cell> bombedCells1, 171
162 Board board1, 172 return players0.stream()
163 Set<Cell> blastedCells1, 173 .map(p -> {
164 Map<PlayerID, Optional<Direction>> speedChangeEvents) { 174 Optional<Direction> speedChangeEvent = speedChangeEvents.get(p.id());
165 //ToDo 175 Direction requestedDirection = speedChangeEvent != null ? speedChangeEvent.orElse(null) : null;
166 return players0; 176 return GameState.nextPlayer(p, playerBonuses.get(p.id()), bombedCells1, board1, blastedCells1, requestedDirection);
177 })
178 .collect(Collectors.toList());
179 }
180
181 private static Player nextPlayer(Player players0, Bonus playerBonus,
182 Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1,
183 Direction requestedDirection) {
184
185 Sq<Player.DirectedPosition> directedPositions1 = GameState.nextPath(players0, requestedDirection);
186
187 // Advance of one SubCell on the player's path
188 directedPositions1 = directedPositions1.tail();
189