The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
teleport.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2016 by Fabian Mueller <[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 version 2
7  or at your option any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY.
10 
11  See the COPYING file for more details.
12 */
13 
14 #include "pathfind/teleport.hpp"
15 
16 #include "display_context.hpp"
17 #include "filter_context.hpp"
18 #include "game_board.hpp"
19 #include "log.hpp"
20 #include "resources.hpp"
22 #include "team.hpp"
23 #include "terrain/filter.hpp"
24 #include "units/unit.hpp"
25 #include "units/filter.hpp"
26 #include "units/map.hpp"
27 
28 static lg::log_domain log_engine("engine");
29 #define ERR_PF LOG_STREAM(err, log_engine)
30 
31 namespace pathfind {
32 
33 
34 namespace {
35  const std::string reversed_suffix = "-__REVERSED__";
36 }
37 
38 // This constructor is *only* meant for loading from saves
39 teleport_group::teleport_group(const config& cfg) : cfg_(cfg), reversed_(cfg["reversed"].to_bool(false)), id_(cfg["id"])
40 {
41  assert(cfg.has_attribute("id"));
42  assert(cfg.has_attribute("reversed"));
43 
44  assert(cfg_.child_count("source") == 1);
45  assert(cfg_.child_count("target") == 1);
46  assert(cfg_.child_count("filter") == 1);
47 }
48 
49 teleport_group::teleport_group(const vconfig& cfg, bool reversed) : cfg_(cfg.get_config()), reversed_(reversed), id_()
50 {
51  assert(cfg_.child_count("source") == 1);
52  assert(cfg_.child_count("target") == 1);
53  assert(cfg_.child_count("filter") == 1);
54  if (cfg["id"].empty()) {
56  } else {
57  id_ = cfg["id"].str();
58  if (reversed_) // Differentiate the reverse tunnel from the forward one
59  id_ += reversed_suffix;
60  }
61 }
62 
64 public:
66  : um_()
67  , gm_(&dc.map())
68  , tm_(&dc.teams())
70  {
71  static unit_map empty_unit_map;
72  um_ = &empty_unit_map;
73  }
74  const unit_map & units() const { return *um_; }
75  const gamemap & map() const { return *gm_; }
76  const std::vector<team> & teams() const { return *tm_; }
77  const std::vector<std::string> & hidden_label_categories() const { return *lbls_; }
78 
79 private:
80  const unit_map * um_;
81  const gamemap * gm_;
82  const std::vector<team> * tm_;
83  const std::vector<std::string> * lbls_;
84 };
85 
87 public:
89  : dc_(fc.get_disp_context())
90  , tod_(&fc.get_tod_man())
91  , gd_(fc.get_game_data())
92  , lk_(fc.get_lua_kernel())
93  {}
94 
95  const display_context & get_disp_context() const { return dc_; }
96  const tod_manager & get_tod_man() const { return *tod_; }
97  const game_data * get_game_data() const { return gd_; }
98  game_lua_kernel * get_lua_kernel() const { return lk_; }
99 
100 private:
102  const tod_manager * tod_;
103  const game_data * gd_;
105 };
106 
108  teleport_pair& loc_pair
109  , const unit& u
110  , const bool ignore_units) const
111 {
112  const map_location &loc = u.get_location();
113 
115  assert(fc);
116 
117  if (ignore_units) {
119  }
120 
121  vconfig filter(cfg_.child_or_empty("filter"), true);
122  vconfig source(cfg_.child_or_empty("source"), true);
123  vconfig target(cfg_.child_or_empty("target"), true);
124  const unit_filter ufilt(filter, resources::filter_con); //Note: Don't use the ignore units filter context here, only for the terrain filters. (That's how it worked before the filter contexts were introduced)
125  if (ufilt.matches(u, loc)) {
126 
127  scoped_xy_unit teleport_unit("teleport_unit", loc.x, loc.y, *resources::units);
128 
129  terrain_filter source_filter(source, fc);
130  source_filter.get_locations(reversed_ ? loc_pair.second : loc_pair.first);
131 
132  terrain_filter target_filter(target, fc);
133  target_filter.get_locations(reversed_ ? loc_pair.first : loc_pair.second);
134  }
135 
136  if (ignore_units) {
137  delete fc;
138  }
139 }
140 
142  return id_;
143 }
144 
146  return cfg_["always_visible"].to_bool(false);
147 }
148 
150  config retval = cfg_;
151  retval["saved"] = "yes";
152  retval["reversed"] = reversed_ ? "yes" : "no";
153  retval["id"] = id_;
154  return retval;
155 }
156 
158  const std::vector<teleport_group>& groups
159  , const unit& u
160  , const team &viewing_team
161  , const bool see_all
162  , const bool ignore_units)
163  : teleport_map_()
164  , sources_()
165  , targets_()
166 {
167 
168  for (const teleport_group& group : groups) {
169 
171  group.get_teleport_pair(locations, u, ignore_units);
172  if (!see_all && !group.always_visible() && viewing_team.is_enemy(u.side())) {
173  teleport_pair filter_locs;
174  for (const map_location &loc : locations.first) {
175  if(!viewing_team.fogged(loc))
176  filter_locs.first.insert(loc);
177  }
178  for (const map_location &loc : locations.second) {
179  if(!viewing_team.fogged(loc))
180  filter_locs.second.insert(loc);
181  }
182  locations.first.swap(filter_locs.first);
183  locations.second.swap(filter_locs.second);
184  }
185  std::string teleport_id = group.get_teleport_id();
186 
187  std::set<map_location>::iterator source_it = locations.first.begin();
188  for (; source_it != locations.first.end(); ++source_it ) {
189  if(teleport_map_.count(*source_it) == 0) {
190  std::set<std::string> id_set;
191  id_set.insert(teleport_id);
192  teleport_map_.insert(std::make_pair(*source_it, id_set));
193  } else {
194  (teleport_map_.find(*source_it)->second).insert(teleport_id);
195  }
196  }
197  sources_.insert(std::make_pair(teleport_id, locations.first));
198  targets_.insert(std::make_pair(teleport_id, locations.second));
199  }
200 }
201 
202 void teleport_map::get_adjacents(std::set<map_location>& adjacents, map_location loc) const {
203 
204  if (teleport_map_.count(loc) == 0) {
205  return;
206  } else {
207  const std::set<std::string>& keyset = (teleport_map_.find(loc)->second);
208  for(std::set<std::string>::const_iterator it = keyset.begin(); it != keyset.end(); ++it) {
209 
210  const std::set<map_location>& target = targets_.find(*it)->second;
211  adjacents.insert(target.begin(), target.end());
212  }
213  }
214 }
215 
216 void teleport_map::get_sources(std::set<map_location>& sources) const {
217 
218  std::map<std::string, std::set<map_location> >::const_iterator it;
219  for(it = sources_.begin(); it != sources_.end(); ++it) {
220  sources.insert(it->second.begin(), it->second.end());
221  }
222 }
223 
224 void teleport_map::get_targets(std::set<map_location>& targets) const {
225 
226  std::map<std::string, std::set<map_location> >::const_iterator it;
227  for(it = targets_.begin(); it != targets_.end(); ++it) {
228  targets.insert(it->second.begin(), it->second.end());
229  }
230 }
231 
232 
234  const team &viewing_team,
235  bool see_all, bool ignore_units)
236 {
237  std::vector<teleport_group> groups;
238 
239  if (u.get_ability_bool("teleport")) {
240  for (const unit_ability & teleport : u.get_abilities("teleport")) {
241  const int tunnel_count = (teleport.first)->child_count("tunnel");
242  for(int i = 0; i < tunnel_count; ++i) {
243  config teleport_group_cfg = (teleport.first)->child("tunnel", i);
244  groups.push_back(teleport_group(vconfig(teleport_group_cfg, true), false));
245  }
246  }
247  }
248 
249  const std::vector<teleport_group>& global_groups = resources::tunnels->get();
250  groups.insert(groups.end(), global_groups.begin(), global_groups.end());
251 
252  return teleport_map(groups, u, viewing_team, see_all, ignore_units);
253 }
254 
255 manager::manager(const config &cfg) : tunnels_(), id_(cfg["next_teleport_group_id"].to_int(0)) {
256  const int tunnel_count = cfg.child_count("tunnel");
257  for(int i = 0; i < tunnel_count; ++i) {
258  const config& t = cfg.child("tunnel", i);
259  if(!t["saved"].to_bool()) {
260  lg::wml_error() << "Do not use [tunnel] directly in a [scenario]. Use it in an [event] or [abilities] tag.\n";
261  continue;
262  }
263  const teleport_group tunnel(t);
264  this->add(tunnel);
265  }
266 }
267 
269  tunnels_.push_back(group);
270 }
271 
272 void manager::remove(const std::string &id) {
274  for(;t != tunnels_.end();) {
275  if (t->get_teleport_id() == id || t->get_teleport_id() == id + reversed_suffix) {
276  t = tunnels_.erase(t);
277  } else {
278  ++t;
279  }
280  }
281 }
282 
283 const std::vector<teleport_group>& manager::get() const {
284  return tunnels_;
285 }
286 
288  config store;
289 
290  std::vector<teleport_group>::const_iterator tunnel = tunnels_.begin();
291  for(; tunnel != tunnels_.end(); ++tunnel) {
292  store.add_child("tunnel", tunnel->to_config());
293  }
294  store["next_teleport_group_id"] = std::to_string(id_);
295 
296  return store;
297 }
298 
300  return std::to_string(++id_);
301 }
302 
303 
304 }//namespace pathfind
std::map< std::string, std::set< map_location > > sources_
Definition: teleport.hpp:129
std::pair< std::set< map_location >, std::set< map_location > > teleport_pair
Definition: teleport.hpp:28
const ignore_units_display_context dc_
Definition: teleport.cpp:101
const map_location & get_location() const
Definition: unit.hpp:286
std::string id_
Definition: formula.cpp:636
Definition: unit.hpp:95
std::string next_unique_id()
Definition: teleport.cpp:299
void remove(const std::string &id)
Definition: teleport.cpp:272
bool is_enemy(int n) const
Definition: team.hpp:247
const std::vector< teleport_group > & get() const
Definition: teleport.cpp:283
int side() const
Definition: unit.hpp:201
config to_config() const
Inherited from savegame_config.
Definition: teleport.cpp:149
void get_targets(std::set< map_location > &targets) const
Definition: teleport.cpp:224
const config & child_or_empty(const std::string &key) const
Returns the first child with the given key, or an empty config if there is none.
Definition: config.cpp:722
bool always_visible() const
Definition: teleport.cpp:145
bool get_ability_bool(const std::string &tag_name, const map_location &loc) const
Returns true if the unit is currently under effect by an ability with this given TAG NAME...
Definition: abilities.cpp:129
-file sdl_utils.hpp
GLdouble GLdouble t
Definition: glew.h:1366
teleport_group(const config &cfg)
Definition: teleport.cpp:39
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:50
const std::vector< std::string > & hidden_label_categories() const
Definition: teleport.cpp:77
void get_sources(std::set< map_location > &sources) const
Definition: teleport.cpp:216
filter_context * filter_con
Definition: resources.cpp:23
game_lua_kernel * get_lua_kernel() const
Definition: teleport.cpp:98
ignore_units_filter_context(const filter_context &fc)
Definition: teleport.cpp:88
const std::vector< team > & teams() const
Definition: teleport.cpp:76
const display_context & get_disp_context() const
Definition: teleport.cpp:95
const unit_map & units() const
Definition: teleport.cpp:74
Encapsulates the map of the game.
Definition: map.hpp:37
const tod_manager & get_tod_man() const
Definition: teleport.cpp:96
const std::vector< std::string > * lbls_
Definition: teleport.cpp:83
config & add_child(const std::string &key)
Definition: config.cpp:743
std::map< std::string, std::set< map_location > > targets_
Definition: teleport.hpp:130
config to_config() const
Inherited from savegame_config.
Definition: teleport.cpp:287
GLsizei const GLint * locations
Definition: glew.h:11075
const game_data * get_game_data() const
Definition: teleport.cpp:97
Encapsulates the map of the game.
Definition: location.hpp:38
void get_locations(std::set< map_location > &locs, bool with_border=false) const
Definition: filter.cpp:495
std::map< map_location, std::set< std::string > > teleport_map_
Definition: teleport.hpp:128
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:262
std::pair< const config *, map_location > unit_ability
The things contained within a unit_ability_list.
Definition: unit.hpp:43
size_t i
Definition: function.cpp:1057
const gamemap & map() const
Definition: teleport.cpp:75
bool fogged(const map_location &loc) const
Definition: team.cpp:575
unit_ability_list get_abilities(const std::string &tag_name, const map_location &loc) const
Definition: abilities.cpp:168
unsigned child_count(const std::string &key) const
Definition: config.cpp:635
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:3448
const std::string & get_teleport_id() const
Definition: teleport.cpp:141
void add(const teleport_group &group)
Definition: teleport.cpp:268
manager(const config &cfg)
Definition: teleport.cpp:255
GLboolean GLuint group
Definition: glew.h:2589
bool has_attribute(const std::string &key) const
Definition: config.cpp:514
static lg::log_domain log_engine("engine")
std::vector< teleport_group > tunnels_
Definition: teleport.hpp:171
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
A variable-expanding proxy for the config class.
Definition: variable.hpp:36
const std::vector< team > * tm_
Definition: teleport.cpp:82
Standard logging facilities (interface).
Container associating units to locations.
Definition: map.hpp:90
ignore_units_display_context(const display_context &dc)
Definition: teleport.cpp:65
void get_teleport_pair(teleport_pair &loc_pair, const unit &u, const bool ignore_units) const
Definition: teleport.cpp:107
GLsizei GLenum * sources
Definition: glew.h:3155
const teleport_map get_teleport_locations(const unit &u, const team &viewing_team, bool see_all, bool ignore_units)
Definition: teleport.cpp:233
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLsizei GLuint * groups
Definition: glew.h:2588
pathfind::manager * tunnels
Definition: resources.cpp:33
GLsizei const GLcharARB ** string
Definition: glew.h:4503
GLsizei GLsizei GLchar * source
Definition: glew.h:1800
unit_map * units
Definition: resources.cpp:35
GLenum target
Definition: glew.h:5190
void get_adjacents(std::set< map_location > &adjacents, map_location loc) const
Definition: teleport.cpp:202