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
|
// -------------------------------------------------------------------------
// AAI
//
// A skirmish AI for the Spring engine.
// Copyright Alexander Seizinger
//
// Released under GPL license: see LICENSE.html for more information.
// -------------------------------------------------------------------------
#include "AAIThreatMap.h"
#include "AAIMap.h"
AAIThreatMap::AAIThreatMap(int xSectors, int ySectors) :
m_estimatedEnemyCombatPowerForSector( xSectors, std::vector<MobileTargetTypeValues>(ySectors) )
{
}
AAIThreatMap::~AAIThreatMap(void)
{
}
void AAIThreatMap::UpdateLocalEnemyCombatPower(const AAITargetType& targetType, const SectorMap& sectors)
{
for(size_t x = 0; x < sectors.size(); ++x)
{
for(size_t y = 0; y < sectors[x].size(); ++y)
{
m_estimatedEnemyCombatPowerForSector[x][y].SetValueForTargetType(targetType, sectors[x][y].GetEnemyCombatPower(targetType) );
}
}
}
const AAISector* AAIThreatMap::DetermineSectorToAttack(const AAITargetType& attackerTargetType, const MapPos& mapPosition, const SectorMap& sectors) const
{
const float3 position( static_cast<float>(mapPosition.x * SQUARE_SIZE), 0.0f, static_cast<float>(mapPosition.y * SQUARE_SIZE));
const SectorIndex startSectorIndex = AAIMap::GetSectorIndex(position);
float highestRating(0.0f);
const AAISector* selectedSector = nullptr;
for(size_t x = 0; x < sectors.size(); ++x)
{
for(size_t y = 0; y < sectors[x].size(); ++y)
{
const int enemyBuildings = sectors[x][y].GetNumberOfEnemyBuildings();
if(enemyBuildings > 0)
{
const float3 sectorCenter = sectors[x][y].GetCenter();
const float dx = sectorCenter.x - position.x;
const float dz = sectorCenter.z - position.z;
const float distSquared = dx * dx + dz * dz;
// distance rating between 0 (close to given position) and 0.9 (~ 0.7 of map size away)
const float distRating = std::min( distSquared / (0.5f * AAIMap::s_maxSquaredMapDist), 0.9f);
// value between 0.1 (15 or more recently lost units) and 1 (no lost units)
const float lostUnitsRating = std::max(1.0f - sectors[x][y].GetTotalLostUnits() / 15.0f, 0.1f);
const float enemyCombatPower = CalculateThreat<EThreatType::COMBAT_POWER>(attackerTargetType, startSectorIndex, SectorIndex(x, y), sectors);
const float rating = static_cast<float>(enemyBuildings) / (0.1f + enemyCombatPower) * (1.0 - distRating) * lostUnitsRating;
if(rating > highestRating)
{
selectedSector = §ors[x][y];
highestRating = rating;
}
}
}
}
return selectedSector;
}
float AAIThreatMap::CalculateEnemyDefencePower(const AAITargetType& targetType, const float3& startPosition, const float3& targetPosition, const SectorMap& sectors) const
{
const SectorIndex startSectorIndex = AAIMap::GetSectorIndex(startPosition);
const SectorIndex targetSectorIndex = AAIMap::GetSectorIndex(targetPosition);
return CalculateThreat<EThreatType::ALL>(targetType, startSectorIndex, targetSectorIndex, sectors);
}
template<EThreatType threatTypeToConsider>
float AAIThreatMap::CalculateThreat(const AAITargetType& targetType, const SectorIndex& startSectorIndex, const SectorIndex& targetSectorIndex, const SectorMap& sectors) const
{
float totalThreat(0.0f);
const float dx = static_cast<float>( targetSectorIndex.x - startSectorIndex.x );
const float dy = static_cast<float>( targetSectorIndex.y - startSectorIndex.y );
const float invDist = fastmath::isqrt2_nosse(dx * dx + dy * dy);
SectorIndex lastSector(startSectorIndex);
bool targetSectorReached(false);
float step(1);
/*FILE* file = fopen("AAIAttackDebug.txt", "w+");
fprintf(file, "Start sector: (%i, %i)\n", startSector.x, startSector.y);
fprintf(file, "Target sector: (%i, %i)\n", targetSector.x, targetSector.y);
fprintf(file, "Distance: %f\n", 1.0f / invDist);*/
while(targetSectorReached == false)
{
const int x = startSectorIndex.x + static_cast<int>( step * dx * invDist );
const int y = startSectorIndex.y + static_cast<int>( step * dy * invDist );
if( (x !=lastSector.x) || (y != lastSector.y) ) // avoid counting the same sector twice if step size is too low because of rounding errors
{
if( static_cast<int>(threatTypeToConsider) & static_cast<int>(EThreatType::COMBAT_POWER) )
totalThreat += m_estimatedEnemyCombatPowerForSector[x][y].GetValueOfTargetType(targetType);
if( static_cast<int>(threatTypeToConsider) & static_cast<int>(EThreatType::LOST_UNITS) )
totalThreat += sectors[x][y].GetLostUnits(targetType);
}
//fprintf(file, "Step: %f, sector (%i, %i), combat power: %f\n", step, x, y, m_estimatedEnemyCombatPowerForSector[x][y].GetValueOfTargetType(targetType));
if((SectorIndex(x, y) == targetSectorIndex) || (step > dx+dy))
targetSectorReached = true;
++step;
}
//fprintf(file, "Final combat power: %f\n", combatPower);
//fclose(file);
return totalThreat;
}
|