Checkin of patch 1020 (file #4046: unit_map_final1.patch) for Sapient.

This commit is contained in:
Rusty Russell 2008-03-26 00:19:29 +00:00
parent 5507d8ff24
commit deb8d64d16
3 changed files with 701 additions and 113 deletions

View file

@ -604,25 +604,17 @@ void formula_ai::play_turn()
move_formula_ = game_logic::formula::create_optional_formula(current_team().ai_parameters()["move"], &function_table);
}
//execute units formulas first
std::vector<gamemap::location> formula_unit_loc;
for(unit_map::const_iterator i = units_.begin(); i != units_.end(); ++i) {
if( (i->second.side() == get_info().team_num) && i->second.has_formula() )
for(unit_map::unit_iterator i = units_.begin() ; i != units_.end() ; ++i)
{
if ( (i->second.side() == get_info().team_num) && i->second.has_formula() )
{
formula_unit_loc.push_back(i->first);
}
}
for(std::vector<gamemap::location>::const_iterator i = formula_unit_loc.begin() ; i != formula_unit_loc.end() ; ++i)
{
unit_map::const_iterator unit_it = units_.find(*i);
if ( unit_it != units_.end() )
{
game_logic::const_formula_ptr formula(new game_logic::formula(unit_it->second.get_formula(), &function_table));
game_logic::const_formula_ptr formula(new game_logic::formula(i->second.get_formula(), &function_table));
game_logic::map_formula_callable callable(this);
callable.add_ref();
callable.add("me", variant(new unit_callable(*unit_it, current_team(), get_info().team_num)));
callable.add("me", variant(new unit_callable(*i, current_team(), get_info().team_num)));
make_move(formula, callable);
}
}
}
game_logic::map_formula_callable callable(this);

View file

