Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues introduced with the prevention of war declarations if they would break alliances #2239

Closed

Conversation

blabber
Copy link
Collaborator

@blabber blabber commented Mar 26, 2024

Commit ecd275d introduced a change that prevents players from declaring war, if this would break existing alliances. There are two remaining issues:

  • AI will fail to declare war, if entangled in a web of alliances
  • Cease-fires running out, will end in an "undefined" state if war can't be entered because of alliances

To fix this:

  • restore the old behavior for the AI
  • automatically extend cease-fires while the fragile diplomatic state is balanced by alliances

Part of #2177

Commit ecd275d introduced a change that
prevents players from declaring war, if this would break existing
alliances. This works for human players who can react on the
notifications that inform them about the issue. AI however might get
caught in a web of alliances they can't resolve themselves. Restore the
old behaviour for AI player wanting to declare war.

Another change related to this: If you have AI players in your team,
they will break alliances as needed if you declare war, as you can't
coordinate preparations for war on team level with them.

While here: Fix a comment.
server/plrhand.cpp Outdated Show resolved Hide resolved
server/plrhand.cpp Show resolved Hide resolved
server/plrhand.cpp Outdated Show resolved Hide resolved
If a cease-fire runs out and this would break existing alliances, extend
the cease-fire by another four turns. The idea is, that the common
allies convince the parties of the cease-fire to extend the pact.

If one of the parties is an AI, the old behavior will be used unchanged.
AI doesn't know how to cancel alliances to enter war if desired, and
might get caught in an eternal cease-fire.

The extension by four turns is arbitrarily chosen and subject to further
discussion, but extending by only one turn would lead to a constant
stream of notifications about cease-fires about to run out.
@blabber
Copy link
Collaborator Author

blabber commented Mar 27, 2024

I think I figured this out, but I still need to do some test.

I extend cease-fires by four turns, if returning to war would break alliances. Any feedback if this should be changed is appreciated. Extending by only one turn, would cause a constant stream of notifications about cease-fires about to run out.

If anyone has a good name for handle_diplomacy_cancel_pact2 (formerly known as handle_diplomacy_cancel_internal), this would be helpful :)

Rename `handle_diplomacy_cancel_pact2` to
`handle_diplomacy_cancel_pact_explicit`. This is not perfect, but better
than the old name.
If the cease-fire is extended for both parties in the same iteration,
this will lead to inconsistent remaining turn numbers.
@blabber
Copy link
Collaborator Author

blabber commented Mar 29, 2024

I managed to test the automatic extension of cease-fires in a test game and as far as I can tell, this works now. I wasn't able to test the AI, but as we are falling back to the old behavior for AI, this should be okay.

Please feel free to test and comment on the fact, that cease-fires are extended by four turns.

@blabber blabber marked this pull request as ready for review March 29, 2024 23:07
@lmoureaux
Copy link
Contributor

Please feel free to test and comment on the fact, that cease-fires are extended by four turns.

Four turns is a quarter of the normal cease-fire duration. It may be hard for the player to cancel it later if they are in Democracy (or planning to be)...
At the very least this should be a constant defined in diplhand.h next to the cease-fire duration (inappropriately called TURNS_LEFT).

@blabber
Copy link
Collaborator Author

blabber commented Mar 30, 2024

Defining the extension period in a header is file is a good idea, I will definitely do that.

Regarding the number of turns, what was your idea when you created the issue?

Extension by one turn will work, but you will get the according notification every turn. This might not be as big an issue as I thought, as there are lots of notifications every turn in the game I am currently playing anyway.

@lmoureaux
Copy link
Contributor

I was thinking one turn but didn't consider notification spam. Maybe it's good to keep reminding the player, like when a city is in disorder.
Casus belli should also be extended I guess?

@blabber
Copy link
Collaborator Author

blabber commented Mar 30, 2024

Casus belli should also be extended I guess?

Maybe, I don't have enough knowledge about the inner workings of diplomacy to comment on this issue. But I will look into it.

