From e814628eaff28b05baa39b782a3abbb84ca77b9d Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Thu, 1 Feb 2024 04:43:00 +0200
Subject: [PATCH 35/35] Keep track of world peace start turn

See RM #219

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 common/game.c                |  3 ++-
 common/game.h                |  1 +
 server/savegame/savecompat.c | 13 +++++++++
 server/savegame/savegame2.c  |  1 +
 server/savegame/savegame3.c  |  3 +++
 server/srv_main.c            | 51 +++++++++++++++++++++++++++++++++---
 6 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/common/game.c b/common/game.c
index 63ca6d9784..f422805a1c 100644
--- a/common/game.c
+++ b/common/game.c
@@ -306,7 +306,7 @@ static void game_defaults(bool keep_ruleset_value)
   game.info.trading_gold     = GAME_DEFAULT_TRADING_GOLD;
   game.info.trading_tech     = GAME_DEFAULT_TRADING_TECH;
   game.info.turn             = 0;
-  game.info.warminglevel     = 0; /* set later */
+  game.info.warminglevel     = 0; /* Set later */
   game.info.year_0_hack      = FALSE;
   game.info.year             = GAME_DEFAULT_START_YEAR;
   game.info.top_cities_count = GAME_DEFAULT_TOP_CITIES_COUNT;
@@ -429,6 +429,7 @@ static void game_defaults(bool keep_ruleset_value)
     game.server.unitwaittime      = GAME_DEFAULT_UNITWAITTIME;
     game.server.plr_colors        = NULL;
     game.server.random_move_time  = NULL;
+    game.server.world_peace_start = 0;
   } else {
     /* Client side takes care of itself in client_main() */
   }
