summaryrefslogtreecommitdiff
path: root/game-engine/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'game-engine/src/main/kotlin')
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt3
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Board.kt99
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/BoardElementType.kt17
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Military.kt33
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt25
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Science.kt56
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GlobalRules.kt4
7 files changed, 235 insertions, 2 deletions
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 60287c84..2c2e5066 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
@@ -5,6 +5,7 @@ import org.luxons.sevenwonders.game.boards.RelativeBoardPosition
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
import org.luxons.sevenwonders.game.resources.Provider
@@ -16,7 +17,7 @@ class Table(val boards: List<Board>) {
val nbPlayers: Int = boards.size
- var currentAge = 0
+ var currentAge: Age = 0
private set
val handRotationDirection: HandRotationDirection
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
new file mode 100644
index 00000000..b02777e5
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Board.kt
@@ -0,0 +1,99 @@
+package org.luxons.sevenwonders.game.boards
+
+import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.Table
+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
+import org.luxons.sevenwonders.game.scoring.PlayerScore
+import org.luxons.sevenwonders.game.scoring.ScoreCategory
+import org.luxons.sevenwonders.game.wonders.Wonder
+
+class Board(val wonder: Wonder, val playerIndex: Int, settings: Settings) {
+
+ val production = Production()
+ val publicProduction = Production()
+ val science = Science()
+ val tradingRules: TradingRules = TradingRules(settings.defaultTradingCost)
+ val military: Military = Military(settings.lostPointsPerDefeat, settings.wonPointsPerVictoryPerAge)
+ private val pointsPer3Gold: Int = settings.pointsPer3Gold
+
+ private val playedCards: MutableList<Card> = arrayListOf()
+ private val specialAbilities: MutableSet<SpecialAbility> = hashSetOf()
+ private val consumedFreeCards: MutableMap<Age, Boolean> = mutableMapOf()
+
+ var gold: Int = settings.initialGold
+
+ var copiedGuild: Card? = null
+ set(copiedGuild) {
+ if (copiedGuild!!.color !== Color.PURPLE) {
+ throw IllegalArgumentException("The given card '$copiedGuild' is not a Guild card")
+ }
+ field = copiedGuild
+ }
+
+ init {
+ this.production.addFixedResource(wonder.initialResource, 1)
+ this.publicProduction.addFixedResource(wonder.initialResource, 1)
+ }
+
+ fun getPlayedCards(): List<Card> = playedCards
+
+ fun addCard(card: Card) {
+ playedCards.add(card)
+ }
+
+ internal fun getNbCardsOfColor(colorFilter: List<Color>): Int = playedCards.count { colorFilter.contains(it.color) }
+
+ fun isPlayed(cardName: String): Boolean = playedCards.count { it.name == cardName } > 0
+
+ fun addGold(amount: Int) {
+ this.gold += amount
+ }
+
+ fun removeGold(amount: Int) {
+ if (gold < amount) {
+ throw InsufficientFundsException(gold, amount)
+ }
+ this.gold -= amount
+ }
+
+ fun addSpecial(specialAbility: SpecialAbility) {
+ specialAbilities.add(specialAbility)
+ }
+
+ fun hasSpecial(specialAbility: SpecialAbility): Boolean = specialAbilities.contains(specialAbility)
+
+ fun canPlayFreeCard(age: Age): Boolean =
+ hasSpecial(SpecialAbility.ONE_FREE_PER_AGE) && !consumedFreeCards.getOrDefault(age, false)
+
+ fun consumeFreeCard(age: Age) {
+ consumedFreeCards[age] = true
+ }
+
+ fun computePoints(table: Table): PlayerScore {
+ val score = PlayerScore(gold)
+ score.put(ScoreCategory.CIVIL, computePointsForCards(table, Color.BLUE))
+ score.put(ScoreCategory.MILITARY, military.totalPoints)
+ score.put(ScoreCategory.SCIENCE, science.computePoints())
+ score.put(ScoreCategory.TRADE, computePointsForCards(table, Color.YELLOW))
+ score.put(ScoreCategory.GUILD, computePointsForCards(table, Color.PURPLE))
+ score.put(ScoreCategory.WONDER, wonder.computePoints(table, playerIndex))
+ score.put(ScoreCategory.GOLD, computeGoldPoints())
+ return score
+ }
+
+ private fun computePointsForCards(table: Table, color: Color): Int = playedCards
+ .filter { (_, color1) -> color1 === color }
+ .flatMap { (_, _, _, effects) -> effects }
+ .map { e -> e.computePoints(table, playerIndex) }
+ .sum()
+
+ private fun computeGoldPoints(): Int = gold / 3 * pointsPer3Gold
+
+ internal class InsufficientFundsException(current: Int, required: Int) :
+ RuntimeException(String.format("Current balance is %d gold, but %d are required", current, required))
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/BoardElementType.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/BoardElementType.kt
new file mode 100644
index 00000000..d35e9777
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/BoardElementType.kt
@@ -0,0 +1,17 @@
+package org.luxons.sevenwonders.game.boards
+
+import org.luxons.sevenwonders.game.cards.Color
+
+enum class BoardElementType {
+ CARD {
+ override fun getElementCount(board: Board, colors: List<Color>?): Int = board.getNbCardsOfColor(colors!!)
+ },
+ BUILT_WONDER_STAGES {
+ override fun getElementCount(board: Board, colors: List<Color>?): Int = board.wonder.nbBuiltStages
+ },
+ DEFEAT_TOKEN {
+ override fun getElementCount(board: Board, colors: List<Color>?): Int = board.military.nbDefeatTokens
+ };
+
+ abstract fun getElementCount(board: Board, colors: List<Color>?): Int
+}
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
new file mode 100644
index 00000000..c00d1ace
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Military.kt
@@ -0,0 +1,33 @@
+package org.luxons.sevenwonders.game.boards
+
+import org.luxons.sevenwonders.game.data.Age
+
+class Military internal constructor(
+ private val lostPointsPerDefeat: Int,
+ private val wonPointsPerVictoryPerAge: Map<Age, Int>
+) {
+ var nbShields = 0
+ private set
+
+ var totalPoints = 0
+ private set
+
+ var nbDefeatTokens = 0
+ private set
+
+ fun addShields(nbShields: Int) {
+ this.nbShields += nbShields
+ }
+
+ fun victory(age: Age) {
+ val wonPoints = wonPointsPerVictoryPerAge[age] ?: throw UnknownAgeException(age)
+ totalPoints += wonPoints
+ }
+
+ fun defeat() {
+ totalPoints -= lostPointsPerDefeat
+ nbDefeatTokens++
+ }
+
+ internal class UnknownAgeException(unknownAge: Age) : IllegalArgumentException(unknownAge.toString())
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt
new file mode 100644
index 00000000..fcd629ec
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/RelativeBoardPosition.kt
@@ -0,0 +1,25 @@
+package org.luxons.sevenwonders.game.boards
+
+enum class RelativeBoardPosition {
+ LEFT {
+ override fun getIndexFrom(playerIndex: Int, nbPlayers: Int): Int {
+ return wrapIndex(playerIndex - 1, nbPlayers)
+ }
+ },
+ SELF {
+ override fun getIndexFrom(playerIndex: Int, nbPlayers: Int): Int {
+ return playerIndex
+ }
+ },
+ RIGHT {
+ override fun getIndexFrom(playerIndex: Int, nbPlayers: Int): Int {
+ return wrapIndex(playerIndex + 1, nbPlayers)
+ }
+ };
+
+ abstract fun getIndexFrom(playerIndex: Int, nbPlayers: Int): Int
+
+ internal fun wrapIndex(index: Int, nbPlayers: Int): Int {
+ return Math.floorMod(index, nbPlayers)
+ }
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Science.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Science.kt
new file mode 100644
index 00000000..839986e0
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/boards/Science.kt
@@ -0,0 +1,56 @@
+package org.luxons.sevenwonders.game.boards
+
+enum class ScienceType {
+ COMPASS,
+ WHEEL,
+ TABLET
+}
+
+class Science {
+
+ private val quantities : MutableMap<ScienceType, Int> = mutableMapOf()
+
+ var jokers: Int = 0
+ private set
+
+ fun size(): Int = quantities.values.sum() + jokers
+
+ fun add(type: ScienceType, quantity: Int) {
+ quantities.merge(type, quantity) { x, y -> x + y }
+ }
+
+ fun addJoker(quantity: Int) {
+ jokers += quantity
+ }
+
+ fun addAll(science: Science) {
+ science.quantities.forEach { type, quantity -> this.add(type, quantity) }
+ jokers += science.jokers
+ }
+
+ fun getQuantity(type: ScienceType): Int = quantities.getOrDefault(type, 0)
+
+ fun computePoints(): Int {
+ val values = ScienceType.values().map(::getQuantity).toMutableList()
+ return computePoints(values, jokers)
+ }
+
+ private fun computePoints(values: MutableList<Int>, jokers: Int): Int {
+ if (jokers == 0) {
+ return computePointsNoJoker(values)
+ }
+ var maxPoints = 0
+ for (i in values.indices) {
+ values[i]++
+ maxPoints = Math.max(maxPoints, computePoints(values, jokers - 1))
+ values[i]--
+ }
+ return maxPoints
+ }
+
+ private fun computePointsNoJoker(values: List<Int>): Int {
+ val independentSquaresSum = values.map { i -> i * i }.sum()
+ val nbGroupsOfAll = values.min() ?: 0
+ return independentSquaresSum + nbGroupsOfAll * 7
+ }
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GlobalRules.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GlobalRules.kt
index 49212ab2..a590efc9 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GlobalRules.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/GlobalRules.kt
@@ -1,6 +1,8 @@
package org.luxons.sevenwonders.game.data
-const val LAST_AGE: Int = 3
+typealias Age = Int
+
+const val LAST_AGE: Age = 3
internal data class GlobalRules(
val minPlayers: Int,
bgstack15