From 6180f7e44778bef26ed4386f260052651da7d4fa Mon Sep 17 00:00:00 2001 From: joffrey-bion Date: Sun, 29 Nov 2020 17:35:19 +0100 Subject: Remove unrealistic transaction options Options where both the left and the right price are more expensive should never be used. Resolves: https://github.com/joffrey-bion/seven-wonders/issues/53 --- .../sevenwonders/model/resources/Resources.kt | 8 ++- .../resources/TransactionOptionsCalculator.kt | 2 + .../resources/TransactionOptionsCalculatorTest.kt | 72 ++++++++++++++++------ 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/resources/Resources.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/resources/Resources.kt index fc99a41d..3bf19964 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/resources/Resources.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/resources/Resources.kt @@ -32,7 +32,9 @@ enum class ResourceType(val symbol: Char) { data class CountedResource( val count: Int, val type: ResourceType, -) +) { + override fun toString(): String = "$count $type" +} @Serializable enum class Provider(val boardPosition: RelativeBoardPosition) { @@ -53,7 +55,9 @@ data class PricedResourceTransaction( override val provider: Provider, override val resources: List, val totalPrice: Int, -) : ResourceTransaction() +) : ResourceTransaction() { + override fun toString(): String = "{$totalPrice coin(s) to $provider for $resources}" +} typealias PricedResourceTransactions = Set diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/TransactionOptionsCalculator.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/TransactionOptionsCalculator.kt index fbbcaa6e..29fcc21b 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/TransactionOptionsCalculator.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/TransactionOptionsCalculator.kt @@ -122,6 +122,8 @@ private class TransactionOptionsCalculator(resourcesToPay: Resources, player: Pl private operator fun PricedResourceTransactions.compareTo(prices: Map): Int = when { left == prices.left -> right.compareTo(prices.right) right == prices.right -> left.compareTo(prices.left) + left < prices.left && right < prices.right -> -1 + left > prices.left && right > prices.right -> 1 else -> 0 } diff --git a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/resources/TransactionOptionsCalculatorTest.kt b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/resources/TransactionOptionsCalculatorTest.kt index da4b608e..4868ca5c 100644 --- a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/resources/TransactionOptionsCalculatorTest.kt +++ b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/resources/TransactionOptionsCalculatorTest.kt @@ -1,6 +1,5 @@ package org.luxons.sevenwonders.engine.resources -import org.junit.Test import org.luxons.sevenwonders.engine.SimplePlayer import org.luxons.sevenwonders.engine.boards.Table import org.luxons.sevenwonders.engine.test.createPricedTransaction @@ -12,6 +11,7 @@ import org.luxons.sevenwonders.model.resources.Provider.RIGHT_PLAYER import org.luxons.sevenwonders.model.resources.ResourceType.* import org.luxons.sevenwonders.model.resources.noTransactions import org.luxons.sevenwonders.model.resources.singleOptionNoTransactionNeeded +import kotlin.test.Test import kotlin.test.assertEquals class TransactionOptionsCalculatorTest { @@ -76,7 +76,7 @@ class TransactionOptionsCalculatorTest { } @Test - fun transactionOptions_fixedResources_overridenCost() { + fun transactionOptions_fixedResources_overridenCost_cheapestFirst() { val board0 = testBoard(STONE) board0.tradingRules.setCost(WOOD, RIGHT_PLAYER, 1) @@ -104,7 +104,7 @@ class TransactionOptionsCalculatorTest { } @Test - fun transactionOptions_mixedResources_overridenCost() { + fun transactionOptions_choiceResources_overridenCost() { val board0 = testBoard(STONE) board0.tradingRules.setCost(WOOD, RIGHT_PLAYER, 1) @@ -130,6 +130,36 @@ class TransactionOptionsCalculatorTest { assertEquals(listOf(noTransactions()), transactionOptions(resources, player2)) } + @Test + fun transactionOptions_mixedResources_overridenCost() { + val board0 = testBoard(WOOD) + board0.production.addChoice(CLAY, ORE) + board0.tradingRules.setCost(CLAY, RIGHT_PLAYER, 1) + + val board1 = testBoard(WOOD) + board1.production.addFixedResource(ORE, 1) + board1.production.addFixedResource(CLAY, 1) + board1.publicProduction.addFixedResource(ORE, 1) + board1.publicProduction.addFixedResource(CLAY, 1) + + val board2 = testBoard(WOOD) + + val table = Table(listOf(board0, board1, board2)) + + val player0 = SimplePlayer(0, table) + val player1 = SimplePlayer(1, table) + val player2 = SimplePlayer(2, table) + + val resources = resourcesOf(ORE, CLAY) + + val clayRightDiscounted = createPricedTransactions(RIGHT_PLAYER, 1, CLAY) + val oreAndClayLeft = createPricedTransactions(LEFT_PLAYER, 4, ORE, CLAY) + + assertEquals(listOf(clayRightDiscounted), transactionOptions(resources, player0)) + assertEquals(listOf(noTransactions()), transactionOptions(resources, player1)) + assertEquals(listOf(oreAndClayLeft), transactionOptions(resources, player2)) + } + @Test fun transactionOptions_mixedResources_overridenCost_sameMultipleTimes() { val board0 = testBoard(WOOD) @@ -170,18 +200,18 @@ class TransactionOptionsCalculatorTest { } @Test - fun transactionOptions_cheapestFirst() { - val board0 = testBoard(WOOD) - board0.production.addChoice(CLAY, ORE) - board0.tradingRules.setCost(CLAY, RIGHT_PLAYER, 1) + fun transactionOptions_avoidOptionsWithWorsePriceOnBothSides() { + val board0 = testBoard(STONE) + board0.tradingRules.setCost(CLAY, LEFT_PLAYER, 1) + board0.tradingRules.setCost(WOOD, RIGHT_PLAYER, 1) - val board1 = testBoard(WOOD) - board1.production.addFixedResource(ORE, 1) - board1.production.addFixedResource(CLAY, 1) - board1.publicProduction.addFixedResource(ORE, 1) - board1.publicProduction.addFixedResource(CLAY, 1) + val board1 = testBoard(CLAY) + board1.publicProduction.addFixedResource(WOOD, 1) + board1.production.addFixedResource(WOOD, 1) val board2 = testBoard(WOOD) + board2.publicProduction.addFixedResource(CLAY, 1) + board2.production.addFixedResource(CLAY, 1) val table = Table(listOf(board0, board1, board2)) @@ -189,13 +219,19 @@ class TransactionOptionsCalculatorTest { val player1 = SimplePlayer(1, table) val player2 = SimplePlayer(2, table) - val resources = resourcesOf(ORE, CLAY) + val resources = resourcesOf(WOOD, CLAY) - val clayRightDiscounted = createPricedTransactions(RIGHT_PLAYER, 1, CLAY) - val oreAndClayLeft = createPricedTransactions(LEFT_PLAYER, 4, ORE, CLAY) + val woodAndClayLeft = createPricedTransaction(LEFT_PLAYER, 3, WOOD, CLAY) + val woodAndClayRight = createPricedTransaction(RIGHT_PLAYER, 3, WOOD, CLAY) + val clayLeftDiscounted = createPricedTransaction(LEFT_PLAYER, 1, CLAY) + val woodRightDiscounted = createPricedTransaction(RIGHT_PLAYER, 1, WOOD) - assertEquals(listOf(clayRightDiscounted), transactionOptions(resources, player0)) - assertEquals(listOf(noTransactions()), transactionOptions(resources, player1)) - assertEquals(listOf(oreAndClayLeft), transactionOptions(resources, player2)) + val everythingLeft = createPricedTransactions(woodAndClayLeft) + val everythingRight = createPricedTransactions(woodAndClayRight) + val woodRightClayLeftDiscounted = createPricedTransactions(woodRightDiscounted, clayLeftDiscounted) + + assertEquals(listOf(woodRightClayLeftDiscounted, everythingLeft, everythingRight), transactionOptions(resources, player0)) + assertEquals(singleOptionNoTransactionNeeded(), transactionOptions(resources, player1)) + assertEquals(singleOptionNoTransactionNeeded(), transactionOptions(resources, player2)) } } -- cgit