<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