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) 2014 - 2018 by Chris Beck <render787@gmail.com>
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 #include "units/filter.hpp"
16 
17 #include "log.hpp"
18 
19 #include "config.hpp"
20 #include "game_data.hpp"
21 #include "map/map.hpp"
22 #include "map/location.hpp"
23 #include "scripting/game_lua_kernel.hpp" //Needed for lua kernel
24 #include "side_filter.hpp"
25 #include "team.hpp"
26 #include "terrain/filter.hpp"
27 #include "tod_manager.hpp"
28 #include "units/unit.hpp"
30 #include "units/types.hpp"
31 #include "variable.hpp" // needed for vconfig, scoped unit
32 #include "wml_exception.hpp" // needed for FAIL
33 #include "formula/callable_objects.hpp"
34 #include "formula/formula.hpp"
36 #include "formula/string_utils.hpp"
37 #include "resources.hpp"
38 
39 #include <boost/optional.hpp>
40 
41 static lg::log_domain log_config("config");
42 #define ERR_CF LOG_STREAM(err, log_config)
43 #define DBG_CF LOG_STREAM(debug, log_config)
44 
45 using namespace unit_filter_impl;
46 
48  : cfg_(cfg)
49  , fc_(resources::filter_con)
50  , use_flat_tod_(false)
51  , impl_(cfg_)
52  , max_matches_(-1)
53 {
54 }
55 
56 bool unit_filter::matches(const unit& u) const {
57  return impl_.matches(unit_filter_impl::unit_filter_args{u, u.get_location(), nullptr, fc_, use_flat_tod_});
58 }
59 
60 bool unit_filter::matches(const unit & u, const unit & u2) const {
61  return impl_.matches(unit_filter_impl::unit_filter_args{u, u.get_location(), &u2, fc_, use_flat_tod_});
62 }
63 
64 std::vector<const unit *> unit_filter::all_matches_on_map(const map_location* loc, const unit* other_unit) const
65 {
66  std::vector<const unit *> ret;
67  int max_matches = max_matches_;
68 
69  for (const unit & u : fc_->get_disp_context().units()) {
70  if (impl_.matches(unit_filter_impl::unit_filter_args{u, loc ? *loc : u.get_location(), other_unit, fc_, use_flat_tod_})) {
71  if(max_matches == 0) {
72  return ret;
73  }
74  --max_matches;
75  ret.push_back(&u);
76  }
77  }
78  return ret;
79 }
80 
82  const unit_map & units = fc_->get_disp_context().units();
83  for(unit_map::const_iterator u = units.begin(); u != units.end(); ++u) {
84  if (matches(*u, u->get_location())) {
85  return u.get_shared_ptr();
86  }
87  }
88  return unit_const_ptr();
89 }
90 
91 namespace {
92 
93 struct unit_filter_xy : public unit_filter_base
94 {
95  unit_filter_xy(const std::string& x, const std::string& y) : x_(x), y_(y) {}
96 
97  virtual bool matches(const unit_filter_args& args) const override
98  {
101 
102  if(x.empty() && y.empty()) {
103  return false;
104  }
105  else if(x == "recall" && y == "recall") {
106  return !args.fc->get_disp_context().map().on_board(args.loc);
107  }
108  else {
109  return args.loc.matches_range(x, y);
110  }
111  }
112 
113  const std::string x_;
114  const std::string y_;
115 };
116 
117 struct unit_filter_adjacent : public unit_filter_base
118 {
119  unit_filter_adjacent(const vconfig& cfg)
120  : child_(cfg)
121  , cfg_(cfg)
122  {
123  }
124 
125  virtual bool matches(const unit_filter_args& args) const override
126  {
127  const unit_map& units = args.fc->get_disp_context().units();
128  adjacent_loc_array_t adjacent;
129  get_adjacent_tiles(args.loc, adjacent.data());
130  int match_count=0;
131 
132  config::attribute_value i_adjacent = cfg_["adjacent"];
133  std::vector<map_location::DIRECTION> dirs;
134  if (i_adjacent.empty()) {
136  } else {
137  dirs = map_location::parse_directions(i_adjacent);
138  }
139  for (map_location::DIRECTION dir : dirs) {
140  unit_map::const_iterator unit_itor = units.find(adjacent[dir]);
141  if (unit_itor == units.end() || !child_.matches(unit_filter_args{*unit_itor, unit_itor->get_location(), &args.u, args.fc, args.use_flat_tod} )) {
142  continue;
143  }
144  auto is_enemy = cfg_["is_enemy"];
145  if (!is_enemy.empty() && is_enemy.to_bool() != args.fc->get_disp_context().get_team(args.u.side()).is_enemy(unit_itor->side())) {
146  continue;
147  }
148  ++match_count;
149  }
150 
151  static std::vector<std::pair<int,int>> default_counts = utils::parse_ranges("1-6");
152  config::attribute_value i_count = cfg_["count"];
153  return in_ranges(match_count, !i_count.blank() ? utils::parse_ranges(i_count) : default_counts);
154  }
155 
156  const unit_filter_compound child_;
157  const vconfig cfg_;
158 };
159 
160 
161 template<typename F>
162 struct unit_filter_child_literal : public unit_filter_base
163 {
164  unit_filter_child_literal(const vconfig& v, const F& f) : v_(v) , f_(f) {}
165  virtual bool matches(const unit_filter_args& args) const override
166  {
167  return f_(v_, args);
168  }
169  vconfig v_;
170  F f_;
171 };
172 
173 template<typename T, typename F>
174 struct unit_filter_attribute_parsed : public unit_filter_base
175 {
176  unit_filter_attribute_parsed(T&& v, F&& f) : v_(std::move(v)), f_(std::move(f)) {}
177  virtual bool matches(const unit_filter_args& args) const override
178  {
179  return f_(v_, args);
180  }
181  T v_;
182  F f_;
183 };
184 
185 template<typename C, typename F>
186 struct unit_filter_attribute_literal : public unit_filter_base
187 {
188  unit_filter_attribute_literal(std::string&& v, C&& c, F&& f) : v_(std::move(v)), c_(std::move(c)), f_(std::move(f)) {}
189  virtual bool matches(const unit_filter_args& args) const override
190  {
193  return f_(c_(v), args);
194  }
195  std::string v_;
196  C c_;
197  F f_;
198 };
199 
200 class contains_dollar_visitor : public boost::static_visitor<bool>
201 {
202 public:
203  contains_dollar_visitor() {}
204 
205 
206  template<typename T>
207  bool operator()(const T&) const { return false; }
208 
209  bool operator()(const t_string&) const { return true; }
210 
211  bool operator()(const std::string& s) const
212  {
213  return s.find('$') != std::string::npos;
214  }
215 };
216 
217 }
218 
219 
220 unit_filter_compound::unit_filter_compound(vconfig cfg)
221  : children_()
222  , cond_children_()
223 {
224  fill(cfg);
225 }
226 
227 bool unit_filter_compound::matches(const unit_filter_args& args) const
228 {
229  bool res;
230 
231  if(args.loc.valid()) {
232  scoped_xy_unit auto_store("this_unit", args.u.get_location(), args.fc->get_disp_context().units());
233  if (args.u2) {
234  const map_location& loc2 = args.u2->get_location();
235  scoped_xy_unit u2_auto_store("other_unit", loc2, args.fc->get_disp_context().units());
236  res = filter_impl(args);
237  } else {
238  res = filter_impl(args);
239  }
240  } else {
241  // If loc is invalid, then this is a recall list unit (already been scoped)
242  res = filter_impl(args);
243  }
244 
245  // Handle [and], [or], and [not] with in-order precedence
246  for(const auto & filter : cond_children_) {
247  bool child_res = filter.second.matches(args);
248 
249  switch (filter.first.v) {
250  case CONDITIONAL_TYPE::AND:
251  res = res && child_res;
252  break;
253  case CONDITIONAL_TYPE::OR:
254  res = res || child_res;
255  break;
257  res = res && !child_res;
258  break;
259  }
260  }
261  return res;
262 }
263 
264 bool unit_filter_compound::filter_impl(const unit_filter_args& args) const
265 {
266  for(const auto & filter : children_) {
267  if (!filter->matches(args)) {
268  return false;
269  }
270  }
271  return true;
272 }
273 
274 template<typename F>
276 {
277  children_.emplace_back(new unit_filter_child_literal<F>(c, func));
278 }
279 
280 template<typename C, typename F>
282 {
283  if(v.blank()) {
284  }
285  else if(v.apply_visitor(contains_dollar_visitor())) {
286  children_.emplace_back(new unit_filter_attribute_literal<C, F>(std::move(v.str()), std::move(conv), std::move(func)));
287  }
288  else {
289  children_.emplace_back(new unit_filter_attribute_parsed<decltype(conv(v)), F>(std::move(conv(v)), std::move(func)));
290  }
291 }
292 
294  {
295  const config& literal = cfg.get_config();
296 
297  //optimisation
298  if(literal.empty()) { return; }
299 
300  create_attribute(literal["name"],
301  [](const config::attribute_value& c) { return c.t_str(); },
302  [](const t_string& str, const unit_filter_args& args) { return str == args.u.name(); }
303  );
304 
305  create_attribute(literal["id"],
306  [](const config::attribute_value& c) { return utils::split(c.str()); },
307  [](const std::vector<std::string>& id_list, const unit_filter_args& args)
308  {
309  return std::find(id_list.begin(), id_list.end(), args.u.id()) != id_list.end();
310  }
311  );
312 
313  create_attribute(literal["speaker"],
314  [](const config::attribute_value& c) { return c.str(); },
315  [](const std::string& speaker, const unit_filter_args& args)
316  {
317  return speaker == args.u.id();
318  }
319  );
320 
321  create_attribute(literal["type"],
322  [](const config::attribute_value& c) { return utils::split(c.str()); },
323  [](const std::vector<std::string>& types, const unit_filter_args& args)
324  {
325  return std::find(types.begin(), types.end(), args.u.type_id()) != types.end();
326  }
327  );
328 
329  create_attribute(literal["type_adv_tree"],
330  [](const config::attribute_value& c) { return utils::split(c.str()); },
331  [](const std::vector<std::string>& types, const unit_filter_args& args)
332  {
333  std::set<std::string> types_expanded;
334  for(const std::string& type : types) {
335  if(types_expanded.count(type)) {
336  continue;
337  }
338  if(const unit_type* ut = unit_types.find(type)) {
339  const auto& tree = ut->advancement_tree();
340  types_expanded.insert(tree.begin(), tree.end());
341  types_expanded.insert(type);
342  }
343  }
344  return types_expanded.find(args.u.type_id()) != types_expanded.end();
345  }
346  );
347 
348  create_attribute(literal["variation"],
349  [](const config::attribute_value& c) { return utils::split(c.str()); },
350  [](const std::vector<std::string>& types, const unit_filter_args& args)
351  {
352  return std::find(types.begin(), types.end(), args.u.variation()) != types.end();
353  }
354  );
355 
356  create_attribute(literal["has_variation"],
357  [](const config::attribute_value& c) { return utils::split(c.str()); },
358  [](const std::vector<std::string>& types, const unit_filter_args& args)
359  {
360  // If this unit is a variation itself then search in the base unit's variations.
361  const unit_type* const type = args.u.variation().empty() ? &args.u.type() : unit_types.find(args.u.type().base_id());
362  assert(type);
363 
364  for(const std::string& variation_id : types) {
365  if (type->has_variation(variation_id)) {
366  return true;
367  }
368  }
369  return false;
370  }
371  );
372 
373  create_attribute(literal["ability"],
374  [](const config::attribute_value& c) { return utils::split(c.str()); },
375  [](const std::vector<std::string>& abilities, const unit_filter_args& args)
376  {
377  for(const std::string& ability_id : abilities) {
378  if (args.u.has_ability_by_id(ability_id)) {
379  return true;
380  }
381  }
382  return false;
383  }
384  );
385 
386  create_attribute(literal["ability_type"],
387  [](const config::attribute_value& c) { return utils::split(c.str()); },
388  [](const std::vector<std::string>& abilities, const unit_filter_args& args)
389  {
390  for(const std::string& ability : abilities) {
391  if (args.u.has_ability_type(ability)) {
392  return true;
393  }
394  }
395  return false;
396  }
397  );
398 
399  create_attribute(literal["ability_type_active"],
400  [](const config::attribute_value& c) { return utils::split(c.str()); },
401  [](const std::vector<std::string>& abilities, const unit_filter_args& args)
402  {
403  for(const std::string& ability : abilities) {
404  if (!args.u.get_abilities(ability, args.loc).empty()) {
405  return true;
406  }
407  }
408  return false;
409  }
410  );
411 
412  create_attribute(literal["trait"],
413  [](const config::attribute_value& c)
414  {
415  auto res = utils::split(c.str());
416  std::sort(res.begin(), res.end());
417  return res;
418 
419  },
420  [](const std::vector<std::string>& check_traits, const unit_filter_args& args)
421  {
422 
423  std::vector<std::string> have_traits = args.u.get_traits_list();
424  std::vector<std::string> isect;
425  std::sort(have_traits.begin(), have_traits.end());
426  std::set_intersection(check_traits.begin(), check_traits.end(), have_traits.begin(), have_traits.end(), std::back_inserter(isect));
427  return !isect.empty();
428  }
429  );
430 
431  create_attribute(literal["race"],
432  [](const config::attribute_value& c) { return utils::split(c.str()); },
433  [](const std::vector<std::string>& races, const unit_filter_args& args)
434  {
435  return std::find(races.begin(), races.end(), args.u.race()->id()) != races.end();
436  }
437  );
438 
439  create_attribute(literal["gender"],
440  [](const config::attribute_value& c) { return string_gender(c.str()); },
441  [](unit_race::GENDER gender, const unit_filter_args& args)
442  {
443  return gender == args.u.gender();
444  }
445  );
446 
447  create_attribute(literal["side"],
448  [](const config::attribute_value& c)
449  {
450  std::vector<int> res;
451  for(const std::string& s : utils::split(c.str())) {
452  res.push_back(std::stoi(s));
453  }
454  return res;
455  },
456  [](const std::vector<int>& sides, const unit_filter_args& args)
457  {
458  return std::find(sides.begin(), sides.end(), args.u.side()) != sides.end();
459  }
460  );
461 
462  create_attribute(literal["status"],
463  [](const config::attribute_value& c) { return utils::split(c.str()); },
464  [](const std::vector<std::string>& statuses, const unit_filter_args& args)
465  {
466  for(const std::string& status : statuses) {
467  if (args.u.get_state(status)) {
468  return true;
469  }
470  }
471  return false;
472  }
473  );
474 
475  create_attribute(literal["has_weapon"],
476  [](const config::attribute_value& c) { return c.str(); },
477  [](const std::string& weapon, const unit_filter_args& args)
478  {
479 
480  for(const attack_type& a : args.u.attacks()) {
481  if(a.id() == weapon) {
482  return true;
483  }
484  }
485  return false;
486  }
487  );
488 
489  create_attribute(literal["role"],
490  [](const config::attribute_value& c) { return c.str(); },
491  [](const std::string& role, const unit_filter_args& args)
492  {
493  return args.u.get_role() == role;
494  }
495  );
496 
497  create_attribute(literal["ai_special"],
498  [](const config::attribute_value& c) { return c.str(); },
499  [](const std::string& ai_special, const unit_filter_args& args)
500  {
501  return (ai_special == "guardian") == args.u.get_state(unit::STATE_GUARDIAN);
502  }
503  );
504 
505  create_attribute(literal["canrecruit"],
506  [](const config::attribute_value& c) { return c.to_bool(); },
507  [](bool canrecruit, const unit_filter_args& args)
508  {
509  return args.u.can_recruit() == canrecruit;
510  }
511  );
512 
513  create_attribute(literal["recall_cost"],
514  [](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
515  [](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
516  {
517  for(auto cost : ranges) {
518  if(cost.first <= args.u.recall_cost() && args.u.recall_cost() <= cost.second) {
519  return true;
520  }
521  }
522  return false;
523  }
524  );
525 
526  create_attribute(literal["level"],
527  [](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
528  [](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
529  {
530  for(auto lvl : ranges) {
531  if(lvl.first <= args.u.level() && args.u.level() <= lvl.second) {
532  return true;
533  }
534  }
535  return false;
536  }
537  );
538 
539  create_attribute(literal["defense"],
540  [](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
541  [](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
542  {
543  int actual_defense = args.u.defense_modifier(args.fc->get_disp_context().map().get_terrain(args.loc));
544  for(auto def : ranges) {
545  if(def.first <= actual_defense && actual_defense <= def.second) {
546  return true;
547  }
548  }
549  return false;
550  }
551  );
552 
553  create_attribute(literal["movement_cost"],
554  [](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
555  [](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
556  {
557  int actual_cost = args.u.movement_cost(args.fc->get_disp_context().map().get_terrain(args.loc));
558  for(auto cost : ranges) {
559  if(cost.first <= actual_cost && actual_cost <= cost.second) {
560  return true;
561  }
562  }
563  return false;
564  }
565  );
566 
567  create_attribute(literal["vision_cost"],
568  [](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
569  [](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
570  {
571  int actual_cost = args.u.vision_cost(args.fc->get_disp_context().map().get_terrain(args.loc));
572  for(auto cost : ranges) {
573  if(cost.first <= actual_cost && actual_cost <= cost.second) {
574  return true;
575  }
576  }
577  return false;
578  }
579  );
580 
581  create_attribute(literal["jamming_cost"],
582  [](const config::attribute_value& c) { return utils::parse_ranges(c.str()); },
583  [](const std::vector<std::pair<int,int>>& ranges, const unit_filter_args& args)
584  {
585  int actual_cost = args.u.jamming_cost(args.fc->get_disp_context().map().get_terrain(args.loc));
586  for(auto cost : ranges) {
587  if(cost.first <= actual_cost && actual_cost <= cost.second) {
588  return true;
589  }
590  }
591  return false;
592  }
593  );
594 
595  create_attribute(literal["lua_function"],
596  [](const config::attribute_value& c) { return c.str(); },
597  [](const std::string& lua_function, const unit_filter_args& args)
598  {
599  if (game_lua_kernel * lk = args.fc->get_lua_kernel()) {
600  return lk->run_filter(lua_function.c_str(), args.u);
601  }
602  return true;
603  }
604  );
605 
606  create_attribute(literal["formula"],
607  [](const config::attribute_value& c)
608  {
609  //TODO: catch syntax error.
611  },
612  [](const wfl::formula& form, const unit_filter_args& args)
613  {
614  try {
615  const wfl::unit_callable main(args.loc, args.u);
616  wfl::map_formula_callable callable(main.fake_ptr());
617  if (args.u2) {
618  std::shared_ptr<wfl::unit_callable> secondary(new wfl::unit_callable(*args.u2));
619  callable.add("other", wfl::variant(secondary));
620  // It's not destroyed upon scope exit because the variant holds a reference
621  }
622  if(!form.evaluate(callable).as_bool()) {
623  return false;
624  }
625  return true;
626  } catch(wfl::formula_error& e) {
627  lg::wml_error() << "Formula error in unit filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
628  // Formulae with syntax errors match nothing
629  return false;
630  }
631  }
632  );
633 
634  create_attribute(literal["find_in"],
635  [](const config::attribute_value& c) { return c.str(); },
636  [](const std::string& find_in, const unit_filter_args& args)
637  {
638  // Allow filtering by searching a stored variable of units
639  if (const game_data * gd = args.fc->get_game_data()) {
640  try
641  {
642  for (const config& c : gd->get_variable_access_read(find_in).as_array())
643  {
644  if(c["id"] == args.u.id()) {
645  return true;
646  }
647  }
648  return false;
649  }
650  catch(const invalid_variablename_exception&)
651  {
652  return false;
653  }
654  }
655  return true;
656  }
657  );
658 
659  if (!literal["x"].blank() || !literal["y"].blank()) {
660  children_.emplace_back(new unit_filter_xy(literal["x"], literal["y"]));
661  }
662 
663  for(auto child : cfg.all_ordered()) {
664  CONDITIONAL_TYPE cond;
665  if(cond.parse(child.first)) {
666  cond_children_.emplace_back(std::piecewise_construct_t(), std::make_tuple(cond), std::make_tuple(child.second));
667  }
668  else if (child.first == "filter_wml") {
669  create_child(child.second, [](const vconfig& c, const unit_filter_args& args) {
670  config fwml = c.get_parsed_config();
671 
672  /* Check if the filter only cares about variables.
673  If so, no need to serialize the whole unit. */
674  config::all_children_itors ci = fwml.all_children_range();
675  if (fwml.all_children_count() == 1 && fwml.attribute_count() == 1 && ci.front().key == "variables") {
676  return args.u.variables().matches(ci.front().cfg);
677  } else {
678  config ucfg;
679  args.u.write(ucfg);
680  return ucfg.matches(fwml);
681  }
682  });
683  }
684  else if (child.first == "filter_vision") {
685  create_child(child.second, [](const vconfig& c, const unit_filter_args& args) {
686  std::set<int> viewers;
687  side_filter ssf(c, args.fc);
688  std::vector<int> sides = ssf.get_teams();
689  viewers.insert(sides.begin(), sides.end());
690 
691  for (const int viewer : viewers) {
692  bool fogged = args.fc->get_disp_context().get_team(viewer).fogged(args.loc);
693  bool hiding = args.u.invisible(args.loc, args.fc->get_disp_context()) && args.fc->get_disp_context().get_team(viewer).is_enemy(args.u.side());
694  bool unit_hidden = fogged || hiding;
695  if (c["visible"].to_bool(true) != unit_hidden) {
696  return true;
697  }
698  }
699  return false;
700  });
701  }
702  else if (child.first == "filter_adjacent") {
703  children_.emplace_back(new unit_filter_adjacent(child.second));
704  }
705  else if (child.first == "filter_location") {
706  create_child(child.second, [](const vconfig& c, const unit_filter_args& args) {
707  return terrain_filter(c, args.fc, args.use_flat_tod).match(args.loc);
708  });
709  }
710  else if (child.first == "filter_side") {
711  create_child(child.second, [](const vconfig& c, const unit_filter_args& args) {
712  return side_filter(c, args.fc).match(args.u.side());
713  });
714  }
715  else if (child.first == "has_attack") {
716  create_child(child.second, [](const vconfig& c, const unit_filter_args& args) {
717  for(const attack_type& a : args.u.attacks()) {
718  if(a.matches_filter(c.get_parsed_config())) {
719  return true;
720  }
721  }
722  return false;
723  });
724  }
725  else {
726  std::stringstream errmsg;
727  errmsg << "encountered a child [" << child.first << "] of a standard unit filter, it is being ignored";
728  DBG_CF << errmsg.str() << std::endl;
729  }
730 
731  }
732  }
733 
734 
735 
static lg::log_domain log_config("config")
boost::intrusive_ptr< const unit > unit_const_ptr
Definition: ptr.hpp:30
std::function< int(lua_State *)> lua_function
unit_iterator end()
Definition: map.hpp:415
std::vector< char_t > string
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
bool to_bool(bool def=false) const
virtual const display_context & get_disp_context() const =0
std::string str(const std::string &fallback="") const
const filter_context * fc_
Definition: filter.hpp:192
bool has_variation(const std::string &variation_id) const
Definition: types.cpp:782
The unit is a guardian - it won't move unless a target is sighted.
Definition: unit.hpp:726
This class represents a single unit of a specific type.
Definition: unit.hpp:100
int max_matches_
Definition: filter.hpp:195
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
#define DBG_CF
Definition: filter.cpp:43
Variant for storing WML attributes.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
std::string filename
Definition: formula.hpp:107
V::result_type apply_visitor(const V &visitor) const
Applies a visitor to the underlying variant.
#define a
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
bool empty() const
Tests for an attribute that either was never set or was set to "".
virtual bool matches(const unit_filter_args &) const =0
void create_child(const vconfig &c, F func)
Definition: filter.cpp:275
std::vector< const unit * > all_matches_on_map(const map_location *loc=nullptr, const unit *other_unit=nullptr) const
Definition: filter.cpp:64
unit_iterator begin()
Definition: map.hpp:405
unit_type_data unit_types
Definition: types.cpp:1453
bool in_ranges(const Cmp c, const std::vector< std::pair< Cmp, Cmp >> &ranges)
Definition: math.hpp:81
STL namespace.
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
-file sdl_utils.hpp
bool empty() const
Definition: config.cpp:830
Definitions for the interface to Wesnoth Markup Language (WML).
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.
unit_filter(vconfig cfg)
Definition: filter.cpp:47
A single unit type that the player may recruit.
Definition: types.hpp:42
game_data * gamedata
Definition: resources.cpp:22
static T & get_lua_kernel(lua_State *L)
std::vector< std::pair< int, int > > parse_ranges(const std::string &str)
std::vector< std::pair< int, int > > default_counts
unit_filter_impl::unit_filter_compound impl_
Definition: filter.hpp:194
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1141
unit_const_ptr first_match_on_map() const
Definition: filter.cpp:81
bool as_bool() const
Returns a boolean state of the variant value.
Definition: variant.cpp:320
bool matches(const unit &u, const map_location &loc) const
Determine if *this matches filter at a specified location.
Definition: filter.hpp:134
filter_context * filter_con
Definition: resources.cpp:23
std::string type
Definition: formula.hpp:105
bool use_flat_tod_
Definition: filter.hpp:193
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
Definition: race.cpp:141
static const std::vector< DIRECTION > & default_dirs()
Default list of directions.
Definition: location.cpp:51
virtual const unit_map & units() const =0
const terrain_code NOT
std::array< map_location, 6 > adjacent_loc_array_t
Definition: location.hpp:130
bool blank() const
Tests for an attribute that was never set.
Encapsulates the map of the game.
Definition: location.hpp:42
std::vector< std::shared_ptr< unit_filter_base > > children_
Definition: filter.hpp:90
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:269
formula_callable_ptr fake_ptr()
Definition: callable.hpp:41
int main()
const config & get_config() const
Definition: variable.hpp:75
static map_location::DIRECTION s
pump_impl & impl_
Definition: pump.cpp:138
std::vector< std::pair< CONDITIONAL_TYPE, unit_filter_compound > > cond_children_
Definition: filter.hpp:91
DIRECTION
Valid directions which can be moved in our hexagonal world.
Definition: location.hpp:44
static int sort(lua_State *L)
Definition: ltablib.cpp:411
void create_attribute(const config::attribute_value c, C conv, F func)
Definition: filter.cpp:281
#define f
bool find(E event, F functor)
Tests whether an event handler is available.
boost::iterator_range< all_children_iterator > all_ordered() const
Definition: variable.hpp:188
static int cond(LexState *ls)
Definition: lparser.cpp:1177
A variable-expanding proxy for the config class.
Definition: variable.hpp:42
Standard logging facilities (interface).
Container associating units to locations.
Definition: map.hpp:99
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
Definition: types.cpp:1276
#define e
unit_iterator find(size_t id)
Definition: map.cpp:311
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
mock_char c
virtual bool matches(const unit_filter_args &u) const override
Definition: filter.cpp:227
bool filter_impl(const unit_filter_args &u) const
Definition: filter.cpp:264