Skip to content

Conversation

@unciv-loof
Copy link
Contributor

@unciv-loof unciv-loof commented Oct 17, 2025

Currently the AI will only ever denounce others when they themselves are denounced (as a reflex).

This PR introduces more reasonable AI denunciation automation logic that considers how rapidly their opinion of another civ has dropped, as well as their current relationship. It also has a hook for a denounce willingness personality trait.
It does not copy logic from Civ V, but is an attempt to imitate it.

It measures the change in opinion across multiple turns by keeping a memory of past opinions. This is represented as an exponential average (a single value) that perpetually converges with the current opinion. It can be adjusted to only consider the change in opinion from the previous turn (period=1), or to consider the cumulative opinion drop across multiple turns (period>1).
The smoothing period is currently set to (30 * game speed modifier), but a fixed value can be used if preferred.

The change in opinion, used to determine whether to denounce the other civ, is calculated as the difference between the actual opinion and the smoothed opinion (memory).
smoothing

The opinion change required to denounce another civ is conservatively set to -65 for neutral relationships (opinion=0).
It is higher for adversaries (more likely to denounce), and lower for friends (less likely to denounce).
Screenshot from 2025-10-17 20-57-22

A very low initial value of -250f is set as the smoothed opinion (memory) in savefiles where an already encountered civ does not have a value associated with it. This is primarily relevant for savefiles created prior to this version, to prevent sudden mass denunciations when updating the game.

Denunciation will not happen if at war, if there is an active DoF, or if a previous denunciation is in effect.

Testing:

  • Spectated AI games on medium-huge maps with 4-16 players, prince-immortal difficulties, quick-standard speeds
  • Loaded older savefiles to check for unexpected behavior

Observations:

  • Likely to denounce if someone deploys their first nuke, or multiple broken promises
  • More likely to denounce in the end game (because more volatile relationships)
  • Likely to counter-denounce if on already poor terms

I have placed the smoothed opinion variable in DiplomacyManager, and the logic to determine whether to denounce in DiplomacyAutomation.

Feedback is appreciated.

@unciv-loof
Copy link
Contributor Author

For those with time to test:

  • How does it compare to your experiences from Civ V?
  • Is the broad level of denunciations appropriate?
  • Is the likelyhood of being denounced by a friend appropriate relative to adversaries?

I am aware there are some missing components from Civ V. For example AI denouncing due to constructing a wonder they coveted. Though in that particular case, I would suggest applying the penalty directly to the relationship opinion. This would be easy to implement (just another diplomacy flag), provide transparency to the end user, and be automatically compatible with the denunciation logic in this PR.

@unciv-loof
Copy link
Contributor Author

From my testing, it is working well.

Examples from spectating:

Default game settings:
Turn 175, India denounced iroquis, perhaps from espionage or similar:
image
Turn 200, world at peace:
image
Turn 225, one war, no denunciations:
image
Turn 250, nuke dropped, likely no denunciation because DoF or war:
image
Turn 275, lots of nukes dropped:
image
.
.
.
Large perlin, 8p/16cs, standard speed, emperor difficulty:
Turn 150, Egypt and Huns on poor terms, denounced then war:
image
Turn 200, Egypt destroyed but otherwise world at peace:
image
Turn 250, world still at peace:
image
Turn 300, nukes dropped, multiple denunciations and war:
image

@yairm210
Copy link
Owner

This is a little too involved for me at the moment, I don't have the brainpower for it currently, sorry -_-

@RobLoach
Copy link
Collaborator

Don't know what any of this means, but I applaud your efforts.

@unciv-loof
Copy link
Contributor Author

unciv-loof commented Oct 25, 2025

The TLDR is that it looks at the cumulative opinion drop over multiple turns, and uses that to determine whether to denounce (combined with factors like friendship level).

In case it is unclear, "opinion" is this number:
image

As for the implementation, one approach could be to have an array of the opinions from the last X turns, and then do some math on that, but it is inflexible and requires storing many numbers, so instead I used an exponential moving average.

@unciv-loof
Copy link
Contributor Author

unciv-loof commented Nov 7, 2025

I can make it even more unlikely for the AI to denounce others, if that is preferred when rolling out.

It's not a significant amount of code, so it can be easily replaced or expanded later, such as with PR.

Otherwise please share concerns or criticisms.

@github-actions
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions
Copy link

Conflicts have been resolved.

@yairm210
Copy link
Owner

@SomeTroglodyte If you have time can you take a look at this?


// limit how many civs we can denounce similtaneously
// TODO: replace this with logic to consider consequences of denouncing others
val maxActiveDenunciations = 5
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, it may be better to collect hardcoded (tweakable for balancing) values in a companion as const val... But this - shouldn't it scale somehow with number of civs in the game?

Copy link
Contributor Author

@unciv-loof unciv-loof Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, possibly. This was not part of my original implementation, but I figured I'd add it as a backstop for the known issue in Civ V where the AIs go on a denouncing spree.

My imagined scenario is:

  1. X is an unfriendly warmonger
  2. The world gangs up on (denounces) X
  3. X is angry with everyone because they denounced them
  4. X counter denounces everyone because their poor relationship makes them prone to doing so

I think it is realistic that the world can gang up on a warmonger (not that this will happen often given the currently extremely lax attitudes against warmongering), but not so realistic that the victim denounces everyone in return, as that is detremental to themself. Ideally they should consider the impact of denouncing others, such as by attempting to preserve existing alliances etc., but that might not be so easy to implement.

I think a possible remidy for this could be:
If a civ is denounced by many others, its opinion of each of them doesn't drop by the full 35, but rather some lower value, i.e. they become numb to being denounced.
For example, when they are first denounced, their opinion would drop by 35. The second denunciation might also hurt, but a little less, say 25. Then 20 for the third one, and so on.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they become numb to being deloused

https://en.wikipedia.org/wiki/Comfortably_Numb

@SomeTroglodyte
Copy link
Collaborator

If you have time can you take a look at this?

So much to read... So I did a code inspect pass only first. Haven't read the comments yet. Need to visit doctor now.... later. None of my nags would be gamebreaking though, and I feel 'loof' was thorough and would trust that their balancing produced more pleasing AI behaviour than current code. Which may need rebalancing if my suspicion EMA was done incorrectly holds true.

@SomeTroglodyte
Copy link
Collaborator

All right, collecting my opinion from this thread...

  • Definitely a good idea
  • Even with a borked formula can't be worse than as it is (unchecked prejudice)
  • No game-breaking mistakes - but give OP time to think
  • "A very low initial value of -250f" - umm, is there a lower bound for opinion as there is for city-state influence? If so, use that? Hmmm... I don't believe there is.
  • "constructing a wonder they coveted" -> apply to opinion -> agree
  • "have an array of" -> there's I think 2 precedents currently, though via lack of brainpowah I can't reliably name them - science - and culture? Anyway, EMA as well-known trend detection tool is at least at par - my 🎲 prejudice.
  • "those with time to test - your experiences from Civ V" - nope, have neither 😲 .
  • "can be easily replaced or expanded later" - exactly.

@unciv-loof
Copy link
Contributor Author

unciv-loof commented Nov 10, 2025

Thanks for the comprehensive feedback. Will work through it all, but need some time.

@github-actions
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@unciv-loof unciv-loof marked this pull request as draft November 15, 2025 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants