mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-22 19:08:48 -04:00
chore: Tile purity
This commit is contained in:
parent
673c33bb01
commit
c1f0b97e2d
@ -240,6 +240,7 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
|
||||
/** Get barbarian civ
|
||||
* @throws NoSuchElementException in no-barbarians games! */
|
||||
fun getBarbarianCivilization() = getCivilization(Constants.barbarians)
|
||||
@Readonly @Suppress("purity") // This should be autorecognized!!
|
||||
fun getDifficulty() = difficultyObject
|
||||
/** Access a cached `GlobalUniques` that combines the [ruleset]'s [globalUniques][Ruleset.globalUniques]
|
||||
* with the Uniques of the chosen [speed] and [difficulty][getDifficulty] */
|
||||
|
@ -324,10 +324,8 @@ class Civilization : IsPartOfGameInfoSerialization {
|
||||
if (!knows(civInfo)) diplomacyFunctions.makeCivilizationsMeet(civInfo)
|
||||
return getDiplomacyManager(civInfo.civName)!!
|
||||
}
|
||||
@Readonly
|
||||
fun getDiplomacyManager(civInfo: Civilization): DiplomacyManager? = getDiplomacyManager(civInfo.civName)
|
||||
@Readonly
|
||||
fun getDiplomacyManager(civName: String): DiplomacyManager? = diplomacy[civName]
|
||||
@Readonly fun getDiplomacyManager(civInfo: Civilization): DiplomacyManager? = getDiplomacyManager(civInfo.civName)
|
||||
@Readonly fun getDiplomacyManager(civName: String): DiplomacyManager? = diplomacy[civName]
|
||||
|
||||
fun getProximity(civInfo: Civilization) = getProximity(civInfo.civName)
|
||||
@Suppress("MemberVisibilityCanBePrivate") // same visibility for overloads
|
||||
@ -347,17 +345,15 @@ class Civilization : IsPartOfGameInfoSerialization {
|
||||
fun getKnownCivsWithSpectators() = diplomacy.values.asSequence().map { it.otherCiv() }
|
||||
.filter { !it.isDefeated() }
|
||||
|
||||
@Readonly
|
||||
fun knows(otherCivName: String) = diplomacy.containsKey(otherCivName)
|
||||
@Readonly
|
||||
fun knows(otherCiv: Civilization) = knows(otherCiv.civName)
|
||||
|
||||
@Readonly fun knows(otherCivName: String) = diplomacy.containsKey(otherCivName)
|
||||
@Readonly fun knows(otherCiv: Civilization) = knows(otherCiv.civName)
|
||||
@Readonly
|
||||
fun getCapital(firstCityIfNoCapital: Boolean = true) = cities.firstOrNull { it.isCapital() } ?:
|
||||
if (firstCityIfNoCapital) cities.firstOrNull() else null
|
||||
@Readonly
|
||||
fun isHuman() = playerType == PlayerType.Human
|
||||
@Readonly
|
||||
fun isAI() = playerType == PlayerType.AI
|
||||
|
||||
@Readonly fun isHuman() = playerType == PlayerType.Human
|
||||
@Readonly fun isAI() = playerType == PlayerType.AI
|
||||
@Readonly
|
||||
fun isAIOrAutoPlaying(): Boolean {
|
||||
if (playerType == PlayerType.AI) return true
|
||||
@ -365,14 +361,11 @@ class Civilization : IsPartOfGameInfoSerialization {
|
||||
val worldScreen = UncivGame.Current.worldScreen ?: return false
|
||||
return worldScreen.viewingCiv == this && worldScreen.autoPlay.isAutoPlaying()
|
||||
}
|
||||
@Readonly
|
||||
fun isOneCityChallenger() = playerType == PlayerType.Human && gameInfo.gameParameters.oneCityChallenge
|
||||
@Readonly
|
||||
fun isCurrentPlayer() = gameInfo.currentPlayerCiv == this
|
||||
@Readonly
|
||||
fun isMajorCiv() = nation.isMajorCiv
|
||||
@Readonly
|
||||
fun isMinorCiv() = nation.isCityState || nation.isBarbarian
|
||||
|
||||
@Readonly fun isOneCityChallenger() = playerType == PlayerType.Human && gameInfo.gameParameters.oneCityChallenge
|
||||
@Readonly fun isCurrentPlayer() = gameInfo.currentPlayerCiv == this
|
||||
@Readonly fun isMajorCiv() = nation.isMajorCiv
|
||||
@Readonly fun isMinorCiv() = nation.isCityState || nation.isBarbarian
|
||||
|
||||
@delegate:Transient
|
||||
val isCityState by lazy { nation.isCityState }
|
||||
@ -380,10 +373,9 @@ class Civilization : IsPartOfGameInfoSerialization {
|
||||
@delegate:Transient
|
||||
val isBarbarian by lazy { nation.isBarbarian }
|
||||
|
||||
@Readonly
|
||||
fun isSpectator() = nation.isSpectator
|
||||
@Readonly
|
||||
fun isAlive(): Boolean = !isDefeated()
|
||||
|
||||
@Readonly fun isSpectator() = nation.isSpectator
|
||||
@Readonly fun isAlive(): Boolean = !isDefeated()
|
||||
|
||||
@delegate:Transient
|
||||
val cityStateType: CityStateType by lazy { gameInfo.ruleset.cityStateTypes[nation.cityStateType!!]!! }
|
||||
@ -407,13 +399,6 @@ class Civilization : IsPartOfGameInfoSerialization {
|
||||
|
||||
}
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
fun getPreferredVictoryTypeObjects(): List<Victory> {
|
||||
val preferredVictoryTypes = getPreferredVictoryTypes()
|
||||
return if (preferredVictoryTypes.contains(Constants.neutralVictoryType)) emptyList()
|
||||
else preferredVictoryTypes.map { gameInfo.ruleset.victories[it]!! }
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun getPersonality(): Personality {
|
||||
return if (isAIOrAutoPlaying()) gameInfo.ruleset.personalities[nation.personality] ?: Personality.neutralPersonality
|
||||
@ -1081,6 +1066,7 @@ class Civilization : IsPartOfGameInfoSerialization {
|
||||
|
||||
fun asPreview() = CivilizationInfoPreview(this)
|
||||
|
||||
@Readonly
|
||||
fun getLastSeenImprovement(position: Vector2): String? {
|
||||
if (isAI() || isSpectator()) return null
|
||||
return lastSeenImprovement[position]
|
||||
|
@ -147,6 +147,7 @@ class DiplomacyFunctions(val civInfo: Civilization) {
|
||||
* Use [UnitMovement.canPassThrough] to check whether a specific unit can pass through
|
||||
* a specific tile.
|
||||
*/
|
||||
@Readonly
|
||||
fun canPassThroughTiles(otherCiv: Civilization): Boolean {
|
||||
if (otherCiv == civInfo) return true
|
||||
if (otherCiv.isBarbarian) return true
|
||||
|
@ -18,10 +18,11 @@ import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.ruleset.unit.BaseUnit
|
||||
import com.unciv.utils.addToMapOfSets
|
||||
import com.unciv.utils.contains
|
||||
import yairm210.purity.annotations.LocalState
|
||||
import yairm210.purity.annotations.Readonly
|
||||
import java.lang.Integer.max
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
|
||||
/** An Unciv map with all properties as produced by the [map editor][com.unciv.ui.screens.mapeditorscreen.MapEditorScreen]
|
||||
* or [MapGenerator][com.unciv.logic.map.mapgenerator.MapGenerator]; or as part of a running [game][GameInfo].
|
||||
@ -400,8 +401,10 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
|
||||
data class ViewableTile(val tile: Tile, val maxHeightSeenToTile: Int, val isVisible: Boolean, val isAttackable: Boolean)
|
||||
|
||||
/** @return List of tiles visible from location [position] for a unit with sight range [sightDistance] */
|
||||
@Readonly
|
||||
fun getViewableTiles(position: Vector2, sightDistance: Int, forAttack: Boolean = false): List<Tile> {
|
||||
val aUnitHeight = get(position).unitHeight
|
||||
@LocalState
|
||||
val viewableTiles = mutableListOf(ViewableTile(
|
||||
get(position),
|
||||
aUnitHeight,
|
||||
@ -412,6 +415,7 @@ class TileMap(initialCapacity: Int = 10) : IsPartOfGameInfoSerialization {
|
||||
for (i in 1..sightDistance+1) { // in each layer,
|
||||
// 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
|
||||
@LocalState
|
||||
val tilesToAddInDistanceI = ArrayList<ViewableTile>()
|
||||
|
||||
for (cTile in getTilesAtDistance(position, i)) { // for each tile in that layer,
|
||||
|
@ -26,6 +26,7 @@ import com.unciv.models.ruleset.unit.BaseUnit
|
||||
import com.unciv.models.ruleset.unit.UnitType
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.UnitMovementMemoryType
|
||||
import yairm210.purity.annotations.Readonly
|
||||
import java.text.DecimalFormat
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.ulp
|
||||
@ -230,6 +231,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
fun getMovementString(): String =
|
||||
(DecimalFormat("0.#").format(currentMovement.toDouble()) + "/" + getMaxMovement()).tr()
|
||||
|
||||
@Readonly @Suppress("purity") // should be autorecognized
|
||||
fun getTile(): Tile = currentTile
|
||||
|
||||
fun getClosestCity(): City? = civ.cities.minByOrNull {
|
||||
@ -284,6 +286,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
|
||||
fun getUniques(): Sequence<Unique> = tempUniquesMap.getAllUniques()
|
||||
|
||||
@Readonly
|
||||
fun getMatchingUniques(
|
||||
uniqueType: UniqueType,
|
||||
gameContext: GameContext = cache.state,
|
||||
@ -296,6 +299,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
yieldAll(civ.getMatchingUniques(uniqueType, gameContext))
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun hasUnique(
|
||||
uniqueType: UniqueType,
|
||||
gameContext: GameContext = cache.state,
|
||||
@ -405,12 +409,14 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
return getRange() * 2
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun isEmbarked(): Boolean {
|
||||
if (!baseUnit.isLandUnit) return false
|
||||
if (cache.canMoveOnWater) return false
|
||||
return currentTile.isWater
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun isInvisible(to: Civilization): Boolean {
|
||||
if (hasUnique(UniqueType.Invisible) && !to.isSpectator())
|
||||
return true
|
||||
|
@ -34,6 +34,7 @@ import com.unciv.utils.DebugUtils
|
||||
import com.unciv.utils.Log
|
||||
import com.unciv.utils.withItem
|
||||
import com.unciv.utils.withoutItem
|
||||
import yairm210.purity.annotations.LocalState
|
||||
import yairm210.purity.annotations.Readonly
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashSet
|
||||
@ -241,9 +242,10 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
|
||||
//region pure functions
|
||||
|
||||
fun isHill() = baseTerrain == Constants.hill || terrainFeatures.contains(Constants.hill)
|
||||
@Readonly fun isHill() = baseTerrain == Constants.hill || terrainFeatures.contains(Constants.hill)
|
||||
|
||||
/** Returns military, civilian and air units in tile */
|
||||
@Readonly
|
||||
fun getUnits() = sequence {
|
||||
if (militaryUnit != null) yield(militaryUnit!!)
|
||||
if (civilianUnit != null) yield(civilianUnit!!)
|
||||
@ -251,6 +253,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
}
|
||||
|
||||
/** This is for performance reasons of canPassThrough() - faster than getUnits().firstOrNull() */
|
||||
@Readonly
|
||||
fun getFirstUnit(): MapUnit? {
|
||||
if (militaryUnit != null) return militaryUnit!!
|
||||
if (civilianUnit != null) return civilianUnit!!
|
||||
@ -258,41 +261,39 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
return null
|
||||
}
|
||||
|
||||
@Readonly
|
||||
@Readonly @Suppress("purity") // should be autorecognized as readonly
|
||||
fun getCity(): City? = owningCity
|
||||
|
||||
internal fun getNaturalWonder(): Terrain =
|
||||
@Readonly internal fun getNaturalWonder(): Terrain =
|
||||
if (naturalWonder == null) throw Exception("No natural wonder exists for this tile!")
|
||||
else ruleset.terrains[naturalWonder!!]!!
|
||||
|
||||
@Readonly
|
||||
fun isVisible(player: Civilization): Boolean {
|
||||
if (DebugUtils.VISIBLE_MAP)
|
||||
return true
|
||||
return player.viewableTiles.contains(this)
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun isExplored(player: Civilization): Boolean {
|
||||
if (DebugUtils.VISIBLE_MAP || player.civName == Constants.spectator)
|
||||
return true
|
||||
return exploredBy.contains(player.civName)
|
||||
}
|
||||
|
||||
@Readonly @Suppress("purity") // should be autorecognized as readonly
|
||||
fun isCityCenter(): Boolean = isCityCenterInternal
|
||||
fun isNaturalWonder(): Boolean = naturalWonder != null
|
||||
fun isImpassible() = lastTerrain.impassable
|
||||
@Readonly fun isNaturalWonder(): Boolean = naturalWonder != null
|
||||
@Readonly fun isImpassible() = lastTerrain.impassable
|
||||
|
||||
fun hasImprovementInProgress() = improvementQueue.isNotEmpty()
|
||||
|
||||
@Readonly
|
||||
fun getTileImprovement(): TileImprovement? = if (improvement == null) null else ruleset.tileImprovements[improvement!!]
|
||||
@Readonly
|
||||
fun isPillaged(): Boolean = improvementIsPillaged || roadIsPillaged
|
||||
@Readonly
|
||||
fun getUnpillagedTileImprovement(): TileImprovement? = if (getUnpillagedImprovement() == null) null else ruleset.tileImprovements[improvement!!]
|
||||
@Readonly
|
||||
fun getTileImprovementInProgress(): TileImprovement? = improvementQueue.firstOrNull()?.let { ruleset.tileImprovements[it.improvement] }
|
||||
@Readonly
|
||||
fun containsGreatImprovement() = getTileImprovement()?.isGreatImprovement() == true
|
||||
@Readonly fun hasImprovementInProgress() = improvementQueue.isNotEmpty()
|
||||
|
||||
@Readonly fun getTileImprovement(): TileImprovement? = if (improvement == null) null else ruleset.tileImprovements[improvement!!]
|
||||
@Readonly fun isPillaged(): Boolean = improvementIsPillaged || roadIsPillaged
|
||||
@Readonly fun getUnpillagedTileImprovement(): TileImprovement? = if (getUnpillagedImprovement() == null) null else ruleset.tileImprovements[improvement!!]
|
||||
@Readonly fun getTileImprovementInProgress(): TileImprovement? = improvementQueue.firstOrNull()?.let { ruleset.tileImprovements[it.improvement] }
|
||||
@Readonly fun containsGreatImprovement() = getTileImprovement()?.isGreatImprovement() == true
|
||||
|
||||
@Readonly
|
||||
fun getImprovementToPillage(): TileImprovement? {
|
||||
@ -319,10 +320,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
return ruleset.tileImprovements[roadStatus.name]!!
|
||||
return null
|
||||
}
|
||||
@Readonly
|
||||
fun canPillageTile(): Boolean {
|
||||
return canPillageTileImprovement() || canPillageRoad()
|
||||
}
|
||||
@Readonly fun canPillageTile(): Boolean = canPillageTileImprovement() || canPillageRoad()
|
||||
@Readonly
|
||||
fun canPillageTileImprovement(): Boolean {
|
||||
return improvement != null && !improvementIsPillaged
|
||||
@ -335,12 +333,10 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
&& !ruleset.tileImprovements[roadStatus.name]!!.hasUnique(UniqueType.Unpillagable)
|
||||
&& !ruleset.tileImprovements[roadStatus.name]!!.hasUnique(UniqueType.Irremovable)
|
||||
}
|
||||
@Readonly
|
||||
fun getUnpillagedImprovement(): String? = if (improvementIsPillaged) null else improvement
|
||||
@Readonly fun getUnpillagedImprovement(): String? = if (improvementIsPillaged) null else improvement
|
||||
|
||||
/** @return [RoadStatus] on this [Tile], pillaged road counts as [RoadStatus.None] */
|
||||
@Readonly
|
||||
fun getUnpillagedRoad(): RoadStatus = if (roadIsPillaged) RoadStatus.None else roadStatus
|
||||
@Readonly fun getUnpillagedRoad(): RoadStatus = if (roadIsPillaged) RoadStatus.None else roadStatus
|
||||
|
||||
@Readonly
|
||||
fun getUnpillagedRoadImprovement(): TileImprovement? {
|
||||
@ -354,12 +350,13 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
* @param viewingCiv `null` means civ-agnostic and thus always showing the actual improvement
|
||||
* @return The improvement name, or `null` if no improvement should be shown
|
||||
*/
|
||||
@Readonly
|
||||
fun getShownImprovement(viewingCiv: Civilization?): String? =
|
||||
if (viewingCiv == null || viewingCiv.playerType == PlayerType.AI || viewingCiv.isSpectator()) improvement
|
||||
else viewingCiv.getLastSeenImprovement(position)
|
||||
|
||||
/** Returns true if this tile has fallout or an equivalent terrain feature */
|
||||
fun hasFalloutEquivalent(): Boolean = terrainFeatures.any { ruleset.terrains[it]!!.hasUnique(UniqueType.NullifyYields)}
|
||||
@Readonly fun hasFalloutEquivalent(): Boolean = terrainFeatures.any { ruleset.terrains[it]!!.hasUnique(UniqueType.NullifyYields)}
|
||||
|
||||
|
||||
fun getRow() = HexMath.getRow(position)
|
||||
@ -367,9 +364,9 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
|
||||
fun getBaseTerrain(): Terrain = baseTerrainObject
|
||||
|
||||
@Readonly
|
||||
fun getOwner(): Civilization? = getCity()?.civ
|
||||
@Readonly fun getOwner(): Civilization? = getCity()?.civ
|
||||
|
||||
@Readonly
|
||||
fun getRoadOwner(): Civilization? {
|
||||
return if (roadOwner != "")
|
||||
tileMap.gameInfo.getCivilization(roadOwner)
|
||||
@ -394,19 +391,22 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
return civInfo.isAtWarWith(tileOwner)
|
||||
}
|
||||
|
||||
fun isRoughTerrain() = allTerrains.any { it.isRough() }
|
||||
@Readonly fun isRoughTerrain() = allTerrains.any { it.isRough() }
|
||||
|
||||
@Transient
|
||||
internal var stateThisTile: GameContext = GameContext.EmptyState
|
||||
/** Checks whether any of the TERRAINS of this tile has a certain unique */
|
||||
@Readonly
|
||||
fun terrainHasUnique(uniqueType: UniqueType, state: GameContext = stateThisTile) =
|
||||
cachedTerrainData.uniques.hasMatchingUnique(uniqueType, state)
|
||||
/** Get all uniques of this type that any TERRAIN on this tile has */
|
||||
@Readonly
|
||||
fun getTerrainMatchingUniques(uniqueType: UniqueType, gameContext: GameContext = stateThisTile ): Sequence<Unique> {
|
||||
return cachedTerrainData.uniques.getMatchingUniques(uniqueType, gameContext)
|
||||
}
|
||||
|
||||
/** Get all uniques of this type that any part of this tile has: terrains, improvement, resource */
|
||||
@Readonly
|
||||
fun getMatchingUniques(uniqueType: UniqueType, gameContext: GameContext = stateThisTile): Sequence<Unique> {
|
||||
var uniques = getTerrainMatchingUniques(uniqueType, gameContext)
|
||||
if (getUnpillagedImprovement() != null) {
|
||||
@ -427,6 +427,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
return civInfo.cities.firstOrNull { it != owningCity && it.isWorked(this) }
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun isBlockaded(): Boolean {
|
||||
val owner = getOwner() ?: return false
|
||||
val unit = militaryUnit
|
||||
@ -463,11 +464,13 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
|| terrainHasUnique(UniqueType.TileProvidesYieldWithoutPopulation)
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun isLocked(): Boolean {
|
||||
val workingCity = getWorkingCity()
|
||||
return workingCity != null && workingCity.lockedTiles.contains(position)
|
||||
}
|
||||
|
||||
|
||||
@Readonly
|
||||
fun providesResources(civInfo: Civilization): Boolean {
|
||||
if (!hasViewableResource(civInfo)) return false
|
||||
if (isCityCenter()) {
|
||||
@ -520,6 +523,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
}
|
||||
|
||||
/** Implements [UniqueParameterType.TerrainFilter][com.unciv.models.ruleset.unique.UniqueParameterType.TerrainFilter] */
|
||||
@Readonly
|
||||
fun matchesTerrainFilter(filter: String, observingCiv: Civilization?, multiFilter: Boolean = true): Boolean {
|
||||
return if (multiFilter) MultiFilter.multiFilter(filter, { matchesSingleTerrainFilter(it, observingCiv) })
|
||||
else matchesSingleTerrainFilter(filter, observingCiv)
|
||||
@ -586,11 +590,13 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
fun hasViewableResource(civInfo: Civilization): Boolean =
|
||||
resource != null && civInfo.tech.isRevealed(tileResource)
|
||||
|
||||
fun getViewableTilesList(distance: Int): List<Tile> = tileMap.getViewableTiles(position, distance)
|
||||
fun getTilesInDistance(distance: Int): Sequence<Tile> = tileMap.getTilesInDistance(position, distance)
|
||||
fun getTilesInDistanceRange(range: IntRange): Sequence<Tile> = tileMap.getTilesInDistanceRange(position, range)
|
||||
fun getTilesAtDistance(distance: Int): Sequence<Tile> = tileMap.getTilesAtDistance(position, distance)
|
||||
|
||||
@Readonly fun getViewableTilesList(distance: Int): List<Tile> = tileMap.getViewableTiles(position, distance)
|
||||
@Readonly fun getTilesInDistance(distance: Int): Sequence<Tile> = tileMap.getTilesInDistance(position, distance)
|
||||
@Readonly fun getTilesInDistanceRange(range: IntRange): Sequence<Tile> = tileMap.getTilesInDistanceRange(position, range)
|
||||
@Readonly fun getTilesAtDistance(distance: Int): Sequence<Tile> = tileMap.getTilesAtDistance(position, distance)
|
||||
|
||||
@Readonly
|
||||
fun getDefensiveBonus(includeImprovementBonus: Boolean = true, unit: MapUnit? = null): Float {
|
||||
var bonus = baseTerrainObject.defenceBonus
|
||||
if (terrainFeatureObjects.isNotEmpty()) {
|
||||
@ -612,6 +618,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
* @param otherTile Destination tile
|
||||
* @return Shortest distance from this [Tile] to [otherTile] in count of tiles including impassable tiles but not including origin tile
|
||||
*/
|
||||
@Readonly
|
||||
fun aerialDistanceTo(otherTile: Tile): Int {
|
||||
val xDelta = position.x - otherTile.position.x
|
||||
val yDelta = position.y - otherTile.position.y
|
||||
@ -628,6 +635,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
return min(distance, wrappedDistance).toInt()
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun canBeSettled(): Boolean {
|
||||
val modConstants = tileMap.gameInfo.ruleset.modOptions.constants
|
||||
return when {
|
||||
@ -641,6 +649,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
}
|
||||
|
||||
/** The two tiles have a river between them */
|
||||
@Readonly
|
||||
fun isConnectedByRiver(otherTile: Tile): Boolean {
|
||||
if (otherTile == this) throw Exception("Should not be called to compare to self!")
|
||||
|
||||
@ -672,6 +681,7 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
* @returns whether units of [civInfo] can pass through this tile, considering only civ-wide filters.
|
||||
* Use [UnitMovement.canPassThrough] to check whether a specific unit can pass through a tile.
|
||||
*/
|
||||
@Readonly
|
||||
fun canCivPassThrough(civInfo: Civilization): Boolean {
|
||||
val tileOwner = getOwner()
|
||||
// comparing the CivInfo objects is cheaper than comparing strings
|
||||
@ -680,7 +690,8 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
&& !getCity()!!.hasJustBeenConquered) return false
|
||||
return civInfo.diplomacyFunctions.canPassThroughTiles(tileOwner)
|
||||
}
|
||||
|
||||
|
||||
@Readonly
|
||||
fun hasEnemyInvisibleUnit(viewingCiv: Civilization): Boolean {
|
||||
val unitsInTile = getUnits()
|
||||
return when {
|
||||
@ -691,28 +702,33 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun hasConnection(civInfo: Civilization) =
|
||||
getUnpillagedRoad() != RoadStatus.None || forestOrJungleAreRoads(civInfo)
|
||||
|
||||
@Readonly
|
||||
fun hasRoadConnection(civInfo: Civilization, mustBeUnpillaged: Boolean) =
|
||||
if (mustBeUnpillaged)
|
||||
(getUnpillagedRoad() == RoadStatus.Road) || forestOrJungleAreRoads(civInfo)
|
||||
else
|
||||
roadStatus == RoadStatus.Road || forestOrJungleAreRoads(civInfo)
|
||||
|
||||
@Readonly
|
||||
fun hasRailroadConnection(mustBeUnpillaged: Boolean) =
|
||||
if (mustBeUnpillaged)
|
||||
getUnpillagedRoad() == RoadStatus.Railroad
|
||||
else
|
||||
roadStatus == RoadStatus.Railroad
|
||||
|
||||
|
||||
@Readonly
|
||||
private fun forestOrJungleAreRoads(civInfo: Civilization) =
|
||||
civInfo.nation.forestsAndJunglesAreRoads
|
||||
&& (terrainFeatures.contains(Constants.jungle) || terrainFeatures.contains(Constants.forest))
|
||||
&& isFriendlyTerritory(civInfo)
|
||||
|
||||
|
||||
@Readonly
|
||||
fun getRulesetIncompatibility(ruleset: Ruleset): HashSet<String> {
|
||||
@LocalState
|
||||
val out = HashSet<String>()
|
||||
if (!ruleset.terrains.containsKey(baseTerrain))
|
||||
out.add("Base terrain [$baseTerrain] does not exist in ruleset!")
|
||||
@ -727,15 +743,17 @@ class Tile : IsPartOfGameInfoSerialization, Json.Serializable {
|
||||
return out
|
||||
}
|
||||
|
||||
@Readonly @Suppress("purity") // should be auto-recognized as readonly
|
||||
fun getContinent() = continent
|
||||
|
||||
/** Checks if this tile is marked as target tile for a building with a [UniqueType.CreatesOneImprovement] unique */
|
||||
fun isMarkedForCreatesOneImprovement() =
|
||||
@Readonly fun isMarkedForCreatesOneImprovement() =
|
||||
turnsToImprovement < 0 && improvementInProgress != null
|
||||
/** Checks if this tile is marked as target tile for a building with a [UniqueType.CreatesOneImprovement] unique creating a specific [improvement] */
|
||||
fun isMarkedForCreatesOneImprovement(improvement: String) =
|
||||
@Readonly fun isMarkedForCreatesOneImprovement(improvement: String) =
|
||||
turnsToImprovement < 0 && improvementInProgress == improvement
|
||||
|
||||
@Readonly
|
||||
private fun approximateMajorDepositDistribution(): Double {
|
||||
// We can't replicate the MapRegions resource distributor, so let's try to get
|
||||
// a close probability of major deposits per tile
|
||||
|
@ -13,6 +13,7 @@ import com.unciv.models.stats.GameResource
|
||||
import com.unciv.models.stats.Stats
|
||||
import com.unciv.ui.objectdescriptions.uniquesToCivilopediaTextLines
|
||||
import com.unciv.ui.screens.civilopediascreen.FormattedLine
|
||||
import yairm210.purity.annotations.Readonly
|
||||
|
||||
class TileResource : RulesetStatsObject(), GameResource {
|
||||
|
||||
@ -52,6 +53,7 @@ class TileResource : RulesetStatsObject(), GameResource {
|
||||
* @see improvedBy
|
||||
* @see UniqueType.ImprovesResources
|
||||
*/
|
||||
@Readonly @Suppress("purity") // requires some plumbing
|
||||
fun getImprovements(): Set<String> {
|
||||
if (improvementsInitialized) return allImprovements
|
||||
val ruleset = this.ruleset
|
||||
|
Loading…
x
Reference in New Issue
Block a user