Skip to content

Commit

Permalink
Update AI trading logic (#12305)
Browse files Browse the repository at this point in the history
* AI behaviour changes

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update ConstructionAutomation.kt

* Update Automation.kt

* Reverting some changes

* Changes

* revert changes

* revert changes

* revert changes

* revert changes

* Update CityLocationTileRanker.kt

* Citizen assignment for stat conversion

* Update CityLocationTileRanker.kt

* Reduce AI settling

* Avoid AI building units when in negative Supply

* Update CityLocationTileRanker.kt

* Update CityLocationTileRanker.kt

* Update CityLocationTileRanker.kt

* Update ConstructionAutomation.kt

* Update build.gradle.kts

* Update gradle-wrapper.properties

* Update CityLocationTileRanker.kt

* Update CityLocationTileRanker.kt

* Update ConstructionAutomation.kt

* Update CityLocationTileRanker.kt

* AI changes for humans

* Fix puppet focus

* Update Automation.kt

* Puppet focus

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update Automation.kt

* Update Stats.kt

* Update CityTurnManager.kt

* Remove specialist science modifier

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update CivilianUnitAutomation.kt

* Update ReligionAutomation.kt

* Worker prioritization

Workers are valuable in expand cities.

* Update ConstructionAutomation.kt

Food always important, it's rarely good to skip e.g. granary if we're on 6 pop.

* Update ConstructionAutomation.kt

Should achieve about the same with less lines of code.

* Update Automation.kt

* Update ConstructionAutomation.kt

* Update Policies.json

* Update Policies.json

* Update Policies.json

* Update ConstructionAutomation.kt

* Update Policies.json

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Rename Crop Yield to Growth

* Update worker usage

* Update UnitAutomation.kt

* Tutorials update

* Update Tutorials.json

* Fix spelling error

* Update Tutorials.json

* Update Tutorials.json

* Update Tutorials.json

* Update Tutorials.json

* Update Tutorials.json

* Update Tutorials.json

* Update Tutorials.json

* Update Tutorials.json

* AI tech and policy choices

* Update Techs.json

* Update Policies.json

* Update ConstructionAutomation.kt

* Update UnitPromotions.json

* Update

* Update Policies.json

* Update Tutorials.json

* ReligionAutomation bugfix

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update ReligionAutomation.kt

* Update AI city settling and science game

* Update ReligionAutomation.kt

* Maybe revert this now the belief picking has improved

* Update ReligionAutomation.kt

* Remove some if-statements

* Update Automation.kt

* Update Automation.kt

* Update ConsoleLauncher.kt

* Update

* Update Automation.kt

* Update TileImprovements.json

* Update AI trading

* Update TradeAutomation.kt
  • Loading branch information
EmperorPinguin authored Oct 20, 2024
1 parent 74806e8 commit e60873d
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@ object TradeAutomation {
* guaranteed to find the best or closest one. */
private fun getCounteroffer(civInfo: Civilization, tradeRequest: TradeRequest): TradeRequest? {
val otherCiv = civInfo.gameInfo.getCivilization(tradeRequest.requestingCiv)
// AIs counteroffering each other is problematic as they tend to ping-pong back and forth forever
if (otherCiv.playerType == PlayerType.AI)
return null
// AIs counteroffering each other could be problematic if they ping-pong back and forth forever
// If this happens, that means our trade automation doesn't settle into an equilibrium that's favourable to both parties, so that should be updated when observed
val evaluation = TradeEvaluation()
var deltaInOurFavor = evaluation.getTradeAcceptability(tradeRequest.trade, civInfo, otherCiv, true)
if (deltaInOurFavor > 0) deltaInOurFavor = (deltaInOurFavor / 1.1f).toInt() // They seem very interested in this deal, let's push it a bit.
Expand All @@ -75,7 +74,8 @@ object TradeAutomation {
continue // For example resources gained by trade or CS
if (offer.type == TradeOfferType.City)
continue // Players generally don't want to give up their cities, and they might misclick

if (offer.type == TradeOfferType.Luxury_Resource)
continue // Don't ask for luxuries as counteroffer, players likely don't want to sell them if they didn't offer them already
if (tradeLogic.currentTrade.theirOffers.any { it.type == offer.type && it.name == offer.name })
continue // So you don't get double offers of open borders declarations of war etc.
if (offer.type == TradeOfferType.Treaty)
Expand Down
14 changes: 8 additions & 6 deletions core/src/com/unciv/logic/trade/TradeEvaluation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ class TradeEvaluation {
private fun evaluateBuyCost(offer: TradeOffer, civInfo: Civilization, tradePartner: Civilization, trade: Trade): Int {
when (offer.type) {
TradeOfferType.Gold -> return offer.amount
// GPT loses 1% of value for each 'future' turn, meaning: gold now is more valuable than gold in the future
TradeOfferType.Gold_Per_Turn -> return (1..offer.duration).sumOf { offer.amount * 0.99.pow(it) }.toInt()
// GPT loses value for each 'future' turn, meaning: gold now is more valuable than gold in the future
// Empire-wide production tends to grow at roughly 2% per turn (quick speed), so let's take that as a base line
// Formula could be more sophisticated by taking into account game speed and estimated chance of the gpt-giver cancelling the trade after X amount of turns
TradeOfferType.Gold_Per_Turn -> return (1..offer.duration).sumOf { offer.amount * 0.98.pow(it) }.toInt()
TradeOfferType.Treaty -> {
return when (offer.name) {
// Since it will be evaluated twice, once when they evaluate our offer and once when they evaluate theirs
Expand Down Expand Up @@ -332,11 +334,11 @@ class TradeEvaluation {
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
// To visualise the function, plug this into a 2d graphing calculator \frac{1000}{x^{1.2}+1.66*1000}
// Goes from 1 at GPT = 0 to .923 at GPT = 100, .577 at GPT = 1000 and 0.415 at GPT = 10000
// The current value of gold will never go below 40%, or the .4f that it is set to (being roughly the efficiency ratio between purchasing and upgrading units)
// So this does not scale off to infinity
return modifier / (goldPerTurn.coerceAtLeast(1.0).pow(1.2) + (1.11 * modifier)) + .1
return modifier/ (goldPerTurn.coerceAtLeast(1.0).pow(1.2) + (1.66 * modifier)) + .4
}

/** This code returns a positive value if the city is significantly far away from the capital
Expand Down

0 comments on commit e60873d

Please sign in to comment.