24 #define ERR_NG LOG_STREAM(err, log_engine) 25 #define WRN_NG LOG_STREAM(warn, log_engine) 26 #define LOG_NG LOG_STREAM(info, log_engine) 27 #define DBG_NG LOG_STREAM(debug, log_engine) 39 for(
const auto& u : that) {
40 add(u.get_location(), u);
69 while(i !=
umap_.end() && (!i->second.unit)) {
85 if(res.second ==
false) {
95 DBG_NG <<
"Unit map: Moving unit from " << src <<
" to " << dst <<
"\n";
99 if(i ==
lmap_.end()) {
115 p->set_location(dst);
119 std::pair<lmap::iterator, bool> res =
lmap_.emplace(dst, uit);
122 if(res.second ==
false) {
123 p->set_location(src);
124 lmap_.emplace(src, uit);
142 std::size_t unit_id = p->underlying_id();
146 ERR_NG <<
"Trying to add " << p->name() <<
" - " << p->id() <<
" at an invalid location; Discarding.\n";
153 DBG_NG <<
"Adding unit " << p->underlying_id() <<
" - " << p->id() <<
" to location: (" << loc <<
")\n";
155 std::pair<umap::iterator, bool> uinsert =
umap_.emplace(unit_id, upod);
157 if(!uinsert.second) {
159 if(!uinsert.first->second.unit) {
160 unit_pod& opod = uinsert.first->second;
165 unit_ptr q = uinsert.first->second.unit;
166 ERR_NG <<
"Trying to add " << p->name()
167 <<
" - " << p->id() <<
" - " << p->underlying_id()
168 <<
" (" << loc <<
") over " << q->name()
169 <<
" - " << q->id() <<
" - " << q->underlying_id()
170 <<
" (" << q->get_location()
173 p->mark_clone(
false);
174 ERR_NG <<
"The new unit was assigned underlying_id=" << p->underlying_id()
175 <<
" to prevent duplicate id conflicts.\n";
177 uinsert =
umap_.emplace(p->underlying_id(), upod);
180 while(!uinsert.second && (++guard < 1e6)) {
181 if(guard % 10 == 9) {
182 ERR_NG <<
"\n\nPlease Report this error to https://gna.org/bugs/index.php?18591 " 183 "\nIn addition to the standard details of operating system and wesnoth version " 184 "and how it happened, please answer the following questions " 185 "\n 1. Were you playing multi-player?" 186 "\n 2. Did you start/restart/reload the game/scenario?" 187 "\nThank you for your help in fixing this bug.\n";
190 p->mark_clone(
false);
191 uinsert =
umap_.emplace(p->underlying_id(), upod);
194 if(!uinsert.second) {
195 throw game::error(
"One million collisions in unit_map");
200 std::pair<lmap::iterator, bool> linsert =
lmap_.emplace(loc, uinsert.first);
203 if(!linsert.second) {
206 umap_.erase(uinsert.first);
209 uinsert.first->second.unit.reset();
212 DBG_NG <<
"Trying to add " << p->name() <<
" - " << p->id() <<
" at location (" << loc <<
"); Occupied by " 213 << (linsert.first->second->second).
unit->
name() <<
" - " << linsert.first->second->second.unit->id()
235 umap::const_iterator ui =
umap_.begin();
236 umap::const_iterator uend =
umap_.end();
238 for(; ui != uend; ++ui) {
239 if(ui->second.ref_count < 0) {
241 bool a_reference_counter_overflowed(
false);
242 assert(a_reference_counter_overflowed);
245 num_iters += ui->second.ref_count;
257 DBG_NG <<
"Delete unit " <<
i->second.unit->underlying_id() <<
"\n";
258 i->second.unit.reset();
271 if(i ==
lmap_.end()) {
278 std::size_t uid(u->underlying_id());
280 DBG_NG <<
"Extract unit " << uid <<
" - " << u->id() <<
" from location: (" << loc <<
")\n";
282 assert(uit->first == uit->second.unit->underlying_id());
283 if(uit->second.ref_count == 0) {
287 uit->second.unit.reset();
314 if((
i !=
umap_.end()) && !
i->second.unit) {
318 return make_unit_iterator<umap::iterator>(
i);
324 return make_unit_iterator<lmap::iterator>(
lmap_.find(loc));
330 for(; i != i_end; ++
i) {
331 if(i->side() == side && i->can_recruit()) {
344 for(; i != i_end; ++
i) {
345 if(i->side() == side && i->can_recruit()) {
346 if((first_leader ==
end()) || (i->underlying_id() < first_leader->underlying_id())) {
359 std::vector<unit_map::unit_iterator> leaders;
360 for(; i != i_end; ++
i) {
361 if(i->side() == side && i->can_recruit()) {
362 leaders.push_back(i);
371 const std::vector<unit_map::unit_iterator>& leaders =
const_cast<unit_map*
>(
this)->
find_leaders(side);
372 std::vector<unit_map::const_unit_iterator> const_leaders(leaders.begin(), leaders.end());
374 return const_leaders;
379 #ifdef DEBUG_UNIT_MAP 382 umap::const_iterator uit(
umap_.begin());
383 for(; uit !=
umap_.end(); ++uit) {
384 if(uit->second.ref_count < 0) {
386 ERR_NG <<
"unit_map pod ref_count <0 is " << uit->second.ref_count << std::endl;
389 if(uit->second.unit) {
390 uit->second.unit->id();
393 if(uit->first <= 0) {
395 ERR_NG <<
"unit_map umap uid <=0 is " << uit->first << std::endl;
398 if(!uit->second.unit && uit->second.ref_count == 0) {
400 ERR_NG <<
"unit_map umap unit==nullptr when refcount == 0" << std::endl;
403 if(uit->second.unit && uit->second.unit->underlying_id() != uit->first) {
405 ERR_NG <<
"unit_map umap uid(" << uit->first <<
") != underlying_id()[" << uit->second.unit->underlying_id()
410 lmap::const_iterator locit(
lmap_.begin());
411 for(; locit !=
lmap_.end(); ++locit) {
412 if(locit->second ==
umap_.end()) {
414 ERR_NG <<
"unit_map lmap element == umap_.end() " << std::endl;
416 if(locit->first != locit->second->second.unit->get_location()) {
418 ERR_NG <<
"unit_map lmap location != unit->get_location() " << std::endl;
433 for(
const umap::value_type&
item :
umap_) {
434 if(
item.second.unit.get() == u) {
std::vector< unit_iterator > find_leaders(int side)
This class represents a single unit of a specific type.
unit_map & operator=(const unit_map &that)
umap_retval_pair_t insert(unit_ptr p)
Inserts the unit pointed to by p into the map.
unit_iterator find_leader(int side)
static l_noret error(LoadState *S, const char *why)
std::size_t erase(const map_location &l)
Erases the unit at location l, if any.
unit_map::unit_iterator make_unit_iterator(const X &i)
std::shared_ptr< unit > unit_ptr
umap_retval_pair_t replace(const map_location &l, unit_ptr p)
Works like unit_map::add; but l is emptied first, if needed.
void swap(unit_map &lhs, unit_map &rhs)
Implement non-member swap function for std::swap (calls unit_map::swap).
umap_retval_pair_t add(const map_location &l, const unit &u)
Adds a copy of unit u at location l of the map.
void clear(bool force=false)
const t_string & name() const
Gets this unit's translatable display name.
std::pair< unit_iterator, bool > umap_retval_pair_t
umap_retval_pair_t move(const map_location &src, const map_location &dst)
Moves a unit from location src to location dst.
umap::iterator begin_core() const
Encapsulates the map of the game.
unit_iterator find(std::size_t id)
unit_iterator find_first_leader(int side)
std::size_t num_iters() const
The pointer to the unit and a reference counter to record the number of extant iteratorspointing to t...
bool has_unit_at(const map_location &loc) const
Tests whether a unit exists at the given location.
bool self_check() const
Checks invariants.
unit_ptr extract(const map_location &loc)
Extracts a unit from the map.
Standard logging facilities (interface).
n_ref_counter::ref_counter< signed int > ref_count
static lg::log_domain log_engine("engine")
lmap lmap_
location -> umap::iterator.
Container associating units to locations.
umap umap_
underlying_id -> unit_pod.
bool is_valid(const umap::const_iterator &i) const
std::string::const_iterator iterator
std::pair< std::string, unsigned > item
bool has_unit(const unit *const u) const
Is the unit in the map?