#include <queue>

#include "CombatCommander.h"

#include "Bases.h"
#include "MapGrid.h"
#include "Micro.h"
#include "Random.h"
#include "UnitUtil.h"
#include "MapTools.h"////spider
#include "ProductionManager.h"


using namespace UAlbertaBot;

// Squad priorities: Which can steal units from others.
// Anyone can steal from the Idle squad.
const size_t IdlePriority = 0;
const size_t OverlordPriority = 1;
const size_t AttackPriority = 2;
const size_t LinePriority = 3;//8.18.2019
const size_t ReconPriority = 4;
const size_t WatchPriority = 5;
const size_t BaseDefensePriority = 6;
const size_t ScoutDefensePriority = 7;
const size_t DropPriority = 8;			// don't steal from Drop squad for anything else
const size_t ScourgePriority = 9;		// scourge go in the Scourge squad, nowhere else

// The attack squads.
const int DefendFrontRadius = 400;
const int AttackRadius = 800;

// Reconnaissance squad.
const int ReconTargetTimeout = 40 * 24;
const int ReconRadius = 400;

CombatCommander::CombatCommander()
	: the(The::Root())
	, _initialized(false)
	, _goAggressive(true)
	, _reconTarget(BWAPI::Positions::Invalid)   // it will be changed later
	, _lastReconTargetChange(0)
{
}

// Called once at the start of the game.
// You can also create new squads at other times.
void CombatCommander::initializeSquads()
{
	// The idle squad includes workers at work (not idle at all) and unassigned overlords.
	SquadOrder idleOrder(SquadOrderTypes::Idle, BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()), 100, "Chill out");
	_squadData.createSquad("Idle", idleOrder, IdlePriority);

	// These squads don't care what order they are given.
	// They analyze the situation for themselves.
	if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Zerg)
	{
		SquadOrder emptyOrder(SquadOrderTypes::Idle, BWAPI::Positions::Origin, 0, "React");

		// The overlord squad has only overlords, but not all overlords:
		// They may be assigned elsewhere too.
		_squadData.createSquad("Overlord", emptyOrder, OverlordPriority);

		// The scourge squad has all the scourge.
		if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Zerg)
		{
			_squadData.createSquad("Scourge", emptyOrder, ScourgePriority);
		}
	}

	// The ground squad will pressure an enemy base.
	SquadOrder attackOrder(getAttackOrder(nullptr));
	_squadData.createSquad("Ground", attackOrder, AttackPriority);

	// The flying squad separates air units so they can act independently.
	_squadData.createSquad("Flying", attackOrder, AttackPriority);

	// The recon squad carries out reconnaissance in force to deny enemy bases.
	// It is filled in when enough units are available.
	_squadData.createSquad("Recon", idleOrder, WatchPriority);//8.14.2019//提升一级侦察单位的优先级
	Squad & reconSquad = _squadData.getSquad("Recon");
	reconSquad.setCombatSimRadius(200);  // combat sim includes units in a smaller radius than for a combat squad
	reconSquad.setFightVisible(true);    // combat sim sees only visible enemy units (not all known enemies)

	BWAPI::Position ourBasePosition = BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation());

	// the scout defense squad will handle chasing the enemy worker scout
	if (Config::Micro::ScoutDefenseRadius > 0)
	{
		SquadOrder enemyScoutDefense(SquadOrderTypes::Defend, ourBasePosition, Config::Micro::ScoutDefenseRadius, "Get the scout");
		_squadData.createSquad("ScoutDefense", enemyScoutDefense, ScoutDefensePriority);
	}

	// If we're expecting to drop, create a drop squad.
	// It is initially ordered to hold ground until it can load up and go.
	if (StrategyManager::Instance().dropIsPlanned())
	{
		SquadOrder doDrop(SquadOrderTypes::Hold, ourBasePosition, AttackRadius, "Wait for transport");
		_squadData.createSquad("Drop", doDrop, DropPriority);
	}
}

void CombatCommander::update(const BWAPI::Unitset & combatUnits)
{
	if (!_initialized)
	{
		initializeSquads();
		_initialized = true;
	}

	int frame8 = BWAPI::Broodwar->getFrameCount() % 8;

	_combatUnits = combatUnits;

	updateDefenseLine(); //更新防守阵线的位置
	updateAttackEnemyBase();
	updateAggression(); //判断是否进攻

	updateBarracks();

	if (frame8 == 1)
	{
		updateIdleSquad();
		//updateOverlordSquad();
		updateScourgeSquad();
		//updateDropSquads();
		updateScoutDefenseSquad();
		updateBaseDefenseSquads();
		//updateWatchSquads();
		//updateReconSquad();
	    updateScoutSquad();
		updateScvScoutSquad();
		updateFindingEnemyBaseSquad();
		///////////////////////++
		//updateStartingBaseDefenseSquad();
		//updateBunkerSquad();
		//updateChokeSquads();
		//updatePioneerSquad();
		//updateTankSquads();
		//updateFrontSquads();
		///////////////////////__
		//updateAttackSquads();
	}
	else if (frame8 % 4 == 2)
	{
		doComsatScan();
	}

	loadOrUnloadBunkers();

	//the.ops.update();

	_squadData.update();          // update() all the squads

	cancelDyingItems();
}

void CombatCommander::updateIdleSquad()
{
	Squad & idleSquad = _squadData.getSquad("Idle");
	for (const auto unit : _combatUnits)
	{
		// if it hasn't been assigned to a squad yet, put it in the low priority idle squad
		if (_squadData.canAssignUnitToSquad(unit, idleSquad))
		{
			_squadData.assignUnitToSquad(unit, idleSquad);
		}
	}
}

// Put all overlords which are not otherwise assigned into the Overlord squad.
void CombatCommander::updateOverlordSquad()
{
	// If we don't have an overlord squad, then do nothing.
	// It is created in initializeSquads().
	if (!_squadData.squadExists("Overlord"))
	{
		return;
	}

	Squad & ovieSquad = _squadData.getSquad("Overlord");
	for (const auto unit : _combatUnits)
	{
		if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord && _squadData.canAssignUnitToSquad(unit, ovieSquad))
		{
			_squadData.assignUnitToSquad(unit, ovieSquad);
		}
	}
}

void CombatCommander::chooseScourgeTarget(const Squad & sourgeSquad)
{
	BWAPI::Position center = sourgeSquad.calcCenter();

	BWAPI::Position bestTarget = Bases::Instance().myStartingBase()->getPosition();
	int bestScore = -99999;

	for (const auto & kv : InformationManager::Instance().getUnitData(BWAPI::Broodwar->enemy()).getUnits())
	{
		const UnitInfo & ui(kv.second);

		// Skip ground units and units known to have moved away some time ago.
		if (!ui.type.isFlyer() ||
			ui.goneFromLastPosition && BWAPI::Broodwar->getFrameCount() - ui.updateFrame < 5 * 24)
		{
			continue;
		}

		int score = MicroScourge::getAttackPriority(ui.type);

		if (ui.unit && ui.unit->isVisible())
		{
			score += 2;
		}

		// Each score increment is worth 2 tiles of distance.
		const int distance = center.getApproxDistance(ui.lastPosition);
		score = 2 * score - distance / 32;
		if (score > bestScore)
		{
			bestTarget = ui.lastPosition;
			bestScore = score;
		}
	}

	_scourgeTarget = bestTarget;
}

// Put all scourge into the Scourge squad.
void CombatCommander::updateScourgeSquad()
{
	// If we don't have a scourge squad, then do nothing.
	// It is created in initializeSquads().
	if (!_squadData.squadExists("Scourge"))
	{
		return;
	}

	Squad & scourgeSquad = _squadData.getSquad("Scourge");

	for (const auto unit : _combatUnits)
	{
		if (unit->getType() == BWAPI::UnitTypes::Zerg_Scourge && _squadData.canAssignUnitToSquad(unit, scourgeSquad))
		{
			_squadData.assignUnitToSquad(unit, scourgeSquad);
		}
	}

	// We want an overlord to come along if the enemy has arbiters or cloaked wraiths,
	// but only if we have overlord speed.
	bool wantDetector =
		BWAPI::Broodwar->self()->getUpgradeLevel(BWAPI::UpgradeTypes::Pneumatized_Carapace) > 0 &&
		InformationManager::Instance().enemyHasAirCloakTech();
	maybeAssignDetector(scourgeSquad, wantDetector);

	// Issue the order.
	chooseScourgeTarget(scourgeSquad);
	SquadOrder scourgeOrder(SquadOrderTypes::OmniAttack, _scourgeTarget, 300, "Air defense");
	scourgeSquad.setSquadOrder(scourgeOrder);
}

// Update the watch squads, which set a sentry in each free base to see enemy expansions
// and possibly stop them. It also clears spider mines as a side effect.
// A free base may get a watch squad with up to 1 zergling and 1 overlord.
// For now, only zerg keeps watch squads, and only when units are available.
void CombatCommander::updateWatchSquads()
{
	// TODO Disabled because it is not in a useful state.
	return;

	// Only if we're zerg.
	if (BWAPI::Broodwar->self()->getRace() != BWAPI::Races::Zerg)
	{
		return;
	}

	// Number of zerglings. Whether to assign overlords--other races can't afford so many detectors.
	int maxWatchers = BWAPI::Broodwar->enemy()->getRace() == BWAPI::Races::Zerg
		? 0
		: UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Zerg_Zergling) - 18;
	const bool wantDetector = wantSquadDetectors();

	for (Base * base : Bases::Instance().getBases())
	{
		std::stringstream squadName;
		BWAPI::TilePosition tile(base->getTilePosition() + BWAPI::TilePosition(2, 1));
		squadName << "Watch " << tile.x << "," << tile.y;

		bool wantWatcher =
			maxWatchers > 0 &&
			base->getOwner() == BWAPI::Broodwar->neutral() &&
			Bases::Instance().connectedToStart(tile) &&
			!base->isReserved();

		if (!wantDetector && !wantWatcher && !_squadData.squadExists(squadName.str()))
		{
			continue;
		}

		// We need the squad object. Create it if it's not already there.
		if (!_squadData.squadExists(squadName.str()))
		{
			SquadOrder watchOrder(SquadOrderTypes::Watch, BWAPI::Position(tile), 0, "Watch");
			_squadData.createSquad(squadName.str(), watchOrder, WatchPriority);
		}
		Squad & watchSquad = _squadData.getSquad(squadName.str());

		// Add or remove the squad's watcher unit, or sentry.
		bool hasWatcher = watchSquad.containsUnitType(BWAPI::UnitTypes::Zerg_Zergling);

		if (hasWatcher && !wantWatcher)
		{
			for (BWAPI::Unit unit : watchSquad.getUnits())
			{
				if (unit->getType() == BWAPI::UnitTypes::Zerg_Zergling)
				{
					watchSquad.removeUnit(unit);
					break;
				}
			}
		}
		else if (!hasWatcher && wantWatcher)
		{
			for (BWAPI::Unit unit : _combatUnits)
			{
				if (unit->getType() == BWAPI::UnitTypes::Zerg_Zergling && _squadData.canAssignUnitToSquad(unit, watchSquad))
				{
					_squadData.assignUnitToSquad(unit, watchSquad);
					--maxWatchers;		// we used one up
					break;
				}
			}
		}

		maybeAssignDetector(watchSquad, wantDetector);

		// Drop the squad if it is no longer needed. Don't clutter the squad display.
		if (watchSquad.isEmpty())
		{
			_squadData.removeSquad(squadName.str());
		}
	}
}

// Update the small recon squad which tries to find and deny enemy bases.
// Units available to the recon squad each have a "weight".
// Weights sum to no more than maxWeight, set below.
void CombatCommander::updateReconSquad()
{
	const int maxWeight = 12;
	Squad & reconSquad = _squadData.getSquad("Recon");

	chooseReconTarget();

	// If nowhere needs seeing, disband the squad. We're done.
	// It can happen that the Watch squad sees all bases, meeting this condition.
	if (!_reconTarget.isValid())
	{
		reconSquad.clear();
		return;
	}

	// Issue the order.
	SquadOrder reconOrder(SquadOrderTypes::Attack, _reconTarget, ReconRadius, "Reconnaissance in force");
	reconSquad.setSquadOrder(reconOrder);

	// Special case: If we started on an island, then the recon squad consists
	// entirely of one flying detector. (Life is easy for zerg, hard for terran.)
	if (Bases::Instance().isIslandStart())
	{
		if (reconSquad.getUnits().size() == 0)
		{
			for (const auto unit : _combatUnits)
			{
				if (unit->getType().isDetector() && _squadData.canAssignUnitToSquad(unit, reconSquad))
				{
					_squadData.assignUnitToSquad(unit, reconSquad);
					break;
				}
			}
		}
		return;
	}

	// What is already in the squad?
	int squadWeight = 0;
	int nMarines = 0;
	int nMedics = 0;
	for (const auto unit : reconSquad.getUnits())
	{
		squadWeight += weighReconUnit(unit);
		if (unit->getType() == BWAPI::UnitTypes::Terran_Marine)
		{
			++nMarines;
		}
		else if (unit->getType() == BWAPI::UnitTypes::Terran_Medic)
		{
			++nMedics;
		}
	}

	// If everything except the detector is gone, let the detector go too.
	// It can't carry out reconnaissance in force.
	if (squadWeight == 0 && !reconSquad.isEmpty())
	{
		reconSquad.clear();
	}

	// What is available to put into the squad?
	int availableWeight = 0;
	for (const auto unit : _combatUnits)
	{
		availableWeight += weighReconUnit(unit);
	}

	// The allowed weight of the recon squad. It should steal few units.
	int weightLimit = availableWeight >= 24
		? 2 + (availableWeight - 24) / 6
		: 0;
	if (weightLimit > maxWeight)
	{
		weightLimit = maxWeight;
	}

	// If the recon squad weighs more than it should, clear it and continue.
	// Also if all marines are gone, but medics remain.
	// Units will be added back in if they should be.
	if (squadWeight > weightLimit ||
		nMarines == 0 && nMedics > 0)
	{
		reconSquad.clear();
		squadWeight = 0;
		nMarines = nMedics = 0;
	}

	bool hasDetector = reconSquad.hasDetector();
	bool wantDetector = wantSquadDetectors();

	if (hasDetector && !wantDetector)
	{
		for (BWAPI::Unit unit : reconSquad.getUnits())
		{
			if (unit->getType().isDetector())
			{
				reconSquad.removeUnit(unit);
				break;
			}
		}
		hasDetector = false;
	}

	// Add units up to the weight limit.
	// In this loop, add no medics, and few enough marines to allow for 2 medics.
	for (const auto unit : _combatUnits)
	{
		if (squadWeight >= weightLimit)
		{
			break;
		}
		BWAPI::UnitType type = unit->getType();
		int weight = weighReconUnit(type);
		if (weight > 0 && squadWeight + weight <= weightLimit && _squadData.canAssignUnitToSquad(unit, reconSquad))
		{
			if (type == BWAPI::UnitTypes::Terran_Marine && !unit->isLoaded())
			{
				if (nMarines * weight < maxWeight - 2 * weighReconUnit(BWAPI::UnitTypes::Terran_Medic))
				{
					_squadData.assignUnitToSquad(unit, reconSquad);
					squadWeight += weight;
					nMarines += 1;
				}
			}
			else if (type != BWAPI::UnitTypes::Terran_Medic)
			{
				_squadData.assignUnitToSquad(unit, reconSquad);
				squadWeight += weight;
			}
		}
		else if (type.isDetector() && wantDetector && !hasDetector && _squadData.canAssignUnitToSquad(unit, reconSquad))
		{
			_squadData.assignUnitToSquad(unit, reconSquad);
			hasDetector = true;
		}
	}

	// Finally, fill in any needed medics.
	if (nMarines > 0 && nMedics < 2)
	{
		for (const auto unit : _combatUnits)
		{
			if (squadWeight >= weightLimit || nMedics >= 2)
			{
				break;
			}
			if (unit->getType() == BWAPI::UnitTypes::Terran_Medic &&
				_squadData.canAssignUnitToSquad(unit, reconSquad))
			{
				_squadData.assignUnitToSquad(unit, reconSquad);
				squadWeight += weighReconUnit(BWAPI::UnitTypes::Terran_Medic);
				nMedics += 1;
			}
		}
	}
}

// The recon squad is allowed up to a certain "weight" of units.
int CombatCommander::weighReconUnit(const BWAPI::Unit unit) const
{
	return weighReconUnit(unit->getType());
}

// The recon squad is allowed up to a certain "weight" of units.
int CombatCommander::weighReconUnit(const BWAPI::UnitType type) const
{
	if (type == BWAPI::UnitTypes::Zerg_Zergling) return 2;
	if (type == BWAPI::UnitTypes::Zerg_Hydralisk) return 3;
	if (type == BWAPI::UnitTypes::Terran_Marine) return 2;
	if (type == BWAPI::UnitTypes::Terran_Medic) return 2;
	if (type == BWAPI::UnitTypes::Terran_Vulture) return 4;
	if (type == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode) return 6;
	if (type == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode) return 6;
	if (type == BWAPI::UnitTypes::Protoss_Zealot) return 4;
	if (type == BWAPI::UnitTypes::Protoss_Dragoon) return 4;
	if (type == BWAPI::UnitTypes::Protoss_Dark_Templar) return 4;

	return 0;
}

// Keep the same reconnaissance target or switch to a new one, depending.
void CombatCommander::chooseReconTarget()
{
	bool change = false;       // switch targets?

	BWAPI::Position nextTarget = getReconLocation();

	// There is nowhere that we need to see. Change to the invalid target.
	if (!nextTarget.isValid())
	{
		change = true;
	}

	// If the current target is invalid, we're starting up.
	else if (!_reconTarget.isValid())
	{
		change = true;
	}

	// If we have spent too long on one target, then probably we haven't been able to reach it.
	else if (BWAPI::Broodwar->getFrameCount() - _lastReconTargetChange >= ReconTargetTimeout)
	{
		change = true;
	}

	// If the target is in sight (of any unit, not only the recon squad) and empty of enemies, we're done.
	else if (BWAPI::Broodwar->isVisible(_reconTarget.x / 32, _reconTarget.y / 32))
	{
		BWAPI::Unitset enemies;
		MapGrid::Instance().getUnits(enemies, _reconTarget, ReconRadius, false, true);
		// We don't particularly care about air units, even when we could engage them.
		for (auto it = enemies.begin(); it != enemies.end();)
		{
			if ((*it)->isFlying())
			{
				it = enemies.erase(it);
			}
			else
			{
				++it;
			}
		}
		if (enemies.empty())
		{
			change = true;
		}
	}

	if (change)
	{
		_reconTarget = nextTarget;
		_lastReconTargetChange = BWAPI::Broodwar->getFrameCount();
	}
}

// Choose an empty base location for the recon squad to check out.
// Called only by setReconTarget().
BWAPI::Position CombatCommander::getReconLocation() const
{
	std::vector<Base *> choices;

	BWAPI::Position startPosition = Bases::Instance().myStartingBase()->getPosition();

	// The choices are neutral bases reachable by ground.
	// Or, if we started on an island, the choices are neutral bases anywhere.
	for (Base * base : Bases::Instance().getBases())
	{
		if (base->owner == BWAPI::Broodwar->neutral() &&
			(Bases::Instance().isIslandStart() || Bases::Instance().connectedToStart(base->getTilePosition())))
		{
			choices.push_back(base);
		}
	}

	// BWAPI::Broodwar->printf("%d recon squad choices", choices.size());

	// If there are none, return an invalid position.
	if (choices.empty())
	{
		return BWAPI::Positions::Invalid;
	}

	// Choose randomly.
	// We may choose the same target we already have. That's OK; if there's another choice,
	// we'll probably switch to it soon.
	Base * base = choices.at(Random::Instance().index(choices.size()));
	return base->getPosition();
}

// Form the ground squad and the flying squad, the main attack squads.
// NOTE Arbiters and guardians go into the ground squad.
//      Devourers and carriers are flying squad if it exists, otherwise ground.
//      Other air units always go into the flying squad.
void CombatCommander::updateAttackSquads()
{
	Squad & groundSquad = _squadData.getSquad("Ground");
	Squad & flyingSquad = _squadData.getSquad("Flying");

	bool groundSquadExists = groundSquad.hasCombatUnits();

	bool flyingSquadExists = false;
	for (const auto unit : flyingSquad.getUnits())
	{
		if (isFlyingSquadUnit(unit->getType()))
		{
			flyingSquadExists = true;
			break;
		}
	}

	for (const auto unit : _combatUnits)
	{
		if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine)continue;

		if (isFlyingSquadUnit(unit->getType()))
		{
			if (_squadData.canAssignUnitToSquad(unit, flyingSquad))
			{
				_squadData.assignUnitToSquad(unit, flyingSquad);
			}
		}

		// Certain flyers go into the flying squad only if it already exists.
		// Otherwise they go into the ground squad.
		else if (isOptionalFlyingSquadUnit(unit->getType()))
		{
			if (flyingSquadExists)
			{
				if (groundSquad.containsUnit(unit))
				{
					groundSquad.removeUnit(unit);
				}
				if (_squadData.canAssignUnitToSquad(unit, flyingSquad))
				{
					_squadData.assignUnitToSquad(unit, flyingSquad);
				}
			}
			else
			{
				if (flyingSquad.containsUnit(unit))
				{
					flyingSquad.removeUnit(unit);
				}
				if (_squadData.canAssignUnitToSquad(unit, groundSquad))
				{
					_squadData.assignUnitToSquad(unit, groundSquad);
				}
			}
		}

		// isGroundSquadUnit() is defined as a catchall, so it has to go last.
		else if (isGroundSquadUnit(unit->getType()))
		{
			if (_squadData.canAssignUnitToSquad(unit, groundSquad))
			{
				_squadData.assignUnitToSquad(unit, groundSquad);
			}
		}
	}

	// Add or remove detectors.
	bool wantDetector = wantSquadDetectors();
	maybeAssignDetector(groundSquad, wantDetector);
	maybeAssignDetector(flyingSquad, wantDetector);

	SquadOrder groundAttackOrder(getAttackOrder(&groundSquad));
	groundSquad.setSquadOrder(groundAttackOrder);

	SquadOrder flyingAttackOrder(getAttackOrder(&flyingSquad));
	flyingSquad.setSquadOrder(flyingAttackOrder);

}

