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) {
if (startBias.startsWith("Avoid ")) {
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 preferredTiles = preferredTiles.filter { it.matchesUniqueFilter(startBias) }
else preferredTiles = preferredTiles.filter { it.matchesTerrainFilter(startBias) }
}
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")) {
if (tile.matchesUniqueFilter(unique.params[1]))
if (tile.matchesFilter(unique.params[1]))
modifiers["[${unique.params[1]}] defence"] = unique.params[0].toInt()
}
@ -228,14 +228,14 @@ object BattleDamage {
+ unit.getCivInfo()
.getMatchingUniques("+[]% Strength for units fighting in []")) {
val filter = unique.params[1]
if (tile.matchesUniqueFilter(filter, unit.getCivInfo()))
if (tile.matchesFilter(filter, unit.getCivInfo()))
modifiers.add(filter, unique.params[0].toInt())
}
// Deprecated since 3.15
for (unique in unit.getCivInfo().getMatchingUniques("+[]% combat bonus for units fighting in []")) {
val filter = unique.params[1]
if (tile.matchesUniqueFilter(filter, unit.getCivInfo()))
if (tile.matchesFilter(filter, unit.getCivInfo()))
modifiers.add(filter, unique.params[0].toInt())
}
//
@ -243,7 +243,7 @@ object BattleDamage {
for (unique in unit.getCivInfo()
.getMatchingUniques("+[]% Strength if within [] tiles of a []")) {
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()
}

View File

@ -67,7 +67,7 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
for (city in civInfo.cities) {
for (tile in city.getTiles()) {
if (tile.isCityCenter()) continue
if (ignoredTileTypes.any { tile.matchesUniqueFilter(it, civInfo) }) continue
if (ignoredTileTypes.any { tile.matchesFilter(it, civInfo) }) continue
val tileUpkeep =
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
@delegate:Transient
val isAdjacentToFreshwater: Boolean by lazy {
matchesUniqueFilter("River") || matchesUniqueFilter("Fresh water")
|| neighbors.any { it.matchesUniqueFilter("Fresh water") }
matchesTerrainFilter("River") || matchesTerrainFilter("Fresh water")
|| neighbors.any { it.matchesTerrainFilter("Fresh water") }
}
var militaryUnit: MapUnit? = null
@ -237,7 +237,7 @@ open class TileInfo {
for (unique in cityWideUniques + civWideUniques) {
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 (matchesUniqueFilter(tileType, observingCiv)
if (matchesTerrainFilter(tileType, observingCiv)
|| tileType == "Strategic resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Strategic
|| tileType == "Luxury resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Luxury
|| tileType == "Bonus resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Bonus
@ -293,7 +293,7 @@ open class TileInfo {
&& observingCiv.tech.isResearched(it.params[2])
}
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.
// If you're attempting that, check that it works!
|| unique.params[1] == "Fresh water" && isAdjacentToFreshwater
@ -312,15 +312,14 @@ open class TileInfo {
if (unique.placeholderText == "[] for each adjacent []") {
val adjacent = unique.params[1]
val numberOfBonuses = neighbors.count {
it.improvement == adjacent
|| it.matchesUniqueFilter(adjacent, observingCiv)
|| it.roadStatus.name == adjacent
it.matchesFilter(adjacent, observingCiv)
|| it.roadStatus.name == adjacent
}
stats.add(unique.stats.times(numberOfBonuses.toFloat()))
}
for (unique in observingCiv.getMatchingUniques("+[]% yield from every []"))
if (improvement.matchesFilter(unique.params[1]))
if (improvement.matchesFilter(unique.params[1]))
stats.timesInPlace(1f + unique.params[0].toFloat() / 100f)
// Deprecated since 3.15
@ -361,7 +360,7 @@ open class TileInfo {
"Cannot be built on bonus resource" in improvement.uniques && resource != null
&& getTileResource().resourceType == ResourceType.Bonus -> false
improvement.uniqueObjects.filter { it.placeholderText == "Cannot be built on [] tiles" }.any {
unique -> matchesUniqueFilter(unique.params[0])
unique -> matchesTerrainFilter(unique.params[0])
} -> false
// 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 {
val filter = it.params[0]
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
improvement.name == "Road" && roadStatus == RoadStatus.None && !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
"Can only be built on Coastal tiles" in improvement.uniques && isCoastalTile() -> true
improvement.uniqueObjects.filter { it.placeholderText == "Can only be built on [] tiles" }.any {
unique -> !matchesUniqueFilter(unique.params[0])
unique -> !matchesTerrainFilter(unique.params[0])
} -> false
else -> resourceIsVisible && getTileResource().improvement == improvement.name
}
@ -398,7 +397,13 @@ open class TileInfo {
* Implementation of _`tileFilter`_
* @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) {
"All" -> true
baseTerrain -> true
@ -406,17 +411,16 @@ open class TileInfo {
"Land" -> isLand
"Coastal" -> isCoastalTile()
"River" -> isAdjacentToRiver()
improvement -> true
naturalWonder -> true
"Open terrain" -> !isRoughTerrain()
"Rough terrain" -> isRoughTerrain()
"Foreign Land" -> civInfo != null && !isFriendlyTerritory(civInfo)
"Friendly Land" -> civInfo != null && isFriendlyTerritory(civInfo)
"Foreign Land" -> observingCiv != null && !isFriendlyTerritory(observingCiv)
"Friendly Land" -> observingCiv != null && isFriendlyTerritory(observingCiv)
resource -> observingCiv != null && hasViewableResource(observingCiv)
else -> {
if (terrainFeatures.contains(filter)) return true
if (hasUnique(filter)) return true
if (resource != null && getTileResource().resourceType.name + " resource" == filter) return true
if (civInfo != null && hasViewableResource(civInfo) && resource == filter) return true
return false
}
}

View File

@ -272,13 +272,13 @@ class Building : NamedStats(), IConstruction {
for (unique in uniqueObjects) when (unique.placeholderText) {
"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 not 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.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.
&& cityCenter.getTilesInDistance(1).none { it.matchesUniqueFilter(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
&& cityCenter.getTilesInDistance(1).none { it.matchesFilter(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 {
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
"Can only be built in annexed cities" -> if (construction.cityInfo.isPuppet || construction.cityInfo.foundingCiv == ""
|| construction.cityInfo.civInfo.civName == construction.cityInfo.foundingCiv) return unique.text