mirror of
https://github.com/glest/glest-source.git
synced 2025-02-24 19:52:25 +01:00
3247 lines
99 KiB
C++
3247 lines
99 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_rule.h"
|
|
|
|
#include <algorithm>
|
|
#include <limits.h>
|
|
|
|
#include "ai.h"
|
|
#include "ai_interface.h"
|
|
#include "unit.h"
|
|
#include "leak_dumper.h"
|
|
|
|
using
|
|
Shared::Graphics::Vec2i;
|
|
|
|
namespace
|
|
Glest {
|
|
namespace
|
|
Game {
|
|
|
|
// =====================================================
|
|
// class AiRule
|
|
// =====================================================
|
|
|
|
AiRule::AiRule(Ai * ai) {
|
|
this->ai = ai;
|
|
}
|
|
|
|
// =====================================================
|
|
// class AiRuleWorkerHarvest
|
|
// =====================================================
|
|
|
|
AiRuleWorkerHarvest::AiRuleWorkerHarvest(Ai * ai) :
|
|
AiRule(ai) {
|
|
stoppedWorkerIndex = -1;
|
|
}
|
|
|
|
bool
|
|
AiRuleWorkerHarvest::test() {
|
|
return ai->findAbleUnit(&stoppedWorkerIndex, ccHarvest, true);
|
|
}
|
|
|
|
void
|
|
AiRuleWorkerHarvest::execute() {
|
|
ai->harvest(stoppedWorkerIndex);
|
|
}
|
|
|
|
// =====================================================
|
|
// class AiRuleRefreshHarvester
|
|
// =====================================================
|
|
|
|
AiRuleRefreshHarvester::AiRuleRefreshHarvester(Ai * ai) :
|
|
AiRule(ai) {
|
|
workerIndex = -1;
|
|
}
|
|
|
|
bool
|
|
AiRuleRefreshHarvester::test() {
|
|
return ai->findAbleUnit(&workerIndex, ccHarvest, ccHarvest);
|
|
}
|
|
|
|
void
|
|
AiRuleRefreshHarvester::execute() {
|
|
ai->harvest(workerIndex);
|
|
}
|
|
|
|
// =====================================================
|
|
// class AiRuleScoutPatrol
|
|
// =====================================================
|
|
|
|
AiRuleScoutPatrol::AiRuleScoutPatrol(Ai * ai) :
|
|
AiRule(ai) {
|
|
}
|
|
|
|
bool
|
|
AiRuleScoutPatrol::test() {
|
|
return ai->isStableBase();
|
|
}
|
|
|
|
void
|
|
AiRuleScoutPatrol::execute() {
|
|
ai->sendScoutPatrol();
|
|
}
|
|
// =====================================================
|
|
// class AiRuleRepair
|
|
// =====================================================
|
|
|
|
AiRuleRepair::AiRuleRepair(Ai * ai) :
|
|
AiRule(ai) {
|
|
damagedUnitIndex = 0;
|
|
damagedUnitIsCastle = false;
|
|
}
|
|
|
|
double
|
|
AiRuleRepair::getMinCastleHpRatio() const {
|
|
return
|
|
0.6;
|
|
}
|
|
|
|
int
|
|
AiRuleRepair::getMinUnitsToRepairCastle() {
|
|
int
|
|
minUnitsRepairingCastle = 7;
|
|
if (ai->getCountOfClass(ucWorker) <= 6) {
|
|
minUnitsRepairingCastle = 1;
|
|
} else if (ai->getCountOfClass(ucWorker) <= 8) {
|
|
minUnitsRepairingCastle = 2;
|
|
} else if (ai->getCountOfClass(ucWorker) <= 10) {
|
|
minUnitsRepairingCastle = 3;
|
|
} else if (ai->getCountOfClass(ucWorker) <= 12) {
|
|
minUnitsRepairingCastle = 5;
|
|
}
|
|
return minUnitsRepairingCastle;
|
|
}
|
|
|
|
bool
|
|
AiRuleRepair::test() {
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
int
|
|
minUnitsRepairingCastle = getMinUnitsToRepairCastle();
|
|
const double
|
|
minCastleHpRatio = getMinCastleHpRatio();
|
|
|
|
// look for a damaged unit and give priority to the factions bases
|
|
// (units that produce workers and store resources)
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
const Unit *
|
|
u = aiInterface->getMyUnit(i);
|
|
//printf("\n\n\n\n!!!!!! Is damaged unit [%d - %s] u->getHpRatio() = %f, hp = %d, mapHp = %d\n",u->getId(),u->getType()->getName().c_str(),u->getHpRatio(),u->getHp(),u->getType()->getTotalMaxHp(u->getTotalUpgrade()));
|
|
if (u->getHpRatio() < 1.f) {
|
|
//printf("\n\n\n\n!!!!!! Is damaged unit [%d - %s] u->getHpRatio() = %f, hp = %d, mapHp = %d\n",u->getId(),u->getType()->getName().c_str(),u->getHpRatio(),u->getHp(),u->getType()->getTotalMaxHp(u->getTotalUpgrade()));
|
|
|
|
bool
|
|
unitCanProduceWorker = false;
|
|
for (int j = 0; unitCanProduceWorker == false &&
|
|
j < u->getType()->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = u->getType()->getCommandType(j);
|
|
|
|
//if the command is produce
|
|
if (ct->getClass() == ccProduce
|
|
|| ct->getClass() == ccMorph) {
|
|
const ProducibleType *
|
|
pt = ct->getProduced();
|
|
if (pt != NULL) {
|
|
const UnitType *
|
|
ut = dynamic_cast <const
|
|
UnitType *>(pt);
|
|
if (ut != NULL
|
|
&& ut->hasCommandClass(ccHarvest) == true
|
|
&& u->getType()->getStoredResourceCount() > 0) {
|
|
//printf("\n\n\n\n!!!!!! found candidate castle unit to repair [%d - %s]\n",u->getId(),u->getType()->getName().c_str());
|
|
unitCanProduceWorker = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (unitCanProduceWorker == true) {
|
|
int
|
|
candidatedamagedUnitIndex = -1;
|
|
int
|
|
unitCountAlreadyRepairingDamagedUnit = 0;
|
|
// Now check if any other unit is able to repair this unit
|
|
for (int i1 = 0; i1 < aiInterface->getMyUnitCount(); ++i1) {
|
|
const Unit *
|
|
u1 = aiInterface->getMyUnit(i1);
|
|
const RepairCommandType *
|
|
rct = static_cast <const
|
|
RepairCommandType *
|
|
>(u1->getType()->getFirstCtOfClass(ccRepair));
|
|
//if(rct) printf("\n\n\n\n^^^^^^^^^^ possible repairer unit [%d - %s] current skill [%d] can reapir damaged unit [%d]\n",u1->getId(),u1->getType()->getName().c_str(),u->getCurrSkill()->getClass(),rct->isRepairableUnitType(u->getType()));
|
|
|
|
if (rct != NULL) {
|
|
//printf("\n\n\n\n^^^^^^^^^^ possible repairer unit [%d - %s] current skill [%d] can repair damaged unit [%d] Castles hp-ratio = %f\n",u1->getId(),u1->getType()->getName().c_str(),u1->getCurrSkill()->getClass(),rct->isRepairableUnitType(u->getType()),u->getHpRatio());
|
|
|
|
if (u1->getCurrSkill()->getClass() == scStop
|
|
|| u1->getCurrSkill()->getClass() == scMove
|
|
|| u->getHpRatio() <= minCastleHpRatio) {
|
|
if (rct->isRepairableUnitType(u->getType())) {
|
|
candidatedamagedUnitIndex = i;
|
|
//return true;
|
|
}
|
|
} else if (u1->getCurrSkill()->getClass() ==
|
|
scRepair) {
|
|
Command *
|
|
cmd = u1->getCurrCommand();
|
|
if (cmd != NULL
|
|
&& cmd->getCommandType()->getClass() ==
|
|
ccRepair) {
|
|
if (cmd->getUnit() != NULL
|
|
&& cmd->getUnit()->getId() ==
|
|
u->getId()) {
|
|
//printf("\n\n\n\n^^^^^^^^^^ unit is ALREADY repairer unit [%d - %s]\n",u1->getId(),u1->getType()->getName().c_str());
|
|
unitCountAlreadyRepairingDamagedUnit++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (candidatedamagedUnitIndex >= 0
|
|
&& unitCountAlreadyRepairingDamagedUnit <
|
|
minUnitsRepairingCastle) {
|
|
//printf("\n\n\n\n^^^^^^^^^^ AI test will repair damaged unit [%d - %s]\n",u->getId(),u->getType()->getName().c_str());
|
|
damagedUnitIndex = candidatedamagedUnitIndex;
|
|
damagedUnitIsCastle = true;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
damagedUnitIsCastle = false;
|
|
damagedUnitIndex = -1;
|
|
// Normal Repair checking
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
const Unit *
|
|
u = aiInterface->getMyUnit(i);
|
|
//printf("\n\n\n\n!!!!!! Is damaged unit [%d - %s] u->getHpRatio() = %f, hp = %d, mapHp = %d\n",u->getId(),u->getType()->getName().c_str(),u->getHpRatio(),u->getHp(),u->getType()->getTotalMaxHp(u->getTotalUpgrade()));
|
|
if (u->getHpRatio() < 1.f) {
|
|
// Now check if any other unit is able to repair this unit
|
|
for (int i1 = 0; i1 < aiInterface->getMyUnitCount(); ++i1) {
|
|
const Unit *
|
|
u1 = aiInterface->getMyUnit(i1);
|
|
const RepairCommandType *
|
|
rct = static_cast <const
|
|
RepairCommandType *
|
|
>(u1->getType()->getFirstCtOfClass(ccRepair));
|
|
//if(rct) printf("\n\n\n\n^^^^^^^^^^ possible repairer unit [%d - %s] current skill [%d] can reapir damaged unit [%d]\n",u1->getId(),u1->getType()->getName().c_str(),u->getCurrSkill()->getClass(),rct->isRepairableUnitType(u->getType()));
|
|
|
|
if (rct != NULL
|
|
&& (u1->getCurrSkill()->getClass() == scStop
|
|
|| u1->getCurrSkill()->getClass() == scMove)) {
|
|
if (rct->isRepairableUnitType(u->getType())) {
|
|
damagedUnitIndex = i;
|
|
//random if return or not so we get different targets from time to time
|
|
if (ai->getRandom()->randRange(0, 1) == 0)
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (damagedUnitIndex != -1) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
AiRuleRepair::execute() {
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
const Unit *
|
|
damagedUnit = aiInterface->getMyUnit(damagedUnitIndex);
|
|
//printf("\n\n\n\n###^^^^^^^^^^ Looking for repairer for damaged unit [%d - %s]\n",damagedUnit->getId(),damagedUnit->getType()->getName().c_str());
|
|
|
|
int
|
|
minUnitsRepairingCastle = getMinUnitsToRepairCastle();
|
|
const double
|
|
minCastleHpRatio = getMinCastleHpRatio();
|
|
|
|
if (minUnitsRepairingCastle > 2) {
|
|
if (damagedUnit->getCurrSkill()->getClass() == scBeBuilt) { // if build is still be build 2 helpers are enough
|
|
minUnitsRepairingCastle = 2;
|
|
}
|
|
|
|
if (!damagedUnitIsCastle) {
|
|
minUnitsRepairingCastle = 2;
|
|
}
|
|
}
|
|
if (aiInterface->getControlType() == ctCpuEasy ||
|
|
aiInterface->getControlType() == ctNetworkCpuEasy) {
|
|
if (!damagedUnitIsCastle) {
|
|
// cpu easy does not repair!
|
|
minUnitsRepairingCastle = 0;
|
|
}
|
|
}
|
|
if (aiInterface->getControlType() == ctCpu ||
|
|
aiInterface->getControlType() == ctNetworkCpu) {
|
|
if (!damagedUnitIsCastle) {
|
|
// cpu does only repair with one unit!
|
|
minUnitsRepairingCastle = 1;
|
|
}
|
|
}
|
|
int
|
|
unitCountAlreadyRepairingDamagedUnit = 0;
|
|
//printf("team %d has damaged unit\n", damagedUnit->getTeam());
|
|
// Now check if any other unit is able to repair this unit
|
|
for (int i1 = 0; i1 < aiInterface->getMyUnitCount(); ++i1) {
|
|
const Unit *
|
|
u1 = aiInterface->getMyUnit(i1);
|
|
const RepairCommandType *
|
|
rct = static_cast <const
|
|
RepairCommandType *
|
|
>(u1->getType()->getFirstCtOfClass(ccRepair));
|
|
//if(rct) printf("\n\n\n\n^^^^^^^^^^ possible repairer unit [%d - %s] current skill [%d] can reapir damaged unit [%d]\n",u1->getId(),u1->getType()->getName().c_str(),u1->getCurrSkill()->getClass(),rct->isRepairableUnitType(u1->getType()));
|
|
Command *
|
|
cmd = u1->getCurrCommand();
|
|
if (cmd != NULL && cmd->getCommandType()->getClass() == ccRepair) {
|
|
//if(cmd->getUnit() != NULL && cmd->getUnit()->getId() == damagedUnit->getId())
|
|
//if(cmd->getUnit() != NULL && cmd->getPos() == damagedUnit->getPosWithCellMapSet())
|
|
|
|
if (rct != NULL) {
|
|
//printf("\n\n\n\n^^^^^^^^^^ possible repairer unit [%d - %s] current skill [%d] can repair damaged unit [%d] Castles hp-ratio = %f\n",u1->getId(),u1->getType()->getName().c_str(),u1->getCurrSkill()->getClass(),rct->isRepairableUnitType(u->getType()),u->getHpRatio());
|
|
|
|
if (((RepairCommandType *) (cmd->getCommandType()))->
|
|
isRepairableUnitType(damagedUnit->getType())) {
|
|
//printf("^^^^test^^^^^^ unit is ALREADY repairer unit [%d - %s]\nminUnitsRepairingCastle=%d\n",u1->getId(), u1->getType()->getName().c_str(), minUnitsRepairingCastle);
|
|
unitCountAlreadyRepairingDamagedUnit++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (unitCountAlreadyRepairingDamagedUnit >= minUnitsRepairingCastle) {
|
|
return;
|
|
}
|
|
|
|
int
|
|
unitGroupCommandId = -1;
|
|
|
|
//find a repairer and issue command
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
const Unit *
|
|
u = aiInterface->getMyUnit(i);
|
|
const RepairCommandType *
|
|
rct = static_cast <const
|
|
RepairCommandType *
|
|
>(u->getType()->getFirstCtOfClass(ccRepair));
|
|
//if(rct) printf("\n\n\n\n^^^^^^^^^^ possible repairer unit [%d - %s] current skill [%d] can reapir damaged unit [%d]\n",u->getId(),u->getType()->getName().c_str(),u->getCurrSkill()->getClass(),rct->isRepairableUnitType(damagedUnit->getType()));
|
|
|
|
if (rct != NULL) {
|
|
//printf("\n\n\n\n^^^^^^^^^^ possible excute repairer unit [%d - %s] current skill [%d] can repair damaged unit [%d] Castles hp-ratio = %f\n",u->getId(),u->getType()->getName().c_str(),u->getCurrSkill()->getClass(),rct->isRepairableUnitType(damagedUnit->getType()),damagedUnit->getHpRatio());
|
|
|
|
if ((u->getCurrSkill()->getClass() == scStop
|
|
|| u->getCurrSkill()->getClass() == scMove
|
|
|| damagedUnit->getHpRatio() <= minCastleHpRatio)) {
|
|
if ((u->getCurrCommand() == NULL
|
|
|| (u->getCurrCommand()->getCommandType()->
|
|
getClass() != ccBuild
|
|
&& u->getCurrCommand()->getCommandType()->
|
|
getClass() != ccProduce))
|
|
&& rct->isRepairableUnitType(damagedUnit->getType())) {
|
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
//printf("\n\n\n\n^^^^^^^^^^ AI execute will repair damaged unit [%d - %s] at pos [%s] cellmapPos [%s] using unit [%d -%s]\n",damagedUnit->getId(),damagedUnit->getType()->getName().c_str(),damagedUnit->getPos().getString().c_str(),damagedUnit->getPosWithCellMapSet().getString().c_str(),u->getId(),u->getType()->getName().c_str());
|
|
|
|
/*
|
|
Map *map= aiInterface->getWorld()->getMap();
|
|
Cell *cell = map->getCell(damagedUnit->getPosWithCellMapSet());
|
|
if(cell != NULL) {
|
|
printf("\n\n\n\n^^^^^^^^^^ cell is ok\n");
|
|
|
|
Unit *cellUnit = cell->getUnit(damagedUnit->getCurrField());
|
|
if(cellUnit != NULL) {
|
|
printf("\n\n\n\n^^^^^^^^^^ cell unit [%d - %s] at pos [%s]\n",cellUnit->getId(),cellUnit->getType()->getName().c_str(),cellUnit->getPos().getString().c_str());
|
|
}
|
|
}
|
|
*/
|
|
|
|
//aiInterface->giveCommand(i, rct, damagedUnit->getPos());
|
|
if (unitCountAlreadyRepairingDamagedUnit <
|
|
minUnitsRepairingCastle) {
|
|
|
|
if (unitGroupCommandId == -1) {
|
|
unitGroupCommandId =
|
|
aiInterface->getWorld()->
|
|
getNextCommandGroupId();
|
|
}
|
|
|
|
aiInterface->giveCommand(i, rct,
|
|
damagedUnit->
|
|
getPosWithCellMapSet(),
|
|
unitGroupCommandId);
|
|
if (aiInterface->isLogLevelEnabled(3) == true)
|
|
aiInterface->printLog(3,
|
|
"Repairing order issued");
|
|
unitCountAlreadyRepairingDamagedUnit++;
|
|
// printf(
|
|
// "^^^^^^^^^^adding one unit to repair ... unitCountAlreadyRepairingDamagedUnit/minUnitsRepairingCastle=%d/%d\n",
|
|
// unitCountAlreadyRepairingDamagedUnit, minUnitsRepairingCastle);
|
|
}
|
|
|
|
if (!damagedUnitIsCastle
|
|
|| unitCountAlreadyRepairingDamagedUnit >=
|
|
minUnitsRepairingCastle) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// =====================================================
|
|
// class AiRuleReturnBase
|
|
// =====================================================
|
|
|
|
AiRuleReturnBase::AiRuleReturnBase(Ai * ai) :
|
|
AiRule(ai) {
|
|
stoppedUnitIndex = -1;
|
|
}
|
|
|
|
bool
|
|
AiRuleReturnBase::test() {
|
|
return ai->findAbleUnit(&stoppedUnitIndex, ccMove, true);
|
|
}
|
|
|
|
void
|
|
AiRuleReturnBase::execute() {
|
|
ai->returnBase(stoppedUnitIndex);
|
|
}
|
|
|
|
// =====================================================
|
|
// class AiRuleMassiveAttack
|
|
// =====================================================
|
|
|
|
AiRuleMassiveAttack::AiRuleMassiveAttack(Ai * ai) :
|
|
AiRule(ai) {
|
|
ultraAttack = false;
|
|
field = fLand;
|
|
}
|
|
|
|
bool
|
|
AiRuleMassiveAttack::test() {
|
|
|
|
if (ai->isStableBase()) {
|
|
ultraAttack = false;
|
|
return ai->beingAttacked(attackPos, field, INT_MAX);
|
|
} else {
|
|
ultraAttack = true;
|
|
return ai->beingAttacked(attackPos, field, baseRadius);
|
|
}
|
|
}
|
|
|
|
void
|
|
AiRuleMassiveAttack::execute() {
|
|
ai->massiveAttack(attackPos, field, ultraAttack);
|
|
}
|
|
// =====================================================
|
|
// class AiRuleAddTasks
|
|
// =====================================================
|
|
|
|
AiRuleAddTasks::AiRuleAddTasks(Ai * ai) :
|
|
AiRule(ai) {
|
|
}
|
|
|
|
bool
|
|
AiRuleAddTasks::test() {
|
|
return !ai->anyTask() || ai->getCountOfClass(ucWorker) < 4;
|
|
}
|
|
|
|
// This function is what triggers the AI to create new units.
|
|
void
|
|
AiRuleAddTasks::execute() {
|
|
int
|
|
buildingCount = ai->getCountOfClass(ucBuilding);
|
|
UnitClass
|
|
ucWorkerType = ucWorker;
|
|
int
|
|
warriorCount = ai->getCountOfClass(ucWarrior, &ucWorkerType);
|
|
int
|
|
workerCount = ai->getCountOfClass(ucWorker);
|
|
int
|
|
upgradeCount = ai->getAiInterface()->getMyUpgradeCount();
|
|
|
|
float
|
|
buildingRatio = ai->getRatioOfClass(ucBuilding);
|
|
float
|
|
warriorRatio = ai->getRatioOfClass(ucWarrior);
|
|
float
|
|
workerRatio = ai->getRatioOfClass(ucWorker);
|
|
|
|
//standard tasks
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("Add a TASK - AiRuleAddTasks adding ProduceTask(ucWorker) workerCount = %d, RULE Name[%s]\n",
|
|
workerCount, this->getName().c_str());
|
|
|
|
//emergency workers
|
|
if (workerCount < 4) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("AAA AiRuleAddTasks adding ProduceTask(ucWorker) workerCount = %d, RULE Name[%s]\n",
|
|
workerCount, this->getName().c_str());
|
|
|
|
ai->addPriorityTask(new ProduceTask(ucWorker));
|
|
}
|
|
// The following rules are specific creation rules for different AI.
|
|
else {
|
|
if (ai->getAiInterface()->getControlType() == ctCpuZeta ||
|
|
ai->getAiInterface()->getControlType() == ctNetworkCpuZeta) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("AAA AiRuleAddTasks adding #1 workerCount = %d[%.2f], buildingCount = %d[%.2f] warriorCount = %d[%.2f] upgradeCount = %d RULE Name[%s]\n",
|
|
workerCount, workerRatio, buildingCount, buildingRatio,
|
|
warriorCount, warriorRatio, upgradeCount,
|
|
this->getName().c_str());
|
|
|
|
//workers
|
|
if (workerCount < 5)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
if (workerCount < 100)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
if (workerRatio < 0.20)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
if (workerRatio < 0.30)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
|
|
//warriors
|
|
if (warriorCount < 10)
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
if (warriorRatio < 0.20)
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
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->getMinWarriors() + 2) {
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
if (buildingCount > 9) {
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
}
|
|
if (buildingCount > 12) {
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
}
|
|
}
|
|
|
|
//buildings
|
|
if (buildingCount < 6 || buildingRatio < 0.20)
|
|
ai->addTask(new BuildTask((UnitType *) NULL));
|
|
if (buildingCount < 10 && workerCount > 12)
|
|
ai->addTask(new BuildTask((UnitType *) NULL));
|
|
//upgrades
|
|
if (upgradeCount == 0 && workerCount > 5)
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
if (upgradeCount == 1 && workerCount > 10)
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
if (upgradeCount == 2 && workerCount > 15)
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
if (ai->isStableBase())
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
} else if (ai->getAiInterface()->getControlType() == ctCpuEasy ||
|
|
ai->getAiInterface()->getControlType() ==
|
|
ctNetworkCpuEasy) { // Easy CPU
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("AAA AiRuleAddTasks adding #2 workerCount = %d[%.2f], buildingCount = %d[%.2f] warriorCount = %d[%.2f] upgradeCount = %d RULE Name[%s]\n",
|
|
workerCount, workerRatio, buildingCount, buildingRatio,
|
|
warriorCount, warriorRatio, upgradeCount,
|
|
this->getName().c_str());
|
|
|
|
//workers
|
|
if (workerCount < buildingCount + 2)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
if (workerCount > 5 && workerRatio < 0.20)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
|
|
//warriors
|
|
if (warriorCount < 10)
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
if (warriorRatio < 0.20)
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
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));
|
|
|
|
//buildings
|
|
if (buildingCount < 6 || buildingRatio < 0.20)
|
|
ai->addTask(new BuildTask((UnitType *) NULL));
|
|
if (buildingCount < 10 && ai->isStableBase())
|
|
ai->addTask(new BuildTask((UnitType *) NULL));
|
|
|
|
//upgrades
|
|
if (upgradeCount == 0 && workerCount > 6)
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
if (upgradeCount == 1 && workerCount > 7)
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
if (upgradeCount == 2 && workerCount > 9)
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
//if(ai->isStableBase()) ai->addTask(new UpgradeTask());
|
|
} else { // normal CPU / UltraCPU ...
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("AAA AiRuleAddTasks adding #3 workerCount = %d[%.2f], buildingCount = %d[%.2f] warriorCount = %d[%.2f] upgradeCount = %d RULE Name[%s]\n",
|
|
workerCount, workerRatio, buildingCount, buildingRatio,
|
|
warriorCount, warriorRatio, upgradeCount,
|
|
this->getName().c_str());
|
|
|
|
//workers
|
|
if (workerCount < 5)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
if (workerCount < 10)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
if (workerRatio < 0.20)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
if (workerRatio < 0.30)
|
|
ai->addTask(new ProduceTask(ucWorker));
|
|
|
|
//warriors
|
|
if (warriorCount < 10)
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
if (warriorRatio < 0.20)
|
|
ai->addTask(new ProduceTask(ucWarrior));
|
|
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));
|
|
|
|
//buildings
|
|
if (buildingCount < 6 || buildingRatio < 0.20)
|
|
ai->addTask(new BuildTask((UnitType *) NULL));
|
|
if (buildingCount < 10 && workerCount > 12)
|
|
ai->addTask(new BuildTask((UnitType *) NULL));
|
|
|
|
//upgrades
|
|
if (upgradeCount == 0 && workerCount > 5)
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
if (upgradeCount == 1 && workerCount > 10)
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
if (upgradeCount == 2 && workerCount > 15)
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
if (ai->isStableBase())
|
|
ai->addTask(new UpgradeTask((const UpgradeType *) NULL));
|
|
}
|
|
}
|
|
}
|
|
|
|
// =====================================================
|
|
// class AiRuleBuildOneFarm
|
|
// =====================================================
|
|
|
|
AiRuleBuildOneFarm::AiRuleBuildOneFarm(Ai * ai) :
|
|
AiRule(ai) {
|
|
farm = NULL;
|
|
}
|
|
|
|
bool
|
|
AiRuleBuildOneFarm::test() {
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
//for all units
|
|
for (int i = 0;
|
|
i < aiInterface->getMyFactionType()->getUnitTypeCount(); ++i) {
|
|
const UnitType *
|
|
ut = aiInterface->getMyFactionType()->getUnitType(i);
|
|
|
|
//for all production commands
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
if (ct->getClass() == ccProduce) {
|
|
const UnitType *
|
|
producedType = static_cast <const
|
|
ProduceCommandType *>(ct)->
|
|
getProducedUnit();
|
|
|
|
//for all resources
|
|
for (int k = 0; k < producedType->getCostCount(); ++k) {
|
|
const Resource *
|
|
r = producedType->getCost(k);
|
|
|
|
//find a food producer in the farm produced units
|
|
if (r->getAmount() < 0
|
|
&& r->getType()->getClass() == rcConsumable
|
|
&& ai->getCountOfType(ut) == 0) {
|
|
if (aiInterface->reqsOk(ct)
|
|
&& aiInterface->getMyFaction()->
|
|
canCreateUnit(ut, true, true, true) == true) {
|
|
farm = ut;
|
|
//printf("AiRuleBuildOneFarm returning true, RULE Name[%s] ut [%s] producedType [%s]\n",this->getName().c_str(),ut->getName().c_str(),producedType->getName().c_str());
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("AiRuleBuildOneFarm returning true, RULE Name[%s]\n",
|
|
this->getName().c_str());
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
AiRuleBuildOneFarm::execute() {
|
|
ai->addPriorityTask(new BuildTask(farm));
|
|
}
|
|
|
|
// =====================================================
|
|
// class AiRuleProduceResourceProducer
|
|
// =====================================================
|
|
|
|
AiRuleProduceResourceProducer::AiRuleProduceResourceProducer(Ai * ai) :
|
|
AiRule(ai) {
|
|
interval = shortInterval;
|
|
rt = NULL;
|
|
newResourceBehaviour =
|
|
Config::getInstance().getBool("NewResourceBehaviour", "false");;
|
|
}
|
|
|
|
bool
|
|
AiRuleProduceResourceProducer::test() {
|
|
//emergency tasks: resource buildings
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
//consumables first
|
|
for (int i = 0;
|
|
i < aiInterface->getTechTree()->getResourceTypeCount(); ++i) {
|
|
rt = aiInterface->getTechTree()->getResourceType(i);
|
|
const Resource *
|
|
r = aiInterface->getResource(rt);
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf("CONSUMABLE [%s][%d] Testing AI RULE Name[%s]\n",
|
|
rt->getName().c_str(), r->getBalance(),
|
|
this->getName().c_str());
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"CONSUMABLE [%s][%d] Testing AI RULE Name[%s]",
|
|
rt->getName().c_str(), r->getBalance(),
|
|
this->getName().c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
bool
|
|
factionUsesResourceType =
|
|
aiInterface->factionUsesResourceType(aiInterface->
|
|
getMyFactionType(), rt);
|
|
if (factionUsesResourceType == true
|
|
&& rt->getClass() == rcConsumable) {
|
|
// The consumable balance is negative
|
|
if (r->getBalance() < 0) {
|
|
if (newResourceBehaviour == true) {
|
|
interval = shortInterval;
|
|
} else {
|
|
interval = longInterval;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
// If the consumable balance is down to 1/3 of what we need
|
|
else {
|
|
if (r->getBalance() * 3 + r->getAmount() < 0) {
|
|
if (newResourceBehaviour == true) {
|
|
interval = shortInterval;
|
|
} else {
|
|
interval = longInterval;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
targetStaticResourceCount = minStaticResources;
|
|
if (aiInterface->getMyFactionType()->
|
|
getAIBehaviorStaticOverideValue(aibsvcMinStaticResourceCount) !=
|
|
INT_MAX) {
|
|
targetStaticResourceCount =
|
|
aiInterface->getMyFactionType()->
|
|
getAIBehaviorStaticOverideValue(aibsvcMinStaticResourceCount);
|
|
}
|
|
|
|
//statics second
|
|
for (int i = 0;
|
|
i < aiInterface->getTechTree()->getResourceTypeCount(); ++i) {
|
|
rt = aiInterface->getTechTree()->getResourceType(i);
|
|
const Resource *
|
|
r = aiInterface->getResource(rt);
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf("STATIC [%s][%d] [min %d] Testing AI RULE Name[%s]\n",
|
|
rt->getName().c_str(), r->getAmount(),
|
|
targetStaticResourceCount, this->getName().c_str());
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"STATIC resource check [%s][%d] [min %d] Testing AI RULE Name[%s]",
|
|
rt->getName().c_str(), r->getAmount(),
|
|
targetStaticResourceCount, this->getName().c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
if (rt->getClass() == rcStatic
|
|
&& r->getAmount() < targetStaticResourceCount) {
|
|
bool
|
|
factionUsesResourceType =
|
|
aiInterface->factionUsesResourceType(aiInterface->
|
|
getMyFactionType(),
|
|
rt);
|
|
if (factionUsesResourceType == true) {
|
|
if (newResourceBehaviour == true)
|
|
interval = shortInterval;
|
|
else
|
|
interval = longInterval;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf("STATIC returning FALSE\n");
|
|
if (aiInterface->isLogLevelEnabled(4) == true)
|
|
aiInterface->printLog(4, "Static Resource check returning FALSE");
|
|
|
|
if (newResourceBehaviour == true)
|
|
interval = longInterval;
|
|
else
|
|
interval = shortInterval;
|
|
return false;
|
|
}
|
|
|
|
void
|
|
AiRuleProduceResourceProducer::execute() {
|
|
ai->addPriorityTask(new ProduceTask(rt));
|
|
ai->addTask(new BuildTask(rt));
|
|
}
|
|
|
|
// =====================================================
|
|
// class AiRuleProduce
|
|
// =====================================================
|
|
|
|
AiRuleProduce::AiRuleProduce(Ai * ai) :
|
|
AiRule(ai) {
|
|
produceTask = NULL;
|
|
newResourceBehaviour =
|
|
Config::getInstance().getBool("NewResourceBehaviour", "false");
|
|
}
|
|
|
|
bool
|
|
AiRuleProduce::test() {
|
|
const Task *
|
|
task = ai->getTask();
|
|
|
|
if (task == NULL || task->getClass() != tcProduce) {
|
|
return false;
|
|
}
|
|
|
|
produceTask = static_cast <const ProduceTask *>(task);
|
|
return true;
|
|
}
|
|
|
|
void
|
|
AiRuleProduce::execute() {
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
if (produceTask != NULL) {
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf("AiRuleProduce producing [%s]\n",
|
|
(produceTask->getUnitType() !=
|
|
NULL ? produceTask->getUnitType()->getName(false).
|
|
c_str() : "null"));
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096, "AiRuleProduce producing [%s]",
|
|
(produceTask->getUnitType() !=
|
|
NULL ? produceTask->getUnitType()->getName(false).
|
|
c_str() : "null"));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
//generic produce task, produce random unit that has the skill or produces the resource
|
|
if (produceTask->getUnitType() == NULL) {
|
|
if (newResourceBehaviour) {
|
|
produceGenericNew(produceTask);
|
|
} else
|
|
produceGeneric(produceTask);
|
|
}
|
|
|
|
//specific produce task, produce if possible, retry if not enough resources
|
|
else {
|
|
produceSpecific(produceTask);
|
|
}
|
|
|
|
//remove the task
|
|
ai->removeTask(produceTask);
|
|
}
|
|
}
|
|
|
|
bool
|
|
AiRuleProduce::canUnitTypeOfferResourceType(const UnitType * ut,
|
|
const ResourceType * rt) {
|
|
bool
|
|
unitTypeOffersResourceType = false;
|
|
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
if (ut != NULL && rt != NULL && aiInterface != NULL
|
|
&& aiInterface->reqsOk(ut)) {
|
|
// Check of the unit 'gives' the resource
|
|
// if the unit produces the resource
|
|
const Resource *
|
|
r = ut->getCost(rt);
|
|
if (r != NULL) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("#2 produceGeneric r = [%s][%d] Testing AI RULE Name[%s]\n",
|
|
r->getDescription(false).c_str(), r->getAmount(),
|
|
this->getName().c_str());
|
|
}
|
|
|
|
if (r != NULL && r->getAmount() < 0) {
|
|
unitTypeOffersResourceType = true;
|
|
} else {
|
|
// for each command check if we produce a unit that handles the resource
|
|
for (int commandIndex = 0;
|
|
commandIndex < ut->getCommandTypeCount(); ++commandIndex) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(commandIndex);
|
|
|
|
//if the command is produce
|
|
if (ct->getClass() == ccProduce
|
|
|| ct->getClass() == ccMorph) {
|
|
const UnitType *
|
|
producedUnit = static_cast <const
|
|
UnitType *>(ct->getProduced());
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceGeneric [%p] Testing AI RULE Name[%s]\n",
|
|
rt, this->getName().c_str());
|
|
|
|
//if the unit produces the resource
|
|
const Resource *
|
|
r = producedUnit->getCost(rt);
|
|
if (r != NULL) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceGeneric r = [%s][%d] Testing AI RULE Name[%s]\n",
|
|
r->getDescription(false).c_str(),
|
|
r->getAmount(), this->getName().c_str());
|
|
}
|
|
|
|
if (r != NULL && r->getAmount() < 0) {
|
|
unitTypeOffersResourceType = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aiInterface != NULL && aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"canUnitTypeOfferResourceType for unit type [%s] for resource type [%s] returned: %d",
|
|
(ut != NULL ? ut->getName(false).c_str() : "n/a"),
|
|
(rt != NULL ? rt->getName(false).c_str() : "n/a"),
|
|
unitTypeOffersResourceType);
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
return unitTypeOffersResourceType;
|
|
}
|
|
|
|
bool
|
|
AiRuleProduce::setAIProduceTaskForResourceType(const ProduceTask * pt,
|
|
AiInterface * aiInterface) {
|
|
bool
|
|
taskAdded = false;
|
|
if (aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcResourceProducerUnits).size() > 0) {
|
|
const
|
|
std::vector <
|
|
FactionType::PairPUnitTypeInt > &
|
|
unitList =
|
|
aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcResourceProducerUnits);
|
|
for (unsigned int i = 0; i < unitList.size(); ++i) {
|
|
const
|
|
FactionType::PairPUnitTypeInt &
|
|
priorityUnit = unitList[i];
|
|
const UnitType *
|
|
ut = priorityUnit.first;
|
|
if (ai->getCountOfType(ut) < priorityUnit.second &&
|
|
canUnitTypeOfferResourceType(ut,
|
|
pt->getResourceType()) ==
|
|
true
|
|
&& aiInterface->getMyFaction()->
|
|
canCreateUnit(priorityUnit.first, false, true,
|
|
true) == true) {
|
|
ai->addTask(new ProduceTask(priorityUnit.first));
|
|
taskAdded = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"setAIProduceTaskForResourceType for resource type [%s] returned: %d",
|
|
pt->getResourceType()->getName(false).c_str(),
|
|
taskAdded);
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
return taskAdded;
|
|
}
|
|
|
|
void
|
|
AiRuleProduce::addUnitTypeToCandidates(const UnitType * producedUnit,
|
|
UnitTypes & ableUnits,
|
|
UnitTypesGiveBack &
|
|
ableUnitsGiveBack,
|
|
bool unitCanGiveBackResource) {
|
|
// if the unit is not already on the list
|
|
if (find(ableUnits.begin(), ableUnits.end(), producedUnit) ==
|
|
ableUnits.end()) {
|
|
ableUnits.push_back(producedUnit);
|
|
ableUnitsGiveBack.push_back(unitCanGiveBackResource);
|
|
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"addUnitTypeToCandidates for unit type [%s] unitCanGiveBackResource = %d",
|
|
producedUnit->getName(false).c_str(),
|
|
unitCanGiveBackResource);
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
AiRuleProduce::produceGenericNew(const ProduceTask * pt) {
|
|
UnitTypes
|
|
ableUnits;
|
|
UnitTypesGiveBack
|
|
ableUnitsGiveBack;
|
|
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
if (pt->getResourceType() != NULL) {
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"****START: produceGeneric for resource type [%s]",
|
|
pt->getResourceType()->getName(false).c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
if (setAIProduceTaskForResourceType(pt, aiInterface) == true) {
|
|
return;
|
|
}
|
|
} else if (pt->getUnitClass() == ucWorker) {
|
|
if (aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcWorkerUnits).size() > 0) {
|
|
const
|
|
std::vector <
|
|
FactionType::PairPUnitTypeInt > &
|
|
unitList =
|
|
aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcWorkerUnits);
|
|
for (unsigned int i = 0; i < unitList.size(); ++i) {
|
|
const
|
|
FactionType::PairPUnitTypeInt &
|
|
priorityUnit = unitList[i];
|
|
if (ai->getCountOfType(priorityUnit.first) <
|
|
priorityUnit.second
|
|
&& aiInterface->getMyFaction()->
|
|
canCreateUnit(priorityUnit.first, false, true,
|
|
true) == true) {
|
|
ai->addTask(new ProduceTask(priorityUnit.first));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
} else if (pt->getUnitClass() == ucWarrior) {
|
|
if (aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcWarriorUnits).size() > 0) {
|
|
const
|
|
std::vector <
|
|
FactionType::PairPUnitTypeInt > &
|
|
unitList =
|
|
aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcWarriorUnits);
|
|
for (unsigned int i = 0; i < unitList.size(); ++i) {
|
|
const
|
|
FactionType::PairPUnitTypeInt &
|
|
priorityUnit = unitList[i];
|
|
if (ai->getCountOfType(priorityUnit.first) <
|
|
priorityUnit.second
|
|
&& aiInterface->getMyFaction()->
|
|
canCreateUnit(priorityUnit.first, false, true,
|
|
true) == true) {
|
|
ai->addTask(new ProduceTask(priorityUnit.first));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//for each unit, produce it if possible
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
if (aiInterface->getMyUnit(i)->getCurrCommand() != NULL
|
|
&& aiInterface->getMyUnit(i)->getCurrCommand()->
|
|
getCommandType()->getClass() == ccBuild) {
|
|
//skip this units as it is currently building something
|
|
continue;
|
|
}
|
|
//for each command
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(i)->getType();
|
|
|
|
//bool produceIt= false;
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is produce
|
|
//bool produceIt= false;
|
|
if (ct->getClass() == ccProduce || ct->getClass() == ccMorph) {
|
|
const UnitType *
|
|
producedUnit = static_cast <const
|
|
UnitType *>(ct->getProduced());
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf("produceGeneric [%p] Testing AI RULE Name[%s]\n",
|
|
pt->getResourceType(),
|
|
this->getName().c_str());
|
|
|
|
//if the unit produces the resource
|
|
if (pt->getResourceType() != NULL) {
|
|
const Resource *
|
|
r = producedUnit->getCost(pt->getResourceType());
|
|
if (r != NULL) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceGeneric r = [%s][%d] Testing AI RULE Name[%s]\n",
|
|
r->getDescription(false).c_str(),
|
|
r->getAmount(), this->getName().c_str());
|
|
}
|
|
|
|
if (r != NULL && r->getAmount() < 0) {
|
|
if (aiInterface->reqsOk(ct)
|
|
&& aiInterface->reqsOk(producedUnit)) {
|
|
//produceIt= true;
|
|
addUnitTypeToCandidates(producedUnit,
|
|
ableUnits,
|
|
ableUnitsGiveBack,
|
|
false);
|
|
}
|
|
}
|
|
} else {
|
|
//if the unit is from the right class
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceGeneric right class = [%d] Testing AI RULE Name[%s]\n",
|
|
producedUnit->isOfClass(pt->getUnitClass()),
|
|
this->getName().c_str());
|
|
|
|
if (producedUnit->isOfClass(pt->getUnitClass())) {
|
|
if (aiInterface->reqsOk(ct)
|
|
&& aiInterface->reqsOk(producedUnit)) {
|
|
//produceIt= true;
|
|
addUnitTypeToCandidates(producedUnit,
|
|
ableUnits,
|
|
ableUnitsGiveBack,
|
|
false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Now check of the unit 'gives' the resource
|
|
// This is likely a unit that it BUILT by another and that is handled by a different AI task type: Build
|
|
// if(produceIt == false && pt->getResourceType() != NULL) {
|
|
// const Resource *r= ut->getCost(pt->getResourceType());
|
|
// if(r != NULL) {
|
|
// if(ai->outputAIBehaviourToConsole()) printf("#2 produceGeneric r = [%s][%d] Testing AI RULE Name[%s]\n",r->getDescription(false).c_str(),r->getAmount(), this->getName().c_str());
|
|
// }
|
|
//
|
|
// if(r != NULL && r->getAmount() < 0) {
|
|
// if(aiInterface->reqsOk(ut)){
|
|
// produceIt= true;
|
|
// addUnitTypeToCandidates(ut, ableUnits,ableUnitsGiveBack, true);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
}
|
|
|
|
//add specific produce task
|
|
if (ableUnits.empty() == false) {
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceGeneric !ableUnits.empty(), ableUnits.size() = [%d] Testing AI RULE Name[%s]\n",
|
|
(int) ableUnits.size(), this->getName().c_str());
|
|
|
|
// Now check if we already have at least 2 produce or morph
|
|
// resource based units, if so prefer units that give back the resource
|
|
if (pt->getResourceType() != NULL && ableUnits.size() > 1) {
|
|
//priority for non produced units
|
|
UnitTypes
|
|
newAbleUnits;
|
|
bool
|
|
haveEnoughProducers = true;
|
|
bool
|
|
haveNonProducers = false;
|
|
for (unsigned int i = 0; i < ableUnits.size(); ++i) {
|
|
const UnitType *
|
|
ut = ableUnits[i];
|
|
bool
|
|
givesBack = ableUnitsGiveBack[i];
|
|
if (givesBack == false && ai->getCountOfType(ut) < 2) {
|
|
haveEnoughProducers = false;
|
|
} else if (givesBack == true) {
|
|
haveNonProducers = true;
|
|
newAbleUnits.push_back(ut);
|
|
}
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In produceGeneric for unit type [%s] givesBack: %d count of unit type: %d",
|
|
ut->getName(false).c_str(), givesBack,
|
|
ai->getCountOfType(ut));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
}
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"haveEnoughProducers [%d] haveNonProducers [%d]",
|
|
haveEnoughProducers, haveNonProducers);
|
|
aiInterface->printLog(4, szBuf);
|
|
|
|
for (unsigned int i = 0; i < ableUnits.size(); ++i) {
|
|
const UnitType *
|
|
ut = ableUnits[i];
|
|
snprintf(szBuf, 8096, "i: %u unit type [%s]", i,
|
|
ut->getName(false).c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
for (unsigned int i = 0; i < newAbleUnits.size(); ++i) {
|
|
const UnitType *
|
|
ut = newAbleUnits[i];
|
|
snprintf(szBuf, 8096, "i: %u new unit type [%s]", i,
|
|
ut->getName(false).c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
}
|
|
|
|
if (haveEnoughProducers == true && haveNonProducers == true) {
|
|
ableUnits = newAbleUnits;
|
|
}
|
|
}
|
|
|
|
//priority for non produced units
|
|
for (unsigned int i = 0; i < ableUnits.size(); ++i) {
|
|
if (ai->getCountOfType(ableUnits[i]) == 0) {
|
|
if (ai->getRandom()->randRange(0, 1) == 0) {
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In produceGeneric priority adding produce task: %d of "
|
|
MG_SIZE_T_SPECIFIER " for unit type [%s]",
|
|
i, ableUnits.size(),
|
|
ableUnits[i]->getName(false).c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->addTask(new ProduceTask(ableUnits[i]));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//normal case
|
|
int
|
|
randomUnitTypeIndex =
|
|
ai->getRandom()->randRange(0, (int) ableUnits.size() - 1);
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In produceGeneric randomUnitTypeIndex = %d of "
|
|
MG_SIZE_T_SPECIFIER " equals unit type [%s]",
|
|
randomUnitTypeIndex, ableUnits.size() - 1,
|
|
ableUnits[randomUnitTypeIndex]->getName(false).
|
|
c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
const UnitType *
|
|
ut = ableUnits[randomUnitTypeIndex];
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"== END In produceGeneric normal adding produce task for unit type [%s]",
|
|
ut->getName(false).c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->addTask(new ProduceTask(ut));
|
|
}
|
|
}
|
|
|
|
void
|
|
AiRuleProduce::produceGeneric(const ProduceTask * pt) {
|
|
typedef
|
|
vector < const UnitType *>
|
|
UnitTypes;
|
|
UnitTypes
|
|
ableUnits;
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
if (pt->getResourceType() != NULL) {
|
|
if (aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcResourceProducerUnits).size() > 0) {
|
|
const
|
|
std::vector <
|
|
FactionType::PairPUnitTypeInt > &
|
|
unitList =
|
|
aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcResourceProducerUnits);
|
|
for (unsigned int i = 0; i < unitList.size(); ++i) {
|
|
const
|
|
FactionType::PairPUnitTypeInt &
|
|
priorityUnit = unitList[i];
|
|
if (ai->getCountOfType(priorityUnit.first) <
|
|
priorityUnit.second
|
|
&& aiInterface->getMyFaction()->
|
|
canCreateUnit(priorityUnit.first, false, true,
|
|
true) == true) {
|
|
//if(ai->getRandom()->randRange(0, 1)==0) {
|
|
ai->addTask(new ProduceTask(priorityUnit.first));
|
|
return;
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
} else if (pt->getUnitClass() == ucWorker) {
|
|
if (aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcWorkerUnits).size() > 0) {
|
|
const
|
|
std::vector <
|
|
FactionType::PairPUnitTypeInt > &
|
|
unitList =
|
|
aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcWorkerUnits);
|
|
for (unsigned int i = 0; i < unitList.size(); ++i) {
|
|
const
|
|
FactionType::PairPUnitTypeInt &
|
|
priorityUnit = unitList[i];
|
|
if (ai->getCountOfType(priorityUnit.first) <
|
|
priorityUnit.second
|
|
&& aiInterface->getMyFaction()->
|
|
canCreateUnit(priorityUnit.first, false, true,
|
|
true) == true) {
|
|
//if(ai->getRandom()->randRange(0, 1)==0) {
|
|
ai->addTask(new ProduceTask(priorityUnit.first));
|
|
return;
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
} else if (pt->getUnitClass() == ucWarrior) {
|
|
if (aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcWarriorUnits).size() > 0) {
|
|
const
|
|
std::vector <
|
|
FactionType::PairPUnitTypeInt > &
|
|
unitList =
|
|
aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcWarriorUnits);
|
|
for (unsigned int i = 0; i < unitList.size(); ++i) {
|
|
const
|
|
FactionType::PairPUnitTypeInt &
|
|
priorityUnit = unitList[i];
|
|
if (ai->getCountOfType(priorityUnit.first) <
|
|
priorityUnit.second
|
|
&& aiInterface->getMyFaction()->
|
|
canCreateUnit(priorityUnit.first, false, true,
|
|
true) == true) {
|
|
//if(ai->getRandom()->randRange(0, 1)==0) {
|
|
ai->addTask(new ProduceTask(priorityUnit.first));
|
|
return;
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//for each unit, produce it if possible
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
if (aiInterface->getMyUnit(i)->getCurrCommand() != NULL
|
|
&& aiInterface->getMyUnit(i)->getCurrCommand()->
|
|
getCommandType()->getClass() == ccBuild) {
|
|
//skip this units as it is currently building something
|
|
continue;
|
|
}
|
|
//for each command
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(i)->getType();
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is produce
|
|
if (ct->getClass() == ccProduce || ct->getClass() == ccMorph) {
|
|
|
|
const UnitType *
|
|
producedUnit = static_cast <const
|
|
UnitType *>(ct->getProduced());
|
|
bool
|
|
produceIt = false;
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf("produceGeneric [%p] Testing AI RULE Name[%s]\n",
|
|
pt->getResourceType(),
|
|
this->getName().c_str());
|
|
|
|
//if the unit produces the resource
|
|
if (pt->getResourceType() != NULL) {
|
|
const Resource *
|
|
r = producedUnit->getCost(pt->getResourceType());
|
|
|
|
if (r != NULL) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceGeneric r = [%s][%d] Testing AI RULE Name[%s]\n",
|
|
r->getDescription(false).c_str(),
|
|
r->getAmount(), this->getName().c_str());
|
|
}
|
|
|
|
if (r != NULL && r->getAmount() < 0) {
|
|
produceIt = true;
|
|
}
|
|
}
|
|
|
|
else {
|
|
//if the unit is from the right class
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceGeneric right class = [%d] Testing AI RULE Name[%s]\n",
|
|
producedUnit->isOfClass(pt->getUnitClass()),
|
|
this->getName().c_str());
|
|
|
|
if (producedUnit->isOfClass(pt->getUnitClass())) {
|
|
if (aiInterface->reqsOk(ct)
|
|
&& aiInterface->reqsOk(producedUnit)) {
|
|
produceIt = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (produceIt) {
|
|
//if the unit is not already on the list
|
|
if (find
|
|
(ableUnits.begin(), ableUnits.end(),
|
|
producedUnit) == ableUnits.end()) {
|
|
ableUnits.push_back(producedUnit);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//add specific produce task
|
|
if (ableUnits.empty() == false) {
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceGeneric !ableUnits.empty(), ableUnits.size() = [%d] Testing AI RULE Name[%s]\n",
|
|
(int) ableUnits.size(), this->getName().c_str());
|
|
|
|
//priority for non produced units
|
|
for (unsigned int i = 0; i < ableUnits.size(); ++i) {
|
|
if (ai->getCountOfType(ableUnits[i]) == 0) {
|
|
if (ai->getRandom()->randRange(0, 1) == 0) {
|
|
ai->addTask(new ProduceTask(ableUnits[i]));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//normal case
|
|
ai->
|
|
addTask(new
|
|
ProduceTask(ableUnits
|
|
[ai->getRandom()->
|
|
randRange(0,
|
|
(int) ableUnits.size() - 1)]));
|
|
}
|
|
}
|
|
|
|
void
|
|
AiRuleProduce::produceSpecific(const ProduceTask * pt) {
|
|
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceSpecific aiInterface->reqsOk(pt->getUnitType()) = [%s][%d] Testing AI RULE Name[%s]\n",
|
|
pt->getUnitType()->getName().c_str(),
|
|
aiInterface->reqsOk(pt->getUnitType()),
|
|
this->getName().c_str());
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"== START produceSpecific aiInterface->reqsOk(pt->getUnitType()) = [%s][%d] Testing AI RULE Name[%s]",
|
|
pt->getUnitType()->getName().c_str(),
|
|
aiInterface->reqsOk(pt->getUnitType()),
|
|
this->getName().c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
//if unit meets requirements
|
|
if (aiInterface->reqsOk(pt->getUnitType())) {
|
|
|
|
const CommandType *
|
|
ctypeForCostCheck = NULL;
|
|
//for each unit
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
//don't use units which are currently building
|
|
if (aiInterface->getMyUnit(i)->getCurrCommand() != NULL
|
|
&& aiInterface->getMyUnit(i)->getCurrCommand()->
|
|
getCommandType()->getClass() == ccBuild) {
|
|
//skip this units as it is currently building something
|
|
continue;
|
|
}
|
|
//for each command
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(i)->getType();
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is produce
|
|
if (ct->getClass() == ccProduce
|
|
|| ct->getClass() == ccMorph) {
|
|
const UnitType *
|
|
producedUnit = static_cast <const
|
|
UnitType *>(ct->getProduced());
|
|
|
|
//if units match
|
|
if (producedUnit == pt->getUnitType()) {
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceSpecific aiInterface->reqsOk(ct) = [%d] Testing AI RULE Name[%s]\n",
|
|
aiInterface->reqsOk(ct),
|
|
this->getName().c_str());
|
|
|
|
if (aiInterface->reqsOk(ct)) {
|
|
if (ctypeForCostCheck == NULL
|
|
|| ct->getClass() == ccMorph) {
|
|
if (ctypeForCostCheck != NULL
|
|
&& ct->getClass() == ccMorph) {
|
|
const MorphCommandType *
|
|
mct = dynamic_cast <const
|
|
MorphCommandType *>(ct);
|
|
if (mct == NULL) {
|
|
throw
|
|
megaglest_runtime_error
|
|
("mct == NULL");
|
|
}
|
|
if (mct->
|
|
getIgnoreResourceRequirements() ==
|
|
true) {
|
|
ctypeForCostCheck = ct;
|
|
}
|
|
} else {
|
|
ctypeForCostCheck = ct;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceSpecific aiInterface->checkCosts(pt->getUnitType()) = [%d] Testing AI RULE Name[%s]\n",
|
|
aiInterface->checkCosts(pt->getUnitType(),
|
|
ctypeForCostCheck),
|
|
this->getName().c_str());
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"produceSpecific aiInterface->checkCosts(pt->getUnitType()) = [%d] Testing AI RULE Name[%s]",
|
|
aiInterface->checkCosts(pt->getUnitType(),
|
|
ctypeForCostCheck),
|
|
this->getName().c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
//if unit doesnt meet resources retry
|
|
if (aiInterface->
|
|
checkCosts(pt->getUnitType(), ctypeForCostCheck) == false) {
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096, "Check costs FAILED.");
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->retryTask(pt);
|
|
return;
|
|
}
|
|
|
|
//produce specific unit
|
|
vector < int >
|
|
producers;
|
|
// Hold a list of units which can produce or morph
|
|
// then a list of commandtypes for each unit
|
|
map < int,
|
|
vector < const CommandType *> >
|
|
producersDefaultCommandType;
|
|
const CommandType *
|
|
defCt = NULL;
|
|
|
|
//for each unit
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
if (aiInterface->getMyUnit(i)->getCurrCommand() != NULL
|
|
&& aiInterface->getMyUnit(i)->getCurrCommand()->
|
|
getCommandType()->getClass() == ccBuild) {
|
|
//skip this units as it is currently building something
|
|
continue;
|
|
}
|
|
//for each command
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(i)->getType();
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is produce
|
|
if (ct->getClass() == ccProduce
|
|
|| ct->getClass() == ccMorph) {
|
|
const UnitType *
|
|
producedUnit = static_cast <const
|
|
UnitType *>(ct->getProduced());
|
|
|
|
//if units match
|
|
if (producedUnit == pt->getUnitType()) {
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceSpecific aiInterface->reqsOk(ct) = [%d] Testing AI RULE Name[%s]\n",
|
|
aiInterface->reqsOk(ct),
|
|
this->getName().c_str());
|
|
|
|
if (aiInterface->reqsOk(ct)) {
|
|
//defCt= ct;
|
|
producers.push_back(i);
|
|
producersDefaultCommandType[i].push_back(ct);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//produce from random producer
|
|
if (producers.empty() == false) {
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceSpecific producers.empty() = [%d] Testing AI RULE Name[%s]\n",
|
|
producers.empty(), this->getName().c_str());
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"produceSpecific producers.empty() = [%d] Testing AI RULE Name[%s]",
|
|
producers.empty(), this->getName().c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
// Narrow down producers list to those who are not busy if possible
|
|
vector < int >
|
|
idle_producers;
|
|
for (unsigned int i = 0; i < producers.size(); ++i) {
|
|
int
|
|
currentProducerIndex = producers[i];
|
|
if (currentProducerIndex >= aiInterface->getMyUnitCount()) {
|
|
char
|
|
szBuf[8096] = "";
|
|
printf
|
|
("In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %d, i = %u,producers.size() = "
|
|
MG_SIZE_T_SPECIFIER "\n", __FILE__, __FUNCTION__,
|
|
__LINE__, currentProducerIndex,
|
|
aiInterface->getMyUnitCount(), i,
|
|
producers.size());
|
|
snprintf(szBuf, 8096,
|
|
"In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %u, i = %u,producers.size() = "
|
|
MG_SIZE_T_SPECIFIER "", __FILE__,
|
|
__FUNCTION__, __LINE__, currentProducerIndex,
|
|
aiInterface->getMyUnitCount(), i,
|
|
producers.size());
|
|
throw
|
|
megaglest_runtime_error(szBuf);
|
|
}
|
|
|
|
const Unit *
|
|
unit = aiInterface->getMyUnit(currentProducerIndex);
|
|
if (unit->anyCommand() == false) {
|
|
idle_producers.push_back(currentProducerIndex);
|
|
}
|
|
}
|
|
if (idle_producers.empty() == false) {
|
|
producers = idle_producers;
|
|
}
|
|
|
|
if (aiInterface->getControlType() == ctCpuZeta ||
|
|
aiInterface->getControlType() == ctNetworkCpuZeta) { // zeta cpu trys to balance the commands to the producers
|
|
int
|
|
randomstart =
|
|
ai->getRandom()->randRange(0,
|
|
(int) producers.size() - 1);
|
|
int
|
|
lowestCommandCount = 1000000;
|
|
int
|
|
currentProducerIndex = producers[randomstart];
|
|
int
|
|
bestIndex = -1;
|
|
//int besti=0;
|
|
int
|
|
currentCommandCount = 0;
|
|
for (unsigned int i = randomstart;
|
|
i < producers.size() + randomstart; i++) {
|
|
int
|
|
prIndex = i;
|
|
if (i >= producers.size()) {
|
|
prIndex = (i - (int) producers.size());
|
|
}
|
|
currentProducerIndex = producers[prIndex];
|
|
|
|
if (currentProducerIndex >=
|
|
aiInterface->getMyUnitCount()) {
|
|
char
|
|
szBuf[8096] = "";
|
|
printf
|
|
("In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %d, i = %u,producers.size() = "
|
|
MG_SIZE_T_SPECIFIER "\n", __FILE__, __FUNCTION__,
|
|
__LINE__, currentProducerIndex,
|
|
aiInterface->getMyUnitCount(), i,
|
|
producers.size());
|
|
snprintf(szBuf, 8096,
|
|
"In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %u, i = %u,producers.size() = "
|
|
MG_SIZE_T_SPECIFIER "", __FILE__,
|
|
__FUNCTION__, __LINE__,
|
|
currentProducerIndex,
|
|
aiInterface->getMyUnitCount(), i,
|
|
producers.size());
|
|
throw
|
|
megaglest_runtime_error(szBuf);
|
|
}
|
|
if (prIndex >= (int) producers.size()) {
|
|
char
|
|
szBuf[8096] = "";
|
|
printf
|
|
("In [%s::%s Line: %d] prIndex >= producers.size(), currentProducerIndex = %d, i = %u,producers.size() = "
|
|
MG_SIZE_T_SPECIFIER " \n", __FILE__,
|
|
__FUNCTION__, __LINE__, prIndex, i,
|
|
producers.size());
|
|
snprintf(szBuf, 8096,
|
|
"In [%s::%s Line: %d] currentProducerIndex >= producers.size(), currentProducerIndex = %d, i = %u,producers.size() = "
|
|
MG_SIZE_T_SPECIFIER "", __FILE__,
|
|
__FUNCTION__, __LINE__,
|
|
currentProducerIndex, i,
|
|
producers.size());
|
|
throw
|
|
megaglest_runtime_error(szBuf);
|
|
}
|
|
|
|
currentCommandCount =
|
|
aiInterface->getMyUnit(currentProducerIndex)->
|
|
getCommandSize();
|
|
if (currentCommandCount == 1
|
|
&& aiInterface->getMyUnit(currentProducerIndex)->
|
|
getCurrCommand()->getCommandType()->getClass() ==
|
|
ccStop) { // special for non buildings
|
|
currentCommandCount = 0;
|
|
}
|
|
if (lowestCommandCount > currentCommandCount) {
|
|
lowestCommandCount =
|
|
aiInterface->getMyUnit(currentProducerIndex)->
|
|
getCommandSize();
|
|
bestIndex = currentProducerIndex;
|
|
//besti=i%(producers.size());
|
|
}
|
|
}
|
|
if (bestIndex >= 0) {
|
|
if (aiInterface->getMyUnit(bestIndex)->
|
|
getCommandSize() > 2) {
|
|
// maybe we need another producer of this kind if possible!
|
|
if (aiInterface->
|
|
reqsOk(aiInterface->getMyUnit(bestIndex)->
|
|
getType())) {
|
|
if (ai->getCountOfClass(ucBuilding) > 5) {
|
|
ai->
|
|
addTask(new
|
|
BuildTask(aiInterface->
|
|
getMyUnit
|
|
(bestIndex)->
|
|
getType()));
|
|
}
|
|
}
|
|
// need to calculate another producer, maybe its better to produce another warrior with another producer
|
|
vector < int >
|
|
backupProducers;
|
|
// find another producer unit which is free and produce any kind of warrior.
|
|
//for each unit
|
|
for (int i = 0; i < aiInterface->getMyUnitCount();
|
|
++i) {
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(i)->getType();
|
|
//for each command
|
|
for (int j = 0; j < ut->getCommandTypeCount();
|
|
++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
//if the command is produce
|
|
if (ct->getClass() == ccProduce) {
|
|
const UnitType *
|
|
unitType = static_cast <const
|
|
UnitType *>(ct->getProduced());
|
|
if (unitType->hasSkillClass(scAttack)
|
|
&& !unitType->
|
|
hasCommandClass(ccHarvest)
|
|
&& aiInterface->reqsOk(ct)) { //this can produce a warrior
|
|
backupProducers.push_back(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!backupProducers.empty()) {
|
|
int
|
|
randomstart =
|
|
ai->getRandom()->randRange(0,
|
|
(int)
|
|
backupProducers.
|
|
size() - 1);
|
|
int
|
|
lowestCommandCount = 1000000;
|
|
int
|
|
currentProducerIndex =
|
|
backupProducers[randomstart];
|
|
int
|
|
bestIndex = -1;
|
|
for (unsigned int i = randomstart;
|
|
i < backupProducers.size() + randomstart;
|
|
i++) {
|
|
int
|
|
prIndex = i;
|
|
if (i >= backupProducers.size()) {
|
|
prIndex =
|
|
(i - (int) backupProducers.size());
|
|
}
|
|
|
|
currentProducerIndex =
|
|
backupProducers[prIndex];
|
|
|
|
if (currentProducerIndex >=
|
|
aiInterface->getMyUnitCount()) {
|
|
char
|
|
szBuf[8096] = "";
|
|
printf
|
|
("In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %d, i = %u,backupProducers.size() = "
|
|
MG_SIZE_T_SPECIFIER "\n", __FILE__,
|
|
__FUNCTION__, __LINE__,
|
|
currentProducerIndex,
|
|
aiInterface->getMyUnitCount(), i,
|
|
backupProducers.size());
|
|
snprintf(szBuf, 8096,
|
|
"In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %d, i = %u,backupProducers.size() = "
|
|
MG_SIZE_T_SPECIFIER "",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__,
|
|
currentProducerIndex,
|
|
aiInterface->
|
|
getMyUnitCount(), i,
|
|
backupProducers.size());
|
|
throw
|
|
megaglest_runtime_error(szBuf);
|
|
}
|
|
if (prIndex >=
|
|
(int) backupProducers.size()) {
|
|
char
|
|
szBuf[8096] = "";
|
|
printf
|
|
("In [%s::%s Line: %d] prIndex >= backupProducers.size(), currentProducerIndex = %d, i = %u,backupProducers.size() = "
|
|
MG_SIZE_T_SPECIFIER " \n", __FILE__,
|
|
__FUNCTION__, __LINE__, prIndex, i,
|
|
backupProducers.size());
|
|
snprintf(szBuf, 8096,
|
|
"In [%s::%s Line: %d] currentProducerIndex >= backupProducers.size(), currentProducerIndex = %d, i = %u,backupProducers.size() = "
|
|
MG_SIZE_T_SPECIFIER "",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__,
|
|
currentProducerIndex, i,
|
|
backupProducers.size());
|
|
throw
|
|
megaglest_runtime_error(szBuf);
|
|
}
|
|
|
|
int
|
|
currentCommandCount =
|
|
aiInterface->
|
|
getMyUnit(currentProducerIndex)->
|
|
getCommandSize();
|
|
if (currentCommandCount == 1
|
|
&& aiInterface->
|
|
getMyUnit(currentProducerIndex)->
|
|
getCurrCommand()->getCommandType()->
|
|
getClass() == ccStop) { // special for non buildings
|
|
currentCommandCount = 0;
|
|
}
|
|
if (lowestCommandCount >
|
|
currentCommandCount) {
|
|
lowestCommandCount =
|
|
currentCommandCount;
|
|
bestIndex = currentProducerIndex;
|
|
if (lowestCommandCount == 0)
|
|
break;
|
|
}
|
|
}
|
|
// a good producer is found, lets choose a warrior production
|
|
vector < int >
|
|
productionCommandIndexes;
|
|
if (bestIndex >= 0) {
|
|
const UnitType *
|
|
ut =
|
|
aiInterface->getMyUnit(bestIndex)->
|
|
getType();
|
|
for (int j = 0;
|
|
j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is produce
|
|
if (ct->getClass() == ccProduce) {
|
|
const UnitType *
|
|
unitType = static_cast <const
|
|
UnitType *>(ct->getProduced());
|
|
if (unitType->
|
|
hasSkillClass(scAttack)
|
|
&& !unitType->
|
|
hasCommandClass(ccHarvest)
|
|
&& aiInterface->reqsOk(ct)) { //this can produce a warrior
|
|
productionCommandIndexes.
|
|
push_back(j);
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
commandIndex =
|
|
productionCommandIndexes[ai->
|
|
getRandom()->
|
|
randRange(0,
|
|
(int)
|
|
productionCommandIndexes.
|
|
size
|
|
() -
|
|
1)];
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::
|
|
debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::
|
|
debugSystem,
|
|
"In [%s::%s Line: %d]\n",
|
|
__FILE__,
|
|
__FUNCTION__,
|
|
__LINE__);
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("zeta #1 produceSpecific giveCommand to unit [%s] commandType [%s]\n",
|
|
aiInterface->getMyUnit(bestIndex)->
|
|
getType()->getName().c_str(),
|
|
ut->getCommandType(commandIndex)->
|
|
getName().c_str());
|
|
if (aiInterface->isLogLevelEnabled(4) ==
|
|
true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"zeta #1 produceSpecific giveCommand to unit [%s] commandType [%s]",
|
|
aiInterface->
|
|
getMyUnit(bestIndex)->
|
|
getType()->getName().
|
|
c_str(),
|
|
ut->
|
|
getCommandType
|
|
(commandIndex)->getName().
|
|
c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
aiInterface->giveCommand(bestIndex,
|
|
ut->
|
|
getCommandType
|
|
(commandIndex));
|
|
}
|
|
} else { // do it like normal CPU
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::
|
|
debugSystem).enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::
|
|
debugSystem,
|
|
"In [%s::%s Line: %d]\n",
|
|
__FILE__,
|
|
__FUNCTION__,
|
|
__LINE__);
|
|
defCt = NULL;
|
|
if (producersDefaultCommandType.
|
|
find(bestIndex) !=
|
|
producersDefaultCommandType.end()) {
|
|
int
|
|
bestCommandTypeCount =
|
|
(int)
|
|
producersDefaultCommandType[bestIndex].
|
|
size();
|
|
int
|
|
bestCommandTypeIndex =
|
|
ai->getRandom()->randRange(0,
|
|
bestCommandTypeCount
|
|
- 1);
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::
|
|
debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::
|
|
debugSystem,
|
|
"In [%s::%s Line: %d] bestCommandTypeIndex = %d, bestCommandTypeCount = %d\n",
|
|
__FILE__,
|
|
__FUNCTION__,
|
|
__LINE__,
|
|
bestCommandTypeIndex,
|
|
bestCommandTypeCount);
|
|
|
|
defCt =
|
|
producersDefaultCommandType[bestIndex]
|
|
[bestCommandTypeIndex];
|
|
}
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("zeta #2 produceSpecific giveCommand to unit [%s] commandType [%s]\n",
|
|
aiInterface->getMyUnit(bestIndex)->
|
|
getType()->getName().c_str(),
|
|
(defCt !=
|
|
NULL ? defCt->getName().
|
|
c_str() : "n/a"));
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"zeta #2 produceSpecific giveCommand to unit [%s] commandType [%s]",
|
|
aiInterface->
|
|
getMyUnit(bestIndex)->
|
|
getType()->getName().c_str(),
|
|
(defCt !=
|
|
NULL ? defCt->getName().
|
|
c_str() : "n/a"));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
if (defCt != NULL)
|
|
aiInterface->giveCommand(bestIndex, defCt);
|
|
}
|
|
} else {
|
|
if (currentCommandCount == 0) {
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::
|
|
debugSystem).enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::
|
|
debugSystem,
|
|
"In [%s::%s Line: %d]\n",
|
|
__FILE__,
|
|
__FUNCTION__,
|
|
__LINE__);
|
|
defCt = NULL;
|
|
if (producersDefaultCommandType.
|
|
find(bestIndex) !=
|
|
producersDefaultCommandType.end()) {
|
|
//defCt = producersDefaultCommandType[bestIndex];
|
|
int
|
|
bestCommandTypeCount =
|
|
(int)
|
|
producersDefaultCommandType[bestIndex].
|
|
size();
|
|
int
|
|
bestCommandTypeIndex =
|
|
ai->getRandom()->randRange(0,
|
|
bestCommandTypeCount
|
|
- 1);
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::
|
|
debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::
|
|
debugSystem,
|
|
"In [%s::%s Line: %d] bestCommandTypeIndex = %d, bestCommandTypeCount = %d\n",
|
|
__FILE__,
|
|
__FUNCTION__,
|
|
__LINE__,
|
|
bestCommandTypeIndex,
|
|
bestCommandTypeCount);
|
|
|
|
defCt =
|
|
producersDefaultCommandType[bestIndex]
|
|
[bestCommandTypeIndex];
|
|
}
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("zeta #3 produceSpecific giveCommand to unit [%s] commandType [%s]\n",
|
|
aiInterface->getMyUnit(bestIndex)->
|
|
getType()->getName().c_str(),
|
|
(defCt !=
|
|
NULL ? defCt->getName().
|
|
c_str() : "n/a"));
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"zeta #3 produceSpecific giveCommand to unit [%s] commandType [%s]",
|
|
aiInterface->
|
|
getMyUnit(bestIndex)->
|
|
getType()->getName().c_str(),
|
|
(defCt !=
|
|
NULL ? defCt->getName().
|
|
c_str() : "n/a"));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
if (defCt != NULL)
|
|
aiInterface->giveCommand(bestIndex, defCt);
|
|
}
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::
|
|
debugSystem,
|
|
"In [%s::%s Line: %d]\n",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__);
|
|
defCt = NULL;
|
|
if (producersDefaultCommandType.find(bestIndex) !=
|
|
producersDefaultCommandType.end()) {
|
|
//defCt = producersDefaultCommandType[bestIndex];
|
|
int
|
|
bestCommandTypeCount =
|
|
(int) producersDefaultCommandType[bestIndex].
|
|
size();
|
|
int
|
|
bestCommandTypeIndex =
|
|
ai->getRandom()->randRange(0,
|
|
bestCommandTypeCount
|
|
- 1);
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::
|
|
debugSystem).enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::
|
|
debugSystem,
|
|
"In [%s::%s Line: %d] bestCommandTypeIndex = %d, bestCommandTypeCount = %d\n",
|
|
__FILE__,
|
|
__FUNCTION__,
|
|
__LINE__,
|
|
bestCommandTypeIndex,
|
|
bestCommandTypeCount);
|
|
|
|
defCt =
|
|
producersDefaultCommandType[bestIndex]
|
|
[bestCommandTypeIndex];
|
|
}
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("zeta #4 produceSpecific giveCommand to unit [%s] commandType [%s]\n",
|
|
aiInterface->getMyUnit(bestIndex)->
|
|
getType()->getName().c_str(),
|
|
(defCt !=
|
|
NULL ? defCt->getName().c_str() : "n/a"));
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"zeta #4 produceSpecific giveCommand to unit [%s] commandType [%s]",
|
|
aiInterface->getMyUnit(bestIndex)->
|
|
getType()->getName().c_str(),
|
|
(defCt !=
|
|
NULL ? defCt->getName().
|
|
c_str() : "n/a"));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
if (defCt != NULL)
|
|
aiInterface->giveCommand(bestIndex, defCt);
|
|
}
|
|
}
|
|
} else {
|
|
int
|
|
pIndex =
|
|
ai->getRandom()->randRange(0,
|
|
(int) producers.size() - 1);
|
|
int
|
|
producerIndex = producers[pIndex];
|
|
defCt = NULL;
|
|
if (producersDefaultCommandType.find(producerIndex) !=
|
|
producersDefaultCommandType.end()) {
|
|
//defCt = producersDefaultCommandType[producerIndex];
|
|
int
|
|
bestCommandTypeCount =
|
|
(int) producersDefaultCommandType[producerIndex].
|
|
size();
|
|
int
|
|
bestCommandTypeIndex =
|
|
ai->getRandom()->randRange(0,
|
|
bestCommandTypeCount -
|
|
1);
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d] bestCommandTypeIndex = %d, bestCommandTypeCount = %d\n",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__,
|
|
bestCommandTypeIndex,
|
|
bestCommandTypeCount);
|
|
|
|
defCt =
|
|
producersDefaultCommandType[producerIndex]
|
|
[bestCommandTypeIndex];
|
|
}
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugSystem).enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d] producers.size() = %d, producerIndex = %d, pIndex = %d, producersDefaultCommandType.size() = %d\n",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__, producers.size(),
|
|
producerIndex, pIndex,
|
|
producersDefaultCommandType.
|
|
size());
|
|
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("produceSpecific giveCommand to unit [%s] commandType [%s]\n",
|
|
aiInterface->getMyUnit(producerIndex)->getType()->
|
|
getName().c_str(),
|
|
(defCt != NULL ? defCt->getName().c_str() : "n/a"));
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"produceSpecific giveCommand to unit [%s] commandType [%s]",
|
|
aiInterface->getMyUnit(producerIndex)->
|
|
getType()->getName().c_str(),
|
|
(defCt !=
|
|
NULL ? defCt->getName().
|
|
c_str() : "(null)"));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
if (defCt != NULL)
|
|
aiInterface->giveCommand(producerIndex, defCt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ========================================
|
|
// class AiRuleBuild
|
|
// ========================================
|
|
|
|
AiRuleBuild::AiRuleBuild(Ai * ai) :
|
|
AiRule(ai) {
|
|
buildTask = NULL;
|
|
}
|
|
|
|
bool
|
|
AiRuleBuild::test() {
|
|
const Task *
|
|
task = ai->getTask();
|
|
|
|
if (task == NULL || task->getClass() != tcBuild) {
|
|
return false;
|
|
}
|
|
|
|
buildTask = static_cast <const BuildTask *>(task);
|
|
return true;
|
|
}
|
|
|
|
|
|
void
|
|
AiRuleBuild::execute() {
|
|
if (buildTask != NULL) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf("BUILD AiRuleBuild Unit Name[%s]\n",
|
|
(buildTask->getUnitType() !=
|
|
NULL ? buildTask->getUnitType()->getName(false).
|
|
c_str() : "null"));
|
|
|
|
//generic build task, build random building that can be built
|
|
if (buildTask->getUnitType() == NULL) {
|
|
buildGeneric(buildTask);
|
|
}
|
|
//specific building task, build if possible, retry if not enough resources or not position
|
|
else {
|
|
buildSpecific(buildTask);
|
|
}
|
|
|
|
//remove the task
|
|
ai->removeTask(buildTask);
|
|
}
|
|
}
|
|
|
|
void
|
|
AiRuleBuild::buildGeneric(const BuildTask * bt) {
|
|
|
|
//find buildings that can be built
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"== START: buildGeneric for resource type [%s]",
|
|
(bt->getResourceType() !=
|
|
NULL ? bt->getResourceType()->getName().
|
|
c_str() : "null"));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
typedef
|
|
vector < const UnitType *>
|
|
UnitTypes;
|
|
UnitTypes
|
|
buildings;
|
|
|
|
if (bt->getResourceType() != NULL) {
|
|
if (aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcResourceProducerUnits).size() > 0) {
|
|
const
|
|
std::vector <
|
|
FactionType::PairPUnitTypeInt > &
|
|
unitList =
|
|
aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcResourceProducerUnits);
|
|
for (unsigned int i = 0; i < unitList.size(); ++i) {
|
|
const
|
|
FactionType::PairPUnitTypeInt &
|
|
priorityUnit = unitList[i];
|
|
if (ai->getCountOfType(priorityUnit.first) <
|
|
priorityUnit.second
|
|
&& aiInterface->getMyFaction()->
|
|
canCreateUnit(priorityUnit.first, true, false,
|
|
false) == true) {
|
|
//if(ai->getRandom()->randRange(0, 1)==0) {
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In buildGeneric for resource type [%s] aibcResourceProducerUnits = "
|
|
MG_SIZE_T_SPECIFIER
|
|
" priorityUnit.first: [%s]\n",
|
|
bt->getResourceType()->getName().
|
|
c_str(), unitList.size(),
|
|
priorityUnit.first->getName().c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->addTask(new BuildTask(priorityUnit.first));
|
|
return;
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcBuildingUnits).size() > 0) {
|
|
const
|
|
std::vector <
|
|
FactionType::PairPUnitTypeInt > &
|
|
unitList =
|
|
aiInterface->getMyFactionType()->
|
|
getAIBehaviorUnits(aibcBuildingUnits);
|
|
for (unsigned int i = 0; i < unitList.size(); ++i) {
|
|
const
|
|
FactionType::PairPUnitTypeInt &
|
|
priorityUnit = unitList[i];
|
|
if (ai->getCountOfType(priorityUnit.first) <
|
|
priorityUnit.second
|
|
&& aiInterface->getMyFaction()->
|
|
canCreateUnit(priorityUnit.first, true, false,
|
|
false) == true) {
|
|
//if(ai->getRandom()->randRange(0, 1)==0) {
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In buildGeneric for resource type [%s] aibcBuildingUnits = "
|
|
MG_SIZE_T_SPECIFIER
|
|
" priorityUnit.first: [%s]\n",
|
|
bt->getResourceType()->getName().
|
|
c_str(), unitList.size(),
|
|
priorityUnit.first->getName().c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->addTask(new BuildTask(priorityUnit.first));
|
|
return;
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//for each unit
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
|
|
//for each command
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(i)->getType();
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is build
|
|
if (ct->getClass() == ccBuild) {
|
|
const BuildCommandType *
|
|
bct = static_cast <const
|
|
BuildCommandType *>(ct);
|
|
|
|
//for each building
|
|
for (int k = 0; k < bct->getBuildingCount(); ++k) {
|
|
const UnitType *
|
|
building = bct->getBuilding(k);
|
|
if (aiInterface->reqsOk(bct)
|
|
&& aiInterface->reqsOk(building)) {
|
|
|
|
//if any building, or produces resource
|
|
const ResourceType *
|
|
rt = bt->getResourceType();
|
|
const Resource *
|
|
cost = building->getCost(rt);
|
|
if (rt == NULL
|
|
|| (cost != NULL && cost->getAmount() < 0)) {
|
|
if (find
|
|
(buildings.begin(), buildings.end(),
|
|
building) == buildings.end()) {
|
|
buildings.push_back(building);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
for (int i = 0; i < (int) buildings.size(); ++i) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In buildGeneric i = %d unit type: [%s]\n", i,
|
|
buildings[i]->getName().c_str());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
}
|
|
|
|
//add specific build task
|
|
buildBestBuilding(buildings);
|
|
}
|
|
|
|
void
|
|
AiRuleBuild::buildBestBuilding(const vector <
|
|
const UnitType * >&buildings) {
|
|
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"==> START buildBestBuilding buildings.size = "
|
|
MG_SIZE_T_SPECIFIER "\n", buildings.size());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
if (!buildings.empty()) {
|
|
|
|
//build the least built building
|
|
bool
|
|
buildingFound = false;
|
|
for (int i = 0; i < 10 && !buildingFound; ++i) {
|
|
|
|
if (i > 0) {
|
|
|
|
//Defensive buildings have priority
|
|
for (int j = 0;
|
|
j < (int) buildings.size() && buildingFound == false;
|
|
++j) {
|
|
const UnitType *
|
|
building = buildings[j];
|
|
if (ai->getCountOfType(building) <= i + 1
|
|
&& isDefensive(building)) {
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In buildBestBuilding defensive building unit type: [%s] i = %d j = %d\n",
|
|
building->getName().c_str(), i, j);
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->addTask(new BuildTask(building));
|
|
buildingFound = true;
|
|
}
|
|
}
|
|
|
|
//Warrior producers next
|
|
for (unsigned int j = 0;
|
|
j < buildings.size() && !buildingFound; ++j) {
|
|
const UnitType *
|
|
building = buildings[j];
|
|
if (ai->getCountOfType(building) <= i + 1
|
|
&& isWarriorProducer(building)) {
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In buildBestBuilding warriorproducer building unit type: [%s] i = %d j = %u\n",
|
|
building->getName().c_str(), i, j);
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->addTask(new BuildTask(building));
|
|
buildingFound = true;
|
|
}
|
|
}
|
|
|
|
//Resource producers next
|
|
for (unsigned int j = 0;
|
|
j < buildings.size() && !buildingFound; ++j) {
|
|
const UnitType *
|
|
building = buildings[j];
|
|
if (ai->getCountOfType(building) <= i + 1
|
|
&& isResourceProducer(building)) {
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In buildBestBuilding resourceproducer building unit type: [%s] i = %d j = %u\n",
|
|
building->getName().c_str(), i, j);
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->addTask(new BuildTask(building));
|
|
buildingFound = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Any building
|
|
for (unsigned int j = 0;
|
|
j < buildings.size() && !buildingFound; ++j) {
|
|
const UnitType *
|
|
building = buildings[j];
|
|
if (ai->getCountOfType(building) <= i) {
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In buildBestBuilding ANY building unit type: [%s] i = %d j = %u\n",
|
|
building->getName().c_str(), i, j);
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->addTask(new BuildTask(building));
|
|
buildingFound = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"==> END buildBestBuilding buildings.size = "
|
|
MG_SIZE_T_SPECIFIER "\n", buildings.size());
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
}
|
|
|
|
void
|
|
AiRuleBuild::buildSpecific(const BuildTask * bt) {
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"== START: buildSpecific for resource type [%s] bt->getUnitType() [%s]",
|
|
(bt->getResourceType() !=
|
|
NULL ? bt->getResourceType()->getName().
|
|
c_str() : "null"),
|
|
(bt->getUnitType() !=
|
|
NULL ? bt->getUnitType()->getName(false).
|
|
c_str() : "null"));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
//if reqs ok
|
|
if (aiInterface->reqsOk(bt->getUnitType())) {
|
|
|
|
//retry if not enough resources
|
|
if (aiInterface->checkCosts(bt->getUnitType(), NULL) == false) {
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In buildSpecific for resource type [%s] checkcosts == false RETRYING",
|
|
(bt->getResourceType() !=
|
|
NULL ? bt->getResourceType()->getName().
|
|
c_str() : "null"));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
ai->retryTask(bt);
|
|
return;
|
|
}
|
|
|
|
vector < int >
|
|
builders;
|
|
// Hold a list of units which can build
|
|
// then a list of build commandtypes for each unit
|
|
map < int,
|
|
vector < const BuildCommandType *> >
|
|
buildersDefaultCommandType;
|
|
const BuildCommandType *
|
|
defBct = NULL;
|
|
|
|
//for each unit
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
|
|
//if the unit is not going to build
|
|
const Unit *
|
|
u = aiInterface->getMyUnit(i);
|
|
if (u->anyCommand() == false
|
|
|| u->getCurrCommand()->getCommandType()->getClass() !=
|
|
ccBuild) {
|
|
|
|
//for each command
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(i)->getType();
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is build
|
|
if (ct->getClass() == ccBuild) {
|
|
const BuildCommandType *
|
|
bct = static_cast <const
|
|
BuildCommandType *>(ct);
|
|
|
|
//for each building
|
|
for (int k = 0; k < bct->getBuildingCount(); ++k) {
|
|
const UnitType *
|
|
building = bct->getBuilding(k);
|
|
|
|
//if building match
|
|
if (bt->getUnitType() == building) {
|
|
if (aiInterface->reqsOk(bct)) {
|
|
builders.push_back(i);
|
|
buildersDefaultCommandType[i].
|
|
push_back(bct);
|
|
//defBct= bct;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//use random builder to build
|
|
if (builders.empty() == false) {
|
|
int
|
|
bIndex =
|
|
ai->getRandom()->randRange(0, (int) builders.size() - 1);
|
|
int
|
|
builderIndex = builders[bIndex];
|
|
Vec2i
|
|
pos;
|
|
Vec2i
|
|
searchPos =
|
|
bt->getForcePos() ? bt->getPos() : ai->
|
|
getRandomHomePosition();
|
|
if (bt->getForcePos() == false) {
|
|
const int
|
|
enemySightDistanceToAvoid = 18;
|
|
vector < Unit * >enemies;
|
|
ai->getAiInterface()->getWorld()->getUnitUpdater()->
|
|
findEnemiesForCell(searchPos,
|
|
bt->getUnitType()->getSize(),
|
|
enemySightDistanceToAvoid,
|
|
ai->getAiInterface()->
|
|
getMyFaction(), enemies, true);
|
|
if (enemies.empty() == false) {
|
|
for (int i1 = 0; i1 < 25 && enemies.empty() == false;
|
|
++i1) {
|
|
for (int j1 = 0;
|
|
j1 < 25 && enemies.empty() == false; ++j1) {
|
|
Vec2i
|
|
tryPos = searchPos + Vec2i(i1, j1);
|
|
|
|
const int
|
|
spacing = 1;
|
|
if (ai->getAiInterface()->
|
|
isFreeCells(tryPos - Vec2i(spacing),
|
|
bt->getUnitType()->
|
|
getSize() + spacing * 2,
|
|
fLand)) {
|
|
enemies.clear();
|
|
ai->getAiInterface()->getWorld()->
|
|
getUnitUpdater()->
|
|
findEnemiesForCell(tryPos,
|
|
bt->getUnitType()->
|
|
getSize(),
|
|
enemySightDistanceToAvoid,
|
|
ai->
|
|
getAiInterface()->
|
|
getMyFaction(),
|
|
enemies, true);
|
|
if (enemies.empty() == true) {
|
|
searchPos = tryPos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (enemies.empty() == false) {
|
|
for (int i1 = -1;
|
|
i1 >= -25 && enemies.empty() == false; --i1) {
|
|
for (int j1 = -1;
|
|
j1 >= -25 && enemies.empty() == false; --j1) {
|
|
Vec2i
|
|
tryPos = searchPos + Vec2i(i1, j1);
|
|
|
|
const int
|
|
spacing = 1;
|
|
if (ai->getAiInterface()->
|
|
isFreeCells(tryPos - Vec2i(spacing),
|
|
bt->getUnitType()->
|
|
getSize() + spacing * 2,
|
|
fLand)) {
|
|
enemies.clear();
|
|
ai->getAiInterface()->getWorld()->
|
|
getUnitUpdater()->
|
|
findEnemiesForCell(tryPos,
|
|
bt->getUnitType()->
|
|
getSize(),
|
|
enemySightDistanceToAvoid,
|
|
ai->
|
|
getAiInterface()->
|
|
getMyFaction(),
|
|
enemies, true);
|
|
if (enemies.empty() == true) {
|
|
searchPos = tryPos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//if free pos give command, else retry
|
|
if (ai->findPosForBuilding(bt->getUnitType(), searchPos, pos)) {
|
|
defBct = NULL;
|
|
if (buildersDefaultCommandType.find(builderIndex) !=
|
|
buildersDefaultCommandType.end()) {
|
|
//defBct = buildersDefaultCommandType[builderIndex];
|
|
int
|
|
bestCommandTypeCount =
|
|
(int) buildersDefaultCommandType[builderIndex].
|
|
size();
|
|
int
|
|
bestCommandTypeIndex =
|
|
ai->getRandom()->randRange(0,
|
|
bestCommandTypeCount -
|
|
1);
|
|
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugSystem).
|
|
enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d] bestCommandTypeIndex = %d, bestCommandTypeCount = %d\n",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__,
|
|
bestCommandTypeIndex,
|
|
bestCommandTypeCount);
|
|
|
|
defBct =
|
|
buildersDefaultCommandType[builderIndex]
|
|
[bestCommandTypeIndex];
|
|
}
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::debugSystem).enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,
|
|
"In [%s::%s Line: %d] builderIndex = %d, bIndex = %d, defBct = %p\n",
|
|
__FILE__, __FUNCTION__,
|
|
__LINE__, builderIndex, bIndex,
|
|
defBct);
|
|
|
|
aiInterface->giveCommand(builderIndex, defBct, pos,
|
|
bt->getUnitType());
|
|
} else {
|
|
ai->retryTask(bt);
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
if (aiInterface->isLogLevelEnabled(4) == true) {
|
|
char
|
|
szBuf[8096] = "";
|
|
snprintf(szBuf, 8096,
|
|
"In buildSpecific for resource type [%s] reqsok == false",
|
|
(bt->getResourceType() !=
|
|
NULL ? bt->getResourceType()->getName().
|
|
c_str() : "null"));
|
|
aiInterface->printLog(4, szBuf);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
bool
|
|
AiRuleBuild::isDefensive(const UnitType * building) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf("BUILD isDefensive check for Unit Name[%s] result = %d\n",
|
|
building->getName(false).c_str(),
|
|
building->hasSkillClass(scAttack));
|
|
|
|
return building->hasSkillClass(scAttack);
|
|
}
|
|
|
|
bool
|
|
AiRuleBuild::isResourceProducer(const UnitType * building) {
|
|
for (int i = 0; i < building->getCostCount(); i++) {
|
|
if (building->getCost(i)->getAmount() < 0) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("BUILD isResourceProducer check for Unit Name[%s] result = true\n",
|
|
building->getName(false).c_str());
|
|
|
|
return true;
|
|
}
|
|
}
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("BUILD isResourceProducer check for Unit Name[%s] result = false\n",
|
|
building->getName(false).c_str());
|
|
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
AiRuleBuild::isWarriorProducer(const UnitType * building) {
|
|
for (int i = 0; i < building->getCommandTypeCount(); i++) {
|
|
const CommandType *
|
|
ct = building->getCommandType(i);
|
|
if (ct->getClass() == ccProduce) {
|
|
const UnitType *
|
|
ut = static_cast <const
|
|
ProduceCommandType *>(ct)->
|
|
getProducedUnit();
|
|
|
|
if (ut->isOfClass(ucWarrior)) {
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("BUILD isWarriorProducer check for Unit Name[%s] result = true\n",
|
|
building->getName(false).c_str());
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
if (ai->outputAIBehaviourToConsole())
|
|
printf
|
|
("BUILD isWarriorProducer check for Unit Name[%s] result = false\n",
|
|
building->getName(false).c_str());
|
|
|
|
return false;
|
|
}
|
|
|
|
// ========================================
|
|
// class AiRuleUpgrade
|
|
// ========================================
|
|
|
|
AiRuleUpgrade::AiRuleUpgrade(Ai * ai) :
|
|
AiRule(ai) {
|
|
upgradeTask = NULL;
|
|
}
|
|
|
|
bool
|
|
AiRuleUpgrade::test() {
|
|
const Task *
|
|
task = ai->getTask();
|
|
|
|
if (task == NULL || task->getClass() != tcUpgrade) {
|
|
return false;
|
|
}
|
|
|
|
upgradeTask = static_cast <const UpgradeTask *>(task);
|
|
return true;
|
|
}
|
|
|
|
void
|
|
AiRuleUpgrade::execute() {
|
|
|
|
//upgrade any upgrade
|
|
if (upgradeTask->getUpgradeType() == NULL) {
|
|
upgradeGeneric(upgradeTask);
|
|
}
|
|
//upgrade specific upgrade
|
|
else {
|
|
upgradeSpecific(upgradeTask);
|
|
}
|
|
|
|
//remove the task
|
|
ai->removeTask(upgradeTask);
|
|
}
|
|
|
|
void
|
|
AiRuleUpgrade::upgradeGeneric(const UpgradeTask * upgt) {
|
|
|
|
typedef
|
|
vector < const UpgradeType *>
|
|
UpgradeTypes;
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
//find upgrades that can be upgraded
|
|
UpgradeTypes
|
|
upgrades;
|
|
|
|
if (aiInterface->getMyFactionType()->getAIBehaviorUpgrades().size() >
|
|
0) {
|
|
const
|
|
std::vector < const UpgradeType *>&
|
|
upgradeList =
|
|
aiInterface->getMyFactionType()->getAIBehaviorUpgrades();
|
|
for (unsigned int i = 0; i < upgradeList.size(); ++i) {
|
|
const UpgradeType *
|
|
priorityUpgrade = upgradeList[i];
|
|
|
|
//for each upgrade, upgrade it if possible
|
|
for (int k = 0; k < aiInterface->getMyUnitCount(); ++k) {
|
|
|
|
//for each command
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(k)->getType();
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is upgrade
|
|
if (ct->getClass() == ccUpgrade) {
|
|
const UpgradeCommandType *
|
|
upgct = dynamic_cast <const
|
|
UpgradeCommandType *>(ct);
|
|
if (upgct != NULL) {
|
|
const UpgradeType *
|
|
upgrade = upgct->getProducedUpgrade();
|
|
if (upgrade == priorityUpgrade) {
|
|
if (aiInterface->reqsOk(upgct) == true &&
|
|
aiInterface->getMyFaction()->
|
|
getUpgradeManager()->
|
|
isUpgradingOrUpgraded(priorityUpgrade)
|
|
== false) {
|
|
//if(ai->getRandom()->randRange(0, 1)==0) {
|
|
ai->
|
|
addTask(new
|
|
UpgradeTask
|
|
(priorityUpgrade));
|
|
return;
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//for each upgrade, upgrade it if possible
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
|
|
//for each command
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(i)->getType();
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is upgrade
|
|
if (ct->getClass() == ccUpgrade) {
|
|
const UpgradeCommandType *
|
|
upgct = static_cast <const
|
|
UpgradeCommandType *>(ct);
|
|
const UpgradeType *
|
|
upgrade = upgct->getProducedUpgrade();
|
|
if (aiInterface->reqsOk(upgct)) {
|
|
upgrades.push_back(upgrade);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//add specific upgrade task
|
|
if (!upgrades.empty()) {
|
|
ai->
|
|
addTask(new
|
|
UpgradeTask(upgrades
|
|
[ai->getRandom()->
|
|
randRange(0,
|
|
(int) upgrades.size() - 1)]));
|
|
}
|
|
}
|
|
|
|
void
|
|
AiRuleUpgrade::upgradeSpecific(const UpgradeTask * upgt) {
|
|
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
//if reqs ok
|
|
if (aiInterface->reqsOk(upgt->getUpgradeType())) {
|
|
|
|
//if resources dont meet retry
|
|
if (!aiInterface->checkCosts(upgt->getUpgradeType(), NULL)) {
|
|
ai->retryTask(upgt);
|
|
return;
|
|
}
|
|
|
|
//for each unit
|
|
for (int i = 0; i < aiInterface->getMyUnitCount(); ++i) {
|
|
|
|
//for each command
|
|
const UnitType *
|
|
ut = aiInterface->getMyUnit(i)->getType();
|
|
for (int j = 0; j < ut->getCommandTypeCount(); ++j) {
|
|
const CommandType *
|
|
ct = ut->getCommandType(j);
|
|
|
|
//if the command is upgrade
|
|
if (ct->getClass() == ccUpgrade) {
|
|
const UpgradeCommandType *
|
|
uct = static_cast <const
|
|
UpgradeCommandType *>(ct);
|
|
const UpgradeType *
|
|
producedUpgrade = uct->getProducedUpgrade();
|
|
|
|
//if upgrades match
|
|
if (producedUpgrade == upgt->getUpgradeType()) {
|
|
if (aiInterface->reqsOk(uct)) {
|
|
if (SystemFlags::
|
|
getSystemSettingType(SystemFlags::
|
|
debugSystem).enabled)
|
|
SystemFlags::OutputDebug(SystemFlags::
|
|
debugSystem,
|
|
"In [%s::%s Line: %d]\n",
|
|
__FILE__,
|
|
__FUNCTION__,
|
|
__LINE__);
|
|
aiInterface->giveCommand(i, uct);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// ========================================
|
|
// class AiRuleExpand
|
|
// ========================================
|
|
|
|
AiRuleExpand::AiRuleExpand(Ai * ai) :
|
|
AiRule(ai) {
|
|
storeType = NULL;
|
|
}
|
|
|
|
bool
|
|
AiRuleExpand::test() {
|
|
AiInterface *
|
|
aiInterface = ai->getAiInterface();
|
|
|
|
int
|
|
unitCount = aiInterface->getMyUnitCount();
|
|
for (int i = 0;
|
|
i < aiInterface->getTechTree()->getResourceTypeCount(); ++i) {
|
|
const ResourceType *
|
|
rt = aiInterface->getTechTree()->getResourceType(i);
|
|
if (rt->getClass() == rcTech) {
|
|
bool
|
|
factionUsesResourceType =
|
|
aiInterface->factionUsesResourceType(aiInterface->
|
|
getMyFactionType(),
|
|
rt);
|
|
if (factionUsesResourceType == true) {
|
|
// If any resource sighted
|
|
if (aiInterface->
|
|
getNearestSightedResource(rt,
|
|
aiInterface->
|
|
getHomeLocation(),
|
|
expandPos, true)) {
|
|
int
|
|
minDistance = INT_MAX;
|
|
storeType = NULL;
|
|
|
|
//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 (ut->getStore(rt) > 0) {
|
|
storeType = ut;
|
|
int
|
|
distance =
|
|
static_cast <
|
|
int>(u->getPosNotThreadSafe().
|
|
dist(expandPos));
|
|
if (distance < minDistance) {
|
|
minDistance = distance;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (minDistance > expandDistance) {
|
|
return true;
|
|
}
|
|
} else {
|
|
// send patrol to look for resource
|
|
ai->sendScoutPatrol();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
AiRuleExpand::execute() {
|
|
ai->addExpansion(expandPos);
|
|
ai->addPriorityTask(new BuildTask(storeType, expandPos));
|
|
}
|
|
|
|
|
|
// ========================================
|
|
// class AiRuleUnBlock
|
|
// ========================================
|
|
|
|
AiRuleUnBlock::AiRuleUnBlock(Ai * ai) :
|
|
AiRule(ai) {
|
|
|
|
}
|
|
|
|
bool
|
|
AiRuleUnBlock::test() {
|
|
return ai->haveBlockedUnits();
|
|
}
|
|
|
|
void
|
|
AiRuleUnBlock::execute() {
|
|
ai->unblockUnits();
|
|
}
|
|
|
|
}
|
|
} //end namespace
|