BWAPI
Public Member Functions | Private Attributes
BasicUnitAction Class Reference

#include <BasicUnitAction.h>

Inheritance diagram for BasicUnitAction:
Inheritance graph
[legend]
Collaboration diagram for BasicUnitAction:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 BasicUnitAction (Unit unit, const std::list< std::set< BWAPI::UnitType >> &targetPriorities)
bool update (const Goal &squadGoal, const UnitGroup &squadUnitGroup)

Private Attributes

std::list< std::set
< BWAPI::UnitType > > 
mTargetPriorities

Detailed Description

Definition at line 6 of file BasicUnitAction.h.


Constructor & Destructor Documentation

BasicUnitAction::BasicUnitAction ( Unit  unit,
const std::list< std::set< BWAPI::UnitType >> &  targetPriorities 
) [inline]

Definition at line 9 of file BasicUnitAction.h.

: SingleMicroActionBaseClass(unit), mTargetPriorities(targetPriorities) {}

Member Function Documentation

bool BasicUnitAction::update ( const Goal squadGoal,
const UnitGroup squadUnitGroup 
) [virtual]

Implements SingleMicroActionBaseClass.

Definition at line 22 of file BasicUnitAction.cpp.

References ActionTypeDef::Attack, BWAPI::Broodwar, ActionTypeDef::Defend, BWAPI::TechTypes::EMP_Shockwave, BWAPI::TechType::energyUsed(), Goal::getActionType(), BWAPI::Game::getRemainingLatencyFrames(), BWAPI::TechType::getWeapon(), ActionTypeDef::Hold, Singleton< T >::Instance(), UnitHelper::isArmyUnit(), UnitHelper::isStaticDefense(), BWAPI::UnitType::isWorker(), AccessTypeDef::Lost, BWAPI::WeaponType::maxRange(), mTargetPriorities, SingleMicroActionBaseClass::mUnit, BWAPI::UnitTypes::Protoss_Arbiter, BWAPI::UnitTypes::Protoss_Scarab, BWAPI::UnitTypes::Protoss_Zealot, ActionTypeDef::Retreat, BWAPI::UnitType::seekRange(), stayAtRange(), BWAPI::UnitType::supplyProvided(), BWAPI::UnitTypes::Terran_Bunker, BWAPI::UnitTypes::Terran_Science_Vessel, BWAPI::UnitTypes::Terran_Vulture_Spider_Mine, BWAPI::UnitType::topSpeed(), BWAPI::UnitTypes::Zerg_Egg, and BWAPI::UnitTypes::Zerg_Larva.

