mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-21 05:09:25 +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)
|
if (offer.type == TradeType.Treaty)
|
||||||
continue // Don't try to counter with a defensive pact or research pact
|
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)
|
if (value > 0)
|
||||||
potentialAsks[offer] = value
|
potentialAsks[offer] = value
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ object NextTurnAutomation {
|
|||||||
// Remove 1 amount as long as doing so does not change the price
|
// Remove 1 amount as long as doing so does not change the price
|
||||||
val originalValue = counterofferAsks[ask]!!
|
val originalValue = counterofferAsks[ask]!!
|
||||||
while (ask.amount > 1
|
while (ask.amount > 1
|
||||||
&& originalValue == evaluation.evaluateBuyCost(
|
&& originalValue == evaluation.evaluateBuyCostWithInflation(
|
||||||
TradeOffer(ask.name, ask.type, ask.amount - 1, ask.duration),
|
TradeOffer(ask.name, ask.type, ask.amount - 1, ask.duration),
|
||||||
civInfo, otherCiv) ) {
|
civInfo, otherCiv) ) {
|
||||||
ask.amount--
|
ask.amount--
|
||||||
@ -216,7 +216,7 @@ object NextTurnAutomation {
|
|||||||
for (goldAsk in counterofferAsks.keys
|
for (goldAsk in counterofferAsks.keys
|
||||||
.filter { it.type == TradeType.Gold_Per_Turn || it.type == TradeType.Gold }
|
.filter { it.type == TradeType.Gold_Per_Turn || it.type == TradeType.Gold }
|
||||||
.sortedByDescending { it.type.ordinal }) { // Do GPT first
|
.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
|
val amountCanBeRemoved = deltaInOurFavor / valueOfOne
|
||||||
if (amountCanBeRemoved >= goldAsk.amount) {
|
if (amountCanBeRemoved >= goldAsk.amount) {
|
||||||
deltaInOurFavor -= counterofferAsks[goldAsk]!!
|
deltaInOurFavor -= counterofferAsks[goldAsk]!!
|
||||||
@ -236,7 +236,7 @@ object NextTurnAutomation {
|
|||||||
.sortedByDescending { it.type.ordinal }) {
|
.sortedByDescending { it.type.ordinal }) {
|
||||||
if (tradeLogic.currentTrade.theirOffers.none { it.type == ourGold.type } &&
|
if (tradeLogic.currentTrade.theirOffers.none { it.type == ourGold.type } &&
|
||||||
counterofferAsks.keys.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)
|
val amountToGive = min(deltaInOurFavor / valueOfOne, ourGold.amount)
|
||||||
deltaInOurFavor -= amountToGive * valueOfOne
|
deltaInOurFavor -= amountToGive * valueOfOne
|
||||||
if (amountToGive > 0) {
|
if (amountToGive > 0) {
|
||||||
|
@ -6,7 +6,6 @@ import com.unciv.logic.automation.ThreatLevel
|
|||||||
import com.unciv.logic.automation.civilization.NextTurnAutomation
|
import com.unciv.logic.automation.civilization.NextTurnAutomation
|
||||||
import com.unciv.logic.city.City
|
import com.unciv.logic.city.City
|
||||||
import com.unciv.logic.civilization.Civilization
|
import com.unciv.logic.civilization.Civilization
|
||||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
|
||||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||||
import com.unciv.logic.map.tile.Tile
|
import com.unciv.logic.map.tile.Tile
|
||||||
import com.unciv.models.ruleset.ModOptionsConstants
|
import com.unciv.models.ruleset.ModOptionsConstants
|
||||||
@ -73,9 +72,9 @@ class TradeEvaluation {
|
|||||||
|
|
||||||
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 { 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()
|
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.
|
// If we're making a peace treaty, don't try to up the bargain for people you don't like.
|
||||||
@ -95,6 +94,12 @@ class TradeEvaluation {
|
|||||||
return sumOfTheirOffers - sumOfOurOffers
|
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 {
|
fun evaluateBuyCost(offer: TradeOffer, civInfo: Civilization, tradePartner: Civilization): Int {
|
||||||
when (offer.type) {
|
when (offer.type) {
|
||||||
TradeType.Gold -> return offer.amount
|
TradeType.Gold -> return offer.amount
|
||||||
@ -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 {
|
fun evaluateSellCost(offer: TradeOffer, civInfo: Civilization, tradePartner: Civilization): Int {
|
||||||
when (offer.type) {
|
when (offer.type) {
|
||||||
TradeType.Gold -> return offer.amount
|
TradeType.Gold -> return offer.amount
|
||||||
@ -275,7 +286,7 @@ class TradeEvaluation {
|
|||||||
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 + distanceBonus
|
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 -> {
|
TradeType.Agreement -> {
|
||||||
if (offer.name == Constants.openBorders) {
|
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
|
/** 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
|
* 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
|
* 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