Step 1 of resolving #6186 freshwater crisis - unify adjacency to a single function, only rivers are outliers (#6219)

This commit is contained in:
Yair Morgenstern
2022-02-25 13:39:34 +02:00
committed by GitHub
parent 8cb73ac91b
commit 78f0ad768a
5 changed files with 21 additions and 23 deletions

View File

@ -21,12 +21,12 @@ object Constants {
const val forest = "Forest"
const val jungle = "Jungle"
const val ice = "Ice"
const val floodPlains = "Flood plains"
val vegetation = arrayOf(forest, jungle)
val sea = arrayOf(ocean, coast)
const val freshWater = "Fresh water"
const val barbarianEncampment = "Barbarian encampment"
const val peaceTreaty = "Peace Treaty"

View File

@ -51,14 +51,6 @@ open class TileInfo {
@Transient
var isOcean = false
// This will be called often - farm can be built on Hill and tundra if adjacent to fresh water
// and farms on adjacent to fresh water tiles will have +1 additional Food after researching Civil Service
@delegate:Transient
val isAdjacentToFreshwater: Boolean by lazy {
matchesTerrainFilter("River") || matchesTerrainFilter("Fresh water")
|| neighbors.any { it.matchesTerrainFilter("Fresh water") }
}
var militaryUnit: MapUnit? = null
var civilianUnit: MapUnit? = null
var airUnits = ArrayList<MapUnit>()
@ -398,7 +390,7 @@ open class TileInfo {
.sumOf { it.params[0].toInt() }
}
if (isAdjacentToRiver()) fertility += 1
if (isAdjacentToFreshwater) fertility += 1 // meaning total +2 for river
if (isAdjacentTo(Constants.freshWater)) fertility += 1 // meaning total +2 for river
if (checkCoasts && isCoastalTile()) fertility += 2
return fertility
}
@ -435,8 +427,8 @@ open class TileInfo {
// Freshwater and non-freshwater cannot be moved to matchesUniqueFilter since that creates an endless feedback.
// If you're attempting that, check that it works!
// Edit: It seems to have been moved?
|| unique.params[1] == "Fresh water" && isAdjacentToFreshwater
|| unique.params[1] == "non-fresh water" && !isAdjacentToFreshwater
|| unique.params[1] == Constants.freshWater && isAdjacentTo(Constants.freshWater)
|| unique.params[1] == "non-fresh water" && !isAdjacentTo(Constants.freshWater)
)
stats.add(unique.stats)
}
@ -496,10 +488,12 @@ open class TileInfo {
}
}
// This should be the only adjacency function
fun isAdjacentTo(terrainFilter:String): Boolean {
if (terrainFilter == "Fresh water" && isAdjacentToFreshwater) return true
return if (terrainFilter == "River") isAdjacentToRiver()
else neighbors.any { neighbor -> neighbor.matchesFilter(terrainFilter) }
// Rivers are odd, as they aren't technically part of any specific tile but still count towards adjacency
if (terrainFilter == "River") return isAdjacentToRiver()
if (terrainFilter == Constants.freshWater && isAdjacentToRiver()) return true
return neighbors.any { neighbor -> neighbor.matchesFilter(terrainFilter) }
}
/** Without regards to what CivInfo it is, a lot of the checks are just for the improvement on the tile.
@ -528,14 +522,14 @@ open class TileInfo {
// Tiles with no terrains, and no turns to build, are like great improvements - they're placeable
improvement.terrainsCanBeBuiltOn.isEmpty() && improvement.turnsToBuild == 0 && isLand -> true
improvement.terrainsCanBeBuiltOn.contains(topTerrain.name) -> true
improvement.uniqueObjects.filter { it.type == UniqueType.MustBeNextTo }.any {
improvement.getMatchingUniques(UniqueType.MustBeNextTo).any {
!isAdjacentTo(it.params[0])
} -> false
!isWater && RoadStatus.values().any { it.name == improvement.name && it > roadStatus } -> true
improvement.name == roadStatus.removeAction -> true
topTerrain.unbuildable && !improvement.isAllowedOnFeature(topTerrain.name) -> false
// DO NOT reverse this &&. isAdjacentToFreshwater() is a lazy which calls a function, and reversing it breaks the tests.
improvement.hasUnique(UniqueType.ImprovementBuildableByFreshWater) && isAdjacentToFreshwater -> true
improvement.hasUnique(UniqueType.ImprovementBuildableByFreshWater) && isAdjacentTo(Constants.freshWater) -> true
// If an unique of this type exists, we want all to match (e.g. Hill _and_ Forest would be meaningful).
improvement.getMatchingUniques(UniqueType.CanOnlyBeBuiltOnTile).let {
@ -574,7 +568,7 @@ open class TileInfo {
"Water resource" -> isWater && observingCiv != null && hasViewableResource(observingCiv)
"Natural Wonder" -> naturalWonder != null
"Featureless" -> terrainFeatures.isEmpty()
"Fresh Water" -> isAdjacentToFreshwater
"Fresh Water" -> isAdjacentTo(Constants.freshWater)
else -> {
if (terrainFeatures.contains(filter)) return true
if (getAllTerrains().any { it.hasUnique(filter) }) return true

View File

@ -2,6 +2,7 @@ package com.unciv.logic.map.mapgenerator
import com.badlogic.gdx.math.Rectangle
import com.badlogic.gdx.math.Vector2
import com.unciv.Constants
import com.unciv.logic.HexMath
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.*
@ -391,7 +392,7 @@ class MapRegions (val ruleset: Ruleset){
evaluateTileForStart(tile)
if (tile.isAdjacentToRiver())
riverTiles.add(tile.position)
else if (tile.isCoastalTile() || tile.isAdjacentToFreshwater)
else if (tile.isCoastalTile() || tile.isAdjacentTo(Constants.freshWater))
wetTiles.add(tile.position)
else
dryTiles.add(tile.position)
@ -422,7 +423,7 @@ class MapRegions (val ruleset: Ruleset){
evaluateTileForStart(tile)
if (tile.isAdjacentToRiver())
riverTiles.add(tile.position)
else if (tile.isCoastalTile() || tile.isAdjacentToFreshwater)
else if (tile.isCoastalTile() || tile.isAdjacentTo(Constants.freshWater))
wetTiles.add(tile.position)
else
dryTiles.add(tile.position)
@ -504,7 +505,7 @@ class MapRegions (val ruleset: Ruleset){
// If terrible, try adding a hill to a dry flat tile
if (innerProduction == 0 || (innerProduction < 2 && outerProduction < 8) || (minorCiv && innerProduction < 4)) {
val hillSpot = startTile.neighbors
.filter { it.isLand && it.terrainFeatures.isEmpty() && !it.isAdjacentToFreshwater && !it.isImpassible() }
.filter { it.isLand && it.terrainFeatures.isEmpty() && !it.isAdjacentTo(Constants.freshWater) && !it.isImpassible() }
.toList().randomOrNull()
val hillEquivalent = ruleset.terrains.values
.firstOrNull { it.type == TerrainType.TerrainFeature && it.production >= 2 && !it.hasUnique(UniqueType.RareFeature) }?.name

View File

@ -170,6 +170,8 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
UniqueType.ConditionalInTiles ->
relevantTile?.matchesFilter(condition.params[0], state.civInfo) == true
UniqueType.ConditionalInTilesNot ->
relevantTile?.matchesFilter(condition.params[0], state.civInfo) == false
UniqueType.ConditionalFightingInTiles ->
state.attackedTile?.matchesFilter(condition.params[0], state.civInfo) == true
UniqueType.ConditionalInTilesAnd ->

View File

@ -3,6 +3,7 @@ package com.unciv.models.translations
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.utils.Array
import com.unciv.Constants
import com.unciv.JsonParser
import com.unciv.models.metadata.BaseRuleset
import com.unciv.models.ruleset.*
@ -241,7 +242,7 @@ object TranslationFileWriter {
val tileFilterMap = ruleset.terrains.keys.toMutableSet().apply { addAll(sequenceOf(
"Friendly Land",
"Foreign Land",
"Fresh water",
Constants.freshWater,
"non-fresh water",
"Open Terrain",
"Rough Terrain",