From ccd4451e46c5fcdd2a2777a0f1b90dd5009675e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C5=82awomir=20Lach?= <slawek@lach.art.pl>
Date: Wed, 14 Dec 2022 17:18:15 +0100
Subject: [PATCH] =?UTF-8?q?!OSDN:=20#TICKET:=2046273=20-=20S=C5=82awomir?=
 =?UTF-8?q?=20Lach=20<slawek@lach.art.pl>?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Introduce sharing city counters' index mechanism.

diff --git a/common/counters.c b/common/counters.c
index f17eaa6d9f..7e0b3d5b25 100644
--- a/common/counters.c
+++ b/common/counters.c
@@ -33,6 +33,7 @@ static struct counter counters[MAX_COUNTERS];
 /* City counters array + related data */
 static struct counter *counters_city[MAX_COUNTERS];
 static int number_city_counters;
+static int highest_index_city_counters;
 
 /************************************************************************//**
   Initialize counters system
@@ -41,6 +42,7 @@ void counters_init(void)
 {
   game.control.num_counters = 0;
   number_city_counters = 0;
+  highest_index_city_counters = 0;
 }
 
 
@@ -55,6 +57,7 @@ void counters_free(void)
 
   game.control.num_counters = 0;
   number_city_counters = 0;
+  highest_index_city_counters = 0;
 }
 
 /************************************************************************//**
@@ -62,7 +65,7 @@ void counters_free(void)
 ****************************************************************************/
 int counters_get_city_counters_count(void)
 {
-  return number_city_counters;
+  return highest_index_city_counters;
 }
 
 /************************************************************************//**
@@ -75,6 +78,18 @@ struct counter *counter_by_id(int id)
   return &counters[id];
 }
 
+/************************************************************************//**
+  Added for future uses only. Return true if counter of some target
+  and behavior could share index.
+****************************************************************************/
+
+static bool counter_allow_index_sharing(enum counter_behaviour behaviour, enum counter_target target)
+{
+  (void) behaviour;
+  (void) target;
+  
+  return TRUE;
+}
 /************************************************************************//**
   Attaching given counter type to array containing counter type
   related to cities. Counter must be present in array for
@@ -82,9 +97,23 @@ struct counter *counter_by_id(int id)
 ****************************************************************************/
 void attach_city_counter(struct counter *counter)
 {
+  
   counters_city[number_city_counters] = counter;
-  counters_city[number_city_counters]->index = number_city_counters;
+  counters_city[number_city_counters]->index = highest_index_city_counters;
   number_city_counters++;
+  
+  if (counter_allow_index_sharing(counter->type, counter->target)) {
+  
+    city_counters_iterate_low_level(pcount) {
+      if (counter->type == pcount->type
+      &&  counter->target == pcount->target) {
+        counters_city[number_city_counters-1]->index = pcount->index ;
+        return;
+      }
+    } city_counters_iterate_low_level_end;
+  }
+  
+  ++highest_index_city_counters;
 }
 
 /************************************************************************//**
diff --git a/common/counters.h b/common/counters.h
index d5cadf0205..ac623350f2 100644
--- a/common/counters.h
+++ b/common/counters.h
@@ -51,16 +51,47 @@ struct counter *counter_by_index(int index, enum counter_target target);
 int counters_get_city_counters_count(void);
 void attach_city_counter(struct counter *counter);
 
-#define city_counters_iterate(pcount) { \
+#define city_counters_iterate_low_level(pcount) { \
    int _i_##pcount; \
    struct counter *pcount; \
    int _ccounter_count_##pcount = counters_get_city_counters_count(); \
    for (_i_##pcount = 0; _i_##pcount < _ccounter_count_##pcount; _i_##pcount++) { \
       pcount = counter_by_index(_i_##pcount, CTGT_CITY);
 
-#define city_counters_iterate_end } \
+#define city_counters_iterate_low_level_end } \
    }
 
+   
+#define city_counters_iterate(pcount, pcity, val_name) { \
+   int _i_##pcount = 0; \
+   struct counter *pcount = NULL; \
+   int _next_index_##pcount = 0; \
+   int _old_##val_name = 0; \
+   int _new_##val_name = 0; \
+   int _ccounter_count_##pcount = counters_get_city_counters_count(); \
+   for (_i_##pcount = 0; _i_##pcount < _ccounter_count_##pcount + 1; _i_##pcount++) { \
+      if (pcount != NULL && pcity != NULL) { \
+        if (pcount->index != _next_index_##pcount) { \
+            pcity->counter_values[pcount->index] = _new_##val_name; \
+         } \
+         if (_ccounter_count_##pcount == _i_##pcount) { \
+            break; \
+         } \
+      } \
+      if (_i_##pcount < _ccounter_count_##pcount) { \
+       pcount = counter_by_index(_i_##pcount, CTGT_CITY); \
+       _old_##val_name = _new_##val_name = 0; \
+       if (pcity != NULL) {\
+          _old_##val_name = pcity->counter_values[pcount->index]; \
+          _new_##val_name = _old_##val_name; \
+       } \
+       if (pcount->index == _next_index_##pcount) { \
+          _next_index_##pcount = _next_index_##pcount + 1;  \
+       } \
+      }
+
+#define city_counters_iterate_end } \
+   }
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/server/citytools.c b/server/citytools.c
index 41eb18e94b..fe1321392f 100644
--- a/server/citytools.c
+++ b/server/citytools.c
@@ -1223,9 +1223,9 @@ bool transfer_city(struct player *ptaker, struct city *pcity,
 
   /* Reset turns owner counters */
   if (city_remains) {
-    city_counters_iterate(pcount) {
+    city_counters_iterate(pcount, pcity, val) {
       if (pcount->type == CB_CITY_OWNED_TURNS) {
-        pcity->counter_values[pcount->index] = 0;
+        _new_val = 0;
       }
     } city_counters_iterate_end;
   }
@@ -2337,9 +2337,9 @@ void send_city_info(struct player *dest, struct city *pcity)
   }
 
   /* Sending counters */
