summaryrefslogtreecommitdiff
path: root/sw-ui/src/main/kotlin/org/luxons
diff options
context:
space:
mode:
authorJoffrey Bion <joffrey.bion@booking.com>2020-05-28 12:47:00 +0200
committerJoffrey Bion <joffrey.bion@booking.com>2020-05-28 13:34:57 +0200
commita4da60fa4a816e3b8428eaffd2bd605dc0aed031 (patch)
tree18fcef04d9826fb94854c1a38584460659d8a3dd /sw-ui/src/main/kotlin/org/luxons
parentAdd server-side support for PLAY_FREE_DISCARDED special ability (diff)
downloadseven-wonders-a4da60fa4a816e3b8428eaffd2bd605dc0aed031.tar.gz
seven-wonders-a4da60fa4a816e3b8428eaffd2bd605dc0aed031.tar.bz2
seven-wonders-a4da60fa4a816e3b8428eaffd2bd605dc0aed031.zip
Add UI support for playing discarded cards
Resolves: https://github.com/joffrey-bion/seven-wonders/issues/25 Resolves: https://github.com/joffrey-bion/seven-wonders/issues/26
Diffstat (limited to 'sw-ui/src/main/kotlin/org/luxons')
-rw-r--r--sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt10
-rw-r--r--sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt234
2 files changed, 134 insertions, 110 deletions
diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt
index 64077359..238240ac 100644
--- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt
+++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/GameScene.kt
@@ -68,15 +68,7 @@ private class GameScene(props: GameSceneProps) : RComponent<GameSceneProps, RSta
topPlayerBoardsSummaries(topBoards)
}
handRotationIndicator(turnInfo.table.handRotationDirection)
- val hand = turnInfo.hand
- if (hand != null) {
- handComponent(
- cards = hand,
- wonderBuildability = turnInfo.wonderBuildability,
- preparedMove = props.preparedMove,
- prepareMove = props.prepareMove
- )
- }
+ handCards(turnInfo, props.preparedMove, props.prepareMove)
val card = props.preparedCard
val move = props.preparedMove
if (card != null && move != null) {
diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt
index e2e89a95..dd8595eb 100644
--- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt
+++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/Hand.kt
@@ -4,137 +4,155 @@ import com.palantir.blueprintjs.*
import kotlinx.css.*
import kotlinx.css.properties.*
import kotlinx.html.DIV
-import org.luxons.sevenwonders.model.MoveType
-import org.luxons.sevenwonders.model.PlayerMove
+import org.luxons.sevenwonders.model.*
import org.luxons.sevenwonders.model.cards.CardPlayability
import org.luxons.sevenwonders.model.cards.HandCard
-import org.luxons.sevenwonders.model.resources.noTransactions
import org.luxons.sevenwonders.model.wonders.WonderBuildability
-import react.RBuilder
-import react.RElementBuilder
+import react.*
import styled.StyledDOMBuilder
import styled.css
import styled.styledDiv
import kotlin.math.absoluteValue
-fun RBuilder.handComponent(
- cards: List<HandCard>,
- wonderBuildability: WonderBuildability,
- preparedMove: PlayerMove?,
- prepareMove: (PlayerMove) -> Unit
+private enum class HandAction(
+ val buttonTitle: String,
+ val moveType: MoveType,
+ val icon: IconName
) {
- styledDiv {
- css {
- handStyle()
- }
- cards.filter { it.name != preparedMove?.cardName }.forEachIndexed { index, c ->
- handCard(
- card = c,
- wonderBuildability = wonderBuildability,
- prepareMove = prepareMove
- ) {
- attrs {
- key = index.toString()
+ PLAY("PLAY", MoveType.PLAY, "play"),
+ PLAY_FREE("Play as this age's free card", MoveType.PLAY_FREE, "play"),
+ PLAY_FREE_DISCARDED("Play discarded card", MoveType.PLAY_FREE_DISCARDED, "play"),
+ COPY_GUILD("Copy this guild card", MoveType.COPY_GUILD, "duplicate")
+}
+
+interface HandProps : RProps {
+ var turnInfo: PlayerTurnInfo
+ var preparedMove: PlayerMove?
+ var prepareMove: (PlayerMove) -> Unit
+}
+
+class HandComponent(props: HandProps) : RComponent<HandProps, RState>(props) {
+
+ override fun RBuilder.render() {
+ val hand = props.turnInfo.cardsToPlay() ?: return
+ styledDiv {
+ css {
+ handStyle()
+ }
+ hand.filter { it.name != props.preparedMove?.cardName }.forEachIndexed { index, c ->
+ handCard(card = c) {
+ attrs {
+ key = index.toString()
+ }
}
}
}
}
-}
-private fun RBuilder.handCard(
- card: HandCard,
- wonderBuildability: WonderBuildability,
- prepareMove: (PlayerMove) -> Unit,
- block: StyledDOMBuilder<DIV>.() -> Unit
-) {
- styledDiv {
- css {
- handCardStyle()
- }
- block()
- cardImage(card) {
+ private fun PlayerTurnInfo.cardsToPlay(): List<HandCard>? = when (action) {
+ Action.PLAY, Action.PLAY_2, Action.PLAY_LAST -> hand
+ Action.PLAY_FREE_DISCARDED -> discardedCards
+ Action.PICK_NEIGHBOR_GUILD -> neighbourGuildCards
+ Action.WAIT, Action.WATCH_SCORE, Action.SAY_READY -> null
+ }
+
+ private fun RBuilder.handCard(
+ card: HandCard,
+ block: StyledDOMBuilder<DIV>.() -> Unit
+ ) {
+ styledDiv {
css {
- handCardImgStyle(card.playability.isPlayable)
+ handCardStyle()
}
+ block()
+ cardImage(card) {
+ css {
+ handCardImgStyle(card.playability.isPlayable)
+ }
+ }
+ actionButtons(card)
}
- actionButtons(card, wonderBuildability, prepareMove)
}
-}
-private fun RBuilder.actionButtons(card: HandCard, wonderBuildability: WonderBuildability, prepareMove: (PlayerMove) -> Unit) {
- styledDiv {
- css {
- alignItems = Align.flexEnd
- display = Display.none
- gridRow = GridRow("1")
- gridColumn = GridColumn("1")
+ private fun RBuilder.actionButtons(card: HandCard) {
+ styledDiv {
+ css {
+ justifyContent = JustifyContent.center
+ alignItems = Align.flexEnd
+ display = Display.none
+ gridRow = GridRow("1")
+ gridColumn = GridColumn("1")
+
+ ancestorHover(".hand-card") {
+ display = Display.flex
+ }
+ }
+ bpButtonGroup {
+ val action = props.turnInfo.action
+ when (action) {
+ Action.PLAY, Action.PLAY_2, Action.PLAY_LAST -> {
+ playCardButton(card, HandAction.PLAY)
+ if (props.turnInfo.getOwnBoard().canPlayAnyCardForFree) {
+ playCardButton(card.copy(playability = CardPlayability.SPECIAL_FREE), HandAction.PLAY_FREE)
+ }
+ }
+ Action.PLAY_FREE_DISCARDED -> playCardButton(card, HandAction.PLAY_FREE_DISCARDED)
+ Action.PICK_NEIGHBOR_GUILD -> playCardButton(card, HandAction.COPY_GUILD)
+ else -> error("unsupported action in hand card: $action")
+ }
- ancestorHover(".hand-card") {
- display = Display.flex
+ if (action.allowsBuildingWonder()) {
+ upgradeWonderButton(card)
+ }
+ if (action.allowsDiscarding()) {
+ discardButton(card)
+ }
}
}
- bpButtonGroup {
- playCardButton(card, prepareMove)
- upgradeWonderButton(wonderBuildability, prepareMove, card)
- discardButton(prepareMove, card)
- }
}
-}
-private fun RElementBuilder<IButtonGroupProps>.playCardButton(
- card: HandCard,
- prepareMove: (PlayerMove) -> Unit
-) {
- bpButton(
- title = "PLAY (${cardPlayabilityInfo(card.playability)})",
- large = true,
- intent = Intent.SUCCESS,
- disabled = !card.playability.isPlayable,
- onClick = {
- val transactions = card.playability.cheapestTransactions.firstOrNull() ?: noTransactions()
- prepareMove(PlayerMove(MoveType.PLAY, card.name, transactions))
- }
- ) {
- bpIcon("play")
- if (card.playability.isPlayable && !card.playability.isFree) {
- priceInfo(card.playability.minPrice)
+ private fun RElementBuilder<IButtonGroupProps>.playCardButton(card: HandCard, handAction: HandAction) {
+ bpButton(title = "${handAction.buttonTitle} (${cardPlayabilityInfo(card.playability)})",
+ large = true,
+ intent = Intent.SUCCESS,
+ disabled = !card.playability.isPlayable,
+ onClick = {
+ val transactions = card.playability.cheapestTransactions.first()
+ props.prepareMove(PlayerMove(handAction.moveType, card.name, transactions))
+ }) {
+ bpIcon(handAction.icon)
+ if (card.playability.isPlayable && !card.playability.isFree) {
+ priceInfo(card.playability.minPrice)
+ }
}
}
-}
-private fun RElementBuilder<IButtonGroupProps>.upgradeWonderButton(
- wonderBuildability: WonderBuildability,
- prepareMove: (PlayerMove) -> Unit,
- card: HandCard
-) {
- bpButton(
- title = "UPGRADE WONDER (${wonderBuildabilityInfo(wonderBuildability)})",
- large = true,
- intent = Intent.PRIMARY,
- disabled = !wonderBuildability.isBuildable,
- onClick = {
- val transactions = wonderBuildability.cheapestTransactions.firstOrNull() ?: noTransactions()
- prepareMove(PlayerMove(MoveType.UPGRADE_WONDER, card.name, transactions))
- }
- ) {
- bpIcon("key-shift")
- if (wonderBuildability.isBuildable && !wonderBuildability.isFree) {
- priceInfo(wonderBuildability.minPrice)
+ private fun RElementBuilder<IButtonGroupProps>.upgradeWonderButton(card: HandCard) {
+ val wonderBuildability = props.turnInfo.wonderBuildability
+ bpButton(title = "UPGRADE WONDER (${wonderBuildabilityInfo(wonderBuildability)})",
+ large = true,
+ intent = Intent.PRIMARY,
+ disabled = !wonderBuildability.isBuildable,
+ onClick = {
+ val transactions = wonderBuildability.cheapestTransactions.first()
+ props.prepareMove(PlayerMove(MoveType.UPGRADE_WONDER, card.name, transactions))
+ }) {
+ bpIcon("key-shift")
+ if (wonderBuildability.isBuildable && !wonderBuildability.isFree) {
+ priceInfo(wonderBuildability.minPrice)
+ }
}
}
-}
-private fun RElementBuilder<IButtonGroupProps>.discardButton(
- prepareMove: (PlayerMove) -> Unit,
- card: HandCard
-) {
- bpButton(
- title = "DISCARD (+3 coins)", // TODO remove hardcoded value
- large = true,
- intent = Intent.DANGER,
- icon = "cross",
- onClick = { prepareMove(PlayerMove(MoveType.DISCARD, card.name)) }
- )
+ private fun RElementBuilder<IButtonGroupProps>.discardButton(card: HandCard) {
+ bpButton(
+ title = "DISCARD (+3 coins)", // TODO remove hardcoded value
+ large = true,
+ intent = Intent.DANGER,
+ icon = "cross",
+ onClick = { props.prepareMove(PlayerMove(MoveType.DISCARD, card.name)) }
+ )
+ }
}
private fun cardPlayabilityInfo(playability: CardPlayability) = when (playability.isPlayable) {
@@ -224,3 +242,17 @@ private fun CSSBuilder.handCardImgStyle(isPlayable: Boolean) {
filter = "grayscale(50%) contrast(50%)"
}
}
+
+fun RBuilder.handCards(
+ turnInfo: PlayerTurnInfo,
+ preparedMove: PlayerMove?,
+ prepareMove: (PlayerMove) -> Unit
+) {
+ child(HandComponent::class) {
+ attrs {
+ this.turnInfo = turnInfo
+ this.preparedMove = preparedMove
+ this.prepareMove = prepareMove
+ }
+ }
+}
bgstack15