From 7e08c999f2ec25514e9c976ef3a25302c305c058 Mon Sep 17 00:00:00 2001 From: Alina Lenk Date: Sat, 18 May 2024 18:22:37 +0200 Subject: [PATCH 08/10] Add "Region Surrounded" TileRel requirement See RM #654 Signed-off-by: Alina Lenk --- client/packhand.c | 64 ++++++++-------- client/text.c | 29 ++++++-- common/map.c | 105 +++++++++++++++++++++------ common/map.h | 10 ++- common/map_types.h | 40 +++++++--- common/metaknowledge.c | 4 + common/reqtext.c | 54 ++++++++++++++ common/requirements.c | 92 ++++++++++++++++++++++- doc/README.effects | 5 +- gen_headers/enums/fc_types_enums.def | 1 + server/generator/mapgen_utils.c | 47 ++++++++---- server/maphand.c | 2 +- 12 files changed, 357 insertions(+), 96 deletions(-) diff --git a/client/packhand.c b/client/packhand.c index b84f21ee88..04b9470c61 100644 --- a/client/packhand.c +++ b/client/packhand.c @@ -3126,20 +3126,12 @@ void handle_spaceship_info(const struct packet_spaceship_info *p) 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; } @@ -3157,42 +3149,46 @@ static inline void update_continent_cache(const struct tile *ptile, { /* 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; diff --git a/client/text.c b/client/text.c index d1c4e01a46..aa26869ef8 100644 --- a/client/text.c +++ b/client/text.c @@ -179,17 +179,34 @@ const char *popup_info_text(struct tile *ptile) 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"), diff --git a/common/map.c b/common/map.c index 1a613ded3b..963faf509e 100644 --- a/common/map.c +++ b/common/map.c @@ -175,7 +175,6 @@ void map_init(struct civ_map *imap, bool server_side) imap->continent_sizes = nullptr; imap->ocean_sizes = nullptr; - imap->lake_surrounders = nullptr; if (server_side) { imap->server.mapsize = MAP_DEFAULT_MAPSIZE; @@ -198,9 +197,12 @@ void map_init(struct civ_map *imap, bool server_side) 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)); } } @@ -561,27 +563,34 @@ void map_free(struct civ_map *fmap, bool server_side) } 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; } /*******************************************************************//** @@ -826,15 +835,69 @@ int get_ocean_size(Continent_id id) } /**********************************************************************//** - 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; + } + } } /*******************************************************************//** diff --git a/common/map.h b/common/map.h index 296db6870d..338dbcb36f 100644 --- a/common/map.h +++ b/common/map.h @@ -72,7 +72,15 @@ int get_direction_for_step(const struct civ_map *nmap, 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); diff --git a/common/map_types.h b/common/map_types.h index 80ccd8fe8f..9fbd487378 100644 --- a/common/map_types.h +++ b/common/map_types.h @@ -88,19 +88,16 @@ struct civ_map { * * 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 */ @@ -123,18 +120,37 @@ struct civ_map { 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; }; }; diff --git a/common/metaknowledge.c b/common/metaknowledge.c index 73765112da..77e448b84e 100644 --- a/common/metaknowledge.c +++ b/common/metaknowledge.c @@ -758,6 +758,10 @@ static bool is_req_knowable(const struct player *pov_player, 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: diff --git a/common/reqtext.c b/common/reqtext.c index b2cd4b2a48..df04820c7e 100644 --- a/common/reqtext.c +++ b/common/reqtext.c @@ -3535,6 +3535,60 @@ bool req_text_insert(char *buf, size_t bufsz, struct player *pplayer, 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. */ diff --git a/common/requirements.c b/common/requirements.c index 7a54e43940..d8a9ddf47c 100644 --- a/common/requirements.c +++ b/common/requirements.c @@ -4774,6 +4774,45 @@ is_form_age_req_active(const struct civ_map *nmap, } } +/**********************************************************************//** + 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 @@ -4870,6 +4909,50 @@ is_tile_rel_req_active(const struct civ_map *nmap, } } 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; } @@ -5832,14 +5915,12 @@ is_max_region_tiles_req_active(const struct civ_map *nmap, 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; } } @@ -7750,6 +7831,9 @@ const char *universal_name_translation(const struct universal *psource, 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); diff --git a/doc/README.effects b/doc/README.effects index 6c45809a6c..01b22367d0 100644 --- a/doc/README.effects +++ b/doc/README.effects @@ -136,9 +136,10 @@ MinLatitude and MaxLatitude are numbers from -1000 (south pole) to 1000 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. diff --git a/gen_headers/enums/fc_types_enums.def b/gen_headers/enums/fc_types_enums.def index f5c2e4f1f2..22b54cd3a3 100644 --- a/gen_headers/enums/fc_types_enums.def +++ b/gen_headers/enums/fc_types_enums.def @@ -111,4 +111,5 @@ enum tilerel_type values SAME_REGION "Same Region" ONLY_OTHER_REGION "Only Other Region" + REGION_SURROUNDED "Region Surrounded" end diff --git a/server/generator/mapgen_utils.c b/server/generator/mapgen_utils.c index 39904b7fcd..950cc1a6f4 100644 --- a/server/generator/mapgen_utils.c +++ b/server/generator/mapgen_utils.c @@ -232,15 +232,19 @@ void smooth_int_map(int *int_map, bool zeroes_at_edges) } /**********************************************************************//** - 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); @@ -250,17 +254,31 @@ static void recalculate_lake_surrounders(void) 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; @@ -332,8 +350,7 @@ static void assign_continent_flood(struct tile *ptile, bool is_land, int nr) /**********************************************************************//** 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) @@ -394,7 +411,7 @@ 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]); @@ -406,7 +423,7 @@ void regenerate_lakes(void) /**********************************************************************//** 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_. @@ -449,7 +466,7 @@ void assign_continent_numbers(void) } } 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); diff --git a/server/maphand.c b/server/maphand.c index 7f5b482f82..75f493d0a5 100644 --- a/server/maphand.c +++ b/server/maphand.c @@ -2108,7 +2108,7 @@ static bool is_claimable_ocean(struct tile *ptile, struct tile *source, 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; } -- 2.34.1