#include "Strategy_CombatTaskManager.h"

using namespace MyBot;

Strategy_CombatTaskManager & Strategy_CombatTaskManager::Instance()
{
	static Strategy_CombatTaskManager instance;

	return instance;
}

void Strategy_CombatTaskManager::update()
{
	// 1초에 6번만 실행
	//if (BWAPI::Broodwar->getFrameCount() % 4 != 0) {
	//	return;
	//}

	bool isToFindError = false;

	if (isToFindError) std::cout << "<a";

	updateUnitCount();

	int mutaliskCount = 0;
	mainCombatMutaliskSquadCenterPosition.x = 0;
	mainCombatMutaliskSquadCenterPosition.y = 0;
	for (auto & unit : StrategyManager::Instance().mainCombatMutaliskSquad.unitset) {
		if (unit->canAttack()) {
			mainCombatMutaliskSquadCenterPosition.x += unit->getPosition().x;
			mainCombatMutaliskSquadCenterPosition.y += unit->getPosition().y;
			mutaliskCount++;
		}
	}
	if (mutaliskCount > 0) {
		mainCombatMutaliskSquadCenterPosition.x /= mutaliskCount;
		mainCombatMutaliskSquadCenterPosition.y /= mutaliskCount;
	}

	for (auto it = attackerTargetMap.begin(); it != attackerTargetMap.end();) {

		BWAPI::Unit attacker = it->first;
		BWAPI::Unit targetUnit = it->second;

		if (attacker == nullptr || attacker->exists() == false || attacker->getHitPoints() <= 0
			|| targetUnit == nullptr || targetUnit->exists() == false || targetUnit->getHitPoints() <= 0)
		{
			//std::cout << " eraseTask " << StrategicTaskUtil::getTaskGoalTypeString(targetTask.taskGoal).c_str() << std::endl;
			it = attackerTargetMap.erase(it);
			return;
		}
		else {
			++it;
		}
	}
	
	if (isToFindError) std::cout << "b";

	// mainBaseDefenseSquad 가 할일이 없으면 근처 점령지역에 있게 한다
	if (StrategyManager::Instance().mainBaseDefenseSquad.unitset.size() >= 1) {

		for (auto & unit : StrategyManager::Instance().mainBaseDefenseSquad.unitset) {
			Mission* unitMission = StrategyManager::Instance().mainBaseDefenseSquad.getUnitMission(unit);
			if (unitMission->missionType == MissionType::Mission_Undefined)
			{
				// 앞마당까지만 먹었으면 앞마당에
				if (InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer).size() == 2) 
				{
					StrategyManager::Instance().mainBaseDefenseSquad.setUnitMission(unit, Mission(MissionType::AttackMove, StrategyManager::Instance().myFirstExpansionBaseLocation->getPosition()));
				}
				// 앞마당을 안먹었거나, 3개이상 먹었으면 가까운 점령지역에 있게 한다
				else {
					double minDistance = 100000000;
					double tempDistance = 0;
					BWAPI::Position targetPosition;
					for (BWTA::BaseLocation * baseLocation : InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer)) {
						tempDistance = unit->getDistance(baseLocation->getPosition());
						if (minDistance > tempDistance) {
							minDistance = tempDistance;
							targetPosition = baseLocation->getPosition();
							StrategyManager::Instance().mainBaseDefenseSquad.setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
						}
					}
				}
			}
		}
	}
	if (isToFindError) std::cout << "c";

	// 가장 우선적인 것은 방어
	if (StrategyManager::Instance().taskList.find(StrategicTask(Attack_Enemy_Worker_In_Main_Region)) != StrategyManager::Instance().taskList.end())
	{
		attackEnemyWorkerUnitInMainRegion();
	}

	if (isToFindError) std::cout << "d";
	if (StrategyManager::Instance().taskList.find(StrategicTask(Attack_Enemy_Dangerous_Building_In_Main_Region)) != StrategyManager::Instance().taskList.end())
	{
		attackEnemyBuildingUnitInMainRegion();
	}
	if (isToFindError) std::cout << "e";

	if (StrategyManager::Instance().taskList.find(StrategicTask(Attack_Enemy_Ground_Unit_In_Our_Region)) != StrategyManager::Instance().taskList.end())
	{
		attackEnemyGroundUnitInOurRegion();
	}
	if (isToFindError) std::cout << "f";

	if (StrategyManager::Instance().taskList.find(StrategicTask(Block_And_Hold_On_ChokePoint)) != StrategyManager::Instance().taskList.end())
	{
		blockAndHoldOnChokePoint();
	}
	if (isToFindError) std::cout << "g";

	// 매복 럴커부대로 매복
	if (StrategyManager::Instance().taskList.find(StrategicTask(Burrow_And_Ambush_Attack_With_Lurker)) != StrategyManager::Instance().taskList.end())
	{
		burrowAndAmbushAttackWithLurker();
	}
	if (isToFindError) std::cout << "i0";

	// 지상군으로 적 공격
	if (StrategyManager::Instance().taskList.find(StrategicTask(Attack_Enemy_BaseLocation_With_Early_Zergling_Unit)) != StrategyManager::Instance().taskList.end())
	{
		attackEnemyWithEarlyZerglingSquad();
	}
	if (isToFindError) std::cout << "i1";

	// 지상군으로 적 공격
	if (StrategyManager::Instance().taskList.find(StrategicTask(Attack_Enemy_BaseLocation_With_Ground_Unit)) != StrategyManager::Instance().taskList.end())
	{
		attackEnemyWithMainCombatGroundSquad();	
	}
	if (isToFindError) std::cout << "i2";

	// 뮤탈로 적 공격
	if (StrategyManager::Instance().taskList.find(StrategicTask(Attack_Enemy_BaseLocation_With_Mutalisk)) != StrategyManager::Instance().taskList.end())
	{
		attackEnemyWithMainCombatMutaliskSquad();
	}
	if (isToFindError) std::cout << "i3";

	// 럴커 드랍
	if (StrategyManager::Instance().taskList.find(StrategicTask(Attack_With_Lurker_Drop)) != StrategyManager::Instance().taskList.end())
	{
		attackWithLurkerDrop();
	}
	if (isToFindError) std::cout << "h";

	// 엘리미네이트 시키기
	if (StrategyManager::Instance().taskList.find(StrategicTask(Eliminate_Enemy_Player)) != StrategyManager::Instance().taskList.end())
	{
		executeEnemyElimination();
	}
	if (isToFindError) std::cout << "j";


	// 임무 미지정 되어있는 / 임무 해제된 일꾼 컨트롤
	// 적 정찰일꾼 쫓아 너무 멀리까지 안가도록 한다
	/*
	if (StrategyManager::Instance().reservedSquad.unitset.size() > 0) {

		Squad* currentSquad = &StrategyManager::Instance().reservedSquad;

		for (auto & unit : currentSquad->unitset) {

			if (unit->getType() == BWAPI::UnitTypes::Zerg_Drone) {
				
				bool isTooFarFromBaseLocation = true;
				for (auto baselocation : InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer)) {
					if (unit->getDistance(baselocation->getPosition()) < 50 * TILE_SIZE) {
						isTooFarFromBaseLocation = false;
						break;
					}
				}
				
				if (isTooFarFromBaseLocation) {
					WorkerManager::Instance().setIdleWorker(unit);
				}
			}
		}
	}
	*/


	/*
	// mainCombatMutaliskSquad 가 존재하면
	if (StrategyManager::Instance().mainCombatMutaliskSquad.unitset.size() >= 1) {

		// 기본적으로 mainCombatMutaliskSquad 자체적으로 똘똘 뭉쳐놓는다
		for (auto & unit : StrategyManager::Instance().mainCombatMutaliskSquad.unitset) {

			// TODO : 적군 본진 근처 바다 한가운데 뭉쳐놓는 것도 좋을듯
			Mission* unitMission = StrategyManager::Instance().mainCombatMutaliskSquad.getUnitMission(unit);
			if (unit->getDistance(mainCombatMutaliskSquadCenterPosition) > 1 * TILE_SIZE)
			{
				StrategyManager::Instance().mainCombatMutaliskSquad.setUnitMission(unit,
					Mission(MissionType::MovePoint, mainCombatMutaliskSquadCenterPosition));
			}
		}
	}
	*/

	// mainCombatMutaliskSquad 가 존재하면
	if (StrategyManager::Instance().mainCombatMutaliskSquad.unitset.size() >= 1) {

		// reinforceMainCombatMutaliskSquad 숫자가 너무 적으면 mainCombatMutaliskSquad 으로 move 시키기보다 자체적으로 뭉치게 한다?
		//if (StrategyManager::Instance().reinforceMainCombatMutaliskSquad.unitset.size() <= 3) {
		//	for (auto & unit : StrategyManager::Instance().reinforceMainCombatMutaliskSquad.unitset) {
		//		StrategyManager::Instance().reinforceMainCombatMutaliskSquad.setUnitMission(unit,
		//			Mission(MissionType::MovePoint, StrategyManager::Instance().reinforceMainCombatMutaliskSquad.unitset.getPosition()));
		//	}
		//}
		// reinforceMainCombatMutaliskSquad 를 mainCombatMutaliskSquad 으로 move 시켜 합류시킨다
		// 문제 : mainCombatMutaliskSquad 가 멀리 떨어져있으면, reinforceMainCombatMutaliskSquad 는 mainCombatMutaliskSquad 에게 합류하는것 만이 최우선 목표가 되고,
		// 합류하기 전에는 방어나, 멀티 지원, 아무것도 못한다
		//else 
		{
			for (auto & unit : StrategyManager::Instance().reinforceMainCombatMutaliskSquad.unitset) {
				StrategyManager::Instance().reinforceMainCombatMutaliskSquad.setUnitMission(unit,
					Mission(MissionType::MovePoint, mainCombatMutaliskSquadCenterPosition));
			}
		}
	}


	// 실제 실행
	StrategyManager::Instance().mainCombatZerglingSquad.executeMission();		///< 메인 공격 저글링 부대 : 본진 / 앞마당 공격
	StrategyManager::Instance().mainCombatHydraliskSquad.executeMission();		///< 메인 공격 히드라 부대 : 본진 / 앞마당 공격
	StrategyManager::Instance().mainCombatLurkerSquad.executeMission();		///< 메인 공격 럴커 부대 : 본진 / 앞마당 공격
	StrategyManager::Instance().mainCombatMutaliskSquad.executeMission();		///< 메인 공격 뮤탈/디바우어러/가디언 부대 : 본진 / 앞마당 공격
	StrategyManager::Instance().mainCombatScourgeSquad.executeMission();		///< 메인 공격 스커지 부대 : 본진 / 앞마당 공격
	StrategyManager::Instance().mainCombatOverlordSquad.executeMission();		///< 메인 공격 오버로드 부대 : 오버로드
	StrategyManager::Instance().mainCombatQueenSquad.executeMission();			///< 메인 공격 퀸 부대 : 퀸
	StrategyManager::Instance().mainCombatDefilerSquad.executeMission();		///< 메인 공격 디파일러 부대 : 디파일러, 먹이용 저글링, 전담 오버로드들
	StrategyManager::Instance().mainCombatUltraliskSquad.executeMission();		///< 메인 공격 울트라 부대 : 본진 / 앞마당 공격

	StrategyManager::Instance().reinforceMainCombatMutaliskSquad.executeMission();		///< 메인 공격 뮤탈 증원 부대

	StrategyManager::Instance().subCombatSquad.executeMission();				///< 서브 공격 부대 : 멀티 공격
	StrategyManager::Instance().subCombatOverlordSquad.executeMission();		///< 서브 공격 지원 부대 : 오버로드. 

	StrategyManager::Instance().subCombatReinforceSquad.executeMission();		///< 서브 증원 부대

	StrategyManager::Instance().dropAttackSquad.executeMission();				///< 드랍부대 : 히드라, 럴커. 전담 오버로드
	StrategyManager::Instance().ambushCombatLurkerSquad.executeMission();		///< 매복부대 : 럴커. 전담 오버로드
	StrategyManager::Instance().multiObstructLurkerSquad.executeMission();		///< 매복부대 : 럴커. 전담 오버로드
	if (isToFindError) std::cout << "k";

	StrategyManager::Instance().mainBaseDefenseSquad.executeMission();			///< 주력 방어 부대 : 저글링, 히드라, 러커, 뮤탈

	StrategyManager::Instance().mainBaseClearSquad1.executeMission();			///< 본진에 들어온 적 정찰유닛 등을 긴급공격하는 부대 : 저글링, 일꾼 등
	StrategyManager::Instance().mainBaseClearSquad2.executeMission();			///< 본진에 들어온 적 벙커 등을 긴급공격하는 부대 : 저글링, 일꾼 등
	StrategyManager::Instance().mainChokepointBlockingSquad.executeMission();
	StrategyManager::Instance().mainBasePatrolSquad.executeMission();			///< 본진 주변 패트롤 부대 : 저글링, 스커지, 오버로드

	StrategyManager::Instance().firstExpansionDefenseSquad.executeMission();	///< 앞마당 방어 부대 : 히드라, 뮤탈
	StrategyManager::Instance().firstExpansionPatrolSquad.executeMission();	///< 앞마당 주변 패트롤 부대 : 저글링, 스커지, 오버로드

	StrategyManager::Instance().secondExpansionDefenseSquad.executeMission();	///< 멀티 방어 부대 : 히드라, 뮤탈
	StrategyManager::Instance().secondExpansionPatrolSquad.executeMission();	///< 멀티 주변 패트롤 부대 : 저글링, 스커지, 오버로드
	if (isToFindError) std::cout << "l";

	/*
	if (getMainCombatUnitCount() <= 4) {
	insertTask(StrategicTask(TaskGoalType::Block_And_Hold_On_ChokePoint, BWAPI::UnitTypes::None, BWAPI::TechTypes::None, BWAPI::UpgradeTypes::None, nullptr,
	InformationManager::Instance().getSecondChokePoint(InformationManager::Instance().selfPlayer)->getCenter(), 0));
	}
	*/
}

