Don't do anything crazy if military is inferior and never give away m… (#9096)

* Don't do anything crazy if military is inferior and never give away more than 10% (ceil) of your cities in any case.

* Don't coerce types implicitly.

* Comment weird distance to capital logic and invert -- => +

* Maximum give away 20% of cities instead of 10%
This commit is contained in:
WhoIsJohannes 2023-04-04 09:50:33 +02:00 committed by GitHub
parent cd4e25a4f1
commit bc341a6fcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -12,6 +12,7 @@ import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.components.extensions.toPercent import com.unciv.ui.components.extensions.toPercent
import com.unciv.ui.screens.victoryscreen.RankingType import com.unciv.ui.screens.victoryscreen.RankingType
import kotlin.math.ceil
import kotlin.math.min import kotlin.math.min
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.sqrt import kotlin.math.sqrt
@ -61,6 +62,12 @@ class TradeEvaluation {
} }
fun getTradeAcceptability(trade: Trade, evaluator: Civilization, tradePartner: Civilization): Int { fun getTradeAcceptability(trade: Trade, evaluator: Civilization, tradePartner: Civilization): Int {
val citiesAskedToSurrender = trade.ourOffers.filter { it.type == TradeType.City }.count()
val maxCitiesToSurrender = ceil(evaluator.cities.size.toFloat() / 5).toInt()
if (citiesAskedToSurrender > maxCitiesToSurrender) {
return Int.MIN_VALUE
}
val sumOfTheirOffers = trade.theirOffers.asSequence() val sumOfTheirOffers = trade.theirOffers.asSequence()
.filter { it.type != TradeType.Treaty } // since treaties should only be evaluated once for 2 sides .filter { it.type != TradeType.Treaty } // since treaties should only be evaluated once for 2 sides
.map { evaluateBuyCost(it, evaluator, tradePartner) }.sum() .map { evaluateBuyCost(it, evaluator, tradePartner) }.sum()
@ -250,12 +257,11 @@ class TradeEvaluation {
val city = civInfo.cities.firstOrNull { it.id == offer.name } val city = civInfo.cities.firstOrNull { it.id == offer.name }
?: throw Exception("Got an offer to sell city id " + offer.name + " which does't seem to exist for this civ!") ?: throw Exception("Got an offer to sell city id " + offer.name + " which does't seem to exist for this civ!")
val capitalcity = civInfo.getCapital()!! val distanceBonus = distanceCityTradeModifier(civInfo, city)
val distanceCost = distanceCityTradeModifier(civInfo, capitalcity, city)
val stats = city.cityStats.currentCityStats val stats = city.cityStats.currentCityStats
val sumOfStats = val sumOfStats =
stats.culture + stats.gold + stats.science + stats.production + stats.happiness + stats.food - distanceCost stats.culture + stats.gold + stats.science + stats.production + stats.happiness + stats.food + distanceBonus
return sumOfStats.toInt() * 100 return min(sumOfStats.toInt() * 100, 1000)
} }
TradeType.Agreement -> { TradeType.Agreement -> {
if (offer.name == Constants.openBorders) { if (offer.name == Constants.openBorders) {
@ -272,11 +278,15 @@ class TradeEvaluation {
} }
} }
private fun distanceCityTradeModifier(civInfo: Civilization, capitalcity: City, city: City): Int{ /** This code returns a positive value if the city is significantly far away from the capital
val distanceBetweenCities = capitalcity.getCenterTile().aerialDistanceTo(city.getCenterTile()) * and given how this method is used this ends up making such cities more expensive. That's how
* I found it. I'm not sure it makes sense. One might also find arguments why cities closer to
* the capital are more expensive. */
private fun distanceCityTradeModifier(civInfo: Civilization, city: City): Int{
val distanceToCapital = civInfo.getCapital()!!.getCenterTile().aerialDistanceTo(city.getCenterTile())
if (distanceBetweenCities < 500) return 0 if (distanceToCapital < 500) return 0
return min(50, (500 - distanceBetweenCities) * civInfo.getEraNumber()) return (distanceToCapital - 500) * civInfo.getEraNumber()
} }
fun evaluatePeaceCostForThem(ourCivilization: Civilization, otherCivilization: Civilization): Int { fun evaluatePeaceCostForThem(ourCivilization: Civilization, otherCivilization: Civilization): Int {
@ -287,11 +297,34 @@ class TradeEvaluation {
if (ourCombatStrength > theirCombatStrength) { if (ourCombatStrength > theirCombatStrength) {
val absoluteAdvantage = ourCombatStrength - theirCombatStrength val absoluteAdvantage = ourCombatStrength - theirCombatStrength
val percentageAdvantage = absoluteAdvantage / theirCombatStrength.toFloat() val percentageAdvantage = absoluteAdvantage / theirCombatStrength.toFloat()
// We don't add the same constraint here. We should not make peace easily if we're
// heavily advantaged.
return (absoluteAdvantage * percentageAdvantage).toInt() * 10 return (absoluteAdvantage * percentageAdvantage).toInt() * 10
} else { } else {
// This results in huge values for large power imbalances. However, we should not give
// up everything just because there is a big power imbalance. There's a better chance to
// recover if you don't give away all your cities for example.
//
// Example A (this would probably give us away everything):
// absoluteAdvantage = 10000 - 100 = 9500
// percentageAdvantage = 9500 / 100 = 95
// return -(9500 * 95) * 10 = -9025000
//
// Example B (this is borderline)
// absoluteAdvantage = 10000 - 2500 = 7500
// percentageAdvantage = 7500 / 2500 = 3
// return -(7500 * 3) * 10 = -225000
//
// Example C (this is fine):
// absoluteAdvantage = 10000 - 5000 = 5000
// percentageAdvantage = 5000 / 5000 = 1
// return -(5000 * 1) * 10 = -50000
//
// Hence we cap the max cost at 100k which equals about 2 or 3 cities in the mid game
// (stats ~30 each)
val absoluteAdvantage = theirCombatStrength - ourCombatStrength val absoluteAdvantage = theirCombatStrength - ourCombatStrength
val percentageAdvantage = absoluteAdvantage / ourCombatStrength.toFloat() val percentageAdvantage = absoluteAdvantage / ourCombatStrength.toFloat()
return -(absoluteAdvantage * percentageAdvantage).toInt() * 10 return -min((absoluteAdvantage * percentageAdvantage).toInt() * 10, 100000)
} }
} }