Project

General

Profile

Feature #642 » 0002-Client-Keep-track-of-continent-and-ocean-sizes.patch

main v2 - Alina Lenk, 05/18/2024 11:55 PM

View differences:

ai/tex/texaiworld.c
**************************************************************************/
void texai_map_close(void)
{
map_free(&(texai_world.map));
map_free(&(texai_world.map), TRUE);
}
/**********************************************************************//**
client/packhand.c
int ts_topo;
if (!map_is_empty()) {
map_free(&(wld.map));
map_free(&(wld.map), FALSE);
free_city_map_index();
}
......
}
}
/**********************************************************************//**
Returns the location of the adjacency count between the two given
continents or oceans, where ID 0 stands for unknown tiles.
**************************************************************************/
static inline int *continent_adjacency_count(Continent_id cont1,
Continent_id cont2)
{
if (cont1 > 0) {
if (cont2 == 0) {
return &wld.map.client.continent_unknown_adj_counts[cont1];
}
} else if (cont1 < 0) {
if (cont2 == 0) {
return &wld.map.client.ocean_unknown_adj_counts[-cont1];
}
} else {
if (cont2 > 0) {
return &wld.map.client.continent_unknown_adj_counts[cont2];
} else if (cont2 < 0) {
return &wld.map.client.ocean_unknown_adj_counts[-cont2];
}
}
return nullptr;
}
/**********************************************************************//**
Incrementally update continent information (sizes and adjacency) for the
given tile switching from one continent to another.
ptile is only used to iterate adjacent tiles, i.e. only its index must
be accurate; everything else may be mid-change.
**************************************************************************/
static inline void update_continent_cache(const struct tile *ptile,
Continent_id old_cont,
Continent_id new_cont)
{
/* Update known continents */
if (new_cont > wld.map.num_continents) {
int i;
/* Expand sizes array */
wld.map.continent_sizes = fc_realloc(wld.map.continent_sizes,
(new_cont + 1) * sizeof(*wld.map.continent_sizes));
/* Expand unknown tile adjacency counts array */
wld.map.client.continent_unknown_adj_counts = fc_realloc(
wld.map.client.continent_unknown_adj_counts,
(new_cont + 1) * sizeof(*wld.map.client.continent_unknown_adj_counts)
);
/* Fill new spots with zeros */
for (i = wld.map.num_continents + 1; i <= new_cont; i++) {
wld.map.continent_sizes[i] = 0;
wld.map.client.continent_unknown_adj_counts[i] = 0;
}
wld.map.num_continents = new_cont;
} else if (new_cont < -wld.map.num_oceans) {
int i;
/* Expand sizes array */
wld.map.ocean_sizes = fc_realloc(wld.map.ocean_sizes,
(-new_cont + 1) * sizeof(*wld.map.ocean_sizes));
/* Expand unknown tile adjacency counts array */
wld.map.client.ocean_unknown_adj_counts = fc_realloc(
wld.map.client.ocean_unknown_adj_counts,
(-new_cont + 1) * sizeof(*wld.map.client.ocean_unknown_adj_counts)
);
/* Fill new spots with zeros */
for (i = wld.map.num_oceans + 1; i <= -new_cont; i++) {
wld.map.ocean_sizes[i] = 0;
wld.map.client.ocean_unknown_adj_counts[i] = 0;
}
wld.map.num_oceans = -new_cont;
}
/* Decrement old continent/ocean size */
if (old_cont > 0) {
wld.map.continent_sizes[old_cont]--;
} else if (old_cont < 0) {
wld.map.ocean_sizes[-old_cont]--;
}
/* Increment new continent/ocean size */
if (new_cont > 0) {
wld.map.continent_sizes[new_cont]++;
} else if (new_cont < 0) {
wld.map.ocean_sizes[-new_cont]++;
}
/* Update tile adjacency counts */
adjc_iterate(&(wld.map), ptile, adj_tile) {
Continent_id adj_cont = tile_continent(adj_tile);
int *padjc_count;
/* Decrement old adjacency */
padjc_count = continent_adjacency_count(old_cont, adj_cont);
if (padjc_count) {
fc_assert(*padjc_count > 0);
(*padjc_count)--;
}
/* Increment new adjacency */
padjc_count = continent_adjacency_count(new_cont, adj_cont);
if (padjc_count) {
(*padjc_count)++;
}
} adjc_iterate_end;
}
/************************************************************************//**
Packet tile_info handler.
****************************************************************************/
......
unit_list_clear(ptile->units);
}
if (ptile->continent != packet->continent) {
update_continent_cache(ptile, ptile->continent, packet->continent);
}
ptile->continent = packet->continent;
wld.map.num_continents = MAX(ptile->continent, wld.map.num_continents);
if (packet->label[0] == '\0') {
if (ptile->label != NULL) {
client/text.c
struct player *plr = client_player();
bool flaggy_unit = (punit != nullptr
&& !is_flagless_to_player(punit, plr));
Continent_id cont = tile_continent(ptile);
astr_clear(&str);
index_to_map_pos(&tile_x, &tile_y, tile_index(ptile));
astr_add_line(&str, _("Location: (%d, %d) [%d]"),
tile_x, tile_y, tile_continent(ptile));
tile_x, tile_y, cont);
index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
astr_add_line(&str, _("Native coordinates: (%d, %d)"),
nat_x, nat_y);
if (cont > 0) {
int size = get_continent_size(cont);
if (wld.map.client.continent_unknown_adj_counts[cont] > 0) {
astr_add_line(&str, _("Continent size: at least %d"), size);
} else {
astr_add_line(&str, _("Continent size: %d"), size);
}
} else if (cont < 0) {
int size = get_ocean_size(-cont);
if (wld.map.client.ocean_unknown_adj_counts[-cont] > 0) {
astr_add_line(&str, _("Ocean size: at least %d"), size);
} else {
astr_add_line(&str, _("Ocean size: %d"), size);
}
}
astr_add_line(&str, _("Latitude: %d"),
map_signed_latitude(ptile));
common/map.c
imap->server.have_huts = FALSE;
imap->server.have_resources = FALSE;
imap->server.team_placement = MAP_DEFAULT_TEAM_PLACEMENT;
} else {
imap->client.continent_unknown_adj_counts = nullptr;
imap->client.ocean_unknown_adj_counts = nullptr;
}
}
......
/*******************************************************************//**
Frees the allocated memory of the map.
***********************************************************************/
void map_free(struct civ_map *fmap)
void map_free(struct civ_map *fmap, bool server_side)
{
if (fmap->tiles) {
/* It is possible that map_init() was called but not map_allocate() */
......
FC_FREE(fmap->lake_surrounders);
fmap->num_oceans = 0;
}
if (!server_side) {
if (fmap->client.continent_unknown_adj_counts) {
FC_FREE(fmap->client.continent_unknown_adj_counts);
fmap->num_continents = 0;
}
if (fmap->client.ocean_unknown_adj_counts) {
FC_FREE(fmap->client.ocean_unknown_adj_counts);
fmap->num_oceans = 0;
}
}
}
/*******************************************************************//**
......
***********************************************************************/
void main_map_free(void)
{
map_free(&(wld.map));
map_free(&(wld.map), is_server());
CALL_FUNC_EACH_AI(map_free);
}
......
{
fc_assert_ret_val(id > 0, -1);
fc_assert_ret_val(id <= wld.map.num_continents, -1);
/* Client updates num_continents, but not continent_sizes */
fc_assert_ret_val(is_server(), -1);
return wld.map.continent_sizes[id];
}
......
{
fc_assert_ret_val(id < 0, -1);
fc_assert_ret_val(id >= -wld.map.num_oceans, -1);
/* Client updates num_oceans, but not lake_surrounders */
fc_assert_ret_val(is_server(), -1);
return wld.map.lake_surrounders[-id];
}
common/map.h
void map_init_topology(void);
void map_allocate(struct civ_map *amap);
void main_map_allocate(void);
void map_free(struct civ_map *fmap);
void map_free(struct civ_map *fmap, bool server_side);
void main_map_free(void);
int map_vector_to_real_distance(int dx, int dy);
common/map_types.h
int south_latitude;
int num_continents;
int num_oceans; /* Not updated at the client */
int num_oceans;
/* These arrays are indexed by continent number (or negative of the
* ocean number) so the 0th element is unused and the array is 1 element
* larger than you'd expect.
......
* The lake_surrounders array tells which single continent surrounds each
* ocean; or -1 if there's more than one adjacent continent.
*/
int *continent_sizes; /* Not updated at the client */
int *ocean_sizes; /* Not updated at the client */
int *continent_sizes;
int *ocean_sizes;
Continent_id *lake_surrounders; /* Not updated at the client */
struct tile *tiles;
......
enum team_placement team_placement;
} server;
/* Add client side when needed */
struct {
/* These arrays count how many adjacencies there are between known
* tiles of a given continent or ocean and unknown tiles, i.e. if a
* single known tile is adjacent to multiple unknowns (or vice versa)
* it gets counted multiple times.
*
* If this is 0 for a continent or ocean, we know for sure that its
* size in continent/ocean_sizes is accurate. */
int *continent_unknown_adj_counts;
int *ocean_unknown_adj_counts;
} client;
};
};
(2-2/2)