void Strategy_CombatTaskManager::attackEnemyWorkerUnitInMainRegion()
{
	Squad* mySquad = &StrategyManager::Instance().mainBaseClearSquad1;

	// HitPoint 가 닳은 유닛은 철수시킨다
	BWAPI::Unit unitToRemove = nullptr;
	for (auto & unit : mySquad->unitset) {
		if (unit->getHitPoints() < unit->getType().maxHitPoints() * 0.3) {
			unitToRemove = unit;
			break;
		}
	}
	if (unitToRemove != nullptr) {
		CommandUtil::move(unitToRemove, StrategyManager::Instance().myMainBaseLocation->getPosition());
		StrategyManager::Instance().moveUnitBetweenSquad(mySquad, &StrategyManager::Instance().reservedSquad, unitToRemove->getType(), 1, unitToRemove);
	}


	for (auto & unit : mySquad->unitset) {

		bool isIdleUnit = true;

		for (auto & iterator : mySquad->unitTargetMap) {
			if (iterator.first == unit) {
				isIdleUnit = false;
				break;
			}
		}

		// 아군 유닛에게 타겟이 지정안되어있으면 지정한다
		if (isIdleUnit) {

			// 적 정찰 일꾼 
			for (auto & enemyUnit : BWAPI::Broodwar->enemy()->getUnits()) {

				if (enemyUnit != nullptr && enemyUnit->exists() && enemyUnit->getHitPoints() > 0 && enemyUnit->getType().isWorker()) {

					if (BWTA::getRegion(enemyUnit->getPosition()) == StrategyManager::Instance().myMainBaseLocation->getRegion()
						|| BWTA::getRegion(enemyUnit->getPosition()) == StrategyManager::Instance().myFirstExpansionBaseLocation->getRegion())
					{
						mySquad->unitTargetMap[unit] = enemyUnit;
						mySquad->setUnitMission(unit, Mission(MissionType::AttackMove, enemyUnit->getPosition()));
						break;
					}
				}
			}
		}
		// 아군 유닛에게 타겟이 지정되어있으면 공격지시한다
		// TODO : 적 정찰 일꾼이 끊임없이 도망치기 때문에, 잘 몰아서 죽여야 한다
		else {
			BWAPI::Unit enemyUnit = mySquad->unitTargetMap[unit];
			if (enemyUnit != nullptr ) {

				// 적 정찰 일꾼이 시야 내에 존재하면
				if (enemyUnit->exists()) {
					mySquad->setUnitMission(unit, Mission(MissionType::Attack, enemyUnit));
				}
				// 적 정찰 일꾼이 시야 내에 존재하지않으면
				else {
					for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer)) {
						BWAPI::Unit enemyUnit = it.first;
						UnitInfo & enemyUnitInfo = it.second;

						mySquad->setUnitMission(unit, Mission(MissionType::AttackMove, enemyUnitInfo.lastPosition));
					}
				}
			}

		}
	}
}

void Strategy_CombatTaskManager::attackEnemyBuildingUnitInMainRegion()
{
	Squad* mySquad = &StrategyManager::Instance().mainBaseClearSquad2;

	// HitPoint 가 닳은 유닛은 철수시킨다
	BWAPI::Unit unitToRemove = nullptr;
	for (auto & unit : mySquad->unitset) {
		if (unit->getHitPoints() < unit->getType().maxHitPoints() * 0.3) {
			unitToRemove = unit;
			break;
		}
	}
	if (unitToRemove != nullptr) {
		CommandUtil::move(unitToRemove, StrategyManager::Instance().myMainBaseLocation->getPosition());
		StrategyManager::Instance().moveUnitBetweenSquad(mySquad, &StrategyManager::Instance().reservedSquad, unitToRemove->getType(), 1, unitToRemove);
	}


	BWAPI::Unit targetEnemyWorker = nullptr;
	BWAPI::Unit targetEnemyMarine = nullptr;
	BWAPI::Unit targetEnemyBuildingToAttackFirst = nullptr;
	BWAPI::Unit targetEnemyBuildingToAttackSecond = nullptr;
	int enemyBuildingCount = 0;

	for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer)) {
		BWAPI::Unit enemyUnit = it.first;
		UnitInfo & enemyUnitInfo = it.second;

		if (BWTA::getRegion(enemyUnitInfo.lastPosition) == StrategyManager::Instance().myMainBaseLocation->getRegion()
			|| BWTA::getRegion(enemyUnitInfo.lastPosition) == StrategyManager::Instance().myFirstExpansionBaseLocation->getRegion())
		{
			if (enemyUnitInfo.lastHealth > 0 && enemyUnitInfo.isLastPositionValid == true && enemyUnit != nullptr && enemyUnit->exists()) {

				if (enemyUnitInfo.type.isWorker()) {
					targetEnemyWorker = enemyUnit;
				}
				else if (enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Marine) {
					targetEnemyMarine = enemyUnit;
				}
				else if (enemyUnitInfo.type.isBuilding()) {
					if (enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Bunker
						|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Pylon
						|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Creep_Colony
						|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Nydus_Canal)
					{
						targetEnemyBuildingToAttackFirst = enemyUnit;
						enemyBuildingCount++;
					}
					else if (enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Photon_Cannon
						|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Sunken_Colony
						|| enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Refinery
						|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Assimilator
						|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Extractor)
					{
						targetEnemyBuildingToAttackSecond = enemyUnit;
						enemyBuildingCount++;
					}
				}				
			}
		}
	}

	for (auto & unit : mySquad->unitset) {
		Mission* unitMission = mySquad->getUnitMission(unit);

		if (targetEnemyBuildingToAttackFirst != nullptr) {

			// targetEnemyBuildingToAttackFirst 가 아직 건설 중인 경우
			if (targetEnemyBuildingToAttackFirst->isCompleted() == false) {

				// 테란이면 건설 일꾼 먼저 죽이고, 마린을 먼저 죽인다
				if (targetEnemyBuildingToAttackFirst->getType().getRace() == BWAPI::Races::Terran) {
					if (targetEnemyWorker != nullptr && targetEnemyWorker->exists()) {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyWorker));
					}
					else if (targetEnemyMarine != nullptr && targetEnemyMarine->exists()) {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyMarine));
					}
					else {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackFirst));
					}
				}
				// 프로토스
				else if (targetEnemyBuildingToAttackFirst->getType().getRace() == BWAPI::Races::Protoss) {

					if (targetEnemyWorker != nullptr && targetEnemyWorker->exists() && unit->getDistance(targetEnemyWorker->getPosition()) < 1 * TILE_SIZE) {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyWorker));
					}
					else {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackFirst));
					}
				}
				// 저그
				else {
					mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackFirst));
				}
			}
			// targetEnemyBuildingToAttackFirst 가 건설 완료 되었으면
			else {
				// 테란이면 건설 일꾼 먼저 죽이고, 마린을 먼저 죽인다
				if (targetEnemyBuildingToAttackFirst->getType().getRace() == BWAPI::Races::Terran) {
					if (targetEnemyWorker != nullptr && targetEnemyWorker->exists()) {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyWorker));
					}
					else if (targetEnemyMarine != nullptr && targetEnemyMarine->exists()) {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyMarine));
					}
					else {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackFirst));
					}
				}
				// 프로토스
				else if (targetEnemyBuildingToAttackFirst->getType().getRace() == BWAPI::Races::Protoss) {

					if (targetEnemyWorker != nullptr && targetEnemyWorker->exists() && unit->getDistance(targetEnemyWorker->getPosition()) < 1 * TILE_SIZE) {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyWorker));
					}
					else if (targetEnemyBuildingToAttackSecond != nullptr && targetEnemyBuildingToAttackSecond->exists()) {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackSecond));
					}
					else {
						mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackFirst));
					}
				}
				// 저그
				else {
					mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackFirst));
				}
			}
		}
		else if (targetEnemyBuildingToAttackSecond != nullptr) {

			// 테란이면 건설 일꾼 먼저 죽인다
			if (targetEnemyBuildingToAttackSecond->getType().getRace() == BWAPI::Races::Terran) {
				if (targetEnemyWorker != nullptr && targetEnemyWorker->exists()) {
					mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyWorker));
				}
				else {
					mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackSecond));
				}
			}
			// 프로토스
			else if (targetEnemyBuildingToAttackSecond->getType().getRace() == BWAPI::Races::Protoss) {

				if (targetEnemyWorker != nullptr && targetEnemyWorker->exists() && unit->getDistance(targetEnemyWorker->getPosition()) < 1 * TILE_SIZE) {
					mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyWorker));
				}
				else {
					mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackSecond));
				}
			}
			// 저그
			else {
				mySquad->setUnitMission(unit, Mission(MissionType::Attack, targetEnemyBuildingToAttackSecond));
			}
		}
	}
}

