From 9568d13d6038235bda3b1cb5fde4c97d7bdaa1b7 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Thu, 26 May 2022 00:17:29 +0300
Subject: [PATCH 22/22] Sanity check research->techs_researched from savegame

See osdn #44595

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 common/research.c           | 17 +++++++++++++++++
 common/research.h           |  2 ++
 server/savegame/savegame2.c | 10 ++++++++++
 server/savegame/savegame3.c | 10 ++++++++++
 4 files changed, 39 insertions(+)

diff --git a/common/research.c b/common/research.c
index 2fbf6f5d41..f52adec14f 100644
--- a/common/research.c
+++ b/common/research.c
@@ -1306,3 +1306,20 @@ struct iterator *research_player_iter_init(struct research_player_iter *it,
 
   return base;
 }
+
+/************************************************************************//**
+  Return recalculated number of techs researched. Useful for
+  sanity checking techs_researched counter.
+****************************************************************************/
+int recalculate_techs_researched(const struct research *presearch)
+{
+  int techs = 1; /* A_NONE known, and not part of below iteration */
+
+  advance_iterate(A_FIRST, t) {
+    if (research_invention_state(presearch, advance_number(t)) == TECH_KNOWN) {
+      techs++;
+    }
+  } advance_iterate_end;
+
+  return techs + presearch->future_tech;
+}
diff --git a/common/research.h b/common/research.h
index 2f8797787e..718f843031 100644
--- a/common/research.h
+++ b/common/research.h
@@ -171,6 +171,8 @@ struct iterator *research_player_iter_init(struct research_player_iter *it,
                   _presearch)
 #define research_players_iterate_end generic_iterate_end
 
+int recalculate_techs_researched(const struct research *presearch);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/server/savegame/savegame2.c b/server/savegame/savegame2.c
index 6257e1f50c..870b9e4485 100644
--- a/server/savegame/savegame2.c
+++ b/server/savegame/savegame2.c
@@ -5227,6 +5227,8 @@ static void sg_load_sanitycheck(struct loaddata *loading)
 
   /* Check researching technologies and goals. */
   researches_iterate(presearch) {
+    int techs;
+
     if (presearch->researching != A_UNSET
         && !is_future_tech(presearch->researching)
         && (valid_advance_by_number(presearch->researching) == NULL
@@ -5246,6 +5248,14 @@ static void sg_load_sanitycheck(struct loaddata *loading)
              research_name_translation(presearch));
       presearch->tech_goal = A_UNSET;
     }
+
+    techs = recalculate_techs_researched(presearch);
+
+    if (presearch->techs_researched != techs) {
+      log_sg(_("%s had finished researches count wrong."),
+             research_name_translation(presearch));
+      presearch->techs_researched = techs;
+    }
   } researches_iterate_end;
 
   players_iterate(pplayer) {
diff --git a/server/savegame/savegame3.c b/server/savegame/savegame3.c
index 25f5126e10..97dcbe301d 100644
--- a/server/savegame/savegame3.c
+++ b/server/savegame/savegame3.c
@@ -7563,6 +7563,8 @@ static void sg_load_sanitycheck(struct loaddata *loading)
 
   /* Check researching technologies and goals. */
   researches_iterate(presearch) {
+    int techs;
+
     if (presearch->researching != A_UNSET
         && !is_future_tech(presearch->researching)
         && (valid_advance_by_number(presearch->researching) == NULL
@@ -7582,6 +7584,14 @@ static void sg_load_sanitycheck(struct loaddata *loading)
              research_name_translation(presearch));
       presearch->tech_goal = A_UNSET;
     }
+
+    techs = recalculate_techs_researched(presearch);
+
+    if (presearch->techs_researched != techs) {
+      log_sg(_("%s had finished researches count wrong."),
+             research_name_translation(presearch));
+      presearch->techs_researched = techs;
+    }
   } researches_iterate_end;
 
   /* Check if some player has more than one of some UTYF_UNIQUE unit type */
-- 
2.35.1