#include "StrategyManager.h"

using namespace MyBot;

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

StrategyManager::StrategyManager()
{
	isToFindError = false;	

	selfPlayer = BWAPI::Broodwar->self();
	selfRace = selfPlayer->getRace();
	enemyPlayer = InformationManager::Instance().enemyPlayer;
	enemyRace = InformationManager::Instance().enemyRace;

	enemyUnitData = &(InformationManager::Instance().getUnitData(InformationManager::Instance().enemyPlayer));
	myUnitData = &(InformationManager::Instance().getUnitData(InformationManager::Instance().selfPlayer));
	enemyMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer);
	myMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().selfPlayer);
	myFirstExpansionBaseLocation = InformationManager::Instance().getFirstExpansionLocation(InformationManager::Instance().selfPlayer);
	myFirstChokepoint = InformationManager::Instance().getFirstChokePoint(InformationManager::Instance().selfPlayer);
	enemyFirstExpansionBaseLocation = InformationManager::Instance().getFirstExpansionLocation(InformationManager::Instance().enemyPlayer);
	enemyFirstChokepoint = InformationManager::Instance().getFirstChokePoint(InformationManager::Instance().enemyPlayer);

	for (BWTA::BaseLocation * baseLocation : BWTA::getBaseLocations()) {
		if (baseLocation == myMainBaseLocation) {
			baseLocationStatusMap[baseLocation] = LocationInfo(LocationStatus::My_MainBase);
		}
		else {
			baseLocationStatusMap[baseLocation] = LocationInfo(LocationStatus::LocationStatus_Unknown);
		}
	}
	for (BWTA::Chokepoint * chokepoint : BWTA::getChokepoints()) {
		chokepointStatusMap[chokepoint] = LocationInfo(LocationStatus::LocationStatus_Unknown);
	}

	myOldBuildStrategy = myCurrentBuildStrategy = BuildStrategy::BuildStrategy_Unknown;
	myOldCombatStrategy = myCurrentCombatStrategy = CombatStrategy::CombatStrategy_Unknown;
	enemyOldBuildStrategy = enemyCurrentBuildStrategy = BuildStrategy::BuildStrategy_Unknown;
	enemyOldCombatStrategy = enemyCurrentCombatStrategy = CombatStrategy::CombatStrategy_Unknown;

	// 정찰 관련
	isToScoutWithOverlord = true;
	isToScoutWithWorker = false;
	isToScoutWithZergling = true;
	isToScoutWithScourge = false;
	isToScoutWithQueen = false;
	workerScoutCondition_completedWorkerCount = -1;
	zerglingScouterNumberFromCombatSquad = 1;
	isEnemyHasDangerousUnitToOverlord = false;

	isToBurrowOnEmptyBaseLocation = true;
	isToBurrowAndAmbushAttackWithLurker = true;

	// 앞마당 건설
	isAlreadySentFirstExpansionHatcheryDrone = false;
	isAlreadySentFirstExpansionCreepColonyDrone = false;

	lastFrameOfExpansionStart = 0;
	lastFrameOfScoutEnemyBaseLocation = 0;
	lastFrameOfMultiObstructZerglingSquad = 0;

	// 전투 관련
	isToMakeQueen = false;
	isToMakeGuardian = false;
	isToMakeDevourer = false;
	isToMakeUltralisk = false;


	// 멀티 확장
	numRiskToStartToConstructFirstExpansion = true;
	lastFrameOfConstructHatcheryOnFirstExpansion = 0;
	lastFrameOfConstructCreepColonyOnFirstExpansion = 0;
	numRiskToStartToConstructSecondExpansion = false;
	isStartedToConstructSecondExpansion = false;

	// 안전지역
	safeLevel1Positions = new std::set<BWAPI::WalkPosition>();
	safeLevel5Positions = new std::set<BWAPI::WalkPosition>();
	safeLevel9Positions = new std::set<BWAPI::WalkPosition>();

	// Nuke 관련
	nukeDetectedPosition = BWAPI::Positions::None;
	nukeDetectedFrame = -1;
	isEnemyHasNuclearMissile = false;

	// fakeMineral 관련
	isFakeMineralCleared = false;
	fakeMineralClearWorker = nullptr;

	// confidenceMap 관련
	auto & theMap = BWEM::Map::Instance();
	confidenceMapForMutalisk = new ConfidenceMap(&theMap);
	confidenceMapForZergling = new ConfidenceMap(&theMap);
	
	setWord();
}

void StrategyManager::onStart()
{
	if (isToFindError) std::cout << "<s";

	updateInformations();

	// 과거 게임 기록을 로딩합니다
	//loadGameRecordList();

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

	// 적군 전략 예측판단
	figureOutEnemyStrategy();

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

	// 적군 전략에 따라 대응해서 아군 전략 변경
	updateMyStrategy();

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

	// 초반에는 자기주도적으로, 아군이 어떻게 게임을 시작해서 풀어나갈지 결정해서 추진한다
	setInitialBuildOrder();

	if (isToFindError) std::cout << "4";
	setInitialSquad();
	if (isToFindError) std::cout << "5>";
}

void StrategyManager::onEnd(bool isWinner)
{
	// 과거 게임 기록 + 이번 게임 기록을 저장합니다
	//saveGameRecordList(isWinner);

	delete safeLevel9Positions;
	delete safeLevel5Positions;
	delete safeLevel1Positions;
}


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

	enemyPlayer = InformationManager::Instance().enemyPlayer;
	enemyRace = InformationManager::Instance().enemyRace;

	enemyUnitData = &(InformationManager::Instance().getUnitData(InformationManager::Instance().enemyPlayer));
	myUnitData = &(InformationManager::Instance().getUnitData(InformationManager::Instance().selfPlayer));
	enemyMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().enemyPlayer);
	myMainBaseLocation = InformationManager::Instance().getMainBaseLocation(InformationManager::Instance().selfPlayer);

	// StrategyManager 가 새로 판단
	myFirstChokepoint = InformationManager::Instance().getFirstChokePoint(InformationManager::Instance().selfPlayer);
	enemyFirstChokepoint = InformationManager::Instance().getFirstChokePoint(InformationManager::Instance().enemyPlayer);
	myFirstExpansionBaseLocation = InformationManager::Instance().getFirstExpansionLocation(InformationManager::Instance().selfPlayer);
	enemyFirstExpansionBaseLocation = InformationManager::Instance().getFirstExpansionLocation(InformationManager::Instance().enemyPlayer);

	// 적 본진 위치를 아직 모르면, 랜덤하게 정해서 결정
	BWTA::BaseLocation* enemyMainBaseLocationTemporal = enemyMainBaseLocation;
	if (enemyMainBaseLocation == nullptr) {
		while (enemyMainBaseLocationTemporal == nullptr) {
			for (BWTA::BaseLocation* startLocation : BWTA::getStartLocations()) {
				if (rand() % 4 == 0) {
					enemyMainBaseLocationTemporal = startLocation;
					break;
				}
			}
		}
	}
		
	// myFirstChokepoint 및 myFirstExpansionBaseLocation 을 fake chokepoint 고려해서 수정
	// (길목들 중 가짜가 아니고, 막혀있는 것이 아니고, 상대편 본진으로 더 가까워지는 방향의 길목)
	auto & theMap = BWEM::Map::Instance();
	const BWEM::Area* myArea = theMap.GetNearestArea(StrategyManager::Instance().myMainBaseLocation->getTilePosition());
	if (myArea != nullptr) {
		const std::map<const Area *, const std::vector<ChokePoint> *> myChokepointMap = myArea->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 = myChokepointMap.begin(); it != myChokepointMap.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(enemyMainBaseLocationTemporal->getPosition());

					if (minDistance > tempDistance) {
						minDistance = tempDistance;

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

					const std::vector<Base> & bases = area->Bases();
					for (size_t j = 0; j < bases.size(); j++) {
						if (bases[j].Geysers().size() > 0) {

							tempDistanceToExpansion = bases[j].Center().getDistance(myMainBaseLocation->getPosition());

							if (minDistanceToExpansion > tempDistanceToExpansion) {
								minDistanceToExpansion = tempDistanceToExpansion;

								for (auto & baselocation : BWTA::getBaseLocations()) {
									if (baselocation->getPosition().getDistance(bases[j].Center()) < 4.0 * TILE_SIZE)
									{
										myFirstExpansionBaseLocation = baselocation;
									}
								}
							}
						}
					}
				}
			}
		}
	}

	if (enemyMainBaseLocation != nullptr) {
		const BWEM::Area* enemyArea = theMap.GetNearestArea(enemyMainBaseLocationTemporal->getTilePosition());
		if (enemyArea != nullptr) {
			const std::map<const Area *, const std::vector<ChokePoint> *> enemyChokepointMap = enemyArea->ChokePointsByArea();
			double minDistance = 100000;
			double tempDistance = 0;
			double minDistanceToExpansion = 100000;
			double tempDistanceToExpansion = 0;
			for (auto it = enemyChokepointMap.begin(); it != enemyChokepointMap.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]);

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

						tempDistance = BWAPI::Position(CP->Center()).getDistance(myMainBaseLocation->getPosition());
						if (minDistance > tempDistance) {
							minDistance = tempDistance;

							for (auto & chokepoint : BWTA::getChokepoints()) {
								if (chokepoint->getCenter().getDistance(BWAPI::Position(CP->Center())) < 4.0 * TILE_SIZE)
								{
									enemyFirstChokepoint = chokepoint;
								}
							}
						}
						
						const std::vector<Base> & bases = area->Bases();
						for (size_t j = 0; j < bases.size(); j++) {
							if (bases[j].Geysers().size() > 0) {

								tempDistanceToExpansion = bases[j].Center().getDistance(enemyMainBaseLocation->getPosition());

								if (minDistanceToExpansion > tempDistanceToExpansion) {
									minDistanceToExpansion = tempDistanceToExpansion;

									for (auto & baselocation : BWTA::getBaseLocations()) {
										if (baselocation->getPosition().getDistance(bases[j].Center()) < 4.0 * TILE_SIZE)
										{
											enemyFirstExpansionBaseLocation = baselocation;
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}


	// 최전방 길목 갱신
	frontlineChokepointList.clear();
	frontlinePosition.x = 0;
	frontlinePosition.y = 0;

	if (InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer).size() == 1) {
		frontlineChokepointList.insert(myFirstChokepoint);
		frontlinePosition = myFirstChokepoint->getCenter();
	}
	else if (InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer).size() == 2) 
	{
		// 일단 앞마당을 최전방이라고 정한다
		// TODO : 여러 StartLocation 에 멀티를 했으면, frontline 은 다른 곳이어야 한다 
		BWTA::BaseLocation* frontlineBaseLocation = myFirstExpansionBaseLocation;

		const BWEM::Area* myFrontlineArea = theMap.GetArea(frontlineBaseLocation->getTilePosition());
		if (myFrontlineArea != nullptr) {
			const std::map<const Area *, const std::vector<ChokePoint> *> chokepointMap = myFrontlineArea->ChokePointsByArea();

			//double distanceToMyFirstExpansion = StrategyManager::Instance().myMainBaseLocation->getGroundDistance(frontlineBaseLocation);
			//double distanceFromMyFirstExpansionToEnemyMainBaseLocation = StrategyManager::Instance().myFirstExpansionBaseLocation->getGroundDistance(enemyMainBaseLocationTemporal);

			for (auto it = chokepointMap.begin(); it != chokepointMap.end(); it++) {
				const std::vector<ChokePoint> * chokepointList = it->second;
				for (int i = 0; i < (int)(chokepointList->size()); i++) {

					const BWEM::ChokePoint * CP = &((*chokepointList)[i]);

					// 최전방 길목들 중 가짜가 아니고, 막혀있는 것이 아니고, 아군 myFirstChokepoint 도 아닌, 길목을 추가
					if (CP->IsPseudo() == false && CP->Blocked() == false) {

						// BWEM 의 CP 와 BWTA 의 Chokepoint 간에 차이가 있기 때문에, CP에서 가장 가까운 Chokepoint 를 선정
						double minDistance = 1000000000;
						double tempDistance;
						BWTA::Chokepoint* closestChokepoint;
						for (auto & chokepoint : BWTA::getChokepoints()) {
							tempDistance = chokepoint->getCenter().getDistance(BWAPI::Position(CP->Center()));
							if (minDistance > tempDistance && chokepoint != myFirstChokepoint)
							{
								minDistance = tempDistance;
								closestChokepoint = chokepoint;
							}
						}
						frontlineChokepointList.insert(closestChokepoint);

					}
				}
			}

			for (auto & chokepoint : frontlineChokepointList) {
				frontlinePosition.x += chokepoint->getCenter().x;
				frontlinePosition.y += chokepoint->getCenter().y;
			}
			if (frontlineChokepointList.size() > 0) {
				frontlinePosition.x /= frontlineChokepointList.size();
				frontlinePosition.y /= frontlineChokepointList.size();
			}
		}
	}
	else if (InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer).size() > 2)
	{
		// TODO : 확장을 여러곳에 했을 경우 frontlinePosition 결정 
		// 본진 앞마당과 멀티의 Tile Path 의 중간지점?
		frontlinePosition.x = BWAPI::Broodwar->mapWidth() * TILE_SIZE / 2;
		frontlinePosition.y = BWAPI::Broodwar->mapHeight() * TILE_SIZE / 2;
	}

	// BaseLocation 에 대한 정보 업데이트 
	for (auto & it : baseLocationStatusMap) {
		it.second.locationStatus = LocationStatus::LocationStatus_Unknown;
	}

	for (BWTA::BaseLocation * baseLocation : InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer)) {
		baseLocationStatusMap[baseLocation].locationStatus = LocationStatus::My_Occupied;
	}
	baseLocationStatusMap[myMainBaseLocation].locationStatus = LocationStatus::My_MainBase;

	for (BWTA::BaseLocation * baseLocation : InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().enemyPlayer)) {
		baseLocationStatusMap[baseLocation].locationStatus = LocationStatus::Enemy_Occupied;
	}
	if (enemyMainBaseLocation != nullptr) {
		baseLocationStatusMap[enemyMainBaseLocation].locationStatus = LocationStatus::Enemy_MainBase;
	}

	for (BWTA::BaseLocation * baseLocation : BWTA::getBaseLocations()) {
		if (BWAPI::Broodwar->isVisible(baseLocation->getTilePosition())) {
			baseLocationStatusMap[baseLocation].lastVisibleTime = BWAPI::Broodwar->getFrameCount();
		}
	}
	
	// Chokepoint 에 대한 정보 업데이트
	for (BWTA::Chokepoint * chokepoint : BWTA::getChokepoints()) {
		if (BWAPI::Broodwar->isVisible(BWAPI::TilePosition(chokepoint->getCenter()))) {
			chokepointStatusMap[chokepoint].lastVisibleTime = BWAPI::Broodwar->getFrameCount();
		}
	}

	// 확장 가능성에 대한 정보 업데이트
	numRiskToStartToConstructFirstExpansion = 0;
	for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer)) {
		BWAPI::Unit enemyUnit = it.first;
		UnitInfo & enemyUnitInfo = it.second;

		if (enemyUnitInfo.type.canAttack()
			&& enemyUnitInfo.lastHealth > 0 && enemyUnitInfo.isLastPositionValid == true
			&& enemyUnitInfo.type.isWorker() == false
			&& BWTA::getRegion(enemyUnitInfo.lastPosition) == StrategyManager::Instance().myFirstExpansionBaseLocation->getRegion())
		{
			numRiskToStartToConstructFirstExpansion ++;
		}
	}

	if (ConstructionManager::Instance().getConstructionQueueItemCount(BWAPI::UnitTypes::Zerg_Hatchery) > 0) {
		std::vector<ConstructionTask> * constructionQueue = ConstructionManager::Instance().getConstructionQueue();

		for (const auto & b : *constructionQueue)
		{
			if (b.type == BWAPI::UnitTypes::Zerg_Hatchery) {

				if (b.desiredPosition.getDistance(myFirstExpansionBaseLocation->getTilePosition()) <= 4 * TILE_SIZE) {
					lastFrameOfConstructHatcheryOnFirstExpansion = BWAPI::Broodwar->getFrameCount();
				}
			}
		}
	}

	if (ConstructionManager::Instance().getConstructionQueueItemCount(BWAPI::UnitTypes::Zerg_Creep_Colony) > 0) {
		std::vector<ConstructionTask> * constructionQueue = ConstructionManager::Instance().getConstructionQueue();

		for (const auto & b : *constructionQueue)
		{
			if (b.type == BWAPI::UnitTypes::Zerg_Creep_Colony) {

				if (b.desiredPosition.getDistance(myFirstExpansionBaseLocation->getTilePosition()) <= 8 * TILE_SIZE) {
					lastFrameOfConstructCreepColonyOnFirstExpansion = BWAPI::Broodwar->getFrameCount();
				}
			}
		}
	}


	//BWAPI::Broodwar->drawTextMap(myFirstExpansionBaseLocation->getPosition().x, myFirstExpansionBaseLocation->getPosition().y+50,  
	//	"lastFrameOfConstructHatcheryOnFirstExpansion : %d", lastFrameOfConstructHatcheryOnFirstExpansion);


	numRiskToStartToConstructSecondExpansion = 0;
	isStartedToConstructSecondExpansion = false;

	//sendWord();
}
void StrategyManager::onNukeDetect(BWAPI::Position target)
{
	nukeDetectedPosition = target;
	isEnemyHasNuclearMissile = true;

	if (nukeDetectedFrame <= 0) {
		nukeDetectedFrame = BWAPI::Broodwar->getFrameCount();
	}
}

