Esempio n. 1
0
std::pair<unit_map::unit_iterator, bool> unit_map::move(const map_location &src, const map_location &dst) {
	self_check();
	DBG_NG << "Unit map: Moving unit from " << src << " to " << dst << "\n";

	//Find the unit at the src location
	t_lmap::iterator i = lmap_.find(src);
	if(i == lmap_.end()) { return std::make_pair(make_unit_iterator(the_end_), false);}

	t_ilist::iterator lit(i->second);

	if(src == dst){ return std::make_pair(make_unit_iterator(lit),true);}

	//Fail if there is no unit to move
	unit *p = lit->unit;
	if(p == NULL){ return std::make_pair(make_unit_iterator(lit), false);}

	p->set_location(dst);

	///@todo upgrade to quick_erase when boost 1.42 supported by wesnoth
	lmap_.erase(i);

	std::pair<t_lmap::iterator,bool> res = lmap_.insert(std::make_pair(dst, lit));

	//Fail and don't move if the destination is already occupied
	if(res.second == false) {
		p->set_location(src);
		lmap_.insert(std::make_pair(src, lit));
		return std::make_pair(make_unit_iterator(lit), false);
	}

	self_check();

	return std::make_pair(make_unit_iterator(lit), true);
}
Esempio n. 2
0
std::pair<unit_map::unit_iterator, bool> unit_map::move(const map_location &src, const map_location &dst) {
	self_check();
	DBG_NG << "Unit map: Moving unit from " << src << " to " << dst << "\n";

	//Find the unit at the src location
	t_lmap::iterator i = lmap_.find(src);
	if(i == lmap_.end()) { return std::make_pair(make_unit_iterator(i), false);}

	t_umap::iterator uit(i->second);

	if(src == dst){ return std::make_pair(make_unit_iterator(uit), true);}

	//Fail if there is no unit to move
	unit_ptr p = uit->second.unit;
	if(!p){ return std::make_pair(make_unit_iterator(uit), false);}

	p->set_location(dst);

	lmap_.erase(i);

	std::pair<t_lmap::iterator,bool> res = lmap_.insert(std::make_pair(dst, uit));

	//Fail and don't move if the destination is already occupied
	if(res.second == false) {
		p->set_location(src);
		lmap_.insert(std::make_pair(src, uit));
		return std::make_pair(make_unit_iterator(uit), false);
	}

	self_check();

	return std::make_pair(make_unit_iterator(uit), true);
}
Esempio n. 3
0
/** Inserts the unit pointed to by @a p into the unit_map.

It needs to succeed on the insertion to the umap and to the lmap
otherwise all operations are reverted.
1. Insert a unit_pod into the list
2. Try insertion into the umap and remove the list item on failure
3. Try insertion in the lmap and remove the umap and the list item on failure

The one oddity is that to facilitate non-invalidating iterators the list
sometimes has NULL pointers which should be used when they correspond
to uids previously used.
 */
std::pair<unit_map::unit_iterator, bool> unit_map::insert(unit *p) {
	self_check();
	assert(p);

	size_t unit_id = p->underlying_id();
	const map_location &loc = p->get_location();

	if (!loc.valid()) {
		ERR_NG << "Trying to add " << p->name()
			<< " - " << p->id() << " at an invalid location; Discarding.\n";
		return std::make_pair(make_unit_iterator(the_end_), false);
	}

	unit_pod upod;
	upod.unit = p;
	upod.deleted_uid = unit_id;
	ilist_.push_front(upod);
	t_ilist::iterator lit(ilist_.begin());

	DBG_NG << "Adding unit " << p->underlying_id() << " - " << p->id()
		<< " to location: (" << loc << ")\n";

	std::pair<t_umap::iterator, bool> uinsert = umap_.insert(std::make_pair(unit_id, lit ));

	if (! uinsert.second) {
		//If the UID is empty reinsert the unit in the same list element
		if ( uinsert.first->second->unit == NULL) {
			ilist_.pop_front();
			lit = uinsert.first->second;
			lit->unit = p;
			assert(lit->ref_count != 0);
		} else {
			unit *q = uinsert.first->second->unit;
			ERR_NG << "Trying to add " << p->name()
				   << " - " << p->id() << " - " << p->underlying_id()
				   << " ("  << loc << ") over " << q->name()
				   << " - " << q->id() << " - " << q->underlying_id()
				   << " ("  << q->get_location()
				   << "). The new unit will be assigned underlying_id="
				   << (1 + n_unit::id_manager::instance().get_save_id())
				   << " to prevent duplicate id conflicts.\n";

			p->clone(false);
			uinsert = umap_.insert(std::make_pair(p->underlying_id(), lit ));
			int guard(0);
			while (!uinsert.second && (++guard < 1e6) ) {
				if(guard % 10 == 9){
					ERR_NG << "\n\nPlease Report this error to https://gna.org/bugs/index.php?18591 "
						"\nIn addition to the standard details of operating system and wesnoth version "
						"and how it happened, please answer the following questions "
						"\n 1. Were you playing mutli-player?"
						"\n 2. Did you start/restart/reload the game/scenario?"
						"\nThank you for your help in fixing this bug.\n";
				}
				p->clone(false);
				uinsert = umap_.insert(std::make_pair(p->underlying_id(), lit )); }
			if (!uinsert.second) {
				throw "One million collisions in unit_map"; }
		}
	}

	std::pair<t_lmap::iterator,bool> linsert = lmap_.insert(std::make_pair(loc, lit ));

	//Fail if the location is occupied
	if(! linsert.second) {
		if(lit->ref_count == 0) {
			//Undo a virgin insertion
			ilist_.pop_front();
			///@todo replace with quick_erase(i) when wesnoth supports  boost 1.42 min version
			umap_.erase(uinsert.first);
		} else {
			//undo a reinsertion
			uinsert.first->second->unit = NULL;
		}
		DBG_NG << "Trying to add " << p->name()
			   << " - " << p->id() << " at location ("<<loc <<"); Occupied  by "
			   <<(linsert.first->second)->unit->name()<< " - " << linsert.first->second->unit->id() <<"\n";

		return std::make_pair(make_unit_iterator(the_end_), false);
	}

	self_check();
	return std::make_pair( make_unit_iterator( lit ), true);
}
Esempio n. 4
0
/** Inserts the unit pointed to by @a p into the unit_map.

It needs to succeed on the insertion to the umap and to the lmap
otherwise all operations are reverted.
1. Construct a unit_pod
2. Try insertion into the umap
3. Try insertion in the lmap and remove the umap entry on failure

The one oddity is that to facilitate non-invalidating iterators the list
sometimes has NULL pointers which should be used when they correspond
to uids previously used.
 */
