The Battle for Wesnoth  1.13.11+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
filter.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
17 #include "config.hpp"
18 #include "display_context.hpp"
19 #include "filter_context.hpp"
20 #include "game_board.hpp"
21 #include "game_data.hpp"
22 #include "log.hpp"
23 #include "map/map.hpp"
24 #include "side_filter.hpp"
25 #include "team.hpp"
26 #include "terrain/filter.hpp"
27 #include "tod_manager.hpp"
28 #include "units/unit.hpp"
29 #include "units/filter.hpp"
30 #include "variable.hpp"
31 #include "formula/callable_objects.hpp"
32 #include "formula/formula.hpp"
35 
36 #include <boost/range/adaptor/transformed.hpp>
37 
38 static lg::log_domain log_engine("engine");
39 #define ERR_NG LOG_STREAM(err, log_engine)
40 #define WRN_NG LOG_STREAM(warn, log_engine)
41 
43 {
44 }
45 
46 terrain_filter::terrain_filter(const vconfig& cfg, const filter_context * fc, const bool flat_tod) :
47  cfg_(cfg),
48  fc_(fc),
49  cache_(),
50  max_loop_(game_config::max_loop),
51  flat_(flat_tod)
52 {
53 }
54 
56  cfg_(cfg),
57  fc_(original.fc_),
58  cache_(),
59  max_loop_(original.max_loop_),
60  flat_(original.flat_)
61 {
62 }
63 
65  xy_pred(), // We should construct this too, since it has no datamembers
66  // use the default constructor.
67  cfg_(other.cfg_),
68  fc_(other.fc_),
69  cache_(),
70  max_loop_(other.max_loop_),
71  flat_(other.flat_)
72 {
73 }
74 
76 {
77  // Use copy constructor to make sure we are coherent
78  if (this != &other) {
79  this->~terrain_filter();
80  new (this) terrain_filter(other) ;
81  }
82  return *this ;
83 }
84 
86  parsed_terrain(nullptr),
87  adjacent_matches(nullptr),
88  adjacent_match_cache(),
89  ufilter_()
90 {}
91 
92 namespace {
93  struct cfg_isor {
94  bool operator() (std::pair<const std::string,const vconfig> val) const {
95  return val.first == "or";
96  }
97  };
98 } //end anonymous namespace
99 
100 bool terrain_filter::match_internal(const map_location& loc, const unit* ref_unit, const bool ignore_xy) const
101 {
102  if (!this->fc_->get_disp_context().map().on_board_with_border(loc)) {
103  return false;
104  }
105 
106  std::string lua_function = cfg_["lua_function"];
107  if (!lua_function.empty() && fc_->get_lua_kernel()) {
108  if (!fc_->get_lua_kernel()->run_filter(lua_function.c_str(), loc)) {
109  return false;
110  }
111  }
112 
113  //Filter Areas
114  if (cfg_.has_attribute("area") &&
115  fc_->get_tod_man().get_area_by_id(cfg_["area"]).count(loc) == 0)
116  return false;
117 
118  if(cfg_.has_attribute("terrain")) {
119  if(cache_.parsed_terrain == nullptr) {
120  cache_.parsed_terrain.reset(new t_translation::ter_match(cfg_["terrain"]));
121  }
122  if(!cache_.parsed_terrain->is_empty) {
125  return false;
126  }
127  }
128  }
129 
130  //Allow filtering on location ranges
131  if (!ignore_xy) {
132  if (!loc.matches_range(cfg_["x"], cfg_["y"])) {
133  return false;
134  }
135  //allow filtering by searching a stored variable of locations
136  if (cfg_.has_attribute("find_in")) {
137  if (const game_data * gd = fc_->get_game_data()) {
138  try
139  {
140  variable_access_const vi = gd->get_variable_access_read(cfg_["find_in"]);
141 
142  bool found = false;
143  for (const config &cfg : vi.as_array()) {
144  if (map_location(cfg, nullptr) == loc) {
145  found = true;
146  break;
147  }
148  }
149  if (!found) return false;
150  }
151  catch (const invalid_variablename_exception&)
152  {
153  return false;
154  }
155  }
156  }
157  if (cfg_.has_attribute("location_id")) {
158  if (loc != fc_->get_disp_context().map().special_location(cfg_["location_id"])) {
159  return false;
160  }
161  }
162  }
163  //Allow filtering on unit
164  if(cfg_.has_child("filter")) {
166  if (!u.valid())
167  return false;
168  if (!cache_.ufilter_) {
169  cache_.ufilter_.reset(new unit_filter(cfg_.child("filter").make_safe()));
170  cache_.ufilter_->set_use_flat_tod(flat_);
171  }
172  if (!cache_.ufilter_->matches(*u, loc))
173  return false;
174  }
175 
176  // Allow filtering on visibility to a side
177  if (cfg_.has_child("filter_vision")) {
178  const vconfig::child_list& vis_filt = cfg_.get_children("filter_vision");
179  vconfig::child_list::const_iterator i, i_end = vis_filt.end();
180  for (i = vis_filt.begin(); i != i_end; ++i) {
181  bool visible = (*i)["visible"].to_bool(true);
182  bool respect_fog = (*i)["respect_fog"].to_bool(true);
183 
184  side_filter ssf(*i, fc_);
185  std::vector<int> sides = ssf.get_teams();
186 
187  bool found = false;
188  for (const int side : sides) {
189  const team &viewing_team = fc_->get_disp_context().get_team(side);
190  bool viewer_sees = respect_fog ? !viewing_team.fogged(loc) : !viewing_team.shrouded(loc);
191  if (visible == viewer_sees) {
192  found = true;
193  break;
194  }
195  }
196  if (!found) {return false;}
197  }
198  }
199 
200  //Allow filtering on adjacent locations
201  if(cfg_.has_child("filter_adjacent_location")) {
202  adjacent_loc_array_t adjacent;
203  get_adjacent_tiles(loc, adjacent.data());
204  const vconfig::child_list& adj_cfgs = cfg_.get_children("filter_adjacent_location");
205  vconfig::child_list::const_iterator i, i_end, i_begin = adj_cfgs.begin();
206  for (i = i_begin, i_end = adj_cfgs.end(); i != i_end; ++i) {
207  int match_count = 0;
208  vconfig::child_list::difference_type index = i - i_begin;
209  std::vector<map_location::DIRECTION> dirs = (*i).has_attribute("adjacent")
211  std::vector<map_location::DIRECTION>::const_iterator j, j_end = dirs.end();
212  for (j = dirs.begin(); j != j_end; ++j) {
213  map_location &adj = adjacent[*j];
214  if (fc_->get_disp_context().map().on_board(adj)) {
215  if(cache_.adjacent_matches == nullptr) {
216  while(index >= std::distance(cache_.adjacent_match_cache.begin(), cache_.adjacent_match_cache.end())) {
217  const vconfig& adj_cfg = adj_cfgs[cache_.adjacent_match_cache.size()];
218  std::pair<terrain_filter, std::map<map_location,bool>> amc_pair(
219  terrain_filter(adj_cfg, *this),
220  std::map<map_location,bool>());
221  cache_.adjacent_match_cache.push_back(amc_pair);
222  }
223  terrain_filter &amc_filter = cache_.adjacent_match_cache[index].first;
224  std::map<map_location,bool> &amc = cache_.adjacent_match_cache[index].second;
225  std::map<map_location,bool>::iterator lookup = amc.find(adj);
226  if(lookup == amc.end()) {
227  if(amc_filter(adj)) {
228  amc[adj] = true;
229  ++match_count;
230  } else {
231  amc[adj] = false;
232  }
233  } else if(lookup->second) {
234  ++match_count;
235  }
236  } else {
237  assert(index < std::distance(cache_.adjacent_matches->begin(), cache_.adjacent_matches->end()));
238  std::set<map_location> &amc = (*cache_.adjacent_matches)[index];
239  if(amc.find(adj) != amc.end()) {
240  ++match_count;
241  }
242  }
243  }
244  }
245  static std::vector<std::pair<int,int>> default_counts = utils::parse_ranges("1-6");
246  std::vector<std::pair<int,int>> counts = (*i).has_attribute("count")
247  ? utils::parse_ranges((*i)["count"]) : default_counts;
248  if(!in_ranges(match_count, counts)) {
249  return false;
250  }
251  }
252  }
253 
254  const t_string& t_tod_type = cfg_["time_of_day"];
255  const t_string& t_tod_id = cfg_["time_of_day_id"];
256  const std::string& tod_type = t_tod_type;
257  const std::string& tod_id = t_tod_id;
258  if(!tod_type.empty() || !tod_id.empty()) {
259  // creating a time_of_day is expensive, only do it if we will use it
260  time_of_day tod;
261 
262  if(flat_) {
263  tod = fc_->get_tod_man().get_time_of_day(loc);
264  } else {
266  }
267 
268  if(!tod_type.empty()) {
269  const std::vector<std::string>& vals = utils::split(tod_type);
270  if(tod.lawful_bonus<0) {
271  if(std::find(vals.begin(),vals.end(),unit_type::ALIGNMENT::enum_to_string(unit_type::ALIGNMENT::CHAOTIC)) == vals.end()) {
272  return false;
273  }
274  } else if(tod.lawful_bonus>0) {
275  if(std::find(vals.begin(),vals.end(),unit_type::ALIGNMENT::enum_to_string(unit_type::ALIGNMENT::LAWFUL)) == vals.end()) {
276  return false;
277  }
278  } else if(std::find(vals.begin(),vals.end(),unit_type::ALIGNMENT::enum_to_string(unit_type::ALIGNMENT::NEUTRAL)) == vals.end()) {
279  return false;
280  }
281  }
282 
283  if(!tod_id.empty()) {
284  if(tod_id != tod.id) {
285  if(std::find(tod_id.begin(),tod_id.end(),',') != tod_id.end() &&
286  std::search(tod_id.begin(),tod_id.end(),
287  tod.id.begin(),tod.id.end()) != tod_id.end()) {
288  const std::vector<std::string>& vals = utils::split(tod_id);
289  if(std::find(vals.begin(),vals.end(),tod.id) == vals.end()) {
290  return false;
291  }
292  } else {
293  return false;
294  }
295  }
296  }
297  }
298 
299  //allow filtering on owner (for villages)
300  const config::attribute_value &owner_side = cfg_["owner_side"];
301  const vconfig& filter_owner = cfg_.child("filter_owner");
302  if(!filter_owner.null()) {
303  if(!owner_side.empty()) {
304  WRN_NG << "duplicate side information in a SLF, ignoring inline owner_side=" << std::endl;
305  }
306  if(!fc_->get_disp_context().map().is_village(loc))
307  return false;
308  side_filter ssf(filter_owner, fc_);
309  const std::vector<int>& sides = ssf.get_teams();
310  bool found = false;
311  if(sides.empty() && fc_->get_disp_context().village_owner(loc) == -1)
312  found = true;
313  for(const int side : sides) {
314  if(fc_->get_disp_context().get_team(side).owns_village(loc)) {
315  found = true;
316  break;
317  }
318  }
319  if(!found)
320  return false;
321  }
322  else if(!owner_side.empty()) {
323  const int side_index = owner_side.to_int(0) - 1;
324  if(fc_->get_disp_context().village_owner(loc) != side_index) {
325  return false;
326  }
327  }
328 
329  if(cfg_.has_attribute("formula")) {
330  try {
332  wfl::map_formula_callable callable(main.fake_ptr());
333  if(ref_unit) {
334  std::shared_ptr<wfl::unit_callable> ref(new wfl::unit_callable(*ref_unit));
335  callable.add("teleport_unit", wfl::variant(ref));
336  // It's not destroyed upon scope exit because the variant holds a reference
337  }
338  const wfl::formula form(cfg_["formula"], new wfl::gamestate_function_symbol_table);
339  if(!form.evaluate(callable).as_bool()) {
340  return false;
341  }
342  return true;
343  } catch(wfl::formula_error& e) {
344  lg::wml_error() << "Formula error in location filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
345  // Formulae with syntax errors match nothing
346  return false;
347  }
348  }
349 
350  return true;
351 }
352 
353 class filter_with_unit : public xy_pred {
355  const unit& ref_;
356 public:
357  filter_with_unit(const terrain_filter& filt, const unit& ref) : filt_(filt), ref_(ref) {}
358  bool operator()(const map_location& loc) const override {
359  return filt_.match(loc, ref_);
360  }
361 };
362 
363 bool terrain_filter::match_impl(const map_location& loc, const unit* ref_unit) const
364 {
365  if(cfg_["x"] == "recall" && cfg_["y"] == "recall") {
366  return !fc_->get_disp_context().map().on_board(loc);
367  }
368  std::set<map_location> hexes;
369  std::vector<map_location> loc_vec(1, loc);
370 
371  std::unique_ptr<scoped_wml_variable> ref_unit_var;
372  if(ref_unit) {
373  if(fc_->get_disp_context().map().on_board(ref_unit->get_location())) {
374  ref_unit_var.reset(new scoped_xy_unit("teleport_unit", ref_unit->get_location(), fc_->get_disp_context().units()));
375  } else {
376  // Possible TODO: Support recall list units?
377  }
378  }
379 
380  //handle radius
381  size_t radius = cfg_["radius"].to_size_t(0);
382  if(radius > max_loop_) {
383  ERR_NG << "terrain_filter: radius greater than " << max_loop_
384  << ", restricting\n";
385  radius = max_loop_;
386  }
387  if ( radius == 0 )
388  hexes.insert(loc_vec.begin(), loc_vec.end());
389  else if ( cfg_.has_child("filter_radius") ) {
390  terrain_filter r_filter(cfg_.child("filter_radius"), *this);
391  if(ref_unit) {
392  get_tiles_radius(fc_->get_disp_context().map(), loc_vec, radius, hexes, false, filter_with_unit(r_filter, *ref_unit));
393  } else {
394  get_tiles_radius(fc_->get_disp_context().map(), loc_vec, radius, hexes, false, r_filter);
395  }
396  } else {
397  get_tiles_radius(fc_->get_disp_context().map(), loc_vec, radius, hexes);
398  }
399 
400  size_t loop_count = 0;
401  std::set<map_location>::const_iterator i;
402  for(i = hexes.begin(); i != hexes.end(); ++i) {
403  bool matches = match_internal(*i, ref_unit, false);
404 
405  //handle [and], [or], and [not] with in-order precedence
408  while(cond != cond_end)
409  {
410  const std::string& cond_name = cond.get_key();
411  const vconfig& cond_cfg = cond.get_child();
412 
413  //handle [and]
414  if(cond_name == "and")
415  {
416  matches = matches && terrain_filter(cond_cfg, *this).match_impl(*i, ref_unit);
417  }
418  //handle [or]
419  else if(cond_name == "or")
420  {
421  matches = matches || terrain_filter(cond_cfg, *this).match_impl(*i, ref_unit);
422  }
423  //handle [not]
424  else if(cond_name == "not")
425  {
426  matches = matches && !terrain_filter(cond_cfg, *this).match_impl(*i, ref_unit);
427  }
428  ++cond;
429  }
430  if(matches) {
431  return true;
432  }
433  if(++loop_count > max_loop_) {
434  std::set<map_location>::const_iterator temp = i;
435  if(++temp != hexes.end()) {
436  ERR_NG << "terrain_filter: loop count greater than " << max_loop_
437  << ", aborting\n";
438  break;
439  }
440  }
441  }
442  return false;
443 }
444 //using a class to be able to firen it in terrain_filter
446 {
447 public:
448  using location_set = std::set<map_location>;
449  struct no_start_set_yet {};
450  struct no_filter
451  {
452  bool operator()(const map_location&) const { return true; }
453  };
454 
455  template<typename T, typename F1, typename F2, typename F3>
456  static void filter_final(T&& src, location_set& dest, const terrain_filter&, const F1& f1, const F2& f2, const F3& f3)
457  {
458  for (const map_location &loc : src) {
459  if (f1(loc) && f2(loc) && f3(loc)) {
460  dest.insert(loc);
461  }
462  }
463  }
464 
465  template<typename T, typename F1, typename F2>
466  static void filter_special_loc(T&& src, location_set& dest, const terrain_filter& filter, const F1& f1, const F2& f2)
467  {
468  if (filter.cfg_.has_attribute("location_id")) {
469  map_location loc2 = filter.fc_->get_disp_context().map().special_location(filter.cfg_["location_id"]);
470  filter_final(src, dest, filter, f1, f2, [loc2](const map_location& loc) { return loc == loc2; });
471  }
472  else {
473  filter_final(src, dest, filter, f1, f2, no_filter());
474  }
475  }
476 
477  template<typename T, typename F1>
478  static void filter_area(T&& src, location_set& dest, const terrain_filter& filter, const F1& f1)
479  {
480  if (filter.cfg_.has_attribute("area")) {
481  const std::set<map_location>& area = filter.fc_->get_tod_man().get_area_by_id(filter.cfg_["area"]);
482  filter_special_loc(src, dest, filter, f1, [&area](const map_location& loc) { return area.find(loc) != area.end(); });
483  }
484  else {
485  filter_special_loc(src, dest, filter, f1, no_filter());
486  }
487  }
488 
489  template<typename T>
490  static void filter_xy(T&& src, location_set& dest, const terrain_filter& filter, bool with_border)
491  {
492  if (filter.cfg_.has_attribute("x") || filter.cfg_.has_attribute("y")) {
493  std::vector<map_location> xy_vector = filter.fc_->get_disp_context().map().parse_location_range(filter.cfg_["x"], filter.cfg_["y"], with_border);
494  filter_area(src, dest, filter, [&xy_vector](const map_location& loc) { return std::find(xy_vector.begin(), xy_vector.end(), loc) != xy_vector.end(); });
495  }
496  else {
497  filter_area(src, dest, filter, no_filter());
498  }
499  }
500 };
501 //using lambdas with boost transformed gives compile erros on gcc (it works on clang and msvc)
503 {
504  map_location operator()(const config& cfg) const { return map_location(cfg, nullptr); }
506 };
507 void terrain_filter::get_locs_impl(std::set<map_location>& locs, const unit* ref_unit, bool with_border) const
508 {
509  std::unique_ptr<scoped_wml_variable> ref_unit_var;
510  if(ref_unit) {
511  if(fc_->get_disp_context().map().on_board(ref_unit->get_location())) {
512  ref_unit_var.reset(new scoped_xy_unit("teleport_unit", ref_unit->get_location(), fc_->get_disp_context().units()));
513  } else {
514  // Possible TODO: Support recall list units?
515  }
516  }
517 
518  std::set<map_location> match_set;
519 
520  // See if the caller provided an override to with_border
521  with_border = cfg_["include_borders"].to_bool(with_border);
522 
523  if (cfg_.has_attribute("find_in")) {
524 
525  if (const game_data * gd = fc_->get_game_data()) {
526  try
527  {
528  auto ar = gd->get_variable_access_read(cfg_["find_in"]).as_array();
529  terrain_filterimpl::filter_xy(ar | boost::adaptors::transformed(cfg_to_loc()), match_set, *this, with_border);
530  }
531  catch (const invalid_variablename_exception&)
532  {
533  //Do nothing
534  }
535  }
536  }
537  else if (cfg_.has_attribute("x") || cfg_.has_attribute("y")) {
538  std::vector<map_location> xy_vector = fc_->get_disp_context().map().parse_location_range(cfg_["x"], cfg_["y"], with_border);
539  terrain_filterimpl::filter_area(xy_vector, match_set, *this, terrain_filterimpl::no_filter());
540  }
541  else if (cfg_.has_attribute("area")) {
542  const std::set<map_location>& area = fc_->get_tod_man().get_area_by_id(cfg_["area"]);
544  }
545  else if (cfg_.has_attribute("location_id")) {
546  map_location loc2 = fc_->get_disp_context().map().special_location(cfg_["location_id"]);
547  if (loc2.valid()) {
548  match_set.insert(loc2);
549  }
550  }
551  else {
552  //consider all locations on the map
553  int bs = fc_->get_disp_context().map().border_size();
554  int w = with_border ? fc_->get_disp_context().map().w() + bs : fc_->get_disp_context().map().w();
555  int h = with_border ? fc_->get_disp_context().map().h() + bs : fc_->get_disp_context().map().h();
556  for (int x = with_border ? 0 - bs : 0; x < w; ++x) {
557  for (int y = with_border ? 0 - bs : 0; y < h; ++y) {
558  match_set.insert(map_location(x, y));
559  }
560  }
561  }
562 
563  //handle location filter
564  if(cfg_.has_child("filter_adjacent_location")) {
565  if(cache_.adjacent_matches == nullptr) {
566  cache_.adjacent_matches.reset(new std::vector<std::set<map_location>>());
567  }
568  const vconfig::child_list& adj_cfgs = cfg_.get_children("filter_adjacent_location");
569  for (unsigned i = 0; i < adj_cfgs.size(); ++i) {
570  std::set<map_location> adj_set;
571  /* GCC-3.3 doesn't like operator[] so use at(), which has the same result */
572  terrain_filter(adj_cfgs.at(i), *this).get_locations(adj_set, with_border);
573  cache_.adjacent_matches->push_back(adj_set);
574  if(i >= max_loop_ && i+1 < adj_cfgs.size()) {
575  ERR_NG << "terrain_filter: loop count greater than " << max_loop_
576  << ", aborting\n";
577  break;
578  }
579  }
580  }
581  std::set<map_location>::iterator loc_itor = match_set.begin();
582  while(loc_itor != match_set.end()) {
583  if(match_internal(*loc_itor, ref_unit, true)) {
584  ++loc_itor;
585  } else {
586  loc_itor = match_set.erase(loc_itor);
587  }
588  }
589 
590  //handle [and], [or], and [not] with in-order precedence
593  int ors_left = std::count_if(cond, cond_end, cfg_isor());
594  while(cond != cond_end)
595  {
596  //if there are no locations or [or] conditions left, go ahead and return empty
597  if(match_set.empty() && ors_left <= 0) {
598  return;
599  }
600 
601  const std::string& cond_name = cond.get_key();
602  const vconfig& cond_cfg = cond.get_child();
603 
604  //handle [and]
605  if(cond_name == "and") {
606  std::set<map_location> intersect_hexes;
607  terrain_filter(cond_cfg, *this).get_locations(intersect_hexes, with_border);
608  std::set<map_location>::iterator intersect_itor = match_set.begin();
609  while(intersect_itor != match_set.end()) {
610  if(intersect_hexes.find(*intersect_itor) == intersect_hexes.end()) {
611  match_set.erase(*intersect_itor++);
612  } else {
613  ++intersect_itor;
614  }
615  }
616  }
617  //handle [or]
618  else if(cond_name == "or") {
619  std::set<map_location> union_hexes;
620  terrain_filter(cond_cfg, *this).get_locations(union_hexes, with_border);
621  //match_set.insert(union_hexes.begin(), union_hexes.end()); //doesn't compile on MSVC
622  std::set<map_location>::iterator insert_itor = union_hexes.begin();
623  while(insert_itor != union_hexes.end()) {
624  match_set.insert(*insert_itor++);
625  }
626  --ors_left;
627  }
628  //handle [not]
629  else if(cond_name == "not") {
630  std::set<map_location> removal_hexes;
631  terrain_filter(cond_cfg, *this).get_locations(removal_hexes, with_border);
632  std::set<map_location>::iterator erase_itor = removal_hexes.begin();
633  while(erase_itor != removal_hexes.end()) {
634  match_set.erase(*erase_itor++);
635  }
636  }
637  ++cond;
638  }
639  if(match_set.empty()) {
640  return;
641  }
642 
643  //handle radius
644  size_t radius = cfg_["radius"].to_size_t(0);
645  if(radius > max_loop_) {
646  ERR_NG << "terrain_filter: radius greater than " << max_loop_
647  << ", restricting\n";
648  radius = max_loop_;
649  }
650  if(radius > 0) {
651  std::vector<map_location> xy_vector (match_set.begin(), match_set.end());
652  if(cfg_.has_child("filter_radius")) {
653  terrain_filter r_filter(cfg_.child("filter_radius"), *this);
654  get_tiles_radius(fc_->get_disp_context().map(), xy_vector, radius, locs, with_border, r_filter);
655  } else {
656  get_tiles_radius(fc_->get_disp_context().map(), xy_vector, radius, locs, with_border);
657  }
658  } else {
659  locs.insert(match_set.begin(), match_set.end());
660  }
661 }
662 
664 {
665  return cfg_.get_config();
666 }
std::vector< int > get_teams() const
Definition: side_filter.cpp:55
bool on_board_with_border(const map_location &loc) const
Definition: map.cpp:374
std::function< int(lua_State *)> lua_function
std::vector< char_t > string
size_t index(const utf8::string &str, const size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
virtual const display_context & get_disp_context() const =0
bool matches_range(const std::string &xloc, const std::string &yloc) const
Definition: location.cpp:316
This class represents a single unit of a specific type.
Definition: unit.hpp:100
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:39
bool run_filter(char const *name, const unit &u)
Runs a script from a unit filter.
bool shrouded(const map_location &loc) const
Definition: team.cpp:633
Variant for storing WML attributes.
map_location operator()(const config &cfg) const
Definition: filter.cpp:504
vconfig get_child() const
Definition: variable.cpp:421
vconfig child(const std::string &key) const
Returns a child of *this whose key is key.
Definition: variable.cpp:252
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::string filename
Definition: formula.hpp:107
bool owns_village(const map_location &loc) const
Definition: team.hpp:184
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.hpp:303
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
Definition: tod_manager.hpp:54
static void filter_final(T &&src, location_set &dest, const terrain_filter &, const F1 &f1, const F2 &f2, const F3 &f3)
Definition: filter.cpp:456
all_children_iterator ordered_end() const
Definition: variable.cpp:450
bool is_village(const map_location &loc) const
Definition: map.cpp:66
virtual bool operator()(const map_location &loc) const
Definition: filter.hpp:52
bool empty() const
Tests for an attribute that either was never set or was set to "".
std::string id
Definition: time_of_day.hpp:91
int lawful_bonus
The % bonus lawful units receive.
Definition: time_of_day.hpp:84
std::unique_ptr< t_translation::ter_match > parsed_terrain
Definition: filter.hpp:86
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:49
bool in_ranges(const Cmp c, const std::vector< std::pair< Cmp, Cmp >> &ranges)
Definition: math.hpp:81
int village_owner(const map_location &loc) const
Given the location of a village, will return the 0-based index of the team that currently owns it...
#define h
static void filter_special_loc(T &&src, location_set &dest, const terrain_filter &filter, const F1 &f1, const F2 &f2)
Definition: filter.cpp:466
terrain_filter_cache cache_
Definition: filter.hpp:97
#define WRN_NG
Definition: filter.cpp:40
static std::vector< DIRECTION > parse_directions(const std::string &str)
Parse_directions takes a comma-separated list, and filters out any invalid directions.
Definition: location.cpp:123
const vconfig cfg_
Definition: filter.hpp:79
-file sdl_utils.hpp
Definitions for the interface to Wesnoth Markup Language (WML).
virtual const gamemap & map() const =0
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
bool match(const map_location &loc) const
Definition: filter.hpp:41
const filter_context * fc_
Definition: filter.hpp:80
Object which defines a time of day with associated bonuses, image, sounds etc.
Definition: time_of_day.hpp:57
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:44
bool null() const
Definition: variable.hpp:73
std::vector< std::pair< int, int > > parse_ranges(const std::string &str)
std::vector< std::pair< int, int > > default_counts
const size_t max_loop_
Definition: filter.hpp:98
const unit & ref_
Definition: filter.cpp:355
bool valid() const
Definition: location.hpp:74
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1141
child_list get_children(const std::string &key) const
Definition: variable.cpp:190
bool as_bool() const
Returns a boolean state of the variant value.
Definition: variant.cpp:320
std::string type
Definition: formula.hpp:105
int w() const
Effective map width.
Definition: map.hpp:90
bool has_child(const std::string &key) const
Returns whether or not *this has a child whose key is key.
Definition: variable.cpp:279
const 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...
t_translation::terrain_code number() const
Definition: terrain.hpp:44
static const std::vector< DIRECTION > & default_dirs()
Default list of directions.
Definition: location.cpp:51
int border_size() const
Size of the map border.
Definition: map.hpp:96
terrain_filter(const vconfig &cfg, const filter_context *fc, const bool flat_tod=false)
Definition: filter.cpp:46
bool match_impl(const map_location &loc, const unit *ref_unit) const
Definition: filter.cpp:363
virtual const unit_map & units() const =0
bool match_internal(const map_location &loc, const unit *ref_unit, const bool ignore_xy) const
Definition: filter.cpp:100
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:98
std::array< map_location, 6 > adjacent_loc_array_t
Definition: location.hpp:130
const terrain_filter & filt_
Definition: filter.cpp:354
filter_with_unit(const terrain_filter &filt, const unit &ref)
Definition: filter.cpp:357
std::unique_ptr< unit_filter > ufilter_
Definition: filter.hpp:94
~terrain_filter()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: filter.cpp:42
Encapsulates the map of the game.
Definition: location.hpp:42
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...
Definition: map.cpp:407
map_location special_location(const std::string &id) const
Definition: map.cpp:311
void get_locations(std::set< map_location > &locs, bool with_border=false) const
gets all locations on the map that match this filter
Definition: filter.hpp:57
int to_int(int def=0) const
config to_config() const
Definition: filter.cpp:663
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:269
int h() const
Effective map height.
Definition: map.hpp:93
bool operator()(const map_location &loc) const override
Definition: filter.cpp:358
Game configuration data as global variables.
Definition: build_info.cpp:53
int main()
const config & get_config() const
Definition: variable.hpp:75
terrain_filter & operator=(const terrain_filter &other)
Definition: filter.cpp:75
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...
size_t i
Definition: function.cpp:933
map_location result_type
Definition: filter.cpp:505
bool fogged(const map_location &loc) const
Definition: team.cpp:642
void get_tiles_radius(const map_location &center, size_t radius, std::set< map_location > &result)
Function that will add to result all locations within radius tiles of center (including center itself...
Definition: pathutils.cpp:68
int w
virtual const tod_manager & get_tod_man() const =0
const std::set< map_location > & get_area_by_id(const std::string &id) const
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:369
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.
void get_locs_impl(std::set< map_location > &locs, const unit *ref_unit, bool with_border) const
Definition: filter.cpp:507
Information on a WML variable.
bool find(E event, F functor)
Tests whether an event handler is available.
const vconfig & make_safe() const
instruct the vconfig to make a private copy of its underlying data.
Definition: variable.cpp:127
const team & get_team(int side) const
virtual const game_data * get_game_data() const =0
static int cond(LexState *ls)
Definition: lparser.cpp:1177
A variable-expanding proxy for the config class.
Definition: variable.hpp:42
static lg::log_domain log_engine("engine")
Standard logging facilities (interface).
virtual game_lua_kernel * get_lua_kernel() const =0
std::vector< std::pair< terrain_filter, std::map< map_location, bool > > > adjacent_match_cache
Definition: filter.hpp:92
std::unique_ptr< std::vector< std::set< map_location > > > adjacent_matches
Definition: filter.hpp:89
#define e
unit_iterator find(size_t id)
Definition: map.cpp:311
bool valid() const
Definition: map.hpp:276
static void filter_area(T &&src, location_set &dest, const terrain_filter &filter, const F1 &f1)
Definition: filter.cpp:478
std::vector< vconfig > child_list
Definition: variable.hpp:78
#define ERR_NG
Definition: filter.cpp:39
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
This structure can be used for matching terrain strings.
static void filter_xy(T &&src, location_set &dest, const terrain_filter &filter, bool with_border)
Definition: filter.cpp:490
bool operator()(const map_location &) const
Definition: filter.cpp:452
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
std::string get_key() const
Definition: variable.cpp:412
bool has_attribute(const std::string &key) const
< Synonym for operator[]
Definition: variable.hpp:99
all_children_iterator ordered_begin() const
In-order iteration over all children.
Definition: variable.cpp:445
std::set< map_location > location_set
Definition: filter.cpp:448