// Unit definitely belongs in the Flying squad.
bool CombatCommander::isFlyingSquadUnit(const BWAPI::UnitType type) const
{
	return
		type == BWAPI::UnitTypes::Zerg_Mutalisk ||
		type == BWAPI::UnitTypes::Terran_Wraith ||
		type == BWAPI::UnitTypes::Terran_Valkyrie ||
		type == BWAPI::UnitTypes::Terran_Battlecruiser ||
		type == BWAPI::UnitTypes::Protoss_Corsair ||
		type == BWAPI::UnitTypes::Protoss_Scout;
}

// Unit belongs in the Flying squad if the Flying squad exists, otherwise the Ground squad.
bool CombatCommander::isOptionalFlyingSquadUnit(const BWAPI::UnitType type) const
{
	return
		type == BWAPI::UnitTypes::Zerg_Devourer ||
		type == BWAPI::UnitTypes::Protoss_Carrier;
}

// Unit belongs in the ground squad.
// With the current definition, it includes everything except workers, so it captures
// everything that is not already taken. It must be the last condition checked.
bool CombatCommander::isGroundSquadUnit(const BWAPI::UnitType type) const
{
	return
		!type.isDetector() &&
		!type.isWorker();
}

// Despite the name, this supports only 1 drop squad which has 1 transport.
// Furthermore, it can only drop once and doesn't know how to reset itself to try again.
// Still, it's a start and it can be effective.
void CombatCommander::updateDropSquads()
{
	// If we don't have a drop squad, then we don't want to drop.
	// It is created in initializeSquads().
	if (!_squadData.squadExists("Drop"))
	{
		return;
	}

	Squad & dropSquad = _squadData.getSquad("Drop");

	// The squad is initialized with a Hold order.
	// There are 3 phases, and in each phase the squad is given a different order:
	// Collect units (Hold); load the transport (Load); go drop (Drop).

	if (dropSquad.getSquadOrder().getType() == SquadOrderTypes::Drop)
	{
		// If it has already been told to Drop, we issue a new drop order in case the
		// target has changed.
		/* TODO not yet supported by the drop code
		SquadOrder dropOrder = SquadOrder(SquadOrderTypes::Drop, getDropLocation(dropSquad), 300, "Go drop!");
		dropSquad.setSquadOrder(dropOrder);
		*/
		return;
	}

	// If we get here, we haven't been ordered to Drop yet.

	// What units do we have, what units do we need?
	BWAPI::Unit transportUnit = nullptr;
	int transportSpotsRemaining = 8;      // all transports are the same size
	bool anyUnloadedUnits = false;
	const auto & dropUnits = dropSquad.getUnits();

	for (const auto unit : dropUnits)
	{
		if (unit->exists())
		{
			if (unit->isFlying() && unit->getType().spaceProvided() > 0)
			{
				transportUnit = unit;
			}
			else
			{
				transportSpotsRemaining -= unit->getType().spaceRequired();
				if (!unit->isLoaded())
				{
					anyUnloadedUnits = true;
				}
			}
		}
	}

	if (transportUnit && transportSpotsRemaining == 0)
	{
		if (anyUnloadedUnits)
		{
			// The drop squad is complete. Load up.
			// See Squad::loadTransport().
			SquadOrder loadOrder(SquadOrderTypes::Load, transportUnit->getPosition(), AttackRadius, "Load up");
			dropSquad.setSquadOrder(loadOrder);
		}
		else
		{
			// We're full. Change the order to Drop.
			SquadOrder dropOrder = SquadOrder(SquadOrderTypes::Drop, getDropLocation(dropSquad), 300, "Go drop!");
			dropSquad.setSquadOrder(dropOrder);
		}
	}
	else
	{
		// The drop squad is not complete. Look for more units.
		for (const auto unit : _combatUnits)
		{
			// If the squad doesn't have a transport, try to add one.
			if (!transportUnit &&
				unit->getType().spaceProvided() > 0 && unit->isFlying() &&
				_squadData.canAssignUnitToSquad(unit, dropSquad))
			{
				_squadData.assignUnitToSquad(unit, dropSquad);
				transportUnit = unit;
			}

			// If the unit fits and is good to drop, add it to the squad.
			// Rewrite unitIsGoodToDrop() to select the units of your choice to drop.
			// Simplest to stick to units that occupy the same space in a transport, to avoid difficulties
			// like "add zealot, add dragoon, can't add another dragoon--but transport is not full, can't go".
			else if (unit->getType().spaceRequired() <= transportSpotsRemaining &&
				unitIsGoodToDrop(unit) &&
				_squadData.canAssignUnitToSquad(unit, dropSquad))
			{
				_squadData.assignUnitToSquad(unit, dropSquad);
				transportSpotsRemaining -= unit->getType().spaceRequired();
			}
		}
	}
}

void CombatCommander::updateScoutDefenseSquad()
{
	if (Config::Micro::ScoutDefenseRadius == 0 || _combatUnits.empty())
	{
		return;
	}

	// Get the region of our starting base.
	BWTA::Region * myRegion = BWTA::getRegion(Bases::Instance().myStartingBase()->getTilePosition());
	if (!myRegion || !myRegion->getCenter().isValid())
	{
		return;
	}

	// Get all of the visible enemy units in this region.
	BWAPI::Unitset enemyUnitsInRegion;
	for (const auto unit : BWAPI::Broodwar->enemy()->getUnits())
	{
		if (BWTA::getRegion(unit->getTilePosition()) == myRegion)
		{
			enemyUnitsInRegion.insert(unit);
		}
	}

	Squad & scoutDefenseSquad = _squadData.getSquad("ScoutDefense");

	// Is exactly one enemy worker here?
	bool assignScoutDefender = enemyUnitsInRegion.size() == 1 && (*enemyUnitsInRegion.begin())->getType().isWorker();

	if (assignScoutDefender)
	{
		if (scoutDefenseSquad.isEmpty())
		{
			// The enemy worker to catch.
			BWAPI::Unit enemyWorker = *enemyUnitsInRegion.begin();

			BWAPI::Unit workerDefender = findClosestWorkerToTarget(_combatUnits, enemyWorker);

			if (workerDefender)
			{
				// grab it from the worker manager and put it in the squad
				if (_squadData.canAssignUnitToSquad(workerDefender, scoutDefenseSquad))
				{
					_squadData.assignUnitToSquad(workerDefender, scoutDefenseSquad);
				}
			}
		}
	}
	// Otherwise the squad should be empty. If not, make it so.
	else if (!scoutDefenseSquad.isEmpty())
	{
		scoutDefenseSquad.clear();
	}
}
//8.8.2019
void CombatCommander::updateResidentBaseSquad()
{
	if (_combatUnits.empty())
	{
		return;
	}

	for (Base * base : Bases::Instance().getBases())
	{
		std::stringstream squadName;
		squadName << "base " << base->getTilePosition().x << "," << base->getTilePosition().y;

		//排除非己方的基地、我方主基地和二基地
		if (base->getOwner() != BWAPI::Broodwar->self() ||
			base == Bases::Instance().myStartingBase() ||
			base == Bases::Instance().getSecondBase(false) ||
			_goAggressive ||
			((BWAPI::Broodwar->getFrameCount() / (24 * 60)) > 20) ||
			(defenseLine != InformationManager::Instance().getPosition("frontLine1") && defenseLine != InformationManager::Instance().getPosition("frontLine2")))
		{
			// Clear any defense squad.
			if (_squadData.squadExists(squadName.str()))
			{
				_squadData.removeSquad(squadName.str());
			}
			continue;
		}


		BWAPI::Position aimPosition;//队伍的防守点
		BWAPI::Position nearestChoke = BWTA::getNearestChokepoint(base->getPosition())->getCenter();
		//假如该基地附近有路口，把集结点设置在路口处
		if (base->getDistance(nearestChoke) < 800)
		{
			aimPosition = getNearPosition(nearestChoke, base->getPosition(), false, 200);
		}
		else
		{
			aimPosition = base->getPosition();
		}

		SquadOrder defendRegion(SquadOrderTypes::Defend, aimPosition, 600, "Defend base");
		if (_squadData.squadExists(squadName.str()))
		{
			_squadData.getSquad(squadName.str()).setSquadOrder(defendRegion);
		}
		else
		{
			_squadData.createSquad(squadName.str(), defendRegion, BaseDefensePriority);
		}

		Squad & defenseSquad = _squadData.getSquad(squadName.str());

		//计算需要添加的单位数量
		int TankNeeded = 1;
		int GoliathNeeded = 0;
		for (BWAPI::Unit unit : defenseSquad.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			{
				TankNeeded -= 1;

				if (unit->canSiege() && !unit->isMoving())
				{
					the.micro.Siege(unit);
				}
			}
			else if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath)
			{
				GoliathNeeded -= 1;
			}
			else
			{
				defenseSquad.removeUnit(unit);
			}
		}

		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if ((unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
				&& TankNeeded > 0 && _squadData.canAssignUnitToSquad(unit, defenseSquad))
			{
				_squadData.assignUnitToSquad(unit, defenseSquad);
				TankNeeded -= 1;
			}
			else if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath
				&& GoliathNeeded > 0 && _squadData.canAssignUnitToSquad(unit, defenseSquad))
			{
				_squadData.assignUnitToSquad(unit, defenseSquad);
				GoliathNeeded -= 1;
			}
			else if (TankNeeded == 0 && GoliathNeeded == 0)
			{
				break;
			}
		}
	}
}


void CombatCommander::updateBaseDefenseSquads()
{
	const int baseDefenseRadius = 600;
	const int baseDefenseHysteresis = 200;

	const int pullWorkerDistance = 256;//256
	const int pullWorkerHysteresis = 128;//128;

	if (_combatUnits.empty())
	{
		return;
	}

	for (Base * base : Bases::Instance().getBases())
	{
		std::stringstream squadName;
		squadName << "Base " << base->getTilePosition().x << "," << base->getTilePosition().y;

		// Don't defend inside the enemy region.
		// It will end badly when we are stealing gas or otherwise proxying.
		if (base->getOwner() != BWAPI::Broodwar->self())
		{
			// Clear any defense squad.
			if (_squadData.squadExists(squadName.str()))
			{
				_squadData.removeSquad(squadName.str());
			}
			continue;
		}

		// Start to defend when enemy comes within baseDefenseRadius.
		// Stop defending when enemy leaves baseDefenseRadius + baseDefenseHysteresis.
		const int defenseRadius = _squadData.squadExists(squadName.str())
			? baseDefenseRadius + baseDefenseHysteresis
			: baseDefenseRadius;

		BWTA::Region * region = BWTA::getRegion(base->getTilePosition());

		// Assume for now that workers at the base are not in danger.
		// We may prove otherwise below.
		base->setWorkerDanger(false);

		// Find any enemy units that are bothering us.
		// Also note how far away the closest one is.
		bool firstWorkerSkipped = false;
		int closestEnemyDistance = 99999;
		BWAPI::Unit closestEnemy = nullptr;
		int nEnemyWorkers = 0;
		int nEnemyGround = 0;
		int nEnemyAir = 0;
		bool enemyHitsGround = false;
		bool enemyHitsAir = false;
		bool enemyHasCloak = false;

		for (BWAPI::Unit unit : BWAPI::Broodwar->enemy()->getUnits())
		{
			const int dist = unit->getDistance(base->getPosition());
			if (dist < defenseRadius ||
				dist < defenseRadius + 300 && BWTA::getRegion(unit->getTilePosition()) == region)
			{
				if (dist < closestEnemyDistance)
				{
					closestEnemyDistance = dist;
					closestEnemy = unit;
				}
				if (unit->getType().isWorker())
				{
					++nEnemyWorkers;
				}
				else if (unit->isFlying())
				{
					if (unit->getType() == BWAPI::UnitTypes::Terran_Battlecruiser ||
						unit->getType() == BWAPI::UnitTypes::Protoss_Arbiter)
					{
						// NOTE Carriers don't need extra, they show interceptors.
						nEnemyAir += 3;
					}
					else
					{
						++nEnemyAir;
					}
				}
				else
				{
					// Workers don't count as ground units here.
					if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode ||
						unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode ||
						unit->getType() == BWAPI::UnitTypes::Protoss_Archon ||
						unit->getType() == BWAPI::UnitTypes::Protoss_Reaver ||
						unit->getType() == BWAPI::UnitTypes::Zerg_Lurker)
					{
						nEnemyGround += 2;
					}
					else
					{
						++nEnemyGround;
					}
				}
				if (UnitUtil::CanAttackGround(unit))
				{
					enemyHitsGround = true;
				}
				if (UnitUtil::CanAttackAir(unit))
				{
					enemyHitsAir = true;
				}
				if (unit->isBurrowed() ||
					unit->isCloaked() ||
					unit->getType().hasPermanentCloak() ||
					unit->getType() == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine ||
					unit->getType() == BWAPI::UnitTypes::Protoss_Arbiter ||
					unit->getType() == BWAPI::UnitTypes::Zerg_Lurker ||
					unit->getType() == BWAPI::UnitTypes::Zerg_Lurker_Egg)
				{
					enemyHasCloak = true;
				}
			}
		}


		if (!closestEnemy)
		{
			// No enemies. Drop the defense squad if we have one.
			if (_squadData.squadExists(squadName.str()))
			{
				_squadData.removeSquad(squadName.str());
			}
			continue;
		}


		// We need a defense squad. If there isn't one, create it.
		// Its goal is not the base location itself, but the enemy closest to it, to ensure
		// that defenders will get close enough to the enemy to act.
		SquadOrder defendRegion(SquadOrderTypes::Defend, closestEnemy->getPosition(), defenseRadius, "Defend base");
		if (_squadData.squadExists(squadName.str()))
		{
			_squadData.getSquad(squadName.str()).setSquadOrder(defendRegion);
		}
		else
		{
			_squadData.createSquad(squadName.str(), defendRegion, BaseDefensePriority);
		}

		Squad & defenseSquad = _squadData.getSquad(squadName.str());

		// Next, figure out how many units we need to assign.

		// A simpleminded way of figuring out how much defense we need.
		const int numDefendersPerEnemyUnit = 2;

		int flyingDefendersNeeded = numDefendersPerEnemyUnit * nEnemyAir;
		int groundDefendersNeeded = nEnemyWorkers + numDefendersPerEnemyUnit * nEnemyGround;

		// Count static defense as defenders.
		// Ignore bunkers; they're more complicated.
		// Cannons are double-counted as air and ground, which can be a mistake.
		bool sunkenDefender = false;
		for (const auto unit : BWAPI::Broodwar->self()->getUnits())
		{
			if ((unit->getType() == BWAPI::UnitTypes::Terran_Missile_Turret ||
				unit->getType() == BWAPI::UnitTypes::Protoss_Photon_Cannon ||
				unit->getType() == BWAPI::UnitTypes::Zerg_Spore_Colony) &&
				unit->isCompleted() && unit->isPowered() &&
				BWTA::getRegion(unit->getTilePosition()) == region)
			{
				flyingDefendersNeeded -= 2;
			}
			if ((unit->getType() == BWAPI::UnitTypes::Protoss_Photon_Cannon ||
				unit->getType() == BWAPI::UnitTypes::Zerg_Sunken_Colony) &&
				unit->isCompleted() && unit->isPowered() &&
				BWTA::getRegion(unit->getTilePosition()) == region)
			{
				sunkenDefender = true;
				groundDefendersNeeded -= 4;
			}
		}

		// Don't let the number of defenders go negative.
		flyingDefendersNeeded = nEnemyAir ? std::max(flyingDefendersNeeded, 2) : 0;
		if (nEnemyGround)
		{
			groundDefendersNeeded = std::max(groundDefendersNeeded, 2);
		}
		else if (nEnemyWorkers)
		{
			// Workers only, no other attackers.
			groundDefendersNeeded = std::max(groundDefendersNeeded, 1 + nEnemyWorkers / 2);
		}
		else
		{
			groundDefendersNeeded = 0;
		}


		// Drop unneeded defenders.
		if (groundDefendersNeeded == 0 && flyingDefendersNeeded == 0)
		{
			defenseSquad.clear();
			//continue;
		}

		if (groundDefendersNeeded == 0)
		{
			// Drop any defenders which can't shoot air.
			BWAPI::Unitset drop;
			for (BWAPI::Unit unit : defenseSquad.getUnits())
			{
				if (!unit->getType().isDetector() && !UnitUtil::CanAttackAir(unit))
				{
					drop.insert(unit);
				}
			}
			for (BWAPI::Unit unit : drop)
			{
				defenseSquad.removeUnit(unit);
			}
			// And carry on. We may still want to add air defenders.
		}
		if (flyingDefendersNeeded == 0)
		{
			// Drop any defenders which can't shoot ground.
			BWAPI::Unitset drop;
			for (BWAPI::Unit unit : defenseSquad.getUnits())
			{
				if (!unit->getType().isDetector() && !UnitUtil::CanAttackGround(unit))
				{
					drop.insert(unit);
				}
			}
			for (BWAPI::Unit unit : drop)
			{
				defenseSquad.removeUnit(unit);
			}
			// And carry on. We may still want to add ground defenders.
		}

		const bool wePulledWorkers =
			std::any_of(defenseSquad.getUnits().begin(), defenseSquad.getUnits().end(), BWAPI::Filter::IsWorker);

		// Pull workers only in narrow conditions.
		// Pulling workers (as implemented) can lead to big losses, but it is sometimes needed to survive.
		const bool pullWorkers =
			Config::Micro::WorkersDefendRush &&
			closestEnemyDistance <= (wePulledWorkers ? pullWorkerDistance + pullWorkerHysteresis : pullWorkerDistance) &&
			buildingRush();

		if (wePulledWorkers && !pullWorkers)
		{
			defenseSquad.releaseWorkers();
		}

		// Now find the actual units to assign.
		updateDefenseSquadUnits(defenseSquad, flyingDefendersNeeded, groundDefendersNeeded, pullWorkers, enemyHitsAir);

		// Assign a detector if appropriate.
		const bool wantDetector =
			!enemyHitsAir ||
			enemyHasCloak && defenseSquad.getUnits().size() >= flyingDefendersNeeded + groundDefendersNeeded;
		maybeAssignDetector(defenseSquad, wantDetector);

		// And, finally, estimate roughly whether the workers may be in danger.
		// If they are not at immediate risk, they should keep mining and we should even be willing to transfer in more.
		if (enemyHitsGround &&
			closestEnemyDistance <= (InformationManager::Instance().enemyHasSiegeMode() ? 12 * 32 : 8 * 32) &&
			int(defenseSquad.getUnits().size()) / 2 < groundDefendersNeeded + flyingDefendersNeeded)
		{
			base->setWorkerDanger(true);
		}
	}
}

BWAPI::Unit CombatCommander::getFrontBarracks()
{
	for (const auto unit : BWAPI::Broodwar->self()->getUnits())
	{
		if (unit->getType() == BWAPI::UnitTypes::Terran_Barracks &&
			unit->isLifted())
		{
			return unit;
		}
	}
	return nullptr;
}


BWAPI::Position CombatCommander::frontBarracksPosition()
{
	BWAPI::Position frontBarracksPosition = BWAPI::Positions::None;
	for (const auto unit : BWAPI::Broodwar->self()->getUnits())
	{
		if (unit->getType() == BWAPI::UnitTypes::Terran_Barracks &&
			unit->isLifted())
		{
			frontBarracksPosition = unit->getPosition();
			break;
		}
	}
	return frontBarracksPosition;
}