void Strategy_CombatTaskManager::attackEnemyGroundUnitInOurRegion()
{
	Mission* unitMission;
	Squad* mySquad = &StrategyManager::Instance().mainBaseDefenseSquad;

	if (mySquad->unitset.size() > 0) {

		int nonWorkerCountAroundMainBase = 0;
		for (auto & unit : mySquad->unitset) {

			if (unit == nullptr) {
				std::cout << "my unit is dead1" << std::endl;
				continue;
			}

			// 아군 본진 주위 방어 전투유닛 숫자 카운트
			if (unit->getType().isWorker() == false 
				&& unit->getDistance(StrategyManager::Instance().myMainBaseLocation->getPosition()) < 5 * TILE_SIZE) {
				nonWorkerCountAroundMainBase++;
			}
		}
		

		for (auto & unit : mySquad->unitset) {

			if (unit == nullptr) {
				std::cout << "my unit is dead2" << std::endl;
				continue;
			}

			unitMission = mySquad->getUnitMission(unit);

			for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer)) {
				BWAPI::Unit enemyUnit = it.first;
				UnitInfo & enemyUnitInfo = it.second;

				if (enemyUnit == nullptr) {
					std::cout << "enemyUnit is null1" << std::endl;
					continue;
				}

				// 본진, 앞마당 뿐만 아니라 전체 점령 지역에 대해 방어
				for (BWTA::BaseLocation* myBaseLocationToDefense : InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer)) {
					if (myBaseLocationToDefense->getPosition().getDistance(enemyUnitInfo.lastPosition) < 8 * TILE_SIZE) {
					
						int mySunkenCount = 0;
						int mySunkenIsAttacked = false;

						// TODO : filter
						for (auto & sunken : BWAPI::Broodwar->getUnitsInRadius(myBaseLocationToDefense->getPosition(), 8 * TILE_SIZE)) {
						
							if (sunken == nullptr) {
								std::cout << "sunken is null1" << std::endl;
								continue;
							}

							if (sunken->getPlayer() == InformationManager::Instance().selfPlayer
								&& (sunken->getType() == BWAPI::UnitTypes::Zerg_Sunken_Colony
									|| sunken->getType() == BWAPI::UnitTypes::Zerg_Creep_Colony)) 
							{
								mySunkenCount++;
								if (sunken->isCompleted() ) {
									if (sunken->getHitPoints() < sunken->getType().maxHitPoints()) {
										mySunkenIsAttacked = true;
									}
								}
								else {
									for (auto & enemyUnitAroundSunken : BWAPI::Broodwar->getUnitsInRadius(sunken->getPosition(), 2 * TILE_SIZE)) {
										if (enemyUnitAroundSunken == nullptr) {
											std::cout << "enemyUnitAroundSunken is null1" << std::endl;
											continue;
										}

										if (enemyUnitAroundSunken->getPlayer() != InformationManager::Instance().selfPlayer) {
											mySunkenIsAttacked = true;
										}
									}
								}

							}
						}
						
						// TODO : region 경계에서 공격하는 적도 공격
						//if (BWTA::getRegion(enemyUnitInfo.lastPosition) == myRegion) {
						if (true) {
							
							// 전투 유닛은 공격							
							if (unit->getType().isWorker() == false) {

								if (unit->getType() == BWAPI::UnitTypes::Zerg_Zergling
									|| unit->getType() == BWAPI::UnitTypes::Zerg_Hydralisk
									|| unit->getType() == BWAPI::UnitTypes::Zerg_Mutalisk ) 
								{
									// 성큰이 없거나, 성큰이 공격 받을때 공격
									if (mySunkenCount == 0) {
										mySquad->setUnitMission(unit, Mission(MissionType::AttackMove, enemyUnitInfo.lastPosition));
									}
									else if (mySunkenIsAttacked) {
										mySquad->setUnitMission(unit, Mission(MissionType::AttackMove, enemyUnitInfo.lastPosition));
									}
									else {
										mySquad->setUnitMission(unit, Mission(MissionType::Move, myBaseLocationToDefense->getPosition()));
									}
								}
								else if (unit->getType() == BWAPI::UnitTypes::Zerg_Lurker) {
									mySquad->setUnitMission(unit, Mission(MissionType::AttackMove, myBaseLocationToDefense->getPosition()));
								}
							}							
							// 일꾼은 버로우 하거나 도망간다
							else {
								if (nonWorkerCountAroundMainBase == 0) {
									if (unit->canBurrow()) {
										unit->burrow();
									}
									else {
										// TODO : 안전한 장소를 찾아 도망치게 한다
										//BWAPI::Position targetPosition = StrategyManager::Instance().myMainBaseLocation->getPosition();
										//targetPosition.x += rand() % 15 * TILE_SIZE - 10 * TILE_SIZE;
										//targetPosition.y += rand() % 15 * TILE_SIZE - 10 * TILE_SIZE;

										//mySquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
									}
								}
							}

						}
					}
				}
			}


		}
	}
}

void Strategy_CombatTaskManager::blockAndHoldOnChokePoint()
{
	Squad* mySquad = &StrategyManager::Instance().mainChokepointBlockingSquad;
	Mission* unitMission;

	// mainChokepointBlockingSquad 로 방어

	// 첫번째 길목 방어

	if (StrategyManager::Instance().lastFrameOfConstructHatcheryOnFirstExpansion == 0
		|| StrategyManager::Instance().lastFrameOfConstructHatcheryOnFirstExpansion + 24 * 60 * 1 < BWAPI::Broodwar->getFrameCount()
		|| StrategyManager::Instance().lastFrameOfConstructCreepColonyOnFirstExpansion + 24 * 60 * 1 < BWAPI::Broodwar->getFrameCount())
	{
		BWTA::Chokepoint * targetChokepoint = StrategyManager::Instance().myFirstChokepoint;

		auto & sidePositions = targetChokepoint->getSides();
		BWAPI::Position left = sidePositions.first;
		BWAPI::Position right = sidePositions.second;

		double chokepointWidth = left.getDistance(right);

		int neededUnitCount = (int)(chokepointWidth / 20);


		if (mySquad->unitset.size() > 0) {

			std::vector<BWAPI::Position> targetPositions;

			// 더 적게 있는 경우
			int divideNumber = neededUnitCount;
			if ((int)(mySquad->unitset.size()) < neededUnitCount) {
				divideNumber = (int)(mySquad->unitset.size());
			}

			// 4마리 필요하면, 5등분
			double gapX = (right.x - left.x) / (neededUnitCount + 1);
			double gapY = (right.y - left.y) / (neededUnitCount + 1);

			for (int i = 0; i < neededUnitCount; i++) {
				targetPositions.push_back(BWAPI::Position((int)(left.x + gapX * i), (int)(left.y + gapY * i)));
			}

			// TODO : 길목보다는 언덕 위 넓은 곳에 학익진 형태로 있는것이 유리
			int unitIndex = 0;
			for (auto it = mySquad->unitset.begin(); it != mySquad->unitset.end(); it++) {

				unitMission = mySquad->getUnitMission(*it);
				if (unitMission->missionType == MissionType::Mission_Undefined) {
					mySquad->setUnitMission(*it, Mission(MissionType::AttackMove, targetPositions[unitIndex]));
					unitIndex++;
					if (unitIndex == neededUnitCount) {
						break;
					}
				}
			}
		}
	}
	// 일단, 길목 주위를 왔다갔다한다
	else {

		BWTA::Chokepoint * targetChokepoint = StrategyManager::Instance().myFirstChokepoint;

		BWAPI::Position targetPosition = targetChokepoint->getCenter();
		targetPosition.x += (rand() % 6) * TILE_SIZE - 3 * TILE_SIZE;

		for (auto it = mySquad->unitset.begin(); it != mySquad->unitset.end(); it++) {

			unitMission = mySquad->getUnitMission(*it);
			if (unitMission->missionType == MissionType::Mission_Undefined) {
				mySquad->setUnitMission(*it, Mission(MissionType::AttackMove, targetPosition));
			}
		}

	}
}

void Strategy_CombatTaskManager::defensePositionWithHydralisk() {

	Mission* unitMission;

	Squad* currentSquad = &StrategyManager::Instance().mainBaseDefenseSquad;
	if (currentSquad->unitset.size() > 0) {

		for (auto & unit : currentSquad->unitset) {

			unitMission = currentSquad->getUnitMission(unit);

			for (auto & chokepoint : StrategyManager::Instance().frontlineChokepointList) {

				// 여러개일 경우 적절히 분산
				if (rand() % 2 == 0) {
					continue;
				}

				if (unitMission->missionType == Mission_Undefined) {
					BWTA::Chokepoint * targetChokepoint = chokepoint;
					if (targetChokepoint != nullptr) {
						currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetChokepoint->getCenter()));
					}
				}
			}
		}
	}
}


