aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ch/epfl/xblast/server/GameState.java200
-rw-r--r--src/ch/epfl/xblast/server/Player.java11
2 files changed, 144 insertions, 67 deletions
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 {
165 * @param speedChangeEvents the speed change events 165 * @param speedChangeEvents the speed change events
166 * @return the next player list 166 * @return the next player list
167 */ 167 */
168 private static List<Player> nextPlayers( 168 private static List<Player> nextPlayers(List<Player> players0, Map<PlayerID, Bonus> playerBonuses,
169 List<Player> players0, 169 Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1,
170 Map<PlayerID, Bonus> playerBonuses, 170 Map<PlayerID, Optional<Direction>> speedChangeEvents) {
171 Set<Cell> bombedCells1, 171
172 Board board1, 172 return players0.stream()
173 Set<Cell> blastedCells1, 173 .map(p -> {
174 Map<PlayerID, Optional<Direction>> speedChangeEvents) { 174 Optional<Direction> speedChangeEvent = speedChangeEvents.get(p.id());
175 List<Player> players1 = new ArrayList<>(); 175 Direction requestedDirection = speedChangeEvent != null ? speedChangeEvent.orElse(null) : null;
176 176 return GameState.nextPlayer(p, playerBonuses.get(p.id()), bombedCells1, board1, blastedCells1, requestedDirection);
177 for (Player player0 : players0) { 177 })
178 Optional<Direction> event = speedChangeEvents.get(player0.id()); 178 .collect(Collectors.toList());
179 // By default the path won't change 179 }
180 Sq<Player.DirectedPosition> directedPositions1 = player0.directedPositions(); 180
181 181 private static Player nextPlayer(Player players0, Bonus playerBonus,
182 // Get the (possibly) requested direction 182 Set<Cell> bombedCells1, Board board1, Set<Cell> blastedCells1,
183 Direction requestedDirection = null; 183 Direction requestedDirection) {
184 if (event != null) { 184
185 requestedDirection = event.orElse(null); 185 Sq<Player.DirectedPosition> directedPositions1 = GameState.nextPath(players0, requestedDirection);
186 } 186
187 187 // Advance of one SubCell on the player's path
188 // Generate the new Sequence of Directed Positions (kinda ugly right now) 188 directedPositions1 = directedPositions1.tail();
189 if (!player0.lifeState().canMove() && requestedDirection != null) { // if the player can't movex 189
190 directedPositions1 = Player.DirectedPosition.stopped(player0.directedPositions().head()); 190 //Check possible collisions and update the Sequence if necessary (kinda ugly right now)
191 } else if (player0.direction().isParallelTo(requestedDirection)) { // if the player want to go to a parallel directionx 191 directedPositions1 = GameState.handleCollisions(players0, directedPositions1, board1, bombedCells1);
192 Player.DirectedPosition requestedDirectedPosition = new Player.DirectedPosition(player0.position(), requestedDirection); 192
193 directedPositions1 = Player.DirectedPosition.moving(requestedDirectedPosition); 193 // Apply damages and generate a new LifeState Sequence
194 } else if (player0.direction().isPerpendicularTo(requestedDirection)) { // if the player want to go to a perpendicular direction 194 Sq<Player.LifeState> lifeStates1 = GameState.nextLifeState(players0, directedPositions1, blastedCells1);
195 Player.DirectedPosition nextCentralSubCell = player0.directedPositions().findFirst(dp -> dp.position().isCentral()); 195
196 Sq<Player.DirectedPosition> toNextCentralSubCell = player0.directedPositions().takeWhile(dp -> !dp.position().isCentral()); 196 // Create the new player given the new parameters
197 Sq<Player.DirectedPosition> pastNextCentralSubCell = Player.DirectedPosition.moving(new Player.DirectedPosition(nextCentralSubCell.position(), requestedDirection)); 197 Player p1 = new Player(players0.id(), lifeStates1, directedPositions1, players0.maxBombs(), players0.bombRange());
198 directedPositions1 = toNextCentralSubCell.concat(pastNextCentralSubCell); 198
199 } 199 // Update the capacities of the player given the possible bonus
200 200 if (playerBonus != null)
201 // Advance of one SubCell on the player's path 201 p1 = playerBonus.applyTo(p1);
202 directedPositions1 = directedPositions1.tail(); 202
203 203 return p1;
204 // Check possible collisions and update the Sequence if necessary (kinda ugly right now) 204 }
205 Cell possiblyBlockingCell = directedPositions1.tail().findFirst(dp -> dp.position().isCentral()).position().containingCell(); 205
206 if (!board1.blockAt(possiblyBlockingCell).canHostPlayer()) { // if block non-free 206 /**
207 Sq<Player.DirectedPosition> actualDirectedPosition = Sq.repeat(1 , player0.directedPositions().head()); 207 * Generate the new Sequence of Directed Positions.
208 directedPositions1 = actualDirectedPosition.concat(directedPositions1); // won't move for a tick 208 *
209 } else if (bombedCells1.contains(possiblyBlockingCell) && possiblyBlockingCell.equals(player0.position().containingCell()) && player0.position().distanceToCentral() == Board.BOMB_BLOCKING_DISTANCE) { 209 * @param player0
210 Sq<Player.DirectedPosition> actualDirectedPosition = Sq.repeat(1 , player0.directedPositions().head()); 210 * @param requestedDirection
211 directedPositions1 = actualDirectedPosition.concat(directedPositions1); // won't move for a tick 211 * @return
212 } 212 */
213 213 private static Sq<Player.DirectedPosition> nextPath(Player player0, Direction requestedDirection) {
214 // Apply damages and generate a new LifeState Sequence 214 if (!player0.lifeState().canMove())
215 Sq<Player.LifeState> lifeStates1; 215 return Player.DirectedPosition.stopped(player0.directedPositions().head());
216 if (player0.lifeState().state() == Player.LifeState.State.VULNERABLE && blastedCells1.contains(directedPositions1.head().position())) { 216
217 lifeStates1 = player0.statesForNextLife(); 217 if (requestedDirection == null)
218 } else { 218 requestedDirection = player0.direction();
219 lifeStates1 = player0.lifeStates().tail(); 219
220 } 220 if (player0.direction().isParallelTo(requestedDirection))
221 221 return Player.DirectedPosition.moving(new Player.DirectedPosition(player0.position(), requestedDirection));
222 // Create the new player given the new parameters 222
223 Player player1 = new Player(player0.id(), lifeStates1, directedPositions1, player0.maxBombs(), player0.bombRange()); 223 if (player0.direction().isPerpendicularTo(requestedDirection)) {
224 224 Player.DirectedPosition nextCentralSubCell = GameState.projectedDirectedPosition(player0, player0.directedPositions());
225 // Update the capacities of the player given the possible bonus 225 Sq<Player.DirectedPosition> toNextCentralSubCell = player0.directedPositions().takeWhile(dp -> !dp.position().isCentral());
226 if (playerBonuses.containsKey(player0.id())) { 226 Player.DirectedPosition centralSubCellDirectedPosition = new Player.DirectedPosition(nextCentralSubCell.position(), requestedDirection);
227 player1 = playerBonuses.get(player0.id()).applyTo(player1); 227 Sq<Player.DirectedPosition> pastNextCentralSubCell = Player.DirectedPosition.moving(centralSubCellDirectedPosition);
228 } 228 return toNextCentralSubCell.concat(pastNextCentralSubCell);
229
230 // Add the newly generated player to the returned list
231 players1.add(player1);
232 } 229 }
233 return players1; 230
231 return player0.directedPositions();
232 }
233
234 /**
235 * Check possible collisions and update the Sequence if necessary (kinda ugly right now)
236 *
237 * @param player0
238 * @param projectedPath
239 * @param board1
240 * @param bombedCells1
241 * @return
242 */
243 private static Sq<Player.DirectedPosition> handleCollisions(Player player0,
244 Sq<Player.DirectedPosition> projectedPath,
245 Board board1, Set<Cell> bombedCells1) {
246
247 Cell projectedCell = GameState.projectedDirectedPosition(player0, projectedPath).position().containingCell();
248 if (GameState.isColliding(player0, projectedCell, board1, bombedCells1))
249 return Sq.repeat(1, player0.directedPositions().head())
250 .concat(projectedPath);
251
252 return projectedPath;
253 }
254
255 /**
256 * @param player0
257 * @param projectedPath
258 * @return
259 */
260
261 private static Player.DirectedPosition projectedDirectedPosition(Player player0, Sq<Player.DirectedPosition> projectedPath) {
262 if (!player0.lifeState().canMove())
263 return new Player.DirectedPosition(player0.position(), player0.direction());
264
265 return projectedPath.tail()
266 .findFirst(directedPos -> directedPos.position().isCentral());
267 }
268
269 /**
270 * @param player0
271 * @param projectedCell
272 * @param board1
273 * @param bombedCells1
274 * @return
275 */
276 private static boolean isColliding(Player player0, Cell projectedCell, Board board1, Set<Cell> bombedCells1) {
277 if (!board1.blockAt(projectedCell).canHostPlayer())
278 return true;
279
280 if (bombedCells1.contains(projectedCell) && projectedCell.equals(player0.position().containingCell()))
281 if (player0.position().distanceToCentral() <= Board.BOMB_BLOCKING_DISTANCE)
282 return true;
283
284 return false;
285 }
286
287 /**
288 * Apply damages and generate a new LifeState Sequence
289 *
290 * @param player0
291 * @param directedPositions1
292 * @param blastedCells1
293 * @return
294 */
295 private static Sq<Player.LifeState> nextLifeState(Player player0, Sq<Player.DirectedPosition> directedPositions1,
296 Set<Cell> blastedCells1) {
297
298 Cell currentCell = directedPositions1.head().position().containingCell();
299
300 if (player0.isVulnerable() && blastedCells1.contains(currentCell))
301 return player0.statesForNextLife();
302 else
303 return player0.lifeStates().tail();
234 } 304 }
235 305
236 /** 306 /**
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 {
238 238
239 int newLives = lives() - 1; 239 int newLives = lives() - 1;
240 240
241 if (newLives >= 0) { 241 if (newLives <= 0) {
242 LifeState dead = new LifeState(newLives, LifeState.State.DEAD); 242 LifeState dead = new LifeState(newLives, LifeState.State.DEAD);
243 nextLifeState = nextLifeState.concat(Sq.constant(dead)); 243 nextLifeState = nextLifeState.concat(Sq.constant(dead));
244 } else { 244 } else {
@@ -260,6 +260,13 @@ public final class Player {
260 } 260 }
261 261
262 /** 262 /**
263 * @return the vulnerability state of the player
264 */
265 public boolean isVulnerable() {
266 return this.lifeState().state() == LifeState.State.VULNERABLE;
267 }
268
269 /**
263 * @return the current number of lives of the player 270 * @return the current number of lives of the player
264 */ 271 */
265 public int lives() { 272 public int lives() {
@@ -270,7 +277,7 @@ public final class Player {