BWAPI
UAlbertaBot_src/Projects/UAlbertaBot/Source/micromanagement/TargetExpert.h
Go to the documentation of this file.
00001 #ifndef TARGET_EXPERT_H
00002 #define TARGET_EXPERT_H
00003 
00004 #include "Properties.h"
00005 
00006 class TargetExpert
00007 {
00008         props::Game     gameProps;
00009 public:
00010         TargetExpert() : gameProps(BWAPI::Broodwar)
00011         {
00012 
00013         }
00014 
00015         void Update()
00016         {
00017                 gameProps = props::Game(BWAPI::Broodwar);
00018         }
00019 
00020         BWAPI::Unit * SelectTarget(const BWAPI::Unit * attacker, const std::vector<BWAPI::Unit *> & targets) const
00021         {
00022                 const props::Unit & attackerProps(gameProps.GetUnitProps(attacker));
00023 
00024                 BWAPI::Unit *   bestTarget(0);
00025                 int                             bestPriorityClass(0);
00026                 float                   bestPriority(0);
00027 
00028                 foreach(BWAPI::Unit * target, targets)
00029                 {
00030                         // Skip any potential targets we cannot actually attack
00031                         const props::Weapon * ourWeapon(attackerProps.GetCorrespondingWeapon(target));
00032                         if(!ourWeapon)
00033                         {
00034                                 continue;
00035                         }
00036 
00037                         // Structures for recording desirability of targeting this unit
00038                         int priorityClass(0);
00039                         float priority(0);
00040 
00041                         // Determine how many frames it will take us to kill this enemy
00042                         const props::Unit & targetProps(gameProps.GetUnitProps(target));
00043                         float killTime(ourWeapon->GetTimeToKill(targetProps, target->getHitPoints(), target->getShields()));
00044 
00045                         // Determine distance to the enemy, and how far we'd have to move to target them
00046                         const float distance(static_cast<float>(attacker->getDistance(const_cast<BWAPI::Unit*>(target))));
00047                         const float ourMoveDistance(std::max(distance - ourWeapon->maxRange, 0.0f));
00048                         if(ourMoveDistance > 0)
00049                         {
00050                                 // If we need to move, adjust kill time accordingly
00051                                 killTime += ourMoveDistance / attackerProps.moveSpeed;
00052                         }
00053                         else
00054                         {
00055                                 // Prefer targets that we can target without moving
00056                                 priorityClass += 5;
00057                         }
00058 
00059                         // Enemy spellcasters are of highest priority
00060                         const BWAPI::UnitType type(target->getType());
00061                         if(type.isSpellcaster())
00062                         {
00063                                 priorityClass += 3;
00064 
00065                                 // Greatly prefer targets that threaten us
00066                                 // Assume spellcaster is dangerous anywhere inside its sight range
00067                                 if(distance < targetProps.sightRange)
00068                                 {
00069                                         priorityClass += 10;
00070                                 }
00071                         }
00072                         // Enemies which can target us are of next highest priority
00073                         else if(const props::Weapon * enemyWeapon = targetProps.GetCorrespondingWeapon(attacker))
00074                         {
00075                                 priorityClass += 2;
00076 
00077                                 // Greatly prefer targets that threaten us
00078                                 if(distance < enemyWeapon->maxRange)
00079                                 {
00080                                         priorityClass += 10;
00081                                 }
00082 
00083                                 // Prefer to target enemies which do high damage but can be killed quickly
00084                                 const float damageRate(enemyWeapon->GetDamageRateTo(attackerProps.sizeType, attackerProps.hitPointsArmor).damagePerFrame);
00085                                 priority = damageRate / killTime;
00086                         }
00087                         // Enemies which can target anything at all are of next highest priority
00088                         else if(const props::Weapon * targetWeapon = targetProps.groundWeapon ? targetProps.groundWeapon : targetProps.airWeapon)
00089                         {
00090                                 priorityClass += 1;
00091 
00092                                 // Prefer to target enemies which do high damage but can be killed quickly
00093                                 const float damageRate(static_cast<float>(targetWeapon->damage) / targetWeapon->cooldown);
00094                                 priority = damageRate / killTime;
00095                         }
00096                         // Buildings have lowest priority
00097                         else
00098                         {
00099                                 // Weights used to determine worth of building
00100                                 const float mineralWeight(1.0f);
00101                                 const float vespeneWeight(2.0f);
00102                                 const float producerBonus(1000.0f);
00103 
00104                                 // Prefer to target buildings worth the most which can be killed quickly
00105                                 float worth(type.mineralPrice() * mineralWeight + type.gasPrice() * vespeneWeight);
00106                                 if(type.canProduce()) worth += producerBonus;
00107                                 priority = worth / killTime;
00108                         }
00109 
00110                         // Unit can be better by being of a higher class, or of a better priority within the original class
00111                         if(!bestTarget || priorityClass > bestPriorityClass || (priorityClass == bestPriorityClass && priority > bestPriority))
00112                         {
00113                                 bestTarget                      = target;
00114                                 bestPriorityClass       = priorityClass;
00115                                 bestPriority            = priority;
00116                         }
00117                 }
00118 
00119                 return bestTarget;
00120         }
00121 };
00122 
00123 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines