Feature #1732 ยป 0036-Add-tiledef-requirement-type.patch
| ai/default/daicity.c | ||
|---|---|---|
|
/* Unskilled in channel digging and merchantry */
|
||
|
case VUT_TERRAIN:
|
||
|
case VUT_EXTRA:
|
||
|
case VUT_TILEDEF:
|
||
|
case VUT_GOOD:
|
||
|
case VUT_TERRAINCLASS:
|
||
|
case VUT_TERRFLAG:
|
||
| ai/default/daieffects.c | ||
|---|---|---|
|
case VUT_ROADFLAG:
|
||
|
case VUT_EXTRAFLAG:
|
||
|
case VUT_EXTRA:
|
||
|
case VUT_TILEDEF:
|
||
|
/* 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_ROADFLAG:
|
||
|
case VUT_TERRAIN:
|
||
|
case VUT_EXTRA:
|
||
|
case VUT_TILEDEF:
|
||
|
case VUT_GOOD:
|
||
|
case VUT_TERRAINCLASS:
|
||
|
case VUT_TERRFLAG:
|
||
| common/extras.h | ||
|---|---|---|
|
} extra_type_list_iterate_rev_end \
|
||
|
}
|
||
|
/* TODO: Tiledef requirement types */
|
||
|
#define extra_deps_iterate(_reqs, _dep) \
|
||
|
{ \
|
||
|
requirement_vector_iterate(_reqs, preq) { \
|
||
| common/fc_types.h | ||
|---|---|---|
|
struct unit_class *uclass;
|
||
|
const struct unit_type *utype;
|
||
|
struct extra_type *extra;
|
||
|
struct tiledef *tiledef;
|
||
|
struct achievement *achievement;
|
||
|
struct nation_group *nationgroup;
|
||
|
struct nation_style *style;
|
||
| common/metaknowledge.c | ||
|---|---|---|
|
|| req->source.kind == VUT_TERRAINALTER
|
||
|
|| req->source.kind == VUT_EXTRA
|
||
|
|| req->source.kind == VUT_EXTRAFLAG
|
||
|
|| req->source.kind == VUT_ROADFLAG) {
|
||
|
|| req->source.kind == VUT_ROADFLAG
|
||
|
|| req->source.kind == VUT_TILEDEF) {
|
||
|
if (context->tile == nullptr) {
|
||
|
/* The tile may exist but not be passed when the problem type is
|
||
|
* RPT_POSSIBLE. */
|
||
| common/reqtext.c | ||
|---|---|---|
|
#include "server_settings.h"
|
||
|
#include "specialist.h"
|
||
|
#include "terrain.h"
|
||
|
#include "tiledef.h"
|
||
|
#include "reqtext.h"
|
||
| ... | ... | |
|
}
|
||
|
break;
|
||
|
case VUT_TILEDEF:
|
||
|
switch (preq->range) {
|
||
|
case REQ_RANGE_LOCAL:
|
||
|
fc_strlcat(buf, prefix, bufsz);
|
||
|
if (preq->present) {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
_("Only applies to \"%s\" tiledef."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
} else {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
_("Does not apply to \"%s\" tiledef."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
}
|
||
|
return TRUE;
|
||
|
case REQ_RANGE_TILE:
|
||
|
fc_strlcat(buf, prefix, bufsz);
|
||
|
if (preq->present) {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Requires %s on the tile."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
} else {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Prevented by %s on the tile."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
}
|
||
|
return TRUE;
|
||
|
case REQ_RANGE_CADJACENT:
|
||
|
fc_strlcat(buf, prefix, bufsz);
|
||
|
if (preq->present) {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Requires %s on the tile or a cardinally "
|
||
|
"adjacent tile."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
} else {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Prevented by %s on the tile or any cardinally "
|
||
|
"adjacent tile."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
}
|
||
|
return TRUE;
|
||
|
case REQ_RANGE_ADJACENT:
|
||
|
fc_strlcat(buf, prefix, bufsz);
|
||
|
if (preq->present) {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Requires %s on the tile or an adjacent "
|
||
|
"tile."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
} else {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Prevented by %s on the tile or any adjacent "
|
||
|
"tile."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
}
|
||
|
return TRUE;
|
||
|
case REQ_RANGE_CITY:
|
||
|
fc_strlcat(buf, prefix, bufsz);
|
||
|
if (preq->present) {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Requires %s on a tile within the city "
|
||
|
"radius."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
} else {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Prevented by %s on any tile within the city "
|
||
|
"radius."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
}
|
||
|
return TRUE;
|
||
|
case REQ_RANGE_TRADE_ROUTE:
|
||
|
fc_strlcat(buf, prefix, bufsz);
|
||
|
if (preq->present) {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Requires %s on a tile within the city "
|
||
|
"radius, or the city radius of a trade partner."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
} else {
|
||
|
cat_snprintf(buf, bufsz,
|
||
|
Q_("?tiledef:Prevented by %s on any tile within the city "
|
||
|
"radius or the city radius of a trade partner."),
|
||
|
tiledef_name_translation(preq->source.value.tiledef));
|
||
|
}
|
||
|
return TRUE;
|
||
|
case REQ_RANGE_CONTINENT:
|
||
|
case REQ_RANGE_PLAYER:
|
||
|
case REQ_RANGE_TEAM:
|
||
|
case REQ_RANGE_ALLIANCE:
|
||
|
case REQ_RANGE_WORLD:
|
||
|
case REQ_RANGE_COUNT:
|
||
|
/* Not supported. */
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case VUT_GOOD:
|
||
|
switch (preq->range) {
|
||
|
case REQ_RANGE_CITY:
|
||
| common/requirements.c | ||
|---|---|---|
|
#include "server_settings.h"
|
||
|
#include "specialist.h"
|
||
|
#include "style.h"
|
||
|
#include "tiledef.h"
|
||
|
#include "victory.h" /* victory_enabled() */
|
||
|
#include "requirements.h"
|
||
| ... | ... | |
|
return;
|
||
|
}
|
||
|
break;
|
||
|
case VUT_TILEDEF:
|
||
|
source->value.tiledef = tiledef_by_rule_name(value);
|
||
|
if (source->value.tiledef != nullptr) {
|
||
|
return;
|
||
|
}
|
||
|
break;
|
||
|
case VUT_GOOD:
|
||
|
source->value.good = goods_by_rule_name(value);
|
||
|
if (source->value.good != nullptr) {
|
||
| ... | ... | |
|
case VUT_EXTRA:
|
||
|
source.value.extra = extra_by_number(value);
|
||
|
return source;
|
||
|
case VUT_TILEDEF:
|
||
|
source.value.tiledef = tiledef_by_number(value);
|
||
|
return source;
|
||
|
case VUT_GOOD:
|
||
|
source.value.good = goods_by_number(value);
|
||
|
return source;
|
||
| ... | ... | |
|
return source->value.plr_flag;
|
||
|
case VUT_EXTRA:
|
||
|
return extra_number(source->value.extra);
|
||
|
case VUT_TILEDEF:
|
||
|
return tiledef_number(source->value.tiledef);
|
||
|
case VUT_GOOD:
|
||
|
return goods_number(source->value.good);
|
||
|
case VUT_TERRAIN:
|
||
| ... | ... | |
|
req.range = REQ_RANGE_LOCAL;
|
||
|
break;
|
||
|
case VUT_EXTRA:
|
||
|
case VUT_TILEDEF:
|
||
|
case VUT_ROADFLAG:
|
||
|
case VUT_EXTRAFLAG:
|
||
|
/* Keep old behavior */
|
||
| ... | ... | |
|
case VUT_EXTRAFLAG:
|
||
|
invalid = (req.range > REQ_RANGE_TRADE_ROUTE);
|
||
|
break;
|
||
|
case VUT_TILEDEF:
|
||
|
invalid = (req.range > REQ_RANGE_TRADE_ROUTE
|
||
|
|| req.range == REQ_RANGE_LOCAL);
|
||
|
break;
|
||
|
case VUT_ACHIEVEMENT:
|
||
|
case VUT_MINTECHS:
|
||
|
case VUT_FUTURETECHS:
|
||
| ... | ... | |
|
case VUT_ROADFLAG:
|
||
|
case VUT_EXTRAFLAG:
|
||
|
case VUT_EXTRA:
|
||
|
case VUT_TILEDEF:
|
||
|
case VUT_GOOD:
|
||
|
case VUT_TECHFLAG:
|
||
|
case VUT_ACHIEVEMENT:
|
||
| ... | ... | |
|
return TRI_MAYBE;
|
||
|
}
|
||
|
/**********************************************************************//**
|
||
|
Determine whether a tiledef 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_req_active(const struct civ_map *nmap,
|
||
|
const struct req_context *context,
|
||
|
const struct req_context *other_context,
|
||
|
const struct requirement *req)
|
||
|
{
|
||
|
const struct tiledef *ptdef;
|
||
|
enum fc_tristate ret;
|
||
|
IS_REQ_ACTIVE_VARIANT_ASSERT(VUT_TILEDEF);
|
||
|
ptdef = req->source.value.tiledef;
|
||
|
switch (req->range) {
|
||
|
case REQ_RANGE_TILE:
|
||
|
/* The requirement is filled if the tile has tiledef of requested type. */
|
||
|
if (!context->tile) {
|
||
|
return TRI_MAYBE;
|
||
|
}
|
||
|
return BOOL_TO_TRISTATE(tile_matches_tiledef(ptdef, context->tile));
|
||
|
case REQ_RANGE_CADJACENT:
|
||
|
if (!context->tile) {
|
||
|
return TRI_MAYBE;
|
||
|
}
|
||
|
return BOOL_TO_TRISTATE(tile_matches_tiledef(ptdef, context->tile)
|
||
|
|| is_tiledef_card_near(nmap, context->tile, ptdef));
|
||
|
case REQ_RANGE_ADJACENT:
|
||
|
if (!context->tile) {
|
||
|
return TRI_MAYBE;
|
||
|
}
|
||
|
return BOOL_TO_TRISTATE(tile_matches_tiledef(ptdef, context->tile)
|
||
|
|| is_tiledef_near_tile(nmap, context->tile, ptdef));
|
||
|
case REQ_RANGE_CITY:
|
||
|
if (!context->city) {
|
||
|
return TRI_MAYBE;
|
||
|
}
|
||
|
city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
|
||
|
city_tile(context->city), ptile) {
|
||
|
if (tile_matches_tiledef(ptdef, ptile)) {
|
||
|
return TRI_YES;
|
||
|
}
|
||
|
} city_tile_iterate_end;
|
||
|
return TRI_NO;
|
||
|
case REQ_RANGE_TRADE_ROUTE:
|
||
|
if (!context->city) {
|
||
|
return TRI_MAYBE;
|
||
|
}
|
||
|
city_tile_iterate(nmap, city_map_radius_sq_get(context->city),
|
||
|
city_tile(context->city), ptile) {
|
||
|
if (tile_matches_tiledef(ptdef, ptile)) {
|
||
|
return TRI_YES;
|
||
|
}
|
||
|
} city_tile_iterate_end;
|
||
|
ret = TRI_NO;
|
||
|
trade_partners_iterate(context->city, trade_partner) {
|
||
|
if (trade_partner == nullptr) {
|
||
|
ret = TRI_MAYBE;
|
||
|
} else {
|
||
|
city_tile_iterate(nmap, city_map_radius_sq_get(trade_partner),
|
||
|
city_tile(trade_partner), ptile) {
|
||
|
if (tile_matches_tiledef(ptdef, ptile)) {
|
||
|
return TRI_YES;
|
||
|
}
|
||
|
} city_tile_iterate_end;
|
||
|
}
|
||
|
} trade_partners_iterate_end;
|
||
|
return ret;
|
||
|
case REQ_RANGE_LOCAL:
|
||
|
case REQ_RANGE_CONTINENT:
|
||
|
case REQ_RANGE_PLAYER:
|
||
|
case REQ_RANGE_TEAM:
|
||
|
case REQ_RANGE_ALLIANCE:
|
||
|
case REQ_RANGE_WORLD:
|
||
|
case REQ_RANGE_COUNT:
|
||
|
break;
|
||
|
}
|
||
|
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] = {is_diplrel_unitany_req_active, REQUCH_NO},
|
||
|
[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_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_MINCALFRAG:
|
||
|
case VUT_TERRAIN:
|
||
|
case VUT_EXTRA:
|
||
|
case VUT_TILEDEF:
|
||
|
case VUT_GOOD:
|
||
|
case VUT_TERRAINCLASS:
|
||
|
case VUT_TERRFLAG:
|
||
| ... | ... | |
|
return psource1->value.plrstate == psource2->value.plrstate;
|
||
|
case VUT_EXTRA:
|
||
|
return psource1->value.extra == psource2->value.extra;
|
||
|
case VUT_TILEDEF:
|
||
|
return psource1->value.tiledef == psource2->value.tiledef;
|
||
|
case VUT_GOOD:
|
||
|
return psource1->value.good == psource2->value.good;
|
||
|
case VUT_TERRAIN:
|
||
| ... | ... | |
|
return plrstate_type_name(psource->value.plrstate);
|
||
|
case VUT_EXTRA:
|
||
|
return extra_rule_name(psource->value.extra);
|
||
|
case VUT_TILEDEF:
|
||
|
return tiledef_rule_name(psource->value.tiledef);
|
||
|
case VUT_GOOD:
|
||
|
return goods_rule_name(psource->value.good);
|
||
|
case VUT_TERRAIN:
|
||
| ... | ... | |
|
case VUT_EXTRA:
|
||
|
fc_strlcat(buf, extra_name_translation(psource->value.extra), bufsz);
|
||
|
return buf;
|
||
|
case VUT_TILEDEF:
|
||
|
fc_strlcat(buf, tiledef_name_translation(psource->value.tiledef), bufsz);
|
||
|
return buf;
|
||
|
case VUT_GOOD:
|
||
|
fc_strlcat(buf, goods_name_translation(psource->value.good), bufsz);
|
||
|
return buf;
|
||
| ... | ... | |
|
/**********************************************************************//**
|
||
|
Find if an extra type fulfills a requirement
|
||
|
TODO: Handle simple VUT_TILEDEF cases.
|
||
|
**************************************************************************/
|
||
|
static enum req_item_found extra_type_found(const struct requirement *preq,
|
||
|
const struct universal *source)
|
||
| doc/README.effects | ||
|---|---|---|
|
Site: World, Alliance, Team, Player, Continent, Traderoute,
|
||
|
City, Tile, Local
|
||
|
Extra: Local, Tile, Adjacent, CAdjacent, Traderoute, City
|
||
|
Tiledef: Tile, Adjacent, CAdjacent, Traderoute, 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 | ||
|---|---|---|
|
/* More generic terrain type currently "Land" or "Ocean" */
|
||
|
TERRAINCLASS "TerrainClass"
|
||
|
TERRFLAG "TerrainFlag"
|
||
|
TILEDEF "Tiledef"
|
||
|
TILE_REL "TileRel"
|
||
|
TOPO "Topology"
|
||
|
UCFLAG "UnitClassFlag"
|
||
| server/cityturn.c | ||
|---|---|---|
|
#include "server_settings.h"
|
||
|
#include "specialist.h"
|
||
|
#include "tech.h"
|
||
|
#include "tiledef.h"
|
||
|
#include "traderoutes.h"
|
||
|
#include "unit.h"
|
||
|
#include "unitlist.h"
|
||
| ... | ... | |
|
pcity, "have_extra");
|
||
|
}
|
||
|
break;
|
||
|
case VUT_TILEDEF:
|
||
|
if (preq->present) {
|
||
|
notify_player(pplayer, city_tile(pcity),
|
||
|
E_CITY_CANTBUILD, ftc_server,
|
||
|
Q_("?tiledef:%s can't build %s from the worklist; "
|
||
|
"%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");
|
||
|
} else {
|
||
|
notify_player(pplayer, city_tile(pcity),
|
||
|
E_CITY_CANTBUILD, ftc_server,
|
||
|
Q_("?tiledef:%s can't build %s from the worklist; "
|
||
|
"%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");
|
||
|
}
|
||
|
break;
|
||
|
case VUT_GOOD:
|
||
|
if (preq->present) {
|
||
|
notify_player(pplayer, city_tile(pcity),
|
||
| server/ruleset/rssanity.c | ||
|---|---|---|
|
case VUT_WRAP:
|
||
|
/* Can have multiple, since it's flag based (wrapx & wrapy) */
|
||
|
case VUT_EXTRA:
|
||
|
case VUT_TILEDEF:
|
||
|
/* Note that there can be more than 1 extra / tile. */
|
||
|
case VUT_MAXTILETOTALUNITS:
|
||
|
case VUT_MAXTILETOPUNITS:
|
||
| tools/ruledit/univ_value.c | ||
|---|---|---|
|
#include "server_settings.h"
|
||
|
#include "specialist.h"
|
||
|
#include "tech.h"
|
||
|
#include "tiledef.h"
|
||
|
#include "traderoutes.h"
|
||
|
/* server */
|
||
| ... | ... | |
|
}
|
||
|
src->value.extra = extra_by_number(0);
|
||
|
return TRUE;
|
||
|
case VUT_TILEDEF:
|
||
|
if (game.control.num_tiledef_types <= 0) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
src->value.tiledef = tiledef_by_number(0);
|
||
|
return TRUE;
|
||
|
case VUT_TECHFLAG:
|
||
|
src->value.techflag = TF_BONUS_TECH;
|
||
|
return TRUE;
|
||
| ... | ... | |
|
cb(extra_rule_name(pextra), univ->value.extra == pextra, data);
|
||
|
} extra_type_re_active_iterate_end;
|
||
|
break;
|
||
|
case VUT_TILEDEF:
|
||
|
tiledef_iterate(ptd) {
|
||
|
cb(tiledef_rule_name(ptd), univ->value.tiledef == ptd, data);
|
||
|
} tiledef_iterate_end;
|
||
|
break;
|
||
|
case VUT_STYLE:
|
||
|
styles_re_active_iterate(pstyle) {
|
||
|
cb(style_rule_name(pstyle), univ->value.style == pstyle, data);
|
||