void Strategy_CombatTaskManager::attackWithLurkerDrop()
{
	Mission* unitMission;

	Squad* currentSquad = &StrategyManager::Instance().mainCombatLurkerSquad;
	if (currentSquad->unitset.size() > 0) {

		for (auto & unit : currentSquad->unitset) {

			unitMission = currentSquad->getUnitMission(unit);
			BWAPI::Position targetPosition = BWAPI::Positions::None;

			double maxDistance = 0;
			double tempDistance = 0;
			for (auto & sunken : BWAPI::Broodwar->self()->getUnits()) {
				if (sunken == nullptr || sunken->exists() == false) continue;

				if (sunken->getType() == BWAPI::UnitTypes::Zerg_Sunken_Colony) {
					tempDistance = StrategyManager::Instance().myFirstExpansionBaseLocation->getPosition().getDistance(sunken->getPosition());
					if (maxDistance < tempDistance) {
						maxDistance = tempDistance;
						targetPosition = sunken->getPosition();
					}
				}
			}

			if (targetPosition == BWAPI::Positions::None)  {
				for (auto & chokepoint : StrategyManager::Instance().frontlineChokepointList) {
					tempDistance = StrategyManager::Instance().myFirstExpansionBaseLocation->getPosition().getDistance(chokepoint->getCenter());
					if (maxDistance < tempDistance) {
						maxDistance = tempDistance;
						targetPosition = chokepoint->getCenter();
					}
				}
			}

			if (targetPosition != BWAPI::Positions::None)  {
				currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
			}
		}
	}
}

void Strategy_CombatTaskManager::burrowAndAmbushAttackWithLurker()
{
	Mission* unitMission;

	Squad* currentSquad = &StrategyManager::Instance().ambushCombatLurkerSquad;
	if (currentSquad->unitset.size() > 0) {

		for (auto & unit : currentSquad->unitset) {

			unitMission = currentSquad->getUnitMission(unit);

			// 아군 지역에서 적군 frontlone 으로 가는 경로에서, 가급적이면 좁은 길목을 찾아서 버로우 해 있는다
			BWAPI::Position targetPosition = StrategyManager::Instance().enemyFirstExpansionBaseLocation->getPosition();

			std::list<BWTA::Chokepoint*> chokepointList = BWTA::getShortestPath2(
				BWAPI::TilePosition(StrategyManager::Instance().frontlinePosition.x / TILE_SIZE, StrategyManager::Instance().frontlinePosition.y / TILE_SIZE),
				BWAPI::TilePosition(targetPosition));

			while (chokepointList.size() > 2) {
				chokepointList.pop_front();
			}
			BWTA::Chokepoint* targetChokepoint = chokepointList.front();
			targetPosition = targetChokepoint->getCenter();
						
			if (targetPosition != BWAPI::Positions::None)  {
				currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
			}
		}
	}

}


void Strategy_CombatTaskManager::attackEnemyWithMainCombatMutaliskSquad()
{
	// 공격 대상 
	BWAPI::Position targetAttackPosition = BWAPI::Positions::None;
	bool isToAttackBaseLocation = false;

	Squad* currentSquad = &StrategyManager::Instance().mainCombatMutaliskSquad;

	// 뮤탈리스크 규모가 절대적으로 적을 때는 안전한 곳에 가있게 한다
	if (flyingState == FlyingState::moveToSafePosition) {

		//targetAttackPosition = StrategyManager::Instance().myMainBaseLocation->getPosition();
		targetAttackPosition = StrategyManager::Instance().getSafePosition(mainCombatMutaliskSquadCenterPosition);
		isToAttackBaseLocation = false;

		moveMutaliskSquad(targetAttackPosition, isToAttackBaseLocation);

		if (currentSquad->unitset.size() >= 8) {
			flyingState = FlyingState::searchForTarget;
		}
	}
	else {
		// 뮤탈 숫자가 많이 줄었으면, 다시 안전한 장소로 돌아간다
		if (currentSquad->unitset.size() < 4) {
			flyingState = FlyingState::moveToSafePosition;
		}
		else {

			// 공격해볼만한 적 BaseLocation 을 찾아본다
			/*
			BWTA::BaseLocation * targetBaseLocation = getWeakestEnemyBaseLocationForMutalisk();
			if (targetBaseLocation != nullptr) {
			targetAttackPosition = targetBaseLocation->getPosition();
			}
			else {
			// 공격해볼만한 적 유닛을 찾아본다
			targetAttackPosition = getTargetPositionInMapToAttackWithMutalisk();
			}
			*/
			targetAttackPosition = getTargetPositionToAttackWithMutalisk();
			isToAttackBaseLocation = false;

			// 공격할만한 적 유닛이 없으면
			if (targetAttackPosition == BWAPI::Positions::None) {

				// 적 앞마당을 안가본지 오래되었으면 가본다
				if (StrategyManager::Instance().enemyFirstExpansionBaseLocation != nullptr) {
					if (StrategyManager::Instance().baseLocationStatusMap[StrategyManager::Instance().enemyFirstExpansionBaseLocation].lastVisibleTime < 0
						|| BWAPI::Broodwar->getFrameCount() - StrategyManager::Instance().baseLocationStatusMap[StrategyManager::Instance().enemyFirstExpansionBaseLocation].lastVisibleTime >= 20 * 60 * 2)
					{
						targetAttackPosition = StrategyManager::Instance().enemyFirstExpansionBaseLocation->getPosition();
						isToAttackBaseLocation = true;
					}
				}
			}

			// TODO : 적 next 멀티를 안가본지 오래되었으면 가본다
				
			// 적 본진을 안가본지 오래되었으면 가본다
			if (targetAttackPosition == BWAPI::Positions::None) {
				if (StrategyManager::Instance().enemyMainBaseLocation != nullptr) {
					if (StrategyManager::Instance().baseLocationStatusMap[StrategyManager::Instance().enemyMainBaseLocation].lastVisibleTime < 0
						|| BWAPI::Broodwar->getFrameCount() - StrategyManager::Instance().baseLocationStatusMap[StrategyManager::Instance().enemyMainBaseLocation].lastVisibleTime >= 20 * 60 * 2)
					{
						targetAttackPosition = StrategyManager::Instance().enemyMainBaseLocation->getPosition();
						isToAttackBaseLocation = true;
					}
				}
			}
				
			// 공격할만한 곳이 없으면 안전한곳으로 가서 뮤탈 숫자를 더 모은다
			if (targetAttackPosition == BWAPI::Positions::None) {
				targetAttackPosition = StrategyManager::Instance().getSafePosition(mainCombatMutaliskSquadCenterPosition);
				isToAttackBaseLocation = false;
			}

			BWAPI::Broodwar->drawCircleMap(targetAttackPosition, 1 * TILE_SIZE, BWAPI::Colors::Red);
			BWAPI::Broodwar->drawCircleMap(targetAttackPosition, 3 * TILE_SIZE, BWAPI::Colors::Red);
			BWAPI::Broodwar->drawCircleMap(targetAttackPosition, 5 * TILE_SIZE, BWAPI::Colors::Red);


			moveMutaliskSquad(targetAttackPosition, isToAttackBaseLocation);
		}
	}
}

