chore(purity): Automation

This commit is contained in:
yairm210 2025-08-12 09:24:27 +03:00
parent 74b32e137a
commit 7f690c3f51
5 changed files with 20 additions and 15 deletions

View File

@ -38,7 +38,7 @@ plugins {
// This is *with* gradle 8.2 downloaded according the project specs, no idea what that's about
kotlin("multiplatform") version "1.9.24"
kotlin("plugin.serialization") version "1.9.24"
id("io.github.yairm210.purity-plugin") version "1.1.0" apply(false)
id("io.github.yairm210.purity-plugin") version "1.1.1" apply(false)
}
allprojects {
@ -68,6 +68,8 @@ allprojects {
"kotlin.collections.sortBy", // moved
"kotlin.Throwable.getStackTrace", // moved
"kotlin.collections.random",
)
wellKnownPureClasses = setOf(
"java.lang.StackTraceElement" // moved

View File

@ -20,6 +20,7 @@ import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.ui.screens.victoryscreen.RankingType
import yairm210.purity.annotations.LocalState
import yairm210.purity.annotations.Readonly
import kotlin.math.min
@ -46,6 +47,7 @@ object Automation {
}
// More complicated logic to properly weigh Food vs other Stats (esp Production)
@Readonly
private fun getFoodModWeight(city: City, surplusFood: Float): Float {
val speed = city.civ.gameInfo.speed.modifier
// Zero out Growth if close to Unhappiness limit
@ -67,10 +69,10 @@ object Automation {
return 1f
}
@Readonly
fun rankStatsForCityWork(stats: Stats, city: City, areWeRankingSpecialist: Boolean, localUniqueCache: LocalUniqueCache): Float {
val cityAIFocus = city.getCityFocus()
val yieldStats = stats.clone()
val civPersonality = city.civ.getPersonality()
@LocalState val yieldStats = stats.clone()
val cityStatsObj = city.cityStats
val civInfo = city.civ
val allTechsAreResearched = civInfo.tech.allTechsAreResearched()
@ -168,7 +170,12 @@ object Automation {
}
// Apply City focus
cityAIFocus.applyWeightTo(yieldStats)
for (stat in cityAIFocus.statValuesForFocus) {
val currentStat = yieldStats[stat]
if (currentStat == 0f) continue
val statMultiplier = cityAIFocus.getStatMultiplier(stat)
yieldStats[stat] = currentStat * statMultiplier
}
return yieldStats.values.sum()
}
@ -206,6 +213,7 @@ object Automation {
return totalCarriableUnits < totalCarryingSlots
}
@Readonly
fun chooseMilitaryUnit(city: City, availableUnits: Sequence<BaseUnit>): String? {
val currentChoice = city.cityConstructions.getCurrentConstruction()
if (currentChoice is BaseUnit && !currentChoice.isCivilian()) return city.cityConstructions.currentConstructionFromQueue
@ -313,6 +321,7 @@ object Automation {
/** Checks both feasibility of Buildings with a CreatesOneImprovement unique
* and resource scarcity making a construction undesirable.
*/
@Readonly
fun allowAutomatedConstruction(
civInfo: Civilization,
city: City,
@ -325,6 +334,7 @@ object Automation {
@Suppress("MemberVisibilityCanBePrivate")
/** Checks both feasibility of Buildings with a [UniqueType.CreatesOneImprovement] unique (appropriate tile available).
* Constructions without pass uncontested. */
@Readonly
fun allowCreateImprovementBuildings(
civInfo: Civilization,
city: City,

View File

@ -69,19 +69,10 @@ enum class CityFocus(
else -> 1f
}
private val statValuesForFocus: List<Stat> by lazy {
val statValuesForFocus: List<Stat> by lazy {
Stat.entries.filter { getStatMultiplier(it) != 1f }
}
fun applyWeightTo(stats: Stats) {
for (stat in statValuesForFocus) {
val currentStat = stats[stat]
if (currentStat == 0f) continue
val statMultiplier = getStatMultiplier(stat)
stats[stat] = currentStat * statMultiplier
}
}
companion object {
@Pure fun safeValueOf(stat: Stat): CityFocus = entries.firstOrNull { it.stat == stat } ?: NoFocus

View File

@ -155,6 +155,7 @@ class CityStats(val city: City) {
return Stats(science = -25f, culture = -25f)
}
@Readonly
fun getGrowthBonus(totalFood: Float): StatMap {
val growthSources = StatMap()
val stateForConditionals = city.state

View File

@ -283,6 +283,7 @@ open class Stats(
}
}
@InternalState
class StatMap : LinkedHashMap<String,Stats>() {
fun add(source: String, stats: Stats) {
// We always clone to avoid touching the mutable stats of uniques