Skip to content

Commit 87d0a4c

Browse files
committed
feat: implement generic Cartesian directions and refactor hex additions
1 parent e6f8650 commit 87d0a4c

File tree

6 files changed

+63
-74
lines changed

6 files changed

+63
-74
lines changed

plugin/src/main/kotlin/sc/plugin2023/Board.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sc.plugin2023
22

33
import com.thoughtworks.xstream.annotations.XStreamAlias
44
import sc.api.plugins.*
5+
import sc.api.plugins.Coordinates
56
import kotlin.random.Random
67
import sc.plugin2023.util.PenguinConstants as Constants
78

@@ -50,7 +51,7 @@ class Board(override val gameField: MutableTwoDBoard<Field> = generateFields()):
5051
fun <T> filterFields(filter: (Field, Coordinates) -> T?): Collection<T> =
5152
gameField.flatMapIndexed { y, row ->
5253
row.mapIndexedNotNull { x, field ->
53-
filter(field, Coordinates.doubledHex(x, y))
54+
filter(field, Coordinates(x * 2 + y % 2, y))
5455
}
5556
}
5657

plugin/src/main/kotlin/sc/plugin2023/GameState.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package sc.plugin2023
33
import com.thoughtworks.xstream.annotations.XStreamAlias
44
import com.thoughtworks.xstream.annotations.XStreamAsAttribute
55
import sc.api.plugins.*
6+
import sc.api.plugins.Coordinates
7+
import sc.api.plugins.HexDirection
68
import sc.plugin2023.util.PenguinsMoveMistake
79
import sc.plugin2023.util.PenguinConstants
810
import sc.shared.InvalidMoveException
@@ -74,10 +76,10 @@ data class GameState @JvmOverloads constructor(
7476
!penguinsPlaced && board[pos].fish == 1
7577

7678
fun immovable(team: Team? = null) =
77-
board.getPenguins()
79+
board.getPenguins()
7880
.filter { team == null || it.second == team }
7981
.takeIf { it.size == PenguinConstants.PENGUINS * (if(team == null) Team.values().size else 1) }
80-
?.all { pair -> pair.first.hexNeighbors.all { board.getOrEmpty(it).fish == 0 } } ?: false
82+
?.all { pair -> HexDirection.values().map { pair.first + it }.all { board.getOrEmpty(it).fish == 0 } } ?: false
8183

8284
override val isOver: Boolean
8385
get() = immovable()

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

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

33
import com.thoughtworks.xstream.annotations.XStreamAlias
44
import sc.api.plugins.Coordinates
5+
import sc.api.plugins.Direction
56
import sc.api.plugins.IMove
6-
import sc.api.plugins.Vector
77

88
@XStreamAlias("move")
9-
/** Ein Spielzug. */
9+
/** Spielzug: Eine Bewegung eines Fisches. */
1010
data class Move(
11-
/** Ursprungsposition des Zugs. */
11+
/** Position des zu bewegenden Fisches. */
1212
val from: Coordinates,
13-
/** Zielposition des Zugs. */
14-
val to: Coordinates,
15-
): IMove, Comparable<Move> {
16-
val delta: Vector?
17-
get() = from?.let { to - it }
18-
19-
fun reversed(): Move? =
20-
from?.let { Move(to, from) }
21-
22-
override fun compareTo(other: Move): Int =
23-
other.delta?.let { delta?.compareTo(it) } ?: 0
13+
/** Bewegungsrichtung des Zugs. */
14+
val direction: Direction,
15+
): IMove {
2416

2517
override fun toString(): String =
26-
"Schwimmen $from zu $to"
18+
"Schwimme von $from in Richtung $direction"
2719

28-
companion object {
29-
@JvmStatic
30-
fun run(start: Coordinates, delta: Vector): Move =
31-
Move(start, (start + delta))
32-
}
3320
}

sdk/src/main/server-api/sc/api/plugins/Coordinates.kt

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ class Positioned<FIELD>(
88
override val value: FIELD
99
): Map.Entry<Coordinates, FIELD>
1010

11-
/** Eine (normalerweise kartesische) 2D-Koordinate der Form (x, y).
12-
* Für Hex-Koordinaten siehe https://www.redblobgames.com/grids/hexagons/#coordinates-doubled */
11+
/** Eine kartesische 2D-Koordinate der Form (x, y). */
1312
@XStreamAlias(value = "coordinates")
1413
data class Coordinates(
1514
@XStreamAsAttribute val x: Int,
@@ -30,31 +29,12 @@ data class Coordinates(
3029
/** Wandelt die [Coordinates] in einen entsprechenden [Vector]. */
3130
operator fun unaryPlus(): Vector = Vector(x, y)
3231

33-
/** Gibt ein Set der vier benachbarten Felder dieser Koordinaten zurück. */
32+
/** Gibt die vier benachbarten Feldkoordinaten zurück. */
3433
val neighbors: Collection<Coordinates>
35-
get() = Vector.cardinals.map { this + it }
36-
37-
val hexNeighbors: Collection<Coordinates>
38-
get() = HexDirection.values().map { this + it }
39-
40-
/** The array indices for a rectangular board of hex fields. */
41-
fun fromDoubledHex() = Coordinates(x / 2, y)
42-
/** Turn array indices for a rectangular board into double Hex coordinates. */
43-
fun toDoubledHex() = doubledHex(x, y)
44-
45-
/**
46-
* Wandelt DoubledHex-[Coordinates] zu [CubeCoordinates] um.
47-
*
48-
* @see <a href="https://www.redblobgames.com/grids/hexagons/#conversions-axial">Cube to Axial Coordinate Conversion</a>
49-
* @see <a href="https://www.redblobgames.com/grids/hexagons/#conversions-doubled">Axial to Doubled Coordinate Conversion</a>
50-
*/
51-
fun doubledHexToCube(): CubeCoordinates =
52-
CubeCoordinates((x - y) / 2, y)
34+
get() = Direction.cardinals.map { this + it }
5335

5436
companion object {
5537
/** Der Ursprung des Koordinatensystems (0, 0). */
5638
val ORIGIN = Coordinates(0, 0)
57-
58-
fun doubledHex(x: Int, y: Int) = Coordinates(x * 2 + y % 2, y)
5939
}
6040
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package sc.api.plugins
2+
3+
import com.thoughtworks.xstream.annotations.XStreamAlias
4+
import kotlin.random.Random
5+
6+
@XStreamAlias(value = "direction")
7+
enum class Direction(val vector: Vector): IVector by vector {
8+
UP(Vector(0, 1)),
9+
// TODO
10+
UP_RIGHT
11+
RIGHT
12+
DOWN_RIGHT
13+
DOWN
14+
DOWN_LEFT
15+
LEFT
16+
UP_LEFT
17+
18+
companion object {
19+
// TODO
20+
val diagonals = arrayOf(Vector(-1, -1), Vector(-1, 1), Vector(1, -1), Vector(1, 1))
21+
val cardinals = arrayOf(UP, RIGHT, DOWN, LEFT)
22+
}
23+
}
24+
25+
enum class HexDirection(val vector: Vector): IVector by vector {
26+
RIGHT(Vector(+2, 0)),
27+
DOWN_RIGHT(Vector(+1, +1)),
28+
DOWN_LEFT(Vector(-1, +1)),
29+
LEFT(Vector(-2, 0)),
30+
UP_LEFT(Vector(-1, -1)),
31+
UP_RIGHT(Vector(+1, -1));
32+
33+
fun withNeighbors(): Array<HexDirection> = arrayOf(rotatedBy(-1), this, rotatedBy(1))
34+
35+
fun opposite(): HexDirection = values().let { it[(ordinal + 3) % it.size] }
36+
37+
fun turnCountTo(target: HexDirection): Int {
38+
val diff = target.ordinal - this.ordinal
39+
return if(diff >= 0) diff else diff + values().size
40+
}
41+
42+
fun rotatedBy(turns: Int): HexDirection = values().let { it[(ordinal + turns).mod(it.size)] }
43+
44+
companion object {
45+
fun random(): HexDirection = values()[Random.nextInt(values().size)]
46+
}
47+
}

sdk/src/main/server-api/sc/api/plugins/Vector.kt

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -43,32 +43,4 @@ data class Vector(override val dx: Int, override val dy: Int): IVector, Comparab
4343
/** Konvertiert den Vektor zu entsprechenden [Coordinates]. */
4444
operator fun unaryPlus(): Coordinates = Coordinates(dx, dy)
4545

46-
companion object {
47-
val diagonals = arrayOf(Vector(-1, -1), Vector(-1, 1), Vector(1, -1), Vector(1, 1))
48-
val cardinals = arrayOf(Vector(-1, 0), Vector(0, -1), Vector(1, 0), Vector(0, 1))
49-
}
50-
}
51-
52-
enum class HexDirection(val vector: Vector): IVector by vector {
53-
RIGHT(Vector(+2, 0)),
54-
DOWN_RIGHT(Vector(+1, +1)),
55-
DOWN_LEFT(Vector(-1, +1)),
56-
LEFT(Vector(-2, 0)),
57-
UP_LEFT(Vector(-1, -1)),
58-
UP_RIGHT(Vector(+1, -1));
59-
60-
fun withNeighbors(): Array<HexDirection> = arrayOf(rotatedBy(-1), this, rotatedBy(1))
61-
62-
fun opposite(): HexDirection = values().let { it[(ordinal + 3) % it.size] }
63-
64-
fun turnCountTo(target: HexDirection): Int {
65-
val diff = target.ordinal - this.ordinal
66-
return if(diff >= 0) diff else diff + values().size
67-
}
68-
69-
fun rotatedBy(turns: Int): HexDirection = values().let { it[(ordinal + turns).mod(it.size)] }
70-
71-
companion object {
72-
fun random(): HexDirection = values()[Random.nextInt(values().size)]
73-
}
7446
}

0 commit comments

Comments
 (0)