mirror of
https://github.com/yairm210/Unciv.git
synced 2025-03-03 22:22:51 +07:00
chore: improvement stat functions are more related to 'stat' than to 'improvement'
This commit is contained in:
parent
e21cfe8145
commit
38f544a35d
@ -1,7 +1,7 @@
|
||||
package com.unciv.logic.automation
|
||||
|
||||
import com.unciv.logic.city.CityFocus
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.city.CityFocus
|
||||
import com.unciv.logic.city.INonPerpetualConstruction
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.logic.map.BFS
|
||||
@ -389,7 +389,7 @@ object Automation {
|
||||
|
||||
// Improvements are good: less points
|
||||
if (tile.improvement != null &&
|
||||
tile.improvementFunctions.getImprovementStats(
|
||||
tile.stats.getImprovementStats(
|
||||
tile.getTileImprovement()!!,
|
||||
city.civ,
|
||||
city,
|
||||
|
@ -169,142 +169,6 @@ class TileInfoImprovementFunctions(val tile: Tile) {
|
||||
}
|
||||
|
||||
|
||||
// Also multiplies the stats by the percentage bonus for improvements (but not for tiles)
|
||||
fun getImprovementStats(
|
||||
improvement: TileImprovement,
|
||||
observingCiv: Civilization,
|
||||
city: City?,
|
||||
cityUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||
): Stats {
|
||||
val stats = improvement.cloneStats()
|
||||
if (tile.hasViewableResource(observingCiv) && tile.tileResource.isImprovedBy(improvement.name)
|
||||
&& tile.tileResource.improvementStats != null
|
||||
)
|
||||
stats.add(tile.tileResource.improvementStats!!.clone()) // resource-specific improvement
|
||||
|
||||
val conditionalState = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.Stats, conditionalState)) {
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.ImprovementStatsForAdjacencies, conditionalState)) {
|
||||
val adjacent = unique.params[1]
|
||||
val numberOfBonuses = tile.neighbors.count {
|
||||
it.matchesFilter(adjacent, observingCiv)
|
||||
|| it.getUnpillagedRoad().name == adjacent
|
||||
}
|
||||
stats.add(unique.stats.times(numberOfBonuses.toFloat()))
|
||||
}
|
||||
|
||||
if (city != null) stats.add(getImprovementStatsForCity(improvement, city, conditionalState, cityUniqueCache))
|
||||
|
||||
for ((stat, value) in getImprovementPercentageStats(improvement, observingCiv, city, cityUniqueCache)) {
|
||||
stats[stat] *= value.toPercent()
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
private fun getImprovementStatsForCity(
|
||||
improvement: TileImprovement,
|
||||
city: City,
|
||||
conditionalState: StateForConditionals,
|
||||
cityUniqueCache: LocalUniqueCache
|
||||
): Stats {
|
||||
val stats = Stats()
|
||||
|
||||
fun statsFromTiles(){
|
||||
// Since the conditionalState contains the current tile, it is different for each tile,
|
||||
// therefore if we want the cache to be useful it needs to hold the pre-filtered uniques,
|
||||
// and then for each improvement we'll filter the uniques locally.
|
||||
// This is still a MASSIVE save of RAM!
|
||||
val tileUniques = cityUniqueCache.get(UniqueType.StatsFromTiles.name,
|
||||
city.getMatchingUniques(UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals)
|
||||
.filter { city.matchesFilter(it.params[2]) }) // These are the uniques for all improvements for this city,
|
||||
.filter { it.conditionalsApply(conditionalState) } // ...and this is those with applicable conditions
|
||||
val improvementUniques =
|
||||
improvement.getMatchingUniques(UniqueType.ImprovementStatsOnTile, conditionalState)
|
||||
|
||||
for (unique in tileUniques + improvementUniques) {
|
||||
if (improvement.matchesFilter(unique.params[1])
|
||||
|| unique.params[1] == Constants.freshWater && tile.isAdjacentTo(Constants.freshWater)
|
||||
|| unique.params[1] == "non-fresh water" && !tile.isAdjacentTo(Constants.freshWater)
|
||||
)
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
}
|
||||
statsFromTiles()
|
||||
|
||||
fun statsFromObject() {
|
||||
// Same as above - cache holds unfiltered uniques for the city, while we use only the filtered ones
|
||||
val uniques = cityUniqueCache.get(UniqueType.StatsFromObject.name,
|
||||
city.getMatchingUniques(UniqueType.StatsFromObject, StateForConditionals.IgnoreConditionals))
|
||||
.filter { it.conditionalsApply(conditionalState) }
|
||||
for (unique in uniques) {
|
||||
if (improvement.matchesFilter(unique.params[1])) {
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
}
|
||||
}
|
||||
statsFromObject()
|
||||
return stats
|
||||
}
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
fun getImprovementPercentageStats(
|
||||
improvement: TileImprovement,
|
||||
observingCiv: Civilization,
|
||||
city: City?,
|
||||
cityUniqueCache: LocalUniqueCache
|
||||
): Stats {
|
||||
val stats = Stats()
|
||||
val conditionalState = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
|
||||
|
||||
// I would love to make an interface 'canCallMatchingUniques'
|
||||
// from which both cityInfo and CivilizationInfo derive, so I don't have to duplicate all this code
|
||||
// But something something too much for this PR.
|
||||
|
||||
if (city != null) {
|
||||
// As above, since the conditional is tile-dependant,
|
||||
// we save uniques in the cache without conditional filtering, and use only filtered ones
|
||||
val allStatPercentUniques = cityUniqueCache.get(UniqueType.AllStatsPercentFromObject.name,
|
||||
city.getMatchingUniques(UniqueType.AllStatsPercentFromObject, StateForConditionals.IgnoreConditionals))
|
||||
.filter { it.conditionalsApply(conditionalState) }
|
||||
for (unique in allStatPercentUniques) {
|
||||
if (!improvement.matchesFilter(unique.params[1])) continue
|
||||
for (stat in Stat.values()) {
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
// Same trick different unique - not sure if worth generalizing this 'late apply' of conditions?
|
||||
val statPercentUniques = cityUniqueCache.get(UniqueType.StatPercentFromObject.name,
|
||||
city.getMatchingUniques(UniqueType.StatPercentFromObject, StateForConditionals.IgnoreConditionals))
|
||||
.filter { it.conditionalsApply(conditionalState) }
|
||||
|
||||
for (unique in statPercentUniques) {
|
||||
if (!improvement.matchesFilter(unique.params[2])) continue
|
||||
val stat = Stat.valueOf(unique.params[1])
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
|
||||
} else {
|
||||
for (unique in observingCiv.getMatchingUniques(UniqueType.AllStatsPercentFromObject, conditionalState)) {
|
||||
if (!improvement.matchesFilter(unique.params[1])) continue
|
||||
for (stat in Stat.values()) {
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
}
|
||||
for (unique in observingCiv.getMatchingUniques(UniqueType.StatPercentFromObject, conditionalState)) {
|
||||
if (!improvement.matchesFilter(unique.params[2])) continue
|
||||
val stat = Stat.valueOf(unique.params[1])
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
|
||||
/** Marks tile as target tile for a building with a [UniqueType.CreatesOneImprovement] unique */
|
||||
fun markForCreatesOneImprovement(improvement: String) {
|
||||
|
@ -3,6 +3,7 @@ package com.unciv.logic.map.tile
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.models.ruleset.tile.TileImprovement
|
||||
import com.unciv.models.ruleset.unique.LocalUniqueCache
|
||||
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
@ -71,7 +72,7 @@ class TileStatFunctions(val tile: Tile) {
|
||||
|
||||
val improvement = tile.getUnpillagedTileImprovement()
|
||||
if (improvement != null)
|
||||
stats.add(tile.improvementFunctions.getImprovementStats(improvement, observingCiv, city, localUniqueCache))
|
||||
stats.add(getImprovementStats(improvement, observingCiv, city, localUniqueCache))
|
||||
|
||||
if (stats.gold != 0f && observingCiv.goldenAges.isGoldenAge())
|
||||
stats.gold++
|
||||
@ -174,4 +175,141 @@ class TileStatFunctions(val tile: Tile) {
|
||||
return stats.food + stats.production + stats.gold
|
||||
}
|
||||
|
||||
|
||||
// Also multiplies the stats by the percentage bonus for improvements (but not for tiles)
|
||||
fun getImprovementStats(
|
||||
improvement: TileImprovement,
|
||||
observingCiv: Civilization,
|
||||
city: City?,
|
||||
cityUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||
): Stats {
|
||||
val stats = improvement.cloneStats()
|
||||
if (tile.hasViewableResource(observingCiv) && tile.tileResource.isImprovedBy(improvement.name)
|
||||
&& tile.tileResource.improvementStats != null
|
||||
)
|
||||
stats.add(tile.tileResource.improvementStats!!.clone()) // resource-specific improvement
|
||||
|
||||
val conditionalState = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.Stats, conditionalState)) {
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.ImprovementStatsForAdjacencies, conditionalState)) {
|
||||
val adjacent = unique.params[1]
|
||||
val numberOfBonuses = tile.neighbors.count {
|
||||
it.matchesFilter(adjacent, observingCiv)
|
||||
|| it.getUnpillagedRoad().name == adjacent
|
||||
}
|
||||
stats.add(unique.stats.times(numberOfBonuses.toFloat()))
|
||||
}
|
||||
|
||||
if (city != null) stats.add(getImprovementStatsForCity(improvement, city, conditionalState, cityUniqueCache))
|
||||
|
||||
for ((stat, value) in getImprovementPercentageStats(improvement, observingCiv, city, cityUniqueCache)) {
|
||||
stats[stat] *= value.toPercent()
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
private fun getImprovementStatsForCity(
|
||||
improvement: TileImprovement,
|
||||
city: City,
|
||||
conditionalState: StateForConditionals,
|
||||
cityUniqueCache: LocalUniqueCache
|
||||
): Stats {
|
||||
val stats = Stats()
|
||||
|
||||
fun statsFromTiles(){
|
||||
// Since the conditionalState contains the current tile, it is different for each tile,
|
||||
// therefore if we want the cache to be useful it needs to hold the pre-filtered uniques,
|
||||
// and then for each improvement we'll filter the uniques locally.
|
||||
// This is still a MASSIVE save of RAM!
|
||||
val tileUniques = cityUniqueCache.get(UniqueType.StatsFromTiles.name,
|
||||
city.getMatchingUniques(UniqueType.StatsFromTiles, StateForConditionals.IgnoreConditionals)
|
||||
.filter { city.matchesFilter(it.params[2]) }) // These are the uniques for all improvements for this city,
|
||||
.filter { it.conditionalsApply(conditionalState) } // ...and this is those with applicable conditions
|
||||
val improvementUniques =
|
||||
improvement.getMatchingUniques(UniqueType.ImprovementStatsOnTile, conditionalState)
|
||||
|
||||
for (unique in tileUniques + improvementUniques) {
|
||||
if (improvement.matchesFilter(unique.params[1])
|
||||
|| unique.params[1] == Constants.freshWater && tile.isAdjacentTo(Constants.freshWater)
|
||||
|| unique.params[1] == "non-fresh water" && !tile.isAdjacentTo(Constants.freshWater)
|
||||
)
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
}
|
||||
statsFromTiles()
|
||||
|
||||
fun statsFromObject() {
|
||||
// Same as above - cache holds unfiltered uniques for the city, while we use only the filtered ones
|
||||
val uniques = cityUniqueCache.get(UniqueType.StatsFromObject.name,
|
||||
city.getMatchingUniques(UniqueType.StatsFromObject, StateForConditionals.IgnoreConditionals))
|
||||
.filter { it.conditionalsApply(conditionalState) }
|
||||
for (unique in uniques) {
|
||||
if (improvement.matchesFilter(unique.params[1])) {
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
}
|
||||
}
|
||||
statsFromObject()
|
||||
return stats
|
||||
}
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
fun getImprovementPercentageStats(
|
||||
improvement: TileImprovement,
|
||||
observingCiv: Civilization,
|
||||
city: City?,
|
||||
cityUniqueCache: LocalUniqueCache
|
||||
): Stats {
|
||||
val stats = Stats()
|
||||
val conditionalState = StateForConditionals(civInfo = observingCiv, city = city, tile = tile)
|
||||
|
||||
// I would love to make an interface 'canCallMatchingUniques'
|
||||
// from which both cityInfo and CivilizationInfo derive, so I don't have to duplicate all this code
|
||||
// But something something too much for this PR.
|
||||
|
||||
if (city != null) {
|
||||
// As above, since the conditional is tile-dependant,
|
||||
// we save uniques in the cache without conditional filtering, and use only filtered ones
|
||||
val allStatPercentUniques = cityUniqueCache.get(UniqueType.AllStatsPercentFromObject.name,
|
||||
city.getMatchingUniques(UniqueType.AllStatsPercentFromObject, StateForConditionals.IgnoreConditionals))
|
||||
.filter { it.conditionalsApply(conditionalState) }
|
||||
for (unique in allStatPercentUniques) {
|
||||
if (!improvement.matchesFilter(unique.params[1])) continue
|
||||
for (stat in Stat.values()) {
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
// Same trick different unique - not sure if worth generalizing this 'late apply' of conditions?
|
||||
val statPercentUniques = cityUniqueCache.get(UniqueType.StatPercentFromObject.name,
|
||||
city.getMatchingUniques(UniqueType.StatPercentFromObject, StateForConditionals.IgnoreConditionals))
|
||||
.filter { it.conditionalsApply(conditionalState) }
|
||||
|
||||
for (unique in statPercentUniques) {
|
||||
if (!improvement.matchesFilter(unique.params[2])) continue
|
||||
val stat = Stat.valueOf(unique.params[1])
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
|
||||
} else {
|
||||
for (unique in observingCiv.getMatchingUniques(UniqueType.AllStatsPercentFromObject, conditionalState)) {
|
||||
if (!improvement.matchesFilter(unique.params[1])) continue
|
||||
for (stat in Stat.values()) {
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
}
|
||||
for (unique in observingCiv.getMatchingUniques(UniqueType.StatPercentFromObject, conditionalState)) {
|
||||
if (!improvement.matchesFilter(unique.params[2])) continue
|
||||
val stat = Stat.valueOf(unique.params[1])
|
||||
stats[stat] += unique.params[0].toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -197,13 +197,13 @@ class CityScreen(
|
||||
fun isExistingImprovementValuable(tile: Tile, improvementToPlace: TileImprovement): Boolean {
|
||||
if (tile.improvement == null) return false
|
||||
val civInfo = city.civ
|
||||
val existingStats = tile.improvementFunctions.getImprovementStats(
|
||||
val existingStats = tile.stats.getImprovementStats(
|
||||
tile.getTileImprovement()!!,
|
||||
civInfo,
|
||||
city,
|
||||
cityUniqueCache
|
||||
)
|
||||
val replacingStats = tile.improvementFunctions.getImprovementStats(
|
||||
val replacingStats = tile.stats.getImprovementStats(
|
||||
improvementToPlace,
|
||||
civInfo,
|
||||
city,
|
||||
|
@ -155,7 +155,7 @@ class ImprovementPickerScreen(
|
||||
val statIcons = getStatIconsTable(provideResource, removeImprovement)
|
||||
|
||||
// get benefits of the new improvement
|
||||
val stats = tile.improvementFunctions.getImprovementStats(
|
||||
val stats = tile.stats.getImprovementStats(
|
||||
improvement,
|
||||
currentPlayerCiv,
|
||||
tile.getCity(),
|
||||
@ -164,7 +164,7 @@ class ImprovementPickerScreen(
|
||||
// subtract the benefits of the replaced improvement, if any
|
||||
val existingImprovement = tile.getTileImprovement()
|
||||
if (existingImprovement != null && removeImprovement) {
|
||||
val existingStats = tile.improvementFunctions.getImprovementStats(
|
||||
val existingStats = tile.stats.getImprovementStats(
|
||||
existingImprovement,
|
||||
currentPlayerCiv,
|
||||
tile.getCity(),
|
||||
|
Loading…
Reference in New Issue
Block a user