Terrainfeature objects transient (#6199)

* terrainFeatures is only set through the setTerrainFeatures function

* Use cached terrainFeatures for performance

* Fixed map editor error due to not setting tileinfo ruleset
Added private set to terrainfeatureobjects
This commit is contained in:
Yair Morgenstern
2022-02-22 11:28:24 +02:00
committed by GitHub
parent c9945ca7ba
commit ca5f48ad61
8 changed files with 39 additions and 32 deletions

View File

@ -110,7 +110,7 @@ class BarbarianManager {
val viableTiles = fogTiles.filter {
!it.isImpassible()
&& it.resource == null
&& it.terrainFeatures.none { feature -> gameInfo.ruleSet.terrains[feature]!!.hasUnique("Only [] improvements may be built on this tile") }
&& it.terrainFeatureObjects.none { feature -> feature.hasUnique("Only [] improvements may be built on this tile") }
&& it.neighbors.any { neighbor -> neighbor.isLand }
&& it !in tooCloseToCapitals
&& it !in tooCloseToCamps

View File

@ -712,13 +712,12 @@ object Battle {
}
tile.roadStatus = RoadStatus.None
if (tile.isLand && !tile.isImpassible() && !tile.terrainFeatures.contains("Fallout")) {
val ruleset = tile.ruleset
val destructionChance = if (tile.hasUnique(UniqueType.ResistsNukes)) 0.25f
else 0.5f
if (Random().nextFloat() < destructionChance) {
for (terrainFeature in tile.terrainFeatures)
if (ruleset.terrains[terrainFeature]!!.hasUnique(UniqueType.DestroyableByNukes))
tile.removeTerrainFeature(terrainFeature)
for (terrainFeature in tile.terrainFeatureObjects)
if (terrainFeature.hasUnique(UniqueType.DestroyableByNukes))
tile.removeTerrainFeature(terrainFeature.name)
tile.addTerrainFeature("Fallout")
}
}

View File

@ -66,6 +66,11 @@ open class TileInfo {
var position: Vector2 = Vector2.Zero
lateinit var baseTerrain: String
var terrainFeatures: List<String> = listOf()
private set
@Transient
var terrainFeatureObjects: List<Terrain> = listOf()
private set
var naturalWonder: String? = null
@ -235,11 +240,10 @@ open class TileInfo {
return civInfo.isAtWarWith(tileOwner)
}
fun getTerrainFeaturesObjects(): List<Terrain> = terrainFeatures.mapNotNull { ruleset.terrains[it] }
fun getAllTerrains(): Sequence<Terrain> = sequence {
yield(baseTerrainObject)
if (naturalWonder != null) yield(getNaturalWonder())
yieldAll(terrainFeatures.asSequence().mapNotNull { ruleset.terrains[it] })
yieldAll(terrainFeatureObjects)
}
fun isRoughTerrain() = getAllTerrains().any{ it.isRough() }
@ -269,7 +273,7 @@ open class TileInfo {
val stateForConditionals = StateForConditionals(civInfo = observingCiv, cityInfo = city, tile = this);
for (terrainFeatureBase in getTerrainFeaturesObjects()) {
for (terrainFeatureBase in terrainFeatureObjects) {
when {
terrainFeatureBase.hasUnique(UniqueType.NullifyYields) ->
return terrainFeatureBase.cloneStats()
@ -365,7 +369,7 @@ open class TileInfo {
private fun getTileStartYield(isCenter: Boolean): Float {
var stats = getBaseTerrain().cloneStats()
for (terrainFeatureBase in getTerrainFeaturesObjects()) {
for (terrainFeatureBase in terrainFeatureObjects) {
if (terrainFeatureBase.overrideStats)
stats = terrainFeatureBase.cloneStats()
else
@ -871,13 +875,16 @@ open class TileInfo {
}
}
fun addTerrainFeature(terrainFeature:String) {
terrainFeatures = ArrayList(terrainFeatures).apply { add(terrainFeature) }
fun setTerrainFeatures(terrainFeatureList:List<String>){
terrainFeatures = terrainFeatureList
terrainFeatureObjects = terrainFeatureList.mapNotNull { ruleset.terrains[it] }
}
fun removeTerrainFeature(terrainFeature: String) {
terrainFeatures = ArrayList(terrainFeatures).apply { remove(terrainFeature) }
}
fun addTerrainFeature(terrainFeature:String) =
setTerrainFeatures(ArrayList(terrainFeatures).apply { add(terrainFeature) })
fun removeTerrainFeature(terrainFeature: String) =
setTerrainFeatures(ArrayList(terrainFeatures).apply { remove(terrainFeature) })
/** If the unit isn't in the ruleset we can't even know what type of unit this is! So check each place
@ -906,7 +913,7 @@ open class TileInfo {
if (naturalWonder != null) {
val naturalWonder = ruleset.terrains[naturalWonder]!!
baseTerrain = naturalWonder.turnsInto!!
terrainFeatures = listOf()
setTerrainFeatures(listOf())
resource = null
improvement = null
}
@ -962,7 +969,7 @@ open class TileInfo {
val newTerrainFeatures = ArrayList<String>()
newTerrainFeatures.add(Constants.hill)
newTerrainFeatures.addAll(copy)
terrainFeatures = newTerrainFeatures
setTerrainFeatures(newTerrainFeatures)
}
}

View File

@ -476,7 +476,7 @@ class MapRegions (val ruleset: Ruleset){
val panicPosition = region.rect.getPosition(Vector2())
val panicTerrain = ruleset.terrains.values.first { it.type == TerrainType.Land }.name
region.tileMap[panicPosition].baseTerrain = panicTerrain
region.tileMap[panicPosition].terrainFeatures = listOf()
region.tileMap[panicPosition].setTerrainFeatures(listOf())
setRegionStart(region, panicPosition)
}
@ -487,7 +487,7 @@ class MapRegions (val ruleset: Ruleset){
private fun normalizeStart(startTile: TileInfo, tileMap: TileMap, minorCiv: Boolean) {
// Remove ice-like features adjacent to start
for (tile in startTile.neighbors) {
val lastTerrain = tile.getTerrainFeaturesObjects().lastOrNull { it.impassable }
val lastTerrain = tile.terrainFeatureObjects.lastOrNull { it.impassable }
if (lastTerrain != null) {
tile.removeTerrainFeature(lastTerrain.name)
}
@ -608,7 +608,7 @@ class MapRegions (val ruleset: Ruleset){
// Start with list of candidate plots sorted in ring order 1,2,3
val candidatePlots = startTile.getTilesInDistanceRange(1..rangeForBonuses)
.filter { it.resource == null && oasisEquivalent !in it.getTerrainFeaturesObjects() }
.filter { it.resource == null && oasisEquivalent !in it.terrainFeatureObjects }
.shuffled().sortedBy { it.aerialDistanceTo(startTile) }.toMutableList()
// Place food bonuses (and oases) as able
@ -1658,8 +1658,8 @@ class MapRegions (val ruleset: Ruleset){
// Check first available out of unbuildable features, then other features, then base terrain
val terrainToCheck = if (tile.terrainFeatures.isEmpty()) tile.getBaseTerrain()
else tile.getTerrainFeaturesObjects().firstOrNull { it.unbuildable }
?: tile.getTerrainFeaturesObjects().first()
else tile.terrainFeatureObjects.firstOrNull { it.unbuildable }
?: tile.terrainFeatureObjects.first()
// Add all applicable qualities
for (unique in terrainToCheck.getMatchingUniques(UniqueType.HasQuality, StateForConditionals(region = region))) {
@ -1765,7 +1765,7 @@ class Region (val tileMap: TileMap, val rect: Rectangle, val continentID: Int =
terrainCounts.clear()
for (tile in tiles) {
val terrainsToCount = if (tile.getAllTerrains().any { it.hasUnique(UniqueType.IgnoreBaseTerrainForRegion) })
tile.getTerrainFeaturesObjects().map { it.name }.asSequence()
tile.terrainFeatureObjects.map { it.name }.asSequence()
else
tile.getAllTerrains().map { it.name }
for (terrain in terrainsToCount) {

View File

@ -167,7 +167,7 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration
}
private fun clearTile(tile: TileInfo){
tile.terrainFeatures = listOf()
tile.setTerrainFeatures(listOf())
tile.resource = null
tile.improvement = null
tile.setTerrainTransients()

View File

@ -83,7 +83,7 @@ class MapEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(BaseScr
terrainFeaturesTable.add(getHex(ImageGetter.getRedCross(50f, 0.6f)).apply {
onClick {
tileAction = {
it.terrainFeatures = listOf()
it.setTerrainFeatures(listOf())
it.naturalWonder = null
it.hasBottomRiver = false
it.hasBottomLeftRiver = false
@ -321,6 +321,7 @@ class MapEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(BaseScr
private fun addTerrainOptions(terrainFeaturesTable: Table, baseTerrainTable: Table) {
for (terrain in ruleset.terrains.values) {
val tileInfo = TileInfo()
tileInfo.ruleset = ruleset
if (terrain.type == TerrainType.TerrainFeature) {
tileInfo.baseTerrain = when {
terrain.occursOn.isNotEmpty() -> terrain.occursOn.first()

View File

@ -87,7 +87,7 @@ class TileMapTests {
tile1.baseTerrain = Constants.hill
tile1.setTerrainTransients()
tile2.baseTerrain = Constants.grassland
tile2.terrainFeatures = listOf(Constants.forest)
tile2.setTerrainFeatures(listOf(Constants.forest))
tile2.setTerrainTransients()
tile3.baseTerrain = Constants.coast
tile3.setTerrainTransients()
@ -114,7 +114,7 @@ class TileMapTests {
@Test
fun canSeeMountainFromForestOverHills() {
tile1.baseTerrain = Constants.grassland
tile1.terrainFeatures = listOf(Constants.forest)
tile1.setTerrainFeatures(listOf(Constants.forest))
tile1.setTerrainTransients()
tile2.baseTerrain = Constants.hill
tile2.setTerrainTransients()
@ -131,7 +131,7 @@ class TileMapTests {
tile1.baseTerrain = Constants.hill
tile1.setTerrainTransients()
tile2.baseTerrain = Constants.grassland
tile2.terrainFeatures = listOf(Constants.forest)
tile1.setTerrainFeatures(listOf(Constants.forest))
tile2.setTerrainTransients()
tile3.baseTerrain = Constants.hill
tile3.setTerrainTransients()
@ -172,10 +172,10 @@ class TileMapTests {
@Test
fun canNOTSeeOutThroughForest() {
tile1.baseTerrain = Constants.grassland
tile1.terrainFeatures = listOf(Constants.forest)
tile1.setTerrainFeatures(listOf(Constants.forest))
tile1.setTerrainTransients()
tile2.baseTerrain = Constants.grassland
tile2.terrainFeatures = listOf(Constants.forest)
tile2.setTerrainFeatures(listOf(Constants.forest))
tile2.setTerrainTransients()
tile3.baseTerrain = Constants.grassland
tile3.setTerrainTransients()
@ -190,7 +190,7 @@ class TileMapTests {
tile1.baseTerrain = Constants.coast
tile1.setTerrainTransients()
tile2.baseTerrain = Constants.grassland
tile2.terrainFeatures = listOf(Constants.jungle)
tile2.setTerrainFeatures(listOf(Constants.forest))
tile2.setTerrainTransients()
tile3.baseTerrain = Constants.coast
tile3.setTerrainTransients()

View File

@ -54,7 +54,7 @@ class UnitMovementAlgorithmsTests {
fun canPassThroughPassableTerrains() {
for (terrain in ruleSet.terrains.values) {
tile.baseTerrain = terrain.name
tile.terrainFeatures = listOf()
tile.setTerrainFeatures(listOf())
tile.setTransients()
unit.baseUnit = BaseUnit().apply { unitType = "Sword"; ruleset = ruleSet }
@ -112,7 +112,7 @@ class UnitMovementAlgorithmsTests {
@Test
fun canNOTEnterIce() {
tile.baseTerrain = Constants.ocean
tile.terrainFeatures = listOf(Constants.ice)
tile.setTerrainFeatures(listOf(Constants.ice))
tile.setTransients()
for (type in ruleSet.unitTypes) {