chore: Readonly 6

This commit is contained in:
yairm210
2025-07-14 16:08:55 +03:00
parent 9e5ae90444
commit adeca1ac1d
8 changed files with 23 additions and 6 deletions

View File

@ -20,7 +20,7 @@ object MultiFilter {
* @param filterFunction The single filter implementation
* @param forUniqueValidityTests Inverts the `non-[filter]` test because Unique validity doesn't check for actual matching
*/
@Readonly @Suppress("purity")
@Readonly @Suppress("purity") // Calls function invoke
fun multiFilter(
input: String,
filterFunction: (String) -> Boolean,

View File

@ -583,10 +583,12 @@ class Civilization : IsPartOfGameInfoSerialization {
}.toList() // Triggers can e.g. add buildings which contain triggers, causing concurrent modification errors
/** Implements [UniqueParameterType.CivFilter][com.unciv.models.ruleset.unique.UniqueParameterType.CivFilter] */
@Readonly
fun matchesFilter(filter: String, state: GameContext? = this.state, multiFilter: Boolean = true): Boolean =
if (multiFilter) MultiFilter.multiFilter(filter, { matchesSingleFilter(it, state) })
else matchesSingleFilter(filter, state)
@Readonly
fun matchesSingleFilter(filter: String, state: GameContext? = this.state): Boolean {
return when (filter) {
"Human player" -> isHuman()

View File

@ -414,7 +414,7 @@ class CityStateFunctions(val civInfo: Civilization) {
return getTributeModifiers(demandingCiv, demandingWorker).values.sum()
}
@Readonly @Suppress("purity")
@Readonly @Suppress("purity") // Local state update
fun getTributeModifiers(demandingCiv: Civilization, demandingWorker: Boolean = false, requireWholeList: Boolean = false): HashMap<String, Int> {
val modifiers = LinkedHashMap<String, Int>() // Linked to preserve order when presenting the modifiers table
// Can't bully major civs or unsettled CS's

View File

@ -471,6 +471,7 @@ class DiplomacyManager() : IsPartOfGameInfoSerialization {
/** Returns true when the [civInfo]'s territory is considered allied for [otherCiv].
* This includes friendly and allied city-states and the open border treaties.
*/
@Readonly
fun isConsideredFriendlyTerritory(): Boolean {
if (civInfo.isCityState &&
(isRelationshipLevelGE(RelationshipLevel.Friend) || otherCiv().hasUnique(UniqueType.CityStateTerritoryAlwaysFriendly)))

View File

@ -377,6 +377,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
getOwner()
}
@Readonly
fun isFriendlyTerritory(civInfo: Civilization): Boolean {
val tileOwner = getOwner()
return when {
@ -387,6 +388,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
}
}
@Readonly
fun isEnemyTerritory(civInfo: Civilization): Boolean {
val tileOwner = getOwner() ?: return false
return civInfo.isAtWarWith(tileOwner)
@ -492,6 +494,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
}
// This should be the only adjacency function
@Readonly
fun isAdjacentTo(terrainFilter: String, observingCiv: Civilization? = null): Boolean {
// Rivers are odd, as they aren't technically part of any specific tile but still count towards adjacency
if (terrainFilter == Constants.river) return isAdjacentToRiver()
@ -522,7 +525,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
else matchesSingleTerrainFilter(filter, observingCiv)
}
@Readonly @Suppress("purity")
@Readonly
private fun matchesSingleTerrainFilter(filter: String, observingCiv: Civilization?): Boolean {
// Constant strings get their own 'when' for performance -
// see https://yairm210.medium.com/kotlin-when-string-optimization-e15c6eea2734
@ -579,6 +582,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
@Readonly @Suppress("purity") // should be auto-recognized!
fun isCoastalTile() = _isCoastalTile
@Readonly
fun hasViewableResource(civInfo: Civilization): Boolean =
resource != null && civInfo.tech.isRevealed(tileResource)

View File

@ -18,6 +18,7 @@ import com.unciv.ui.objectdescriptions.BuildingDescriptions
import com.unciv.ui.objectdescriptions.ImprovementDescriptions
import com.unciv.ui.objectdescriptions.uniquesToCivilopediaTextLines
import com.unciv.ui.screens.civilopediascreen.FormattedLine
import yairm210.purity.annotations.Readonly
import kotlin.math.pow
class Nation : RulesetObject() {
@ -265,7 +266,8 @@ class Nation : RulesetObject() {
}
}
}
@Readonly
fun matchesFilter(filter: String, state: GameContext? = null, multiFilter: Boolean = true): Boolean {
// Todo: Add 'multifilter=false' option to Multifilter itself to cut down on duplicate code
return if (multiFilter) MultiFilter.multiFilter(filter, {
@ -278,6 +280,7 @@ class Nation : RulesetObject() {
state == null && hasTagUnique(filter)
}
@Readonly
private fun matchesSingleFilter(filter: String): Boolean {
// All cases are compile-time constants, for performance
return when (filter) {

View File

@ -12,6 +12,7 @@ import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.components.extensions.colorFromRGB
import com.unciv.ui.objectdescriptions.uniquesToCivilopediaTextLines
import com.unciv.ui.screens.civilopediascreen.FormattedLine
import yairm210.purity.annotations.Readonly
class Terrain : RulesetStatsObject() {
@ -47,6 +48,7 @@ class Terrain : RulesetStatsObject() {
var damagePerTurn = 0
// Shouldn't this just be a lazy property so it's automatically cached?
@Readonly
fun isRough(): Boolean = hasUnique(UniqueType.RoughTerrain)
/** Tests base terrains, features and natural wonders whether they should be treated as Land/Water.
@ -160,6 +162,7 @@ class Terrain : RulesetStatsObject() {
/** Terrain filter matching is "pure" - input always returns same output, and it's called a bajillion times */
val cachedMatchesFilterResult = HashMap<String, Boolean>()
@Readonly
fun matchesFilter(filter: String, state: GameContext? = null, multiFilter: Boolean = true): Boolean {
return if (multiFilter) MultiFilter.multiFilter(filter, {
cachedMatchesFilterResult.getOrPut(it) { matchesSingleFilter(it) } ||
@ -172,6 +175,7 @@ class Terrain : RulesetStatsObject() {
}
/** Implements [UniqueParameterType.TerrainFilter][com.unciv.models.ruleset.unique.UniqueParameterType.TerrainFilter] */
@Readonly
fun matchesSingleFilter(filter: String): Boolean {
return when (filter) {
in Constants.all -> true

View File

@ -14,6 +14,7 @@ import com.unciv.utils.Log
import com.unciv.utils.debug
import java.util.Locale
import org.jetbrains.annotations.VisibleForTesting
import yairm210.purity.annotations.Pure
import yairm210.purity.annotations.Readonly
/**
@ -473,7 +474,7 @@ private fun String.translateIndividualWord(language: String, hideIcons: Boolean,
* For example, a string like 'The city of [New [York]]' will return ['New [York]'],
* allowing us to have nested translations!
*/
@Readonly @Suppress("purity")
@Readonly @Suppress("purity") // Local state update
fun String.getPlaceholderParameters(): List<String> {
if (!this.contains('[')) return emptyList()
@ -512,6 +513,7 @@ fun String.equalsPlaceholderText(str: String): Boolean {
return this.getPlaceholderText() == str
}
@Pure
fun String.hasPlaceholderParameters(): Boolean {
if (!this.contains('[')) return false
return squareBraceRegex.containsMatchIn(this.removeConditionals())
@ -529,12 +531,13 @@ fun String.fillPlaceholders(vararg strings: String): String {
return filledString
}
@Pure
fun String.getModifiers(): List<Unique> {
if (!this.contains('<')) return emptyList()
return pointyBraceRegex.findAll(this).map { Unique(it.groups[1]!!.value) }.toList()
}
@Readonly @Suppress("purity") // todo fix val reference in purity
@Pure @Suppress("purity") // todo fix val reference in purity
fun String.removeConditionals(): String {
if (!this.contains('<')) return this // no need to regex search
return this