Project

General

Profile

Feature #1787 ยป 0056-Add-TiledefConnected-requirement-type.patch

Marko Lindqvist, 01/18/2026 01:49 PM

View differences:

ai/default/daieffects.c
case VUT_EXTRAFLAG:
case VUT_EXTRA:
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
/* TODO: These could be determined by building a map of all
* possible futures (e.g. terrain transformations, etc.),
* and traversing it for all tiles in largest possible range
ai/default/daimilitary.c
case VUT_TERRAIN:
case VUT_EXTRA:
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
case VUT_GOOD:
case VUT_TERRAINCLASS:
case VUT_TERRFLAG:
common/reqtext.c
}
/*************************************************************//**
Append text for a requirement type.
Append text for a requirement type.
returns TRUE if success, FALSE if any problem or "Not supported".
Returns TRUE if success, FALSE if any problem or "Not supported".
*****************************************************************/
static bool req_text_tiledef(char *buf, size_t bufsz,
struct player *pplayer,
......
/* Not supported. */
return FALSE;
}
return TRUE;
}
/*************************************************************//**
Append text for a requirement type.
Returns TRUE if success, FALSE if any problem or "Not supported".
*****************************************************************/
static bool req_text_tiledef_conn(char *buf, size_t bufsz,
struct player *pplayer,
const struct requirement *preq,
const char *prefix)
{
if (preq->range == REQ_RANGE_CITY) {
fc_strlcat(buf, prefix, bufsz);
if (preq->present) {
cat_snprintf(buf, bufsz,
Q_("tdconn:Requires access to tiledef %s."),
tiledef_name_translation(preq->source.value.tiledef));
} else {
cat_snprintf(buf, bufsz,
Q_("?tdconn:Prevented by access to tiledef %s."),
tiledef_name_translation(preq->source.value.tiledef));
}
return TRUE;
}
/* Not supported. */
return FALSE;
}
/*************************************************************//**
Append text for a requirement type.
......
case VUT_TILEDEF:
return req_text_tiledef(buf, bufsz, pplayer, preq, prefix);
case VUT_TILEDEF_CONNECTED:
return req_text_tiledef_conn(buf, bufsz, pplayer, preq, prefix);
case VUT_GOOD:
return req_text_good(buf, bufsz, pplayer, preq, prefix);
common/requirements.c
}
break;
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
source->value.tiledef = tiledef_by_rule_name(value);
if (source->value.tiledef != nullptr) {
return;
......
source.value.extra = extra_by_number(value);
return source;
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
source.value.tiledef = tiledef_by_number(value);
return source;
case VUT_GOOD:
......
case VUT_EXTRA:
return extra_number(source->value.extra);
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
return tiledef_number(source->value.tiledef);
case VUT_GOOD:
return goods_number(source->value.good);
......
case VUT_ORIGINAL_OWNER:
case VUT_CITYSTATUS:
case VUT_GOOD:
case VUT_TILEDEF_CONNECTED:
req.range = REQ_RANGE_CITY;
break;
case VUT_GOVERNMENT:
......
break;
case VUT_GOOD:
case VUT_ORIGINAL_OWNER:
case VUT_TILEDEF_CONNECTED:
invalid = (req.range != REQ_RANGE_CITY);
break;
case VUT_MINCULTURE:
......
case VUT_EXTRAFLAG:
case VUT_EXTRA:
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
case VUT_GOOD:
case VUT_TECHFLAG:
case VUT_ACHIEVEMENT:
......
return TRI_MAYBE;
}
/**********************************************************************//**
Determine whether a tiledef connected 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 tiledef requirement
**************************************************************************/
static enum fc_tristate
is_tiledef_conn_req_active(const struct civ_map *nmap,
const struct req_context *context,
const struct req_context *other_context,
const struct requirement *req)
{
IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TILEDEF_CONNECTED);
if (!is_server()) {
/* Client does not know about access areas */
return TRI_MAYBE;
}
if (req->range == REQ_RANGE_CITY) {
if (context->city == nullptr
|| context->city->server.aarea == nullptr) {
return TRI_MAYBE;
}
if (BV_ISSET(context->city->server.aarea->tiledefs,
tiledef_index(req->source.value.tiledef))) {
return TRI_YES;
}
return TRI_NO;
}
fc_assert_msg(FALSE, "Invalid range %d.", req->range);
return TRI_MAYBE;
}
/**********************************************************************//**
Determine whether a goods requirement is satisfied in a given context,
ignoring parts of the requirement that can be handled uniformly for all
......
[VUT_DIPLREL_UNITANY_O] = {is_diplrel_unitany_o_req_active, REQUCH_NO},
[VUT_EXTRA] = {is_extra_req_active, REQUCH_NO, REQUC_LOCAL},
[VUT_TILEDEF] = {is_tiledef_req_active, REQUCH_NO, REQUC_LOCAL},
[VUT_TILEDEF_CONNECTED] = {is_tiledef_conn_req_active, REQUCH_NO, REQUC_LOCAL},
[VUT_EXTRAFLAG] = {is_extraflag_req_active, REQUCH_NO, REQUC_LOCAL},
[VUT_FUTURETECHS] = {is_futuretechs_req_active, REQUCH_ACT, REQUC_WORLD},
[VUT_GOOD] = {is_good_req_active, REQUCH_NO},
......
case VUT_TERRAIN:
case VUT_EXTRA:
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
case VUT_GOOD:
case VUT_TERRAINCLASS:
case VUT_TERRFLAG:
......
case VUT_EXTRA:
return psource1->value.extra == psource2->value.extra;
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
return psource1->value.tiledef == psource2->value.tiledef;
case VUT_GOOD:
return psource1->value.good == psource2->value.good;
......
case VUT_EXTRA:
return extra_rule_name(psource->value.extra);
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
return tiledef_rule_name(psource->value.tiledef);
case VUT_GOOD:
return goods_rule_name(psource->value.good);
......
fc_strlcat(buf, extra_name_translation(psource->value.extra), bufsz);
return buf;
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
fc_strlcat(buf, tiledef_name_translation(psource->value.tiledef), bufsz);
return buf;
case VUT_GOOD:
doc/README.effects
City, Tile, Local
Extra: Local, Tile, Adjacent, CAdjacent, Traderoute, City
Tiledef: Tile, Adjacent, CAdjacent, Traderoute, City
TiledefConnected: City
RoadFlag: Local, Tile, Adjacent, CAdjacent, Traderoute, City
ExtraFlag: Local, Tile, Adjacent, CAdjacent, Traderoute, City
Terrain: Tile, Adjacent, CAdjacent, Traderoute, City
gen_headers/enums/fc_types_enums.def
TERRAINCLASS "TerrainClass"
TERRFLAG "TerrainFlag"
TILEDEF "Tiledef"
TILEDEF_CONNECTED "TiledefConnected"
TILE_REL "TileRel"
TOPO "Topology"
UCFLAG "UnitClassFlag"
server/cityturn.c
pcity, "have_tiledef");
}
break;
case VUT_TILEDEF_CONNECTED:
if (preq->present) {
notify_player(pplayer, city_tile(pcity),
E_CITY_CANTBUILD, ftc_server,
Q_("?tdconn:%s can't build %s from the worklist; "
"access to %s is required. Postponing..."),
city_link(pcity),
tgt_name,
tiledef_name_translation(preq->source.value.tiledef));
script_server_signal_emit(signal_name, ptarget,
pcity, "need_tiledef_conn");
} else {
notify_player(pplayer, city_tile(pcity),
E_CITY_CANTBUILD, ftc_server,
Q_("?tdconn:%s can't build %s from the worklist; "
"access to %s is prohibited. Postponing..."),
city_link(pcity),
tgt_name,
tiledef_name_translation(preq->source.value.tiledef));
script_server_signal_emit(signal_name, ptarget,
pcity, "have_tiledef_conn");
}
break;
case VUT_GOOD:
if (preq->present) {
notify_player(pplayer, city_tile(pcity),
server/ruleset/rssanity.c
/* Can have multiple, since it's flag based (wrapx & wrapy) */
case VUT_EXTRA:
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
/* Note that there can be more than 1 extra / tile. */
case VUT_MAXTILETOTALUNITS:
case VUT_MAXTILETOPUNITS:
tools/ruledit/univ_value.c
src->value.extra = extra_by_number(0);
return TRUE;
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
if (game.control.num_tiledef_types <= 0) {
return FALSE;
}
......
} extra_type_re_active_iterate_end;
break;
case VUT_TILEDEF:
case VUT_TILEDEF_CONNECTED:
tiledef_iterate(ptd) {
cb(tiledef_rule_name(ptd), univ->value.tiledef == ptd, data);
} tiledef_iterate_end;
    (1-1/1)