16 #define GETTEXT_DOMAIN "wesnoth-lib"
32 #include "formula/callable_objects.hpp"
38 #include <boost/range/adaptor/transformed.hpp>
41 #define ERR_NG LOG_STREAM(err, log_engine)
42 #define WRN_NG LOG_STREAM(warn, log_engine)
45 #define ERR_WML LOG_STREAM(err, log_wml)
64 max_loop_(original.max_loop_),
75 max_loop_(other.max_loop_),
84 this->~terrain_filter();
85 new (
this) terrain_filter(other) ;
91 parsed_terrain(nullptr),
92 adjacent_matches(nullptr),
93 adjacent_match_cache(),
150 if (!found)
return false;
159 std::set<map_location> matching_locs;
162 if(test_loc.
valid()) {
163 matching_locs.insert(test_loc);
166 if (matching_locs.count(loc) == 0) {
187 vconfig::child_list::const_iterator
i, i_end = vis_filt.end();
188 for (
i = vis_filt.begin();
i != i_end; ++
i) {
189 bool visible = (*i)[
"visible"].to_bool(
true);
190 bool respect_fog = (*i)[
"respect_fog"].to_bool(
true);
193 std::vector<int> sides = ssf.
get_teams();
196 for (
const int side : sides) {
198 bool viewer_sees = respect_fog ? !viewing_team.
fogged(loc) : !viewing_team.
shrouded(loc);
199 if (visible == viewer_sees) {
204 if (!found) {
return false;}
212 vconfig::child_list::const_iterator
i, i_end, i_begin = adj_cfgs.begin();
213 for (
i = i_begin, i_end = adj_cfgs.end();
i != i_end; ++
i) {
215 vconfig::child_list::difference_type
index =
i - i_begin;
216 std::vector<map_location::DIRECTION> dirs = (*i).has_attribute(
"adjacent")
218 std::vector<map_location::DIRECTION>::const_iterator j, j_end = dirs.end();
219 for (j = dirs.begin(); j != j_end; ++j) {
225 std::pair<terrain_filter, std::map<map_location,bool>> amc_pair(
227 std::map<map_location,bool>());
233 if(lookup == amc.end()) {
234 if(amc_filter(adj)) {
240 }
else if(lookup->second) {
246 if(amc.find(adj) != amc.end()) {
253 std::vector<std::pair<int,int>> counts = (*i).has_attribute(
"count")
263 const std::string& tod_type = t_tod_type;
264 const std::string& tod_id = t_tod_id;
265 if(!tod_type.empty() || !tod_id.empty()) {
275 if(!tod_type.empty()) {
276 const std::vector<std::string>& vals =
utils::split(tod_type);
278 if(std::find(vals.begin(),vals.end(), unit_alignments::chaotic) == vals.end()) {
282 if(std::find(vals.begin(),vals.end(), unit_alignments::lawful) == vals.end()) {
285 }
else if(std::find(vals.begin(),vals.end(), unit_alignments::neutral) == vals.end() &&
286 std::find(vals.begin(),vals.end(), unit_alignments::liminal) == vals.end()) {
291 if(!tod_id.empty()) {
292 if(tod_id != tod.
id) {
293 if(std::find(tod_id.begin(),tod_id.end(),
',') != tod_id.end() &&
294 std::search(tod_id.begin(),tod_id.end(),
295 tod.
id.begin(),tod.
id.end()) != tod_id.end()) {
296 const std::vector<std::string>& vals =
utils::split(tod_id);
297 if(std::find(vals.begin(),vals.end(),tod.
id) == vals.end()) {
310 if(!filter_owner.
null()) {
311 if(!owner_side.
empty()) {
312 WRN_NG <<
"duplicate side information in a SLF, ignoring inline owner_side=";
317 const std::vector<int>& sides = ssf.
get_teams();
321 for(
const int side : sides) {
330 else if(!owner_side.
empty()) {
331 const int side_num = owner_side.
to_int(0);
342 auto ref = std::make_shared<wfl::unit_callable>(*ref_unit);
353 lg::log_to_chat() <<
"Formula error in location filter: " <<
e.type <<
" at " <<
e.filename <<
':' <<
e.line <<
")\n";
354 ERR_WML <<
"Formula error in location filter: " <<
e.type <<
" at " <<
e.filename <<
':' <<
e.line <<
")";
369 return filt_.match(loc, ref_);
375 if(
cfg_[
"x"] ==
"recall" &&
cfg_[
"y"] ==
"recall") {
378 std::set<map_location> hexes;
379 std::vector<map_location> loc_vec(1, loc);
381 std::unique_ptr<scoped_wml_variable> ref_unit_var;
391 std::size_t radius =
cfg_[
"radius"].to_size_t(0);
398 hexes.insert(loc_vec.begin(), loc_vec.end());
410 std::size_t loop_count = 0;
411 std::set<map_location>::const_iterator
i;
412 for(
i = hexes.begin();
i != hexes.end(); ++
i) {
419 matches = matches &&
terrain_filter(filter, *
this).match_impl(*
i, ref_unit);
422 else if(key ==
"or") {
423 matches = matches ||
terrain_filter(filter, *
this).match_impl(*
i, ref_unit);
426 else if(key ==
"not") {
427 matches = matches && !
terrain_filter(filter, *
this).match_impl(*
i, ref_unit);
435 std::set<map_location>::const_iterator temp =
i;
436 if(++temp != hexes.end()) {
456 template<
typename T,
typename F1,
typename F2,
typename F3>
460 if (f1(loc) && f2(loc) && f3(loc)) {
466 template<
typename T,
typename F1,
typename F2>
469 if (filter.cfg_.has_attribute(
"location_id")) {
470 std::set<map_location> matching_locs;
471 for(
const auto&
id :
utils::split(filter.cfg_[
"location_id"])) {
472 map_location test_loc = filter.fc_->get_disp_context().map().special_location(
id);
473 if(test_loc.
valid()) {
474 matching_locs.insert(test_loc);
477 filter_final(src, dest, filter, f1, f2, [matching_locs](
const map_location& loc) {
return matching_locs.count(loc) > 0; });
480 filter_final(src, dest, filter, f1, f2,
no_filter());
484 template<
typename T,
typename F1>
487 if (filter.cfg_.has_attribute(
"area")) {
488 const std::set<map_location>& area = filter.fc_->get_tod_man().get_area_by_id(filter.cfg_[
"area"]);
489 filter_special_loc(src, dest, filter, f1, [&area](
const map_location& loc) {
return area.find(loc) != area.end(); });
492 filter_special_loc(src, dest, filter, f1,
no_filter());
499 if (filter.cfg_.has_attribute(
"x") || filter.cfg_.has_attribute(
"y")) {
500 std::vector<map_location> xy_vector = filter.fc_->get_disp_context().map().parse_location_range(filter.cfg_[
"x"], filter.cfg_[
"y"], with_border);
501 filter_area(src, dest, filter, [&xy_vector](
const map_location& loc) {
return std::find(xy_vector.begin(), xy_vector.end(), loc) != xy_vector.end(); });
504 filter_area(src, dest, filter,
no_filter());
516 std::unique_ptr<scoped_wml_variable> ref_unit_var;
525 std::set<map_location> match_set;
528 with_border =
cfg_[
"include_borders"].to_bool(with_border);
535 auto ar = gd->get_variable_access_read(
cfg_[
"find_in"]).as_array();
555 if(test_loc.
valid()) {
556 match_set.insert(test_loc);
560 else if (
cfg_[
"gives_income"].to_bool()) {
569 for (
int x = with_border ? 0 - bs : 0; x <
w; ++x) {
570 for (
int y = with_border ? 0 - bs : 0; y <
h; ++y) {
582 for (
unsigned i = 0;
i < adj_cfgs.size(); ++
i) {
583 std::set<map_location> adj_set;
585 terrain_filter(adj_cfgs.at(
i), *
this).get_locations(adj_set, with_border);
595 while(loc_itor != match_set.end()) {
599 loc_itor = match_set.erase(loc_itor);
608 if(match_set.empty() && ors_left <= 0) {
614 std::set<map_location> intersect_hexes;
615 terrain_filter(filter, *
this).get_locations(intersect_hexes, with_border);
617 while(intersect_itor != match_set.end()) {
618 if(intersect_hexes.find(*intersect_itor) == intersect_hexes.end()) {
619 match_set.erase(*intersect_itor++);
626 else if(key ==
"or") {
627 std::set<map_location> union_hexes;
628 terrain_filter(filter, *
this).get_locations(union_hexes, with_border);
631 while(insert_itor != union_hexes.end()) {
632 match_set.insert(*insert_itor++);
637 else if(key ==
"not") {
638 std::set<map_location> removal_hexes;
639 terrain_filter(filter, *
this).get_locations(removal_hexes, with_border);
641 while(erase_itor != removal_hexes.end()) {
642 match_set.erase(*erase_itor++);
646 if(match_set.empty()) {
651 std::size_t radius =
cfg_[
"radius"].to_size_t(0);
658 std::vector<map_location> xy_vector (match_set.begin(), match_set.end());
666 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)=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.
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...
int main(int, char **argv)
map_location operator()(const config &cfg) const
Encapsulates the map of the game.
static const std::vector< DIRECTION > & default_dirs()
Default list of directions.
static std::vector< DIRECTION > parse_directions(const std::string &str)
Parse_directions takes a comma-separated list, and filters out any invalid 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")