pathfind/teleport.cpp

Go to the documentation of this file.
00001 /* $Id: teleport.cpp 53324 2012-02-29 09:11:28Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2010 by Fabian Mueller <fabianmueller5@gmx.de>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 #include "pathfind/teleport.hpp"
00016 
00017 #include "serialization/string_utils.hpp"
00018 #include "unit.hpp"
00019 #include "log.hpp"
00020 #include "resources.hpp"
00021 
00022 #include "foreach.hpp"
00023 
00024 static lg::log_domain log_engine("engine");
00025 #define ERR_PF LOG_STREAM(err, log_engine)
00026 
00027 namespace {
00028     const std::string reversed_suffix = "-__REVERSED__";
00029 }
00030 
00031 // This constructor is *only* meant for loading from saves
00032 pathfind::teleport_group::teleport_group(const config& cfg) : cfg_(cfg), reversed_(cfg["reversed"].to_bool(false)), id_(cfg["id"])
00033 {
00034     assert(cfg.has_attribute("id"));
00035     assert(cfg.has_attribute("reversed"));
00036 
00037     assert(cfg_.child_count("source") == 1);
00038     assert(cfg_.child_count("target") == 1);
00039     assert(cfg_.child_count("filter") == 1);
00040 }
00041 
00042 pathfind::teleport_group::teleport_group(const vconfig& cfg, bool reversed) : cfg_(cfg.get_config()), reversed_(reversed), id_()
00043 {
00044     assert(cfg_.child_count("source") == 1);
00045     assert(cfg_.child_count("target") == 1);
00046     assert(cfg_.child_count("filter") == 1);
00047     if (cfg["id"].empty()) {
00048         id_ = resources::tunnels->next_unique_id();
00049     } else {
00050         id_ = cfg["id"].str();
00051         if (reversed_) // Differentiate the reverse tunnel from the forward one
00052             id_ += reversed_suffix;
00053     }
00054 }
00055 
00056 void pathfind::teleport_group::get_teleport_pair(
00057           teleport_pair& loc_pair
00058         , const unit& u
00059         , const bool ignore_units) const
00060 {
00061     const map_location &loc = u.get_location();
00062     static unit_map empty_unit_map;
00063     unit_map *units;
00064     if (ignore_units) {
00065         units = &empty_unit_map;
00066     } else {
00067         units = resources::units;
00068     }
00069     vconfig filter(cfg_.child_or_empty("filter"), true);
00070     vconfig source(cfg_.child_or_empty("source"), true);
00071     vconfig target(cfg_.child_or_empty("target"), true);
00072     if (u.matches_filter(filter, loc)) {
00073 
00074         scoped_xy_unit teleport_unit("teleport_unit", loc.x, loc.y, *resources::units);
00075 
00076         terrain_filter source_filter(source, *units);
00077         source_filter.get_locations(reversed_ ? loc_pair.second : loc_pair.first);
00078 
00079         terrain_filter target_filter(target, *units);
00080         target_filter.get_locations(reversed_ ? loc_pair.first : loc_pair.second);
00081     }
00082 }
00083 
00084 const std::string& pathfind::teleport_group::get_teleport_id() const {
00085     return id_;
00086 }
00087 
00088 bool pathfind::teleport_group::always_visible() const {
00089     return cfg_["always_visible"].to_bool(false);
00090 }
00091 
00092 config pathfind::teleport_group::to_config() const {
00093     config retval = cfg_;
00094     retval["saved"] = "yes";
00095     retval["reversed"] = reversed_ ? "yes" : "no";
00096     retval["id"] = id_;
00097     return retval;
00098 }
00099 
00100 pathfind::teleport_map::teleport_map(
00101           const std::vector<teleport_group>& groups
00102         , const unit& u
00103         , const team &viewing_team
00104         , const bool see_all
00105         , const bool ignore_units)
00106     : teleport_map_()
00107     , sources_()
00108     , targets_()
00109 {
00110 
00111     foreach(const teleport_group& group, groups) {
00112 
00113         teleport_pair locations;
00114         group.get_teleport_pair(locations, u, ignore_units);
00115         if (!see_all && !group.always_visible() && viewing_team.is_enemy(u.side())) {
00116             teleport_pair filter_locs;
00117             foreach(const map_location &loc, locations.first)
00118                 if(!viewing_team.fogged(loc))
00119                     filter_locs.first.insert(loc);
00120             foreach(const map_location &loc, locations.second)
00121                 if(!viewing_team.fogged(loc))
00122                     filter_locs.second.insert(loc);
00123             locations.first.swap(filter_locs.first);
00124             locations.second.swap(filter_locs.second);
00125         }
00126         std::string teleport_id = group.get_teleport_id();
00127 
00128         std::set<map_location>::iterator source_it = locations.first.begin();
00129         for (; source_it != locations.first.end(); ++source_it ) {
00130             if(teleport_map_.count(*source_it) == 0) {
00131                 std::set<std::string> id_set;
00132                 id_set.insert(teleport_id);
00133                 teleport_map_.insert(std::make_pair(*source_it, id_set));
00134             } else {
00135                 (teleport_map_.find(*source_it)->second).insert(teleport_id);
00136             }
00137         }
00138         sources_.insert(std::make_pair(teleport_id, locations.first));
00139         targets_.insert(std::make_pair(teleport_id, locations.second));
00140     }
00141 }
00142 
00143 void pathfind::teleport_map::get_adjacents(std::set<map_location>& adjacents, map_location loc) const {
00144 
00145     if (teleport_map_.count(loc) == 0) {
00146         return;
00147     } else {
00148         const std::set<std::string>& keyset = (teleport_map_.find(loc)->second);
00149         for(std::set<std::string>::const_iterator it = keyset.begin(); it != keyset.end(); ++it) {
00150 
00151             const std::set<map_location>& target = targets_.find(*it)->second;
00152             adjacents.insert(target.begin(), target.end());
00153         }
00154     }
00155 }
00156 
00157 void pathfind::teleport_map::get_sources(std::set<map_location>& sources) const {
00158 
00159     std::map<std::string, std::set<map_location> >::const_iterator it;
00160     for(it = sources_.begin(); it != sources_.end(); ++it) {
00161         sources.insert(it->second.begin(), it->second.end());
00162     }
00163 }
00164 
00165 void pathfind::teleport_map::get_targets(std::set<map_location>& targets) const {
00166 
00167     std::map<std::string, std::set<map_location> >::const_iterator it;
00168     for(it = targets_.begin(); it != targets_.end(); ++it) {
00169         targets.insert(it->second.begin(), it->second.end());
00170     }
00171 }
00172 
00173 
00174 const pathfind::teleport_map pathfind::get_teleport_locations(const unit &u,
00175     const team &viewing_team,
00176     bool see_all, bool ignore_units)
00177 {
00178     std::vector<teleport_group> groups;
00179 
00180     if (u.get_ability_bool("teleport")) {
00181 
00182         unit_ability_list teleport_list = u.get_abilities("teleport");
00183 
00184         std::vector<std::pair<const config *, map_location> > teleports = teleport_list.cfgs;
00185         std::vector<std::pair<const config *, map_location> >::const_iterator it = teleports.begin();
00186 
00187         for(; it != teleports.end(); ++it) {
00188             const int tunnel_count = (it->first)->child_count("tunnel");
00189             for(int i = 0; i < tunnel_count; ++i) {
00190                 config teleport_group_cfg = (it->first)->child("tunnel", i);
00191                 teleport_group group = teleport_group(vconfig(teleport_group_cfg, true), false);
00192                 groups.push_back(group);
00193             }
00194         }
00195     }
00196 
00197     const std::vector<teleport_group>& global_groups = resources::tunnels->get();
00198     groups.insert(groups.end(), global_groups.begin(), global_groups.end());
00199 
00200     return teleport_map(groups, u, viewing_team, see_all, ignore_units);
00201 }
00202 
00203 pathfind::manager::manager(const config &cfg) : tunnels_(), id_(lexical_cast_default<int>(cfg["next_teleport_group_id"], 0)) {
00204     const int tunnel_count = cfg.child_count("tunnel");
00205     for(int i = 0; i < tunnel_count; ++i) {
00206         const config& t = cfg.child("tunnel", i);
00207         if(!t["saved"].to_bool()) {
00208             lg::wml_error << "Do not use [tunnel] directly in a [scenario]. Use it in an [event] or [abilities] tag.\n";
00209             continue;
00210         }
00211         const pathfind::teleport_group tunnel(t);
00212         this->add(tunnel);
00213     }
00214 }
00215 
00216 void pathfind::manager::add(const teleport_group &group) {
00217     tunnels_.push_back(group);
00218 }
00219 
00220 void pathfind::manager::remove(const std::string &id) {
00221     std::vector<pathfind::teleport_group>::iterator t = tunnels_.begin();
00222     for(;t != tunnels_.end();) {
00223         if (t->get_teleport_id() == id || t->get_teleport_id() == id + reversed_suffix) {
00224             t = tunnels_.erase(t);
00225         } else {
00226             ++t;
00227         }
00228     }
00229 }
00230 
00231 const std::vector<pathfind::teleport_group>& pathfind::manager::get() const {
00232     return tunnels_;
00233 }
00234 
00235 config pathfind::manager::to_config() const {
00236     config store;
00237 
00238     std::vector<pathfind::teleport_group>::const_iterator tunnel = tunnels_.begin();
00239     for(; tunnel != tunnels_.end(); ++tunnel) {
00240         store.add_child("tunnel", tunnel->to_config());
00241     }
00242     store["next_teleport_group_id"] = str_cast(id_);
00243 
00244     return store;
00245 }
00246 
00247 std::string pathfind::manager::next_unique_id() {
00248     return str_cast(++id_);
00249 }
00250 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:07 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs