Advanced Civ

In my last game, I found that AIs cancel resources trade deals very often, to a degree of disrupting game flows. [...] Could this behavior be made less frequent and/or more natural? For example, with some probabilities/uncertainties for cancelling resources trades. Thanks.
Maybe implementing a negligibly threshold might do the trick, say if the re-evaluation of a deal deviates less than 10% from the existing deal, just leave it as is.
Both approaches are already implemented (since v0.95 I think or even earlier). All the same, I also recall seeing the AI cancel trades only to ask for an extra 1 or 2 gold. @Bestban: Is that what usually happened in your game? Or did they refuse to trade some of the resources involved? How many players were there?

I fully agree with the sentiment that the AI shouldn't minmax its trades at the expense of the game flow. Actually, I even put a comment to that effect in the cancellation code:
Spoiler :
Code:
if (iChange < 0)
{
   //return (iTheirValue * 110 >= iOurValue * 100);
   // <advc.133> Always 125 in K-Mod
   int iTolerance = (bHuman ? 145 : 155) - std::min(35, iDealAge);
   // <advc.155>
   if(bSameTeam)
   {
      if(iTheyReceive < iThreshold)
         return true;
      iTolerance = 150;
   } // </advc.155>
   if(iTolerance * // </advc.133>
         iWeReceive >= iTheyReceive * 100) // K-Mod
      return true;
   /*  <advc.036> Need to make trades more stable in large games,
       even to the detriment of the AI. But mustn't cling to a bad deal
       indefinitely -> randomize it. */
   if(!bHuman)
      return false;
   double prCancel = (0.025 * iTolerance) /
         (GET_TEAM(kPlayer.getTeam()).getHasMetCivCount() *
         iTheyReceive / (double)iWeReceive);
   return (prCancel < ::hash(g.getGameTurn(), getID()));
   // </advc.036>
}
Maybe I just need to tweak the numbers a bit.
Not sure if this is new, since I just had my first AdvCiv game completed. An enlarged map by this change for Replay does look very nice :thumbsup:.
I've added that just recently after seeing Kjotleik's post here. I had been thinking about enlarging more screens but somehow never thought of the replay screen. Good to know that it's working correctly on another person's monitor.
Another thing that bugs me for a long time: I often use CTRL + H to select wounded units from a stack, which doesn't work when there are air or sea units on the same tile. This is an old bug also happening in vanilla, but maybe you care to fix this anyway?
It doesn't sound difficult. The desired behavior is that all wounded units with the same domain type (land/ sea/ air) as the currently selected unit(s) become selected?
 
I've added that just recently after seeing Kjotleik's post here. I had been thinking about enlarging more screens but somehow never thought of the replay screen. Good to know that it's working correctly on another person's monitor.
For what it's worth, I have recently added full-screen capabilities to some screens in my BUG-based mod.
(It's not as clean as I would like yet, and I also just realized I messed up the commit order and messages - the correct (and necessary) InterfaceUtils.py doesn't appear until the third commit)

Here are the commits, in case it helps:
Tech Advisor
Tech Advisor again (InterfaceUtils.py incomplete)
Civic Advisor (InterfaceUtils.py now correct)
Victory and Finance Advisors, some mod-specific stuff
Sevopedia
 
Have not read the full code, but shouldn't this be the other way round, like iTolerance * iWeReceive <= iTheyReceive * 100 ?
Code:
   if(iTolerance * // </advc.133>
         iWeReceive >= iTheyReceive * 100) // K-Mod

It doesn't sound difficult. The desired behavior is that all wounded units with the same domain type (land/ sea/ air) as the currently selected unit(s) become selected?

yes, exactly. This bugs me since the release of BTS....
 
Have not read the full code, but shouldn't this be the other way round, like iTolerance * iWeReceive <= iTheyReceive * 100 ?
I should've mentioned the function name; it's CvPlayerAI::AI_considerOffer, i.e. the same function is used for deciding whether to accept a trade (iChange positive) and whether to continue a trade (iChange negative), and, in the latter case, returning true means continue and false means cancel. So if we (the AI) inflate the value of what we receive and the result is at least as good as what they receive, then we don't cancel the trade. I hope that makes sense; these inequations really are error-prone.

