summaryrefslogtreecommitdiff
path: root/game-engine
diff options
context:
space:
mode:
Diffstat (limited to 'game-engine')
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Boards.kt22
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt3
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt13
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt33
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt5
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt10
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)
bgstack15