Add tests for city class and introduce small refactor (#9965)

* ♻ extract methods to improve readability

* 💚 introduce tests for city logic
This commit is contained in:
Framonti
2023-08-24 16:14:02 +02:00
committed by GitHub
parent 94dbb3377a
commit 53748a40d7
2 changed files with 171 additions and 12 deletions

View File

@ -202,19 +202,39 @@ class City : IsPartOfGameInfoSerialization {
fun getCityResources(): ResourceSupplyList {
val cityResources = ResourceSupplyList()
val resourceModifer = HashMap<String,Float>()
val resourceModifer = HashMap<String, Float>()
for (resource in civ.gameInfo.ruleset.tileResources.values)
resourceModifer[resource.name] = civ.getResourceModifier(resource)
getResourcesFromTiles(resourceModifer, cityResources)
getResourceFromUniqueImprovedTiles(cityResources, resourceModifer)
manageCityResourcesRequiredByBuildings(cityResources)
getCityResourcesFromUniqueBuildings(cityResources, resourceModifer)
if (civ.isCityState() && isCapital() && civ.cityStateResource != null) {
cityResources.add(
getRuleset().tileResources[civ.cityStateResource]!!,
"Mercantile City-State"
)
}
return cityResources
}
private fun getResourcesFromTiles(resourceModifer: HashMap<String, Float>, cityResources: ResourceSupplyList) {
for (tileInfo in getTiles().filter { it.resource != null }) {
val resource = tileInfo.tileResource
val amount = getTileResourceAmount(tileInfo) * resourceModifer[resource.name]!!
if (amount > 0) cityResources.add(resource, "Tiles", amount.toInt())
}
}
for (tileInfo in getTiles()) {
private fun getResourceFromUniqueImprovedTiles(cityResources: ResourceSupplyList, resourceModifer: HashMap<String, Float>) {
for (tileInfo in getTiles().filter { it.getUnpillagedImprovement() != null }) {
val stateForConditionals = StateForConditionals(civ, this, tile = tileInfo)
if (tileInfo.getUnpillagedImprovement() == null) continue
val tileImprovement = tileInfo.getUnpillagedTileImprovement()
for (unique in tileImprovement!!.getMatchingUniques(UniqueType.ProvidesResources, stateForConditionals)) {
val resource = getRuleset().tileResources[unique.params[1]] ?: continue
@ -231,14 +251,18 @@ class City : IsPartOfGameInfoSerialization {
)
}
}
}
private fun manageCityResourcesRequiredByBuildings(cityResources: ResourceSupplyList) {
val freeBuildings = civ.civConstructions.getFreeBuildings(id)
for (building in cityConstructions.getBuiltBuildings()) {
// Free buildings cost no resources
if (building.name in freeBuildings) continue
cityResources.subtractResourceRequirements(building.getResourceRequirementsPerTurn(), getRuleset(), "Buildings")
}
}
private fun getCityResourcesFromUniqueBuildings(cityResources: ResourceSupplyList, resourceModifer: HashMap<String, Float>) {
for (unique in getLocalMatchingUniques(UniqueType.ProvidesResources, StateForConditionals(civ, this))) { // E.G "Provides [1] [Iron]"
val resource = getRuleset().tileResources[unique.params[1]]
?: continue
@ -247,15 +271,6 @@ class City : IsPartOfGameInfoSerialization {
(unique.params[0].toFloat() * resourceModifer[resource.name]!!).toInt()
)
}
if (civ.isCityState() && isCapital() && civ.cityStateResource != null) {
cityResources.add(
getRuleset().tileResources[civ.cityStateResource]!!,
"Mercantile City-State"
)
}
return cityResources
}
/** Gets the number of resources available to this city

View File

@ -0,0 +1,144 @@
package com.unciv.logic.city
import com.badlogic.gdx.math.Vector2
import com.unciv.logic.civilization.Civilization
import com.unciv.testing.GdxTestRunner
import com.unciv.uniques.TestGame
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(GdxTestRunner::class)
class CityTest {
private lateinit var testCiv: Civilization
private lateinit var capitalCity: City
private val testGame = TestGame()
@Before
fun setUp() {
testGame.makeHexagonalMap(2)
testCiv = testGame.addCiv()
capitalCity = testGame.addCity(testCiv, testGame.getTile(Vector2.Zero))
}
@Test
fun `should not destroy city when it's an original capital`() {
// when
capitalCity.destroyCity()
// then
assertTrue(testCiv.cities.contains(capitalCity))
}
@Test
fun `should destroy city when it's not original capital`() {
// given
var nonCapitalCity = testGame.addCity(testCiv, testGame.getTile(Vector2(1f, 1f)))
// when
nonCapitalCity.destroyCity()
// then
assertTrue(testCiv.cities.contains(capitalCity))
assertFalse(testCiv.cities.contains(nonCapitalCity))
}
@Test
fun `should move capital when destroyed`() {
// given
var nonCapitalCity = testGame.addCity(testCiv, testGame.getTile(Vector2(1f, 1f)))
nonCapitalCity.name = "Not capital"
// when
capitalCity.destroyCity(overrideSafeties = true)
// then
assertFalse(testCiv.cities.contains(capitalCity))
assertTrue(testCiv.cities[0].isCapital())
assertEquals("Not capital", testCiv.cities[0].name)
}
@Test
fun `should set terrain as city ruin when city is destroyed`() {
// when
capitalCity.destroyCity(overrideSafeties = true)
// then
assertEquals("City ruins", testGame.getTile(Vector2.Zero).improvement)
}
@Test
fun `should sell building`() {
// given
val expectedMonumentSellingGoldGain = 4
capitalCity.cityConstructions.addBuilding("Monument")
// when
capitalCity.sellBuilding("Monument")
// then
assertEquals(expectedMonumentSellingGoldGain, testCiv.gold)
}
@Test
fun `should sell only one building per turn`() {
// given
capitalCity.cityConstructions.addBuilding("Monument")
// when
capitalCity.sellBuilding("Monument")
// then
assertTrue(capitalCity.hasSoldBuildingThisTurn)
}
@Test
fun `should get resources from tiles`() {
// given
testCiv.tech.addTechnology("Iron Working")
testCiv.tech.addTechnology("Mining")
val tile = testGame.setTileFeatures(Vector2(1f, 1f))
tile.resource = "Iron"
tile.resourceAmount = 4
tile.improvement = "Mine"
// when
val cityResources = capitalCity.getCityResources()
// then
assertEquals(1, cityResources.size)
assertEquals("4 Iron from Tiles", cityResources[0].toString())
}
@Test
fun `should get resources from unique buildings`() {
// given
val building = testGame.createBuilding("Provides [4] [Iron]")
capitalCity.cityConstructions.addBuilding(building.name)
// when
val cityResources = capitalCity.getCityResources()
// then
assertEquals(1, cityResources.size)
assertEquals("4 Iron from Buildings", cityResources[0].toString())
}
@Test
fun `should reduce resources due to buildings`() {
// given
capitalCity.cityConstructions.addBuilding("Factory")
// when
val cityResources = capitalCity.getCityResources()
// then
assertEquals(1, cityResources.size)
assertEquals("-1 Coal from Buildings", cityResources[0].toString())
}
}