16 #define GETTEXT_DOMAIN "wesnoth-lib"
31 #include "formula/callable_objects.hpp"
37 #include <boost/range/adaptor/transformed.hpp>
40 #define ERR_NG LOG_STREAM(err, log_engine)
41 #define WRN_NG LOG_STREAM(warn, log_engine)
44 #define ERR_WML LOG_STREAM(err, log_wml)
63 , max_loop_(original.max_loop_)
64 , flat_(original.flat_)
73 , max_loop_(other.max_loop_)
82 this->~terrain_filter();
83 new (
this) terrain_filter(other) ;
89 : parsed_terrain(nullptr)
90 , adjacent_matches(nullptr)
91 , adjacent_match_cache()
149 if (!found)
return false;
158 std::set<map_location> matching_locs;
161 if(test_loc.
valid()) {
162 matching_locs.insert(test_loc);
165 if (matching_locs.count(loc) == 0) {
186 vconfig::child_list::const_iterator
i, i_end = vis_filt.end();
187 for (
i = vis_filt.begin();
i != i_end; ++
i) {
188 bool visible = (*i)[
"visible"].to_bool(
true);
189 bool respect_fog = (*i)[
"respect_fog"].to_bool(
true);
192 std::vector<int> sides = ssf.
get_teams();
195 for (
const int side : sides) {
197 bool viewer_sees = respect_fog ? !viewing_team.
fogged(loc) : !viewing_team.
shrouded(loc);
198 if (visible == viewer_sees) {
203 if (!found) {
return false;}
211 vconfig::child_list::const_iterator
i, i_end, i_begin = adj_cfgs.begin();
212 for (
i = i_begin, i_end = adj_cfgs.end();
i != i_end; ++
i) {
214 vconfig::child_list::difference_type
index =
i - i_begin;
215 std::vector<map_location::direction> dirs = (*i).has_attribute(
"adjacent")
217 std::vector<map_location::direction>::const_iterator j, j_end = dirs.end();
218 for (j = dirs.begin(); j != j_end; ++j) {
219 const map_location &adj = adjacent[
static_cast<int>(*j)];
224 std::pair<terrain_filter, std::map<map_location,bool>> amc_pair(
226 std::map<map_location,bool>());
232 if(lookup == amc.end()) {
233 if(amc_filter(adj)) {
239 }
else if(lookup->second) {
245 if(amc.find(adj) != amc.end()) {
252 std::vector<std::pair<int,int>> counts = (*i).has_attribute(
"count")
262 const std::string& tod_type = t_tod_type;
263 const std::string& tod_id = t_tod_id;
264 if(!tod_type.empty() || !tod_id.empty()) {
274 if(!tod_type.empty()) {
275 const std::vector<std::string>& vals =
utils::split(tod_type);
277 if(std::find(vals.begin(),vals.end(), unit_alignments::chaotic) == vals.end()) {
281 if(std::find(vals.begin(),vals.end(), unit_alignments::lawful) == vals.end()) {
284 }
else if(std::find(vals.begin(),vals.end(), unit_alignments::neutral) == vals.end() &&
285 std::find(vals.begin(),vals.end(), unit_alignments::liminal) == vals.end()) {
290 if(!tod_id.empty()) {
291 if(tod_id != tod.
id) {
292 if(std::find(tod_id.begin(),tod_id.end(),
',') != tod_id.end() &&
293 std::search(tod_id.begin(),tod_id.end(),
294 tod.
id.begin(),tod.
id.end()) != tod_id.end()) {
295 const std::vector<std::string>& vals =
utils::split(tod_id);
296 if(std::find(vals.begin(),vals.end(),tod.
id) == vals.end()) {
309 if(!filter_owner.
null()) {
310 if(!owner_side.
empty()) {
311 WRN_NG <<
"duplicate side information in a SLF, ignoring inline owner_side=";
316 const std::vector<int>& sides = ssf.
get_teams();
320 for(
const int side : sides) {
329 else if(!owner_side.
empty()) {
330 const int side_num = owner_side.
to_int(0);
341 auto ref = std::make_shared<wfl::unit_callable>(*ref_unit);
352 lg::log_to_chat() <<
"Formula error in location filter: " <<
e.type <<
" at " <<
e.filename <<
':' <<
e.line <<
")\n";
353 ERR_WML <<
"Formula error in location filter: " <<
e.type <<
" at " <<
e.filename <<
':' <<
e.line <<
")";
368 return filt_.match(loc, ref_);
374 if(
cfg_[
"x"] ==
"recall" &&
cfg_[
"y"] ==
"recall") {
377 std::set<map_location> hexes;
378 std::vector<map_location> loc_vec(1, loc);
380 std::unique_ptr<scoped_wml_variable> ref_unit_var;
390 std::size_t radius =
cfg_[
"radius"].to_size_t(0);
397 hexes.insert(loc_vec.begin(), loc_vec.end());
409 std::size_t loop_count = 0;
410 std::set<map_location>::const_iterator
i;
411 for(
i = hexes.begin();
i != hexes.end(); ++
i) {
418 matches = matches &&
terrain_filter(filter, *
this).match_impl(*
i, ref_unit);
421 else if(key ==
"or") {
422 matches = matches ||
terrain_filter(filter, *
this).match_impl(*
i, ref_unit);
425 else if(key ==
"not") {
426 matches = matches && !
terrain_filter(filter, *
this).match_impl(*
i, ref_unit);
434 std::set<map_location>::const_iterator temp =
i;
435 if(++temp != hexes.end()) {
455 template<
typename T,
typename F1,
typename F2,
typename F3>
459 if (f1(loc) && f2(loc) && f3(loc)) {
465 template<
typename T,
typename F1,
typename F2>
468 if (filter.cfg_.has_attribute(
"location_id")) {
469 std::set<map_location> matching_locs;
470 for(
const auto&
id :
utils::split(filter.cfg_[
"location_id"])) {
471 map_location test_loc = filter.fc_->get_disp_context().map().special_location(
id);
472 if(test_loc.
valid()) {
473 matching_locs.insert(test_loc);
476 filter_final(
src, dest, filter, f1, f2, [matching_locs](
const map_location& loc) {
return matching_locs.count(loc) > 0; });
483 template<
typename T,
typename F1>
486 if (filter.cfg_.has_attribute(
"area")) {
487 const std::set<map_location>& area = filter.fc_->get_tod_man().get_area_by_id(filter.cfg_[
"area"]);
488 filter_special_loc(
src, dest, filter, f1, [&area](
const map_location& loc) {
return area.find(loc) != area.end(); });
498 if (filter.cfg_.has_attribute(
"x") || filter.cfg_.has_attribute(
"y")) {
499 std::vector<map_location> xy_vector = filter.fc_->get_disp_context().map().parse_location_range(filter.cfg_[
"x"], filter.cfg_[
"y"], with_border);
500 filter_area(
src, dest, filter, [&xy_vector](
const map_location& loc) {
return std::find(xy_vector.begin(), xy_vector.end(), loc) != xy_vector.end(); });
515 std::unique_ptr<scoped_wml_variable> ref_unit_var;
524 std::set<map_location> match_set;
527 with_border =
cfg_[
"include_borders"].to_bool(with_border);
534 auto ar = gd->get_variable_access_read(
cfg_[
"find_in"]).as_array();
554 if(test_loc.
valid()) {
555 match_set.insert(test_loc);
559 else if (
cfg_[
"gives_income"].to_bool()) {
568 for (
int x = with_border ? 0 - bs : 0; x <
w; ++x) {
569 for (
int y = with_border ? 0 - bs : 0; y <
h; ++y) {
581 for (
unsigned i = 0;
i < adj_cfgs.size(); ++
i) {
582 std::set<map_location> adj_set;
584 terrain_filter(adj_cfgs.at(
i), *
this).get_locations(adj_set, with_border);
594 while(loc_itor != match_set.end()) {
598 loc_itor = match_set.erase(loc_itor);
607 if(match_set.empty() && ors_left <= 0) {
613 std::set<map_location> intersect_hexes;
614 terrain_filter(filter, *
this).get_locations(intersect_hexes, with_border);
616 while(intersect_itor != match_set.end()) {
617 if(intersect_hexes.find(*intersect_itor) == intersect_hexes.end()) {
618 match_set.erase(*intersect_itor++);
625 else if(key ==
"or") {
626 std::set<map_location> union_hexes;
627 terrain_filter(filter, *
this).get_locations(union_hexes, with_border);
630 while(insert_itor != union_hexes.end()) {
631 match_set.insert(*insert_itor++);
636 else if(key ==
"not") {
637 std::set<map_location> removal_hexes;
638 terrain_filter(filter, *
this).get_locations(removal_hexes, with_border);
640 while(erase_itor != removal_hexes.end()) {
641 match_set.erase(*erase_itor++);
645 if(match_set.empty()) {
650 std::size_t radius =
cfg_[
"radius"].to_size_t(0);
657 std::vector<map_location> xy_vector (match_set.begin(), match_set.end());
665 locs.insert(match_set.begin(), match_set.end());
Variant for storing WML attributes.
int to_int(int def=0) const
bool empty() const
Tests for an attribute that either was never set or was set to "".
A config object defines a single node in a WML file, with access to child nodes.
const team & get_team(int side) const
This getter takes a 1-based side number, not a 0-based team number.
int village_owner(const map_location &loc) const
Given the location of a village, will return the 1-based number of the team that currently owns it,...
virtual const gamemap & map() const =0
virtual const unit_map & units() const =0
virtual const display_context & get_disp_context() const =0
virtual game_lua_kernel * get_lua_kernel() const =0
virtual const tod_manager & get_tod_man() const =0
virtual const game_data * get_game_data() const =0
virtual bool matches(const gamemap_base &m, map_location l) const =0
filter_with_unit(const terrain_filter &filt, const unit &ref)
const terrain_filter & filt_
bool operator()(const map_location &loc) const override
bool run_filter(char const *name, const unit &u)
Runs a script from a unit filter.
int w() const
Effective map width.
int h() const
Effective map height.
map_location special_location(const std::string &id) const
std::vector< map_location > parse_location_range(const std::string &xvals, const std::string &yvals, bool with_border=false) const
Parses ranges of locations into a vector of locations, using this map's dimensions as bounds.
bool on_board_with_border(const map_location &loc) const
int border_size() const
Size of the map border.
bool on_board(const map_location &loc) const
Tell if a location is on the map.
bool is_village(const map_location &loc) const
const std::vector< map_location > & villages() const
Return a list of the locations of villages on the map.
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
std::vector< int > get_teams() const
This class stores all the data for a single 'side' (in game nomenclature).
bool owns_village(const map_location &loc) const
bool shrouded(const map_location &loc) const
bool fogged(const map_location &loc) const
bool match_internal(const map_location &loc, const unit *ref_unit, const bool ignore_xy) const
~terrain_filter()
Default implementation, but defined out-of-line for efficiency reasons.
bool match_impl(const map_location &loc, const unit *ref_unit) const
terrain_filter(const vconfig &cfg, const filter_context *fc, const bool flat_tod)
terrain_filter & operator=(const terrain_filter &other)
terrain_filter_cache cache_
const std::size_t max_loop_
const filter_context * fc_
void get_locs_impl(std::set< map_location > &locs, const unit *ref_unit, bool with_border) const
static void filter_xy(T &&src, location_set &dest, const terrain_filter &filter, bool with_border)
static void filter_area(T &&src, location_set &dest, const terrain_filter &filter, const F1 &f1)
std::set< map_location > location_set
static void filter_special_loc(T &&src, location_set &dest, const terrain_filter &filter, const F1 &f1, const F2 &f2)
static void filter_final(T &&src, location_set &dest, const terrain_filter &, const F1 &f1, const F2 &f2, const F3 &f3)
t_translation::terrain_code number() const
const time_of_day get_illuminated_time_of_day(const unit_map &units, const gamemap &map, const map_location &loc, int for_turn=0) const
Returns time of day object for the passed turn at a location.
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
const std::set< map_location > & get_area_by_id(const std::string &id) const
unit_iterator find(std::size_t id)
This class represents a single unit of a specific type.
Information on a WML variable.
maybe_const_t< config::child_itors, V > as_array() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
A variable-expanding proxy for the config class.
all_children_iterator ordered_begin() const
In-order iteration over all children.
bool has_attribute(const std::string &key) const
< Synonym for operator[]
std::vector< vconfig > child_list
vconfig child(const std::string &key) const
Returns a child of *this whose key is key.
const config & get_config() const
all_children_iterator ordered_end() const
const vconfig & make_safe() const
instruct the vconfig to make a private copy of its underlying data.
boost::iterator_range< all_children_iterator > all_ordered() const
child_list get_children(const std::string &key) const
bool has_child(const std::string &key) const
Returns whether or not *this has a child whose key is key.
bool as_bool() const
Returns a boolean state of the variant value.
Definitions for the interface to Wesnoth Markup Language (WML).
const map_location & get_location() const
The current map location this unit is at.
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Standard logging facilities (interface).
bool in_ranges(const Cmp c, const std::vector< std::pair< Cmp, Cmp >> &ranges)
Game configuration data as global variables.
const std::size_t max_loop
The maximum number of hexes on a map and items in an array and also used as maximum in wml loops.
std::vector< std::pair< int, int > > default_counts
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
std::function< int(lua_State *)> lua_function
bool terrain_matches(const terrain_code &src, const terrain_code &dest)
Tests whether a specific terrain matches an expression, for matching rules see above.
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
std::vector< std::pair< int, int > > parse_ranges_unsigned(const std::string &str)
Handles a comma-separated list of inputs to parse_range, in a context that does not expect negative v...
std::vector< std::string > split(const config_attribute_value &val)
std::string::const_iterator iterator
void get_tiles_radius(const map_location ¢er, std::size_t radius, std::set< map_location > &result)
Function that will add to result all locations within radius tiles of center (including center itself...
rect src
Non-transparent portion of the surface to compose.
map_location operator()(const config &cfg) const
Encapsulates the map of the game.
static std::vector< direction > parse_directions(const std::string &str)
Parse_directions takes a comma-separated list, and filters out any invalid directions.
static std::vector< direction > all_directions()
bool matches_range(const std::string &xloc, const std::string &yloc) const
This structure can be used for matching terrain strings.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
std::unique_ptr< unit_filter > ufilter_
std::vector< std::pair< terrain_filter, std::map< map_location, bool > > > adjacent_match_cache
std::unique_ptr< t_translation::ter_match > parsed_terrain
std::unique_ptr< std::vector< std::set< map_location > > > adjacent_matches
bool operator()(const map_location &) const
Object which defines a time of day with associated bonuses, image, sounds etc.
int lawful_bonus
The % bonus lawful units receive.
static lg::log_domain log_engine("engine")
static lg::log_domain log_wml("wml")