diff options
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') |