void StrategyManager::update()
{	
	if (isToFindError) std::cout << "k";

	updateInformations();

	if (BWAPI::Broodwar->getFrameCount() == 5) {
		updateSafePositions();
	}

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

	updateConfidenceMap();

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

	// 상황을 판단해서, 빌드 전략, 전투 전략을 update 하고, 	
	// 전략에 따라 Task List 를 업데이트 한다. 
	updateStatusAndStrategyAndTaskList();
	
	if (isToFindError) std::cout << "y";

	// 상황 및 Task List 에 따라 각 Squad 에 대한 유닛 배치를 조정한다
	if (BWAPI::Broodwar->getFrameCount() % 5 == 4) {
		updateSquad();
	}

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

	// 정찰을 실행한다
	executeScout();
	if (isToFindError) std::cout << "l";

	// 빌드 전략에 따라 빌드 관련 타스크들을 수행한다
	executeBuild();
	if (isToFindError) std::cout << "m";

	// 확장 관련 타스크들을 수행한다
	executeExpansion();
	if (isToFindError) std::cout << "n";

	// 전투 전략에 따라 전투 관련 타스크들을 수행한다
	executeCombat();
	if (isToFindError) std::cout << "o";

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

	// 핵미사일
	/*
	if (nukeDetectedFrame > 0) {

		// 핵미사일 떨어지기 전 : 고스트를 빨리 죽이거나, 도망쳐야 함
		if (BWAPI::Broodwar->getFrameCount() - nukeDetectedFrame < 380) {
			
			BWAPI::Broodwar->drawTextScreen(200, 100, "Nuclear missile will be arrived by %d frame", 380 - (BWAPI::Broodwar->getFrameCount() - nukeDetectedFrame));

			if (nukeDetectedPosition != BWAPI::Positions::Unknown) {
				BWAPI::Broodwar->drawCircleMap(nukeDetectedPosition, 40, BWAPI::Colors::Red, true);
			}
			else {
				if (BWAPI::Broodwar->getFrameCount() - nukeDetectedFrame < 150) {
				}
			}
		}
		// 핵미사일 떨어진 후
		else {
			nukeDetectedFrame = 0;
		}
	}
	*/
		
	// 건물 건설 취소
	// TODO : Bullet 을 갖고 판단?
	for (auto& unit : BWAPI::Broodwar->self()->getUnits()) {
		if (unit == nullptr || unit->exists() == false) continue;
		if (unit->isMorphing() && unit->getHitPoints() < 20) {
			for (auto & enemyUnit : BWAPI::Broodwar->getUnitsInRadius(unit->getPosition(), 5 * TILE_SIZE)) {
				int enemyCombatUnitCount = 0;
				if (enemyUnit->getPlayer() != BWAPI::Broodwar->self() 
					&& enemyUnit->canAttack() && enemyUnit->getType().isWorker() == false) {
					enemyCombatUnitCount++;
				}
				if (enemyCombatUnitCount >= 2) {
					unit->cancelMorph();
					std::cout << "cancelMorph by danger " << unit->getType().getName().c_str() << " " << unit->getPosition().x / TILE_SIZE << "," << unit->getPosition().y / TILE_SIZE << std::endl;
				}
			}
		}
	}

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

	// TODO : 가스 일꾼 수 조정
	// 아래 코드에서 널포인터 에러나는 듯
	if (WorkerManager::Instance().getNumMineralWorkers() <= 9 
		&& WorkerManager::Instance().getNumGasWorkers() >= 3
		&& (BWAPI::Broodwar->self()->gas() / (BWAPI::Broodwar->self()->minerals()+1)) > 3
		&& BWAPI::Broodwar->self()->minerals() < 200)
	{
		Config::Macro::WorkersPerRefinery = 1;
		/*
		int numGasWorker = 0;
		for (auto & worker : WorkerManager::Instance().getWorkerData().getWorkers()) {
			if (WorkerManager::Instance().getWorkerData().getWorkerJob(worker) == WorkerData::WorkerJob::Gas) {
				numGasWorker++;
				if (numGasWorker > 1){
					WorkerManager::Instance().setIdleWorker(worker);
				}
			}
		}
		*/
	}
	else {
		Config::Macro::WorkersPerRefinery = 3;
	}

	// 성큰 간격 조정
	if (BWAPI::Broodwar->self()->allUnitCount(BWAPI::UnitTypes::Zerg_Creep_Colony) >= 1)
	{
		Config::Macro::BuildingDefenseTowerSpacing = 0;
		/*
		int numGasWorker = 0;
		for (auto & worker : WorkerManager::Instance().getWorkerData().getWorkers()) {
		if (WorkerManager::Instance().getWorkerData().getWorkerJob(worker) == WorkerData::WorkerJob::Gas) {
		numGasWorker++;
		if (numGasWorker > 1){
		WorkerManager::Instance().setIdleWorker(worker);
		}
		}
		}
		*/
	}

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


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

	// 이번 게임의 로그를 남깁니다
	//saveGameLog();

	if (isToFindError) std::cout << "v";
}


void StrategyManager::updateConfidenceMap()
{
	// 4 프레임마다 1번씩 업데이트
	if (BWAPI::Broodwar->getFrameCount() % 4 != 0) {
		return;
	}

	// 일단, 현재 눈에 보이는 유닛들만 갖고 ConfidenceMap 을 구성한다
	for (int j = 0; j < confidenceMapForMutalisk->Height(); ++j) {
		for (int i = 0; i < confidenceMapForMutalisk->Width(); ++i) {
			confidenceMapForMutalisk->GetCell(i, j).clear();
		}
	}

	for (BWAPI::Unit unit : BWAPI::Broodwar->self()->getUnits()) {
		confidenceMapForMutalisk->Add(unit);
	}
	for (BWAPI::Unit unit : InformationManager::Instance().enemyPlayer->getUnits()) {
		confidenceMapForMutalisk->Add(unit);
	}

}


