\hypertarget{classBasicUnitAction}{\section{\-Basic\-Unit\-Action \-Class \-Reference}
\label{classBasicUnitAction}\index{\-Basic\-Unit\-Action@{\-Basic\-Unit\-Action}}
}


{\ttfamily \#include $<$\-Basic\-Unit\-Action.\-h$>$}



\-Inheritance diagram for \-Basic\-Unit\-Action\-:\nopagebreak
\begin{figure}[H]
\begin{center}
\leavevmode
\includegraphics[width=238pt]{classBasicUnitAction__inherit__graph}
\end{center}
\end{figure}


\-Collaboration diagram for \-Basic\-Unit\-Action\-:\nopagebreak
\begin{figure}[H]
\begin{center}
\leavevmode
\includegraphics[width=238pt]{classBasicUnitAction__coll__graph}
\end{center}
\end{figure}
\subsection*{\-Public \-Member \-Functions}
\begin{DoxyCompactItemize}
\item 
\hyperlink{classBasicUnitAction_a9da1de11751fffcb48a5ec9181402d61}{\-Basic\-Unit\-Action} (\hyperlink{Interface_8h_ab8fbb9e601c27f783b69f16c5a1fd40a}{\-Unit} unit, const std\-::list$<$ std\-::set$<$ \hyperlink{classBWAPI_1_1UnitType}{\-B\-W\-A\-P\-I\-::\-Unit\-Type} $>$$>$ \&target\-Priorities)
\item 
bool \hyperlink{classBasicUnitAction_a5cfdd9e3257503499f1968629f0f7db6}{update} (const \hyperlink{classGoal}{\-Goal} \&squad\-Goal, const \hyperlink{classUnitGroup}{\-Unit\-Group} \&squad\-Unit\-Group)
\end{DoxyCompactItemize}
\subsection*{\-Private \-Attributes}
\begin{DoxyCompactItemize}
\item 
std\-::list$<$ std\-::set\*
$<$ \hyperlink{classBWAPI_1_1UnitType}{\-B\-W\-A\-P\-I\-::\-Unit\-Type} $>$ $>$ \hyperlink{classBasicUnitAction_a3ea9e7e4be7bde0a04d98cff9d40de18}{m\-Target\-Priorities}
\end{DoxyCompactItemize}


\subsection{\-Detailed \-Description}


\-Definition at line 6 of file \-Basic\-Unit\-Action.\-h.



\subsection{\-Constructor \& \-Destructor \-Documentation}
\hypertarget{classBasicUnitAction_a9da1de11751fffcb48a5ec9181402d61}{\index{\-Basic\-Unit\-Action@{\-Basic\-Unit\-Action}!\-Basic\-Unit\-Action@{\-Basic\-Unit\-Action}}
\index{\-Basic\-Unit\-Action@{\-Basic\-Unit\-Action}!BasicUnitAction@{\-Basic\-Unit\-Action}}
\subsubsection[{\-Basic\-Unit\-Action}]{\setlength{\rightskip}{0pt plus 5cm}{\bf \-Basic\-Unit\-Action\-::\-Basic\-Unit\-Action} (
\begin{DoxyParamCaption}
\item[{{\bf \-Unit}}]{unit, }
\item[{const std\-::list$<$ std\-::set$<$ {\bf \-B\-W\-A\-P\-I\-::\-Unit\-Type} $>$$>$ \&}]{target\-Priorities}
\end{DoxyParamCaption}
)\hspace{0.3cm}{\ttfamily  \mbox{[}inline\mbox{]}}}}\label{classBasicUnitAction_a9da1de11751fffcb48a5ec9181402d61}


\-Definition at line 9 of file \-Basic\-Unit\-Action.\-h.


\begin{DoxyCode}
: SingleMicroActionBaseClass(unit), mTargetPriorities(targetPriorities) {}
\end{DoxyCode}


\subsection{\-Member \-Function \-Documentation}
\hypertarget{classBasicUnitAction_a5cfdd9e3257503499f1968629f0f7db6}{\index{\-Basic\-Unit\-Action@{\-Basic\-Unit\-Action}!update@{update}}
\index{update@{update}!BasicUnitAction@{\-Basic\-Unit\-Action}}
\subsubsection[{update}]{\setlength{\rightskip}{0pt plus 5cm}bool {\bf \-Basic\-Unit\-Action\-::update} (
\begin{DoxyParamCaption}
\item[{const {\bf \-Goal} \&}]{squad\-Goal, }
\item[{const {\bf \-Unit\-Group} \&}]{squad\-Unit\-Group}
\end{DoxyParamCaption}
)\hspace{0.3cm}{\ttfamily  \mbox{[}virtual\mbox{]}}}}\label{classBasicUnitAction_a5cfdd9e3257503499f1968629f0f7db6}


\-Implements \hyperlink{classSingleMicroActionBaseClass_aecc4881945144ca283aaf4dfd9397a4f}{\-Single\-Micro\-Action\-Base\-Class}.



\-Definition at line 22 of file \-Basic\-Unit\-Action.\-cpp.



\-References \-Action\-Type\-Def\-::\-Attack, \-B\-W\-A\-P\-I\-::\-Broodwar, \-Action\-Type\-Def\-::\-Defend, \-B\-W\-A\-P\-I\-::\-Tech\-Types\-::\-E\-M\-P\-\_\-\-Shockwave, \-B\-W\-A\-P\-I\-::\-Tech\-Type\-::energy\-Used(), \-Goal\-::get\-Action\-Type(), \-B\-W\-A\-P\-I\-::\-Game\-::get\-Remaining\-Latency\-Frames(), \-B\-W\-A\-P\-I\-::\-Tech\-Type\-::get\-Weapon(), \-Action\-Type\-Def\-::\-Hold, \-Singleton$<$ T $>$\-::\-Instance(), \-Unit\-Helper\-::is\-Army\-Unit(), \-Unit\-Helper\-::is\-Static\-Defense(), \-B\-W\-A\-P\-I\-::\-Unit\-Type\-::is\-Worker(), \-Access\-Type\-Def\-::\-Lost, \-B\-W\-A\-P\-I\-::\-Weapon\-Type\-::max\-Range(), m\-Target\-Priorities, \-Single\-Micro\-Action\-Base\-Class\-::m\-Unit, \-B\-W\-A\-P\-I\-::\-Unit\-Types\-::\-Protoss\-\_\-\-Arbiter, \-B\-W\-A\-P\-I\-::\-Unit\-Types\-::\-Protoss\-\_\-\-Scarab, \-B\-W\-A\-P\-I\-::\-Unit\-Types\-::\-Protoss\-\_\-\-Zealot, \-Action\-Type\-Def\-::\-Retreat, \-B\-W\-A\-P\-I\-::\-Unit\-Type\-::seek\-Range(), stay\-At\-Range(), \-B\-W\-A\-P\-I\-::\-Unit\-Type\-::supply\-Provided(), \-B\-W\-A\-P\-I\-::\-Unit\-Types\-::\-Terran\-\_\-\-Bunker, \-B\-W\-A\-P\-I\-::\-Unit\-Types\-::\-Terran\-\_\-\-Science\-\_\-\-Vessel, \-B\-W\-A\-P\-I\-::\-Unit\-Types\-::\-Terran\-\_\-\-Vulture\-\_\-\-Spider\-\_\-\-Mine, \-B\-W\-A\-P\-I\-::\-Unit\-Type\-::top\-Speed(), \-B\-W\-A\-P\-I\-::\-Unit\-Types\-::\-Zerg\-\_\-\-Egg, and \-B\-W\-A\-P\-I\-::\-Unit\-Types\-::\-Zerg\-\_\-\-Larva.


\begin{DoxyCode}
{
        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;
}\end{DoxyCode}


\-Here is the call graph for this function\-:\nopagebreak
\begin{figure}[H]
\begin{center}
\leavevmode
\includegraphics[width=350pt]{classBasicUnitAction_a5cfdd9e3257503499f1968629f0f7db6_cgraph}
\end{center}
\end{figure}




\subsection{\-Member \-Data \-Documentation}
\hypertarget{classBasicUnitAction_a3ea9e7e4be7bde0a04d98cff9d40de18}{\index{\-Basic\-Unit\-Action@{\-Basic\-Unit\-Action}!m\-Target\-Priorities@{m\-Target\-Priorities}}
\index{m\-Target\-Priorities@{m\-Target\-Priorities}!BasicUnitAction@{\-Basic\-Unit\-Action}}
\subsubsection[{m\-Target\-Priorities}]{\setlength{\rightskip}{0pt plus 5cm}std\-::list$<$std\-::set$<${\bf \-B\-W\-A\-P\-I\-::\-Unit\-Type}$>$ $>$ {\bf \-Basic\-Unit\-Action\-::m\-Target\-Priorities}\hspace{0.3cm}{\ttfamily  \mbox{[}private\mbox{]}}}}\label{classBasicUnitAction_a3ea9e7e4be7bde0a04d98cff9d40de18}


\-Definition at line 14 of file \-Basic\-Unit\-Action.\-h.



\-Referenced by update().



\-The documentation for this class was generated from the following files\-:\begin{DoxyCompactItemize}
\item 
\-Skynet/\-Skynet/\hyperlink{BasicUnitAction_8h}{\-Basic\-Unit\-Action.\-h}\item 
\-Skynet/\-Skynet/\hyperlink{BasicUnitAction_8cpp}{\-Basic\-Unit\-Action.\-cpp}\end{DoxyCompactItemize}
