diff --git a/CLAUDE.md b/CLAUDE.md
index 7cbe5ec..2c815ce 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -9,8 +9,10 @@ No `java`/`gradle` on PATH — use Android Studio's bundled JDK:
```bash
export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
-./gradlew :engine:jvmTest # evaluator + engine tests
-./gradlew :sim:run --args="50000" # simulate 50k hands, print bot stats
+./gradlew :engine:jvmTest # engine tests (JVM)
+./gradlew :engine:testAndroidHostTest # same suite, Android variant
+./gradlew :sim:run --args="50000" # simulate 50k hands, print bot stats
+./gradlew :app:assembleDebug # build the APK
```
## Layout
@@ -21,7 +23,9 @@ export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
| `engine/src/commonMain/.../bot/` | Skill/style profiles, `MathBot` |
| `engine/src/commonMain/.../game/` | `Table` — betting rounds, side pots, showdown |
| `sim/` | JVM-only headless simulator used to **tune** bot profiles |
-| `assets/cards/` | 52 CC0 card faces + generated backs |
+| `app/` | Android app: Compose table, `PokerViewModel` |
+| `assets/cards/` | 52 CC0 card faces + generated backs (**source of truth**) |
+| `tools/generate_card_assets.sh` | Rasterises those SVGs into `app/.../drawable-*` |
`engine` is pure Kotlin with no platform APIs, so `androidTarget()` /
`iosArm64()` slot in without touching `commonMain`.
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
new file mode 100644
index 0000000..894be11
--- /dev/null
+++ b/app/build.gradle.kts
@@ -0,0 +1,47 @@
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin.compose)
+}
+
+android {
+ namespace = "com.jsjdesigns.poker"
+ compileSdk = 37
+
+ defaultConfig {
+ applicationId = "com.jsjdesigns.poker"
+ minSdk = 26
+ targetSdk = 37
+ versionCode = 1
+ versionName = "0.1.0"
+ }
+
+ buildTypes {
+ release { isMinifyEnabled = false }
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
+
+ buildFeatures { compose = true }
+}
+
+dependencies {
+ implementation(project(":engine"))
+ implementation(libs.kotlinx.coroutines.android)
+ implementation(libs.androidx.core.ktx)
+ implementation(libs.androidx.activity.compose)
+ implementation(libs.androidx.lifecycle.viewmodel.compose)
+ implementation(libs.androidx.lifecycle.runtime.ktx)
+ implementation(libs.androidx.lifecycle.runtime.compose)
+ implementation(platform(libs.androidx.compose.bom))
+ implementation(libs.androidx.compose.ui)
+ implementation(libs.androidx.compose.ui.graphics)
+ implementation(libs.androidx.compose.ui.tooling.preview)
+ implementation(libs.androidx.compose.material3)
+ debugImplementation(libs.androidx.compose.ui.tooling)
+
+ testImplementation(libs.junit)
+ testImplementation(libs.kotlinx.coroutines.test)
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..5587b1b
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/jsjdesigns/poker/CardArt.kt b/app/src/main/java/com/jsjdesigns/poker/CardArt.kt
new file mode 100644
index 0000000..ece56a4
--- /dev/null
+++ b/app/src/main/java/com/jsjdesigns/poker/CardArt.kt
@@ -0,0 +1,74 @@
+package com.jsjdesigns.poker
+
+import androidx.annotation.DrawableRes
+
+/**
+ * Maps a deck index (0..51) to its drawable.
+ *
+ * Generated by tools/generate_card_assets.sh's companion step — regenerate rather
+ * than hand-editing. References are static so R8 resource shrinking cannot strip
+ * the artwork, which `getIdentifier` lookups would risk.
+ *
+ * Order matches [com.jsjdesigns.poker.core.Card]: index = (rank - 2) * 4 + suit,
+ * suits ordered clubs, diamonds, hearts, spades.
+ */
+private val CARD_FACES = intArrayOf(
+ R.drawable.card_2_of_clubs, // 0
+ R.drawable.card_2_of_diamonds, // 1
+ R.drawable.card_2_of_hearts, // 2
+ R.drawable.card_2_of_spades, // 3
+ R.drawable.card_3_of_clubs, // 4
+ R.drawable.card_3_of_diamonds, // 5
+ R.drawable.card_3_of_hearts, // 6
+ R.drawable.card_3_of_spades, // 7
+ R.drawable.card_4_of_clubs, // 8
+ R.drawable.card_4_of_diamonds, // 9
+ R.drawable.card_4_of_hearts, // 10
+ R.drawable.card_4_of_spades, // 11
+ R.drawable.card_5_of_clubs, // 12
+ R.drawable.card_5_of_diamonds, // 13
+ R.drawable.card_5_of_hearts, // 14
+ R.drawable.card_5_of_spades, // 15
+ R.drawable.card_6_of_clubs, // 16
+ R.drawable.card_6_of_diamonds, // 17
+ R.drawable.card_6_of_hearts, // 18
+ R.drawable.card_6_of_spades, // 19
+ R.drawable.card_7_of_clubs, // 20
+ R.drawable.card_7_of_diamonds, // 21
+ R.drawable.card_7_of_hearts, // 22
+ R.drawable.card_7_of_spades, // 23
+ R.drawable.card_8_of_clubs, // 24
+ R.drawable.card_8_of_diamonds, // 25
+ R.drawable.card_8_of_hearts, // 26
+ R.drawable.card_8_of_spades, // 27
+ R.drawable.card_9_of_clubs, // 28
+ R.drawable.card_9_of_diamonds, // 29
+ R.drawable.card_9_of_hearts, // 30
+ R.drawable.card_9_of_spades, // 31
+ R.drawable.card_10_of_clubs, // 32
+ R.drawable.card_10_of_diamonds, // 33
+ R.drawable.card_10_of_hearts, // 34
+ R.drawable.card_10_of_spades, // 35
+ R.drawable.card_jack_of_clubs, // 36
+ R.drawable.card_jack_of_diamonds, // 37
+ R.drawable.card_jack_of_hearts, // 38
+ R.drawable.card_jack_of_spades, // 39
+ R.drawable.card_queen_of_clubs, // 40
+ R.drawable.card_queen_of_diamonds, // 41
+ R.drawable.card_queen_of_hearts, // 42
+ R.drawable.card_queen_of_spades, // 43
+ R.drawable.card_king_of_clubs, // 44
+ R.drawable.card_king_of_diamonds, // 45
+ R.drawable.card_king_of_hearts, // 46
+ R.drawable.card_king_of_spades, // 47
+ R.drawable.card_ace_of_clubs, // 48
+ R.drawable.card_ace_of_diamonds, // 49
+ R.drawable.card_ace_of_hearts, // 50
+ R.drawable.card_ace_of_spades, // 51
+)
+
+@DrawableRes
+fun cardFace(index: Int): Int = CARD_FACES[index]
+
+@DrawableRes
+fun cardBack(): Int = R.drawable.card_back
diff --git a/app/src/main/java/com/jsjdesigns/poker/MainActivity.kt b/app/src/main/java/com/jsjdesigns/poker/MainActivity.kt
new file mode 100644
index 0000000..b8f5235
--- /dev/null
+++ b/app/src/main/java/com/jsjdesigns/poker/MainActivity.kt
@@ -0,0 +1,20 @@
+package com.jsjdesigns.poker
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.lifecycle.viewmodel.compose.viewModel
+
+class MainActivity : ComponentActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContent {
+ MaterialTheme(colorScheme = darkColorScheme()) {
+ val vm: PokerViewModel = viewModel()
+ TableScreen(vm)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/jsjdesigns/poker/PokerViewModel.kt b/app/src/main/java/com/jsjdesigns/poker/PokerViewModel.kt
new file mode 100644
index 0000000..6aa84ec
--- /dev/null
+++ b/app/src/main/java/com/jsjdesigns/poker/PokerViewModel.kt
@@ -0,0 +1,139 @@
+package com.jsjdesigns.poker
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.jsjdesigns.poker.bot.BotProfile
+import com.jsjdesigns.poker.bot.MathBot
+import com.jsjdesigns.poker.bot.PlayStyle
+import com.jsjdesigns.poker.bot.SkillLevel
+import com.jsjdesigns.poker.game.Action
+import com.jsjdesigns.poker.game.ActionType
+import com.jsjdesigns.poker.game.HumanAgent
+import com.jsjdesigns.poker.game.Seat
+import com.jsjdesigns.poker.game.Table
+import com.jsjdesigns.poker.game.TableSnapshot
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import kotlin.random.Random
+
+const val HERO_SEAT = 0
+private const val STARTING_STACK = 200
+private const val SMALL_BLIND = 1
+private const val BIG_BLIND = 2
+
+data class UiState(
+ val snapshot: TableSnapshot? = null,
+ val handsPlayed: Int = 0,
+ val message: String? = null,
+)
+
+/**
+ * Drives a continuous cash game and publishes it to Compose.
+ *
+ * **Frames are queued, not conflated.** The engine can emit the flop, turn and
+ * river of an all-in runout within microseconds of each other. Pushing those
+ * straight into a `StateFlow` would collapse them — `StateFlow` keeps only the
+ * latest value — and the board would appear to jump from empty to complete.
+ * Instead the engine's suspending observer sends into a [Channel], a consumer
+ * paces each frame, and only then is `StateFlow` updated. Because the observer
+ * suspends when the channel is full, the engine cannot outrun the animation:
+ * backpressure does the pacing for us.
+ */
+class PokerViewModel : ViewModel() {
+
+ private val human = HumanAgent()
+ private val frames = Channel(capacity = 32)
+
+ private val _state = MutableStateFlow(UiState())
+ val state: StateFlow = _state.asStateFlow()
+
+ /** What the player is being asked to decide, or null when it isn't their turn. */
+ val offer = human.offer
+
+ private val roster = listOf(
+ BotProfile("You", SkillLevel.EXPERT, PlayStyle.TIGHT_AGGRESSIVE),
+ BotProfile("Ada", SkillLevel.EXPERT, PlayStyle.TIGHT_AGGRESSIVE, "Ice-cold. Punishes mistakes."),
+ BotProfile("Bruno", SkillLevel.ADVANCED, PlayStyle.LOOSE_AGGRESSIVE, "Relentless pressure."),
+ BotProfile("Cleo", SkillLevel.INTERMEDIATE, PlayStyle.TRAPPER, "Quiet until she has you."),
+ BotProfile("Dex", SkillLevel.INTERMEDIATE, PlayStyle.CALLING_STATION, "Pays to see it."),
+ BotProfile("Enzo", SkillLevel.BEGINNER, PlayStyle.MANIAC, "Chaos, and certain he's winning."),
+ )
+
+ private val seats: List
+ private val table: Table
+
+ init {
+ val deckRandom = Random(System.nanoTime())
+ seats = roster.mapIndexed { i, profile ->
+ val agent = if (i == HERO_SEAT) human else MathBot(profile, Random(deckRandom.nextLong()))
+ Seat(i, profile.name, STARTING_STACK, agent)
+ }
+ table = Table(
+ seats = seats,
+ smallBlind = SMALL_BLIND,
+ bigBlind = BIG_BLIND,
+ random = deckRandom,
+ observer = { frames.send(it) },
+ )
+
+ viewModelScope.launch { consumeFrames() }
+ viewModelScope.launch(Dispatchers.Default) { playContinuously() }
+ }
+
+ private suspend fun consumeFrames() {
+ for (frame in frames) {
+ _state.value = _state.value.copy(snapshot = frame.maskedFor(HERO_SEAT))
+ delay(pacingMillis(frame))
+ }
+ }
+
+ /**
+ * How long to hold a frame on screen. Zero when the player is on the clock —
+ * never make someone wait to act — and longest for cards landing and for the
+ * showdown, which are the moments worth watching.
+ */
+ private fun pacingMillis(frame: TableSnapshot): Long = when (frame.phase) {
+ TableSnapshot.Phase.DEALT -> 400
+ TableSnapshot.Phase.BETTING ->
+ if (frame.toAct == HERO_SEAT) 0 else if (frame.toAct != null) 250 else 450
+ TableSnapshot.Phase.STREET_COMPLETE -> 700
+ TableSnapshot.Phase.SHOWDOWN -> 2200
+ TableSnapshot.Phase.COMPLETE -> 1200
+ }
+
+ private suspend fun playContinuously() {
+ while (true) {
+ // Cash-game convention: top anyone back up who cannot cover a blind.
+ for (s in seats) if (s.stack < BIG_BLIND) s.stack = STARTING_STACK
+ table.advanceButton()
+ runCatching { table.playHand() }
+ .onSuccess { _state.value = _state.value.copy(handsPlayed = _state.value.handsPlayed + 1) }
+ .onFailure { return } // scope cancelled: the screen went away
+ }
+ }
+
+ fun submit(action: Action) {
+ viewModelScope.launch { human.submit(action) }
+ }
+
+ fun fold() = submit(Action(ActionType.FOLD))
+
+ fun checkOrCall() {
+ val o = offer.value ?: return
+ submit(if (o.canCheck) Action(ActionType.CHECK) else Action(ActionType.CALL, o.toCall))
+ }
+
+ fun raiseTo(amount: Int) = submit(Action(ActionType.RAISE, amount))
+
+ override fun onCleared() {
+ // Release a hand parked on human input so the coroutine can finish.
+ viewModelScope.launch { human.cancel() }
+ frames.close()
+ super.onCleared()
+ }
+}
diff --git a/app/src/main/java/com/jsjdesigns/poker/TableScreen.kt b/app/src/main/java/com/jsjdesigns/poker/TableScreen.kt
new file mode 100644
index 0000000..2a83d19
--- /dev/null
+++ b/app/src/main/java/com/jsjdesigns/poker/TableScreen.kt
@@ -0,0 +1,260 @@
+package com.jsjdesigns.poker
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBarsPadding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.Slider
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.jsjdesigns.poker.game.SeatSnapshot
+import com.jsjdesigns.poker.game.TableSnapshot
+
+private val Felt = Color(0xFF0B3D26)
+
+@Composable
+fun TableScreen(vm: PokerViewModel) {
+ val state by vm.state.collectAsStateWithLifecycle()
+ val offer by vm.offer.collectAsStateWithLifecycle()
+ val snap = state.snapshot
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(Felt)
+ .systemBarsPadding()
+ .padding(12.dp),
+ ) {
+ Text(
+ text = "Hand ${state.handsPlayed + 1} ${snap?.street ?: ""}",
+ color = Color.White.copy(alpha = 0.6f),
+ fontSize = 12.sp,
+ )
+
+ Spacer(Modifier.height(8.dp))
+
+ // Opponents
+ // Weighted rather than fixed-width: five opponents must all fit on a
+ // phone, and a horizontally scrolling table hides players from you.
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
+ ) {
+ snap?.seats?.filter { it.index != HERO_SEAT }?.forEach { seat ->
+ Box(Modifier.weight(1f)) {
+ OpponentSeat(seat, isTurn = snap.toAct == seat.index)
+ }
+ }
+ }
+
+ Spacer(Modifier.weight(1f))
+
+ // Board and pot
+ Column(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Text(
+ text = "POT ${snap?.pot ?: 0}",
+ color = Color(0xFFE3C179),
+ fontWeight = FontWeight.Bold,
+ fontSize = 18.sp,
+ )
+ Spacer(Modifier.height(8.dp))
+ Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
+ val board = snap?.board.orEmpty()
+ repeat(5) { i ->
+ if (i < board.size) {
+ CardImage(board[i], Modifier.size(54.dp, 81.dp))
+ } else {
+ Box(
+ Modifier
+ .size(54.dp, 81.dp)
+ .clip(RoundedCornerShape(4.dp))
+ .background(Color.White.copy(alpha = 0.06f)),
+ )
+ }
+ }
+ }
+ }
+
+ Spacer(Modifier.weight(1f))
+
+ // Hero
+ val hero = snap?.seats?.firstOrNull { it.index == HERO_SEAT }
+ HeroSeat(hero, isTurn = snap?.toAct == HERO_SEAT)
+
+ Spacer(Modifier.height(12.dp))
+
+ ActionBar(
+ offer = offer,
+ onFold = vm::fold,
+ onCheckCall = vm::checkOrCall,
+ onRaise = vm::raiseTo,
+ )
+ }
+}
+
+@Composable
+private fun OpponentSeat(seat: SeatSnapshot, isTurn: Boolean) {
+ Card(
+ colors = CardDefaults.cardColors(
+ containerColor = if (isTurn) Color(0xFF1D6B45) else Color.White.copy(alpha = 0.07f),
+ ),
+ modifier = Modifier.fillMaxWidth(),
+ ) {
+ Column(
+ modifier = Modifier.padding(6.dp),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Row(horizontalArrangement = Arrangement.spacedBy(2.dp)) {
+ if (seat.folded) {
+ Box(Modifier.size(24.dp, 36.dp))
+ } else {
+ val hole = seat.hole
+ repeat(2) { i ->
+ CardImage(hole?.getOrNull(i), Modifier.size(24.dp, 36.dp))
+ }
+ }
+ }
+ Spacer(Modifier.height(4.dp))
+ Text(
+ seat.name + if (seat.isButton) " ⏺" else "",
+ color = Color.White,
+ fontSize = 11.sp,
+ fontWeight = FontWeight.Medium,
+ modifier = Modifier.alpha(if (seat.folded) 0.4f else 1f),
+ )
+ Text(
+ if (seat.allIn) "ALL IN" else "${seat.stack}",
+ color = if (seat.allIn) Color(0xFFE3C179) else Color.White.copy(alpha = 0.7f),
+ fontSize = 11.sp,
+ )
+ if (seat.committedThisRound > 0) {
+ Text(
+ "bet ${seat.committedThisRound}",
+ color = Color(0xFFE3C179),
+ fontSize = 10.sp,
+ )
+ }
+ }
+ }
+}
+
+@Composable
+private fun HeroSeat(seat: SeatSnapshot?, isTurn: Boolean) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
+ ) {
+ Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
+ repeat(2) { i ->
+ CardImage(seat?.hole?.getOrNull(i), Modifier.size(64.dp, 96.dp))
+ }
+ }
+ Column {
+ Text(
+ (seat?.name ?: "You") + if (seat?.isButton == true) " ⏺" else "",
+ color = if (isTurn) Color(0xFFE3C179) else Color.White,
+ fontWeight = FontWeight.Bold,
+ )
+ Text("${seat?.stack ?: 0}", color = Color.White.copy(alpha = 0.75f))
+ if ((seat?.committedThisRound ?: 0) > 0) {
+ Text("bet ${seat?.committedThisRound}", color = Color(0xFFE3C179), fontSize = 12.sp)
+ }
+ }
+ }
+}
+
+@Composable
+private fun ActionBar(
+ offer: com.jsjdesigns.poker.game.DecisionOffer?,
+ onFold: () -> Unit,
+ onCheckCall: () -> Unit,
+ onRaise: (Int) -> Unit,
+) {
+ if (offer == null) {
+ Box(Modifier.fillMaxWidth().height(96.dp), contentAlignment = Alignment.Center) {
+ Text("Waiting…", color = Color.White.copy(alpha = 0.4f))
+ }
+ return
+ }
+
+ var raiseTo by remember { mutableIntStateOf(offer.minRaiseTo) }
+ // Reset the slider whenever a new decision arrives, or it keeps the old hand's value.
+ LaunchedEffect(offer) { raiseTo = offer.minRaiseTo }
+
+ Column(Modifier.fillMaxWidth()) {
+ if (offer.canRaise && offer.maxRaiseTo > offer.minRaiseTo) {
+ Text("Raise to $raiseTo", color = Color.White, fontSize = 13.sp)
+ Slider(
+ value = raiseTo.toFloat(),
+ onValueChange = { raiseTo = it.toInt() },
+ valueRange = offer.minRaiseTo.toFloat()..offer.maxRaiseTo.toFloat(),
+ )
+ }
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ ) {
+ Button(
+ onClick = onFold,
+ modifier = Modifier.weight(1f),
+ colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF8F1218)),
+ ) { Text("Fold") }
+
+ Button(
+ onClick = onCheckCall,
+ modifier = Modifier.weight(1f),
+ colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF2C6E49)),
+ ) { Text(if (offer.canCheck) "Check" else "Call ${offer.toCall}") }
+
+ if (offer.canRaise && offer.maxRaiseTo > offer.minRaiseTo) {
+ Button(
+ onClick = { onRaise(raiseTo) },
+ modifier = Modifier.weight(1f),
+ colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF14357A)),
+ ) { Text(if (raiseTo >= offer.maxRaiseTo) "All in" else "Raise") }
+ }
+ }
+ }
+}
+
+@Composable
+private fun CardImage(index: Int?, modifier: Modifier) {
+ Image(
+ painter = painterResource(if (index != null) cardFace(index) else cardBack()),
+ contentDescription = null,
+ modifier = modifier.clip(RoundedCornerShape(4.dp)),
+ )
+}
diff --git a/app/src/main/res/drawable-hdpi/card_10_of_clubs.png b/app/src/main/res/drawable-hdpi/card_10_of_clubs.png
new file mode 100644
index 0000000..061135f
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_10_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_10_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_10_of_diamonds.png
new file mode 100644
index 0000000..5c08e11
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_10_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_10_of_hearts.png b/app/src/main/res/drawable-hdpi/card_10_of_hearts.png
new file mode 100644
index 0000000..1865743
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_10_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_10_of_spades.png b/app/src/main/res/drawable-hdpi/card_10_of_spades.png
new file mode 100644
index 0000000..9ce8f60
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_10_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_2_of_clubs.png b/app/src/main/res/drawable-hdpi/card_2_of_clubs.png
new file mode 100644
index 0000000..fb658b7
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_2_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_2_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_2_of_diamonds.png
new file mode 100644
index 0000000..03b3aa8
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_2_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_2_of_hearts.png b/app/src/main/res/drawable-hdpi/card_2_of_hearts.png
new file mode 100644
index 0000000..3cc7a38
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_2_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_2_of_spades.png b/app/src/main/res/drawable-hdpi/card_2_of_spades.png
new file mode 100644
index 0000000..7a7f28f
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_2_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_3_of_clubs.png b/app/src/main/res/drawable-hdpi/card_3_of_clubs.png
new file mode 100644
index 0000000..7653eed
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_3_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_3_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_3_of_diamonds.png
new file mode 100644
index 0000000..55aa313
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_3_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_3_of_hearts.png b/app/src/main/res/drawable-hdpi/card_3_of_hearts.png
new file mode 100644
index 0000000..d569ae2
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_3_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_3_of_spades.png b/app/src/main/res/drawable-hdpi/card_3_of_spades.png
new file mode 100644
index 0000000..c59ce01
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_3_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_4_of_clubs.png b/app/src/main/res/drawable-hdpi/card_4_of_clubs.png
new file mode 100644
index 0000000..be0aa59
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_4_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_4_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_4_of_diamonds.png
new file mode 100644
index 0000000..1e3e32d
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_4_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_4_of_hearts.png b/app/src/main/res/drawable-hdpi/card_4_of_hearts.png
new file mode 100644
index 0000000..86ef290
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_4_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_4_of_spades.png b/app/src/main/res/drawable-hdpi/card_4_of_spades.png
new file mode 100644
index 0000000..b46575b
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_4_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_5_of_clubs.png b/app/src/main/res/drawable-hdpi/card_5_of_clubs.png
new file mode 100644
index 0000000..ba55e9a
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_5_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_5_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_5_of_diamonds.png
new file mode 100644
index 0000000..4c331b0
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_5_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_5_of_hearts.png b/app/src/main/res/drawable-hdpi/card_5_of_hearts.png
new file mode 100644
index 0000000..d5bec87
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_5_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_5_of_spades.png b/app/src/main/res/drawable-hdpi/card_5_of_spades.png
new file mode 100644
index 0000000..d9c0165
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_5_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_6_of_clubs.png b/app/src/main/res/drawable-hdpi/card_6_of_clubs.png
new file mode 100644
index 0000000..9d7c7b5
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_6_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_6_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_6_of_diamonds.png
new file mode 100644
index 0000000..50290c3
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_6_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_6_of_hearts.png b/app/src/main/res/drawable-hdpi/card_6_of_hearts.png
new file mode 100644
index 0000000..d91b312
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_6_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_6_of_spades.png b/app/src/main/res/drawable-hdpi/card_6_of_spades.png
new file mode 100644
index 0000000..d225342
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_6_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_7_of_clubs.png b/app/src/main/res/drawable-hdpi/card_7_of_clubs.png
new file mode 100644
index 0000000..eab9c85
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_7_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_7_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_7_of_diamonds.png
new file mode 100644
index 0000000..40a3581
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_7_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_7_of_hearts.png b/app/src/main/res/drawable-hdpi/card_7_of_hearts.png
new file mode 100644
index 0000000..88e1103
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_7_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_7_of_spades.png b/app/src/main/res/drawable-hdpi/card_7_of_spades.png
new file mode 100644
index 0000000..c56c9c3
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_7_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_8_of_clubs.png b/app/src/main/res/drawable-hdpi/card_8_of_clubs.png
new file mode 100644
index 0000000..9f39e34
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_8_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_8_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_8_of_diamonds.png
new file mode 100644
index 0000000..51a434e
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_8_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_8_of_hearts.png b/app/src/main/res/drawable-hdpi/card_8_of_hearts.png
new file mode 100644
index 0000000..31e0417
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_8_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_8_of_spades.png b/app/src/main/res/drawable-hdpi/card_8_of_spades.png
new file mode 100644
index 0000000..bcb5810
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_8_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_9_of_clubs.png b/app/src/main/res/drawable-hdpi/card_9_of_clubs.png
new file mode 100644
index 0000000..c4de5da
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_9_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_9_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_9_of_diamonds.png
new file mode 100644
index 0000000..4a32804
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_9_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_9_of_hearts.png b/app/src/main/res/drawable-hdpi/card_9_of_hearts.png
new file mode 100644
index 0000000..4943fcd
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_9_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_9_of_spades.png b/app/src/main/res/drawable-hdpi/card_9_of_spades.png
new file mode 100644
index 0000000..25f4f34
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_9_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_ace_of_clubs.png b/app/src/main/res/drawable-hdpi/card_ace_of_clubs.png
new file mode 100644
index 0000000..6ab66b8
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_ace_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_ace_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_ace_of_diamonds.png
new file mode 100644
index 0000000..f49f833
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_ace_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_ace_of_hearts.png b/app/src/main/res/drawable-hdpi/card_ace_of_hearts.png
new file mode 100644
index 0000000..0460f39
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_ace_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_ace_of_spades.png b/app/src/main/res/drawable-hdpi/card_ace_of_spades.png
new file mode 100644
index 0000000..521a7bd
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_ace_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_back.png b/app/src/main/res/drawable-hdpi/card_back.png
new file mode 100644
index 0000000..a1a3590
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_back.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_back_blue.png b/app/src/main/res/drawable-hdpi/card_back_blue.png
new file mode 100644
index 0000000..fd7a622
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_back_blue.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_back_red.png b/app/src/main/res/drawable-hdpi/card_back_red.png
new file mode 100644
index 0000000..a1a3590
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_back_red.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_jack_of_clubs.png b/app/src/main/res/drawable-hdpi/card_jack_of_clubs.png
new file mode 100644
index 0000000..5b02422
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_jack_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_jack_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_jack_of_diamonds.png
new file mode 100644
index 0000000..8ddcff9
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_jack_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_jack_of_hearts.png b/app/src/main/res/drawable-hdpi/card_jack_of_hearts.png
new file mode 100644
index 0000000..0fd51df
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_jack_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_jack_of_spades.png b/app/src/main/res/drawable-hdpi/card_jack_of_spades.png
new file mode 100644
index 0000000..9a40209
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_jack_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_king_of_clubs.png b/app/src/main/res/drawable-hdpi/card_king_of_clubs.png
new file mode 100644
index 0000000..8b16952
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_king_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_king_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_king_of_diamonds.png
new file mode 100644
index 0000000..076d1c9
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_king_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_king_of_hearts.png b/app/src/main/res/drawable-hdpi/card_king_of_hearts.png
new file mode 100644
index 0000000..68c6ad4
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_king_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_king_of_spades.png b/app/src/main/res/drawable-hdpi/card_king_of_spades.png
new file mode 100644
index 0000000..8e9cb78
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_king_of_spades.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_queen_of_clubs.png b/app/src/main/res/drawable-hdpi/card_queen_of_clubs.png
new file mode 100644
index 0000000..e644152
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_queen_of_clubs.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_queen_of_diamonds.png b/app/src/main/res/drawable-hdpi/card_queen_of_diamonds.png
new file mode 100644
index 0000000..929a4ac
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_queen_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_queen_of_hearts.png b/app/src/main/res/drawable-hdpi/card_queen_of_hearts.png
new file mode 100644
index 0000000..055ac2c
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_queen_of_hearts.png differ
diff --git a/app/src/main/res/drawable-hdpi/card_queen_of_spades.png b/app/src/main/res/drawable-hdpi/card_queen_of_spades.png
new file mode 100644
index 0000000..fb7ea2c
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/card_queen_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_10_of_clubs.png b/app/src/main/res/drawable-mdpi/card_10_of_clubs.png
new file mode 100644
index 0000000..f810aef
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_10_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_10_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_10_of_diamonds.png
new file mode 100644
index 0000000..244a276
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_10_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_10_of_hearts.png b/app/src/main/res/drawable-mdpi/card_10_of_hearts.png
new file mode 100644
index 0000000..e79fc00
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_10_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_10_of_spades.png b/app/src/main/res/drawable-mdpi/card_10_of_spades.png
new file mode 100644
index 0000000..25b44a1
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_10_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_2_of_clubs.png b/app/src/main/res/drawable-mdpi/card_2_of_clubs.png
new file mode 100644
index 0000000..6196347
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_2_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_2_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_2_of_diamonds.png
new file mode 100644
index 0000000..5665fab
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_2_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_2_of_hearts.png b/app/src/main/res/drawable-mdpi/card_2_of_hearts.png
new file mode 100644
index 0000000..52aacb5
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_2_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_2_of_spades.png b/app/src/main/res/drawable-mdpi/card_2_of_spades.png
new file mode 100644
index 0000000..1a7e1f8
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_2_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_3_of_clubs.png b/app/src/main/res/drawable-mdpi/card_3_of_clubs.png
new file mode 100644
index 0000000..0340059
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_3_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_3_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_3_of_diamonds.png
new file mode 100644
index 0000000..083f8db
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_3_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_3_of_hearts.png b/app/src/main/res/drawable-mdpi/card_3_of_hearts.png
new file mode 100644
index 0000000..c69ba25
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_3_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_3_of_spades.png b/app/src/main/res/drawable-mdpi/card_3_of_spades.png
new file mode 100644
index 0000000..3fbc644
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_3_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_4_of_clubs.png b/app/src/main/res/drawable-mdpi/card_4_of_clubs.png
new file mode 100644
index 0000000..0750b1a
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_4_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_4_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_4_of_diamonds.png
new file mode 100644
index 0000000..e713af7
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_4_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_4_of_hearts.png b/app/src/main/res/drawable-mdpi/card_4_of_hearts.png
new file mode 100644
index 0000000..13bfa45
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_4_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_4_of_spades.png b/app/src/main/res/drawable-mdpi/card_4_of_spades.png
new file mode 100644
index 0000000..895ce53
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_4_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_5_of_clubs.png b/app/src/main/res/drawable-mdpi/card_5_of_clubs.png
new file mode 100644
index 0000000..3a70e09
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_5_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_5_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_5_of_diamonds.png
new file mode 100644
index 0000000..784249f
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_5_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_5_of_hearts.png b/app/src/main/res/drawable-mdpi/card_5_of_hearts.png
new file mode 100644
index 0000000..cd0860b
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_5_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_5_of_spades.png b/app/src/main/res/drawable-mdpi/card_5_of_spades.png
new file mode 100644
index 0000000..267b625
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_5_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_6_of_clubs.png b/app/src/main/res/drawable-mdpi/card_6_of_clubs.png
new file mode 100644
index 0000000..30f6c43
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_6_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_6_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_6_of_diamonds.png
new file mode 100644
index 0000000..3fead69
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_6_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_6_of_hearts.png b/app/src/main/res/drawable-mdpi/card_6_of_hearts.png
new file mode 100644
index 0000000..9e92cb6
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_6_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_6_of_spades.png b/app/src/main/res/drawable-mdpi/card_6_of_spades.png
new file mode 100644
index 0000000..4c80a33
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_6_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_7_of_clubs.png b/app/src/main/res/drawable-mdpi/card_7_of_clubs.png
new file mode 100644
index 0000000..36f0691
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_7_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_7_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_7_of_diamonds.png
new file mode 100644
index 0000000..9ee63cc
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_7_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_7_of_hearts.png b/app/src/main/res/drawable-mdpi/card_7_of_hearts.png
new file mode 100644
index 0000000..d6196aa
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_7_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_7_of_spades.png b/app/src/main/res/drawable-mdpi/card_7_of_spades.png
new file mode 100644
index 0000000..c84847f
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_7_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_8_of_clubs.png b/app/src/main/res/drawable-mdpi/card_8_of_clubs.png
new file mode 100644
index 0000000..7bb707b
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_8_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_8_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_8_of_diamonds.png
new file mode 100644
index 0000000..5d23a03
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_8_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_8_of_hearts.png b/app/src/main/res/drawable-mdpi/card_8_of_hearts.png
new file mode 100644
index 0000000..ed7a3dc
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_8_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_8_of_spades.png b/app/src/main/res/drawable-mdpi/card_8_of_spades.png
new file mode 100644
index 0000000..26629e0
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_8_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_9_of_clubs.png b/app/src/main/res/drawable-mdpi/card_9_of_clubs.png
new file mode 100644
index 0000000..dddc915
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_9_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_9_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_9_of_diamonds.png
new file mode 100644
index 0000000..f7aa8cd
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_9_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_9_of_hearts.png b/app/src/main/res/drawable-mdpi/card_9_of_hearts.png
new file mode 100644
index 0000000..a97f227
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_9_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_9_of_spades.png b/app/src/main/res/drawable-mdpi/card_9_of_spades.png
new file mode 100644
index 0000000..7103ba7
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_9_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_ace_of_clubs.png b/app/src/main/res/drawable-mdpi/card_ace_of_clubs.png
new file mode 100644
index 0000000..86a1480
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_ace_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_ace_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_ace_of_diamonds.png
new file mode 100644
index 0000000..d9a624b
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_ace_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_ace_of_hearts.png b/app/src/main/res/drawable-mdpi/card_ace_of_hearts.png
new file mode 100644
index 0000000..4891404
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_ace_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_ace_of_spades.png b/app/src/main/res/drawable-mdpi/card_ace_of_spades.png
new file mode 100644
index 0000000..d7ecb3e
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_ace_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_back.png b/app/src/main/res/drawable-mdpi/card_back.png
new file mode 100644
index 0000000..a33da9b
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_back.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_back_blue.png b/app/src/main/res/drawable-mdpi/card_back_blue.png
new file mode 100644
index 0000000..6da685a
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_back_blue.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_back_red.png b/app/src/main/res/drawable-mdpi/card_back_red.png
new file mode 100644
index 0000000..a33da9b
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_back_red.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_jack_of_clubs.png b/app/src/main/res/drawable-mdpi/card_jack_of_clubs.png
new file mode 100644
index 0000000..b603864
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_jack_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_jack_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_jack_of_diamonds.png
new file mode 100644
index 0000000..df913c8
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_jack_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_jack_of_hearts.png b/app/src/main/res/drawable-mdpi/card_jack_of_hearts.png
new file mode 100644
index 0000000..12c9d2b
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_jack_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_jack_of_spades.png b/app/src/main/res/drawable-mdpi/card_jack_of_spades.png
new file mode 100644
index 0000000..eaf5efb
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_jack_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_king_of_clubs.png b/app/src/main/res/drawable-mdpi/card_king_of_clubs.png
new file mode 100644
index 0000000..2f96435
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_king_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_king_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_king_of_diamonds.png
new file mode 100644
index 0000000..508436a
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_king_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_king_of_hearts.png b/app/src/main/res/drawable-mdpi/card_king_of_hearts.png
new file mode 100644
index 0000000..6a6f380
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_king_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_king_of_spades.png b/app/src/main/res/drawable-mdpi/card_king_of_spades.png
new file mode 100644
index 0000000..3a804fb
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_king_of_spades.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_queen_of_clubs.png b/app/src/main/res/drawable-mdpi/card_queen_of_clubs.png
new file mode 100644
index 0000000..2d21630
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_queen_of_clubs.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_queen_of_diamonds.png b/app/src/main/res/drawable-mdpi/card_queen_of_diamonds.png
new file mode 100644
index 0000000..7fde53a
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_queen_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_queen_of_hearts.png b/app/src/main/res/drawable-mdpi/card_queen_of_hearts.png
new file mode 100644
index 0000000..a3e1810
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_queen_of_hearts.png differ
diff --git a/app/src/main/res/drawable-mdpi/card_queen_of_spades.png b/app/src/main/res/drawable-mdpi/card_queen_of_spades.png
new file mode 100644
index 0000000..ebad7fd
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/card_queen_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_10_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_10_of_clubs.png
new file mode 100644
index 0000000..83925d4
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_10_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_10_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_10_of_diamonds.png
new file mode 100644
index 0000000..e96bf59
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_10_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_10_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_10_of_hearts.png
new file mode 100644
index 0000000..2fe0768
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_10_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_10_of_spades.png b/app/src/main/res/drawable-xhdpi/card_10_of_spades.png
new file mode 100644
index 0000000..21f078d
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_10_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_2_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_2_of_clubs.png
new file mode 100644
index 0000000..6376d14
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_2_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_2_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_2_of_diamonds.png
new file mode 100644
index 0000000..8c85d92
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_2_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_2_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_2_of_hearts.png
new file mode 100644
index 0000000..689201a
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_2_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_2_of_spades.png b/app/src/main/res/drawable-xhdpi/card_2_of_spades.png
new file mode 100644
index 0000000..eab86a9
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_2_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_3_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_3_of_clubs.png
new file mode 100644
index 0000000..bff6553
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_3_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_3_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_3_of_diamonds.png
new file mode 100644
index 0000000..405711e
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_3_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_3_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_3_of_hearts.png
new file mode 100644
index 0000000..58973fa
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_3_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_3_of_spades.png b/app/src/main/res/drawable-xhdpi/card_3_of_spades.png
new file mode 100644
index 0000000..cd7e619
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_3_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_4_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_4_of_clubs.png
new file mode 100644
index 0000000..7ee8261
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_4_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_4_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_4_of_diamonds.png
new file mode 100644
index 0000000..f453c91
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_4_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_4_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_4_of_hearts.png
new file mode 100644
index 0000000..c551599
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_4_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_4_of_spades.png b/app/src/main/res/drawable-xhdpi/card_4_of_spades.png
new file mode 100644
index 0000000..db596a2
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_4_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_5_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_5_of_clubs.png
new file mode 100644
index 0000000..47a32e6
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_5_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_5_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_5_of_diamonds.png
new file mode 100644
index 0000000..e28b519
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_5_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_5_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_5_of_hearts.png
new file mode 100644
index 0000000..321faac
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_5_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_5_of_spades.png b/app/src/main/res/drawable-xhdpi/card_5_of_spades.png
new file mode 100644
index 0000000..322c612
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_5_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_6_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_6_of_clubs.png
new file mode 100644
index 0000000..e155286
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_6_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_6_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_6_of_diamonds.png
new file mode 100644
index 0000000..03bed89
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_6_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_6_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_6_of_hearts.png
new file mode 100644
index 0000000..1da3496
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_6_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_6_of_spades.png b/app/src/main/res/drawable-xhdpi/card_6_of_spades.png
new file mode 100644
index 0000000..8d25429
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_6_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_7_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_7_of_clubs.png
new file mode 100644
index 0000000..1eef2a4
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_7_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_7_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_7_of_diamonds.png
new file mode 100644
index 0000000..dcf486e
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_7_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_7_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_7_of_hearts.png
new file mode 100644
index 0000000..ca5a36c
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_7_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_7_of_spades.png b/app/src/main/res/drawable-xhdpi/card_7_of_spades.png
new file mode 100644
index 0000000..adee0df
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_7_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_8_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_8_of_clubs.png
new file mode 100644
index 0000000..3ab11b5
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_8_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_8_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_8_of_diamonds.png
new file mode 100644
index 0000000..98751a6
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_8_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_8_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_8_of_hearts.png
new file mode 100644
index 0000000..97e4af6
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_8_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_8_of_spades.png b/app/src/main/res/drawable-xhdpi/card_8_of_spades.png
new file mode 100644
index 0000000..5f9ebfb
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_8_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_9_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_9_of_clubs.png
new file mode 100644
index 0000000..f41babb
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_9_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_9_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_9_of_diamonds.png
new file mode 100644
index 0000000..2161e0b
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_9_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_9_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_9_of_hearts.png
new file mode 100644
index 0000000..cad8e97
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_9_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_9_of_spades.png b/app/src/main/res/drawable-xhdpi/card_9_of_spades.png
new file mode 100644
index 0000000..da1f0a3
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_9_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_ace_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_ace_of_clubs.png
new file mode 100644
index 0000000..02c7c0a
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_ace_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_ace_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_ace_of_diamonds.png
new file mode 100644
index 0000000..d1b6dea
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_ace_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_ace_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_ace_of_hearts.png
new file mode 100644
index 0000000..22c25b2
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_ace_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_ace_of_spades.png b/app/src/main/res/drawable-xhdpi/card_ace_of_spades.png
new file mode 100644
index 0000000..56622ba
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_ace_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_back.png b/app/src/main/res/drawable-xhdpi/card_back.png
new file mode 100644
index 0000000..6cf2743
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_back.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_back_blue.png b/app/src/main/res/drawable-xhdpi/card_back_blue.png
new file mode 100644
index 0000000..92dc440
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_back_blue.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_back_red.png b/app/src/main/res/drawable-xhdpi/card_back_red.png
new file mode 100644
index 0000000..6cf2743
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_back_red.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_jack_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_jack_of_clubs.png
new file mode 100644
index 0000000..28581ef
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_jack_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_jack_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_jack_of_diamonds.png
new file mode 100644
index 0000000..2dddef3
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_jack_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_jack_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_jack_of_hearts.png
new file mode 100644
index 0000000..36af5e0
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_jack_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_jack_of_spades.png b/app/src/main/res/drawable-xhdpi/card_jack_of_spades.png
new file mode 100644
index 0000000..5238a97
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_jack_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_king_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_king_of_clubs.png
new file mode 100644
index 0000000..33723e7
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_king_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_king_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_king_of_diamonds.png
new file mode 100644
index 0000000..9517967
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_king_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_king_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_king_of_hearts.png
new file mode 100644
index 0000000..b3421e3
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_king_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_king_of_spades.png b/app/src/main/res/drawable-xhdpi/card_king_of_spades.png
new file mode 100644
index 0000000..c7432bf
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_king_of_spades.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_queen_of_clubs.png b/app/src/main/res/drawable-xhdpi/card_queen_of_clubs.png
new file mode 100644
index 0000000..e2b3b52
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_queen_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_queen_of_diamonds.png b/app/src/main/res/drawable-xhdpi/card_queen_of_diamonds.png
new file mode 100644
index 0000000..139bc29
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_queen_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_queen_of_hearts.png b/app/src/main/res/drawable-xhdpi/card_queen_of_hearts.png
new file mode 100644
index 0000000..2f952d2
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_queen_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xhdpi/card_queen_of_spades.png b/app/src/main/res/drawable-xhdpi/card_queen_of_spades.png
new file mode 100644
index 0000000..8b244b3
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/card_queen_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_10_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_10_of_clubs.png
new file mode 100644
index 0000000..02d7057
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_10_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_10_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_10_of_diamonds.png
new file mode 100644
index 0000000..45e92df
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_10_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_10_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_10_of_hearts.png
new file mode 100644
index 0000000..33545c1
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_10_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_10_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_10_of_spades.png
new file mode 100644
index 0000000..ea93a39
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_10_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_2_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_2_of_clubs.png
new file mode 100644
index 0000000..e983203
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_2_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_2_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_2_of_diamonds.png
new file mode 100644
index 0000000..400696e
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_2_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_2_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_2_of_hearts.png
new file mode 100644
index 0000000..7484860
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_2_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_2_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_2_of_spades.png
new file mode 100644
index 0000000..2f1a489
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_2_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_3_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_3_of_clubs.png
new file mode 100644
index 0000000..a21f9d2
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_3_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_3_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_3_of_diamonds.png
new file mode 100644
index 0000000..4e28c0d
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_3_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_3_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_3_of_hearts.png
new file mode 100644
index 0000000..26a5081
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_3_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_3_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_3_of_spades.png
new file mode 100644
index 0000000..a906fb6
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_3_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_4_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_4_of_clubs.png
new file mode 100644
index 0000000..05409e0
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_4_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_4_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_4_of_diamonds.png
new file mode 100644
index 0000000..1ad36fa
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_4_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_4_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_4_of_hearts.png
new file mode 100644
index 0000000..09afe76
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_4_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_4_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_4_of_spades.png
new file mode 100644
index 0000000..edd4731
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_4_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_5_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_5_of_clubs.png
new file mode 100644
index 0000000..74a3fc3
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_5_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_5_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_5_of_diamonds.png
new file mode 100644
index 0000000..eefa04d
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_5_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_5_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_5_of_hearts.png
new file mode 100644
index 0000000..d52d51c
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_5_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_5_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_5_of_spades.png
new file mode 100644
index 0000000..bffa28b
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_5_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_6_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_6_of_clubs.png
new file mode 100644
index 0000000..beb15c7
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_6_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_6_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_6_of_diamonds.png
new file mode 100644
index 0000000..59db265
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_6_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_6_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_6_of_hearts.png
new file mode 100644
index 0000000..5e93d93
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_6_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_6_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_6_of_spades.png
new file mode 100644
index 0000000..80cd1b4
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_6_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_7_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_7_of_clubs.png
new file mode 100644
index 0000000..99720b0
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_7_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_7_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_7_of_diamonds.png
new file mode 100644
index 0000000..056e195
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_7_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_7_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_7_of_hearts.png
new file mode 100644
index 0000000..0c6294c
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_7_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_7_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_7_of_spades.png
new file mode 100644
index 0000000..b65b745
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_7_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_8_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_8_of_clubs.png
new file mode 100644
index 0000000..bbda0f6
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_8_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_8_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_8_of_diamonds.png
new file mode 100644
index 0000000..009dd1f
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_8_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_8_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_8_of_hearts.png
new file mode 100644
index 0000000..0729966
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_8_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_8_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_8_of_spades.png
new file mode 100644
index 0000000..d13f0bc
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_8_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_9_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_9_of_clubs.png
new file mode 100644
index 0000000..091909c
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_9_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_9_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_9_of_diamonds.png
new file mode 100644
index 0000000..d7daaea
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_9_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_9_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_9_of_hearts.png
new file mode 100644
index 0000000..ab778a0
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_9_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_9_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_9_of_spades.png
new file mode 100644
index 0000000..c4e6491
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_9_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_ace_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_ace_of_clubs.png
new file mode 100644
index 0000000..e2e44f9
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_ace_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_ace_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_ace_of_diamonds.png
new file mode 100644
index 0000000..6107768
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_ace_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_ace_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_ace_of_hearts.png
new file mode 100644
index 0000000..c0d63c8
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_ace_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_ace_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_ace_of_spades.png
new file mode 100644
index 0000000..22bacf8
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_ace_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_back.png b/app/src/main/res/drawable-xxhdpi/card_back.png
new file mode 100644
index 0000000..8659897
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_back.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_back_blue.png b/app/src/main/res/drawable-xxhdpi/card_back_blue.png
new file mode 100644
index 0000000..dcd083d
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_back_blue.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_back_red.png b/app/src/main/res/drawable-xxhdpi/card_back_red.png
new file mode 100644
index 0000000..8659897
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_back_red.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_jack_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_jack_of_clubs.png
new file mode 100644
index 0000000..c260f94
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_jack_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_jack_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_jack_of_diamonds.png
new file mode 100644
index 0000000..8b3e94a
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_jack_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_jack_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_jack_of_hearts.png
new file mode 100644
index 0000000..9cbc5fa
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_jack_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_jack_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_jack_of_spades.png
new file mode 100644
index 0000000..b166e80
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_jack_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_king_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_king_of_clubs.png
new file mode 100644
index 0000000..96eba0f
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_king_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_king_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_king_of_diamonds.png
new file mode 100644
index 0000000..ed15874
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_king_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_king_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_king_of_hearts.png
new file mode 100644
index 0000000..317cf4b
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_king_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_king_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_king_of_spades.png
new file mode 100644
index 0000000..589f2cb
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_king_of_spades.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_queen_of_clubs.png b/app/src/main/res/drawable-xxhdpi/card_queen_of_clubs.png
new file mode 100644
index 0000000..0be27f7
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_queen_of_clubs.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_queen_of_diamonds.png b/app/src/main/res/drawable-xxhdpi/card_queen_of_diamonds.png
new file mode 100644
index 0000000..f996aed
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_queen_of_diamonds.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_queen_of_hearts.png b/app/src/main/res/drawable-xxhdpi/card_queen_of_hearts.png
new file mode 100644
index 0000000..a3544ad
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_queen_of_hearts.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/card_queen_of_spades.png b/app/src/main/res/drawable-xxhdpi/card_queen_of_spades.png
new file mode 100644
index 0000000..a477a91
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/card_queen_of_spades.png differ
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..6861825
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Hold\'em
+
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..de174d9
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/build.gradle.kts b/build.gradle.kts
index 58b2789..b9f09a2 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,7 +1,6 @@
plugins {
alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.kotlin.jvm) apply false
- alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.kotlin.multiplatform.library) apply false
diff --git a/engine/src/commonTest/kotlin/com/jsjdesigns/poker/game/SnapshotDeliveryTest.kt b/engine/src/commonTest/kotlin/com/jsjdesigns/poker/game/SnapshotDeliveryTest.kt
new file mode 100644
index 0000000..9bda8aa
--- /dev/null
+++ b/engine/src/commonTest/kotlin/com/jsjdesigns/poker/game/SnapshotDeliveryTest.kt
@@ -0,0 +1,104 @@
+package com.jsjdesigns.poker.game
+
+import com.jsjdesigns.poker.core.StackedDeck
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runTest
+import kotlin.random.Random
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+private class Shoves : PlayerAgent {
+ override suspend fun act(ctx: DecisionContext): Action = when {
+ ctx.canRaise -> Action(ActionType.RAISE, ctx.maxRaiseTo)
+ ctx.toCall > 0 -> Action(ActionType.CALL, ctx.toCall)
+ else -> Action(ActionType.CHECK)
+ }
+}
+
+/**
+ * How snapshots reach the UI matters as much as what is in them.
+ *
+ * An all-in runout emits flop, turn and river within microseconds. A consumer
+ * that keeps only the latest value will show the player an empty board and then a
+ * complete one, losing the runout entirely.
+ */
+class SnapshotDeliveryTest {
+
+ private fun table(observer: suspend (TableSnapshot) -> Unit, seats: List) = Table(
+ seats = seats,
+ smallBlind = 5,
+ bigBlind = 10,
+ random = Random(1),
+ deck = StackedDeck.of(listOf("Ah Ad", "Kh Kd"), "2c 7d 9s Jc 3h"),
+ observer = observer,
+ )
+
+ @Test
+ fun `a channel preserves every runout frame`() = runTest {
+ val received = mutableListOf()
+ val channel = Channel(capacity = 32)
+
+ val consumer = launch {
+ for (frame in channel) received += frame
+ }
+
+ val seats = listOf(Seat(0, "A", 100, Shoves()), Seat(1, "B", 100, Shoves()))
+ table({ channel.send(it) }, seats).playHand()
+ channel.close()
+ consumer.join()
+
+ val boardSizes = received.map { it.board.size }.distinct().sorted()
+ assertEquals(
+ listOf(0, 3, 4, 5), boardSizes,
+ "every stage of the board must survive delivery",
+ )
+ }
+
+ /**
+ * Documents *why* the channel is required: the same run through a conflating
+ * StateFlow drops intermediate frames. This is a characterisation test — if it
+ * ever starts preserving them, the reasoning above can be revisited.
+ */
+ @Test
+ fun `a conflating StateFlow loses runout frames`() = runTest {
+ val flow = MutableStateFlow(null)
+ val observed = mutableListOf()
+
+ val seats = listOf(Seat(0, "A", 100, Shoves()), Seat(1, "B", 100, Shoves()))
+ // A collector that is not actively suspended on every emission — exactly the
+ // situation a recomposing UI is in — sees only whatever the latest value is.
+ table({ flow.value = it; observed += flow.value!! }, seats).playHand()
+
+ // The final value is all a late subscriber would ever see.
+ val lateSubscriberSees = flow.value
+ assertEquals(5, lateSubscriberSees?.board?.size, "only the river survives")
+ assertTrue(
+ observed.map { it.board.size }.distinct().size > 1,
+ "the engine did emit intermediate frames; conflation is what loses them",
+ )
+ }
+
+ @Test
+ fun `backpressure lets a slow consumer keep up without dropping frames`() = runTest {
+ val received = mutableListOf()
+ // Capacity 1 forces the engine to wait on nearly every emission.
+ val channel = Channel(capacity = 1)
+
+ val consumer = launch {
+ for (frame in channel) received += frame
+ }
+
+ val seats = listOf(Seat(0, "A", 100, Shoves()), Seat(1, "B", 100, Shoves()))
+ table({ channel.send(it) }, seats).playHand()
+ channel.close()
+ consumer.join()
+
+ assertEquals(
+ listOf(0, 3, 4, 5), received.map { it.board.size }.distinct().sorted(),
+ "a suspending observer means the engine cannot outrun the UI",
+ )
+ }
+}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 76e27bf..088ce34 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -16,6 +16,7 @@ androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref =
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" }
+androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
diff --git a/settings.gradle.kts b/settings.gradle.kts
index cf4fe76..fc20f0b 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -21,4 +21,4 @@ dependencyResolutionManagement {
}
rootProject.name = "Poker"
-include(":engine", ":sim")
+include(":engine", ":sim", ":app")
diff --git a/tools/generate_card_assets.sh b/tools/generate_card_assets.sh
new file mode 100755
index 0000000..4304c19
--- /dev/null
+++ b/tools/generate_card_assets.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# Rasterises the card SVGs into Android density buckets.
+#
+# The SVGs in assets/cards/ stay the source of truth; this regenerates the
+# drawables at any size. Uses macOS `sips`, which renders SVG directly — no
+# librsvg or ImageMagick needed.
+#
+# Note the `card_` prefix: Android resource names may not start with a digit, so
+# `10_of_clubs.svg` must become `card_10_of_clubs.png`.
+#
+# Usage: tools/generate_card_assets.sh
+set -euo pipefail
+
+SRC="$(cd "$(dirname "$0")/.." && pwd)/assets/cards"
+RES="$(cd "$(dirname "$0")/.." && pwd)/app/src/main/res"
+
+# Card art is 2:3. Widths are chosen so xxhdpi lands at a crisp 240x360.
+declare -a BUCKETS=(
+ "mdpi:80:120"
+ "hdpi:120:180"
+ "xhdpi:160:240"
+ "xxhdpi:240:360"
+)
+
+count=0
+for bucket in "${BUCKETS[@]}"; do
+ IFS=':' read -r density width height <<< "$bucket"
+ out="$RES/drawable-$density"
+ mkdir -p "$out"
+ for svg in "$SRC"/*.svg; do
+ base="$(basename "$svg" .svg)"
+ # playing_cards_deck is the 52-card contact sheet, not a usable game asset.
+ [ "$base" = "playing_cards_deck" ] && continue
+ sips -s format png -z "$height" "$width" "$svg" --out "$out/card_$base.png" >/dev/null 2>&1
+ count=$((count + 1))
+ done
+ echo " $density (${width}x${height}): $(ls "$out" | wc -l | tr -d ' ') files"
+done
+
+echo "generated $count PNGs"
+du -sh "$RES" | awk '{print " total: " $1}'