void Strategy_CombatTaskManager::attackEnemyWithEarlyZerglingSquad()
{
	Squad* currentSquad = &StrategyManager::Instance().mainCombatZerglingSquad;
	if (currentSquad->unitset.size() == 0) {
		return;
	}

	BWTA::BaseLocation * enemyMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer);
	if (enemyMainBaseLocation == nullptr) {
		return;
	}	
	
	// 저글링으로 절대 못이길 상황이면 후퇴 : 적 고급 유닛이 많이 나온 경우
	// TODO : 저글링을 우회해서 들어가서 일꾼을 몇명이라도 죽이거나
	// 혹은 아군 본진 근처 맵 중앙 쪽으로 보내서 적 유닛이 함부로 못 들어오도록 해야함
	if (isImpossibleToWinTheCombat()) {
		for (auto & unit : currentSquad->unitset) {
			currentSquad->setUnitMission(unit, Mission(MissionType::Move, StrategyManager::Instance().myFirstExpansionBaseLocation->getPosition()));
		}
	}
	// 저글링으로 싸워볼만하면 공격
	else {
		BWAPI::Unit enemyUnitAroundEnemyChokepointClosestToOurBase = getEnemyUnitAroundEnemyChokepointClosestToEnemyFirstExpansionLocation();
		BWAPI::Unit mostUrgentTarget = getMostUrgentEnemyUnit();

		BWAPI::Broodwar->drawCircleMap(StrategyManager::Instance().enemyFirstChokepoint->getCenter(), 4 * TILE_SIZE, BWAPI::Colors::Red);
		if (enemyUnitAroundEnemyChokepointClosestToOurBase != nullptr) {
			BWAPI::Broodwar->drawCircleMap(enemyUnitAroundEnemyChokepointClosestToOurBase->getPosition(), 1 * TILE_SIZE, BWAPI::Colors::Red);
		}
		if (mostUrgentTarget != nullptr) {
			BWAPI::Broodwar->drawCircleMap(mostUrgentTarget->getPosition(), 1 * TILE_SIZE, BWAPI::Colors::Yellow);
		}
		if (concentrationAttackTargetUnit != nullptr) {
			BWAPI::Broodwar->drawCircleMap(concentrationAttackTargetUnit->getPosition(), 1 * TILE_SIZE, BWAPI::Colors::Blue);
		}

		for (auto & unit : currentSquad->unitset) {

			if (unit == nullptr || unit->exists() == false || unit->getHitPoints() == 0 || unit->isCompleted() == false) continue;

			Mission* unitMission = currentSquad->getUnitMission(unit);
			bool hasOrderedNewMission = false;

			// 해당 저글링의 기존 타겟
			BWAPI::Unit targetUnit = nullptr;
			if (attackerTargetMap.find(unit) != attackerTargetMap.end()) {
				targetUnit = attackerTargetMap[unit];
			}

			// 기존 타겟을 곧 죽일 수 있는 때라면 끝까지 죽인다
			if (targetUnit != nullptr 
				&& targetUnit->getDistance(unit->getPosition()) < 32
				&& targetUnit->exists() 
				&& targetUnit->isFlying() == false
				&& targetUnit->getHitPoints() < targetUnit->getType().maxHitPoints() * 0.2)
			{
				currentSquad->setUnitMission(unit, Mission(MissionType::Attack, targetUnit));
				hasOrderedNewMission = true;
			}
			// 기존 타겟이 없거나, 아직 죽이려면 많이 남은 경우, 다른 타겟으로 바꿔야 하는지 검토한다
			else {

				// 적 길목을 아직 못봤다면 먼저 이동
				if (BWAPI::Broodwar->isExplored(BWAPI::TilePosition(StrategyManager::Instance().enemyFirstChokepoint->getCenter())) == false) {
					//std::cout << "Move to enemyFirstChokepoint ";
					//std::cout << " " << unit->getID() << " M F";
					currentSquad->setUnitMission(unit, Mission(MissionType::Move, StrategyManager::Instance().enemyFirstChokepoint->getCenter()));
					hasOrderedNewMission = true;
				}

				if (hasOrderedNewMission == false) {

					// 적 공격유닛이 극소수인 경우
					if (isEasyToKillEnemyCombatUnitsWithZergling() )
					{
						// 적 유닛/건물이 길목을 막고 있으면 그것을 먼저 공격
						if (enemyCombatUnitAroundEnemyChokepoint + enemyDefenseBuildingAroundEnemyBase
							+ enemyWorkerUnitAroundEnemyChokepoint >= 2) {

							if (enemyUnitAroundEnemyChokepointClosestToOurBase != nullptr && enemyUnitAroundEnemyChokepointClosestToOurBase->exists() && enemyUnitAroundEnemyChokepointClosestToOurBase->getHitPoints() > 0) {
								//std::cout << "Attack enemyUnitAroundEnemyChokepointClosestToOurBase" << std::endl;
								//std::cout << " " << unit->getID() << " A CH " << targetUnit->getType().getName().c_str() << " " << targetUnit->getID();
								currentSquad->setUnitMission(unit, Mission(MissionType::Attack, enemyUnitAroundEnemyChokepointClosestToOurBase));
								attackerTargetMap[unit] = nullptr;
								hasOrderedNewMission = true;
							}
							else {
								//std::cout << "AttackMove enemyFirstChokepoint" << std::endl;
								//std::cout << " " << unit->getID() << " AM CH";
								currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, StrategyManager::Instance().enemyFirstChokepoint->getCenter()));
								attackerTargetMap[unit] = nullptr;
								hasOrderedNewMission = true;
							}
						}
						// 적 일꾼이 길목을 막고있지 않다면, 
						else {
							// 적 본진 건물을 아직 못봤다면 먼저 이동
							if (BWAPI::Broodwar->isExplored(BWAPI::TilePosition(StrategyManager::Instance().enemyMainBaseLocation->getPosition())) == false) {
								//std::cout << "Move to enemyMainBaseLocation ";
								//std::cout << " " << unit->getID() << " M B";
								currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, StrategyManager::Instance().enemyMainBaseLocation->getPosition()));
								hasOrderedNewMission = true;
							}
						}

						// 적 길목막고있는 일꾼도 없고, 적 본진 건물도 이미 봤다면
						if (hasOrderedNewMission == false) {

							// 적 공격 유닛이 있으면, 집중 공격 대상을 하나 잡아서 집중공격
							if (enemyCombatUnitCount > 0) {

								if (concentrationAttackTargetUnit == nullptr || concentrationAttackTargetUnit->exists() == false || concentrationAttackTargetUnit->getHitPoints() == 0 || concentrationAttackTargetUnit->isVisible() == false) {
									// 가장 가까운 적 공격유닛 아무나 하나 새로 잡는다
									concentrationAttackTargetUnit = getNearestAndWeakestEnemyGroundCombatUnit(unit->getPosition());
								}

								if (concentrationAttackTargetUnit != nullptr && concentrationAttackTargetUnit->exists() && concentrationAttackTargetUnit->getHitPoints() > 0) {

									// 많이 안맞았으면 계속 싸운다
									if (unit->getHitPoints() > 10) {
										targetUnit = concentrationAttackTargetUnit;
										currentSquad->setUnitMission(unit, Mission(MissionType::Attack, targetUnit));
										//std::cout << "Attack concentrationAttackTargetUnit " << targetUnit->getID() << " " << targetUnit->getType().getName().c_str() << std::endl;
										//std::cout << " " << unit->getID() << " " << unit->getHitPoints() << " A CO " << targetUnit->getType().getName().c_str() << " " << targetUnit->getID();
										attackerTargetMap[unit] = targetUnit;
										hasOrderedNewMission = true;
									}
									// 많이 맞았으면 뒤로 뺀다
									else {
										// 싸우던 중이었거나 이동하던 중이었으면 이동 위치 새로 결정
										if (unitMission->missionType == MissionType::Attack || unitMission->missionType == MissionType::AttackMove || unitMission->missionType == MissionType::Move) {

											// 가까이에 전부 체력 적은 아군 유닛밖에 없으면 끝까지 싸운다
											// 가까이에 체력 많은 아군 유닛이 있으면 다른 곳으로 이동시킨다
											if (isThereHealthyFriendUnitAround(unit->getPosition(), 4 * TILE_SIZE)) {

												// 우선 공격 대상 건물을 공격하러 가게 한다
												if (mostUrgentTarget != nullptr && mostUrgentTarget->exists() && mostUrgentTarget->getHitPoints() > 0) {
													targetUnit = mostUrgentTarget;
													currentSquad->setUnitMission(unit, Mission(MissionType::Attack, targetUnit));
													//std::cout << "Attack mostUrgentTarget " << targetUnit->getID() << " " << targetUnit->getType().getName().c_str() << std::endl;
													//std::cout << " " << unit->getID() << " A U " << targetUnit->getType().getName().c_str() << " " << targetUnit->getID();
													attackerTargetMap[unit] = targetUnit;
													hasOrderedNewMission = true;
												}

												if (hasOrderedNewMission == false) {
													// 단순하게 적군 앞마당으로 이동
													BWAPI::Position targetPosition = StrategyManager::Instance().enemyFirstExpansionBaseLocation->getPosition();
													currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
													//std::cout << "Move Flee " << unit->getID() << " to " << targetPosition.x << "," << targetPosition.y << std::endl;
													//std::cout << " " << unit->getID() << " " << unit->getHitPoints() << " M F to " << targetPosition.x << "," << targetPosition.y << std::endl;
													attackerTargetMap[unit] = targetUnit;
													hasOrderedNewMission = true;
												}
											}
										}
										// 뒤로 이동 다 했으면, 다시 전투
										else if (unitMission->missionType == MissionType::Mission_Undefined) {
											targetUnit = concentrationAttackTargetUnit;
											currentSquad->setUnitMission(unit, Mission(MissionType::Attack, targetUnit));
											//std::cout << "Attack concentrationAttackTargetUnit " << targetUnit->getID() << " " << targetUnit->getType().getName().c_str() << std::endl;
											//std::cout << " " << unit->getID() << " " << unit->getHitPoints() << " A CO " << targetUnit->getType().getName().c_str() << " " << targetUnit->getID();
											attackerTargetMap[unit] = targetUnit;
											hasOrderedNewMission = true;
										}
									}
								}
							}
							// 적 공격 유닛이 없으면
							else {
								// 공격유닛 생산 건물 등 우선공격대상 건물 mostUrgentTarget 을 공격
								if (mostUrgentTarget != nullptr && mostUrgentTarget->exists() && mostUrgentTarget->getHitPoints() > 0) {

									// mostUrgentTarget 에 최대 6마리만 붙인다
									if (getNumberOfSameTargeting(mostUrgentTarget) < 6) {
										targetUnit = mostUrgentTarget;
										currentSquad->setUnitMission(unit, Mission(MissionType::Attack, targetUnit));
										//std::cout << "Attack mostUrgentTarget " << targetUnit->getID() << " " << targetUnit->getType().getName().c_str() << std::endl;
										std::cout << " " << unit->getID() << " A U " << targetUnit->getType().getName().c_str() << " " << targetUnit->getID();
										attackerTargetMap[unit] = targetUnit;
										hasOrderedNewMission = true;
									}
								}
							}
						}
					}
				}
			}
					
			// 적 공격 유닛이 다수 있어서 공격유닛과 전투를 하지 않기로 했으면 일꾼을 공격
			// 적 공격 유닛이 전혀 없고, 공격유닛 생산 건물 같은 긴급히 공격할 대상이 없는 상황이 되어도 일꾼을 공격
			if (hasOrderedNewMission == false) {

				if (enemyWorkerUnitCount > 0) {

					bool isToFindAnotherTarget = false;

					if (targetUnit == nullptr) {
						isToFindAnotherTarget = true;
					}
					else {
						// 기존 타겟이 공격유닛인 경우, 일꾼으로 타겟 변경
						if (targetUnit->getType().isWorker() == false && targetUnit->getHitPoints() >= 35) {
							isToFindAnotherTarget = true;
						}
					}

					if (isToFindAnotherTarget){

						// 가장 가까운 적 일꾼유닛 하나를 집중 공격 : 적 일꾼 1마리당 아군 저글링 3마리씩 공격하도록 한다
						BWAPI::Unit closestEnemyWorker = getNearestEnemyWorkerForMeleeAttack(unit->getPosition(), 3);

						// 가까이에 공격할 일꾼이 있으면 공격
						if (closestEnemyWorker != nullptr && closestEnemyWorker->exists() && closestEnemyWorker->getHitPoints() > 0) {
							targetUnit = closestEnemyWorker;
							currentSquad->setUnitMission(unit, Mission(MissionType::Attack, targetUnit));
							//std::cout << "Attack closestEnemyWorker Worker " << targetUnit->getID() << " " << targetUnit->getType().getName().c_str() << std::endl;
							//std::cout << " " << unit->getID() << " A CL " << targetUnit->getType().getName().c_str() << " " << targetUnit->getID();
							attackerTargetMap[unit] = targetUnit;
							hasOrderedNewMission = true;
						}								
					}
				}
				// 적 일꾼 유닛이 없으면
				else {							
					// 적 미네랄을 다 안봤으면, 미네랄 위치로 이동해서 적 일꾼 유닛을 찾아본다
					if (isAllMineralExplored(StrategyManager::Instance().enemyMainBaseLocation) == false) {
						BWAPI::Position targetPosition = getFarthestMineralPosition(unit->getPosition(), StrategyManager::Instance().enemyMainBaseLocation);						
						currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
						hasOrderedNewMission = true;
					}	
				}
			}

			// 적 공격 유닛이 없고, 우선공격대상 건물 mostUrgentTarget 이 없고, 일꾼이 없으면, 다른 일반 건물 / 유닛을 공격한다
			if (hasOrderedNewMission == false) {

				BWAPI::Position targetPosition = getNearestEnemyUnitToGroundAttack(unit->getPosition());
				if (targetPosition != BWAPI::Positions::None) {
					currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
					hasOrderedNewMission = true;
				}
			}

			// 명령을 내린 것이 없으면, 기본적으로 적 진지를 향해 AttackMove 
			if (hasOrderedNewMission == false) {
				//std::cout << "Move to enemyMainBaseLocation ";
				//std::cout << " " << unit->getID() << " M B";
				currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, StrategyManager::Instance().enemyMainBaseLocation, StrategyManager::Instance().enemyMainBaseLocation->getPosition()));
			}
		}
	}

	BWAPI::Broodwar->drawTextScreen(300, 250, "zerglingScouterNumberFromCombatSquad : %d", StrategyManager::Instance().zerglingScouterNumberFromCombatSquad);
}

