summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/build.gradle.kts1
-rw-r--r--build.gradle.kts1
-rw-r--r--game-engine/build.gradle.kts1
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Game.kt3
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Settings.kt6
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Boards.kt85
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Cards.kt74
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerMove.kt11
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt20
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Board.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Military.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Table.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt66
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Hands.kt1
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/RequirementsSatisfaction.kt13
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinition.kt3
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.kt6
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt8
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt15
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt33
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt34
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt15
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/api/BoardsKtTest.kt1
-rw-r--r--game-model/build.gradle47
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/Boards.kt44
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt (renamed from game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt)8
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/PlayerTurnInfo.kt (renamed from game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerTurnInfo.kt)13
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/Table.kt24
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt (renamed from game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt)7
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt65
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/cards/HandRotationDirection.kt (renamed from game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/HandRotationDirection.kt)0
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt9
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/Provider.kt (renamed from game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Provider.kt)0
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt9
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/ResourceType.kt (renamed from game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceType.kt)0
-rw-r--r--game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt32
-rw-r--r--settings.gradle13
39 files changed, 399 insertions, 279 deletions
diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts
index e1d56e59..8bb77645 100644
--- a/backend/build.gradle.kts
+++ b/backend/build.gradle.kts
@@ -12,6 +12,7 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
}
dependencies {
+ compile(project(":game-model"))
compile(project(":game-engine"))
compile(kotlin("stdlib-jdk8"))
compile(kotlin("reflect")) // required by Spring 5
diff --git a/build.gradle.kts b/build.gradle.kts
index 4bfe4816..cd926085 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,5 +1,6 @@
plugins {
val kotlinVersion = "1.3.31"
+ id("kotlin-multiplatform") version kotlinVersion apply false
id("org.jetbrains.kotlin.jvm") version kotlinVersion apply false
id("org.jetbrains.kotlin.plugin.spring") version kotlinVersion apply false
}
diff --git a/game-engine/build.gradle.kts b/game-engine/build.gradle.kts
index 674ac00e..6f135a90 100644
--- a/game-engine/build.gradle.kts
+++ b/game-engine/build.gradle.kts
@@ -4,6 +4,7 @@ plugins {
}
dependencies {
+ implementation(project(":game-model"))
implementation(kotlin("stdlib-jdk8"))
implementation("com.github.salomonbrys.kotson:kotson:2.5.0")
testImplementation(kotlin("test"))
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Game.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Game.kt
index 9b4eff72..266a57a5 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Game.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Game.kt
@@ -1,7 +1,7 @@
package org.luxons.sevenwonders.game
import org.luxons.sevenwonders.game.api.Action
-import org.luxons.sevenwonders.game.api.HandCard
+import org.luxons.sevenwonders.game.cards.HandCard
import org.luxons.sevenwonders.game.api.PlayerMove
import org.luxons.sevenwonders.game.api.PlayerTurnInfo
import org.luxons.sevenwonders.game.api.toApiTable
@@ -16,6 +16,7 @@ import org.luxons.sevenwonders.game.cards.Hands
import org.luxons.sevenwonders.game.data.LAST_AGE
import org.luxons.sevenwonders.game.effects.SpecialAbility
import org.luxons.sevenwonders.game.moves.Move
+import org.luxons.sevenwonders.game.moves.resolve
import org.luxons.sevenwonders.game.score.ScoreBoard
import org.luxons.sevenwonders.game.api.Table as ApiTable
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Settings.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Settings.kt
index 63d5052f..ad6cb105 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Settings.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/Settings.kt
@@ -1,15 +1,15 @@
package org.luxons.sevenwonders.game
import org.luxons.sevenwonders.game.api.CustomizableSettings
+import org.luxons.sevenwonders.game.api.WonderSide
import org.luxons.sevenwonders.game.api.WonderSidePickMethod
-import org.luxons.sevenwonders.game.data.definitions.WonderSide
-import java.util.Random
+import kotlin.random.Random
internal class Settings(
val nbPlayers: Int,
customSettings: CustomizableSettings = CustomizableSettings()
) {
- val random: Random = customSettings.randomSeedForTests?.let { Random(it) } ?: Random()
+ val random: Random = customSettings.randomSeedForTests?.let { Random(it) } ?: Random
val timeLimitInSeconds: Int = customSettings.timeLimitInSeconds
val initialGold: Int = customSettings.initialGold
val discardedCardGold: Int = customSettings.discardedCardGold
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 470b4efa..5dff8636 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
@@ -4,29 +4,18 @@ 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.cards.TableCard
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.wonders.ApiWonder
+import org.luxons.sevenwonders.game.wonders.ApiWonderStage
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
-data class Board(
- val playerIndex: Int,
- val wonder: Wonder,
- val production: ApiProduction,
- val publicProduction: ApiProduction,
- val science: ApiScience,
- val military: ApiMilitary,
- val playedCards: List<List<TableCard>>,
- val gold: Int
-)
-
internal fun InternalBoard.toApiBoard(player: Player, lastMove: Move?): Board = Board(
playerIndex = playerIndex,
wonder = wonder.toApiWonder(player, lastMove),
@@ -49,45 +38,24 @@ internal fun List<TableCard>.toColumns(): List<List<TableCard>> {
return listOf(resourceCardsCol) + otherColsSorted
}
-data class Wonder(
- val name: String,
- val initialResource: ResourceType,
- val stages: List<WonderStage>,
- val image: String,
- val nbBuiltStages: Int,
- val buildability: WonderBuildability
-)
-
-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,
- buildability = computeBuildabilityBy(player)
-)
-
-data class WonderStage(
- val cardBack: CardBack?,
- val isBuilt: Boolean,
- val requirements: Requirements,
- val builtDuringLastMove: Boolean
-)
+internal fun InternalWonder.toApiWonder(player: Player, lastMove: Move?): ApiWonder =
+ ApiWonder(
+ name = name,
+ initialResource = initialResource,
+ stages = stages.map { it.toApiWonderStage(lastBuiltStage == it, lastMove) },
+ image = image,
+ nbBuiltStages = nbBuiltStages,
+ buildability = computeBuildabilityBy(player)
+ )
internal fun InternalWonderStage.toApiWonderStage(
isLastBuiltStage: Boolean,
lastMove: Move?
-): WonderStage =
- WonderStage(
- cardBack = cardBack,
- isBuilt = isBuilt,
- requirements = requirements,
- builtDuringLastMove = lastMove?.type == MoveType.UPGRADE_WONDER && isLastBuiltStage
- )
-
-data class ApiProduction(
- val fixedResources: List<ApiCountedResource>,
- val alternativeResources: Set<Set<ResourceType>>
+): ApiWonderStage = ApiWonderStage(
+ cardBack = cardBack,
+ isBuilt = isBuilt,
+ requirements = requirements.toApiRequirements(),
+ builtDuringLastMove = lastMove?.type == MoveType.UPGRADE_WONDER && isLastBuiltStage
)
internal fun Production.toApiProduction(): ApiProduction = ApiProduction(
@@ -95,29 +63,16 @@ internal fun Production.toApiProduction(): ApiProduction = ApiProduction(
alternativeResources = getAlternativeResources()
)
-data class ApiCountedResource(
- val count: Int,
- val type: ResourceType
+internal fun Requirements.toApiRequirements(): ApiRequirements = ApiRequirements(
+ gold = gold,
+ resources = resources.toCountedResourcesList()
)
internal fun Resources.toCountedResourcesList(): List<ApiCountedResource> =
quantities.map { (type, count) -> ApiCountedResource(count, type) }.sortedBy { it.type }
-data class ApiMilitary(
- var nbShields: Int,
- var totalPoints: Int,
- var nbDefeatTokens: Int
-)
-
internal fun Military.toApiMilitary(): ApiMilitary = ApiMilitary(nbShields, totalPoints, nbDefeatTokens)
-data class ApiScience(
- var jokers: Int,
- var nbWheels: Int,
- var nbCompasses: Int,
- var nbTablets: Int
-)
-
internal fun Science.toApiScience(): ApiScience = ApiScience(
jokers = jokers,
nbWheels = getQuantity(ScienceType.WHEEL),
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Cards.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Cards.kt
index c0e51ec5..7587d69a 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Cards.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Cards.kt
@@ -2,56 +2,30 @@ package org.luxons.sevenwonders.game.api
import org.luxons.sevenwonders.game.Player
import org.luxons.sevenwonders.game.cards.Card
-import org.luxons.sevenwonders.game.cards.CardBack
-import org.luxons.sevenwonders.game.cards.CardPlayability
-import org.luxons.sevenwonders.game.cards.Color
-import org.luxons.sevenwonders.game.cards.Requirements
+import org.luxons.sevenwonders.game.cards.HandCard
+import org.luxons.sevenwonders.game.cards.TableCard
import org.luxons.sevenwonders.game.moves.Move
-data class TableCard(
- val name: String,
- val color: Color,
- val requirements: Requirements,
- val chainParent: String?,
- val chainChildren: List<String>,
- val image: String,
- val back: CardBack,
- val playedDuringLastMove: Boolean
-)
+internal fun Card.toTableCard(lastMove: Move? = null): TableCard =
+ TableCard(
+ name = name,
+ color = color,
+ requirements = requirements.toApiRequirements(),
+ chainParent = chainParent,
+ chainChildren = chainChildren,
+ image = image,
+ back = back,
+ playedDuringLastMove = lastMove != null && this.name == lastMove.card.name
+ )
-internal fun Card.toTableCard(lastMove: Move? = null): TableCard = TableCard(
- name = name,
- color = color,
- requirements = requirements,
- chainParent = chainParent,
- chainChildren = chainChildren,
- image = image,
- back = back,
- playedDuringLastMove = lastMove != null && this.name == lastMove.card.name
-)
-
-/**
- * A card with contextual information relative to the hand it is sitting in. The extra information is especially useful
- * because it frees the client from a painful business logic implementation.
- */
-data class HandCard(
- val name: String,
- val color: Color,
- val requirements: Requirements,
- val chainParent: String?,
- val chainChildren: List<String>,
- val image: String,
- val back: CardBack,
- val playability: CardPlayability
-)
-
-internal fun Card.toHandCard(player: Player): HandCard = HandCard(
- name = name,
- color = color,
- requirements = requirements,
- chainParent = chainParent,
- chainChildren = chainChildren,
- image = image,
- back = back,
- playability = computePlayabilityBy(player)
-)
+internal fun Card.toHandCard(player: Player): HandCard =
+ HandCard(
+ name = name,
+ color = color,
+ requirements = requirements.toApiRequirements(),
+ chainParent = chainParent,
+ chainChildren = chainChildren,
+ image = image,
+ back = back,
+ playability = computePlayabilityBy(player)
+ )
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerMove.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerMove.kt
deleted file mode 100644
index 22cc36f0..00000000
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerMove.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.luxons.sevenwonders.game.api
-
-import org.luxons.sevenwonders.game.moves.MoveType
-import org.luxons.sevenwonders.game.resources.ResourceTransactions
-import org.luxons.sevenwonders.game.resources.noTransactions
-
-data class PlayerMove(
- val type: MoveType,
- val cardName: String,
- val transactions: ResourceTransactions = noTransactions()
-)
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 c44f0a4c..de6e587d 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,22 +1,9 @@
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
-import org.luxons.sevenwonders.game.moves.MoveType
-import org.luxons.sevenwonders.game.resources.ResourceTransactions
import org.luxons.sevenwonders.game.boards.Table as InternalTable
-data class Table(
- val boards: List<Board>,
- val currentAge: Age,
- val handRotationDirection: HandRotationDirection,
- val lastPlayedMoves: List<PlayedMove>
-) {
- val nbPlayers: Int = boards.size
-}
-
internal fun InternalTable.toApiTable(): Table = Table(
boards = boards.mapIndexed { i, b -> b.toApiBoard(SimplePlayer(i, this), lastPlayedMoves.getOrNull(i)) },
currentAge = currentAge,
@@ -24,13 +11,6 @@ internal fun InternalTable.toApiTable(): Table = Table(
lastPlayedMoves = lastPlayedMoves.map { it.toPlayedMove() }
)
-data class PlayedMove(
- val playerIndex: Int,
- val type: MoveType,
- val card: TableCard,
- val transactions: ResourceTransactions
-)
-
internal fun Move.toPlayedMove(): PlayedMove = PlayedMove(
playerIndex = playerContext.index,
type = type,
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Board.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Board.kt
index 04dd2d25..a43b8a3c 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Board.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Board.kt
@@ -2,9 +2,9 @@ package org.luxons.sevenwonders.game.boards
import org.luxons.sevenwonders.game.Player
import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.Age
import org.luxons.sevenwonders.game.cards.Card
import org.luxons.sevenwonders.game.cards.Color
-import org.luxons.sevenwonders.game.data.Age
import org.luxons.sevenwonders.game.effects.SpecialAbility
import org.luxons.sevenwonders.game.resources.Production
import org.luxons.sevenwonders.game.resources.TradingRules
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Military.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Military.kt
index c482c596..98404d94 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Military.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Military.kt
@@ -1,6 +1,6 @@
package org.luxons.sevenwonders.game.boards
-import org.luxons.sevenwonders.game.data.Age
+import org.luxons.sevenwonders.game.api.Age
internal class Military(
private val lostPointsPerDefeat: Int,
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Table.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Table.kt
index 6a0980c4..168649f4 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Table.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Table.kt
@@ -1,9 +1,9 @@
package org.luxons.sevenwonders.game.boards
+import org.luxons.sevenwonders.game.api.Age
import org.luxons.sevenwonders.game.cards.Card
import org.luxons.sevenwonders.game.cards.Color
import org.luxons.sevenwonders.game.cards.HandRotationDirection
-import org.luxons.sevenwonders.game.data.Age
import org.luxons.sevenwonders.game.moves.Move
/**
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 18d9cb96..b983aa0e 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
@@ -6,8 +6,6 @@ import org.luxons.sevenwonders.game.effects.Effect
import org.luxons.sevenwonders.game.resources.ResourceTransactions
import org.luxons.sevenwonders.game.resources.noTransactions
-data class CardBack(val image: String)
-
internal data class Card(
val name: String,
val color: Color,
@@ -19,9 +17,9 @@ internal data class Card(
val back: CardBack
) {
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.assess(player))
+ isAlreadyOnBoard(player.board) -> Playability.incompatibleWithBoard() // cannot play twice the same card
+ isParentOnBoard(player.board) -> Playability.chainable()
+ else -> Playability.requirementDependent(requirements.assess(player))
}
fun isPlayableOnBoardWith(board: Board, transactions: ResourceTransactions) =
@@ -41,46 +39,26 @@ internal data class Card(
}
}
-enum class Color(val isResource: Boolean) {
- BROWN(true),
- GREY(true),
- YELLOW(false),
- BLUE(false),
- GREEN(false),
- RED(false),
- PURPLE(false)
-}
-
-data class CardPlayability(
- val isPlayable: Boolean,
- 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 {
+private object Playability {
- 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,
- isChainable = true,
- minPrice = 0,
- cheapestTransactions = setOf(noTransactions()),
- playabilityLevel = PlayabilityLevel.CHAINABLE
- )
+ internal fun chainable(): CardPlayability = CardPlayability(
+ isPlayable = true,
+ isChainable = true,
+ minPrice = 0,
+ cheapestTransactions = setOf(noTransactions()),
+ playabilityLevel = PlayabilityLevel.CHAINABLE
+ )
- internal fun requirementDependent(satisfaction: RequirementsSatisfaction): CardPlayability = CardPlayability(
- isPlayable = satisfaction.satisfied,
- isChainable = false,
- minPrice = satisfaction.minPrice,
- cheapestTransactions = satisfaction.cheapestTransactions,
- playabilityLevel = satisfaction.level
- )
- }
+ internal fun requirementDependent(satisfaction: RequirementsSatisfaction): CardPlayability = CardPlayability(
+ isPlayable = satisfaction.satisfied,
+ isChainable = false,
+ minPrice = satisfaction.minPrice,
+ cheapestTransactions = satisfaction.cheapestTransactions,
+ playabilityLevel = satisfaction.level
+ )
}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Hands.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Hands.kt
index 0a81db5f..19490b9c 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Hands.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Hands.kt
@@ -1,7 +1,6 @@
package org.luxons.sevenwonders.game.cards
import org.luxons.sevenwonders.game.Player
-import org.luxons.sevenwonders.game.api.HandCard
import org.luxons.sevenwonders.game.api.toHandCard
internal class Hands(private val hands: List<List<Card>>) {
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/RequirementsSatisfaction.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/RequirementsSatisfaction.kt
index 7f21a9fd..87b35723 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/RequirementsSatisfaction.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/RequirementsSatisfaction.kt
@@ -3,19 +3,6 @@ package org.luxons.sevenwonders.game.cards
import org.luxons.sevenwonders.game.resources.ResourceTransactions
import org.luxons.sevenwonders.game.resources.noTransactions
-enum class PlayabilityLevel {
- CHAINABLE,
- NO_REQUIREMENTS,
- ENOUGH_RESOURCES,
- ENOUGH_GOLD,
- ENOUGH_GOLD_AND_RES,
- REQUIRES_HELP,
- MISSING_REQUIRED_GOLD,
- MISSING_GOLD_FOR_RES,
- UNAVAILABLE_RESOURCES,
- INCOMPATIBLE_WITH_BOARD
-}
-
internal data class RequirementsSatisfaction(
val satisfied: Boolean,
val level: PlayabilityLevel,
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinition.kt
index 5a3c097f..43c48aa7 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinition.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GameDefinition.kt
@@ -5,6 +5,7 @@ import com.google.gson.Gson
import com.google.gson.GsonBuilder
import org.luxons.sevenwonders.game.Game
import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.Age
import org.luxons.sevenwonders.game.api.CustomizableSettings
import org.luxons.sevenwonders.game.boards.Board
import org.luxons.sevenwonders.game.data.definitions.DecksDefinition
@@ -25,8 +26,6 @@ import org.luxons.sevenwonders.game.resources.Production
import org.luxons.sevenwonders.game.resources.ResourceType
import org.luxons.sevenwonders.game.resources.Resources
-typealias Age = Int
-
internal const val LAST_AGE: Age = 3
internal data class GlobalRules(
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt
index 20477266..b090547d 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt
@@ -3,7 +3,7 @@ package org.luxons.sevenwonders.game.data.definitions
import org.luxons.sevenwonders.game.cards.Card
import org.luxons.sevenwonders.game.cards.CardBack
import org.luxons.sevenwonders.game.cards.Decks
-import java.util.Random
+import kotlin.random.Random
internal class DeckDefinition(
val cards: List<CardDefinition>,
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.kt
index 742cc5ae..fb0eccda 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/WonderDefinition.kt
@@ -1,15 +1,11 @@
package org.luxons.sevenwonders.game.data.definitions
+import org.luxons.sevenwonders.game.api.WonderSide
import org.luxons.sevenwonders.game.cards.Requirements
import org.luxons.sevenwonders.game.resources.ResourceType
import org.luxons.sevenwonders.game.wonders.Wonder
import org.luxons.sevenwonders.game.wonders.WonderStage
-enum class WonderSide {
- A,
- B
-}
-
internal class WonderDefinition(
private val name: String,
private val sides: Map<WonderSide, WonderSideDefinition>
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt
index 1ac68d27..98a96fd9 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt
@@ -23,3 +23,11 @@ internal abstract class Move(
class InvalidMoveException internal constructor(move: Move, message: String) : IllegalArgumentException(
"Player ${move.playerContext.index} cannot perform move ${move.type}: $message"
)
+
+internal fun MoveType.resolve(move: PlayerMove, card: Card, context: PlayerContext): Move = when (this) {
+ MoveType.PLAY -> PlayCardMove(move, card, context)
+ MoveType.PLAY_FREE -> PlayFreeCardMove(move, card, context)
+ MoveType.UPGRADE_WONDER -> BuildWonderMove(move, card, context)
+ MoveType.DISCARD -> DiscardMove(move, card, context)
+ MoveType.COPY_GUILD -> CopyGuildMove(move, card, context)
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt
deleted file mode 100644
index 8062e212..00000000
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.luxons.sevenwonders.game.moves
-
-import org.luxons.sevenwonders.game.PlayerContext
-import org.luxons.sevenwonders.game.api.PlayerMove
-import org.luxons.sevenwonders.game.cards.Card
-
-enum class MoveType(private val create: (move: PlayerMove, card: Card, context: PlayerContext) -> Move) {
- PLAY(::PlayCardMove),
- PLAY_FREE(::PlayFreeCardMove),
- UPGRADE_WONDER(::BuildWonderMove),
- DISCARD(::DiscardMove),
- COPY_GUILD(::CopyGuildMove);
-
- internal fun resolve(move: PlayerMove, card: Card, context: PlayerContext): Move = create(move, card, context)
-}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt
index 60d57e44..4a3a483c 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt
@@ -1,26 +1,29 @@
package org.luxons.sevenwonders.game.resources
import org.luxons.sevenwonders.game.Player
+import org.luxons.sevenwonders.game.api.ApiCountedResource
+import org.luxons.sevenwonders.game.api.toCountedResourcesList
-typealias ResourceTransactions = Collection<ResourceTransaction>
+fun Map<Provider, Resources>.toTransactions(): ResourceTransactions =
+ filterValues { !it.isEmpty() }
+ .map { (p, res) -> ResourceTransaction(p, res.toCountedResourcesList()) }
+ .toSet()
-fun noTransactions(): ResourceTransactions = emptySet()
+fun ResourceTransactions.asResources(): Resources = flatMap { it.resources }.asResources()
-fun Map<Provider, Resources>.toTransactions(): ResourceTransactions =
- filterValues { !it.isEmpty() }.map { (p, res) -> ResourceTransaction(p, res) }.toSet()
+fun ResourceTransaction.asResources(): Resources = resources.asResources()
-fun ResourceTransactions.asResources(): Resources = map { it.resources }.merge()
+fun List<ApiCountedResource>.asResources(): Resources = map { it.asResources() }.merge()
-internal fun ResourceTransactions.execute(player: Player) = forEach { it.execute(player) }
+fun ApiCountedResource.asResources(): Resources = resourcesOf(type to count)
-data class ResourceTransaction(val provider: Provider, val resources: Resources) {
+internal fun ResourceTransactions.execute(player: Player) = forEach { it.execute(player) }
- internal fun execute(player: Player) {
- val board = player.board
- val price = board.tradingRules.computeCost(this)
- board.removeGold(price)
- val providerPosition = provider.boardPosition
- val providerBoard = player.getBoard(providerPosition)
- providerBoard.addGold(price)
- }
+internal fun ResourceTransaction.execute(player: Player) {
+ val board = player.board
+ val price = board.tradingRules.computeCost(this)
+ board.removeGold(price)
+ val providerPosition = provider.boardPosition
+ val providerBoard = player.getBoard(providerPosition)
+ providerBoard.addGold(price)
}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt
index 3b3c81ea..a006fadf 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt
@@ -17,7 +17,7 @@ class TradingRules internal constructor(private val defaultCost: Int) {
internal fun computeCost(transactions: ResourceTransactions): Int = transactions.map { computeCost(it) }.sum()
- internal fun computeCost(transact: ResourceTransaction) = computeCost(transact.resources, transact.provider)
+ internal fun computeCost(transact: ResourceTransaction) = computeCost(transact.asResources(), transact.provider)
private fun computeCost(resources: Resources, provider: Provider): Int =
resources.quantities.map { (type, qty) -> getCost(type, provider) * qty }.sum()
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 5e1cece0..fc2e8676 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
@@ -30,9 +30,9 @@ internal class Wonder(
fun computeBuildabilityBy(player: Player): WonderBuildability {
if (nbBuiltStages == stages.size) {
- return WonderBuildability.alreadyBuilt()
+ return Buildability.alreadyBuilt()
}
- return WonderBuildability.requirementDependent(nextStage.requirements.assess(player))
+ return Buildability.requirementDependent(nextStage.requirements.assess(player))
}
fun isNextStageBuildable(board: Board, boughtResources: ResourceTransactions): Boolean =
@@ -47,26 +47,16 @@ internal class Wonder(
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 {
+private object Buildability {
- fun alreadyBuilt() = WonderBuildability(
- isBuildable = false,
- playabilityLevel = PlayabilityLevel.INCOMPATIBLE_WITH_BOARD
- )
+ 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
- )
- }
+ 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 7b5b9411..a63ccdd6 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
@@ -2,11 +2,11 @@ package org.luxons.sevenwonders.game
import org.junit.Test
import org.luxons.sevenwonders.game.api.Action
-import org.luxons.sevenwonders.game.api.HandCard
+import org.luxons.sevenwonders.game.cards.HandCard
import org.luxons.sevenwonders.game.api.PlayedMove
import org.luxons.sevenwonders.game.api.PlayerMove
import org.luxons.sevenwonders.game.api.PlayerTurnInfo
-import org.luxons.sevenwonders.game.api.TableCard
+import org.luxons.sevenwonders.game.cards.TableCard
import org.luxons.sevenwonders.game.data.GameDefinition
import org.luxons.sevenwonders.game.data.LAST_AGE
import org.luxons.sevenwonders.game.moves.MoveType
@@ -110,5 +110,14 @@ class GameTest {
)
private fun HandCard.toPlayedCard(): TableCard =
- TableCard(name, color, requirements, chainParent, chainChildren, image, back, true)
+ TableCard(
+ name,
+ color,
+ requirements,
+ chainParent,
+ chainChildren,
+ image,
+ back,
+ true
+ )
}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/api/BoardsKtTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/api/BoardsKtTest.kt
index bbba2422..244c30a8 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/api/BoardsKtTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/api/BoardsKtTest.kt
@@ -1,6 +1,7 @@
package org.luxons.sevenwonders.game.api
import org.luxons.sevenwonders.game.cards.Color
+import org.luxons.sevenwonders.game.cards.TableCard
import org.luxons.sevenwonders.game.test.testCard
import kotlin.test.Test
import kotlin.test.assertEquals
diff --git a/game-model/build.gradle b/game-model/build.gradle
new file mode 100644
index 00000000..4656b652
--- /dev/null
+++ b/game-model/build.gradle
@@ -0,0 +1,47 @@
+plugins {
+ id 'kotlin-multiplatform'
+}
+
+kotlin {
+ jvm()
+ js()
+ mingwX64("mingw")
+ sourceSets {
+ commonMain {
+ dependencies {
+ implementation kotlin('stdlib-common')
+ }
+ }
+ commonTest {
+ dependencies {
+ implementation kotlin('test-common')
+ implementation kotlin('test-annotations-common')
+ }
+ }
+ jvmMain {
+ dependencies {
+ implementation kotlin('stdlib-jdk8')
+ }
+ }
+ jvmTest {
+ dependencies {
+ implementation kotlin('test')
+ implementation kotlin('test-junit')
+ }
+ }
+ jsMain {
+ dependencies {
+ implementation kotlin('stdlib-js')
+ }
+ }
+ jsTest {
+ dependencies {
+ implementation kotlin('test-js')
+ }
+ }
+ mingwMain {
+ }
+ mingwTest {
+ }
+ }
+} \ No newline at end of file
diff --git a/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/Boards.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/Boards.kt
new file mode 100644
index 00000000..698615e9
--- /dev/null
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/Boards.kt
@@ -0,0 +1,44 @@
+package org.luxons.sevenwonders.game.api
+
+import org.luxons.sevenwonders.game.cards.TableCard
+import org.luxons.sevenwonders.game.resources.ResourceType
+import org.luxons.sevenwonders.game.wonders.ApiWonder
+
+data class Board(
+ val playerIndex: Int,
+ val wonder: ApiWonder,
+ val production: ApiProduction,
+ val publicProduction: ApiProduction,
+ val science: ApiScience,
+ val military: ApiMilitary,
+ val playedCards: List<List<TableCard>>,
+ val gold: Int
+)
+
+data class ApiRequirements(
+ val gold: Int = 0,
+ val resources: List<ApiCountedResource> = emptyList()
+)
+
+data class ApiProduction(
+ val fixedResources: List<ApiCountedResource>,
+ val alternativeResources: Set<Set<ResourceType>>
+)
+
+data class ApiCountedResource(
+ val count: Int,
+ val type: ResourceType
+)
+
+data class ApiMilitary(
+ val nbShields: Int,
+ val totalPoints: Int,
+ val nbDefeatTokens: Int
+)
+
+data class ApiScience(
+ val jokers: Int,
+ val nbWheels: Int,
+ val nbCompasses: Int,
+ val nbTablets: Int
+)
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt
index eb72f971..ac2c2b14 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/CustomizableSettings.kt
@@ -1,7 +1,6 @@
package org.luxons.sevenwonders.game.api
-import org.luxons.sevenwonders.game.data.definitions.WonderSide
-import java.util.Random
+import kotlin.random.Random
data class CustomizableSettings(
val randomSeedForTests: Long? = null,
@@ -15,6 +14,11 @@ data class CustomizableSettings(
val wonPointsPerVictoryPerAge: Map<Int, Int> = mapOf(1 to 1, 2 to 3, 3 to 5)
)
+enum class WonderSide {
+ A,
+ B
+}
+
enum class WonderSidePickMethod {
ALL_A {
override fun pickSide(random: Random, lastPickedSide: WonderSide?): WonderSide {
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerTurnInfo.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/PlayerTurnInfo.kt
index 1eefba81..c5feb6c5 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerTurnInfo.kt
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/PlayerTurnInfo.kt
@@ -1,5 +1,10 @@
package org.luxons.sevenwonders.game.api
+import org.luxons.sevenwonders.game.cards.HandCard
+import org.luxons.sevenwonders.game.cards.TableCard
+import org.luxons.sevenwonders.game.moves.MoveType
+import org.luxons.sevenwonders.game.resources.ResourceTransactions
+import org.luxons.sevenwonders.game.resources.noTransactions
import org.luxons.sevenwonders.game.wonders.WonderBuildability
enum class Action(val message: String) {
@@ -10,7 +15,7 @@ enum class Action(val message: String) {
WAIT("Please wait for other players to perform extra actions.")
}
-data class PlayerTurnInfo internal constructor(
+data class PlayerTurnInfo(
val playerIndex: Int,
val table: Table,
val action: Action,
@@ -22,3 +27,9 @@ data class PlayerTurnInfo internal constructor(
val message: String = action.message
val wonderBuildability: WonderBuildability = table.boards[playerIndex].wonder.buildability
}
+
+data class PlayerMove(
+ val type: MoveType,
+ val cardName: String,
+ val transactions: ResourceTransactions = noTransactions()
+)
diff --git a/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/Table.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/Table.kt
new file mode 100644
index 00000000..23ab6ee2
--- /dev/null
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/api/Table.kt
@@ -0,0 +1,24 @@
+package org.luxons.sevenwonders.game.api
+
+import org.luxons.sevenwonders.game.cards.HandRotationDirection
+import org.luxons.sevenwonders.game.cards.TableCard
+import org.luxons.sevenwonders.game.moves.MoveType
+import org.luxons.sevenwonders.game.resources.ResourceTransactions
+
+typealias Age = Int
+
+data class Table(
+ val boards: List<Board>,
+ val currentAge: Age,
+ val handRotationDirection: HandRotationDirection,
+ val lastPlayedMoves: List<PlayedMove>
+) {
+ val nbPlayers: Int = boards.size
+}
+
+data class PlayedMove(
+ val playerIndex: Int,
+ val type: MoveType,
+ val card: TableCard,
+ val transactions: ResourceTransactions
+)
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt
index c89205c0..3a8387a3 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt
@@ -5,7 +5,12 @@ enum class RelativeBoardPosition(private val offset: Int) {
SELF(0),
RIGHT(1);
- fun getIndexFrom(playerIndex: Int, nbPlayers: Int): Int = Math.floorMod(playerIndex + offset, nbPlayers)
+ fun getIndexFrom(playerIndex: Int, nbPlayers: Int): Int = (playerIndex + offset) floorMod nbPlayers
}
fun neighboursPositions() = listOf(RelativeBoardPosition.LEFT, RelativeBoardPosition.RIGHT)
+
+private infix fun Int.floorMod(divisor: Int): Int {
+ val rem = this % divisor
+ return if (rem >= 0) rem else rem + divisor
+}
diff --git a/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt
new file mode 100644
index 00000000..ab0e0297
--- /dev/null
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt
@@ -0,0 +1,65 @@
+package org.luxons.sevenwonders.game.cards
+
+import org.luxons.sevenwonders.game.api.ApiRequirements
+import org.luxons.sevenwonders.game.resources.ResourceTransactions
+
+data class TableCard(
+ val name: String,
+ val color: Color,
+ val requirements: ApiRequirements,
+ val chainParent: String?,
+ val chainChildren: List<String>,
+ val image: String,
+ val back: CardBack,
+ val playedDuringLastMove: Boolean
+)
+
+/**
+ * A card with contextual information relative to the hand it is sitting in. The extra information is especially useful
+ * because it frees the client from a painful business logic implementation.
+ */
+data class HandCard(
+ val name: String,
+ val color: Color,
+ val requirements: ApiRequirements,
+ val chainParent: String?,
+ val chainChildren: List<String>,
+ val image: String,
+ val back: CardBack,
+ val playability: CardPlayability
+)
+
+data class CardBack(val image: String)
+
+enum class PlayabilityLevel {
+ CHAINABLE,
+ NO_REQUIREMENTS,
+ ENOUGH_RESOURCES,
+ ENOUGH_GOLD,
+ ENOUGH_GOLD_AND_RES,
+ REQUIRES_HELP,
+ MISSING_REQUIRED_GOLD,
+ MISSING_GOLD_FOR_RES,
+ UNAVAILABLE_RESOURCES,
+ INCOMPATIBLE_WITH_BOARD
+}
+
+enum class Color(val isResource: Boolean) {
+ BROWN(true),
+ GREY(true),
+ YELLOW(false),
+ BLUE(false),
+ GREEN(false),
+ RED(false),
+ PURPLE(false)
+}
+
+data class CardPlayability(
+ val isPlayable: Boolean,
+ val isChainable: Boolean = false,
+ val minPrice: Int = Int.MAX_VALUE,
+ val cheapestTransactions: Set<ResourceTransactions> = emptySet(),
+ val playabilityLevel: PlayabilityLevel
+) {
+ val isFree: Boolean = minPrice == 0
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/HandRotationDirection.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/cards/HandRotationDirection.kt
index a10ec19f..a10ec19f 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/HandRotationDirection.kt
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/cards/HandRotationDirection.kt
diff --git a/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt
new file mode 100644
index 00000000..d982c100
--- /dev/null
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt
@@ -0,0 +1,9 @@
+package org.luxons.sevenwonders.game.moves
+
+enum class MoveType {
+ PLAY,
+ PLAY_FREE,
+ UPGRADE_WONDER,
+ DISCARD,
+ COPY_GUILD;
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Provider.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/Provider.kt
index 5d0f3159..5d0f3159 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Provider.kt
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/Provider.kt
diff --git a/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt
new file mode 100644
index 00000000..77a8670d
--- /dev/null
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt
@@ -0,0 +1,9 @@
+package org.luxons.sevenwonders.game.resources
+
+import org.luxons.sevenwonders.game.api.ApiCountedResource
+
+typealias ResourceTransactions = Collection<ResourceTransaction>
+
+data class ResourceTransaction(val provider: Provider, val resources: List<ApiCountedResource>)
+
+fun noTransactions(): ResourceTransactions = emptySet()
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceType.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/ResourceType.kt
index 5c92b887..5c92b887 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceType.kt
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/resources/ResourceType.kt
diff --git a/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt
new file mode 100644
index 00000000..6480e935
--- /dev/null
+++ b/game-model/src/commonMain/kotlin/org/luxons/sevenwonders/game/wonders/Wonder.kt
@@ -0,0 +1,32 @@
+package org.luxons.sevenwonders.game.wonders
+
+import org.luxons.sevenwonders.game.api.ApiRequirements
+import org.luxons.sevenwonders.game.cards.CardBack
+import org.luxons.sevenwonders.game.cards.PlayabilityLevel
+import org.luxons.sevenwonders.game.resources.ResourceTransactions
+import org.luxons.sevenwonders.game.resources.ResourceType
+
+data class ApiWonder(
+ val name: String,
+ val initialResource: ResourceType,
+ val stages: List<ApiWonderStage>,
+ val image: String,
+ val nbBuiltStages: Int,
+ val buildability: WonderBuildability
+)
+
+data class ApiWonderStage(
+ val cardBack: CardBack?,
+ val isBuilt: Boolean,
+ val requirements: ApiRequirements,
+ val builtDuringLastMove: Boolean
+)
+
+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
+}
diff --git a/settings.gradle b/settings.gradle
index c6e5be16..ca2127cc 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,5 +1,18 @@
+pluginManagement {
+ resolutionStrategy {
+ eachPlugin {
+ if (requested.id.id == "kotlin-multiplatform") {
+ useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
+ }
+ }
+ }
+}
+
rootProject.name = "seven-wonders"
include 'frontend'
include 'backend'
include 'game-engine'
+include 'game-model'
+
+enableFeaturePreview('GRADLE_METADATA')
bgstack15