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 »