1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
// -------------------------------------------------------------------------
// AAI
//
// A skirmish AI for the Spring engine.
// Copyright Alexander Seizinger
//
// Released under GPL license: see LICENSE.html for more information.
// -------------------------------------------------------------------------
#ifndef AAI_EXECUTE_H
#define AAI_EXECUTE_H
#include "aidef.h"
#include "AAITypes.h"
#include "AAIUnitTypes.h"
#include "AAIBuildTable.h"
namespace springLegacyAI {
struct UnitDef;
}
using namespace springLegacyAI;
enum class BuildOrderStatus : int {BUILDING_INVALID, NO_BUILDSITE_FOUND, NO_BUILDER_AVAILABLE, SUCCESSFUL};
class AAI;
class AAIBuildTable;
class AAIBrain;
class AAIMap;
class AAIUnitTable;
class AAISector;
struct AvailableMetalSpot
{
AvailableMetalSpot(AAIMetalSpot* metalSpot, AAIConstructor* builder, UnitDefId extractor) :
metalSpot(metalSpot),
builder(builder),
extractor(extractor)
{}
AAIMetalSpot* metalSpot;
AAIConstructor* builder;
UnitDefId extractor;
};
class AAIExecute
{
public:
AAIExecute(AAI* ai);
~AAIExecute(void);
//! @brief Determines starting sector, adds another sector to base and initializes buildqueues
void InitAI(UnitId commanderUnitId, UnitDefId commanderDefId);
//! @brief Orders the unit to move to the given position
void SendUnitToPosition(UnitId unitId, const float3& position) const;
//! @brief Add the given unit to an existing group (or create new one if necessary)
void AddUnitToGroup(const UnitId& unitId, const UnitDefId& unitDefId);
//! @brief Selects combat unit according to given criteria and tries to order its construction
void BuildCombatUnitOfCategory(const AAIMovementType& moveType, const TargetTypeValues& combatPowerCriteria, const UnitSelectionCriteria& unitSelectionCriteria, const std::vector<float>& factoryUtilization, bool urgent);
void BuildScouts();
//! @brief Looks for the next suitable destination for the given scout and orders it to move there
void SendScoutToNewDest(UnitId scoutId) const;
//! @brief Returns the current unit production rate (i.e. how many unit AAI tries to order per unit production update step)
int GetUnitProductionRate() const { return m_unitProductionRate; }
//! @brief Adjusts the unit production rate based on the current average length of the buildqueues of active factories
void AdjustUnitProductionRate();
//! @brief Returns the number of Build Tasks that could not be linked to a construction unit (for debugging only - should be zero)
unsigned int GetLinkingBuildTaskToBuilderFailedCounter() const { return m_linkingBuildTaskToBuilderFailed; };
//! @brief Searches for a position to retreat unit of certain type
float3 DetermineSafePos(UnitDefId unitDefId, float3 unit_pos) const;
// checks if ressources are sufficient and orders construction of new buildings
void CheckRessources();
// checks if buildings of that type could be replaced with more efficient one (e.g. mex -> moho)
void CheckExtractorUpgrade();
void CheckRadarUpgrade();
void CheckJammerUpgrade();
// checks which building type is most important to be constructed and tries to start construction
void CheckConstruction();
// the following functions determine how urgent it is to build a further building of the specified type
void CheckFactories();
void CheckRecon();
void CheckStationaryArty();
//
void CheckDefences();
//! @brief Check if construction nano turrets shall be ordered to support busy static constructors
void CheckConstructionOfNanoTurret();
//! @brief Cleans up buildmap/updates internal counters/frees metalspots if contruction has failed
void ConstructionFailed(const float3& buildsite, UnitDefId unitDefId);
//! @brief Orders construction of static defence to protect metal extractor
void BuildStaticDefenceForExtractor(UnitId extractorId, UnitDefId extractorDefId) const;
//! @brief Returns a position for the unit to withdraw from close quarters combat (but try to keep enemies in weapons range)
//! Returns ZeroVector if no suitable pos found (or no enemies close enough)
float3 GetFallBackPos(const float3& pos, float maxFallbackDist) const;
//! @brief Checks if a combat unit attacked by given enemy shall move back a little to maintain distance to attacker
void CheckKeepDistanceToEnemy(UnitId unitId, UnitDefId unitDefId, UnitDefId enemyDefId);
//! @brief Tries to call support against specific attacker (e.g. air)
void DefendUnitVS(const UnitId& unitId, const AAITargetType& attackerTargetType, const float3& attackerPosition, float urgency) const;
//! @brief Tries to add the given number of units to the most suitable buildqueue (returns whether units have been successfully added)
bool TryAddingUnitsToBuildqueue(UnitDefId unitDefId, int number, BuildQueuePosition queuePosition, bool ignoreMaxQueueLength = false);
//! @brief Adds the given number of units to the given buildqueue
bool AddUnitsToBuildqueue(UnitDefId unitDefId, int number, Buildqueue buildqueue, BuildQueuePosition position, bool ignoreMaxQueueLength);
//! @brief Determines buildsite for a unit (not building) that shall be constructed by the given construction unit
BuildSite DetermineBuildsiteForUnit(UnitId constructor, UnitDefId unitDefId) const;
//! @brief Sets urgency to construct building of given category to given value if larger than current value
void SetConstructionUrgencyIfHigher(const AAIUnitCategory& category, float urgency)
{
if(m_constructionUrgency[category.GetArrayIndex()] < urgency)
m_constructionUrgency[category.GetArrayIndex()] = urgency;
}
// debug
void GiveOrder(Command *c, int unit, const char *owner) const;
private:
// custom relations
float static sector_threat(const AAISector *sector);
bool static least_dangerous(const AAISector *left, const AAISector *right);
bool static suitable_for_power_plant(AAISector *left, AAISector *right);
bool static suitable_for_ground_factory(AAISector *left, AAISector *right);
bool static suitable_for_sea_factory(AAISector *left, AAISector *right);
bool static defend_vs_ground(const AAISector *left, const AAISector *right);
bool static defend_vs_air(const AAISector *left, const AAISector *right);
bool static defend_vs_hover(const AAISector *left, const AAISector *right);
bool static defend_vs_sea(const AAISector *left, const AAISector *rightt);
bool static defend_vs_submarine(const AAISector *left, const AAISector *right);
float static learned;
float static current;
//! @brief Calls construction fucntion for given category and resets urgency to 0.0f if construction order has been given
void TryConstruction(const AAIUnitCategory& category);
//! @brief Tries to build a defence building vs target type in the specified sector
//! returns BUILDORDER_SUCCESSFUL if successful
BuildOrderStatus BuildStationaryDefenceVS(const AAITargetType& targetType, const AAISector *dest);
//! @brief Tries to build a defence fitting to given criteria
BuildOrderStatus BuildStaticDefence(const AAISector* sector, const StaticDefenceSelectionCriteria& selectionCriteria, bool water) const;
//! @brief Returns true if a construction unit was ordered to assist construction of a building of givn category
bool AssistConstructionOfCategory(const AAIUnitCategory& category);
// chooses a starting sector close to specified sector
void ChooseDifferentStartingSector(int x, int y);
//! @brief Returns closest (taking into account movement speed) group with units of specified unit type that may reach the location
AAIGroup* GetClosestGroupForDefence(const AAITargetType& attackerTargetType, const float3& pos, int importance) const;
//! @brief Determines buildsite for a building that shall be constructed by the given construction unit
BuildSite DetermineBuildsite(UnitId builder, UnitDefId buildingDefId) const;
//! @brief Determines buildiste for the given building in the given sector, returns ZeroVector if none found
BuildSite DetermineBuildsiteInSector(UnitDefId building, const AAISector* sector) const;
void stopUnit(int unit);
void ConstructBuildingAt(int building, int builder, float3 position);
bool IsBusy(int unit);
//! @brief Determine sectors that are suitable to construct eco (power plants, storage, metal makers); highest ranked sector is first in the list
void DetermineSectorsToConstructEco(std::list<AAISector*>& sectors) const;
//! @brief Tries to order construction of given building in one of the given sectors
BuildOrderStatus ConstructBuildingInSectors(UnitDefId building, std::list<AAISector*>& availableSectors);
//! @brief Helper function for construction of buildings
BuildOrderStatus TryConstructionOfBuilding(UnitDefId building, AAISector* sector);
//! @brief Tries to find a suitable buildsite and builder to start the construction of the given building;
BuildOrderStatus TryConstructionOf(UnitDefId building, const AAISector* sector);
BuildOrderStatus TryConstructionOf(UnitDefId landBuilding, UnitDefId seaBuilding, const AAISector* sector);
bool BuildStaticConstructor();
bool BuildDefences();
bool BuildRadar();
bool BuildJammer();
bool BuildExtractor();
bool BuildMetalMaker();
bool BuildStorage();
bool BuildPowerPlant();
bool BuildArty();
bool BuildAirBase();
//! Urgency of construction of building of the different categories
std::vector<float> m_constructionUrgency;
//! Pointer to correspondind construction function for each category (or nullptr if none)
std::vector< bool (AAIExecute::*) ()> m_constructionFunctions;
//! Sector where next static defence shall be build (nullptr if none)
AAISector* m_sectorToBuildNextDefence;
//! Target type against which which next defence shall be effective
AAITargetType m_nextDefenceVsTargetType;
//! The number of units the AI tries to order in every unit production update step
int m_unitProductionRate;
//! The total number of issued orders (primarily for debug purposes)
mutable int m_numberOfIssuedOrders;
//! Number of times a building was created but no suitable builder could be identfied (should be zero - just for debug purposes)
unsigned int m_linkingBuildTaskToBuilderFailed;
AAI *ai;
};
#endif
|