///////////////////////////////////////////////++
//以当前的防守点为中心，确定各个队列的位置，以组成阵线
BWAPI::Position  CombatCommander::getSquadPosition(std::string squadID)
{
	BWAPI::Position center = defenseLine;

	if (Bases::Instance().enemyStart())
	{
		if (center == Bases::Instance().enemyStart()->getPosition())
		{
			return Bases::Instance().enemyStart()->getPosition();
		}
	}
	/*
	if (frontBarracksPosition() != BWAPI::Positions::None &&
		(defenseLine == InformationManager::Instance().getPosition("frontLine2") || defenseLine == InformationManager::Instance().getPosition("frontLine3")))
	{
		center = getNearPosition(frontBarracksPosition(), _lastDefenseLine, false, 200);
	}
	else
	{
		center = defenseLine;
	}
	*/
	//计算三角函数值
	double cos, sin;
	if (defenseLine == InformationManager::Instance().getPosition("frontLine3") && Bases::Instance().getSecondBase(1))
	{
		BWAPI::Position enemySecBase = Bases::Instance().getSecondBase(1)->getPosition();
		cos = -(enemySecBase.x - defenseLine.x) / sqrt(pow(enemySecBase.x - defenseLine.x, 2) + pow(enemySecBase.y - defenseLine.y, 2));
		sin = -(enemySecBase.y - defenseLine.y) / sqrt(pow(enemySecBase.x - defenseLine.x, 2) + pow(enemySecBase.y - defenseLine.y, 2));
	}
	else
	{
		cos = (_lastDefenseLine.x - defenseLine.x) / sqrt(pow(_lastDefenseLine.x - defenseLine.x, 2) + pow(_lastDefenseLine.y - defenseLine.y, 2));
		sin = (_lastDefenseLine.y - defenseLine.y) / sqrt(pow(_lastDefenseLine.x - defenseLine.x, 2) + pow(_lastDefenseLine.y - defenseLine.y, 2));
	}

	BWAPI::Position resultPosition;//最终将要返回的位置变量

	if (squadID == "00")
	{
		return center;
	}
	//计算Tank阵线的位置
	else if (squadID == "11")//阵线下左方
	{
		double col = 60.0;//竖直步长
		double row = 120.0;//水平步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		int a2 = int(row * sin);
		int b2 = - int(row * cos);
		resultPosition.x = center.x + a1 + a2;
		resultPosition.y = center.y + b1 + b2;
	}
	else if (squadID == "12")//阵线下方
	{
		double col = 60.0;//竖直步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		resultPosition.x = center.x + a1;
		resultPosition.y = center.y + b1;
	}
	else if (squadID == "13")//阵线下右方
	{
		double col = 60.0;//竖直步长
		double row = 120.0;//水平步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		int a2 = - int(row * sin);
		int b2 = int(row * cos);
		resultPosition.x = center.x + a1 + a2;
		resultPosition.y = center.y + b1 + b2;
	}
	//计算两翼队列的位置
	else if (squadID == "21")//左翼
	{
		double col = 0;//竖直步长
		double row = 100.0;//水平步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		int a2 = int(row * sin);
		int b2 = -int(row * cos);
		resultPosition.x = center.x + a1 + a2;
		resultPosition.y = center.y + b1 + b2;
	}
	else if (squadID == "22")//右翼
	{
		double col = 0;//竖直步长
		double row = 100.0;//水平步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		int a2 = -int(row * sin);
		int b2 = int(row * cos);
		resultPosition.x = center.x + a1 + a2;
		resultPosition.y = center.y + b1 + b2;
	}
	//计算先锋队列的位置
	else if (squadID == "31")//左左
	{
		double col = 0;//竖直步长
		double row = 180.0;//水平步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		int a2 = int(row * sin);
		int b2 = -int(row * cos);
		resultPosition.x = center.x + a1 + a2;
		resultPosition.y = center.y + b1 + b2;
	}
	else if (squadID == "32")//前中
	{
		double col = 60.0;//竖直步长
		int a1 = -int(col * cos);
		int b1 = -int(col * sin);
		resultPosition.x = center.x + a1;
		resultPosition.y = center.y + b1;
	}
	else if (squadID == "33")//右右
	{
		double col = 0;//竖直步长
		double row = 180.0;//水平步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		int a2 = -int(row * sin);
		int b2 = int(row * cos);
		resultPosition.x = center.x + a1 + a2;
		resultPosition.y = center.y + b1 + b2;
	}
	else if (squadID == "41")//最后方的SCV队列
	{
		double col = 200.0;//竖直步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		resultPosition.x = center.x + a1;
		resultPosition.y = center.y + b1;
	}
	else if (squadID == "51")//前左
	{
		double col = 60;//竖直步长
		double row = 100.0;//水平步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		int a2 = int(row * sin);
		int b2 = -int(row * cos);
		resultPosition.x = center.x + a1 + a2;
		resultPosition.y = center.y + b1 + b2;
	}
	else if (squadID == "52")//前右
	{
		double col = 60;//竖直步长
		double row = 100.0;//水平步长
		int a1 = int(col * cos);
		int b1 = int(col * sin);
		int a2 = int(row * sin);
		int b2 = -int(row * cos);
		resultPosition.x = center.x + a1 + a2;
		resultPosition.y = center.y + b1 + b2;
	}
	if (resultPosition.isValid())
	{
		return resultPosition;
	}
	else
	{
		return BWAPI::Position(0, 0);
	}
}

void  CombatCommander::updateAttackEnemyBase()
{	
	//每10秒更新一次
	int interval = BWAPI::Broodwar->getFrameCount() % (24 * 10);
	if (interval != 1){ return; }

	if (defenseLine == InformationManager::Instance().getPosition("chokePoint2") ||
		defenseLine == InformationManager::Instance().getPosition("frontLine1") ||
		!Bases::Instance().enemyStart())
	{
		_aimEnemyBase = BWAPI::Positions::None;
		return;
	}
	//寻找最适合进攻的敌方基地
	Base * aimBase = nullptr;
	BWAPI::Position myStartBasePos = Bases::Instance().myStartingBase()->getPosition();

	if (defenseLine == InformationManager::Instance().getPosition("frontLine2"))
	{
		for (Base * base : Bases::Instance().getBases())
		{
			BWAPI::Position basePos = base->getPosition();
			//基地位置修正
			basePos.x += 50;
			basePos.y += 50;

			//不是敌方的基地则跳过
			if (base->getOwner() != BWAPI::Broodwar->enemy() &&
				BWAPI::Broodwar->isExplored(base->getTilePosition())){ continue; }

			BWAPI::Unit depot = BWAPI::Broodwar->getClosestUnit(
				basePos,
				BWAPI::Filter::IsEnemy && 
				(BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Command_Center ||
				BWAPI::Filter::GetType == BWAPI::UnitTypes::Zerg_Hatchery ||
				BWAPI::Filter::GetType == BWAPI::UnitTypes::Protoss_Nexus),
				160);
			if (!depot){ continue; }

			//跳过敌方主基地
			if (base == Bases::Instance().enemyStart() || base == Bases::Instance().getSecondBase(1)){ continue; }

			//判断是否在我方阵线这一侧//向量判断法
			BWAPI::Position line2 = InformationManager::Instance().getPosition("frontLine2");
			BWAPI::Position line3 = InformationManager::Instance().getPosition("frontLine3");
			//向量点乘
			int dot = (line3.x - line2.x) * (basePos.x - line2.x) + (line3.y - line2.y) * (basePos.y - line2.y);
			//过滤掉阵线另一侧的敌方基地
			if (dot > 0){ continue; }
			//剩下的都是需要进攻的基地，选择一个离我方主基地最近的
			if (!aimBase)
			{
				aimBase = base;
			}
			else if (BuildingManager::Instance().getDistance(basePos, myStartBasePos) <
				BuildingManager::Instance().getDistance(aimBase->getPosition(), myStartBasePos))
			{
				aimBase = base;
			}
		}
	}
	else if (defenseLine == InformationManager::Instance().getPosition("frontLine3"))
	{
		for (Base * base : Bases::Instance().getBases())
		{
			BWAPI::Position basePos = base->getPosition();
			//基地位置修正
			basePos.x += 50;
			basePos.y += 50;

			//不是敌方的基地则跳过
			if (base->getOwner() != BWAPI::Broodwar->enemy() &&
				BWAPI::Broodwar->isExplored(base->getTilePosition())){ continue; }

			BWAPI::Unit depot = BWAPI::Broodwar->getClosestUnit(
				basePos,
				BWAPI::Filter::IsEnemy &&
				(BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Command_Center ||
				BWAPI::Filter::GetType == BWAPI::UnitTypes::Zerg_Hatchery ||
				BWAPI::Filter::GetType == BWAPI::UnitTypes::Protoss_Nexus),
				160);
			if (!depot){ continue; }

			//跳过敌方主基地
			if (base == Bases::Instance().enemyStart() || base == Bases::Instance().getSecondBase(1)){ continue; }

			//跳过没有路径可以进入的基地
			if (the.partitions.id(basePos) != the.partitions.id(myStartBasePos)){ continue; }

			//剩下的都是需要进攻的基地，选择一个离我方主基地最近的
			if (!aimBase)
			{
				aimBase = base;
			}
			else if (BuildingManager::Instance().getDistance(basePos, myStartBasePos) <
				BuildingManager::Instance().getDistance(aimBase->getPosition(), myStartBasePos))
			{
				aimBase = base;
			}
		}
	}
	if (aimBase)
	{
		_aimEnemyBase = aimBase->getPosition();
	}
	else
	{
		_aimEnemyBase = BWAPI::Positions::None;
	}
}



//更新防守阵线的位置

void  CombatCommander::updateDefenseLine()
{
	//每8秒更新一次
	int interval = BWAPI::Broodwar->getFrameCount() % (24 * 8);
	if (interval != 1){ return; }
	int seconds = BWAPI::Broodwar->getFrameCount() / 24;

	//获取目前基地数量和部队数量
	int numVultures = UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Vulture);
	int numGoliaths = UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Goliath);
	int numTanks = UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
		+ UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode);
	int numAttackUnits = numVultures + numGoliaths + numTanks;
	int supplyUsed = BWAPI::Broodwar->self()->supplyUsed() / 2;


	//读取机甲阵线的位置
	BWAPI::Position denfenceLine0 = InformationManager::Instance().getPosition("chokePoint2");
	BWAPI::Position denfenceLine1 = InformationManager::Instance().getPosition("frontLine1");
	BWAPI::Position denfenceLine2 = InformationManager::Instance().getPosition("frontLine2");
	BWAPI::Position denfenceLine3 = InformationManager::Instance().getPosition("frontLine3");
	
	if (supplyUsed > 160 || 
		(!_aimEnemyBase && Bases::Instance().isInFrontBaseFree() && defenseLine == denfenceLine2 && supplyUsed > 136) ||
		(isTimeToPush() && supplyUsed > 100))
	{
		if (defenseLine == denfenceLine2)
		{
			defenseLine = denfenceLine3;
			_lastDefenseLine = denfenceLine2;
		}
		return;
	}
	else if (supplyUsed > 136 ||
		(!_aimEnemyBase && defenseLine == denfenceLine1 && supplyUsed > 98) ||
		(isTimeToPush() && supplyUsed > 80))
	{
		if (defenseLine == denfenceLine1)
		{
			defenseLine = denfenceLine2;
			_lastDefenseLine = denfenceLine1;
		}
		return;
	}
	else if (supplyUsed > 68)
	{
		if (defenseLine == denfenceLine0)
		{
			defenseLine = denfenceLine1;
			_lastDefenseLine = denfenceLine0;
		}
		return;
	}
	else if (seconds < 30)
	{
		defenseLine = denfenceLine0;
	}
	return;
}

BWAPI::Position CombatCommander::getDefenseLine()
{
	return defenseLine;
}

void  CombatCommander::updateTankSquads()
{
	//1秒钟更新一次队列的位置
	int frame24 = BWAPI::Broodwar->getFrameCount() % 24;
	if (frame24 != 1) { return; }

	if (_goAggressive || defenseLine == InformationManager::Instance().getPosition("chokePoint2"))
	{
		if (_squadData.squadExists("tankSquad1"))
		{
			_squadData.removeSquad("tankSquad1");
		}
		if (_squadData.squadExists("tankSquad2"))
		{
			_squadData.removeSquad("tankSquad2");
		}
		if (_squadData.squadExists("tankSquad3"))
		{
			_squadData.removeSquad("tankSquad3");
		}
		if (_squadData.squadExists("tankSquad4"))
		{
			_squadData.removeSquad("tankSquad4");
		}
		if (_squadData.squadExists("tankSquad5"))
		{
			_squadData.removeSquad("tankSquad5");
		}
		return;
	}

	if (_combatUnits.empty())
	{
		return;
	}

	const int tankDefenseRadius = 400;

	//每个小队3个坦克
	int TankNeeded1 = 3;
	int TankNeeded2 = 3;
	int TankNeeded3 = 3;

	//tank队列1
	if (getSquadPosition("12").isValid())
	{
		SquadOrder tankOrder1(SquadOrderTypes::Defend, getSquadPosition("12"), tankDefenseRadius, "Defend");
		if (_squadData.squadExists("tankSquad1"))
		{
			_squadData.getSquad("tankSquad1").setSquadOrder(tankOrder1);
		}
		else
		{
			_squadData.createSquad("tankSquad1", tankOrder1, ReconPriority);
		}
	}
	if (_squadData.squadExists("tankSquad1"))//@zhang 2019年8月29日22:50:36 UAlbertaBot::SquadData::getSquad error
	{
		Squad & tankSquad1 = _squadData.getSquad("tankSquad1");

		//计算需要添加的单位数量
		for (BWAPI::Unit unit : tankSquad1.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			{
				TankNeeded1 -= 1;
			}
		}
	}


	//tank队列2
	if (getSquadPosition("11").isValid())
	{
		SquadOrder tankOrder2(SquadOrderTypes::Defend, getSquadPosition("11"), tankDefenseRadius, "Defend");
		if (_squadData.squadExists("tankSquad2"))
		{
			_squadData.getSquad("tankSquad2").setSquadOrder(tankOrder2);
		}
		else
		{
			_squadData.createSquad("tankSquad2", tankOrder2, LinePriority);
		}
	}
	if (_squadData.squadExists("tankSquad2"))//@zhang 2019年8月29日22:50:36 UAlbertaBot::SquadData::getSquad error
	{
		Squad & tankSquad2 = _squadData.getSquad("tankSquad2");

		//计算需要添加的单位数量
		for (BWAPI::Unit unit : tankSquad2.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			{
				TankNeeded2 -= 1;
			}
		}
	}


	//tank队列3
	if (getSquadPosition("13").isValid())
	{
		SquadOrder tankOrder3(SquadOrderTypes::Defend, getSquadPosition("13"), tankDefenseRadius, "Defend");
		if (_squadData.squadExists("tankSquad3"))
		{
			_squadData.getSquad("tankSquad3").setSquadOrder(tankOrder3);
		}
		else
		{
			_squadData.createSquad("tankSquad3", tankOrder3, LinePriority);
		}
	}
	if (_squadData.squadExists("tankSquad3"))//@zhang 2019年8月29日22:50:36 UAlbertaBot::SquadData::getSquad error
	{
		Squad & tankSquad3 = _squadData.getSquad("tankSquad3");

		//计算需要添加的单位数量
		for (BWAPI::Unit unit : tankSquad3.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			{
				TankNeeded3 -= 1;
			}
		}
	}


	//tank队列4
	if (getSquadPosition("31").isValid())
	{
		SquadOrder tankOrder(SquadOrderTypes::Defend, getSquadPosition("31"), tankDefenseRadius, "Defend");
		if (_squadData.squadExists("tankSquad4"))
		{
			_squadData.getSquad("tankSquad4").setSquadOrder(tankOrder);
		}
		else
		{
			_squadData.createSquad("tankSquad4", tankOrder, LinePriority);
		}
	}
	//if (_squadData.squadExists("tankSquad4"))//@zhang 2019年8月29日22:50:36 UAlbertaBot::SquadData::getSquad error
	//{
	//	Squad & tankSquad4 = _squadData.getSquad("tankSquad4");
	//}


	//tank队列5
	if (getSquadPosition("33").isValid())
	{
		SquadOrder tankOrder(SquadOrderTypes::Defend, getSquadPosition("33"), tankDefenseRadius, "Defend");
		if (_squadData.squadExists("tankSquad5"))
		{
			_squadData.getSquad("tankSquad5").setSquadOrder(tankOrder);
		}
		else
		{
			_squadData.createSquad("tankSquad5", tankOrder, LinePriority);
		}
	}
	//if (_squadData.squadExists("tankSquad5"))//@zhang 2019年8月29日22:50:36 UAlbertaBot::SquadData::getSquad error
	//{
	//	Squad & tankSquad5 = _squadData.getSquad("tankSquad5");
	//}



	//添加作战单位
	for (const auto unit : _combatUnits)
	{
		if ((unit->getType() != BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode && unit->getType() != BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)) { continue; }

		if (TankNeeded1 > 0 && _squadData.squadExists("tankSquad1"))
		{
			Squad & tankSquad1 = _squadData.getSquad("tankSquad1");
			if (_squadData.canAssignUnitToSquad(unit, tankSquad1))
			{
				_squadData.assignUnitToSquad(unit, tankSquad1);
				TankNeeded1 -= 1;
			}

		}
		else if (TankNeeded2 > 0 && _squadData.squadExists("tankSquad1"))
		{
			Squad & tankSquad2 = _squadData.getSquad("tankSquad2");
			if (_squadData.canAssignUnitToSquad(unit, tankSquad2))
			{
				_squadData.assignUnitToSquad(unit, tankSquad2);
				TankNeeded2 -= 1;
			}
		}
		else if (TankNeeded3 > 0 && _squadData.squadExists("tankSquad1"))
		{
			Squad & tankSquad3 = _squadData.getSquad("tankSquad3");
			if (_squadData.canAssignUnitToSquad(unit, tankSquad3))
			{
				_squadData.assignUnitToSquad(unit, tankSquad3);
				TankNeeded3 -= 1;
			}

		}
		else
		{
			if (_squadData.squadExists("tankSquad4") && _squadData.squadExists("tankSquad5"))
			{
				Squad & tankSquad4 = _squadData.getSquad("tankSquad4");
				Squad & tankSquad5 = _squadData.getSquad("tankSquad5");
				if (tankSquad4.getUnits().size() < tankSquad5.getUnits().size() &&
					_squadData.canAssignUnitToSquad(unit, tankSquad4))
				{
					_squadData.assignUnitToSquad(unit, tankSquad4);
				}
				else if (_squadData.canAssignUnitToSquad(unit, tankSquad5))
				{
					_squadData.assignUnitToSquad(unit, tankSquad5);
				}
			}

		}
	}
}

//7.1
void  CombatCommander::updateStartingBaseDefenseSquad()
{
	if (_combatUnits.empty())
	{
		return;
	}

	const int chokeDefenseRadius = 600;
	int closestEnemyDistance = 99999;
	BWAPI::Unit closestEnemy = nullptr;

	BWTA::Region * region = BWTA::getRegion(Bases::Instance().myStartingBase()->getTilePosition());

	for (BWAPI::Unit unit : BWAPI::Broodwar->enemy()->getUnits())
	{
		int dist = unit->getDistance(Bases::Instance().myStartingBase()->getPosition());
		if (dist < chokeDefenseRadius ||
			dist < chokeDefenseRadius + 300 && BWTA::getRegion(unit->getTilePosition()) == region)
		{
			if (dist < closestEnemyDistance)
			{
				closestEnemyDistance = dist;
				closestEnemy = unit;
			}
		}
	}

	BWAPI::Position pos1;

	if (closestEnemy)
	{
		pos1 = closestEnemy->getPosition();
	}
	else
	{
		BWAPI::Position basePos = Bases::Instance().myStartingBase()->getPosition();
		//主基地位置修正
		basePos.x += 50;
		basePos.y += 50;

		BWAPI::Position choke1 = BWTA::getNearestChokepoint(basePos)->getCenter();
		pos1 = CombatCommander::Instance().getNearPosition(basePos, choke1, false, 160);
	}

	int numGoliaths = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Goliath);

	if (numGoliaths > 0)
	{
		SquadOrder goliathOrder(SquadOrderTypes::Defend, pos1, chokeDefenseRadius, "goliath");
		if (_squadData.squadExists("startBaseSquad"))
		{
			_squadData.getSquad("startBaseSquad").setSquadOrder(goliathOrder);
		}
		else
		{
			_squadData.createSquad("startBaseSquad", goliathOrder, WatchPriority);
		}

		Squad & goliathSquad = _squadData.getSquad("startBaseSquad");
		//计算需要添加的单位数量
		int goliathNeeded = 5;

		for (BWAPI::Unit unit : goliathSquad.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath)
			{
				goliathNeeded -= 1;
			}
		}

		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if ((unit->getType() == BWAPI::UnitTypes::Terran_Goliath)
				&& goliathNeeded > 0 && _squadData.canAssignUnitToSquad(unit, goliathSquad))
			{
				_squadData.assignUnitToSquad(unit, goliathSquad);
				goliathNeeded -= 1;
			}
		}
	}
	else if (_squadData.squadExists("startBaseSquad"))
	{
		_squadData.removeSquad("startBaseSquad");
	}
}

//6.29
void  CombatCommander::updateBunkerSquad()
{
	int numMarines = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Marine);

	if (_combatUnits.empty())
	{
		return;
	}

	const int chokeDefenseRadius = 300;

	//分别获取各个地堡的位置
	BWAPI::Position pos1 = InformationManager::Instance().getPosition("chokePoint1");//主基地的路口
	BWAPI::Position pos2 = InformationManager::Instance().getPosition("chokePoint2");//二基地的路口
	BWAPI::Position pos3 = Bases::Instance().myStartingBase()->getPosition();//主基地的中心

	//squad2跟随阵线移动
	if (!_goAggressive && numMarines > 0)
	{
		BWAPI::Position squad2Position;//squad当前应该防守的位置

		//获取路口二的地堡
		BWAPI::Unit bunker2 = BWAPI::Broodwar->getClosestUnit(
			InformationManager::Instance().getPosition("chokePoint2"),
			BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
			200);

		//假如阵线成功推出去，则防守在阵线上
		if (defenseLine != InformationManager::Instance().getPosition("chokePoint2"))
		{
			squad2Position = defenseLine;
		}
		//阵线没有推出去，假如路口二的地堡修建好了，则防守该位置
		else if (StrategyManager::Instance().isSecondBaseReady() && 
			Bases::Instance().getSecondBase(0) &&
			!bunker2)
		{
			BWAPI::Position mySecondBase = Bases::Instance().getSecondBase(0)->getPosition();

			squad2Position = getNearPosition(pos2, mySecondBase, false, 100);
		}
		else if (StrategyManager::Instance().isSecondBaseReady() &&
			Bases::Instance().getSecondBase(0) && bunker2)
		{
			BWAPI::Position mySecondBase = Bases::Instance().getSecondBase(0)->getPosition();

			squad2Position = getNearPosition(pos2, mySecondBase, true, 60);
		}
		//不满足上述条件，则防守路口1
		else
		{
			squad2Position = pos1;
		}

		SquadOrder bunkerOrder2(SquadOrderTypes::Defend, squad2Position, chokeDefenseRadius, "marine2");
		if (_squadData.squadExists("bunkerSquad2"))
		{
			_squadData.getSquad("bunkerSquad2").setSquadOrder(bunkerOrder2);
		}
		else
		{
			_squadData.createSquad("bunkerSquad2", bunkerOrder2, BaseDefensePriority);
		}

		Squad & bunkerSquad2 = _squadData.getSquad("bunkerSquad2");
		//计算需要添加的单位数量
		int MarineNeeded2 = std::min(8, numMarines);

		for (BWAPI::Unit unit : bunkerSquad2.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Marine)
			{
				MarineNeeded2 -= 1;
			}
		}

		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if ((unit->getType() == BWAPI::UnitTypes::Terran_Marine)
				&& MarineNeeded2 > 0 && _squadData.canAssignUnitToSquad(unit, bunkerSquad2))
			{
				_squadData.assignUnitToSquad(unit, bunkerSquad2);
				MarineNeeded2 -= 1;
			}
		}
	}
	else if (_squadData.squadExists("bunkerSquad2"))
	{
		_squadData.removeSquad("bunkerSquad2");
	}
}

void  CombatCommander::updateChokeSquads()
{
	int numCC = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Command_Center);
	int minute = BWAPI::Broodwar->getFrameCount() / (24 * 60);
	int numSCV = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_SCV);


	if (_combatUnits.empty())
	{
		return;
	}

	const int chokeDefenseRadius = 100;

	//分别获取各个路口的位置
	BWAPI::Position choke1 = InformationManager::Instance().getPosition("chokePoint1");
	BWAPI::Position choke2 = InformationManager::Instance().getPosition("chokePoint2");
	BWAPI::Position choke3 = InformationManager::Instance().getPosition("chokePoint3");
	BWAPI::Position choke4 = InformationManager::Instance().getPosition("chokePoint4");
	BWAPI::Position choke5 = Bases::Instance().myStartingBase()->getPosition();
	////zhangtaidong190613 当分基地路口有bunker没人的时候，不要marine
	BWAPI::Unit bunker1 = BWAPI::Broodwar->getClosestUnit(
		InformationManager::Instance().getPosition("bunkerPoint"),
		BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
		30);
	BWAPI::Unit bunker3 = BWAPI::Broodwar->getClosestUnit(
		InformationManager::Instance().getPosition("chokePoint2"),
		BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
		30);

	//优先更新路口4的队列
    if (!_goAggressive && defenseLine == InformationManager::Instance().getPosition("chokePoint2") &&
		(BWAPI::Broodwar->mapFileName() == "(2)Destination.scx" || BWAPI::Broodwar->mapFileName() == "(4)Andromeda.scx"))
	{
		SquadOrder chokeOrder4(SquadOrderTypes::Defend, choke4, chokeDefenseRadius, "Defend choke");
		if (_squadData.squadExists("chokeSquad4"))
		{
			_squadData.getSquad("chokeSquad4").setSquadOrder(chokeOrder4);
		}
		else
		{
			_squadData.createSquad("chokeSquad4", chokeOrder4, ReconPriority);
		}

		Squad & chokeSquad4 = _squadData.getSquad("chokeSquad4");
		//计算需要添加的单位数量
		int TankNeeded4 = 2;
		for (BWAPI::Unit unit : chokeSquad4.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			{
				TankNeeded4 -= 1;
			}
		}

		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if ((unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
				&& TankNeeded4 > 0 && _squadData.canAssignUnitToSquad(unit, chokeSquad4))
			{
				_squadData.assignUnitToSquad(unit, chokeSquad4);
				TankNeeded4 -= 1;
			}
		}
	}
	else if (_squadData.squadExists("chokeSquad4"))
	{
		_squadData.removeSquad("chokeSquad4");
	}

	BWAPI::Unit choke2Bunker = BWAPI::Broodwar->getClosestUnit(
		choke2,
		BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
		6 * 32);

	//更新路口1的队列
	if (!_goAggressive && !choke2Bunker && !StrategyManager::Instance().isSecondBaseReady())
	{
		SquadOrder chokeOrder1(SquadOrderTypes::Defend, choke1, chokeDefenseRadius, "Defend choke");
		if (_squadData.squadExists("chokeSquad1"))
		{
			_squadData.getSquad("chokeSquad1").setSquadOrder(chokeOrder1);
		}
		else
		{
			_squadData.createSquad("chokeSquad1", chokeOrder1, AttackPriority);
		}

		Squad & chokeSquad1 = _squadData.getSquad("chokeSquad1");
		//计算需要添加的单位数量
		int TankNeeded1 = 2;
		int  numSCV = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_SCV);
		for (BWAPI::Unit unit : chokeSquad1.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			{
				TankNeeded1 -= 1;
				if (!unit->isSieged() && !unit->isMoving())
				{
					unit->siege();
				}
			}
		}

		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if ((unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
				&& TankNeeded1 > 0 && _squadData.canAssignUnitToSquad(unit, chokeSquad1))
			{
				_squadData.assignUnitToSquad(unit, chokeSquad1);
				TankNeeded1 -= 1;
			}
		}
	}
	else if (_squadData.squadExists("chokeSquad1"))
	{
		_squadData.removeSquad("chokeSquad1");
	}
	
	//更新路口2的队列
	if (defenseLine == InformationManager::Instance().getPosition("chokePoint2") && !_goAggressive && StrategyManager::Instance().isSecondBaseReady())
	{
		BWAPI::Position pos2 = InformationManager::Instance().getPosition("frontLine1");
		SquadOrder chokeOrder2(SquadOrderTypes::Defend, getNearPosition(choke2, pos2, false, 60), chokeDefenseRadius, "Defend choke");
		if (_squadData.squadExists("chokeSquad2"))
		{
			_squadData.getSquad("chokeSquad2").setSquadOrder(chokeOrder2);
		}
		else
		{
			_squadData.createSquad("chokeSquad2", chokeOrder2, AttackPriority);
		}

		Squad & chokeSquad2 = _squadData.getSquad("chokeSquad2");
		//计算需要添加的单位数量
		int TankNeeded2 = 6;
		int GoliathNeeded2 = 6;
		for (BWAPI::Unit unit : chokeSquad2.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			{
				TankNeeded2 -= 1;
				if (!unit->isSieged() && !unit->isMoving())
				{
					unit->siege();
				}
			}
			if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath)
			{
				GoliathNeeded2 -= 1;
			}
		}

		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if ((unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
				&& TankNeeded2 > 0 && _squadData.canAssignUnitToSquad(unit, chokeSquad2))
			{
				_squadData.assignUnitToSquad(unit, chokeSquad2);
				TankNeeded2 -= 1;
			}
			if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath && GoliathNeeded2 > 0 && _squadData.canAssignUnitToSquad(unit, chokeSquad2))
			{
				_squadData.assignUnitToSquad(unit, chokeSquad2);
				GoliathNeeded2 -= 1;
			}
		}
	}
	else if (_squadData.squadExists("chokeSquad2"))
	{
		_squadData.removeSquad("chokeSquad2");
	}

	//更新路口3的队列
	if (numCC > 4 && !_goAggressive)
	{
		SquadOrder chokeOrder3(SquadOrderTypes::Defend, choke3, chokeDefenseRadius, "Defend choke");
		if (_squadData.squadExists("chokeSquad3"))
		{
			_squadData.getSquad("chokeSquad3").setSquadOrder(chokeOrder3);
		}
		else
		{
			_squadData.createSquad("chokeSquad3", chokeOrder3, AttackPriority);
		}

		Squad & chokeSquad3 = _squadData.getSquad("chokeSquad3");
		//计算需要添加的单位数量
		int TankNeeded3 = 1;
		int GoliathNeeded3 = 1;
		int SCVNeeded3 = 1;
		for (BWAPI::Unit unit : chokeSquad3.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			{
				TankNeeded3 -= 1;
				if (!unit->isSieged() && !unit->isMoving())
				{
					unit->siege();
				}
			}
			if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath)
			{
				GoliathNeeded3 -= 1;
			}
			if (unit->getType() == BWAPI::UnitTypes::Terran_SCV)
			{
				SCVNeeded3 -= 1;
			}
		}

		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if ((unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
				&& TankNeeded3 > 0 && _squadData.canAssignUnitToSquad(unit, chokeSquad3))
			{
				_squadData.assignUnitToSquad(unit, chokeSquad3);
				TankNeeded3 -= 1;
			}
			if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath && GoliathNeeded3 > 0 && _squadData.canAssignUnitToSquad(unit, chokeSquad3))
			{
				_squadData.assignUnitToSquad(unit, chokeSquad3);
				GoliathNeeded3 -= 1;
			}
			if (unit->getType() == BWAPI::UnitTypes::Terran_SCV && SCVNeeded3 > 0 && _squadData.canAssignUnitToSquad(unit, chokeSquad3))
			{
				_squadData.assignUnitToSquad(unit, chokeSquad3);
				SCVNeeded3 -= 1;
			}
		}
	}
	else if (_squadData.squadExists("chokeSquad3"))
	{
		_squadData.removeSquad("chokeSquad3");
	}
}

//将雷车和机器人作为先锋，为坦克抵挡敌方的冲击
void CombatCommander::updatePioneerSquad()
{
	//1秒钟更新一次队列的位置
	int interval = BWAPI::Broodwar->getFrameCount() % 24;
	if (interval != 1) { return; }

	if (_combatUnits.empty())
	{
		return;
	}

	const int DefenseRadius = 160;

	//设置左方的队列
	if (!_goAggressive && defenseLine != InformationManager::Instance().getPosition("chokePoint2"))
	{
		if (getSquadPosition("32").isValid())
		{

			SquadOrder pioneerOrder1(SquadOrderTypes::Defend, getSquadPosition("32"), DefenseRadius, "Defend");
			if (_squadData.squadExists("pioneerSquad1"))
			{
				_squadData.getSquad("pioneerSquad1").setSquadOrder(pioneerOrder1);
			}
			else
			{
				_squadData.createSquad("pioneerSquad1", pioneerOrder1, LinePriority);
			}

			Squad & pioneerSquad1 = _squadData.getSquad("pioneerSquad1");
			//添加作战单位
			for (const auto unit : _combatUnits)
			{
				if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture &&
					_squadData.canAssignUnitToSquad(unit, pioneerSquad1)) {
					_squadData.assignUnitToSquad(unit, pioneerSquad1);
				}
			}
		}
	}
	else if (_squadData.squadExists("pioneerSquad1"))
	{
		_squadData.removeSquad("pioneerSquad1");
	}
}

void CombatCommander::updateSpiderSquads()
{
	int numCC = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Command_Center);
	if (numCC == 1)
	{
		return;
	}
	if (_goAggressive)
	{
		if (_squadData.squadExists("spiderSquad1"))
		{
			_squadData.removeSquad("spiderSquad1");
		}
		for (const auto unit : _combatUnits)
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture &&  unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) && !unit->isMoving())
			{
				unit->useTech(BWAPI::TechTypes::Spider_Mines, unit->getPosition());
			}
		}
		return;
	}
	BWAPI::Player self = BWAPI::Broodwar->self();

	//更新队列的单位，到达合适位置则放雷
	if (_squadData.squadExists("spiderSquad1"))
	{
		Squad & spiderSquad1 = _squadData.getSquad("spiderSquad1");
		//计算需要添加的单位数量
		int VulturesNeeded1 = 1;
		for (BWAPI::Unit unit : spiderSquad1.getUnits())
		{
			if (unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
			{
				VulturesNeeded1 -= 1;
				if (!unit->isMoving())
				{
					unit->useTech(BWAPI::TechTypes::Spider_Mines, unit->getPosition());
				}
			}
			else if (!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
			{
				spiderSquad1.removeUnit(unit);
			}
		}
		//添加作战单位
		for (const auto unit : _combatUnits)
		{
		if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture
			&& VulturesNeeded1 > 0 && _squadData.canAssignUnitToSquad(unit, spiderSquad1))
			{
			    _squadData.assignUnitToSquad(unit, spiderSquad1);
				VulturesNeeded1 -= 1;
			}
		}
	}
	else if (self->hasResearched(BWAPI::TechTypes::Spider_Mines))
	{
		SquadOrder spiderSquadOrder(SquadOrderTypes::Defend, defenseLine, 200, "put spider mines");
		_squadData.createSquad("spiderSquad1", spiderSquadOrder, WatchPriority);
	}

	if (_squadData.squadExists("spiderSquad2"))
	{
		Squad & spiderSquad2 = _squadData.getSquad("spiderSquad2");
		//计算需要添加的单位数量
		int VulturesNeeded2 = 1;
		for (BWAPI::Unit unit : spiderSquad2.getUnits())
		{
			if (unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
			{
				VulturesNeeded2 -= 1;
				if (!unit->isMoving())
				{
					unit->useTech(BWAPI::TechTypes::Spider_Mines, unit->getPosition());
				}
			}
			else if (!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
			{
				spiderSquad2.removeUnit(unit);
			}
		}
		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture
				&& VulturesNeeded2 > 0 && _squadData.canAssignUnitToSquad(unit, spiderSquad2))
			{
				_squadData.assignUnitToSquad(unit, spiderSquad2);
				VulturesNeeded2 -= 1;
			}
		}
	}
	else if (self->hasResearched(BWAPI::TechTypes::Spider_Mines))
	{
		SquadOrder spiderSquadOrder(SquadOrderTypes::Defend, defenseLine, 200, "put spider mines");
		_squadData.createSquad("spiderSquad2", spiderSquadOrder, WatchPriority);
	}

	int sec = BWAPI::Broodwar->getFrameCount() / 24;//当前的游戏总时间，单位s
	//每5秒更新一次雷车放雷的位置
	if ((sec % 5) != 1 || _combatUnits.empty())
	{
		return;
	}

	if (!spiderStep)
	{
		spiderStep = 3;
	}

	int step = 1;

	BWAPI::Position targetPosition;

	BWAPI::Position denfenceLine0 = InformationManager::Instance().getPosition("chokePoint2");
	BWAPI::Position denfenceLine1 = InformationManager::Instance().getPosition("frontLine1");
	BWAPI::Position denfenceLine2 = InformationManager::Instance().getPosition("frontLine2");
	BWAPI::Position denfenceLine3 = InformationManager::Instance().getPosition("frontLine3");

	if (defenseLine == InformationManager::Instance().getPosition("frontLine3"))
	{
		const std::vector<BWAPI::TilePosition> & tilePositions = MapTools::Instance().getClosestTilesTo(denfenceLine3);
		if (spiderStep >= tilePositions.size() || spiderStep >= 15)
		{
			spiderStep = 1;
		}
		targetPosition = BWAPI::Position(tilePositions[spiderStep]);
		spiderStep += step;
	}
	else if (defenseLine == InformationManager::Instance().getPosition("frontLine2"))
	{
		BWAPI::TilePosition start = BWAPI::TilePosition(denfenceLine3);
		BWAPI::TilePosition end = BWAPI::TilePosition(denfenceLine1);
		const std::vector<BWAPI::TilePosition> & tilePositions = BWTA::getShortestPath(start, end);
		if (spiderStep >= tilePositions.size())
		{
			spiderStep = 2;
		}
		targetPosition = BWAPI::Position(tilePositions[spiderStep]);
		spiderStep += step;
	}
	else if (defenseLine == InformationManager::Instance().getPosition("frontLine1"))
	{
		BWAPI::TilePosition start = BWAPI::TilePosition(denfenceLine1);
		BWAPI::TilePosition end = BWAPI::TilePosition(denfenceLine0);
		const std::vector<BWAPI::TilePosition> & tilePositions = BWTA::getShortestPath(start, end);
		if (spiderStep >= tilePositions.size())
		{
			spiderStep = 2;
		}
		targetPosition = BWAPI::Position(tilePositions[spiderStep]);
		spiderStep += step;
	}
	else if (defenseLine == InformationManager::Instance().getPosition("chokePoint2"))
	{
		BWAPI::TilePosition start = BWAPI::TilePosition(denfenceLine0);
		BWAPI::TilePosition end = BWAPI::TilePosition(denfenceLine1);
		const std::vector<BWAPI::TilePosition> & tilePositions = BWTA::getShortestPath(start, end);
		if (spiderStep >= tilePositions.size())
		{
			spiderStep = 2;
		}
		targetPosition = BWAPI::Position(tilePositions[spiderStep]);
		spiderStep += step;
	}

	if (_squadData.squadExists("spiderSquad1"))
	{
		SquadOrder spiderSquadOrder(SquadOrderTypes::Attack, targetPosition, 200, "put spider mines");
		_squadData.getSquad("spiderSquad1").setSquadOrder(spiderSquadOrder);
	}
	else
	{
		SquadOrder spiderSquadOrder(SquadOrderTypes::Attack, targetPosition, 200, "put spider mines");
		_squadData.createSquad("spiderSquad1", spiderSquadOrder, ReconPriority);
	}
	if (_squadData.squadExists("spiderSquad2"))
	{
		SquadOrder spiderSquadOrder(SquadOrderTypes::Attack, targetPosition, 200, "put spider mines");
		_squadData.getSquad("spiderSquad2").setSquadOrder(spiderSquadOrder);
	}
	else
	{
		SquadOrder spiderSquadOrder(SquadOrderTypes::Attack, targetPosition, 200, "put spider mines");
		_squadData.createSquad("spiderSquad2", spiderSquadOrder, ReconPriority);
	}

}

///////////////////////////////////////////////__

//7.3.2019
//frontPos和backPos两点连线方向作为朝向
//获取frontPos点前方或者后方distance距离的一个坐标点
//isFront为true则获取前方，否则获取后方的点
BWAPI::Position CombatCommander::getNearPosition(BWAPI::Position frontPos, BWAPI::Position backPos, bool isFront, int distance)
{
	//计算三角函数值
	double cos = (backPos.x - frontPos.x) / sqrt(pow(backPos.x - frontPos.x, 2) + pow(backPos.y - frontPos.y, 2));
	double sin = (backPos.y - frontPos.y) / sqrt(pow(backPos.x - frontPos.x, 2) + pow(backPos.y - frontPos.y, 2));

	BWAPI::Position resultPosition;//最终将要返回的位置变量

	//获取frontPos前方的点
	if (isFront)
	{
		int a1 = int(distance * cos);
		int b1 = int(distance * sin);
		resultPosition.x = frontPos.x - a1;
		resultPosition.y = frontPos.y - b1;
		return resultPosition;
	}
	//获取frontPos后方的点
	else
	{
		int a1 = int(distance * cos);
		int b1 = int(distance * sin);
		resultPosition.x = frontPos.x + a1;
		resultPosition.y = frontPos.y + b1;
		return resultPosition;
	}
}
//7.19.2019//
BWAPI::Position CombatCommander::getRowPosition(BWAPI::Position frontPos, BWAPI::Position backPos, int interval, int length)
{
	//计算三角函数值
	double cos = (backPos.x - frontPos.x) / sqrt(pow(backPos.x - frontPos.x, 2) + pow(backPos.y - frontPos.y, 2));
	double sin = (backPos.y - frontPos.y) / sqrt(pow(backPos.x - frontPos.x, 2) + pow(backPos.y - frontPos.y, 2));

	BWAPI::Position leftPosition;//左边的点

	int a1 = int(length * sin);
	int b1 = -int(length * cos);
	leftPosition.x = frontPos.x + a1;
	leftPosition.y = frontPos.y + b1;

	int a2 = -int(interval * sin);
	int b2 = int(interval * cos);

	int numMines = length / interval * 2;

	for (int i = 0; i < numMines; i++)
	{
		BWAPI::Unitset barrier = BWAPI::Broodwar->getUnitsInRadius(
			leftPosition, 20, 
			BWAPI::Filter::GetType != BWAPI::UnitTypes::Terran_Vulture);

		if (leftPosition.isValid())
		{
			if (barrier.size() == 0 &&
				the.partitions.id(leftPosition) == the.partitions.id(Bases::Instance().myStartingBase()->getPosition()) &&
				the.partitions.walkable(BWAPI::WalkPosition(leftPosition)) &&
				canUseMinePosition(leftPosition))
			{
				return leftPosition;
			}
			else
			{
				leftPosition.x += a2;
				leftPosition.y += b2;
			}
		}
		else
		{
			leftPosition.x += a2;
			leftPosition.y += b2;
		}
	}
	return  BWAPI::Positions::None;
}

void CombatCommander::updateGoliathSquad()
{
	if (_goAggressive || defenseLine == InformationManager::Instance().getPosition("chokePoint2"))
	{
		if (_squadData.squadExists("goliathSquad1"))
		{
			_squadData.removeSquad("goliathSquad1");
		}
		if (_squadData.squadExists("goliathSquad2"))
		{
			_squadData.removeSquad("goliathSquad2");
		}
		return;
	}

	int frame60 = BWAPI::Broodwar->getFrameCount() % 60;

	if (_combatUnits.empty() || frame60 != 1){ return; }

	const int frontDefenseRadius = 160;

	//位置更新
	if (getSquadPosition("21").isValid())
	{
		SquadOrder Order(SquadOrderTypes::Defend, getSquadPosition("21"), frontDefenseRadius, "Defend");
		if (_squadData.squadExists("goliathSquad1"))
		{
			_squadData.getSquad("goliathSquad1").setSquadOrder(Order);
		}
		else
		{
			_squadData.createSquad("goliathSquad1", Order, LinePriority);
		}
	}

	if (getSquadPosition("22").isValid())
	{
		SquadOrder Order(SquadOrderTypes::Defend, getSquadPosition("22"), frontDefenseRadius, "Defend");
		if (_squadData.squadExists("goliathSquad2"))
		{
			_squadData.getSquad("goliathSquad2").setSquadOrder(Order);
		}
		else
		{
			_squadData.createSquad("goliathSquad2", Order, LinePriority);
		}
	}

	Squad & goliathSquad1 = _squadData.getSquad("goliathSquad1");
	Squad & goliathSquad2 = _squadData.getSquad("goliathSquad2");

	//添加作战单位
	for (const auto unit : _combatUnits)
	{
		if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath)
		{
			if (goliathSquad1.getUnits().size() < goliathSquad2.getUnits().size() && 
				_squadData.canAssignUnitToSquad(unit, goliathSquad1))
			{
				_squadData.assignUnitToSquad(unit, goliathSquad1);
			}
			else if (_squadData.canAssignUnitToSquad(unit, goliathSquad2))
			{
				_squadData.assignUnitToSquad(unit, goliathSquad2);
			}
		}
	}
}

