Feature #642 » 0002-Client-Keep-track-of-continent-and-ocean-sizes.patch
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;
|
||
};
|
||
};
|
||
- « Previous
- 1
- 2
- Next »