std::pair<unit_map::unit_iterator, bool> unit_map::insert(unit_ptr p) {
	self_check();
	assert(p);

	size_t unit_id = p->underlying_id();
	const map_location &loc = p->get_location();

	if (!loc.valid()) {
		ERR_NG << "Trying to add " << p->name()
			<< " - " << p->id() << " at an invalid location; Discarding.\n";
		return std::make_pair(make_unit_iterator(umap_.end()), false);
	}

	unit_pod upod;
	upod.unit = p ;

	DBG_NG << "Adding unit " << p->underlying_id() << " - " << p->id()
		<< " to location: (" << loc << ")\n";

	std::pair<t_umap::iterator, bool> uinsert = umap_.insert(std::make_pair(unit_id, upod ));

	if (! uinsert.second) {
		//If the pod is empty reinsert the unit in the same list element
		if (!uinsert.first->second.unit) {
			unit_pod &opod = uinsert.first->second;
			opod.unit = p ;
			assert(opod.ref_count != 0);
		} else {
			unit_ptr q = uinsert.first->second.unit;
			ERR_NG << "Trying to add " << p->name()
				   << " - " << p->id() << " - " << p->underlying_id()
				   << " ("  << loc << ") over " << q->name()
				   << " - " << q->id() << " - " << q->underlying_id()
				   << " ("  << q->get_location()
				   << ").";

			p->clone(false);
			ERR_NG << "The new unit was assigned underlying_id="
				   << p->underlying_id()
				   << " to prevent duplicate id conflicts.\n";

			uinsert = umap_.insert(std::make_pair(p->underlying_id(), upod ));
			int guard(0);
			while (!uinsert.second && (++guard < 1e6) ) {
				if(guard % 10 == 9){
					ERR_NG << "\n\nPlease Report this error to https://gna.org/bugs/index.php?18591 "
						"\nIn addition to the standard details of operating system and wesnoth version "
						"and how it happened, please answer the following questions "
						"\n 1. Were you playing multi-player?"
						"\n 2. Did you start/restart/reload the game/scenario?"
						"\nThank you for your help in fixing this bug.\n";
				}
				p->clone(false);
				uinsert = umap_.insert(std::make_pair(p->underlying_id(), upod )); }
			if (!uinsert.second) {
				throw game::error("One million collisions in unit_map"); }
		}
	}

	std::pair<t_lmap::iterator,bool> linsert = lmap_.insert(std::make_pair(loc, uinsert.first ));

	//Fail if the location is occupied
	if(! linsert.second) {
		if(upod.ref_count == 0) {
			//Undo a virgin insertion
			umap_.erase(uinsert.first);
		} else {
			//undo a reinsertion
			uinsert.first->second.unit.reset();
		}
		DBG_NG << "Trying to add " << p->name()
			   << " - " << p->id() << " at location ("<<loc <<"); Occupied  by "
			   <<(linsert.first->second->second).unit->name()<< " - " << linsert.first->second->second.unit->id() <<"\n";

		return std::make_pair(make_unit_iterator(umap_.end()), false);
	}

	self_check();
	return std::make_pair( make_unit_iterator( uinsert.first ), true);
}