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
|
// -------------------------------------------------------------------------
// AAI
//
// A skirmish AI for the Spring engine.
// Copyright Alexander Seizinger
//
// Released under GPL license: see LICENSE.html for more information.
// -------------------------------------------------------------------------
#ifndef AAI_BUILDTREE_H
#define AAI_BUILDTREE_H
#include "AAIUnitTypes.h"
#include "AAITypes.h"
#include "AAIUnitStatistics.h"
#include "LegacyCpp/IAICallback.h"
#include <stdio.h>
#include <list>
#include <vector>
//! @brief This class stores the build-tree, this includes which unit builds another, to which side each unit belongs
class AAIBuildTree
{
public:
AAIBuildTree();
~AAIBuildTree(void);
//! @brief Generates buildtree for current game/mod
bool Generate(springLegacyAI::IAICallback* cb);
//! @brief Saves the combat power of units to given
void SaveCombatPowerOfUnits(FILE* saveFile) const;
//! @brief Initializes the combat power of units and invokes update of the unit types (returns true if successful)
bool LoadCombatPowerOfUnits(FILE* inputFile);
//! @brief Initializes the combat power (called if no saved data from previous games available)
void InitCombatPowerOfUnits(springLegacyAI::IAICallback* cb);
//! @brief Updates combat power statistics when a unit kills another
void UpdateCombatPowerStatistics(UnitDefId attackerDefId, UnitDefId killedUnitDefId);
//! @brief Prints summary of newly created buildtree
void PrintSummaryToFile(const std::string& filename, springLegacyAI::IAICallback* cb) const;
//! @brief Returns whether given the given unit type can be constructed by the given constructor unit type
bool CanBuildUnitType(UnitDefId unitDefIdBuilder, UnitDefId unitDefId) const;
//! @brief Return side of given unit type (0 if not initialized)
int GetSideOfUnitType(UnitDefId unitDefId) const { return m_initialized ? m_sideOfUnitType[unitDefId.id] : 0; }
//! @brief Returns the list of units that can construct the given unit.
const std::list<UnitDefId>& GetConstructedByList(UnitDefId unitDefId) const { return m_unitTypeCanBeConstructedtByLists[unitDefId.id]; }
//! @brief Returns the list of units that can be construct by the given unit.
const std::list<UnitDefId>& GetCanConstructList(UnitDefId unitDefId) const { return m_unitTypeCanConstructLists[unitDefId.id]; }
//! @brief Returns the number of sides
int GetNumberOfSides() const { return m_numberOfSides; }
//! @brief Returns the number of factories
int GetNumberOfFactories() const { return static_cast<int>( m_factoryIdsTable.size() ); }
//! @brief Returns the table linking factory ids with UnitDefId
const std::vector<UnitDefId>& GetFactoryDefIdLookupTable() const { return m_factoryIdsTable; }
//! @brief Returns whether a given unit type is a starting unit for one side
bool IsStartingUnit(UnitDefId unitDefId) const;
//! @brief Returns start units (probably not needed anymore when refactoring AAIBuildTable is finished)
UnitDefId GetStartUnit(int side) const { return m_initialized ? UnitDefId(m_startUnitsOfSide[side]) : UnitDefId(0); }
//! @brief Returns the unit type properties of the given unit type
const UnitTypeProperties& GetUnitTypeProperties(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id]; }
//! @brief Returns the total cost of the given unit type
float GetTotalCost(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_totalCost; }
//! @brief Returns the buildtime of the given unit type
float GetBuildtime(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_buildtime; }
//! @brief Returns the hitpoints/health of the given unit type
float GetHealth(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_health; }
//! @brief Returns the primary ability (equal to maximum weapons range for combat units)
float GetPrimaryAbility(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_primaryAbility; }
float GetMaxRange(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_primaryAbility; }
float GetBuildspeed(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_primaryAbility; }
//! @brief Returns the secondary ability (equal to maximum speed for combat units)
float GetSecondaryAbility(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_secondaryAbility; }
float GetMaxSpeed(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_secondaryAbility; }
//! @brief Returns the footprint of the given unit, i.e. number of map tiles occupied in horizontal/vertical direction
const UnitFootprint& GetFootprint(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_footprint; }
//! @brief Returns the category that the given unit belongs to
const AAIUnitCategory& GetUnitCategory(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_unitCategory; }
//! @brief Returns movement type of given unit type
const AAIMovementType& GetMovementType(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_movementType; }
//! @brief Returns the unit type
const AAIUnitType& GetUnitType(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_unitType; }
//! @brief Returns the target type
const AAITargetType& GetTargetType(UnitDefId unitDefId) const { return m_unitTypeProperties[unitDefId.id].m_targetType; }
//! @brief Returns combat power of given unit type
const TargetTypeValues& GetCombatPower(UnitDefId unitDefId) const { return m_combatPowerOfUnits[unitDefId.id]; }
//! @brief Returns the list of units of the given category for given side
const std::list<UnitDefId>& GetUnitsInCategory(const AAIUnitCategory& category, int side) const { return m_unitsInCategory[side-1][category.GetArrayIndex()]; }
//! @brief Returns the list of units of the given combat category for given side
const std::list<UnitDefId>& GetUnitsInCombatUnitCategory(const AAICombatUnitCategory& combatUnitCategory, int side) const { return m_unitsInCombatCategory[side-1][combatUnitCategory.GetArrayIndex()]; }
//! @brief Returns the list of units of the given target type
const std::list<UnitDefId>& GetUnitsOfTargetType(const AAITargetType& targetType, int side) const;
//! @brief Returns metal extractor with the largest yardmap
UnitDefId GetLargestExtractor() const;
//! @brief Returns the unit category statistics for given side
const AAIUnitStatistics& GetUnitStatistics(int side) const { return m_unitCategoryStatisticsOfSide[side-1]; }
//! @brief Returns the corresponding human readable name of the given category
const std::string& GetCategoryName(const AAIUnitCategory& category) const { return m_unitCategoryNames[category.GetArrayIndex()]; }
//! @brief Returns a list containing all unit categories of combat units
const auto& GetCombatUnitCatgegories() const { return m_combatUnitCategories; }
private:
//! @brief Sets side for given unit type, and recursively calls itself for all unit types that can be constructed by it.
void AssignSideToUnitType(int side, UnitDefId unitDefId);
//! @brief Returns the primary ability (weapon range for combat units, artillery, or static defences, los for scout, radar(jammer) range,
//! buildtime for constructors, metal extraction for extractors, metal storage capacity for storages), generated power for power plants
float DeterminePrimaryAbility(const springLegacyAI::UnitDef* unitDef, const AAIUnitCategory& unitCategory, springLegacyAI::IAICallback* cb) const;
//! @brief Returns the secondary ability (movement speed for combat units, artillery, scouts, or mobile constructors,
//! sonar(jammer) range, energy storage capacity for storages)
float DetermineSecondaryAbility(const springLegacyAI::UnitDef* unitDef, const AAIUnitCategory& unitCategory) const;
//! @brief Returns movement type of given unit definition
EMovementType DetermineMovementType(const springLegacyAI::UnitDef* unitDef) const;
//! @brief Returns target type of given movement type
ETargetType DetermineTargetType(const AAIMovementType& moveType) const;
//! @brief Returns Unit Category for given unit definition
EUnitCategory DetermineUnitCategory(const springLegacyAI::UnitDef* unitDef) const;
//! @brief Determines th e factory ids of all factories (must be called after unit types have been determined)
void InitFactoryDefIdLookUpTable(int numberOfFactories);
//! @brief Determines and sets the unit types for the given unit.
void UpdateUnitTypes(UnitDefId unitDefId, const springLegacyAI::UnitDef* unitDef);
//! @brief Determines the unit type of combat units (called after combat power has been loaded/initialized)
void UpdateUnitTypesOfCombatUnits();
//! @brief Calculates the value for the update of the combar power of the given attacker and killed unit type
float CalculateCombatPowerChange(UnitDefId attackerUnitDefId, UnitDefId killedUnitDefId) const;
//-----------------------------------------------------------------------------------------------------------------
// helper functions for determineUnitCategory(...)
//-----------------------------------------------------------------------------------------------------------------
bool IsNanoTurret(const springLegacyAI::UnitDef* unitDef) const;
bool IsScout(const springLegacyAI::UnitDef* unitDef) const;
bool IsMobileTransport(const springLegacyAI::UnitDef* unitDef) const;
bool IsArtillery(const springLegacyAI::UnitDef* unitDef, float artilleryRangeThreshold) const;
bool IsMissileLauncher(const springLegacyAI::UnitDef* unitDef) const;
bool IsDeflectionShieldEmitter(const springLegacyAI::UnitDef* unitDef) const;
float GetMaxDamage(const springLegacyAI::UnitDef* unitDef) const;
//-----------------------------------------------------------------------------------------------------------------
// member variables
//-----------------------------------------------------------------------------------------------------------------
//! Flag if build tree is initialized
bool m_initialized;
//! For every unit type, a list of unit types (unit type id) that may contsruct it
std::vector< std::list<UnitDefId> > m_unitTypeCanBeConstructedtByLists;
//! For every unit type, a list of unit types (unit type id) that it may contsruct (e.g. empty if it cannot construct any units)
std::vector< std::list<UnitDefId> > m_unitTypeCanConstructLists;
//! Properties of every unit type needed by other parts of AAI for decision making
std::vector< UnitTypeProperties > m_unitTypeProperties;
//! For every unit type, the side/faction it belongs to (0 if no side)
std::vector< int > m_sideOfUnitType;
//! For every side, the start unit, i.e. root of the buildtree (commander for original TA like mods)
std::vector< int > m_startUnitsOfSide;
//! The number of sides (i.e. groups of units with disjunct buildtree)
int m_numberOfSides;
//! For every side (not neutral), a list of units that belong to a certain category (order: m_unitsInCategory[side][category])
std::vector< std::vector< std::list<UnitDefId> > > m_unitsInCategory;
//! For every side (not neutral), a list of units that belong to a certain combat category (order: m_unitsInCombatCategory[side][category])
std::vector< std::vector< std::list<UnitDefId> > > m_unitsInCombatCategory;
//! An array containing the unit categories of the different combat units
std::array< AAIUnitCategory, 5 > m_combatUnitCategories;
//! For every side, min/max/avg values for various data (e.g. cost) for every unit category
std::vector< AAIUnitStatistics > m_unitCategoryStatisticsOfSide;
//! For each unit category, a human readable description of it
std::vector< std::string > m_unitCategoryNames;
//! The combat power of every unit
std::vector<TargetTypeValues> m_combatPowerOfUnits;
//! This vetcor stores the UnitDefIds corresponding to any valid factory id
std::vector<UnitDefId> m_factoryIdsTable;
};
#endif
|