<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40584 >

> [chrisk - Mon Dec 01 18:55:21 2008]:
> 
> Loading 1894m: Aztec nation missing is game, not listed in
> civserver, city of Zinaparo shown but wiped off the map when
> I fly along.

There were two bugs in the loading code that the attached
patch fixes. I tested it with your save game and others
and it appears to work now.

The first bug was an incorrect use of players_iterate
in map_load which I missed when I made the player handling
improvements. It should use player_slots_iterate since
it only cares about the player slot numbers for setting
bits in the bit vector ptile->known.

The second bug was that the player loading code was not
setting player slots to used (player_slot_set_used) so
when it later called players_iterate, it would iterate
over nothing. Or sometimes something, since the call to
aifill in load_rulesets would actually set a few slots
used during the game load! (I address that in another
ticket.)

So the patch adds slot initialization code based on what
player<plrno> sections are present in the secfile. There
does not seem to be any function that can be used to
simply check for the presence of a given section, so I
also added secfile_has_section() to utility/registry.[ch]
for that purpose.


-----------------------------------------------------------------------
お疲れさまでした。
 common/player.h    |    2 ++
 server/savegame.c  |   47 ++++++++++++++++++++++++++++++++---------------
 utility/registry.c |   16 ++++++++++++++++
 utility/registry.h |    3 +++
 4 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/common/player.h b/common/player.h
index 824cbaa..cea345c 100644
--- a/common/player.h
+++ b/common/player.h
@@ -317,6 +317,8 @@ do {\
   }\
 } while (0)
 
+/* NB!!! This will only iterate over players for
+ * which player_slot_is_used() returns TRUE. */
 #define players_iterate(NAME_pplayer)\
 do {\
   player_slots_iterate(NAME_pplayer) {\
diff --git a/server/savegame.c b/server/savegame.c
index af5b82e..16256a0 100644
--- a/server/savegame.c
+++ b/server/savegame.c
@@ -1089,11 +1089,11 @@ static void map_load(struct section_file *file,
      * now we convert it to bv_player. */
     whole_map_iterate(ptile) {
       BV_CLR_ALL(ptile->tile_known);
-      players_iterate(pplayer) {
-	if (known[tile_index(ptile)] & (1u << player_index(pplayer))) {
-	  BV_SET(ptile->tile_known, player_index(pplayer));
-	}
-      } players_iterate_end;
+      player_slots_iterate(pslot) {
+        if (known[tile_index(ptile)] & (1u << player_index(pslot))) {
+          BV_SET(ptile->tile_known, player_index(pslot));
+        }
+      } player_slots_iterate_end;
     } whole_map_iterate_end;
   }
   map.have_resources = TRUE;
@@ -4520,6 +4520,8 @@ static void game_load_internal(struct section_file *file)
     /* override previous load */
     set_player_count(0);
   } else {
+    int loaded_players = 0;
+
     /* destroyed wonders: */
     string = secfile_lookup_str_default(file, NULL,
                                         "game.destroyed_wonders_new");
@@ -4563,16 +4565,31 @@ static void game_load_internal(struct section_file *file)
     init_available_nations();
 
     /* Now, load the players. */
-    players_iterate(pplayer) {
-      int n = player_index(pplayer);
-      player_load_main(pplayer, n, file, savefile_options,
-		       technology_order, technology_order_size);
-
-      player_load_cities(pplayer, n, file, savefile_options,
-			 improvement_order, improvement_order_size);
-      player_load_units(pplayer, n, file, savefile_options, base_order);
-      player_load_attributes(pplayer, n, file);
-    } players_iterate_end;
+    player_slots_iterate(pplayer) {
+      int plrno = player_number(pplayer);
+      if (!secfile_has_section(file, "player%d", plrno)) {
+        player_slot_set_used(pplayer, FALSE);
+        continue;
+      }
+      player_slot_set_used(pplayer, TRUE);
+      player_load_main(pplayer, plrno, file, savefile_options,
+                       technology_order, technology_order_size);
+      player_load_cities(pplayer, plrno, file, savefile_options,
+                         improvement_order, improvement_order_size);
+      player_load_units(pplayer, plrno, file, savefile_options, base_order);
+      player_load_attributes(pplayer, plrno, file);
+      loaded_players++;
+    } player_slots_iterate_end;
+
+    /* Check that the number of players loaded matches the
+     * number of players set in the save file. */
+    if (loaded_players != player_count()) {
+      freelog(LOG_ERROR, "The value of game.nplayers (%d) from the loaded "
+              "game does not match the number of players present (%d). "
+              "Setting game.nplayers to %d.",
+              player_count(), loaded_players, loaded_players);
+      set_player_count(loaded_players);
+    }
 
     /* In case of tech_leakage, we can update research only after all
      * the players have been loaded */
diff --git a/utility/registry.c b/utility/registry.c
index 9ea895d..6b7ee7e 100644
--- a/utility/registry.c
+++ b/utility/registry.c
@@ -1775,3 +1775,19 @@ char **secfile_get_section_entries(struct section_file *my_section_file,
 
   return ret;
 }
+
+/****************************************************************************
+  Returns TRUE if the given section exists in the secfile.
+****************************************************************************/
+bool secfile_has_section(const struct section_file *sf,
+                         const char *section_name_fmt, ...)
+{
+  char name[MAX_LEN_BUFFER];
+  va_list ap;
+
+  va_start(ap, section_name_fmt);
+  my_vsnprintf(name, sizeof(name), section_name_fmt, ap);
+  va_end(ap);
+
+  return hash_key_exists(sf->hash_sections, name);
+}
diff --git a/utility/registry.h b/utility/registry.h
index 783d78f..aa8805b 100644
--- a/utility/registry.h
+++ b/utility/registry.h
@@ -119,6 +119,9 @@ char **secfile_lookup_str_vec(struct section_file *my_section_file,
 char **secfile_get_secnames_prefix(struct section_file *my_section_file,
 				   const char *prefix, int *num);
 
+bool secfile_has_section(const struct section_file *sf,
+                         const char *section_name, ...)
+                         fc__attribute((__format__ (__printf__, 2, 3)));
 char **secfile_get_section_entries(struct section_file *my_section_file,
 				   const char *section, int *num);
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to