Skip to content

Commit 88d4c57

Browse files
feat(api)!: Track the game id as part of the game state
1 parent 8af95b3 commit 88d4c57

File tree

12 files changed

+228
-111
lines changed

12 files changed

+228
-111
lines changed

api/src/main/java/org/xxdc/oss/example/Game.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ public Game(int size, boolean persistenceEnabled, PlayerNode... players) {
6161
this.moveNumber = 0;
6262
this.gameState = new ArrayDeque<>();
6363
this.gameState.add(
64-
new GameState(GameBoard.withDimension(size), this.playerNodes.playerMarkerList(), 0));
64+
new GameState(
65+
gameId, GameBoard.withDimension(size), this.playerNodes.playerMarkerList(), 0));
6566
this.persistenceEnabled = persistenceEnabled;
6667
}
6768

@@ -144,17 +145,6 @@ public void playWithAction(Consumer<Game> postMoveAction) {
144145
}
145146
}
146147

147-
/**
148-
* Returns the unique identifier for this game instance (Deprecated).
149-
*
150-
* @return the game ID
151-
* @deprecated use {@link #id()} instead
152-
*/
153-
@Deprecated(since = "1.5.0", forRemoval = true)
154-
public UUID getGameId() {
155-
return gameId;
156-
}
157-
158148
/**
159149
* Returns the unique identifier for this game instance.
160150
*

api/src/main/java/org/xxdc/oss/example/GameState.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.Serializable;
44
import java.util.ArrayList;
55
import java.util.List;
6+
import java.util.UUID;
67

78
/**
89
* Represents the current state of a game, including the game board, player markers, and the index
@@ -11,26 +12,33 @@
1112
* Implements the JsonSerializable and Serializable interfaces, allowing the game state to be
1213
* serialized and deserialized.
1314
*
15+
* @param gameId The unique game id
1416
* @param board The game board.
1517
* @param playerMarkers The list of player markers.
1618
* @param currentPlayerIndex The index of the current player in the {@code playerMarkers} list.
1719
* @param lastMove The index of the last move made on the game board.
1820
*/
1921
public record GameState(
20-
GameBoard board, List<String> playerMarkers, int currentPlayerIndex, int lastMove)
22+
java.util.UUID gameId,
23+
GameBoard board,
24+
List<String> playerMarkers,
25+
int currentPlayerIndex,
26+
int lastMove)
2127
implements JsonSerializable, Serializable {
2228

2329
/**
2430
* Constructs a new {@link GameState} instance with the provided game board, player markers, and
2531
* the index of the current player. The last move index is set to -1 to indicate that no move has
2632
* been made yet.
2733
*
34+
* @param gameId The unique game id
2835
* @param board The game board.
2936
* @param playerMarkers The list of player markers.
3037
* @param currentPlayerIndex The index of the current player in the {@code playerMarkers} list.
3138
*/
32-
public GameState(GameBoard board, List<String> playerMarkers, int currentPlayerIndex) {
33-
this(board, playerMarkers, currentPlayerIndex, -1);
39+
public GameState(
40+
UUID gameId, GameBoard board, List<String> playerMarkers, int currentPlayerIndex) {
41+
this(gameId, board, playerMarkers, currentPlayerIndex, -1);
3442
}
3543

3644
/**
@@ -43,6 +51,7 @@ public GameState(GameBoard board, List<String> playerMarkers, int currentPlayerI
4351
*/
4452
public GameState(GameState state) {
4553
this(
54+
state.gameId,
4655
state.board,
4756
new ArrayList<>(state.playerMarkers),
4857
state.currentPlayerIndex,
@@ -108,7 +117,8 @@ public boolean isTerminal() {
108117
public String asJsonString() {
109118
StringBuilder json = new StringBuilder();
110119
json.append("{");
111-
if (playerMarkers.size() > 0) {
120+
json.append("\"gameId\":\"").append(gameId).append("\",");
121+
if (!playerMarkers.isEmpty()) {
112122
json.append("\"playerMarkers\":[\"")
113123
.append(String.join("\",\"", playerMarkers))
114124
.append("\"],");
@@ -131,7 +141,7 @@ public String asJsonString() {
131141
public GameState afterPlayerMoves(int move) {
132142
GameBoard newBoard = board.withMove(currentPlayer(), move);
133143
int newCurrentPlayerIndex = (currentPlayerIndex + 1) % playerMarkers.size();
134-
return new GameState(newBoard, playerMarkers, newCurrentPlayerIndex, move);
144+
return new GameState(gameId, newBoard, playerMarkers, newCurrentPlayerIndex, move);
135145
}
136146

137147
/**

api/src/test/java/org/xxdc/oss/example/AlphaBetaTest.java

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static org.xxdc.oss.example.TestData.*;
66

77
import java.util.List;
8+
import java.util.UUID;
89
import org.testng.Assert;
910
import org.testng.annotations.Ignore;
1011
import org.testng.annotations.Test;
@@ -38,10 +39,16 @@ public void testAlphaBetaShouldPreventOpponentWinningNextMove() {
3839
{"O", "O", "_"}
3940
});
4041

41-
assertEquals(new AlphaBeta(new GameState(board[0], List.of("X", "O"), 1)).bestMove(), 2);
42+
assertEquals(
43+
new AlphaBeta(new GameState(UUID.randomUUID(), board[0], List.of("X", "O"), 1)).bestMove(),
44+
2);
4245
Assert.assertTrue(board[1].withMove("X", 8).hasChain("X"));
43-
assertEquals(new AlphaBeta(new GameState(board[2], List.of("X", "O"), 1)).bestMove(), 8);
44-
assertEquals(new AlphaBeta(new GameState(board[1], List.of("X", "O"), 1)).bestMove(), 8);
46+
assertEquals(
47+
new AlphaBeta(new GameState(UUID.randomUUID(), board[2], List.of("X", "O"), 1)).bestMove(),
48+
8);
49+
assertEquals(
50+
new AlphaBeta(new GameState(UUID.randomUUID(), board[1], List.of("X", "O"), 1)).bestMove(),
51+
8);
4552
}
4653

4754
@Test
@@ -89,12 +96,24 @@ public void testAlphaBetaShouldChooseWinningMove() {
8996
{"O", "X", "_"},
9097
{"O", "_", "_"}
9198
});
92-
assertEquals(new AlphaBeta(new GameState(board[0], List.of("X", "O"), 0)).bestMove(), 2);
93-
assertEquals(new AlphaBeta(new GameState(board[1], List.of("X", "O"), 0)).bestMove(), 8);
94-
assertEquals(new AlphaBeta(new GameState(board[2], List.of("X", "O"), 0)).bestMove(), 7);
95-
assertEquals(new AlphaBeta(new GameState(board[3], List.of("X", "O"), 1)).bestMove(), 5);
96-
assertEquals(new AlphaBeta(new GameState(board[4], List.of("X", "O"), 1)).bestMove(), 8);
97-
assertEquals(new AlphaBeta(new GameState(board[5], List.of("X", "O"), 1)).bestMove(), 0);
99+
assertEquals(
100+
new AlphaBeta(new GameState(UUID.randomUUID(), board[0], List.of("X", "O"), 0)).bestMove(),
101+
2);
102+
assertEquals(
103+
new AlphaBeta(new GameState(UUID.randomUUID(), board[1], List.of("X", "O"), 0)).bestMove(),
104+
8);
105+
assertEquals(
106+
new AlphaBeta(new GameState(UUID.randomUUID(), board[2], List.of("X", "O"), 0)).bestMove(),
107+
7);
108+
assertEquals(
109+
new AlphaBeta(new GameState(UUID.randomUUID(), board[3], List.of("X", "O"), 1)).bestMove(),
110+
5);
111+
assertEquals(
112+
new AlphaBeta(new GameState(UUID.randomUUID(), board[4], List.of("X", "O"), 1)).bestMove(),
113+
8);
114+
assertEquals(
115+
new AlphaBeta(new GameState(UUID.randomUUID(), board[5], List.of("X", "O"), 1)).bestMove(),
116+
0);
98117
}
99118

100119
@Test
@@ -106,7 +125,8 @@ public void testAlphaBetaSupportsNonStandardPlayers() {
106125
{"♣", "♠", "_"},
107126
{"♣", "_", "_"}
108127
});
109-
assertEquals(new AlphaBeta(new GameState(board, List.of("♣", "♠"), 1)).bestMove(), 8);
128+
assertEquals(
129+
new AlphaBeta(new GameState(UUID.randomUUID(), board, List.of("♣", "♠"), 1)).bestMove(), 8);
110130
}
111131

112132
@Test
@@ -120,7 +140,7 @@ public void testAlphaBetaRejectsGamesWithMoreTThanTwoPlayers() {
120140
});
121141
Assert.assertThrows(
122142
IllegalArgumentException.class,
123-
() -> new AlphaBeta(new GameState(board, List.of("♣", "♠", "♦"), 1)));
143+
() -> new AlphaBeta(new GameState(UUID.randomUUID(), board, List.of("♣", "♠", "♦"), 1)));
124144
}
125145

126146
@Test
@@ -134,7 +154,8 @@ public void testAlphaBetaCanPlayLargeGames() {
134154
{"♣", "♠", "_", "_"},
135155
{"_", "♠", "_", "_"}
136156
});
137-
assertEquals(new AlphaBeta(new GameState(board, List.of("♣", "♠"), 1)).bestMove(), 1);
157+
assertEquals(
158+
new AlphaBeta(new GameState(UUID.randomUUID(), board, List.of("♣", "♠"), 1)).bestMove(), 1);
138159
}
139160

140161
@Ignore(
@@ -151,7 +172,7 @@ public void testAlphaBetaCanPlayLargerGamesWhenDepthLimited() {
151172
{"_", "_", "_", "_"},
152173
{"_", "_", "_", "_"}
153174
});
154-
GameState state = new GameState(board, List.of("♣", "♠"), 1);
175+
GameState state = new GameState(UUID.randomUUID(), board, List.of("♣", "♠"), 1);
155176
BotStrategyConfig config = BotStrategyConfig.newBuilder().maxDepth(3).build();
156177
assertTrue(new AlphaBeta(state, config).bestMove() > 0);
157178
}
@@ -165,7 +186,8 @@ public void testAlphaBetaCanPlayBlogConfiguration() {
165186
{"O", "_", "_"},
166187
{"O", "X", "X"}
167188
});
168-
assertEquals(new AlphaBeta(new GameState(board, List.of("O", "X"), 0)).bestMove(), 4);
189+
assertEquals(
190+
new AlphaBeta(new GameState(UUID.randomUUID(), board, List.of("O", "X"), 0)).bestMove(), 4);
169191
}
170192

171193
@Test
@@ -177,6 +199,7 @@ public void testAlphaBetaCanPlayBlogConfigurationTwo() {
177199
{"X", "X", "_"},
178200
{"_", "_", "_"}
179201
});
180-
assertEquals(new AlphaBeta(new GameState(board, List.of("O", "X"), 0)).bestMove(), 2);
202+
assertEquals(
203+
new AlphaBeta(new GameState(UUID.randomUUID(), board, List.of("O", "X"), 0)).bestMove(), 2);
181204
}
182205
}

api/src/test/java/org/xxdc/oss/example/GameStateTest.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static org.xxdc.oss.example.TestData.createBoardWith;
44

55
import java.util.List;
6+
import java.util.UUID;
67
import org.testng.Assert;
78
import org.testng.annotations.Test;
89

@@ -17,10 +18,11 @@ public void testGameStateShouldCreateJsonString() {
1718
{"_", "X", "_"},
1819
{"_", "_", "_"}
1920
});
20-
var gameState = new GameState(gameBoard, List.of("X", "O"), 1);
21+
var gameId = UUID.fromString("00000000-0000-0000-0000-000000000000");
22+
var gameState = new GameState(gameId, gameBoard, List.of("X", "O"), 1);
2123
var json = gameState.asJsonString();
2224
var expectedJson =
23-
"{\"playerMarkers\":[\"X\",\"O\"],\"currentPlayerIndex\":1,\"board\":{\"dimension\":3,\"content\":[\"X\",\"O\",null,null,\"X\",null,null,null,null]}}";
25+
"{\"gameId\":\"00000000-0000-0000-0000-000000000000\",\"playerMarkers\":[\"X\",\"O\"],\"currentPlayerIndex\":1,\"board\":{\"dimension\":3,\"content\":[\"X\",\"O\",null,null,\"X\",null,null,null,null]}}";
2426
Assert.assertEquals(json, expectedJson);
2527
}
2628

@@ -33,10 +35,12 @@ public void shouldCorrectlyUpdateStateAfterMove() {
3335
{"_", "X", "_"},
3436
{"_", "_", "_"}
3537
});
36-
var gameState = new GameState(gameBoard, List.of("X", "O"), 1);
38+
var gameId = UUID.randomUUID();
39+
var gameState = new GameState(gameId, gameBoard, List.of("X", "O"), 1);
3740
var gameStateAfterMove = gameState.afterPlayerMoves(3);
3841
var expectedGameState =
3942
new GameState(
43+
gameId,
4044
createBoardWith(
4145
new String[][] {
4246
{"X", "O", "_"},

api/src/test/java/org/xxdc/oss/example/MaxNTest.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static org.xxdc.oss.example.TestData.*;
55

66
import java.util.List;
7+
import java.util.UUID;
78
import org.testng.Assert;
89
import org.testng.annotations.Test;
910
import org.xxdc.oss.example.bot.MaxN;
@@ -22,7 +23,8 @@ public void testMaxNShouldPreventOpponentWinningNextMoveOne() {
2223
{"O", "_", "_"}
2324
});
2425
Assert.assertTrue(board[0].withMove("X", 8).hasChain("X"));
25-
assertEquals(new MaxN(new GameState(board[0], List.of("X", "O"), 1)).bestMove(), 8);
26+
assertEquals(
27+
new MaxN(new GameState(UUID.randomUUID(), board[0], List.of("X", "O"), 1)).bestMove(), 8);
2628
}
2729

2830
@Test
@@ -51,10 +53,13 @@ public void testMaxNShouldPreventOpponentWinningNextMove() {
5153
{"O", "O", "_"}
5254
});
5355

54-
assertEquals(new MaxN(new GameState(board[0], List.of("X", "O"), 1)).bestMove(), 2);
56+
assertEquals(
57+
new MaxN(new GameState(UUID.randomUUID(), board[0], List.of("X", "O"), 1)).bestMove(), 2);
5558
Assert.assertTrue(board[1].withMove("X", 8).hasChain("X"));
56-
assertEquals(new MaxN(new GameState(board[1], List.of("X", "O"), 1)).bestMove(), 8);
57-
assertEquals(new MaxN(new GameState(board[2], List.of("X", "O"), 1)).bestMove(), 8);
59+
assertEquals(
60+
new MaxN(new GameState(UUID.randomUUID(), board[1], List.of("X", "O"), 1)).bestMove(), 8);
61+
assertEquals(
62+
new MaxN(new GameState(UUID.randomUUID(), board[2], List.of("X", "O"), 1)).bestMove(), 8);
5863
}
5964

6065
@Test
@@ -102,12 +107,18 @@ public void testMaxNShouldChooseWinningMove() {
102107
{"O", "X", "_"},
103108
{"O", "_", "_"}
104109
});
105-
assertEquals(new MaxN(new GameState(board[0], List.of("X", "O"), 0)).bestMove(), 2);
106-
assertEquals(new MaxN(new GameState(board[1], List.of("X", "O"), 0)).bestMove(), 8);
107-
assertEquals(new MaxN(new GameState(board[2], List.of("X", "O"), 0)).bestMove(), 7);
108-
assertEquals(new MaxN(new GameState(board[3], List.of("X", "O"), 1)).bestMove(), 5);
109-
assertEquals(new MaxN(new GameState(board[4], List.of("X", "O"), 1)).bestMove(), 8);
110-
assertEquals(new MaxN(new GameState(board[5], List.of("X", "O"), 1)).bestMove(), 0);
110+
assertEquals(
111+
new MaxN(new GameState(UUID.randomUUID(), board[0], List.of("X", "O"), 0)).bestMove(), 2);
112+
assertEquals(
113+
new MaxN(new GameState(UUID.randomUUID(), board[1], List.of("X", "O"), 0)).bestMove(), 8);
114+
assertEquals(
115+
new MaxN(new GameState(UUID.randomUUID(), board[2], List.of("X", "O"), 0)).bestMove(), 7);
116+
assertEquals(
117+
new MaxN(new GameState(UUID.randomUUID(), board[3], List.of("X", "O"), 1)).bestMove(), 5);
118+
assertEquals(
119+
new MaxN(new GameState(UUID.randomUUID(), board[4], List.of("X", "O"), 1)).bestMove(), 8);
120+
assertEquals(
121+
new MaxN(new GameState(UUID.randomUUID(), board[5], List.of("X", "O"), 1)).bestMove(), 0);
111122
}
112123

113124
@Test
@@ -120,9 +131,12 @@ public void testMaxNShouldSupportAMultiPlayerGame() {
120131
{"O", "_", "/"},
121132
{"O", "_", "_"}
122133
});
123-
assertEquals(new MaxN(new GameState(board, List.of("/", "X", "O"), 0)).bestMove(), 8);
124-
assertEquals(new MaxN(new GameState(board, List.of("X", "/", "O"), 0)).bestMove(), 8);
125-
assertEquals(new MaxN(new GameState(board, List.of("O", "/", "X"), 0)).bestMove(), 8);
134+
assertEquals(
135+
new MaxN(new GameState(UUID.randomUUID(), board, List.of("/", "X", "O"), 0)).bestMove(), 8);
136+
assertEquals(
137+
new MaxN(new GameState(UUID.randomUUID(), board, List.of("X", "/", "O"), 0)).bestMove(), 8);
138+
assertEquals(
139+
new MaxN(new GameState(UUID.randomUUID(), board, List.of("O", "/", "X"), 0)).bestMove(), 8);
126140
}
127141

128142
@Test
@@ -135,6 +149,7 @@ public void testMaxNShouldSupportAMultiPlayerGameFromBlog() {
135149
{"O", "O", "_"},
136150
{"/", "/", "_"}
137151
});
138-
assertEquals(new MaxN(new GameState(board, List.of("O", "X", "/"), 0)).bestMove(), 5);
152+
assertEquals(
153+
new MaxN(new GameState(UUID.randomUUID(), board, List.of("O", "X", "/"), 0)).bestMove(), 5);
139154
}
140155
}

0 commit comments

Comments
 (0)