diff options
Diffstat (limited to 'game-engine')
8 files changed, 71 insertions, 19 deletions
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Boards.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Boards.kt index e1b9c4e9..8bc87b55 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Boards.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Boards.kt @@ -1,14 +1,17 @@ package org.luxons.sevenwonders.game.api +import org.luxons.sevenwonders.game.Player import org.luxons.sevenwonders.game.boards.Military import org.luxons.sevenwonders.game.boards.Science import org.luxons.sevenwonders.game.boards.ScienceType import org.luxons.sevenwonders.game.cards.CardBack +import org.luxons.sevenwonders.game.cards.Requirements import org.luxons.sevenwonders.game.moves.Move import org.luxons.sevenwonders.game.moves.MoveType import org.luxons.sevenwonders.game.resources.Production import org.luxons.sevenwonders.game.resources.ResourceType import org.luxons.sevenwonders.game.resources.Resources +import org.luxons.sevenwonders.game.wonders.WonderBuildability import org.luxons.sevenwonders.game.boards.Board as InternalBoard import org.luxons.sevenwonders.game.wonders.Wonder as InternalWonder import org.luxons.sevenwonders.game.wonders.WonderStage as InternalWonderStage @@ -24,9 +27,9 @@ data class Board( val gold: Int ) -internal fun InternalBoard.toApiBoard(lastMove: Move?): Board = Board( +internal fun InternalBoard.toApiBoard(player: Player, lastMove: Move?): Board = Board( playerIndex = playerIndex, - wonder = wonder.toApiWonder(lastMove), + wonder = wonder.toApiWonder(player, lastMove), production = production.toApiProduction(), publicProduction = publicProduction.toApiProduction(), science = science.toApiScience(), @@ -40,27 +43,34 @@ data class Wonder( val initialResource: ResourceType, val stages: List<WonderStage>, val image: String, - val nbBuiltStages: Int + val nbBuiltStages: Int, + val buildability: WonderBuildability ) -internal fun InternalWonder.toApiWonder(lastMove: Move?): Wonder = Wonder( +internal fun InternalWonder.toApiWonder(player: Player, lastMove: Move?): Wonder = Wonder( name = name, initialResource = initialResource, stages = stages.map { it.toApiWonderStage(lastBuiltStage == it, lastMove) }, image = image, - nbBuiltStages = nbBuiltStages + nbBuiltStages = nbBuiltStages, + buildability = computeBuildabilityBy(player) ) data class WonderStage( val cardBack: CardBack?, val isBuilt: Boolean, + val requirements: Requirements, val builtDuringLastMove: Boolean ) -internal fun InternalWonderStage.toApiWonderStage(isLastBuiltStage: Boolean, lastMove: Move?): WonderStage = +internal fun InternalWonderStage.toApiWonderStage( + isLastBuiltStage: Boolean, + lastMove: Move? +): WonderStage = WonderStage( cardBack = cardBack, isBuilt = isBuilt, + requirements = requirements, builtDuringLastMove = lastMove?.type == MoveType.UPGRADE_WONDER && isLastBuiltStage ) diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt index 4be897db..c44f0a4c 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt @@ -1,5 +1,6 @@ package org.luxons.sevenwonders.game.api +import org.luxons.sevenwonders.game.SimplePlayer import org.luxons.sevenwonders.game.cards.HandRotationDirection import org.luxons.sevenwonders.game.data.Age import org.luxons.sevenwonders.game.moves.Move @@ -17,7 +18,7 @@ data class Table( } internal fun InternalTable.toApiTable(): Table = Table( - boards = boards.mapIndexed { i, b -> b.toApiBoard(lastPlayedMoves.getOrNull(i)) }, + boards = boards.mapIndexed { i, b -> b.toApiBoard(SimplePlayer(i, this), lastPlayedMoves.getOrNull(i)) }, currentAge = currentAge, handRotationDirection = handRotationDirection, lastPlayedMoves = lastPlayedMoves.map { it.toPlayedMove() } diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt index 66f657b7..cf4df44e 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt @@ -21,7 +21,7 @@ internal data class Card( fun computePlayabilityBy(player: Player): CardPlayability = when { isAlreadyOnBoard(player.board) -> CardPlayability.incompatibleWithBoard() // cannot play twice the same card isParentOnBoard(player.board) -> CardPlayability.chainable() - else -> CardPlayability.requirementDependent(requirements.computeSatisfaction(player)) + else -> CardPlayability.requirementDependent(requirements.assess(player)) } fun isPlayableOnBoardWith(board: Board, transactions: ResourceTransactions) = @@ -53,20 +53,22 @@ enum class Color { data class CardPlayability( val isPlayable: Boolean, - val isFree: Boolean = false, val isChainable: Boolean = false, val minPrice: Int = Int.MAX_VALUE, val cheapestTransactions: Set<ResourceTransactions> = emptySet(), val playabilityLevel: PlayabilityLevel ) { + val isFree: Boolean = minPrice == 0 + companion object { - internal fun incompatibleWithBoard(): CardPlayability = - CardPlayability(isPlayable = false, playabilityLevel = PlayabilityLevel.INCOMPATIBLE_WITH_BOARD) + internal fun incompatibleWithBoard(): CardPlayability = CardPlayability( + isPlayable = false, + playabilityLevel = PlayabilityLevel.INCOMPATIBLE_WITH_BOARD + ) internal fun chainable(): CardPlayability = CardPlayability( isPlayable = true, - isFree = true, isChainable = true, minPrice = 0, cheapestTransactions = setOf(noTransactions()), @@ -75,7 +77,6 @@ data class CardPlayability( internal fun requirementDependent(satisfaction: RequirementsSatisfaction): CardPlayability = CardPlayability( isPlayable = satisfaction.satisfied, - isFree = satisfaction.minPrice == 0, isChainable = false, minPrice = satisfaction.minPrice, cheapestTransactions = satisfaction.cheapestTransactions, diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt index 36a09ba2..27f73109 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt @@ -17,7 +17,7 @@ data class Requirements internal constructor( * Returns information about the extent to which the given [player] meets these requirements, either on its own or * by buying resources to neighbours. */ - internal fun computeSatisfaction(player: Player): RequirementsSatisfaction { + internal fun assess(player: Player): RequirementsSatisfaction { if (player.board.gold < gold) { return RequirementsSatisfaction.missingRequiredGold(gold) } diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt index a91a2af1..6ffda080 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt @@ -82,4 +82,6 @@ class MutableResources( other is Resources && quantities.filterValues { it > 0 } == other.quantities.filterValues { it > 0 } override fun hashCode(): Int = quantities.filterValues { it > 0 }.hashCode() + + override fun toString(): String = "$quantities" } diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt index 4910c51f..5e1cece0 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt @@ -3,6 +3,8 @@ package org.luxons.sevenwonders.game.wonders import org.luxons.sevenwonders.game.Player import org.luxons.sevenwonders.game.boards.Board import org.luxons.sevenwonders.game.cards.CardBack +import org.luxons.sevenwonders.game.cards.PlayabilityLevel +import org.luxons.sevenwonders.game.cards.RequirementsSatisfaction import org.luxons.sevenwonders.game.resources.ResourceTransactions import org.luxons.sevenwonders.game.resources.ResourceType @@ -26,6 +28,13 @@ internal class Wonder( val lastBuiltStage: WonderStage? get() = stages.getOrNull(nbBuiltStages - 1) + fun computeBuildabilityBy(player: Player): WonderBuildability { + if (nbBuiltStages == stages.size) { + return WonderBuildability.alreadyBuilt() + } + return WonderBuildability.requirementDependent(nextStage.requirements.assess(player)) + } + fun isNextStageBuildable(board: Board, boughtResources: ResourceTransactions): Boolean = nbBuiltStages < stages.size && nextStage.isBuildable(board, boughtResources) @@ -37,3 +46,27 @@ internal class Wonder( fun computePoints(player: Player): Int = stages.filter { it.isBuilt }.flatMap { it.effects }.sumBy { it.computePoints(player) } } + +data class WonderBuildability( + val isBuildable: Boolean, + val minPrice: Int = Int.MAX_VALUE, + val cheapestTransactions: Set<ResourceTransactions> = emptySet(), + val playabilityLevel: PlayabilityLevel +) { + val isFree: Boolean = minPrice == 0 + + companion object { + + fun alreadyBuilt() = WonderBuildability( + isBuildable = false, + playabilityLevel = PlayabilityLevel.INCOMPATIBLE_WITH_BOARD + ) + + internal fun requirementDependent(satisfaction: RequirementsSatisfaction) = WonderBuildability( + isBuildable = satisfaction.satisfied, + minPrice = satisfaction.minPrice, + cheapestTransactions = satisfaction.cheapestTransactions, + playabilityLevel = satisfaction.level + ) + } +} diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt index 11293b64..12f867f2 100644 --- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt +++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt @@ -71,6 +71,11 @@ class GameTest { } private fun createPlayCardMove(turnInfo: PlayerTurnInfo): MoveExpectation { + val wonderBuildability = turnInfo.table.boards[turnInfo.playerIndex].wonder.buildability + if (wonderBuildability.isBuildable) { + val transactions = wonderBuildability.cheapestTransactions.first() + return planMove(turnInfo, MoveType.UPGRADE_WONDER, turnInfo.hand.first(), transactions) + } val playableCard = turnInfo.hand.firstOrNull { it.playability.isPlayable } return if (playableCard != null) { planMove(turnInfo, MoveType.PLAY, playableCard, playableCard.playability.cheapestTransactions.first()) diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt index 5f6c18b0..eccca3e7 100644 --- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt +++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt @@ -45,7 +45,7 @@ class RequirementsTest { assertEquals(boardGold >= requiredGold, requirements.areMetWithHelpBy(board, noTransactions())) - val satisfaction = requirements.computeSatisfaction(player) + val satisfaction = requirements.assess(player) if (boardGold >= requiredGold) { if (requiredGold == 0) { assertEquals(RequirementsSatisfaction.noRequirements(), satisfaction) @@ -67,7 +67,7 @@ class RequirementsTest { assertEquals(initialResource == requiredResource, requirements.areMetWithHelpBy(board, noTransactions())) if (initialResource == requiredResource) { - val satisfaction = requirements.computeSatisfaction(player) + val satisfaction = requirements.assess(player) assertEquals(RequirementsSatisfaction.enoughResources(), satisfaction) } } @@ -89,7 +89,7 @@ class RequirementsTest { assertEquals(producedResource == requiredResource, requirements.areMetWithHelpBy(board, noTransactions())) if (producedResource == requiredResource) { - val satisfaction = requirements.computeSatisfaction(player) + val satisfaction = requirements.assess(player) assertEquals(RequirementsSatisfaction.enoughResources(), satisfaction) } } @@ -115,7 +115,7 @@ class RequirementsTest { val neighbourHasResource = boughtResource == requiredResource assertEquals(neighbourHasResource, requirements.areMetWithHelpBy(board, resources)) - val satisfaction = requirements.computeSatisfaction(player) + val satisfaction = requirements.assess(player) if (neighbourHasResource) { val transactions = setOf( createTransactions(Provider.LEFT_PLAYER, requiredResource), @@ -141,7 +141,7 @@ class RequirementsTest { val transactions = createTransactions(Provider.RIGHT_PLAYER, requiredResource) assertTrue(requirements.areMetWithHelpBy(board, transactions)) - assertTrue(requirements.computeSatisfaction(player).satisfied) + assertTrue(requirements.assess(player).satisfied) requirements.pay(player, transactions) |