Ctrl+H: Done. But it could be some time until I can deploy the bugfix. :(
 
So if we (the AI) inflate the value of what we receive and the result is at least as good as what they receive, then we don't cancel the trade. I hope that makes sense; these inequations really are error-prone.

That makes perfect sense. hmmm. Maybe 10%-20% tolerance is too still too low. Given a trade value of 5 (9) gold, 6 (11) gold obviously exceeds 20%, but still, to a human player the difference is probably negligible. But I don't know how iWeReceive and iTheyReceive value are scaled...

Ctrl+H: Done. But it could be some time until I can deploy the bugfix. :(

Thank you so much for this! And no rush.
 
For what it's worth, I have recently added full-screen capabilities to some screens in my BUG-based mod. [...] Here are the commits, in case it helps:
If an advisor screen doesn't use the additional space, then I'd rather show more of the HUD. The BtS tech tree has at most 7 techs per column, so it fits into the BUG widescreen dimensions. The BtS civics, finances and victory info also fit snugly. Sevopedia I've already enlarged this spring (commit 1 2). One could find uses for extra space of course and having a full-screen option would be nice in any case, also for mod-mods. E.g. keldath's DotO adds some rows for special religion techs to the Tech Advisor. For the moment, I'll just bookmark those BitBucket links. Handling the size settings and window decorations in an abstract class is obviously a good thought. I'll probably want to use that when I enlarge another screen. (Military Advisor could use more space and shouldn't be too difficult to enlarge.)

I hadn't even been aware of the MNAI repository. I'll keep an eye on that too. I've just skimmed through the entire history and bookmarked 100 or so commits that sounded like they could be applicable to the BtS rules. For most of those, I'll probably (hopefully I guess) find out quickly that they don't apply after all, are superseded by K-Mod/AdvCiv changes or by each other or just more trouble than they're worth. Still, I expect that there'll be some things I can adopt. Some changes that I made, I've noticed, MNAI had made years earlier.

Speaking of keldath ...
Well just thought id mention the pop up, its realy fine.
Thanks for giving word. :)
Maybe 10%-20% tolerance is too still too low. Given a trade value of 5 (9) gold, 6 (11) gold obviously exceeds 20%, but still, to a human player the difference is probably negligible. But I don't know how iWeReceive and iTheyReceive value are scaled...
Thanks for taking a look at this. Having another pair of eyes on the code will sometimes reveal silly mistakes.

If a human player is paying 5 gold for a resource that the AI thinks is worth 6, then iWeReceive is 10 and iTheyReceive 12. (For gold, the AI evaluation simply doubles the value.) So if iTolerance is at least 120, the AI won't cancel that trade (in theory). iTolerance currently starts at 145 and decreases by 1 with each turn since the signing of the deal down to a lower bound of 110. So after 26 turns, the AI will consider (probabilistically) canceling the trade. If iTheyReceive is 14 (AI will ask for 2 more gold), then iTolerance would have to be 140 to continue the trade, i.e. the AI will cancel with a per-turn probability of 34% as soon as the forced 10 turns are over if we assume that the human player has met 7 rivals. All that seems a bit too strict, so I do think that the initial tolerance value should be increased a bit, but I'm not convinced that this is the main issue.

It's possible that the AI evaluation of resources is jittery; the randomization should cushion that. However, once the trade value of a resource drops below a threshold, about the equivalent of 2 gold per turn I think, the AI becomes unwilling to accept that resource at all. The AI also becomes unwilling to give a nonsurplus resource away when approaching the health/ happiness cap in it's own cities. In that case, there is no delay through randomization, but it could be added (in CvPlayerAI::AI_checkCancel I guess).

Edit: punctuation
 
Last edited:
If a human player is paying 5 gold for a resource that the AI thinks is worth 6, then iWeReceive is 10 and iTheyReceive 12. (For gold, the AI evaluation simply doubles the value.) So if iTolerance is at least 120, the AI won't cancel that trade (in theory). iTolerance currently starts at 145 and decreases by 1 with each turn since the signing of the deal down to a lower bound of 110. So after 26 turns, the AI will consider (probabilistically) canceling the trade.

I agree, this seems a bit too strict, because this basically means that the AI will cancel such a deal after about 30 turns, although for an "average" human the difference between 5 and 6 gold is barely worth mentioning.

It's possible that the AI evaluation of resources is jittery; the randomization should cushion that.
Can't say whether there's an issue in resource evaluation, but I doubt the randomization changes that much (if the probability is .34 and it is evaluated each turn). Binomial distribution says that this adds a delay rarely exceeding 5 turns.
 
Is that what usually happened in your game? Or did they refuse to trade some of the resources involved?
Yes. Those AIs that showed up were looking to cancel the deals I proposed before. Those resources deals were already benefiting more for AIs, compared with what I got, not fair trades for me already. I had to pay more to them to be accepted; still they came to cancel them. Also, it happened once that the same AI on the same turn cancelled multiple deals, each with separate trade window popups. For example, cancelling 3 deals with 3 different window popups on the same turn.
How many players were there?
It was a Standard Map size with the default number of players, e.g. 8 if I'm correct.
double prCancel = (0.025 * iTolerance) / ...
More Tolerance results in more cancellations?
:confused: I'm unfamiliar with Civ4/AdvCiv code and could be wrong; feel free to correct this one and those below.
double prCancel = ... / (... * iTheyReceive / ...);
They receive more; then fewer cancellations?
double prCancel = ... / (... / (double)iWeReceive);
We receive more; then we'll cancel more? :cry:
::hash(g.getGameTurn(), getID())
What does this returned hash value mean, against the prCancel?

:) Also, it would be nice if a relation weight can be considered in the resource trades as well in the future. Thanks.
 
I agree, this seems a bit too strict, because this basically means that the AI will cancel such a deal after about 30 turns, although for an "average" human the difference between 5 and 6 gold is barely worth mentioning.
I figure that a resource deal won't normally last much longer than 30 turns anyway because of changes in circumstances on either side. That's also a matter of the game speed setting though, so, yeah, I shouldn't needlessly put this kind of expiration date on a deal that is, essentially, fair. I'm thinking of simply adding 10 percentage points to the initial tolerance. That way, the lower bound will be 120 and the 5-vs-6 gold deal will never cross it. It also occurs to me that the "volumes" of resource trades don't increase as steeply as the total income over the course of a game. I.e. in the early game, 5 gold for a resource might be typical and 20% of that could be worth haggling over, but, in the late game, 20% of, say, 15 gold is negligible. So I guess one should also set the trade values in relation to the per-turn commerce of the AI. Game speed adjustment could also make sense; e.g. divide the age of the deal by the Golden Age modifier (200% on Marathon, 125% on Epic).
Can't say whether there's an issue in resource evaluation, but I doubt the randomization changes that much (if the probability is .34 and it is evaluated each turn). Binomial distribution says that this adds a delay rarely exceeding 5 turns.
I agree that it's too high in this case; though even a 34% chance could help against brief fluctuations in the trade value.
[...] I had to pay more to them to be accepted; still they came to cancel them. [...] It was a Standard Map size with the default number of players, e.g. 8 if I'm correct.
Thanks. Sounds like the code I posted is indeed the problem then.
I'm unfamiliar with Civ4/AdvCiv code and could be wrong; [...]
I think you're right. :blush:
Ditto. Maybe the main mistake is the variable name. I think it's really the probability of continuing the trade. In that case, HasMetCivCounter needs to be inverted though ... Well, I'm sure I can get the logic right on a second attempt. Sorry about the confusion.
What does this returned hash value mean, against the prCancel?
The hash is a floating point number between 0 and 1. I use that instead of a random number so that checking for cancellation several times during one turn doesn't result in a higher overall probability. Actually, I don't think cancellation is ever checked more than once per turn, so I should probably just use a random number.
Also, it would be nice if a relation weight can be considered in the resource trades as well in the future. Thanks.
There are attitude thresholds (mostly for strategic resources) and the amount of gold that the AI makes available for trade is based on relations. But I don't think the resource trade value computation is based on relations, and perhaps it should be. Same for technologies I guess. For war trades, relations already matter. I wouldn't want to discourage trade with disgruntled AI civs too much though because that would contribute to cementing relations.
Also, it happened once that the same AI on the same turn cancelled multiple deals, each with separate trade window popups. For example, cancelling 3 deals with 3 different window popups on the same turn.
Would be nice to collate that into a single popup. But it bit painful to implement it seems. Hopefully, the popups are less of an issue once the cancellation conditions are tweaked.
 
If an advisor screen doesn't use the additional space, then I'd rather show more of the HUD.
That's fair. In Fall from Heaven, the tech tree is much taller and the civics have longer descriptions (on the other hand, the finance advisor certainly doesn't need the extra space). Although, to be honest, to me it is also an aesthetic decision, as the advisor "windows" just look better in full-screen IMO. One player reported they dislike the look of it so much that they play in lower resolution (than the actual resolution of their screen), which horrified me enough to start looking into it.

