Feature #678 » 0009-Add-Same-Terrain-Class-TileRel-requirement.patch
common/metaknowledge.c | ||
---|---|---|
}
|
||
if (req->source.kind == VUT_TILE_REL) {
|
||
enum known_type needed;
|
||
if (context->tile == NULL || other_context->tile == NULL) {
|
||
/* The tile may exist but not be passed when the problem type is
|
||
* RPT_POSSIBLE. */
|
||
return prob_type == RPT_CERTAIN;
|
||
}
|
||
if (tile_get_known(other_context->tile, pov_player) == TILE_UNKNOWN) {
|
||
switch (req->source.value.tilerel) {
|
||
case TREL_REGION_SURROUNDED:
|
||
/* Too complicated to figure out */
|
||
return FALSE;
|
||
case TREL_SAME_TCLASS:
|
||
/* Evaluated based on actual terrain type's class */
|
||
needed = TILE_KNOWN_SEEN;
|
||
break;
|
||
default:
|
||
/* Only need the continent ID; known is enough */
|
||
needed = TILE_KNOWN_UNSEEN;
|
||
break;
|
||
}
|
||
if (req->source.value.tilerel == TREL_REGION_SURROUNDED) {
|
||
/* Too complicated to figure out */
|
||
if (tile_get_known(other_context->tile, pov_player) < needed) {
|
||
return FALSE;
|
||
}
|
||
... | ... | |
case REQ_RANGE_ADJACENT:
|
||
/* TODO: Known tiles might be enough to determine the answer already;
|
||
* should we check on an individual requirement basis? */
|
||
if (tile_get_known(context->tile, pov_player) == TILE_UNKNOWN) {
|
||
if (tile_get_known(context->tile, pov_player) < needed) {
|
||
return FALSE;
|
||
}
|
||
range_adjc_iterate(&(wld.map), context->tile, req->range, adj_tile) {
|
||
if (tile_get_known(adj_tile, pov_player) == TILE_UNKNOWN) {
|
||
if (tile_get_known(adj_tile, pov_player) < needed) {
|
||
return FALSE;
|
||
}
|
||
} range_adjc_iterate_end;
|
common/reqtext.c | ||
---|---|---|
case VUT_TILE_REL:
|
||
switch (preq->source.value.tilerel) {
|
||
case TREL_SAME_TCLASS:
|
||
switch (preq->range) {
|
||
case REQ_RANGE_TILE:
|
||
fc_strlcat(buf, prefix, bufsz);
|
||
if (preq->present) {
|
||
fc_strlcat(buf, _("Must be on the same terrain class."),
|
||
bufsz);
|
||
} else {
|
||
fc_strlcat(buf, _("Must be on a different terrain class."),
|
||
bufsz);
|
||
}
|
||
return TRUE;
|
||
case REQ_RANGE_CADJACENT:
|
||
fc_strlcat(buf, prefix, bufsz);
|
||
if (preq->present) {
|
||
fc_strlcat(buf, _("Must be cardinally adjacent to the same "
|
||
"terrain class."),
|
||
bufsz);
|
||
} else {
|
||
fc_strlcat(buf, _("Must not be cardinally adjacent to the same "
|
||
"terrain class."),
|
||
bufsz);
|
||
}
|
||
return TRUE;
|
||
case REQ_RANGE_ADJACENT:
|
||
fc_strlcat(buf, prefix, bufsz);
|
||
if (preq->present) {
|
||
fc_strlcat(buf, _("Must be adjacent to the same terrain class."),
|
||
bufsz);
|
||
} else {
|
||
fc_strlcat(buf, _("Must not be adjacent to the same terrain "
|
||
"class."),
|
||
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_SAME_REGION:
|
||
switch (preq->range) {
|
||
case REQ_RANGE_TILE:
|
common/requirements.c | ||
---|---|---|
/* Same requirement at different ranges. Note that same range is
|
||
* already covered by are_requirements_opposites() above. */
|
||
switch (req1->source.value.tilerel) {
|
||
case TREL_SAME_TCLASS:
|
||
case TREL_SAME_REGION:
|
||
case TREL_REGION_SURROUNDED:
|
||
/* Negated req at larger range contradicts present req at
|
||
... | ... | |
return FALSE;
|
||
}
|
||
}
|
||
if (req1->source.value.tilerel == TREL_REGION_SURROUNDED
|
||
|| req2->source.value.tilerel == TREL_REGION_SURROUNDED) {
|
||
if (req1->source.value.tilerel == TREL_SAME_TCLASS
|
||
&& req2->source.value.tilerel == TREL_SAME_REGION) {
|
||
/* Same region at any range implies same terrain class at that range
|
||
* and any larger range ~> contradicts negated */
|
||
return (!req1->present && req2->present
|
||
&& (req1->range >= req2->range));
|
||
} else if (req2->source.value.tilerel == TREL_SAME_TCLASS
|
||
&& req1->source.value.tilerel == TREL_SAME_REGION) {
|
||
/* Same as above */
|
||
return (req1->present && !req2->present
|
||
&& (req1->range <= req2->range));
|
||
} else 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;
|
||
... | ... | |
}
|
||
if (surr->present && surr->range == REQ_RANGE_TILE) {
|
||
/* Target tile must be part of a surrounded region
|
||
* ~> not the same terrain class
|
||
* ~> not the same region
|
||
* ~> not touched by a third region */
|
||
switch (other->source.value.tilerel) {
|
||
case TREL_SAME_TCLASS:
|
||
case TREL_SAME_REGION:
|
||
return (other->present && other->range == REQ_RANGE_TILE);
|
||
case TREL_ONLY_OTHER_REGION:
|
||
... | ... | |
}
|
||
switch (req->source.value.tilerel) {
|
||
case TREL_SAME_TCLASS:
|
||
if (tile_terrain(other_context->tile) == T_UNKNOWN) {
|
||
return TRI_MAYBE;
|
||
}
|
||
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_SAME_TCLASS));
|
||
{
|
||
enum terrain_class cls = terrain_type_terrain_class(
|
||
tile_terrain(other_context->tile));
|
||
bool seen_unknown = FALSE;
|
||
const struct terrain *terr;
|
||
if ((terr = tile_terrain(context->tile)) == T_UNKNOWN) {
|
||
seen_unknown = TRUE;
|
||
} else if (terrain_type_terrain_class(terr) == cls) {
|
||
return TRUE;
|
||
}
|
||
range_adjc_iterate(nmap, context->tile, req->range, adj_tile) {
|
||
if ((terr = tile_terrain(adj_tile)) == T_UNKNOWN) {
|
||
seen_unknown = TRUE;
|
||
} else if (terrain_type_terrain_class(terr) == cls) {
|
||
return TRUE;
|
||
}
|
||
} range_adjc_iterate_end;
|
||
if (seen_unknown) {
|
||
return TRI_MAYBE;
|
||
} else {
|
||
return TRI_NO;
|
||
}
|
||
}
|
||
break;
|
||
case TREL_SAME_REGION:
|
||
if (tile_continent(other_context->tile) == 0) {
|
||
return TRI_MAYBE;
|
||
... | ... | |
return buf;
|
||
case VUT_TILE_REL:
|
||
switch (psource->value.tilerel) {
|
||
case TREL_SAME_TCLASS:
|
||
fc_strlcat(buf, _("Same terrain class"), bufsz);
|
||
break;
|
||
case TREL_SAME_REGION:
|
||
fc_strlcat(buf, _("Same continent/ocean"), bufsz);
|
||
break;
|
doc/README.effects | ||
---|---|---|
(north pole).
|
||
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), "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), or "Region Surrounded" (on or adjacent to a lake/island touching only
|
||
the other tile's continent/ocean).
|
||
one of "Same Terrain Class" (on or adjacent to the same terrain class as the
|
||
other tile, depending on range), "Same Region" (on or adjacent to the same
|
||
continent/ocean as the other tile), "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), 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 | ||
---|---|---|
prefix TREL_
|
||
count
|
||
values
|
||
SAME_TCLASS "Same Terrain Class"
|
||
SAME_REGION "Same Region"
|
||
ONLY_OTHER_REGION "Only Other Region"
|
||
REGION_SURROUNDED "Region Surrounded"
|