Skip to content

Commit 868a439

Browse files
committed
build: add old game plugins for reference
1 parent c78035c commit 868a439

File tree

514 files changed

+119127
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

514 files changed

+119127
-0
lines changed

.old-plugins/blokus_2020/Board.kt

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package sc.plugin2020
2+
3+
import com.thoughtworks.xstream.annotations.XStreamAlias
4+
import com.thoughtworks.xstream.annotations.XStreamConverter
5+
import com.thoughtworks.xstream.annotations.XStreamImplicit
6+
import com.thoughtworks.xstream.converters.collections.ArrayConverter
7+
import com.thoughtworks.xstream.converters.extended.ToStringConverter
8+
import sc.api.plugins.IBoard
9+
import sc.plugin2020.util.Constants
10+
import sc.plugin2020.util.CubeCoordinates
11+
import sc.shared.PlayerColor
12+
import kotlin.collections.HashSet
13+
import kotlin.math.max
14+
import kotlin.math.min
15+
16+
@XStreamAlias(value = "board")
17+
data class Board(
18+
@XStreamConverter(value = ArrayConverter::class, nulls = [ToStringConverter::class])
19+
@XStreamImplicit(itemFieldName = "fields")
20+
val gameField: Array<Array<Field?>>
21+
): IBoard {
22+
23+
val fields: List<Field>
24+
get() = gameField.flatMap { it.filterNotNull() }
25+
26+
constructor(): this(fillGameField()) {
27+
blockFields(randomFields())
28+
}
29+
30+
/** Creates a new Board with blockers at the given [blockedFields]. */
31+
constructor(vararg blockedFields: CubeCoordinates): this() {
32+
blockFields(blockedFields.toSet())
33+
}
34+
35+
/** Creates a new Board from clones of the given [fields]. Does not fill it up! */
36+
constructor(fields: Collection<Field>): this(gameFieldFromFields(fields))
37+
38+
/** Copy constructor to create a new deeply copied state from the given [board]. */
39+
constructor(board: Board): this(board.fields)
40+
41+
/** Creates a deep copy of this [Board]. */
42+
public override fun clone() = Board(this)
43+
44+
/** Returns [amount] random fields from [fields]. */
45+
fun randomFields(amount: Int = 3): Collection<Field> {
46+
val all = this.fields
47+
val fields = HashSet<Field>()
48+
while(fields.size < amount)
49+
fields.add(all.random())
50+
return fields
51+
}
52+
53+
private fun blockFields(fields: Collection<CubeCoordinates>) {
54+
fields.forEach {
55+
this.gameField[it.x + SHIFT][it.y + SHIFT] = Field(it.x, it.y, true)
56+
}
57+
}
58+
59+
fun getField(pos: CubeCoordinates): Field =
60+
gameField[pos.x + SHIFT][pos.y + SHIFT] ?: throw IndexOutOfBoundsException("No field at $pos")
61+
62+
override fun getField(cubeX: Int, cubeY: Int): Field =
63+
this.getField(CubeCoordinates(cubeX, cubeY))
64+
65+
fun getField(cubeX: Int, cubeY: Int, cubeZ: Int): Field =
66+
this.getField(CubeCoordinates(cubeX, cubeY, cubeZ))
67+
68+
/** @return all Pieces on the Board. Prefer [GameState.getDeployedPieces] if possible for better performance. */
69+
fun getPieces(): List<Piece> {
70+
val pieces = mutableListOf<Piece>()
71+
for(x in -SHIFT..SHIFT) {
72+
for(y in max(-SHIFT, -x - SHIFT)..min(SHIFT, -x + SHIFT)) {
73+
val field = gameField[x + SHIFT][y + SHIFT]
74+
if(field != null)
75+
pieces.addAll(field.pieces)
76+
}
77+
}
78+
return pieces
79+
}
80+
81+
override fun toString(): String {
82+
val text = StringBuilder("Board")
83+
for (x in 0 until Constants.BOARD_SIZE) {
84+
val line = StringBuilder()
85+
for (y in 0 until Constants.BOARD_SIZE) {
86+
val field = this.gameField[x][y]
87+
when {
88+
field == null -> line.insert(0, ' ')
89+
!field.hasOwner -> line.append("[]")
90+
else -> line.append(field.owner!!.letter).append(field.topPiece!!.type.letter)
91+
}
92+
}
93+
text.append('\n').append(line)
94+
}
95+
return text.toString()
96+
}
97+
98+
override fun equals(other: Any?): Boolean {
99+
if(this === other) return true
100+
if(javaClass != other?.javaClass) return false
101+
return gameField.contentDeepEquals((other as Board).gameField)
102+
}
103+
104+
override fun hashCode(): Int =
105+
gameField.contentDeepHashCode()
106+
107+
fun getFieldsOwnedBy(owner: PlayerColor): List<Field> = fields.filter { it.owner == owner }
108+
109+
companion object {
110+
private const val SHIFT = (Constants.BOARD_SIZE - 1) / 2
111+
112+
private fun emptyGameField() = Array(Constants.BOARD_SIZE) { arrayOfNulls<Field>(Constants.BOARD_SIZE) }
113+
114+
/** Fills the given [gameField] with all missing Fields for a valid Board. */
115+
@JvmStatic
116+
fun fillGameField(gameField: Array<Array<Field?>> = emptyGameField()): Array<Array<Field?>> {
117+
for(x in -SHIFT..SHIFT) {
118+
for(y in max(-SHIFT, -x - SHIFT)..min(SHIFT, -x + SHIFT)) {
119+
if(gameField[x + SHIFT][y + SHIFT] == null) {
120+
gameField[x + SHIFT][y + SHIFT] = Field(CubeCoordinates(x, y))
121+
}
122+
}
123+
}
124+
return gameField
125+
}
126+
127+
/** Creates a new gameField from clones of the given [fields].
128+
* @return a gameField consisting only of clones of the [fields] */
129+
@JvmStatic
130+
fun gameFieldFromFields(fields: Collection<Field>): Array<Array<Field?>> {
131+
val gameField = emptyGameField()
132+
var x: Int
133+
var y: Int
134+
for(f in fields) {
135+
if(f.coordinates.x > SHIFT || f.coordinates.x < -SHIFT || f.coordinates.y > SHIFT || f.coordinates.y < -SHIFT)
136+
throw IndexOutOfBoundsException()
137+
x = f.coordinates.x + SHIFT
138+
y = f.coordinates.y + SHIFT
139+
gameField[x][y] = f.clone()
140+
}
141+
return gameField
142+
}
143+
}
144+
}

