Skip to content

Commit 5e3eede

Browse files
committed
feat(plugin26): implement GameState methods
1 parent 65402e4 commit 5e3eede

File tree

5 files changed

+41
-32
lines changed

5 files changed

+41
-32
lines changed

plugin2026/src/main/kotlin/sc/plugin2026/Board.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sc.plugin2026
22

33
import com.thoughtworks.xstream.annotations.XStreamAlias
44
import sc.api.plugins.Coordinates
5+
import sc.api.plugins.ITeam
56
import sc.api.plugins.MutableTwoDBoard
67
import sc.api.plugins.RectangularBoard
78
import sc.api.plugins.Team
@@ -35,11 +36,11 @@ class Board(gameField: MutableTwoDBoard<FieldS> = randomFields()): RectangularBo
3536
fun getTeam(pos: Coordinates): Team? =
3637
this[pos].state.team
3738

38-
fun fieldsForTeam(team: Team): Collection<Coordinates> =
39+
fun fieldsForTeam(team: ITeam): Collection<Coordinates> =
3940
filterValues { field -> field.state.team == team }.map { it.key }
4041

4142
companion object {
42-
/** Erstellt eine zufälliges Spielbrett. */
43+
/** Erstellt ein zufälliges Spielbrett. */
4344
private fun randomFields(): MutableTwoDBoard<FieldS> {
4445
val fields = generateFields { x, y -> FieldS(x, y) }
4546

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
1-
package sc.plugin2019
1+
package sc.plugin2026
22

33
import com.thoughtworks.xstream.annotations.XStreamAlias
44
import com.thoughtworks.xstream.annotations.XStreamAsAttribute
5-
import sc.api.plugins.Direction
65
import sc.api.plugins.ITeam
76
import sc.api.plugins.Stat
87
import sc.api.plugins.Team
98
import sc.api.plugins.TwoPlayerGameState
10-
import sc.plugin2026.Board
11-
import sc.plugin2026.FieldState
12-
import sc.plugin2026.Move
13-
import sc.plugin2026.PiranhaMoveMistake
9+
import sc.framework.plugins.maxByNoEqual
1410
import sc.plugin2026.util.GameRuleLogic
1511
import sc.plugin2026.util.PiranhaConstants
16-
import sc.shared.IMoveMistake
12+
import sc.plugin2026.util.PiranhasWinReason
1713
import sc.shared.InvalidMoveException
18-
import sc.shared.MoveMistake
1914
import sc.shared.WinCondition
15+
import sc.shared.WinReasonTie
2016

2117
/**
2218
* The GameState class represents the current state of the game.
@@ -37,19 +33,31 @@ data class GameState @JvmOverloads constructor(
3733
/** Der zuletzt gespielte Zug. */
3834
override var lastMove: Move? = null,
3935
): TwoPlayerGameState<Move>(Team.ONE) {
40-
36+
4137
override fun getPointsForTeam(team: ITeam): IntArray =
42-
GameRuleLogic.greatestSwarmSize(board, team) // TODO important
38+
intArrayOf(GameRuleLogic.greatestSwarmSize(board, team))
4339

4440
// TODO test if one player is surrounded he loses
4541
override val isOver: Boolean
46-
get() = players.any { it.inGoal } && turn.mod(2) == 0 || turn / 2 >= PiranhaConstants.ROUND_LIMIT
42+
get() = Team.values().any { GameRuleLogic.isSwarmConnected(board, it) } && turn.mod(2) == 0 ||
43+
turn / 2 >= PiranhaConstants.ROUND_LIMIT
4744

4845
override val winCondition: WinCondition?
49-
get() = TODO("Not yet implemented")
46+
get() {
47+
val winners = Team.values().filter { team -> GameRuleLogic.isSwarmConnected(board, team) }
48+
return when(winners.size) {
49+
0 -> null
50+
1 -> WinCondition(winners.single(), PiranhasWinReason.SOLE_SWARM)
51+
else ->
52+
winners.maxByNoEqual { team -> GameRuleLogic.greatestSwarmSize(board, team) }
53+
?.let {
54+
WinCondition(it, PiranhasWinReason.BIGGER_SWARM)
55+
} ?: WinCondition(null, WinReasonTie)
56+
}
57+
}
5058

5159
override fun performMoveDirectly(move: Move) {
52-
if (board.getTeam(move.from) != currentTeam) {
60+
if(board.getTeam(move.from) != currentTeam) {
5361
throw InvalidMoveException(PiranhaMoveMistake.WRONG_START, move)
5462
}
5563
GameRuleLogic.checkMove(board, move)?.let { throw InvalidMoveException(it, move) }
@@ -59,12 +67,12 @@ data class GameState @JvmOverloads constructor(
5967
}
6068

6169
override fun getSensibleMoves(): List<Move> {
62-
val piranhas = board.filterValues { field -> field.state.team == currentTeam }
63-
val moves = ArrayList<Move>(piranhas.size * 2)
64-
for(piranha in piranhas) {
65-
moves.addAll(GameRuleLogic.possibleMovesFor(board, piranha.key))
66-
}
67-
return moves
70+
val piranhas = board.filterValues { field -> field.state.team == currentTeam }
71+
val moves = ArrayList<Move>(piranhas.size * 2)
72+
for(piranha in piranhas) {
73+
moves.addAll(GameRuleLogic.possibleMovesFor(board, piranha.key))
74+
}
75+
return moves
6876
}
6977

7078
override fun moveIterator(): Iterator<Move> =
@@ -73,7 +81,10 @@ data class GameState @JvmOverloads constructor(
7381
override fun clone(): TwoPlayerGameState<Move> =
7482
copy(board = board.clone())
7583

76-
override fun teamStats(team: ITeam): List<Stat> = listOf() // TODO
77-
84+
override fun teamStats(team: ITeam): List<Stat> =
85+
listOf(
86+
Stat("Fische", board.fieldsForTeam(team).size),
87+
Stat("Schwarmgröße", GameRuleLogic.greatestSwarmSize(board, team))
88+
)
7889

7990
}

plugin2026/src/main/kotlin/sc/plugin2026/util/GamePlugin.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import sc.shared.*
1111

1212
@XStreamAlias(value = "winreason")
1313
enum class PiranhasWinReason(override val message: String, override val isRegular: Boolean = true): IWinReason {
14-
BIGGER_SWARM("%s hat den größeren Schwarm")
15-
14+
SOLE_SWARM("%s hat als einziger einen zusammenhängenden Schwarm"),
15+
BIGGER_SWARM("%s hat den größeren Schwarm"),
1616
}
1717

1818
class GamePlugin: IGamePlugin<Move> {

plugin2026/src/main/kotlin/sc/plugin2026/util/GameRuleLogic.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package sc.plugin2026.util
22

33
import sc.api.plugins.Coordinates
44
import sc.api.plugins.Direction
5-
import sc.api.plugins.Team
5+
import sc.api.plugins.ITeam
66
import sc.plugin2026.Board
77
import sc.plugin2026.FieldState
88
import sc.plugin2026.Move
@@ -146,21 +146,21 @@ object GameRuleLogic {
146146
}
147147

148148
@JvmStatic
149-
fun greatestSwarm(board: Board, team: Team): Set<Coordinates> {
149+
fun greatestSwarm(board: Board, team: ITeam): Set<Coordinates> {
150150
val occupiedFields = board.fieldsForTeam(team)
151151
return greatestSwarm(occupiedFields.toHashSet())
152152
}
153153

154154
@JvmStatic
155-
fun greatestSwarmSize(board: Board, team: Team): Int =
155+
fun greatestSwarmSize(board: Board, team: ITeam): Int =
156156
greatestSwarm(board, team).size
157157

158158
@JvmStatic
159159
fun greatestSwarmSize(set: Set<Coordinates>): Int =
160160
greatestSwarm(set).size
161161

162162
@JvmStatic
163-
fun isSwarmConnected(board: Board, team: Team): Boolean {
163+
fun isSwarmConnected(board: Board, team: ITeam): Boolean {
164164
val fieldsWithFish = board.fieldsForTeam(team)
165165
val numGreatestSwarm: Int = greatestSwarmSize(fieldsWithFish.toHashSet())
166166
return numGreatestSwarm == fieldsWithFish.size

plugin2026/src/main/kotlin/sc/plugin2026/util/Point.kt

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)