diff options
-rw-r--r-- | src/ch/epfl/xblast/RunLengthEncoder.java | 34 | ||||
-rw-r--r-- | src/ch/epfl/xblast/server/GameStateSerializer.java | 90 | ||||
-rw-r--r-- | src/ch/epfl/xblast/server/Level.java | 134 | ||||
-rw-r--r-- | test/ch/epfl/xblast/GameStateSerializerTest.java | 39 |
4 files changed, 297 insertions, 0 deletions
diff --git a/src/ch/epfl/xblast/RunLengthEncoder.java b/src/ch/epfl/xblast/RunLengthEncoder.java new file mode 100644 index 0000000..a3c8a88 --- /dev/null +++ b/src/ch/epfl/xblast/RunLengthEncoder.java | |||
@@ -0,0 +1,34 @@ | |||
1 | package ch.epfl.xblast; | ||
2 | |||
3 | import java.util.ArrayList; | ||
4 | import java.util.List; | ||
5 | |||
6 | /** | ||
7 | * @author Timothée FLOURE (257420) | ||
8 | */ | ||
9 | public final class RunLengthEncoder { | ||
10 | |||
11 | /** | ||
12 | * Encode the given Byte sequence using the run length encoding. | ||
13 | * | ||
14 | * @param input the given byte sequence | ||
15 | * @return the encoded byte sequence | ||
16 | */ | ||
17 | public static List<Byte> encode(List<Byte> input) { | ||
18 | List<Byte> output = new ArrayList<>(); | ||
19 | |||
20 | return output; | ||
21 | } | ||
22 | |||
23 | /** | ||
24 | * Decode the given Byte sequence using the run length encoding. | ||
25 | * | ||
26 | * @param input the given encoded byte sequence | ||
27 | * @return the decoded byte sequence | ||
28 | */ | ||
29 | public static List<Byte> decode(List<Byte> input) { | ||
30 | List<Byte> output = new ArrayList<>(); | ||
31 | |||
32 | return output; | ||
33 | } | ||
34 | } | ||
diff --git a/src/ch/epfl/xblast/server/GameStateSerializer.java b/src/ch/epfl/xblast/server/GameStateSerializer.java new file mode 100644 index 0000000..4a133e5 --- /dev/null +++ b/src/ch/epfl/xblast/server/GameStateSerializer.java | |||
@@ -0,0 +1,90 @@ | |||
1 | package ch.epfl.xblast.server; | ||
2 | |||
3 | import ch.epfl.xblast.Cell; | ||
4 | import ch.epfl.xblast.Direction; | ||
5 | import ch.epfl.xblast.RunLengthEncoder; | ||
6 | import ch.epfl.xblast.server.painter.*; | ||
7 | |||
8 | import java.util.*; | ||
9 | import java.util.stream.Collectors; | ||
10 | |||
11 | /** | ||
12 | * @author Timothée FLOURE (257420) | ||
13 | */ | ||
14 | public final class GameStateSerializer { | ||
15 | |||
16 | /** | ||
17 | * @param painter | ||
18 | * @param board | ||
19 | * @return | ||
20 | */ | ||
21 | private static List<Byte> serializeBoard(BoardPainter painter, Board board) { | ||
22 | return RunLengthEncoder.encode(Cell.SPIRAL_ORDER.stream() | ||
23 | .map(c -> painter.byteForCell(board, c)) | ||
24 | .collect(Collectors.toList())); | ||
25 | } | ||
26 | |||
27 | private static byte serializeBlast(Set<Cell> blastedCells, Cell cell) { | ||
28 | return ExplosionPainter.byteForBlast( | ||
29 | blastedCells.contains(cell.neighbor(Direction.N)), | ||
30 | blastedCells.contains(cell.neighbor(Direction.E)), | ||
31 | blastedCells.contains(cell.neighbor(Direction.S)), | ||
32 | blastedCells.contains(cell.neighbor(Direction.W))); | ||
33 | } | ||
34 | |||
35 | private static byte serializeExplosion(Map<Cell, Bomb> bombedCells, Set<Cell> blastedCells, Cell cell) { | ||
36 | if (bombedCells.containsKey(cell)) | ||
37 | return ExplosionPainter.byteForBomb(bombedCells.get(cell)); | ||
38 | else | ||
39 | return serializeBlast(blastedCells, cell); | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * @param bombedCells | ||
44 | * @param blastedCells | ||
45 | * @return | ||
46 | */ | ||
47 | private static List<Byte> serializeExplosions(Map<Cell, Bomb> bombedCells, Set<Cell> blastedCells) { | ||
48 | return RunLengthEncoder.encode(Cell.ROW_MAJOR_ORDER.stream() | ||
49 | .map(c -> serializeExplosion(bombedCells, blastedCells, c)) | ||
50 | .collect(Collectors.toList())); | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * Serialize a whole game state. | ||
55 | * | ||
56 | * @param boardPainter board painter related to the actual level | ||
57 | * @param gameState GameState to be serialized | ||
58 | * @return the serialized game state | ||
59 | */ | ||
60 | public static List<Byte> serialize(BoardPainter boardPainter, GameState gameState) { | ||
61 | List<Byte> output = new ArrayList<>(); | ||
62 | List<Byte> data = new ArrayList<>(); | ||
63 | |||
64 | // Board | ||
65 | data.addAll(serializeBoard(boardPainter, gameState.board())); | ||
66 | |||
67 | // Blasts and Bombs | ||
68 | data.addAll(serializeExplosions(gameState.bombedCells(), gameState.blastedCells())); | ||
69 | |||
70 | // Players | ||
71 | for (Player player : gameState.players()) { | ||
72 | List<Byte> serializedPlayer = new ArrayList<>(); | ||
73 | serializedPlayer.add((byte) player.lives()); | ||
74 | serializedPlayer.add((byte) player.position().x()); | ||
75 | serializedPlayer.add((byte) player.position().y()); | ||
76 | serializedPlayer.add(PlayerPainter.byteForPlayer(player, gameState.ticks())); | ||
77 | |||
78 | data.addAll(serializedPlayer); | ||
79 | } | ||
80 | |||
81 | // Ticks | ||
82 | data.add((byte) (gameState.remainingTime() / 2)); | ||
83 | |||
84 | // Build output | ||
85 | output.add((byte) data.size()); | ||
86 | output.addAll(data); | ||
87 | |||
88 | return output; | ||
89 | } | ||
90 | } | ||
diff --git a/src/ch/epfl/xblast/server/Level.java b/src/ch/epfl/xblast/server/Level.java new file mode 100644 index 0000000..81bc85b --- /dev/null +++ b/src/ch/epfl/xblast/server/Level.java | |||
@@ -0,0 +1,134 @@ | |||
1 | package ch.epfl.xblast.server; | ||
2 | |||
3 | import ch.epfl.xblast.*; | ||
4 | import ch.epfl.xblast.server.painter.*; | ||
5 | |||
6 | import java.util.Arrays; | ||
7 | import java.util.List; | ||
8 | import java.util.HashMap; | ||
9 | |||
10 | /** | ||
11 | * @author Timothée FLOURE (257420) | ||
12 | */ | ||
13 | public final class Level { | ||
14 | |||
15 | /** Players' initial parameters **/ | ||
16 | private static final int PLAYER_INITIAL_LIVES = 5; | ||
17 | private static final int PLAYER_INITIAL_BOMB_MAXIMUM = 5; | ||
18 | private static final int PLAYER_INITIAL_BOMB_RANGE = 5; | ||
19 | |||
20 | /** Players' initial positions (Ugly!) **/ | ||
21 | private static final Cell PLAYER_1_INITIAL_POSITION = new Cell(1,1); | ||
22 | private static final Cell PLAYER_2_INITIAL_POSITION = new Cell(16,1); | ||
23 | private static final Cell PLAYER_3_INITIAL_POSITION = new Cell(16,14); | ||
24 | private static final Cell PLAYER_4_INITIAL_POSITION = new Cell(1,14); | ||
25 | |||
26 | /** Level values **/ | ||
27 | private final BoardPainter painter; | ||
28 | private final GameState initialState; | ||
29 | |||
30 | /** | ||
31 | * Build the default board of the game. | ||
32 | * | ||
33 | * @return the default board | ||
34 | */ | ||
35 | private static BoardPainter buildDefaultBoardPainter() { | ||
36 | // Create the blocks map | ||
37 | HashMap<Block,BlockImage> blocksMap = new HashMap<>(); | ||
38 | |||
39 | // Fill the blocks map | ||
40 | blocksMap.put(Block.FREE, BlockImage.IRON_FLOOR); | ||
41 | blocksMap.put(Block.DESTRUCTIBLE_WALL, BlockImage.EXTRA); | ||
42 | blocksMap.put(Block.CRUMBLING_WALL, BlockImage.EXTRA_O); | ||
43 | blocksMap.put(Block.INDESTRUCTIBLE_WALL, BlockImage.DARK_BLOCK); | ||
44 | blocksMap.put(Block.BONUS_BOMB, BlockImage.BONUS_BOMB); | ||
45 | blocksMap.put(Block.BONUS_RANGE, BlockImage.BONUS_RANGE); | ||
46 | |||
47 | // Create and return the board painter | ||
48 | return new BoardPainter(blocksMap, BlockImage.IRON_FLOOR_S); | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * Build the default game state of the game. | ||
53 | * | ||
54 | * @return the default game state | ||
55 | */ | ||
56 | private static GameState buildDefaultGameState() { | ||
57 | return new GameState(buildDefaultBoard(), buildDefaultPlayers()); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Build the default board of the game. | ||
62 | * | ||
63 | * @return the default board. | ||
64 | */ | ||
65 | private static Board buildDefaultBoard() { | ||
66 | |||
67 | // Ugly! | ||
68 | Block __ = Block.FREE; | ||
69 | Block XX = Block.INDESTRUCTIBLE_WALL; | ||
70 | Block xx = Block.DESTRUCTIBLE_WALL; | ||
71 | |||
72 | return Board.ofQuadrantNWBlocksWalled( | ||
73 | Arrays.asList( | ||
74 | Arrays.asList(__, __, __, __, __, xx, __), | ||
75 | Arrays.asList(__, XX, xx, XX, xx, XX, xx), | ||
76 | Arrays.asList(__, xx, __, __, __, xx, __), | ||
77 | Arrays.asList(xx, XX, __, XX, XX, XX, XX), | ||
78 | Arrays.asList(__, xx, __, xx, __, __, __), | ||
79 | Arrays.asList(xx, XX, xx, XX, xx, XX, __))); | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * Build the default players of the games. | ||
84 | * | ||
85 | * @return a list of the 4 players built using the default parameters. | ||
86 | */ | ||
87 | private static List<Player> buildDefaultPlayers() { | ||
88 | // Ugly! | ||
89 | return Arrays.asList( | ||
90 | new Player(PlayerID.PLAYER_1, PLAYER_INITIAL_LIVES, PLAYER_1_INITIAL_POSITION, | ||
91 | PLAYER_INITIAL_BOMB_MAXIMUM, PLAYER_INITIAL_BOMB_RANGE), | ||
92 | new Player(PlayerID.PLAYER_2, PLAYER_INITIAL_LIVES, PLAYER_2_INITIAL_POSITION, | ||
93 | PLAYER_INITIAL_BOMB_MAXIMUM, PLAYER_INITIAL_BOMB_RANGE), | ||
94 | new Player(PlayerID.PLAYER_3, PLAYER_INITIAL_LIVES, PLAYER_3_INITIAL_POSITION, | ||
95 | PLAYER_INITIAL_BOMB_MAXIMUM, PLAYER_INITIAL_BOMB_RANGE), | ||
96 | new Player(PlayerID.PLAYER_4, PLAYER_INITIAL_LIVES, PLAYER_4_INITIAL_POSITION, | ||
97 | PLAYER_INITIAL_BOMB_MAXIMUM, PLAYER_INITIAL_BOMB_RANGE) | ||
98 | ); | ||