void  CombatCommander::updateBaseAttackSquad()
{
	if (_goAggressive || defenseLine == InformationManager::Instance().getPosition("chokePoint2") || !_aimEnemyBase)
	{
		if (_squadData.squadExists("baseAttackSquad"))
		{
			_squadData.removeSquad("baseAttackSquad");
		}
		return;
	}

	int interval = BWAPI::Broodwar->getFrameCount() % 24;

	if (_combatUnits.empty() || interval != 10){ return; }

	//评估敌方分基地的防守力量
	int score = 4;    
	if (_aimEnemyBase)
	{
		std::vector<UnitInfo> enemies;
		InformationManager::Instance().getNearbyForce(enemies, _aimEnemyBase, BWAPI::Broodwar->enemy(), 300);
		for (const auto & enemy : enemies)
		{
			if (!enemy.type.isWorker())
			{
				++score;
			}
		}
	}

	//计算我方可以派去进攻的单位数量
	int myNumAbleUnits = 0;

	if (_squadData.squadExists("pioneerSquad1"))
	{
		myNumAbleUnits += std::min(int(_squadData.getSquad("pioneerSquad1").getUnits().size()), 8);
	}
	if (_squadData.squadExists("goliathSquad1") && _squadData.squadExists("goliathSquad2"))
	{
		myNumAbleUnits += std::min(int(_squadData.getSquad("goliathSquad1").getUnits().size() + _squadData.getSquad("goliathSquad2").getUnits().size()), 12);
	}
	if (_squadData.squadExists("tankSquad2") && _squadData.squadExists("tankSquad3"))
	{
		myNumAbleUnits += int(_squadData.getSquad("tankSquad2").getUnits().size() +
			_squadData.getSquad("tankSquad3").getUnits().size());
	}

	//根据得分决定派多少兵力进攻,分数过大就暂时不进攻
	if (score > myNumAbleUnits)
	{
		if (_squadData.squadExists("baseAttackSquad"))
		{
			_squadData.removeSquad("baseAttackSquad");
		}
		return;
	}

	int numVultureAdd = score / 4 + 1;
	int numGoliathAdd = score / 2;
	int numTankAdd = score / 2;

	const int attackRadius = 460;

	//位置更新
	SquadOrder Order(SquadOrderTypes::Attack, _aimEnemyBase, attackRadius, "Attack Enemy Base");
	if (_squadData.squadExists("baseAttackSquad"))
	{
		_squadData.getSquad("baseAttackSquad").setSquadOrder(Order);
	}
	else
	{
		_squadData.createSquad("baseAttackSquad", Order, ReconPriority);
	}

	Squad & baseAttackSquad = _squadData.getSquad("baseAttackSquad");

	//查看队伍中已有的单位
	for (auto unit : baseAttackSquad.getUnits())
	{
		if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture)
		{
			numVultureAdd -= 1;
		}
		else if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath)
		{
			numGoliathAdd -= 1;
		}
		else if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode ||
			unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
		{
			numTankAdd -= 1;
		}
	}

	//添加作战单位
	for (const auto unit : _combatUnits)
	{
		if (numVultureAdd + numGoliathAdd + numTankAdd == 0){ break; }

		if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture  && 
			_squadData.canAssignUnitToSquad(unit, baseAttackSquad) &&
			numVultureAdd > 0)
		{
			_squadData.assignUnitToSquad(unit, baseAttackSquad);
			numVultureAdd -= 1;
		}
		else if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath  && 
			_squadData.canAssignUnitToSquad(unit, baseAttackSquad) &&
			numGoliathAdd > 0)
		{
			_squadData.assignUnitToSquad(unit, baseAttackSquad);
			numGoliathAdd -= 1;
		}
		else if ((unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode) &&
			_squadData.canAssignUnitToSquad(unit, baseAttackSquad) &&
			numTankAdd > 0)
		{
			_squadData.assignUnitToSquad(unit, baseAttackSquad);
			numTankAdd -= 1;
		}
	}
}

////Z190510E 划分阵线的部队 start
void  CombatCommander::updateFrontSquads()
{
	int numCC = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Command_Center);
	int minute = BWAPI::Broodwar->getFrameCount() / (24 * 60);

	if (_goAggressive || numCC <= 2 || defenseLine == InformationManager::Instance().getPosition("chokePoint2"))
	{
		if (_squadData.squadExists("frontSquad1"))
		{
			_squadData.removeSquad("frontSquad1");
		}
		if (_squadData.squadExists("frontSquad2"))
		{
			_squadData.removeSquad("frontSquad2");
		}
		return;
	}

	int frame60 = BWAPI::Broodwar->getFrameCount() % 60;
	if (_combatUnits.empty() || frame60 != 1){ return; }

		const int frontDefenseRadius = 160;
		const int frontAttackRadius = 600;

		int numVultures = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Vulture);
		int numGoliaths = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Goliath);
		int numTanks = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			+ UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode);
		int numAttackUnits = numVultures + numTanks + numGoliaths;

		int score = 0;     // the final score will be 0 or negative
		if (_aimEnemyBase)
		{
			std::vector<UnitInfo> enemies;
			InformationManager::Instance().getNearbyForce(enemies, _aimEnemyBase, BWAPI::Broodwar->enemy(), 600);
			for (const auto & enemy : enemies)
			{
				if (!enemy.type.isWorker())
				{
					--score;
				}
			}
		}

		//调整位置
		if (score > -20 && _aimEnemyBase && _squadData.squadExists("frontSquad1"))
		{
			SquadOrder frontSquadOrder1(SquadOrderTypes::Attack, _aimEnemyBase, frontAttackRadius, "Defend front1");
			_squadData.getSquad("frontSquad1").setSquadOrder(frontSquadOrder1);
		}
		else if (_squadData.squadExists("frontSquad1") && getSquadPosition("11").isValid())
		{
			SquadOrder frontSquadOrder1(SquadOrderTypes::Defend, getSquadPosition("11"), frontDefenseRadius, "Defend front1");
			_squadData.getSquad("frontSquad1").setSquadOrder(frontSquadOrder1);
		}
		else if (getSquadPosition("11").isValid())
		{
			SquadOrder frontSquadOrder1(SquadOrderTypes::Defend, getSquadPosition("11"), frontDefenseRadius, "Defend front1");
			_squadData.createSquad("frontSquad1", frontSquadOrder1, ReconPriority);
		}

		if (score > -20 && score < -10 && _aimEnemyBase && _squadData.squadExists("frontSquad2"))
		{
			SquadOrder frontSquadOrder2(SquadOrderTypes::Attack, _aimEnemyBase, frontAttackRadius, "Defend front2");
			_squadData.getSquad("frontSquad2").setSquadOrder(frontSquadOrder2);
		}
		else if (_squadData.squadExists("frontSquad2") && getSquadPosition("13").isValid())
		{
			SquadOrder frontSquadOrder2(SquadOrderTypes::Defend, getSquadPosition("13"), frontDefenseRadius, "Defend front2");
			_squadData.getSquad("frontSquad2").setSquadOrder(frontSquadOrder2);
		}
		else if (getSquadPosition("13").isValid())
		{
			SquadOrder frontSquadOrder2(SquadOrderTypes::Defend, getSquadPosition("13"), frontDefenseRadius, "Defend front2");
			_squadData.createSquad("frontSquad2", frontSquadOrder2, ReconPriority);//Z190510优先级增加，不然不容易分到兵
		}
	
	
		//为第1个队伍更新分配
		if (_squadData.squadExists("frontSquad1"))
		{
			Squad & frontSquad1 = _squadData.getSquad("frontSquad1");
			//计算需要添加的单位数量
			int VultureNeeded1 = 3;
			int GoliathNeeded1 = 6;
			int TankNeeded1 = 3;
			//int  numSCV = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_SCV);
			for (BWAPI::Unit unit : frontSquad1.getUnits())
			{
				if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture)
				{
					VultureNeeded1 -= 1;
				}
				if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath)
				{
					GoliathNeeded1 -= 1;
				}
				if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
				{
					TankNeeded1 -= 1;
					if (!unit->isSieged() && !unit->isMoving())
					{
						unit->siege();
					}
				}

			}
			//添加作战单位
			for (const auto unit : _combatUnits)
			{
				if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture && VultureNeeded1 > 0 && _squadData.canAssignUnitToSquad(unit, frontSquad1))
				{
					_squadData.assignUnitToSquad(unit, frontSquad1);
					VultureNeeded1 -= 1;
				}
				if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath && GoliathNeeded1 > 0 && _squadData.canAssignUnitToSquad(unit, frontSquad1))
				{
					_squadData.assignUnitToSquad(unit, frontSquad1);
					GoliathNeeded1 -= 1;
				}
				if ((unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
					&& TankNeeded1 > 0 && _squadData.canAssignUnitToSquad(unit, frontSquad1))
				{
					_squadData.assignUnitToSquad(unit, frontSquad1);
					TankNeeded1 -= 1;
				}
			}
		}

		//为第2个队伍更新分配
		if (_squadData.squadExists("frontSquad2"))
		{
			Squad & frontSquad2 = _squadData.getSquad("frontSquad2");
			//计算需要添加的单位数量
			int VultureNeeded1 = 3;
			int GoliathNeeded1 = 6;
			int TankNeeded1 = 3;
			//int  numSCV = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_SCV);
			for (BWAPI::Unit unit : frontSquad2.getUnits())
			{
				if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture)
				{
					VultureNeeded1 -= 1;
				}
				if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath)
				{
					GoliathNeeded1 -= 1;
				}
				if (unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
				{
					TankNeeded1 -= 1;
					if (!unit->isSieged() && !unit->isMoving())
					{
						unit->siege();
					}
				}

			}
			//添加作战单位
			for (const auto unit : _combatUnits)
			{
				if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture && VultureNeeded1 > 0 && _squadData.canAssignUnitToSquad(unit, frontSquad2))
				{
					_squadData.assignUnitToSquad(unit, frontSquad2);
					VultureNeeded1 -= 1;
				}
				if (unit->getType() == BWAPI::UnitTypes::Terran_Goliath && GoliathNeeded1 > 0 && _squadData.canAssignUnitToSquad(unit, frontSquad2))
				{
					_squadData.assignUnitToSquad(unit, frontSquad2);
					GoliathNeeded1 -= 1;
				}
				if ((unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode || unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
					&& TankNeeded1 > 0 && _squadData.canAssignUnitToSquad(unit, frontSquad2))
				{
					_squadData.assignUnitToSquad(unit, frontSquad2);
					TankNeeded1 -= 1;
				}
			}
		}
	
}
////Z190510E 划分阵线的部队 end

void CombatCommander::updateDefenseSquadUnits(Squad & defenseSquad, const size_t & flyingDefendersNeeded, const size_t & groundDefendersNeeded, bool pullWorkers, bool enemyHasAntiAir)
{
	const BWAPI::Unitset & squadUnits = defenseSquad.getUnits();

	// Count what is already in the squad, being careful not to double-count a unit as air and ground defender.
	size_t flyingDefendersInSquad = 0;
	size_t groundDefendersInSquad = 0;
	size_t versusBoth = 0;
	for (BWAPI::Unit defender : squadUnits)
	{
		bool versusAir = UnitUtil::CanAttackAir(defender);
		bool versusGround = UnitUtil::CanAttackGround(defender);
		if (versusGround && versusAir)
		{
			++versusBoth;
		}
		else if (versusGround)
		{
			++groundDefendersInSquad;
		}
		else if (versusAir)
		{
			++flyingDefendersInSquad;
		}
	}
	// Assign dual-purpose units to whatever side needs them, priority to ground.
	if (groundDefendersNeeded > groundDefendersInSquad)
	{
		size_t add = std::min(versusBoth, groundDefendersNeeded - groundDefendersInSquad);
		groundDefendersInSquad += add;
		versusBoth -= add;
	}
	if (flyingDefendersNeeded > flyingDefendersInSquad)
	{
		size_t add = std::min(versusBoth, flyingDefendersNeeded - flyingDefendersInSquad);
		flyingDefendersInSquad += add;
	}

	//BWAPI::Broodwar->printf("defenders %d/%d %d/%d",
	//	groundDefendersInSquad, groundDefendersNeeded, flyingDefendersInSquad, flyingDefendersNeeded);

	// Add flying defenders.
	size_t flyingDefendersAdded = 0;
	BWAPI::Unit defenderToAdd;
	while (flyingDefendersNeeded > flyingDefendersInSquad + flyingDefendersAdded &&
		(defenderToAdd = findClosestDefender(defenseSquad, defenseSquad.getSquadOrder().getPosition(), true, false, enemyHasAntiAir)))
	{
		_squadData.assignUnitToSquad(
			defenderToAdd, defenseSquad);
		++flyingDefendersAdded;
	}

	// Add ground defenders.
	size_t groundDefendersAdded = 0;
	while (groundDefendersNeeded > groundDefendersInSquad + groundDefendersAdded &&
		(defenderToAdd = findClosestDefender(defenseSquad, defenseSquad.getSquadOrder().getPosition(), false, pullWorkers, enemyHasAntiAir)))
	{
		if (defenderToAdd->getType().isWorker())
		{
			UAB_ASSERT(pullWorkers, "pulled worker defender mistakenly");
			WorkerManager::Instance().setCombatWorker(defenderToAdd);
		}
		_squadData.assignUnitToSquad(defenderToAdd, defenseSquad);
		++groundDefendersAdded;
		if (defenderToAdd->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode && !defenderToAdd->isMoving())
		{
			defenderToAdd->siege();
		}
	}
}

// Choose a defender to join the base defense squad.
BWAPI::Unit CombatCommander::findClosestDefender(const Squad & defenseSquad, BWAPI::Position pos, bool flyingDefender, bool pullWorkers, bool enemyHasAntiAir)
{
	BWAPI::Unit closestDefender = nullptr;
	int minDistance = 99999;

	for (const auto unit : _combatUnits)
	{
		if (flyingDefender && !UnitUtil::CanAttackAir(unit) ||
			!flyingDefender && !UnitUtil::CanAttackGround(unit))
		{
			continue;
		}

		if (!_squadData.canAssignUnitToSquad(unit, defenseSquad))
		{
			continue;
		}

		int dist = unit->getDistance(pos);

		// Pull workers only if requested, and not from distant bases.
		if (unit->getType().isWorker())
		{
			if (!pullWorkers || dist > 18 * 32)
			{
				continue;
			}
			// Pull workers only if other units are considerably farther away.
			dist += 12 * 32;
		}

		// If the enemy can't shoot up, prefer air units as defenders.
		if (!enemyHasAntiAir && unit->isFlying())
		{
			dist -= 12 * 32;     // may become negative - that's OK
		}

		if (dist < minDistance)
		{
			closestDefender = unit;
			minDistance = dist;
		}
	}

	return closestDefender;
}

// NOTE This implementation is kind of cheesy. Orders ought to be delegated to a squad.
void CombatCommander::loadOrUnloadBunkers()
{
	int frame24 = BWAPI::Broodwar->getFrameCount() % 5;
	if (frame24 != 1){ return; }
	if (BWAPI::Broodwar->self()->getRace() != BWAPI::Races::Terran)
	{
		return;
	}
	/*
	BWAPI::Unit bunker3 = BWAPI::Broodwar->getClosestUnit(
		InformationManager::Instance().getPosition("bunkerPoint3"),
		BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
		30);
	BWAPI::Unit bunkerA = BWAPI::Broodwar->getClosestUnit(
		InformationManager::Instance().getPosition("bunkerPoint"),
		BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
		30);

	for (const auto bunker : BWAPI::Broodwar->self()->getUnits())
	{
		if (bunker->getType() == BWAPI::UnitTypes::Terran_Bunker)
		{

			//zhangtaidong190613 修改逻辑，优先填满（或填2个兵到分基地bunker,存在bunker3，未满			
			if (bunker->getDistance(InformationManager::Instance().getPosition("bunkerPoint3")) < 30 && bunker->isCompleted() && bunker->getSpaceRemaining() > 0)
			{

				if (bunkerA && bunkerA->getLoadedUnits().size() > 0)
				{
					the.micro.UnloadAll(bunkerA);
					//bunkerA->unloadAll();
					BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
						bunkerA->getPosition(),
						BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
						12 * 32);
					if (marine)
					{
						the.micro.Move(marine, InformationManager::Instance().getPosition("bunkerPoint3"));
					}
				}
				//下面地堡装人
				BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
					bunker->getPosition(),
					BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
					6 * 32);
				if (marine)
				{
					the.micro.Load(bunker, marine);
				}

			}
			else if (bunker->getSpaceRemaining() > 0 && bunker3 &&bunker3->getSpaceRemaining() == 0)
			{
				BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
					bunker->getPosition(),
					BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
					6 * 32);
				if (marine)
				{
					the.micro.Load(bunker, marine);
				}
			}
			else if (bunker->getSpaceRemaining() > 0 && !bunker3)
			{
				BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
					bunker->getPosition(),
					BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
					6 * 32);
				if (marine)
				{
					the.micro.Load(bunker, marine);
				}

				
				// BWAPI::Broodwar->drawCircleMap(bunker->getPosition(), 12 * 32, BWAPI::Colors::Cyan);
				// BWAPI::Broodwar->drawCircleMap(bunker->getPosition(), 18 * 32, BWAPI::Colors::Orange);

				// Are there enemies close to the bunker?
				//bool enemyIsNear = true;
				/*
				// 1. Is any enemy unit within a small radius?
				BWAPI::Unitset enemiesNear = BWAPI::Broodwar->getUnitsInRadius(bunker->getPosition(), 12 * 32,
				BWAPI::Filter::IsEnemy);
				if (enemiesNear.empty())
				{
				// 2. Is a fast enemy unit within a wider radius?
				enemiesNear = BWAPI::Broodwar->getUnitsInRadius(bunker->getPosition(), 18 * 32,
				BWAPI::Filter::IsEnemy &&
				(BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Vulture ||
				BWAPI::Filter::GetType == BWAPI::UnitTypes::Zerg_Mutalisk)
				);
				enemyIsNear = !enemiesNear.empty();
				}
				else
				{
				enemyIsNear = true;
				}
				

				//if (enemyIsNear)
				//{
				//	// Load one marine at a time if there is free space.
				//	if (bunker->getSpaceRemaining() > 0)
				//	{
				//		BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
				//			bunker->getPosition(),
				//			BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
				//			6 * 32);
				//		if (marine)
				//		{
				//			the.micro.Load(bunker, marine);
				//		}
				//	}
				//}
				//else
				//{
				//	the.micro.UnloadAll(bunker);
				//}
				*/

BWAPI::Position pos1 = InformationManager::Instance().getPosition("bunkerPoint");//主基地的路口一
BWAPI::Position pos2 = InformationManager::Instance().getPosition("chokePoint2");//二基地的路口
BWAPI::Position pos3 = Bases::Instance().myStartingBase()->getPosition();//主基地的中心
BWAPI::Position pos4 =
CombatCommander::Instance().getNearPosition(InformationManager::Instance().getPosition("frontLine1"),
InformationManager::Instance().getPosition("frontLine2"), false, 200);
BWAPI::Position pos5 =
CombatCommander::Instance().getNearPosition(InformationManager::Instance().getPosition("frontLine2"),
InformationManager::Instance().getPosition("frontLine3"), false, 200);
BWAPI::Position pos6;
if (Bases::Instance().enemyStart() && Bases::Instance().getSecondBase(1))
{
	pos6 = CombatCommander::Instance().getNearPosition(InformationManager::Instance().getPosition("frontLine3"),
		Bases::Instance().getSecondBase(1)->getPosition(), false, 120);
}
else
{
	pos6 = InformationManager::Instance().getPosition("frontLine3");
}
int numMarines = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Marine);

	for (const auto bunker : BWAPI::Broodwar->self()->getUnits())
	{
		if (bunker->getType() == BWAPI::UnitTypes::Terran_Bunker)
		{
			//主基地的地堡
			if (bunker->getDistance(pos3) < 100)
			{
				BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
					bunker->getPosition(),
					BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
					6 * 32);
				if (marine && bunker->getSpaceRemaining() > 0)
				{
					the.micro.Load(bunker, marine);
				}
				if (numMarines < 8 && marine && bunker->getSpaceRemaining() == 0)
				{
					the.micro.UnloadAll(bunker);
				}
			}
			//路口一和路口二重合
			else if (bunker->getDistance(pos1) < 160 && bunker->getDistance(pos2) < 160)
			{
				if (defenseLine != InformationManager::Instance().getPosition("chokePoint2"))
				{
					the.micro.UnloadAll(bunker);
				}
				else
				{
					BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
						InformationManager::Instance().getPosition("chokePoint1"),
						BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
						30 * 30);
					if (marine && bunker->getSpaceRemaining() > 0)
					{
						the.micro.Load(bunker, marine);
					}
				}
			}
			//路口一
			else if (bunker->getDistance(pos1) < 160)
			{
				/*
				BWAPI::Unit choke2Bunker = BWAPI::Broodwar->getClosestUnit(
					pos2,
					BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
					60);
					*/
				if (StrategyManager::Instance().isSecondBaseReady() || 
					defenseLine != InformationManager::Instance().getPosition("chokePoint2"))
				{
					the.micro.UnloadAll(bunker);
				}
				else
				{
					BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
						InformationManager::Instance().getPosition("chokePoint1"),
						BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
						30 * 30);
					if (marine && bunker->getSpaceRemaining() > 0)
					{
						the.micro.Load(bunker, marine);
					}
				}
			}
			//路口二
			else if (bunker->getDistance(pos2) < 160)
			{
				if (defenseLine != InformationManager::Instance().getPosition("chokePoint2"))
				{
					the.micro.UnloadAll(bunker);
				}
				else
				{
					BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
						bunker->getPosition(),
						BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
						30 * 30);
					if (marine && bunker->getSpaceRemaining() > 0)
					{
						the.micro.Load(bunker, marine);
					}
				}
			}
			//阵线一
			else if (bunker->getDistance(pos4) < 200)
			{
				if (defenseLine == InformationManager::Instance().getPosition("frontLine1"))
				{
					BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
						bunker->getPosition(),
						BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
						30 * 30);
					if (marine && bunker->getSpaceRemaining() > 0)
					{
						the.micro.Load(bunker, marine);
					}
				}
				else
				{
					the.micro.UnloadAll(bunker);
				}
			}
			//阵线二
			else if (bunker->getDistance(pos5) < 300)
			{
				if (defenseLine == InformationManager::Instance().getPosition("frontLine2"))
				{
					BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
						bunker->getPosition(),
						BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
						30 * 30);
					if (marine && bunker->getSpaceRemaining() > 0)
					{
						the.micro.Load(bunker, marine);
					}
				}
				else
				{
					the.micro.UnloadAll(bunker);
				}
			}
			//阵线三
			else if (bunker->getDistance(pos6) < 300)
			{
				if (defenseLine == InformationManager::Instance().getPosition("frontLine3"))
				{
					BWAPI::Unit marine = BWAPI::Broodwar->getClosestUnit(
						bunker->getPosition(),
						BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Marine,
						30 * 30);
					if (marine && bunker->getSpaceRemaining() > 0)
					{
						the.micro.Load(bunker, marine);
					}
				}
				else
				{
					the.micro.UnloadAll(bunker);
				}
			}
		}
	}
}
// Should squads have detectors assigned? Does not apply to all squads.
// Yes if the enemy has cloaked units. Also yes if the enemy is protoss and has observers
// and we have cloaked units--we want to shoot down those observers.
// Otherwise no if the detectors are in danger of dying.
bool CombatCommander::wantSquadDetectors() const
{
	if (BWAPI::Broodwar->enemy()->getRace() == BWAPI::Races::Protoss &&
		InformationManager::Instance().enemyHasMobileDetection())
	{
		if (BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Cloaking_Field) ||
			BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Personnel_Cloaking) ||
			UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Protoss_Dark_Templar) > 0 ||
			UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Protoss_Arbiter) > 0 ||
			BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Burrowing) ||
			BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Lurker_Aspect))
		{
			return true;
		}
	}

	return
		BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Protoss ||      // observers should be safe-ish
		!InformationManager::Instance().enemyHasAntiAir() ||
		InformationManager::Instance().enemyCloakedUnitsSeen();
}