void StrategyManager::updateStatusAndStrategyAndTaskList()
{
	// State Machine 으로 구현?
	// 어떤 조건에 해당하게 되면 기존 State 에서 다음 State 로 전환
	
	// 고려 조건 :
	// 아군과 적군 사이의 거리
	// 적군의 종족
	// 맵 사이즈. 2인용 맵. 4인용 맵. 8인용 맵
	// 적군의 유닛 출현
	
	// 적군 전략 예측판단
	figureOutEnemyStrategy();

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

	// 적군 전략에 따라 대응해서 아군 전략 변경
	updateMyStrategy();

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

	// 적군 전략 / 아군 전략에 따라 타스크 추가
	updateScoutTask();

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

	if (isToFindError) std::cout << "y";
	updateBuildTask();
	if (isToFindError) std::cout << "z2";
	updateCombatTask();
	if (isToFindError) std::cout << "a";
	updateExpansionTask();
	if (isToFindError) std::cout << "b";

	// 완료된 StrategicTask 은 삭제한다
	clearCompletedTask();
	if (isToFindError) std::cout << "c";
}


void StrategyManager::setInitialBuildOrder()
{
	// 초기 전략 설정
	// TODO : 상대방 ID 에 따라, 지도에 따라, 과거 통계를 활용하여 초기 전략 결정

	Strategy_InitialBuildOrderManager::Instance().setInitialBuildOrder();
}

