mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-16 10:49:17 +07:00
AI trading uses gold inflation (#10370)
* Fixed cities being sold for at most 1000 gold * Replaced evaluateBuy/SellCost with evaluateBuy/SellCostWithInflation * Fixed goldInflation being multiplied instead of divided * Increased inflation modifier, lowering it's impact * Changed inflation values to be lower * Moved return value to be inline again (it was moved for testing)
This commit is contained in:
@ -175,7 +175,7 @@ object NextTurnAutomation {
|
||||
if (offer.type == TradeType.Treaty)
|
||||
continue // Don't try to counter with a defensive pact or research pact
|
||||
|
||||
val value = evaluation.evaluateBuyCost(offer, civInfo, otherCiv)
|
||||
val value = evaluation.evaluateBuyCostWithInflation(offer, civInfo, otherCiv)
|
||||
if (value > 0)
|
||||
potentialAsks[offer] = value
|
||||
}
|
||||
@ -204,7 +204,7 @@ object NextTurnAutomation {
|
||||
// Remove 1 amount as long as doing so does not change the price
|
||||
val originalValue = counterofferAsks[ask]!!
|
||||
while (ask.amount > 1
|
||||
&& originalValue == evaluation.evaluateBuyCost(
|
||||
&& originalValue == evaluation.evaluateBuyCostWithInflation(
|
||||
TradeOffer(ask.name, ask.type, ask.amount - 1, ask.duration),
|
||||
civInfo, otherCiv) ) {
|
||||
ask.amount--
|
||||
@ -216,7 +216,7 @@ object NextTurnAutomation {
|
||||
for (goldAsk in counterofferAsks.keys
|
||||
.filter { it.type == TradeType.Gold_Per_Turn || it.type == TradeType.Gold }
|
||||
.sortedByDescending { it.type.ordinal }) { // Do GPT first
|
||||
val valueOfOne = evaluation.evaluateBuyCost(TradeOffer(goldAsk.name, goldAsk.type, 1, goldAsk.duration), civInfo, otherCiv)
|
||||
val valueOfOne = evaluation.evaluateBuyCostWithInflation(TradeOffer(goldAsk.name, goldAsk.type, 1, goldAsk.duration), civInfo, otherCiv)
|
||||
val amountCanBeRemoved = deltaInOurFavor / valueOfOne
|
||||
if (amountCanBeRemoved >= goldAsk.amount) {
|
||||
deltaInOurFavor -= counterofferAsks[goldAsk]!!
|
||||
@ -236,7 +236,7 @@ object NextTurnAutomation {
|
||||
.sortedByDescending { it.type.ordinal }) {
|
||||
if (tradeLogic.currentTrade.theirOffers.none { it.type == ourGold.type } &&
|
||||
counterofferAsks.keys.none { it.type == ourGold.type } ) {
|
||||
val valueOfOne = evaluation.evaluateSellCost(TradeOffer(ourGold.name, ourGold.type, 1, ourGold.duration), civInfo, otherCiv)
|
||||
val valueOfOne = evaluation.evaluateSellCostWithInflation(TradeOffer(ourGold.name, ourGold.type, 1, ourGold.duration), civInfo, otherCiv)
|
||||
val amountToGive = min(deltaInOurFavor / valueOfOne, ourGold.amount)
|
||||
deltaInOurFavor -= amountToGive * valueOfOne
|
||||
if (amountToGive > 0) {
|
||||
|
@ -6,7 +6,6 @@ import com.unciv.logic.automation.ThreatLevel
|
||||
import com.unciv.logic.automation.civilization.NextTurnAutomation
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.ruleset.ModOptionsConstants
|
||||
@ -73,9 +72,9 @@ class TradeEvaluation {
|
||||
|
||||
val sumOfTheirOffers = trade.theirOffers.asSequence()
|
||||
.filter { it.type != TradeType.Treaty } // since treaties should only be evaluated once for 2 sides
|
||||
.map { evaluateBuyCost(it, evaluator, tradePartner) }.sum()
|
||||
.map { evaluateBuyCostWithInflation(it, evaluator, tradePartner) }.sum()
|
||||
|
||||
var sumOfOurOffers = trade.ourOffers.sumOf { evaluateSellCost(it, evaluator, tradePartner) }
|
||||
var sumOfOurOffers = trade.ourOffers.sumOf { evaluateSellCostWithInflation(it, evaluator, tradePartner) }
|
||||
|
||||
val relationshipLevel = evaluator.getDiplomacyManager(tradePartner).relationshipIgnoreAfraid()
|
||||
// If we're making a peace treaty, don't try to up the bargain for people you don't like.
|
||||
@ -94,6 +93,12 @@ class TradeEvaluation {
|
||||
|
||||
return sumOfTheirOffers - sumOfOurOffers
|
||||
}
|
||||
|
||||
fun evaluateBuyCostWithInflation(offer: TradeOffer, civInfo: Civilization, tradePartner: Civilization): Int {
|
||||
if (offer.type != TradeType.Gold && offer.type != TradeType.Gold_Per_Turn)
|
||||
return (evaluateBuyCost(offer, civInfo, tradePartner) / getGoldInflation(civInfo)).toInt()
|
||||
return evaluateBuyCost(offer, civInfo, tradePartner)
|
||||
}
|
||||
|
||||
fun evaluateBuyCost(offer: TradeOffer, civInfo: Civilization, tradePartner: Civilization): Int {
|
||||
when (offer.type) {
|
||||
@ -198,6 +203,12 @@ class TradeEvaluation {
|
||||
}
|
||||
|
||||
|
||||
fun evaluateSellCostWithInflation(offer: TradeOffer, civInfo: Civilization, tradePartner: Civilization): Int {
|
||||
if (offer.type != TradeType.Gold && offer.type != TradeType.Gold_Per_Turn)
|
||||
return (evaluateSellCost(offer, civInfo, tradePartner) / getGoldInflation(civInfo)).toInt()
|
||||
return evaluateSellCost(offer, civInfo, tradePartner)
|
||||
}
|
||||
|
||||
fun evaluateSellCost(offer: TradeOffer, civInfo: Civilization, tradePartner: Civilization): Int {
|
||||
when (offer.type) {
|
||||
TradeType.Gold -> return offer.amount
|
||||
@ -275,7 +286,7 @@ class TradeEvaluation {
|
||||
val stats = city.cityStats.currentCityStats
|
||||
val sumOfStats =
|
||||
stats.culture + stats.gold + stats.science + stats.production + stats.happiness + stats.food + distanceBonus
|
||||
return min(sumOfStats.toInt() * 100, 1000)
|
||||
return (sumOfStats.toInt() * 100).coerceAtLeast(1000)
|
||||
}
|
||||
TradeType.Agreement -> {
|
||||
if (offer.name == Constants.openBorders) {
|
||||
@ -292,6 +303,20 @@ class TradeEvaluation {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns how much one gold is worth now in comparison to starting out the game
|
||||
* Gold is worth less as the civilization has a higher income
|
||||
*/
|
||||
fun getGoldInflation(civInfo: Civilization): Double {
|
||||
val modifier = 1000.0
|
||||
val goldPerTurn = civInfo.stats.statsForNextTurn.gold.toDouble()
|
||||
// To visualise the function, plug this into a 2d graphing calculator \frac{1000}{x^{1.2}+1.11*1000}
|
||||
// Goes from 1 at GPT = 0 to .834 at GPT = 100, .296 at GPT = 1000 and 0.116 at GPT = 10000
|
||||
// The current value of gold will never go below 10% or the .1f that it is set to
|
||||
// So this does not scale off to infinity
|
||||
return modifier / (goldPerTurn.pow(1.2).coerceAtLeast(0.0) + (1.11f * modifier)) + .1f
|
||||
}
|
||||
|
||||
/** This code returns a positive value if the city is significantly far away from the capital
|
||||
* 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
|
||||
|
Reference in New Issue
Block a user