Ejemplo n.º 1
0
std::list<ActionChain*> ActionFactory::createChains(const model::World& w, const model::Trooper& trooper, std::list<Tactician::Tactic> tactics, bool isFirstMove){

	std::list<ActionChain*> res_chains;
	ActionChain* new_chain = NULL;
	const std::vector<model::Trooper>& troopers = w.getTroopers();


	ActionChain* heal_chain = ActionFactory::heal(w, trooper, tactics, isFirstMove);
	
	if (heal_chain){
		ActionChunk first = *((heal_chain->chain).begin());
		model::ActionType firstType = first.action_type;

		if (isActionAvailable(trooper, firstType))
			res_chains.push_back(heal_chain);
		else
			delete heal_chain;
	}
	
	ActionChain* atack_chain = ActionFactory::atack(w, trooper, tactics, isFirstMove);

	if (atack_chain){//TODO: avoid copy-paste
		ActionChunk first = *((atack_chain->chain).begin());
		model::ActionType firstType = first.action_type;

		if (isActionAvailable(trooper, firstType))
			res_chains.push_back(atack_chain);
		else
			delete atack_chain;
	}
	
	if (gMainDst == Vector2d(-1, -1)){
		if (model::COMMANDER == trooper.getType()){

			const std::vector<model::Player>players = w.getPlayers();
			if (players[0].getApproximateX() != -1 || players[1].getApproximateX() != -1 ||
				players[2].getApproximateX() != -1 || players[3].getApproximateX() != -1){
				//already we have this info
				std::vector<model::Player>::const_iterator it = players.begin();
				float min = 1 << 20;
				Vector2d approximate(-1, -1);
				for (; it != players.end(); ++it){
					if (it->getName() == "m16a" || it->getName() == "MyStrategy"|| it->getApproximateX() == -1)
						continue;
					Vector2d tmp(it->getApproximateX(), it->getApproximateY());
					float d = dist(tmp, Vector2d(trooper.getX(), trooper.getY()));
					if (min > d){
						min = d;
						approximate = tmp;
					}
				}
				gMainDst = processApproximate(w, approximate);
			}
			else if (isActionAvailable(trooper, model::REQUEST_ENEMY_DISPOSITION)){
				std::list<ActionChunk> c;
				ActionChunk chunk(model::REQUEST_ENEMY_DISPOSITION, Vector2d(-1, -1));
				c.push_back(chunk);
				ActionChain *new_chain = new ActionChain();
				new_chain->executor = &trooper;
				new_chain->chain = c;
				res_chains.push_back(new_chain);
				
			}
		}
	}

	if (tactics.end() != std::find(tactics.begin(), tactics.end(), Tactician::MOVE) && 
		isActionAvailable(trooper, model::MOVE))
	{
		do{

			if (trooper.getStance() != model::STANDING){
				std::list<ActionChunk> c;
				ActionChunk chunk(model::RAISE_STANCE, Vector2d(-1, -1));
				c.push_back(chunk);
				new_chain = new ActionChain();
				new_chain->executor = &trooper;
				new_chain->chain = c;
				if (isActionAvailable(trooper, model::RAISE_STANCE))
					res_chains.push_back(new_chain);
				break;
			}

			model::TrooperType Susanin_type = model::UNKNOWN_TROOPER;
			if (gMove_head.empty()){
				gMove_head.push_back(model::SOLDIER);
				gMove_head.push_back(model::COMMANDER);
				gMove_head.push_back(model::FIELD_MEDIC);
			}
			const model::Trooper *susanin = NULL;
			
			while(susanin == NULL){
				std::list<model::TrooperType>::iterator type_it = gMove_head.begin();
				for (; type_it != gMove_head.end() && susanin == NULL; ++type_it){
					std::vector<model::Trooper>::const_iterator tr_it = troopers.begin();
					for (; tr_it != troopers.end(); ++tr_it){
						if (tr_it->isTeammate() && tr_it->getType() == *type_it){
							susanin = &(*tr_it);
							break;
						}
					}
				}

				if (susanin == NULL){
					gMove_head.push_back(*(gMove_head.begin()));
					gMove_head.erase(gMove_head.begin());
				}

			}

			Vector2d dst = Vector2d(susanin->getX(), susanin->getY());
			Vector2d src(trooper.getX(), trooper.getY());
			if (isFirstMove){
				if (trooper.getDistanceTo(*susanin) == 0)
						gMediatorDst = findDest(w, dst);
				else
					gMediatorDst = findNearestFree(w, src, dst);
			}
			dst = gMediatorDst;

			PathFinder pf;
			std::list<Vector2d> path = pf.calcOptimalPath(w, src, dst);
			if (!path.empty()){
				path.pop_front();

				std::list<Vector2d>::iterator it = path.begin();

				std::list<ActionChunk> c;

				for (; it != path.end(); ++it){
					if (!PathFinder::isTropperInCell(w, *it)){//TODO: eliminate
						ActionChunk chunk(model::MOVE, *it);
						c.push_back(chunk);
					}
				}
				new_chain = new ActionChain();
				new_chain->executor = &trooper;
				new_chain->chain = c;
				if (isActionAvailable(trooper, model::MOVE))
					res_chains.push_back(new_chain);
			}
			else if (susanin->getDistanceTo(trooper) == 0){//try to change susanin
				gMove_head.push_back(*(gMove_head.begin()));
				gMove_head.erase(gMove_head.begin());
			}
		}while(0);
	}


	return res_chains;

}