void Strategy_CombatTaskManager::attackEnemyWithMainCombatGroundSquad()
{
	// 끊임없는 정찰을 통해 정보 확보
	// 정찰 : Zergling 을 BaseLocation 마다 보내놓고, 길목마다 보내놓는다
	// 정찰 : Queen 이 있으면, Parasite 를 적극 활용

	// 아군 유닛 시야범위 내에 적군 유닛이 들어오거나, 아군 유닛이 적의 공격을 받으면, 상황판단

	// 아군 BaseLocation 이 있는 Region 내 유닛이 공격받을 경우 

	// 아군이 공격하러 들어가는 것에 있어서
	// 공격 목표 결정 -> 지상 유닛은 단계적으로 ChokePoint 로 이동. 지상 유닛들의 50%가 모이면 다음 ChokePoint 로 이동
	// 공격 목표 결정 -> 공중 유닛은 바로 전투 유리한 장소를 정해서 공격. 그냥 가면 도중에 발각되고, 공격당함. 언덕위, 가장자리로 돌아서 이동해야.

	bool isToRetreat = false;


	/*
	if (InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Terran_Vulture, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Terran_Bunker, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Terran_Goliath, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Protoss_Dragoon, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Protoss_Photon_Cannon, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Protoss_Archon, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Zerg_Hydralisk, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Zerg_Mutalisk, InformationManager::Instance().enemyPlayer) >= 1
		|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Zerg_Sunken_Colony, InformationManager::Instance().enemyPlayer) >= 1
		)
	{
		isToRetreat = true;
	}
	*/

	Squad* currentSquad = nullptr;

	int totalSquadSize = StrategyManager::Instance().mainCombatZerglingSquad.unitset.size() 
		+ StrategyManager::Instance().mainCombatHydraliskSquad.unitset.size()
		+ StrategyManager::Instance().mainCombatLurkerSquad.unitset.size()
		+ StrategyManager::Instance().mainCombatUltraliskSquad.unitset.size() 
		+ StrategyManager::Instance().mainCombatQueenSquad.unitset.size()
		+ StrategyManager::Instance().mainCombatDefilerSquad.unitset.size()
		+ StrategyManager::Instance().mainCombatScourgeSquad.unitset.size()
		+ StrategyManager::Instance().mainCombatMutaliskSquad.unitset.size();

	// 공격을 시작할만한 상황이 되기 전까지는 방어를 합니다
	if (combatState == CombatState::defenseMode) {

		// 아군 방어 건물이 세워져있는 위치
		targetAssemblePositionForGroundUnits = StrategyManager::Instance().myFirstExpansionBaseLocation->getPosition();
		targetAttackPositionForGroundUnits = targetAssemblePositionForGroundUnits;


		/// 아군 공격유닛 들에게 방어를 지시합니다
		// 아군 공격유닛을 방어 건물이 세워져있는 위치로 배치시킵니다
		// 아군 공격유닛을 아군 방어 건물 뒤쪽에 배치시켰다가 적들이 방어 건물을 공격하기 시작했을 때 다함께 싸우게하면 더 좋을 것입니다
		
		for (int i = 0; i <= 7; i++) {
			if (i == 0) currentSquad = &StrategyManager::Instance().mainCombatZerglingSquad;
			else if (i == 1) currentSquad = &StrategyManager::Instance().mainCombatHydraliskSquad;
			else if (i == 2) currentSquad = &StrategyManager::Instance().mainCombatLurkerSquad;
			else if (i == 3) currentSquad = &StrategyManager::Instance().mainCombatUltraliskSquad;
			else if (i == 4) currentSquad = &StrategyManager::Instance().mainCombatQueenSquad;
			else if (i == 5) currentSquad = &StrategyManager::Instance().mainCombatDefilerSquad;
			else if (i == 6) currentSquad = &StrategyManager::Instance().mainCombatScourgeSquad;
			else if (i == 7) currentSquad = &StrategyManager::Instance().mainCombatMutaliskSquad;

			for (auto & unit : currentSquad->unitset) {
				currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetAttackPositionForGroundUnits));
			}
		}

		/// 공격 모드로 전환할 때인지 여부를 판단합니다
		if (isTimeToStartAttack()) {
			combatState = CombatState::gatherToAttack;
		}
	}
	// 공격 모드에서는 공격을 실행합니다 
	else {

		BWTA::BaseLocation* targetBaseLocation = getWeakestEnemyBaseLocationForGroundCombatUnit();

		if (targetBaseLocation == nullptr) {
			return;
		}

		/// 방어 모드로 전환할 때인지 여부를 판단합니다
		if (isTimeToRetreatFromCombat()) {
			combatState = CombatState::defenseMode;
			return;
		}

		// TODO : 메인공격부대는 메인지원부대와 함께 적진을 향해 공격한다
		// TODO : 메인증원부대는 메인공격부대 위치로 attackMove 시킨다

		// 아군 공격 유닛들에게 frontlinePosition 으로 이동을 지시합니다 
		if (combatState == CombatState::gatherToAttack) {

			targetAssemblePositionForGroundUnits = StrategyManager::Instance().frontlinePosition;
			targetAttackPositionForGroundUnits = targetAssemblePositionForGroundUnits;

			if (getMyUnitCount(targetAttackPositionForGroundUnits, 8 * TILE_SIZE) > totalSquadSize * 0.5) {
				combatState = CombatState::prepareToAttackStart;
			}

		}
		// 아군 공격 유닛들에게 공격대상 베이스에서 어느 정도 떨어진 지점으로 이동을 지시합니다 
		else if (combatState == CombatState::prepareToAttackStart) {
			
			targetAssemblePositionForGroundUnits = getAssemblePositionForGroundAttack(StrategyManager::Instance().frontlinePosition, targetBaseLocation->getPosition());
			targetAttackPositionForGroundUnits = targetAssemblePositionForGroundUnits;

			if (getMyUnitCount(targetAttackPositionForGroundUnits, 8 * TILE_SIZE) > totalSquadSize * 0.5) {
				combatState = CombatState::attackEnemyChokepoint1;
			}
		}
		// 아군 공격 유닛들에게 targetBaseLocation 으로 가기 위한 중간 지점으로 공격을 지시합니다 
		else if (combatState == CombatState::attackEnemyChokepoint1) {

			targetAssemblePositionForGroundUnits = getAssemblePositionForGroundAttack(
				getAssemblePositionForGroundAttack(StrategyManager::Instance().frontlinePosition, targetBaseLocation->getPosition()),
				targetBaseLocation->getPosition());

			targetAttackPositionForGroundUnits = targetAssemblePositionForGroundUnits;

			if (getMyUnitCount(targetAttackPositionForGroundUnits, 8 * TILE_SIZE) > totalSquadSize * 0.5) {
				combatState = CombatState::attackEnemyChokepoint2;
			}
		}
		else if (combatState == CombatState::attackEnemyChokepoint2) {
			
			targetAssemblePositionForGroundUnits = getAssemblePositionForGroundAttack(
				getAssemblePositionForGroundAttack(StrategyManager::Instance().frontlinePosition, targetBaseLocation->getPosition()),
				targetBaseLocation->getPosition());

			std::list<BWTA::Chokepoint*> chokepointList = BWTA::getShortestPath2(
				BWAPI::TilePosition(targetAssemblePositionForGroundUnits),
				targetBaseLocation->getTilePosition());

			if (chokepointList.size() <= 1) {
				combatState = CombatState::attackEnemyBaseLocation;
				return;
			}
			else {
				chokepointList.pop_front();
				BWTA::Chokepoint* targetChokepoint = chokepointList.front();
				if (targetChokepoint != nullptr) {
					targetAttackPositionForGroundUnits = targetChokepoint->getCenter();

					if (getMyUnitCount(targetAttackPositionForGroundUnits, 8 * TILE_SIZE) > totalSquadSize * 0.5) {
						combatState = CombatState::attackEnemyChokepoint3;
					}
				}
			}
		}
		else if (combatState == CombatState::attackEnemyChokepoint3) {
			
			targetAssemblePositionForGroundUnits = getAssemblePositionForGroundAttack(
				getAssemblePositionForGroundAttack(StrategyManager::Instance().frontlinePosition, targetBaseLocation->getPosition()),
				targetBaseLocation->getPosition());

			std::list<BWTA::Chokepoint*> chokepointList = BWTA::getShortestPath2(
				BWAPI::TilePosition(targetAssemblePositionForGroundUnits),
				targetBaseLocation->getTilePosition());

			if (chokepointList.size() <= 2) {
				combatState = CombatState::attackEnemyBaseLocation;
				return;
			}
			else {
				chokepointList.pop_front();
				chokepointList.pop_front();
				BWTA::Chokepoint* targetChokepoint = chokepointList.front();
				if (targetChokepoint != nullptr) {
					targetAttackPositionForGroundUnits = targetChokepoint->getCenter();

					if (getMyUnitCount(targetAttackPositionForGroundUnits, 8 * TILE_SIZE) > totalSquadSize * 0.5) {
						combatState = CombatState::attackEnemyBaseLocation;
					}
				}
			}
		}
		else if (combatState == CombatState::attackEnemyBaseLocation) {

			targetAssemblePositionForGroundUnits = BWTA::getNearestChokepoint(targetBaseLocation->getPosition())->getCenter();

			targetAttackPositionForGroundUnits = targetBaseLocation->getPosition();
		}

		// 아군 공격부대에게 targetAttackPositionForGroundUnits 로 공격을 지시합니다
		Squad* currentSquad = nullptr;

		for (int i = 0; i <= 5; i++) {
			if (i == 0) currentSquad = &StrategyManager::Instance().mainCombatZerglingSquad;
			else if (i == 1) currentSquad = &StrategyManager::Instance().mainCombatHydraliskSquad;
			else if (i == 2) currentSquad = &StrategyManager::Instance().mainCombatLurkerSquad;
			else if (i == 3) currentSquad = &StrategyManager::Instance().mainCombatUltraliskSquad;
			else if (i == 4) currentSquad = &StrategyManager::Instance().mainCombatQueenSquad;
			else if (i == 5) currentSquad = &StrategyManager::Instance().mainCombatDefilerSquad;

			for (auto & unit : currentSquad->unitset) {
				currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetAttackPositionForGroundUnits));
			}
		}
	}
}


void Strategy_CombatTaskManager::updateUnitMissionForZerglingAsFindEnemyMainBaseLocation()
{
}

void Strategy_CombatTaskManager::updateUnitMissionForZerglingAsFastAttack()
{
}

