Fixes bug where in some cases building improvements would increase the base yield of the tile (#4217)

* Fixes bug where in some cases building improvements would increase the base yield of the tile

* Removed unncessary test

* Implemented requested changes

* Implemented requested changes

* Fixed build errors
This commit is contained in:
Xander Lenstra 2021-06-24 14:55:41 +02:00 committed by GitHub
parent b43257cea8
commit 1c42e1e730
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 28 deletions

View File

@ -239,9 +239,9 @@ object GameStarter {
for (startBias in civ.nation.startBias) { for (startBias in civ.nation.startBias) {
if (startBias.startsWith("Avoid ")) { if (startBias.startsWith("Avoid ")) {
val tileToAvoid = startBias.removePrefix("Avoid [").removeSuffix("]") val tileToAvoid = startBias.removePrefix("Avoid [").removeSuffix("]")
preferredTiles = preferredTiles.filter { !it.matchesUniqueFilter(tileToAvoid) } preferredTiles = preferredTiles.filter { !it.matchesTerrainFilter(tileToAvoid) }
} else if (startBias == Constants.coast) preferredTiles = preferredTiles.filter { it.isCoastalTile() } } else if (startBias == Constants.coast) preferredTiles = preferredTiles.filter { it.isCoastalTile() }
else preferredTiles = preferredTiles.filter { it.matchesUniqueFilter(startBias) } else preferredTiles = preferredTiles.filter { it.matchesTerrainFilter(startBias) }
} }
startingLocation = if (preferredTiles.isNotEmpty()) preferredTiles.random() else freeTiles.random() startingLocation = if (preferredTiles.isNotEmpty()) preferredTiles.random() else freeTiles.random()

View File

@ -205,7 +205,7 @@ object BattleDamage {
} }
for (unique in defender.unit.getMatchingUniques("+[]% defence in [] tiles")) { for (unique in defender.unit.getMatchingUniques("+[]% defence in [] tiles")) {
if (tile.matchesUniqueFilter(unique.params[1])) if (tile.matchesFilter(unique.params[1]))
modifiers["[${unique.params[1]}] defence"] = unique.params[0].toInt() modifiers["[${unique.params[1]}] defence"] = unique.params[0].toInt()
} }
@ -228,14 +228,14 @@ object BattleDamage {
+ unit.getCivInfo() + unit.getCivInfo()
.getMatchingUniques("+[]% Strength for units fighting in []")) { .getMatchingUniques("+[]% Strength for units fighting in []")) {
val filter = unique.params[1] val filter = unique.params[1]
if (tile.matchesUniqueFilter(filter, unit.getCivInfo())) if (tile.matchesFilter(filter, unit.getCivInfo()))
modifiers.add(filter, unique.params[0].toInt()) modifiers.add(filter, unique.params[0].toInt())
} }
// Deprecated since 3.15 // Deprecated since 3.15
for (unique in unit.getCivInfo().getMatchingUniques("+[]% combat bonus for units fighting in []")) { for (unique in unit.getCivInfo().getMatchingUniques("+[]% combat bonus for units fighting in []")) {
val filter = unique.params[1] val filter = unique.params[1]
if (tile.matchesUniqueFilter(filter, unit.getCivInfo())) if (tile.matchesFilter(filter, unit.getCivInfo()))
modifiers.add(filter, unique.params[0].toInt()) modifiers.add(filter, unique.params[0].toInt())
} }
// //
@ -243,7 +243,7 @@ object BattleDamage {
for (unique in unit.getCivInfo() for (unique in unit.getCivInfo()
.getMatchingUniques("+[]% Strength if within [] tiles of a []")) { .getMatchingUniques("+[]% Strength if within [] tiles of a []")) {
if (tile.getTilesInDistance(unique.params[1].toInt()) if (tile.getTilesInDistance(unique.params[1].toInt())
.any { it.matchesUniqueFilter(unique.params[2]) } .any { it.matchesFilter(unique.params[2]) }
) )
modifiers[unique.params[2]] = unique.params[0].toInt() modifiers[unique.params[2]] = unique.params[0].toInt()
} }

View File

@ -67,7 +67,7 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
for (city in civInfo.cities) { for (city in civInfo.cities) {
for (tile in city.getTiles()) { for (tile in city.getTiles()) {
if (tile.isCityCenter()) continue if (tile.isCityCenter()) continue
if (ignoredTileTypes.any { tile.matchesUniqueFilter(it, civInfo) }) continue if (ignoredTileTypes.any { tile.matchesFilter(it, civInfo) }) continue
val tileUpkeep = val tileUpkeep =
when (tile.roadStatus) { when (tile.roadStatus) {

View File

@ -42,8 +42,8 @@ open class TileInfo {
// and farms on adjacent to fresh water tiles will have +1 additional Food after researching Civil Service // and farms on adjacent to fresh water tiles will have +1 additional Food after researching Civil Service
@delegate:Transient @delegate:Transient
val isAdjacentToFreshwater: Boolean by lazy { val isAdjacentToFreshwater: Boolean by lazy {
matchesUniqueFilter("River") || matchesUniqueFilter("Fresh water") matchesTerrainFilter("River") || matchesTerrainFilter("Fresh water")
|| neighbors.any { it.matchesUniqueFilter("Fresh water") } || neighbors.any { it.matchesTerrainFilter("Fresh water") }
} }
var militaryUnit: MapUnit? = null var militaryUnit: MapUnit? = null
@ -237,7 +237,7 @@ open class TileInfo {
for (unique in cityWideUniques + civWideUniques) { for (unique in cityWideUniques + civWideUniques) {
val tileType = unique.params[1] val tileType = unique.params[1]
if (tileType == improvement) continue // This is added to the calculation in getImprovementStats. we don't want to add it twice if (tileType == improvement) continue // This is added to the calculation in getImprovementStats. we don't want to add it twice
if (matchesUniqueFilter(tileType, observingCiv) if (matchesTerrainFilter(tileType, observingCiv)
|| tileType == "Strategic resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Strategic || tileType == "Strategic resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Strategic
|| tileType == "Luxury resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Luxury || tileType == "Luxury resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Luxury
|| tileType == "Bonus resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Bonus || tileType == "Bonus resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Bonus
@ -293,7 +293,7 @@ open class TileInfo {
&& observingCiv.tech.isResearched(it.params[2]) && observingCiv.tech.isResearched(it.params[2])
} }
for (unique in cityWideUniques + improvementUniques) { for (unique in cityWideUniques + improvementUniques) {
if (matchesUniqueFilter(unique.params[1]) if (improvement.matchesFilter(unique.params[1])
// Freshwater and non-freshwater cannot be moved to matchesUniqueFilter since that creates an enless feedback. // Freshwater and non-freshwater cannot be moved to matchesUniqueFilter since that creates an enless feedback.
// If you're attempting that, check that it works! // If you're attempting that, check that it works!
|| unique.params[1] == "Fresh water" && isAdjacentToFreshwater || unique.params[1] == "Fresh water" && isAdjacentToFreshwater
@ -312,8 +312,7 @@ open class TileInfo {
if (unique.placeholderText == "[] for each adjacent []") { if (unique.placeholderText == "[] for each adjacent []") {
val adjacent = unique.params[1] val adjacent = unique.params[1]
val numberOfBonuses = neighbors.count { val numberOfBonuses = neighbors.count {
it.improvement == adjacent it.matchesFilter(adjacent, observingCiv)
|| it.matchesUniqueFilter(adjacent, observingCiv)
|| it.roadStatus.name == adjacent || it.roadStatus.name == adjacent
} }
stats.add(unique.stats.times(numberOfBonuses.toFloat())) stats.add(unique.stats.times(numberOfBonuses.toFloat()))
@ -361,7 +360,7 @@ open class TileInfo {
"Cannot be built on bonus resource" in improvement.uniques && resource != null "Cannot be built on bonus resource" in improvement.uniques && resource != null
&& getTileResource().resourceType == ResourceType.Bonus -> false && getTileResource().resourceType == ResourceType.Bonus -> false
improvement.uniqueObjects.filter { it.placeholderText == "Cannot be built on [] tiles" }.any { improvement.uniqueObjects.filter { it.placeholderText == "Cannot be built on [] tiles" }.any {
unique -> matchesUniqueFilter(unique.params[0]) unique -> matchesTerrainFilter(unique.params[0])
} -> false } -> false
// Road improvements can change on tiles with irremovable improvements - nothing else can, though. // Road improvements can change on tiles with irremovable improvements - nothing else can, though.
@ -377,7 +376,7 @@ open class TileInfo {
improvement.uniqueObjects.filter { it.placeholderText == "Must be next to []" }.any { improvement.uniqueObjects.filter { it.placeholderText == "Must be next to []" }.any {
val filter = it.params[0] val filter = it.params[0]
if (filter == "River") return@any !isAdjacentToRiver() if (filter == "River") return@any !isAdjacentToRiver()
else return@any !neighbors.any { neighbor -> neighbor.matchesUniqueFilter(filter) } else return@any !neighbors.any { neighbor -> neighbor.matchesFilter(filter) }
} -> false } -> false
improvement.name == "Road" && roadStatus == RoadStatus.None && !isWater -> true improvement.name == "Road" && roadStatus == RoadStatus.None && !isWater -> true
improvement.name == "Railroad" && this.roadStatus != RoadStatus.Railroad && !isWater -> true improvement.name == "Railroad" && this.roadStatus != RoadStatus.Railroad && !isWater -> true
@ -388,7 +387,7 @@ open class TileInfo {
improvement.hasUnique("Can also be built on tiles adjacent to fresh water") && isAdjacentToFreshwater -> true improvement.hasUnique("Can also be built on tiles adjacent to fresh water") && isAdjacentToFreshwater -> true
"Can only be built on Coastal tiles" in improvement.uniques && isCoastalTile() -> true "Can only be built on Coastal tiles" in improvement.uniques && isCoastalTile() -> true
improvement.uniqueObjects.filter { it.placeholderText == "Can only be built on [] tiles" }.any { improvement.uniqueObjects.filter { it.placeholderText == "Can only be built on [] tiles" }.any {
unique -> !matchesUniqueFilter(unique.params[0]) unique -> !matchesTerrainFilter(unique.params[0])
} -> false } -> false
else -> resourceIsVisible && getTileResource().improvement == improvement.name else -> resourceIsVisible && getTileResource().improvement == improvement.name
} }
@ -398,7 +397,13 @@ open class TileInfo {
* Implementation of _`tileFilter`_ * Implementation of _`tileFilter`_
* @see <a href="https://github.com/yairm210/Unciv/wiki/uniques#user-content-tilefilter">tileFilter</a> * @see <a href="https://github.com/yairm210/Unciv/wiki/uniques#user-content-tilefilter">tileFilter</a>
*/ */
fun matchesUniqueFilter(filter: String, civInfo: CivilizationInfo? = null): Boolean { fun matchesFilter(filter: String, civInfo: CivilizationInfo? = null): Boolean {
if (matchesTerrainFilter(filter, civInfo)) return true
if (improvement != null && ruleset.tileImprovements[improvement]!!.matchesFilter(filter)) return true
return false
}
fun matchesTerrainFilter(filter: String, observingCiv: CivilizationInfo? = null): Boolean {
return when (filter) { return when (filter) {
"All" -> true "All" -> true
baseTerrain -> true baseTerrain -> true
@ -406,17 +411,16 @@ open class TileInfo {
"Land" -> isLand "Land" -> isLand
"Coastal" -> isCoastalTile() "Coastal" -> isCoastalTile()
"River" -> isAdjacentToRiver() "River" -> isAdjacentToRiver()
improvement -> true
naturalWonder -> true naturalWonder -> true
"Open terrain" -> !isRoughTerrain() "Open terrain" -> !isRoughTerrain()
"Rough terrain" -> isRoughTerrain() "Rough terrain" -> isRoughTerrain()
"Foreign Land" -> civInfo != null && !isFriendlyTerritory(civInfo) "Foreign Land" -> observingCiv != null && !isFriendlyTerritory(observingCiv)
"Friendly Land" -> civInfo != null && isFriendlyTerritory(civInfo) "Friendly Land" -> observingCiv != null && isFriendlyTerritory(observingCiv)
resource -> observingCiv != null && hasViewableResource(observingCiv)
else -> { else -> {
if (terrainFeatures.contains(filter)) return true if (terrainFeatures.contains(filter)) return true
if (hasUnique(filter)) return true if (hasUnique(filter)) return true
if (resource != null && getTileResource().resourceType.name + " resource" == filter) return true if (resource != null && getTileResource().resourceType.name + " resource" == filter) return true
if (civInfo != null && hasViewableResource(civInfo) && resource == filter) return true
return false return false
} }
} }

View File

@ -272,13 +272,13 @@ class Building : NamedStats(), IConstruction {
for (unique in uniqueObjects) when (unique.placeholderText) { for (unique in uniqueObjects) when (unique.placeholderText) {
"Enables nuclear weapon" -> if(!construction.cityInfo.civInfo.gameInfo.gameParameters.nuclearWeaponsEnabled) return "Disabled by setting" "Enables nuclear weapon" -> if(!construction.cityInfo.civInfo.gameInfo.gameParameters.nuclearWeaponsEnabled) return "Disabled by setting"
"Must be on []" -> if (!cityCenter.matchesUniqueFilter(unique.params[0], civInfo)) return unique.text "Must be on []" -> if (!cityCenter.matchesTerrainFilter(unique.params[0], civInfo)) return unique.text
"Must not be on []" -> if (cityCenter.matchesUniqueFilter(unique.params[0], civInfo)) return unique.text "Must not be on []" -> if (cityCenter.matchesTerrainFilter(unique.params[0], civInfo)) return unique.text
"Must be next to []" -> if (!(unique.params[0] == "Fresh water" && cityCenter.isAdjacentToRiver()) // Fresh water is special, in that rivers are not tiles themselves but also fit the filter. "Must be next to []" -> if (!(unique.params[0] == "Fresh water" && cityCenter.isAdjacentToRiver()) // Fresh water is special, in that rivers are not tiles themselves but also fit the filter.
&& cityCenter.getTilesInDistance(1).none { it.matchesUniqueFilter(unique.params[0], civInfo) }) return unique.text && cityCenter.getTilesInDistance(1).none { it.matchesFilter(unique.params[0], civInfo) }) return unique.text
"Must not be next to []" -> if (cityCenter.getTilesInDistance(1).any { it.matchesUniqueFilter(unique.params[0], civInfo) }) return unique.text "Must not be next to []" -> if (cityCenter.getTilesInDistance(1).any { it.matchesFilter(unique.params[0], civInfo) }) return unique.text
"Must have an owned [] within [] tiles" -> if (cityCenter.getTilesInDistance(unique.params[1].toInt()).none { "Must have an owned [] within [] tiles" -> if (cityCenter.getTilesInDistance(unique.params[1].toInt()).none {
it.matchesUniqueFilter(unique.params[0], civInfo) && it.getOwner() == construction.cityInfo.civInfo it.matchesFilter(unique.params[0], civInfo) && it.getOwner() == construction.cityInfo.civInfo
}) return unique.text }) return unique.text
"Can only be built in annexed cities" -> if (construction.cityInfo.isPuppet || construction.cityInfo.foundingCiv == "" "Can only be built in annexed cities" -> if (construction.cityInfo.isPuppet || construction.cityInfo.foundingCiv == ""
|| construction.cityInfo.civInfo.civName == construction.cityInfo.foundingCiv) return unique.text || construction.cityInfo.civInfo.civName == construction.cityInfo.foundingCiv) return unique.text