Skip to content

Commit

Permalink
Fix asymmetric turns_left when auto canceling
Browse files Browse the repository at this point in the history
an alliance to two players because their cease fire expired to war.

Reported by Marko Lindqvist <cazfi>

See bug #24033

[[originally from svn r30536]]
  • Loading branch information
kvilhaugsvik committed Nov 11, 2015
1 parent 2166b22 commit c5f83a9
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
1 change: 1 addition & 0 deletions common/player.c
Expand Up @@ -287,6 +287,7 @@ static void player_diplstate_defaults(const struct player *plr1,
diplstate->turns_left = 0;
diplstate->has_reason_to_cancel = 0;
diplstate->contact_turns_left = 0;
diplstate->auto_cancel_turn = -1;
}


Expand Down
2 changes: 2 additions & 0 deletions common/player.h
Expand Up @@ -192,6 +192,8 @@ struct player_diplstate {
int turns_left; /* until pact (e.g., cease-fire) ends */
int has_reason_to_cancel; /* 0: no, 1: this turn, 2: this or next turn */
int contact_turns_left; /* until contact ends */

int auto_cancel_turn; /* used to avoid asymmetric turns_left */
};

/***************************************************************************
Expand Down
34 changes: 31 additions & 3 deletions server/srv_main.c
Expand Up @@ -757,7 +757,10 @@ static void update_diplomatics(void)
state->has_reason_to_cancel = MAX(state->has_reason_to_cancel - 1, 0);
state->contact_turns_left = MAX(state->contact_turns_left - 1, 0);

if (state->type == DS_ARMISTICE) {
if (state->type == DS_ARMISTICE
/* Don't count down if auto canceled this turn. Auto canceling
* happens in this loop. */
&& state->auto_cancel_turn != game.info.turn) {
state->turns_left--;
if (state->turns_left <= 0) {
state->type = DS_PEACE;
Expand Down Expand Up @@ -807,16 +810,41 @@ static void update_diplomatics(void)
if (plr3 != plr1 && plr3 != plr2
&& pplayers_allied(plr3, plr1)
&& pplayers_allied(plr3, plr2)) {
struct player_diplstate *to1
= player_diplstate_get(plr3, plr1);
struct player_diplstate *from1
= player_diplstate_get(plr1, plr3);
struct player_diplstate *to2
= player_diplstate_get(plr3, plr2);
struct player_diplstate *from2
= player_diplstate_get(plr2, plr3);

notify_player(plr3, NULL, E_TREATY_BROKEN, ftc_server,
_("The cease-fire between %s and %s has run out. "
"They are at war. You cancel your alliance "
"with both."),
player_name(plr1),
player_name(plr2));
player_diplstate_get(plr3, plr1)->has_reason_to_cancel = TRUE;
player_diplstate_get(plr3, plr2)->has_reason_to_cancel = TRUE;

/* Cancel the alliance. */
to1->has_reason_to_cancel = TRUE;
to2->has_reason_to_cancel = TRUE;
handle_diplomacy_cancel_pact(plr3, player_number(plr1), CLAUSE_ALLIANCE);
handle_diplomacy_cancel_pact(plr3, player_number(plr2), CLAUSE_ALLIANCE);

/* Avoid asymmetric turns_left for the armistice. */
to1->auto_cancel_turn = game.info.turn;
from1->auto_cancel_turn = game.info.turn;

to2->auto_cancel_turn = game.info.turn;
from2->auto_cancel_turn = game.info.turn;

/* Count down for this turn. */
to1->turns_left--;
from1->turns_left--;

to2->turns_left--;
from2->turns_left--;
}
} players_iterate_alive_end;
break;
Expand Down

0 comments on commit c5f83a9

Please sign in to comment.