.old-plugins/blokus_2020/Field.kt

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package sc.plugin2020
2+
3+
import com.thoughtworks.xstream.annotations.XStreamAlias
4+
import com.thoughtworks.xstream.annotations.XStreamAsAttribute
5+
import com.thoughtworks.xstream.annotations.XStreamImplicit
6+
import sc.api.plugins.IField
7+
import sc.plugin2020.util.CubeCoordinates
8+
import sc.shared.PlayerColor
9+
import java.util.*
10+
11+
@XStreamAlias("field")
12+
class Field(
13+
x: Int = 0,
14+
y: Int = 0,
15+
z: Int = -x - y,
16+
pieces: Stack<Piece> = Stack(),
17+
@XStreamAsAttribute
18+
val isObstructed: Boolean = false
19+
): CubeCoordinates(x, y, z), IField {
20+
21+
// Custom getter because an empty collection in XML gets deserialized to null, not to an empty collection!
22+
// See http://x-stream.github.io/faq.html#Serialization_implicit_null
23+
@XStreamImplicit
24+
var pieces = pieces
25+
internal set
26+
get() {
27+
@Suppress("SENSELESS_COMPARISON")
28+
if(field == null) field = Stack()
29+
return field
30+
}
31+
32+
val fieldState: FieldState
33+
get() {
34+
if(isObstructed)
35+
return FieldState.OBSTRUCTED
36+
return when(owner) {
37+
PlayerColor.RED -> FieldState.RED
38+
PlayerColor.BLUE -> FieldState.BLUE
39+
null -> FieldState.EMPTY
40+
}
41+
}
42+
43+
/** @return true iff this [Field] has no pieces and is not obstructed. */
44+
val isEmpty: Boolean
45+
get() = pieces.isEmpty() && !isObstructed
46+
47+
/** @return true iff this [Field] has pieces on it */
48+
val hasOwner: Boolean
49+
get() = pieces.isNotEmpty()
50+
51+
/** Since [Field] is a subclass of [CubeCoordinates], this returns itself. */
52+
val coordinates: CubeCoordinates
53+
get() = this
54+
55+
/** @return owner of the uppermost piece on this field, or null if it is empty. */
56+
val owner: PlayerColor?
57+
get() = topPiece?.owner
58+
59+
/** @return the uppermost piece on the field, or null is it is empty. */
60+
val topPiece: Piece?
61+
get() = if(pieces.isEmpty()) null else pieces.peek()
62+
63+
constructor(position: CubeCoordinates, obstructed: Boolean): this(position.x, position.y, position.z, isObstructed = obstructed)
64+
65+
constructor(position: CubeCoordinates, vararg pieces: Piece): this(position.x, position.y, position.z, pieces.toCollection(Stack()))
66+
67+
constructor (x: Int, y: Int, obstructed: Boolean): this(x, y, isObstructed = obstructed)
68+
69+
constructor(x: Int, y: Int, vararg pieces: Piece): this(x, y, pieces = pieces.toCollection(Stack()) as Stack<Piece>)
70+
71+
constructor(field: Field): this(field.x, field.y, field.z, field.pieces.toCollection(Stack()), field.isObstructed)
72+
73+
public override fun clone() = Field(this)
74+
75+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package sc.plugin2020
2+
3+
enum class FieldState {
4+
EMPTY,
5+
OBSTRUCTED,
6+
RED,
7+
BLUE
8+
}

.old-plugins/blokus_2020/GameState.kt

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package sc.plugin2020
2+
3+
import com.thoughtworks.xstream.annotations.XStreamAlias
4+
import com.thoughtworks.xstream.annotations.XStreamAsAttribute
5+
import com.thoughtworks.xstream.annotations.XStreamOmitField
6+
import sc.api.plugins.TwoPlayerGameState
7+
import sc.framework.plugins.Player
8+
import sc.plugin2020.util.Constants
9+
import sc.plugin2020.util.GameRuleLogic
10+
import sc.shared.PlayerColor
11+
12+
@XStreamAlias(value = "state")
13+
class GameState @JvmOverloads constructor(
14+
override var red: Player = Player(PlayerColor.RED),
15+
override var blue: Player = Player(PlayerColor.BLUE),
16+
override var board: Board = Board(),
17+
turn: Int = 0,
18+
private val undeployedRedPieces: MutableList<Piece> = parsePiecesString(Constants.STARTING_PIECES, PlayerColor.RED),
19+
private val undeployedBluePieces: MutableList<Piece> = parsePiecesString(Constants.STARTING_PIECES, PlayerColor.BLUE),
20+
override var lastMove: Move? = null
21+
): TwoPlayerGameState<Player>() {
22+
23+
@XStreamOmitField
24+
private var allPieces: Collection<Piece> = undeployedBluePieces + undeployedRedPieces + board.getPieces()
25+
26+
@XStreamAsAttribute
27+
override var turn = turn
28+
set(value) {
29+
field = value
30+
currentPlayerColor = currentPlayerFromTurn()
31+
}
32+
33+
@XStreamAsAttribute
34+
override var currentPlayerColor: PlayerColor = currentPlayerFromTurn()
35+
private set
36+
37+
val gameStats: Array<IntArray>
38+
get() = PlayerColor.values().map { getPlayerStats(it) }.toTypedArray()
39+
40+
fun readResolve(): GameState {
41+
allPieces = undeployedBluePieces + undeployedRedPieces + board.getPieces()
42+
return this
43+
}
44+
45+
/** Copy constructor to create a new deeply copied state from the given [state]. */
46+
constructor(state: GameState): this(state.red.clone(), state.blue.clone(), state.board.clone(), state.turn, ArrayList(state.undeployedRedPieces), ArrayList(state.undeployedBluePieces), state.lastMove)
47+
48+
/** Creates a deep copy of this [GameState]. */
49+
public override fun clone() = GameState(this)
50+
51+
fun getUndeployedPieces(owner: PlayerColor): MutableList<Piece> {
52+
return when(owner) {
53+
PlayerColor.RED -> undeployedRedPieces
54+
PlayerColor.BLUE -> undeployedBluePieces
55+
}
56+
}
57+
58+
fun getDeployedPieces(owner: PlayerColor): List<Piece> {
59+
val ownedPieces = allPieces.filterTo(ArrayList()) { it.owner == owner }
60+
getUndeployedPieces(owner).forEach { ownedPieces.remove(it) }
61+
return ownedPieces
62+
}
63+
64+
fun addPlayer(player: Player) {
65+
when(player.color) {
66+
PlayerColor.RED -> red = player
67+
PlayerColor.BLUE -> blue = player
68+
}
69+
}
70+
71+
override fun getPointsForPlayer(playerColor: PlayerColor): Int {
72+
return GameRuleLogic.freeBeeNeighbours(this.board, playerColor)
73+
}
74+
75+
fun getPlayerStats(p: Player): IntArray {
76+
return getPlayerStats(p.color)
77+
}
78+
79+
fun getPlayerStats(playerColor: PlayerColor): IntArray =
80+
intArrayOf(this.getPointsForPlayer(playerColor))
81+
82+
override fun toString(): String = "GameState Zug $turn"
83+
84+
override fun equals(other: Any?): Boolean {
85+
if(this === other) return true
86+
if(other !is GameState) return false
87+
88+
if(red != other.red) return false
89+
if(blue != other.blue) return false
90+
if(board != other.board) return false
91+
if(undeployedRedPieces != other.undeployedRedPieces) return false
92+
if(undeployedBluePieces != other.undeployedBluePieces) return false
93+
if(allPieces.size != other.allPieces.size || !allPieces.containsAll(other.allPieces)) return false
94+
if(turn != other.turn) return false
95+
if(currentPlayerColor != other.currentPlayerColor) return false
96+
97+
return true
98+
}
99+
100+
override fun hashCode(): Int {
101+
var result = red.hashCode()
102+
result = 31 * result + blue.hashCode()
103+
result = 31 * result + board.hashCode()
104+
result = 31 * result + undeployedRedPieces.hashCode()
105+
result = 31 * result + undeployedBluePieces.hashCode()
106+
result = 31 * result + allPieces.hashCode()
107+
result = 31 * result + turn
108+
return result
109+
}
110+
111+
companion object {
112+
fun parsePiecesString(s: String, p: PlayerColor): ArrayList<Piece> {
113+
val l = ArrayList<Piece>()
114+
for(c in s.toCharArray()) {
115+
when(c) {
116+
'Q' -> l.add(Piece(p, PieceType.BEE))
117+
'S' -> l.add(Piece(p, PieceType.SPIDER))
118+
'G' -> l.add(Piece(p, PieceType.GRASSHOPPER))
119+
'B' -> l.add(Piece(p, PieceType.BEETLE))
120+
'A' -> l.add(Piece(p, PieceType.ANT))
121+
}
122+
}
123+
return l
124+
}
125+
}
126+
}

.old-plugins/blokus_2020/Move.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package sc.plugin2020
2+
3+
import com.thoughtworks.xstream.annotations.XStreamAlias
4+
import sc.api.plugins.IMove
5+
import sc.plugin2020.util.CubeCoordinates
6+
7+
/* NOTE: Remember to add all these classes to classesToRegister in sc/plugin2020/util/Configuration.kt */
8+
sealed class Move: IMove {
9+
abstract val destination: CubeCoordinates?
10+
var hint: String? = null
11+
}
12+
13+
@XStreamAlias(value = "setmove")
14+
data class SetMove(val piece: Piece, override val destination: CubeCoordinates): Move() {
15+
override fun toString() = String.format("Set %s %s to %s", this.piece.owner, this.piece.type, this.destination)
16+
}
17+
18+
@XStreamAlias(value = "dragmove")
19+
data class DragMove(val start: CubeCoordinates, override val destination: CubeCoordinates): Move() {
20+
override fun toString() = String.format("Drag from %s to %s", this.start, this.destination)
21+
}
22+
23+
@XStreamAlias(value = "skipmove")
24+
object SkipMove: Move() {
25+
override val destination: CubeCoordinates?
26+
get() = null
27+
override fun equals(other: Any?) = other is SkipMove
28+
override fun toString() = "SkipMove"
29+
}

0 commit comments

Comments
 (0)