00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
00384
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
00406
00407
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