void Strategy_CombatTaskManager::updateUnitMissionForZerglingAsEliminateAttack()
{
	/*
	bool isToReassignUnitMission = false;
	BWAPI::Unit targetEnemyUnit = nullptr;
	BWAPI::Position targetEnemyUnitPosition = BWAPI::Positions::None;
	BWTA::BaseLocation * enemyMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer);

	// 저글링이 만들어지면, 적군 MainBaseLocation 을 향해 공격
	for (auto & unit : BWAPI::Broodwar->self()->getUnits())
	{
		if (unit == nullptr || unit->exists() == false || unit->getHitPoints() == 0 || unit->isCompleted() == false) continue;

		if (unit->getType() == BWAPI::UnitTypes::Zerg_Zergling)
		{
			if (enemyMainBaseLocation != nullptr)
			{
				int enemyCombatUnitCount = InformationManager::Instance().getNumUnits(InformationManager::Instance().getBasicCombatUnitType(InformationManager::Instance().enemyRace), InformationManager::Instance().enemyPlayer);
				int enemyWorkerUnitCount = InformationManager::Instance().getNumUnits(InformationManager::Instance().getWorkerType(InformationManager::Instance().enemyRace), InformationManager::Instance().enemyPlayer);
				// 파일런, 벙커, 크립콜로니
				int enemyBasicDepenseBuildingCount = InformationManager::Instance().getNumUnits(InformationManager::Instance().getBasicDefenseBuildingType(InformationManager::Instance().enemyRace), InformationManager::Instance().enemyPlayer);
				// 포톤캐논, 터렛, 성큰콜로니
				int enemyAdvancedDepenseBuildingCount = InformationManager::Instance().getNumUnits(InformationManager::Instance().getAdvancedDefenseBuildingType(InformationManager::Instance().enemyRace), InformationManager::Instance().enemyPlayer);

				//std::cout << "enemyCombatUnitCount : " << enemyCombatUnitCount << ", enemyWorkerUnitCount : " << enemyWorkerUnitCount << std::endl;

				bool hasOrderedNewMission = false;

				int selfZerglingCount = BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling);
				if (selfZerglingCount >= 40) {

					// 무조건 적진 공격
					if (true) {

						if (targetEnemyUnit == nullptr) {

							// 가장 가까운 적 공격유닛 하나를 집중 공격
							int minDistanceToAttack = INT_MAX;
							int tempDistanceToAttack;
							int minHitPointToAttack = INT_MAX;
							int tempHitPointToAttack;

							// BWAPI::Broodwar->enemy()->getUnits 를 사용하면, 아군 가시거리내에 있지 않으면 조회안된다
							// 그래서, InformationManager::Instance().getUnitAndUnitInfoMap 을 사용해야 한다
							for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer))
							{
								BWAPI::Unit enemyUnit = it.first;
								const UnitInfo & enemyUnitInfo = it.second;


								if (enemyUnitInfo.type == InformationManager::Instance().getBasicCombatUnitType(InformationManager::Instance().enemyRace))
								{
									tempDistanceToAttack = unit->getDistance(enemyUnitInfo.lastPosition);
									if (tempDistanceToAttack < minDistanceToAttack) {
										minDistanceToAttack = tempDistanceToAttack;

										targetEnemyUnit = enemyUnit;
										targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
									}
									else if (tempDistanceToAttack == minDistanceToAttack) {
										tempHitPointToAttack = enemyUnitInfo.lastHealth + enemyUnitInfo.lastShields;
										if (tempHitPointToAttack < minHitPointToAttack) {
											minHitPointToAttack = tempHitPointToAttack;

											targetEnemyUnit = enemyUnit;
											targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
										}
									}
								}
							}
						}

						if (targetEnemyUnit != nullptr) {
							setUnitMission(unit, Mission(MissionType::Attack, targetEnemyUnit));
							hasOrderedNewMission = true;
						}
					}
					else if (enemyWorkerUnitCount > 0) {

						if (targetEnemyUnit == nullptr) {

							// 가장 가까운 적 일꾼유닛 하나를 집중 공격
							int minDistanceToAttack = INT_MAX;
							int tempDistanceToAttack;
							int minHitPointToAttack = INT_MAX;
							int tempHitPointToAttack;

							for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer))
							{
								BWAPI::Unit enemyUnit = it.first;
								const UnitInfo & enemyUnitInfo = it.second;

								if (enemyUnitInfo.type == InformationManager::Instance().getWorkerType(InformationManager::Instance().enemyRace))
								{
									tempDistanceToAttack = unit->getDistance(enemyUnitInfo.lastPosition);
									if (tempDistanceToAttack < minDistanceToAttack) {
										minDistanceToAttack = tempDistanceToAttack;
										targetEnemyUnit = enemyUnit;
										targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
									}
									else if (tempDistanceToAttack == minDistanceToAttack) {
										tempHitPointToAttack = enemyUnitInfo.lastHealth + enemyUnitInfo.lastShields;
										if (tempHitPointToAttack < minHitPointToAttack) {
											minHitPointToAttack = tempHitPointToAttack;
											targetEnemyUnit = enemyUnit;
											targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
										}
									}
								}
							}
						}

						if (targetEnemyUnit != nullptr) {
							setUnitMission(unit, Mission(MissionType::Attack, targetEnemyUnit));
							hasOrderedNewMission = true;
						}
					}
					if (hasOrderedNewMission == false) {
						setUnitMission(unit, Mission(MissionType::Move, nullptr, InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer)->getPosition()));
					}
				}
				else if (selfZerglingCount >= 12) {
					for (BWTA::BaseLocation * baseLocation : BWTA::getBaseLocations()) {
						if (baseLocation == InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer)) continue;

						if (unit->isIdle()) {
							if (rand() % 10 == 0) {
								setUnitMission(unit, Mission(MissionType::AttackMove, nullptr, baseLocation->getPosition()));
							}
						}
					}
				}
			}
		}
	}
	*/
}


void Strategy_CombatTaskManager::updateUnitMissionForMutaliskAsAttack()
{
	/*
	bool isToReassignUnitMission = false;
	BWAPI::Unit targetEnemyUnit = nullptr;
	BWAPI::Position targetEnemyUnitPosition = BWAPI::Positions::None;
	BWTA::BaseLocation * enemyMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer);

	for (auto & unit : BWAPI::Broodwar->self()->getUnits())
	{
		if (unit == nullptr || unit->exists() == false || unit->getHitPoints() == 0 || unit->isCompleted() == false) continue;

		if (unit->getType() == BWAPI::UnitTypes::Zerg_Mutalisk)
		{
			if (enemyMainBaseLocation != nullptr)
			{
				int enemyCombatUnitCount = InformationManager::Instance().getNumUnits(InformationManager::Instance().getBasicCombatUnitType(InformationManager::Instance().enemyRace), InformationManager::Instance().enemyPlayer);
				int enemyWorkerUnitCount = InformationManager::Instance().getNumUnits(InformationManager::Instance().getWorkerType(InformationManager::Instance().enemyRace), InformationManager::Instance().enemyPlayer);
				// 파일런, 벙커, 크립콜로니
				int enemyBasicDepenseBuildingCount = InformationManager::Instance().getNumUnits(InformationManager::Instance().getBasicDefenseBuildingType(InformationManager::Instance().enemyRace), InformationManager::Instance().enemyPlayer);
				// 포톤캐논, 터렛, 성큰콜로니
				int enemyAdvancedDepenseBuildingCount = InformationManager::Instance().getNumUnits(InformationManager::Instance().getAdvancedDefenseBuildingType(InformationManager::Instance().enemyRace), InformationManager::Instance().enemyPlayer);

				//std::cout << "enemyCombatUnitCount : " << enemyCombatUnitCount << ", enemyWorkerUnitCount : " << enemyWorkerUnitCount << std::endl;

				bool hasOrderedNewMission = false;

				int selfMutaliskCount = BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Mutalisk);
				if (selfMutaliskCount >= 9) {
					// 적 공격유닛이 몇명 안되면 공격유닛을 공격. 너무 많으면 그냥 일꾼만 죽인다
					if (enemyCombatUnitCount > 0 && enemyCombatUnitCount <= 6) {

						if (targetEnemyUnit == nullptr) {

							// 가장 가까운 적 공격유닛 하나를 집중 공격
							int minDistanceToAttack = INT_MAX;
							int tempDistanceToAttack;
							int minHitPointToAttack = INT_MAX;
							int tempHitPointToAttack;

							// BWAPI::Broodwar->enemy()->getUnits 를 사용하면, 아군 가시거리내에 있지 않으면 조회안된다
							// 그래서, InformationManager::Instance().getUnitAndUnitInfoMap 을 사용해야 한다
							for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer))
							{
								BWAPI::Unit enemyUnit = it.first;
								const UnitInfo & enemyUnitInfo = it.second;

								if (enemyUnitInfo.type == InformationManager::Instance().getBasicCombatUnitType(InformationManager::Instance().enemyRace))
								{
									tempDistanceToAttack = unit->getDistance(enemyUnitInfo.lastPosition);
									if (tempDistanceToAttack < minDistanceToAttack) {
										minDistanceToAttack = tempDistanceToAttack;

										targetEnemyUnit = enemyUnit;
										targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
									}
									else if (tempDistanceToAttack == minDistanceToAttack) {
										tempHitPointToAttack = enemyUnitInfo.lastHealth + enemyUnitInfo.lastShields;
										if (tempHitPointToAttack < minHitPointToAttack) {
											minHitPointToAttack = tempHitPointToAttack;

											targetEnemyUnit = enemyUnit;
											targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
										}
									}
								}
							}
						}

						if (targetEnemyUnit != nullptr) {
							setUnitMission(unit, Mission(MissionType::MoveRoundAboutWay, targetEnemyUnit, targetEnemyUnitPosition));
							hasOrderedNewMission = true;
						}
					}
					else if (enemyWorkerUnitCount > 0) {

						if (targetEnemyUnit == nullptr) {

							// 가장 멀리있는 적 일꾼유닛 하나를 집중 공격
							int minDistanceToAttack = 0;
							int tempDistanceToAttack;
							int minHitPointToAttack = INT_MAX;
							int tempHitPointToAttack;

							for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer))
							{
								BWAPI::Unit enemyUnit = it.first;
								const UnitInfo & enemyUnitInfo = it.second;

								if (enemyUnitInfo.type == InformationManager::Instance().getWorkerType(InformationManager::Instance().enemyRace))
								{
									tempDistanceToAttack = unit->getDistance(enemyUnitInfo.lastPosition);
									if (tempDistanceToAttack > minDistanceToAttack) {
										minDistanceToAttack = tempDistanceToAttack;
										targetEnemyUnit = enemyUnit;
										targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
									}
									else if (tempDistanceToAttack == minDistanceToAttack) {
										tempHitPointToAttack = enemyUnitInfo.lastHealth + enemyUnitInfo.lastShields;
										if (tempHitPointToAttack < minHitPointToAttack) {
											minHitPointToAttack = tempHitPointToAttack;
											targetEnemyUnit = enemyUnit;
											targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
										}
									}
								}
							}
						}

						if (targetEnemyUnit != nullptr) {
							setUnitMission(unit, Mission(MissionType::MoveRoundAboutWay, targetEnemyUnit, targetEnemyUnitPosition));
							hasOrderedNewMission = true;
						}
					}
				}
				else if (selfMutaliskCount <= 4) {
					setUnitMission(unit, Mission(MissionType::Move, nullptr, InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().selfPlayer)->getPosition()));
				}
			}
		}
	}
	*/
}

