Skip to content

Commit 65402e4

Browse files
committed
feat(plugin26): implement GameRuleLogic swarm checks
1 parent e0f3b99 commit 65402e4

File tree

2 files changed

+31
-27
lines changed

2 files changed

+31
-27
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class Board(gameField: MutableTwoDBoard<FieldS> = randomFields()): RectangularBo
3535
fun getTeam(pos: Coordinates): Team? =
3636
this[pos].state.team
3737

38+
fun fieldsForTeam(team: Team): Collection<Coordinates> =
39+
filterValues { field -> field.state.team == team }.map { it.key }
40+
3841
companion object {
3942
/** Erstellt eine zufälliges Spielbrett. */
4043
private fun randomFields(): MutableTwoDBoard<FieldS> {

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

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import sc.api.plugins.Coordinates
44
import sc.api.plugins.Direction
55
import sc.api.plugins.Team
66
import sc.plugin2026.Board
7-
import sc.plugin2026.Field
87
import sc.plugin2026.FieldState
98
import sc.plugin2026.Move
109
import sc.plugin2026.PiranhaMoveMistake
@@ -86,58 +85,58 @@ object GameRuleLogic {
8685
.map { direction -> Move(pos, direction)}
8786
.filter { move -> checkMove(board, move) == null }
8887

89-
private fun getDirectNeighbour(board: Board, f: Field, parentSet: Set<Field>): Set<Field> {
90-
val returnSet: MutableSet<Field> = java.util.HashSet()
88+
private fun getDirectNeighbour(f: Coordinates, parentSet: Set<Coordinates>): Set<Coordinates> {
89+
val returnSet: MutableSet<Coordinates> = HashSet()
9190
for(i in -1..1) {
9291
for(j in -1..1) {
9392
val x = f.x + i
9493
val y = f.y + j
9594
if(x < 0 || x >= PiranhaConstants.BOARD_LENGTH || y < 0 || y >= PiranhaConstants.BOARD_LENGTH || (i == 0 && j == 0)) continue
9695

97-
val field: Field = board.getField(x, y)
98-
if(parentSet.contains(field)) {
99-
returnSet.add(field)
96+
val coord = Coordinates(x, y)
97+
if(parentSet.contains(coord)) {
98+
returnSet.add(coord)
10099
}
101100
}
102101
}
103102
return returnSet
104103
}
105104

106-
private fun getSwarm(board: Board, found: MutableSet<Field>, swarm: MutableSet<Field>): MutableSet<Field> {
105+
private fun getSwarm(found: MutableSet<Coordinates>, swarm: MutableSet<Coordinates>): MutableSet<Coordinates> {
107106
if(swarm.isEmpty() && !found.isEmpty()) {
108107
val field = found.iterator().next()
109108
swarm.add(field)
110109
found.remove(field)
111110
}
112111

113-
var tmpSwarm: MutableSet<Field> = java.util.HashSet(swarm)
112+
var tmpSwarm: MutableSet<Coordinates> = HashSet(swarm)
114113
// O(swarm.size()) time
115114
for(field in swarm) {
116115
// Constant time for both calls (max of 8 neighbors)
117-
val neighbours = getDirectNeighbour(board, field, found)
116+
val neighbours = getDirectNeighbour(field, found)
118117
tmpSwarm.addAll(neighbours)
119118
}
120119

121120
// O(found.size()*swarm.size()) time
122121
// FIXME: Might be improved O(swarm.size()) should be possible
123-
if(swarm.size != tmpSwarm.size) tmpSwarm = getSwarm(board, found, tmpSwarm)
122+
if(swarm.size != tmpSwarm.size) tmpSwarm = getSwarm(found, tmpSwarm)
124123

125124
swarm.addAll(tmpSwarm)
126125

127126
found.removeAll(swarm)
128127
return swarm
129128
}
130129

131-
fun greatestSwarm(board: Board, fieldsToCheck: Set<Field>): Set<Field> {
130+
@JvmStatic
131+
fun greatestSwarm(fieldsToCheck: Set<Coordinates>): Set<Coordinates> {
132132
// Make a copy, so there will be no conflict with direct calls.
133-
val occupiedFields: MutableSet<Field> = java.util.HashSet(fieldsToCheck)
134-
var greatestSwarm: Set<Field> = java.util.HashSet()
133+
val occupiedFields: MutableSet<Coordinates> = HashSet(fieldsToCheck)
134+
var greatestSwarm: Set<Coordinates> = HashSet()
135135
var maxSize = -1
136136

137137
// this is a maximum of MAX_FISH iterations, so it is a linear iteration altogether
138138
while(!occupiedFields.isEmpty() && occupiedFields.size > maxSize) {
139-
val empty: MutableSet<Field> = java.util.HashSet()
140-
val swarm: Set<Field> = getSwarm(board, occupiedFields, empty)
139+
val swarm: Set<Coordinates> = getSwarm(occupiedFields, HashSet())
141140
if(maxSize < swarm.size) {
142141
maxSize = swarm.size
143142
greatestSwarm = swarm
@@ -146,22 +145,24 @@ object GameRuleLogic {
146145
return greatestSwarm
147146
}
148147

149-
fun greatestSwarm(board: Board, player: Team?): Set<Field> {
150-
val occupiedFields = getOwnFields(board, player)
151-
return greatestSwarm(board, occupiedFields)
148+
@JvmStatic
149+
fun greatestSwarm(board: Board, team: Team): Set<Coordinates> {
150+
val occupiedFields = board.fieldsForTeam(team)
151+
return greatestSwarm(occupiedFields.toHashSet())
152152
}
153153

154-
fun greatestSwarmSize(board: Board, player: Team?): Int {
155-
return greatestSwarm(board, player).size
156-
}
154+
@JvmStatic
155+
fun greatestSwarmSize(board: Board, team: Team): Int =
156+
greatestSwarm(board, team).size
157157

158-
fun greatestSwarmSize(board: Board, set: Set<Field?>): Int {
159-
return greatestSwarm(board, set).size
160-
}
158+
@JvmStatic
159+
fun greatestSwarmSize(set: Set<Coordinates>): Int =
160+
greatestSwarm(set).size
161161

162-
fun isSwarmConnected(board: Board, player: Team?): Boolean {
163-
val fieldsWithFish = getOwnFields(board, player)
164-
val numGreatestSwarm: Int = greatestSwarmSize(board, fieldsWithFish)
162+
@JvmStatic
163+
fun isSwarmConnected(board: Board, team: Team): Boolean {
164+
val fieldsWithFish = board.fieldsForTeam(team)
165+
val numGreatestSwarm: Int = greatestSwarmSize(fieldsWithFish.toHashSet())
165166
return numGreatestSwarm == fieldsWithFish.size
166167
}
167168
}

0 commit comments

Comments
 (0)