It would help, if you could elaborate a little why you think casus belli should be extended too 😅

While here, get rid of the magic number and define the number of turns
to extend cease-fires in `TURN_EXTEND_CEASEFIRE`.
@blabber
Copy link
Collaborator Author

blabber commented Mar 30, 2024

Successfully tested with cease-fire extension by one turn. Cancelling the blocking alliance drops you into war at TC.

I am still not sure what to do with casus belli. I am not sure how cease-fire and casus belli interact with each other.

@blabber
Copy link
Collaborator Author

blabber commented Mar 30, 2024

At the very least this should be a constant defined in diplhand.h next to the cease-fire duration (inappropriately called TURNS_LEFT).

TURNS_LEFT is not cease-fire specific, but also affects armistice. Therefore a neutral name makes a little more sense.

@lmoureaux
Copy link
Contributor

From a quick inspection of the code, it seems that being at war with one of your allies doesn't provide a casus belli (the Senate will object war declaration). This is a bit weird but understandable: if one player in an alliance isn't subject to the Senate restrictions, this player could declare war at will and their allies simply follow. This would make the senate moot.

Is my interpretation of the code correct? ie given the following players, A can't declare war on C?

A B C
A Democracy Alliance Peace
B (any gov) War
C (any gov)

@blabber
Copy link
Collaborator Author

blabber commented Mar 31, 2024

I am a little confused. It seems you are reasoning about code I haven't touched? I kept all the checks regarding war declarations in place and added the alliance check after all other checks have returned without objecting the war declaration. The rules I implement are agnostic about the government type.

It follows a description of the implemented rules. I think they are not too complicated, but difficult to explain. If we are concerned that players are having problems with these rules, this functionality could be made configurable.

If we want to make this configurable, I would need a few more hints on how to implement this.

War declaration

A B C
A Alliance
B Alliance Alliance
C Alliance

A can't declare war against C, as it would

  1. break the alliance with B, if B is not As teammate
  2. force B to break its alliance with C, if B is As teammate

Exception: if B is As teammate and an AI, it will break the alliance with C if this allows A to declare war.

Cease-Fire

A B C
A Cease-Fire Alliance
B Cease-Fire Alliance
C Alliance Alliance

When the cease-fire between A and B runs out, it will extended by another turn, to protect the alliances with C. As soon as A or B cancels the alliance with C (or vice-versa), the cease-fire will actually run out at TC and they'll drop into war. This applies only, if A and B are human players.

@lmoureaux
Copy link
Contributor

I am a little confused. It seems you are reasoning about code I haven't touched?

I am a bit confused as well :D The level of entanglement in these situations doesn't make things easy. Casi belli are events that allow cancelling treaties despite the Senate. For instance spies poisoning cities. Maybe also launching a spaceship.

My concern is that the game might give a casus belli to one of the players when the cease-fire runs out (or someone declares war). If we forcefully keep the cease-fire running, the casus belli might not appear again. This might prevent a war declaration that would have been possible otherwise.

Now looking at the code I couldn't find a casus belli generated when someone declares war, which I find weird but it seems to be this way. So what I described is probably not happening.

@blabber
Copy link
Collaborator Author

blabber commented Apr 1, 2024

I tried to make sense out of the casus belli related code, but I guess I will need some more time to make sense out of it...

But the Freeciv help documents that a casus belli is provided if

An alliance is broken due to a war between a player's allies (given until turn end to the side(s) you break alliance with).

Breaking alliances due to a war is exactly what my code tries to prevent. On the other hand cancelling an alliance and declaring war afterwards seems not to provide a casus belli, therefore cautious players could already avoid this casus belli.

@blabber blabber marked this pull request as draft April 5, 2024 21:33
@blabber
Copy link
Collaborator Author

blabber commented Apr 5, 2024

After reverting the commit on which these changes were based, I will close this PR and open another on containing the whole changeset.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants