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