- added a new EnumParser class to convert enum to string and vice versa

- factions can now customize some more of the AI behavior
This commit is contained in:
Mark Vejvoda 2012-03-31 05:54:24 +00:00
parent 53d0204cb9
commit 030582c1ef
9 changed files with 238 additions and 29 deletions

View File

@ -15,6 +15,7 @@
#include "unit_type.h"
#include "unit.h"
#include "map.h"
#include "faction_type.h"
#include "leak_dumper.h"
using namespace Shared::Graphics;
@ -234,6 +235,53 @@ UpgradeTask * UpgradeTask::loadGame(const XmlNode *rootNode, Faction *faction) {
void Ai::init(AiInterface *aiInterface, int useStartLocation) {
this->aiInterface= aiInterface;
Faction *faction = this->aiInterface->getMyFaction();
if(faction->getAIBehaviorStaticOverideValue(aibsvcMaxBuildRadius) != INT_MAX) {
maxBuildRadius = faction->getAIBehaviorStaticOverideValue(aibsvcMaxBuildRadius);
//printf("Discovered overriden static value for AI, maxBuildRadius = %d\n",maxBuildRadius);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriors) != INT_MAX) {
minMinWarriors = faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriors);
//printf("Discovered overriden static value for AI, minMinWarriors = %d\n",minMinWarriors);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriorsExpandCpuEasy) != INT_MAX) {
minMinWarriorsExpandCpuEasy = faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriorsExpandCpuEasy);
//printf("Discovered overriden static value for AI, minMinWarriorsExpandCpuEasy = %d\n",minMinWarriorsExpandCpuEasy);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriorsExpandCpuMega) != INT_MAX) {
minMinWarriorsExpandCpuMega = faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriorsExpandCpuMega);
//printf("Discovered overriden static value for AI, minMinWarriorsExpandCpuMega = %d\n",minMinWarriorsExpandCpuMega);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriorsExpandCpuUltra) != INT_MAX) {
minMinWarriorsExpandCpuUltra = faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriorsExpandCpuUltra);
//printf("Discovered overriden static value for AI, minMinWarriorsExpandCpuUltra = %d\n",minMinWarriorsExpandCpuUltra);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriorsExpandCpuNormal) != INT_MAX) {
minMinWarriorsExpandCpuNormal = faction->getAIBehaviorStaticOverideValue(aibsvcMinMinWarriorsExpandCpuNormal);
//printf("Discovered overriden static value for AI, minMinWarriorsExpandCpuNormal = %d\n",minMinWarriorsExpandCpuNormal);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcMaxMinWarriors) != INT_MAX) {
maxMinWarriors = faction->getAIBehaviorStaticOverideValue(aibsvcMaxMinWarriors);
//printf("Discovered overriden static value for AI, maxMinWarriors = %d\n",maxMinWarriors);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcMaxExpansions) != INT_MAX) {
maxExpansions = faction->getAIBehaviorStaticOverideValue(aibsvcMaxExpansions);
//printf("Discovered overriden static value for AI, maxExpansions = %d\n",maxExpansions);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcVillageRadius) != INT_MAX) {
villageRadius = faction->getAIBehaviorStaticOverideValue(aibsvcVillageRadius);
//printf("Discovered overriden static value for AI, villageRadius = %d\n",villageRadius);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcScoutResourceRange) != INT_MAX) {
scoutResourceRange = faction->getAIBehaviorStaticOverideValue(aibsvcScoutResourceRange);
//printf("Discovered overriden static value for AI, scoutResourceRange = %d\n",scoutResourceRange);
}
if(faction->getAIBehaviorStaticOverideValue(aibsvcMinWorkerAttackersHarvesting) != INT_MAX) {
minWorkerAttackersHarvesting = faction->getAIBehaviorStaticOverideValue(aibsvcMinWorkerAttackersHarvesting);
//printf("Discovered overriden static value for AI, scoutResourceRange = %d\n",scoutResourceRange);
}
if(useStartLocation == -1) {
startLoc = random.randRange(0, aiInterface->getMapMaxPlayers()-1);
}
@ -709,7 +757,7 @@ void Ai::sendScoutPatrol(){
//printf("is inside map\n");
// find first resource in this area
Vec2i resPos;
if(aiInterface->isResourceInRegion(pos, rt, resPos, 20)){
if(aiInterface->isResourceInRegion(pos, rt, resPos, scoutResourceRange)){
// found a possible target.
pos= resPos;
//printf("lets try the new target\n");
@ -738,8 +786,6 @@ void Ai::sendScoutPatrol(){
}
void Ai::massiveAttack(const Vec2i &pos, Field field, bool ultraAttack){
const int minWorkerAttackersHarvesting = 3;
int producerWarriorCount=0;
int maxProducerWarriors=random.randRange(1,11);
int unitCount = aiInterface->getMyUnitCount();
@ -1126,6 +1172,29 @@ void Ai::saveGame(XmlNode *rootNode) const {
// RandomGen random;
aiNode->addAttribute("random",intToStr(random.getLastNumber()), mapTagReplacements);
// std::map<int,int> factionSwitchTeamRequestCount;
// int maxBuildRadius;
aiNode->addAttribute("maxBuildRadius",intToStr(maxBuildRadius), mapTagReplacements);
// int minMinWarriors;
aiNode->addAttribute("minMinWarriors",intToStr(minMinWarriors), mapTagReplacements);
// int minMinWarriorsExpandCpuEasy;
aiNode->addAttribute("minMinWarriorsExpandCpuEasy",intToStr(minMinWarriorsExpandCpuEasy), mapTagReplacements);
// int minMinWarriorsExpandCpuMega;
aiNode->addAttribute("minMinWarriorsExpandCpuMega",intToStr(minMinWarriorsExpandCpuMega), mapTagReplacements);
// int minMinWarriorsExpandCpuUltra;
aiNode->addAttribute("minMinWarriorsExpandCpuUltra",intToStr(minMinWarriorsExpandCpuUltra), mapTagReplacements);
// int minMinWarriorsExpandCpuNormal;
aiNode->addAttribute("minMinWarriorsExpandCpuNormal",intToStr(minMinWarriorsExpandCpuNormal), mapTagReplacements);
// int maxMinWarriors;
aiNode->addAttribute("maxMinWarriors",intToStr(maxMinWarriors), mapTagReplacements);
// int maxExpansions;
aiNode->addAttribute("maxExpansions",intToStr(maxExpansions), mapTagReplacements);
// int villageRadius;
aiNode->addAttribute("villageRadius",intToStr(villageRadius), mapTagReplacements);
// int scoutResourceRange;
aiNode->addAttribute("scoutResourceRange",intToStr(scoutResourceRange), mapTagReplacements);
// int minWorkerAttackersHarvesting;
aiNode->addAttribute("minWorkerAttackersHarvesting",intToStr(minWorkerAttackersHarvesting), mapTagReplacements);
}
void Ai::loadGame(const XmlNode *rootNode, Faction *faction) {
@ -1170,6 +1239,29 @@ void Ai::loadGame(const XmlNode *rootNode, Faction *faction) {
// RandomGen random;
random.setLastNumber(aiNode->getAttribute("random")->getIntValue());
// std::map<int,int> factionSwitchTeamRequestCount;
// int maxBuildRadius;
maxBuildRadius = aiNode->getAttribute("maxBuildRadius")->getIntValue();
// int minMinWarriors;
minMinWarriors = aiNode->getAttribute("minMinWarriors")->getIntValue();
// int minMinWarriorsExpandCpuEasy;
minMinWarriorsExpandCpuEasy = aiNode->getAttribute("minMinWarriorsExpandCpuEasy")->getIntValue();
// int minMinWarriorsExpandCpuMega;
minMinWarriorsExpandCpuMega = aiNode->getAttribute("minMinWarriorsExpandCpuMega")->getIntValue();
// int minMinWarriorsExpandCpuUltra;
minMinWarriorsExpandCpuUltra = aiNode->getAttribute("minMinWarriorsExpandCpuUltra")->getIntValue();
// int minMinWarriorsExpandCpuNormal;
minMinWarriorsExpandCpuNormal = aiNode->getAttribute("minMinWarriorsExpandCpuNormal")->getIntValue();
// int maxMinWarriors;
maxMinWarriors = aiNode->getAttribute("maxMinWarriors")->getIntValue();
// int maxExpansions;
maxExpansions = aiNode->getAttribute("maxExpansions")->getIntValue();
// int villageRadius;
villageRadius = aiNode->getAttribute("villageRadius")->getIntValue();
// int scoutResourceRange;
scoutResourceRange = aiNode->getAttribute("scoutResourceRange")->getIntValue();
// int minWorkerAttackersHarvesting;
minWorkerAttackersHarvesting = aiNode->getAttribute("minWorkerAttackersHarvesting")->getIntValue();
}
}}//end namespace

View File

@ -129,17 +129,19 @@ public:
class Ai {
private:
static const int maxBuildRadius= 40;
int maxBuildRadius;
static const int minMinWarriors= 7;
static const int minMinWarriorsExpandCpuEasy= 1;
static const int minMinWarriorsExpandCpuMega= 3;
static const int minMinWarriorsExpandCpuUltra= 3;
static const int minMinWarriorsExpandCpuNormal= 3;
static const int maxMinWarriors= 20;
int minMinWarriors;
int minMinWarriorsExpandCpuEasy;
int minMinWarriorsExpandCpuMega;
int minMinWarriorsExpandCpuUltra;
int minMinWarriorsExpandCpuNormal;
int maxMinWarriors;
static const int maxExpansions= 2;
static const int villageRadius= 15;
int maxExpansions;
int villageRadius;
int scoutResourceRange;
int minWorkerAttackersHarvesting;
public:
enum ResourceUsage {
@ -163,20 +165,32 @@ private:
Positions expansionPositions;
RandomGen random;
std::map<int,int> factionSwitchTeamRequestCount;
int minWarriors;
bool getAdjacentUnits(std::map<float, std::map<int, const Unit *> > &signalAdjacentUnits, const Unit *unit);
public:
Ai() {
aiInterface = NULL;
startLoc = -1;
// Defaults that used to be static which can now be overriden
maxBuildRadius = 40;
minMinWarriors = 7;
minMinWarriorsExpandCpuEasy = 1;
minMinWarriorsExpandCpuMega = 3;
minMinWarriorsExpandCpuUltra = 3;
minMinWarriorsExpandCpuNormal = 3;
maxMinWarriors = 20;
maxExpansions = 2;
villageRadius = 15;
scoutResourceRange = 20;
minWorkerAttackersHarvesting = 3;
aiInterface = NULL;
startLoc = -1;
randomMinWarriorsReached = false;
minWarriors = 0;
minWarriors = 0;
}
~Ai();
int minWarriors;
void init(AiInterface *aiInterface,int useStartLocation=-1);
void update();
@ -185,6 +199,8 @@ public:
RandomGen* getRandom() {return &random;}
int getCountOfType(const UnitType *ut);
int getMinWarriors() const { return minWarriors; }
int getCountOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount=NULL);
float getRatioOfClass(UnitClass uc,UnitClass *additionalUnitClassToExcludeFromCount=NULL);

View File

@ -430,7 +430,7 @@ void AiRuleAddTasks::execute(){
if(warriorRatio<0.30) ai->addTask(new ProduceTask(ucWarrior));
if(workerCount>=10) ai->addTask(new ProduceTask(ucWarrior));
if(workerCount>=15) ai->addTask(new ProduceTask(ucWarrior));
if(warriorCount<ai->minWarriors+2)
if(warriorCount < ai->getMinWarriors() + 2)
{
ai->addTask(new ProduceTask(ucWarrior));
if( buildingCount>9 )
@ -603,8 +603,8 @@ bool AiRuleProduceResourceProducer::test(){
}
int targetStaticResourceCount = minStaticResources;
if(aiInterface->getMyFactionType()->getAIBehaviorMinStaticResourceCount() != INT_MAX) {
targetStaticResourceCount = aiInterface->getMyFactionType()->getAIBehaviorMinStaticResourceCount();
if(aiInterface->getMyFactionType()->getAIBehaviorStaticOverideValue(aibsvcMinStaticResourceCount) != INT_MAX) {
targetStaticResourceCount = aiInterface->getMyFactionType()->getAIBehaviorStaticOverideValue(aibsvcMinStaticResourceCount);
}
//statics second

View File

@ -4,6 +4,9 @@
#include <cassert>
#include <stdio.h>
#include "vec.h"
#include <map>
#include <string>
#include <stdexcept>
// ==============================================================
// This file is part of Glest (www.glest.org)
@ -17,9 +20,41 @@
// ==============================================================
using namespace Shared::Graphics;
using namespace std;
namespace Glest{ namespace Game{
template<typename T>
class EnumParser {
private:
typedef map<string, T> enumMapType;
typedef typename enumMapType::const_iterator enumMapTypeIter;
EnumParser();
enumMapType enumMap;
public:
static T getEnum(const string &value) {
static EnumParser<T> parser;
enumMapTypeIter iValue = parser.enumMap.find(value);
if(iValue == parser.enumMap.end()) {
throw std::runtime_error("unknown enum lookup [" + value + "]");
}
return iValue->second;
}
static string getString(const T &value) {
static EnumParser<T> parser;
for(enumMapTypeIter iValue = parser.enumMap.first();
iValue != parser.enumMap.end(); ++iValue) {
if(iValue->second == value) {
return iValue->first;
}
}
throw std::runtime_error("unknown enum lookup [" + intToStr(value) + "]");
}
};
// =====================================================
// class GameConstants
// =====================================================

View File

@ -452,6 +452,11 @@ FactionPersonalityType Faction::getPersonalityType() const {
return factionType->getPersonalityType();
}
int Faction::getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type) const {
return factionType->getAIBehaviorStaticOverideValue(type);
}
Unit * Faction::getUnit(int i) const {
Unit *result = units[i];
return result;

View File

@ -22,6 +22,7 @@
#include "command_type.h"
#include "base_thread.h"
#include <set>
#include "faction_type.h"
#include "leak_dumper.h"
using std::map;
@ -186,8 +187,10 @@ public:
bool getCpuUltraControl() const {return control==ctCpuUltra;}
bool getCpuMegaControl() const {return control==ctCpuMega;}
ControlType getControlType() const {return control;}
FactionPersonalityType getPersonalityType() const;
void setPersonalityType(FactionPersonalityType pType) { overridePersonalityType=pType; }
int getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type) const;
Unit *getUnit(int i) const;
int getUnitCount() const;

View File

@ -33,7 +33,6 @@ namespace Glest{ namespace Game{
FactionType::FactionType() {
music = NULL;
personalityType = fpt_Normal;
aIBehavior_minStaticResourceCount = INT_MAX;
}
//load a faction, given a directory
@ -42,8 +41,6 @@ void FactionType::load(const string &factionName, const TechTree *techTree, Chec
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
aIBehavior_minStaticResourceCount = INT_MAX;
string techTreePath = techTree->getPath();
string techTreeName=techTree->getName();
string currentPath = "";
@ -221,9 +218,30 @@ void FactionType::load(const string &factionName, const TechTree *techTree, Chec
if(factionNode->hasChild("ai-behavior") == true) {
const XmlNode *aiNode= factionNode->getChild("ai-behavior");
if(aiNode->hasAttribute("min-static-resource-count") == true) {
aIBehavior_minStaticResourceCount = aiNode->getAttribute("min-static-resource-count")->getIntValue();
//printf("aIBehavior_minStaticResourceCount = %d\n",aIBehavior_minStaticResourceCount);
mapAIBehaviorStaticOverrideValues[aibsvcMinStaticResourceCount] = aiNode->getAttribute("min-static-resource-count")->getIntValue();
}
if(aiNode->hasChild("static-values") == true) {
const XmlNode *aiNodeUnits= aiNode->getChild("static-values");
for(int i = 0; i < aiNodeUnits->getChildCount(); ++i) {
const XmlNode *unitNode= aiNodeUnits->getChild("static", i);
AIBehaviorStaticValueCategory type = aibsvcMaxBuildRadius;
if(unitNode->hasAttribute("type") == true) {
type = static_cast<AIBehaviorStaticValueCategory>(
unitNode->getAttribute("type")->getIntValue());
}
else {
type = EnumParser<AIBehaviorStaticValueCategory>::getEnum(
unitNode->getAttribute("type-name")->getValue());
//printf("Discovered overriden static value for AI, type = %d, value = %d\n",type,value);
}
int value = unitNode->getAttribute("value")->getIntValue();
mapAIBehaviorStaticOverrideValues[type]=value;
//printf("Discovered overriden static value for AI, type = %d, value = %d\n",type,value);
}
}
if(aiNode->hasChild("worker-units") == true) {
const XmlNode *aiNodeUnits= aiNode->getChild("worker-units");
for(int i = 0; i < aiNodeUnits->getChildCount(); ++i) {
@ -279,6 +297,16 @@ void FactionType::load(const string &factionName, const TechTree *techTree, Chec
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
int FactionType::getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type) const {
int result = INT_MAX;
std::map<AIBehaviorStaticValueCategory, int >::const_iterator iterFind =
mapAIBehaviorStaticOverrideValues.find(type);
if(iterFind != mapAIBehaviorStaticOverrideValues.end()) {
result = iterFind->second;
}
return result;
}
const std::vector<FactionType::PairPUnitTypeInt> FactionType::getAIBehaviorUnits(AIBehaviorUnitCategory category) const {
std::map<AIBehaviorUnitCategory, std::vector<PairPUnitTypeInt> >::const_iterator iterFind = mapAIBehaviorUnitCategories.find(category);
if(iterFind != mapAIBehaviorUnitCategories.end()) {

View File

@ -15,12 +15,14 @@
#include "unit_type.h"
#include "upgrade_type.h"
#include "sound.h"
#include <map>
#include <string>
#include "util.h"
#include "leak_dumper.h"
using Shared::Sound::StrSound;
namespace Glest{ namespace Game{
// =====================================================
// class FactionType
//
@ -34,6 +36,35 @@ enum AIBehaviorUnitCategory {
aibcBuildingUnits
};
enum AIBehaviorStaticValueCategory {
aibsvcMaxBuildRadius,
aibsvcMinMinWarriors,
aibsvcMinMinWarriorsExpandCpuEasy,
aibsvcMinMinWarriorsExpandCpuMega,
aibsvcMinMinWarriorsExpandCpuUltra,
aibsvcMinMinWarriorsExpandCpuNormal,
aibsvcMaxMinWarriors,
aibsvcMaxExpansions,
aibsvcVillageRadius,
aibsvcMinStaticResourceCount,
aibsvcScoutResourceRange,
aibsvcMinWorkerAttackersHarvesting
};
template <>
inline EnumParser<AIBehaviorStaticValueCategory>::EnumParser() {
enumMap["MaxBuildRadius"] = aibsvcMaxBuildRadius;
enumMap["MinMinWarriors"] = aibsvcMinMinWarriors;
enumMap["MinMinWarriorsExpandCpuEasy"] = aibsvcMinMinWarriorsExpandCpuEasy;
enumMap["MinMinWarriorsExpandCpuMega"] = aibsvcMinMinWarriorsExpandCpuMega;
enumMap["MinMinWarriorsExpandCpuUltra"] = aibsvcMinMinWarriorsExpandCpuUltra;
enumMap["MinMinWarriorsExpandCpuNormal"]= aibsvcMinMinWarriorsExpandCpuNormal;
enumMap["MaxMinWarriors"] = aibsvcMaxMinWarriors;
enumMap["MaxExpansions"] = aibsvcMaxExpansions;
enumMap["VillageRadius"] = aibsvcVillageRadius;
enumMap["MinStaticResourceCount"] = aibsvcMinStaticResourceCount;
enumMap["ScoutResourceRange"] = aibsvcScoutResourceRange;
enumMap["MinWorkerAttackersHarvesting"] = aibsvcMinWorkerAttackersHarvesting;
}
class FactionType {
public:
@ -54,7 +85,7 @@ private:
std::map<AIBehaviorUnitCategory, std::vector<PairPUnitTypeInt> > mapAIBehaviorUnitCategories;
std::vector<const UpgradeType*> vctAIBehaviorUpgrades;
int aIBehavior_minStaticResourceCount;
std::map<AIBehaviorStaticValueCategory, int > mapAIBehaviorStaticOverrideValues;
public:
//init
@ -65,7 +96,7 @@ public:
const std::vector<FactionType::PairPUnitTypeInt> getAIBehaviorUnits(AIBehaviorUnitCategory category) const;
const std::vector<const UpgradeType*> getAIBehaviorUpgrades() const { return vctAIBehaviorUpgrades; };
int getAIBehaviorMinStaticResourceCount() const { return aIBehavior_minStaticResourceCount; }
int getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type) const;
//get
int getUnitTypeCount() const {return unitTypes.size();}

View File

@ -244,7 +244,6 @@ public:
}
};
}}//end namespace
#endif