{
        const int seekRange = 448;
        // TODO: Implement a better system, maybe some PFs and other goodies
        // currently a copy paste of 2010 micro

        if(mUnit->isAttackFrame() || mUnit->isStasised() || mUnit->isLockedDown())
                return true;

        const bool isTargetOfThreat = AOEThreatTracker::Instance().isTargetOfThreat(mUnit);
        if(!isTargetOfThreat)
        {
                const AOEThreat &closestThreat = AOEThreatTracker::Instance().getClosestThreat(mUnit);
                if(closestThreat)
                {
                        const int distanceToThreat = mUnit->getDistance(closestThreat->getPosition());
                        if(distanceToThreat < closestThreat->getRadius()+32)
                        {
                                stayAtRange(mUnit, closestThreat->getPosition(), closestThreat->getRadius() + 64, distanceToThreat);
                                return true;
                        }
                }
        }

        const BWAPI::UnitType &actionUnitType = mUnit->getType();

        const bool shouldEngage = squadGoal.getActionType() == ActionType::Attack || squadGoal.getActionType() == ActionType::Defend || squadGoal.getActionType() == ActionType::Hold;

        int currentTargetPriority = std::numeric_limits<int>::max();
        Unit currentTargetUnit;

        int goalTartgetDistance = std::numeric_limits<int>::max();
        int goalTargetPriority = std::numeric_limits<int>::max();
        Unit goalTargetUnit;

        int closestUnitDistance = std::numeric_limits<int>::max();
        int closestUnitRange = 0;
        Unit closestUnit;

        UnitGroup possibleTargets;
        for each(Unit unit in UnitTracker::Instance().selectAllEnemy())
        {
                if(unit->isStasised())
                        continue;

                const BWAPI::UnitType &type = unit->getType();
                if(type == BWAPI::UnitTypes::Zerg_Egg || type == BWAPI::UnitTypes::Zerg_Larva || type == BWAPI::UnitTypes::Protoss_Scarab)
                        continue;

                if(unit->accessibility() == AccessType::Lost)
                        continue;

                if(mUnit->getPosition().getApproxDistance(unit->getPosition()) > seekRange)
                        continue;

                if(unit->canAttack(mUnit) || type == BWAPI::UnitTypes::Terran_Science_Vessel)
                {
                        const int weaponRange = type == BWAPI::UnitTypes::Terran_Science_Vessel ? BWAPI::TechTypes::EMP_Shockwave.getWeapon().maxRange() : type == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine ? BWAPI::UnitTypes::Terran_Vulture_Spider_Mine.seekRange() : unit->getWeaponMaxRange(mUnit);
                        const int distance = mUnit->getDistance(unit) - weaponRange;
                        if(distance < closestUnitDistance)
                        {
                                closestUnitRange = weaponRange;
                                closestUnitDistance = distance;
                                closestUnit = unit;
                        }
                }

                if(type == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine && actionUnitType == BWAPI::UnitTypes::Protoss_Zealot)
                        continue;

                if(!mUnit->canAttackNow(unit))
                        continue;

                //TODO: health tracker of some type, if the unit will be dead by the time the bullet hits, continue

                const bool isActionUnitSlower = actionUnitType.topSpeed()*0.7 < type.topSpeed();
                const bool isUnitGoalWorthy = (shouldEngage && squadGoal.getEngageUnits().count(unit) != 0) || unit->isInRange(mUnit) || mUnit->isInRange(unit);

                int unitPriority = isUnitGoalWorthy ? 0 : isActionUnitSlower ? 4 : 2;

                std::list<std::set<BWAPI::UnitType>>::const_iterator it = mTargetPriorities.begin();
                while(it != mTargetPriorities.end())
                {
                        if(it->count(type) != 0)
                                break;
                        else
                                ++unitPriority;

                        ++it;
                }

                if(it == mTargetPriorities.end())//Unit not found in the priorities list
                {
                        if(UnitHelper::isArmyUnit(type) || UnitHelper::isStaticDefense(type) || type == BWAPI::UnitTypes::Terran_Bunker)
                                unitPriority += 1;
                        else if(type.isWorker())
                                unitPriority += 2;
                        else if(type.supplyProvided() > 0)
                                unitPriority += 3;
                        else
                                unitPriority += 4;

                        if(!unit->isCompleted())
                                unitPriority += 1;
                }

                if(squadGoal.getActionType() != ActionType::Retreat && mUnit->isInRange(unit))
                {
                        if(unitPriority < currentTargetPriority || (unitPriority == currentTargetPriority && unit->totalHitPointFraction() < currentTargetUnit->totalHitPointFraction()))
                        {
                                currentTargetPriority = unitPriority;
                                currentTargetUnit = unit;
                        }
                }

                if(!isUnitGoalWorthy && isActionUnitSlower)
                        continue;

                const int distance = mUnit->getDistance(unit);
                if(unitPriority < goalTargetPriority || (unitPriority == goalTargetPriority && distance < goalTartgetDistance))
                {
                        goalTartgetDistance = distance;
                        goalTargetPriority = unitPriority;
                        goalTargetUnit = unit;
                }
        }

        // If the target of a threat, dont do anything to cause it to move
        if(isTargetOfThreat)
        {
                if(currentTargetUnit)
                        mUnit->attack(currentTargetUnit);
                else
                        mUnit->stop();
                return true;
        }
        
        const int closestDistance = closestUnit ? mUnit->getDistance(closestUnit) : 0;
        if(closestUnit)
        {
                bool doNotEngageClosest = false;
                if(closestDistance < closestUnitRange + 250)
                {
                        if(squadGoal.getAvoidUnits().count(closestUnit) != 0)
                                doNotEngageClosest = true;
                        else
                                doNotEngageClosest = !goalTargetUnit && mUnit->getDistance(squadGoal.getPositionForMerge()) < 140;
                }

                if(doNotEngageClosest)
                {
                        stayAtRange(mUnit, closestUnit->getPosition(), closestUnitRange + 290, closestDistance);
                        return true;
                }

                bool canAttack = mUnit->canAttackAir() || mUnit->canAttackGround();
                if(actionUnitType == BWAPI::UnitTypes::Protoss_Arbiter)
                        canAttack = false;

                if(!canAttack && actionUnitType.isSpellcaster())
                {
                        for each(BWAPI::TechType tech in mUnit->getType().abilities())
                        {
                                if(BWAPI::Broodwar->self()->hasResearched(tech) && mUnit->getEnergy() >= tech.energyUsed())
                                        canAttack = true;
                        }
                }

                int rangeToStayAt = 0;
                if(!canAttack)
                        rangeToStayAt = closestUnitRange+32;

                if(actionUnitType.maxEnergy() > 0 && closestUnit->getType() == BWAPI::UnitTypes::Terran_Science_Vessel)
                        rangeToStayAt = std::max(rangeToStayAt, BWAPI::TechTypes::EMP_Shockwave.getWeapon().maxRange()+32);

                if(rangeToStayAt != 0 && closestDistance < rangeToStayAt)
                {
                        stayAtRange(mUnit, closestUnit->getPosition(), rangeToStayAt, closestDistance);
                        return true;
                }
        }

        const bool canAttackCurrentTarget = currentTargetUnit && mUnit->getRemainingCooldown(currentTargetUnit) <= BWAPI::Broodwar->getRemainingLatencyFrames();
        const bool isCurrentTargetImportant = currentTargetUnit && (UnitHelper::isArmyUnit(currentTargetUnit->getType()) || UnitHelper::isStaticDefense(currentTargetUnit->getType()));
        const bool goalBetterThanCurrent = canAttackCurrentTarget && goalTargetPriority < currentTargetPriority && !isCurrentTargetImportant;

        if(goalBetterThanCurrent)
        {
                mUnit->attack(goalTargetUnit);
                return true;
        }
        else if(canAttackCurrentTarget)
        {
                mUnit->attack(currentTargetUnit);
                return true;
        }

        if(closestUnit && !goalTargetUnit && closestUnit->getType() == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine)
        {
                if(closestDistance < BWAPI::UnitTypes::Terran_Vulture_Spider_Mine.seekRange()+32)
                {
                        stayAtRange(mUnit, closestUnit->getPosition(), BWAPI::UnitTypes::Terran_Vulture_Spider_Mine.seekRange()+32, closestDistance);
                        return true;
                }
        }

        if(closestUnit && closestUnit->exists() && currentTargetUnit)
        {
                if(mUnit->canAttack(closestUnit))
                {
                        const int myRange = mUnit->getWeaponMaxRange(closestUnit);
                        if(closestDistance < myRange && myRange > 60)
                        {
                                stayAtRange(mUnit, closestUnit->getPosition(), myRange, closestDistance);
                                return true;
                        }
                }
        }

        if(goalTargetUnit && goalTargetPriority < currentTargetPriority)
        {
                mUnit->attack(goalTargetUnit);
                return true;
        }

        if(!canAttackCurrentTarget)
        {
                if(squadGoal.getActionType() == ActionType::Attack)
                {
                        if(!isCurrentTargetImportant && mUnit->getDistance(currentTargetUnit) > 5)
                        {
                                mUnit->move(currentTargetUnit->getPosition());
                                return true;
                        }
                }
        }

        if(currentTargetUnit)
        {
                mUnit->attack(currentTargetUnit);
                return true;
        }

        if(closestUnit && mUnit->canAttack(closestUnit))
        {
                mUnit->attack(closestUnit);
                return true;
        }

        return false;
}

Here is the call graph for this function:


Member Data Documentation

std::list<std::set<BWAPI::UnitType> > BasicUnitAction::mTargetPriorities [private]

Definition at line 14 of file BasicUnitAction.h.

Referenced by update().


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines