Perf: RequiresResource -> RequiredResources, for CivInfo.setTransients memory performance

Also a couple of other small perf changes
This commit is contained in:
yairm210 2024-04-25 14:48:03 +03:00
parent b67b92de45
commit 03dfd6ee82
7 changed files with 21 additions and 25 deletions

View File

@ -387,7 +387,7 @@ object NextTurnAutomation {
continue
val buildingToSell = civInfo.gameInfo.ruleset.buildings.values.filter {
city.cityConstructions.isBuilt(it.name)
&& it.requiresResource(resource, StateForConditionals(civInfo, city))
&& it.requiredResources(StateForConditionals(civInfo, city)).contains(resource)
&& it.isSellable()
&& !civInfo.civConstructions.hasFreeBuilding(city, it) }
.randomOrNull()

View File

@ -613,7 +613,7 @@ class Civilization : IsPartOfGameInfoSerialization {
fun isDefeated() = when {
isBarbarian() || isSpectator() -> false // Barbarians and voyeurs can't lose
hasEverOwnedOriginalCapital -> cities.isEmpty()
else -> units.getCivUnits().none()
else -> units.getCivUnitsSize() == 0
}
fun getEra(): Era = tech.era

View File

@ -49,9 +49,17 @@ class CivInfoTransientCache(val civInfo: Civilization) {
fun setTransients() {
val ruleset = civInfo.gameInfo.ruleset
val buildingsToRequiredResources = ruleset.buildings.values
.filter { civInfo.getEquivalentBuilding(it) == it }
.associateWith { it.requiredResources() }
val unitsToRequiredResources = ruleset.units.values
.filter { civInfo.getEquivalentUnit(it) == it }
.associateWith { it.requiredResources() }
for (resource in ruleset.tileResources.values.asSequence().filter { it.resourceType == ResourceType.Strategic }.map { it.name }) {
val applicableBuildings = ruleset.buildings.values.filter { it.requiresResource(resource, StateForConditionals.IgnoreConditionals) && civInfo.getEquivalentBuilding(it) == it }
val applicableUnits = ruleset.units.values.filter { it.requiresResource(resource, StateForConditionals.IgnoreConditionals) && civInfo.getEquivalentUnit(it) == it }
val applicableBuildings = buildingsToRequiredResources.filter { it.value.contains(resource) }.map { it.key }
val applicableUnits = unitsToRequiredResources.filter { it.value.contains(resource) }.map { it.key }
val lastEraForBuilding = applicableBuildings.maxOfOrNull { it.era(ruleset)?.eraNumber ?: 0 }
val lastEraForUnit = applicableUnits.maxOfOrNull { it.era(ruleset)?.eraNumber ?: 0 }

View File

@ -38,7 +38,7 @@ class Tile : IsPartOfGameInfoSerialization {
//region Serialized fields
var militaryUnit: MapUnit? = null
var civilianUnit: MapUnit? = null
var airUnits = ArrayList<MapUnit>()
var airUnits = ArrayList<MapUnit>(0)
var position: Vector2 = Vector2.Zero
lateinit var baseTerrain: String
@ -46,7 +46,7 @@ class Tile : IsPartOfGameInfoSerialization {
private set
/** Should be immutable - never be altered in-place, instead replaced */
var exploredBy = HashSet<String>()
var exploredBy = HashSet<String>(0)
var naturalWonder: String? = null
var resource: String? = null

View File

@ -568,12 +568,4 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
resourceRequirements[unique.params[1]] += unique.params[0].toInt()
return resourceRequirements
}
override fun requiresResource(resource: String, stateForConditionals: StateForConditionals?): Boolean {
if (getResourceRequirementsPerTurn(stateForConditionals).contains(resource)) return true
for (unique in getMatchingUniques(UniqueType.CostsResources, stateForConditionals)) {
if (unique.params[1] == resource) return true
}
return false
}
}

View File

@ -21,7 +21,7 @@ interface IConstruction : INamed {
/** Gets *per turn* resource requirements - does not include immediate costs for stockpiled resources.
* Uses [stateForConditionals] to determine which civ or city this is built for*/
fun getResourceRequirementsPerTurn(stateForConditionals: StateForConditionals? = null): Counter<String>
fun requiresResource(resource: String, stateForConditionals: StateForConditionals? = null): Boolean
fun requiredResources(stateForConditionals: StateForConditionals? = null): Set<String>
/** We can't call this getMatchingUniques because then it would conflict with IHasUniques */
fun getMatchingUniquesNotConflicting(uniqueType: UniqueType) = sequenceOf<Unique>()
}
@ -103,6 +103,11 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
override fun getMatchingUniquesNotConflicting(uniqueType: UniqueType): Sequence<Unique> =
getMatchingUniques(uniqueType)
override fun requiredResources(stateForConditionals: StateForConditionals?): Set<String> {
return getResourceRequirementsPerTurn(stateForConditionals).keys +
getMatchingUniques(UniqueType.CostsResources, stateForConditionals).map { it.params[1] }
}
}
@ -249,8 +254,7 @@ open class PerpetualConstruction(override var name: String, val description: Str
override fun getResourceRequirementsPerTurn(stateForConditionals: StateForConditionals?) = Counter.ZERO
override fun requiresResource(resource: String, stateForConditionals: StateForConditionals?) = false
override fun requiredResources(stateForConditionals: StateForConditionals?): Set<String> = emptySet()
}
open class PerpetualStatConversion(val stat: Stat) :

View File

@ -420,14 +420,6 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
return resourceRequirements
}
override fun requiresResource(resource: String, stateForConditionals: StateForConditionals?): Boolean {
if (getResourceRequirementsPerTurn(stateForConditionals).contains(resource)) return true
for (unique in getMatchingUniques(UniqueType.CostsResources, stateForConditionals)) {
if (unique.params[1] == resource) return true
}
return false
}
fun isRanged() = rangedStrength > 0
fun isMelee() = !isRanged() && strength > 0