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 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
|
// -------------------------------------------------------------------------
// AAI
//
// A skirmish AI for the Spring engine.
// Copyright Alexander Seizinger
//
// Released under GPL license: see LICENSE.html for more information.
// -------------------------------------------------------------------------
#ifndef AAI_SECTOR_H
#define AAI_SECTOR_H
#include "System/float3.h"
#include "aidef.h"
#include "AAITypes.h"
#include "AAIUnitTypes.h"
#include "AAIBuildTree.h"
#include <list>
#include <vector>
class AAI;
class AAIUnitTable;
class AAIMap;
class AAIThreatMap;
class BuildMapTileType;
class AAIMetalSpot;
namespace springLegacyAI {
struct UnitDef;
}
using namespace springLegacyAI;
enum Direction {WEST, EAST, SOUTH, NORTH, CENTER, NO_DIRECTION};
struct DefenceCoverage
{
Direction direction;
float defence;
};
struct SectorIndex
{
SectorIndex(int x, int y) : x(x), y(y) {};
bool operator==(const SectorIndex& rhs) const { return (x == rhs.x) && (y == rhs.y); }
int x = 0;
int y = 0;
};
class AAISector
{
public:
friend AAIMap;
AAISector();
~AAISector(void);
//! @brief Adds a metal spot to the list of metal spots in the sector
void AddMetalSpot(AAIMetalSpot *spot);
//! @brief Associates an extractor with a metal spot in that sector
void AddExtractor(UnitId unitId, UnitDefId unitDefId, float3 position);
//! @brief Looks for metal spot that corresponds to given position and marks it as free
void FreeMetalSpot(float3 position, UnitDefId extractorDefId);
void Init(AAI *ai, int x, int y);
//! @brief Loads sector data from given file
void LoadDataFromFile(FILE* file);
//! @brief Saves sector data to given file
void SaveDataToFile(FILE* file);
//! @brief Updates learning data for sector
void UpdateLearnedData();
//! @brief Adds/removes the sector from base sectors; returns true if succesful
bool AddToBase(bool addToBase);
//! @brief Returns the corresponding index of the sector
const SectorIndex GetSectorIndex() const { return m_sectorIndex; }
//! @brief Returns the distance (in sectors) to the base
int GetDistanceToBase() const { return m_distanceToBase; }
//! @brief Returns the number of metal spots in this sector
int GetNumberOfMetalSpots() const { return metalSpots.size(); }
//! @brief Returns the number of buildings of the given category in this sector
int GetNumberOfBuildings(const AAIUnitCategory& category) const { return m_ownBuildingsOfCategory[category.GetArrayIndex()]; }
//! @brief Returns the number of buildings belonging to allied players
int GetNumberOfAlliedBuildings() const { return m_alliedBuildings; }
//! @brief Returns the number of buildings belonging to hostile players
int GetNumberOfEnemyBuildings() const { return m_enemyBuildings; }
//! @brief Resets the own combat power / number of allied buildings
void ResetLocalCombatPower();
//! @brief Resets the number / combat power of spotted enemy units
void ResetScoutedEnemiesData();
//! @brief Updates enemy combat power and counters
void AddScoutedEnemyUnit(UnitDefId enemyDefId, int framesSinceLastUpdate);
//! @brief Return the total number of enemy combat units
float GetTotalEnemyCombatUnits() const { return m_enemyCombatUnits.CalcuateSum(); };
//! @brief Returns whether sector is supsected to be occupied by enemy units (according to scouting or sensor)
bool IsOccupiedByEnemies() const{ return (GetTotalEnemyCombatUnits() > 0.1f) || (m_enemyBuildings > 0) || (m_enemyUnitsDetectedBySensor > 0); }
//! @brief Returns number of enemy units of given target type spotted in this sector (float as number decreases over time if sector is not scouted)
float GetNumberOfEnemyCombatUnits(const AAITargetType& targetType) const { return m_enemyCombatUnits.GetValue(targetType); };
const TargetTypeValues& GetNumberOfEnemyCombatUnits() const { return m_enemyCombatUnits; };
//! @brief Decreases number of lost units by a factor < 1 such that AAI "forgets" about lost unit over time
void DecreaseLostUnits();
//! @brief Returns whether sector can be considered for expansion of base
bool IsSectorSuitableForBaseExpansion() const;
//! @brief Returns true if sector shall be considered for selection of construction of further metal extractor
bool ShallBeConsideredForExtractorConstruction() const;
//! @brief Returns true if free metal spot available in sector
bool AreFreeMetalSpotsAvailable() const;
//! @brief Returns a buildsite that has been chosen randomly (the given number of trials) - ZeroVector if none found
BuildSite DetermineRandomBuildsite(UnitDefId buildingDefId, int trials) const;
//! @brief Searches for a buildsite that is preferably elevated with respect to its surroundings and not close to the map edges
BuildSite DetermineElevatedBuildsite(UnitDefId buildingDefId, float range) const;
//! @brief Returns position of known enemy buildings (or center if no buidlings in sector)
float3 DetermineAttackPosition() const;
//! @brief Adds building of category to sector
void AddBuilding(const AAIUnitCategory& category) { m_ownBuildingsOfCategory[category.GetArrayIndex()] += 1; };
//! @brief Removes building from sector
void RemoveBuilding(const AAIUnitCategory& category) { m_ownBuildingsOfCategory[category.GetArrayIndex()] -= 1; };
//! @brief Returns true if local combat power does not suffice to defend vs attack by given target type
bool IsSupportNeededToDefenceVs(const AAITargetType& targetType) const;
//! @brief Returns how often units in sector have been attacked by given mobile target type
float GetLocalAttacksBy(const AAITargetType& targetType, float previousGames, float currentGame) const;
//! @brief Get total (mobile + static) defence power of enemy vs given target type (according to spotted units)
float GetEnemyCombatPowerVsUnits(const MobileTargetTypeValues& unitsOfTargetType) const;
//! @brief Get total (mobile + static) defence power vs given target type
float GetEnemyCombatPower(const AAITargetType& targetType) const { return m_enemyStaticCombatPower.GetValueOfTargetType(targetType) + m_enemyMobileCombatPower.GetValueOfTargetType(targetType); }
//! @brief Returns combat power of own/allied static defences against given target type
float GetFriendlyStaticDefencePower(const AAITargetType& targetType) const { return m_friendlyStaticCombatPower.GetValueOfTargetType(targetType); }
//! @brief Returns cmbat power of own/allied static defences against given target type
float GetFriendlyCombatPower(const AAITargetType& targetType) const { return m_friendlyStaticCombatPower.GetValueOfTargetType(targetType) + m_friendlyMobileCombatPower.GetValueOfTargetType(targetType); }
//! @brief Adds given values to friendly combat power in this sector
void AddFriendlyCombatPower(const TargetTypeValues& combatPower) { m_friendlyMobileCombatPower.AddCombatPower(combatPower); }
//! @brief Updates threat map storing where own buildings/units got killed
void UpdateThreatValues(UnitDefId destroyedDefId, UnitDefId attackerDefId);
//! @brief Returns lost units in that sector
float GetLostUnits(const AAITargetType& targetType) const { return m_lostUnits.GetValueOfTargetType(targetType); }
//! @brief Returns the total number (i.e. of all target types) of lost units in this sector
float GetTotalLostUnits() const { return m_lostUnits.CalculateSum(); }
//! @brief Returns number of attacks by the main combat categories (ground, hover, air)
float GetTotalAttacksInThisGame() const
{
return m_attacksByTargetTypeInCurrentGame.CalculateSum();
}
//! @brief Returns number of attacks by the main combat categories (ground, hover, air)
float GetTotalAttacksInPreviousGames() const
{
return m_attacksByTargetTypeInPreviousGames.CalculateSum();
}
//! @brief Returns center position of the sector
float3 GetCenter() const;
//! @brief Returns the continent ID of the center of the sector
int GetContinentID() const { return m_continentId; }
//! @brief Returns the ratio of flat terrain tiles in this sector
float GetFlatTilesRatio() const { return m_flatTilesRatio; }
//! @brief Returns the ratio of water tiles in this sector
float GetWaterTilesRatio() const { return m_waterTilesRatio; }
//! @brief Increments corresponding counter (used to avoid trying to build static defences in a sector with no suitable buildsites)
void FailedToConstructStaticDefence() { ++m_failedAttemptsToConstructStaticDefence; }
//! @brief Returns the importance of a static defence against the target type with highest priority
float GetImportanceForStaticDefenceVs(AAITargetType& targetType, const GamePhase& gamePhase, float previousGames, float currentGame);
//! @brief Returns the rating of this sector as destination to attack (0.0f if no suitable target)
float GetAttackRating(const AAISector* currentSector, bool landSectorSelectable, bool waterSectorSelectable, const MobileTargetTypeValues& targetTypeOfUnits) const;
//! @brief Returns the rating of this sector as destination to attack (0.0f if no suitable target)
float GetAttackRating(const std::vector<float>& globalCombatPower, const std::vector< std::vector<float> >& continentCombatPower, const MobileTargetTypeValues& assaultGroupsOfType, float maxLostUnits) const;
//! @brief Returns rating as next destination for scout of given movement type
float GetRatingAsNextScoutDestination(const AAIMovementType& scoutMoveType, const AAITargetType& scoutTargetType, const float3& currentPositionOfScout);
//! @brief Returns the rating to be selected for a rally point for units of given movement type
float GetRatingForRallyPoint(const AAIMovementType& moveType, int continentId) const;
//! @brief Returns the rating as starting sector (if a new one has to be selected as the current is already occupied by other AAI player)
float GetRatingAsStartSector() const;
//! @brief Returns rating as sector to build a power plant
float GetRatingForPowerPlant(float weightPreviousGames, float weightCurrentGame) const;
//! @brief Shall be called when scout is sent to this sector (resets counter how often this sector has been skipped)
void SelectedAsScoutDestination() { m_skippedAsScoutDestination = 0; }
//! @brief Searches for a free position in sector on specified continent (use -1 if continent does not matter).
//! Returns position or ZeroVector if none found.
float3 DetermineUnitMovePos(AAIMovementType moveType, int continentId) const;
//! @brief Returns true if pos lies within this sector
bool PosInSector(const float3& pos) const;
//! @brief Determines ratio of water cells of this sector
float DetermineWaterRatio() const;
//! @brief Determines ratio of flat cells of this sector
float DetermineFlatRatio() const;
//! @brief Returns true if sector is connected with a big ocean (and not only a small pond)
bool ConnectedToOcean() const;
//! @brief Returns minimum distance to one of the map edges (in sector sizes)
int GetEdgeDistance() const { return m_minSectorDistanceToMapEdge; }
//! @brief Determines rectangle for possible buildsite
void DetermineBuildsiteRectangle(int *xStart, int *xEnd, int *yStart, int *yEnd) const;
// list of all metal spots in the sector
std::list<AAIMetalSpot*> metalSpots;
// importance of the sector
float importance_this_game;
float importance_learned;
private:
//! @brief Helper function to determine position to move units to
bool IsValidMovePos(const float3& pos, BuildMapTileType forbiddenMapTileTypes, int continentId) const;
//! @brief Returns true if further static defences may be built in this sector
bool AreFurtherStaticDefencesAllowed() const;
AAI *ai;
//! The corresponding index of the sector
SectorIndex m_sectorIndex;
//! Id of the continent of the center of the sector
int m_continentId;
//! Ratio of flat terrain tiles
float m_flatTilesRatio;
//! Ratio of water tiles
float m_waterTilesRatio;
//! Distance (in sectors) to own base, i.e 0 = belongs to base, 1 = neighbour to base, ...
int m_distanceToBase;
//! Bitmask storing movement types that may maneuver in this sector
uint32_t m_suitableMovementTypes;
//! Minimum distance to one of the map edges (in sector sizes)
int m_minSectorDistanceToMapEdge;
//! How many units have recently been lost in that sector (float as the number decays over time)
MobileTargetTypeValues m_lostUnits;
//! Number of own buildings of each category in the sector
std::vector<int> m_ownBuildingsOfCategory;
//! Number of spotted enemy combat units (float values as number decays over time)
TargetTypeValues m_enemyCombatUnits; // 0 surface, 1 air, 3 ship, 4 submarine, 5 static defences
//! Number of buildings enemy players have constructed in this sector
int m_enemyBuildings;
//! Number of buildings allied players have constructed in this sector
int m_alliedBuildings;
//! Number of enemy units detected by sensor (radar/sonar)
int m_enemyUnitsDetectedBySensor;
//! The combat power against mobile targets of all hostile static defences in this sector
MobileTargetTypeValues m_enemyStaticCombatPower;
//! The combat power against mobile targets of all hostile combat units in this sector
MobileTargetTypeValues m_enemyMobileCombatPower;
//! The combat power against mobile targets of all friendly static defences in this sector
MobileTargetTypeValues m_friendlyStaticCombatPower;
//! The combat power against mobile targets of all friendly combat units in this sector
MobileTargetTypeValues m_friendlyMobileCombatPower;
//! Stores how often buildings in this sector have been attacked(=destroyed) by a certain target type in previous games
MobileTargetTypeValues m_attacksByTargetTypeInPreviousGames;
//! Stores how often buildings in this sector have been attacked(=destroyed) by a certain target type in the current game
MobileTargetTypeValues m_attacksByTargetTypeInCurrentGame;
//! indicates how many times scouts have been sent to another sector
int m_skippedAsScoutDestination;
//! How many times AAI tried to build defences in this sector but failed (because of unavailable buildsite)
int m_failedAttemptsToConstructStaticDefence;
};
#endif
|