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;
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);
144 std::size_t unit_id =
p->underlying_id();
148 ERR_NG <<
"Trying to add " <<
p->name() <<
" - " <<
p->id() <<
" at an invalid location; Discarding.";
155 DBG_NG <<
"Adding unit " <<
p->underlying_id() <<
" - " <<
p->id() <<
" to location: (" <<
loc <<
")";
157 std::pair<umap::iterator, bool> uinsert =
umap_.emplace(unit_id, upod);
159 if(!uinsert.second) {
161 if(!uinsert.first->second.unit) {
162 unit_pod& opod = uinsert.first->second;
167 unit_ptr q = uinsert.first->second.unit;
168 ERR_NG <<
"Trying to add " <<
p->name()
169 <<
" - " <<
p->id() <<
" - " <<
p->underlying_id()
170 <<
" (" <<
loc <<
") over " << q->name()
171 <<
" - " << q->id() <<
" - " << q->underlying_id()
172 <<
" (" << q->get_location()
175 p->mark_clone(
false);
176 ERR_NG <<
"The new unit was assigned underlying_id=" <<
p->underlying_id()
177 <<
" to prevent duplicate id conflicts.";
179 uinsert =
umap_.emplace(
p->underlying_id(), upod);
182 while(!uinsert.second && (++guard < 1e6)) {
183 p->mark_clone(
false);
184 uinsert =
umap_.emplace(
p->underlying_id(), upod);
187 if(!uinsert.second) {
188 throw game::error(
"One million collisions in unit_map");
193 std::pair<lmap::iterator, bool> linsert =
lmap_.emplace(
loc, uinsert.first);
196 if(!linsert.second) {
199 umap_.erase(uinsert.first);
202 uinsert.first->second.unit.reset();
205 DBG_NG <<
"Trying to add " <<
p->name() <<
" - " <<
p->id() <<
" at location (" <<
loc <<
"); Occupied by "
206 << (linsert.first->second->second).
unit->
name() <<
" - " << linsert.first->second->second.unit->id()
228 umap::const_iterator ui =
umap_.begin();
229 umap::const_iterator uend =
umap_.end();
231 for(; ui != uend; ++ui) {
232 if(ui->second.ref_count < 0) {
234 bool a_reference_counter_overflowed(
false);
235 assert(a_reference_counter_overflowed);
250 DBG_NG <<
"Delete unit " <<
i->second.unit->underlying_id();
251 i->second.unit.reset();
271 std::size_t uid(u->underlying_id());
273 DBG_NG <<
"Extract unit " << uid <<
" - " << u->id() <<
" from location: (" <<
loc <<
")";
275 assert(uit->first == uit->second.unit->underlying_id());
276 if(uit->second.ref_count == 0) {
280 uit->second.unit.reset();
307 if((
i !=
umap_.end()) && !
i->second.unit) {
311 return make_unit_iterator<umap::iterator>(
i);
317 return make_unit_iterator<lmap::iterator>(
lmap_.find(
loc));
323 for(;
i != i_end; ++
i) {
324 if(
i->side() == side &&
i->can_recruit()) {
337 for(;
i != i_end; ++
i) {
338 if(
i->side() == side &&
i->can_recruit()) {
339 if((first_leader ==
end()) || (
i->underlying_id() < first_leader->underlying_id())) {
352 std::vector<unit_map::unit_iterator> leaders;
353 for(;
i != i_end; ++
i) {
354 if(
i->side() == side &&
i->can_recruit()) {
355 leaders.push_back(
i);
364 const std::vector<unit_map::unit_iterator>& leaders =
const_cast<unit_map*
>(
this)->
find_leaders(side);
365 std::vector<unit_map::const_unit_iterator> const_leaders(leaders.begin(), leaders.end());
367 return const_leaders;
372 #ifdef DEBUG_UNIT_MAP
375 umap::const_iterator uit(
umap_.begin());
376 for(; uit !=
umap_.end(); ++uit) {
377 if(uit->second.ref_count < 0) {
379 ERR_NG <<
"unit_map pod ref_count <0 is " << uit->second.ref_count;
382 if(uit->second.unit) {
383 uit->second.unit->id();
386 if(uit->first <= 0) {
388 ERR_NG <<
"unit_map umap uid <=0 is " << uit->first;
391 if(!uit->second.unit && uit->second.ref_count == 0) {
393 ERR_NG <<
"unit_map umap unit==nullptr when refcount == 0";
396 if(uit->second.unit && uit->second.unit->underlying_id() != uit->first) {
398 ERR_NG <<
"unit_map umap uid(" << uit->first <<
") != underlying_id()[" << uit->second.unit->underlying_id()
403 lmap::const_iterator locit(
lmap_.begin());
404 for(; locit !=
lmap_.end(); ++locit) {
405 if(locit->second ==
umap_.end()) {
407 ERR_NG <<
"unit_map lmap element == umap_.end() ";
409 if(locit->first != locit->second->second.unit->get_location()) {
411 ERR_NG <<
"unit_map lmap location != unit->get_location() ";
426 for(
const umap::value_type& item :
umap_) {
427 if(item.second.unit.get() == u) {
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
static display * get_singleton()
Returns the display object if a display object exists.
Container associating units to locations.
umap::iterator begin_core() const
std::vector< unit_iterator > find_leaders(int side)
umap umap_
underlying_id -> unit_pod.
bool has_unit_at(const map_location &loc) const
Tests whether a unit exists at the given location.
std::pair< unit_iterator, bool > umap_retval_pair_t
bool self_check() const
Checks invariants.
void clear(bool force=false)
unit_ptr extract(const map_location &loc)
Extracts a unit from the map.
unit_iterator find(std::size_t id)
unit_map & operator=(const unit_map &that)
umap_retval_pair_t replace(const map_location &l, const unit_ptr &p)
Works like unit_map::add; but l is emptied first, if needed.
unit_map::unit_iterator make_unit_iterator(const X &i)
std::size_t num_iters() const
unit_iterator find_first_leader(int side)
lmap lmap_
location -> umap::iterator.
bool has_unit(const unit *const u) const
Is the unit in the map?
std::size_t erase(const map_location &l)
Erases the unit at location l, if any.
umap_retval_pair_t add(const map_location &l, const unit &u)
Adds a copy of unit u at location l of the map.
unit_iterator find_leader(int side)
umap_retval_pair_t insert(const unit_ptr &p)
Inserts the unit pointed to by p into the map.
bool is_valid(const umap::const_iterator &i) const
umap_retval_pair_t move(const map_location &src, const map_location &dst)
Moves a unit from location src to location dst.
This class represents a single unit of a specific type.
map_display and display: classes which take care of displaying the map and game-data on the screen.
const t_string & name() const
Gets this unit's translatable display name.
Standard logging facilities (interface).
std::string::const_iterator iterator
std::shared_ptr< unit > unit_ptr
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
Base class for all the errors encountered by the engine.
Encapsulates the map of the game.
The pointer to the unit and a reference counter to record the number of extant iteratorspointing to t...
n_ref_counter::ref_counter< signed int > ref_count
void swap(unit_map &lhs, unit_map &rhs)
Implement non-member swap function for std::swap (calls unit_map::swap).
static lg::log_domain log_engine("engine")