create ICantPlayCommand

+ move canBePlayThisCard
This commit is contained in:
2025-03-05 02:08:05 +01:00
parent 32472018d4
commit b6908cc712
4 changed files with 124 additions and 64 deletions

View File

@@ -76,4 +76,75 @@ data class GameState(
if (lastCard == null) error("No card") if (lastCard == null) error("No card")
return this.playerDiffIndex(lastCard.player) == 1 return this.playerDiffIndex(lastCard.player) == 1
} }
fun playableCards(player: Player): List<Card> =
deck
.playersHands[player]
?.filter { canBePlayThisCard(player, it) }
?: emptyList()
fun canBePlayThisCard(
player: Player,
card: Card,
): Boolean {
val cardOnBoard = lastCard?.card ?: return false
return when (cardOnBoard) {
is Card.NumericCard -> {
when (card) {
is Card.AllColorCard -> true
is Card.NumericCard -> card.number == cardOnBoard.number || card.color == cardOnBoard.color
is Card.ColorCard -> card.color == cardOnBoard.color
}
}
is Card.ReverseCard -> {
when (card) {
is Card.ReverseCard -> true
is Card.AllColorCard -> true
is Card.ColorCard -> card.color == cardOnBoard.color
}
}
is Card.PassCard -> {
if (player.cardOnBoardIsForYou) {
false
} else {
when (card) {
is Card.AllColorCard -> true
is Card.ColorCard -> card.color == cardOnBoard.color
}
}
}
is Card.ChangeColorCard -> {
when (card) {
is Card.AllColorCard -> true
is Card.ColorCard -> card.color == lastColor
}
}
is Card.Plus2Card -> {
if (player.cardOnBoardIsForYou && card is Card.Plus2Card) {
true
} else {
when (card) {
is Card.AllColorCard -> true
is Card.Plus2Card -> true
is Card.ColorCard -> card.color == cardOnBoard.color
}
}
}
is Card.Plus4Card -> {
if (player.cardOnBoardIsForYou && card is Card.Plus4Card) {
true
} else {
when (card) {
is Card.AllColorCard -> true
is Card.ColorCard -> card.color == lastColor
}
}
}
}
}
} }

View File

@@ -2,6 +2,7 @@ package eventDemo.app.command
import eventDemo.app.GameState import eventDemo.app.GameState
import eventDemo.app.command.command.GameCommand import eventDemo.app.command.command.GameCommand
import eventDemo.app.command.command.ICantPlayCommand
import eventDemo.app.command.command.IWantToJoinTheGameCommand import eventDemo.app.command.command.IWantToJoinTheGameCommand
import eventDemo.app.command.command.IWantToPlayCardCommand import eventDemo.app.command.command.IWantToPlayCardCommand
import eventDemo.app.command.command.IamReadyToPlayCommand import eventDemo.app.command.command.IamReadyToPlayCommand
@@ -46,6 +47,7 @@ class GameCommandHandler(
is IWantToPlayCardCommand -> command.run(gameState, playerNotifier, eventStream) is IWantToPlayCardCommand -> command.run(gameState, playerNotifier, eventStream)
is IamReadyToPlayCommand -> command.run(gameState, playerNotifier, eventStream) is IamReadyToPlayCommand -> command.run(gameState, playerNotifier, eventStream)
is IWantToJoinTheGameCommand -> command.run(gameState, playerNotifier, eventStream) is IWantToJoinTheGameCommand -> command.run(gameState, playerNotifier, eventStream)
is ICantPlayCommand -> command.run(gameState, playerNotifier, eventStream)
} }
} }
} }

View File

@@ -0,0 +1,45 @@
package eventDemo.app.command.command
import eventDemo.app.GameState
import eventDemo.app.entity.GameId
import eventDemo.app.entity.Player
import eventDemo.app.event.GameEventStream
import eventDemo.app.event.event.PlayerHavePassEvent
import eventDemo.libs.command.CommandId
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* A command to perform an action to play a new card
*/
@Serializable
@SerialName("Pass")
data class ICantPlayCommand(
override val payload: Payload,
) : GameCommand {
override val id: CommandId = CommandId()
@Serializable
data class Payload(
override val gameId: GameId,
override val player: Player,
) : GameCommand.Payload
fun run(
state: GameState,
playerNotifier: (String) -> Unit,
eventStream: GameEventStream,
) {
val playableCards = state.playableCards(payload.player)
if (playableCards.isEmpty()) {
eventStream.publish(
PlayerHavePassEvent(
payload.gameId,
payload.player,
),
)
} else {
playerNotifier("You can and must play one card, like ${playableCards.first()::class.simpleName}")
}
}
}

View File

@@ -32,7 +32,12 @@ data class IWantToPlayCardCommand(
playerNotifier: (String) -> Unit, playerNotifier: (String) -> Unit,
eventStream: GameEventStream, eventStream: GameEventStream,
) { ) {
if (state.canBePlayThisCard()) { if (!state.isReady) {
playerNotifier("The game is Not started")
return
}
if (state.canBePlayThisCard(payload.player, payload.card)) {
eventStream.publish( eventStream.publish(
CardIsPlayedEvent( CardIsPlayedEvent(
payload.gameId, payload.gameId,
@@ -44,67 +49,4 @@ data class IWantToPlayCardCommand(
playerNotifier("You cannot play this card") playerNotifier("You cannot play this card")
} }
} }
fun GameState.canBePlayThisCard(): Boolean {
if (!isReady) return false
val cardOnBoard = lastCard?.card ?: return false
return when (cardOnBoard) {
is Card.NumericCard -> {
when (payload.card) {
is Card.AllColorCard -> true
is Card.NumericCard -> payload.card.number == cardOnBoard.number || payload.card.color == cardOnBoard.color
is Card.ColorCard -> payload.card.color == cardOnBoard.color
}
}
is Card.ReverseCard -> {
when (payload.card) {
is Card.ReverseCard -> true
is Card.AllColorCard -> true
is Card.ColorCard -> payload.card.color == cardOnBoard.color
}
}
is Card.PassCard -> {
if (payload.player.cardOnBoardIsForYou) {
false
} else {
when (payload.card) {
is Card.AllColorCard -> true
is Card.ColorCard -> payload.card.color == cardOnBoard.color
}
}
}
is Card.ChangeColorCard -> {
when (payload.card) {
is Card.AllColorCard -> true
is Card.ColorCard -> payload.card.color == lastColor
}
}
is Card.Plus2Card -> {
if (payload.player.cardOnBoardIsForYou && payload.card is Card.Plus2Card) {
true
} else {
when (payload.card) {
is Card.AllColorCard -> true
is Card.Plus2Card -> true
is Card.ColorCard -> payload.card.color == cardOnBoard.color
}
}
}
is Card.Plus4Card -> {
if (payload.player.cardOnBoardIsForYou && payload.card is Card.Plus4Card) {
true
} else {
when (payload.card) {
is Card.AllColorCard -> true
is Card.ColorCard -> payload.card.color == lastColor
}
}
}
}
}
} }