Feature #654 » 0008-Add-Region-Surrounded-TileRel-requirement.patch
client/packhand.c | ||
---|---|---|
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];
|
||
}
|
||
if (cont1 == cont2) {
|
||
return nullptr;
|
||
} else if (cont1 >= 0 && cont2 <= 0) {
|
||
return &wld.map.client.adj_matrix[cont1][-cont2];
|
||
} else if (cont1 <= 0 && cont2 >= 0) {
|
||
return &wld.map.client.adj_matrix[cont2][-cont1];
|
||
}
|
||
return nullptr;
|
||
}
|
||
... | ... | |
{
|
||
/* Update known continents */
|
||
if (new_cont > wld.map.num_continents) {
|
||
int i;
|
||
int cont;
|
||
/* 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)
|
||
);
|
||
/* Expand adjacency matrix */
|
||
wld.map.client.adj_matrix = fc_realloc(wld.map.client.adj_matrix,
|
||
(new_cont + 1) * sizeof(*wld.map.client.adj_matrix));
|
||
/* 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;
|
||
/* Initialize new spots */
|
||
for (cont = wld.map.num_continents + 1; cont <= new_cont; cont++) {
|
||
wld.map.continent_sizes[cont] = 0;
|
||
wld.map.client.adj_matrix[cont] = fc_calloc(wld.map.num_oceans + 1,
|
||
sizeof(*wld.map.client.adj_matrix[cont]));
|
||
}
|
||
wld.map.num_continents = new_cont;
|
||
} else if (new_cont < -wld.map.num_oceans) {
|
||
int i;
|
||
int cont, ocean;
|
||
/* 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)
|
||
);
|
||
/* Initialize new spots */
|
||
for (ocean = wld.map.num_oceans + 1; ocean <= -new_cont; ocean++) {
|
||
wld.map.ocean_sizes[ocean] = 0;
|
||
}
|
||
/* Expand adjacency matrix */
|
||
for (cont = 0; cont <= wld.map.num_continents; cont++) {
|
||
wld.map.client.adj_matrix[cont] = fc_realloc(
|
||
wld.map.client.adj_matrix[cont],
|
||
(-new_cont + 1) * sizeof(*wld.map.client.adj_matrix[cont])
|
||
);
|
||
/* 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;
|
||
for (ocean = wld.map.num_oceans + 1; ocean <= -new_cont; ocean++) {
|
||
wld.map.client.adj_matrix[cont][ocean] = 0;
|
||
}
|
||
}
|
||
wld.map.num_oceans = -new_cont;
|
client/text.c | ||
---|---|---|
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 {
|
||
Continent_id surrounder = get_island_surrounder(cont);
|
||
if (is_whole_continent_known(cont)) {
|
||
astr_add_line(&str, _("Continent size: %d"), size);
|
||
if (surrounder < 0) {
|
||
astr_add_line(&str, _("Surrounded by ocean %d"), -surrounder);
|
||
}
|
||
} else {
|
||
astr_add_line(&str, _("Continent size: at least %d"), size);
|
||
if (surrounder < 0) {
|
||
astr_add_line(&str, _("Maybe surrounded by ocean %d"), -surrounder);
|
||
}
|
||
}
|
||
} 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 {
|
||
Continent_id surrounder = get_lake_surrounder(cont);
|
||
if (is_whole_ocean_known(-cont)) {
|
||
astr_add_line(&str, _("Ocean size: %d"), size);
|
||
if (surrounder > 0) {
|
||
astr_add_line(&str, _("Surrounded by continent %d"), surrounder);
|
||
}
|
||
} else {
|
||
astr_add_line(&str, _("Ocean size: at least %d"), size);
|
||
if (surrounder > 0) {
|
||
astr_add_line(&str, _("Maybe surrounded by continent %d"),
|
||
surrounder);
|
||
}
|
||
}
|
||
}
|
||
astr_add_line(&str, _("Latitude: %d"),
|
common/map.c | ||
---|---|---|
imap->continent_sizes = nullptr;
|
||
imap->ocean_sizes = nullptr;
|
||
imap->lake_surrounders = nullptr;
|
||
if (server_side) {
|
||
imap->server.mapsize = MAP_DEFAULT_MAPSIZE;
|
||
... | ... | |
imap->server.have_huts = FALSE;
|
||
imap->server.have_resources = FALSE;
|
||
imap->server.team_placement = MAP_DEFAULT_TEAM_PLACEMENT;
|
||
imap->server.island_surrounders = nullptr;
|
||
imap->server.lake_surrounders = nullptr;
|
||
} else {
|
||
imap->client.continent_unknown_adj_counts = nullptr;
|
||
imap->client.ocean_unknown_adj_counts = nullptr;
|
||
imap->client.adj_matrix = fc_malloc(sizeof(*imap->client.adj_matrix));
|
||
*imap->client.adj_matrix = fc_malloc(sizeof(**imap->client.adj_matrix));
|
||
}
|
||
}
|
||
... | ... | |
}
|
||
if (fmap->continent_sizes) {
|
||
FC_FREE(fmap->continent_sizes);
|
||
fmap->num_continents = 0;
|
||
}
|
||
if (fmap->ocean_sizes) {
|
||
FC_FREE(fmap->ocean_sizes);
|
||
fmap->num_oceans = 0;
|
||
}
|
||
if (fmap->lake_surrounders) {
|
||
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 (server_side) {
|
||
if (fmap->server.island_surrounders) {
|
||
FC_FREE(fmap->server.island_surrounders);
|
||
}
|
||
if (fmap->server.lake_surrounders) {
|
||
FC_FREE(fmap->server.lake_surrounders);
|
||
}
|
||
if (fmap->client.ocean_unknown_adj_counts) {
|
||
FC_FREE(fmap->client.ocean_unknown_adj_counts);
|
||
fmap->num_oceans = 0;
|
||
} else {
|
||
if (fmap->client.adj_matrix) {
|
||
int i;
|
||
for (i = 0; i <= fmap->num_continents; i++) {
|
||
if (fmap->client.adj_matrix[i]) {
|
||
free(fmap->client.adj_matrix[i]);
|
||
}
|
||
}
|
||
FC_FREE(fmap->client.adj_matrix);
|
||
}
|
||
}
|
||
/* For any code that tries accessing sizes, surrounders etc. */
|
||
fmap->num_continents = fmap->num_oceans = 0;
|
||
}
|
||
/*******************************************************************//**
|
||
... | ... | |
}
|
||
/**********************************************************************//**
|
||
Get continent surrounding lake, or -1 if there is multiple continents.
|
||
Get the single ocean surrounding a given island, a positive value if
|
||
there isn't one single surrounding ocean, or 0 if client-side and there
|
||
could still be one but we don't know any concrete candidate.
|
||
**************************************************************************/
|
||
int get_lake_surrounders(Continent_id id)
|
||
int get_island_surrounder(Continent_id id)
|
||
{
|
||
fc_assert_ret_val(id > 0, +1);
|
||
fc_assert_ret_val(id <= wld.map.num_continents, +1);
|
||
if (is_server()) {
|
||
return -wld.map.server.island_surrounders[id];
|
||
} else {
|
||
Continent_id ocean, surrounder = 0;
|
||
for (ocean = 1; ocean <= wld.map.num_oceans; ocean++) {
|
||
if (wld.map.client.adj_matrix[id][ocean] > 0) {
|
||
if (surrounder == 0) {
|
||
surrounder = ocean;
|
||
} else if (surrounder != ocean) {
|
||
/* More than one adjacent ocean */
|
||
return +1;
|
||
}
|
||
}
|
||
}
|
||
if (surrounder == 0 && is_whole_continent_known(id)) {
|
||
return +1;
|
||
} else {
|
||
return -surrounder;
|
||
}
|
||
}
|
||
}
|
||
/**********************************************************************//**
|
||
Get the single continent surrounding a given lake, a negative value if
|
||
there isn't one single surrounding continent, or 0 if client-side and
|
||
there could still be one but we don't know any concrete candidate.
|
||
**************************************************************************/
|
||
int get_lake_surrounder(Continent_id 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];
|
||
if (is_server()) {
|
||
return wld.map.server.lake_surrounders[-id];
|
||
} else {
|
||
Continent_id cont, surrounder = 0;
|
||
for (cont = 1; cont <= wld.map.num_continents; cont++) {
|
||
if (wld.map.client.adj_matrix[cont][-id] > 0) {
|
||
if (surrounder == 0) {
|
||
surrounder = cont;
|
||
} else if (surrounder != cont) {
|
||
/* More than one adjacent continent */
|
||
return -1;
|
||
}
|
||
}
|
||
}
|
||
if (surrounder == 0 && is_whole_ocean_known(-id)) {
|
||
return -1;
|
||
} else {
|
||
return surrounder;
|
||
}
|
||
}
|
||
}
|
||
/*******************************************************************//**
|
common/map.h | ||
---|---|---|
int get_continent_size(Continent_id id);
|
||
int get_ocean_size(Continent_id id);
|
||
int get_lake_surrounders(Continent_id id);
|
||
int get_island_surrounder(Continent_id id);
|
||
int get_lake_surrounder(Continent_id id);
|
||
#define is_whole_continent_known(cont) \
|
||
(is_server() || wld.map.client.adj_matrix[cont][0] == 0)
|
||
/* Use positive ocean ID */
|
||
#define is_whole_ocean_known(ocean) \
|
||
(is_server() || wld.map.client.adj_matrix[0][ocean] == 0)
|
||
/* Specific functions for start positions. */
|
||
struct startpos *map_startpos_by_number(int id);
|
common/map_types.h | ||
---|---|---|
*
|
||
* The _sizes arrays give the sizes (in tiles) of each continent and
|
||
* ocean.
|
||
*
|
||
* The lake_surrounders array tells which single continent surrounds each
|
||
* ocean; or -1 if there's more than one adjacent continent.
|
||
*/
|
||
int *continent_sizes;
|
||
int *ocean_sizes;
|
||
Continent_id *lake_surrounders; /* Not updated at the client */
|
||
struct tile *tiles;
|
||
struct startpos_hash *startpos_table;
|
||
union {
|
||
struct {
|
||
/* Server settings */
|
||
enum mapsize_type mapsize; /* How the map size is defined */
|
||
int size; /* Used to calculate [xy]size */
|
||
int tilesperplayer; /* Tiles per player; used to calculate size */
|
||
... | ... | |
bool have_huts;
|
||
bool have_resources;
|
||
enum team_placement team_placement;
|
||
/* 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 _surrounders arrays tell which single continent surrounds each
|
||
* ocean, or which single ocean (positive ocean number) surrounds each
|
||
* continent; or -1 if there's more than one adjacent region.
|
||
*/
|
||
Continent_id *island_surrounders;
|
||
Continent_id *lake_surrounders;
|
||
} server;
|
||
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.
|
||
/* This matrix counts how many adjacencies there are between known
|
||
* tiles of each continent and each ocean, as well as between both of
|
||
* those and unknown tiles. If a single tile of one region is
|
||
* adjacent to multiple tiles of another (or multiple unknowns), it
|
||
* gets counted multiple times.
|
||
*
|
||
* The matrix is continent-major, i.e.
|
||
* - adj_matrix[continent][ocean] is the adjacency count between a
|
||
* continent and an ocean
|
||
* - adj_matrix[continent][0] is the unknown adjacency count for a
|
||
* continent
|
||
* - adj_matrix[0][ocean] is the unknown adjacency count for an ocean
|
||
* - adj_matrix[0][0] is unused
|
||
*
|
||
* 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;
|
||
* If an unknown adjacency count is 0, we know for sure that the
|
||
* known size of that continent or ocean is accurate. */
|
||
int **adj_matrix;
|
||
} client;
|
||
};
|
||
};
|
common/metaknowledge.c | ||
---|---|---|
if (tile_get_known(other_context->tile, pov_player) == TILE_UNKNOWN) {
|
||
return FALSE;
|
||
}
|
||
if (req->source.value.tilerel == TREL_REGION_SURROUNDED) {
|
||
/* Too complicated to figure out */
|
||
return FALSE;
|
||
}
|
||
switch (req->range) {
|
||
case REQ_RANGE_TILE:
|
common/reqtext.c | ||
---|---|---|
break;
|
||
}
|
||
break;
|
||
case TREL_REGION_SURROUNDED:
|
||
switch (preq->range) {
|
||
case REQ_RANGE_TILE:
|
||
fc_strlcat(buf, prefix, bufsz);
|
||
if (preq->present) {
|
||
fc_strlcat(buf, _("Must be on a lake or island surrounded by "
|
||
"this continent or ocean."),
|
||
bufsz);
|
||
} else {
|
||
fc_strlcat(buf, _("Must not be on a lake or island surrounded "
|
||
"by this continent or ocean."),
|
||
bufsz);
|
||
}
|
||
return TRUE;
|
||
case REQ_RANGE_CADJACENT:
|
||
fc_strlcat(buf, prefix, bufsz);
|
||
if (preq->present) {
|
||
fc_strlcat(buf, _("Must be on or cardinally adjacent to a lake "
|
||
"or island surrounded by this continent or "
|
||
"ocean."),
|
||
bufsz);
|
||
} else {
|
||
fc_strlcat(buf, _("Must not be on nor cardinally adjacent to a "
|
||
"lake or island surrounded by this continent "
|
||
"or ocean."),
|
||
bufsz);
|
||
}
|
||
return TRUE;
|
||
case REQ_RANGE_ADJACENT:
|
||
fc_strlcat(buf, prefix, bufsz);
|
||
if (preq->present) {
|
||
fc_strlcat(buf, _("Must be on or adjacent to a lake or island "
|
||
"surrounded by this continent or ocean."),
|
||
bufsz);
|
||
} else {
|
||
fc_strlcat(buf, _("Must not be on nor adjacent to a lake or "
|
||
"island surrounded by this continent or "
|
||
"ocean."),
|
||
bufsz);
|
||
}
|
||
return TRUE;
|
||
case REQ_RANGE_CITY:
|
||
case REQ_RANGE_TRADE_ROUTE:
|
||
case REQ_RANGE_CONTINENT:
|
||
case REQ_RANGE_PLAYER:
|
||
case REQ_RANGE_TEAM:
|
||
case REQ_RANGE_ALLIANCE:
|
||
case REQ_RANGE_WORLD:
|
||
case REQ_RANGE_LOCAL:
|
||
case REQ_RANGE_COUNT:
|
||
/* Not supported. */
|
||
break;
|
||
}
|
||
break;
|
||
case TREL_COUNT:
|
||
/* Invalid. */
|
common/requirements.c | ||
---|---|---|
* already covered by are_requirements_opposites() above. */
|
||
switch (req1->source.value.tilerel) {
|
||
case TREL_SAME_REGION:
|
||
case TREL_REGION_SURROUNDED:
|
||
/* Negated req at larger range contradicts present req at
|
||
* smaller range. */
|
||
if (req1->range > req2->range) {
|
||
... | ... | |
return FALSE;
|
||
}
|
||
}
|
||
if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
|
||
|| req2->source.value.tilerel == TREL_REGION_SURROUNDED) {
|
||
const struct requirement *surr, *other;
|
||
if (req1->source.value.tilerel == TREL_REGION_SURROUNDED) {
|
||
surr = req1;
|
||
other = req2;
|
||
} else {
|
||
surr = req2;
|
||
other = req1;
|
||
}
|
||
if (surr->present && surr->range == REQ_RANGE_TILE) {
|
||
/* Target tile must be part of a surrounded region
|
||
* ~> not the same region
|
||
* ~> not touched by a third region */
|
||
switch (other->source.value.tilerel) {
|
||
case TREL_SAME_REGION:
|
||
return (other->present && other->range == REQ_RANGE_TILE);
|
||
case TREL_ONLY_OTHER_REGION:
|
||
return (!other->present);
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
/* No further contradictions we can detect */
|
||
return FALSE;
|
||
default:
|
||
... | ... | |
}
|
||
}
|
||
/**********************************************************************//**
|
||
Determine whether the given continent or ocean might be surrounded by a
|
||
specific desired surrounder.
|
||
**************************************************************************/
|
||
static inline enum fc_tristate
|
||
does_region_surrounder_match(Continent_id cont, Continent_id surrounder)
|
||
{
|
||
Continent_id actual_surrounder;
|
||
bool whole_known;
|
||
if (cont > 0) {
|
||
actual_surrounder = get_island_surrounder(cont);
|
||
whole_known = is_whole_continent_known(cont);
|
||
if (actual_surrounder > 0) {
|
||
return TRI_NO;
|
||
}
|
||
} else if (cont < 0) {
|
||
actual_surrounder = get_lake_surrounder(cont);
|
||
whole_known = is_whole_ocean_known(-cont);
|
||
if (actual_surrounder < 0) {
|
||
return TRI_NO;
|
||
}
|
||
} else {
|
||
return TRI_MAYBE;
|
||
}
|
||
if (actual_surrounder == 0 || surrounder == 0) {
|
||
return TRI_MAYBE;
|
||
} else if (actual_surrounder != surrounder) {
|
||
return TRI_NO;
|
||
} else if (!whole_known) {
|
||
return TRI_MAYBE;
|
||
} else {
|
||
return TRI_YES;
|
||
}
|
||
}
|
||
/**********************************************************************//**
|
||
Determine whether a tile relationship requirement is satisfied in a given
|
||
context, ignoring parts of the requirement that can be handled uniformly
|
||
... | ... | |
}
|
||
}
|
||
break;
|
||
case TREL_REGION_SURROUNDED:
|
||
fc_assert_ret_val_msg((req->range == REQ_RANGE_TILE
|
||
|| req->range == REQ_RANGE_CADJACENT
|
||
|| req->range == REQ_RANGE_ADJACENT),
|
||
TRI_MAYBE,
|
||
"Invalid range %d for tile relation \"%s\" req",
|
||
req->range,
|
||
tilerel_type_name(TREL_REGION_SURROUNDED));
|
||
{
|
||
bool seen_maybe = FALSE;
|
||
Continent_id wanted = tile_continent(other_context->tile);
|
||
switch (does_region_surrounder_match(tile_continent(context->tile),
|
||
wanted)) {
|
||
case TRI_YES:
|
||
return TRI_YES;
|
||
case TRI_MAYBE:
|
||
seen_maybe = TRUE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
range_adjc_iterate(nmap, context->tile, req->range, adj_tile) {
|
||
switch (does_region_surrounder_match(tile_continent(adj_tile),
|
||
wanted)) {
|
||
case TRI_YES:
|
||
return TRI_YES;
|
||
case TRI_MAYBE:
|
||
seen_maybe = TRUE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
} range_adjc_iterate_end;
|
||
if (seen_maybe) {
|
||
return TRI_MAYBE;
|
||
} else {
|
||
return TRI_NO;
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
... | ... | |
if (cont > 0) {
|
||
min_tiles = nmap->continent_sizes[cont];
|
||
if (is_server() || (nmap->client.continent_unknown_adj_counts[cont]
|
||
== 0)) {
|
||
if (is_whole_continent_known(cont)) {
|
||
max_tiles = min_tiles;
|
||
}
|
||
} else if (cont < 0) {
|
||
min_tiles = nmap->ocean_sizes[-cont];
|
||
if (is_server() || (nmap->client.ocean_unknown_adj_counts[-cont]
|
||
== 0)) {
|
||
if (is_whole_ocean_known(-cont)) {
|
||
max_tiles = min_tiles;
|
||
}
|
||
}
|
||
... | ... | |
case TREL_ONLY_OTHER_REGION:
|
||
fc_strlcat(buf, _("Only other continent/ocean"), bufsz);
|
||
break;
|
||
case TREL_REGION_SURROUNDED:
|
||
fc_strlcat(buf, _("Lake/island surrounded"), bufsz);
|
||
break;
|
||
case TREL_COUNT:
|
||
fc_assert(psource->value.tilerel != TREL_COUNT);
|
||
fc_strlcat(buf, "error", bufsz);
|
doc/README.effects | ||
---|---|---|
TileRel is about the relation to a specific other tile; currently only available
|
||
for action enablers (see also README.actions) and a select few effects. It is
|
||
one of "Same Region" (on or adjacent to the same continent/ocean as the other
|
||
tile, depending on range) or "Only Other Region" (only adjacent to tiles of its
|
||
tile, depending on range), "Only Other Region" (only adjacent to tiles of its
|
||
own or the other tile's continent/ocean, not a third one; not available at Tile
|
||
range).
|
||
range), or "Region Surrounded" (on or adjacent to a lake/island touching only
|
||
the other tile's continent/ocean).
|
||
MaxDistanceSq is about the (squared) distance between two tiles; currently
|
||
only available for action enablers (see also README.actions) and a select
|
||
few effects.
|
gen_headers/enums/fc_types_enums.def | ||
---|---|---|
values
|
||
SAME_REGION "Same Region"
|
||
ONLY_OTHER_REGION "Only Other Region"
|
||
REGION_SURROUNDED "Region Surrounded"
|
||
end
|
server/generator/mapgen_utils.c | ||
---|---|---|
}
|
||
/**********************************************************************//**
|
||
Calculate wld.map.lake_surrounders[] array
|
||
Calculate wld.map.*_surrounders[] arrays
|
||
**************************************************************************/
|
||
static void recalculate_lake_surrounders(void)
|
||
static void recalculate_surrounders(void)
|
||
{
|
||
size_t size;
|
||
size = (wld.map.num_oceans + 1) * sizeof(*wld.map.lake_surrounders);
|
||
wld.map.lake_surrounders = fc_realloc(wld.map.lake_surrounders, size);
|
||
memset(wld.map.lake_surrounders, 0, size);
|
||
size = (wld.map.num_continents + 1) * sizeof(*wld.map.server.island_surrounders);
|
||
wld.map.server.island_surrounders = fc_realloc(wld.map.server.island_surrounders, size);
|
||
memset(wld.map.server.island_surrounders, 0, size);
|
||
size = (wld.map.num_oceans + 1) * sizeof(*wld.map.server.lake_surrounders);
|
||
wld.map.server.lake_surrounders = fc_realloc(wld.map.server.lake_surrounders, size);
|
||
memset(wld.map.server.lake_surrounders, 0, size);
|
||
whole_map_iterate(&(wld.map), ptile) {
|
||
const struct terrain *pterrain = tile_terrain(ptile);
|
||
... | ... | |
continue;
|
||
}
|
||
if (!is_ocean(pterrain)) {
|
||
if (is_ocean(pterrain)) {
|
||
fc_assert_action(cont < 0, continue);
|
||
adjc_iterate(&(wld.map), ptile, adj_tile) {
|
||
Continent_id adj_cont = tile_continent(adj_tile);
|
||
if (!is_ocean_tile(adj_tile)) {
|
||
fc_assert_action(adj_cont > 0, continue);
|
||
if (wld.map.server.island_surrounders[adj_cont] == 0) {
|
||
wld.map.server.island_surrounders[adj_cont] = -cont;
|
||
} else if (wld.map.server.island_surrounders[adj_cont] != -cont) {
|
||
wld.map.server.island_surrounders[adj_cont] = -1;
|
||
}
|
||
}
|
||
} adjc_iterate_end;
|
||
} else {
|
||
fc_assert_action(cont > 0, continue);
|
||
adjc_iterate(&(wld.map), ptile, adj_tile) {
|
||
Continent_id adj_cont = tile_continent(adj_tile);
|
||
if (is_ocean_tile(adj_tile)) {
|
||
fc_assert_action(adj_cont < 0, continue);
|
||
if (wld.map.lake_surrounders[-adj_cont] == 0) {
|
||
wld.map.lake_surrounders[-adj_cont] = cont;
|
||
} else if (wld.map.lake_surrounders[-adj_cont] != cont) {
|
||
wld.map.lake_surrounders[-adj_cont] = -1;
|
||
if (wld.map.server.lake_surrounders[-adj_cont] == 0) {
|
||
wld.map.server.lake_surrounders[-adj_cont] = cont;
|
||
} else if (wld.map.server.lake_surrounders[-adj_cont] != cont) {
|
||
wld.map.server.lake_surrounders[-adj_cont] = -1;
|
||
}
|
||
}
|
||
} adjc_iterate_end;
|
||
... | ... | |
/**********************************************************************//**
|
||
Regenerate all oceanic tiles for small water bodies as lakes.
|
||
Assumes assign_continent_numbers() and recalculate_lake_surrounders()
|
||
have already been done!
|
||
Assumes assign_continent_numbers() has already been called!
|
||
FIXME: insufficiently generalized, use terrain property.
|
||
**************************************************************************/
|
||
void regenerate_lakes(void)
|
||
... | ... | |
if (terrain_type_terrain_class(pterrain) != TC_OCEAN) {
|
||
continue;
|
||
}
|
||
if (0 < wld.map.lake_surrounders[-here]) {
|
||
if (0 < wld.map.server.lake_surrounders[-here]) {
|
||
if (terrain_control.lake_max_size >= wld.map.ocean_sizes[-here]) {
|
||
int frozen = terrain_has_flag(pterrain, TER_FROZEN);
|
||
tile_change_terrain(ptile, lake_for_ocean[frozen][-here-1]);
|
||
... | ... | |
/**********************************************************************//**
|
||
Assigns continent and ocean numbers to all tiles, and set
|
||
map.num_continents and map.num_oceans. Recalculates continent and
|
||
ocean sizes, and lake_surrounders[] arrays.
|
||
ocean sizes and surrounders.
|
||
Continents have numbers 1 to map.num_continents _inclusive_.
|
||
Oceans have (negative) numbers -1 to -map.num_oceans _inclusive_.
|
||
... | ... | |
}
|
||
} whole_map_iterate_end;
|
||
recalculate_lake_surrounders();
|
||
recalculate_surrounders();
|
||
log_verbose("Map has %d continents and %d oceans",
|
||
wld.map.num_continents, wld.map.num_oceans);
|
server/maphand.c | ||
---|---|---|
bool other_continent;
|
||
if (get_ocean_size(-cont) <= MAXIMUM_CLAIMED_OCEAN_SIZE
|
||
&& get_lake_surrounders(cont) == source_cont) {
|
||
&& get_lake_surrounder(cont) == source_cont) {
|
||
return TRUE;
|
||
}
|
||