#include "Strategy_ScoutTaskManager.h"

using namespace MyBot;

Strategy_ScoutTaskManager::Strategy_ScoutTaskManager()
{
	isToFindError = false;

	enemyMainBaseLocation = nullptr;
	enemyFirstExpansionBaseLocation = nullptr;
	myMainBaseLocation = nullptr;
	enemyFirstChokepoint = nullptr;

	currentScoutWorker = nullptr;
	currentScoutOverlord = nullptr;
	currentScoutZergling = nullptr;

	currentScoutWorkerStatus = ScoutStatus::NoScout;
	currentScoutOverlordStatus = ScoutStatus::NoScout;
	currentScoutZerglingStatus = ScoutStatus::NoScout;

	currentScoutWorkerTargetBaseLocation = nullptr;
	currentScoutOverlordTargetBaseLocation = nullptr;
	currentScoutZerglingTargetBaseLocation = nullptr;

	currentScoutTargetPosition = BWAPI::Positions::None;

	currentScoutFreeToVertexIndex = -1;
}

Strategy_ScoutTaskManager & Strategy_ScoutTaskManager::Instance()
{
	static Strategy_ScoutTaskManager instance;
	return instance;
}

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

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

	enemyMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer);
	myMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().selfPlayer);
	enemyFirstExpansionBaseLocation = StrategyManager::Instance().enemyFirstExpansionBaseLocation;
	enemyFirstChokepoint = StrategyManager::Instance().enemyFirstChokepoint;

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

	// scoutUnitAndPositionMap 정리
	for (auto it = scoutUnitAndPositionMap.begin(); it != scoutUnitAndPositionMap.end(); ) {
		// 죽은 유닛 정리
		if (it->first == nullptr || it->first->exists() == false || it->first->getHitPoints() <= 0) {
			it = scoutUnitAndPositionMap.erase(it);
		}
		// 정찰에서 임무 해제된 유닛 정리
		else if (StrategyManager::Instance().scoutDroneSquad.unitset.find(it->first) == StrategyManager::Instance().scoutDroneSquad.unitset.end()
			&& StrategyManager::Instance().scoutOverlordSquad1.unitset.find(it->first) == StrategyManager::Instance().scoutOverlordSquad1.unitset.end()
			&& StrategyManager::Instance().scoutOverlordSquad2.unitset.find(it->first) == StrategyManager::Instance().scoutOverlordSquad2.unitset.end()
			&& StrategyManager::Instance().scoutOverlordSquad3.unitset.find(it->first) == StrategyManager::Instance().scoutOverlordSquad3.unitset.end()
			&& StrategyManager::Instance().scoutOverlordSquad4.unitset.find(it->first) == StrategyManager::Instance().scoutOverlordSquad4.unitset.end()
			&& StrategyManager::Instance().scoutOverlordSquad5.unitset.find(it->first) == StrategyManager::Instance().scoutOverlordSquad5.unitset.end()
			&& StrategyManager::Instance().scoutZerglingSquad.unitset.find(it->first) == StrategyManager::Instance().scoutZerglingSquad.unitset.end()
			&& StrategyManager::Instance().scoutScourgeSquad.unitset.find(it->first) == StrategyManager::Instance().scoutScourgeSquad.unitset.end()
			&& StrategyManager::Instance().multiObstructZerglingSquad.unitset.find(it->first) == StrategyManager::Instance().multiObstructZerglingSquad.unitset.end()
			&& StrategyManager::Instance().multiObstructLurkerSquad.unitset.find(it->first) == StrategyManager::Instance().multiObstructLurkerSquad.unitset.end()) 
		{
			it = scoutUnitAndPositionMap.erase(it);
		}
		else {
			it++;
		}
	}

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

	// 정찰해야할 곳이 여러곳인데, 정찰 유닛은 한정되어있다면, 중요한 곳부터 정찰한다

	// scoutOverlordSquad1 : 적 본진       -> 본진 근처
	// scoutOverlordSquad2 : 적 앞마당     -> 앞마당 근처
	// scoutOverlordSquad3 : 아군 앞마당   -> 아군 앞마당 근처
	// scoutOverlordSquad4 : 적 길목       -> 적 길목 근처
	// scoutOverlordSquad5 : 아군 길목     -> 아군 길목 근처

	// 가장 우선적인 것은 적 본진을 찾는 것
	if (StrategyManager::Instance().taskList.find(StrategicTask(Figure_Out_Enemy_Race)) != StrategyManager::Instance().taskList.end()
		|| StrategyManager::Instance().taskList.find(StrategicTask(Figure_Out_Enemy_BaseLocation)) != StrategyManager::Instance().taskList.end()) 
	{
		if (isToFindError) std::cout << "f";
		moveScoutSquadToFindEnemyBaseLocation();
	}
	
	// 그다움 우선적인 것은 적 앞마당과 적 길목, 그리고 적 본진을 둘러보는 것
	if (StrategyManager::Instance().taskList.find(StrategicTask(Scout_Enemy_First_Expansion)) != StrategyManager::Instance().taskList.end())
	{
		if (isToFindError) std::cout << "g";
		moveScoutSquadToScoutEnemyFirstExpansion();
	}

	if (StrategyManager::Instance().taskList.find(StrategicTask(Scout_Enemy_Chokepoint)) != StrategyManager::Instance().taskList.end())
	{
		if (isToFindError) std::cout << "h";
		moveScoutSquadToScoutEnemyOuterChokePoint();
	}

	if (StrategyManager::Instance().taskList.find(StrategicTask(Scout_Enemy_MainBaseLocation)) != StrategyManager::Instance().taskList.end())
	{
		if (isToFindError) std::cout << "j";
		moveScoutSquadToScoutEnemyBaseLocation();
	}

	// 그다음 우선적인 것은 적의 다른 멀티를 정찰하는 것
	if (StrategyManager::Instance().taskList.find(StrategicTask(Scout_Enemy_Other_Expansion)) != StrategyManager::Instance().taskList.end())
	{
		if (isToFindError) std::cout << "k";
		moveScoutSquadToScoutEnemyOtherExpansion(*(StrategyManager::Instance().taskList.find(StrategicTask(Scout_Enemy_Other_Expansion))));
	}

	// 그다음 우선적인 것은 빈 멀티를 둘러보는 것
	if (StrategyManager::Instance().taskList.find(StrategicTask(Scout_Empty_BaseLocations)) != StrategyManager::Instance().taskList.end())
	{
		if (isToFindError) std::cout << "l";
		moveMultiObstructSquadToScoutBaseLocations();
	}

	// 럴커로 멀티 방해
	if (StrategyManager::Instance().taskList.find(StrategicTask(Burrow_On_Empty_BaseLocation)) != StrategyManager::Instance().taskList.end())
	{
		obstructEnemyExpansionWithLurker();
	}

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

	// 
	moveScoutSquadToScoutOurFirstExpansion();

	if (isToFindError) std::cout << "c";
	moveScoutSquadToScoutMyOuterChokePoint();
		
	if (isToFindError) std::cout << "v";

	// 기본적으로 임무 미지정 되어있는 / 임무 해제된 오버로드 컨트롤
	if (StrategyManager::Instance().reservedSquad.unitset.size() > 0) {

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

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

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

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

				//if (unitMission->missionType != MissionType::Move) {

				// 24 frame 마다 다시 계산
				if (unitMission->missionSetFrame + 24 < BWAPI::Broodwar->getFrameCount()) {
					currentSquad->setUnitMission(unit, Mission(MissionType::Move, StrategyManager::Instance().getSafePositionForUnit(unit)));
				}
			}
		}
	}

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

	StrategyManager::Instance().scoutDroneSquad.executeMission();
	if (isToFindError) std::cout << "n";
	StrategyManager::Instance().scoutOverlordSquad1.executeMission();
	if (isToFindError) std::cout << "m";
	StrategyManager::Instance().scoutOverlordSquad2.executeMission();
	if (isToFindError) std::cout << ",";
	StrategyManager::Instance().scoutOverlordSquad3.executeMission();
	if (isToFindError) std::cout << ".";
	StrategyManager::Instance().scoutOverlordSquad4.executeMission();
	if (isToFindError) std::cout << ".";
	StrategyManager::Instance().scoutOverlordSquad5.executeMission();
	if (isToFindError) std::cout << ".";
	StrategyManager::Instance().scoutZerglingSquad.executeMission();
	if (isToFindError) std::cout << "/";
	StrategyManager::Instance().scoutScourgeSquad.executeMission();
	if (isToFindError) std::cout << "q";
	StrategyManager::Instance().multiObstructZerglingSquad.executeMission();
	if (isToFindError) std::cout << "w";
	StrategyManager::Instance().multiObstructLurkerSquad.executeMission();
	if (isToFindError) std::cout << "w";

	StrategyManager::Instance().reservedSquad.executeMission();

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

	//clearFinishedScoutUnit();

	drawStatus();

	if (isToFindError) std::cout << "m" << std::endl;
}

void Strategy_ScoutTaskManager::clearFinishedScoutUnit()
{
	Squad* currentSquad = nullptr;
	for (int i = 0; i < 9; i++) {
		if (i == 0) currentSquad = &StrategyManager::Instance().scoutOverlordSquad1;
		else if (i == 1) currentSquad = &StrategyManager::Instance().scoutOverlordSquad2;
		else if (i == 2) currentSquad = &StrategyManager::Instance().scoutOverlordSquad3;
		else if (i == 3) currentSquad = &StrategyManager::Instance().scoutDroneSquad;
		else if (i == 4) currentSquad = &StrategyManager::Instance().scoutZerglingSquad;
		else if (i == 5) currentSquad = &StrategyManager::Instance().scoutScourgeSquad;
		else if (i == 6) currentSquad = &StrategyManager::Instance().scoutQueenSquad;
		else if (i == 7) currentSquad = &StrategyManager::Instance().multiObstructZerglingSquad;
		else if (i == 8) currentSquad = &StrategyManager::Instance().multiObstructLurkerSquad;

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

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

			if (unitMission->missionType == MissionType::Move) {
			}
			else if (unitMission->missionType == MissionType::MoveAndHoldPosition) {
			}
		}
	}
}

// TODO : 적 유닛이 길목을 막아 Region 안에 건물이 있는지 확인 못하는 경우, 길목 유닛 만으로 MainBaseLocation 확정해야함
// 상대방 MainBaseLocation 위치를 모르는 상황이면, StartLocation 들에 대해 아군의 MainBaseLocation에서 가까운 것부터 순서대로 정찰
// 상대방 MainBaseLocation 위치를 아는 상황이면, 해당 BaseLocation 이 있는 Region의 가장자리를 따라 계속 이동함 (정찰 유닛이 죽을때까지) 
void Strategy_ScoutTaskManager::moveScoutSquadToFindEnemyBaseLocation()
{
	// 적진 위치를 찾는데에는 오버로드, 드론, 저글링을 보낸다
	Mission* unitMission;

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

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

		for (auto & unit : currentSquad->unitset) {
			
			unitMission = currentSquad->getUnitMission(unit);

			// 적군 MainBaseLocation 위치를 알면 바로 이동시킨다
			if (enemyMainBaseLocation != nullptr) {
				if (BWAPI::Broodwar->isExplored(enemyMainBaseLocation->getTilePosition()) == false) {
					currentSquad->setUnitMission(unit, Mission(MissionType::Move, enemyMainBaseLocation->getPosition()));
					scoutUnitAndPositionMap[unit] = enemyMainBaseLocation->getPosition();
				}
			}
			else {
				if (StrategyManager::Instance().isEnemyHasDangerousUnitToOverlord) {
					BWAPI::Position targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit);
					currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
					scoutUnitAndPositionMap[unit] = targetPosition;					
				}
				else {

					// 유닛이 목적지가 없거나, 목적지가 방문되었으면, 새로운 목적지를 세팅한다
					if (unitMission->missionType == Mission_Undefined
						|| BWAPI::Broodwar->isExplored(BWAPI::TilePosition(unitMission->targetPosition)))
					{
						int closestDistance = INT_MAX;
						int tempDistance = 0;
						BWTA::BaseLocation * closestBaseLocation = nullptr;
						for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations())
						{
							// 안가봤던 곳이면
							if (BWAPI::Broodwar->isExplored(startLocation->getTilePosition()) == false)
							{
								// AirDistance 를 기준으로, 정찰 유닛으로부터 가장 가까운 미정찰 BaseLocation 을 새로운 정찰 대상 currentScoutTargetBaseLocation 으로 잡아서 이동
								tempDistance = unit->getDistance(startLocation->getPosition());

								if (tempDistance > 0 && tempDistance < closestDistance) {
									closestBaseLocation = startLocation;
									closestDistance = tempDistance;
								}
							}
						}

						if (closestBaseLocation) {
							currentSquad->setUnitMission(unit, Mission(MissionType::Move, closestBaseLocation->getPosition()));
							scoutUnitAndPositionMap[unit] = closestBaseLocation->getPosition();
						}
					}
				}
			}
		}
	}

	currentSquad = &StrategyManager::Instance().scoutOverlordSquad2;

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

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

			unitMission = currentSquad->getUnitMission(unit);

			// 적군 MainBaseLocation 위치를 알면 바로 이동시킨다
			if (enemyMainBaseLocation != nullptr) {
				if (BWAPI::Broodwar->isExplored(enemyMainBaseLocation->getTilePosition()) == false) {
					currentSquad->setUnitMission(unit, Mission(MissionType::Move, enemyMainBaseLocation->getPosition()));
					scoutUnitAndPositionMap[unit] = enemyMainBaseLocation->getPosition();
				}
			}
			else {
				if (StrategyManager::Instance().isEnemyHasDangerousUnitToOverlord) {
					BWAPI::Position targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit);
					currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
					scoutUnitAndPositionMap[unit] = targetPosition;
				}
				else {

					// 유닛이 목적지가 없거나, 목적지가 방문되었으면, 새로운 목적지를 세팅한다
					if (unitMission->missionType == Mission_Undefined
						|| BWAPI::Broodwar->isExplored(BWAPI::TilePosition(unitMission->targetPosition)))
					{
						int closestDistance = INT_MAX;
						int tempDistance = 0;
						BWTA::BaseLocation * closestBaseLocation = nullptr;
						for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations())
						{

							// 안가봤던 곳이고, 다른 오버로드 유닛이나 저글링 유닛이 안가보는 곳을 먼저 선택
							if (BWAPI::Broodwar->isExplored(startLocation->getTilePosition()) == false)
							{
								bool isOKToGo = true;
								for (auto & it : scoutUnitAndPositionMap) {
									if (it.second == startLocation->getPosition()) {
										isOKToGo = false;
										break;
									}
								}

								if (isOKToGo) {

									// AirDistance 를 기준으로, 정찰 유닛으로부터 가장 가까운 미정찰 BaseLocation 을 새로운 정찰 대상 currentScoutTargetBaseLocation 으로 잡아서 이동
									tempDistance = unit->getDistance(startLocation->getPosition());

									if (tempDistance > 0 && tempDistance < closestDistance) {
										closestBaseLocation = startLocation;
										closestDistance = tempDistance;
									}
								}
							}
						}

						if (closestBaseLocation) {
							currentSquad->setUnitMission(unit, Mission(MissionType::Move, closestBaseLocation->getPosition()));
							scoutUnitAndPositionMap[unit] = closestBaseLocation->getPosition();
						}
					}
				}
			}
		}
	}

	// 드론
	currentSquad = &StrategyManager::Instance().scoutDroneSquad;
	if (currentSquad->unitset.size() > 0) {

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

			unitMission = currentSquad->getUnitMission(unit);

			// 적군 MainBaseLocation 위치를 알면 바로 이동시킨다
			if (enemyMainBaseLocation != nullptr) {
				if (BWAPI::Broodwar->isExplored(enemyMainBaseLocation->getTilePosition()) == false) {
					currentSquad->setUnitMission(unit, Mission(MissionType::Move, enemyMainBaseLocation->getPosition()));
				}
			}
			else {
				// 유닛이 목적지가 없거나, 목적지가 방문되었으면, 새로운 목적지를 세팅한다
				if (currentSquad->getUnitMission(unit)->missionType == Mission_Undefined
					|| BWAPI::Broodwar->isExplored(BWAPI::TilePosition(unitMission->targetPosition)))
				{
					int closestDistance = INT_MAX;
					int tempDistance = 0;
					BWTA::BaseLocation * closestBaseLocation = nullptr;
					for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations())
					{
						// 안가봤던 곳이고, 다른 오버로드 유닛이나 저글링 유닛이 안가보는 곳을 먼저 선택
						if (BWAPI::Broodwar->isExplored(startLocation->getTilePosition()) == false) 
						{							
							bool isOKToGo = true;
							for (auto & it : scoutUnitAndPositionMap) {
								if (it.second == startLocation->getPosition()) {
									isOKToGo = false;
									break;
								}
							}

							if (isOKToGo) {
								// GroundDistance 를 기준으로 아군 BaseLocation 으로부터 가까운 미정찰 BaseLocation 을 새로운 정찰 대상 currentScoutTargetBaseLocation 으로 잡아서 이동
								tempDistance = (int)(InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->self())->getGroundDistance(startLocation) + 0.5);

								if (tempDistance > 0 && tempDistance < closestDistance) {
									closestBaseLocation = startLocation;
									closestDistance = tempDistance;
								}
							}
						}
					}

					if (closestBaseLocation) {
						currentSquad->setUnitMission(unit, Mission(MissionType::Move, closestBaseLocation->getPosition()));
						scoutUnitAndPositionMap[unit] = closestBaseLocation->getPosition();
					}
					// 갈 곳이 없으면, 아직 안가본 곳을 선택. 오버로드보다 빠르게 정찰하기 위해서
					else {

						int closestDistance = INT_MAX;
						int tempDistance = 0;
						BWTA::BaseLocation * closestBaseLocation = nullptr;
						for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations())
						{
							// 안가봤던 곳을 선택
							if (BWAPI::Broodwar->isExplored(startLocation->getTilePosition()) == false)
							{
								// GroundDistance 를 기준으로 아군 BaseLocation 으로부터 가까운 미정찰 BaseLocation 을 새로운 정찰 대상 currentScoutTargetBaseLocation 으로 잡아서 이동
								tempDistance = (int)(InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->self())->getGroundDistance(startLocation) + 0.5);

								if (tempDistance > 0 && tempDistance < closestDistance) {
									closestBaseLocation = startLocation;
									closestDistance = tempDistance;
								}
							}
						}

						if (closestBaseLocation) {
							currentSquad->setUnitMission(unit, Mission(MissionType::Move, closestBaseLocation->getPosition()));
							scoutUnitAndPositionMap[unit] = closestBaseLocation->getPosition();
						}
					}
				}
			}
		}
	}

	// 저글링
	currentSquad = &StrategyManager::Instance().scoutZerglingSquad;
	if (currentSquad->unitset.size() > 0) {

		int currentSquadSize = currentSquad->unitset.size();

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

			unitMission = currentSquad->getUnitMission(unit);

			// 적군 MainBaseLocation 위치를 알면 바로 이동시킨다
			if (enemyMainBaseLocation != nullptr) {
				if (BWAPI::Broodwar->isExplored(enemyMainBaseLocation->getTilePosition()) == false) {
					currentSquad->setUnitMission(unit, Mission(MissionType::Move, enemyMainBaseLocation->getPosition()));
				}
			}
			else {
				// 유닛이 목적지가 없거나, 목적지가 방문되었으면, 새로운 목적지를 세팅한다
				if (unitMission->missionType == Mission_Undefined
					|| BWAPI::Broodwar->isExplored(BWAPI::TilePosition(unitMission->targetPosition)))
				{
					int minAssigned = 10000;
					
					BWTA::BaseLocation * targetBaseLocation = nullptr;					

					for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations())
					{
						// 안가봤던 곳 중에서, 다른 유닛들이 가장 적게 가는 곳
						if (BWAPI::Broodwar->isExplored(startLocation->getTilePosition()) == false)
						{
							int currentAssigned = 0;
							for (auto & it : scoutUnitAndPositionMap) {
								if (it.second == startLocation->getPosition()) {
									currentAssigned++;
								}
							}

							if (minAssigned >= currentAssigned) {
								minAssigned = currentAssigned;
								targetBaseLocation = startLocation;
							}
						}
					}

					if (targetBaseLocation) {
						currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetBaseLocation->getPosition()));
						scoutUnitAndPositionMap[unit] = targetBaseLocation->getPosition();
					}
				}
			}
		}
	}

}

void Strategy_ScoutTaskManager::moveScoutSquadToScoutEnemyBaseLocation()
{
	if (enemyMainBaseLocation != nullptr)
	{
		// 오버로드 1
		Squad* currentSquad = &StrategyManager::Instance().scoutOverlordSquad1;
		for (auto & unit : currentSquad->unitset) {

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

			BWAPI::Position targetPosition;

			if (StrategyManager::Instance().isEnemyHasDangerousUnitToOverlord) {
				targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit);
			}
			else {
				// 적군 MainBaseLocation 위치는 알되, 아직 가보지 않았다면, 바로 이동시킨다
				if (BWAPI::Broodwar->isExplored(enemyMainBaseLocation->getTilePosition()) == false) {
					targetPosition = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer)->getPosition();
				}
				else {

					// 적군 첫번째 길목과 MainBaseLocation을 왔다갔다 한다
					if (StrategyManager::Instance().chokepointStatusMap[enemyFirstChokepoint].lastVisibleTime < 0
						|| BWAPI::Broodwar->getFrameCount() - StrategyManager::Instance().chokepointStatusMap[enemyFirstChokepoint].lastVisibleTime >= 20 * 60 * 2) 
					{
						targetPosition = StrategyManager::Instance().enemyFirstChokepoint->getCenter();
					}
					else {
						targetPosition = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer)->getPosition();
					}

				}
			}
			currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
			scoutUnitAndPositionMap[unit] = targetPosition;
		}

		// 오버로드 2
		currentSquad = &StrategyManager::Instance().scoutOverlordSquad2;
		for (auto & unit : currentSquad->unitset) {

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

			BWAPI::Position targetPosition;
			if (StrategyManager::Instance().isEnemyHasDangerousUnitToOverlord) {
				targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit);
			}
			else {
				// 적군 MainBaseLocation 위치는 알되, 아직 가보지 않았다면, 바로 이동시킨다
				if (BWAPI::Broodwar->isExplored(enemyMainBaseLocation->getTilePosition()) == false) {
					targetPosition = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer)->getPosition();
				}
				// 적군 MainBaseLocation 에 가봤다면, 적진 앞마당에 간다
				else if (BWAPI::Broodwar->isExplored(StrategyManager::Instance().enemyFirstExpansionBaseLocation->getTilePosition()) == false) {
					targetPosition = StrategyManager::Instance().enemyFirstExpansionBaseLocation->getPosition();
				}
				else {

					// 적군 앞마당과 길목을 왔다갔다 한다
					if (StrategyManager::Instance().chokepointStatusMap[enemyFirstChokepoint].lastVisibleTime < 0
						|| BWAPI::Broodwar->getFrameCount() - StrategyManager::Instance().chokepointStatusMap[enemyFirstChokepoint].lastVisibleTime >= 20 * 60 * 2)
					{
						targetPosition = StrategyManager::Instance().enemyFirstChokepoint->getCenter();
					}
					else {
						targetPosition = StrategyManager::Instance().enemyFirstExpansionBaseLocation->getPosition();
					}
				}
			}
			currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
			scoutUnitAndPositionMap[unit] = targetPosition;
		}

		/*
		// 드론
		for (auto & unit : StrategyManager::Instance().scoutDroneSquad.unitset) {

			Mission* unitMission = StrategyManager::Instance().scoutDroneSquad.getUnitMission(unit);

			BWAPI::Position targetPosition;
			if (StrategyManager::Instance().isVeryDangerousToScoutWithDrone()) {
				targetPosition = StrategyManager::Instance().myMainBaseLocation->getPosition();
			}
			else {
				// 적군 MainBaseLocation 위치는 알되, 아직 가보지 않았다면, 바로 이동시킨다
				if (BWAPI::Broodwar->isExplored(enemyMainBaseLocation->getTilePosition()) == false) {
					targetPosition = enemyMainBaseLocation->getPosition();
					std::cout << "scoutDroneSquad target enemyMainBaseLocation : " << targetPosition.x / TILE_SIZE << "," << targetPosition.y / TILE_SIZE << std::endl;
				}
				else if (BWAPI::Broodwar->isExplored(StrategyManager::Instance().enemyFirstExpansionBaseLocation->getTilePosition()) == false) {
					targetPosition = StrategyManager::Instance().enemyFirstExpansionBaseLocation->getPosition();
					std::cout << "scoutDroneSquad target enemyFirstExpansionBaseLocation : " << targetPosition.x / TILE_SIZE << "," << targetPosition.y / TILE_SIZE << std::endl;
				}
				// 가보았다면, 돌아온다
				else {
					targetPosition = StrategyManager::Instance().myMainBaseLocation->getPosition();
					StrategyManager::Instance().isToScoutWithWorker = false;
				}
			}
			StrategyManager::Instance().scoutDroneSquad.setUnitMission(unit, Mission(MissionType::Move, targetPosition));
			scoutUnitAndPositionMap[unit] = targetPosition;
		}
		*/

		// 저글링
		for (auto & unit : StrategyManager::Instance().scoutZerglingSquad.unitset) {
			Mission* unitMission = StrategyManager::Instance().scoutZerglingSquad.getUnitMission(unit);

			BWAPI::Position targetPosition;
			// 적군 MainBaseLocation 위치는 알되, 아직 가보지 않았다면, 바로 이동시킨다
			if (BWAPI::Broodwar->isExplored(enemyMainBaseLocation->getTilePosition()) == false) {
				targetPosition = enemyMainBaseLocation->getPosition();
			}
			// 가보았다면, 주위를 둘러본다
			else {
				targetPosition = getScoutFleePositionFromEnemyRegionVertices(unit);
			}
			StrategyManager::Instance().scoutZerglingSquad.setUnitMission(unit, Mission(MissionType::Move, targetPosition));
			scoutUnitAndPositionMap[unit] = targetPosition;
		}
	}
}

void Strategy_ScoutTaskManager::moveScoutSquadToScoutEnemyFirstExpansion()
{
	if (enemyMainBaseLocation != nullptr) {

		// 오버로드 1마리만 보낸다
		Squad* currentSquad = &StrategyManager::Instance().scoutOverlordSquad1;
		if (currentSquad->unitset.size() > 0) {

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

				BWAPI::Position targetPosition;

				if (StrategyManager::Instance().isEnemyHasDangerousUnitToOverlord) {
					targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit);
				}
				else {
					targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit, InformationManager::Instance().getFirstExpansionLocation(InformationManager::Instance().enemyPlayer)->getPosition());
				}

				currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
				scoutUnitAndPositionMap[unit] = targetPosition;
			}
		}
	}
}


void Strategy_ScoutTaskManager::moveScoutSquadToScoutOurFirstExpansion()
{
	// 오버로드 1마리만 보낸다
	Squad* currentSquad = &StrategyManager::Instance().scoutOverlordSquad3;
	if (currentSquad->unitset.size() > 0) {

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

			BWAPI::Position targetPosition;
			if (StrategyManager::Instance().isEnemyHasDangerousUnitToOverlord) {
				targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit);
			}
			else {
				targetPosition = InformationManager::Instance().getFirstExpansionLocation(InformationManager::Instance().selfPlayer)->getPosition();
			}
			currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
			scoutUnitAndPositionMap[unit] = targetPosition;
		}
	}
}


void Strategy_ScoutTaskManager::moveScoutSquadToScoutEnemyOuterChokePoint()
{
	if (enemyMainBaseLocation != nullptr)
	{
		// 오버로드 1마리만 보낸다

		BWTA::Chokepoint* targetChokepoint = nullptr;
		int count = 0;
		for (auto & chokepoint : BWTA::getShortestPath2(myMainBaseLocation->getTilePosition(), enemyMainBaseLocation->getTilePosition())) {
			count++;
			if (count == 2) {
				targetChokepoint = chokepoint;
				break;
			}
		}
		if (targetChokepoint != nullptr) {
			Squad* currentSquad = &StrategyManager::Instance().scoutOverlordSquad4;
			if (currentSquad->unitset.size() > 0) {

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

					BWAPI::Position targetPosition;

					if (StrategyManager::Instance().isEnemyHasDangerousUnitToOverlord
						|| InformationManager::Instance().enemyRace == BWAPI::Races::Terran) {
						targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit);
					}
					else {
						targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit, targetChokepoint->getCenter());
					}

					currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
					scoutUnitAndPositionMap[unit] = targetPosition;
				}
			}
		}
	}
}


void Strategy_ScoutTaskManager::moveScoutSquadToScoutMyOuterChokePoint()
{
	// 오버로드 1마리만 보낸다
	Squad* currentSquad = &StrategyManager::Instance().scoutOverlordSquad5;

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

		for (auto & unit : currentSquad->unitset) {
			
			if (StrategyManager::Instance().frontlineChokepointList.size() > 0) {

				auto it = StrategyManager::Instance().frontlineChokepointList.begin();

				BWTA::Chokepoint* chokepoint = *it;

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

				BWAPI::Position targetPosition;

				if (StrategyManager::Instance().isEnemyHasDangerousUnitToOverlord) {
					targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit);
				}
				else {
					targetPosition = StrategyManager::Instance().getSafePositionForUnit(unit, chokepoint->getCenter());
				}

				currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
				scoutUnitAndPositionMap[unit] = targetPosition;
			}
		}
	}
}

void Strategy_ScoutTaskManager::moveScoutSquadToScoutEnemyOtherExpansion(StrategicTask task)
{

}

/// 멀티 방해 부대를 각각의 BaseLocation 위치에 이동시킵니다
void Strategy_ScoutTaskManager::moveMultiObstructSquadToScoutBaseLocations()
{
	if (enemyMainBaseLocation != nullptr)
	{
		// 저글링
		Squad* currentSquad = &StrategyManager::Instance().multiObstructZerglingSquad;
		for (auto & unit : currentSquad->unitset) {

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

			
			BWTA::BaseLocation* targetBaseLocation = nullptr;

			int dangerousLevel = 0;
			int minDangerousLevel = INT_MAX;

			for (auto & it : StrategyManager::Instance().baseLocationStatusMap) {
				BWTA::BaseLocation* baseLocation = it.first;
				LocationInfo& locationInfo = it.second;

				if (it.second.locationStatus == LocationStatus::My_MainBase
					|| it.second.locationStatus == LocationStatus::My_Occupied
					|| it.second.locationStatus == LocationStatus::Enemy_MainBase
					|| it.second.locationStatus == LocationStatus::Enemy_Occupied)
				{
					continue;
				}

				if (baseLocation->isIsland() == true) {
					continue;
				}

				// 이미 다른 저글링이 배정되어 있지 않은 곳
				bool isAnotherScoutUnitAssigned = false;
				for (auto & it2 : scoutUnitAndPositionMap) {
					if (it2.second == baseLocation->getPosition()
						&& it2.first != unit
						&& it2.first->getType() == BWAPI::UnitTypes::Zerg_Zergling) {
						isAnotherScoutUnitAssigned = true;
						break;
					}
				}
				if (isAnotherScoutUnitAssigned) {
					continue;
				}

				// 적 본진에서 가까운 곳을 먼저 가보도록, 적 본진으로부터의 거리를 우선적으로 계산
				if (baseLocation->isIsland()) {
					dangerousLevel = (int)(baseLocation->getAirDistance(enemyMainBaseLocation) - baseLocation->getAirDistance(myMainBaseLocation));
				}
				else {
					dangerousLevel = (int)(baseLocation->getGroundDistance(enemyMainBaseLocation) - baseLocation->getGroundDistance(myMainBaseLocation));
				}

				// 미네랄 멀티 지역은 비선호
				if (baseLocation->isMineralOnly()) {
					dangerousLevel += 10 * TILE_SIZE;
				}

				if (dangerousLevel < minDangerousLevel) {
					targetBaseLocation = baseLocation;
					minDangerousLevel = dangerousLevel;
					//std::cout << "obstruct zergling " << unit->getID() << " targetBaseLocation " << targetBaseLocation->getTilePosition().x << ", " << targetBaseLocation->getTilePosition().y << std::endl;
				}
			}

			if (targetBaseLocation != nullptr) {
				BWAPI::Position targetPosition = targetBaseLocation->getPosition();
				scoutUnitAndPositionMap[unit] = targetPosition;

				// 아직 도착 안했으면 이동
				if (unit->getDistance(targetPosition) > 5 * TILE_SIZE) {
					currentSquad->setUnitMission(unit, Mission(MissionType::Move, targetPosition));
				}
				// 도착하면 
				else {

					// 적 전투유닛이나 건물이 없고, 일꾼 및 일반건물만 있으면 공격
					int enemyGroundCombatUnitCount = 0;
					int enemyFlyerCombatUnitCount = 0;
					int enemyUnitCount = 0;
					for (auto & enemyUnit : BWAPI::Broodwar->getUnitsInRadius(targetPosition, 5 * TILE_SIZE)) {
						if (enemyUnit != nullptr && enemyUnit->exists() && enemyUnit->getPlayer() == StrategyManager::Instance().enemyPlayer) {
							
							enemyUnitCount++;

							if (enemyUnit->getType().canAttack() && enemyUnit->getType().isWorker() == false) {

								if (enemyUnit->getType().isFlyer()) {
									enemyFlyerCombatUnitCount++;
								}
								else {
									enemyGroundCombatUnitCount++;
								}
							}
						}
					}

					if (enemyUnitCount > 0) {
						if (enemyFlyerCombatUnitCount == 0 && enemyGroundCombatUnitCount == 0) {
							if (unit->isBurrowed()) {
								unit->unburrow();
							}
							else {
								currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
							}
						}
						else {
							if (unit->canBurrow() && unit->isBurrowed() == false) {
								unit->burrow();
							}
							else {
								currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
							}
						}
					}	
					else {
						if (unit->canBurrow() && unit->isBurrowed() == false) {
							unit->burrow();
						}
						else {
							currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
						}

					}
				}
			}
		}
	}

}

void Strategy_ScoutTaskManager::obstructEnemyExpansionWithLurker()
{
	if (enemyMainBaseLocation != nullptr)
	{
		// 러커
		Squad* currentSquad = &StrategyManager::Instance().multiObstructLurkerSquad;
		for (auto & unit : currentSquad->unitset) {

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

			// 이미 가서 버로우 해있으면 바로 continue
			if (scoutUnitAndPositionMap.find(unit) != scoutUnitAndPositionMap.end()
				&& unit->getDistance(scoutUnitAndPositionMap[unit]) < 4 * TILE_SIZE
				&& unit->isBurrowed()) 
			{
				continue;
			}


			BWTA::BaseLocation* targetBaseLocation = nullptr;
			int dangerousLevel = 0;
			int minDangerousLevel = INT_MAX;

			for (auto & it : StrategyManager::Instance().baseLocationStatusMap) {
				BWTA::BaseLocation* baseLocation = it.first;
				LocationInfo& locationInfo = it.second;

				if (it.second.locationStatus == LocationStatus::My_MainBase
					|| it.second.locationStatus == LocationStatus::My_Occupied
					|| it.second.locationStatus == LocationStatus::Enemy_MainBase
					|| it.second.locationStatus == LocationStatus::Enemy_Occupied)
				{
					continue;
				}

				if (baseLocation->isIsland() == true) {
					continue;
				}

				// 이미 보고있는곳은 제외?
				//if (locationInfo.lastVisibleTime < 0
				//	|| BWAPI::Broodwar->getFrameCount() - locationInfo.lastVisibleTime <= 20 * 60 * 2) {
				//	continue;
				//}

				// 이미 다른 러커가 배정되어 있지 않은 곳
				bool isAnotherScoutUnitAssigned = false;
				for (auto & it2 : scoutUnitAndPositionMap) {
					if (it2.second == baseLocation->getPosition() 
						&& it2.first != unit
						&& it2.first->getType() == BWAPI::UnitTypes::Zerg_Lurker
						) 
					{
						isAnotherScoutUnitAssigned = true;
						break;
					}
				}
				if (isAnotherScoutUnitAssigned) {
					continue;
				}

				// 적 본진에서 가장 가까운 곳을 먼저 가보도록, 적 본진으로부터의 거리를 우선적으로 계산
				if (baseLocation->isIsland()) {
					dangerousLevel = (int)(baseLocation->getAirDistance(enemyMainBaseLocation) - baseLocation->getAirDistance(myMainBaseLocation));
				}
				else {
					dangerousLevel = (int)(baseLocation->getGroundDistance(enemyMainBaseLocation) - baseLocation->getGroundDistance(myMainBaseLocation));
				}

				// 미네랄 멀티 지역은 비선호
				if (baseLocation->isMineralOnly()) {
					dangerousLevel += 10 * TILE_SIZE;
				}

				// fakeMineral에 막혀있는 경우, 해당 지역은 안감
				BWAPI::TilePosition fakeBaseLocationPosition = StrategyManager::Instance().getNearestBaseLocationPositionBlockedByFakeMineral(enemyMainBaseLocation->getTilePosition());
				if (fakeBaseLocationPosition == baseLocation->getTilePosition()) {
					dangerousLevel += 100000;
				}

				if (dangerousLevel < minDangerousLevel) {
					targetBaseLocation = baseLocation;
					minDangerousLevel = dangerousLevel;
					//std::cout << "obstruct lurker " << unit->getID() << " targetBaseLocation " << targetBaseLocation->getTilePosition().x << "," << targetBaseLocation->getTilePosition().y << std::endl;
				}
			}

			if (targetBaseLocation != nullptr) {

				/*
				// fake chokepoint 처리
				BWTA::Chokepoint* targetChokepoint = nullptr;
				
				const BWEM::Area* tempArea = theMap.GetNearestArea(targetBaseLocation->getTilePosition());
				if (tempArea != nullptr) {
					const std::map<const Area *, const std::vector<ChokePoint> *> tempChokepointMap = tempArea->ChokePointsByArea();
					//std::cout << "myArea " 
					//	<< " base " << myArea->Bases().size()
					//	<< " neighborArea " << myArea->ChokePointsByArea().size()
					//	<< " TopLeft " << myArea->TopLeft().x << "," << myArea->TopLeft().y
					//	<< " BottomRight " << myArea->BottomRight().x << "," << myArea->BottomRight().y
					//	<< std::endl;

					double minDistance = 100000;
					double tempDistance = 0;
					double minDistanceToExpansion = 100000;
					double tempDistanceToExpansion = 0;

					for (auto it = tempChokepointMap.begin(); it != tempChokepointMap.end(); it++) {
						const Area * area = it->first;
						const std::vector<ChokePoint> * chokepointList = it->second;
						for (size_t i = 0; i < chokepointList->size(); i++) {

							const BWEM::ChokePoint * CP = &((*chokepointList)[i]);
							//std::cout << "ChokePoint " << CP->Center().x << "," << CP->Center().y
							//	<< "IsPseudo " << CP->IsPseudo()
							//	<< "Blocked " << CP->Blocked()
							//	<< std::endl;

							if (CP->IsPseudo() == false && CP->Blocked() == false) {

								tempDistance = BWAPI::Position(CP->Center()).getDistance(enemyMainBaseLocation->getPosition());

								if (minDistance > tempDistance) {
									minDistance = tempDistance;

									for (auto & chokepoint : BWTA::getChokepoints()) {
										if (chokepoint->getCenter().getDistance(BWAPI::Position(CP->Center())) < 4.0 * TILE_SIZE)
										{
											targetChokepoint = chokepoint;

											std::cout << "obstruct lurker " << unit->getID()
												<< " targetChokepoint " << targetChokepoint->getCenter().x / 32 << "," << targetChokepoint->getCenter().y /32
												<< std::endl;

										}
									}
								}
							}
						}
					}
				}


				if (targetChokepoint != nullptr) {
					BWAPI::Position targetPosition = targetChokepoint->getCenter();
					currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
					scoutUnitAndPositionMap[unit] = targetPosition;
					std::cout << "lurker obstruct " << targetPosition.x / TILE_SIZE << "," << targetPosition.y / TILE_SIZE << std::endl;
				}
				*/

				BWAPI::Position targetPosition = targetBaseLocation->getPosition();
				currentSquad->setUnitMission(unit, Mission(MissionType::AttackMove, targetPosition));
				scoutUnitAndPositionMap[unit] = targetPosition;
				//std::cout << "lurker obstruct " << targetPosition.x / TILE_SIZE << "," << targetPosition.y / TILE_SIZE << std::endl;

			}
		}
	}
}

/// 정찰 부대를 지도 전체를 훑으며 이동시킵니다
void Strategy_ScoutTaskManager::moveScoutSquadForEntireMap()
{

	// 모든 startLocation 을 다 가보았는가
	/*
	bool everyStartLocationExplored = true;
	for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations())
	{
	if (BWAPI::Broodwar->isExplored(startLocation->getTilePosition()) == false) {
	everyStartLocationExplored = false;
	break;
	}
	}
	*/
}

