mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-24 03:53:12 -04:00
Linting and re-sort Tile class so the regions are no longer lying (#11649)
* Rename TileInfoImprovementFunctions * Linting and re-sort Tile class so the regions are no longer lying
This commit is contained in:
parent
9757cae098
commit
c6e3ff5d1b
@ -11,7 +11,6 @@ import com.unciv.logic.civilization.NotificationCategory
|
|||||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||||
import com.unciv.logic.map.mapunit.MapUnit
|
import com.unciv.logic.map.mapunit.MapUnit
|
||||||
import com.unciv.logic.map.tile.Tile
|
import com.unciv.logic.map.tile.Tile
|
||||||
import com.unciv.logic.map.tile.TileStatFunctions
|
|
||||||
import com.unciv.logic.map.tile.toStats
|
import com.unciv.logic.map.tile.toStats
|
||||||
import com.unciv.models.UnitActionType
|
import com.unciv.models.UnitActionType
|
||||||
import com.unciv.models.ruleset.tile.ResourceType
|
import com.unciv.models.ruleset.tile.ResourceType
|
||||||
@ -278,7 +277,7 @@ class WorkerAutomation(
|
|||||||
var repairBonusPriority = tile.getImprovementToRepair()!!.getTurnsToBuild(unit.civ,unit) - UnitActionsFromUniques.getRepairTurns(unit)
|
var repairBonusPriority = tile.getImprovementToRepair()!!.getTurnsToBuild(unit.civ,unit) - UnitActionsFromUniques.getRepairTurns(unit)
|
||||||
if (tile.improvementInProgress == Constants.repair) repairBonusPriority += UnitActionsFromUniques.getRepairTurns(unit) - tile.turnsToImprovement
|
if (tile.improvementInProgress == Constants.repair) repairBonusPriority += UnitActionsFromUniques.getRepairTurns(unit) - tile.turnsToImprovement
|
||||||
|
|
||||||
val repairPriority = repairBonusPriority + Automation.rankStatsValue(TileStatFunctions(tile).getStatDiffForImprovement(tile.getTileImprovement()!!, unit.civ, tile.owningCity), unit.civ)
|
val repairPriority = repairBonusPriority + Automation.rankStatsValue(tile.stats.getStatDiffForImprovement(tile.getTileImprovement()!!, unit.civ, tile.owningCity), unit.civ)
|
||||||
if (repairPriority > rank.improvementPriority!!) {
|
if (repairPriority > rank.improvementPriority!!) {
|
||||||
rank.improvementPriority = repairPriority
|
rank.improvementPriority = repairPriority
|
||||||
rank.bestImprovement = null
|
rank.bestImprovement = null
|
||||||
|
@ -56,7 +56,7 @@ class CityFounder {
|
|||||||
|
|
||||||
if (civInfo.gameInfo.ruleset.tileImprovements.containsKey(Constants.cityCenter))
|
if (civInfo.gameInfo.ruleset.tileImprovements.containsKey(Constants.cityCenter))
|
||||||
tile.changeImprovement(Constants.cityCenter, civInfo)
|
tile.changeImprovement(Constants.cityCenter, civInfo)
|
||||||
tile.improvementInProgress = null
|
tile.stopWorkingOnImprovement()
|
||||||
|
|
||||||
val ruleset = civInfo.gameInfo.ruleset
|
val ruleset = civInfo.gameInfo.ruleset
|
||||||
city.workedTiles = hashSetOf() //reassign 1st working tile
|
city.workedTiles = hashSetOf() //reassign 1st working tile
|
||||||
@ -111,8 +111,8 @@ class CityFounder {
|
|||||||
* This method attempts to return the first unused city name of the [foundingCiv], taking used
|
* This method attempts to return the first unused city name of the [foundingCiv], taking used
|
||||||
* city names into consideration (including foreign cities). If that fails, it then checks
|
* city names into consideration (including foreign cities). If that fails, it then checks
|
||||||
* whether the civilization has [UniqueType.BorrowsCityNames] and, if true, returns a borrowed
|
* whether the civilization has [UniqueType.BorrowsCityNames] and, if true, returns a borrowed
|
||||||
* name. Else, it repeatedly attaches one of the given [prefixes] to the list of names up to ten
|
* name. Else, it repeatedly attaches one of the given [prefixes][NamingConstants.prefixes] to the list of names
|
||||||
* times until an unused name is successfully generated. If all else fails, null is returned.
|
* up to ten times until an unused name is successfully generated. If all else fails, null is returned.
|
||||||
*
|
*
|
||||||
* @param foundingCiv The civilization that founded this city.
|
* @param foundingCiv The civilization that founded this city.
|
||||||
* @param aliveCivs Every civilization currently alive.
|
* @param aliveCivs Every civilization currently alive.
|
||||||
|
@ -46,7 +46,7 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
private set
|
private set
|
||||||
|
|
||||||
/** Should be immutable - never be altered in-place, instead replaced */
|
/** Should be immutable - never be altered in-place, instead replaced */
|
||||||
var exploredBy = HashSet<String>(0)
|
private var exploredBy = HashSet<String>(0)
|
||||||
|
|
||||||
var naturalWonder: String? = null
|
var naturalWonder: String? = null
|
||||||
var resource: String? = null
|
var resource: String? = null
|
||||||
@ -55,13 +55,14 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
field = value
|
field = value
|
||||||
}
|
}
|
||||||
var resourceAmount: Int = 0
|
var resourceAmount: Int = 0
|
||||||
|
|
||||||
var improvement: String? = null
|
var improvement: String? = null
|
||||||
var improvementInProgress: String? = null
|
var improvementInProgress: String? = null
|
||||||
var improvementIsPillaged = false
|
var improvementIsPillaged = false
|
||||||
|
|
||||||
var roadStatus = RoadStatus.None
|
var roadStatus = RoadStatus.None
|
||||||
var roadIsPillaged = false
|
var roadIsPillaged = false
|
||||||
var roadOwner: String = "" // either who last built the road or last owner of tile
|
private var roadOwner: String = "" // either who last built the road or last owner of tile
|
||||||
var turnsToImprovement: Int = 0
|
var turnsToImprovement: Int = 0
|
||||||
|
|
||||||
var hasBottomRightRiver = false
|
var hasBottomRightRiver = false
|
||||||
@ -81,11 +82,18 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
lateinit var ruleset: Ruleset // a tile can be a tile with a ruleset, even without a map.
|
lateinit var ruleset: Ruleset // a tile can be a tile with a ruleset, even without a map.
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
val improvementFunctions = TileInfoImprovementFunctions(this)
|
val improvementFunctions = TileImprovementFunctions(this)
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
val stats = TileStatFunctions(this)
|
val stats = TileStatFunctions(this)
|
||||||
|
|
||||||
|
// This is for performance - since we access the neighbors of a tile ALL THE TIME,
|
||||||
|
// and the neighbors of a tile never change, it's much more efficient to save the list once and for all!
|
||||||
|
@delegate:Transient
|
||||||
|
val neighbors: Sequence<Tile> by lazy { getTilesAtDistance(1).toList().asSequence() }
|
||||||
|
// We have to .toList() so that the values are stored together once for caching,
|
||||||
|
// and the toSequence so that aggregations (like neighbors.flatMap{it.units} don't take up their own space
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private var isCityCenterInternal = false
|
private var isCityCenterInternal = false
|
||||||
|
|
||||||
@ -106,6 +114,9 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
@Transient
|
@Transient
|
||||||
var isOcean = false
|
var isOcean = false
|
||||||
|
|
||||||
|
@delegate:Transient
|
||||||
|
private val _isCoastalTile: Boolean by lazy { neighbors.any { it.baseTerrain == Constants.coast } }
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
var unitHeight = 0
|
var unitHeight = 0
|
||||||
|
|
||||||
@ -153,6 +164,11 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
}
|
}
|
||||||
return tileResourceCache!!
|
return tileResourceCache!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private var isAdjacentToRiver = false
|
||||||
|
@Transient
|
||||||
|
private var isAdjacentToRiverKnown = false
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
fun clone(): Tile {
|
fun clone(): Tile {
|
||||||
@ -197,10 +213,6 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
|
|
||||||
fun isHill() = baseTerrain == Constants.hill || terrainFeatures.contains(Constants.hill)
|
fun isHill() = baseTerrain == Constants.hill || terrainFeatures.contains(Constants.hill)
|
||||||
|
|
||||||
fun containsGreatImprovement(): Boolean {
|
|
||||||
return getTileImprovement()?.isGreatImprovement() == true
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns military, civilian and air units in tile */
|
/** Returns military, civilian and air units in tile */
|
||||||
fun getUnits() = sequence {
|
fun getUnits() = sequence {
|
||||||
if (militaryUnit != null) yield(militaryUnit!!)
|
if (militaryUnit != null) yield(militaryUnit!!)
|
||||||
@ -234,28 +246,16 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
return exploredBy.contains(player.civName)
|
return exploredBy.contains(player.civName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setExplored(player: Civilization, isExplored: Boolean, explorerPosition: Vector2? = null) {
|
|
||||||
if (isExplored) {
|
|
||||||
// Disable the undo button if a new tile has been explored
|
|
||||||
if (!exploredBy.contains(player.civName)) {
|
|
||||||
GUI.clearUndoCheckpoints()
|
|
||||||
exploredBy = exploredBy.withItem(player.civName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player.playerType == PlayerType.Human)
|
|
||||||
player.exploredRegion.checkTilePosition(position, explorerPosition)
|
|
||||||
} else {
|
|
||||||
exploredBy = exploredBy.withoutItem(player.civName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isCityCenter(): Boolean = isCityCenterInternal
|
fun isCityCenter(): Boolean = isCityCenterInternal
|
||||||
fun isNaturalWonder(): Boolean = naturalWonder != null
|
fun isNaturalWonder(): Boolean = naturalWonder != null
|
||||||
fun isImpassible() = lastTerrain.impassable
|
fun isImpassible() = lastTerrain.impassable
|
||||||
|
|
||||||
|
|
||||||
fun getTileImprovement(): TileImprovement? = if (improvement == null) null else ruleset.tileImprovements[improvement!!]
|
fun getTileImprovement(): TileImprovement? = if (improvement == null) null else ruleset.tileImprovements[improvement!!]
|
||||||
|
fun isPillaged(): Boolean = improvementIsPillaged || roadIsPillaged
|
||||||
fun getUnpillagedTileImprovement(): TileImprovement? = if (getUnpillagedImprovement() == null) null else ruleset.tileImprovements[improvement!!]
|
fun getUnpillagedTileImprovement(): TileImprovement? = if (getUnpillagedImprovement() == null) null else ruleset.tileImprovements[improvement!!]
|
||||||
fun getTileImprovementInProgress(): TileImprovement? = if (improvementInProgress == null) null else ruleset.tileImprovements[improvementInProgress!!]
|
fun getTileImprovementInProgress(): TileImprovement? = if (improvementInProgress == null) null else ruleset.tileImprovements[improvementInProgress!!]
|
||||||
|
fun containsGreatImprovement() = getTileImprovement()?.isGreatImprovement() == true
|
||||||
|
|
||||||
fun getImprovementToPillage(): TileImprovement? {
|
fun getImprovementToPillage(): TileImprovement? {
|
||||||
if (canPillageTileImprovement())
|
if (canPillageTileImprovement())
|
||||||
@ -299,34 +299,6 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
else ruleset.tileImprovements[getUnpillagedRoad().name]
|
else ruleset.tileImprovements[getUnpillagedRoad().name]
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Does not remove roads */
|
|
||||||
fun removeImprovement() =
|
|
||||||
improvementFunctions.changeImprovement(null)
|
|
||||||
|
|
||||||
fun changeImprovement(improvementStr: String, civToHandleCompletion: Civilization? = null, unit: MapUnit? = null) =
|
|
||||||
improvementFunctions.changeImprovement(improvementStr, civToHandleCompletion, unit)
|
|
||||||
|
|
||||||
// function handling when adding a road to the tile
|
|
||||||
fun addRoad(roadType: RoadStatus, creatingCivInfo: Civilization?) {
|
|
||||||
roadStatus = roadType
|
|
||||||
roadIsPillaged = false
|
|
||||||
if (getOwner() != null) {
|
|
||||||
roadOwner = getOwner()!!.civName
|
|
||||||
} else if (creatingCivInfo != null) {
|
|
||||||
roadOwner = creatingCivInfo.civName // neutral tile, use building unit
|
|
||||||
creatingCivInfo.neutralRoads.add(this.position)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// function handling when removing a road from the tile
|
|
||||||
fun removeRoad() {
|
|
||||||
roadIsPillaged = false
|
|
||||||
if (roadStatus == RoadStatus.None) return
|
|
||||||
roadStatus = RoadStatus.None
|
|
||||||
if (owningCity == null)
|
|
||||||
getRoadOwner()?.neutralRoads?.remove(this.position)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getShownImprovement(viewingCiv: Civilization?): String? {
|
fun getShownImprovement(viewingCiv: Civilization?): String? {
|
||||||
return if (viewingCiv == null || viewingCiv.playerType == PlayerType.AI || viewingCiv.isSpectator())
|
return if (viewingCiv == null || viewingCiv.playerType == PlayerType.AI || viewingCiv.isSpectator())
|
||||||
improvement
|
improvement
|
||||||
@ -338,13 +310,6 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
fun hasFalloutEquivalent(): Boolean = terrainFeatures.any { ruleset.terrains[it]!!.hasUnique(UniqueType.NullifyYields)}
|
fun hasFalloutEquivalent(): Boolean = terrainFeatures.any { ruleset.terrains[it]!!.hasUnique(UniqueType.NullifyYields)}
|
||||||
|
|
||||||
|
|
||||||
// This is for performance - since we access the neighbors of a tile ALL THE TIME,
|
|
||||||
// and the neighbors of a tile never change, it's much more efficient to save the list once and for all!
|
|
||||||
@delegate:Transient
|
|
||||||
val neighbors: Sequence<Tile> by lazy { getTilesAtDistance(1).toList().asSequence() }
|
|
||||||
// We have to .toList() so that the values are stored together once for caching,
|
|
||||||
// and the toSequence so that aggregations (like neighbors.flatMap{it.units} don't take up their own space
|
|
||||||
|
|
||||||
fun getRow() = HexMath.getRow(position)
|
fun getRow() = HexMath.getRow(position)
|
||||||
fun getColumn() = HexMath.getColumn(position)
|
fun getColumn() = HexMath.getColumn(position)
|
||||||
|
|
||||||
@ -537,8 +502,6 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
|
|
||||||
fun hasImprovementInProgress() = improvementInProgress != null && turnsToImprovement > 0
|
fun hasImprovementInProgress() = improvementInProgress != null && turnsToImprovement > 0
|
||||||
|
|
||||||
@delegate:Transient
|
|
||||||
private val _isCoastalTile: Boolean by lazy { neighbors.any { it.baseTerrain == Constants.coast } }
|
|
||||||
fun isCoastalTile() = _isCoastalTile
|
fun isCoastalTile() = _isCoastalTile
|
||||||
|
|
||||||
fun hasViewableResource(civInfo: Civilization): Boolean =
|
fun hasViewableResource(civInfo: Civilization): Boolean =
|
||||||
@ -593,28 +556,6 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Shows important properties of this tile for debugging _only_, it helps to see what you're doing */
|
|
||||||
override fun toString(): String {
|
|
||||||
val lineList = arrayListOf("Tile @$position")
|
|
||||||
if (!this::baseTerrain.isInitialized) return lineList[0] + ", uninitialized"
|
|
||||||
if (isCityCenter()) lineList += getCity()!!.name
|
|
||||||
lineList += baseTerrain
|
|
||||||
for (terrainFeature in terrainFeatures) lineList += terrainFeature
|
|
||||||
if (resource != null) {
|
|
||||||
lineList += if (tileResource.resourceType == ResourceType.Strategic)
|
|
||||||
"{$resourceAmount} {$resource}"
|
|
||||||
else
|
|
||||||
resource!!
|
|
||||||
}
|
|
||||||
if (naturalWonder != null) lineList += naturalWonder!!
|
|
||||||
if (roadStatus !== RoadStatus.None && !isCityCenter()) lineList += roadStatus.name
|
|
||||||
if (improvement != null) lineList += improvement!!
|
|
||||||
if (civilianUnit != null) lineList += civilianUnit!!.name + " - " + civilianUnit!!.civ.civName
|
|
||||||
if (militaryUnit != null) lineList += militaryUnit!!.name + " - " + militaryUnit!!.civ.civName
|
|
||||||
if (this::baseTerrainObject.isInitialized && isImpassible()) lineList += Constants.impassable
|
|
||||||
return lineList.joinToString()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The two tiles have a river between them */
|
/** The two tiles have a river between them */
|
||||||
fun isConnectedByRiver(otherTile: Tile): Boolean {
|
fun isConnectedByRiver(otherTile: Tile): Boolean {
|
||||||
if (otherTile == this) throw Exception("Should not be called to compare to self!")
|
if (otherTile == this) throw Exception("Should not be called to compare to self!")
|
||||||
@ -630,10 +571,6 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient
|
|
||||||
private var isAdjacentToRiver = false
|
|
||||||
@Transient
|
|
||||||
private var isAdjacentToRiverKnown = false
|
|
||||||
fun isAdjacentToRiver(): Boolean {
|
fun isAdjacentToRiver(): Boolean {
|
||||||
if (!isAdjacentToRiverKnown) {
|
if (!isAdjacentToRiverKnown) {
|
||||||
isAdjacentToRiver =
|
isAdjacentToRiver =
|
||||||
@ -646,43 +583,6 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
return isAdjacentToRiver
|
return isAdjacentToRiver
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allows resetting the cached value [isAdjacentToRiver] will return
|
|
||||||
* @param isKnownTrue Set this to indicate you need to update the cache due to **adding** a river edge
|
|
||||||
* (removing would need to look at other edges, and that is what isAdjacentToRiver will do)
|
|
||||||
*/
|
|
||||||
private fun resetAdjacentToRiverTransient(isKnownTrue: Boolean = false) {
|
|
||||||
isAdjacentToRiver = isKnownTrue
|
|
||||||
isAdjacentToRiverKnown = isKnownTrue
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the "has river" state of one edge of this Tile. Works for all six directions.
|
|
||||||
* @param otherTile The neighbor tile in the direction the river we wish to change is (If it's not a neighbor, this does nothing).
|
|
||||||
* @param newValue The new river edge state: `true` to create a river, `false` to remove one.
|
|
||||||
* @param convertTerrains If true, calls MapGenerator's convertTerrains to apply UniqueType.ChangesTerrain effects.
|
|
||||||
* @return The state did change (`false`: the edge already had the `newValue`)
|
|
||||||
*/
|
|
||||||
fun setConnectedByRiver(otherTile: Tile, newValue: Boolean, convertTerrains: Boolean = false): Boolean {
|
|
||||||
//todo synergy potential with [MapEditorEditRiversTab]?
|
|
||||||
val field = when (tileMap.getNeighborTileClockPosition(this, otherTile)) {
|
|
||||||
2 -> otherTile::hasBottomLeftRiver // we're to the bottom-left of it
|
|
||||||
4 -> ::hasBottomRightRiver // we're to the top-left of it
|
|
||||||
6 -> ::hasBottomRiver // we're directly above it
|
|
||||||
8 -> ::hasBottomLeftRiver // we're to the top-right of it
|
|
||||||
10 -> otherTile::hasBottomRightRiver // we're to the bottom-right of it
|
|
||||||
12 -> otherTile::hasBottomRiver // we're directly below it
|
|
||||||
else -> return false
|
|
||||||
}
|
|
||||||
if (field.get() == newValue) return false
|
|
||||||
field.set(newValue)
|
|
||||||
val affectedTiles = listOf(this, otherTile)
|
|
||||||
for (tile in affectedTiles)
|
|
||||||
tile.resetAdjacentToRiverTransient(newValue)
|
|
||||||
if (convertTerrains)
|
|
||||||
MapGenerator.Helpers.convertTerrains(ruleset, affectedTiles)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns whether units of [civInfo] can pass through this tile, considering only civ-wide filters.
|
* @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.
|
* Use [UnitMovement.canPassThrough] to check whether a specific unit can pass through a tile.
|
||||||
@ -751,6 +651,20 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
fun isMarkedForCreatesOneImprovement(improvement: String) =
|
fun isMarkedForCreatesOneImprovement(improvement: String) =
|
||||||
turnsToImprovement < 0 && improvementInProgress == improvement
|
turnsToImprovement < 0 && improvementInProgress == improvement
|
||||||
|
|
||||||
|
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
|
||||||
|
var probability = 0.0
|
||||||
|
for (unique in allTerrains.flatMap { it.getMatchingUniques(UniqueType.MajorStrategicFrequency) }) {
|
||||||
|
val frequency = unique.params[0].toIntOrNull() ?: continue
|
||||||
|
if (frequency <= 0) continue
|
||||||
|
// The unique param is literally "every N tiles", so to get a probability p=1/f
|
||||||
|
probability += 1.0 / frequency
|
||||||
|
}
|
||||||
|
return if (probability == 0.0) 0.04 // This is the default of 1 per 25 tiles
|
||||||
|
else probability
|
||||||
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
//region state-changing functions
|
//region state-changing functions
|
||||||
|
|
||||||
@ -839,20 +753,6 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
var probability = 0.0
|
|
||||||
for (unique in allTerrains.flatMap { it.getMatchingUniques(UniqueType.MajorStrategicFrequency) }) {
|
|
||||||
val frequency = unique.params[0].toIntOrNull() ?: continue
|
|
||||||
if (frequency <= 0) continue
|
|
||||||
// The unique param is literally "every N tiles", so to get a probability p=1/f
|
|
||||||
probability += 1.0 / frequency
|
|
||||||
}
|
|
||||||
return if (probability == 0.0) 0.04 // This is the default of 1 per 25 tiles
|
|
||||||
else probability
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setTerrainFeatures(terrainFeatureList: List<String>) {
|
fun setTerrainFeatures(terrainFeatureList: List<String>) {
|
||||||
terrainFeatures = terrainFeatureList
|
terrainFeatures = terrainFeatureList
|
||||||
terrainFeatureObjects = terrainFeatureList.mapNotNull { ruleset.terrains[it] }
|
terrainFeatureObjects = terrainFeatureList.mapNotNull { ruleset.terrains[it] }
|
||||||
@ -928,6 +828,35 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Does not remove roads */
|
||||||
|
fun removeImprovement() =
|
||||||
|
improvementFunctions.changeImprovement(null)
|
||||||
|
|
||||||
|
fun changeImprovement(improvementStr: String, civToHandleCompletion: Civilization? = null, unit: MapUnit? = null) =
|
||||||
|
improvementFunctions.changeImprovement(improvementStr, civToHandleCompletion, unit)
|
||||||
|
|
||||||
|
// function handling when adding a road to the tile
|
||||||
|
fun addRoad(roadType: RoadStatus, creatingCivInfo: Civilization?) {
|
||||||
|
roadStatus = roadType
|
||||||
|
roadIsPillaged = false
|
||||||
|
if (getOwner() != null) {
|
||||||
|
roadOwner = getOwner()!!.civName
|
||||||
|
} else if (creatingCivInfo != null) {
|
||||||
|
roadOwner = creatingCivInfo.civName // neutral tile, use building unit
|
||||||
|
creatingCivInfo.neutralRoads.add(this.position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function handling when removing a road from the tile
|
||||||
|
fun removeRoad() {
|
||||||
|
roadIsPillaged = false
|
||||||
|
if (roadStatus == RoadStatus.None) return
|
||||||
|
roadStatus = RoadStatus.None
|
||||||
|
if (owningCity == null)
|
||||||
|
getRoadOwner()?.neutralRoads?.remove(this.position)
|
||||||
|
}
|
||||||
|
|
||||||
fun startWorkingOnImprovement(improvement: TileImprovement, civInfo: Civilization, unit: MapUnit) {
|
fun startWorkingOnImprovement(improvement: TileImprovement, civInfo: Civilization, unit: MapUnit) {
|
||||||
improvementInProgress = improvement.name
|
improvementInProgress = improvement.name
|
||||||
turnsToImprovement = if (civInfo.gameInfo.gameParameters.godMode) 1
|
turnsToImprovement = if (civInfo.gameInfo.gameParameters.godMode) 1
|
||||||
@ -978,18 +907,6 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
owningCity!!.civ.cache.updateCivResources()
|
owningCity!!.civ.cache.updateCivResources()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearAllPathfindingCaches() {
|
|
||||||
val units = tileMap.gameInfo.civilizations.asSequence()
|
|
||||||
.filter { it.isAlive() }
|
|
||||||
.flatMap { it.units.getCivUnits() }
|
|
||||||
Log.debug("%s: road pillaged, clearing cache for %d units", this, { units.count() })
|
|
||||||
for (otherUnit in units) {
|
|
||||||
otherUnit.movement.clearPathfindingCache()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isPillaged(): Boolean = improvementIsPillaged || roadIsPillaged
|
|
||||||
|
|
||||||
fun setRepaired() {
|
fun setRepaired() {
|
||||||
improvementInProgress = null
|
improvementInProgress = null
|
||||||
turnsToImprovement = 0
|
turnsToImprovement = 0
|
||||||
@ -1002,6 +919,31 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun clearAllPathfindingCaches() {
|
||||||
|
val units = tileMap.gameInfo.civilizations.asSequence()
|
||||||
|
.filter { it.isAlive() }
|
||||||
|
.flatMap { it.units.getCivUnits() }
|
||||||
|
Log.debug("%s: road pillaged, clearing cache for %d units", this, { units.count() })
|
||||||
|
for (otherUnit in units) {
|
||||||
|
otherUnit.movement.clearPathfindingCache()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setExplored(player: Civilization, isExplored: Boolean, explorerPosition: Vector2? = null) {
|
||||||
|
if (isExplored) {
|
||||||
|
// Disable the undo button if a new tile has been explored
|
||||||
|
if (!exploredBy.contains(player.civName)) {
|
||||||
|
GUI.clearUndoCheckpoints()
|
||||||
|
exploredBy = exploredBy.withItem(player.civName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.playerType == PlayerType.Human)
|
||||||
|
player.exploredRegion.checkTilePosition(position, explorerPosition)
|
||||||
|
} else {
|
||||||
|
exploredBy = exploredBy.withoutItem(player.civName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign a continent ID to this tile.
|
* Assign a continent ID to this tile.
|
||||||
*
|
*
|
||||||
@ -1018,5 +960,67 @@ class Tile : IsPartOfGameInfoSerialization {
|
|||||||
/** Clear continent ID, for map editor */
|
/** Clear continent ID, for map editor */
|
||||||
fun clearContinent() { continent = -1 }
|
fun clearContinent() { continent = -1 }
|
||||||
|
|
||||||
|
/** Allows resetting the cached value [isAdjacentToRiver] will return
|
||||||
|
* @param isKnownTrue Set this to indicate you need to update the cache due to **adding** a river edge
|
||||||
|
* (removing would need to look at other edges, and that is what isAdjacentToRiver will do)
|
||||||
|
*/
|
||||||
|
private fun resetAdjacentToRiverTransient(isKnownTrue: Boolean = false) {
|
||||||
|
isAdjacentToRiver = isKnownTrue
|
||||||
|
isAdjacentToRiverKnown = isKnownTrue
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "has river" state of one edge of this Tile. Works for all six directions.
|
||||||
|
* @param otherTile The neighbor tile in the direction the river we wish to change is (If it's not a neighbor, this does nothing).
|
||||||
|
* @param newValue The new river edge state: `true` to create a river, `false` to remove one.
|
||||||
|
* @param convertTerrains If true, calls MapGenerator's convertTerrains to apply UniqueType.ChangesTerrain effects.
|
||||||
|
* @return The state did change (`false`: the edge already had the `newValue`)
|
||||||
|
*/
|
||||||
|
fun setConnectedByRiver(otherTile: Tile, newValue: Boolean, convertTerrains: Boolean = false): Boolean {
|
||||||
|
//todo synergy potential with [MapEditorEditRiversTab]?
|
||||||
|
val field = when (tileMap.getNeighborTileClockPosition(this, otherTile)) {
|
||||||
|
2 -> otherTile::hasBottomLeftRiver // we're to the bottom-left of it
|
||||||
|
4 -> ::hasBottomRightRiver // we're to the top-left of it
|
||||||
|
6 -> ::hasBottomRiver // we're directly above it
|
||||||
|
8 -> ::hasBottomLeftRiver // we're to the top-right of it
|
||||||
|
10 -> otherTile::hasBottomRightRiver // we're to the bottom-right of it
|
||||||
|
12 -> otherTile::hasBottomRiver // we're directly below it
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
if (field.get() == newValue) return false
|
||||||
|
field.set(newValue)
|
||||||
|
val affectedTiles = listOf(this, otherTile)
|
||||||
|
for (tile in affectedTiles)
|
||||||
|
tile.resetAdjacentToRiverTransient(newValue)
|
||||||
|
if (convertTerrains)
|
||||||
|
MapGenerator.Helpers.convertTerrains(ruleset, affectedTiles)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
//region Overrides
|
||||||
|
|
||||||
|
/** Shows important properties of this tile for debugging _only_, it helps to see what you're doing */
|
||||||
|
override fun toString(): String {
|
||||||
|
val lineList = arrayListOf("Tile @$position")
|
||||||
|
if (!this::baseTerrain.isInitialized) return lineList[0] + ", uninitialized"
|
||||||
|
if (isCityCenter()) lineList += getCity()!!.name
|
||||||
|
lineList += baseTerrain
|
||||||
|
for (terrainFeature in terrainFeatures) lineList += terrainFeature
|
||||||
|
if (resource != null) {
|
||||||
|
lineList += if (tileResource.resourceType == ResourceType.Strategic)
|
||||||
|
"{$resourceAmount} {$resource}"
|
||||||
|
else
|
||||||
|
resource!!
|
||||||
|
}
|
||||||
|
if (naturalWonder != null) lineList += naturalWonder!!
|
||||||
|
if (roadStatus !== RoadStatus.None && !isCityCenter()) lineList += roadStatus.name
|
||||||
|
if (improvement != null) lineList += improvement!!
|
||||||
|
if (civilianUnit != null) lineList += civilianUnit!!.name + " - " + civilianUnit!!.civ.civName
|
||||||
|
if (militaryUnit != null) lineList += militaryUnit!!.name + " - " + militaryUnit!!.civ.civName
|
||||||
|
if (this::baseTerrainObject.isInitialized && isImpassible()) lineList += Constants.impassable
|
||||||
|
return lineList.joinToString()
|
||||||
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ enum class ImprovementBuildingProblem(
|
|||||||
Other
|
Other
|
||||||
}
|
}
|
||||||
|
|
||||||
class TileInfoImprovementFunctions(val tile: Tile) {
|
class TileImprovementFunctions(val tile: Tile) {
|
||||||
|
|
||||||
/** Returns true if the [improvement] can be built on this [Tile] */
|
/** Returns true if the [improvement] can be built on this [Tile] */
|
||||||
fun canBuildImprovement(improvement: TileImprovement, civInfo: Civilization): Boolean = getImprovementBuildingProblems(improvement, civInfo).none()
|
fun canBuildImprovement(improvement: TileImprovement, civInfo: Civilization): Boolean = getImprovementBuildingProblems(improvement, civInfo).none()
|
||||||
@ -114,7 +114,7 @@ class TileInfoImprovementFunctions(val tile: Tile) {
|
|||||||
// Otherwise, we can if this improvement removes the top terrain
|
// Otherwise, we can if this improvement removes the top terrain
|
||||||
if (!hasUnique(UniqueType.RemovesFeaturesIfBuilt, stateForConditionals)) return false
|
if (!hasUnique(UniqueType.RemovesFeaturesIfBuilt, stateForConditionals)) return false
|
||||||
if (knownFeatureRemovals.isNullOrEmpty()) return false
|
if (knownFeatureRemovals.isNullOrEmpty()) return false
|
||||||
val featureRemovals = tile.terrainFeatures.mapNotNull { feature ->
|
val featureRemovals = tile.terrainFeatures.mapNotNull { feature ->
|
||||||
tile.ruleset.tileRemovals.firstOrNull { it.name == Constants.remove + feature } }
|
tile.ruleset.tileRemovals.firstOrNull { it.name == Constants.remove + feature } }
|
||||||
if (featureRemovals.isEmpty()) return false
|
if (featureRemovals.isEmpty()) return false
|
||||||
if (featureRemovals.any { it !in knownFeatureRemovals }) return false
|
if (featureRemovals.any { it !in knownFeatureRemovals }) return false
|
@ -119,7 +119,7 @@ class ConsoleTileCommands: ConsoleCommandNode {
|
|||||||
.flatMap { civ -> civ.cities }
|
.flatMap { civ -> civ.cities }
|
||||||
.firstOrNull { it.name.toCliInput() == param }
|
.firstOrNull { it.name.toCliInput() == param }
|
||||||
// If the user didn't specify a City, they must have given us a Civilization instead -
|
// If the user didn't specify a City, they must have given us a Civilization instead -
|
||||||
// copy of TileInfoImprovementFunctions.takeOverTilesAround.fallbackNearestCity
|
// copy of TileImprovementFunctions.takeOverTilesAround.fallbackNearestCity
|
||||||
?: console.getCivByName(params[0]) // throws if no match
|
?: console.getCivByName(params[0]) // throws if no match
|
||||||
.cities.minByOrNull { it.getCenterTile().aerialDistanceTo(selectedTile) + (if (it.isBeingRazed) 5 else 0) }
|
.cities.minByOrNull { it.getCenterTile().aerialDistanceTo(selectedTile) + (if (it.isBeingRazed) 5 else 0) }
|
||||||
}
|
}
|
||||||
|
@ -428,13 +428,12 @@ object UnitActionsFromUniques {
|
|||||||
val tile = unit.currentTile
|
val tile = unit.currentTile
|
||||||
if (!tile.isPillaged()) return 0
|
if (!tile.isPillaged()) return 0
|
||||||
if (tile.improvementInProgress == Constants.repair) return tile.turnsToImprovement
|
if (tile.improvementInProgress == Constants.repair) return tile.turnsToImprovement
|
||||||
var repairTurns = tile.ruleset.tileImprovements[Constants.repair]!!.getTurnsToBuild(unit.civ, unit)
|
val repairTurns = tile.ruleset.tileImprovements[Constants.repair]!!.getTurnsToBuild(unit.civ, unit)
|
||||||
|
|
||||||
val pillagedImprovement = tile.getImprovementToRepair()!!
|
val pillagedImprovement = tile.getImprovementToRepair()!!
|
||||||
val turnsToBuild = pillagedImprovement.getTurnsToBuild(unit.civ, unit)
|
val turnsToBuild = pillagedImprovement.getTurnsToBuild(unit.civ, unit)
|
||||||
// cap repair to number of turns to build original improvement
|
// cap repair to number of turns to build original improvement
|
||||||
if (turnsToBuild < repairTurns) repairTurns = turnsToBuild
|
return repairTurns.coerceAtMost(turnsToBuild)
|
||||||
return repairTurns
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getRepairActions(unit: MapUnit, tile: Tile) = sequenceOf(getRepairAction(unit)).filterNotNull()
|
internal fun getRepairActions(unit: MapUnit, tile: Tile) = sequenceOf(getRepairAction(unit)).filterNotNull()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user