mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 11:34:54 -04:00
chore(purity)
This commit is contained in:
parent
a4a573a945
commit
8e5b36984c
@ -67,6 +67,7 @@ allprojects {
|
||||
|
||||
"kotlin.collections.random",
|
||||
"kotlin.hashCode",
|
||||
"kotlin.collections.shuffled",
|
||||
)
|
||||
wellKnownPureClasses = setOf(
|
||||
"java.lang.StackTraceElement" // moved
|
||||
|
@ -9,6 +9,8 @@ import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.logic.map.mapunit.MapUnit
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import yairm210.purity.annotations.Pure
|
||||
import yairm210.purity.annotations.Readonly
|
||||
|
||||
object AirUnitAutomation {
|
||||
|
||||
@ -29,7 +31,7 @@ object AirUnitAutomation {
|
||||
if (friendlyUnusedFighterCount < enemyFighters) return
|
||||
|
||||
if (friendlyUsedFighterCount <= enemyFighters) {
|
||||
fun airSweepDamagePercentBonus(): Int {
|
||||
@Readonly fun airSweepDamagePercentBonus(): Int {
|
||||
return unit.getMatchingUniques(UniqueType.StrengthWhenAirsweep)
|
||||
.sumOf { it.params[0].toInt() }
|
||||
}
|
||||
@ -149,6 +151,7 @@ object AirUnitAutomation {
|
||||
* Ranks the tile to nuke based off of all tiles in it's blast radius
|
||||
* By default the value is -500 to prevent inefficient nuking.
|
||||
*/
|
||||
@Readonly
|
||||
private fun getNukeLocationValue(nuke: MapUnit, tile: Tile): Int {
|
||||
val civ = nuke.civ
|
||||
if (!Nuke.mayUseNuke(MapUnitCombatant(nuke), tile)) return Int.MIN_VALUE
|
||||
@ -166,6 +169,7 @@ object AirUnitAutomation {
|
||||
var explosionValue = -500
|
||||
|
||||
// Returns either ourValue or thierValue depending on if the input Civ matches the Nuke's Civ
|
||||
@Pure
|
||||
fun evaluateCivValue(targetCiv: Civilization, ourValue: Int, theirValue: Int): Int {
|
||||
if (targetCiv == civ) // We are nuking something that we own!
|
||||
return ourValue
|
||||
|
@ -11,9 +11,11 @@ import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionModifiers
|
||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionModifiers.canUse
|
||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActions
|
||||
import yairm210.purity.annotations.Readonly
|
||||
|
||||
object CivilianUnitAutomation {
|
||||
|
||||
@Readonly
|
||||
fun shouldClearTileForAddInCapitalUnits(unit: MapUnit, tile: Tile) =
|
||||
tile.isCityCenter() && tile.getCity()!!.isCapital()
|
||||
&& !unit.hasUnique(UniqueType.AddInCapital)
|
||||
@ -23,6 +25,7 @@ object CivilianUnitAutomation {
|
||||
// To allow "found city" actions that can only trigger a limited number of times
|
||||
|
||||
// Slightly modified getUsableUnitActionUniques() to allow for settlers with *conditional* settling uniques
|
||||
@Readonly
|
||||
fun hasSettlerAction(uniqueType: UniqueType) =
|
||||
unit.getMatchingUniques(uniqueType, GameContext.IgnoreConditionals)
|
||||
.filter { unique -> !unique.hasModifier(UniqueType.UnitActionExtraLimitedTimes) }
|
||||
@ -172,6 +175,7 @@ object CivilianUnitAutomation {
|
||||
return // The AI doesn't know how to handle unknown civilian units
|
||||
}
|
||||
|
||||
@Readonly
|
||||
private fun isLateGame(civ: Civilization): Boolean {
|
||||
val researchCompletePercent =
|
||||
(civ.tech.researchedTechnologies.size * 1.0f) / civ.gameInfo.ruleset.technologies.size
|
||||
|
@ -8,6 +8,7 @@ import com.unciv.logic.city.City
|
||||
import com.unciv.logic.map.mapunit.MapUnit
|
||||
import com.unciv.logic.map.mapunit.movement.PathsToTilesWithinTurn
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import yairm210.purity.annotations.Readonly
|
||||
|
||||
object HeadTowardsEnemyCityAutomation {
|
||||
|
||||
@ -28,6 +29,7 @@ object HeadTowardsEnemyCityAutomation {
|
||||
)
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun getEnemyCitiesByPriority(unit: MapUnit): Sequence<City> {
|
||||
val enemies = unit.civ.getKnownCivs()
|
||||
.filter { unit.civ.isAtWarWith(it) && it.cities.isNotEmpty() }
|
||||
@ -94,6 +96,7 @@ object HeadTowardsEnemyCityAutomation {
|
||||
}
|
||||
|
||||
/** Cannot take within 5 turns */
|
||||
@Readonly
|
||||
private fun cannotTakeCitySoon(
|
||||
ourUnitsAroundEnemyCity: Sequence<MapUnit>,
|
||||
city: City
|
||||
|
@ -24,12 +24,14 @@ import com.unciv.models.ruleset.unit.BaseUnit
|
||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsPillage
|
||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsUpgrade
|
||||
import com.unciv.utils.randomWeighted
|
||||
import yairm210.purity.annotations.Readonly
|
||||
|
||||
object UnitAutomation {
|
||||
|
||||
private const val CLOSE_ENEMY_TILES_AWAY_LIMIT = 5
|
||||
private const val CLOSE_ENEMY_TURNS_AWAY_LIMIT = 3f
|
||||
|
||||
@Readonly
|
||||
private fun isGoodTileToExplore(unit: MapUnit, tile: Tile): Boolean {
|
||||
return (tile.getOwner() == null || !tile.getOwner()!!.isCityState)
|
||||
&& tile.getTilesInDistance(unit.getVisibilityRange()).any { !unit.civ.hasExplored(it) }
|
||||
@ -103,6 +105,7 @@ object UnitAutomation {
|
||||
return false
|
||||
}
|
||||
|
||||
@Readonly
|
||||
private fun isGoodTileForFogBusting(unit: MapUnit, tile: Tile): Boolean {
|
||||
return unit.movement.canMoveTo(tile)
|
||||
&& tile.getOwner() == null
|
||||
@ -153,8 +156,10 @@ object UnitAutomation {
|
||||
/** Get the base unit this map unit could upgrade to, respecting researched tech and nation uniques only.
|
||||
* Note that if the unit can't upgrade, the current BaseUnit is returned.
|
||||
*/
|
||||
@Readonly
|
||||
private fun getUnitsToUpgradeTo(unit: MapUnit): Sequence<BaseUnit> {
|
||||
|
||||
@Readonly
|
||||
fun isInvalidUpgradeDestination(baseUnit: BaseUnit): Boolean {
|
||||
if (!unit.civ.tech.isResearched(baseUnit))
|
||||
return true
|
||||
@ -423,6 +428,7 @@ object UnitAutomation {
|
||||
/**
|
||||
* @return true if the tile is safe and the unit can heal to full within [turns]
|
||||
*/
|
||||
@Readonly
|
||||
private fun canUnitHealInTurnsOnCurrentTile(unit: MapUnit, turns: Int, noEnemyDistance: Int = 3): Boolean {
|
||||
if (unit.hasUnique(UniqueType.HealsEvenAfterAction)) return false // We can keep on moving
|
||||
// Check if we are not in a safe city and there is an enemy nearby this isn't a good tile to heal on
|
||||
@ -433,6 +439,7 @@ object UnitAutomation {
|
||||
return healthRequiredPerTurn <= unit.rankTileForHealing(unit.getTile())
|
||||
}
|
||||
|
||||
@Readonly
|
||||
private fun getDangerousTiles(unit: MapUnit): HashSet<Tile> {
|
||||
val nearbyEnemyUnits = unit.currentTile.getTilesInDistance(3)
|
||||
.flatMap { tile -> tile.getUnits().filter { unit.civ.isAtWarWith(it.civ) } }
|
||||
@ -517,6 +524,7 @@ object UnitAutomation {
|
||||
private fun tryPrepare(unit: MapUnit): Boolean {
|
||||
val civInfo = unit.civ
|
||||
|
||||
@Readonly
|
||||
fun hasPreparationFlag(targetCiv: Civilization): Boolean {
|
||||
val diploManager = civInfo.getDiplomacyManager(targetCiv)!!
|
||||
if (diploManager.hasFlag(DiplomacyFlags.Denunciation)
|
||||
@ -685,7 +693,7 @@ object UnitAutomation {
|
||||
unit.movement.headTowards(closestReachableCityNeedsDefending.getCenterTile())
|
||||
return true
|
||||
}
|
||||
|
||||
@Readonly
|
||||
private fun isCityThatNeedsDefendingInWartime(city: City): Boolean {
|
||||
if (city.health < city.getMaxHealth()) return true // this city is under attack!
|
||||
for (enemyCivCity in city.civ.diplomacy.values
|
||||
@ -696,7 +704,7 @@ object UnitAutomation {
|
||||
}
|
||||
|
||||
private fun tryStationingMeleeNavalUnit(unit: MapUnit): Boolean {
|
||||
fun isMeleeNaval(mapUnit: MapUnit) = mapUnit.baseUnit.isMelee() && mapUnit.type.isWaterUnit()
|
||||
@Readonly fun isMeleeNaval(mapUnit: MapUnit) = mapUnit.baseUnit.isMelee() && mapUnit.type.isWaterUnit()
|
||||
|
||||
if (!isMeleeNaval(unit)) return false
|
||||
val closeCity = unit.getTile().getTilesInDistance(3)
|
||||
|
@ -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.Readonly
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
@ -678,7 +679,8 @@ object Battle {
|
||||
city.isBeingRazed = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Readonly
|
||||
fun getMapCombatantOfTile(tile: Tile): ICombatant? {
|
||||
if (tile.isCityCenter()) return CityCombatant(tile.getCity()!!)
|
||||
if (tile.militaryUnit != null) return MapUnitCombatant(tile.militaryUnit!!)
|
||||
|
@ -15,6 +15,7 @@ import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.components.extensions.toPercent
|
||||
import com.unciv.ui.screens.worldscreen.bottombar.BattleTable
|
||||
import yairm210.purity.annotations.Readonly
|
||||
import kotlin.math.ulp
|
||||
import kotlin.random.Random
|
||||
|
||||
@ -28,6 +29,7 @@ object Nuke {
|
||||
*
|
||||
* Both [BattleTable.simulateNuke] and [AirUnitAutomation.automateNukes] check range, so that check is omitted here.
|
||||
*/
|
||||
@Readonly
|
||||
fun mayUseNuke(nuke: MapUnitCombatant, targetTile: Tile): Boolean {
|
||||
val attackerCiv = nuke.getCivInfo()
|
||||
val launchTile = nuke.getTile()
|
||||
|
@ -30,6 +30,7 @@ class ThreatManager(val civInfo: Civilization) {
|
||||
* The result value is cached and since it is called each turn in NextTurnAutomation.getUnitPriority
|
||||
* each subsequent calls are likely to be free.
|
||||
*/
|
||||
@Readonly @Suppress("purity") //tilesWithEnemies is implicit cache
|
||||
fun getDistanceToClosestEnemyUnit(tile: Tile, maxDist: Int, takeLargerValues: Boolean = true): Int {
|
||||
val tileData = distanceToClosestEnemyTiles[tile]
|
||||
// Needs to be a high value, but not the max value so we can still add to it. Example: nextTurnAutomation sorting
|
||||
|
@ -12,6 +12,7 @@ import com.unciv.models.ruleset.tile.TileResource
|
||||
import com.unciv.models.ruleset.unique.GameContext
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.utils.randomWeighted
|
||||
import yairm210.purity.annotations.Readonly
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
@ -80,6 +81,7 @@ object LuxuryResourcePlacementLogic {
|
||||
return Pair(cityStateLuxuries, randomLuxuries)
|
||||
}
|
||||
|
||||
@Readonly
|
||||
private fun getLuxuriesForRandomPlacement(
|
||||
assignableLuxuries: List<TileResource>,
|
||||
amountRegionsWithLuxury: HashMap<String, Int>,
|
||||
@ -97,6 +99,7 @@ object LuxuryResourcePlacementLogic {
|
||||
return remainingLuxuries.drop(targetDisabledLuxuries)
|
||||
}
|
||||
|
||||
@Readonly
|
||||
private fun getCandidateLuxuries(
|
||||
assignableLuxuries: List<TileResource>,
|
||||
amountRegionsWithLuxury: HashMap<String, Int>,
|
||||
|
@ -5,6 +5,7 @@ import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.ruleset.unit.BaseUnit
|
||||
import com.unciv.ui.components.extensions.toPercent
|
||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionsUpgrade
|
||||
import yairm210.purity.annotations.Readonly
|
||||
import kotlin.math.pow
|
||||
|
||||
class UnitUpgradeManager(val unit: MapUnit) {
|
||||
@ -16,6 +17,7 @@ class UnitUpgradeManager(val unit: MapUnit) {
|
||||
* @param ignoreResources Ignore resource requirements (tech still counts)
|
||||
* Used to display disabled Upgrade button
|
||||
*/
|
||||
@Readonly
|
||||
fun canUpgrade(
|
||||
unitToUpgradeTo: BaseUnit,
|
||||
ignoreRequirements: Boolean = false,
|
||||
|
@ -108,6 +108,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
|
||||
super<INonPerpetualConstruction>.isUnavailableBySettings(gameInfo) ||
|
||||
(!gameInfo.gameParameters.nuclearWeaponsEnabled && isNuclearWeapon())
|
||||
|
||||
@Readonly
|
||||
fun getUpgradeUnits(gameContext: GameContext = GameContext.EmptyState): Sequence<String> {
|
||||
return sequence {
|
||||
yieldIfNotNull(upgradesTo)
|
||||
@ -116,6 +117,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
|
||||
}
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun getRulesetUpgradeUnits(gameContext: GameContext = GameContext.EmptyState): Sequence<BaseUnit> {
|
||||
return sequence {
|
||||
for (unit in getUpgradeUnits(gameContext))
|
||||
|
@ -83,6 +83,7 @@ fun <T> Sequence<T>.toGdxArray(): Array<T> {
|
||||
}
|
||||
|
||||
/** [yield][SequenceScope.yield]s [element] if it's not null */
|
||||
@Pure
|
||||
suspend fun <T> SequenceScope<T>.yieldIfNotNull(element: T?) {
|
||||
if (element != null) yield(element)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user