void StrategyManager::updateSquad()
{
	// TODO : 타스크가 제거되어 해당 타스크를 수행하던 Squad가 할일이 없어진 경우 Squad에서 유닛 해제

	// 새로 만들어진 유닛은 일단 무조건 reservedSquad 로 편성한다
	for (auto & kv : InformationManager::Instance().getUnitAndUnitInfoMap(BWAPI::Broodwar->self())) {
		BWAPI::Unit unit = kv.first;
		UnitInfo & ui = kv.second;
		if (unit->getType().isBuilding() == false && ui.isAssignedToSquad == false) {
			reservedSquad.addUnit(unit);
			ui.isAssignedToSquad = true;
		}
	}

	// 사망한 유닛은 Squad 에서 삭제한다
	clearDeadUnitInSquad();

	// 기본적으로 reservedSquad 의 저글링은 무조건 mainBaseDefenseSquad 에 추가한다
	moveUnitBetweenSquad(&reservedSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Zergling);

	// 기본적으로 reservedSquad 의 히드라는 무조건 mainBaseDefenseSquad 에 추가한다
	// 히드라가 러커로 변태하면, mainBaseDefenseSquad 에 있는 러커 중 
	// 일부만 ambushCombatLurkerSquad 로, 혹은 multiObstructLurkerSquad 로 편입시킨다
	moveUnitBetweenSquad(&reservedSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Hydralisk);
	moveUnitBetweenSquad(&reservedSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Lurker);

	// 기본적으로 reservedSquad 의 스커지는 무조건 mainBaseDefenseSquad 에 추가한다
	moveUnitBetweenSquad(&reservedSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Scourge);
	// 기본적으로 reservedSquad 의 퀸은 무조건 mainBaseDefenseSquad 에 추가한다
	moveUnitBetweenSquad(&reservedSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Queen);
	// 기본적으로 reservedSquad 의 디파일러는 무조건 mainBaseDefenseSquad 에 추가한다
	moveUnitBetweenSquad(&reservedSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Defiler);
	// 기본적으로 reservedSquad 의 울트라리스크는 무조건 mainBaseDefenseSquad 에 추가한다
	moveUnitBetweenSquad(&reservedSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Ultralisk);

	// 최초로 태어난 뮤탈리스크는 mainCombatMutaliskSquad 에 편입시킨다
	if (mainCombatMutaliskSquad.unitset.size() == 0) {
		moveUnitBetweenSquad(&reservedSquad, &mainCombatMutaliskSquad, BWAPI::UnitTypes::Zerg_Mutalisk);
		moveUnitBetweenSquad(&reinforceMainCombatMutaliskSquad, &mainCombatMutaliskSquad, BWAPI::UnitTypes::Zerg_Mutalisk);
	}
	// 기본적으로 reservedSquad 의 뮤탈리스크는 reinforceMainCombatMutaliskSquad 에 편입시킨다
	else {
		moveUnitBetweenSquad(&reservedSquad, &reinforceMainCombatMutaliskSquad, BWAPI::UnitTypes::Zerg_Mutalisk);
	}
	// reinforceMainCombatMutaliskSquad 유닛이 mainCombatMutaliskSquad 에 가까이 도착하면 편입시킨다
	for (auto it = reinforceMainCombatMutaliskSquad.unitset.begin(); it != reinforceMainCombatMutaliskSquad.unitset.end();) {
		BWAPI::Unit unit = *it;
		if (unit->getDistance(Strategy_CombatTaskManager::Instance().mainCombatMutaliskSquadCenterPosition) < 2 * TILE_SIZE) {
			mainCombatMutaliskSquad.addUnit(unit);
			it = reinforceMainCombatMutaliskSquad.removeUnit(it);
		}
		else {
			++it;
		}
	}


	// 타스크가 추가되었는데 해당 타스크를 수행할 Squad에 유닛이 없는 경우 Squad에 유닛 배치
	// TODO : 여러 타스크가 동시에 존재하는데, 전체 유닛이 얼마 없는 경우, 우선순위에 따라 유닛 배치
	for (auto task = StrategyManager::Instance().taskList.begin(); task != StrategyManager::Instance().taskList.end(); task++) {

		// 적이 랜덤 이거나,
		// 3인용 이상 맵이어서 상대방 베이스 위치를 파악해야 할때
		if (task->taskGoal == TaskGoalType::Figure_Out_Enemy_Race
			|| task->taskGoal == TaskGoalType::Figure_Out_Enemy_BaseLocation) {

			// 정찰 오버로드 부대는 1마리씩 운영
			if (isToScoutWithOverlord == true) {
				if (scoutOverlordSquad1.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad1, BWAPI::UnitTypes::Zerg_Overlord);

					if (getUnitNumberInSquad(&scoutOverlordSquad1, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
						moveUnitBetweenSquad(&mainCombatMutaliskSquad, &scoutOverlordSquad1, BWAPI::UnitTypes::Zerg_Overlord);
					}
				}
				if (scoutOverlordSquad2.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad2, BWAPI::UnitTypes::Zerg_Overlord);

					if (getUnitNumberInSquad(&scoutOverlordSquad2, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
						moveUnitBetweenSquad(&mainCombatMutaliskSquad, &scoutOverlordSquad2, BWAPI::UnitTypes::Zerg_Overlord);
					}
				}
				if (scoutOverlordSquad3.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad3, BWAPI::UnitTypes::Zerg_Overlord);

					if (getUnitNumberInSquad(&scoutOverlordSquad3, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
						moveUnitBetweenSquad(&mainCombatMutaliskSquad, &scoutOverlordSquad3, BWAPI::UnitTypes::Zerg_Overlord);
					}
				}
				if (scoutOverlordSquad4.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad4, BWAPI::UnitTypes::Zerg_Overlord);

					if (getUnitNumberInSquad(&scoutOverlordSquad4, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
						moveUnitBetweenSquad(&mainCombatMutaliskSquad, &scoutOverlordSquad4, BWAPI::UnitTypes::Zerg_Overlord);
					}
				}
				if (scoutOverlordSquad5.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad5, BWAPI::UnitTypes::Zerg_Overlord);

					if (getUnitNumberInSquad(&scoutOverlordSquad5, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
						moveUnitBetweenSquad(&mainCombatMutaliskSquad, &scoutOverlordSquad5, BWAPI::UnitTypes::Zerg_Overlord);
					}
				}
			}
			else {
				breakUpSquad(&scoutOverlordSquad1);
				breakUpSquad(&scoutOverlordSquad2);
				breakUpSquad(&scoutOverlordSquad3);
				breakUpSquad(&scoutOverlordSquad4);
				breakUpSquad(&scoutOverlordSquad5);
			}

			// 정찰 드론은 1마리만 운용
			if (isToScoutWithWorker == true ) {
				if (scoutDroneSquad.unitset.size() == 0) {
					// 일꾼은 workerScoutCondition_completedWorkerCount 숫자만큼 만들어지면 정찰을 보낸다
					if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Drone) >= workerScoutCondition_completedWorkerCount
						&& StrategyManager::Instance().workerScoutCondition_completedWorkerCount != -1)
					{
						BWAPI::Unit unit = WorkerManager::Instance().getClosestMineralWorkerTo(myMainBaseLocation->getPosition());
						moveUnitBetweenSquad(&reservedSquad, &scoutDroneSquad, BWAPI::UnitTypes::Zerg_Drone, 1, unit);
						WorkerManager::Instance().setScoutWorker(unit);
					}
				}
			}
			else if (scoutDroneSquad.unitset.size() > 0) {
				breakUpSquad(&scoutDroneSquad);
			}

			if (isToScoutWithZergling == true) {

				// 일반적으로 정찰 저글링은 1마리만 운용
				if (myCurrentCombatStrategy != CombatStrategy::Zerg_Combat_4Drone_Zergling_Rush) {
					if (scoutZerglingSquad.unitset.size() == 0)
					{
						moveUnitBetweenSquad(&mainBaseDefenseSquad, &scoutZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling);
						lastFrameOfScoutEnemyBaseLocation = BWAPI::Broodwar->getFrameCount();
					}
				}
				// 빠른 저글링 러시 Zerg_Combat_4Drone_Zergling_Rush 전략일때는 정찰 저글링에 전부 투입
				else {
					moveUnitBetweenSquad(&mainBaseDefenseSquad, &scoutZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling, 
						getUnitNumberInSquad(&mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Zergling));
					lastFrameOfScoutEnemyBaseLocation = BWAPI::Broodwar->getFrameCount();
				}
			}
		}
		// 적 베이스 위치는 파악된 상태에서, 적 베이스 / 길목을 정찰
		else if (task->taskGoal == TaskGoalType::Scout_Enemy_MainBaseLocation
			|| task->taskGoal == TaskGoalType::Scout_Enemy_First_Expansion
			|| task->taskGoal == TaskGoalType::Scout_Enemy_Other_Expansion
			|| task->taskGoal == TaskGoalType::Scout_Enemy_Chokepoint)
		{
			// 정찰 오버로드 부대는 1마리씩 운영
			if (isToScoutWithOverlord == true) {
				if (scoutOverlordSquad1.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad1, BWAPI::UnitTypes::Zerg_Overlord);
				}
				if (scoutOverlordSquad2.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad2, BWAPI::UnitTypes::Zerg_Overlord);
				}
				if (scoutOverlordSquad3.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad3, BWAPI::UnitTypes::Zerg_Overlord);
				}
				if (scoutOverlordSquad4.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad4, BWAPI::UnitTypes::Zerg_Overlord);
				}
				if (scoutOverlordSquad5.unitset.size() == 0) {
					moveUnitBetweenSquad(&reservedSquad, &scoutOverlordSquad5, BWAPI::UnitTypes::Zerg_Overlord);
				}
			}
			else {
				breakUpSquad(&scoutOverlordSquad1);
				breakUpSquad(&scoutOverlordSquad2);
				breakUpSquad(&scoutOverlordSquad3);
				breakUpSquad(&scoutOverlordSquad4);
				breakUpSquad(&scoutOverlordSquad5);
			}

			// 정찰 드론은 최대 1마리만 운용
			if (isToScoutWithWorker == true) {
				if (scoutDroneSquad.unitset.size() == 0) {
					// 일꾼은 workerScoutCondition_completedWorkerCount 숫자만큼 만들어지면 정찰을 보낸다
					if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Drone) >= workerScoutCondition_completedWorkerCount
						&& StrategyManager::Instance().workerScoutCondition_completedWorkerCount != -1)
					{
						BWAPI::Unit unit = WorkerManager::Instance().getClosestMineralWorkerTo(myMainBaseLocation->getPosition());
						moveUnitBetweenSquad(&reservedSquad, &scoutDroneSquad, BWAPI::UnitTypes::Zerg_Drone, 1, unit);
						WorkerManager::Instance().setScoutWorker(unit);
					}
				}
			}
			else if (scoutDroneSquad.unitset.size() > 0) {
				breakUpSquad(&scoutDroneSquad);
			}

			// 저글링이 최소 4마리 초과여야만 저글링으로 정찰
			if (isToScoutWithZergling == false) {
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) > 4) {
					isToScoutWithZergling = true;
				}
			}

			// 정찰 저글링은 zerglingScouterNumberFromCombatSquad 마리만 운용
			if (isToScoutWithZergling == true && (int)(scoutZerglingSquad.unitset.size()) < zerglingScouterNumberFromCombatSquad) {
				
				// 일반적으로, 너무 자주 정찰 보내면 저글링이 모자르기 때문에 3분마다 저글링 보낸다 
				// 
				if (myCurrentCombatStrategy == CombatStrategy::Zerg_Combat_4Drone_Zergling_Rush
					|| lastFrameOfScoutEnemyBaseLocation + 24 * 60 * 3 < BWAPI::Broodwar->getFrameCount())
				{
					moveUnitBetweenSquad(&mainBaseDefenseSquad, &scoutZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling);

					if ((int)(scoutZerglingSquad.unitset.size()) < zerglingScouterNumberFromCombatSquad)
					{
						moveUnitBetweenSquad(&mainCombatZerglingSquad, &scoutZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling);
					}

					if (scoutZerglingSquad.unitset.size() > 0) {
						lastFrameOfScoutEnemyBaseLocation = BWAPI::Broodwar->getFrameCount();
					}
				}
			}
			else if (isToScoutWithZergling == false && scoutZerglingSquad.unitset.size() > 0) {
				breakUpSquad(&scoutZerglingSquad);
			}

			// 정찰 스커지는 기본적으로 모든 스커지를 다 투입. 나중에 전투 부대로 재배치
			if (isToScoutWithScourge == true) {
				moveUnitBetweenSquad(&reservedSquad, &scoutScourgeSquad, BWAPI::UnitTypes::Zerg_Scourge);
			}
			else if (isToScoutWithScourge == false && scoutScourgeSquad.unitset.size() > 0) {
				breakUpSquad(&scoutScourgeSquad);
			}

			// 정찰 퀸은 기본적으로 모든 퀸을 다 투입. 나중에 전투 부대로 재배치
			if (isToScoutWithQueen == true) {
				moveUnitBetweenSquad(&reservedSquad, &scoutQueenSquad, BWAPI::UnitTypes::Zerg_Queen);
			}
			else if (isToScoutWithQueen == false && scoutQueenSquad.unitset.size() > 0) {
				breakUpSquad(&scoutQueenSquad);
			}
		}
		else if (task->taskGoal == TaskGoalType::Scout_Empty_BaseLocations || task->taskGoal == TaskGoalType::Burrow_On_Empty_BaseLocation)
		{
			int multiObstructZerglingSquadCount = 0;
			int multiObstructLurkerSquadCount = 0;

			if (BWAPI::Broodwar->getFrameCount() > 24 * 60 * 8) {
				multiObstructZerglingSquadCount = 4;
				multiObstructLurkerSquadCount = 2;
			}
			else if (BWAPI::Broodwar->getFrameCount() > 24 * 60 * 5) {
				multiObstructZerglingSquadCount = 2;
				multiObstructLurkerSquadCount = 1;
			}
			else if (BWAPI::Broodwar->getFrameCount() > 24 * 60 * 3) {
				multiObstructZerglingSquadCount = 1;
				multiObstructLurkerSquadCount = 0;
			}

			// 멀티 방해 저글링을 너무 자주 많이 운용하지는 않는다
			if (getUnitNumberInSquad(&multiObstructZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling) < multiObstructZerglingSquadCount
				&& lastFrameOfMultiObstructZerglingSquad + 24 * 60 * 2 < BWAPI::Broodwar->getFrameCount()) {
				moveUnitBetweenSquad(&mainBaseDefenseSquad, &multiObstructZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling);
				lastFrameOfMultiObstructZerglingSquad = BWAPI::Broodwar->getFrameCount();
			}
			// 멀티 방해 러커를 너무 많이 운용하지 않는다
			if (getUnitNumberInSquad(&multiObstructLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker) < multiObstructLurkerSquadCount) {
				moveUnitBetweenSquad(&mainBaseDefenseSquad, &multiObstructLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker);
			}

			// 아군 해처리 건설하려는 곳에 아군 멀티 방해 저글링 / 러커 있으면,  일단 그냥 놔둔다. 
			// 상황판단하기 쉽지 않다. 조금 옆에 건설해도 큰 상관없다.
		}

		if (task->taskGoal == TaskGoalType::Attack_Enemy_Worker_In_Main_Region) {

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

				if (enemyUnitInfo.type.isWorker()) {

					if (BWTA::getRegion(enemyUnitInfo.lastPosition) == myMainBaseLocation->getRegion()
						|| BWTA::getRegion(enemyUnitInfo.lastPosition) == myFirstExpansionBaseLocation->getRegion())
					{
						if (enemyUnitInfo.lastHealth > 0 && enemyUnitInfo.isLastPositionValid == true) {
							enemyWorkerCount++;
						}
					}
				}
			}

			if (enemyWorkerCount > 0) {

				if (myCurrentCombatStrategy != CombatStrategy::Zerg_Combat_4Drone_Zergling_Rush) {
					if (getUnitNumberInSquad(&mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling) < enemyWorkerCount * 2) {
						moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling);
					}
					if (getUnitNumberInSquad(&mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling) < enemyWorkerCount * 2) {
						moveUnitBetweenSquad(&scoutZerglingSquad, &mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling);
					}
					if (getUnitNumberInSquad(&mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling) < enemyWorkerCount * 2) {
						moveUnitBetweenSquad(&multiObstructZerglingSquad, &mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling);
					}
					if (getUnitNumberInSquad(&mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling) < enemyWorkerCount * 2) {
						moveUnitBetweenSquad(&mainCombatZerglingSquad, &mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling);
					}
				}

				// 적 일꾼에 대해서는 아군 드론 붙인다
				if (getUnitNumberInSquad(&mainBaseClearSquad1) < enemyWorkerCount) {
					moveUnitBetweenSquad(&reservedSquad, &mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Drone);
				}

				// 적 일꾼이 아군 일꾼을 공격하면, 특히 SCV 가 공격하면, 아군 일꾼이 죽을 수 있다
				// 에러 : reservedSquad 에 없다
				/*
				if (getUnitNumberInSquad(&mainBaseClearSquad1) < enemyWorkerCount * 2) {
				for (auto & myWorker : WorkerManager::Instance().getWorkerData().getWorkers()) {
				if (myWorker != nullptr
				&& myWorker->exists()
				&& WorkerManager::Instance().isMineralWorker(myWorker)
				&& myWorker->isUnderAttack())
				{
				moveUnitBetweenSquad(&reservedSquad, &mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Drone, 1, myWorker);
				}
				}
				}
				*/

			}
			else {
				breakUpSquad(&mainBaseClearSquad1);
			}
		}

		if (task->taskGoal == TaskGoalType::Attack_Enemy_Dangerous_Building_In_Main_Region) {

			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) == myMainBaseLocation->getRegion()
					|| BWTA::getRegion(enemyUnitInfo.lastPosition) == myFirstExpansionBaseLocation->getRegion())
				{
					if (enemyUnitInfo.lastHealth > 0 && enemyUnitInfo.isLastPositionValid == true) {
						if (enemyUnitInfo.type.isBuilding()) {
							// 테란의 날라다니는 건물은 일단 mainBaseClearSquad2 가 담당하지 않는다
							if (enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Bunker
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Refinery
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Pylon
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Photon_Cannon
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Assimilator
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Extractor
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Creep_Colony
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Nydus_Canal
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Sunken_Colony)
							{
								enemyBuildingCount++;
							}
						}
					}
				}
			}

			// 적 건물 : 벙커, 포톤, 성큰, 가스 등
			if (enemyBuildingCount > 0) {
				if (getUnitNumberInSquad(&mainBaseClearSquad2, BWAPI::UnitTypes::Zerg_Zergling) < 4) {
					moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainBaseClearSquad2, BWAPI::UnitTypes::Zerg_Zergling);
				}
				if (getUnitNumberInSquad(&mainBaseClearSquad2, BWAPI::UnitTypes::Zerg_Zergling) < 4) {
					moveUnitBetweenSquad(&scoutZerglingSquad, &mainBaseClearSquad2, BWAPI::UnitTypes::Zerg_Zergling);
				}
				if (getUnitNumberInSquad(&mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling) < 4) {
					moveUnitBetweenSquad(&mainChokepointBlockingSquad, &mainBaseClearSquad1, BWAPI::UnitTypes::Zerg_Zergling);
				}
				if (getUnitNumberInSquad(&mainBaseClearSquad2, BWAPI::UnitTypes::Zerg_Zergling) < 4) {
					moveUnitBetweenSquad(&multiObstructZerglingSquad, &mainBaseClearSquad2, BWAPI::UnitTypes::Zerg_Zergling);
				}
				if (getUnitNumberInSquad(&mainBaseClearSquad2, BWAPI::UnitTypes::Zerg_Zergling) < 4) {
					moveUnitBetweenSquad(&mainCombatZerglingSquad, &mainBaseClearSquad2, BWAPI::UnitTypes::Zerg_Zergling);
				}

				if (getUnitNumberInSquad(&mainBaseClearSquad2) < enemyBuildingCount * 7) {
					// 극 초반일때만, 일꾼까지 동원
					if (BWAPI::Broodwar->getFrameCount() < 24 * 60 * 5) {
						moveUnitBetweenSquad(&reservedSquad, &mainBaseClearSquad2, BWAPI::UnitTypes::Zerg_Drone);
					}
				}

			}
			else {
				breakUpSquad(&mainBaseClearSquad2);
			}

		}

		if (task->taskGoal == TaskGoalType::Attack_Enemy_Ground_Unit_In_Our_Region) {

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

				if (enemyUnitInfo.type.isWorker() == false
					&& enemyUnitInfo.type.canAttack()
					&& enemyUnitInfo.type.isFlyer() == false
					&& enemyUnitInfo.lastHealth > 0
					&& enemyUnitInfo.isLastPositionValid == true)
				{
					for (BWTA::BaseLocation* baselocation : InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer)) {
						if (baselocation->getPosition().getDistance(enemyUnitInfo.lastPosition) < 16 * TILE_SIZE) {
							enemyCount++;
						}
					}
				}
			}

			if (enemyCount > 0) {

				// 다른 부대에서 공격유닛을 긴급 차출해서 mainBaseDefenseSquad 에 추가한다
				if (getUnitNumberInSquad(&mainBaseDefenseSquad) < enemyCount * 2) {
					moveUnitBetweenSquad(&mainCombatHydraliskSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Hydralisk);
				}
				if (getUnitNumberInSquad(&mainBaseDefenseSquad) < enemyCount * 2) {
					moveUnitBetweenSquad(&scoutZerglingSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Zergling);
				}
				if (getUnitNumberInSquad(&mainBaseDefenseSquad) < enemyCount * 2) {
					moveUnitBetweenSquad(&multiObstructZerglingSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Zergling);
				}
				if (getUnitNumberInSquad(&mainBaseDefenseSquad) < enemyCount * 2) {
					moveUnitBetweenSquad(&mainCombatZerglingSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Zergling);
				}
				if (getUnitNumberInSquad(&mainBaseDefenseSquad) < enemyCount * 2) {
					moveUnitBetweenSquad(&ambushCombatLurkerSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Lurker);
				}
				if (getUnitNumberInSquad(&mainBaseDefenseSquad) < enemyCount * 2) {
					moveUnitBetweenSquad(&multiObstructLurkerSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Lurker);
				}
				if (getUnitNumberInSquad(&mainBaseDefenseSquad) < enemyCount * 2) {
					moveUnitBetweenSquad(&mainCombatLurkerSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Lurker);
				}

				// 전투 유닛이 없을 때에도 일꾼은 공격하지 않는다 ?
				//if (getUnitNumberInSquad(&mainBaseClearSquad1) < enemyCount * 2) {
				//	moveUnitBetweenSquad(&reservedSquad, &mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Drone);
				//}
			}
			else {
				//breakUpSquad(&mainBaseDefenseSquad);
			}
		}

		if (task->taskGoal == TaskGoalType::Block_And_Hold_On_ChokePoint) {

			// 저글링이 최소 4마리는 mainChokepointBlockingSquad 에 남아있도록 한다
			if (getUnitNumberInSquad(&mainChokepointBlockingSquad) < 4) {
				moveUnitBetweenSquad(&scoutZerglingSquad, &mainChokepointBlockingSquad, BWAPI::UnitTypes::Zerg_Zergling);
			}
			if (getUnitNumberInSquad(&mainChokepointBlockingSquad) < 4) {
				moveUnitBetweenSquad(&multiObstructZerglingSquad, &mainChokepointBlockingSquad, BWAPI::UnitTypes::Zerg_Zergling);
			}
		}
		
		if (task->taskGoal == TaskGoalType::Burrow_And_Ambush_Attack_With_Lurker)
		{
			int ambushCombatLurkerSquadCount = 0;

			if (BWAPI::Broodwar->getFrameCount() > 24 * 60 * 8) {
				ambushCombatLurkerSquadCount = 4;
			}
			else if (BWAPI::Broodwar->getFrameCount() > 24 * 60 * 5) {
				ambushCombatLurkerSquadCount = 2;
			}

			// 매복 러커를 너무 많이 운용하지 않는다
			if (getUnitNumberInSquad(&ambushCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker) < ambushCombatLurkerSquadCount) {
				moveUnitBetweenSquad(&mainBaseDefenseSquad, &ambushCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker);
			}
			if (getUnitNumberInSquad(&ambushCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker) < ambushCombatLurkerSquadCount) {
				moveUnitBetweenSquad(&mainCombatLurkerSquad, &ambushCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker);
			}
		}

		if (task->taskGoal == TaskGoalType::Defense_Position_With_Hydralisk) {
		}

		if (task->taskGoal == TaskGoalType::Attack_Enemy_BaseLocation_With_Early_Zergling_Unit) {

			if (enemyMainBaseLocation != nullptr) {
				
				// 저글링 총동원
				moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling, 
					getUnitNumberInSquad(&mainBaseDefenseSquad, BWAPI::UnitTypes::Zerg_Zergling));

				// 정찰 저글링은 zerglingScouterNumberFromCombatSquad 마리만 놔두고 총동원
				if (getUnitNumberInSquad(&scoutZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling) > zerglingScouterNumberFromCombatSquad) {
					moveUnitBetweenSquad(&scoutZerglingSquad, &mainCombatZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling, 1);
				}
			}
		}

		
		if (task->taskGoal == TaskGoalType::Attack_Enemy_BaseLocation_With_Ground_Unit) {

			// 모든 mainBaseDefenseSquad 부대에 있던 저글링, 히드라, 러커, 울트라리스크, 디파일러를 공격부대에 편입시킨다
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatHydraliskSquad, BWAPI::UnitTypes::Zerg_Hydralisk);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker);
			moveUnitBetweenSquad(&ambushCombatLurkerSquad, &mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker);
			moveUnitBetweenSquad(&multiObstructLurkerSquad, &mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatUltraliskSquad, BWAPI::UnitTypes::Zerg_Ultralisk);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatQueenSquad, BWAPI::UnitTypes::Zerg_Queen);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatDefilerSquad, BWAPI::UnitTypes::Zerg_Defiler);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatScourgeSquad, BWAPI::UnitTypes::Zerg_Scourge);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatMutaliskSquad, BWAPI::UnitTypes::Zerg_Mutalisk);

			// 오버로드 1기씩 각 부대에 편입시킨다
			// TODO : 오버로드 움직임을 제어해야함. 안그러면 오버로드 계속 이동하다가 죽음
			if (getUnitNumberInSquad(&mainCombatZerglingSquad, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
				moveUnitBetweenSquad(&reservedSquad, &mainCombatZerglingSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			if (getUnitNumberInSquad(&mainCombatHydraliskSquad, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
				moveUnitBetweenSquad(&reservedSquad, &mainCombatHydraliskSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			if (getUnitNumberInSquad(&mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
				moveUnitBetweenSquad(&reservedSquad, &mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			if (getUnitNumberInSquad(&mainCombatDefilerSquad, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
				moveUnitBetweenSquad(&reservedSquad, &mainCombatDefilerSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
		}



		if (task->taskGoal == TaskGoalType::Attack_Enemy_BaseLocation_With_Mutalisk) {

			/*
			// 오버로드 1기를 편입시킨다
			if (mainCombatMutaliskSquad.unitset.size() > 0) {

			bool isOverlordContained = false;
			for (auto & unit : mainCombatMutaliskSquad.unitset) {
			if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord) {
			isOverlordContained = true;
			}
			}

			double minDistance = 1000000000;
			double tempDistance = 0;
			BWAPI::Unit minDistanceOverlord = nullptr;
			for (auto & unit : reservedSquad.unitset) {
			if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord) {
			tempDistance = unit->getDistance(myMainBaseLocation->getPosition());
			if (minDistance > tempDistance) {
			minDistance = tempDistance;
			minDistanceOverlord = unit;
			}
			}
			}

			if (minDistanceOverlord != nullptr) {
			moveUnitBetweenSquad(&mainCombatMutaliskSquad, &reservedSquad, BWAPI::UnitTypes::Zerg_Overlord);
			moveUnitBetweenSquad(&reservedSquad, &mainCombatMutaliskSquad, BWAPI::UnitTypes::Zerg_Overlord, 1, minDistanceOverlord);
			}
			}
			*/

		}

		if (task->taskGoal == TaskGoalType::Attack_With_Lurker_Drop) {
		}

		if (task->taskGoal == TaskGoalType::Eliminate_Enemy_Player) {

			// 모든 저글링, 히드라, 러커, 울트라리스크, 디파일러를 공격부대에 편입시킨다
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling);
			moveUnitBetweenSquad(&multiObstructZerglingSquad, &mainCombatZerglingSquad, BWAPI::UnitTypes::Zerg_Zergling);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatHydraliskSquad, BWAPI::UnitTypes::Zerg_Hydralisk);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker);
			moveUnitBetweenSquad(&multiObstructLurkerSquad, &mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker);
			moveUnitBetweenSquad(&ambushCombatLurkerSquad, &mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Lurker);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatUltraliskSquad, BWAPI::UnitTypes::Zerg_Ultralisk);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatQueenSquad, BWAPI::UnitTypes::Zerg_Queen);
			moveUnitBetweenSquad(&mainBaseDefenseSquad, &mainCombatDefilerSquad, BWAPI::UnitTypes::Zerg_Defiler);

			/*
			// 오버로드 1기씩 각 부대에 편입시킨다
			// TODO : 오버로드 움직임을 제어해야함. 안그러면 오버로드 계속 이동하다가 죽음
			if (getUnitNumberInSquad(&mainCombatZerglingSquad, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
			moveUnitBetweenSquad(&reservedSquad, &mainCombatZerglingSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			if (getUnitNumberInSquad(&mainCombatHydraliskSquad, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
			moveUnitBetweenSquad(&reservedSquad, &mainCombatHydraliskSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			if (getUnitNumberInSquad(&mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
			moveUnitBetweenSquad(&reservedSquad, &mainCombatLurkerSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			if (getUnitNumberInSquad(&mainCombatUltraliskSquad, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
			moveUnitBetweenSquad(&reservedSquad, &mainCombatUltraliskSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			if (getUnitNumberInSquad(&mainCombatDefilerSquad, BWAPI::UnitTypes::Zerg_Overlord) == 0) {
			moveUnitBetweenSquad(&reservedSquad, &mainCombatDefilerSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			*/
		}

		// 멀티
		if (task->taskGoal == TaskGoalType::Build_Expansion_On_Ground){

			// 드론은 BuildManager 가 지정

			// 오버로드 1기 추가
			if (getUnitNumberInSquad(&newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Overlord) < 1) {
				moveUnitBetweenSquad(&reservedSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}

			// 뮤탈 1기 추가
			if (getUnitNumberInSquad(&newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Mutalisk) < 1) {
				moveUnitBetweenSquad(&mainCombatMutaliskSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Mutalisk);
			}

			// 저글링 1기 추가
			// 저글링을 나중에 빼내야 한다
			//if (getUnitNumberInSquad(&newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Zergling) < 1) {
			//	moveUnitBetweenSquad(&mainBaseDefenseSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Zergling);
			//}

		}
		else if (task->taskGoal == TaskGoalType::Build_Expansion_On_Island) {

			/*

			if (myMainBaseLocation != nullptr && enemyMainBaseLocation != nullptr) {

			if (task->targetPosition != BWAPI::Positions::None) {

			int dangerousLevel = (int)(task->targetPosition.getDistance(myMainBaseLocation->getPosition()) - task->targetPosition.getDistance(enemyMainBaseLocation->getPosition()));

			int droneUnitCount = 0;
			int overlordUnitCount = 0;
			int zerglingUnitCount = 0;
			int hydraliskUnitCount = 0;

			int droneUnitCountMax = 1;
			int overlordUnitCountMax = 0;
			int zerglingUnitCountMax = 0;
			int hydraliskUnitCountMax = 0;

			if (dangerousLevel < -1000) {
			droneUnitCountMax = 1;
			overlordUnitCountMax = 0;
			zerglingUnitCountMax = 0;
			hydraliskUnitCountMax = 0;
			}
			else if (dangerousLevel < -100) {
			droneUnitCountMax = 2;
			overlordUnitCountMax = 1;
			zerglingUnitCountMax = 2;
			hydraliskUnitCountMax = 0;
			}
			else if (dangerousLevel >= -100) {
			droneUnitCountMax = 2;
			overlordUnitCountMax = 1;
			zerglingUnitCountMax = 2;
			hydraliskUnitCountMax = 2;
			}

			for (auto & unit : newExpansionSetupSquad.unitset) {
			if (unit->getType() == BWAPI::UnitTypes::Zerg_Drone) droneUnitCount++;
			else if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord) overlordUnitCount++;
			else if (unit->getType() == BWAPI::UnitTypes::Zerg_Zergling) zerglingUnitCount++;
			else if (unit->getType() == BWAPI::UnitTypes::Zerg_Hydralisk) hydraliskUnitCount++;
			}

			if (droneUnitCount < droneUnitCountMax) {
			moveUnitBetweenSquad(&reservedSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Drone);
			}
			if (overlordUnitCount < overlordUnitCountMax) {
			moveUnitBetweenSquad(&reservedSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			if (zerglingUnitCount < zerglingUnitCountMax) {
			moveUnitBetweenSquad(&reservedSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Zergling);
			}
			if (hydraliskUnitCount < hydraliskUnitCountMax) {
			moveUnitBetweenSquad(&mainBaseClearSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Hydralisk);
			}

			droneUnitCount = 0;
			overlordUnitCount = 0;
			zerglingUnitCount = 0;
			hydraliskUnitCount = 0;
			for (auto & unit : newExpansionSetupSquad.unitset) {
			if (unit->getType() == BWAPI::UnitTypes::Zerg_Drone) droneUnitCount++;
			else if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord) overlordUnitCount++;
			else if (unit->getType() == BWAPI::UnitTypes::Zerg_Zergling) zerglingUnitCount++;
			else if (unit->getType() == BWAPI::UnitTypes::Zerg_Hydralisk) hydraliskUnitCount++;
			}

			if (overlordUnitCount < zerglingUnitCountMax) {
			moveUnitBetweenSquad(&scoutOverlordSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Overlord);
			}
			if (zerglingUnitCount < zerglingUnitCountMax) {
			moveUnitBetweenSquad(&mainBaseClearSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Zergling);
			}

			if (hydraliskUnitCount < hydraliskUnitCountMax) {
			moveUnitBetweenSquad(&reservedSquad, &newExpansionSetupSquad, BWAPI::UnitTypes::Zerg_Hydralisk);
			}

			droneUnitCount = 0;
			overlordUnitCount = 0;
			zerglingUnitCount = 0;
			hydraliskUnitCount = 0;

			std::cout << "newExpansionSetupSquad " << newExpansionSetupSquad.unitset.size() << " to " << task->targetPosition.x / TILE_SIZE << ", " << task->targetPosition.y / TILE_SIZE << std::endl;

			for (auto & unit : newExpansionSetupSquad.unitset) {
			if (unit->getType() == BWAPI::UnitTypes::Zerg_Drone) droneUnitCount++;
			else if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord) overlordUnitCount++;
			else if (unit->getType() == BWAPI::UnitTypes::Zerg_Zergling) zerglingUnitCount++;
			else if (unit->getType() == BWAPI::UnitTypes::Zerg_Hydralisk) hydraliskUnitCount++;
			}
			*/
		}

	}

	// Task 가 없는 Squad 는 해체한다
	//breakUpSquadsThatHasNoTask();
}


void StrategyManager::executeScout()
{
	Strategy_ScoutTaskManager::Instance().update();
}

void StrategyManager::executeBuild()
{
	Strategy_BuildTaskManager::Instance().update();
}


void StrategyManager::executeCombat()
{
	Strategy_CombatTaskManager::Instance().update();
}

void StrategyManager::executeExpansion()
{
	// 일꾼이 충분히 생산되어 2개의 BaseLocation 이 원활히 돌아가고 있을때 일꾼 1마리로 개척
	if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Drone) > 16) {
		clearFakeMineral();
	}

	Strategy_ExpansionTaskManager::Instance().update();
}

void StrategyManager::setWord()
{
	words.push_back("Psalms #23");
	words.push_back("The LORD is my shepherd, I shall not be in want.");
	words.push_back("He makes me lie down in green pastures, he leads me beside quiet waters,");
	words.push_back("he restores my soul. He guides me in paths of righteousness for his name's sake.");
	words.push_back("Even though I walk through the valley of the shadow of death, I will fear no evil, for you are with me; your rod and your staff, they comfort me.");
	words.push_back("You prepare a table before me in the presence of my enemies. You anoint my head with oil; my cup overflows.");
	words.push_back("Surely goodness and love will follow me all the days of my life, and I will dwell in the house of the LORD forever.");
}

void StrategyManager::sendWord()
{
	for (size_t i = 0; i < words.size(); i++) {
		if (BWAPI::Broodwar->getFrameCount() == 24 * (60 + i * 3 )) {
			BWAPI::Broodwar->sendText("%s", words[i].c_str());
		}
	}


}

