The Battle for Wesnoth  1.15.0-dev
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 https://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_data.hpp"
21 #include "log.hpp"
22 #include "map/map.hpp"
23 #include "side_filter.hpp"
24 #include "team.hpp"
25 #include "terrain/filter.hpp"
26 #include "tod_manager.hpp"
27 #include "units/unit.hpp"
28 #include "units/filter.hpp"
29 #include "variable.hpp"
30 #include "formula/callable_objects.hpp"
31 #include "formula/formula.hpp"
34 
35 #include <boost/range/adaptor/transformed.hpp>
36 
37 static lg::log_domain log_engine("engine");
38 #define ERR_NG LOG_STREAM(err, log_engine)
39 #define WRN_NG LOG_STREAM(warn, log_engine)
40 
42 {
43 }
44 
45 terrain_filter::terrain_filter(const vconfig& cfg, const filter_context * fc, const bool flat_tod) :
46  cfg_(cfg),
47  fc_(fc),
48  cache_(),
50  flat_(flat_tod)
51 {
52 }
53 
55  cfg_(cfg),
56  fc_(original.fc_),
57  cache_(),
58  max_loop_(original.max_loop_),
59  flat_(original.flat_)
60 {
61 }
62 
64  xy_pred(), // We should construct this too, since it has no datamembers
65  // use the default constructor.
66  cfg_(other.cfg_),
67  fc_(other.fc_),
68  cache_(),
69  max_loop_(other.max_loop_),
70  flat_(other.flat_)
71 {
72 }
73 
75 {
76  // Use copy constructor to make sure we are coherent
77  if (this != &other) {
78  this->~terrain_filter();
79  new (this) terrain_filter(other) ;
80  }
81  return *this ;
82 }
83 
85  parsed_terrain(nullptr),
86  adjacent_matches(nullptr),
87  adjacent_match_cache(),
88  ufilter_()
89 {}
90 
91 namespace {
92  struct cfg_isor {
93  bool operator() (std::pair<const std::string,const vconfig> val) const {
94  return val.first == "or";
95  }
96  };
97 } //end anonymous namespace
98 
99 bool terrain_filter::match_internal(const map_location& loc, const unit* ref_unit, const bool ignore_xy) const
100 {
101  if (!this->fc_->get_disp_context().map().on_board_with_border(loc)) {
102  return false;
103  }
104 
105  std::string lua_function = cfg_["lua_function"];
106  if (!lua_function.empty() && fc_->get_lua_kernel()) {
107  if (!fc_->get_lua_kernel()->run_filter(lua_function.c_str(), loc)) {
108  return false;
109  }
110  }
111 
112  //Filter Areas
113  if (cfg_.has_attribute("area") &&
114  fc_->get_tod_man().get_area_by_id(cfg_["area"]).count(loc) == 0)
115  return false;
116 
117  if(cfg_.has_attribute("terrain")) {
118  if(cache_.parsed_terrain == nullptr) {
119  cache_.parsed_terrain.reset(new t_translation::ter_match(cfg_["terrain"]));
120  }
121  if(!cache_.parsed_terrain->is_empty) {
124  return false;
125  }
126  }
127  }
128 
129  //Allow filtering on location ranges
130  if (!ignore_xy) {
131  if (!loc.matches_range(cfg_["x"], cfg_["y"])) {
132  return false;
133  }
134  //allow filtering by searching a stored variable of locations
135  if (cfg_.has_attribute("find_in")) {
136  if (const game_data * gd = fc_->get_game_data()) {
137  try
138  {
139  variable_access_const vi = gd->get_variable_access_read(cfg_["find_in"]);
140 
141  bool found = false;
142  for (const config &cfg : vi.as_array()) {
143  if (map_location(cfg, nullptr) == loc) {
144  found = true;
145  break;
146  }
147  }
148  if (!found) return false;
149  }
150  catch (const invalid_variablename_exception&)
151  {
152  return false;
153  }
154  }
155  }
156  if (cfg_.has_attribute("location_id")) {
157  if (loc != fc_->get_disp_context().map().special_location(cfg_["location_id"])) {
158  return false;
159  }
160  }
161  }
162  //Allow filtering on unit
163  if(cfg_.has_child("filter")) {
165  if (!u.valid())
166  return false;
167  if (!cache_.ufilter_) {
168  cache_.ufilter_.reset(new unit_filter(cfg_.child("filter").make_safe()));
169  cache_.ufilter_->set_use_flat_tod(flat_);
170  }
171  if (!cache_.ufilter_->matches(*u, loc))
172  return false;
173  }
174 
175  // Allow filtering on visibility to a side
176  if (cfg_.has_child("filter_vision")) {
177  const vconfig::child_list& vis_filt = cfg_.get_children("filter_vision");
178  vconfig::child_list::const_iterator i, i_end = vis_filt.end();
179  for (i = vis_filt.begin(); i != i_end; ++i) {
180  bool visible = (*i)["visible"].to_bool(true);
181  bool respect_fog = (*i)["respect_fog"].to_bool(true);
182 
183  side_filter ssf(*i, fc_);
184  std::vector<int> sides = ssf.get_teams();
185 
186  bool found = false;
187  for (const int side : sides) {
188  const team &viewing_team = fc_->get_disp_context().get_team(side);
189  bool viewer_sees = respect_fog ? !viewing_team.fogged(loc) : !viewing_team.shrouded(loc);
190  if (visible == viewer_sees) {
191  found = true;
192  break;
193  }
194  }
195  if (!found) {return false;}
196  }
197  }
198 
199  //Allow filtering on adjacent locations
200  if(cfg_.has_child("filter_adjacent_location")) {
201  adjacent_loc_array_t adjacent;
202  get_adjacent_tiles(loc, adjacent.data());
203  const vconfig::child_list& adj_cfgs = cfg_.get_children("filter_adjacent_location");
204  vconfig::child_list::const_iterator i, i_end, i_begin = adj_cfgs.begin();
205  for (i = i_begin, i_end = adj_cfgs.end(); i != i_end; ++i) {
206  int match_count = 0;
207  vconfig::child_list::difference_type index = i - i_begin;
208  std::vector<map_location::DIRECTION> dirs = (*i).has_attribute("adjacent")
210  std::vector<map_location::DIRECTION>::const_iterator j, j_end = dirs.end();
211  for (j = dirs.begin(); j != j_end; ++j) {
212  map_location &adj = adjacent[*j];
213  if (fc_->get_disp_context().map().on_board(adj)) {
214  if(cache_.adjacent_matches == nullptr) {
215  while(index >= std::distance(cache_.adjacent_match_cache.begin(), cache_.adjacent_match_cache.end())) {
216  const vconfig& adj_cfg = adj_cfgs[cache_.adjacent_match_cache.size()];
217  std::pair<terrain_filter, std::map<map_location,bool>> amc_pair(
218  terrain_filter(adj_cfg, *this),
219  std::map<map_location,bool>());
220  cache_.adjacent_match_cache.push_back(amc_pair);
221  }
222  terrain_filter &amc_filter = cache_.adjacent_match_cache[index].first;
223  std::map<map_location,bool> &amc = cache_.adjacent_match_cache[index].second;
224  std::map<map_location,bool>::iterator lookup = amc.find(adj);
225  if(lookup == amc.end()) {
226  if(amc_filter(adj)) {
227  amc[adj] = true;
228  ++match_count;
229  } else {
230  amc[adj] = false;
231  }
232  } else if(lookup->second) {
233  ++match_count;
234  }
235  } else {
236  assert(index < std::distance(cache_.adjacent_matches->begin(), cache_.adjacent_matches->end()));
237  std::set<map_location> &amc = (*cache_.adjacent_matches)[index];
238  if(amc.find(adj) != amc.end()) {
239  ++match_count;
240  }
241  }
242  }
243  }
244  static std::vector<std::pair<int,int>> default_counts = utils::parse_ranges("1-6");
245  std::vector<std::pair<int,int>> counts = (*i).has_attribute("count")
246  ? utils::parse_ranges((*i)["count"]) : default_counts;
247  if(!in_ranges(match_count, counts)) {
248  return false;
249  }
250  }
251  }
252 
253  const t_string& t_tod_type = cfg_["time_of_day"];
254  const t_string& t_tod_id = cfg_["time_of_day_id"];
255  const std::string& tod_type = t_tod_type;
256  const std::string& tod_id = t_tod_id;
257  if(!tod_type.empty() || !tod_id.empty()) {
258  // creating a time_of_day is expensive, only do it if we will use it
259  time_of_day tod;
260 
261  if(flat_) {
262  tod = fc_->get_tod_man().get_time_of_day(loc);
263  } else {
265  }
266 
267  if(!tod_type.empty()) {
268  const std::vector<std::string>& vals = utils::split(tod_type);
269  if(tod.lawful_bonus<0) {
270  if(std::find(vals.begin(),vals.end(),unit_type::ALIGNMENT::enum_to_string(unit_type::ALIGNMENT::CHAOTIC)) == vals.end()) {
271  return false;
272  }
273  } else if(tod.lawful_bonus>0) {
274  if(std::find(vals.begin(),vals.end(),unit_type::ALIGNMENT::enum_to_string(unit_type::ALIGNMENT::LAWFUL)) == vals.end()) {
275  return false;
276  }
277  } else if(std::find(vals.begin(),vals.end(),unit_type::ALIGNMENT::enum_to_string(unit_type::ALIGNMENT::NEUTRAL)) == vals.end()) {
278  return false;
279  }
280  }
281 
282  if(!tod_id.empty()) {
283  if(tod_id != tod.id) {
284  if(std::find(tod_id.begin(),tod_id.end(),',') != tod_id.end() &&
285  std::search(tod_id.begin(),tod_id.end(),
286  tod.id.begin(),tod.id.end()) != tod_id.end()) {
287  const std::vector<std::string>& vals = utils::split(tod_id);
288  if(std::find(vals.begin(),vals.end(),tod.id) == vals.end()) {
289  return false;
290  }
291  } else {
292  return false;
293  }
294  }
295  }
296  }
297 
298  //allow filtering on owner (for villages)
299  const config::attribute_value &owner_side = cfg_["owner_side"];
300  const vconfig& filter_owner = cfg_.child("filter_owner");
301  if(!filter_owner.null()) {
302  if(!owner_side.empty()) {
303  WRN_NG << "duplicate side information in a SLF, ignoring inline owner_side=" << std::endl;
304  }
305  if(!fc_->get_disp_context().map().is_village(loc))
306  return false;
307  side_filter ssf(filter_owner, fc_);
308  const std::vector<int>& sides = ssf.get_teams();
309  bool found = false;
310  if(sides.empty() && fc_->get_disp_context().village_owner(loc) == -1)
311  found = true;
312  for(const int side : sides) {
313  if(fc_->get_disp_context().get_team(side).owns_village(loc)) {
314  found = true;
315  break;
316  }
317  }
318  if(!found)
319  return false;
320  }
321  else if(!owner_side.empty()) {
322  const int side_index = owner_side.to_int(0) - 1;
323  if(fc_->get_disp_context().village_owner(loc) != side_index) {
324  return false;
325  }
326  }
327 
328  if(cfg_.has_attribute("formula")) {
329  try {
331  wfl::map_formula_callable callable(main.fake_ptr());
332  if(ref_unit) {
333  auto ref = std::make_shared<wfl::unit_callable>(*ref_unit);
334  callable.add("teleport_unit", wfl::variant(ref));
335  // It's not destroyed upon scope exit because the variant holds a reference
336  }
338  const wfl::formula form(cfg_["formula"], &symbols);
339  if(!form.evaluate(callable).as_bool()) {
340  return false;
341  }
342  return true;
343  } catch(const 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  std::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  std::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  std::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 }
bool operator()(const map_location &) const
Definition: filter.cpp:452
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...
std::function< int(lua_State *)> lua_function
bool empty() const
Tests for an attribute that either was never set or was set to "".
int h() const
Effective map height.
Definition: map.hpp:116
const team & get_team(int side) const
virtual const display_context & get_disp_context() const =0
vconfig child(const std::string &key) const
Returns a child of *this whose key is key.
Definition: variable.cpp:252
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.cpp:517
This class represents a single unit of a specific type.
Definition: unit.hpp:99
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
all_children_iterator ordered_begin() const
In-order iteration over all children.
Definition: variable.cpp:445
bool run_filter(char const *name, const unit &u)
Runs a script from a unit filter.
virtual bool operator()(const map_location &loc) const
Definition: filter.hpp:51
Variant for storing WML attributes.
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
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
bool has_attribute(const std::string &key) const
< Synonym for operator[]
Definition: variable.hpp:99
map_location operator()(const config &cfg) const
Definition: filter.cpp:504
std::string id
Definition: time_of_day.hpp:91
int border_size() const
Size of the map border.
Definition: map.hpp:119
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:85
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:50
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:96
bool in_ranges(const Cmp c, const std::vector< std::pair< Cmp, Cmp >> &ranges)
Definition: math.hpp:66
#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
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:360
terrain_filter_cache cache_
Definition: filter.hpp:96
#define WRN_NG
Definition: filter.cpp:39
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:78
std::string get_key() const
Definition: variable.cpp:412
const std::set< map_location > & get_area_by_id(const std::string &id) const
-file sdl_utils.hpp
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...
Definition: game_config.cpp:91
Definitions for the interface to Wesnoth Markup Language (WML).
virtual const gamemap & map() const =0
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:56
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_internal(const map_location &loc, const unit *ref_unit, const bool ignore_xy) const
Definition: filter.cpp:99
void get_locs_impl(std::set< map_location > &locs, const unit *ref_unit, bool with_border) const
Definition: filter.cpp:507
const filter_context * fc_
Definition: filter.hpp:79
config to_config() const
Definition: filter.cpp:663
Object which defines a time of day with associated bonuses, image, sounds etc.
Definition: time_of_day.hpp:57
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&#39;s dimensions as bounds...
Definition: map.cpp:399
child_list get_children(const std::string &key) const
Definition: variable.cpp:190
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:44
const vconfig & make_safe() const
instruct the vconfig to make a private copy of its underlying data.
Definition: variable.cpp:127
std::vector< std::pair< int, int > > parse_ranges(const std::string &str)
std::vector< std::pair< int, int > > default_counts
const unit & ref_
Definition: filter.cpp:355
bool on_board_with_border(const map_location &loc) const
Definition: map.cpp:365
map_formula_callable & add(const std::string &key, const variant &value)
Definition: callable.hpp:252
all_children_iterator ordered_end() const
Definition: variable.cpp:450
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
bool valid() const
Definition: location.hpp:93
std::string type
Definition: formula.hpp:105
static const std::vector< DIRECTION > & default_dirs()
Default list of directions.
Definition: location.cpp:51
terrain_filter(const vconfig &cfg, const filter_context *fc, const bool flat_tod=false)
Definition: filter.cpp:45
virtual const unit_map & units() const =0
std::array< map_location, 6 > adjacent_loc_array_t
Definition: location.hpp:170
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:93
~terrain_filter()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: filter.cpp:41
Encapsulates the map of the game.
Definition: location.hpp:42
unit_iterator find(std::size_t id)
Definition: map.cpp:311
bool shrouded(const map_location &loc) const
Definition: team.cpp:644
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.
int w() const
Effective map width.
Definition: map.hpp:113
std::size_t i
Definition: function.cpp:933
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:269
bool operator()(const map_location &loc) const override
Definition: filter.cpp:358
bool has_child(const std::string &key) const
Returns whether or not *this has a child whose key is key.
Definition: variable.cpp:279
Game configuration data as global variables.
Definition: build_info.cpp:46
int main()
terrain_filter & operator=(const terrain_filter &other)
Definition: filter.cpp:74
t_translation::terrain_code number() const
Definition: terrain.hpp:44
void get_tiles_radius(const map_location &center, 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...
Definition: pathutils.cpp:68
map_location result_type
Definition: filter.cpp:505
int w
bool matches_range(const std::string &xloc, const std::string &yloc) const
Definition: location.cpp:316
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.
Definition: unicode.cpp:71
virtual const tod_manager & get_tod_man() const =0
bool is_village(const map_location &loc) const
Definition: map.cpp:64
Information on a WML variable.
virtual const game_data * get_game_data() const =0
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1174
static int cond(LexState *ls)
Definition: lparser.cpp:1177
std::vector< int > get_teams() const
Definition: side_filter.cpp:54
A variable-expanding proxy for the config class.
Definition: variable.hpp:42
static lg::log_domain log_engine("engine")
const config & get_config() const
Definition: variable.hpp:75
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:91
bool fogged(const map_location &loc) const
Definition: team.cpp:653
std::unique_ptr< std::vector< std::set< map_location > > > adjacent_matches
Definition: filter.hpp:88
#define e
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...
static void filter_area(T &&src, location_set &dest, const terrain_filter &filter, const F1 &f1)
Definition: filter.cpp:478
bool match_impl(const map_location &loc, const unit *ref_unit) const
Definition: filter.cpp:363
std::vector< vconfig > child_list
Definition: variable.hpp:78
bool as_bool() const
Returns a boolean state of the variant value.
Definition: variant.cpp:320
bool owns_village(const map_location &loc) const
Definition: team.hpp:185
#define ERR_NG
Definition: filter.cpp:38
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
bool null() const
Definition: variable.hpp:73
bool valid() const
Definition: map.hpp:276
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
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
map_location special_location(const std::string &id) const
Definition: map.cpp:302
const std::size_t max_loop_
Definition: filter.hpp:97
bool match(const map_location &loc) const
Definition: filter.hpp:40
std::set< map_location > location_set
Definition: filter.cpp:448