Feature #652 » 0007-Support-MaxRegionTiles-at-C-Adjacent-ranges.patch
common/reqtext.c | ||
---|---|---|
case VUT_MAX_REGION_TILES:
|
||
switch (preq->range) {
|
||
case REQ_RANGE_CADJACENT:
|
||
fc_strlcat(buf, prefix, bufsz);
|
||
/* Off-by-one: The requirement counts the tile itself, we're phrasing
|
||
* the helptext in terms of *other* tiles only. */
|
||
if (preq->present) {
|
||
if (preq->source.value.region_tiles == 1) {
|
||
/* Special case for zero */
|
||
fc_strlcat(buf,
|
||
_("No other cardinally adjacent tile may be part of "
|
||
"the same continent or ocean."),
|
||
bufsz);
|
||
} else {
|
||
cat_snprintf(buf, bufsz,
|
||
PL_("No more than %d other cardinally adjacent tile "
|
||
"may be part of the same continent or ocean.",
|
||
"No more than %d other cardinally adjacent tiles "
|
||
"may be part of the same continent or ocean.",
|
||
preq->source.value.region_tiles - 1),
|
||
preq->source.value.region_tiles - 1);
|
||
}
|
||
} else {
|
||
cat_snprintf(buf, bufsz,
|
||
PL_("Requires at least %d other cardinally adjacent "
|
||
"tile of the same continent or ocean.",
|
||
"Requires at least %d other cardinally adjacent "
|
||
"tiles of the same continent or ocean.",
|
||
preq->source.value.region_tiles),
|
||
preq->source.value.region_tiles);
|
||
}
|
||
return TRUE;
|
||
case REQ_RANGE_ADJACENT:
|
||
fc_strlcat(buf, prefix, bufsz);
|
||
/* Off-by-one: The requirement counts the tile itself, we're phrasing
|
||
* the helptext in terms of *other* tiles only. */
|
||
if (preq->present) {
|
||
if (preq->source.value.region_tiles == 1) {
|
||
/* Special case for zero */
|
||
fc_strlcat(buf,
|
||
_("No other adjacent tile may be part of the same "
|
||
"continent or ocean."),
|
||
bufsz);
|
||
} else {
|
||
cat_snprintf(buf, bufsz,
|
||
PL_("No more than %d other adjacent tile may be "
|
||
"part of the same continent or ocean.",
|
||
"No more than %d other adjacent tiles may be "
|
||
"part of the same continent or ocean.",
|
||
preq->source.value.region_tiles - 1),
|
||
preq->source.value.region_tiles - 1);
|
||
}
|
||
} else {
|
||
cat_snprintf(buf, bufsz,
|
||
PL_("Requires at least %d other adjacent tile of the "
|
||
"same continent or ocean.",
|
||
"Requires at least %d other adjacent tiles of the "
|
||
"same continent or ocean.",
|
||
preq->source.value.region_tiles),
|
||
preq->source.value.region_tiles);
|
||
}
|
||
return TRUE;
|
||
case REQ_RANGE_CONTINENT:
|
||
fc_strlcat(buf, prefix, bufsz);
|
||
if (preq->present) {
|
||
... | ... | |
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:
|
common/requirements.c | ||
---|---|---|
invalid = (req.range != REQ_RANGE_PLAYER);
|
||
break;
|
||
case VUT_MAX_REGION_TILES:
|
||
invalid = (req.range != REQ_RANGE_CONTINENT);
|
||
invalid = (req.range != REQ_RANGE_CONTINENT
|
||
&& req.range != REQ_RANGE_CADJACENT
|
||
&& req.range != REQ_RANGE_ADJACENT);
|
||
break;
|
||
case VUT_IMPROVEMENT:
|
||
/* Valid ranges depend on the building genus (wonder/improvement),
|
||
... | ... | |
* for MaxRegionTiles requirements. */
|
||
return FALSE;
|
||
} else if (req1->range != req2->range) {
|
||
/* Counting completely separate things */
|
||
/* FIXME: Finding contradictions across ranges not yet supported.
|
||
* In particular, a max at a small range and a min at a larger range
|
||
* needs extra work to figure out. */
|
||
return FALSE;
|
||
}
|
||
return are_bounds_contradictions(
|
||
... | ... | |
const struct req_context *other_context,
|
||
const struct requirement *req)
|
||
{
|
||
int known_tiles;
|
||
bool known_accurate;
|
||
int max_tiles, min_tiles = 1;
|
||
IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_MAX_REGION_TILES);
|
||
switch (req->range) {
|
||
case REQ_RANGE_CADJACENT:
|
||
case REQ_RANGE_ADJACENT:
|
||
/* The tile itself is included in the range */
|
||
max_tiles = 1 + ((req->range == REQ_RANGE_CADJACENT)
|
||
? nmap->num_cardinal_dirs
|
||
: nmap->num_valid_dirs);
|
||
if (context->tile == nullptr || tile_continent(context->tile) == 0) {
|
||
/* Note: If we know the tile's position, we could come up with a
|
||
* better upper bound by checking how many [cardinally] adjacent
|
||
* tiles share the same continent/ocean among each other.
|
||
* Probably not worth the effort though. */
|
||
break;
|
||
} else {
|
||
Continent_id cont = tile_continent(context->tile);
|
||
const enum direction8 *dirlist = ((req->range == REQ_RANGE_CADJACENT)
|
||
? nmap->cardinal_dirs
|
||
: nmap->valid_dirs);
|
||
int dircount = max_tiles - 1;
|
||
adjc_dirlist_iterate(nmap, context->tile, adj_tile, _dir,
|
||
dirlist, dircount) {
|
||
Continent_id adj_cont = tile_continent(adj_tile);
|
||
if (adj_cont == cont) {
|
||
min_tiles++;
|
||
} else if (adj_cont != 0) {
|
||
max_tiles--;
|
||
}
|
||
} adjc_dirlist_iterate_end;
|
||
}
|
||
break;
|
||
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) {
|
||
known_tiles = nmap->continent_sizes[cont];
|
||
known_accurate = (is_server()
|
||
|| (nmap->client.continent_unknown_adj_counts[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) {
|
||
known_tiles = nmap->ocean_sizes[-cont];
|
||
known_accurate = (is_server()
|
||
|| (nmap->client.ocean_unknown_adj_counts[-cont] == 0));
|
||
} else {
|
||
/* Even if we don't know the continent, we know it has at least one
|
||
* tile (the target tile) */
|
||
known_tiles = 1;
|
||
known_accurate = FALSE;
|
||
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 tile number requirement.",
|
||
"Illegal range %d for max region tiles requirement.",
|
||
req->range);
|
||
return TRI_MAYBE;
|
||
}
|
||
if (known_tiles > req->source.value.region_tiles) {
|
||
/* We already know about more tiles than the limit */
|
||
if (min_tiles > req->source.value.region_tiles) {
|
||
return TRI_NO;
|
||
} else if (known_accurate) {
|
||
/* We know there aren't any more tiles that could break the limit */
|
||
} else if (max_tiles <= req->source.value.region_tiles) {
|
||
return TRI_YES;
|
||
}
|
||
return TRI_MAYBE;
|
doc/README.effects | ||
---|---|---|
MinVeteran: Local
|
||
MinHitPoints: Local
|
||
MaxDistanceSq: Tile
|
||
MaxRegionTiles: Continent
|
||
MaxRegionTiles: Continent, Adjacent, CAdjacent
|
||
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).
|
||
MaxRegionTiles is about the number of tiles of the same continent or ocean as
|
||
the target tile in the given range (including the tile itself). At "Continent"
|
||
range this is just the full continent/ocean size.
|
||
CityStatus is "OwnedByOriginal", "Transferred", "Starved",
|
||
"Disorder", or "Celebration"
|
||
The difference between "OwnedByOriginal" and "Transferred" is that
|
server/cityturn.c | ||
---|---|---|
break;
|
||
case VUT_MAX_REGION_TILES:
|
||
/* Changing the continent size is hard; cf. VUT_TERRAINCLASS above.
|
||
* Change this when we support other ranges. */
|
||
* Change this when we support less fixed ranges (e.g. city?). */
|
||
purge = TRUE;
|
||
break;
|
||
case VUT_ROADFLAG:
|
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
|
||
... | ... | |
/* Can have multiple requirements of these types */
|
||
case VUT_MINLATITUDE:
|
||
case VUT_MAXLATITUDE:
|
||
case VUT_MAX_REGION_TILES:
|
||
/* Can have multiple requirements at different ranges.
|
||
* TODO: Compare to number of legal ranges? */
|
||
break;
|