Skip to content

Commit 73873b7

Browse files
committed
feat(plugin): pass moves remove colors gracefully
NOTE: Also adds a new Constants, `PASS_MOVE_SKIPS`, which can be used for alternate game play in which pass moves skip a turn only, without removing the color from gameplay feat(plugin): add a separate SkipMove, only skipping one turn
1 parent 466236b commit 73873b7

File tree

6 files changed

+41
-21
lines changed

6 files changed

+41
-21
lines changed

plugin/src/server/sc/plugin2021/Game.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,12 @@ class Game(UUID: String = GamePlugin.PLUGIN_UUID): RoundBasedGameInstance<Player
161161
logger.debug("Current State: $gameState")
162162
logger.debug("Performing Move $data")
163163
GameRuleLogic.performMove(gameState, data)
164-
GameRuleLogic.validateMovability(gameState)
165-
next(if(gameState.orderedColors.isNotEmpty()) gameState.currentPlayer else null)
164+
if (!isGameOver()) {
165+
GameRuleLogic.validateMovability(gameState)
166+
next(gameState.currentPlayer)
167+
} else {
168+
next(null)
169+
}
166170
logger.debug("Current Board:\n${gameState.board}")
167171
} catch(e: InvalidMoveException) {
168172
super.catchInvalidMove(e, fromPlayer)
@@ -171,4 +175,5 @@ class Game(UUID: String = GamePlugin.PLUGIN_UUID): RoundBasedGameInstance<Player
171175

172176
override fun getCurrentState(): IGameState = gameState
173177

178+
fun isGameOver(): Boolean = gameState.orderedColors.isEmpty()
174179
}

plugin/src/shared/sc/plugin2021/GameState.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,11 @@ class GameState @JvmOverloads constructor(
111111
* Do not do anything with currentColor before the turn is done for good.
112112
*/
113113
fun removeActiveColor() {
114+
logger.info("Removed $currentColor from the game")
114115
orderedColors.remove(currentColor)
115116
if (orderedColors.isNotEmpty())
116117
currentColorIndex = (currentColorIndex + orderedColors.size - 1) % orderedColors.size
118+
logger.debug("Remaining Colors: $orderedColors")
117119
}
118120

119121
override fun toString(): String = "GameState $round/$turn -> $currentColor"

plugin/src/shared/sc/plugin2021/Move.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,10 @@ class SetMove(val piece: Piece): Move(piece.color) {
1616

1717
@XStreamAlias(value = "passmove")
1818
class PassMove(color: Color): Move(color) {
19-
override fun toString(): String = "$color passed out"
19+
override fun toString(): String = "$color passed"
20+
}
21+
22+
@XStreamAlias(value = "skipmove")
23+
class SkipMove(color: Color): Move(color) {
24+
override fun toString(): String = "$color skipped"
2025
}

plugin/src/shared/sc/plugin2021/util/GameRuleLogic.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ object GameRuleLogic {
2828
validateMoveColor(gameState, move)
2929

3030
when (move) {
31+
is SkipMove -> {}
3132
is PassMove -> {
32-
throw InvalidMoveException("Color ${move.color} intentionally passed out", move)
33+
gameState.removeActiveColor()
3334
}
3435
is SetMove -> {
3536
if (Constants.VALIDATE_MOVE)

plugin/src/test/sc/plugin2021/GameRuleLogicTest.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,13 @@ class GameRuleLogicTest: StringSpec({
9191
GameRuleLogic.getPointsFromUndeployed(emptySet(), false) shouldBe 15
9292
GameRuleLogic.getPointsFromUndeployed(emptySet(), true) shouldBe 20
9393
}
94-
"After the color check, PassMoves throw" {
94+
"After the color check, PassMoves remove the color" {
9595
val state = GameState()
96-
assertThrows<InvalidMoveException> {
96+
assertDoesNotThrow {
9797
GameRuleLogic.performMove(state, PassMove(Color.BLUE))
9898
}
99-
state.orderedColors.size shouldBe 4
99+
state.orderedColors.size shouldBe 3
100+
state.currentColor shouldBe Color.YELLOW
100101
}
101102
"All possible start moves get calculated" {
102103
val piece = PieceShape.PENTO_W

plugin/src/test/sc/plugin2021/GameTest.kt

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,32 @@ class GameTest: StringSpec({
1616
Color.BLUE.team
1717
val game = Game()
1818
val state = game.gameState
19-
val first = game.onPlayerJoined()
20-
val second = game.onPlayerJoined()
19+
val player = Pair(game.onPlayerJoined(), game.onPlayerJoined())
2120

22-
first.color shouldBe Team.ONE
23-
second.color shouldBe Team.TWO
21+
player.first.color shouldBe Team.ONE
22+
player.second.color shouldBe Team.TWO
2423

2524
game.start()
2625

27-
val e: InvalidMoveException = assertThrows {
28-
state.currentPlayer shouldBe first
29-
state.currentColor shouldBe Color.BLUE
30-
game.onAction(state.currentPlayer, PassMove(state.currentColor))
31-
}
26+
state.currentPlayer shouldBe player.first
27+
state.currentColor shouldBe Color.BLUE
28+
game.onAction(state.currentPlayer, PassMove(state.currentColor))
29+
30+
state.currentPlayer shouldBe player.second
31+
state.currentColor shouldBe Color.YELLOW
32+
game.onAction(state.currentPlayer, PassMove(state.currentColor))
33+
34+
state.currentPlayer shouldBe player.first
35+
state.currentColor shouldBe Color.RED
36+
game.onAction(player.first, PassMove(Color.RED))
37+
38+
state.currentPlayer shouldBe player.second
39+
state.currentColor shouldBe Color.GREEN
40+
game.onAction(player.second, PassMove(Color.GREEN))
3241

33-
game.winners shouldBe listOf(second)
42+
game.winners shouldBe player.toList()
3443

35-
game.playerScores shouldContainExactly listOf(
36-
PlayerScore(ScoreCause.RULE_VIOLATION, e.message, Constants.LOSE_SCORE, -178),
37-
PlayerScore(ScoreCause.REGULAR, "", Constants.WIN_SCORE, -178)
38-
)
44+
game.playerScores shouldContainExactly List(2) {PlayerScore(ScoreCause.REGULAR, "", Constants.DRAW_SCORE, -178)}
3945
}
4046
"A few moves can be performd without issues" {
4147
val game = Game()

0 commit comments

Comments
 (0)