-  city_counters_iterate(pcount) {
+  city_counters_iterate_low_level(pcount) {
     city_counter_refresh(pcity, pcount->index);
-  } city_counters_iterate_end;
+  } city_counters_iterate_low_level_end;
 
   if (game.info.team_pooled_research
       && player_list_size(team_members(powner->team)) > 1) {
diff --git a/server/cityturn.c b/server/cityturn.c
index 6cb18b1cb1..7e075f3385 100644
--- a/server/cityturn.c
+++ b/server/cityturn.c
@@ -3347,9 +3347,9 @@ static void update_city_activity(struct city *pcity)
       pcity->rapture++;
 
       /* Update city's celebrating counters */
-      city_counters_iterate(pcount) {
+      city_counters_iterate(pcount,pcity,val) {
         if (pcount->type == CB_CITY_CELEBRATION_TURNS) {
-          pcity->counter_values[pcount->index]++;
+          ++_new_val;
         }
       } city_counters_iterate_end;
 
@@ -3366,9 +3366,10 @@ static void update_city_activity(struct city *pcity)
       }
 
       /* Update city's celebrating counters */
-      city_counters_iterate(pcount) {
+
+      city_counters_iterate(pcount,pcity,val) {
         if (pcount->type == CB_CITY_CELEBRATION_TURNS) {
-          pcity->counter_values[pcount->index] = 0;
+          _new_val = 0;
         }
       } city_counters_iterate_end;
       pcity->rapture = 0;
diff --git a/server/ruleset.c b/server/ruleset.c
index ba79594214..34cc7b0f44 100644
--- a/server/ruleset.c
+++ b/server/ruleset.c
@@ -8212,7 +8212,7 @@ Send the counters ruleset information  to the specified connections.
 **************************************************************************/
 static void send_ruleset_counters(struct conn_list *dest)
 {
-  city_counters_iterate(pcount) {
+  city_counters_iterate_low_level(pcount) {
     struct packet_ruleset_counter packet;
 
     sz_strlcpy(packet.name, untranslated_name(&pcount->name));
@@ -8223,7 +8223,7 @@ static void send_ruleset_counters(struct conn_list *dest)
     packet.def = pcount->def;
 
     lsend_packet_ruleset_counter(dest, &packet);
-  } city_counters_iterate_end;
+  } city_counters_iterate_low_level_end;
 }
 
 /**********************************************************************//**
diff --git a/server/srv_main.c b/server/srv_main.c
index dc0e0781ed..aeb0bea84a 100644
--- a/server/srv_main.c
+++ b/server/srv_main.c
@@ -1534,14 +1534,13 @@ static void end_turn(void)
   /* Update city's counter values */
   players_iterate(pplayer) {
     city_list_iterate(pplayer->cities, pcity) {
-      city_counters_iterate(pcount) {
-        int old_val = pcity->counter_values[pcount->index];
-
+      city_counters_iterate(pcount,pcity,val) {
+        
         if (pcount->type == CB_CITY_OWNED_TURNS) {
-          pcity->counter_values[pcount->index]++;
+          _new_val++;
         }
 
-        if (pcity->counter_values[pcount->index] != old_val) {
+        if (_new_val != _old_val) {
 
           city_counter_refresh(pcity, pcount->index);
         }
diff --git a/tools/ruledit/univ_value.c b/tools/ruledit/univ_value.c
index 4ddcbe52ba..c645e25a90 100644
--- a/tools/ruledit/univ_value.c
+++ b/tools/ruledit/univ_value.c
@@ -259,9 +259,9 @@ void universal_kind_values(struct universal *univ,
     } advance_re_active_iterate_end;
     break;
   case VUT_COUNTER:
-    city_counters_iterate(pcount) {
+    city_counters_iterate_low_level(pcount) {
       cb(counter_rule_name(pcount), univ->value.counter == pcount, data);
-    } city_counters_iterate_end;
+    } city_counters_iterate_low_level_end;
     break;
   case VUT_GOVERNMENT:
     governments_re_active_iterate(pgov) {
diff --git a/tools/ruleutil/rulesave.c b/tools/ruleutil/rulesave.c
index 7a7b221e0d..da4f81606c 100644
--- a/tools/ruleutil/rulesave.c
+++ b/tools/ruleutil/rulesave.c
@@ -1759,7 +1759,7 @@ static bool save_game_ruleset(const char *filename, const char *name)
   comment_counters(sfile);
   
   sect_idx = 0;
-  city_counters_iterate(pcounter) {
+  city_counters_iterate_low_level(pcounter) {
     char path[512];
 
     fc_snprintf(path, sizeof(path), "counter_%d", sect_idx++);
@@ -1771,7 +1771,7 @@ static bool save_game_ruleset(const char *filename, const char *name)
 
     secfile_insert_str(sfile, counter_behaviour_name(pcounter->type), "%s.type", path);
 
-  } city_counters_iterate_end;
+  } city_counters_iterate_low_level_end;
 
   locks = FALSE;
   settings_iterate(SSET_ALL, pset) {
-- 
2.39.0

