Caption Sequence jacks as WILD or REMOVE
A jack's power is carried by its artwork on a real deck — drawn in profile it shows one eye and removes a chip, drawn face-on it shows two and is wild. These cards render as rank and suit only, so J♦ and J♠ were indistinguishable in hand despite doing opposite things. Jacks in hand now carry the word on their face, and the hint under the hand says what tapping will do rather than the generic "tap a highlighted square", which was wrong for a one-eyed jack anyway — those target an opponent's chip, not a highlighted empty square. The caption is a general PlayingCardView option, so any later game whose cards carry meaning beyond rank and suit can use it. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015qjfMiPUDshdKEUa6vxqzN
This commit is contained in:
@@ -41,6 +41,12 @@ fun PlayingCardView(
|
||||
width: Dp = 64.dp,
|
||||
selected: Boolean = false,
|
||||
enabled: Boolean = true,
|
||||
/**
|
||||
* Short note printed on the face, for when the rank and suit alone do not
|
||||
* say what the card does — a Sequence jack being the obvious case, since
|
||||
* one-eyed and two-eyed jacks are only distinguishable by their artwork.
|
||||
*/
|
||||
caption: String? = null,
|
||||
onClick: (() -> Unit)? = null,
|
||||
) {
|
||||
val ink = if (card.suit.isRed) CardRed else CardBlack
|
||||
@@ -61,6 +67,8 @@ fun PlayingCardView(
|
||||
),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
// Shrink the pips slightly when a caption has to share the face.
|
||||
val pipScale = if (caption == null) 0.34f else 0.28f
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
@@ -69,13 +77,22 @@ fun PlayingCardView(
|
||||
text = card.rank.short,
|
||||
color = ink,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = (width.value * 0.34f).sp,
|
||||
fontSize = (width.value * pipScale).sp,
|
||||
)
|
||||
Text(
|
||||
text = card.suit.symbol,
|
||||
color = ink,
|
||||
fontSize = (width.value * 0.34f).sp,
|
||||
fontSize = (width.value * pipScale).sp,
|
||||
)
|
||||
if (caption != null) {
|
||||
Text(
|
||||
text = caption,
|
||||
color = ink,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = (width.value * 0.145f).sp,
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ import androidx.compose.ui.unit.sp
|
||||
import org.prolibertate.games.game.cards.Card
|
||||
import org.prolibertate.games.game.sequence.BOARD_SIZE
|
||||
import org.prolibertate.games.game.sequence.ExchangeDeadCard
|
||||
import org.prolibertate.games.game.sequence.isOneEyedJack
|
||||
import org.prolibertate.games.game.sequence.isTwoEyedJack
|
||||
import org.prolibertate.games.game.sequence.NO_TEAM
|
||||
import org.prolibertate.games.game.sequence.PlaceChip
|
||||
import org.prolibertate.games.game.sequence.RemoveChip
|
||||
@@ -54,6 +56,17 @@ import org.prolibertate.games.ui.theme.TeamColours
|
||||
*/
|
||||
private val HighlightAmber = Color(0xFFFFC107)
|
||||
|
||||
/**
|
||||
* What a jack does, printed on its face. On a real deck this is carried by the
|
||||
* artwork — a jack shown in profile has one eye and removes a chip, one shown
|
||||
* face-on has two and is wild — which a rank-and-suit card cannot convey.
|
||||
*/
|
||||
private fun jackCaption(card: Card): String? = when {
|
||||
isTwoEyedJack(card) -> "WILD"
|
||||
isOneEyedJack(card) -> "REMOVE"
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* The Sequence board.
|
||||
*
|
||||
@@ -294,6 +307,9 @@ private fun HandStrip(
|
||||
width = cardWidth,
|
||||
selected = card == selected,
|
||||
enabled = card in playable,
|
||||
// A jack's power comes from its artwork, which these cards
|
||||
// do not have, so spell it out on the face instead.
|
||||
caption = jackCaption(card),
|
||||
onClick = {
|
||||
val dead = exchanges[card]
|
||||
if (dead != null) onExchange(dead) else onSelect(card)
|
||||
@@ -301,9 +317,18 @@ private fun HandStrip(
|
||||
)
|
||||
}
|
||||
}
|
||||
selected?.let {
|
||||
selected?.let { card ->
|
||||
Text(
|
||||
text = "Tap a highlighted square to play ${it.label}.",
|
||||
text = when {
|
||||
isTwoEyedJack(card) ->
|
||||
"${card.label} is wild — tap any empty square."
|
||||
|
||||
isOneEyedJack(card) ->
|
||||
"${card.label} removes a chip — tap an opponent's, " +
|
||||
"as long as it isn't part of a finished sequence."
|
||||
|
||||
else -> "Tap a highlighted square to play ${card.label}."
|
||||
},
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user