mirror of
https://github.com/glest/glest-source.git
synced 2025-02-24 19:52:25 +01:00
1915 lines
57 KiB
C++
1915 lines
57 KiB
C++
// ==============================================================
|
|
// This file is part of Glest (www.glest.org)
|
|
//
|
|
// Copyright (C) 2001-2008 Martiño Figueroa
|
|
//
|
|
// You can redistribute this code and/or modify it under
|
|
// the terms of the GNU General Public License as published
|
|
// by the Free Software Foundation; either version 2 of the
|
|
// License, or (at your option) any later version
|
|
// ==============================================================
|
|
|
|
#include "ai.h"
|
|
#include "ai_interface.h"
|
|
#include "ai_rule.h"
|
|
#include "unit_type.h"
|
|
#include "unit.h"
|
|
#include "map.h"
|
|
#include "faction_type.h"
|
|
#include "leak_dumper.h"
|
|
|
|
using namespace
|
|
Shared::Graphics;
|
|
using namespace
|
|
Shared::Util;
|
|
|
|
namespace
|
|
Glest {
|
|
namespace
|
|
Game {
|
|
|
|
Task::Task() {
|
|
taskClass = tcProduce;
|
|
}
|
|
|
|
//void Task::saveGame(XmlNode *rootNode) const {
|
|
// std::map<string,string> mapTagReplacements;
|
|
// XmlNode *taskNode = rootNode->addChild("Task");
|
|
//}
|
|
|
|
// =====================================================
|
|
// class ProduceTask
|
|
// =====================================================
|
|
ProduceTask::ProduceTask() :
|
|
Task() {
|
|
taskClass = tcProduce;
|
|
unitType = NULL;
|
|
resourceType = NULL;
|
|
unitClass = ucWarrior;
|
|
}
|
|
|
|
ProduceTask::ProduceTask(UnitClass unitClass) :
|
|
Task() {
|
|
taskClass = tcProduce;
|
|
this->unitClass = unitClass;
|
|
unitType = NULL;
|
|
resourceType = NULL;
|
|
}
|
|
|
|
ProduceTask::ProduceTask(const UnitType * unitType) :
|
|
Task() {
|
|
taskClass = tcProduce;
|
|
this->unitType = unitType;
|
|
resourceType = NULL;
|
|
unitClass = ucWarrior;
|
|
}
|
|
|
|
ProduceTask::ProduceTask(const ResourceType * resourceType) :
|
|
Task() {
|
|
taskClass = tcProduce;
|
|
unitType = NULL;
|
|
unitClass = ucWarrior;
|
|
this->resourceType = resourceType;
|
|
}
|
|
|
|
string
|
|
ProduceTask::toString() const {
|
|
string
|
|
str = "Produce ";
|
|
if (unitType != NULL) {
|
|
str += unitType->getName(false);
|
|
}
|
|
return
|
|
str;
|
|
}
|
|
|
|
void
|
|
ProduceTask::saveGame(XmlNode * rootNode) const {
|
|
std::map <
|
|
string,
|
|
string >
|
|
mapTagReplacements;
|
|
XmlNode *
|
|
taskNode = rootNode->addChild("Task");
|
|
taskNode->
|
|
addAttribute("taskClass", intToStr(taskClass), mapTagReplacements);
|
|
XmlNode *
|
|
produceTaskNode = taskNode->addChild("ProduceTask");
|
|
|
|
// UnitClass unitClass;
|
|
produceTaskNode->
|
|
addAttribute("unitClass", intToStr(unitClass), mapTagReplacements);
|
|
// const UnitType *unitType;
|
|
if (unitType != NULL) {
|
|
produceTaskNode->addAttribute("unitType",
|
|
unitType->getName(false),
|
|
mapTagReplacements);
|
|
}
|
|
// const ResourceType *resourceType;
|
|
if (resourceType != NULL) {
|
|
produceTaskNode->addAttribute("resourceType",
|
|
resourceType->getName(false),
|
|
mapTagReplacements);
|
|
}
|
|
}
|
|
|
|
ProduceTask *
|
|
ProduceTask::loadGame(const XmlNode * rootNode, Faction * faction) {
|
|
const XmlNode *
|
|
produceTaskNode = rootNode->getChild("ProduceTask");
|
|
|
|
ProduceTask *
|
|
newTask = new ProduceTask();
|
|
// UnitClass unitClass;
|
|
newTask->unitClass =
|
|
static_cast <UnitClass>
|
|
(produceTaskNode->getAttribute("unitClass")->getIntValue());
|
|
// const UnitType *unitType;
|
|
if (produceTaskNode->hasAttribute("unitType")) {
|
|
string
|
|
unitTypeName =
|
|
produceTaskNode->getAttribute("unitType")->getValue();
|
|
newTask->unitType = faction->getType()->getUnitType(unitTypeName);
|
|
}
|
|
// const ResourceType *resourceType;
|
|
if (produceTaskNode->hasAttribute("resourceType")) {
|
|
string
|
|
resourceTypeName =
|
|
produceTaskNode->getAttribute("resourceType")->getValue();
|
|
newTask->resourceType =
|
|
faction->getTechTree()->getResourceType(resourceTypeName);
|
|
}
|
|
|
|
return newTask;
|
|
}
|
|
|
|
// =====================================================
|
|
// class BuildTask
|
|
// =====================================================
|
|
BuildTask::BuildTask() {
|
|
taskClass = tcBuild;
|
|
this->unitType = NULL;
|
|
resourceType = NULL;
|
|
forcePos = false;
|
|
}
|
|
|
|
BuildTask::BuildTask(const UnitType * unitType) {
|
|
taskClass = tcBuild;
|
|
this->unitType = unitType;
|
|
resourceType = NULL;
|
|
forcePos = false;
|
|
}
|
|
|
|
BuildTask::BuildTask(const ResourceType * resourceType) {
|
|
taskClass = tcBuild;
|
|
unitType = NULL;
|
|
this->resourceType = resourceType;
|
|
forcePos = false;
|
|
}
|
|
|
|
BuildTask::BuildTask(const UnitType * unitType, const Vec2i & pos) {
|
|
taskClass = tcBuild;
|
|
this->unitType = unitType;
|
|
resourceType = NULL;
|
|
forcePos = true;
|
|
this->pos = pos;
|
|
}
|
|
|
|
string
|
|
BuildTask::toString() const {
|
|
string
|
|
str = "Build ";
|
|
if (unitType != NULL) {
|
|
str += unitType->getName(false);
|
|
}
|
|
return
|
|
str;
|
|
}
|
|
|
|
void
|
|
BuildTask::saveGame(XmlNode * rootNode) const {
|
|
std::map <
|
|
string,
|
|
string >
|
|
mapTagReplacements;
|
|
XmlNode *
|
|
taskNode = rootNode->addChild("Task");
|
|
taskNode->
|
|
addAttribute("taskClass", intToStr(taskClass), mapTagReplacements);
|
|
XmlNode *
|
|
buildTaskNode = taskNode->addChild("BuildTask");
|
|
|
|
// const UnitType *unitType;
|
|
if (unitType != NULL) {
|
|
buildTaskNode->addAttribute("unitType", unitType->getName(false),
|
|
mapTagReplacements);
|
|
}
|
|
// const ResourceType *resourceType;
|
|
if (resourceType != NULL) {
|
|
buildTaskNode->addAttribute("resourceType",
|
|
resourceType->getName(),
|
|
mapTagReplacements);
|
|
}
|
|
// bool forcePos;
|
|
buildTaskNode->addAttribute("forcePos", intToStr(forcePos),
|
|
mapTagReplacements);
|
|
// Vec2i pos;
|
|
buildTaskNode->addAttribute("pos", pos.getString(),
|
|
mapTagReplacements);
|
|
}
|
|
|
|
BuildTask *
|
|
BuildTask::loadGame(const XmlNode * rootNode, Faction * faction) {
|
|
const XmlNode *
|
|
buildTaskNode = rootNode->getChild("BuildTask");
|
|
|
|
BuildTask *
|
|
newTask = new BuildTask();
|
|
if (buildTaskNode->hasAttribute("unitType")) {
|
|
string
|
|
unitTypeName =
|
|
buildTaskNode->getAttribute("unitType")->getValue();
|
|
newTask->unitType = faction->getType()->getUnitType(unitTypeName);
|
|
}
|
|
if (buildTaskNode->hasAttribute("resourceType")) {
|
|
string
|
|
resourceTypeName =
|
|
buildTaskNode->getAttribute("resourceType")->getValue();
|
|
newTask->resourceType =
|
|
faction->getTechTree()->getResourceType(resourceTypeName);
|
|
}
|
|
|
|
newTask->forcePos =
|
|
buildTaskNode->getAttribute("forcePos")->getIntValue() != 0;
|
|
newTask->pos =
|
|
Vec2i::strToVec2(buildTaskNode->getAttribute("pos")->getValue());
|
|
|
|
return newTask;
|
|
}
|
|
|
|
// =====================================================
|
|
// class UpgradeTask
|
|
// =====================================================
|
|
UpgradeTask::UpgradeTask() {
|
|
taskClass = tcUpgrade;
|
|
this->upgradeType = NULL;
|
|
}
|
|
|
|
UpgradeTask::UpgradeTask(const UpgradeType * upgradeType) {
|
|
taskClass = tcUpgrade;
|
|
this->upgradeType = upgradeType;
|
|
}
|
|
|
|
string
|
|
UpgradeTask::toString() const {
|
|
string
|
|
str = "Build ";
|
|
if (upgradeType != NULL) {
|
|
str += upgradeType->getName();
|
|
}
|
|
return
|
|
str;
|
|
}
|
|
|
|
void
|
|
UpgradeTask::saveGame(XmlNode * rootNode) const {
|
|
std::map <
|
|
string,
|
|
string >
|
|
mapTagReplacements;
|
|
XmlNode *
|
|
taskNode = rootNode->addChild("Task");
|
|
taskNode->
|
|
addAttribute("taskClass", intToStr(taskClass), mapTagReplacements);
|
|
XmlNode *
|
|
upgradeTaskNode = taskNode->addChild("UpgradeTask");
|
|
|
|
if (upgradeType != NULL) {
|
|
//upgradeType->saveGame(upgradeTaskNode);
|
|
upgradeTaskNode->addAttribute("upgradeType",
|
|
upgradeType->getName(),
|
|
mapTagReplacements);
|
|
}
|
|
}
|
|
|
|
UpgradeTask *
|
|
UpgradeTask::loadGame(const XmlNode * rootNode, Faction * faction) {
|
|
const XmlNode *
|
|
upgradeTaskNode = rootNode->getChild("UpgradeTask");
|
|
|
|
UpgradeTask *
|
|
newTask = new UpgradeTask();
|
|
if (upgradeTaskNode->hasAttribute("upgradeType")) {
|
|
string
|
|
upgradeTypeName =
|
|
upgradeTaskNode->getAttribute("upgradeType")->getValue();
|
|
newTask->upgradeType =
|
|
faction->getType()->getUpgradeType(upgradeTypeName);
|
|
}
|
|
return newTask;
|
|
}
|
|
|
|
// =====================================================
|
|
// class Ai
|
|
// =====================================================
|
|
|
|
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(aibsvcMinMinWarriorsExpandCpuZeta)
|
|
!= INT_MAX) {
|
|
minMinWarriorsExpandCpuZeta =
|
|
faction->
|
|
getAIBehaviorStaticOverideValue
|
|
(aibsvcMinMinWarriorsExpandCpuZeta);
|
|
//printf("Discovered overriden static value for AI, minMinWarriorsExpandCpuZeta = %d\n",minMinWarriorsExpandCpuZeta);
|
|
}
|
|
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 (faction->getAIBehaviorStaticOverideValue(aibsvcMinBuildSpacing) !=
|
|
INT_MAX) {
|
|
minBuildSpacing =
|
|
faction->getAIBehaviorStaticOverideValue(aibsvcMinBuildSpacing);
|
|
//printf("Discovered overriden static value for AI, scoutResourceRange = %d\n",scoutResourceRange);
|
|
}
|
|
|
|
if (useStartLocation == -1) {
|
|
startLoc =
|
|
random.randRange(0, aiInterface->getMapMaxPlayers() - 1);
|
|
} else {
|
|
startLoc = useStartLocation;
|
|
}
|
|
minWarriors = minMinWarriors;
|
|
randomMinWarriorsReached = false;
|
|
//add ai rules
|
|
aiRules.clear();
|
|
aiRules.push_back(new AiRuleWorkerHarvest(this));
|
|
aiRules.push_back(new AiRuleRefreshHarvester(this));
|
|
aiRules.push_back(new AiRuleScoutPatrol(this));
|
|
aiRules.push_back(new AiRuleUnBlock(this));
|
|
aiRules.push_back(new AiRuleReturnBase(this));
|
|
aiRules.push_back(new AiRuleMassiveAttack(this));
|
|
aiRules.push_back(new AiRuleAddTasks(this));
|
|
aiRules.push_back(new AiRuleProduceResourceProducer(this));
|
|
aiRules.push_back(new AiRuleBuildOneFarm(this));
|
|
aiRules.push_back(new AiRuleProduce(this));
|
|
aiRules.push_back(new AiRuleBuild(this));
|
|
aiRules.push_back(new AiRuleUpgrade(this));
|
|
aiRules.push_back(new AiRuleExpand(this));
|
|
aiRules.push_back(new AiRuleRepair(this));
|
|
aiRules.push_back(new AiRuleRepair(this));
|
|
}
|
|
|
|
Ai::~Ai() {
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d] deleting AI aiInterface [%p]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
aiInterface);
|
|
deleteValues(tasks.begin(), tasks.end());
|
|
tasks.clear();
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d] deleting AI aiInterface [%p]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
aiInterface);
|
|
|
|
deleteValues(aiRules.begin(), aiRules.end());
|
|
aiRules.clear();
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d] deleting AI aiInterface [%p]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
aiInterface);
|
|
|
|
aiInterface = NULL;
|
|
}
|
|
|
|
RandomGen *
|
|
Ai::getRandom() {
|
|
// if(Thread::isCurrentThreadMainThread() == false) {
|
|
// throw megaglest_runtime_error("Invalid access to AI random from outside main thread current id = " +
|
|
// intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId()));
|
|
// }
|
|
return &random;
|
|
}
|
|
|
|
void
|
|
Ai::update() {
|
|
|
|
Chrono
|
|
chrono;
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled)
|
|
chrono.start();
|
|
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [START]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
chrono.getMillis());
|
|
|
|
if (aiInterface->getMyFaction()->getFirstSwitchTeamVote() != NULL) {
|
|
const SwitchTeamVote *
|
|
vote = aiInterface->getMyFaction()->getFirstSwitchTeamVote();
|
|
aiInterface->getMyFaction()->
|
|
setCurrentSwitchTeamVoteFactionIndex(vote->factionIndex);
|
|
|
|
factionSwitchTeamRequestCount[vote->factionIndex]++;
|
|
int
|
|
factionSwitchTeamRequestCountCurrent =
|
|
factionSwitchTeamRequestCount[vote->factionIndex];
|
|
|
|
//int allowJoinTeam = random.randRange(0, 100);
|
|
//srand(time(NULL) + aiInterface->getMyFaction()->getIndex());
|
|
Chrono
|
|
seed(true);
|
|
srand((unsigned int) seed.getCurTicks() +
|
|
aiInterface->getMyFaction()->getIndex());
|
|
|
|
int
|
|
allowJoinTeam = rand() % 100;
|
|
|
|
SwitchTeamVote *
|
|
voteResult =
|
|
aiInterface->getMyFaction()->getSwitchTeamVote(vote->
|
|
factionIndex);
|
|
voteResult->voted = true;
|
|
voteResult->allowSwitchTeam = false;
|
|
|
|
const GameSettings *
|
|
settings = aiInterface->getWorld()->getGameSettings();
|
|
|
|
// If AI player already lost game they cannot vote
|
|
if (aiInterface->getWorld()->
|
|
factionLostGame(aiInterface->getFactionIndex()) == true) {
|
|
voteResult->allowSwitchTeam = true;
|
|
} else {
|
|
// Can only ask the AI player 2 times max per game
|
|
if (factionSwitchTeamRequestCountCurrent <= 2) {
|
|
// x% chance the AI will answer yes
|
|
if (settings->getAiAcceptSwitchTeamPercentChance() >= 100) {
|
|
voteResult->allowSwitchTeam = true;
|
|
} else if (settings->getAiAcceptSwitchTeamPercentChance() <=
|
|
0) {
|
|
voteResult->allowSwitchTeam = false;
|
|
} else {
|
|
voteResult->allowSwitchTeam =
|
|
(allowJoinTeam >=
|
|
(100 -
|
|
settings->getAiAcceptSwitchTeamPercentChance()));
|
|
}
|
|
}
|
|
}
|
|
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"AI for faction# %d voted %s [%d] CountCurrent [%d] PercentChance [%d]",
|
|
aiInterface->getMyFaction()->getIndex(),
|
|
(voteResult->allowSwitchTeam ? "Yes" : "No"),
|
|
allowJoinTeam, factionSwitchTeamRequestCountCurrent,
|
|
settings->getAiAcceptSwitchTeamPercentChance());
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d] %s\n", __FILE__,
|
|
__FUNCTION__, __LINE__, szBuf);
|
|
|
|
aiInterface->printLog(3, szBuf);
|
|
|
|
aiInterface->giveCommandSwitchTeamVote(aiInterface->
|
|
getMyFaction(),
|
|
voteResult);
|
|
}
|
|
|
|
//process ai rules
|
|
for (unsigned int ruleIdx = 0; ruleIdx < aiRules.size(); ++ruleIdx) {
|
|
AiRule *
|
|
rule = aiRules[ruleIdx];
|
|
if (rule == NULL) {
|
|
throw
|
|
megaglest_runtime_error("rule == NULL");
|
|
}
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugPerformance).enabled
|
|
&& chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [ruleIdx = %d]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
chrono.getMillis(), ruleIdx);
|
|
// Determines wether to process AI rules. Whether a particular rule is processed, is weighted by getTestInterval().
|
|
// Values returned by getTestInterval() are defined in ai_rule.h.
|
|
if ((aiInterface->getTimer() %
|
|
(rule->getTestInterval() * GameConstants::updateFps /
|
|
1000)) == 0) {
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugPerformance).enabled
|
|
&& chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [ruleIdx = %d, before rule->test()]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
chrono.getMillis(), ruleIdx);
|
|
|
|
//printf("Testing AI Faction # %d RULE Name[%s]\n",aiInterface->getFactionIndex(),rule->getName().c_str());
|
|
|
|
// Test to see if AI can execute rule e.g. is there a worker available to for harvesting wood?
|
|
if (rule->test()) {
|
|
if (outputAIBehaviourToConsole())
|
|
printf
|
|
("\n\nYYYYY Executing AI Faction # %d RULE Name[%s]\n\n",
|
|
aiInterface->getFactionIndex(),
|
|
rule->getName().c_str());
|
|
|
|
aiInterface->printLog(3,
|
|
intToStr(1000 *
|
|
aiInterface->getTimer() /
|
|
GameConstants::updateFps) +
|
|
": Executing rule: " +
|
|
rule->getName() + '\n');
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [ruleIdx = %d, before rule->execute() [%s]]\n",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__, chrono.getMillis(),
|
|
ruleIdx,
|
|
rule->getName().c_str());
|
|
// Execute the rule.
|
|
rule->execute();
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [ruleIdx = %d, after rule->execute() [%s]]\n",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__, chrono.getMillis(),
|
|
ruleIdx,
|
|
rule->getName().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [END]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
chrono.getMillis());
|
|
}
|
|
|
|
|
|
// ==================== state requests ====================
|
|
|
|
int
|
|
Ai::getCountOfType(const UnitType * ut) {
|
|
int
|
|
count = 0;
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
if (ut == aiInterface->getMyUnit(i)->getType()) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
int
|
|
Ai::getCountOfClass(UnitClass uc,
|
|
UnitClass * additionalUnitClassToExcludeFromCount) {
|
|
int
|
|
count = 0;
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
if (aiInterface->getMyUnit(i)->getType()->isOfClass(uc)) {
|
|
// Skip unit if it ALSO contains the exclusion unit class type
|
|
if (additionalUnitClassToExcludeFromCount != NULL) {
|
|
if (aiInterface->getMyUnit(i)->getType()->
|
|
isOfClass(*additionalUnitClassToExcludeFromCount)) {
|
|
continue;
|
|
}
|
|
}
|
|
++count;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
float
|
|
Ai::getRatioOfClass(UnitClass uc,
|
|
UnitClass * additionalUnitClassToExcludeFromCount) {
|
|
if (aiInterface->getMyUnitCount() == 0) {
|
|
return 0;
|
|
} else {
|
|
//return static_cast<float>(getCountOfClass(uc,additionalUnitClassToExcludeFromCount)) / aiInterface->getMyUnitCount();
|
|
return truncateDecimal < float >(static_cast <
|
|
float
|
|
>(getCountOfClass
|
|
(uc,
|
|
additionalUnitClassToExcludeFromCount))
|
|
/ aiInterface->getMyUnitCount(),
|
|
6);
|
|
}
|
|
}
|
|
|
|
const ResourceType *
|
|
Ai::getNeededResource(int unitIndex) {
|
|
int
|
|
amount = INT_MAX;
|
|
const ResourceType *
|
|
neededResource = NULL;
|
|
const TechTree *
|
|
tt = aiInterface->getTechTree();
|
|
const Unit *
|
|
unit = aiInterface->getMyUnit(unitIndex);
|
|
|
|
for (int i = 0; i < tt->getResourceTypeCount(); ++i) {
|
|
const ResourceType *
|
|
rt = tt->getResourceType(i);
|
|
const Resource *
|
|
r = aiInterface->getResource(rt);
|
|
|
|
if (rt->getClass() != rcStatic && rt->getClass() != rcConsumable) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"Examining resource [%s] amount [%d] (previous amount [%d]",
|
|
rt->getName().c_str(), r->getAmount(), amount);
|
|
aiInterface->printLog(3, szBuf);
|
|
}
|
|
|
|
if (rt->getClass() != rcStatic && rt->getClass() != rcConsumable
|
|
&& r->getAmount() < amount) {
|
|
|
|
// Only have up to x units going for this resource so we can focus
|
|
// on other needed resources for other units
|
|
const int
|
|
maxUnitsToHarvestResource = 5;
|
|
|
|
vector < int >
|
|
unitsGettingResource = findUnitsHarvestingResourceType(rt);
|
|
if ((int) unitsGettingResource.size() <=
|
|
maxUnitsToHarvestResource) {
|
|
// Now MAKE SURE the unit has a harvest command for this resource
|
|
// AND that the resource is within eye-sight to avoid units
|
|
// standing around doing nothing.
|
|
const HarvestCommandType *
|
|
hct =
|
|
unit->getType()->getFirstHarvestCommand(rt,
|
|
unit->
|
|
getFaction());
|
|
Vec2i
|
|
resPos;
|
|
if (hct != NULL
|
|
&& aiInterface->getNearestSightedResource(rt,
|
|
aiInterface->
|
|
getHomeLocation
|
|
(), resPos,
|
|
false)) {
|
|
amount = r->getAmount();
|
|
neededResource = rt;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"Unit [%d - %s] looking for resources (not static or consumable)",
|
|
unit->getId(), unit->getType()->getName(false).c_str());
|
|
aiInterface->printLog(3, szBuf);
|
|
snprintf(szBuf, 8096, "[resource type count %d] Needed resource [%s].",
|
|
tt->getResourceTypeCount(),
|
|
(neededResource !=
|
|
NULL ? neededResource->getName().c_str() : "<none>"));
|
|
aiInterface->printLog(3, szBuf);
|
|
|
|
return neededResource;
|
|
}
|
|
|
|
bool
|
|
Ai::beingAttacked(Vec2i & pos, Field & field, int radius) {
|
|
const Unit *
|
|
enemy = aiInterface->getFirstOnSightEnemyUnit(pos, field, radius);
|
|
return (enemy != NULL);
|
|
}
|
|
|
|
bool
|
|
Ai::isStableBase() {
|
|
UnitClass
|
|
ucWorkerType = ucWorker;
|
|
if (getCountOfClass(ucWarrior, &ucWorkerType) > minWarriors) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"Base is stable [minWarriors = %d found = %d]",
|
|
minWarriors, ucWorkerType);
|
|
aiInterface->printLog(4, szBuf);
|
|
|
|
return true;
|
|
} else {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"Base is NOT stable [minWarriors = %d found = %d]",
|
|
minWarriors, ucWorkerType);
|
|
aiInterface->printLog(4, szBuf);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Ai::findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly) {
|
|
vector < int >
|
|
units;
|
|
|
|
*unitIndex = -1;
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
const Unit *
|
|
unit = aiInterface->getMyUnit(i);
|
|
if (unit->getType()->isCommandable()
|
|
&& unit->getType()->hasCommandClass(ability)) {
|
|
if (!idleOnly || !unit->anyCommand()
|
|
|| unit->getCurrCommand()->getCommandType()->
|
|
getClass() == ccStop) {
|
|
units.push_back(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (units.empty()) {
|
|
return false;
|
|
} else {
|
|
*unitIndex = units[random.randRange(0, (int) units.size() - 1)];
|
|
return true;
|
|
}
|
|
}
|
|
|
|
vector < int >
|
|
Ai::findUnitsHarvestingResourceType(const ResourceType * rt) {
|
|
vector < int >
|
|
units;
|
|
|
|
Map *
|
|
map = aiInterface->getMap();
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
const Unit *
|
|
unit = aiInterface->getMyUnit(i);
|
|
if (unit->getType()->isCommandable()) {
|
|
if (unit->getType()->hasCommandClass(ccHarvest)) {
|
|
if (unit->anyCommand()
|
|
&& unit->getCurrCommand()->getCommandType()->
|
|
getClass() == ccHarvest) {
|
|
Command *
|
|
command = unit->getCurrCommand();
|
|
const HarvestCommandType *
|
|
hct = dynamic_cast <const
|
|
HarvestCommandType *>(command->getCommandType());
|
|
if (hct != NULL) {
|
|
const Vec2i
|
|
unitTargetPos = unit->getTargetPos();
|
|
SurfaceCell *
|
|
sc =
|
|
map->
|
|
getSurfaceCell(Map::
|
|
toSurfCoords(unitTargetPos));
|
|
Resource *
|
|
r = sc->getResource();
|
|
if (r != NULL && r->getType() == rt) {
|
|
units.push_back(i);
|
|
}
|
|
}
|
|
}
|
|
} else if (unit->getType()->hasCommandClass(ccProduce)) {
|
|
if (unit->anyCommand()
|
|
&& unit->getCurrCommand()->getCommandType()->
|
|
getClass() == ccProduce) {
|
|
Command *
|
|
command = unit->getCurrCommand();
|
|
const ProduceCommandType *
|
|
pct = dynamic_cast <const
|
|
ProduceCommandType *>(command->getCommandType());
|
|
if (pct != NULL) {
|
|
const UnitType *
|
|
ut = pct->getProducedUnit();
|
|
if (ut != NULL) {
|
|
const Resource *
|
|
r = ut->getCost(rt);
|
|
if (r != NULL) {
|
|
if (r != NULL && r->getAmount() < 0) {
|
|
units.push_back(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (unit->getType()->hasCommandClass(ccBuild)) {
|
|
if (unit->anyCommand()
|
|
&& unit->getCurrCommand()->getCommandType()->
|
|
getClass() == ccBuild) {
|
|
Command *
|
|
command = unit->getCurrCommand();
|
|
const BuildCommandType *
|
|
bct = dynamic_cast <const
|
|
BuildCommandType *>(command->getCommandType());
|
|
if (bct != NULL) {
|
|
for (int j = 0; j < bct->getBuildingCount(); ++j) {
|
|
const UnitType *
|
|
ut = bct->getBuilding(j);
|
|
if (ut != NULL) {
|
|
const Resource *
|
|
r = ut->getCost(rt);
|
|
if (r != NULL) {
|
|
if (r != NULL && r->getAmount() < 0) {
|
|
units.push_back(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return units;
|
|
}
|
|
|
|
//vector<int> Ai::findUnitsDoingCommand(CommandClass currentCommand) {
|
|
// vector<int> units;
|
|
//
|
|
// for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
// const Unit *unit= aiInterface->getMyUnit(i);
|
|
// if(unit->getType()->isCommandable() && unit->getType()->hasCommandClass(currentCommand)) {
|
|
// if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == currentCommand) {
|
|
// units.push_back(i);
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// return units;
|
|
//}
|
|
|
|
bool
|
|
Ai::findAbleUnit(int *unitIndex, CommandClass ability,
|
|
CommandClass currentCommand) {
|
|
vector < int >
|
|
units;
|
|
|
|
*unitIndex = -1;
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
const Unit *
|
|
unit = aiInterface->getMyUnit(i);
|
|
if (unit->getType()->isCommandable()
|
|
&& unit->getType()->hasCommandClass(ability)) {
|
|
if (unit->anyCommand()
|
|
&& unit->getCurrCommand()->getCommandType()->
|
|
getClass() == currentCommand) {
|
|
units.push_back(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (units.empty()) {
|
|
return false;
|
|
} else {
|
|
*unitIndex = units[random.randRange(0, (int) units.size() - 1)];
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Ai::findPosForBuilding(const UnitType * building,
|
|
const Vec2i & searchPos, Vec2i & outPos) {
|
|
|
|
for (int currRadius = 0; currRadius < maxBuildRadius; ++currRadius) {
|
|
for (int i = searchPos.x - currRadius; i < searchPos.x + currRadius;
|
|
++i) {
|
|
for (int j = searchPos.y - currRadius;
|
|
j < searchPos.y + currRadius; ++j) {
|
|
outPos = Vec2i(i, j);
|
|
if (aiInterface->
|
|
isFreeCells(outPos - Vec2i(minBuildSpacing),
|
|
building->getAiBuildSize() +
|
|
minBuildSpacing * 2, fLand)) {
|
|
int
|
|
aiBuildSizeDiff =
|
|
building->getAiBuildSize() - building->getSize();
|
|
if (aiBuildSizeDiff > 0) {
|
|
int
|
|
halfSize = aiBuildSizeDiff / 2;
|
|
outPos.x += halfSize;
|
|
outPos.y += halfSize;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
// ==================== tasks ====================
|
|
|
|
void
|
|
Ai::addTask(const Task * task) {
|
|
tasks.push_back(task);
|
|
aiInterface->printLog(2, "Task added: " + task->toString());
|
|
}
|
|
|
|
void
|
|
Ai::addPriorityTask(const Task * task) {
|
|
deleteValues(tasks.begin(), tasks.end());
|
|
tasks.clear();
|
|
|
|
tasks.push_back(task);
|
|
aiInterface->printLog(2, "Priority Task added: " + task->toString());
|
|
}
|
|
|
|
bool
|
|
Ai::anyTask() {
|
|
return !tasks.empty();
|
|
}
|
|
|
|
const Task *
|
|
Ai::getTask() const {
|
|
if (tasks.empty()) {
|
|
return NULL;
|
|
} else {
|
|
return tasks.front();
|
|
}
|
|
}
|
|
|
|
void
|
|
Ai::removeTask(const Task * task) {
|
|
aiInterface->printLog(2, "Task removed: " + task->toString());
|
|
tasks.remove(task);
|
|
delete
|
|
task;
|
|
}
|
|
|
|
void
|
|
Ai::retryTask(const Task * task) {
|
|
tasks.remove(task);
|
|
tasks.push_back(task);
|
|
}
|
|
// ==================== expansions ====================
|
|
|
|
void
|
|
Ai::addExpansion(const Vec2i & pos) {
|
|
|
|
//check if there is a nearby expansion
|
|
for (Positions::iterator it = expansionPositions.begin();
|
|
it != expansionPositions.end(); ++it) {
|
|
if ((*it).dist(pos) < villageRadius) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
//add expansion
|
|
expansionPositions.push_front(pos);
|
|
|
|
//remove expansion if queue is list is full
|
|
if ((int) expansionPositions.size() > maxExpansions) {
|
|
expansionPositions.pop_back();
|
|
}
|
|
}
|
|
|
|
Vec2i
|
|
Ai::getRandomHomePosition() {
|
|
|
|
if (expansionPositions.empty() || random.randRange(0, 1) == 0) {
|
|
return aiInterface->getHomeLocation();
|
|
}
|
|
|
|
return expansionPositions[random.
|
|
randRange(0,
|
|
(int) expansionPositions.size() -
|
|
1)];
|
|
}
|
|
|
|
// ==================== actions ====================
|
|
|
|
void
|
|
Ai::sendScoutPatrol() {
|
|
|
|
Vec2i
|
|
pos;
|
|
int
|
|
unit;
|
|
bool
|
|
possibleTargetFound = false;
|
|
|
|
bool
|
|
ultraResourceAttack = (aiInterface->getControlType() == ctCpuUltra
|
|
|| aiInterface->getControlType() ==
|
|
ctNetworkCpuUltra)
|
|
&& random.randRange(0, 2) == 1;
|
|
bool
|
|
megaResourceAttack = (aiInterface->getControlType() == ctCpuZeta
|
|
|| aiInterface->getControlType() ==
|
|
ctNetworkCpuZeta)
|
|
&& random.randRange(0, 1) == 1;
|
|
|
|
if (megaResourceAttack || ultraResourceAttack) {
|
|
Map *
|
|
map = aiInterface->getMap();
|
|
|
|
const TechTree *
|
|
tt = aiInterface->getTechTree();
|
|
const ResourceType *
|
|
rt = tt->getResourceType(0);
|
|
int
|
|
tryCount = 0;
|
|
int
|
|
height = map->getH();
|
|
int
|
|
width = map->getW();
|
|
|
|
for (int i = 0; i < tt->getResourceTypeCount(); ++i) {
|
|
const ResourceType *
|
|
rt_ = tt->getResourceType(i);
|
|
//const Resource *r= aiInterface->getResource(rt);
|
|
|
|
if (rt_->getClass() == rcTech) {
|
|
rt = rt_;
|
|
break;
|
|
}
|
|
}
|
|
//printf("looking for resource %s\n",rt->getName().c_str());
|
|
while (possibleTargetFound == false) {
|
|
tryCount++;
|
|
if (tryCount == 4) {
|
|
//printf("no target found\n");
|
|
break;
|
|
}
|
|
pos =
|
|
Vec2i(random.randRange(2, width - 2),
|
|
random.randRange(2, height - 2));
|
|
if (map->isInside(pos)
|
|
&& map->isInsideSurface(map->toSurfCoords(pos))) {
|
|
//printf("is inside map\n");
|
|
// find first resource in this area
|
|
Vec2i
|
|
resPos;
|
|
if (aiInterface->
|
|
isResourceInRegion(pos, rt, resPos,
|
|
scoutResourceRange)) {
|
|
// found a possible target.
|
|
pos = resPos;
|
|
//printf("lets try the new target\n");
|
|
possibleTargetFound = true;
|
|
break;
|
|
}
|
|
}
|
|
//else printf("is outside map\n");
|
|
}
|
|
}
|
|
|
|
std::vector < Vec2i > warningEnemyList =
|
|
aiInterface->getEnemyWarningPositionList();
|
|
if ((possibleTargetFound == false)
|
|
&& (warningEnemyList.empty() == false)) {
|
|
//for(int i = (int)warningEnemyList.size() - 1; i <= 0; --i) {
|
|
//Vec2i &checkPos = warningEnemyList[i];
|
|
Vec2i & checkPos = warningEnemyList[0];
|
|
if (random.randRange(0, 1) == 1) {
|
|
pos = checkPos;
|
|
possibleTargetFound = true;
|
|
warningEnemyList.clear();
|
|
} else {
|
|
aiInterface->removeEnemyWarningPositionFromList(checkPos);
|
|
}
|
|
//break;
|
|
//}
|
|
}
|
|
|
|
if (possibleTargetFound == false) {
|
|
startLoc = (startLoc + 1) % aiInterface->getMapMaxPlayers();
|
|
pos = aiInterface->getStartLocation(startLoc);
|
|
//printf("normal target used\n");
|
|
}
|
|
|
|
if (aiInterface->getHomeLocation() != pos) {
|
|
if (findAbleUnit(&unit, ccAttack, false)) {
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugSystem).enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d]\n", __FILE__,
|
|
__FUNCTION__, __LINE__);
|
|
|
|
aiInterface->giveCommand(unit, ccAttack, pos);
|
|
aiInterface->printLog(2,
|
|
"Scout patrol sent to: " +
|
|
intToStr(pos.x) + "," +
|
|
intToStr(pos.y) + "\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
Ai::massiveAttack(const Vec2i & pos, Field field, bool ultraAttack) {
|
|
int
|
|
producerWarriorCount = 0;
|
|
int
|
|
maxProducerWarriors = random.randRange(1, 11);
|
|
int
|
|
unitCount = aiInterface->getMyUnitCount();
|
|
int
|
|
unitGroupCommandId = -1;
|
|
|
|
int
|
|
attackerWorkersHarvestingCount = 0;
|
|
for (int i = 0; i < unitCount; ++i) {
|
|
bool
|
|
isWarrior = false;
|
|
bool
|
|
productionInProgress = false;
|
|
const Unit *
|
|
unit = aiInterface->getMyUnit(i);
|
|
const AttackCommandType *
|
|
act = unit->getType()->getFirstAttackCommand(field);
|
|
|
|
if (aiInterface->getControlType() == ctCpuZeta ||
|
|
aiInterface->getControlType() == ctNetworkCpuZeta) {
|
|
if (producerWarriorCount > maxProducerWarriors) {
|
|
if (unit->getCommandSize() > 0 &&
|
|
unit->getCurrCommand()->getCommandType() != NULL
|
|
&& (unit->getCurrCommand()->getCommandType()->
|
|
getClass() == ccBuild
|
|
|| unit->getCurrCommand()->getCommandType()->
|
|
getClass() == ccMorph
|
|
|| unit->getCurrCommand()->getCommandType()->
|
|
getClass() == ccProduce)) {
|
|
productionInProgress = true;
|
|
isWarrior = false;
|
|
producerWarriorCount++;
|
|
} else {
|
|
isWarrior =
|
|
!unit->getType()->hasCommandClass(ccHarvest);
|
|
}
|
|
|
|
} else {
|
|
isWarrior = !unit->getType()->hasCommandClass(ccHarvest)
|
|
&& !unit->getType()->hasCommandClass(ccProduce);
|
|
}
|
|
} else {
|
|
isWarrior = !unit->getType()->hasCommandClass(ccHarvest)
|
|
&& !unit->getType()->hasCommandClass(ccProduce);
|
|
}
|
|
|
|
bool
|
|
alreadyAttacking =
|
|
(unit->getCurrSkill()->getClass() == scAttack);
|
|
|
|
bool
|
|
unitSignalledToAttack = false;
|
|
if (alreadyAttacking == false
|
|
&& unit->getType()->hasSkillClass(scAttack)
|
|
&& (aiInterface->getControlType() == ctCpuUltra
|
|
|| aiInterface->getControlType() == ctCpuZeta
|
|
|| aiInterface->getControlType() == ctNetworkCpuUltra
|
|
|| aiInterface->getControlType() == ctNetworkCpuZeta)) {
|
|
//printf("~~~~~~~~ Unit [%s - %d] checking if unit is being attacked\n",unit->getFullName().c_str(),unit->getId());
|
|
|
|
std::pair < bool, Unit * >beingAttacked =
|
|
aiInterface->getWorld()->getUnitUpdater()->
|
|
unitBeingAttacked(unit);
|
|
if (beingAttacked.first == true) {
|
|
Unit *
|
|
enemy = beingAttacked.second;
|
|
const AttackCommandType *
|
|
act_forenemy =
|
|
unit->getType()->getFirstAttackCommand(enemy->
|
|
getCurrField());
|
|
|
|
//printf("~~~~~~~~ Unit [%s - %d] attacked by enemy [%s - %d] act_forenemy [%p] enemy->getCurrField() = %d\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId(),act_forenemy,enemy->getCurrField());
|
|
|
|
if (act_forenemy != NULL) {
|
|
bool
|
|
shouldAttack = true;
|
|
if (unit->getType()->hasSkillClass(scHarvest)) {
|
|
shouldAttack =
|
|
(attackerWorkersHarvestingCount >
|
|
minWorkerAttackersHarvesting);
|
|
if (shouldAttack == false) {
|
|
attackerWorkersHarvestingCount++;
|
|
}
|
|
}
|
|
if (shouldAttack) {
|
|
if (unitGroupCommandId == -1) {
|
|
unitGroupCommandId =
|
|
aiInterface->getWorld()->
|
|
getNextCommandGroupId();
|
|
}
|
|
|
|
aiInterface->giveCommand(i, act_forenemy,
|
|
beingAttacked.second->
|
|
getPos(),
|
|
unitGroupCommandId);
|
|
unitSignalledToAttack = true;
|
|
}
|
|
} else {
|
|
const AttackStoppedCommandType *
|
|
asct_forenemy =
|
|
unit->getType()->
|
|
getFirstAttackStoppedCommand(enemy->getCurrField());
|
|
//printf("~~~~~~~~ Unit [%s - %d] found enemy [%s - %d] asct_forenemy [%p] enemy->getCurrField() = %d\n",unit->getFullName().c_str(),unit->getId(),enemy->getFullName().c_str(),enemy->getId(),asct_forenemy,enemy->getCurrField());
|
|
if (asct_forenemy != NULL) {
|
|
bool
|
|
shouldAttack = true;
|
|
if (unit->getType()->hasSkillClass(scHarvest)) {
|
|
shouldAttack =
|
|
(attackerWorkersHarvestingCount >
|
|
minWorkerAttackersHarvesting);
|
|
if (shouldAttack == false) {
|
|
attackerWorkersHarvestingCount++;
|
|
}
|
|
}
|
|
if (shouldAttack) {
|
|
// printf("~~~~~~~~ Unit [%s - %d] WILL AttackStoppedCommand [%s - %d]\n", unit->getFullName().c_str(),
|
|
// unit->getId(), enemy->getFullName().c_str(), enemy->getId());
|
|
|
|
if (unitGroupCommandId == -1) {
|
|
unitGroupCommandId =
|
|
aiInterface->getWorld()->
|
|
getNextCommandGroupId();
|
|
}
|
|
|
|
aiInterface->giveCommand(i, asct_forenemy,
|
|
beingAttacked.second->
|
|
getCenteredPos(),
|
|
unitGroupCommandId);
|
|
unitSignalledToAttack = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (alreadyAttacking == false && act != NULL
|
|
&& (ultraAttack || isWarrior) && unitSignalledToAttack == false) {
|
|
bool
|
|
shouldAttack = true;
|
|
if (unit->getType()->hasSkillClass(scHarvest)) {
|
|
shouldAttack =
|
|
(attackerWorkersHarvestingCount >
|
|
minWorkerAttackersHarvesting);
|
|
if (shouldAttack == false) {
|
|
attackerWorkersHarvestingCount++;
|
|
}
|
|
}
|
|
|
|
// Zeta CPU does not send ( far away ) units which are currently producing something
|
|
if (aiInterface->getControlType() == ctCpuZeta
|
|
|| aiInterface->getControlType() == ctNetworkCpuZeta) {
|
|
if (!isWarrior) {
|
|
if (!productionInProgress) {
|
|
shouldAttack = false;
|
|
//printf("no attack \n ");
|
|
}
|
|
}
|
|
}
|
|
if (shouldAttack) {
|
|
if (unitGroupCommandId == -1) {
|
|
unitGroupCommandId =
|
|
aiInterface->getWorld()->getNextCommandGroupId();
|
|
}
|
|
|
|
aiInterface->giveCommand(i, act, pos, unitGroupCommandId);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aiInterface->getControlType() == ctCpuEasy ||
|
|
aiInterface->getControlType() == ctNetworkCpuEasy) {
|
|
minWarriors += minMinWarriorsExpandCpuEasy;
|
|
} else if (aiInterface->getControlType() == ctCpuZeta ||
|
|
aiInterface->getControlType() == ctNetworkCpuZeta) {
|
|
minWarriors += minMinWarriorsExpandCpuZeta;
|
|
if (minWarriors > maxMinWarriors - 1 || randomMinWarriorsReached) {
|
|
randomMinWarriorsReached = true;
|
|
minWarriors =
|
|
random.randRange(maxMinWarriors - 10, maxMinWarriors * 2);
|
|
}
|
|
} else if (minWarriors < maxMinWarriors) {
|
|
if (aiInterface->getControlType() == ctCpuUltra ||
|
|
aiInterface->getControlType() == ctNetworkCpuUltra) {
|
|
minWarriors += minMinWarriorsExpandCpuUltra;
|
|
} else {
|
|
minWarriors += minMinWarriorsExpandCpuNormal;
|
|
}
|
|
}
|
|
aiInterface->printLog(2,
|
|
"Massive attack to pos: " + intToStr(pos.x) +
|
|
", " + intToStr(pos.y) + "\n");
|
|
}
|
|
|
|
void
|
|
Ai::returnBase(int unitIndex) {
|
|
Vec2i
|
|
pos;
|
|
//std::pair<CommandResult,string> r(crFailUndefined,"");
|
|
//aiInterface->getFactionIndex();
|
|
pos = Vec2i(random.randRange(-villageRadius, villageRadius),
|
|
random.randRange(-villageRadius, villageRadius)) +
|
|
getRandomHomePosition();
|
|
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d]\n", __FILE__,
|
|
__FUNCTION__, __LINE__);
|
|
//r= aiInterface->giveCommand(unitIndex, ccMove, pos);
|
|
aiInterface->giveCommand(unitIndex, ccMove, pos);
|
|
|
|
//aiInterface->printLog(1, "Order return to base pos:" + intToStr(pos.x)+", "+intToStr(pos.y)+": "+rrToStr(r)+"\n");
|
|
}
|
|
|
|
void
|
|
Ai::harvest(int unitIndex) {
|
|
const ResourceType *
|
|
rt = getNeededResource(unitIndex);
|
|
if (rt != NULL) {
|
|
const HarvestCommandType *
|
|
hct =
|
|
aiInterface->getMyUnit(unitIndex)->getType()->
|
|
getFirstHarvestCommand(rt,
|
|
aiInterface->getMyUnit(unitIndex)->
|
|
getFaction());
|
|
|
|
Vec2i
|
|
resPos;
|
|
if (hct != NULL
|
|
&& aiInterface->getNearestSightedResource(rt,
|
|
aiInterface->
|
|
getHomeLocation(),
|
|
resPos, false)) {
|
|
resPos =
|
|
resPos + Vec2i(random.randRange(-2, 2),
|
|
random.randRange(-2, 2));
|
|
aiInterface->giveCommand(unitIndex, hct, resPos, -1);
|
|
//aiInterface->printLog(4, "Order harvest pos:" + intToStr(resPos.x)+", "+intToStr(resPos.y)+": "+rrToStr(r)+"\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
Ai::haveBlockedUnits() {
|
|
Chrono
|
|
chrono;
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled)
|
|
chrono.start();
|
|
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [START]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
chrono.getMillis());
|
|
|
|
int
|
|
unitCount = aiInterface->getMyUnitCount();
|
|
Map *
|
|
map = aiInterface->getMap();
|
|
//If there is no close store
|
|
for (int j = 0; j < unitCount; ++j) {
|
|
const Unit *
|
|
u = aiInterface->getMyUnit(j);
|
|
const UnitType *
|
|
ut = u->getType();
|
|
|
|
// If this building is a store
|
|
if (u->isAlive() && ut->isMobile() && u->getPath() != NULL
|
|
&& (u->getPath()->isBlocked()
|
|
|| u->getPath()->getBlockCount())) {
|
|
Vec2i
|
|
unitPos = u->getPosNotThreadSafe();
|
|
|
|
//printf("#1 AI found blocked unit [%d - %s]\n",u->getId(),u->getFullName().c_str());
|
|
|
|
int
|
|
failureCount = 0;
|
|
int
|
|
cellCount = 0;
|
|
|
|
for (int i = -1; i <= 1; ++i) {
|
|
for (int j = -1; j <= 1; ++j) {
|
|
Vec2i
|
|
pos = unitPos + Vec2i(i, j);
|
|
if (map->isInside(pos)
|
|
&& map->isInsideSurface(map->toSurfCoords(pos))) {
|
|
if (pos != unitPos) {
|
|
bool
|
|
canUnitMoveToCell =
|
|
map->aproxCanMove(u, unitPos, pos);
|
|
if (canUnitMoveToCell == false) {
|
|
failureCount++;
|
|
}
|
|
cellCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bool
|
|
unitImmediatelyBlocked = (failureCount == cellCount);
|
|
//printf("#1 unitImmediatelyBlocked = %d, failureCount = %d, cellCount = %d\n",unitImmediatelyBlocked,failureCount,cellCount);
|
|
|
|
if (unitImmediatelyBlocked) {
|
|
//printf("#1 AI unit IS BLOCKED [%d - %s]\n",u->getId(),u->getFullName().c_str());
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [START]\n",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__, chrono.getMillis());
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [START]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
chrono.getMillis());
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
Ai::getAdjacentUnits(std::map < float, std::map < int,
|
|
const Unit * > >&signalAdjacentUnits,
|
|
const Unit * unit) {
|
|
//printf("In getAdjacentUnits...\n");
|
|
|
|
bool
|
|
result = false;
|
|
Map *
|
|
map = aiInterface->getMap();
|
|
Vec2i
|
|
unitPos = unit->getPosNotThreadSafe();
|
|
for (int i = -1; i <= 1; ++i) {
|
|
for (int j = -1; j <= 1; ++j) {
|
|
Vec2i
|
|
pos = unitPos + Vec2i(i, j);
|
|
if (map->isInside(pos)
|
|
&& map->isInsideSurface(map->toSurfCoords(pos))) {
|
|
if (pos != unitPos) {
|
|
Unit *
|
|
adjacentUnit =
|
|
map->getCell(pos)->getUnit(unit->getCurrField());
|
|
if (adjacentUnit != NULL
|
|
&& adjacentUnit->getFactionIndex() ==
|
|
unit->getFactionIndex()) {
|
|
if (adjacentUnit->getType()->isMobile()
|
|
&& adjacentUnit->getPath() != NULL) {
|
|
//signalAdjacentUnits.push_back(adjacentUnit);
|
|
float
|
|
dist = unitPos.dist(adjacentUnit->getPos());
|
|
|
|
std::map < float,
|
|
std::map < int, const Unit *> >::iterator
|
|
iterFind1 = signalAdjacentUnits.find(dist);
|
|
if (iterFind1 == signalAdjacentUnits.end()) {
|
|
signalAdjacentUnits[dist][adjacentUnit->
|
|
getId()] =
|
|
adjacentUnit;
|
|
|
|
getAdjacentUnits(signalAdjacentUnits,
|
|
adjacentUnit);
|
|
result = true;
|
|
} else {
|
|
std::map < int, const Unit *>::iterator
|
|
iterFind2 =
|
|
iterFind1->second.find(adjacentUnit->
|
|
getId());
|
|
if (iterFind2 == iterFind1->second.end()) {
|
|
signalAdjacentUnits[dist][adjacentUnit->
|
|
getId()] =
|
|
adjacentUnit;
|
|
getAdjacentUnits(signalAdjacentUnits,
|
|
adjacentUnit);
|
|
result = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void
|
|
Ai::unblockUnits() {
|
|
Chrono
|
|
chrono;
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled)
|
|
chrono.start();
|
|
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [START]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
chrono.getMillis());
|
|
|
|
int
|
|
unitCount = aiInterface->getMyUnitCount();
|
|
Map *
|
|
map = aiInterface->getMap();
|
|
// Find blocked units and move surrounding units out of the way
|
|
std::map < float,
|
|
std::map < int, const Unit *> >
|
|
signalAdjacentUnits;
|
|
for (int idx = 0; idx < unitCount; ++idx) {
|
|
const Unit *
|
|
u = aiInterface->getMyUnit(idx);
|
|
const UnitType *
|
|
ut = u->getType();
|
|
|
|
// If this building is a store
|
|
if (u->isAlive() && ut->isMobile() && u->getPath() != NULL
|
|
&& (u->getPath()->isBlocked()
|
|
|| u->getPath()->getBlockCount())) {
|
|
Vec2i
|
|
unitPos = u->getPosNotThreadSafe();
|
|
|
|
//printf("#2 AI found blocked unit [%d - %s]\n",u->getId(),u->getFullName().c_str());
|
|
|
|
//int failureCount = 0;
|
|
//int cellCount = 0;
|
|
|
|
for (int i = -1; i <= 1; ++i) {
|
|
for (int j = -1; j <= 1; ++j) {
|
|
Vec2i
|
|
pos = unitPos + Vec2i(i, j);
|
|
if (map->isInside(pos)
|
|
&& map->isInsideSurface(map->toSurfCoords(pos))) {
|
|
if (pos != unitPos) {
|
|
bool
|
|
canUnitMoveToCell =
|
|
map->aproxCanMove(u, unitPos, pos);
|
|
if (canUnitMoveToCell == false) {
|
|
//failureCount++;
|
|
getAdjacentUnits(signalAdjacentUnits, u);
|
|
}
|
|
//cellCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//bool unitImmediatelyBlocked = (failureCount == cellCount);
|
|
//printf("#2 unitImmediatelyBlocked = %d, failureCount = %d, cellCount = %d, signalAdjacentUnits.size() = %d\n",unitImmediatelyBlocked,failureCount,cellCount,signalAdjacentUnits.size());
|
|
}
|
|
}
|
|
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [START]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
chrono.getMillis());
|
|
|
|
if (signalAdjacentUnits.empty() == false) {
|
|
//printf("#2 AI units ARE BLOCKED about to unblock\n");
|
|
|
|
int
|
|
unitGroupCommandId = -1;
|
|
|
|
for (std::map < float, std::map < int,
|
|
const Unit * > >::reverse_iterator iterMap =
|
|
signalAdjacentUnits.rbegin();
|
|
iterMap != signalAdjacentUnits.rend(); ++iterMap) {
|
|
|
|
for (std::map < int, const Unit * >::iterator iterMap2 =
|
|
iterMap->second.begin();
|
|
iterMap2 != iterMap->second.end(); ++iterMap2) {
|
|
//int idx = iterMap2->first;
|
|
const Unit *
|
|
adjacentUnit = iterMap2->second;
|
|
if (adjacentUnit != NULL
|
|
&& adjacentUnit->getType()->
|
|
getFirstCtOfClass(ccMove) != NULL) {
|
|
const CommandType *
|
|
ct =
|
|
adjacentUnit->getType()->getFirstCtOfClass(ccMove);
|
|
|
|
for (int moveAttempt = 1; moveAttempt <= villageRadius;
|
|
++moveAttempt) {
|
|
Vec2i
|
|
pos =
|
|
Vec2i(random.
|
|
randRange(-villageRadius * 2,
|
|
villageRadius * 2),
|
|
random.randRange(-villageRadius * 2,
|
|
villageRadius * 2)) +
|
|
adjacentUnit->getPosNotThreadSafe();
|
|
|
|
bool
|
|
canUnitMoveToCell =
|
|
map->aproxCanMove(adjacentUnit,
|
|
adjacentUnit->
|
|
getPosNotThreadSafe(), pos);
|
|
if (canUnitMoveToCell == true) {
|
|
|
|
if (ct != NULL) {
|
|
if (unitGroupCommandId == -1) {
|
|
unitGroupCommandId =
|
|
aiInterface->getWorld()->
|
|
getNextCommandGroupId();
|
|
}
|
|
|
|
//std::pair<CommandResult,string> r = aiInterface->giveCommand(adjacentUnit,ct, pos, unitGroupCommandId);
|
|
aiInterface->giveCommand(adjacentUnit, ct,
|
|
pos,
|
|
unitGroupCommandId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
|
|
enabled && chrono.getMillis() > 0)
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
|
|
"In [%s::%s Line: %d] took msecs: %lld [START]\n",
|
|
__FILE__, __FUNCTION__, __LINE__,
|
|
chrono.getMillis());
|
|
}
|
|
|
|
bool
|
|
Ai::outputAIBehaviourToConsole() const {
|
|
return
|
|
false;
|
|
}
|
|
|
|
void
|
|
Ai::saveGame(XmlNode * rootNode) const {
|
|
std::map <
|
|
string,
|
|
string >
|
|
mapTagReplacements;
|
|
XmlNode *
|
|
aiNode = rootNode->addChild("Ai");
|
|
|
|
// AiInterface *aiInterface;
|
|
// AiRules aiRules;
|
|
// int startLoc;
|
|
aiNode->
|
|
addAttribute("startLoc", intToStr(startLoc), mapTagReplacements);
|
|
// bool randomMinWarriorsReached;
|
|
aiNode->
|
|
addAttribute("randomMinWarriorsReached",
|
|
intToStr(randomMinWarriorsReached), mapTagReplacements);
|
|
// Tasks tasks;
|
|
for (Tasks::const_iterator it = tasks.begin(); it != tasks.end();
|
|
++it) {
|
|
(*it)->saveGame(aiNode);
|
|
}
|
|
// Positions expansionPositions;
|
|
for (Positions::const_iterator it = expansionPositions.begin();
|
|
it != expansionPositions.end(); ++it) {
|
|
XmlNode *
|
|
expansionPositionsNode = aiNode->addChild("expansionPositions");
|
|
expansionPositionsNode->addAttribute("pos", (*it).getString(),
|
|
mapTagReplacements);
|
|
}
|
|
|
|
// 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 minMinWarriorsExpandCpuZeta;
|
|
aiNode->addAttribute("minMinWarriorsExpandCpuZeta",
|
|
intToStr(minMinWarriorsExpandCpuZeta),
|
|
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) {
|
|
const XmlNode *
|
|
aiNode = rootNode->getChild("Ai");
|
|
|
|
startLoc = aiNode->getAttribute("startLoc")->getIntValue();
|
|
randomMinWarriorsReached =
|
|
aiNode->getAttribute("randomMinWarriorsReached")->getIntValue() !=
|
|
0;
|
|
|
|
vector < XmlNode * >taskNodeList = aiNode->getChildList("Task");
|
|
for (unsigned int i = 0; i < taskNodeList.size(); ++i) {
|
|
XmlNode *
|
|
taskNode = taskNodeList[i];
|
|
TaskClass
|
|
taskClass =
|
|
static_cast <TaskClass>
|
|
(taskNode->getAttribute("taskClass")->getIntValue());
|
|
switch (taskClass) {
|
|
case tcProduce:
|
|
{
|
|
ProduceTask *
|
|
newTask = ProduceTask::loadGame(taskNode, faction);
|
|
tasks.push_back(newTask);
|
|
}
|
|
break;
|
|
case tcBuild:
|
|
{
|
|
BuildTask *
|
|
newTask = BuildTask::loadGame(taskNode, faction);
|
|
tasks.push_back(newTask);
|
|
}
|
|
break;
|
|
case tcUpgrade:
|
|
{
|
|
UpgradeTask *
|
|
newTask = UpgradeTask::loadGame(taskNode, faction);
|
|
tasks.push_back(newTask);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
vector < XmlNode * >expansionPositionsNodeList =
|
|
aiNode->getChildList("expansionPositions");
|
|
for (unsigned int i = 0; i < expansionPositionsNodeList.size(); ++i) {
|
|
XmlNode *
|
|
expansionPositionsNode = expansionPositionsNodeList[i];
|
|
Vec2i
|
|
pos =
|
|
Vec2i::strToVec2(expansionPositionsNode->getAttribute("pos")->
|
|
getValue());
|
|
expansionPositions.push_back(pos);
|
|
}
|
|
|
|
// 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 minMinWarriorsExpandCpZeta;
|
|
minMinWarriorsExpandCpuZeta =
|
|
aiNode->getAttribute("minMinWarriorsExpandCpuZeta")->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
|