|
BWAPI
|
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
1.7.6.1