unit_map.cpp

Go to the documentation of this file.
00001 /* $Id: unit_map.cpp 26760 2008-05-21 19:26:59Z mordante $ */
00002 /*
00003    Copyright (C) 2006 - 2008 by Rusty Russell <rusty@rustcorp.com.au>
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 /** @file unit_map.cpp */
00016 
00017 #include "unit.hpp"
00018 #include "unit_map.hpp"
00019 #include "log.hpp"
00020 #include "random.hpp"
00021 
00022 #include <sstream>
00023 #include <cassert>
00024 
00025 #define ERR_NG LOG_STREAM(err, engine)
00026 #define WRN_NG LOG_STREAM(warn, engine)
00027 #define LOG_NG LOG_STREAM(info, engine)
00028 
00029 typedef std::pair<std::string, std::pair<bool, std::pair<gamemap::location, unit>*> > umap_pair;
00030 
00031 unit_map::unit_map(const gamemap::location &loc, const unit &u) : num_iters_(0), num_invalid_(0)
00032 {
00033     add(new std::pair<gamemap::location,unit>(loc, u));
00034 }
00035 
00036 unit_map::unit_map(const unit_map &that)
00037 {
00038     *this = that;
00039 }
00040 
00041 unit_map &unit_map::operator =(const unit_map &that)
00042 {
00043     clear();
00044     num_iters_ = 0;
00045     num_invalid_ = 0;
00046     for (umap::const_iterator i = that.map_.begin(); i != that.map_.end(); i++) {
00047         if (i->second.first) {
00048             add(i->second.second);
00049         } 
00050     }
00051     return *this;
00052 }
00053 
00054 unit_map::~unit_map()
00055 {
00056     delete_all();
00057 }
00058 
00059 std::pair<gamemap::location,unit>* unit_map::unit_iterator::operator->() const
00060 {
00061     assert(valid());
00062     return i_->second.second;
00063 }
00064 
00065 std::pair<gamemap::location,unit>& unit_map::unit_iterator::operator*() const
00066 {
00067     assert(valid());
00068     return *i_->second.second;
00069 }
00070 
00071 unit_map::unit_iterator unit_map::unit_iterator::operator++() {
00072     
00073     assert(i_ != map_->map_.end());
00074     
00075     ++i_;
00076     while (i_ != map_->map_.end() && !valid()) { 
00077         ++i_; 
00078     }
00079     
00080     return *this;
00081 }
00082     
00083 unit_map::unit_iterator unit_map::unit_iterator::operator++(int){
00084     
00085     assert(i_ != map_->map_.end());
00086     
00087     umap::iterator iter(i_);
00088     ++i_;
00089     while (i_ != map_->map_.end() && !valid()) { 
00090         ++i_; 
00091     }
00092     
00093     return unit_iterator(iter, map_);
00094 }
00095 
00096 // Due to unit <-> unit_map dependencies, must be out of line.
00097 const std::pair<gamemap::location,unit>* unit_map::const_unit_iterator::operator->() const
00098 {
00099     assert(valid());
00100     return i_->second.second;
00101 }
00102 
00103 const std::pair<gamemap::location,unit>& unit_map::const_unit_iterator::operator*() const
00104 {
00105     assert(valid());
00106     return *i_->second.second;
00107 }
00108 
00109 unit_map::const_unit_iterator unit_map::const_unit_iterator::operator++() {
00110     
00111     assert(i_ != map_->map_.end());
00112     
00113     ++i_;
00114     while (i_ != map_->map_.end() && !valid()) { 
00115         ++i_; 
00116     }
00117     
00118     return *this;
00119 }
00120 
00121 unit_map::const_unit_iterator unit_map::const_unit_iterator::operator--() {
00122     
00123     umap::const_iterator begin = map_->begin().i_;
00124     
00125     assert(i_ != begin);
00126     
00127     --i_;   
00128     while (i_ != begin && !valid()) { 
00129         --i_; 
00130     }
00131     
00132     return *this;
00133 }
00134     
00135 unit_map::const_unit_iterator unit_map::const_unit_iterator::operator++(int){
00136     
00137     assert(i_ != map_->map_.end());
00138     
00139     umap::const_iterator iter(i_);
00140     ++i_;
00141     while (i_ != map_->map_.end() && !valid()) { 
00142         ++i_; 
00143     }
00144     
00145     return const_unit_iterator(iter, map_);
00146 }
00147 
00148 unit_map::unit_xy_iterator::unit_xy_iterator(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) { 
00149     if (i.valid()) loc_ = i->first; 
00150 }
00151 
00152 
00153 std::pair<gamemap::location,unit>* unit_map::unit_xy_iterator::operator->() const
00154 {
00155     assert(valid());
00156     return i_->second.second;
00157 }
00158 
00159 std::pair<gamemap::location,unit>& unit_map::unit_xy_iterator::operator*() const
00160 {
00161     assert(valid());
00162     return *i_->second.second;
00163 }
00164 
00165 unit_map::unit_xy_iterator unit_map::unit_xy_iterator::operator++() {
00166     
00167     assert(i_ != map_->map_.end());
00168     
00169     ++i_;   
00170     while (i_ != map_->map_.end() && !valid()) { 
00171         ++i_; 
00172     }
00173     
00174     if (i_ != map_->map_.end()) {
00175         loc_ = i_->second.second->first;
00176     }
00177     
00178     return *this;
00179 }
00180     
00181 unit_map::unit_xy_iterator unit_map::unit_xy_iterator::operator++(int){
00182     
00183     assert(i_ != map_->map_.end());
00184     
00185     umap::iterator iter(i_);
00186     gamemap::location pre_loc = loc_;
00187     ++i_;
00188     while (i_ != map_->map_.end() && !valid()) { 
00189         ++i_; 
00190     }
00191     
00192     if (i_ != map_->map_.end()) {
00193         loc_ = i_->second.second->first;
00194     }
00195     
00196     return unit_xy_iterator(iter, map_, pre_loc);
00197 }
00198 
00199 bool unit_map::unit_xy_iterator::valid() const { 
00200     return i_ != map_->map_.end() && i_->second.first && loc_ == i_->second.second->first; 
00201 }
00202 
00203 unit_map::const_unit_xy_iterator::const_unit_xy_iterator(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) { 
00204     if (i.valid()) loc_ = i->first; 
00205 }
00206 
00207 unit_map::const_unit_xy_iterator::const_unit_xy_iterator(const const_unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_)  { 
00208     if (i.valid()) loc_ = i->first; 
00209 }
00210 
00211 const std::pair<gamemap::location,unit>* unit_map::const_unit_xy_iterator::operator->() const {
00212     assert(valid());
00213     return i_->second.second;
00214 }
00215 
00216 const std::pair<gamemap::location,unit>& unit_map::const_unit_xy_iterator::operator*() const {
00217     assert(valid());
00218     return *i_->second.second;
00219 }
00220 
00221 unit_map::const_unit_xy_iterator unit_map::const_unit_xy_iterator::operator++() {
00222     
00223     assert(i_ != map_->map_.end());
00224     
00225     ++i_;
00226     while (i_ != map_->map_.end() && !valid()) { 
00227         ++i_; 
00228     }
00229     
00230     if (i_ != map_->map_.end()) {
00231         loc_ = i_->second.second->first;
00232     }
00233     
00234     return *this;
00235 }
00236     
00237 unit_map::const_unit_xy_iterator unit_map::const_unit_xy_iterator::operator++(int){
00238     
00239     assert(i_ != map_->map_.end());
00240     
00241     gamemap::location pre_loc = loc_;
00242     
00243     umap::const_iterator iter(i_);  
00244     ++i_;
00245     while (i_ != map_->map_.end() && !valid()) { 
00246         ++i_; 
00247     }
00248     
00249     if (i_ != map_->map_.end()) {
00250         loc_ = i_->second.second->first;
00251     }
00252     
00253     return const_unit_xy_iterator(iter, map_, pre_loc);
00254 }
00255 
00256 bool unit_map::const_unit_xy_iterator::valid() const { 
00257     return i_ != map_->map_.end() && i_->second.first && loc_ == i_->second.second->first; 
00258 }
00259 
00260 
00261 unit_map::xy_accessor::xy_accessor(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
00262     if (i.valid()) loc_ = i->first; 
00263 }
00264 
00265 unit_map::xy_accessor::xy_accessor(const unit_xy_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
00266     if (i.valid()) loc_ = i->first; 
00267 }
00268     
00269         
00270 std::pair<gamemap::location,unit>* unit_map::xy_accessor::operator->() {
00271     if (!valid()) { assert(0); }
00272     return i_->second.second;
00273 }
00274 
00275 std::pair<gamemap::location,unit>& unit_map::xy_accessor::operator*() {
00276     if (!valid()) { assert(0); }
00277     return *i_->second.second;
00278 }
00279         
00280         
00281 bool unit_map::xy_accessor::valid() {
00282     if (i_->second.first && i_->second.second->first == loc_) {
00283         return true;
00284     }
00285     
00286     unit_iterator u_iter = map_->find(loc_);
00287     
00288     if (u_iter.valid()) {
00289         i_ = u_iter.i_;
00290         loc_ = i_->second.second->first;
00291         return true;
00292     }
00293     
00294     return false;   
00295 }
00296 
00297 unit_map::const_xy_accessor::const_xy_accessor(const const_unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
00298     if (i.valid()) loc_ = i->first; 
00299 }
00300 
00301 unit_map::const_xy_accessor::const_xy_accessor(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
00302     if (i.valid()) loc_ = i->first; 
00303 }
00304 
00305 unit_map::const_xy_accessor::const_xy_accessor(const const_unit_xy_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
00306     if (i.valid()) loc_ = i->first; 
00307 }
00308 
00309 unit_map::const_xy_accessor::const_xy_accessor(const unit_xy_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
00310     if (i.valid()) loc_ = i->first; 
00311 }   
00312         
00313 const std::pair<gamemap::location,unit>* unit_map::const_xy_accessor::operator->() {
00314     if (!valid()) { assert(0); }
00315     return i_->second.second;
00316 }
00317 
00318 const std::pair<gamemap::location,unit>& unit_map::const_xy_accessor::operator*() {
00319     if (!valid()) { assert(0); }
00320     return *i_->second.second;
00321 }
00322         
00323         
00324 bool unit_map::const_xy_accessor::valid() {
00325     if (i_->second.first && i_->second.second->first == loc_) {
00326         return true;
00327     }
00328     
00329     const_unit_iterator u_iter = map_->find(loc_);
00330     
00331     if (u_iter.valid()) {
00332         i_ = u_iter.i_;
00333         loc_ = i_->second.second->first;
00334         return true;
00335     }
00336     
00337     return false;   
00338 }
00339 
00340 
00341 unit_map::unit_iterator unit_map::find(const gamemap::location &loc) {
00342     lmap::const_iterator i = lmap_.find(loc);
00343     if (i == lmap_.end()) {
00344         return unit_iterator(map_.end(), this);
00345     }
00346  
00347     umap::iterator iter = map_.find(i->second);
00348 
00349     assert(iter->second.first);
00350     return unit_iterator(iter , this);
00351 }
00352 
00353 
00354 unit_map::const_unit_iterator unit_map::find(const gamemap::location &loc) const {
00355     lmap::const_iterator iter = lmap_.find(loc);
00356     if (iter == lmap_.end()) {
00357         return const_unit_iterator(map_.end(), this);
00358     }
00359     
00360     umap::const_iterator i = map_.find(iter->second);
00361     
00362     assert(i->second.first);
00363     return const_unit_iterator(i , this);
00364 }
00365 
00366 unit_map::unit_iterator unit_map::find(const std::string &id) {
00367     umap::iterator iter = map_.find(id);
00368     if (iter == map_.end() || !iter->second.first) {
00369         return unit_iterator(map_.end(), this);
00370     }
00371     return unit_iterator(iter, this);   
00372 }
00373 
00374 unit_map::const_unit_iterator unit_map::find(const std::string &id) const {
00375     umap::const_iterator iter = map_.find(id);
00376     if (iter == map_.end() || !iter->second.first) {
00377         return const_unit_iterator(map_.end(), this);
00378     }       
00379     return const_unit_iterator(iter, this); 
00380 }
00381 
00382 unit_map::unit_iterator unit_map::begin() {     
00383         // clean if there are more invalid than valid, this block just needs to go somewhere that is likely to be
00384         // called when num_iters_ == 0. This seems as good a place as any.
00385         if (num_invalid_ > lmap_.size() && num_iters_ == 0) {
00386             clean_invalid();
00387         }
00388         
00389         umap::iterator i = map_.begin();
00390         while (i != map_.end() && !i->second.first) { 
00391             ++i; 
00392         }
00393         return unit_iterator(i, this);
00394 }
00395 
00396 
00397 void unit_map::add(std::pair<gamemap::location,unit> *p)
00398 {
00399     std::string unit_id = p->second.underlying_id();
00400     umap::iterator iter = map_.find(unit_id);
00401 
00402     if (iter == map_.end()) {
00403         map_[unit_id] = std::pair<bool, std::pair<gamemap::location, unit>*>(true, p);
00404     } else {    
00405         // if iter->second.first, then this is a duplicate underlying_id, or the map is already in an undefined
00406         // state due to a different duplicate id entry. This is not allowed. By storing it with a different id it
00407         // will not be accessible with find(std::string).
00408         if (iter->second.first) {
00409             std::stringstream id;
00410             id << unit_id << "-duplicate-" << get_random();
00411             unit_id = id.str();
00412             
00413             map_[unit_id] = std::pair<bool, std::pair<gamemap::location, unit>*>(true, p);
00414             WRN_NG << "unit_map::add -- duplicate id in unit map: " << p->second.underlying_id() << "\n";
00415         } else {
00416             iter->second.second = p;
00417             validate(iter);
00418         }
00419     
00420     }
00421 
00422     std::pair<lmap::iterator,bool> res = lmap_.insert(std::pair<gamemap::location,std::string>(p->first, unit_id));
00423     assert(res.second);
00424 }
00425 
00426 void unit_map::replace(std::pair<gamemap::location,unit> *p)
00427 {
00428     if (erase(p->first) != 1)
00429         assert(0);
00430     add(p);
00431 }
00432 
00433 void unit_map::delete_all()
00434 {
00435     for (umap::iterator i = map_.begin(); i != map_.end(); ++i) {
00436         if (i->second.first) delete(i->second.second);
00437     }
00438         
00439     lmap_.clear();
00440     map_.clear();
00441 }
00442 
00443 std::pair<gamemap::location,unit> *unit_map::extract(const gamemap::location &loc)
00444 {
00445     lmap::iterator i = lmap_.find(loc);
00446     if (i == lmap_.end())
00447         return NULL;
00448 
00449     umap::iterator iter = map_.find(i->second);
00450     std::pair<gamemap::location,unit> *res = iter->second.second;   
00451     
00452     invalidate(iter);
00453     lmap_.erase(i); 
00454     
00455     return res;
00456 }
00457 
00458 size_t unit_map::erase(const gamemap::location &loc)
00459 {
00460     lmap::iterator i = lmap_.find(loc);
00461     if (i == lmap_.end())
00462         return 0;
00463             
00464     umap::iterator iter = map_.find(i->second);
00465 
00466     invalidate(iter);
00467     
00468     delete iter->second.second;
00469     lmap_.erase(i);
00470     
00471     return 1;
00472 }
00473 
00474 void unit_map::erase(xy_accessor pos)
00475 {
00476     assert(pos.valid());
00477     
00478     if (erase(pos->first) != 1)
00479         assert(0);
00480 }
00481 
00482 void unit_map::clear()
00483 {
00484     delete_all();
00485 }
00486 
00487 void unit_map::clean_invalid() {
00488     size_t num_cleaned = 0;
00489     
00490     umap::iterator iter;
00491     for (iter = map_.begin(); iter != map_.end(); ++iter) {
00492         if (!iter->second.first) {
00493             map_.erase(iter--);
00494             num_cleaned++;
00495         }
00496     }
00497     
00498     num_invalid_ -= num_cleaned;
00499     
00500     LOG_NG << "unit_map::clean_invalid - removed " << num_cleaned << " invalid map entries.\n";
00501 }
00502             

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs