From f256fd364dc8eb0c0d25a62b4bd3faa0730155df Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Wed, 4 May 2022 06:33:55 +0300
Subject: [PATCH 53/53] Factor out governments detection from found_new_tech()

Requested by Jacob Nevins

See osdn #44510

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 server/techtools.c | 95 +++++++++++++++++++++++++++++++++++-----------
 server/techtools.h | 15 +++++++-
 2 files changed, 86 insertions(+), 24 deletions(-)

diff --git a/server/techtools.c b/server/techtools.c
index a2680cd856..a3e43c2ac4 100644
--- a/server/techtools.c
+++ b/server/techtools.c
@@ -318,7 +318,7 @@ void found_new_tech(struct research *presearch, Tech_type_id tech_found,
                     bool was_discovery, bool saving_bulbs)
 {
   int had_embassies[player_slot_count()];
-  bool could_switch[player_slot_count()][government_count()];
+  struct cur_govs_data *could_switch;
   bool was_first = FALSE;
   bool bonus_tech_hack = FALSE;
   int i;
@@ -374,19 +374,10 @@ void found_new_tech(struct research *presearch, Tech_type_id tech_found,
 
     /* Count EFT_HAVE_EMBASSIES effect for each player. */
     had_embassies[i] = get_player_bonus(aplayer, EFT_HAVE_EMBASSIES);
-
-    if (presearch != research_get(aplayer)) {
-      continue;
-    }
-
-    /* Memorize for the players sharing the research what government
-     * they could switch on. */
-    governments_iterate(pgov) {
-      could_switch[i][government_index(pgov)]
-          = can_change_to_government(aplayer, pgov);
-    } governments_iterate_end;
   } players_iterate_end;
 
+  could_switch = create_current_governments_data(presearch);
+
   /* got_tech allows us to change research without applying techpenalty
    * (without losing bulbs) */
   if (tech_found == presearch->researching) {
@@ -420,6 +411,8 @@ void found_new_tech(struct research *presearch, Tech_type_id tech_found,
     i = player_index(aplayer);
 
     if (presearch == research_get(aplayer)) {
+      char buf[250];
+
       /* Only for players sharing the research. */
       remove_obsolete_buildings(aplayer);
 
@@ -441,17 +434,9 @@ void found_new_tech(struct research *presearch, Tech_type_id tech_found,
        * that world-ranged effects will not be updated immediately. */
       unit_list_refresh_vision(aplayer->units);
 
-      /* Notify a player about new governments available */
-      governments_iterate(pgov) {
-        if (!could_switch[i][government_index(pgov)]
-            && can_change_to_government(aplayer, pgov)) {
-          notify_player(aplayer, NULL, E_NEW_GOVERNMENT, ftc_server,
-                        _("Discovery of %s makes the government form %s"
-                          " available. You may want to start a revolution."),
-                        advance_name,
-                        government_name_translation(pgov));
-        }
-      } governments_iterate_end;
+      fc_snprintf(buf, sizeof(buf), _("Discovery of %s"), advance_name);
+
+      notify_new_government_options(aplayer, could_switch, buf);
     }
 
     /* For any player. */
@@ -479,6 +464,8 @@ void found_new_tech(struct research *presearch, Tech_type_id tech_found,
     }
   } shuffled_players_iterate_end;
 
+  free_current_governments_data(could_switch);
+
   if (tech_found == presearch->tech_goal) {
     presearch->tech_goal = A_UNSET;
   }
@@ -1404,3 +1391,65 @@ bool tech_transfer(struct player *plr_recv, struct player *plr_donor,
 
   return TRUE;
 }
+
+/************************************************************************//**
+  Create data block listing what are the current government options of
+  the players participating in the research.
+
+  Use free_current_governments_data() to free the returned data.
+****************************************************************************/
+struct cur_govs_data *create_current_governments_data(struct research *presearch)
+{
+  struct cur_govs_data *data = fc_malloc(sizeof(struct cur_govs_data));
+
+  data->players = fc_malloc(sizeof(*data->players) * player_slot_count());
+
+  players_iterate(pplayer) {
+    data->players[player_index(pplayer)].govs = fc_malloc(sizeof(bool) * government_count());
+  } players_iterate_end;
+
+  research_players_iterate(presearch, pplayer) {
+    /* Memorize for the players sharing the research what government
+     * they could switch on. */
+    governments_iterate(pgov) {
+      data->players[player_index(pplayer)].govs[government_index(pgov)]
+        = can_change_to_government(pplayer, pgov);
+    } governments_iterate_end;
+  } research_players_iterate_end;
+
+  return data;
+}
+
+/************************************************************************//**
+  Free the data block returned from the create_current_governments_data()
+****************************************************************************/
+void free_current_governments_data(struct cur_govs_data *data)
+{
+  players_iterate(pplayer) {
+    free(data->players[player_index(pplayer)].govs);
+  } players_iterate_end;
+
+  free(data->players);
+  free(data);
+}
+
+/************************************************************************//**
+  Notify player about any new government options they have compared
+  to the data block provided.
+****************************************************************************/
+void notify_new_government_options(struct player *pplayer,
+                                   struct cur_govs_data *data,
+                                   const char *reason)
+{
+  governments_iterate(pgov) {
+    if (!data->players[player_index(pplayer)].govs[government_index(pgov)]
+        && can_change_to_government(pplayer, pgov)) {
+      notify_player(pplayer, NULL, E_NEW_GOVERNMENT, ftc_server,
+                    /* TRANS: "Discovery of <tech>" */
+                    _("%s makes the government form %s"
+                      " available. You may want to start a revolution."),
+                    reason,
+                    government_name_translation(pgov));
+    }
+  } governments_iterate_end;
+}
diff --git a/server/techtools.h b/server/techtools.h
index 845e480dd8..030d4faa87 100644
--- a/server/techtools.h
+++ b/server/techtools.h
@@ -1,4 +1,4 @@
-/**********************************************************************
+/***********************************************************************
  Freeciv - Copyright (C) 2005 The Freeciv Team
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -13,11 +13,19 @@
 #ifndef FC__TECHTOOLS_H
 #define FC__TECHTOOLS_H
 
+/* common */
+#include "government.h"
 #include "player.h"
 #include "tech.h"
 
 struct research;
 
+struct cur_govs_data {
+  struct {
+    bool *govs;
+  } *players;
+};
+
 void research_apply_penalty(struct research *presearch, Tech_type_id tech,
                             int penalty_percent);
 void do_tech_parasite_effect(struct player *pplayer);
@@ -45,4 +53,9 @@ void give_initial_techs(struct research *presearch, int num_random_techs);
 bool tech_transfer(struct player *plr_recv, struct player *plr_donor,
                    Tech_type_id tech);
 
+struct cur_govs_data *create_current_governments_data(struct research *presearch);
+void free_current_governments_data(struct cur_govs_data *data);
+void notify_new_government_options(struct player *pplayer, struct cur_govs_data *data,
+                                   const char *reason);
+
 #endif  /* FC__TECHTOOLS_H */
-- 
2.35.1