void Strategy_CombatTaskManager::updateUnitMissionForOverlord()
{
	/*
	bool isToReassignUnitMission = false;
	BWAPI::Unit targetEnemyUnit = nullptr;
	BWAPI::Position targetEnemyUnitPosition = BWAPI::Positions::None;
	BWTA::BaseLocation * selfMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().selfPlayer);

	for (auto & unit : BWAPI::Broodwar->self()->getUnits())
	{
	if (unit == nullptr || unit->exists() == false || unit->getHitPoints() == 0 || unit->isCompleted() == false) continue;

	if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord)
	{
	if (selfMainBaseLocation != nullptr)
	{
	if (unit->isIdle()) {
	setUnitMission(unit, Mission(MissionType::Move, nullptr, InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().selfPlayer)->getPosition()));
	}
	}
	}
	}
	*/
}

void Strategy_CombatTaskManager::updateUnitMissionForLurker()
{
	/*
	bool isToReassignUnitMission = false;
	BWAPI::Unit targetEnemyUnit = nullptr;
	BWAPI::Position targetEnemyUnitPosition = BWAPI::Positions::None;
	BWTA::BaseLocation * selfMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().selfPlayer);

	for (auto & unit : BWAPI::Broodwar->self()->getUnits())
	{
	if (unit == nullptr || unit->exists() == false || unit->getHitPoints() == 0 || unit->isCompleted() == false) continue;

	if (unit->getType() == BWAPI::UnitTypes::Zerg_Lurker)
	{
	if (selfMainBaseLocation != nullptr)
	{
	if (unit->isIdle()) {

	if (unit->getDistance(InformationManager::Instance().getSecondChokePoint(InformationManager::Instance().selfPlayer)->getCenter()) > 8 * TILE_SIZE) {
	setUnitMission(unit, Mission(MissionType::Move, nullptr, InformationManager::Instance().getSecondChokePoint(InformationManager::Instance().selfPlayer)->getCenter()));
	}
	else {
	setUnitMission(unit, Mission(MissionType::Burrow, nullptr, InformationManager::Instance().getSecondChokePoint(InformationManager::Instance().selfPlayer)->getCenter()));
	}
	}
	}
	}
	}
	*/
}

void Strategy_CombatTaskManager::updateUnitMissionForQueen()
{
	/*
	bool isToReassignUnitMission = false;
	BWAPI::Unit targetEnemyUnit = nullptr;
	BWAPI::Position targetEnemyUnitPosition = BWAPI::Positions::None;
	BWTA::BaseLocation * enemyMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer);
	BWTA::BaseLocation * selfMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().selfPlayer);

	// 그냥 BWAPI::Broodwar->enemy()->getUnits() 라고 하면, 보이지 않게 된 유닛은 조회 안되고, 
	// getUnitAndUnitInfoMap로 해도 enemyUnit 은 보이지 않게되면, getType() 했을때 Unknown 으로 조회된다
	for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer))
	{
		BWAPI::Unit enemyUnit = it.first;
		UnitInfo & enemyUnitInfo = it.second;

		if (enemyUnitInfo.type.isBuilding() || enemyUnit->isParasited() == true || enemyUnitInfo.isAssignedAsParasiteTarget == true) {
			continue;
		}

		targetEnemyUnit = nullptr;
		targetEnemyUnitPosition = BWAPI::Positions::None;

		// TODO : Queen 임무 지정 Unit 포인터 저장 -> 임무 수행 도중 사망하거나, maelstrome / stasis field 당하거나 다른 Queen 지정

		// TODO : 가장 가까운 Queen 이 처리


		// Parasite 대상
		if (enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Science_Vessel
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Dropship
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Observer
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Shuttle
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Carrier
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Mutalisk)
		{
			// 이미 다른 Queen 이 Parasite 할 예정이면, skip 한다
			if (enemyUnitInfo.isAssignedAsParasiteTarget == false) {

				for (auto & unit : BWAPI::Broodwar->self()->getUnits())
				{
					if (unit == nullptr || unit->exists() == false || unit->getHitPoints() == 0 || unit->isCompleted() == false) continue;

					if (unit->getType() == BWAPI::UnitTypes::Zerg_Queen)
					{
						if (unit->isIdle()) {

							if (BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Parasite)
								&& unit->getEnergy() >= BWAPI::TechTypes::Parasite.energyCost())
							{
								targetEnemyUnit = enemyUnit;
								targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
								enemyUnitInfo.isAssignedAsParasiteTarget = true;
								setUnitMission(unit, Mission(MissionType::Parasite, targetEnemyUnit, targetEnemyUnitPosition));
								break;
							}
						}
					}
				}
			}
		}

		// Spawn_Broodlings 대상
		if (enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Reaver
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_High_Templar
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Archon
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Dark_Archon
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Lurker
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Ultralisk
			|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Defiler)
		{
			if (enemyUnitInfo.isAssignedAsSpawnBroodlingsTarget == false) {

				for (auto & unit : BWAPI::Broodwar->self()->getUnits())
				{
					if (unit == nullptr || unit->exists() == false || unit->getHitPoints() == 0 || unit->isCompleted() == false) continue;

					if (unit->getType() == BWAPI::UnitTypes::Zerg_Queen)
					{
						if (unit->isIdle()) {

							if (BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Spawn_Broodlings)
								&& unit->getEnergy() >= BWAPI::TechTypes::Spawn_Broodlings.energyCost())
							{
								targetEnemyUnit = enemyUnit;
								targetEnemyUnitPosition = enemyUnitInfo.lastPosition;
								enemyUnitInfo.isAssignedAsSpawnBroodlingsTarget = true;
								setUnitMission(unit, Mission(MissionType::Spawn_Broodlings, targetEnemyUnit, targetEnemyUnitPosition));
								break;
							}
						}
					}
				}
			}
		}
	}
	*/
	// 

	// TODO : 임무완수 여부 체크. 임무 없으면 제자리로 이동?

	/*
	for (auto & unit : BWAPI::Broodwar->self()->getUnits())
	{
	if (unit == nullptr || unit->exists() == false || unit->getHitPoints() == 0 || unit->isCompleted() == false) continue;

	if (unit->getType() == BWAPI::UnitTypes::Zerg_Queen)
	{
	if (selfMainBaseLocation != nullptr)
	{
	if (unit->isIdle()) {
	setUnitMission(unit, Mission(MissionType::Move, nullptr, InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().selfPlayer)->getPosition()));
	}
	}
	}
	}
	*/

}


void Strategy_CombatTaskManager::executeEnemyElimination()
{
	int enemyBuildingCount = 0;
	int enemyNonBuildingCount = 0;
	BWAPI::Position targetPosition = BWAPI::Positions::None;
	for (auto & enemyUnit : StrategyManager::Instance().enemyPlayer->getUnits()) {

		if (enemyUnit->getType().isBuilding()) {
			enemyBuildingCount++;
			targetPosition = enemyUnit->getPosition();
		}
		else {
			enemyNonBuildingCount++;
		}
	}

	Squad* currentSquad = nullptr;
	for (int i = 0; i < 12; i++) {
		if (i == 0) currentSquad = &StrategyManager::Instance().mainCombatZerglingSquad;
		else if (i == 1) currentSquad = &StrategyManager::Instance().mainCombatHydraliskSquad;
		else if (i == 2) currentSquad = &StrategyManager::Instance().mainCombatLurkerSquad;
		else if (i == 3) currentSquad = &StrategyManager::Instance().mainCombatMutaliskSquad;
		else if (i == 4) currentSquad = &StrategyManager::Instance().mainCombatScourgeSquad;
		else if (i == 5) currentSquad = &StrategyManager::Instance().mainCombatOverlordSquad;
		else if (i == 6) currentSquad = &StrategyManager::Instance().mainCombatQueenSquad;
		else if (i == 7) currentSquad = &StrategyManager::Instance().mainCombatUltraliskSquad;
		else if (i == 8) currentSquad = &StrategyManager::Instance().reinforceMainCombatMutaliskSquad;
		else if (i == 9) currentSquad = &StrategyManager::Instance().subCombatSquad;
		else if (i == 10) currentSquad = &StrategyManager::Instance().subCombatOverlordSquad;
		else if (i == 11) currentSquad = &StrategyManager::Instance().subCombatReinforceSquad;
		
		if (enemyBuildingCount > 0) {
			for (auto & unit : currentSquad->unitset) {
				currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
			}
		}
		else 
		{		
			for (auto & unit : currentSquad->unitset) {
				Mission* unitMission = currentSquad->getUnitMission(unit);
				
				/*
				bool isStopped = false;
				UnitAndUnitInfoMap & unitAndUnitInfoMap = InformationManager::Instance().getUnitAndUnitInfoMap(StrategyManager::Instance().selfPlayer);
				if (unitAndUnitInfoMap.find(unit) != unitAndUnitInfoMap.end()) {
					auto it = unitAndUnitInfoMap.find(unit);
					UnitInfo & unitInfo = it->second;
					if (unitInfo.lastPosition == unitInfo.positionBefore
						&& unitInfo.lastPositionRecordFrame - unitInfo.positionBeforeRecordFrame >= 10) 
					{
						isStopped = true;
						std::cout << unit->getType().getName().c_str() << " is stopped at " << unitInfo.lastPosition.x / TILE_SIZE << "," << unitInfo.lastPosition.y / TILE_SIZE << std::endl;
					}
				}
				*/

				if (unitMission->targetPosition == BWAPI::Positions::None 
					//|| isStopped == true
					|| unit->isIdle()
					) 
				{
					targetPosition = BWAPI::Position(rand() % BWAPI::Broodwar->mapWidth() * TILE_SIZE, rand() % BWAPI::Broodwar->mapHeight() * TILE_SIZE);
					currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
				}
				else {
					if (unit->getDistance(unitMission->targetPosition) < 3 * TILE_SIZE) {
						targetPosition = BWAPI::Position(rand() % BWAPI::Broodwar->mapWidth() * TILE_SIZE, rand() % BWAPI::Broodwar->mapHeight() * TILE_SIZE);
						currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
					}
				}

			}
		}
	}
}