BWAPI::Position Strategy_ScoutTaskManager::getScoutFleePositionFromEnemyRegionVertices(BWAPI::Unit unit)
{
	// calculate enemy region vertices if we haven't yet
	if (enemyBaseRegionVertices.empty()) {
		calculateEnemyRegionVertices();
	}

	if (enemyBaseRegionVertices.empty()) {
		return BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation());
	}

	// if this is the first flee, we will not have a previous perimeter index
	if (currentScoutFreeToVertexIndex == -1)
	{
		// so return the closest position in the polygon
		int closestPolygonIndex = getClosestVertexIndex(unit);

		if (closestPolygonIndex == -1)
		{
			return BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation());
		}
		else
		{
			// set the current index so we know how to iterate if we are still fleeing later
			currentScoutFreeToVertexIndex = closestPolygonIndex;
			return enemyBaseRegionVertices[closestPolygonIndex];
		}
	}
	// if we are still fleeing from the previous frame, get the next location if we are close enough
	else
	{
		double distanceFromCurrentVertex = enemyBaseRegionVertices[currentScoutFreeToVertexIndex].getDistance(unit->getPosition());

		// keep going to the next vertex in the perimeter until we get to one we're far enough from to issue another move command
		while (distanceFromCurrentVertex < 128)
		{
			currentScoutFreeToVertexIndex = (currentScoutFreeToVertexIndex + 1) % enemyBaseRegionVertices.size();

			distanceFromCurrentVertex = enemyBaseRegionVertices[currentScoutFreeToVertexIndex].getDistance(unit->getPosition());
		}

		return enemyBaseRegionVertices[currentScoutFreeToVertexIndex];
	}
}

// Enemy MainBaseLocation 이 있는 Region 의 가장자리를  enemyBaseRegionVertices 에 저장한다
// Region 내 모든 건물을 Eliminate 시키기 위한 지도 탐색 로직 작성시 참고할 수 있다
void Strategy_ScoutTaskManager::calculateEnemyRegionVertices()
{
	BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy());
	if (!enemyBaseLocation) {
		return;
	}

	BWTA::Region * enemyRegion = enemyBaseLocation->getRegion();
	if (!enemyRegion) {
		return;
	}

	// 아군 Main BaseLocation 으로부터 가까운 순서대로 정렬된 타일들의 전체 목록을 갖고와서, enemyRegion 에 해당하는 타일들만 추려내면, 
	// enemyRegion 의 타일 중 아군 Main BaseLocation 으로부터 가장 가까운 순서대로 정렬된 타일들의 목록을 만들 수 있다
	const BWAPI::Position basePosition = BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation());
	const std::vector<BWAPI::TilePosition> & closestTobase = MapTools::Instance().getClosestTilesTo(basePosition);

	std::set<BWAPI::Position> unsortedVertices;

	// check each tile position
	for (size_t i(0); i < closestTobase.size(); ++i)
	{
		const BWAPI::TilePosition & tp = closestTobase[i];

		if (BWTA::getRegion(tp) != enemyRegion)
		{
			continue;
		}

		// a tile is 'surrounded' if
		// 1) in all 4 directions there's a tile position in the current region
		// 2) in all 4 directions there's a buildable tile
		bool surrounded = true;
		if (BWTA::getRegion(BWAPI::TilePosition(tp.x + 1, tp.y)) != enemyRegion || !BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tp.x + 1, tp.y))
			|| BWTA::getRegion(BWAPI::TilePosition(tp.x, tp.y + 1)) != enemyRegion || !BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tp.x, tp.y + 1))
			|| BWTA::getRegion(BWAPI::TilePosition(tp.x - 1, tp.y)) != enemyRegion || !BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tp.x - 1, tp.y))
			|| BWTA::getRegion(BWAPI::TilePosition(tp.x, tp.y - 1)) != enemyRegion || !BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tp.x, tp.y - 1)))
		{
			surrounded = false;
		}

		// Region의 가장자리 타일들 (surrounded 되지 않은 타일들)만 추가한다
		// push the tiles that aren't surrounded 
		if (!surrounded && BWAPI::Broodwar->isBuildable(tp))
		{
			unsortedVertices.insert(BWAPI::Position(tp) + BWAPI::Position(16, 16));
		}
	}

	std::vector<BWAPI::Position> sortedVertices;
	BWAPI::Position current = *unsortedVertices.begin();

	enemyBaseRegionVertices.push_back(current);
	unsortedVertices.erase(current);

	// while we still have unsorted vertices left, find the closest one remaining to current
	while (!unsortedVertices.empty())
	{
		double bestDist = 1000000;
		BWAPI::Position bestPos;

		for (const BWAPI::Position & pos : unsortedVertices)
		{
			double dist = pos.getDistance(current);

			if (dist < bestDist)
			{
				bestDist = dist;
				bestPos = pos;
			}
		}

		current = bestPos;
		sortedVertices.push_back(bestPos);
		unsortedVertices.erase(bestPos);
	}

	// let's close loops on a threshold, eliminating death grooves
	int distanceThreshold = 100;

	while (true)
	{
		// find the largest index difference whose distance is less than the threshold
		int maxFarthest = 0;
		int maxFarthestStart = 0;
		int maxFarthestEnd = 0;

		// for each starting vertex
		for (int i(0); i < (int)sortedVertices.size(); ++i)
		{
			int farthest = 0;
			int farthestIndex = 0;

			// only test half way around because we'll find the other one on the way back
			for (size_t j(1); j < sortedVertices.size() / 2; ++j)
			{
				int jindex = (i + j) % sortedVertices.size();

				if (sortedVertices[i].getDistance(sortedVertices[jindex]) < distanceThreshold)
				{
					farthest = j;
					farthestIndex = jindex;
				}
			}

			if (farthest > maxFarthest)
			{
				maxFarthest = farthest;
				maxFarthestStart = i;
				maxFarthestEnd = farthestIndex;
			}
		}

	// stop when we have no long chains within the threshold
	if (maxFarthest < 4)
	{
		break;
	}

	double dist = sortedVertices[maxFarthestStart].getDistance(sortedVertices[maxFarthestEnd]);

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

	for (size_t s(maxFarthestEnd); s != maxFarthestStart; s = (s + 1) % sortedVertices.size())
	{
		temp.push_back(sortedVertices[s]);
	}

	sortedVertices = temp;
	}

	enemyBaseRegionVertices = sortedVertices;
}

int Strategy_ScoutTaskManager::getClosestVertexIndex(BWAPI::Unit unit)
{
	int closestIndex = -1;
	double closestDistance = 10000000;

	for (size_t i(0); i < enemyBaseRegionVertices.size(); ++i)
	{
		double dist = unit->getDistance(enemyBaseRegionVertices[i]);
		if (dist < closestDistance)
		{
			closestDistance = dist;
			closestIndex = i;
		}
	}

	return closestIndex;
}

void Strategy_ScoutTaskManager::drawStatus()
{

}

