From 6c3b6f0d04ba74ea60d1a8335d96d413137986d4 Mon Sep 17 00:00:00 2001 From: yairm210 Date: Sun, 17 Aug 2025 15:03:12 +0300 Subject: [PATCH] chore(purity) - Etc --- build.gradle.kts | 5 +---- .../unciv/logic/automation/city/ConstructionAutomation.kt | 3 ++- .../logic/automation/civilization/NextTurnAutomation.kt | 3 ++- core/src/com/unciv/logic/automation/unit/RoadToAutomation.kt | 2 ++ .../unciv/logic/automation/unit/SpecificUnitAutomation.kt | 3 +++ core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt | 4 +++- core/src/com/unciv/logic/battle/Battle.kt | 5 ++++- 7 files changed, 17 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6992659e6e..b200860f6c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -49,7 +49,7 @@ allprojects { apply(plugin = "io.github.yairm210.purity-plugin") configure{ wellKnownPureFunctions = setOf( - "kotlin.with", + "kotlin.with", // moved ) wellKnownReadonlyFunctions = setOf( "com.badlogic.gdx.math.Vector2.len", @@ -63,9 +63,6 @@ allprojects { "com.badlogic.gdx.files.FileHandle.isFile", "com.badlogic.gdx.files.FileHandle.name", - "kotlin.collections.sortBy", // moved - "kotlin.Throwable.getStackTrace", // moved - "kotlin.collections.random", "kotlin.hashCode", "kotlin.collections.shuffled", diff --git a/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt b/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt index d1f34a03f2..34c46112d2 100644 --- a/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt +++ b/core/src/com/unciv/logic/automation/city/ConstructionAutomation.kt @@ -192,7 +192,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions) { // Is there already a Workboat nearby? // todo Still ignores whether that boat can reach the not-yet-found tile to improve 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) .any { it.civilianUnit?.isOurWorkBoat() == true } if (alreadyHasWorkBoat) return diff --git a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt index a0219fce56..53077ca7c9 100644 --- a/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/NextTurnAutomation.kt @@ -230,6 +230,7 @@ object NextTurnAutomation { } private fun chooseTechToResearch(civInfo: Civilization) { + @Readonly fun getGroupedResearchableTechs(): List> { val researchableTechs = civInfo.gameInfo.ruleset.technologies.values .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 */ - fun automateCityConquer(civInfo: Civilization, city: City){ + private fun automateCityConquer(civInfo: Civilization, city: City){ @Readonly fun ourUnitsInRange(range: Int) = city.getCenterTile().getTilesInDistance(range) .mapNotNull { it.militaryUnit }.filter { it.civ == civInfo }.toList() diff --git a/core/src/com/unciv/logic/automation/unit/RoadToAutomation.kt b/core/src/com/unciv/logic/automation/unit/RoadToAutomation.kt index e382658ff2..95de78198f 100644 --- a/core/src/com/unciv/logic/automation/unit/RoadToAutomation.kt +++ b/core/src/com/unciv/logic/automation/unit/RoadToAutomation.kt @@ -11,6 +11,7 @@ import com.unciv.logic.map.tile.RoadStatus import com.unciv.logic.map.tile.Tile import com.unciv.utils.Log import com.unciv.utils.debug +import yairm210.purity.annotations.Readonly /** 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 */ + @Readonly fun shouldBuildRoadOnTile(tile: Tile): Boolean { if (tile.roadIsPillaged) return true return !tile.isCityCenter() // Can't build road on city tiles diff --git a/core/src/com/unciv/logic/automation/unit/SpecificUnitAutomation.kt b/core/src/com/unciv/logic/automation/unit/SpecificUnitAutomation.kt index ae01f51c7a..6ab1a18fba 100644 --- a/core/src/com/unciv/logic/automation/unit/SpecificUnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/unit/SpecificUnitAutomation.kt @@ -151,6 +151,7 @@ object SpecificUnitAutomation { if (bestCityLocation == null) { // Find the best tile that is within + @Readonly fun isTileRankOK(it: Map.Entry): Boolean { if (it.key in dangerousTiles && it.key != unit.getTile()) return false val pathSize = unit.movement.getShortestPath(it.key).size @@ -174,6 +175,7 @@ object SpecificUnitAutomation { // 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 */ + @Readonly fun getFrontierScore(city: City) = city.getCenterTile() .getTilesAtDistance(city.civ.gameInfo.ruleset.modOptions.constants.minimalCityDistance + 1) .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 if (tryRunAwayIfNeccessary(unit)) return unit.movement.headTowards(bestCityLocation) + val shouldSettleNow = (unit.getTile() == bestCityLocation && unit.hasMovement()) if (shouldSettle) foundCityAction.action.invoke() //TODO: evaluate 1-tile move with settle on same turn as "safe" } diff --git a/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt b/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt index 7afa48e35d..459d4d4996 100644 --- a/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt +++ b/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt @@ -400,7 +400,8 @@ class WorkerAutomation( 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 { 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 * @return Yes the location is good for a Fort here */ + @Readonly fun evaluateFortPlacement(tile: Tile, isCitadel: Boolean): Boolean { return tile.improvement != Constants.fort // don't build fort if it is already here && evaluateFortSurroundings(tile, isCitadel) > 0 diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index 32b9146e01..e3e5428b2c 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -25,6 +25,7 @@ import com.unciv.models.stats.SubStat import com.unciv.ui.components.UnitMovementMemoryType import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsPillage import com.unciv.utils.debug +import yairm210.purity.annotations.Pure import yairm210.purity.annotations.Readonly import kotlin.math.max import kotlin.math.min @@ -306,6 +307,7 @@ object Battle { } /** See [UniqueType.KillUnitPlunder] for params */ + @Readonly private fun getKillUnitPlunderUniques(civUnit: ICombatant, defeatedUnit: MapUnitCombatant): ArrayList { val bonusUniques = ArrayList() @@ -332,7 +334,7 @@ object Battle { * @param defenderDealt Damage done by defender to attacker */ 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) companion object { val None = DamageDealt(0, 0) @@ -707,6 +709,7 @@ object Battle { val fromTile = defender.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 return !defender.unit.movement.canMoveTo(tile) || defender.isLandUnit() && !tile.isLand // forbid retreat from land to sea - embarked already excluded