Added tests to ensure that resources from buildings behave as expected (#9860)

* Added tests to ensure that resources from buildings behave as expected

* More tests suggested by @SeventhM

* Caught an edge case - if you pillage your own tile improvement, your resources would not have updated!

* Actually every time an improvement changes you could have a resource change

* Update resources eon every improvement change because they could be providing resources via uniques
This commit is contained in:
Yair Morgenstern 2023-08-03 11:38:36 +03:00 committed by GitHub
parent 15bfaa24a5
commit fc40da11d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 143 additions and 9 deletions

View File

@ -21,8 +21,8 @@ import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.UniqueMap
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unique.UniqueTriggerActivation
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
@ -513,11 +513,11 @@ class CityConstructions : IsPartOfGameInfoSerialization {
UniqueType.StatsFromTiles, UniqueType.StatsFromTilesWithout, UniqueType.StatsFromObject,
UniqueType.StatPercentFromObject, UniqueType.AllStatsPercentFromObject
)
updateUniques()
// Happiness is global, so it could affect all cities
if(building.isStatRelated(Stat.Happiness)) {
if (building.isStatRelated(Stat.Happiness)) {
for (city in civ.cities) {
city.reassignPopulationDeferred()
}
@ -525,8 +525,6 @@ class CityConstructions : IsPartOfGameInfoSerialization {
else if(uniqueTypesModifyingYields.any { building.hasUnique(it) })
city.reassignPopulationDeferred()
city.civ.cache.updateCivResources() // this building could be a resource-requiring one
addFreeBuildings()
}
@ -556,14 +554,16 @@ class CityConstructions : IsPartOfGameInfoSerialization {
builtBuildings.remove(buildingName)
city.civ.cache.updateCitiesConnectedToCapital(false) // could be a connecting building, like a harbor
updateUniques()
city.civ.cache.updateCivResources() // this building could be a resource-requiring one
}
fun updateUniques(onLoadGame:Boolean = false) {
builtBuildingUniqueMap.clear()
for (building in getBuiltBuildings())
builtBuildingUniqueMap.addUniques(building.uniqueObjects)
if (!onLoadGame) city.cityStats.update()
if (!onLoadGame) {
city.cityStats.update()
city.civ.cache.updateCivResources()
}
}
fun addFreeBuildings() {

View File

@ -689,6 +689,8 @@ class Civilization : IsPartOfGameInfoSerialization {
tacticalAI.init(this)
cache.updateCivResources()
cache.setTransients()
}

View File

@ -311,6 +311,11 @@ open class Tile : IsPartOfGameInfoSerialization {
fun changeImprovement(improvementStr: String?) {
improvementIsPillaged = false
improvement = improvementStr
if (owningCity != null){
owningCity!!.civ.cache.updateCivResources()
}
}
// function handling when adding a road to the tile
@ -931,6 +936,8 @@ open class Tile : IsPartOfGameInfoSerialization {
}
owningCity?.reassignPopulationDeferred()
if (owningCity != null)
owningCity!!.civ.cache.updateCivResources()
}
fun isPillaged(): Boolean {

View File

@ -0,0 +1,125 @@
package com.unciv.uniques
import com.unciv.testing.GdxTestRunner
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(GdxTestRunner::class)
class ResourceTests {
private val game = TestGame().apply { makeHexagonalMap(2) }
private val civInfo = game.addCiv()
private val city = game.addCity(civInfo, game.tileMap[0,0])
@Test
fun testConsumesResourceUnique() {
val consumesCoal = game.createBuilding("Consumes [1] [Coal]")
city.cityConstructions.addBuilding(consumesCoal.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == -1)
}
@Test
fun testResourceProductionModifierDoesNotAffectConsumption() {
val consumesCoal = game.createBuilding("Consumes [1] [Coal]")
val doubleCoal = game.createBuilding("Double quantity of [Coal] produced")
val doubleStrategic = game.createBuilding("Quantity of strategic resources produced by the empire +[100]%")
city.cityConstructions.addBuilding(consumesCoal.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == -1)
city.cityConstructions.addBuilding(doubleCoal.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == -1)
city.cityConstructions.addBuilding(doubleStrategic.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == -1)
}
@Test
fun testResourceProductionAndConsumptionModifierDoesNotAffectConsumption() {
val consumesCoal = game.createBuilding("Consumes [1] [Coal]")
val providesCoal = game.createBuilding("Provides [1] [Coal]")
val doubleCoal = game.createBuilding("Double quantity of [Coal] produced")
val doubleStrategic = game.createBuilding("Quantity of strategic resources produced by the empire +[100]%")
city.cityConstructions.addBuilding(providesCoal.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 1)
city.cityConstructions.addBuilding(doubleCoal.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 2)
city.cityConstructions.addBuilding(doubleStrategic.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 4)
city.cityConstructions.addBuilding(consumesCoal.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 3) // Produce 4 (1*2*2), consume 1
}
@Test
fun testBuildingGrantedByUniqueGrantsResource() {
val resourceProvider = game.createBuilding("Provides [1] [Coal]")
val resourceProviderProvider = game.createBuilding("Gain a free [${resourceProvider.name}] [in this city]")
city.cityConstructions.addBuilding(resourceProviderProvider.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 1)
}
@Test
fun testTileProvidesResourceOnlyWithRequiredTech() {
val tile = game.tileMap[1,1]
tile.resource = "Coal"
tile.improvement = "Mine"
tile.resourceAmount = 1
civInfo.tech.addTechnology(game.ruleset.tileImprovements["Mine"]!!.techRequired!!)
Assert.assertEquals(civInfo.getCivResourcesByName()["Coal"], 0)
civInfo.tech.addTechnology(game.ruleset.tileResources["Coal"]!!.revealedBy!!)
Assert.assertEquals(civInfo.getCivResourcesByName()["Coal"], 1)
}
@Test
fun testTileDoesNotProvideResourceWithPillagedImprovement() {
val tile = game.tileMap[1,1]
tile.resource = "Coal"
tile.improvement = "Mine"
tile.resourceAmount = 1
civInfo.tech.addTechnology(game.ruleset.tileImprovements["Mine"]!!.techRequired!!)
civInfo.tech.addTechnology(game.ruleset.tileResources["Coal"]!!.revealedBy!!)
Assert.assertEquals(civInfo.getCivResourcesByName()["Coal"], 1)
tile.setPillaged()
Assert.assertEquals(civInfo.getCivResourcesByName()["Coal"], 0)
}
@Test
/** The revealing tech should not affect whether we can get the resource from improvements */
fun testImprovementProvidesResourceEvenWithoutTech() {
val tile = game.tileMap[1,1]
val improvement = game.createTileImprovement("Provides [1] [Coal]", "Consumes [1] [Silver]")
tile.improvement = improvement.name
civInfo.cache.updateCivResources()
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 1)
Assert.assertTrue(civInfo.getCivResourcesByName()["Silver"] == -1)
}
@Test
/** The revealing tech should not affect whether we can get the resource from improvements */
fun testImprovementProvidesResourceWithUniqueBonuses() {
val tile = game.tileMap[1,1]
val improvement = game.createTileImprovement("Provides [1] [Coal]")
tile.improvement = improvement.name
civInfo.cache.updateCivResources()
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 1)
val doubleCoal = game.createBuilding("Double quantity of [Coal] produced")
city.cityConstructions.addBuilding(doubleCoal.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 2)
val doubleStrategic = game.createBuilding("Quantity of strategic resources produced by the empire +[100]%")
city.cityConstructions.addBuilding(doubleStrategic.name)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 4)
}
}

View File

@ -12,7 +12,7 @@ import org.junit.runner.RunWith
@RunWith(GdxTestRunner::class)
class TriggeredUniquesTests {
class TimedUniquesTests {
private val game = TestGame().apply { makeHexagonalMap(2) }
private val civInfo = game.addCiv()
private val policy =