Project

General

Profile

Feature #629 » 0004-Add-MaxRegionTiles-continent-size-requirement-type.patch

main v4 - Alina Lenk, 06/02/2024 12:31 PM

View differences:

ai/default/daieffects.c
case VUT_GOOD:
case VUT_MINCALFRAG:
case VUT_MAX_DISTANCE_SQ:
case VUT_MAX_REGION_TILES:
case VUT_COUNT:
/* No sensible implementation possible with data available. */
break;
ai/default/daimilitary.c
case VUT_TERRFLAG:
case VUT_TERRAINALTER:
case VUT_MAX_DISTANCE_SQ:
case VUT_MAX_REGION_TILES:
case VUT_NONE:
return tri_req_active(context, other_context, req);
case VUT_COUNT:
common/fc_types.h
int min_cities;
int latitude;
int distance_sq;
int region_tiles;
enum topo_flag topo_property;
enum wrap_flag wrap_property;
common/reqtext.c
}
break;
case VUT_MAX_REGION_TILES:
switch (preq->range) {
case REQ_RANGE_CONTINENT:
fc_strlcat(buf, prefix, bufsz);
if (preq->present) {
cat_snprintf(buf, bufsz,
_("Requires a continent or ocean size of at most %d."),
preq->source.value.region_tiles);
} else {
cat_snprintf(buf, bufsz,
_("Requires a continent or ocean size of at least %d."),
preq->source.value.region_tiles + 1);
}
return TRUE;
case REQ_RANGE_PLAYER:
case REQ_RANGE_TEAM:
case REQ_RANGE_ALLIANCE:
case REQ_RANGE_WORLD:
case REQ_RANGE_LOCAL:
case REQ_RANGE_TILE:
case REQ_RANGE_CADJACENT:
case REQ_RANGE_ADJACENT:
case REQ_RANGE_CITY:
case REQ_RANGE_TRADE_ROUTE:
case REQ_RANGE_COUNT:
/* Not supported. */
break;
}
break;
case VUT_COUNT:
break;
}
common/requirements.c
return;
}
break;
case VUT_MAX_REGION_TILES:
source->value.region_tiles = atoi(value);
if (0 < source->value.region_tiles) {
return;
}
break;
case VUT_COUNT:
break;
}
......
case VUT_MAX_DISTANCE_SQ:
source.value.distance_sq = value;
return source;
case VUT_MAX_REGION_TILES:
source.value.region_tiles = value;
return source;
case VUT_COUNT:
break;
}
......
return source->value.latitude;
case VUT_MAX_DISTANCE_SQ:
return source->value.distance_sq;
case VUT_MAX_REGION_TILES:
return source->value.region_tiles;
case VUT_COUNT:
break;
}
......
case VUT_SERVERSETTING:
req.range = REQ_RANGE_WORLD;
break;
case VUT_MAX_REGION_TILES:
req.range = REQ_RANGE_CONTINENT;
break;
}
}
......
case VUT_PLAYER_STATE:
invalid = (req.range != REQ_RANGE_PLAYER);
break;
case VUT_MAX_REGION_TILES:
invalid = (req.range != REQ_RANGE_CONTINENT);
break;
case VUT_IMPROVEMENT:
/* Valid ranges depend on the building genus (wonder/improvement),
* which might not have been loaded from the ruleset yet.
......
case VUT_MINLATITUDE:
case VUT_MAXLATITUDE:
case VUT_MAX_DISTANCE_SQ:
case VUT_MAX_REGION_TILES:
/* Most requirements don't support 'survives'. */
invalid = survives;
break;
......
return are_bounds_contradictions(
req1->source.value.distance_sq, req1->present,
req2->source.value.distance_sq, req2->present);
case VUT_MAX_REGION_TILES:
if (req2->source.kind != VUT_MAX_REGION_TILES) {
/* Finding contradictions across requirement kinds isn't supported
* for MaxRegionTiles requirements. */
return FALSE;
}
return are_bounds_contradictions(
req1->source.value.region_tiles, req1->present,
req2->source.value.region_tiles, req2->present);
default:
/* No special knowledge exists. The requirements aren't the exact
* opposite of each other per the initial check. */
......
return TRI_MAYBE;
}
/**********************************************************************//**
Determine whether a maximum tiles of same region requirement is satisfied
in a given context, ignoring parts of the requirement that can be handled
uniformly for all requirement types.
context, other_context and req must not be null,
and req must be a max region tiles requirement
**************************************************************************/
static enum fc_tristate
is_max_region_tiles_req_active(const struct civ_map *nmap,
const struct req_context *context,
const struct req_context *other_context,
const struct requirement *req)
{
int max_tiles, min_tiles = 1;
IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MAX_REGION_TILES);
switch (req->range) {
case REQ_RANGE_CONTINENT:
{
Continent_id cont = context->tile ? tile_continent(context->tile) : 0;
fc_assert_ret_val(cont <= nmap->num_continents, TRI_MAYBE);
fc_assert_ret_val(-cont <= nmap->num_oceans, TRI_MAYBE);
/* Note: We could come up with a better upper bound by subtracting
* all other continent/ocean sizes, or all except the largest if we
* don't know the tile.
* We could even do a flood-fill count of the unknown area bordered
* by known tiles of the continent.
* Probably not worth the effort though. */
max_tiles = nmap->xsize * nmap->ysize;
if (cont > 0) {
min_tiles = nmap->continent_sizes[cont];
if (is_server() || (nmap->client.continent_unknown_adj_counts[cont]
== 0)) {
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)) {
max_tiles = min_tiles;
}
}
}
break;
default:
fc_assert_msg(FALSE,
"Illegal range %d for max region tiles requirement.",
req->range);
return TRI_MAYBE;
}
if (min_tiles > req->source.value.region_tiles) {
return TRI_NO;
} else if (max_tiles <= req->source.value.region_tiles) {
return TRI_YES;
}
return TRI_MAYBE;
}
/**********************************************************************//**
Determine whether a minimum year requirement is satisfied in a given
context, ignoring parts of the requirement that can be handled uniformly
......
[VUT_PLAYER_FLAG] = {is_plr_flag_req_active, REQUCH_NO},
[VUT_PLAYER_STATE] = {is_plr_state_req_active, REQUCH_NO},
[VUT_MAX_DISTANCE_SQ] = {is_max_distance_sq_req_active, REQUCH_YES},
[VUT_MAX_REGION_TILES] = {is_max_region_tiles_req_active, REQUCH_NO},
[VUT_MAXLATITUDE] = {is_latitude_req_active, REQUCH_YES},
[VUT_MAXTILEUNITS] = {is_maxunitsontile_req_active, REQUCH_NO},
[VUT_MINCALFRAG] = {is_mincalfrag_req_active, REQUCH_NO},
......
case VUT_TERRAINALTER:
case VUT_MINYEAR:
case VUT_MAX_DISTANCE_SQ:
case VUT_MAX_REGION_TILES:
case VUT_NONE:
case VUT_COUNT:
/* Not implemented. */
......
return psource1->value.latitude == psource2->value.latitude;
case VUT_MAX_DISTANCE_SQ:
return psource1->value.distance_sq == psource2->value.distance_sq;
case VUT_MAX_REGION_TILES:
return psource1->value.region_tiles == psource2->value.region_tiles;
case VUT_COUNT:
break;
}
......
case VUT_MAX_DISTANCE_SQ:
fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.distance_sq);
return buffer;
case VUT_MAX_REGION_TILES:
fc_snprintf(buffer, sizeof(buffer), "%d", psource->value.region_tiles);
return buffer;
case VUT_COUNT:
break;
......
cat_snprintf(buf, bufsz, _("Squared distance <= %d"),
psource->value.distance_sq);
return buf;
case VUT_MAX_REGION_TILES:
cat_snprintf(buf, bufsz, _("%d or fewer region tiles"),
psource->value.region_tiles);
return buf;
case VUT_COUNT:
break;
}
doc/README.effects
MinVeteran: Local
MinHitPoints: Local
MaxDistanceSq: Tile
MaxRegionTiles: Continent
MinSize is the minimum size of a city required.
......
MaxDistanceSq is about the (squared) distance between two tiles; currently
only available for action enablers (see also README.actions) and a select
few effects.
MaxRegionTiles is continent or ocean size (number of tiles).
CityStatus is "OwnedByOriginal", "Transferred", "Starved",
"Disorder", or "Celebration"
The difference between "OwnedByOriginal" and "Transferred" is that
gen_headers/enums/fc_types_enums.def
MAXLATITUDE "MaxLatitude"
MAXTILEUNITS "MaxUnitsOnTile"
MAX_DISTANCE_SQ "MaxDistanceSq"
MAX_REGION_TILES "MaxRegionTiles"
MINCALFRAG "MinCalFrag"
MINCITIES "MinCities"
MINCULTURE "MinCulture"
server/cityturn.c
pcity, "have_terrainflag");
}
break;
case VUT_MAX_REGION_TILES:
/* Changing the continent size is hard; cf. VUT_TERRAINCLASS above.
* Change this when we support less fixed ranges (e.g. city?). */
purge = TRUE;
break;
case VUT_ROADFLAG:
if (preq->present) {
notify_player(pplayer, city_tile(pcity),
server/ruleset/rssanity.c
case VUT_ORIGINAL_OWNER: /* City range -> only one original owner */
case VUT_FORM_AGE:
case VUT_MAX_DISTANCE_SQ: /* Breaks nothing, but has no sense either */
case VUT_MAX_REGION_TILES: /* Breaks nothing, but has no sense either */
/* There can be only one requirement of these types (with current
* range limitations)
* Requirements might be identical, but we consider multiple
tools/ruledit/univ_value.c
case VUT_MAX_DISTANCE_SQ:
src->value.distance_sq = 0;
return TRUE;
case VUT_MAX_REGION_TILES:
src->value.region_tiles = 0;
return TRUE;
case VUT_COUNT:
fc_assert(src->kind != VUT_COUNT);
return FALSE;
......
case VUT_MINLATITUDE:
case VUT_MAXLATITUDE:
case VUT_MAX_DISTANCE_SQ:
case VUT_MAX_REGION_TILES:
/* Requirement types having numerical value */
cb(nullptr, FALSE, data);
break;
(4-4/4)