@@ -9,7 +9,6 @@ object GameRuleLogic {
9
9
10
10
const val SMALLEST_SCORE_POSSIBLE = - 89
11
11
12
- // TODO: Add all the needed logic as static (@JvmStatic) functions here
13
12
/* * Calculates the score for the given list in pieces.
14
13
* Assumes the game has ended and the pieces are in order of placement.
15
14
*/
@@ -96,6 +95,16 @@ object GameRuleLogic {
96
95
}
97
96
}
98
97
98
+ /* * Returns true if [move] is valid, false otherwise. */
99
+ @JvmStatic
100
+ fun isValidSetMove (gameState : GameState , move : SetMove ) =
101
+ try {
102
+ validateSetMove(gameState, move)
103
+ true
104
+ } catch (e: InvalidMoveException ) {
105
+ false
106
+ }
107
+
99
108
/* * Checks if the given [position] is already obstructed by another piece. */
100
109
@JvmStatic
101
110
fun isObstructed (board : Board , position : Coordinates ): Boolean =
@@ -130,6 +139,10 @@ object GameRuleLogic {
130
139
fun isOnCorner (position : Coordinates ): Boolean =
131
140
Corner .asSet().contains(position)
132
141
142
+ @JvmStatic
143
+ fun isFirstMove (gameState : GameState ) =
144
+ gameState.deployedPieces.getValue(gameState.currentColor).isEmpty()
145
+
133
146
/* * Returns a random pentomino which is not the `x` one (Used to get a valid starting piece). */
134
147
@JvmStatic
135
148
fun getRandomPentomino () =
@@ -139,35 +152,13 @@ object GameRuleLogic {
139
152
140
153
/* * Returns a list of all possible SetMoves. */
141
154
@JvmStatic
142
- fun getPossibleMoves (gameState : GameState ): Set <SetMove > {
143
- // TODO: Use appropriate move calculation here
144
- if (gameState.deployedPieces.getValue(gameState.currentColor).isEmpty()) return getPossibleStartMoves(gameState)
145
- val color = gameState.currentColor
146
-
147
- val moves = mutableSetOf<SetMove >()
148
- gameState.undeployedPieceShapes.getValue(color).map {
149
- val area = it.coordinates.area()
150
- for (y in 0 until Constants .BOARD_SIZE - area.dy)
151
- for (x in 0 until Constants .BOARD_SIZE - area.dx)
152
- for (variant in it.variants)
153
- moves + = SetMove (Piece (color, it, variant.key, Coordinates (x, y)))
154
- }
155
- return moves
156
- }
155
+ fun getPossibleMoves (gameState : GameState ) =
156
+ streamPossibleMoves(gameState).toSet()
157
157
158
158
/* * Returns a list of possible SetMoves if it's the first round. */
159
159
@JvmStatic
160
- fun getPossibleStartMoves (gameState : GameState ): Set <SetMove > {
161
- val color = gameState.currentColor
162
- val kind = gameState.startPiece
163
- val moves = mutableSetOf<SetMove >()
164
- for (variant in kind.variants) {
165
- for (corner in Corner .values()) {
166
- moves.add(SetMove (Piece (color, kind, variant.key, corner.align(variant.key.area()))))
167
- }
168
- }
169
- return moves.filterValidMoves(gameState)
170
- }
160
+ fun getPossibleStartMoves (gameState : GameState ) =
161
+ streamPossibleStartMoves(gameState).toSet()
171
162
172
163
/* *
173
164
* Returns a list of all moves, impossible or not.
@@ -176,7 +167,7 @@ object GameRuleLogic {
176
167
* Set as `::getPossibleMoves`
177
168
*/
178
169
@JvmStatic
179
- fun getAllMoves (gameState : GameState ): Set <SetMove > {
170
+ fun getAllMoves (): Set <SetMove > {
180
171
val moves = mutableSetOf<SetMove >()
181
172
for (color in Color .values()) {
182
173
for (shape in PieceShape .values()) {
@@ -193,4 +184,38 @@ object GameRuleLogic {
193
184
}
194
185
return moves
195
186
}
187
+
188
+ /* * Ensures the currently active color of [gameState] can perform a move. */
189
+ @JvmStatic
190
+ fun validateMovability (gameState : GameState ) {
191
+ if (streamPossibleMoves(gameState).none { isValidSetMove(gameState, it) })
192
+ gameState.removeActiveColor()
193
+ }
194
+
195
+ /* * Streams all possible moves in the current turn of [gameState]. */
196
+ @JvmStatic
197
+ fun streamPossibleMoves (gameState : GameState ) =
198
+ if (isFirstMove(gameState))
199
+ streamPossibleStartMoves(gameState)
200
+ else sequence<SetMove > {
201
+ val color = gameState.currentColor
202
+ gameState.undeployedPieceShapes.getValue(color).map {
203
+ val area = it.coordinates.area()
204
+ for (y in 0 until Constants .BOARD_SIZE - area.dy)
205
+ for (x in 0 until Constants .BOARD_SIZE - area.dx)
206
+ for (variant in it.variants)
207
+ yield (SetMove (Piece (color, it, variant.key, Coordinates (x, y))))
208
+ }
209
+ }.filter { isValidSetMove(gameState, it) }
210
+
211
+ /* * Streams all possible moves if it's the first turn of [gameState]. */
212
+ @JvmStatic
213
+ fun streamPossibleStartMoves (gameState : GameState ) = sequence<SetMove > {
214
+ val kind = gameState.startPiece
215
+ for (variant in kind.variants) {
216
+ for (corner in Corner .values()) {
217
+ yield (SetMove (Piece (gameState.currentColor, kind, variant.key, corner.align(variant.key.area()))))
218
+ }
219
+ }
220
+ }.filter { isValidSetMove(gameState, it) }
196
221
}
0 commit comments