chore(purity): Autosuggested, removed more localstate

This commit is contained in:
yairm210 2025-08-05 09:13:05 +03:00
parent 33cd9821d0
commit e3599e4591
5 changed files with 29 additions and 16 deletions

View File

@ -58,7 +58,8 @@ allprojects {
"com.badlogic.gdx.math.Vector2.cpy", "com.badlogic.gdx.math.Vector2.cpy",
"com.badlogic.gdx.math.Vector2.hashCode", "com.badlogic.gdx.math.Vector2.hashCode",
"java.util.BitSet.get" "java.util.BitSet.get", // moved
"kotlin.collections.getValue", // moved
) )
wellKnownPureClasses = setOf<String>( wellKnownPureClasses = setOf<String>(
) )
@ -71,6 +72,7 @@ allprojects {
"kotlin.collections.Set", "kotlin.collections.Set",
"kotlin.collections.Map", "kotlin.collections.Map",
"kotlin.collections.ArrayDequeue", "kotlin.collections.ArrayDequeue",
"java.util.BitSet",
"com.unciv.models.stats.Stats", "com.unciv.models.stats.Stats",
"com.unciv.models.Counter", "com.unciv.models.Counter",

View File

@ -7,7 +7,7 @@ import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
import com.unciv.ui.components.input.KeyboardBinding import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.screens.cityscreen.CitizenManagementTable import com.unciv.ui.screens.cityscreen.CitizenManagementTable
import com.unciv.ui.images.ImageGetter import yairm210.purity.annotations.Pure
/** /**
* Controls automatic worker-to-tile assignment * Controls automatic worker-to-tile assignment
@ -60,16 +60,17 @@ enum class CityFocus(
val binding: KeyboardBinding = val binding: KeyboardBinding =
binding ?: binding ?:
KeyboardBinding.values().firstOrNull { it.name == name } ?: KeyboardBinding.entries.firstOrNull { it.name == name } ?:
KeyboardBinding.None KeyboardBinding.None
@Pure
open fun getStatMultiplier(stat: Stat) = when (this.stat) { open fun getStatMultiplier(stat: Stat) = when (this.stat) {
stat -> 3.05f // on ties, prefer the Focus stat -> 3.05f // on ties, prefer the Focus
else -> 1f else -> 1f
} }
private val statValuesForFocus: List<Stat> by lazy { private val statValuesForFocus: List<Stat> by lazy {
Stat.values().filter { getStatMultiplier(it) != 1f } Stat.entries.filter { getStatMultiplier(it) != 1f }
} }
fun applyWeightTo(stats: Stats) { fun applyWeightTo(stats: Stats) {
@ -82,9 +83,7 @@ enum class CityFocus(
} }
companion object { companion object {
fun safeValueOf(stat: Stat): CityFocus { @Pure fun safeValueOf(stat: Stat): CityFocus = entries.firstOrNull { it.stat == stat } ?: NoFocus
return values().firstOrNull { it.stat == stat } ?: NoFocus
}
// set used in Automation. All non-Food Focuses, so targets 0 Surplus Food // set used in Automation. All non-Food Focuses, so targets 0 Surplus Food
val zeroFoodFocuses = setOf( val zeroFoodFocuses = setOf(

View File

@ -201,7 +201,7 @@ class Civilization : IsPartOfGameInfoSerialization {
// Limit camera within explored region // Limit camera within explored region
var exploredRegion = ExploredRegion() var exploredRegion = ExploredRegion()
fun hasExplored(tile: Tile) = tile.isExplored(this) @Readonly fun hasExplored(tile: Tile) = tile.isExplored(this)
val lastSeenImprovement = LastSeenImprovement() val lastSeenImprovement = LastSeenImprovement()

View File

@ -24,7 +24,7 @@ class UnitMovement(val unit: MapUnit) {
class ParentTileAndTotalMovement(val tile: Tile, val parentTile: Tile, val totalMovement: Float) class ParentTileAndTotalMovement(val tile: Tile, val parentTile: Tile, val totalMovement: Float)
fun isUnknownTileWeShouldAssumeToBePassable(tile: Tile) = !unit.civ.hasExplored(tile) @Readonly fun isUnknownTileWeShouldAssumeToBePassable(tile: Tile) = !unit.civ.hasExplored(tile)
/** /**
@ -109,6 +109,7 @@ class UnitMovement(val unit: MapUnit) {
* Does not consider if the [destination] tile can actually be entered, use [canMoveTo] for that. * Does not consider if the [destination] tile can actually be entered, use [canMoveTo] for that.
* Returns an empty list if there's no way to get to the destination. * Returns an empty list if there's no way to get to the destination.
*/ */
@Readonly
fun getShortestPath(destination: Tile, avoidDamagingTerrain: Boolean = false): List<Tile> { fun getShortestPath(destination: Tile, avoidDamagingTerrain: Boolean = false): List<Tile> {
if (unit.cache.cannotMove) return listOf() if (unit.cache.cannotMove) return listOf()
@ -142,7 +143,8 @@ class UnitMovement(val unit: MapUnit) {
var distance = 1 var distance = 1
val unitMaxMovement = unit.getMaxMovement().toFloat() val unitMaxMovement = unit.getMaxMovement().toFloat()
val newTilesToCheck = ArrayList<Tile>() val newTilesToCheck = ArrayList<Tile>()
val visitedTilesBitset = BitSet().apply { set(currentTile.zeroBasedIndex) } val visitedTilesBitset = BitSet()
visitedTilesBitset.set(currentTile.zeroBasedIndex)
val civilization = unit.civ val civilization = unit.civ
val passThroughCacheNew = ArrayList<Boolean?>() val passThroughCacheNew = ArrayList<Boolean?>()
@ -226,6 +228,7 @@ class UnitMovement(val unit: MapUnit) {
class UnreachableDestinationException(msg: String) : Exception(msg) class UnreachableDestinationException(msg: String) : Exception(msg)
@Readonly
fun getTileToMoveToThisTurn(finalDestination: Tile): Tile { fun getTileToMoveToThisTurn(finalDestination: Tile): Tile {
val currentTile = unit.getTile() val currentTile = unit.getTile()
@ -283,10 +286,12 @@ class UnitMovement(val unit: MapUnit) {
} }
/** Cached and thus not as performance-heavy as [canReach] */ /** Cached and thus not as performance-heavy as [canReach] */
@Readonly
fun canReachInCurrentTurn(destination: Tile) = canReachCommon(destination) { fun canReachInCurrentTurn(destination: Tile) = canReachCommon(destination) {
getDistanceToTiles().containsKey(it) getDistanceToTiles().containsKey(it)
} }
@Readonly
private inline fun canReachCommon(destination: Tile, specificFunction: (Tile) -> Boolean) = when { private inline fun canReachCommon(destination: Tile, specificFunction: (Tile) -> Boolean) = when {
unit.cache.cannotMove -> unit.cache.cannotMove ->
destination == unit.getTile() destination == unit.getTile()
@ -302,6 +307,7 @@ class UnitMovement(val unit: MapUnit) {
* @param includeOtherEscortUnit determines whether or not this method will also check its the other escort unit if it has one * @param includeOtherEscortUnit determines whether or not this method will also check its the other escort unit if it has one
* Leave it as default unless you know what [getReachableTilesInCurrentTurn] does. * Leave it as default unless you know what [getReachableTilesInCurrentTurn] does.
*/ */
@Readonly
fun getReachableTilesInCurrentTurn(includeOtherEscortUnit: Boolean = true): Sequence<Tile> { fun getReachableTilesInCurrentTurn(includeOtherEscortUnit: Boolean = true): Sequence<Tile> {
return when { return when {
unit.cache.cannotMove -> sequenceOf(unit.getTile()) unit.cache.cannotMove -> sequenceOf(unit.getTile())
@ -320,11 +326,13 @@ class UnitMovement(val unit: MapUnit) {
} }
/** Returns whether we can perform a swap move to the specified tile */ /** Returns whether we can perform a swap move to the specified tile */
@Readonly
fun canUnitSwapTo(destination: Tile): Boolean { fun canUnitSwapTo(destination: Tile): Boolean {
return canReachInCurrentTurn(destination) && canUnitSwapToReachableTile(destination) return canReachInCurrentTurn(destination) && canUnitSwapToReachableTile(destination)
} }
/** Returns the tiles to which we can perform a swap move */ /** Returns the tiles to which we can perform a swap move */
@Readonly
fun getUnitSwappableTiles(): Sequence<Tile> { fun getUnitSwappableTiles(): Sequence<Tile> {
return getReachableTilesInCurrentTurn().filter { canUnitSwapToReachableTile(it) } return getReachableTilesInCurrentTurn().filter { canUnitSwapToReachableTile(it) }
} }
@ -333,6 +341,7 @@ class UnitMovement(val unit: MapUnit) {
* Returns whether we can perform a unit swap move to the specified tile, given that it is * Returns whether we can perform a unit swap move to the specified tile, given that it is
* reachable in the current turn * reachable in the current turn
*/ */
@Readonly
private fun canUnitSwapToReachableTile(reachableTile: Tile): Boolean { private fun canUnitSwapToReachableTile(reachableTile: Tile): Boolean {
// Air units cannot swap // Air units cannot swap
if (unit.baseUnit.movesLikeAirUnits) return false if (unit.baseUnit.movesLikeAirUnits) return false
@ -592,6 +601,7 @@ class UnitMovement(val unit: MapUnit) {
unit.mostRecentMoveType = UnitMovementMemoryType.UnitMoved unit.mostRecentMoveType = UnitMovementMemoryType.UnitMoved
} }
@Readonly
private fun isCityCenterCannotEnter(tile: Tile) = tile.isCityCenter() private fun isCityCenterCannotEnter(tile: Tile) = tile.isCityCenter()
&& tile.getOwner() != unit.civ && tile.getOwner() != unit.civ
&& !tile.getCity()!!.hasJustBeenConquered && !tile.getCity()!!.hasJustBeenConquered
@ -602,6 +612,7 @@ class UnitMovement(val unit: MapUnit) {
* @param includeOtherEscortUnit determines whether or not this method will also check if the other escort unit [canMoveTo] if it has one. * @param includeOtherEscortUnit determines whether or not this method will also check if the other escort unit [canMoveTo] if it has one.
* Leave it as default unless you know what [canMoveTo] does. * Leave it as default unless you know what [canMoveTo] does.
*/ */
@Readonly
fun canMoveTo(tile: Tile, assumeCanPassThrough: Boolean = false, allowSwap: Boolean = false, includeOtherEscortUnit: Boolean = true): Boolean { fun canMoveTo(tile: Tile, assumeCanPassThrough: Boolean = false, allowSwap: Boolean = false, includeOtherEscortUnit: Boolean = true): Boolean {
if (unit.baseUnit.movesLikeAirUnits) if (unit.baseUnit.movesLikeAirUnits)
return canAirUnitMoveTo(tile, unit) return canAirUnitMoveTo(tile, unit)

View File

@ -17,6 +17,7 @@ import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unique.expressions.Expressions import com.unciv.models.ruleset.unique.expressions.Expressions
import yairm210.purity.annotations.Cache import yairm210.purity.annotations.Cache
import yairm210.purity.annotations.LocalState import yairm210.purity.annotations.LocalState
import yairm210.purity.annotations.Pure
import yairm210.purity.annotations.Readonly import yairm210.purity.annotations.Readonly
class UniqueValidator(val ruleset: Ruleset) { class UniqueValidator(val ruleset: Ruleset) {
@ -76,7 +77,7 @@ class UniqueValidator(val ruleset: Ruleset) {
val prefix by lazy { getUniqueContainerPrefix(uniqueContainer) + "\"${unique.text}\"" } val prefix by lazy { getUniqueContainerPrefix(uniqueContainer) + "\"${unique.text}\"" }
if (unique.type == null) return checkUntypedUnique(unique, tryFixUnknownUniques, uniqueContainer, prefix, reportRulesetSpecificErrors) if (unique.type == null) return checkUntypedUnique(unique, tryFixUnknownUniques, uniqueContainer, prefix, reportRulesetSpecificErrors)
@LocalState val rulesetErrors = RulesetErrorList(ruleset) val rulesetErrors = RulesetErrorList(ruleset)
if (uniqueContainer != null && if (uniqueContainer != null &&
!(unique.type.canAcceptUniqueTarget(uniqueContainer.getUniqueTarget()) || !(unique.type.canAcceptUniqueTarget(uniqueContainer.getUniqueTarget()) ||
@ -156,7 +157,7 @@ class UniqueValidator(val ruleset: Ruleset) {
uniqueContainer: IHasUniques?, uniqueContainer: IHasUniques?,
unique: Unique unique: Unique
): RulesetErrorList { ): RulesetErrorList {
@LocalState val rulesetErrors = RulesetErrorList() val rulesetErrors = RulesetErrorList()
if (!complianceError.acceptableParameterTypes.contains(UniqueParameterType.Countable)) return rulesetErrors if (!complianceError.acceptableParameterTypes.contains(UniqueParameterType.Countable)) return rulesetErrors
val parseError = Expressions.getParsingError(complianceError.parameterName) val parseError = Expressions.getParsingError(complianceError.parameterName)
@ -199,7 +200,7 @@ class UniqueValidator(val ruleset: Ruleset) {
uniqueContainer: IHasUniques?, uniqueContainer: IHasUniques?,
reportRulesetSpecificErrors: Boolean reportRulesetSpecificErrors: Boolean
): RulesetErrorList { ): RulesetErrorList {
@LocalState val rulesetErrors = RulesetErrorList() val rulesetErrors = RulesetErrorList()
if (unique.hasFlag(UniqueFlag.NoConditionals)) { if (unique.hasFlag(UniqueFlag.NoConditionals)) {
rulesetErrors.add( rulesetErrors.add(
"$prefix contains the conditional \"${conditional.text}\"," + "$prefix contains the conditional \"${conditional.text}\"," +
@ -287,11 +288,11 @@ class UniqueValidator(val ruleset: Ruleset) {
return rulesetErrors return rulesetErrors
} }
@Readonly @Pure
private fun getUniqueTypeSpecificErrors( private fun getUniqueTypeSpecificErrors(
prefix: String, unique: Unique, uniqueContainer: IHasUniques?, reportRulesetSpecificErrors: Boolean prefix: String, unique: Unique, uniqueContainer: IHasUniques?, reportRulesetSpecificErrors: Boolean
): RulesetErrorList { ): RulesetErrorList {
@LocalState val rulesetErrors = RulesetErrorList() val rulesetErrors = RulesetErrorList()
when(unique.type) { when(unique.type) {
UniqueType.RuinsUpgrade -> { UniqueType.RuinsUpgrade -> {
if (reportRulesetSpecificErrors && !anyAncientRuins) if (reportRulesetSpecificErrors && !anyAncientRuins)
@ -308,7 +309,7 @@ class UniqueValidator(val ruleset: Ruleset) {
prefix: String, prefix: String,
uniqueContainer: IHasUniques? uniqueContainer: IHasUniques?
): RulesetErrorList { ): RulesetErrorList {
@LocalState val rulesetErrors = RulesetErrorList() val rulesetErrors = RulesetErrorList()
val deprecationAnnotation = unique.getDeprecationAnnotation() val deprecationAnnotation = unique.getDeprecationAnnotation()
if (deprecationAnnotation != null) { if (deprecationAnnotation != null) {
val replacementUniqueText = unique.getReplacementText(ruleset) val replacementUniqueText = unique.getReplacementText(ruleset)