diff options
Diffstat (limited to 'src/ch')
-rw-r--r-- | src/ch/epfl/xblast/server/GameState.java | 112 |
1 files changed, 111 insertions, 1 deletions
diff --git a/src/ch/epfl/xblast/server/GameState.java b/src/ch/epfl/xblast/server/GameState.java index 5386311..522a367 100644 --- a/src/ch/epfl/xblast/server/GameState.java +++ b/src/ch/epfl/xblast/server/GameState.java | |||
@@ -295,7 +295,36 @@ public final class GameState { | |||
295 | * @return the next game state | 295 | * @return the next game state |
296 | */ | 296 | */ |
297 | public GameState next(Map<PlayerID, Optional<Direction>> speedChangeEvents, Set<PlayerID> bombDropEvents) { | 297 | public GameState next(Map<PlayerID, Optional<Direction>> speedChangeEvents, Set<PlayerID> bombDropEvents) { |
298 | return null; // TODO | 298 | // 1. blasts evolution |
299 | List<Sq<Cell>> blasts1 = GameState.nextBlasts(this.blasts, this.board, this.explosions); | ||
300 | |||
301 | // 2. board evolution | ||
302 | Set<Cell> blastedCells1 = GameState.blastedCells(blasts1); | ||
303 | Map<Cell, PlayerID> consumedBonuses = this.consumedBonuses(); | ||
304 | Board board1 = GameState.nextBoard(this.board, consumedBonuses.keySet(), blastedCells1); | ||
305 | |||
306 | // 3. existing explosions evolution | ||
307 | List<Sq<Sq<Cell>>> explosions1 = GameState.nextExplosions(this.explosions); | ||
308 | |||
309 | // 4.1. existing bombs evolution | ||
310 | Set<Cell> blastedCells0 = this.blastedCells(); | ||
311 | List<Bomb> explodingBombs = this.filterExplodingBombs(this.bombs, blastedCells0); | ||
312 | List<Bomb> bombs = this.bombs.stream().filter(b -> !explodingBombs.contains(b)).collect(Collectors.toList()); | ||
313 | |||
314 | // 4.2. subsequent explosions addition | ||
315 | explodingBombs.forEach(b -> explosions1.addAll(b.explosion())); | ||
316 | |||
317 | // 4.3. newly dropped bombs addition | ||
318 | Set<PlayerID> topPriorityBombDropEvents = discardConflictingBombDropEvents(bombDropEvents); | ||
319 | bombs.addAll(GameState.newlyDroppedBombs(this.players, topPriorityBombDropEvents, this.bombs)); | ||
320 | |||
321 | // 5. players evolution | ||
322 | Map<PlayerID, Bonus> playerBonuses = mapPlayersToBonuses(consumedBonuses); | ||
323 | Set<Cell> bombedCells1 = GameState.bombedCells(bombs).keySet(); | ||
324 | List<Player> players1 = GameState.nextPlayers( | ||
325 | this.players, playerBonuses, bombedCells1, board1, blastedCells1, speedChangeEvents); | ||
326 | |||
327 | return new GameState(this.ticks, board1, players1, bombs, explosions1, blasts1); | ||
299 | } | 328 | } |
300 | 329 | ||
301 | /** | 330 | /** |
@@ -324,4 +353,85 @@ public final class GameState { | |||
324 | .get(); | 353 | .get(); |
325 | } | 354 | } |
326 | 355 | ||
356 | /** | ||
357 | * Returns a mapping of players from their location. | ||
358 | * | ||
359 | * @param players a list of players to map | ||
360 | * @return the location->player mapping | ||
361 | */ | ||
362 | private Map<Cell, List<PlayerID>> mapPlayersCells(List<Player> players) { | ||
363 | return players.stream() | ||
364 | .collect( | ||
365 | Collectors.groupingBy(p -> p.position().containingCell(), | ||
366 | Collectors.mapping(Player::id, Collectors.toList()))); | ||
367 | } | ||
368 | |||
369 | /** | ||
370 | * Returns a mapping of top-priority player from their location. | ||
371 | * Conflicts are resolved using the current turn's players priority order. | ||
372 | * | ||
373 | * @param players a list of players to map | ||
374 | * @return the location->top-priority player mapping | ||
375 | */ | ||
376 | private Map<Cell, PlayerID> mapTopPriorityPlayerCells(List<Player> players) { | ||
377 | return this.mapPlayersCells(players).entrySet().stream() | ||
378 | .collect(Collectors.toMap( | ||
379 | Map.Entry::getKey, | ||
380 | e -> resolveConflict(e.getValue()))); | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * Returns a mapping of location of consumed bonuses and their top-priority claimant. | ||
385 | * | ||
386 | * @return the bonus-location->player mapping | ||
387 | */ | ||
388 | private Map<Cell, PlayerID> consumedBonuses() { | ||
389 | return this.mapTopPriorityPlayerCells( | ||
390 | this.alivePlayers().stream() | ||
391 | .filter(p -> p.position().isCentral()) | ||
392 | .filter(p -> this.board.blockAt(p.position().containingCell()).isBonus()) | ||
393 | .collect(Collectors.toList())); | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * Returns a mapping of players and their newly acquired bonus. | ||
398 | * | ||
399 | * @param consumedBonuses a mapping of bonus location and their claimants | ||
400 | * @return the player->bonus mapping | ||
401 | */ | ||
402 | private Map<PlayerID, Bonus> mapPlayersToBonuses(Map<Cell, PlayerID> consumedBonuses) { | ||
403 | return consumedBonuses.entrySet().stream() | ||
404 | .collect(Collectors.toMap( | ||
405 | Map.Entry::getValue, | ||
406 | e -> this.board.blockAt(e.getKey()).associatedBonus())); | ||
407 | } | ||
408 | |||
409 | /** | ||
410 | * Returns a conflict-free set a player bomb dropping events. | ||
411 | * | ||
412 | * @param bombDropEvents the bomb drop events to filter | ||
413 | * @return the conflict-free set of bomb drop events | ||
414 | */ | ||
415 | private Set<PlayerID> discardConflictingBombDropEvents(Set<PlayerID> bombDropEvents) { | ||
416 | return EnumSet.copyOf( | ||
417 | this.mapTopPriorityPlayerCells( | ||
418 | this.alivePlayers().stream() | ||
419 | .filter(bombDropEvents::contains) | ||
420 | .collect(Collectors.toList()) | ||
421 | ).values()); | ||
422 | } | ||
423 | |||
424 | /** | ||
425 | * Returns a list of exploding bombs (reached by a blast or consumed fuse). | ||
426 | * | ||
427 | * @param bombs the list of bombs | ||
428 | * @param blastedCells the set of blasted cells | ||
429 | * @return the list of exploding bombs | ||
430 | */ | ||
431 | private List<Bomb> filterExplodingBombs(List<Bomb> bombs, Set<Cell> blastedCells) { | ||
432 | return bombs.stream() | ||
433 | .filter(b -> blastedCells.contains(b.position()) || b.fuseLength() == 0) | ||
434 | .collect(Collectors.toList()); | ||
435 | } | ||
436 | |||
327 | } | 437 | } |