@@ -2,10 +2,21 @@ package sc.plugin2019
2
2
3
3
import com.thoughtworks.xstream.annotations.XStreamAlias
4
4
import com.thoughtworks.xstream.annotations.XStreamAsAttribute
5
+ import sc.api.plugins.Direction
6
+ import sc.api.plugins.ITeam
7
+ import sc.api.plugins.Stat
5
8
import sc.api.plugins.Team
6
9
import sc.api.plugins.TwoPlayerGameState
7
10
import sc.plugin2026.Board
11
+ import sc.plugin2026.FieldState
8
12
import sc.plugin2026.Move
13
+ import sc.plugin2026.PiranhaMoveMistake
14
+ import sc.plugin2026.util.GameRuleLogic
15
+ import sc.plugin2026.util.PiranhaConstants
16
+ import sc.shared.IMoveMistake
17
+ import sc.shared.InvalidMoveException
18
+ import sc.shared.MoveMistake
19
+ import sc.shared.WinCondition
9
20
10
21
/* *
11
22
* The GameState class represents the current state of the game.
@@ -28,8 +39,91 @@ data class GameState @JvmOverloads constructor(
28
39
): TwoPlayerGameState<Move>(Team .ONE ) {
29
40
30
41
override fun getPointsForTeam (team : ITeam ): IntArray =
31
- GameRuleLogic .greatestSwarmSize(board, playerColor) // TODO important
42
+ GameRuleLogic .greatestSwarmSize(board, team) // TODO important
43
+
44
+ // TODO test if one player is surrounded he loses
45
+ override val isOver: Boolean
46
+ get() = players.any { it.inGoal } && turn.mod(2 ) == 0 || turn / 2 >= PiranhaConstants .ROUND_LIMIT
47
+
48
+ override val winCondition: WinCondition ?
49
+ get() = TODO (" Not yet implemented" )
50
+
51
+ override fun performMoveDirectly (move : Move ) {
52
+ if (board.getTeam(move.from) != currentTeam) {
53
+ throw InvalidMoveException (PiranhaMoveMistake .WRONG_START , move)
54
+ }
55
+ checkMove(move)?.let { throw InvalidMoveException (it, move) }
56
+ val distance = movementDistance(move)
57
+ board[move.from].state = FieldState .EMPTY
58
+ board[move.from + move.direction.vector * distance].state = FieldState .from(currentTeam)
59
+ }
60
+
61
+ fun movementDistance (move : Move ): Int {
62
+ var count = 1
63
+ var pos = move.from
64
+ while (true ) {
65
+ pos + = move.direction
66
+ val field = board.getOrNull(pos) ? : break
67
+ if (field.state.team != null ) {
68
+ count++
69
+ }
70
+ }
71
+ pos = move.from
72
+ while (true ) {
73
+ pos + = move.direction.opposite
74
+ val field = board.getOrNull(pos) ? : break
75
+ if (field.state.team != null ) {
76
+ count++
77
+ }
78
+ }
79
+ return count
80
+ }
81
+
82
+ fun checkMove (move : Move ): IMoveMistake ? {
83
+ val distance = movementDistance(move)
84
+ var pos = move.from
85
+ var moved = 1
86
+ while (moved < distance) {
87
+ pos + = move.direction
88
+ val field = board.getOrNull(pos) ? : return MoveMistake .DESTINATION_OUT_OF_BOUNDS
89
+ if (field.state.team == otherTeam) {
90
+ return PiranhaMoveMistake .JUMP_OVER_OPPONENT
91
+ }
92
+ moved++
93
+ }
94
+ pos + = move.direction
95
+ val state = board.getOrNull(pos)?.state
96
+ return when (state) {
97
+ null -> MoveMistake .DESTINATION_OUT_OF_BOUNDS
98
+ FieldState .OBSTRUCTED -> MoveMistake .DESTINATION_BLOCKED
99
+ else -> {
100
+ if (state.team == currentTeam) {
101
+ MoveMistake .DESTINATION_BLOCKED_BY_SELF
102
+ } else {
103
+ null
104
+ }
105
+ }
106
+ }
107
+ }
108
+
109
+ override fun moveIterator (): Iterator <Move > {
110
+ val piranhas = board.filterValues { field -> field.state.team == currentTeam }
111
+ val moves = ArrayList <Move >(piranhas.size * 2 )
112
+ for (piranha in piranhas) {
113
+ for (direction in Direction .values()) {
114
+ val move = Move (piranha.key, direction)
115
+ if (checkMove(move) == null ) {
116
+ moves.add(move)
117
+ }
118
+ }
119
+ }
120
+ return moves.iterator()
121
+ }
122
+
123
+ override fun clone (): TwoPlayerGameState <Move > =
124
+ copy(board = board.clone())
125
+
126
+ override fun teamStats (team : ITeam ): List <Stat > = listOf () // TODO
32
127
33
- // TODO implement missing methods - check previous years
34
128
35
129
}
0 commit comments