Skip to content

Commit a693238

Browse files
committed
Some changes
Signed-off-by: Efeturi Money <[email protected]>
1 parent 9c237f2 commit a693238

File tree

28 files changed

+179
-268
lines changed

28 files changed

+179
-268
lines changed

Diff for: .idea/gradle.xml

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: engine/api/build.gradle.kts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
plugins {
2+
alias(libs.plugins.kotlin.jvm)
3+
}
4+
5+
dependencies {
6+
implementation(libs.kotlin.stdlib)
7+
implementation(libs.kotlinx.immutable)
8+
implementation(libs.kotlinx.coroutines.core)
9+
implementation(libs.jetbrains.compose.runtime)
10+
implementation(libs.jetbrains.compose.ui.util)
11+
}

Diff for: engine/api/src/dev/efemoney/lexiko/engine/api/bag.kt

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package dev.efemoney.lexiko.engine.api
2+
3+
import androidx.compose.runtime.Stable
4+
import androidx.compose.ui.util.fastForEach
5+
6+
@Stable
7+
interface BagOfTiles {
8+
val remainingTilesCount: Int
9+
val isEmpty get() = remainingTilesCount == 0
10+
11+
fun pickRandomTile(): Tile?
12+
fun pickRandomTiles(max: Int): List<Tile> =
13+
if (isEmpty) emptyList() else buildList { for (i in 0..<max) add(pickRandomTile() ?: break) }
14+
15+
fun returnTile(tile: Tile)
16+
fun returnTiles(tiles: List<Tile>) = tiles.fastForEach(::returnTile)
17+
}
18+
19+
interface InitialBagOfTiles : BagOfTiles {
20+
fun pickTile(char: TileChar): Tile?
21+
fun pickTiles(chars: List<TileChar>): List<Tile> =
22+
chars.mapNotNull(::pickTile).also { require(it.size == chars.size) { "Some tiles are not available" } }
23+
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package dev.efemoney.lexiko.engine.api
22

33
import androidx.compose.runtime.Stable
4-
import dev.efemoney.lexiko.engine.impl.BoardImpl
54

65
@Stable
76
interface Board {
@@ -20,16 +19,6 @@ interface MutableBoard : Board {
2019
override operator fun get(position: TilePosition): MutableTileSlot = get(position.row, position.col)
2120
}
2221

23-
fun Board(tilePlacement: TilePlacement = TilePlacement.None): Board =
24-
BoardImpl(initialTilePlacement = tilePlacement)
25-
26-
fun Board(placeTiles: MutableBoard.() -> Unit): Board =
27-
BoardImpl().also(placeTiles)
28-
29-
context(MutableBoard)
30-
fun Tile.placeAt(position: TilePosition) = internal.place(tile = this, at = position)
31-
32-
3322
@Stable
3423
interface TileSlot {
3524
val position: TilePosition
@@ -42,14 +31,12 @@ interface MutableTileSlot : TileSlot {
4231
}
4332

4433
operator fun TileSlot.component1() = position
45-
4634
operator fun TileSlot.component2() = multiplier
47-
4835
operator fun TileSlot.component3() = tile
4936

5037

5138
@JvmInline
52-
value class TilePlacement private constructor(private val tiles: Map<TilePosition, Tile> = emptyMap()) {
39+
value class TilePlacement private constructor(private val tiles: Map<TilePosition, Tile>) {
5340

5441
constructor(build: Builder.() -> Unit) : this(buildMap { Builder(this).apply(build) })
5542

@@ -62,25 +49,6 @@ value class TilePlacement private constructor(private val tiles: Map<TilePositio
6249
}
6350

6451
companion object {
65-
val None = TilePlacement()
66-
}
67-
}
68-
69-
// region Internal
70-
71-
internal interface BoardInternal : MutableBoard {
72-
fun place(tile: Tile, at: TilePosition)
73-
fun place(tiles: List<Tile>, startAt: TilePosition, direction: Direction)
74-
}
75-
76-
internal fun interface OnConflict {
77-
operator fun invoke(slot: TileSlot, old: Tile, new: Tile)
78-
79-
companion object {
80-
val DoNothing = OnConflict { _, _, _ -> }
52+
val None = TilePlacement(emptyMap())
8153
}
8254
}
83-
84-
internal val MutableBoard.internal get() = this as BoardInternal
85-
86-
// endregion

Diff for: engine/src/dev/efemoney/lexiko/engine/api/position.kt renamed to engine/api/src/dev/efemoney/lexiko/engine/api/position.kt

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
package dev.efemoney.lexiko.engine.api
44

5-
import dev.efemoney.lexiko.engine.impl.packInts
6-
import dev.efemoney.lexiko.engine.impl.requireIn
7-
import dev.efemoney.lexiko.engine.impl.unpackInt1
8-
import dev.efemoney.lexiko.engine.impl.unpackInt2
5+
import androidx.compose.ui.util.packInts
6+
import androidx.compose.ui.util.unpackInt1
7+
import androidx.compose.ui.util.unpackInt2
98

109
@JvmInline
1110
value class TilePosition private constructor(private val packed: Long) {
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,20 @@
11
package dev.efemoney.lexiko.engine.api
22

3-
import dev.efemoney.lexiko.engine.impl.DoubleLetterMultiplier
4-
import dev.efemoney.lexiko.engine.impl.DoubleWordMultiplier
5-
import dev.efemoney.lexiko.engine.impl.Multiplier
6-
import dev.efemoney.lexiko.engine.impl.TripleLetterMultiplier
7-
import dev.efemoney.lexiko.engine.impl.TripleWordMultiplier
8-
import dev.efemoney.lexiko.engine.impl.hasMultiplier
9-
103
class Tile internal constructor(
114
val char: TileChar,
125
val point: TilePoint,
136
) : Comparable<Tile> {
14-
157
override fun compareTo(other: Tile) = char.compareTo(other.char)
16-
8+
override fun hashCode() = 31 * char.hashCode() + point.hashCode()
179
override fun equals(other: Any?): Boolean {
1810
if (this === other) return true
1911
if (other !is Tile) return false
2012
return char != other.char && point == other.point
2113
}
22-
23-
override fun hashCode() = 31 * char.hashCode() + point.hashCode()
2414
}
2515

2616
@JvmInline
2717
value class TileChar(private val char: Char) {
28-
2918
val value get() = char.uppercaseChar()
3019

3120
init {
@@ -46,16 +35,28 @@ value class TilePoint(val value: Int) {
4635
}
4736
}
4837

49-
enum class TileMultiplier(internal val value: Multiplier, val string: String) {
38+
sealed interface TileMultiplier {
39+
val string: String
40+
41+
data class Word(private val multiplier: Int) : TileMultiplier {
42+
override val string = "${multiplier}W"
43+
}
44+
45+
data class Letter(private val multiplier: Int) : TileMultiplier {
46+
override val string = "${multiplier}L"
47+
}
48+
}
49+
50+
/*enum class TileMultiplier(internal val value: Multiplier, val string: String) {
5051
TripleWord(TripleWordMultiplier, "3W"),
5152
TripleLetter(TripleLetterMultiplier, "3L"),
5253
DoubleWord(DoubleWordMultiplier, "2W"),
5354
DoubleLetter(DoubleLetterMultiplier, "2L"),
5455
;
5556
5657
internal companion object {
57-
fun forPosition(position: TilePosition) =
58+
fun of(position: TilePosition) =
5859
TileMultiplier.entries.firstOrNull { position.hasMultiplier(it.value) }
5960
}
60-
}
61+
}*/
6162

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package dev.efemoney.lexiko.engine.api
2+
3+
internal inline fun Int.requireIn(range: IntRange, lazyMessage: () -> Any): Int {
4+
require(this in range, lazyMessage)
5+
return this
6+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package dev.efemoney.lexiko.engine.api
2+
3+
@JvmInline
4+
value class Word(private val tiles: Sequence<Tile>)
5+
6+
@JvmInline
7+
value class Letter(private val tile: Tile)

Diff for: engine/build.gradle.kts renamed to engine/impl/build.gradle.kts

+1-5
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,12 @@ dependencies {
77
kotlinCompilerPluginClasspath(libs.androidx.compose.compiler)
88
ksp(libs.kotlinInject.compiler)
99

10+
implementation(projects.engine.api)
1011
implementation(libs.kotlin.stdlib)
1112
implementation(libs.kotlinx.immutable)
1213
implementation(libs.kotlinx.coroutines.core)
1314
implementation(libs.jetbrains.compose.runtime)
1415
implementation(libs.jetbrains.compose.ui.util)
1516
implementation(libs.molecule.runtime)
1617
implementation(libs.kotlinInject.runtime)
17-
18-
testImplementation(libs.kotlin.test)
19-
testImplementation(libs.kotlinx.coroutines.test)
20-
testImplementation(libs.turbine)
21-
testImplementation(libs.junit)
2218
}
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package dev.efemoney.lexiko.engine.api
2+
3+
import dev.efemoney.lexiko.engine.impl.DefaultBagOfTiles
4+
5+
fun BagOfTiles(): BagOfTiles = DefaultBagOfTiles()
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package dev.efemoney.lexiko.engine.api
2+
3+
import dev.efemoney.lexiko.engine.impl.BoardImpl
4+
5+
fun Board(tilePlacement: TilePlacement = TilePlacement.None): Board =
6+
BoardImpl(initialTilePlacement = tilePlacement)
7+
8+
context(InitialBagOfTiles)
9+
fun Board(placeTiles: context(InitialBagOfTiles) MutableBoard.() -> Unit): Board {
10+
return BoardImpl().also { placeTiles(self, it) }
11+
}
12+
13+
context(MutableBoard)
14+
fun Tile.placeAt(position: TilePosition) = internal.place(this, at = position)
15+
16+
@JvmInline
17+
value class TilePlacement private constructor(private val placement: Map<TilePosition, Tile>) {
18+
19+
constructor(build: Builder.() -> Unit) : this(buildMap { Builder(this).apply(build) })
20+
21+
operator fun get(position: TilePosition) = placement[position]
22+
23+
@JvmInline
24+
value class Builder internal constructor(private val map: MutableMap<TilePosition, Tile>) {
25+
26+
infix fun Tile.at(position: TilePosition) = map.put(position, this)
27+
}
28+
29+
companion object {
30+
val None = TilePlacement(emptyMap())
31+
}
32+
}
33+
34+
// region Implementation
35+
36+
private val InitialBagOfTiles.self get() = this
37+
38+
internal interface BoardInternal : MutableBoard {
39+
fun place(tile: Tile, at: TilePosition)
40+
fun place(tiles: List<Tile>, startAt: TilePosition, direction: Direction)
41+
}
42+
43+
internal val Board.internal get() = this as BoardInternal
44+
45+
internal fun interface OnConflict {
46+
operator fun invoke(slot: TileSlot, old: Tile, new: Tile)
47+
48+
companion object {
49+
val DoNothing = OnConflict { _, _, _ -> }
50+
}
51+
}
52+
53+
// endregion

Diff for: engine/src/dev/efemoney/lexiko/engine/game.kt renamed to engine/impl/src/dev/efemoney/lexiko/engine/game.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import dev.efemoney.lexiko.engine.api.Board
1111
import dev.efemoney.lexiko.engine.api.PlayerId
1212
import dev.efemoney.lexiko.engine.events.GameEvent
1313
import dev.efemoney.lexiko.engine.events.GameEventHandlers
14-
import dev.efemoney.lexiko.engine.impl.BagOfTilesImpl
1514
import dev.efemoney.lexiko.engine.impl.BoardImpl
15+
import dev.efemoney.lexiko.engine.impl.DefaultBagOfTiles
1616
import kotlinx.coroutines.CoroutineName
1717
import kotlinx.coroutines.CoroutineScope
1818
import kotlinx.coroutines.channels.Channel
@@ -25,7 +25,7 @@ internal class GameContext(
2525
val host: PlayerId,
2626
val players: SnapshotStateList<PlayerId>,
2727
val board: BoardImpl,
28-
val bag: BagOfTilesImpl,
28+
val bag: DefaultBagOfTiles,
2929
) {
3030
fun send(event: GameEvent) = scope.launch { events.send(event) }
3131
}
@@ -47,7 +47,7 @@ class Game internal constructor(private val eventHandlers: GameEventHandlers) {
4747
host = host,
4848
players = mutableStateListOf(host),
4949
board = BoardImpl(),
50-
bag = BagOfTilesImpl(),
50+
bag = DefaultBagOfTiles(),
5151
)
5252
}
5353
LaunchedEffect(context) {

0 commit comments

Comments
 (0)