diff --git a/core/src/com/unciv/Constants.kt b/core/src/com/unciv/Constants.kt index ba9a014b7d..caa57a436a 100644 --- a/core/src/com/unciv/Constants.kt +++ b/core/src/com/unciv/Constants.kt @@ -21,11 +21,11 @@ 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" diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 96029d6d4c..ba909af80f 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -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() @@ -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 diff --git a/core/src/com/unciv/logic/map/mapgenerator/MapRegions.kt b/core/src/com/unciv/logic/map/mapgenerator/MapRegions.kt index 5c27a093b7..b8e8bd7c59 100644 --- a/core/src/com/unciv/logic/map/mapgenerator/MapRegions.kt +++ b/core/src/com/unciv/logic/map/mapgenerator/MapRegions.kt @@ -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 diff --git a/core/src/com/unciv/models/ruleset/unique/Unique.kt b/core/src/com/unciv/models/ruleset/unique/Unique.kt index 7e17a355a8..912172cd96 100644 --- a/core/src/com/unciv/models/ruleset/unique/Unique.kt +++ b/core/src/com/unciv/models/ruleset/unique/Unique.kt @@ -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 -> diff --git a/core/src/com/unciv/models/translations/TranslationFileWriter.kt b/core/src/com/unciv/models/translations/TranslationFileWriter.kt index 2e815c7f1b..7e80a0e01f 100644 --- a/core/src/com/unciv/models/translations/TranslationFileWriter.kt +++ b/core/src/com/unciv/models/translations/TranslationFileWriter.kt @@ -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",