Add unit state for tile improvement conditionals (#13574)

* Use stateForConditionals through build improvement checks

* Fix tests
This commit is contained in:
Rob Loach
2025-07-05 17:06:43 -04:00
committed by GitHub
parent 4f9ca56781
commit abf63dbc91
14 changed files with 95 additions and 85 deletions

View File

@ -342,7 +342,7 @@ object Automation {
if (!construction.hasCreateOneImprovementUnique()) return true // redundant but faster???
val improvement = construction.getImprovementToCreate(city.getRuleset(), civInfo) ?: return true
return city.getTiles().any {
it.improvementFunctions.canBuildImprovement(improvement, civInfo)
it.improvementFunctions.canBuildImprovement(improvement, city.state)
}
}
@ -439,7 +439,7 @@ object Automation {
val civ = city.civ
return city.getTiles().filter {
(it.getTileImprovement() == null || improvementIsRemovable(city, it))
&& it.improvementFunctions.canBuildImprovement(improvement, civ)
&& it.improvementFunctions.canBuildImprovement(improvement, city.state)
}.maxByOrNull {
// Needs to take into account future improvement layouts, and better placement of citadel-like improvements
rankStatsValue(it.stats.getStatDiffForImprovement(improvement, civ, city, localUniqueCache, it.stats.getTileStats(city, civ, localUniqueCache)), civ) + (

View File

@ -227,7 +227,7 @@ object SpecificUnitAutomation {
it.isLand && it.resource == null && !it.isCityCenter()
&& (unit.currentTile == it || unit.movement.canMoveTo(it))
&& it.improvement == null
&& it.improvementFunctions.canBuildImprovement(improvement, unit.civ)
&& it.improvementFunctions.canBuildImprovement(improvement, unit.cache.state)
&& Automation.rankTile(it, unit.civ, localUniqueCache) > averageTerrainStatsValue
}

View File

@ -368,10 +368,11 @@ class WorkerAutomation(
// You can keep working on half-built improvements, even if they're unique to another civ
if (tile.improvementInProgress != null) return ruleSet.tileImprovements[tile.improvementInProgress!!]
val stateForConditionals = StateForConditionals(civInfo = unit.civ, unit = unit, tile = tile)
val potentialTileImprovements = ruleSet.tileImprovements.filter {
(it.value.uniqueTo == null || unit.civ.matchesFilter(it.value.uniqueTo!!, StateForConditionals(unit = unit, tile = tile)))
(it.value.uniqueTo == null || unit.civ.matchesFilter(it.value.uniqueTo!!, stateForConditionals))
&& unit.canBuildImprovement(it.value, tile)
&& tile.improvementFunctions.canBuildImprovement(it.value, civInfo)
&& tile.improvementFunctions.canBuildImprovement(it.value, stateForConditionals)
}
if (potentialTileImprovements.isEmpty()) return null
@ -685,7 +686,7 @@ class WorkerAutomation(
!tile.hasViewableResource(civInfo) -> false
else -> tile.tileResource.getImprovements().any {
val improvement = civInfo.gameInfo.ruleset.tileImprovements[it]!!
tile.improvementFunctions.canBuildImprovement(improvement, civInfo)
tile.improvementFunctions.canBuildImprovement(improvement, civInfo.state)
}
}

View File

@ -12,58 +12,62 @@ object ImprovementFunctions {
/** Generates a sequence of reasons that prevent building given [improvement].
* If the sequence is empty, improvement can be built immediately.
*/
fun getImprovementBuildingProblems(improvement: TileImprovement, civInfo: Civilization, tile: Tile? = null): Sequence<ImprovementBuildingProblem> = sequence {
val stateForConditionals = StateForConditionals(civInfo, tile = tile)
fun getImprovementBuildingProblems(improvement: TileImprovement, stateForConditionals: StateForConditionals, tile: Tile? = null): Sequence<ImprovementBuildingProblem> = sequence {
if (stateForConditionals.civInfo != null) {
val civInfo: Civilization = stateForConditionals.civInfo
if (improvement.uniqueTo != null && !civInfo.matchesFilter(improvement.uniqueTo!!))
yield(ImprovementBuildingProblem.WrongCiv)
if (civInfo.cache.uniqueImprovements.any { it.replaces == improvement.name })
yield(ImprovementBuildingProblem.Replaced)
if (improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!))
yield(ImprovementBuildingProblem.MissingTech)
if (improvement.getMatchingUniques(UniqueType.Unbuildable, StateForConditionals.IgnoreConditionals)
.any { it.modifiers.isEmpty() })
yield(ImprovementBuildingProblem.Unbuildable)
else if (improvement.hasUnique(UniqueType.Unbuildable, stateForConditionals))
yield(ImprovementBuildingProblem.ConditionallyUnbuildable)
if (improvement.uniqueTo != null && !civInfo.matchesFilter(improvement.uniqueTo!!))
yield(ImprovementBuildingProblem.WrongCiv)
if (civInfo.cache.uniqueImprovements.any { it.replaces == improvement.name })
yield(ImprovementBuildingProblem.Replaced)
if (improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!))
yield(ImprovementBuildingProblem.MissingTech)
if (improvement.getMatchingUniques(UniqueType.Unbuildable, StateForConditionals.IgnoreConditionals)
.any { it.modifiers.isEmpty() })
yield(ImprovementBuildingProblem.Unbuildable)
else if (improvement.hasUnique(UniqueType.Unbuildable, stateForConditionals))
yield(ImprovementBuildingProblem.ConditionallyUnbuildable)
if (improvement.hasUnique(UniqueType.Unavailable, stateForConditionals))
yield(ImprovementBuildingProblem.ConditionallyUnbuildable)
if (improvement.hasUnique(UniqueType.Unavailable, stateForConditionals))
yield(ImprovementBuildingProblem.ConditionallyUnbuildable)
if (improvement.getMatchingUniques(UniqueType.OnlyAvailable, StateForConditionals.IgnoreConditionals)
.any { !it.conditionalsApply(stateForConditionals) })
yield(ImprovementBuildingProblem.UnmetConditional)
if (improvement.getMatchingUniques(UniqueType.OnlyAvailable, StateForConditionals.IgnoreConditionals)
.any { !it.conditionalsApply(stateForConditionals) })
yield(ImprovementBuildingProblem.UnmetConditional)
if (improvement.getMatchingUniques(UniqueType.ObsoleteWith, stateForConditionals)
.any { civInfo.tech.isResearched(it.params[0]) })
yield(ImprovementBuildingProblem.Obsolete)
if (improvement.getMatchingUniques(UniqueType.ObsoleteWith, stateForConditionals)
.any { civInfo.tech.isResearched(it.params[0]) })
yield(ImprovementBuildingProblem.Obsolete)
if (improvement.getMatchingUniques(UniqueType.ConsumesResources, stateForConditionals)
.any { civInfo.getResourceAmount(it.params[1]) < it.params[0].toInt() })
yield(ImprovementBuildingProblem.MissingResources)
if (improvement.getMatchingUniques(UniqueType.ConsumesResources, stateForConditionals)
.any { civInfo.getResourceAmount(it.params[1]) < it.params[0].toInt() })
yield(ImprovementBuildingProblem.MissingResources)
if (improvement.getMatchingUniques(UniqueType.CostsResources)
.any { civInfo.getResourceAmount(it.params[1]) < it.params[0].toInt() *
(if (it.isModifiedByGameSpeed()) civInfo.gameInfo.speed.modifier else 1f) })
yield(ImprovementBuildingProblem.MissingResources)
if (tile != null){
if (tile.getOwner() != civInfo && !improvement.hasUnique(UniqueType.CanBuildOutsideBorders, stateForConditionals)) {
if (!improvement.hasUnique(UniqueType.CanBuildJustOutsideBorders, stateForConditionals))
yield(ImprovementBuildingProblem.OutsideBorders)
else if (tile.neighbors.none { it.getOwner() == civInfo })
yield(ImprovementBuildingProblem.NotJustOutsideBorders)
}
val knownFeatureRemovals = tile.ruleset.nonRoadTileRemovals
.filter { rulesetImprovement ->
rulesetImprovement.techRequired == null || civInfo.tech.isResearched(rulesetImprovement.techRequired!!)
if (improvement.getMatchingUniques(UniqueType.CostsResources)
.any { civInfo.getResourceAmount(it.params[1]) < it.params[0].toInt() *
(if (it.isModifiedByGameSpeed()) civInfo.gameInfo.speed.modifier else 1f) })
yield(ImprovementBuildingProblem.MissingResources)
if (tile != null) {
if (tile.getOwner() != civInfo && !improvement.hasUnique(UniqueType.CanBuildOutsideBorders, stateForConditionals)) {
if (!improvement.hasUnique(UniqueType.CanBuildJustOutsideBorders, stateForConditionals))
yield(ImprovementBuildingProblem.OutsideBorders)
else if (tile.neighbors.none { it.getOwner() == civInfo })
yield(ImprovementBuildingProblem.NotJustOutsideBorders)
}
if (!tile.improvementFunctions.canImprovementBeBuiltHere(improvement, tile.hasViewableResource(civInfo), knownFeatureRemovals, stateForConditionals))
// There are way too many conditions in that functions, besides, they are not interesting
// at least for the current usecases. Improve if really needed.
yield(ImprovementBuildingProblem.Other)
val knownFeatureRemovals = tile.ruleset.nonRoadTileRemovals
.filter { rulesetImprovement ->
rulesetImprovement.techRequired == null || civInfo.tech.isResearched(rulesetImprovement.techRequired!!)
}
if (!tile.improvementFunctions.canImprovementBeBuiltHere(improvement, tile.hasViewableResource(civInfo), knownFeatureRemovals, stateForConditionals))
// There are way too many conditions in that functions, besides, they are not interesting
// at least for the current usecases. Improve if really needed.
yield(ImprovementBuildingProblem.Other)
}
}
else {
yield(ImprovementBuildingProblem.WrongCiv)
}
}
}

View File

@ -538,12 +538,12 @@ class TechManager : IsPartOfGameInfoSerialization {
fun getBestRoadAvailable(): RoadStatus {
val railroadImprovement = getRuleset().railroadImprovement // May not exist in mods
if (railroadImprovement != null && (railroadImprovement.techRequired == null || isResearched(railroadImprovement.techRequired!!))
&& ImprovementFunctions.getImprovementBuildingProblems(railroadImprovement, civInfo).none())
&& ImprovementFunctions.getImprovementBuildingProblems(railroadImprovement, civInfo.state).none())
return RoadStatus.Railroad
val roadImprovement = getRuleset().roadImprovement
if (roadImprovement != null && (roadImprovement.techRequired == null || isResearched(roadImprovement.techRequired!!))
&& ImprovementFunctions.getImprovementBuildingProblems(roadImprovement, civInfo).none())
&& ImprovementFunctions.getImprovementBuildingProblems(roadImprovement, civInfo.state).none())
return RoadStatus.Road
return RoadStatus.None

View File

@ -34,8 +34,8 @@ object MapPathing {
return tile.hasRoadConnection(unit.civ, false)
|| tile.hasRailroadConnection(false)
|| roadImprovement != null && tile.improvementFunctions.canBuildImprovement(roadImprovement, unit.civ)
|| railRoadImprovement != null && tile.improvementFunctions.canBuildImprovement(railRoadImprovement, unit.civ)
|| roadImprovement != null && tile.improvementFunctions.canBuildImprovement(roadImprovement, unit.cache.state)
|| railRoadImprovement != null && tile.improvementFunctions.canBuildImprovement(railRoadImprovement, unit.cache.state)
}
/**

View File

@ -35,7 +35,7 @@ object TileDescription {
else
FormattedLine(tile.resource!!, link="Resource/${tile.resource}")
if (tile.resource != null && viewingCiv != null && tile.hasViewableResource(viewingCiv)) {
val resourceImprovement = tile.tileResource.getImprovements().firstOrNull { tile.improvementFunctions.canBuildImprovement(tile.ruleset.tileImprovements[it]!!, viewingCiv) }
val resourceImprovement = tile.tileResource.getImprovements().firstOrNull { tile.improvementFunctions.canBuildImprovement(tile.ruleset.tileImprovements[it]!!, viewingCiv.state) }
val tileImprovement = tile.ruleset.tileImprovements[resourceImprovement]
if (tileImprovement?.techRequired != null
&& !viewingCiv.tech.isResearched(tileImprovement.techRequired!!)) {

View File

@ -37,13 +37,13 @@ enum class ImprovementBuildingProblem(
class TileImprovementFunctions(val tile: Tile) {
/** Returns true if the [improvement] can be built on this [Tile] */
fun canBuildImprovement(improvement: TileImprovement, civInfo: Civilization): Boolean = getImprovementBuildingProblems(improvement, civInfo).none()
fun canBuildImprovement(improvement: TileImprovement, stateForConditionals: StateForConditionals): Boolean = getImprovementBuildingProblems(improvement, stateForConditionals).none()
/** Generates a sequence of reasons that prevent building given [improvement].
* If the sequence is empty, improvement can be built immediately.
*/
fun getImprovementBuildingProblems(improvement: TileImprovement, civInfo: Civilization): Sequence<ImprovementBuildingProblem> =
ImprovementFunctions.getImprovementBuildingProblems(improvement, civInfo, tile)
fun getImprovementBuildingProblems(improvement: TileImprovement, stateForConditionals: StateForConditionals): Sequence<ImprovementBuildingProblem> =
ImprovementFunctions.getImprovementBuildingProblems(improvement, stateForConditionals, tile)
/** Without regards to what CivInfo it is (so no tech requirement check), a lot of the checks are just for the improvement on the tile.
* Doubles as a check for the map editor.

View File

@ -179,10 +179,14 @@ class TileResource : RulesetStatsObject(), GameResource {
}
/** @return Of all the potential improvements in [getImprovements], the first this [civ] can actually build, if any. */
fun getImprovingImprovement(tile: Tile, civ: Civilization): String? {
return getImprovements().firstOrNull {
tile.improvementFunctions.canBuildImprovement(civ.gameInfo.ruleset.tileImprovements[it]!!, civ)
fun getImprovingImprovement(tile: Tile, stateForConditionals: StateForConditionals): String? {
if (stateForConditionals.civInfo != null) {
val civ: Civilization = stateForConditionals.civInfo
return getImprovements().firstOrNull {
tile.improvementFunctions.canBuildImprovement(civ.gameInfo.ruleset.tileImprovements[it]!!, stateForConditionals)
}
}
return null
}
fun matchesFilter(filter: String, state: StateForConditionals? = null): Boolean =

View File

@ -263,7 +263,7 @@ class CityScreen(
val improvementToPlace = pickTileData!!.improvement
return when {
tile.isMarkedForCreatesOneImprovement() -> Color.BROWN to 0.7f
!tile.improvementFunctions.canBuildImprovement(improvementToPlace, city.civ) -> Color.RED to 0.4f
!tile.improvementFunctions.canBuildImprovement(improvementToPlace, city.state) -> Color.RED to 0.4f
isExistingImprovementValuable(tile) -> Color.ORANGE to 0.5f
tile.improvement != null -> Color.YELLOW to 0.6f
tile.turnsToImprovement > 0 -> Color.YELLOW to 0.6f
@ -475,7 +475,7 @@ class CityScreen(
val pickTileData = this.pickTileData!!
this.pickTileData = null
val improvement = pickTileData.improvement
if (tileInfo.improvementFunctions.canBuildImprovement(improvement, city.civ)) {
if (tileInfo.improvementFunctions.canBuildImprovement(improvement, city.state)) {
if (pickTileData.isBuying) {
BuyButtonFactory(this).askToBuyConstruction(pickTileData.building, pickTileData.buyStat, tileInfo)
} else {

View File

@ -292,7 +292,7 @@ class CityStateDiplomacyTable(private val diplomacyScreen: DiplomacyScreen) {
for (improvableTile in improvableResourceTiles)
for (tileImprovement in improvements.values)
if (improvableTile.tileResource.isImprovedBy(tileImprovement.name)
&& improvableTile.improvementFunctions.canBuildImprovement(tileImprovement, otherCiv)
&& improvableTile.improvementFunctions.canBuildImprovement(tileImprovement, otherCiv.state)
)
needsImprovements = true
@ -372,7 +372,7 @@ class CityStateDiplomacyTable(private val diplomacyScreen: DiplomacyScreen) {
for (improvableTile in improvableResourceTiles) {
for (tileImprovement in tileImprovements.values) {
if (improvableTile.tileResource.isImprovedBy(tileImprovement.name)
&& improvableTile.improvementFunctions.canBuildImprovement(tileImprovement, otherCiv)
&& improvableTile.improvementFunctions.canBuildImprovement(tileImprovement, otherCiv.state)
) {
val improveTileButton =
"Build [${tileImprovement}] on [${improvableTile.tileResource}] (200 Gold)".toTextButton()

View File

@ -142,7 +142,7 @@ class ImprovementPickerScreen(
// *other* improvements with same shortcutKey
.filter { it.shortcutKey == improvement.shortcutKey && it != improvement }
// civ can build it (checks tech researched)
.filter { tile.improvementFunctions.canBuildImprovement(it, currentPlayerCiv) }
.filter { tile.improvementFunctions.canBuildImprovement(it, unit.cache.state) }
// is technologically more advanced
.filter { getRequiredTechColumn(it) > techLevel }
.any()
@ -283,10 +283,10 @@ class ImprovementPickerScreen(
private fun getProblemReport(improvement: TileImprovement) = getProblemReport(tile, tileWithoutLastTerrain, improvement)
private fun getProblemReport(tile: Tile, tileWithoutLastTerrain: Tile?, improvement: TileImprovement): ProblemReport? {
val report = ProblemReport()
var unbuildableBecause = tile.improvementFunctions.getImprovementBuildingProblems(improvement, currentPlayerCiv).toSet()
var unbuildableBecause = tile.improvementFunctions.getImprovementBuildingProblems(improvement, unit.cache.state).toSet()
if (!canReport(unbuildableBecause) && tileWithoutLastTerrain != null) {
// Try after pretending to have removed the top terrain layer.
unbuildableBecause = tileWithoutLastTerrain.improvementFunctions.getImprovementBuildingProblems(improvement, currentPlayerCiv).toSet()
unbuildableBecause = tileWithoutLastTerrain.improvementFunctions.getImprovementBuildingProblems(improvement, unit.cache.state).toSet()
if (!canReport(unbuildableBecause)) return null
report.suggestRemoval = true
}

View File

@ -287,9 +287,9 @@ object UnitActionsFromUniques {
private fun getWaterImprovementAction(unit: MapUnit, tile: Tile): UnitAction? {
if (!tile.isWater || !unit.hasUnique(UniqueType.CreateWaterImprovements) || tile.resource == null) return null
val improvementName = tile.tileResource.getImprovingImprovement(tile, unit.civ) ?: return null
val improvementName = tile.tileResource.getImprovingImprovement(tile, unit.cache.state) ?: return null
val improvement = tile.ruleset.tileImprovements[improvementName] ?: return null
if (!tile.improvementFunctions.canBuildImprovement(improvement, unit.civ)) return null
if (!tile.improvementFunctions.canBuildImprovement(improvement, unit.cache.state)) return null
return UnitAction(UnitActionType.CreateImprovement, 82f, "Create [$improvementName]",
action = {
@ -303,15 +303,16 @@ object UnitActionsFromUniques {
val uniquesToCheck = UnitActionModifiers.getUsableUnitActionUniques(unit, UniqueType.ConstructImprovementInstantly)
val civResources = unit.civ.getCivResourcesByName()
val stateForConditionals = StateForConditionals(civInfo = unit.civ, unit = unit, tile = tile)
for (unique in uniquesToCheck) {
val improvementFilter = unique.params[0]
val improvements = tile.ruleset.tileImprovements.values.filter { it.matchesFilter(improvementFilter, StateForConditionals(unit = unit, tile = tile)) }
val improvements = tile.ruleset.tileImprovements.values.filter { it.matchesFilter(improvementFilter, stateForConditionals) }
for (improvement in improvements) {
// Try to skip Improvements we can never build
// (getImprovementBuildingProblems catches those so the button is always disabled, but it nevertheless looks nicer)
if (tile.improvementFunctions.getImprovementBuildingProblems(improvement, unit.civ).any { it.permanent })
if (tile.improvementFunctions.getImprovementBuildingProblems(improvement, stateForConditionals).any { it.permanent })
continue
val resourcesAvailable = improvement.getMatchingUniques(UniqueType.ConsumesResources).none { improvementUnique ->
@ -335,7 +336,7 @@ object UnitActionsFromUniques {
}.takeIf {
resourcesAvailable
&& unit.hasMovement()
&& tile.improvementFunctions.canBuildImprovement(improvement, unit.civ)
&& tile.improvementFunctions.canBuildImprovement(improvement, unit.cache.state)
// Next test is to prevent interfering with UniqueType.CreatesOneImprovement -
// not pretty, but users *can* remove the building from the city queue an thus clear this:
&& !tile.isMarkedForCreatesOneImprovement()
@ -447,7 +448,7 @@ object UnitActionsFromUniques {
ImprovementPickerScreen.canReport(
tile.improvementFunctions.getImprovementBuildingProblems(
it,
unit.civ
unit.cache.state
).toSet()
)
&& unit.canBuildImprovement(it)

View File

@ -62,7 +62,7 @@ class TileImprovementConstructionTests {
city.civ = civInfo
}
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo)
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo.state)
Assert.assertTrue(improvement.name, canBeBuilt)
}
}
@ -80,7 +80,7 @@ class TileImprovementConstructionTests {
if (improvement.hasUnique(UniqueType.CanOnlyBeBuiltOnTile, StateForConditionals.IgnoreConditionals)) continue
tile.setTransients()
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo)
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo.state)
Assert.assertTrue(improvement.name, canBeBuilt)
}
}
@ -101,7 +101,7 @@ class TileImprovementConstructionTests {
civInfo.tech.addTechnology(tech.name)
city.civ = civInfo
}
val canBeBuilt = coastalTile.improvementFunctions.canBuildImprovement(improvement, civInfo)
val canBeBuilt = coastalTile.improvementFunctions.canBuildImprovement(improvement, civInfo.state)
Assert.assertTrue(improvement.name, canBeBuilt)
}
}
@ -113,7 +113,7 @@ class TileImprovementConstructionTests {
for (improvement in testGame.ruleset.tileImprovements.values) {
if (!improvement.uniques.contains("Can only be built on [Coastal] tiles")) continue
civInfo.setNameForUnitTests(improvement.uniqueTo ?: "OtherCiv")
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo)
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo.state)
Assert.assertFalse(improvement.name, canBeBuilt)
}
}
@ -124,7 +124,7 @@ class TileImprovementConstructionTests {
if (improvement.uniqueTo == null) continue
civInfo.setNameForUnitTests("OtherCiv")
val tile = tileMap[1,1]
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo)
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo.state)
Assert.assertFalse(improvement.name, canBeBuilt)
}
}
@ -142,7 +142,7 @@ class TileImprovementConstructionTests {
tile.baseTerrain = "Plains"
tile.resource = wrongResource.name
tile.setTransients()
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo)
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo.state)
Assert.assertFalse(improvement.name, canBeBuilt)
}
}
@ -177,7 +177,7 @@ class TileImprovementConstructionTests {
for (improvement in testGame.ruleset.tileImprovements.values) {
if (!improvement.uniques.contains("Cannot be built on [Bonus resource] tiles")) continue
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo)
val canBeBuilt = tile.improvementFunctions.canBuildImprovement(improvement, civInfo.state)
Assert.assertFalse(improvement.name, canBeBuilt)
}
}
@ -229,13 +229,13 @@ class TileImprovementConstructionTests {
val improvement = testGame.createTileImprovement()
Assert.assertFalse("Forest doesn't allow building unless allowed",
tile.improvementFunctions.canBuildImprovement(improvement, civInfo))
tile.improvementFunctions.canBuildImprovement(improvement, civInfo.state))
val allowedImprovement = testGame.createTileImprovement()
allowedImprovement.terrainsCanBeBuiltOn += "Forest"
Assert.assertTrue("Forest should allow building when allowed",
tile.improvementFunctions.canBuildImprovement(allowedImprovement, civInfo))
tile.improvementFunctions.canBuildImprovement(allowedImprovement, civInfo.state))
tile.setImprovement(allowedImprovement.name)
Assert.assertTrue(tile.improvement == allowedImprovement.name)
Assert.assertTrue("Forest should not be removed with this improvement", tile.terrainFeatures.contains("Forest"))
@ -248,7 +248,7 @@ class TileImprovementConstructionTests {
tile.addTerrainFeature("Forest")
val improvement = testGame.createTileImprovement("Does not need removal of [Forest]")
Assert.assertTrue(tile.improvementFunctions.canBuildImprovement(improvement, civInfo))
Assert.assertTrue(tile.improvementFunctions.canBuildImprovement(improvement, civInfo.state))
tile.setImprovement(improvement.name)
Assert.assertTrue(tile.improvement == improvement.name)
Assert.assertTrue("Forest should not be removed with this improvement", tile.terrainFeatures.contains("Forest"))