mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-24 03:53:12 -04:00
chore(purity): Replace extra @LocalState with declaring that the classes are well known local state classes
This commit is contained in:
parent
152acba973
commit
68894cdac5
@ -38,7 +38,7 @@ plugins {
|
|||||||
// This is *with* gradle 8.2 downloaded according the project specs, no idea what that's about
|
// This is *with* gradle 8.2 downloaded according the project specs, no idea what that's about
|
||||||
kotlin("multiplatform") version "1.9.24"
|
kotlin("multiplatform") version "1.9.24"
|
||||||
kotlin("plugin.serialization") version "1.9.24"
|
kotlin("plugin.serialization") version "1.9.24"
|
||||||
id("io.github.yairm210.purity-plugin") version "0.0.43" apply(false)
|
id("io.github.yairm210.purity-plugin") version "0.0.45" apply(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
@ -49,28 +49,32 @@ 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.assert",
|
"kotlin.lazy", // moved
|
||||||
"kotlin.lazy",
|
"kotlin.getValue", // moved
|
||||||
"kotlin.getValue",
|
"kotlin.error", // moved
|
||||||
"kotlin.error",
|
|
||||||
)
|
)
|
||||||
wellKnownReadonlyFunctions = setOf(
|
wellKnownReadonlyFunctions = setOf(
|
||||||
"com.badlogic.gdx.math.Vector2.len",
|
"com.badlogic.gdx.math.Vector2.len",
|
||||||
"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.lang.reflect.Field.getAnnotation", // not sure if generic enough to be useful globally
|
|
||||||
"java.lang.Class.getField",
|
|
||||||
|
|
||||||
// Looks like the Collection.contains is not considered overridden :thunk:
|
|
||||||
"kotlin.Array.get",
|
|
||||||
"kotlin.collections.mutableSetOf",
|
|
||||||
"kotlin.collections.withIndex", // applicable to sequence as well
|
|
||||||
"kotlin.collections.intersect",
|
|
||||||
"kotlin.collections.maxOfOrNull",
|
|
||||||
"kotlin.collections.minOfOrNull",
|
|
||||||
"kotlin.reflect.KMutableProperty0.get", // also 1 and 2
|
|
||||||
)
|
)
|
||||||
wellKnownPureClasses = setOf(
|
wellKnownPureClasses = setOf<String>(
|
||||||
|
)
|
||||||
|
wellKnownInternalStateClasses = setOf<String>(
|
||||||
|
// Moved all
|
||||||
|
"kotlin.collections.MutableList",
|
||||||
|
"kotlin.collections.MutableSet",
|
||||||
|
"kotlin.collections.MutableMap",
|
||||||
|
"kotlin.collections.List",
|
||||||
|
"kotlin.collections.Set",
|
||||||
|
"kotlin.collections.Map",
|
||||||
|
"kotlin.collections.ArrayDequeue",
|
||||||
|
|
||||||
|
"com.unciv.models.stats.Stats",
|
||||||
|
"com.unciv.models.Counter",
|
||||||
|
"com.unciv.models.ruleset.tile.ResourceSupplyList",
|
||||||
|
"com.badlogic.gdx.math.Vector2",
|
||||||
)
|
)
|
||||||
warnOnPossibleAnnotations = true
|
warnOnPossibleAnnotations = true
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,7 @@ object MultiFilter {
|
|||||||
fun getAllSingleFilters(input: String): Sequence<String> = when {
|
fun getAllSingleFilters(input: String): Sequence<String> = when {
|
||||||
input.hasSurrounding(andPrefix, andSuffix) && input.contains(andSeparator) -> {
|
input.hasSurrounding(andPrefix, andSuffix) && input.contains(andSeparator) -> {
|
||||||
// Resolve "AND" filters
|
// Resolve "AND" filters
|
||||||
@LocalState
|
@LocalState val filters = input.removeSurrounding(andPrefix, andSuffix)
|
||||||
val filters = input.removeSurrounding(andPrefix, andSuffix)
|
|
||||||
.splitToSequence(andSeparator)
|
.splitToSequence(andSeparator)
|
||||||
filters.flatMap { getAllSingleFilters(it) }
|
filters.flatMap { getAllSingleFilters(it) }
|
||||||
}
|
}
|
||||||
|
@ -183,11 +183,13 @@ object Automation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
@Readonly
|
||||||
fun providesUnneededCarryingSlots(baseUnit: BaseUnit, civInfo: Civilization): Boolean {
|
fun providesUnneededCarryingSlots(baseUnit: BaseUnit, civInfo: Civilization): Boolean {
|
||||||
// Simplified, will not work for crazy mods with more than one carrying filter for a unit
|
// Simplified, will not work for crazy mods with more than one carrying filter for a unit
|
||||||
val carryUnique = baseUnit.getMatchingUniques(UniqueType.CarryAirUnits).first()
|
val carryUnique = baseUnit.getMatchingUniques(UniqueType.CarryAirUnits).first()
|
||||||
val carryFilter = carryUnique.params[1]
|
val carryFilter = carryUnique.params[1]
|
||||||
|
|
||||||
|
@Readonly
|
||||||
fun getCarryAmount(mapUnit: MapUnit): Int {
|
fun getCarryAmount(mapUnit: MapUnit): Int {
|
||||||
val mapUnitCarryUnique =
|
val mapUnitCarryUnique =
|
||||||
mapUnit.getMatchingUniques(UniqueType.CarryAirUnits).firstOrNull() ?: return 0
|
mapUnit.getMatchingUniques(UniqueType.CarryAirUnits).firstOrNull() ?: return 0
|
||||||
@ -338,6 +340,7 @@ object Automation {
|
|||||||
|
|
||||||
/** Determines whether the AI should be willing to spend strategic resources to build
|
/** Determines whether the AI should be willing to spend strategic resources to build
|
||||||
* [construction] for [civInfo], assumes that we are actually able to do so. */
|
* [construction] for [civInfo], assumes that we are actually able to do so. */
|
||||||
|
@Readonly
|
||||||
fun allowSpendingResource(civInfo: Civilization, construction: INonPerpetualConstruction, cityInfo: City? = null): Boolean {
|
fun allowSpendingResource(civInfo: Civilization, construction: INonPerpetualConstruction, cityInfo: City? = null): Boolean {
|
||||||
// City states do whatever they want
|
// City states do whatever they want
|
||||||
if (civInfo.isCityState)
|
if (civInfo.isCityState)
|
||||||
@ -418,13 +421,14 @@ object Automation {
|
|||||||
else -> ThreatLevel.Medium
|
else -> ThreatLevel.Medium
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Readonly
|
||||||
private fun improvementIsRemovable(city: City, tile: Tile): Boolean {
|
private fun improvementIsRemovable(city: City, tile: Tile): Boolean {
|
||||||
val gameContext = GameContext(city.civ, city, tile = tile)
|
val gameContext = GameContext(city.civ, city, tile = tile)
|
||||||
return (tile.getTileImprovement()?.hasUnique(UniqueType.AutomatedUnitsWillNotReplace, gameContext) == false && tile.getTileImprovement()?.hasUnique(UniqueType.Irremovable, gameContext) == false)
|
return (tile.getTileImprovement()?.hasUnique(UniqueType.AutomatedUnitsWillNotReplace, gameContext) == false && tile.getTileImprovement()?.hasUnique(UniqueType.Irremovable, gameContext) == false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Support [UniqueType.CreatesOneImprovement] unique - find best tile for placement automation */
|
/** Support [UniqueType.CreatesOneImprovement] unique - find best tile for placement automation */
|
||||||
|
@Readonly
|
||||||
fun getTileForConstructionImprovement(city: City, improvement: TileImprovement): Tile? {
|
fun getTileForConstructionImprovement(city: City, improvement: TileImprovement): Tile? {
|
||||||
val localUniqueCache = LocalUniqueCache()
|
val localUniqueCache = LocalUniqueCache()
|
||||||
val civ = city.civ
|
val civ = city.civ
|
||||||
@ -441,6 +445,7 @@ object Automation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ranks a tile for any purpose except the expansion algorithm of cities
|
// Ranks a tile for any purpose except the expansion algorithm of cities
|
||||||
|
@Readonly
|
||||||
internal fun rankTile(tile: Tile?, civInfo: Civilization,
|
internal fun rankTile(tile: Tile?, civInfo: Civilization,
|
||||||
localUniqueCache: LocalUniqueCache): Float {
|
localUniqueCache: LocalUniqueCache): Float {
|
||||||
if (tile == null) return 0f
|
if (tile == null) return 0f
|
||||||
@ -460,6 +465,7 @@ object Automation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ranks a tile for the expansion algorithm of cities
|
// Ranks a tile for the expansion algorithm of cities
|
||||||
|
@Readonly
|
||||||
internal fun rankTileForExpansion(tile: Tile, city: City,
|
internal fun rankTileForExpansion(tile: Tile, city: City,
|
||||||
localUniqueCache: LocalUniqueCache): Int {
|
localUniqueCache: LocalUniqueCache): Int {
|
||||||
// https://github.com/Gedemon/Civ5-DLL/blob/aa29e80751f541ae04858b6d2a2c7dcca454201e/CvGameCoreDLL_Expansion1/CvCity.cpp#L10301
|
// https://github.com/Gedemon/Civ5-DLL/blob/aa29e80751f541ae04858b6d2a2c7dcca454201e/CvGameCoreDLL_Expansion1/CvCity.cpp#L10301
|
||||||
@ -513,6 +519,7 @@ object Automation {
|
|||||||
return score
|
return score
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Readonly
|
||||||
fun rankStatsValue(stats: Stats, civInfo: Civilization): Float {
|
fun rankStatsValue(stats: Stats, civInfo: Civilization): Float {
|
||||||
var rank = 0.0f
|
var rank = 0.0f
|
||||||
rank += stats.food * 1.2f //food get more value to keep city growing
|
rank += stats.food * 1.2f //food get more value to keep city growing
|
||||||
|
@ -35,7 +35,7 @@ object BattleDamage {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
private fun getGeneralModifiers(combatant: ICombatant, enemy: ICombatant, combatAction: CombatAction, tileToAttackFrom: Tile): Counter<String> {
|
private fun getGeneralModifiers(combatant: ICombatant, enemy: ICombatant, combatAction: CombatAction, tileToAttackFrom: Tile): Counter<String> {
|
||||||
@LocalState val modifiers = Counter<String>()
|
val modifiers = Counter<String>()
|
||||||
|
|
||||||
val conditionalState = getStateForConditionals(combatAction, combatant, enemy)
|
val conditionalState = getStateForConditionals(combatAction, combatant, enemy)
|
||||||
val civInfo = combatant.getCivInfo()
|
val civInfo = combatant.getCivInfo()
|
||||||
@ -101,7 +101,7 @@ object BattleDamage {
|
|||||||
private fun getUnitUniqueModifiers(combatant: MapUnitCombatant, enemy: ICombatant, conditionalState: GameContext,
|
private fun getUnitUniqueModifiers(combatant: MapUnitCombatant, enemy: ICombatant, conditionalState: GameContext,
|
||||||
tileToAttackFrom: Tile): Counter<String> {
|
tileToAttackFrom: Tile): Counter<String> {
|
||||||
val civInfo = combatant.getCivInfo()
|
val civInfo = combatant.getCivInfo()
|
||||||
@LocalState val modifiers = Counter<String>()
|
val modifiers = Counter<String>()
|
||||||
|
|
||||||
for (unique in combatant.getMatchingUniques(UniqueType.Strength, conditionalState, true)) {
|
for (unique in combatant.getMatchingUniques(UniqueType.Strength, conditionalState, true)) {
|
||||||
modifiers.add(getModifierStringFromUnique(unique), unique.params[0].toInt())
|
modifiers.add(getModifierStringFromUnique(unique), unique.params[0].toInt())
|
||||||
@ -179,7 +179,7 @@ object BattleDamage {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
private fun getTerrainAttackModifiers(attacker: MapUnitCombatant, defender: ICombatant, tileToAttackFrom: Tile): Counter<String> {
|
private fun getTerrainAttackModifiers(attacker: MapUnitCombatant, defender: ICombatant, tileToAttackFrom: Tile): Counter<String> {
|
||||||
@LocalState val modifiers = Counter<String>()
|
val modifiers = Counter<String>()
|
||||||
if (attacker.unit.isEmbarked() && defender.getTile().isLand
|
if (attacker.unit.isEmbarked() && defender.getTile().isLand
|
||||||
&& !attacker.unit.hasUnique(UniqueType.AttackAcrossCoast)
|
&& !attacker.unit.hasUnique(UniqueType.AttackAcrossCoast)
|
||||||
)
|
)
|
||||||
@ -219,7 +219,7 @@ object BattleDamage {
|
|||||||
fun getAirSweepAttackModifiers(
|
fun getAirSweepAttackModifiers(
|
||||||
attacker: ICombatant
|
attacker: ICombatant
|
||||||
): Counter<String> {
|
): Counter<String> {
|
||||||
@LocalState val modifiers = Counter<String>()
|
val modifiers = Counter<String>()
|
||||||
|
|
||||||
if (attacker is MapUnitCombatant) {
|
if (attacker is MapUnitCombatant) {
|
||||||
for (unique in attacker.unit.getMatchingUniques(UniqueType.StrengthWhenAirsweep)) {
|
for (unique in attacker.unit.getMatchingUniques(UniqueType.StrengthWhenAirsweep)) {
|
||||||
|
@ -39,7 +39,7 @@ object CityResources {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
private fun getResourcesGeneratedByCityNotIncludingBuildings(city: City, resourceModifers: Map<String, Float>): ResourceSupplyList {
|
private fun getResourcesGeneratedByCityNotIncludingBuildings(city: City, resourceModifers: Map<String, Float>): ResourceSupplyList {
|
||||||
@LocalState val cityResources = ResourceSupplyList()
|
val cityResources = ResourceSupplyList()
|
||||||
|
|
||||||
cityResources.add(getResourcesFromTiles(city, resourceModifers))
|
cityResources.add(getResourcesFromTiles(city, resourceModifers))
|
||||||
cityResources.add(getResourceFromUniqueImprovedTiles(city, resourceModifers))
|
cityResources.add(getResourceFromUniqueImprovedTiles(city, resourceModifers))
|
||||||
@ -79,7 +79,7 @@ object CityResources {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
private fun getResourcesFromTiles(city: City, resourceModifer: Map<String, Float>): ResourceSupplyList {
|
private fun getResourcesFromTiles(city: City, resourceModifer: Map<String, Float>): ResourceSupplyList {
|
||||||
@LocalState val resourceSupplyList = ResourceSupplyList()
|
val resourceSupplyList = ResourceSupplyList()
|
||||||
for (tileInfo in city.getTiles().filter { it.resource != null }) {
|
for (tileInfo in city.getTiles().filter { it.resource != null }) {
|
||||||
val resource = tileInfo.tileResource
|
val resource = tileInfo.tileResource
|
||||||
val amount = getTileResourceAmount(city, tileInfo) * resourceModifer[resource.name]!!
|
val amount = getTileResourceAmount(city, tileInfo) * resourceModifer[resource.name]!!
|
||||||
@ -90,7 +90,7 @@ object CityResources {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
private fun getResourceFromUniqueImprovedTiles(city: City, resourceModifer: Map<String, Float>): ResourceSupplyList {
|
private fun getResourceFromUniqueImprovedTiles(city: City, resourceModifer: Map<String, Float>): ResourceSupplyList {
|
||||||
@LocalState val resourceSupplyList = ResourceSupplyList()
|
val resourceSupplyList = ResourceSupplyList()
|
||||||
for (tileInfo in city.getTiles().filter { it.getUnpillagedImprovement() != null }) {
|
for (tileInfo in city.getTiles().filter { it.getUnpillagedImprovement() != null }) {
|
||||||
val gameContext = GameContext(city.civ, city, tile = tileInfo)
|
val gameContext = GameContext(city.civ, city, tile = tileInfo)
|
||||||
val tileImprovement = tileInfo.getUnpillagedTileImprovement()
|
val tileImprovement = tileInfo.getUnpillagedTileImprovement()
|
||||||
@ -114,7 +114,7 @@ object CityResources {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
private fun getNegativeCityResourcesRequiredByBuildings(city: City): ResourceSupplyList {
|
private fun getNegativeCityResourcesRequiredByBuildings(city: City): ResourceSupplyList {
|
||||||
@LocalState val resourceSupplyList = ResourceSupplyList()
|
val resourceSupplyList = ResourceSupplyList()
|
||||||
val freeBuildings = city.civ.civConstructions.getFreeBuildingNames(city)
|
val freeBuildings = city.civ.civConstructions.getFreeBuildingNames(city)
|
||||||
for (building in city.cityConstructions.getBuiltBuildings()) {
|
for (building in city.cityConstructions.getBuiltBuildings()) {
|
||||||
// Free buildings cost no resources
|
// Free buildings cost no resources
|
||||||
@ -126,7 +126,7 @@ object CityResources {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
private fun getCityResourcesFromCiv(city: City, resourceModifers: HashMap<String, Float>): ResourceSupplyList {
|
private fun getCityResourcesFromCiv(city: City, resourceModifers: HashMap<String, Float>): ResourceSupplyList {
|
||||||
@LocalState val resourceSupplyList = ResourceSupplyList()
|
val resourceSupplyList = ResourceSupplyList()
|
||||||
// This includes the uniques from buildings, from this and all other cities
|
// This includes the uniques from buildings, from this and all other cities
|
||||||
for (unique in city.getMatchingUniques(UniqueType.ProvidesResources, city.state)) { // E.G "Provides [1] [Iron]"
|
for (unique in city.getMatchingUniques(UniqueType.ProvidesResources, city.state)) { // E.G "Provides [1] [Iron]"
|
||||||
val resource = city.getRuleset().tileResources[unique.params[1]]
|
val resource = city.getRuleset().tileResources[unique.params[1]]
|
||||||
|
@ -5,7 +5,6 @@ import com.unciv.models.Counter
|
|||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.unique.Unique
|
import com.unciv.models.ruleset.unique.Unique
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
|
|
||||||
/** Manages calculating Great Person Points per City for nextTurn. See public constructor(city) below for details. */
|
/** Manages calculating Great Person Points per City for nextTurn. See public constructor(city) below for details. */
|
||||||
@ -134,13 +133,11 @@ class GreatPersonPointsBreakdown private constructor(private val ruleset: Rulese
|
|||||||
@Readonly
|
@Readonly
|
||||||
fun sum(): Counter<String> {
|
fun sum(): Counter<String> {
|
||||||
// Accumulate base points as fake "fixed-point"
|
// Accumulate base points as fake "fixed-point"
|
||||||
@LocalState
|
|
||||||
val result = Counter<String>()
|
val result = Counter<String>()
|
||||||
for (entry in basePoints)
|
for (entry in basePoints)
|
||||||
result.add(entry.counter * fixedPointFactor)
|
result.add(entry.counter * fixedPointFactor)
|
||||||
|
|
||||||
// Accumulate percentage bonuses additively not multiplicatively
|
// Accumulate percentage bonuses additively not multiplicatively
|
||||||
@LocalState
|
|
||||||
val bonuses = Counter<String>()
|
val bonuses = Counter<String>()
|
||||||
for (entry in percentBonuses) {
|
for (entry in percentBonuses) {
|
||||||
bonuses.add(entry.counter)
|
bonuses.add(entry.counter)
|
||||||
|
@ -10,7 +10,6 @@ import com.unciv.models.Religion
|
|||||||
import com.unciv.models.ruleset.unique.Unique
|
import com.unciv.models.ruleset.unique.Unique
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.ui.components.extensions.toPercent
|
import com.unciv.ui.components.extensions.toPercent
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
|
|
||||||
class CityReligionManager : IsPartOfGameInfoSerialization {
|
class CityReligionManager : IsPartOfGameInfoSerialization {
|
||||||
@ -282,7 +281,7 @@ class CityReligionManager : IsPartOfGameInfoSerialization {
|
|||||||
/** Doesn't update the pressures, only returns what they are if the update were to happen right now */
|
/** Doesn't update the pressures, only returns what they are if the update were to happen right now */
|
||||||
@Readonly
|
@Readonly
|
||||||
fun getPressuresFromSurroundingCities(): Counter<String> {
|
fun getPressuresFromSurroundingCities(): Counter<String> {
|
||||||
@LocalState val addedPressure = Counter<String>()
|
val addedPressure = Counter<String>()
|
||||||
if (city.isHolyCity()) {
|
if (city.isHolyCity()) {
|
||||||
addedPressure[religionThisIsTheHolyCityOf!!] = 5 * pressureFromAdjacentCities
|
addedPressure[religionThisIsTheHolyCityOf!!] = 5 * pressureFromAdjacentCities
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,6 @@ import com.unciv.ui.components.extensions.toPercent
|
|||||||
import com.unciv.ui.screens.victoryscreen.RankingType
|
import com.unciv.ui.screens.victoryscreen.RankingType
|
||||||
import org.jetbrains.annotations.VisibleForTesting
|
import org.jetbrains.annotations.VisibleForTesting
|
||||||
import yairm210.purity.annotations.Cache
|
import yairm210.purity.annotations.Cache
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
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
|
||||||
@ -750,7 +749,6 @@ class Civilization : IsPartOfGameInfoSerialization {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
fun calculateScoreBreakdown(): HashMap<String,Double> {
|
fun calculateScoreBreakdown(): HashMap<String,Double> {
|
||||||
@LocalState
|
|
||||||
val scoreBreakdown = hashMapOf<String,Double>()
|
val scoreBreakdown = hashMapOf<String,Double>()
|
||||||
// 1276 is the number of tiles in a medium sized map. The original uses 4160 for this,
|
// 1276 is the number of tiles in a medium sized map. The original uses 4160 for this,
|
||||||
// but they have bigger maps
|
// but they have bigger maps
|
||||||
|
@ -27,7 +27,6 @@ import com.unciv.models.ruleset.unit.BaseUnit
|
|||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import com.unciv.ui.screens.victoryscreen.RankingType
|
import com.unciv.ui.screens.victoryscreen.RankingType
|
||||||
import com.unciv.utils.randomWeighted
|
import com.unciv.utils.randomWeighted
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
@ -418,7 +417,6 @@ class CityStateFunctions(val civInfo: Civilization) {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
fun getTributeModifiers(demandingCiv: Civilization, demandingWorker: Boolean = false, requireWholeList: Boolean = false): HashMap<String, Int> {
|
fun getTributeModifiers(demandingCiv: Civilization, demandingWorker: Boolean = false, requireWholeList: Boolean = false): HashMap<String, Int> {
|
||||||
@LocalState
|
|
||||||
val modifiers = LinkedHashMap<String, Int>() // Linked to preserve order when presenting the modifiers table
|
val modifiers = LinkedHashMap<String, Int>() // Linked to preserve order when presenting the modifiers table
|
||||||
// Can't bully major civs or unsettled CS's
|
// Can't bully major civs or unsettled CS's
|
||||||
if (!civInfo.isCityState) {
|
if (!civInfo.isCityState) {
|
||||||
|
@ -128,11 +128,9 @@ object HexMath {
|
|||||||
@Readonly
|
@Readonly
|
||||||
fun hex2WorldCoords(hexCoord: Vector2): Vector2 {
|
fun hex2WorldCoords(hexCoord: Vector2): Vector2 {
|
||||||
// Distance between cells = 2* normal of triangle = 2* (sqrt(3)/2) = sqrt(3)
|
// Distance between cells = 2* normal of triangle = 2* (sqrt(3)/2) = sqrt(3)
|
||||||
@LocalState
|
|
||||||
val xVector = getVectorByClockHour(10)
|
val xVector = getVectorByClockHour(10)
|
||||||
xVector.scl(sqrt(3.0).toFloat() * hexCoord.x)
|
xVector.scl(sqrt(3.0).toFloat() * hexCoord.x)
|
||||||
|
|
||||||
@LocalState
|
|
||||||
val yVector = getVectorByClockHour(2)
|
val yVector = getVectorByClockHour(2)
|
||||||
yVector.scl(sqrt(3.0).toFloat() * hexCoord.y)
|
yVector.scl(sqrt(3.0).toFloat() * hexCoord.y)
|
||||||
|
|
||||||
@ -143,10 +141,8 @@ object HexMath {
|
|||||||
@Readonly
|
@Readonly
|
||||||
fun world2HexCoords(worldCoord: Vector2): Vector2 {
|
fun world2HexCoords(worldCoord: Vector2): Vector2 {
|
||||||
// D: diagonal, A: antidiagonal versors
|
// D: diagonal, A: antidiagonal versors
|
||||||
@LocalState
|
|
||||||
val D = getVectorByClockHour(10)
|
val D = getVectorByClockHour(10)
|
||||||
D.scl(sqrt(3.0).toFloat())
|
D.scl(sqrt(3.0).toFloat())
|
||||||
@LocalState
|
|
||||||
val A = getVectorByClockHour(2)
|
val A = getVectorByClockHour(2)
|
||||||
A.scl(sqrt(3.0).toFloat())
|
A.scl(sqrt(3.0).toFloat())
|
||||||
val den = D.x * A.y - D.y * A.x
|
val den = D.x * A.y - D.y * A.x
|
||||||
@ -219,7 +215,6 @@ object HexMath {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
fun getVectorsAtDistance(origin: Vector2, distance: Int, maxDistance: Int, worldWrap: Boolean): List<Vector2> {
|
fun getVectorsAtDistance(origin: Vector2, distance: Int, maxDistance: Int, worldWrap: Boolean): List<Vector2> {
|
||||||
@LocalState
|
|
||||||
val vectors = mutableListOf<Vector2>()
|
val vectors = mutableListOf<Vector2>()
|
||||||
if (distance == 0) {
|
if (distance == 0) {
|
||||||
return listOf(origin.cpy())
|
return listOf(origin.cpy())
|
||||||
@ -259,7 +254,6 @@ object HexMath {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
fun getVectorsInDistance(origin: Vector2, distance: Int, worldWrap: Boolean): List<Vector2> {
|
fun getVectorsInDistance(origin: Vector2, distance: Int, worldWrap: Boolean): List<Vector2> {
|
||||||
@LocalState
|
|
||||||
val hexesToReturn = mutableListOf<Vector2>()
|
val hexesToReturn = mutableListOf<Vector2>()
|
||||||
for (i in 0..distance) {
|
for (i in 0..distance) {
|
||||||
hexesToReturn += getVectorsAtDistance(origin, i, distance, worldWrap)
|
hexesToReturn += getVectorsAtDistance(origin, i, distance, worldWrap)
|
||||||
|
@ -405,7 +405,6 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
|
|||||||
@Readonly
|
@Readonly
|
||||||
fun getViewableTiles(position: Vector2, sightDistance: Int, forAttack: Boolean = false): List<Tile> {
|
fun getViewableTiles(position: Vector2, sightDistance: Int, forAttack: Boolean = false): List<Tile> {
|
||||||
val aUnitHeight = get(position).unitHeight
|
val aUnitHeight = get(position).unitHeight
|
||||||
@LocalState
|
|
||||||
val viewableTiles = mutableListOf(ViewableTile(
|
val viewableTiles = mutableListOf(ViewableTile(
|
||||||
get(position),
|
get(position),
|
||||||
aUnitHeight,
|
aUnitHeight,
|
||||||
@ -416,7 +415,6 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
|
|||||||
for (i in 1..sightDistance+1) { // in each layer,
|
for (i in 1..sightDistance+1) { // in each layer,
|
||||||
// This is so we don't use tiles in the same distance to "see over",
|
// This is so we don't use tiles in the same distance to "see over",
|
||||||
// that is to say, the "viewableTiles.contains(it) check will return false for neighbors from the same distance
|
// that is to say, the "viewableTiles.contains(it) check will return false for neighbors from the same distance
|
||||||
@LocalState
|
|
||||||
val tilesToAddInDistanceI = ArrayList<ViewableTile>()
|
val tilesToAddInDistanceI = ArrayList<ViewableTile>()
|
||||||
|
|
||||||
for (cTile in getTilesAtDistance(position, i)) { // for each tile in that layer,
|
for (cTile in getTilesAtDistance(position, i)) { // for each tile in that layer,
|
||||||
|
@ -329,7 +329,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
|||||||
* StateForConditionals is assumed to regarding this mapUnit*/
|
* StateForConditionals is assumed to regarding this mapUnit*/
|
||||||
@Readonly
|
@Readonly
|
||||||
fun getResourceRequirementsPerTurn(): Counter<String> {
|
fun getResourceRequirementsPerTurn(): Counter<String> {
|
||||||
@LocalState val resourceRequirements = Counter<String>()
|
val resourceRequirements = Counter<String>()
|
||||||
if (baseUnit.requiredResource != null) resourceRequirements[baseUnit.requiredResource!!] = 1
|
if (baseUnit.requiredResource != null) resourceRequirements[baseUnit.requiredResource!!] = 1
|
||||||
for (unique in getMatchingUniques(UniqueType.ConsumesResources, cache.state))
|
for (unique in getMatchingUniques(UniqueType.ConsumesResources, cache.state))
|
||||||
resourceRequirements.add(unique.params[1], unique.params[0].toInt())
|
resourceRequirements.add(unique.params[1], unique.params[0].toInt())
|
||||||
|
@ -738,7 +738,6 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
fun getRulesetIncompatibility(ruleset: Ruleset): HashSet<String> {
|
fun getRulesetIncompatibility(ruleset: Ruleset): HashSet<String> {
|
||||||
@LocalState
|
|
||||||
val out = HashSet<String>()
|
val out = HashSet<String>()
|
||||||
if (!ruleset.terrains.containsKey(baseTerrain))
|
if (!ruleset.terrains.containsKey(baseTerrain))
|
||||||
out.add("Base terrain [$baseTerrain] does not exist in ruleset!")
|
out.add("Base terrain [$baseTerrain] does not exist in ruleset!")
|
||||||
|
@ -11,8 +11,11 @@ import com.unciv.models.ruleset.unique.UniqueType
|
|||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import com.unciv.models.stats.Stats
|
import com.unciv.models.stats.Stats
|
||||||
import com.unciv.ui.components.extensions.toPercent
|
import com.unciv.ui.components.extensions.toPercent
|
||||||
|
import yairm210.purity.annotations.LocalState
|
||||||
|
import yairm210.purity.annotations.Readonly
|
||||||
import java.util.EnumMap
|
import java.util.EnumMap
|
||||||
|
|
||||||
|
@Readonly
|
||||||
fun List<Pair<String, Stats>>.toStats(): Stats {
|
fun List<Pair<String, Stats>>.toStats(): Stats {
|
||||||
val stats = Stats()
|
val stats = Stats()
|
||||||
for ((_, statsToAdd) in this)
|
for ((_, statsToAdd) in this)
|
||||||
@ -28,6 +31,7 @@ class TileStatFunctions(val tile: Tile) {
|
|||||||
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||||
): Stats = getTileStats(tile.getCity(), observingCiv, localUniqueCache)
|
): Stats = getTileStats(tile.getCity(), observingCiv, localUniqueCache)
|
||||||
|
|
||||||
|
@Readonly @Suppress("purity") // requires "for @LocalState X"
|
||||||
fun getTileStats(
|
fun getTileStats(
|
||||||
city: City?, observingCiv: Civilization?,
|
city: City?, observingCiv: Civilization?,
|
||||||
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||||
@ -51,21 +55,22 @@ class TileStatFunctions(val tile: Tile) {
|
|||||||
return statsBreakdown.toStats()
|
return statsBreakdown.toStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Readonly
|
||||||
fun getTileStatsBreakdown(city: City?, observingCiv: Civilization?,
|
fun getTileStatsBreakdown(city: City?, observingCiv: Civilization?,
|
||||||
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)
|
||||||
): List<Pair<String, Stats>> {
|
): List<Pair<String, Stats>> {
|
||||||
val gameContext = GameContext(civInfo = observingCiv, city = city, tile = tile)
|
val gameContext = GameContext(civInfo = observingCiv, city = city, tile = tile)
|
||||||
val listOfStats = getTerrainStatsBreakdown(gameContext)
|
@LocalState val listOfStats = getTerrainStatsBreakdown(gameContext)
|
||||||
|
|
||||||
val otherYieldsIgnored = tile.allTerrains.any { it.hasUnique(UniqueType.NullifyYields, gameContext) }
|
val otherYieldsIgnored = tile.allTerrains.any { it.hasUnique(UniqueType.NullifyYields, gameContext) }
|
||||||
|
|
||||||
val improvement = if (otherYieldsIgnored) null // Treat it as if there is no improvement
|
val improvement = if (otherYieldsIgnored) null // Treat it as if there is no improvement
|
||||||
else tile.getUnpillagedTileImprovement()
|
else tile.getUnpillagedTileImprovement()
|
||||||
val improvementStats = improvement?.cloneStats() ?: Stats.ZERO // If improvement==null, will never be added to
|
@LocalState val improvementStats = improvement?.cloneStats() ?: Stats.ZERO // If improvement==null, will never be added to
|
||||||
|
|
||||||
val road = if (otherYieldsIgnored) null
|
val road = if (otherYieldsIgnored) null
|
||||||
else tile.getUnpillagedRoadImprovement()
|
else tile.getUnpillagedRoadImprovement()
|
||||||
val roadStats = road?.cloneStats() ?: Stats.ZERO
|
@LocalState val roadStats = road?.cloneStats() ?: Stats.ZERO
|
||||||
|
|
||||||
if (city != null) {
|
if (city != null) {
|
||||||
val statsFromTilesUniques =
|
val statsFromTilesUniques =
|
||||||
@ -135,6 +140,7 @@ class TileStatFunctions(val tile: Tile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Ensures each stat is >= [minimumStats].stat - modifies in place */
|
/** Ensures each stat is >= [minimumStats].stat - modifies in place */
|
||||||
|
@Readonly
|
||||||
private fun missingFromMinimum(current: Stats, minimumStats: Stats): Stats {
|
private fun missingFromMinimum(current: Stats, minimumStats: Stats): Stats {
|
||||||
// Note: Not `for ((stat, value) in other)` - that would skip zero values
|
// Note: Not `for ((stat, value) in other)` - that would skip zero values
|
||||||
val missingStats = Stats()
|
val missingStats = Stats()
|
||||||
@ -148,6 +154,7 @@ class TileStatFunctions(val tile: Tile) {
|
|||||||
/** Gets stats of a single Terrain, unifying the Stats class a Terrain inherits and the Stats Unique
|
/** Gets stats of a single Terrain, unifying the Stats class a Terrain inherits and the Stats Unique
|
||||||
* @return A Stats reference, must not be mutated
|
* @return A Stats reference, must not be mutated
|
||||||
*/
|
*/
|
||||||
|
@Readonly
|
||||||
private fun getSingleTerrainStats(terrain: Terrain, gameContext: GameContext): ArrayList<Pair<String, Stats>> {
|
private fun getSingleTerrainStats(terrain: Terrain, gameContext: GameContext): ArrayList<Pair<String, Stats>> {
|
||||||
val list = arrayListOf(terrain.name to (terrain as Stats))
|
val list = arrayListOf(terrain.name to (terrain as Stats))
|
||||||
|
|
||||||
@ -158,8 +165,10 @@ class TileStatFunctions(val tile: Tile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Gets basic stats to start off [getTileStats] or [getTileStartYield], independently mutable result */
|
/** Gets basic stats to start off [getTileStats] or [getTileStartYield], independently mutable result */
|
||||||
|
@Readonly
|
||||||
fun getTerrainStatsBreakdown(gameContext: GameContext = GameContext()): ArrayList<Pair<String, Stats>> {
|
fun getTerrainStatsBreakdown(gameContext: GameContext = GameContext()): ArrayList<Pair<String, Stats>> {
|
||||||
var list = ArrayList<Pair<String, Stats>>()
|
// needs to be marked, because it's a var
|
||||||
|
@LocalState var list = ArrayList<Pair<String, Stats>>()
|
||||||
|
|
||||||
// allTerrains iterates over base, natural wonder, then features
|
// allTerrains iterates over base, natural wonder, then features
|
||||||
for (terrain in tile.allTerrains) {
|
for (terrain in tile.allTerrains) {
|
||||||
@ -183,7 +192,8 @@ class TileStatFunctions(val tile: Tile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only gets the tile percentage bonus, not the improvement percentage bonus
|
// Only gets the tile percentage bonus, not the improvement percentage bonus
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate", "purity")
|
||||||
|
@Readonly
|
||||||
fun getTilePercentageStats(observingCiv: Civilization?, city: City?, uniqueCache: LocalUniqueCache): EnumMap<TilePercentageCategory, Stats> {
|
fun getTilePercentageStats(observingCiv: Civilization?, city: City?, uniqueCache: LocalUniqueCache): EnumMap<TilePercentageCategory, Stats> {
|
||||||
val terrainStats = Stats()
|
val terrainStats = Stats()
|
||||||
val gameContext = GameContext(civInfo = observingCiv, city = city, tile = tile)
|
val gameContext = GameContext(civInfo = observingCiv, city = city, tile = tile)
|
||||||
@ -274,6 +284,7 @@ class TileStatFunctions(val tile: Tile) {
|
|||||||
|
|
||||||
/** Returns the extra stats that we would get if we switched to this improvement
|
/** Returns the extra stats that we would get if we switched to this improvement
|
||||||
* Can be negative if we're switching to a worse improvement */
|
* Can be negative if we're switching to a worse improvement */
|
||||||
|
@Readonly
|
||||||
fun getStatDiffForImprovement(
|
fun getStatDiffForImprovement(
|
||||||
improvement: TileImprovement,
|
improvement: TileImprovement,
|
||||||
observingCiv: Civilization,
|
observingCiv: Civilization,
|
||||||
@ -285,16 +296,17 @@ class TileStatFunctions(val tile: Tile) {
|
|||||||
val currentStats = currentTileStats
|
val currentStats = currentTileStats
|
||||||
?: getTileStats(city, observingCiv, cityUniqueCache)
|
?: getTileStats(city, observingCiv, cityUniqueCache)
|
||||||
|
|
||||||
val tileClone = tile.clone(addUnits = false)
|
@LocalState val tileClone = tile.clone(addUnits = false)
|
||||||
tileClone.setTerrainTransients()
|
tileClone.setTerrainTransients()
|
||||||
|
|
||||||
tileClone.setImprovement(improvement.name)
|
tileClone.setImprovement(improvement.name)
|
||||||
val futureStats = tileClone.stats.getTileStats(city, observingCiv, cityUniqueCache)
|
@LocalState val futureStats = tileClone.stats.getTileStats(city, observingCiv, cityUniqueCache)
|
||||||
|
|
||||||
return futureStats.minus(currentStats)
|
return futureStats.minus(currentStats)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also multiplies the stats by the percentage bonus for improvements (but not for tiles)
|
// Also multiplies the stats by the percentage bonus for improvements (but not for tiles)
|
||||||
|
@Readonly
|
||||||
private fun getExtraImprovementStats(
|
private fun getExtraImprovementStats(
|
||||||
improvement: TileImprovement,
|
improvement: TileImprovement,
|
||||||
observingCiv: Civilization,
|
observingCiv: Civilization,
|
||||||
|
@ -52,7 +52,6 @@ open class Counter<K>(
|
|||||||
@Readonly
|
@Readonly
|
||||||
/** Creates a new instance (does not modify) */
|
/** Creates a new instance (does not modify) */
|
||||||
operator fun times(amount: Int): Counter<K> {
|
operator fun times(amount: Int): Counter<K> {
|
||||||
@LocalState
|
|
||||||
val newCounter = Counter<K>()
|
val newCounter = Counter<K>()
|
||||||
for (key in keys) newCounter[key] = this[key] * amount
|
for (key in keys) newCounter[key] = this[key] * amount
|
||||||
return newCounter
|
return newCounter
|
||||||
|
@ -556,7 +556,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
|
|||||||
state ?: GameContext.EmptyState)
|
state ?: GameContext.EmptyState)
|
||||||
if (uniques.none() && requiredResource == null) return Counter.ZERO
|
if (uniques.none() && requiredResource == null) return Counter.ZERO
|
||||||
|
|
||||||
@LocalState val resourceRequirements = Counter<String>()
|
val resourceRequirements = Counter<String>()
|
||||||
if (requiredResource != null) resourceRequirements[requiredResource!!] = 1
|
if (requiredResource != null) resourceRequirements[requiredResource!!] = 1
|
||||||
for (unique in uniques)
|
for (unique in uniques)
|
||||||
resourceRequirements.add(unique.params[1], unique.params[0].toInt())
|
resourceRequirements.add(unique.params[1], unique.params[0].toInt())
|
||||||
|
@ -13,7 +13,6 @@ import com.unciv.models.stats.Stat
|
|||||||
import com.unciv.models.stats.Stat.Companion.statsUsableToBuy
|
import com.unciv.models.stats.Stat.Companion.statsUsableToBuy
|
||||||
import com.unciv.ui.components.extensions.toPercent
|
import com.unciv.ui.components.extensions.toPercent
|
||||||
import com.unciv.ui.components.fonts.Fonts
|
import com.unciv.ui.components.fonts.Fonts
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Pure
|
import yairm210.purity.annotations.Pure
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
@ -133,7 +132,7 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
|
|||||||
|
|
||||||
@Readonly
|
@Readonly
|
||||||
override fun getStockpiledResourceRequirements(state: GameContext): Counter<String> {
|
override fun getStockpiledResourceRequirements(state: GameContext): Counter<String> {
|
||||||
@LocalState val counter = Counter<String>()
|
val counter = Counter<String>()
|
||||||
for (unique in getMatchingUniquesNotConflicting(UniqueType.CostsResources, state)){
|
for (unique in getMatchingUniquesNotConflicting(UniqueType.CostsResources, state)){
|
||||||
var amount = unique.params[0].toInt()
|
var amount = unique.params[0].toInt()
|
||||||
if (unique.isModifiedByGameSpeed()) amount = (amount * state.gameInfo!!.speed.modifier).toInt()
|
if (unique.isModifiedByGameSpeed()) amount = (amount * state.gameInfo!!.speed.modifier).toInt()
|
||||||
|
@ -14,7 +14,6 @@ import com.unciv.models.stats.Stats
|
|||||||
import com.unciv.ui.objectdescriptions.uniquesToCivilopediaTextLines
|
import com.unciv.ui.objectdescriptions.uniquesToCivilopediaTextLines
|
||||||
import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
||||||
import yairm210.purity.annotations.Cache
|
import yairm210.purity.annotations.Cache
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
|
|
||||||
class TileResource : RulesetStatsObject(), GameResource {
|
class TileResource : RulesetStatsObject(), GameResource {
|
||||||
@ -61,7 +60,7 @@ class TileResource : RulesetStatsObject(), GameResource {
|
|||||||
val ruleset = this.ruleset
|
val ruleset = this.ruleset
|
||||||
?: throw IllegalStateException("No ruleset on TileResource when initializing improvements")
|
?: throw IllegalStateException("No ruleset on TileResource when initializing improvements")
|
||||||
|
|
||||||
@LocalState val allImprovementsLocal = mutableSetOf<String>()
|
val allImprovementsLocal = mutableSetOf<String>()
|
||||||
|
|
||||||
if (improvement != null) allImprovementsLocal += improvement!!
|
if (improvement != null) allImprovementsLocal += improvement!!
|
||||||
allImprovementsLocal.addAll(improvedBy)
|
allImprovementsLocal.addAll(improvedBy)
|
||||||
|
@ -11,7 +11,6 @@ import com.unciv.models.translations.getModifiers
|
|||||||
import com.unciv.models.translations.getPlaceholderParameters
|
import com.unciv.models.translations.getPlaceholderParameters
|
||||||
import com.unciv.models.translations.getPlaceholderText
|
import com.unciv.models.translations.getPlaceholderText
|
||||||
import com.unciv.models.translations.removeConditionals
|
import com.unciv.models.translations.removeConditionals
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
@ -181,12 +180,12 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
|
|||||||
// note this is only done for the replacement, not the deprecated unique, thus parameters of
|
// note this is only done for the replacement, not the deprecated unique, thus parameters of
|
||||||
// conditionals on the deprecated unique are ignored
|
// conditionals on the deprecated unique are ignored
|
||||||
|
|
||||||
@LocalState val finalPossibleUniques = ArrayList<String>()
|
val finalPossibleUniques = ArrayList<String>()
|
||||||
|
|
||||||
for (possibleUnique in possibleUniques) {
|
for (possibleUnique in possibleUniques) {
|
||||||
var resultingUnique = possibleUnique
|
var resultingUnique = possibleUnique
|
||||||
|
|
||||||
@LocalState val timesParameterWasSeen = Counter<String>()
|
val timesParameterWasSeen = Counter<String>()
|
||||||
for (parameter in possibleUnique.replace('<', ' ').getPlaceholderParameters()) {
|
for (parameter in possibleUnique.replace('<', ' ').getPlaceholderParameters()) {
|
||||||
val parameterHasSign = parameter.startsWith('-') || parameter.startsWith('+')
|
val parameterHasSign = parameter.startsWith('-') || parameter.startsWith('+')
|
||||||
val parameterUnsigned = if (parameterHasSign) parameter.drop(1) else parameter
|
val parameterUnsigned = if (parameterHasSign) parameter.drop(1) else parameter
|
||||||
|
@ -13,7 +13,6 @@ import com.unciv.models.ruleset.validation.Suppression
|
|||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import com.unciv.models.stats.SubStat
|
import com.unciv.models.stats.SubStat
|
||||||
import com.unciv.models.translations.TranslationFileWriter
|
import com.unciv.models.translations.TranslationFileWriter
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Pure
|
import yairm210.purity.annotations.Pure
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
|
|
||||||
@ -714,7 +713,7 @@ enum class UniqueParameterType(
|
|||||||
}
|
}
|
||||||
@Readonly
|
@Readonly
|
||||||
private fun scanExistingValues(type: UniqueParameterType, ruleset: Ruleset): Set<String> {
|
private fun scanExistingValues(type: UniqueParameterType, ruleset: Ruleset): Set<String> {
|
||||||
@LocalState val result = mutableSetOf<String>()
|
val result = mutableSetOf<String>()
|
||||||
for (unique in ruleset.allUniques()) {
|
for (unique in ruleset.allUniques()) {
|
||||||
val parameterMap = unique.type?.parameterTypeMap ?: continue
|
val parameterMap = unique.type?.parameterTypeMap ?: continue
|
||||||
for ((index, param) in unique.params.withIndex()) {
|
for ((index, param) in unique.params.withIndex()) {
|
||||||
|
@ -1489,7 +1489,7 @@ enum class UniqueType(
|
|||||||
* For 95% of cases, auto-matching is fine. */
|
* For 95% of cases, auto-matching is fine. */
|
||||||
@Readonly
|
@Readonly
|
||||||
open fun parameterTypeMapInitializer(): ArrayList<List<UniqueParameterType>> {
|
open fun parameterTypeMapInitializer(): ArrayList<List<UniqueParameterType>> {
|
||||||
@LocalState val map = ArrayList<List<UniqueParameterType>>()
|
val map = ArrayList<List<UniqueParameterType>>()
|
||||||
for (placeholder in text.getPlaceholderParameters()) {
|
for (placeholder in text.getPlaceholderParameters()) {
|
||||||
val matchingParameterTypes = placeholder
|
val matchingParameterTypes = placeholder
|
||||||
.split('/')
|
.split('/')
|
||||||
|
@ -26,7 +26,6 @@ import com.unciv.ui.objectdescriptions.BaseUnitDescriptions
|
|||||||
import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
||||||
import com.unciv.utils.yieldIfNotNull
|
import com.unciv.utils.yieldIfNotNull
|
||||||
import yairm210.purity.annotations.Cache
|
import yairm210.purity.annotations.Cache
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
@ -478,7 +477,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
|
|||||||
|
|
||||||
/** Returns resource requirements from both uniques and requiredResource field */
|
/** Returns resource requirements from both uniques and requiredResource field */
|
||||||
override fun getResourceRequirementsPerTurn(state: GameContext?): Counter<String> {
|
override fun getResourceRequirementsPerTurn(state: GameContext?): Counter<String> {
|
||||||
@LocalState val resourceRequirements = Counter<String>()
|
val resourceRequirements = Counter<String>()
|
||||||
if (requiredResource != null) resourceRequirements[requiredResource!!] = 1
|
if (requiredResource != null) resourceRequirements[requiredResource!!] = 1
|
||||||
for (unique in getMatchingUniques(UniqueType.ConsumesResources, state ?: GameContext.EmptyState))
|
for (unique in getMatchingUniques(UniqueType.ConsumesResources, state ?: GameContext.EmptyState))
|
||||||
resourceRequirements.add(unique.params[1], unique.params[0].toInt())
|
resourceRequirements.add(unique.params[1], unique.params[0].toInt())
|
||||||
|
@ -349,7 +349,7 @@ class UniqueValidator(val ruleset: Ruleset) {
|
|||||||
unique: Unique,
|
unique: Unique,
|
||||||
): List<UniqueComplianceError> {
|
): List<UniqueComplianceError> {
|
||||||
if (unique.type == null) return emptyList()
|
if (unique.type == null) return emptyList()
|
||||||
@LocalState val errorList = ArrayList<UniqueComplianceError>()
|
val errorList = ArrayList<UniqueComplianceError>()
|
||||||
for ((index, param) in unique.params.withIndex()) {
|
for ((index, param) in unique.params.withIndex()) {
|
||||||
// Trying to catch the error at #11404
|
// Trying to catch the error at #11404
|
||||||
if (unique.type.parameterTypeMap.size != unique.params.size) {
|
if (unique.type.parameterTypeMap.size != unique.params.size) {
|
||||||
|
@ -125,6 +125,7 @@ open class Stats(
|
|||||||
|
|
||||||
/** **Non-Mutating function**
|
/** **Non-Mutating function**
|
||||||
* @return a new [Stats] instance with the result of multiplying each value of this instance by [number] as a new instance */
|
* @return a new [Stats] instance with the result of multiplying each value of this instance by [number] as a new instance */
|
||||||
|
@Readonly
|
||||||
operator fun times(number: Float) = Stats(
|
operator fun times(number: Float) = Stats(
|
||||||
production * number,
|
production * number,
|
||||||
food * number,
|
food * number,
|
||||||
|
@ -483,7 +483,7 @@ fun String.getPlaceholderParameters(): List<String> {
|
|||||||
|
|
||||||
val stringToParse = this.removeConditionals()
|
val stringToParse = this.removeConditionals()
|
||||||
|
|
||||||
@LocalState val parameters = ArrayList<String>()
|
val parameters = ArrayList<String>()
|
||||||
var depthOfBraces = 0
|
var depthOfBraces = 0
|
||||||
var startOfCurrentParameter = -1
|
var startOfCurrentParameter = -1
|
||||||
stringToParse.indices.forEach { i ->
|
stringToParse.indices.forEach { i ->
|
||||||
|
@ -9,7 +9,6 @@ import com.unciv.models.translations.removeConditionals
|
|||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.ui.components.fonts.FontRulesetIcons
|
import com.unciv.ui.components.fonts.FontRulesetIcons
|
||||||
import com.unciv.ui.components.fonts.Fonts
|
import com.unciv.ui.components.fonts.Fonts
|
||||||
import yairm210.purity.annotations.LocalState
|
|
||||||
import yairm210.purity.annotations.Readonly
|
import yairm210.purity.annotations.Readonly
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
|
||||||
@ -180,7 +179,7 @@ object UnitActionModifiers {
|
|||||||
if (maxUsages!=null) effects += "${usagesLeft(unit, actionUnique)}/$maxUsages"
|
if (maxUsages!=null) effects += "${usagesLeft(unit, actionUnique)}/$maxUsages"
|
||||||
|
|
||||||
if (actionUnique.hasModifier(UniqueType.UnitActionStatsCost)) {
|
if (actionUnique.hasModifier(UniqueType.UnitActionStatsCost)) {
|
||||||
@LocalState val statCost = Stats()
|
val statCost = Stats()
|
||||||
for (conditional in actionUnique.getModifiers(UniqueType.UnitActionStatsCost))
|
for (conditional in actionUnique.getModifiers(UniqueType.UnitActionStatsCost))
|
||||||
statCost.add(conditional.stats)
|
statCost.add(conditional.stats)
|
||||||
effects += statCost.toStringOnlyIcons(false)
|
effects += statCost.toStringOnlyIcons(false)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user