// Add or remove a given squad's detector, subject to availability.
// Because this checks the content of the squad, it should be called
// after any other units are added or removed.
void CombatCommander::maybeAssignDetector(Squad & squad, bool wantDetector)
{
	if (squad.hasDetector())
	{
		// If the detector is the only thing left in the squad, we don't want to keep it.
		if (!wantDetector || squad.getUnits().size() == 1)
		{
			for (BWAPI::Unit unit : squad.getUnits())
			{
				if (unit->getType().isDetector())
				{
					squad.removeUnit(unit);
					return;
				}
			}
		}
	}
	else
	{
		// Don't add a detector to an empty squad.
		if (wantDetector && !squad.getUnits().empty())
		{
			for (BWAPI::Unit unit : _combatUnits)
			{
				if (unit->getType().isDetector() && _squadData.canAssignUnitToSquad(unit, squad))
				{
					_squadData.assignUnitToSquad(unit, squad);
					return;
				}
			}
		}
	}
}

// Scan enemy cloaked units.
void CombatCommander::doComsatScan()
{
	if (BWAPI::Broodwar->self()->getRace() != BWAPI::Races::Terran)
	{
		return;
	}

	if (UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Comsat_Station) == 0)
	{
		_lastScanMinute = 0;//7.22.2019
		return;
	}

	if (!Bases::Instance().enemyStart())
	{
		BWAPI::Position aimPos = Bases::Instance().getNextStartingBase();

		if (aimPos.isValid())
		{
			(void)the.micro.Scan(aimPos);
		}
	}
	else if (Bases::Instance().enemyStart())
	{
		int minute = BWAPI::Broodwar->getFrameCount() / (24 * 60);

		////+  7.29@liang 可扫描中心和四角共五个点
		static int scanID = 0; // 决定循环扫描基地附近的哪个点， 5个一循环
		int xPlus = 0;
		int yPlus = 0;

		if (minute - _lastScanMinute > 3)
		{
			BWAPI::Position enemyBase = Bases::Instance().enemyStart()->getPosition();
			//(void)the.micro.Scan(enemyBase);

			if (scanID == 0)
			{
				xPlus = 0; // 扫描点偏移量
				yPlus = 0;
			}
			else if (scanID == 1)
			{
				xPlus = 200;
				yPlus = 200;
			}
			else if (scanID == 2)
			{
				xPlus = -200;
				yPlus = -200;
			}
			else if (scanID == 3)
			{
				xPlus = -200;
				yPlus = 200;
			}
			else if (scanID == 4)
			{
				xPlus = 200;
				yPlus = -200;
			}
			BWAPI::Position enemyBaseNeighbor = BWAPI::Position(enemyBase.x + xPlus, enemyBase.y + yPlus);
			if (enemyBaseNeighbor.isValid())
			{
				(void)the.micro.Scan(enemyBaseNeighbor);
				scanID = (scanID + 1) % 5;
			}
			////-  7.29@liang
			_lastScanMinute = BWAPI::Broodwar->getFrameCount() / (24 * 60);
		}
	}


	/*
	//7.22.2019//假如探知了对方的主基地位置，使用雷达侦察一次
	if (Bases::Instance().enemyStart())
	{
		int minute = BWAPI::Broodwar->getFrameCount() / (24 * 60);
		if (minute - _lastScanMinute > 3)
		{
			BWAPI::Position enemyBase = Bases::Instance().enemyStart()->getPosition();
			(void)the.micro.Scan(enemyBase);
			_lastScanMinute = BWAPI::Broodwar->getFrameCount() / (24 * 60);
		}
	}
	*/
	// Does the enemy have undetected cloaked units that we may be able to engage?
	for (const auto unit : BWAPI::Broodwar->enemy()->getUnits())
	{
		if (unit->isVisible() &&
			(!unit->isDetected() || unit->getOrder() == BWAPI::Orders::Burrowing) &&
			unit->getPosition().isValid())
		{
			// At most one scan per call. We don't check whether it succeeds.
			(void)the.micro.Scan(unit->getPosition());
			// Also make sure the Info Manager knows that the enemy can burrow.
			InformationManager::Instance().enemySeenBurrowing();
			break;
		}
	}
}

// What units do you want to drop into the enemy base from a transport?
bool CombatCommander::unitIsGoodToDrop(const BWAPI::Unit unit) const
{
	return
		unit->getType() == BWAPI::UnitTypes::Protoss_Dark_Templar ||
		unit->getType() == BWAPI::UnitTypes::Terran_Vulture;
}

// Get our money back at the last moment for stuff that is about to be destroyed.
// It is not ideal: A building which is destined to die only after it is completed
// will be completed and die.
// Special case for a zerg sunken colony while it is morphing: It will lose up to
// 100 hp when the morph finishes, so cancel if it would be weak when it finishes.
// NOTE See BuildingManager::cancelBuilding() for another way to cancel buildings.
void CombatCommander::cancelDyingItems()
{
	for (const auto unit : BWAPI::Broodwar->self()->getUnits())
	{
		BWAPI::UnitType type = unit->getType();
		if (unit->isUnderAttack() &&
			(type.isBuilding() && !unit->isCompleted() ||
			type == BWAPI::UnitTypes::Zerg_Egg ||
			type == BWAPI::UnitTypes::Zerg_Lurker_Egg ||
			type == BWAPI::UnitTypes::Zerg_Cocoon
			) &&
			(unit->getHitPoints() < 30 ||
			type == BWAPI::UnitTypes::Zerg_Sunken_Colony && unit->getHitPoints() < 130 && unit->getRemainingBuildTime() < 24
			))
		{
			if (unit->canCancelMorph())
			{
				unit->cancelMorph();
			}
			else if (unit->canCancelConstruction())
			{
				the.micro.Cancel(unit);
			}
		}
	}
}

BWAPI::Position CombatCommander::getDefendLocation()
{
	return BWTA::getRegion(InformationManager::Instance().getMyMainBaseLocation()->getTilePosition())->getCenter();
}

// How good is it to pull this worker for combat?
int CombatCommander::workerPullScore(BWAPI::Unit worker)
{
	return
		(worker->getHitPoints() == worker->getType().maxHitPoints() ? 10 : 0) +
		(worker->getShields() == worker->getType().maxShields() ? 4 : 0) +
		(worker->isCarryingGas() ? -3 : 0) +
		(worker->isCarryingMinerals() ? -2 : 0);
}

// Pull workers off of mining and into the attack squad.
// The argument n can be zero or negative or huge. Nothing awful will happen.
// Tries to pull the "best" workers for combat, as decided by workerPullScore() above.
void CombatCommander::pullWorkers(int n)
{
	std::priority_queue<BWAPI::Unit, std::vector<BWAPI::Unit>, PullWorkerCompare> workers;

	Squad & groundSquad = _squadData.getSquad("Ground");

	for (const auto unit : _combatUnits)
	{
		if (unit->getType().isWorker() &&
			WorkerManager::Instance().isFree(unit) &&
			_squadData.canAssignUnitToSquad(unit, groundSquad))
		{
			workers.push(unit);
		}
	}

	int nLeft = n;

	while (nLeft > 0 && !workers.empty())
	{
		BWAPI::Unit worker = workers.top();
		workers.pop();
		_squadData.assignUnitToSquad(worker, groundSquad);
		--nLeft;
	}
}

// Release workers from the attack squad.
void CombatCommander::releaseWorkers()
{
	Squad & groundSquad = _squadData.getSquad("Ground");
	groundSquad.releaseWorkers();
}

void CombatCommander::drawSquadInformation(int x, int y)
{
	_squadData.drawSquadInformation(x, y);
}

void CombatCommander::drawCombatSimInformation()
{
	if (Config::Debug::DrawCombatSimulationInfo)
	{
		_squadData.drawCombatSimInformation();
	}
}

// Create an attack order for the given squad (which may be null).
// For a squad with ground units, ignore targets which are not accessible by ground.
SquadOrder CombatCommander::getAttackOrder(const Squad * squad)
{
	// 1. Clear any obstacles around our bases.
	// Most maps don't have any such thing, but see e.g. Arkanoid and Sparkle.
	// Only ground squads are sent to clear obstacles.
	// NOTE Turned off because there is a bug affecting the map Pathfinder.
	if (false && squad && squad->getUnits().size() > 0 && squad->hasGround() && squad->canAttackGround())
	{
		// We check our current bases (formerly plus 2 bases we may want to take next).
		/*
		Base * baseToClear1 = nullptr;
		Base * baseToClear2 = nullptr;
		BWAPI::TilePosition nextBasePos = MapTools::Instance().getNextExpansion(false, true, false);
		if (nextBasePos.isValid())
		{
		// The next mineral-optional expansion.
		baseToClear1 = Bases::Instance().getBaseAtTilePosition(nextBasePos);
		}
		nextBasePos = MapTools::Instance().getNextExpansion(false, true, true);
		if (nextBasePos.isValid())
		{
		// The next gas expansion.
		baseToClear2 = Bases::Instance().getBaseAtTilePosition(nextBasePos);
		}
		*/

		// Then pick any base with blockers and clear it.
		// The blockers are neutral buildings, and we can get their initial positions.
		// || base == baseToClear1 || base == baseToClear2
		const int squadPartition = squad->mapPartition();
		for (Base * base : Bases::Instance().getBases())
		{
			if (base->getBlockers().size() > 0 &&
				(base->getOwner() == BWAPI::Broodwar->self()) &&
				squadPartition == the.partitions.id(base->getPosition()))
			{
				BWAPI::Unit target = *(base->getBlockers().begin());
				return SquadOrder(SquadOrderTypes::DestroyNeutral, target->getInitialPosition(), 256, "Destroy neutrals");
			}
		}
	}

	// 2. If we're defensive, look for a front line to hold. No attacks.
	BWAPI::Unit choke2Bunker = BWAPI::Broodwar->getClosestUnit(
		InformationManager::Instance().getPosition("chokePoint2"),
		BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
		60);

	if (!_goAggressive)
	{
		if (StrategyManager::Instance().isSecondBaseReady())
		{
			//return SquadOrder(SquadOrderTypes::Defend, getDefenseLocation(), DefendFrontRadius, "Defend front");
			if (getSquadPosition("00").isValid())
			{
				return SquadOrder(SquadOrderTypes::Defend, getSquadPosition("00"), 100, "Defend front");
			}
			else
			{
				return SquadOrder(SquadOrderTypes::Defend, defenseLine, 100, "Defend front");
			}
		}
		else
		{
			return SquadOrder(SquadOrderTypes::Defend, InformationManager::Instance().getPosition("chokePoint1"), 100, "Defend front");
		}
	}

	// 3. Otherwise we are aggressive. Look for a spot to attack.
	BWAPI::Position aimPosition;
	BWAPI::Position unitClostestToEnemyPosition = BWAPI::Positions::None;

	return SquadOrder(SquadOrderTypes::Attack, getAttackLocation(squad), AttackRadius, "Attack enemy");

	/*
	if (frontBarracksPosition() && _clostestUnit && _barracksIsWorking)
	{
		aimPosition = getNearPosition(frontBarracksPosition(), unitClostestToEnemyPosition, false, 100);
		return SquadOrder(SquadOrderTypes::Attack, aimPosition, AttackRadius, "Attack enemy");
	} 
	else
	{
		return SquadOrder(SquadOrderTypes::Attack, getAttackLocation(squad), AttackRadius, "Attack enemy");
	}
	*/
}

// Choose a point of attack for the given squad (which may be null).
// For a squad with ground units, ignore targets which are not accessible by ground.
BWAPI::Position CombatCommander::getAttackLocation(const Squad * squad)
{
	// Know where the squad is. If it's empty or unknown, assume it is at our start position.
	// NOTE In principle, different members of the squad may be in different map partitions,
	// unable to reach each others' positions by ground. We ignore that complication.
	// NOTE Since we aren't doing islands, all squads are reachable from the start position.
	//const int squadPartition = squad
	//	? squad->mapPartition()
	//	: the.partitions.id(Bases::Instance().myStartingBase()->getTilePosition());
	const int squadPartition = the.partitions.id(Bases::Instance().myStartingBase()->getTilePosition());

	// Ground and air considerations.
	bool hasGround = true;
	bool hasAir = false;
	bool canAttackGround = true;
	bool canAttackAir = false;
	if (squad)
	{
		hasGround = squad->hasGround();
		hasAir = squad->hasAir();
		canAttackGround = squad->canAttackGround();
		canAttackAir = squad->canAttackAir();
	}

	// 1. Attack the enemy base with the weakest defense.
	// Only if the squad can attack ground. Lift the command center and it is no longer counted as a base.
	if (canAttackGround)
	{
		Base * targetBase = nullptr;
		int bestScore = -99999;
		for (Base * base : Bases::Instance().getBases())
		{
			if (base->getOwner() == BWAPI::Broodwar->enemy())
			{
				// Ground squads ignore enemy bases which they cannot reach.
				if (hasGround && squadPartition != the.partitions.id(base->getTilePosition()))
				{
					continue;
				}

				int score = 0;     // the final score will be 0 or negative
				std::vector<UnitInfo> enemies;
				InformationManager::Instance().getNearbyForce(enemies, base->getPosition(), BWAPI::Broodwar->enemy(), 384);
				for (const auto & enemy : enemies)
				{
					// Count enemies that are buildings or slow-moving units good for defense.
					if (enemy.type.isBuilding() ||
						enemy.type == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode ||
						enemy.type == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode ||
						enemy.type == BWAPI::UnitTypes::Protoss_Reaver ||
						enemy.type == BWAPI::UnitTypes::Protoss_High_Templar ||
						enemy.type == BWAPI::UnitTypes::Zerg_Lurker ||
						enemy.type == BWAPI::UnitTypes::Zerg_Guardian)
					{
						// If the unit could attack (some units of) the squad, count it.
						if (hasGround && UnitUtil::TypeCanAttackGround(enemy.type) ||			// doesn't recognize casters
							hasAir && UnitUtil::TypeCanAttackAir(enemy.type) ||					// doesn't recognize casters
							enemy.type == BWAPI::UnitTypes::Protoss_High_Templar)				// spellcaster
						{
							--score;
						}
					}
				}
				if (score > bestScore)
				{
					targetBase = base;
					bestScore = score;
				}
			}
		}
		if (targetBase)
		{
			return targetBase->getPosition();
		}
	}

	// 2. Attack known enemy buildings.
	// We assume that a terran can lift the buildings; otherwise, the squad must be able to attack ground.
	if (canAttackGround || BWAPI::Broodwar->enemy()->getRace() == BWAPI::Races::Terran)
	{
		for (const auto & kv : InformationManager::Instance().getUnitInfo(BWAPI::Broodwar->enemy()))
		{
			const UnitInfo & ui = kv.second;

			// 1. Special case for refinery buildings because their ground reachability is tricky to check.
			// 2. We only know that a building is lifted while it is in sight. That can cause oscillatory
			// behavior--we move away, can't see it, move back because now we can attack it, see it is lifted, ....
			if (ui.type.isBuilding() &&
				ui.lastPosition.isValid() &&
				!ui.goneFromLastPosition &&
				(ui.type.isRefinery() || squadPartition == the.partitions.id(ui.lastPosition)))
				// (!hasGround || (!ui.type.isRefinery() && squadPartition == the.partitions.id(ui.lastPosition))))
			{
				if (ui.unit->exists() && ui.unit->isLifted())
				{
					// The building is lifted. Only if the squad can hit it.
					if (canAttackAir)
					{
						return ui.lastPosition;
					}
				}
				else
				{
					// The building is not known for sure to be lifted.
					return ui.lastPosition;
				}
			}
		}
	}

	// 3. Attack visible enemy units.
	const BWAPI::Position squadCenter = squad
		? squad->calcCenter()
		: Bases::Instance().myStartingBase()->getPosition();
	for (const auto unit : BWAPI::Broodwar->enemy()->getUnits())
	{
		if (unit->getType() == BWAPI::UnitTypes::Zerg_Larva ||
			!unit->exists() ||
			!unit->isDetected() ||
			!unit->getPosition().isValid())
		{
			continue;
		}

		// Ground squads ignore enemy units which are not accessible by ground, except when nearby.
		// The "when nearby" exception allows a chance to attack enemies that are in range,
		// even if they are beyond a barrier. It's very rough.
		if (hasGround &&
			squadPartition != the.partitions.id(unit->getPosition()) &&
			unit->getDistance(squadCenter) > 300)
		{
			continue;
		}

		if (unit->isFlying() && canAttackAir || !unit->isFlying() && canAttackGround)
		{
			return unit->getPosition();
		}
	}

	// 4. We can't see anything, so explore the map until we find something.
	return MapGrid::Instance().getLeastExplored(hasGround && !hasAir, squadPartition);
}

// Choose a point of attack for the given drop squad.
BWAPI::Position CombatCommander::getDropLocation(const Squad & squad)
{
	// 0. If we're defensive, stay at the start location.
	/* unneeded
	if (!_goAggressive)
	{
	return BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation());
	}
	*/

	// Otherwise we are aggressive. Look for a spot to attack.

	// 1. The enemy main base, if known.
	if (InformationManager::Instance().getEnemyMainBaseLocation())
	{
		return InformationManager::Instance().getEnemyMainBaseLocation()->getPosition();
	}

	// 2. Any known enemy base.
	/* TODO not ready yet
	Base * targetBase = nullptr;
	int bestScore = -99999;
	for (Base * base : Bases::Instance().getBases())
	{
	if (base->getOwner() == BWAPI::Broodwar->enemy())
	{
	int score = 0;     // the final score will be 0 or negative
	std::vector<UnitInfo> enemies;
	InformationManager::Instance().getNearbyForce(enemies, base->getPosition(), BWAPI::Broodwar->enemy(), 600);
	for (const auto & enemy : enemies)
	{
	if (enemy.type.isBuilding() && (UnitUtil::TypeCanAttackGround(enemy.type) || enemy.type.isDetector()))
	{
	--score;
	}
	}
	if (score > bestScore)
	{
	targetBase = base;
	bestScore = score;
	}
	}
	if (targetBase)
	{
	return targetBase->getPosition();
	}
	}
	*/

	// 3. Any known enemy buildings.
	for (const auto & kv : InformationManager::Instance().getUnitInfo(BWAPI::Broodwar->enemy()))
	{
		const UnitInfo & ui = kv.second;

		if (ui.type.isBuilding() && ui.lastPosition.isValid() && !ui.goneFromLastPosition)
		{
			return ui.lastPosition;
		}
	}

	// 4. We can't see anything, so explore the map until we find something.
	return MapGrid::Instance().getLeastExplored();
}

