chore(purity) - Etc

This commit is contained in:
yairm210 2025-08-17 15:03:12 +03:00
parent fb107465a4
commit 6c3b6f0d04
7 changed files with 17 additions and 8 deletions

View File

@ -49,7 +49,7 @@ allprojects {
apply(plugin = "io.github.yairm210.purity-plugin") apply(plugin = "io.github.yairm210.purity-plugin")
configure<yairm210.purity.PurityConfiguration>{ configure<yairm210.purity.PurityConfiguration>{
wellKnownPureFunctions = setOf( wellKnownPureFunctions = setOf(
"kotlin.with", "kotlin.with", // moved
) )
wellKnownReadonlyFunctions = setOf( wellKnownReadonlyFunctions = setOf(
"com.badlogic.gdx.math.Vector2.len", "com.badlogic.gdx.math.Vector2.len",
@ -63,9 +63,6 @@ allprojects {
"com.badlogic.gdx.files.FileHandle.isFile", "com.badlogic.gdx.files.FileHandle.isFile",
"com.badlogic.gdx.files.FileHandle.name", "com.badlogic.gdx.files.FileHandle.name",
"kotlin.collections.sortBy", // moved
"kotlin.Throwable.getStackTrace", // moved
"kotlin.collections.random", "kotlin.collections.random",
"kotlin.hashCode", "kotlin.hashCode",
"kotlin.collections.shuffled", "kotlin.collections.shuffled",

View File

@ -192,7 +192,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions) {
// Is there already a Workboat nearby? // Is there already a Workboat nearby?
// todo Still ignores whether that boat can reach the not-yet-found tile to improve // todo Still ignores whether that boat can reach the not-yet-found tile to improve
val twoTurnsMovement = buildableWorkboatUnits.maxOf { it.movement } * 2 val twoTurnsMovement = buildableWorkboatUnits.maxOf { it.movement } * 2
fun MapUnit.isOurWorkBoat() = cache.hasUniqueToCreateWaterImprovements && this.civ == this@ConstructionAutomation.civInfo @Readonly fun MapUnit.isOurWorkBoat() = cache.hasUniqueToCreateWaterImprovements
&& this.civ == this@ConstructionAutomation.civInfo
val alreadyHasWorkBoat = city.getCenterTile().getTilesInDistance(twoTurnsMovement) val alreadyHasWorkBoat = city.getCenterTile().getTilesInDistance(twoTurnsMovement)
.any { it.civilianUnit?.isOurWorkBoat() == true } .any { it.civilianUnit?.isOurWorkBoat() == true }
if (alreadyHasWorkBoat) return if (alreadyHasWorkBoat) return

View File

@ -230,6 +230,7 @@ object NextTurnAutomation {
} }
private fun chooseTechToResearch(civInfo: Civilization) { private fun chooseTechToResearch(civInfo: Civilization) {
@Readonly
fun getGroupedResearchableTechs(): List<List<Technology>> { fun getGroupedResearchableTechs(): List<List<Technology>> {
val researchableTechs = civInfo.gameInfo.ruleset.technologies.values val researchableTechs = civInfo.gameInfo.ruleset.technologies.values
.asSequence() .asSequence()
@ -407,7 +408,7 @@ object NextTurnAutomation {
} }
/** All units will continue after this to the regular automation, so units not moved in this function will still move */ /** All units will continue after this to the regular automation, so units not moved in this function will still move */
fun automateCityConquer(civInfo: Civilization, city: City){ private fun automateCityConquer(civInfo: Civilization, city: City){
@Readonly fun ourUnitsInRange(range: Int) = city.getCenterTile().getTilesInDistance(range) @Readonly fun ourUnitsInRange(range: Int) = city.getCenterTile().getTilesInDistance(range)
.mapNotNull { it.militaryUnit }.filter { it.civ == civInfo }.toList() .mapNotNull { it.militaryUnit }.filter { it.civ == civInfo }.toList()

View File

@ -11,6 +11,7 @@ import com.unciv.logic.map.tile.RoadStatus
import com.unciv.logic.map.tile.Tile import com.unciv.logic.map.tile.Tile
import com.unciv.utils.Log import com.unciv.utils.Log
import com.unciv.utils.debug import com.unciv.utils.debug
import yairm210.purity.annotations.Readonly
/** Responsible for automation the "build road to" action /** Responsible for automation the "build road to" action
@ -140,6 +141,7 @@ class RoadToAutomation(val civInfo: Civilization) {
/** Conditions for whether it is acceptable to build a road on this tile */ /** Conditions for whether it is acceptable to build a road on this tile */
@Readonly
fun shouldBuildRoadOnTile(tile: Tile): Boolean { fun shouldBuildRoadOnTile(tile: Tile): Boolean {
if (tile.roadIsPillaged) return true if (tile.roadIsPillaged) return true
return !tile.isCityCenter() // Can't build road on city tiles return !tile.isCityCenter() // Can't build road on city tiles

View File

@ -151,6 +151,7 @@ object SpecificUnitAutomation {
if (bestCityLocation == null) { if (bestCityLocation == null) {
// Find the best tile that is within // Find the best tile that is within
@Readonly
fun isTileRankOK(it: Map.Entry<Tile, Float>): Boolean { fun isTileRankOK(it: Map.Entry<Tile, Float>): Boolean {
if (it.key in dangerousTiles && it.key != unit.getTile()) return false if (it.key in dangerousTiles && it.key != unit.getTile()) return false
val pathSize = unit.movement.getShortestPath(it.key).size val pathSize = unit.movement.getShortestPath(it.key).size
@ -174,6 +175,7 @@ object SpecificUnitAutomation {
// Try to move towards the frontier // Try to move towards the frontier
/** @return the number of tiles 4 (un-modded) out from this city that could hold a city, ie how lonely this city is */ /** @return the number of tiles 4 (un-modded) out from this city that could hold a city, ie how lonely this city is */
@Readonly
fun getFrontierScore(city: City) = city.getCenterTile() fun getFrontierScore(city: City) = city.getCenterTile()
.getTilesAtDistance(city.civ.gameInfo.ruleset.modOptions.constants.minimalCityDistance + 1) .getTilesAtDistance(city.civ.gameInfo.ruleset.modOptions.constants.minimalCityDistance + 1)
.count { it.canBeSettled() && (it.getOwner() == null || it.getOwner() == city.civ ) } .count { it.canBeSettled() && (it.getOwner() == null || it.getOwner() == city.civ ) }
@ -198,6 +200,7 @@ object SpecificUnitAutomation {
//Settle if we're already on the best tile, before looking if we should retreat from barbarians //Settle if we're already on the best tile, before looking if we should retreat from barbarians
if (tryRunAwayIfNeccessary(unit)) return if (tryRunAwayIfNeccessary(unit)) return
unit.movement.headTowards(bestCityLocation) unit.movement.headTowards(bestCityLocation)
val shouldSettleNow = (unit.getTile() == bestCityLocation && unit.hasMovement())
if (shouldSettle) foundCityAction.action.invoke() if (shouldSettle) foundCityAction.action.invoke()
//TODO: evaluate 1-tile move with settle on same turn as "safe" //TODO: evaluate 1-tile move with settle on same turn as "safe"
} }

View File

@ -400,7 +400,8 @@ class WorkerAutomation(
val lastTerrain = tile.lastTerrain val lastTerrain = tile.lastTerrain
fun isRemovable(terrain: Terrain): Boolean = potentialTileImprovements.containsKey(Constants.remove + terrain.name) @Readonly fun isRemovable(terrain: Terrain): Boolean =
potentialTileImprovements.containsKey(Constants.remove + terrain.name)
val improvementStringForResource: String? = when { val improvementStringForResource: String? = when {
tile.resource == null || !tile.hasViewableResource(civInfo) -> null tile.resource == null || !tile.hasViewableResource(civInfo) -> null
@ -653,6 +654,7 @@ class WorkerAutomation(
* @param isCitadel Controls within borders check - true also allows 1 tile outside borders * @param isCitadel Controls within borders check - true also allows 1 tile outside borders
* @return Yes the location is good for a Fort here * @return Yes the location is good for a Fort here
*/ */
@Readonly
fun evaluateFortPlacement(tile: Tile, isCitadel: Boolean): Boolean { fun evaluateFortPlacement(tile: Tile, isCitadel: Boolean): Boolean {
return tile.improvement != Constants.fort // don't build fort if it is already here return tile.improvement != Constants.fort // don't build fort if it is already here
&& evaluateFortSurroundings(tile, isCitadel) > 0 && evaluateFortSurroundings(tile, isCitadel) > 0

View File

@ -25,6 +25,7 @@ import com.unciv.models.stats.SubStat
import com.unciv.ui.components.UnitMovementMemoryType import com.unciv.ui.components.UnitMovementMemoryType
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsPillage import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsPillage
import com.unciv.utils.debug import com.unciv.utils.debug
import yairm210.purity.annotations.Pure
import yairm210.purity.annotations.Readonly import yairm210.purity.annotations.Readonly
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -306,6 +307,7 @@ object Battle {
} }
/** See [UniqueType.KillUnitPlunder] for params */ /** See [UniqueType.KillUnitPlunder] for params */
@Readonly
private fun getKillUnitPlunderUniques(civUnit: ICombatant, defeatedUnit: MapUnitCombatant): ArrayList<Unique> { private fun getKillUnitPlunderUniques(civUnit: ICombatant, defeatedUnit: MapUnitCombatant): ArrayList<Unique> {
val bonusUniques = ArrayList<Unique>() val bonusUniques = ArrayList<Unique>()
@ -332,7 +334,7 @@ object Battle {
* @param defenderDealt Damage done by defender to attacker * @param defenderDealt Damage done by defender to attacker
*/ */
data class DamageDealt(val attackerDealt: Int, val defenderDealt: Int) { data class DamageDealt(val attackerDealt: Int, val defenderDealt: Int) {
operator fun plus(other: DamageDealt) = @Pure operator fun plus(other: DamageDealt) =
DamageDealt(attackerDealt + other.attackerDealt, defenderDealt + other.defenderDealt) DamageDealt(attackerDealt + other.attackerDealt, defenderDealt + other.defenderDealt)
companion object { companion object {
val None = DamageDealt(0, 0) val None = DamageDealt(0, 0)
@ -707,6 +709,7 @@ object Battle {
val fromTile = defender.getTile() val fromTile = defender.getTile()
val attackerTile = attacker.getTile() val attackerTile = attacker.getTile()
@Readonly
fun canNotWithdrawTo(tile: Tile): Boolean { // if the tile is what the defender can't withdraw to, this fun will return true fun canNotWithdrawTo(tile: Tile): Boolean { // if the tile is what the defender can't withdraw to, this fun will return true
return !defender.unit.movement.canMoveTo(tile) return !defender.unit.movement.canMoveTo(tile)
|| defender.isLandUnit() && !tile.isLand // forbid retreat from land to sea - embarked already excluded || defender.isLandUnit() && !tile.isLand // forbid retreat from land to sea - embarked already excluded