EDIT
(Military Advisor could use more space and shouldn't be too difficult to enlarge.)
Looks like I missed that commit
 
I'm thinking of simply adding 10 percentage points to the initial tolerance.

Sounds reasonable. Game speed adjustment also makes sense (I actually thought that all game-turn modifiers are game-speed adjusted).

So I guess one should also set the trade values in relation to the per-turn commerce of the AI.

This would have the effect that larger AIs assign different trade values compared to smaller AIs, which is probably not intended.
 
This would have the effect that larger AIs assign different trade values compared to smaller AIs, which is probably not intended.

But it's actually good. If you have 40 cities, 15 of them unhealthy, a health point is worth a heck of a lot more than the 6gpt the AI will offer.
Either in the form of more cash, or giving me (the smaller civ) several resources in return.

Every unhealthiness point eliminated by a trade should be worth at least 1gpt. Include buildings in that, so Rice would be worth more than Fish when you have Granaries but not Harbors.

And I don't know if the AI considers goodwill at all. Does a civ charge more if it's Annoyed with you? Give you a discount for Pleased?
 
Last edited:
Finally got around to updating the formula: Git commit
It's no less arcane than before, but at least all the factors should be on the correct side of the fraction bar, and the probabilities looked sensible in the few tests I did. In the 5 vs. 7 gold example (assuming 7 civs met, Normal speed), the AI code will – if it indeed works like my Excel sheet – cancel the deal with a 10% per-turn probability if the AI civ's per-turn income in terms of gold plus research is less than ca. 120. If the income is higher, the deal will certainly continue. 5 vs. 6 should never be canceled (regardless of income). We'll have to see if this actually fixes the problem of frivolous renegotiations.
Game speed adjustment also makes sense (I actually thought that all game-turn modifiers are game-speed adjusted)
Diplomacy isn't speed-adjusted at all in BtS as far as I'm aware. Obviously, peace treaties last 10 turns on all game speed setting. I'm applying a slight adjustment to the decay of AI memory/ treaty counters (e.g. "you declared war on us", "years of peace"). Contact frequencies (ContactRand, ContactDelay) should arguably also be adjusted; currently they aren't. That ties in with the recent discussion about annoying AI trade offers.
So I guess one should also set the trade values in relation to the per-turn commerce of the AI.
This would have the effect that larger AIs assign different trade values compared to smaller AIs, which is probably not intended.
I've expressed myself badly. "Put it in relation" I meant. I.e. the income affects only the cancellation probability, not the trade value.
But it's actually good. If you have 40 cities, 15 of them unhealthy, a health point is worth a heck of a lot more than the 6gpt the AI will offer.
Either in the form of more cash, or giving me (the smaller civ) several resources in return. Every unhealthiness point eliminated by a trade should be worth at least 1gpt. Include buildings in that, so Rice would be worth more than Fish when you have Granaries but not Harbors.
That evaluation is already in place, including buildings. Functions CvPlayerAI::AI_bonusTradeVal, AI_bonusVal, AI_baseBonusVal in case that someone wants to scrutinize that; it's a lot of code though. I suspect (hope) that this change is the cause of this behavior:
[...] Those resources deals were already benefiting more for AIs, compared with what I got, not fair trades for me already. I had to pay more to them to be accepted [...].
The prices that the AI pays and charges for resources aren't only based on the need of the recipient though; the prices also reflect that surplus resources are of no value to the seller – apart from selling to a different buyer. The number of potential buyers is taken into account. Still, 6 gold per turn for a health resource needed in 15 cities isn't the intended behavior.
And I don't know if the AI considers goodwill at all. Does a civ charge more if it's Annoyed with you? Give you a discount for Pleased?
Not for resources, technologies and civic/religion changes. For war trades, brokered peace and embargoes, attitude matters. I think, in BtS, the attitude toward the broker does actually not matter. The philosophy seems to be that attitude affects only the willingness to trade (including the amount of gold available for trade). So, I've changed that for the three-party trades and should probably also add a slight attitude adjustment to the trade value for technologies, resources and (work in progress) cities.
 
[...] the advisor "windows" just look better in full-screen IMO. One player reported they dislike the look of it so much that they play in lower resolution (than the actual resolution of their screen), which horrified me enough to start looking into it.
I still have a pretty small monitor (1280x1024), so I may underestimate how bad it looks on larger ones. When treating an advisor screen as a window, it should help to use the same frame and dimensions as the Inland Advisor (screenshot attached): This is more of a note to myself; I think your approach of maximizing most screens is perfectly reasonable.
(Military Advisor could use more space and shouldn't be too difficult to enlarge.)
Looks like I missed that commit
Thanks. I was going to adopt that right away, but then remembered that I also wanted to adopt something from the PlatyUI Military Advisor. I'm attaching a screenshot (sorry about the ugly annotation). That complicates the task of overhauling the Military Advisor a bit.
 

Attachments

  • inland-advisor.jpg
    inland-advisor.jpg
    145 KB · Views: 113
  • platy military advisor.jpg
    platy military advisor.jpg
    97.6 KB · Views: 114
i would highly recommend using platy's ui rather than some of bugs.
you know that already from me, maybe have it optional as i did (sort of)
i love his civics and religion screens.
Yup, those are the two screens that I'd like to include just as they are in PlatyUI. I'd like to keep the BUG Religion Advisor as an option though. And Platy's Dawn-of-Man screen has potential. I'm attaching a mockup of what it should look like imo. And some Platy screenshots (never mind the annotations).

Regarding tech and resource trade values based on relations, upon further reflection, that may not be the best approach. Tech and resources tend to be traded in kind. Adjusting the trade value to attitude means that an AI civ will have to pay extra if it likes its AI trade partner better than vice versa. In a real negotiation, that would seem like difficult position to take. It might be better to assign a higher trade value to gold when it comes from a civ that the recipient likes. In itself, that doesn't make much sense either, but, indirectly, it would make it cheaper to purchase tech from a friendly civ than from a pleased civ.
 

Attachments

  • DoM-mockup.jpg
    DoM-mockup.jpg
    135.6 KB · Views: 114
  • platy DoM.jpg
    platy DoM.jpg
    114.6 KB · Views: 209
  • platy religion advisor.jpg
    platy religion advisor.jpg
    117.4 KB · Views: 119
  • platy corporation advisor.jpg
    platy corporation advisor.jpg
    81.9 KB · Views: 125
Back
Top Bottom