Skip to content

Commit 1d2bf6c

Browse files
committed
Finished game backend
1 parent 73411ec commit 1d2bf6c

File tree

1 file changed

+69
-4
lines changed

1 file changed

+69
-4
lines changed

games-core/src/main/kotlin/net/zomis/games/impl/SpiceRoad.kt

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
package net.zomis.games.impl
22

33
import net.zomis.games.cards.CardZone
4+
import net.zomis.games.common.next
45
import net.zomis.games.dsl.*
56
import kotlin.math.absoluteValue
67

78
object SpiceRoadDsl {
89
data class PlayParameter(val card: SpiceRoadGameModel.ActionCard, val remove: SpiceRoadGameModel.Caravan, val add: SpiceRoadGameModel.Caravan)
10+
data class AcquireParameter(val card: SpiceRoadGameModel.ActionCard, val payArray: List<SpiceRoadGameModel.Spice>)
911

1012
val factory = GameCreator(SpiceRoadGameModel::class)
1113
val play = factory.action("play", PlayParameter::class)
1214
val claim = factory.action("claim", SpiceRoadGameModel.PointCard::class)
1315
val rest = factory.action("rest", Unit::class)
14-
val acquire = factory.action("acquire", SpiceRoadGameModel.ActionCard::class)
16+
val acquire = factory.action("acquire", AcquireParameter::class)
1517
val game = factory.game("Spice Road") {
1618
this.setup {
1719
this.players(2..5)
@@ -33,8 +35,10 @@ object SpiceRoadDsl {
3335
this.view("silverCoins") { game.silverCoins.size }
3436
this.action(claim).requires { game.currentPlayer.caravan.has(this.action.parameter.cost) }
3537
this.action(claim).effect {
38+
//TODO add gold and silver logic
3639
game.currentPlayer.caravan -= this.action.parameter.cost
3740
game.currentPlayer.points += this.action.parameter.points
41+
game.currentPlayer.pointCards++
3842
game.visiblePointCards.card(this.action.parameter).remove()
3943
if (game.pointsDeck.size > 0) {
4044
game.pointsDeck.random(this.replayable, 1, "NewPointCard") { it.toStateString() }.forEach { it.moveTo(game.visiblePointCards) }
@@ -54,7 +58,8 @@ object SpiceRoadDsl {
5458
card.gain != null -> parameter(PlayParameter(card, SpiceRoadGameModel.Caravan(), card.gain))
5559
card.upgrade != null -> {
5660
fun rec(scope: ActionChoicesNextScope<SpiceRoadGameModel, PlayParameter>,
57-
remaining: SpiceRoadGameModel.Caravan, upgrades: Int,
61+
remaining: SpiceRoadGameModel.Caravan,
62+
upgrades: Int,
5863
remove: SpiceRoadGameModel.Caravan = SpiceRoadGameModel.Caravan(),
5964
add: SpiceRoadGameModel.Caravan = SpiceRoadGameModel.Caravan()) {
6065
scope.parameter(PlayParameter(card, remove, add))
@@ -78,14 +83,60 @@ object SpiceRoadDsl {
7883
}
7984
}
8085
}
86+
this.action(acquire).effect {
87+
game.currentPlayer.caravan -= action.parameter.payArray.fold(SpiceRoadGameModel.Caravan(), { acc, x -> acc + x.toCaravan() })
88+
game.visibleActionCards.cards.mapIndexed { index, card -> card.addSpice(action.parameter.payArray.getOrNull(index)) }
89+
90+
game.currentPlayer.caravan += action.parameter.card.takeAllSpice()
91+
game.visibleActionCards.card(action.parameter.card).moveTo(game.currentPlayer.hand)
92+
93+
if (game.actionDeck.size > 0) {
94+
game.actionDeck.random(this.replayable, 1, "NewActionCard") { it.toStateString() }.forEach { it.moveTo(game.visibleActionCards) }
95+
}
96+
}
97+
this.action(acquire).choose {
98+
options({ game.visibleActionCards.cards.filterIndexed { index, _ -> index <= game.currentPlayer.caravan.count } }) { card ->
99+
fun rec(scope: ActionChoicesNextScope<SpiceRoadGameModel, AcquireParameter>,
100+
remaining: SpiceRoadGameModel.Caravan,
101+
leftToPay: Int,
102+
payList: List<SpiceRoadGameModel.Spice> = emptyList()
103+
) {
104+
if (leftToPay <= 0) {
105+
scope.parameter(AcquireParameter(card, payList))
106+
return
107+
}
108+
scope.options({ remaining.spice.keys }) { payWith ->
109+
rec(this, remaining - payWith.toCaravan(), leftToPay - 1, payList + payWith)
110+
}
111+
}
112+
rec(this, context.game.currentPlayer.caravan, context.game.visibleActionCards.card(card).index)
113+
}
114+
}
115+
this.allActions.precondition { game.currentPlayer.index == playerIndex }
116+
this.allActions.after {
117+
val gameEnd = when (game.playerCount) {
118+
1, 2, 3 -> game.currentPlayer.pointCards == 6
119+
else -> game.currentPlayer.pointCards == 5
120+
}
121+
if (gameEnd) {
122+
when (game.turnsLeft) {
123+
-1 -> game.turnsLeft = game.playerCount - (game.currentPlayerIndex + 1)
124+
0 -> this.eliminations.eliminateBy(game.players.mapIndexed { index, player -> index to player }, compareBy({ it.points }, { +it.index }))
125+
else -> game.turnsLeft--
126+
}
127+
}
128+
}
129+
this.allActions.after { game.currentPlayerIndex = game.currentPlayerIndex.next(game.playerCount) }
130+
81131
}
82132
}
83133
}
84134

85135
class SpiceRoadGameModel(val playerCount: Int) {
86136
//Turn: Action -> Caravan Limit (discard to hand size) (-> Game end trigger check)
87137
//Actions: acquire, claim, rest, play
88-
val currentPlayerIndex = 0
138+
var turnsLeft = -1
139+
var currentPlayerIndex = 0
89140
val currentPlayer: Player get() = players[currentPlayerIndex]
90141
val players = (0 until playerCount).map { Player(it) }
91142
val pointsDeck = CardZone<PointCard>(pointsCards.split("\n").map { x -> x.split(",") }.map { (x, y) -> PointCard(x.toInt(), y.toCaravan()!!) }.toMutableList())
@@ -104,9 +155,22 @@ class SpiceRoadGameModel(val playerCount: Int) {
104155
val silverCoins = (0 until playerCount * 2).map { Coin(1) }
105156

106157
class ActionCard(val upgrade: Int?, val gain: Caravan?, val trade: Pair<Caravan, Caravan>?) {
158+
var spiceOnMe = Caravan()
107159
fun toStateString(): String = "$upgrade $gain ${trade?.first}->${trade?.second}"
108160

109-
fun toViewable(): Map<String, Any?> = mapOf("upgrade" to upgrade, "gain" to gain?.toViewable(), "trade" to if (trade == null) null else mapOf("give" to trade.first.toViewable(), "get" to trade.second.toViewable()))
161+
fun toViewable(): Map<String, Any?> = mapOf("upgrade" to upgrade, "gain" to gain?.toViewable(), "trade" to if (trade == null) null else mapOf("give" to trade.first.toViewable(), "get" to trade.second.toViewable()), "bonusSpice" to spiceOnMe.toViewable())
162+
163+
fun addSpice(spice: Spice?) {
164+
if (spice != null) {
165+
spiceOnMe += spice.toCaravan()
166+
}
167+
}
168+
169+
fun takeAllSpice(): Caravan {
170+
val tmp = spiceOnMe
171+
spiceOnMe = Caravan()
172+
return tmp
173+
}
110174
}
111175

112176
class PointCard(val points: Int, val cost: Caravan) {
@@ -130,6 +194,7 @@ class SpiceRoadGameModel(val playerCount: Int) {
130194
ActionCard(null, Spice.YELLOW.toCaravan(2), null))
131195
)
132196
var points = 0
197+
var pointCards = 0
133198

134199
fun toViewable(): Map<String, Any?> {
135200
return mapOf(

0 commit comments

Comments
 (0)