@ -17,11 +17,17 @@
#include "unit.hpp"
#include "unit_map.hpp"
#include "log.hpp"
#include <cassert>
#define WRN_NG LOG_STREAM(warn, engine)
#define LOG_NG LOG_STREAM(info, engine)
typedef std::pair<std::string, std::pair<bool, std::pair<gamemap::location, unit>*> > umap_pair;
//! A unit map with a copy of a single unit in it.
unit_map::unit_map(const gamemap::location &loc, const unit &u)
unit_map::unit_map(const gamemap::location &loc, const unit &u) : num_iters_(0), num_invalid_(0)
{
add(new std::pair<gamemap::location,unit>(loc, u));
}
@ -34,8 +40,12 @@ unit_map::unit_map(const unit_map &that)
unit_map &unit_map::operator =(const unit_map &that)
{
clear();
for (pmap::const_iterator i = that.map_.begin(); i != that.map_.end(); i++) {
add(new std::pair<gamemap::location,unit>(*i->second));
num_iters_ = 0;
num_invalid_ = 0;
for (umap::const_iterator i = that.map_.begin(); i != that.map_.end(); i++) {
if (i->second.first) {
add(i->second.second);
}
}
return *this;
}
@ -45,60 +55,422 @@ unit_map::~unit_map()
delete_all();
}
std::pair<gamemap::location,unit>* unit_map::unit_iterator::operator->() const
{
assert(valid());
return i_->second.second;
}
std::pair<gamemap::location,unit>& unit_map::unit_iterator::operator*() const
{
assert(valid());
return *i_->second.second;
}
unit_map::unit_iterator unit_map::unit_iterator::operator++() {
assert(i_ != map_->map_.end());
++i_;
while (i_ != map_->map_.end() && !valid()) {
++i_;
}
return *this;
}
unit_map::unit_iterator unit_map::unit_iterator::operator++(int){
assert(i_ != map_->map_.end());
umap::iterator iter(i_);
++i_;
while (i_ != map_->map_.end() && !valid()) {
++i_;
}
return unit_iterator(iter, map_);
}
// Due to unit <-> unit_map dependencies, must be out of line.
std::pair<gamemap::location,unit>& unit_map::iterator::operator*() const
const std::pair<gamemap::location,unit>* unit_map::const_unit_iterator::operator->() const
{
return *i_->second;
assert(valid());
return i_->second.second;
}
const std::pair<gamemap::location,unit>& unit_map::const_iterator::operator*() const
const std::pair<gamemap::location,unit>& unit_map::const_unit_iterator::operator*() const
{
return *i_->second;
assert(valid());
return *i_->second.second;
}
unit_map::const_unit_iterator unit_map::const_unit_iterator::operator++() {
assert(i_ != map_->map_.end());
++i_;
while (i_ != map_->map_.end() && !valid()) {
++i_;
}
return *this;
}
unit_map::const_unit_iterator unit_map::const_unit_iterator::operator--() {
umap::const_iterator begin = map_->begin().i_;
assert(i_ != begin);
--i_;
while (i_ != begin && !valid()) {
--i_;
}
return *this;
}
unit_map::const_unit_iterator unit_map::const_unit_iterator::operator++(int){
assert(i_ != map_->map_.end());
umap::const_iterator iter(i_);
++i_;
while (i_ != map_->map_.end() && !valid()) {
++i_;
}
return const_unit_iterator(iter, map_);
}
unit_map::unit_xy_iterator::unit_xy_iterator(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
if (i.valid()) loc_ = i->first;
}
std::pair<gamemap::location,unit>* unit_map::unit_xy_iterator::operator->() const
{
assert(valid());
return i_->second.second;
}
std::pair<gamemap::location,unit>& unit_map::unit_xy_iterator::operator*() const
{
assert(valid());
return *i_->second.second;
}
unit_map::unit_xy_iterator unit_map::unit_xy_iterator::operator++() {
assert(i_ != map_->map_.end());
++i_;
while (i_ != map_->map_.end() && !valid()) {
++i_;
}
if (i_ != map_->map_.end()) {
loc_ = i_->second.second->first;
}
return *this;
}
unit_map::unit_xy_iterator unit_map::unit_xy_iterator::operator++(int){
assert(i_ != map_->map_.end());
umap::iterator iter(i_);
gamemap::location pre_loc = loc_;
++i_;
while (i_ != map_->map_.end() && !valid()) {
++i_;
}
if (i_ != map_->map_.end()) {
loc_ = i_->second.second->first;
}
return unit_xy_iterator(iter, map_, pre_loc);
}
bool unit_map::unit_xy_iterator::valid() const {
return i_ != map_->map_.end() && i_->second.first && loc_ == i_->second.second->first;
}
unit_map::const_unit_xy_iterator::const_unit_xy_iterator(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
if (i.valid()) loc_ = i->first;
}
unit_map::const_unit_xy_iterator::const_unit_xy_iterator(const const_unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
if (i.valid()) loc_ = i->first;
}
const std::pair<gamemap::location,unit>* unit_map::const_unit_xy_iterator::operator->() const {
assert(valid());
return i_->second.second;
}
const std::pair<gamemap::location,unit>& unit_map::const_unit_xy_iterator::operator*() const {
assert(valid());
return *i_->second.second;
}
unit_map::const_unit_xy_iterator unit_map::const_unit_xy_iterator::operator++() {
assert(i_ != map_->map_.end());
++i_;
while (i_ != map_->map_.end() && !valid()) {
++i_;
}
if (i_ != map_->map_.end()) {
loc_ = i_->second.second->first;
}
return *this;
}
unit_map::const_unit_xy_iterator unit_map::const_unit_xy_iterator::operator++(int){
assert(i_ != map_->map_.end());
gamemap::location pre_loc = loc_;
umap::const_iterator iter(i_);
++i_;
while (i_ != map_->map_.end() && !valid()) {
++i_;
}
if (i_ != map_->map_.end()) {
loc_ = i_->second.second->first;
}
return const_unit_xy_iterator(iter, map_, pre_loc);
}
bool unit_map::const_unit_xy_iterator::valid() const {
return i_ != map_->map_.end() && i_->second.first && loc_ == i_->second.second->first;
}
unit_map::xy_accessor::xy_accessor(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
if (i.valid()) loc_ = i->first;
}
unit_map::xy_accessor::xy_accessor(const unit_xy_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
if (i.valid()) loc_ = i->first;
}
std::pair<gamemap::location,unit>* unit_map::xy_accessor::operator->() {
if (!valid()) { assert(0); }
return i_->second.second;
}
std::pair<gamemap::location,unit>& unit_map::xy_accessor::operator*() {
if (!valid()) { assert(0); }
return *i_->second.second;
}
bool unit_map::xy_accessor::valid() {
if (i_->second.first && i_->second.second->first == loc_) {
return true;
}
unit_iterator u_iter = map_->find(loc_);
if (u_iter.valid()) {
i_ = u_iter.i_;
loc_ = i_->second.second->first;
return true;
}
return false;
}
unit_map::const_xy_accessor::const_xy_accessor(const const_unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
if (i.valid()) loc_ = i->first;
}
unit_map::const_xy_accessor::const_xy_accessor(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
if (i.valid()) loc_ = i->first;
}
unit_map::const_xy_accessor::const_xy_accessor(const const_unit_xy_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
if (i.valid()) loc_ = i->first;
}
unit_map::const_xy_accessor::const_xy_accessor(const unit_xy_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) {
if (i.valid()) loc_ = i->first;
}
const std::pair<gamemap::location,unit>* unit_map::const_xy_accessor::operator->() {
if (!valid()) { assert(0); }
return i_->second.second;
}
const std::pair<gamemap::location,unit>& unit_map::const_xy_accessor::operator*() {
if (!valid()) { assert(0); }
return *i_->second.second;
}
bool unit_map::const_xy_accessor::valid() {
if (i_->second.first && i_->second.second->first == loc_) {
return true;
}
const_unit_iterator u_iter = map_->find(loc_);
if (u_iter.valid()) {
i_ = u_iter.i_;
loc_ = i_->second.second->first;
return true;
}
return false;
}
unit_map::unit_iterator unit_map::find(const gamemap::location &loc) {
lmap::const_iterator iter = lmap_.find(loc);
if (iter == lmap_.end()) {
return unit_iterator(map_.end(), this);
}
umap::iterator i = map_.find(iter->second->second.underlying_id());
i->second.second->first = loc;
return unit_iterator(i , this);
}
unit_map::const_unit_iterator unit_map::find(const gamemap::location &loc) const {
lmap::const_iterator iter = lmap_.find(loc);
if (iter == lmap_.end()) {
return const_unit_iterator(map_.end(), this);
}
umap::const_iterator i = map_.find(iter->second->second.underlying_id());
i->second.second->first = loc;
return const_unit_iterator(i , this);
}
unit_map::unit_iterator unit_map::begin() {
// clean if there are more invalid than valid
if (num_invalid_ > lmap_.size() && num_iters_ == 0) {
clean_invalid();
}
umap::iterator i = map_.begin();
while (i != map_.end() && !i->second.first) {
++i;
}
return unit_iterator(i, this);
}
void unit_map::add(std::pair<gamemap::location,unit> *p)
{
std::pair<pmap::iterator,bool> res = map_.insert(std::pair<gamemap::location,std::pair<gamemap::location,unit>*>(p->first, p));
std::pair<lmap::iterator,bool> res = lmap_.insert(std::pair<gamemap::location,std::pair<gamemap::location,unit>*>(p->first, p));
assert(res.second);
umap::iterator iter = map_.find(p->second.underlying_id());
if (iter != map_.end() && iter->second.first && iter->second.second->first != p->first) {
WRN_NG << "unit_map::add -- duplicate unique id in unit_map: " << p->second.underlying_id() << "\n";
}
if (iter != map_.end() && !iter->second.first) {
num_invalid_--;
}
map_[p->second.underlying_id()] = std::pair<bool, std::pair<gamemap::location, unit>*>(true, p);
}
void unit_map::replace(std::pair<gamemap::location,unit> *p)
{
if (erase(p->first) != 1)
assert(0);
map_.insert(std::pair<gamemap::location,std::pair<gamemap::location,unit>*>(p->first, p));
add(p);
}
void unit_map::delete_all()
{
for (pmap::iterator i = map_.begin(); i != map_.end(); i++) {
for (lmap::iterator i = lmap_.begin(); i != lmap_.end(); ++i) {
delete(i->second);
}
lmap_.clear();
map_.clear();
}
//! Extract (like erase, but don't delete).
std::pair<gamemap::location,unit> *unit_map::extract(const gamemap::location &loc)
{
pmap::iterator i = map_.find(loc);
if (i == map_.end())
lmap::iterator i = lmap_.find(loc);
if (i == lmap_.end())
return NULL;
std::pair<gamemap::location,unit> *res = i->second;
map_.erase(i);
std::pair<gamemap::location,unit> *res = i->second;
umap::iterator iter = map_.find(i->second->second.underlying_id());
lmap_.erase(i);
update_validity(iter);
return res;
}
size_t unit_map::erase(const gamemap::location &loc)
{
pmap::iterator i = map_.find(loc);
if (i == map_.end())
lmap::iterator i = lmap_.find(loc);
if (i == lmap_.end())
return 0;
umap::iterator iter = map_.find(i->second->second.underlying_id());
delete i->second;
map_.erase(i);
lmap_.erase(i);
update_validity(iter);
return 1;
}
void unit_map::erase(iterator pos)
void unit_map::update_validity(umap::iterator iter)
{
lmap::const_iterator i;
for (i = lmap_.begin(); i != lmap_.end(); ++i) {
if (i->second->second.underlying_id() == iter->first) {
iter->second.second = i->second;
break;
}
}
if (i == lmap_.end()) {
if (iter->second.first) {
iter->second.first = false;
++num_invalid_;
}
} else {
if (!iter->second.first) {
iter->second.first = true;
--num_invalid_;
}
}
}
void unit_map::erase(xy_accessor pos)
{
assert(pos.valid());
if (erase(pos->first) != 1)
assert(0);
}
@ -106,5 +478,21 @@ void unit_map::erase(iterator pos)
void unit_map::clear()
{
delete_all();
map_.clear();
}
void unit_map::clean_invalid() {
size_t num_cleaned = 0;
umap::iterator iter;
for (iter = map_.begin(); iter != map_.end(); ++iter) {
if (!iter->second.first) {
map_.erase(iter--);
num_cleaned++;
}
}
num_invalid_ -= num_cleaned;
LOG_NG << "unit_map::clean_invalid - removed " << num_cleaned << " invalid map entries.\n";
}

View file

@ -34,103 +34,296 @@ class unit;
class unit_map
{
private:
//! Used so unit_map can keep a count of iterators and clean invalid pointers when no iterators exist. Every iterator and accessor has a counter instance.
struct iterator_counter {
iterator_counter() : has_map_(false) {}
iterator_counter(const unit_map* map) : map_(map), has_map_(true)
{ map_->add_iter(); }
iterator_counter(const iterator_counter& i) : has_map_(i.has_map_) {
if (has_map_)
{ map_ = i.map_; map_->add_iter(); }
}
iterator_counter &operator =(const iterator_counter &that) {
if (this == &that)
return *this;
if (has_map_) map_->remove_iter();
has_map_ = that.has_map_;
if (has_map_) {
map_=that.map_;
map_->add_iter();
}
return *this;
}
~iterator_counter() {if (has_map_) map_->remove_iter(); }
private:
const unit_map* map_;
bool has_map_;
};
public:
unit_map() { };
unit_map() : num_iters_(0), num_invalid_(0) { };
unit_map(const unit_map &that);
unit_map &operator =(const unit_map &that);
//! A unit map with a single unit in it.
explicit unit_map(const gamemap::location &loc, const unit &u);
~unit_map();
//! Keyed with unit's underlying_id. bool flag is whether the following pair pointer is valid. pointer to pair used to imitate a map<location, unit>
typedef std::map<std::string,std::pair<bool, std::pair<gamemap::location,unit>*> > umap;
//! Maintains only the valid pairs. Used to determine validity in umap, and for faster lookup by location.
typedef std::map<gamemap::location, std::pair<gamemap::location, unit>*> lmap;
struct const_unit_iterator;
struct unit_xy_iterator;
struct const_unit_xy_iterator;
struct xy_accessor;
struct const_xy_accessor;
//! We actually keep map to pointers to pairs. Easy to fake iterators.
typedef std::map<gamemap::location,std::pair<gamemap::location,unit>*> pmap;
struct iterator;
struct const_iterator {
const_iterator() { }
const_iterator(const iterator &i) : i_(i.i_) { }
const std::pair<gamemap::location,unit>* operator->() const
{ return i_->second; }
const std::pair<gamemap::location,unit>& operator*() const;
const_iterator operator++()
{ return const_iterator(++i_); }
const_iterator operator++(int)
{ return const_iterator(i_++); }
const_iterator operator--()
{ return const_iterator(--i_); }
bool operator==(const const_iterator &that) const
{ return that.i_ == this->i_; }
bool operator!=(const const_iterator &that) const
{ return that.i_ != this->i_; }
explicit const_iterator(pmap::const_iterator i) : i_(i) { }
private:
pmap::const_iterator i_;
};
struct iterator {
iterator() { }
std::pair<gamemap::location,unit> *operator->() const
{ return i_->second; }
//! For iterating over every unit. Iterator is valid as long as there is there is a unit w/ matching underlying_id in the map.
struct unit_iterator
{
unit_iterator() { }
unit_iterator(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) { }
unit_iterator(umap::iterator i, unit_map* map) : counter(map), i_(i), map_(map) { }
std::pair<gamemap::location,unit> *operator->() const;
std::pair<gamemap::location,unit>& operator*() const;
iterator operator++()
{ return iterator(++i_); }
unit_iterator operator++();
unit_iterator operator++(int);
iterator operator++(int)
{ return iterator(i_++); }
bool operator==(const iterator &that) const
bool operator==(const unit_iterator &that) const
{ return that.i_ == this->i_; }
bool operator!=(const iterator &that) const
bool operator!=(const unit_iterator &that) const
{ return that.i_ != this->i_; }
explicit iterator(pmap::iterator i) : i_(i) { }
friend struct const_iterator;
bool valid() const
{ return i_ != map_->map_.end() && i_->second.first; }
friend struct const_unit_iterator;
friend struct unit_xy_iterator;
friend struct const_unit_xy_iterator;
friend struct xy_accessor;
friend struct const_xy_accessor;
private:
pmap::iterator i_;
iterator_counter counter;
umap::iterator i_;
unit_map* map_;
};
struct const_unit_iterator
{
const_unit_iterator(const unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) { }
const_unit_iterator() { }
const_unit_iterator(const const_unit_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_) { }
const_unit_iterator(umap::const_iterator i, const unit_map* map): counter(map), i_(i), map_(map) { }
const std::pair<gamemap::location,unit>* operator->() const;
const std::pair<gamemap::location,unit>& operator*() const;
iterator find(const gamemap::location &loc) {
return iterator(map_.find(loc));
}
const_iterator find(const gamemap::location &loc) const {
return const_iterator(map_.find(loc));
}
const_unit_iterator operator++();
const_unit_iterator operator++(int);
const_unit_iterator operator--();
bool operator==(const const_unit_iterator &that) const
{ return that.i_ == this->i_; }
bool operator!=(const const_unit_iterator &that) const
{ return that.i_ != this->i_; }
bool valid() const
{ return i_ != map_->map_.end() && i_->second.first; }
friend struct const_unit_xy_iterator;
friend struct const_xy_accessor;
private:
iterator_counter counter;
umap::const_iterator i_;
const unit_map* map_;
};
typedef unit_iterator iterator;
typedef const_unit_iterator const_iterator;
//! Similar to unit_iterator, except that becomes invalid if unit is moved while the iterator points at it. Can update to the new position w/ update_loc().
struct unit_xy_iterator
{
unit_xy_iterator(const unit_iterator &i);
unit_xy_iterator() { }
unit_xy_iterator(const unit_xy_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_)
{ if (i.valid()) loc_ = i.loc_; }
unit_xy_iterator(umap::iterator i, unit_map* map, gamemap::location loc): counter(map), i_(i), map_(map), loc_(loc) { }
std::pair<gamemap::location,unit>* operator->() const;
std::pair<gamemap::location,unit>& operator*() const;
unit_xy_iterator operator++();
unit_xy_iterator operator++(int);
bool operator==(const unit_xy_iterator &that) const
{ return that.i_ == this->i_; }
bool operator!=(const unit_xy_iterator &that) const
{ return that.i_ != this->i_; }
bool valid() const;
friend struct const_unit_xy_iterator;
friend struct xy_accessor;
friend struct const_xy_accessor;
private:
iterator_counter counter;
umap::iterator i_;
unit_map* map_;
gamemap::location loc_;
};
struct const_unit_xy_iterator
{
const_unit_xy_iterator(const unit_iterator &i);
const_unit_xy_iterator(const const_unit_iterator &i);
const_unit_xy_iterator() { }
const_unit_xy_iterator(umap::const_iterator i, const unit_map* map, gamemap::location loc): counter(map), i_(i), map_(map), loc_(loc) { }
const_unit_xy_iterator(const unit_xy_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_)
{ if (i.valid()) loc_ = i.loc_; }
const_unit_xy_iterator(const const_unit_xy_iterator &i) : counter(i.map_), i_(i.i_), map_(i.map_)
{ if (i.valid()) loc_ = i.loc_; }
const std::pair<gamemap::location,unit>* operator->() const;
const std::pair<gamemap::location,unit>& operator*() const;
const_unit_xy_iterator operator++();
const_unit_xy_iterator operator++(int);
bool operator==(const const_unit_xy_iterator &that) const
{ return that.i_ == this->i_; }
bool operator!=(const const_unit_xy_iterator &that) const
{ return that.i_ != this->i_; }
bool valid() const;
friend struct const_xy_accessor;
private:
iterator_counter counter;
umap::const_iterator i_;
const unit_map* map_;
gamemap::location loc_;
};
//! Used to access the unit at a given position. Is valid as long as any unit is in that position. Can switch from invalid to valid.
struct xy_accessor
{
xy_accessor(const unit_iterator &i);
xy_accessor(const unit_xy_iterator &i);
xy_accessor() { }
std::pair<gamemap::location,unit>* operator->();
std::pair<gamemap::location,unit>& operator*();
bool valid();
private:
iterator_counter counter;
umap::iterator i_;
unit_map* map_;
gamemap::location loc_;
};
struct const_xy_accessor
{
const_xy_accessor(const unit_iterator &i);
const_xy_accessor(const unit_xy_iterator &i);
const_xy_accessor(const const_unit_iterator &i);
const_xy_accessor(const const_unit_xy_iterator &i);
const_xy_accessor() { }
const std::pair<gamemap::location,unit>* operator->();
const std::pair<gamemap::location,unit>& operator*();
bool valid();
private:
iterator_counter counter;
umap::const_iterator i_;
const unit_map* map_;
gamemap::location loc_;
};
//! Return object can be implicitly converted to any of the other iterators or accessors
unit_iterator find(const gamemap::location &loc) ;
//! Return object can be implicity converted to any of the other const iterators or accessors
const_unit_iterator find(const gamemap::location &loc) const;
size_t count(const gamemap::location &loc) const {
return map_.count(loc);
return lmap_.count(loc);
}
iterator begin() {
return iterator(map_.begin());
//! Return object can be implicitly converted to any of the other iterators or accessors
unit_iterator begin();
//! Return object can be implicity converted to any of the other const iterators or accessors
const_unit_iterator begin() const {
umap::const_iterator i = map_.begin();
while (i != map_.end() && !i->second.first) {
++i;
}
return const_unit_iterator(i, this);
}
const_iterator begin() const {
return const_iterator(map_.begin());
}
iterator end() {
return iterator(map_.end());
}
const_iterator end() const {
return const_iterator(map_.end());
//! Return object can be implicitly converted to any of the other iterators or accessors
unit_iterator end() {
return iterator(map_.end(), this);
}
//! Return object can be implicity converted to any of the other const iterators or accessors
const_unit_iterator end() const {
return const_iterator(map_.end(), this);
}
size_t size() const {
return map_.size();
return lmap_.size();
}
void clear();
@ -138,25 +331,40 @@ public:
//! Extract (like erase, only don't delete).
std::pair<gamemap::location,unit> *extract(const gamemap::location &loc);
//! Map owns pointer after this. Loc must be currently empty.
//! Map owns pointer after this. Loc must be currently empty. unit's underlying_id should not be present in the map already
void add(std::pair<gamemap::location,unit> *p);
//! Like add, but loc must be occupied (implicitly erased).
void replace(std::pair<gamemap::location,unit> *p);
void erase(iterator pos);
void erase(xy_accessor pos);
size_t erase(const gamemap::location &loc);
void swap(unit_map& o) {
map_.swap(o.map_);
lmap_.swap(o.lmap_);
}
//! Removes invalid entries in map_. Called automatically when safe and needed.
void clean_invalid();
private:
void update_validity(umap::iterator iter);
void delete_all();
void add_iter() const { ++num_iters_; }
void remove_iter() const { --num_iters_; }
//! A map of pairs is redundant, but makes it possible to imitate a map of location,unit.
std::map<gamemap::location,std::pair<gamemap::location,unit>*> map_;
//! Key: unit's underlying_id. bool indicates validity of pointer. pointer to pair used to imitate a map<location, unit>
std::map<std::string,std::pair<bool, std::pair<gamemap::location,unit>*> > map_;
//! Maintains only the valid pairs. Used to determine validity in umap, and for faster lookup by location.
std::map<gamemap::location, std::pair<gamemap::location, unit>*> lmap_;
mutable size_t num_iters_;
size_t num_invalid_;
};
#endif // UNIT_MAP_H_INCLUDED