// We're being defensive. Get the location to defend.
BWAPI::Position CombatCommander::getDefenseLocation()
{
	////////////////////////////////////++
	BWAPI::Position defenseLine = getDefenseLine();
	return defenseLine;
	/*
	int numCC = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Command_Center);
	int numVultures = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Vulture);
	int numGoliaths = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Goliath);
	int numTanks = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
		+ UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode);
	int numAttackUnits = numVultures + numTanks + numGoliaths;
	int minute = BWAPI::Broodwar->getFrameCount() / (24 * 60);

	//获取机甲阵线的位置
	BWAPI::Position denfenceLine = InformationManager::Instance().getPosition("chokePoint1");
	BWAPI::Position denfenceLine0 = InformationManager::Instance().getPosition("chokePoint2");
	BWAPI::Position denfenceLine1 = InformationManager::Instance().getPosition("frontLine1");
	BWAPI::Position denfenceLine2 = InformationManager::Instance().getPosition("frontLine2");
	BWAPI::Position denfenceLine3 = InformationManager::Instance().getPosition("frontLine3");

	if (numCC <= 2 && numAttackUnits < 15)
	{
		return denfenceLine0;
	}
	else if (numCC <= 2 && numTanks > 10 && numVultures > 15)
	{
		return denfenceLine1;
	}
	else if (numCC >= 5 && numAttackUnits > 40)
	{
		return denfenceLine3;
	}
	else if (numCC >= 4 && numAttackUnits > 30)
	{
		return denfenceLine2;
	}
	else 
	{
		return denfenceLine1;
	}
	*/
	////////////////////////////////////__
}
void CombatCommander::clearSquad(std::string squadName)
{
	if (_squadData.squadExists(squadName))
	{
		_squadData.removeSquad(squadName);
	}
	return;
	/*
	if (lastModule == "A1")
	{
		_squadData.removeSquad("bunkerSquad2");
	}
	else if (lastModule == "A2")
	{
		_squadData.removeSquad("bunkerSquad2");
	}
	else if (lastModule == "A3")
	{
		_squadData.removeSquad("bunkerSquad2");
	}
	else if (lastModule == "B2")
	{
		_squadData.removeSquad("bunkerSquad2");
		_squadData.removeSquad("chokeSquad1");
		_squadData.removeSquad("chokeSquad2");
		_squadData.removeSquad("chokeSquad3");
		_squadData.removeSquad("chokeSquad4");
	}
	else if (lastModule == "B3")
	{
		_squadData.removeSquad("attackSquad");
		_squadData.removeSquad("mineRowFrontSquad");
	}
	return;
	*/
}

bool  CombatCommander::isTimeToPush()
{
	bool shouldPush = false;

	//阵线一定范围内的我方单位
	BWAPI::Unitset ourUnits = BWAPI::Broodwar->getUnitsInRadius(
		defenseLine, 500, BWAPI::Filter::IsOwned);

	BWAPI::Unitset enemyUnits;
	//离阵线最近的敌方单位，可能不存在
	BWAPI::Unit clostestEnemyUnit = BWAPI::Broodwar->getClosestUnit(
		defenseLine,
		BWAPI::Filter::IsEnemy,
		600);
	//以该敌方单位为中心，获取一定范围内的敌方单位
	if (clostestEnemyUnit)
	{
		enemyUnits = BWAPI::Broodwar->getUnitsInRadius(
			clostestEnemyUnit->getPosition(), 500, 
			BWAPI::Filter::IsEnemy && BWAPI::Filter::GetType != BWAPI::UnitTypes::Buildings);
	}

	//假如敌方单位数量小于我方一半，则推进阵线
	if (enemyUnits.size() < 5 &&
		ourUnits.size() > 6)
	{
		shouldPush = true;
	}
	return shouldPush;
}


void  CombatCommander::updateAggression()
{	
	//每5秒更新一次
	int interval = BWAPI::Broodwar->getFrameCount() % (24 * 5);
	if (interval != 1){ return; }

	if (StrategyManager::Instance().getCurrentModule() == "C1")
	{
		BWAPI::Position denfenceLine3 = InformationManager::Instance().getPosition("frontLine3");
		int numVultures = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Vulture);
		int numGoliaths = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Goliath);
		int numTanks = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode)
			+ UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode);
		int numAttackUnits = numVultures + numGoliaths + numTanks;
		int supplyUsed = BWAPI::Broodwar->self()->supplyUsed() / 2;

		//当阵线推进到第三阵线的时候，伺机选择发动总攻
		if (supplyUsed == 200)
		{
			setAggression(true);
		}
		else if (defenseLine == denfenceLine3 && supplyUsed > 180)
		{
			setAggression(true);
		}
		else if (defenseLine == denfenceLine3 && supplyUsed > 160 && !_aimEnemyBase)
		{
			setAggression(true);
		}
		else if (supplyUsed < 140)
		{
			setAggression(false);
		}
	}
	else if (StrategyManager::Instance().getCurrentModule() == "C2")
	{
		setAggression(true);
	}
	else if (StrategyManager::Instance().getCurrentModule() == "A1" ||
		StrategyManager::Instance().getCurrentModule() == "A2" ||
		StrategyManager::Instance().getCurrentModule() == "A3" ||
		StrategyManager::Instance().getCurrentModule() == "A4")
	{
		setAggression(false);
	}
	return;
}
void CombatCommander::updateB3Squad()
{
	if (_combatUnits.empty())
	{
		return;
	}

	const int chokeDefenseRadius = 400;

	//分别获取各个地堡的位置
	BWAPI::Position pos2 = InformationManager::Instance().getPosition("chokePoint2");//二基地的路口
	BWAPI::Position pos3 = Bases::Instance().myStartingBase()->getPosition();//主基地的中心
	
		if (!_squadData.squadExists("attackSquad"))
		{
			SquadOrder attackOrder(SquadOrderTypes::Defend, pos2, chokeDefenseRadius, "attack");
			_squadData.createSquad("attackSquad", attackOrder, AttackPriority);
		}

		Squad & attackSquad = _squadData.getSquad("attackSquad");
		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Marine ||
				unit->getType() == BWAPI::UnitTypes::Terran_Goliath ||
				unit->getType() == BWAPI::UnitTypes::Terran_Vulture ||
				unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode ||
				unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode)
			{
				if (_squadData.canAssignUnitToSquad(unit, attackSquad))
				{
					_squadData.assignUnitToSquad(unit, attackSquad);
				}
			}
		}

		if (!_goAggressive)
		{
			BWAPI::Unit bunker2 = BWAPI::Broodwar->getClosestUnit(
				InformationManager::Instance().getPosition("chokePoint2"),
				BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
				6 * 30);
			if (bunker2)
			{
				SquadOrder attackOrder(SquadOrderTypes::Defend, bunker2->getPosition(), chokeDefenseRadius, "attack");
				attackSquad.setSquadOrder(attackOrder);
			}
			else
			{
				SquadOrder attackOrder(SquadOrderTypes::Defend, InformationManager::Instance().getPosition("chokePoint1"), chokeDefenseRadius, "attack");
				attackSquad.setSquadOrder(attackOrder);
			}
		}
		else
		{
			SquadOrder AttackOrder(getAttackOrder(&attackSquad));
			attackSquad.setSquadOrder(AttackOrder);
		}
}
//7.19.2019//
//在前线埋雷的雷车队 
void CombatCommander::updateMineAsRowFrontSquad(BWAPI::Position frontPos, BWAPI::Position backPos, int interval, int length, bool doubleLine)
{
	int numVultures = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Vulture);

	if (_combatUnits.empty())
	{
		return;
	}

	const int chokeDefenseRadius = 300;

	//获取埋雷的地点
	BWAPI::Position aimMinePosition = getRowPosition(frontPos, backPos, interval, length);
	//假如第一排放满了雷，则开始放第二排。一共放两排
	if (aimMinePosition == BWAPI::Positions::None && doubleLine)
	{
		BWAPI::Position  frontPos2 = getNearPosition(frontPos, backPos, true, 100);
		aimMinePosition = getRowPosition(frontPos2, backPos, interval, length);
	}
	SquadOrder mineOrder(SquadOrderTypes::Attack, aimMinePosition, chokeDefenseRadius, "attack");

	if (!aimMinePosition)
	{
		if (_squadData.squadExists("mineRowFrontSquad"))
		{
			_squadData.removeSquad("mineRowFrontSquad");
		}
		return;
	}
	else if (!_squadData.squadExists("mineRowFrontSquad"))
	{
		_squadData.createSquad("mineRowFrontSquad", mineOrder, ReconPriority);
	}

	Squad & mineSquad = _squadData.getSquad("mineRowFrontSquad");

	//将雷车集结在埋雷的位置
	mineSquad.setSquadOrder(mineOrder);

	//计算队列中还剩有蜘蛛雷的雷车的数量，把没有剩余蜘蛛雷的雷车移出队列
	int vultureNeeded = 3;

	BWAPI::Unitset units = mineSquad.getUnits();

	for (BWAPI::Unitset::iterator it = units.begin(); it != units.end(); it++)
	{
		BWAPI::Unit unit = *it;

		//移除没有雷的雷车
		if (unit->getType() != BWAPI::UnitTypes::Terran_Vulture ||
			!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
		{
			mineSquad.removeUnit(unit);
			continue;
		}
		vultureNeeded -= 1;
		//放雷
		if ((BWAPI::Broodwar->getFrameCount() - unit->getLastCommandFrame() > 120 || unit->getLastCommand().getType() != BWAPI::UnitCommandTypes::Use_Tech_Position) &&
			unit->getDistance(aimMinePosition) < 100 &&
			unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
		{
			unit->useTech(BWAPI::TechTypes::Spider_Mines, aimMinePosition);
		}
	}

	//if (mineSquad.getUnits().size() > 1)
	//{
	//	for (const auto unit : mineSquad.getUnits())
	//		//for (BWAPI::Unit unit : mineSquad.getUnits())
	//	{
	//		//移除没有雷的雷车
	//		if (unit->getType() != BWAPI::UnitTypes::Terran_Vulture ||
	//			!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
	//		{
	//			mineSquad.removeUnit(unit);
	//			continue;
	//		}
	//		vultureNeeded -= 1;
	//		//放雷
	//		if ((BWAPI::Broodwar->getFrameCount() - unit->getLastCommandFrame() > 120 || unit->getLastCommand().getType() != BWAPI::UnitCommandTypes::Use_Tech_Position) &&
	//			unit->getDistance(aimMinePosition) < 100 &&
	//			unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
	//		{
	//			unit->useTech(BWAPI::TechTypes::Spider_Mines, aimMinePosition);
	//		}
	//	}
	//}


	//添加作战单位
	for (const auto unit : _combatUnits)
	{
		if (vultureNeeded <= 0) { break; }

		if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture &&
			unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) &&
			_squadData.canAssignUnitToSquad(unit, mineSquad))
		{
			_squadData.assignUnitToSquad(unit, mineSquad);
			vultureNeeded -= 1;
		}
	}
}

//7.24.2019//
//在阵线后方埋雷的雷车队 
void CombatCommander::updateMineAsRowBackSquad(BWAPI::Position frontPos, BWAPI::Position backPos, int interval, int length)
{
	int numVultures = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Vulture);

	if (_combatUnits.empty())
	{
		return;
	}

	const int chokeDefenseRadius = 300;

	//获取埋雷的地点
	BWAPI::Position aimMinePosition;
	for (int i = 3; i < 8; i++)
	{
		BWAPI::Position  frontPos2 = getNearPosition(frontPos, backPos, false, 150 * i);
		aimMinePosition = getRowPosition(frontPos2, backPos, interval, length);
		if (aimMinePosition != BWAPI::Positions::None)
		{
			break;
		}
	}
	SquadOrder mineOrder(SquadOrderTypes::Attack, aimMinePosition, chokeDefenseRadius, "attack");

	if (!aimMinePosition)
	{
		if (_squadData.squadExists("mineRowBackSquad"))
		{
			_squadData.removeSquad("mineRowBackSquad");
		}
		return;
	}
	else if (!_squadData.squadExists("mineRowBackSquad"))
	{
		_squadData.createSquad("mineRowBackSquad", mineOrder, ReconPriority);
	}
	if (_squadData.squadExists("mineRowBackSquad"))
	{
		Squad & mineSquad = _squadData.getSquad("mineRowBackSquad");

		//将雷车集结在埋雷的位置
		mineSquad.setSquadOrder(mineOrder);

		//计算队列中还剩有蜘蛛雷的雷车的数量，把没有剩余蜘蛛雷的雷车移出队列
		int vultureNeeded = 3;
		bool isUnitMine = false;

		BWAPI::Unitset units = mineSquad.getUnits();

		for (BWAPI::Unitset::iterator it = units.begin(); it != units.end(); it++)
		{
			BWAPI::Unit unit = *it;

			for (const auto unit : mineSquad.getUnits())
				//for (BWAPI::Unit unit : mineSquad.getUnits())
			{
				//移除没有雷的雷车
				if (unit->getType() != BWAPI::UnitTypes::Terran_Vulture ||
					!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
				{
					mineSquad.removeUnit(unit);
					continue;
				}
				vultureNeeded -= 1;
				//放雷
				if ((BWAPI::Broodwar->getFrameCount() - unit->getLastCommandFrame() > 120 || unit->getLastCommand().getType() != BWAPI::UnitCommandTypes::Use_Tech_Position) &&
					unit->getDistance(aimMinePosition) < 100 &&
					unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) &&
					!isUnitMine)
				{
					unit->useTech(BWAPI::TechTypes::Spider_Mines, aimMinePosition);
					isUnitMine = true;
				}
			}
		}
		//if (mineSquad.getUnits().size() > 1)
		//{
		//	for (const auto unit : mineSquad.getUnits())
		//	//for (BWAPI::Unit unit : mineSquad.getUnits())
		//	{
		//		//移除没有雷的雷车
		//		if (unit->getType() != BWAPI::UnitTypes::Terran_Vulture ||
		//			!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
		//		{
		//			mineSquad.removeUnit(unit);
		//			continue;
		//		}
		//		vultureNeeded -= 1;
		//		//放雷
		//		if ((BWAPI::Broodwar->getFrameCount() - unit->getLastCommandFrame() > 120 || unit->getLastCommand().getType() != BWAPI::UnitCommandTypes::Use_Tech_Position) &&
		//			unit->getDistance(aimMinePosition) < 100 &&
		//			unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) &&
		//			!isUnitMine)
		//		{
		//			unit->useTech(BWAPI::TechTypes::Spider_Mines, aimMinePosition);
		//			isUnitMine = true;
		//		}
		//	}
		//}
		

		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if (vultureNeeded <= 0) { break; }

			if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture &&
				unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) &&
				_squadData.canAssignUnitToSquad(unit, mineSquad))
			{
				_squadData.assignUnitToSquad(unit, mineSquad);
				vultureNeeded -= 1;
			}
		}
	}
	
}
//8.7.2019
void CombatCommander::liftAndMoveEbay()
{
	for (const auto unit : BWAPI::Broodwar->self()->getUnits())
	{
		if (unit->getType() != BWAPI::UnitTypes::Terran_Engineering_Bay){ continue; }

		if (!unit->isLifted())
		{
			unit->lift();
			return;
		}
		else
		{
			the.micro.Move(unit, Bases::Instance().myStartingBase()->getPosition());
			StrategyManager::Instance().setEbayIsLifted(true);
			return;
		}
	}
}

void CombatCommander::updateSecondBase()
{
	int numCC = UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Command_Center);

	if (numCC != 2){ return; }

	if (!Bases::Instance().getSecondBase(0)) { return; }

	BWAPI::Position secondBasePos = Bases::Instance().getSecondBase(0)->getPosition();

	for (const auto unit : BWAPI::Broodwar->self()->getUnits())
	{
		if (unit->getType() != BWAPI::UnitTypes::Terran_Command_Center){ continue; }
		if (BuildingManager::Instance().getDistance(unit->getPosition(), Bases::Instance().myStartingBase()->getPosition()) < 100){ continue; }

		if (BuildingManager::Instance().getDistance(unit->getPosition(), secondBasePos) < 160 &&
			unit->isLifted() &&
			!unit->isMoving() && 
			BWAPI::Broodwar->getFrameCount() % (24 * 5) == 1)
		{
			if (unit->canLand(BWAPI::TilePosition(secondBasePos)))
			{
				unit->land(BWAPI::TilePosition(secondBasePos));
				return;
			}
		}
		else if (!unit->isLifted() && BuildingManager::Instance().getDistance(unit->getPosition(), secondBasePos) > 260)
		{
			unit->lift();
			return;
		}
		else if (BuildingManager::Instance().getDistance(unit->getPosition(), secondBasePos) > 260)
		{
			unit->move(secondBasePos);
			return;
		}
	}
}

////////////////////////
void CombatCommander::updateBarracks()
{
	//每3秒更新一次
	int interval = BWAPI::Broodwar->getFrameCount() % (24 * 3);
	if (interval != 1){ return; }

	int minute = BWAPI::Broodwar->getFrameCount() / (24 * 60);

	BWAPI::Unit bunker2 = BWAPI::Broodwar->getClosestUnit(
		InformationManager::Instance().getPosition("chokePoint2"),
		BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
		100);

	////////////////////更新路口的兵营的升降////////////////////
	for (BWAPI::Unit barracks : BWAPI::Broodwar->self()->getUnits())
	{
		if (barracks->getType() != BWAPI::UnitTypes::Terran_Barracks){ continue; }

		if (minute < 10 && UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Command_Center) < 2)
		{
			//判断路口附近是否有敌人
			bool hasEnemy = false;
			for (BWAPI::Unit unit : BWAPI::Broodwar->enemy()->getUnits())
			{
				int dist = unit->getDistance(InformationManager::Instance().getPosition("barracksPoint"));
				if (dist < 400)
				{
					hasEnemy = true;
					break;
				}
			}

			//假如当前生产队列中有机枪兵，或者附近有敌人，让兵营落下
			if (ProductionManager::Instance().getQueue().anyInQueue(BWAPI::UnitTypes::Terran_Marine) || hasEnemy)
			{
				if (!barracks->isMoving() && barracks->isLifted())
				{
					const std::vector<BWAPI::TilePosition> & closestToLand = MapTools::Instance().getClosestTilesTo(InformationManager::Instance().getPosition("barracksPoint"));
					for (size_t i(0); i < closestToLand.size(); ++i)
					{
						if (barracks->canLand(closestToLand[i]))
						{
							barracks->land(closestToLand[i]);
							return;
						}
					}
				}
			}
			//在一定条件下升起兵营
			else if (CombatCommander::Instance().getDefenseLine() != InformationManager::Instance().getPosition("chokePoint2") ||
				(!hasEnemy && CombatCommander::Instance().getAggression()) ||
				(!hasEnemy && bunker2) ||
				(!hasEnemy && minute > 6) ||
				(!hasEnemy && UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Vulture) > 0) ||
				(!hasEnemy && ProductionManager::Instance().getQueue().anyInQueue(BWAPI::UnitTypes::Terran_Bunker) && UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Factory) > 0))
			{
				if (!barracks->isLifted() &&
					barracks->getDistance(InformationManager::Instance().getPosition("barracksPoint")) < 160)
				{
					barracks->lift();
					return;
				}
			}
		}
		//移开兵营
		else
		{
			//假如当前生产队列中有机枪兵，或者附近有敌人，让兵营落下
			if (ProductionManager::Instance().getQueue().anyInQueue(BWAPI::UnitTypes::Terran_Marine))
			{
				if (barracks->isLifted())
				{
					const std::vector<BWAPI::TilePosition> & closestToLand = MapTools::Instance().getClosestTilesTo(barracks->getPosition());
					for (size_t i(0); i < closestToLand.size(); ++i)
					{
						if (barracks->canLand(closestToLand[i]))
						{
							barracks->land(closestToLand[i]);
							return;
						}
					}
				}
			}
			else if (barracks->getDistance(defenseLine) > 600)
			{
				if (barracks->isLifted())
				{
					barracks->move(defenseLine);
				}
				else if(barracks->getDistance(InformationManager::Instance().getPosition("barracksPoint")) < 160)
				{
					barracks->lift();
				}
			}
		}
	}

	/*
	/////////////////更新阵线上的兵营的位置////////////////////

	//阵线没有形成的时候，不需要任何操作
	if (CombatCommander::Instance().getDefenseLine() == InformationManager::Instance().getPosition("chokePoint2") && !_goAggressive){ return; }

	for (const auto unit : BWAPI::Broodwar->self()->getUnits())
	{
		if (unit->getType() != BWAPI::UnitTypes::Terran_Barracks){ continue; }

		if (!unit->isLifted() && !getFrontBarracks())
		{
			unit->lift();
			return;
		}

		if (!_clostestUnit)
		{
			the.micro.Move(unit, getNearPosition(defenseLine, _lastDefenseLine, true, 200));
			return;
		}

		//判断阵线附近是否有敌人
		bool hasEnemy = false;
		BWAPI::Unitset nearbyEnemies;
		MapGrid::Instance().getUnits(nearbyEnemies, _clostestUnit->getPosition(), 120, false, true);
		if (!nearbyEnemies.empty())
		{
			hasEnemy = true;
		}

		if (!_barracksIsWorking)
		{
			if (_clostestUnit)
			{
				the.micro.Move(unit, _clostestUnit->getPosition());
			}
			else
			{
				the.micro.Move(unit, getNearPosition(defenseLine, _lastDefenseLine, true, 200));
			}
		}
		else
		{
			//假如阵线上没有敌方单位，兵营待在阵线最前方
			if (!hasEnemy && !_goAggressive)
			{
				the.micro.Move(unit, getNearPosition(defenseLine, _lastDefenseLine, true, 200));
			}
			//假如发动总攻，并且附近没有敌方单位，则移动到我方最前方的单位的位置
			else if (!hasEnemy && _goAggressive)
			{
				Squad & centerSquad = _squadData.getSquad("Ground");

				BWAPI::Position aimPosition;
				std::vector<BWAPI::TilePosition> tiles = BWTA::getShortestPath(BWAPI::TilePosition(_clostestUnit->getPosition()),
					BWAPI::TilePosition(getAttackLocation(&centerSquad)));

				if (tiles.size() < 10)
				{
					aimPosition = getAttackLocation(&centerSquad);
				}
				else
				{
					aimPosition = getNearPosition(BWAPI::Position(tiles[5]), BWAPI::Position(tiles[0]), true, 100);
				}
				the.micro.Move(unit, aimPosition);
			}
			//假如阵线上有敌方单位，则移动到离阵线最近的敌方单位的位置
			else if (hasEnemy && unit->getDistance(getNearPosition(defenseLine, _lastDefenseLine, true, 200)) > 100)
			{
				//获取最近的敌方单位
				BWAPI::Position clostestEnemyUnitPosition;
				int minDist = 9999;
				for (const auto unit : nearbyEnemies)
				{
					int dist = unit->getDistance(_clostestUnit);
					if (dist < minDist)
					{
						clostestEnemyUnitPosition = unit->getPosition();
						minDist = dist;
					}
				}
				the.micro.Move(unit, clostestEnemyUnitPosition);
			}
			else if (hasEnemy && unit->getDistance(getNearPosition(defenseLine, _lastDefenseLine, true, 200)) <= 100 && !_goAggressive)
			{
				the.micro.Move(unit, getNearPosition(defenseLine, _lastDefenseLine, true, 200));
			}
		}
		break;
	}
	*/

	/*
	for (const auto unit : BWAPI::Broodwar->self()->getUnits())
	{
		if (unit->getType() != BWAPI::UnitTypes::Terran_Barracks){ continue; }

		//假如当前生产队列中有机枪兵，让兵营落下
		if (ProductionManager::Instance().getQueue().anyInQueue(BWAPI::UnitTypes::Terran_Marine)
			&& !unit->isMoving()
			&& unit->isLifted())
		{
			const std::vector<BWAPI::TilePosition> & closestToLand = MapTools::Instance().getClosestTilesTo(barracks->getPosition());
			for (size_t i(0); i < closestToLand.size(); ++i)
			{
				if (barracks->canLand(closestToLand[i]))
				{
					barracks->land(closestToLand[i]);
					return;
				}
			}
		}

		BWAPI::Unit bunker = BWAPI::Broodwar->getClosestUnit(
			InformationManager::Instance().getPosition("chokePoint2"),
			BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker,
			100);
		//在合适的时机升起兵营，并移动到路口2
		if (bunker && barracks->isLifted())
		{
			barracks->move(InformationManager::Instance().getPosition("chokePoint2"));
			return;
		}
		else if ((ProductionManager::Instance().getQueue().anyInQueue(BWAPI::UnitTypes::Terran_Bunker) &&
			UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Bunker) > 0) ||
			CombatCommander::Instance().getAggression() ||
			bunker)
		{
			if (!barracks->isLifted())
			{
				barracks->lift();
				return;
			}
		}
	}
	else if (barracks2)
	{
		//假如当前生产队列中有机枪兵，让兵营落下
		if (ProductionManager::Instance().getQueue().anyInQueue(BWAPI::UnitTypes::Terran_Marine)
			&& !barracks2->isMoving()
			&& barracks2->isLifted())
		{
			const std::vector<BWAPI::TilePosition> & closestToLand = MapTools::Instance().getClosestTilesTo(barracks2->getPosition());
			for (size_t i(0); i < closestToLand.size(); ++i)
			{
				if (barracks2->canLand(closestToLand[i]))
				{
					barracks2->land(closestToLand[i]);
					return;
				}
			}
		}

		//假如兵营堵住了路口，把它升起
		const std::vector<BWAPI::TilePosition> & tilePositions =
			BWTA::getShortestPath(BWAPI::TilePosition(InformationManager::Instance().getPosition("chokePoint1")),
			BWAPI::TilePosition(InformationManager::Instance().getPosition("frontLine1")));
		if (tilePositions.size() == 0 &&
			UnitUtil::GetUncompletedUnitCount(BWAPI::UnitTypes::Terran_Marine) == 0 &&
			!barracks2->isLifted())
		{
			barracks->lift();
			return;
		}
	}

	}
	*/
}

