BWAPI::Unit ProductionManager::getClosestUnitToPosition(const BWAPI::Unitset & units, BWAPI::Position closestTo)
{
    if (units.size() == 0)
    {
        return nullptr;
    }

    // if we don't care where the unit is return the first one we have
    if (closestTo == BWAPI::Positions::None)
    {
        return *(units.begin());
    }

    BWAPI::Unit closestUnit = nullptr;
    double minDist(1000000);

	for (auto & unit : units) 
    {
        UAB_ASSERT(unit != nullptr, "Unit was null");

		double distance = unit->getDistance(closestTo);
		if (!closestUnit || distance < minDist) 
        {
			closestUnit = unit;
			minDist = distance;
		}
	}

    return closestUnit;
}
Beispiel #2
0
void CombatCommander::StayPut() {

	Squad & stayPut = _squadData.getSquad("StayPut");
	// defend untill we have a science vessel
	if (_combatUnits.empty() || BWAPI::Broodwar->self()->allUnitCount(BWAPI::UnitTypes::Terran_Science_Vessel) == 1)
	{
		return;
	}

	for (auto & unit : _combatUnits)
	{
		// get every unit of a lower priority and put it into the defense squad
		if (!unit->getType().isWorker() && (unit->getType() != BWAPI::UnitTypes::Zerg_Overlord) && _squadData.canAssignUnitToSquad(unit, stayPut))
		{
			// if theres a bunker with room, go into it
			for (auto unit2 : BWAPI::Broodwar->self()->getUnits()){
				if ((*unit2).getType() == BWAPI::UnitTypes::Terran_Bunker){
					BWAPI::Unit bunker = BWAPI::Broodwar->getUnit((*unit2).getID());
					BWAPI::Unitset set = bunker->getLoadedUnits();
					if (set.size() < 4) {
						(*unit).rightClick(bunker);
					}
				}
			}
			// add units to squad
			_squadData.assignUnitToSquad(unit, stayPut);
		}
	}

	// fufill squad order
	SquadOrder mainAttackOrder(SquadOrderTypes::Defend, defensePos, 300, "Attack Enemy Base");
	stayPut.setSquadOrder(mainAttackOrder);
}
bool Squad::unitNearEnemy(BWAPI::Unit unit)
{
	assert(unit);

	BWAPI::Unitset enemyNear;

	MapGrid::Instance().GetUnits(enemyNear, unit->getPosition(), 400, false, true);

	return enemyNear.size() > 0;
}
Beispiel #4
0
std::unordered_map<BWAPI::Unit, BWAPI::Unit> RangedManager::assignEnemy(const BWAPI::Unitset &meleeUnits, BWAPI::Unitset & meleeUnitTargets)
{
	std::unordered_map<BWAPI::Unit, BWAPI::Unit> attacker2target;
	std::vector<PairEdge> edges(meleeUnits.size()*meleeUnitTargets.size());
	int top = 0;
	for (auto &attacker : meleeUnits)
	{
		for (auto &target : meleeUnitTargets)
		{
			if (!target)
				continue;
			edges[top].attacker = attacker;
			edges[top].target = target;
			int groundWeaponRange = attacker->getType().groundWeapon().maxRange();
			edges[top++].distance = -getRealPriority(attacker, target);
		}
	}
	sort(edges.begin(), edges.end());
	sort(edges.begin(), edges.end(), [](PairEdge a, PairEdge b)
	{
		return a.target->getID() <b.target->getID();
	});
	PairEdge dummy;
	dummy.target = nullptr;
	edges.push_back(dummy);
	BWAPI::Unit p = nullptr;
	int sum = 0;
	for (auto idx = edges.begin(); idx!=edges.end(); idx++)
	{
		if (!idx->target)
			continue;
		double Health = (((double)idx->target->getHitPoints() + idx->target->getShields()));
		if (idx->target->getType().size() == BWAPI::UnitSizeTypes::Small)
			Health *= 2;
		if (idx->target->getType().size() == BWAPI::UnitSizeTypes::Medium)
			Health *= 1.5;
		if (p != idx->target)
		{
			sum = 0;
			p = idx->target;			
		}
		else
		{
			sum++;
			//assign at most 7 units attack
			//BWAPI::Broodwar <<( idx->target->getHitPoints()+idx->target->getShields()) / idx->attacker->getType().groundWeapon().damageAmount() << std::endl;
			if (sum>std::min(8, 1+(int)(Health / idx->attacker->getType().groundWeapon().damageAmount())))
			{
				idx->attacker = nullptr;
				if (meleeUnitTargets.find(idx->target) != meleeUnitTargets.end())
					meleeUnitTargets.erase(idx->target);
			}
		}
	}
	int t = 0;
	for (bool halt=false; halt == false; halt = true)
	{
		halt= true;
		auto tmpRangeStart = edges.begin();
		auto maxRangeStart = tmpRangeStart, maxRangeEnd = tmpRangeStart;
		double tmpsum = 0, tmpres = INT_MIN;
		for (auto idx = edges.begin(); idx->target != nullptr; idx++)
		{
			if (attacker2target.find(idx->attacker) != attacker2target.end())
				continue;
			if (idx->target != (idx + 1)->target)
			{
				if (tmpsum > tmpres)
				{
					tmpres = tmpsum;
					maxRangeStart = tmpRangeStart;
					maxRangeEnd = idx + 1;
				}
				tmpsum = 0;
				tmpRangeStart = idx + 1;
			}
			else
				tmpsum += getRealPriority(idx->attacker, idx->target);
		}
		for (auto kdx = maxRangeStart; kdx < maxRangeEnd; kdx++)
		{
			if (attacker2target.find(kdx->attacker) != attacker2target.end())
				continue;
			attacker2target[kdx->attacker] = kdx->target;
			halt = false;
		}
		t++;
	}
	return attacker2target;
}
BWAPI::Unit ProductionManager::getProducer(MetaType t, BWAPI::Position closestTo)
{
    // get the type of unit that builds this
    BWAPI::UnitType producerType = t.whatBuilds();

    // make a set of all candidate producers
    BWAPI::Unitset candidateProducers;
    for (auto & unit : BWAPI::Broodwar->self()->getUnits())
    {
        UAB_ASSERT(unit != nullptr, "Unit was null");

        // reasons a unit can not train the desired type
        if (unit->getType() != producerType)                    { continue; }
        if (!unit->isCompleted())                               { continue; }
        if (unit->isTraining())                                 { continue; }
        if (unit->isLifted())                                   { continue; }
        if (!unit->isPowered())                                 { continue; }

        // if the type is an addon, some special cases
        if (t.getUnitType().isAddon())
        {
            // if the unit already has an addon, it can't make one
            if (unit->getAddon() != nullptr)
            {
                continue;
            }

            // if we just told this unit to build an addon, then it will not be building another one
            // this deals with the frame-delay of telling a unit to build an addon and it actually starting to build
            if (unit->getLastCommand().getType() == BWAPI::UnitCommandTypes::Build_Addon 
                && (BWAPI::Broodwar->getFrameCount() - unit->getLastCommandFrame() < 10)) 
            { 
                continue; 
            }

            bool isBlocked = false;

            // if the unit doesn't have space to build an addon, it can't make one
            BWAPI::TilePosition addonPosition(unit->getTilePosition().x + unit->getType().tileWidth(), unit->getTilePosition().y + unit->getType().tileHeight() - t.getUnitType().tileHeight());
            BWAPI::Broodwar->drawBoxMap(addonPosition.x*32, addonPosition.y*32, addonPosition.x*32 + 64, addonPosition.y*32 + 64, BWAPI::Colors::Red);
            
            for (int i=0; i<unit->getType().tileWidth() + t.getUnitType().tileWidth(); ++i)
            {
                for (int j=0; j<unit->getType().tileHeight(); ++j)
                {
                    BWAPI::TilePosition tilePos(unit->getTilePosition().x + i, unit->getTilePosition().y + j);

                    // if the map won't let you build here, we can't build it
                    if (!BWAPI::Broodwar->isBuildable(tilePos))
                    {
                        isBlocked = true;
                        BWAPI::Broodwar->drawBoxMap(tilePos.x*32, tilePos.y*32, tilePos.x*32 + 32, tilePos.y*32 + 32, BWAPI::Colors::Red);
                    }

                    // if there are any units on the addon tile, we can't build it
                    BWAPI::Unitset uot = BWAPI::Broodwar->getUnitsOnTile(tilePos.x, tilePos.y);
                    if (uot.size() > 0 && !(uot.size() == 1 && *(uot.begin()) == unit))
                    {
                        isBlocked = true;;
                        BWAPI::Broodwar->drawBoxMap(tilePos.x*32, tilePos.y*32, tilePos.x*32 + 32, tilePos.y*32 + 32, BWAPI::Colors::Red);
                    }
                }
            }

            if (isBlocked)
            {
                continue;
            }
        }
        
        // if the type requires an addon and the producer doesn't have one
        typedef std::pair<BWAPI::UnitType, int> ReqPair;
        for (const ReqPair & pair : t.getUnitType().requiredUnits())
        {
            BWAPI::UnitType requiredType = pair.first;
            if (requiredType.isAddon())
            {
                if (!unit->getAddon() || (unit->getAddon()->getType() != requiredType))
                {
                    continue;
                }
            }
        }

        // if we haven't cut it, add it to the set of candidates
        candidateProducers.insert(unit);
    }

    return getClosestUnitToPosition(candidateProducers, closestTo);
}
int LurkerManager::targetsInRange(BWAPI::Unit LurkerUnit, const BWAPI::Unitset & targets) {
	BWAPI::Unitset nearbyEnemies;
	MapGrid::Instance().GetUnits(nearbyEnemies, LurkerUnit->getPosition() , BWAPI::UnitTypes::Zerg_Lurker.seekRange() + 10, false, true);
	return nearbyEnemies.size();
}
std::unordered_map<BWAPI::Unit, BWAPI::Unit> InterceptorManager::assignEnemy(const BWAPI::Unitset &meleeUnits, const BWAPI::Unitset & meleeUnitTargets)
{
	std::unordered_map<BWAPI::Unit, BWAPI::Unit> attacker2target;
	std::vector<PairEdge> edges(meleeUnits.size()*meleeUnitTargets.size());
	int top = 0;
	for (auto &attacker : meleeUnits)
	{
		for (auto &target : meleeUnitTargets)
		{
			edges[top].attacker = attacker;
			edges[top].target = target;
			int groundWeaponRange = attacker->getType().groundWeapon().maxRange();
			edges[top++].distance = -getRealPriority(attacker, target);
		}
	}
	sort(edges.begin(), edges.end());
	edges.resize(edges.size()*3/4);
	sort(edges.begin(), edges.end(), [](PairEdge a, PairEdge b)
	{
		return (int)a.target < (int)b.target;
	});
	PairEdge dummy;
	dummy.target = nullptr;
	edges.push_back(dummy);
	BWAPI::Unit p = nullptr;
	int sum = 0;
	for (auto idx = edges.begin(); idx->target != nullptr; idx++)
	{
		if (p != idx->target)
		{
			sum = 0;
			p = idx->target;
		}
		else
		{
			sum++;
			//assign at most 7 units attack
			//BWAPI::Broodwar <<( idx->target->getHitPoints()+idx->target->getShields()) / idx->attacker->getType().groundWeapon().damageAmount() << std::endl;
			int damagePerUnit = idx->attacker->getType().groundWeapon().damageAmount();
			if (sum<std::min(6, std::max(2*idx->target->getHitPoints() / idx->attacker->getType().groundWeapon().damageAmount() - 1, 1)))
			{
				idx->attacker = nullptr;
			}
		}
	}
	for (bool halt = true; halt == false; halt = true)
	{
		auto tmpRangeStart = edges.begin();
		auto maxRangeStart = tmpRangeStart, maxRangeEnd = tmpRangeStart;
		double tmpsum = 0, tmpres = INT_MIN;
		for (auto idx = edges.begin(); idx->target != nullptr; idx++)
		{
			if (attacker2target.find(idx->attacker) != attacker2target.end())
				continue;
			if (idx->target != (idx + 1)->target)
			{
				if (tmpsum > tmpres)
				{
					tmpres = tmpsum;
					maxRangeStart = tmpRangeStart;
					maxRangeEnd = idx + 1;
				}
				tmpsum = 0;
				tmpRangeStart = idx + 1;
			}
			else
				tmpsum += getRealPriority(idx->attacker, idx->target);
		}
		for (auto kdx = maxRangeStart; kdx != maxRangeEnd; kdx++)
		{
			if (attacker2target.find(kdx->attacker) != attacker2target.end())
				continue;
			attacker2target[kdx->attacker] = kdx->target;
			halt = false;
		}
	}
	return attacker2target;
}
Beispiel #8
0
void CombatCommander::updateScoutDefenseSquad() 
{
    if (_combatUnits.empty()) 
    { 
        return; 
    }

    // if the current squad has units in it then we can ignore this
    Squad & scoutDefenseSquad = _squadData.getSquad("ScoutDefense");
  
    // get the region that our base is located in
    BWTA::Region * myRegion = BWTA::getRegion(BWAPI::Broodwar->self()->getStartLocation());
    if (!myRegion && myRegion->getCenter().isValid())
    {
        return;
    }

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

    // if there's an enemy worker in our region then assign someone to chase him
    bool assignScoutDefender = enemyUnitsInRegion.size() == 1 && (*enemyUnitsInRegion.begin())->getType().isWorker();

    // if our current squad is empty and we should assign a worker, do it
    if (scoutDefenseSquad.isEmpty() && assignScoutDefender)
    {
        // the enemy worker that is attacking us
        BWAPI::Unit enemyWorker = *enemyUnitsInRegion.begin();

        // get our worker unit that is mining that is closest to it
        BWAPI::Unit workerDefender = findClosestWorkerToTarget(_combatUnits, enemyWorker);

		if (enemyWorker && workerDefender)
		{
			// grab it from the worker manager and put it in the squad
            if (_squadData.canAssignUnitToSquad(workerDefender, scoutDefenseSquad))
            {
			    WorkerManager::Instance().setCombatWorker(workerDefender);
                _squadData.assignUnitToSquad(workerDefender, scoutDefenseSquad);
            }
		}
    }
    // if our squad is not empty and we shouldn't have a worker chasing then take him out of the squad
    else if (!scoutDefenseSquad.isEmpty() && !assignScoutDefender)
    {
        for (auto & unit : scoutDefenseSquad.getUnits())
        {
            unit->stop();
            if (unit->getType().isWorker())
            {
                WorkerManager::Instance().finishedWithWorker(unit);
            }
        }

        scoutDefenseSquad.clear();
    }
}
Beispiel #9
0
//dist is distance between middle unit and target gravity center, interval is length of arc between two units
bool MicroManager::formSquad(const BWAPI::Unitset & targets, int dist, int radius, double angle, int interval)
{
	const BWAPI::Unitset & meleeUnits = getUnits();
	bool attacked = false;
	BWAPI::Position tpos = targets.getPosition();
	BWAPI::Position mpos = meleeUnits.getPosition();

	//do not from squad when fighting or close to enemy
	for (auto & unit : meleeUnits){
		if (unit->isUnderAttack() || unit->isAttackFrame() || targets.size() == 0|| unit->getDistance(tpos) < 80)
			attacked = true;
	}
	if (attacked) {
		BWAPI::Broodwar->drawTextScreen(200, 340, "%s", "Attacked or No targets, Stop Formation");
		return false;
	}
	//if there is a building near the unit, do not form
	for (auto & target : targets){
		auto type = target->getType();
		if (type.isBuilding()){
			return false;
		}
	}
	//Formation is set false by Squad for 5 seconds after formation finished once
	if (!getFormation()){
		BWAPI::Broodwar->drawTextScreen(200, 340, "%s", "Finished Formation");
		return false;
	}
	//BWAPI::Broodwar->drawTextScreen(200, 340, "%s", "Forming");

	const double PI = 3.14159265;

	double ang = angle / 180 * PI;

	//the angle of mid_point on arc
	double m_ang = atan2(mpos.y - tpos.y, mpos.x - tpos.x);
	//circle center
	int cx = (int)(tpos.x - (radius-dist) * cos(m_ang));
	int cy = (int)(tpos.y - (radius-dist) * sin(m_ang));
	BWAPI::Position c;
	c.x = cx; c.y = cy;
	//mid_point on arc
	BWAPI::Position m;
	m.x = (int)(cx + radius*cos(m_ang));
	m.y = (int)(cy + radius*sin(m_ang));
	BWAPI::Broodwar->drawLineMap(c, m, BWAPI::Colors::Yellow);

	BWAPI::Unitset unassigned;
	for (auto & unit : meleeUnits){
		unassigned.insert(unit);
	}

	//move every positions on the arc to the closest unit
	BWAPI::Position tmp;
	int try_time = 0;
	int r = radius;
	int total_dest_dist = 0;
	int num_assigned = 0;

	while (unassigned.size() > 0 && try_time < 5){
		double ang_interval = interval * 1.0 / r;
		double final_ang;
		int num_to_assign;
		int max_units = (int)(ang / ang_interval) + 1;
		if (unassigned.size() < (unsigned)max_units){
			num_to_assign = unassigned.size();
			final_ang = ang_interval * num_to_assign;
		}
		else {
			num_to_assign = max_units;
			final_ang = ang;
		}
		for (int i = 0; i < num_to_assign; i++) {
			//assign from two ends to middle
			double a = m_ang + pow(-1, i % 2)*(final_ang / 2 - (i / 2)*ang_interval);
			int min_dist = MAXINT;
			BWAPI::Unit closest_unit = nullptr;
			tmp.x = (int)(cx + r * cos(a));
			tmp.y = (int)(cy + r * sin(a));
			for (auto & unit : unassigned){
				int d = unit->getDistance(tmp);
				if (d < min_dist){
					min_dist = d;
					closest_unit = unit;
				}
			}
			//if it's a unit far away from fight, do not assign it to a position
			if (closest_unit && min_dist > 300){
				unassigned.erase(closest_unit);
				continue;
			}
			if (tmp.isValid() && closest_unit){
				BWAPI::Broodwar->drawLineMap(closest_unit->getPosition(), tmp, BWAPI::Colors::Red);
				Micro::SmartMove(closest_unit, tmp);
				unassigned.erase(closest_unit);
				//find the total distance between unit and destination
				total_dest_dist += min_dist;
				num_assigned++;
			}		
		}
		r += 40;
		try_time++;
	}

	//if max destination distance less than 32, means forming has been finished
	if (num_assigned > 0 && total_dest_dist / num_assigned <= 32){
		return true;
	}
	else {
		BWAPI::Broodwar->drawTextScreen(200, 340, "%s", "Forming");
		return false;
	}
}
Beispiel #10
0
BWAPI::Unit ProductionManager::getClosestUnitToPosition(const BWAPI::Unitset & units, BWAPI::Position closestTo)
{
	

    if (units.size() == 0)
    {
        return nullptr;
    }

    // if we don't care where the unit is return the first one we have
    if (closestTo == BWAPI::Positions::None)
    {
        return *(units.begin());
    }

    BWAPI::Unit closestUnit = nullptr;
    double minDist(1000000);
	
	/*
	bool makeFirstSunken = false;
	if (!BuildingManager::Instance().isCreepStarted())
	{
	
		BWAPI::TilePosition myHatchPos = BuildingManager::Instance().createdHatcheriesVector[0];
		if (closestTo == BWAPI::Position(myHatchPos))
		{
			makeFirstSunken = true;
			BWAPI::Unitset myUnits = BWAPI::Broodwar->self()->getUnits();

			for (auto & unit : myUnits)
			{
				if (unit->getID() == BuildingManager::Instance().sunkenID)
				{
					return unit;
				}
			}

			//return BWAPI::Unit(BuildingManager::Instance().sunkenID);
		}
	
	
	}
	/*
	std::vector<BWAPI::TilePosition> myUnitsTile;
	std::vector<BWAPI::Position> myUnitsPosition;

	std::vector<BWAPI::TilePosition> myUnitsTile2;
	std::vector<BWAPI::Position> myUnitsPosition2;
	for (auto & unit : units)
	{
		myUnitsTile.push_back(unit->getTilePosition());
		myUnitsPosition.push_back(unit->getPosition());
	}
	BWAPI::Unitset myUnits = BWAPI::Broodwar->self()->getUnits();
	for (BWAPI::Unit p : myUnits)
	{
		if (p->getType().isWorker())
		{
			myUnitsTile2.push_back(p->getTilePosition());
			myUnitsPosition2.push_back(p->getPosition());
		}
	}
	*/
	for (auto & unit : units) 
	{ 
		
		/**
		if (makeFirstSunken)
		{
			BWAPI::TilePosition myHatchPos = BuildingManager::Instance().createdHatcheriesVector[0];
			BWAPI::TilePosition tempPosition;
			tempPosition.x = myHatchPos.x+2;
			tempPosition.y = myHatchPos.y+2;

			if (tempPosition == unit->getTilePosition())
			{
				return unit;
			}
			
		}
		*/

        UAB_ASSERT(unit != nullptr, "Unit was null");

		double distance = unit->getDistance(closestTo);
		if (!closestUnit || distance < minDist) 
        {
			closestUnit = unit;
			minDist = distance;
		}
	}
	//BWAPI::TilePosition myHatchPos = BuildingManager::Instance().createdHatcheriesVector[0];
	//BWAPI::TilePosition finalTilePos = closestUnit->getTilePosition();

    return closestUnit;
}