The Battle for Wesnoth  1.13.4+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 - 2016 by Chris Beck <[email protected]>
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 "global.hpp"
18 #include "log.hpp"
19 
20 #include "config.hpp"
21 #include "display_context.hpp"
22 #include "filter_context.hpp"
23 #include "game_data.hpp"
24 #include "utils/make_enum.hpp"
25 #include "map/map.hpp"
26 #include "map/location.hpp"
27 #include "scripting/game_lua_kernel.hpp" //Needed for lua kernel
28 #include "side_filter.hpp"
29 #include "team.hpp"
30 #include "terrain/filter.hpp"
31 #include "tod_manager.hpp"
32 #include "units/unit.hpp"
34 #include "units/map.hpp"
35 #include "units/types.hpp"
36 #include "variable.hpp" // needed for vconfig, scoped unit
37 #include "wml_exception.hpp" // needed for FAIL
38 #include "formula/callable_objects.hpp"
39 #include "formula/formula.hpp"
40 
41 #include <boost/optional.hpp>
42 #include <boost/make_shared.hpp>
43 #include <boost/shared_ptr.hpp>
44 
45 #include <vector>
46 
47 static lg::log_domain log_config("config");
48 #define ERR_CF LOG_STREAM(err, log_config)
49 #define DBG_CF LOG_STREAM(debug, log_config)
50 
51 // Defined out of line to avoid including config in unit_filter.hpp
53  return impl_->to_config();
54 }
55 
56 ///Defined out of line to prevent including unit at unit_filter.hpp
57 bool unit_filter::matches(const unit & u) const {
58  return matches (u, u.get_location());
59 }
60 
61 bool unit_filter::matches(const unit & u, const map_location & loc, const unit & u2) const {
62  return impl_->matches(u,loc,&u2);
63 }
64 
65 bool unit_filter::matches(const unit & u, const unit & u2) const {
66  return matches(u, u.get_location(), u2);
67 }
68 
69 //bool unit_filter::matches(const unit & /*u*/, const map_location & /*loc*/) const {
70 // assert(false && "called match against a pure abstract unit_filter! this indicates a programmer error, this function must be overrided");
71 // return false;
72 //}
73 
74 
75 /// Forward declare the "construct" method which constructs an appropriate filter impl
76 static boost::shared_ptr<unit_filter_abstract_impl> construct(const vconfig & vcfg, const filter_context & fc, bool flat_tod);
77 
78 /// Null unit filter is built when the input config is null
80 public:
82  virtual bool matches(const unit & /*u*/, const map_location & /*loc*/, const unit *) const {
83  return true;
84  }
85  virtual std::vector<const unit *> all_matches_on_map(unsigned max_matches) const {
86  std::vector<const unit *> ret;
87  for(const unit & u : fc_.get_disp_context().units()) {
88  --max_matches;
89  ret.push_back(&u);
90  if(max_matches == 0) {
91  return ret;
92  }
93  }
94  return ret;
95  }
96 
99  }
100 
101 
103 
104  config to_config() const {
105  return config();
106  }
107 
108  bool empty() const {
109  return true;
110  }
111 
112 private:
114 };
115 
116 /// This enum helps to evaluate conditional filters
117 namespace conditional {
118  MAKE_ENUM (TYPE,
119  (AND, "and")
120  (OR, "or")
121  (NOT, "not")
122  )
123 }
124 
125 
126 /// The basic unit filter gives a generic implementation of the match fcn
128 public:
129  basic_unit_filter_impl(const vconfig & vcfg, const filter_context & fc, bool flat_tod)
130  : fc_(fc)
131  , vcfg(vcfg)
132  , use_flat_tod_(flat_tod)
133  , cond_children_()
135  {
136  // Handle [and], [or], and [not] with in-order precedence
139  while(cond != cond_end)
140  {
141  const std::string& cond_name = cond.get_key();
143  if(type.parse(cond_name)) {
144  const vconfig& cond_filter = cond.get_child();
145 
146  cond_children_.push_back(unit_filter(cond_filter, &fc_, use_flat_tod_));
147  cond_child_types_.push_back(type);
148  }
149  else {
150  static const int NUM_VALID_TAGS = 5;
151  static const std::string valid_tags[NUM_VALID_TAGS] = {
152  "filter_vision",
153  "filter_adjacent",
154  "filter_location",
155  "filter_side",
156  "filter_wml",
157  };
158  static const std::string* const valid_tags_end = valid_tags + NUM_VALID_TAGS;
159 
160  if (std::find(valid_tags, valid_tags_end, cond_name) == valid_tags_end){
161  std::stringstream errmsg;
162  errmsg << "encountered a child [" << cond_name << "] of a standard unit filter, it is being ignored";
163  DBG_CF << errmsg.str() << std::endl; //FAIL( errmsg.str() );
164  }
165 
166  }
167  ++cond;
168  }
169  this->vcfg.make_safe();
170  }
171 
172  virtual bool matches(const unit & u, const map_location & loc, const unit * u2) const;
173  virtual std::vector<const unit *> all_matches_on_map(unsigned max_matches) const;
174  virtual unit_const_ptr first_match_on_map() const;
175  config to_config() const {
176  return vcfg.get_config();
177  }
178 
180 private:
182  const vconfig vcfg;
184 
185  std::vector<unit_filter> cond_children_;
186  std::vector<conditional::TYPE> cond_child_types_;
187 
188  bool internal_matches_filter(const unit & u, const map_location & loc, const unit* u2) const;
189 };
190 
191 /** "Factory" method which constructs an appropriate implementation
192  *
193  */
194 
195 static boost::shared_ptr<unit_filter_abstract_impl> construct(const vconfig & vcfg, const filter_context & fc, bool flat_tod)
196 {
197  if (vcfg.empty()) {
198  return boost::make_shared<null_unit_filter_impl> (fc);
199  }
200  if (vcfg.get_config().attribute_count() == 1 && vcfg.get_config().all_children_count() == 0 && vcfg.has_attribute("limit")) {
201  return boost::make_shared<null_unit_filter_impl> (fc);
202  }
203  return boost::make_shared<basic_unit_filter_impl>(vcfg, fc, flat_tod);
204  //TODO: Add more efficient implementations for special cases
205 }
206 
207 /** Ctor of unit filter
208  * unit_filter::unit_filter acts as a factory, selecting the appropriate implementation class
209  */
210 unit_filter::unit_filter(const vconfig & vcfg, const filter_context * fc, bool flat_tod)
211  : max_matches_(static_cast<unsigned>(-1))
212 {
213  if(vcfg) {
214  max_matches_ = vcfg["limit"].to_unsigned(max_matches_);
215  }
216  if (!fc) {
217  assert(false && "attempt to instantiate a unit filter with a null filter context!");
218  }
219  impl_ = construct(vcfg, *fc, flat_tod);
220 }
221 
222 /** Begin implementations of filter impl's
223  */
224 
225 bool basic_unit_filter_impl::matches(const unit & u, const map_location& loc, const unit * u2) const
226 {
227  bool matches = true;
228 
229  if(loc.valid()) {
230  scoped_xy_unit auto_store("this_unit", loc.x, loc.y, fc_.get_disp_context().units());
231  if (u2) {
232  const map_location& loc2 = u2->get_location();
233  scoped_xy_unit auto_store("other_unit", loc2.x, loc2.y, fc_.get_disp_context().units());
234  matches = internal_matches_filter(u, loc, u2);
235  } else {
236  matches = internal_matches_filter(u, loc, u2);
237  }
238  } else {
239  // If loc is invalid, then this is a recall list unit (already been scoped)
240  matches = internal_matches_filter(u, loc, nullptr);
241  }
242 
243  // Handle [and], [or], and [not] with in-order precedence
244  for (size_t i = 0; i < cond_children_.size(); i++) {
245  switch (cond_child_types_[i].v) {
246  case conditional::TYPE::AND:
247  matches = matches && cond_children_[i].matches(u,loc);
248  break;
249  case conditional::TYPE::OR:
250  matches = matches || cond_children_[i].matches(u,loc);
251  break;
253  matches = matches && !cond_children_[i].matches(u,loc);
254  }
255  }
256  return matches;
257 }
258 
260 {
261  if (!vcfg["name"].blank() && vcfg["name"].t_str() != u.name()) {
262  return false;
263  }
264 
265  if (!vcfg["id"].empty()) {
266  std::vector<std::string> id_list = utils::split(vcfg["id"]);
267  if (std::find(id_list.begin(), id_list.end(), u.id()) == id_list.end()) {
268  return false;
269  }
270  }
271 
272  // Allow 'speaker' as an alternative to id, since people use it so often
273  if (!vcfg["speaker"].blank() && vcfg["speaker"].str() != u.id()) {
274  return false;
275  }
276 
277  if (vcfg.has_child("filter_location")) {
278  if (vcfg.count_children("filter_location") > 1) {
279  FAIL("Encountered multiple [filter_location] children of a standard unit filter. "
280  "This is not currently supported and in all versions of wesnoth would have "
281  "resulted in the later children being ignored. You must use [and] or similar "
282  "to achieve the desired result.");
283  }
284  terrain_filter filt(vcfg.child("filter_location"), &fc_, use_flat_tod_);
285  if (!filt.match(loc)) {
286  return false;
287  }
288  }
289 
290  if(vcfg.has_child("filter_side")) {
291  if (vcfg.count_children("filter_side") > 1) {
292  FAIL("Encountered multiple [filter_side] children of a standard unit filter. "
293  "This is not currently supported and in all versions of wesnoth would have "
294  "resulted in the later children being ignored. You must use [and] or similar "
295  "to achieve the desired result.");
296  }
297  side_filter filt(vcfg.child("filter_side"), &fc_);
298  if(!filt.match(u.side()))
299  return false;
300  }
301 
302  // Also allow filtering on location ranges outside of the location filter
303  if (!vcfg["x"].blank() || !vcfg["y"].blank()){
304  if(vcfg["x"] == "recall" && vcfg["y"] == "recall") {
305  //locations on the map are considered to not be on a recall list
306  if (fc_.get_disp_context().map().on_board(loc))
307  {
308  return false;
309  }
310  } else if(vcfg["x"].empty() && vcfg["y"].empty()) {
311  return false;
312  } else if(!loc.matches_range(vcfg["x"], vcfg["y"])) {
313  return false;
314  }
315  }
316 
317  // The type could be a comma separated list of types
318  if (!vcfg["type"].empty()) {
319  std::vector<std::string> types = utils::split(vcfg["type"]);
320  if (std::find(types.begin(), types.end(), u.type_id()) == types.end()) {
321  return false;
322  }
323  }
324 
325  // The variation_type could be a comma separated list of types
326  if (!vcfg["variation"].empty())
327  {
328  std::vector<std::string> types = utils::split(vcfg["variation"]);
329  if (std::find(types.begin(), types.end(), u.variation()) == types.end()) {
330  return false;
331  }
332  }
333 
334  // The has_variation_type could be a comma separated list of types
335  if (!vcfg["has_variation"].empty())
336  {
337  bool match = false;
338  // If this unit is a variation itself then search in the base unit's variations.
339  const unit_type* const type = u.variation().empty() ? &u.type() : unit_types.find(u.type().base_id());
340  assert(type);
341 
342  for (const std::string& variation_id : utils::split(vcfg["has_variation"])) {
343  if (type->has_variation(variation_id)) {
344  match = true;
345  break;
346  }
347  }
348  if (!match) return false;
349  }
350 
351  if (!vcfg["ability"].empty())
352  {
353  bool match = false;
354 
355  for (const std::string& ability_id : utils::split(vcfg["ability"])) {
356  if (u.has_ability_by_id(ability_id)) {
357  match = true;
358  break;
359  }
360  }
361  if (!match) return false;
362  }
363 
364  if (!vcfg["race"].empty()) {
365  std::vector<std::string> races = utils::split(vcfg["race"]);
366  if (std::find(races.begin(), races.end(), u.race()->id()) == races.end()) {
367  return false;
368  }
369  }
370 
371  if (!vcfg["gender"].blank() && string_gender(vcfg["gender"]) != u.gender()) {
372  return false;
373  }
374 
375  if (!vcfg["side"].empty() && vcfg["side"].to_int(-999) != u.side()) {
376  std::vector<std::string> sides = utils::split(vcfg["side"]);
377  const std::string u_side = std::to_string(u.side());
378  if (std::find(sides.begin(), sides.end(), u_side) == sides.end()) {
379  return false;
380  }
381  }
382 
383  // handle statuses list
384  if (!vcfg["status"].empty()) {
385  bool status_found = false;
386  std::map<std::string, std::string> states_map = u.get_states();
387 
388  for (const std::string status : utils::split(vcfg["status"])) {
389  if (states_map[status] == "yes") {
390  status_found = true;
391  break;
392  }
393  }
394 
395  if(!status_found) {
396  return false;
397  }
398  }
399 
400  if (vcfg.has_child("has_attack")) {
401  const vconfig& weap_filter = vcfg.child("has_attack");
402  bool has_weapon = false;
403  const std::vector<attack_type>& attacks = u.attacks();
404  for(std::vector<attack_type>::const_iterator i = attacks.begin();
405  i != attacks.end(); ++i) {
406  if(i->matches_filter(weap_filter.get_parsed_config())) {
407  has_weapon = true;
408  break;
409  }
410  }
411  if(!has_weapon) {
412  return false;
413  }
414  } else if (!vcfg["has_weapon"].blank()) {
415  std::string weapon = vcfg["has_weapon"];
416  bool has_weapon = false;
417  const std::vector<attack_type>& attacks = u.attacks();
418  for(std::vector<attack_type>::const_iterator i = attacks.begin();
419  i != attacks.end(); ++i) {
420  if(i->id() == weapon) {
421  has_weapon = true;
422  break;
423  }
424  }
425  if(!has_weapon) {
426  return false;
427  }
428  }
429 
430  if (!vcfg["role"].blank() && vcfg["role"].str() != u.get_role()) {
431  return false;
432  }
433 
434  if (!vcfg["ai_special"].blank() && ((vcfg["ai_special"].str() == "guardian") != u.get_state(unit::STATE_GUARDIAN))) {
435  return false;
436  }
437 
438  if (!vcfg["canrecruit"].blank() && vcfg["canrecruit"].to_bool() != u.can_recruit()) {
439  return false;
440  }
441 
442  if (!vcfg["recall_cost"].blank() && vcfg["recall_cost"].to_int(-1) != u.recall_cost()) {
443  return false;
444  }
445 
446  if (!vcfg["level"].blank() && vcfg["level"].to_int(-1) != u.level()) {
447  return false;
448  }
449 
450  if (!vcfg["defense"].blank() && vcfg["defense"].to_int(-1) != u.defense_modifier(fc_.get_disp_context().map().get_terrain(loc))) {
451  return false;
452  }
453 
454  if (!vcfg["movement_cost"].blank() && vcfg["movement_cost"].to_int(-1) != u.movement_cost(fc_.get_disp_context().map().get_terrain(loc))) {
455  return false;
456  }
457 
458  // Now start with the new WML based comparison.
459  // If a key is in the unit and in the filter, they should match
460  // filter only => not for us
461  // unit only => not filtered
462  config unit_cfg; // No point in serializing the unit once for each [filter_wml]!
463  for (const vconfig& wmlcfg : vcfg.get_children("filter_wml")) {
464  config fwml = wmlcfg.get_parsed_config();
465  /* Check if the filter only cares about variables.
466  If so, no need to serialize the whole unit. */
469  if (std::distance(ai.first, ai.second) == 0 &&
470  std::distance(ci.first, ci.second) == 1 &&
471  ci.first->key == "variables") {
472  if (!u.variables().matches(ci.first->cfg))
473  return false;
474  } else {
475  if (unit_cfg.empty())
476  u.write(unit_cfg);
477  if (!unit_cfg.matches(fwml))
478  return false;
479  }
480  }
481 
482  for (const vconfig& vision : vcfg.get_children("filter_vision")) {
483  std::set<int> viewers;
484 
485  // Use standard side filter
486  side_filter ssf(vision, &fc_);
487  std::vector<int> sides = ssf.get_teams();
488  viewers.insert(sides.begin(), sides.end());
489 
490  bool found = false;
491  for (const int viewer : viewers) {
492  bool fogged = fc_.get_disp_context().teams()[viewer - 1].fogged(loc);
493  bool hiding = u.invisible(loc/*, false(?) */);
494  bool unit_hidden = fogged || hiding;
495  if (vision["visible"].to_bool(true) != unit_hidden) {
496  found = true;
497  break;
498  }
499  }
500  if (!found) {return false;}
501  }
502 
503  if (vcfg.has_child("filter_adjacent")) {
504  const unit_map& units = fc_.get_disp_context().units();
505  map_location adjacent[6];
506  get_adjacent_tiles(loc, adjacent);
507 
508  for (const vconfig& adj_cfg : vcfg.get_children("filter_adjacent")) {
509  int match_count=0;
510  unit_filter filt(adj_cfg, &fc_, use_flat_tod_);
511 
512  config::attribute_value i_adjacent = adj_cfg["adjacent"];
513  std::vector<map_location::DIRECTION> dirs;
514  if (i_adjacent.blank()) {
516  } else {
517  dirs = map_location::parse_directions(i_adjacent);
518  }
519 
520  std::vector<map_location::DIRECTION>::const_iterator j, j_end = dirs.end();
521  for (j = dirs.begin(); j != j_end; ++j) {
522  unit_map::const_iterator unit_itor = units.find(adjacent[*j]);
523  if (unit_itor == units.end() || !filt(*unit_itor, u)) {
524  continue;
525  }
526  boost::optional<bool> is_enemy;
527  if (!adj_cfg["is_enemy"].blank()) {
528  is_enemy = adj_cfg["is_enemy"].to_bool();
529  }
530  if (!is_enemy || *is_enemy ==
531  fc_.get_disp_context().teams()[u.side() - 1].is_enemy(unit_itor->side())) {
532  ++match_count;
533  }
534  }
535 
536  static std::vector<std::pair<int,int> > default_counts = utils::parse_ranges("1-6");
537  config::attribute_value i_count = adj_cfg["count"];
538  if(!in_ranges(match_count, !i_count.blank() ? utils::parse_ranges(i_count) : default_counts)) {
539  return false;
540  }
541  }
542  }
543 
544  if (!vcfg["find_in"].blank()) {
545  // Allow filtering by searching a stored variable of units
546  if (const game_data * gd = fc_.get_game_data()) {
547  try
548  {
549  variable_access_const vi = gd->get_variable_access_read(vcfg["find_in"]);
550  bool found_id = false;
551  for (const config& c : vi.as_array())
552  {
553  if(c["id"] == u.id())
554  found_id = true;
555  }
556  if(!found_id)
557  {
558  return false;
559  }
560  }
561  catch(const invalid_variablename_exception&)
562  {
563  return false;
564  }
565  }
566  }
567  if (!vcfg["formula"].blank()) {
568  try {
569  const unit_callable main(loc,u);
570  game_logic::map_formula_callable callable(&main);
571  if (u2) {
573  callable.add("other", variant(secondary.get()));
574  // It's not destroyed upon scope exit because the variant holds a reference
575  }
576  const game_logic::formula form(vcfg["formula"]);
577  if(!form.evaluate(callable).as_bool()) {
578  return false;
579  }
580  return true;
581  } catch(game_logic::formula_error& e) {
582  lg::wml_error() << "Formula error in unit filter: " << e.type << " at " << e.filename << ':' << e.line << ")\n";
583  // Formulae with syntax errors match nothing
584  return false;
585  }
586  }
587 
588  if (!vcfg["lua_function"].blank()) {
589  if (game_lua_kernel * lk = fc_.get_lua_kernel()) {
590  bool b = lk->run_filter(vcfg["lua_function"].str().c_str(), u);
591  if (!b) return false;
592  }
593  }
594 
595  return true;
596 }
597 
598 std::vector<const unit *> basic_unit_filter_impl::all_matches_on_map(unsigned max_matches) const {
599  std::vector<const unit *> ret;
600  for (const unit & u : fc_.get_disp_context().units()) {
601  if (matches(u, u.get_location(), nullptr)) {
602  if(max_matches == 0) {
603  return ret;
604  }
605  --max_matches;
606  ret.push_back(&u);
607  }
608  }
609  return ret;
610 }
611 
613  const unit_map & units = fc_.get_disp_context().units();
614  for(unit_map::const_iterator u = units.begin(); u != units.end(); u++) {
615  if (matches(*u,u->get_location(),nullptr)) {
616  return u.get_shared_ptr();
617  }
618  }
619  return unit_const_ptr();
620 }
basic_unit_filter_impl(const vconfig &vcfg, const filter_context &fc, bool flat_tod)
Definition: filter.cpp:129
std::vector< int > get_teams() const
Definition: side_filter.cpp:72
static lg::log_domain log_config("config")
TYPE
UNSCALED : image will be drawn "as is" without changing size, even in case of redraw SCALED_TO_ZOOM :...
Definition: image.hpp:208
boost::intrusive_ptr< const unit > unit_const_ptr
Definition: ptr.hpp:30
const std::string & id() const
Definition: unit.hpp:148
size_t count_children(const std::string &key) const
Definition: variable.cpp:211
unit_iterator end()
Definition: map.hpp:311
const map_location & get_location() const
Definition: unit.hpp:286
bool matches(const config &filter) const
Definition: config.cpp:1410
virtual const display_context & get_disp_context() const =0
const t_terrain NOT
bool matches_range(const std::string &xloc, const std::string &yloc) const
Definition: location.cpp:311
config to_config() const
Definition: filter.cpp:175
bool has_variation(const std::string &variation_id) const
Definition: types.cpp:736
std::pair< const_attribute_iterator, const_attribute_iterator > const_attr_itors
Definition: config.hpp:418
bool get_state(const std::string &state) const
Definition: unit.cpp:1289
This enum helps to evaluate conditional filters.
Definition: filter.cpp:117
variable_info_detail::maybe_const< vit, config::child_itors >::type as_array() const
might throw invalid_variablename_exception
Definition: unit.hpp:95
#define DBG_CF
Definition: filter.cpp:49
const t_string & name() const
The unit name for display.
Definition: unit.hpp:158
unsigned attribute_count() const
Note: this function also counts the 'blank' attributes, so it might return more than one might expect...
Definition: config.hpp:425
int movement_cost(const t_translation::t_terrain &terrain) const
Definition: unit.hpp:308
const GLfloat * c
Definition: glew.h:12741
vconfig get_child() const
Definition: variable.cpp:374
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
vconfig child(const std::string &key) const
Returns a child of *this whose key is key.
Definition: variable.cpp:243
virtual std::vector< const unit * > all_matches_on_map(unsigned max_matches) const
Definition: filter.cpp:598
config get_parsed_config() const
Definition: variable.cpp:131
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
#define MAKE_ENUM(NAME, CONTENT)
Definition: make_enum.hpp:157
const filter_context & fc_
Definition: filter.cpp:113
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:274
all_children_iterator ordered_end() const
Definition: variable.cpp:403
virtual bool matches(const unit &, const map_location &, const unit *) const
Definition: filter.cpp:82
virtual unit_const_ptr first_match_on_map() const
Definition: filter.cpp:612
config to_config() const
Definition: filter.cpp:104
const std::string & id() const
Definition: race.hpp:33
unit_iterator begin()
Definition: map.hpp:308
unit_type_data unit_types
Definition: types.cpp:1314
boost::shared_ptr< unit_filter_abstract_impl > impl_
Definition: filter.hpp:108
int side() const
Definition: unit.hpp:201
void write(config &cfg) const
Definition: unit.cpp:1379
bool as_bool() const
Definition: variant.cpp:580
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:128
bool internal_matches_filter(const unit &u, const map_location &loc, const unit *u2) const
Definition: filter.cpp:259
-file sdl_utils.hpp
bool empty() const
Definition: config.cpp:1105
Definitions for the interface to Wesnoth Markup Language (WML).
virtual const gamemap & map() const =0
GLsizei GLenum GLenum * types
Definition: glew.h:3155
Variant for storing WML attributes.
Definition: config.hpp:223
int defense_modifier(const t_translation::t_terrain &terrain) const
Definition: unit.cpp:1520
bool blank() const
Tests for an attribute that was never set.
Definition: config.cpp:367
const unit_type & type() const
The type of the unit (accounting for gender and variation).
Definition: unit.hpp:144
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
const std::string & type_id() const
The id of the type of the unit.
Definition: unit.hpp:142
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:57
The basic unit filter gives a generic implementation of the match fcn.
Definition: filter.cpp:127
const filter_context & fc_
Definition: filter.cpp:181
pointer get_shared_ptr() const
Definition: map.hpp:180
bool valid() const
Definition: location.hpp:69
child_list get_children(const std::string &key) const
Definition: variable.cpp:181
bool matches(const unit &u, const map_location &loc) const
Determine if *this matches filter at a specified location.
Definition: filter.hpp:67
const vconfig vcfg
Definition: filter.cpp:182
const GLdouble * v
Definition: glew.h:1359
all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:1127
virtual ~basic_unit_filter_impl()
Definition: filter.cpp:179
bool has_child(const std::string &key) const
Returns whether or not *this has a child whose key is key.
Definition: variable.cpp:270
bool can_recruit() const
Definition: unit.hpp:207
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
Definition: race.cpp:161
std::pair< all_children_iterator, all_children_iterator > all_children_itors
Definition: config.hpp:665
static const std::vector< DIRECTION > & default_dirs()
Default list of directions.
Definition: location.cpp:55
unit_race::GENDER gender() const
Definition: unit.hpp:203
virtual const unit_map & units() const =0
unsigned max_matches_
Definition: filter.hpp:109
const std::vector< attack_type > & attacks() const
Definition: unit.hpp:271
bool invisible(const map_location &loc, bool see_all=true) const
Definition: unit.cpp:2291
Encapsulates the map of the game.
Definition: location.hpp:38
virtual std::vector< const unit * > all_matches_on_map(unsigned max_matches) const
Definition: filter.cpp:85
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:31
virtual bool empty() const
Definition: filter.hpp:46
virtual const std::vector< team > & teams() const =0
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:262
std::vector< unit_filter > cond_children_
Definition: filter.cpp:185
std::vector< std::pair< int, int > > parse_ranges(std::string const &str)
config & variables()
Definition: unit.hpp:366
null_unit_filter_impl(const filter_context &fc)
Definition: filter.cpp:81
const std::map< std::string, std::string > get_states() const
Definition: unit.cpp:1267
config to_config() const
Definition: filter.cpp:52
const config & get_config() const
Definition: variable.hpp:68
virtual unit_const_ptr first_match_on_map() const
Definition: filter.cpp:97
const_attr_itors attribute_range() const
Definition: config.cpp:984
static boost::shared_ptr< unit_filter_abstract_impl > construct(const vconfig &vcfg, const filter_context &fc, bool flat_tod)
Forward declare the "construct" method which constructs an appropriate filter impl.
Definition: filter.cpp:195
bool empty() const
Definition: variable.hpp:93
Information on a WML variable.
size_t i
Definition: function.cpp:1057
const std::string & variation() const
Definition: unit.hpp:155
int level() const
Definition: unit.hpp:175
map_formula_callable & add(const std::string &key, const variant &value)
Definition: formula.cpp:41
bool empty() const
Definition: filter.cpp:108
int main(int argc, char **argv)
unit_filter(const vconfig &cfg, const filter_context *fc, bool use_flat_tod=false)
Constructs a unit filter from a config and a context. This function should give the most efficient im...
Definition: filter.cpp:210
t_translation::t_terrain get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:341
virtual bool matches(const unit &u, const map_location &loc, const unit *u2) const
Begin implementations of filter impl's.
Definition: filter.cpp:225
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:467
const std::string & base_id() const
The id of the original type from which this (variation) descended.
Definition: types.hpp:119
int recall_cost() const
Definition: unit.hpp:177
bool find(E event, F functor)
Tests whether an event handler is available.
Null unit filter is built when the input config is null.
Definition: filter.cpp:79
virtual const game_data * get_game_data() const =0
static int cond(LexState *ls)
Definition: lparser.cpp:1168
unsigned all_children_count() const
Definition: config.cpp:646
A variable-expanding proxy for the config class.
Definition: variable.hpp:36
Standard logging facilities (interface).
virtual game_lua_kernel * get_lua_kernel() const =0
static const char * match(MatchState *ms, const char *s, const char *p)
Definition: lstrlib.cpp:409
Container associating units to locations.
Definition: map.hpp:90
virtual ~null_unit_filter_impl()
Definition: filter.cpp:102
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:1155
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
#define e
#define FAIL(message)
unit_iterator find(size_t id)
Definition: map.cpp:285
std::vector< conditional::TYPE > cond_child_types_
Definition: filter.cpp:186
const std::string & get_role() const
Definition: unit.hpp:265
const std::string weapon
GLuint GLdouble GLdouble u2
Definition: glew.h:2972
bool has_ability_by_id(const std::string &ability) const
Definition: unit.cpp:1357
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
void make_safe() const
instruct the vconfig to make a private copy of its underlying data.
Definition: variable.cpp:119
const unit_race * race() const
Never returns nullptr, but may point to the null race.
Definition: unit.hpp:371
Defines the MAKE_ENUM macro.
GLsizei const GLcharARB ** string
Definition: glew.h:4503
std::string get_key() const
Definition: variable.cpp:365
unit_map * units
Definition: resources.cpp:35
bool has_attribute(const std::string &key) const
< Synonym for operator[]
Definition: variable.hpp:92
all_children_iterator ordered_begin() const
In-order iteration over all children.
Definition: variable.cpp:398
bool in_ranges(const Cmp c, const std::vector< std::pair< Cmp, Cmp > > &ranges)
Definition: util.hpp:195