diff --git a/common/game.h b/common/game.h
index 4585c1d0bd..df8ae0c7f2 100644
--- a/common/game.h
+++ b/common/game.h
@@ -235,6 +235,7 @@ struct civ_game {
                           * the server we need to remember the old setting */
       bool last_updated_year; /* last_updated is still counted as year in this
                                * game. */
+      int world_peace_start;
       char rulesetdir[MAX_LEN_NAME];
       char demography[MAX_LEN_DEMOGRAPHY];
       char allow_take[MAX_LEN_ALLOW_TAKE];
diff --git a/server/savegame/savecompat.c b/server/savegame/savecompat.c
index 304489c76f..689993e396 100644
--- a/server/savegame/savecompat.c
+++ b/server/savegame/savecompat.c
@@ -2437,6 +2437,10 @@ static void compat_load_030300(struct loaddata *loading,
 
   secfile_insert_bool(loading->file, FALSE, "map.altitude");
 
+  /* World Peace has never started in the old savegame. */
+  game.info.turn = secfile_lookup_int_default(loading->file, 0, "game.turn");
+  secfile_insert_int(loading->file, game.info.turn, "game.world_peace_start");
+
   {
     int ssa_count;
 
@@ -3324,6 +3328,15 @@ static void compat_load_dev(struct loaddata *loading)
 
     secfile_insert_bool(loading->file, FALSE, "map.altitude");
 
+    /* World Peace has never started in the old savegame. */
+    game.info.turn
+      = secfile_lookup_int_default(loading->file, 0, "game.turn");
+    game.server.world_peace_start
+      = secfile_lookup_int_default(loading->file, game.info.turn,
+                                   "game.world_peace_start");
+    secfile_replace_int(loading->file, game.server.world_peace_start,
+                        "game.world_peace_start");
+
     /* Add actions for unit activities */
     loading->activities.size
       = secfile_lookup_int_default(loading->file, 0,
diff --git a/server/savegame/savegame2.c b/server/savegame/savegame2.c
index 3f31c20117..edf7a4f248 100644
--- a/server/savegame/savegame2.c
+++ b/server/savegame/savegame2.c
@@ -1926,6 +1926,7 @@ static void sg_load_game(struct loaddata *loading)
     = secfile_lookup_int_default(loading->file, 0, "game.turn");
   sg_failure_ret(secfile_lookup_int(loading->file, &game.info.year,
                                     "game.year"), "%s", secfile_error());
+  game.server.world_peace_start = game.info.turn;
   game.info.year_0_hack
     = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
 
diff --git a/server/savegame/savegame3.c b/server/savegame/savegame3.c
index ce5e0c591b..d00c93e728 100644
--- a/server/savegame/savegame3.c
+++ b/server/savegame/savegame3.c
@@ -2181,6 +2181,8 @@ static void sg_load_game(struct loaddata *loading)
     = secfile_lookup_int_default(loading->file, 0, "game.turn");
   sg_failure_ret(secfile_lookup_int(loading->file, &game.info.year,
                                     "game.year"), "%s", secfile_error());
+  sg_failure_ret(secfile_lookup_int(loading->file, &game.server.world_peace_start,
+                                    "game.world_peace_start"), "%s", secfile_error());
   game.info.year_0_hack
     = secfile_lookup_bool_default(loading->file, FALSE, "game.year_0_hack");
 
@@ -2313,6 +2315,7 @@ static void sg_save_game(struct savedata *saving)
 
   secfile_insert_int(saving->file, game.info.turn, "game.turn");
   secfile_insert_int(saving->file, game.info.year, "game.year");
+  secfile_insert_int(saving->file, game.server.world_peace_start, "game.world_peace_start");
   secfile_insert_bool(saving->file, game.info.year_0_hack,
                       "game.year_0_hack");
 
diff --git a/server/srv_main.c b/server/srv_main.c
index ef98756e93..7edf693839 100644
--- a/server/srv_main.c
+++ b/server/srv_main.c
@@ -174,6 +174,8 @@ static void save_all_map_images(void);
 
 static void handle_observer_ready(struct connection *pconn);
 
+static void world_peace_update(void);
+
 /* command-line arguments to server */
 struct server_arguments srvarg;
 
@@ -1760,6 +1762,8 @@ static void end_turn(void)
     } whole_map_iterate_end;
   } extra_type_by_cause_iterate_end;
 
+  world_peace_update();
+
   update_diplomatics();
   make_history_report();
   settings_turn();
@@ -2951,7 +2955,7 @@ static void srv_running(void)
       }
 
       while (server_sniff_all_input() == S_E_OTHERWISE) {
-        /* nothing */
+        /* Nothing */
       }
 
       between_turns = timer_renew(between_turns, TIMER_USER, TIMER_ACTIVE,
@@ -2998,11 +3002,11 @@ static void srv_running(void)
 	/* endturn was reached - rank users based on team scores */
 	rank_users(TRUE);
       } else { 
-	/* game ended for victory conditions - rank users based on survival */
+	/* Game ended for victory conditions - rank users based on survival */
 	rank_users(FALSE);
       }
     } else if (S_S_OVER == server_state()) {
-      /* game terminated by /endgame command - calculate team scores */
+      /* Game terminated by /endgame command - calculate team scores */
       rank_users(TRUE);
     }
   }
@@ -3849,3 +3853,44 @@ static void save_all_map_images(void)
     }
   }
 }
+
+/**********************************************************************//**
+  Does this turn count as world peace turn?
+**************************************************************************/
+static bool world_peace_turn(void)
+{
+  players_iterate_alive(pplayer) {
+    bool contact = FALSE;
+
+    players_iterate_alive(other) {
+      if (pplayer != other) {
+        struct player_diplstate *dstate = player_diplstate_get(pplayer, other);
+
+        if (dstate->type == DS_WAR) {
+          return FALSE;
+        }
+        if (dstate->type != DS_NO_CONTACT) {
+          contact = TRUE;
+        }
+      }
+    } players_iterate_alive_end;
+
+    if (!contact) {
+      /* Peace only because there's nobody to show aggression against does not count. */
+      return FALSE;
+    }
+  } players_iterate_alive_end;
+
+  return TRUE;
+}
+
+/**********************************************************************//**
+  Update world peace data.
+**************************************************************************/
+static void world_peace_update(void)
+{
+  if (!world_peace_turn()) {
+    /* Consecutive world peace turns begin *earliest* after this turn, overwrite older claims. */
+    game.server.world_peace_start = game.info.turn;
+  }
+}
-- 
2.43.0