//8.5.2019
void CombatCommander::updateBarracksIsWorking()
{
	if (UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Barracks) == 0 ||
		!frontBarracksPosition())
	{
		_barracksIsWorking = false;
	}

	if (_clostestUnit)
	{
		if (frontBarracksPosition() && getFrontBarracks()->getDistance(_clostestUnit) > 500)
		{
			_barracksIsWorking = false;
		}
		else if (frontBarracksPosition() && getFrontBarracks()->getDistance(_clostestUnit) < 100)
		{
			_barracksIsWorking = true;
		}
	}
}

void CombatCommander::updateClostestUnit()
{
	//得到当前阵线单位的位置
	BWAPI::Position unitClostestToEnemyPosition = BWAPI::Positions::None;
	if (_squadData.squadExists("pioneerSquad1") &&
		!_squadData.getSquad("pioneerSquad1").isEmpty() &&
		_squadData.getSquad("pioneerSquad1").getSquadOrder().getPosition().isValid())
	{
		Squad & pioneerSquad = _squadData.getSquad("pioneerSquad1");

		int minDist = 9999;
		for (BWAPI::Unit unit : pioneerSquad.getUnits())
		{
			int dist = unit->getDistance(pioneerSquad.getSquadOrder().getPosition());
			if (dist < minDist)
			{
				_clostestUnit = unit;
				minDist = dist;
			}
		}
	}

    if (unitClostestToEnemyPosition == BWAPI::Positions::None &&
		!_squadData.getSquad("Ground").isEmpty() &&
		_squadData.getSquad("Ground").getSquadOrder().getPosition().isValid())
	{
		Squad & centerSquad = _squadData.getSquad("Ground");
		int minDist = 9999;
		for (BWAPI::Unit unit : centerSquad.getUnits())
		{
			int dist = unit->getDistance(centerSquad.getSquadOrder().getPosition());
			if (dist < minDist)
			{
				_clostestUnit = unit;
				minDist = dist;
			}
		}
	}
}

////////////////////////

// 未开基地中，在矿和指挥中心之间的点 @liang
BWAPI::Position CombatCommander::getPointBetweenCC_Mineral()
{
	BWAPI::Position outputPos, minePos, basePos;
	for (const auto& baseLocation : BWTA::getBaseLocations()) {
		basePos = baseLocation->getPosition();
		BWAPI::Unit Command_Center = BWAPI::Broodwar->getClosestUnit(basePos, BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Command_Center, 30);
		if (Command_Center) continue;  // 排除已开基地

		//draw a circle at each mineral patch
		for (const auto& mineral : baseLocation->getStaticMinerals()) {

			if (mineral->getInitialResources() <= 64)  continue;// 排除零碎小矿
			minePos = mineral->getInitialPosition();
			outputPos = BWAPI::Position((minePos.x + basePos.x) / 2, (minePos.y + basePos.y) / 2);

			BWAPI::Unit spider = BWAPI::Broodwar->getClosestUnit(outputPos, BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine, 20);
			if (spider) break; // 已放一个雷则离开

			//BWAPI::Broodwar->drawCircleMap(outputPos, 30, BWAPI::Colors::Cyan); // test
			return outputPos;
		}
	}
	return BWAPI::Positions::None;
}

void CombatCommander::updateFindingEnemyBaseSquad()
{
	if (_combatUnits.empty())
	{
		return;
	}

	if (!Bases::Instance().enemyStart() && 
		BWAPI::Broodwar->getFrameCount() / (24 * 60) > 8)
	{
		BWAPI::Position aimPos = Bases::Instance().getNextStartingBase();

		SquadOrder Order(SquadOrderTypes::Attack, aimPos, 600, "find enemy main base");

		if (_squadData.squadExists("findEnemyBaseSquad"))
		{
			_squadData.getSquad("findEnemyBaseSquad").setSquadOrder(Order);
		}
		else
		{
			_squadData.createSquad("findEnemyBaseSquad", Order, WatchPriority);
		}

		Squad & Squad = _squadData.getSquad("findEnemyBaseSquad");

		//计算需要添加的单位数量
		int vultureNeeded = 3;

		for (BWAPI::Unit unit : Squad.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture)
			{
				vultureNeeded -= 1;
			}
		}

		//添加单位
		for (const auto unit : _combatUnits)
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture
				&& vultureNeeded > 0 && _squadData.canAssignUnitToSquad(unit, Squad))
			{
				_squadData.assignUnitToSquad(unit, Squad);
				vultureNeeded -= 1;
			}
		}
	}
	else if (_squadData.squadExists("findEnemyBaseSquad"))
	{
		_squadData.removeSquad("findEnemyBaseSquad");
	}

}

void CombatCommander::updateHarassSquad()
{
	if (_combatUnits.empty())
	{
		return;
	}

	int interval = BWAPI::Broodwar->getFrameCount() % 24;

	if (interval != 1) { return; }

	const int chokeDefenseRadius = 400;

	if (!_squadData.squadExists("harassSquad"))
	{
		SquadOrder attackOrder(SquadOrderTypes::Attack, Bases::Instance().enemyStart()->getPosition() , chokeDefenseRadius, "attack");
		_squadData.createSquad("harassSquad", attackOrder, LinePriority);
	}

	Squad & attackSquad = _squadData.getSquad("harassSquad");

	//添加作战单位
	for (const auto unit : _combatUnits)
	{
		if (unit->getType() == BWAPI::UnitTypes::Terran_Marine ||
			unit->getType() == BWAPI::UnitTypes::Terran_Goliath ||
			unit->getType() == BWAPI::UnitTypes::Terran_Vulture ||
			unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode ||
			unit->getType() == BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode)
		{
			if (_squadData.canAssignUnitToSquad(unit, attackSquad))
			{
				_squadData.assignUnitToSquad(unit, attackSquad);
			}
		}
	}
}

void CombatCommander::updateScvScoutSquad()
{
	if (_combatUnits.empty())
	{
		return;
	}

	int minute = BWAPI::Broodwar->getFrameCount() / (24 * 60);
	if (minute > 3)
	{
		if (_squadData.squadExists("scvScoutSquad"))
		{
			_squadData.removeSquad("scvScoutSquad");
		}
		return;
	}

	//只在前期使用SCV侦察
	if (defenseLine != InformationManager::Instance().getPosition("chokePoint2"))
	{
		if (_squadData.squadExists("scvScoutSquad"))
		{
			_squadData.removeSquad("scvScoutSquad");
		}
		return;
	}

	//假如有雷车侦察，就不需要SCV
	if (BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Spider_Mines))
	{
		if (_squadData.squadExists("scvScoutSquad"))
		{
			_squadData.removeSquad("scvScoutSquad");
		}
		return;
	}

	//在SCV数量达到13时，开始侦察
	if (UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_SCV) < 13)
	{
		if (_squadData.squadExists("scvScoutSquad"))
		{
			_squadData.removeSquad("scvScoutSquad");
		}
		return;
	}

	//判断是否有需要探索的分基地
	BWAPI::Position aimMinePosition = Bases::Instance().getSCVScoutTargetPosition();

	const int scoutAttackRadius = 360;

	SquadOrder mineOrder(SquadOrderTypes::Attack, aimMinePosition, scoutAttackRadius, "attack");

	if (!aimMinePosition)
	{
		if (_squadData.squadExists("scvScoutSquad"))
		{
			_squadData.removeSquad("scvScoutSquad");
		}
		return;
	}
	else if (!_squadData.squadExists("scvScoutSquad"))
	{
		_squadData.createSquad("scvScoutSquad", mineOrder, WatchPriority);
	}

	Squad & scoutSquad = _squadData.getSquad("scvScoutSquad");

	//将雷车集结在埋雷的位置
	scoutSquad.setSquadOrder(mineOrder);

	//计算队列中还剩有蜘蛛雷的雷车的数量，把没有剩余蜘蛛雷的雷车移出队列
	int scvNeeded = 1;

	if (scoutSquad.getUnits().size() > 0)
	{
		scvNeeded--;
 	}

	//for (BWAPI::Unit unit : scoutSquad.getUnits())
	//{
	//	if (unit->getType() != BWAPI::UnitTypes::Terran_SCV)
	//	{
	//		scoutSquad.removeUnit(unit);
	//		continue;
	//	}
	//	scvNeeded -= 1;
	//}

	//添加单位
	for (const auto unit : _combatUnits)
	{
		if (scvNeeded <= 0){ break; }

		if (unit->getType() == BWAPI::UnitTypes::Terran_SCV &&
			_squadData.canAssignUnitToSquad(unit, scoutSquad))
		{
			_squadData.assignUnitToSquad(unit, scoutSquad);
			scvNeeded -= 1;
		}
	}
}

void CombatCommander::updateScoutSquad()
{
	if (_combatUnits.empty())
	{
		return;
	}

	//假如没有研究出蜘蛛雷，删除队伍
	if (!BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Spider_Mines))
	{
		if (_squadData.squadExists("scoutSquad"))
		{
			_squadData.removeSquad("scoutSquad");
		}
		return;
	}
	//判断是否有需要探索的分基地
	BWAPI::Position aimMinePosition = Bases::Instance().getScoutTargetPosition();

	const int scoutAttackRadius = 360;

	SquadOrder mineOrder(SquadOrderTypes::Attack, aimMinePosition, scoutAttackRadius, "attack");

	if (!aimMinePosition)
	{
		if (_squadData.squadExists("scoutSquad"))
		{
			_squadData.removeSquad("scoutSquad");
		}
		return;
	}
	else if (!_squadData.squadExists("scoutSquad"))
	{
		_squadData.createSquad("scoutSquad", mineOrder, WatchPriority);
	}

	Squad & scoutSquad = _squadData.getSquad("scoutSquad");

	//将雷车集结在埋雷的位置
	scoutSquad.setSquadOrder(mineOrder);

	//查看是否还有雷车有雷
	bool hasSpiderMine = false;
	for (const auto unit : _combatUnits)
	{
		if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture &&
			unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
		{
			hasSpiderMine = true;
			break;
		}
	}

	//计算队列中还剩有蜘蛛雷的雷车的数量，把没有剩余蜘蛛雷的雷车移出队列
	int vultureNeeded = 1;

	if (scoutSquad.getUnits().size() > 0)
	{
		BWAPI::Unit unit = * scoutSquad.getUnits().begin();
		//移除没有雷的雷车
		if (!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) && hasSpiderMine)
		{
			scoutSquad.removeUnit(unit);
		}
		else
		{
			vultureNeeded--;
			//放雷
			if ((BWAPI::Broodwar->getFrameCount() - unit->getLastCommandFrame() > 120 || unit->getLastCommand().getType() != BWAPI::UnitCommandTypes::Use_Tech_Position) &&
				unit->getDistance(aimMinePosition) < 100 &&
				unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) &&
				!unit->isMoving())
			{
				unit->useTech(BWAPI::TechTypes::Spider_Mines, aimMinePosition);
			}
		}
	}

	//for (BWAPI::Unit unit : scoutSquad.getUnits())
	//{
	//	//移除没有雷的雷车
	//	if (!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) && hasSpiderMine)
	//	{
	//		scoutSquad.removeUnit(unit);
	//		continue;
	//	}
	//	vultureNeeded -= 1;
	//	//放雷
	//	if ((BWAPI::Broodwar->getFrameCount() - unit->getLastCommandFrame() > 120 || unit->getLastCommand().getType() != BWAPI::UnitCommandTypes::Use_Tech_Position) &&
	//		unit->getDistance(aimMinePosition) < 100 &&
	//		unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) &&
	//		!unit->isMoving())
	//	{
	//		unit->useTech(BWAPI::TechTypes::Spider_Mines, aimMinePosition);
	//	}
	//}

	//添加作战单位
	for (const auto unit : _combatUnits)
	{
		if (vultureNeeded <= 0){ break; }

		if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture &&
			unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) &&
			_squadData.canAssignUnitToSquad(unit, scoutSquad))
		{
			_squadData.assignUnitToSquad(unit, scoutSquad);
			vultureNeeded -= 1;
		}
		else if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture &&
			_squadData.canAssignUnitToSquad(unit, scoutSquad) &&
			!hasSpiderMine)
		{
			_squadData.assignUnitToSquad(unit, scoutSquad);
			vultureNeeded -= 1;
		}
	}
}


//在command center和矿之间放雷的队伍 @liang
void CombatCommander::updateMineCC_MineralSquad()
{
	int numVultures = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Terran_Vulture);

	if (_combatUnits.empty())
	{
		return;
	}

	const int chokeDefenseRadius = 300;

	//获取埋雷的地点
	BWAPI::Position aimMinePosition = getPointBetweenCC_Mineral();

	SquadOrder mineOrder(SquadOrderTypes::Attack, aimMinePosition, chokeDefenseRadius, "attack");

	if (!aimMinePosition)
	{
		if (_squadData.squadExists("mineBaseSquad"))
		{
			_squadData.removeSquad("mineBaseSquad");
		}
		return;
	}
	else if (!_squadData.squadExists("mineBaseSquad"))
	{
		_squadData.createSquad("mineBaseSquad", mineOrder, ReconPriority);
	}
	if (_squadData.squadExists("mineBaseSquad"))
	{
		Squad & mineSquad = _squadData.getSquad("mineBaseSquad");

		//将雷车集结在埋雷的位置
		mineSquad.setSquadOrder(mineOrder);

		//计算队列中还剩有蜘蛛雷的雷车的数量，把没有剩余蜘蛛雷的雷车移出队列
		int vultureNeeded = 1;
		bool isUnitMine = false;
		if (mineSquad.getUnits().size() > 0)
		{
			for (BWAPI::Unit unit : mineSquad.getUnits())//@zhang 2019年9月4日18:18:11 修复bug
			{
				//移除没有雷的雷车
				if (unit->getType() != BWAPI::UnitTypes::Terran_Vulture ||
					!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
				{
					mineSquad.removeUnit(unit);
					continue;
				}
				vultureNeeded -= 1;
				//放雷
				if ((BWAPI::Broodwar->getFrameCount() - unit->getLastCommandFrame() > 120 || unit->getLastCommand().getType() != BWAPI::UnitCommandTypes::Use_Tech_Position) &&
					unit->getDistance(aimMinePosition) < 100 &&
					unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) &&
					!isUnitMine)
				{
					unit->useTech(BWAPI::TechTypes::Spider_Mines, aimMinePosition);
					isUnitMine = true;
				}
			}
		}
			

		//添加作战单位
		for (const auto unit : _combatUnits)
		{
			if (vultureNeeded <= 0) { break; }

			if (unit->getType() == BWAPI::UnitTypes::Terran_Vulture &&
				unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines) &&
				_squadData.canAssignUnitToSquad(unit, mineSquad))
			{
				_squadData.assignUnitToSquad(unit, mineSquad);
				vultureNeeded -= 1;
			}
		}
	}

	
}



bool CombatCommander::canUseMinePosition(BWAPI::Position targetPos)
{
	bool canUseSpiderMine = false;

	if (UnitUtil::GetCompletedUnitCount(BWAPI::UnitTypes::Terran_Vulture) == 0)
	{
		return canUseSpiderMine;
	}

	for (const auto unit : _combatUnits)
	{
		if (unit->getType() != BWAPI::UnitTypes::Terran_Vulture ||
			!unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines))
		{
			continue;
		}
		if (unit->canUseTechPosition(BWAPI::TechTypes::Spider_Mines, targetPos))
		{
			canUseSpiderMine = true;
			break;
		}
	}
	return canUseSpiderMine;
}
//放于阵线后方，负责修理单位，建造地堡和防空塔
void CombatCommander::updateScvSquad()
{
	if (_combatUnits.empty())
	{
		return;
	}

	const int chokeDefenseRadius = 400;


	BWAPI::Position squadPosition = getSquadPosition("41");

	if (defenseLine != InformationManager::Instance().getPosition("chokePoint2"))
	{
		SquadOrder scvOrder(SquadOrderTypes::Idle, squadPosition, chokeDefenseRadius, "repair and build");
		if (_squadData.squadExists("scvSquad"))
		{
			_squadData.getSquad("scvSquad").setSquadOrder(scvOrder);
		}
		else
		{
			_squadData.createSquad("scvSquad", scvOrder, ReconPriority);
		}

		Squad & scvSquad = _squadData.getSquad("scvSquad");
		//计算需要添加的单位数量
		int scvNeeded = 4;
		for (BWAPI::Unit unit : scvSquad.getUnits())
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_SCV)
			{
				scvNeeded -= 1;
			}
		}

		//添加单位
		for (const auto unit : _combatUnits)
		{
			if (unit->getType() == BWAPI::UnitTypes::Terran_SCV 
				&& scvNeeded > 0 && _squadData.canAssignUnitToSquad(unit, scvSquad))
			{
				_squadData.assignUnitToSquad(unit, scvSquad);
				scvNeeded -= 1;
			}
		}
	}
	else if (_squadData.squadExists("scvSquad"))
	{
		_squadData.removeSquad("scvSquad");
	} 
}
// Choose one worker to pull for scout defense.
BWAPI::Unit CombatCommander::findClosestWorkerToTarget(BWAPI::Unitset & unitsToAssign, BWAPI::Unit target)
{
	UAB_ASSERT(target != nullptr, "target was null");
	if (!target)
	{
		return nullptr;
	}

	BWAPI::Unit closestMineralWorker = nullptr;
	int closestDist = Config::Micro::ScoutDefenseRadius + 128;    // more distant workers do not get pulled

	for (const auto unit : unitsToAssign)
	{
		if (unit->getType().isWorker() && WorkerManager::Instance().isFree(unit))
		{
			int dist = unit->getDistance(target);
			if (unit->isCarryingMinerals())
			{
				dist += 96;
			}

			if (dist < closestDist)
			{
				closestMineralWorker = unit;
				dist = closestDist;
			}
		}
	}

	return closestMineralWorker;
}

int CombatCommander::numZerglingsInOurBase() const
{
	const int concernRadius = 200;
	int zerglings = 0;

	BWTA::BaseLocation * main = InformationManager::Instance().getMyMainBaseLocation();
	BWAPI::Position myBasePosition(main->getPosition());

	for (auto unit : BWAPI::Broodwar->enemy()->getUnits())
	{
		if (unit->getType() == BWAPI::UnitTypes::Zerg_Zergling &&
			unit->getDistance(myBasePosition) < concernRadius)
		{
			++zerglings;
		}
	}
	return zerglings;
}

// Is an enemy building near our base? If so, we may pull workers.
bool CombatCommander::buildingRush() const
{
	// If we have units, there will be no need to pull workers.
	/*if (InformationManager::Instance().weHaveCombatUnits())//@zhang 
	{
		return false;
	}*/

	BWTA::BaseLocation * main = InformationManager::Instance().getMyMainBaseLocation();
	BWAPI::Position myBasePosition(main->getPosition());

	for (const auto unit : BWAPI::Broodwar->enemy()->getUnits())
	{
		if (unit->getType().isBuilding() && unit->getDistance(myBasePosition) < 1200)
		{
			return true;
		}
	}

	return false;
}

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