// ============================================================== // This file is part of Glest (www.glest.org) // // Copyright (C) 2001-2008 Martio 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 #include #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) { } double AiRuleRepair::getMinCastleHpRatio() { return 0.6; } int AiRuleRepair::getMinUnitsToRepairCastle() { int minUnitsRepairingCastle = 7; if(ai->getCountOfClass(ucWorker) <= 4) { minUnitsRepairingCastle = 1; } else if(ai->getCountOfClass(ucWorker) <= 7) { minUnitsRepairingCastle = 2; } else if(ai->getCountOfClass(ucWorker) <= 10) { 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(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; } } } } int candidatedamagedUnitIndex=-1; if(unitCanProduceWorker == true) { 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(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; return true; } } } } // 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(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; 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(); 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(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() == scRepair) { Command *cmd = u1->getCurrCommand(); if(cmd != NULL && cmd->getCommandType()->getClass() == ccRepair) { if(cmd->getUnit() != NULL && cmd->getUnit()->getId() == damagedUnit->getId()) { //printf("\n\n\n\n^^^^^^^^^^ unit is ALREADY repairer unit [%d - %s]\n",u1->getId(),u1->getType()->getName().c_str()); unitCountAlreadyRepairingDamagedUnit++; } } } } } //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(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(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) { aiInterface->giveCommand(i, rct, damagedUnit->getPosWithCellMapSet()); aiInterface->printLog(3, "Repairing order issued"); unitCountAlreadyRepairingDamagedUnit++; } if(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) { } 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; } 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)); } else{ if( ai->getAiInterface()->getControlType() == ctCpuMega || ai->getAiInterface()->getControlType() == ctNetworkCpuMega) { 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<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)); if(warriorCountminWarriors+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()); if(buildingCount<10 && workerCount>12) ai->addTask(new BuildTask()); //upgrades if(upgradeCount==0 && workerCount>5) ai->addTask(new UpgradeTask()); if(upgradeCount==1 && workerCount>10) ai->addTask(new UpgradeTask()); if(upgradeCount==2 && workerCount>15) ai->addTask(new UpgradeTask()); if(ai->isStableBase()) ai->addTask(new UpgradeTask()); } 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(workerCountaddTask(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()); if(buildingCount<10 && ai->isStableBase()) ai->addTask(new BuildTask()); //upgrades if(upgradeCount==0 && workerCount>6) ai->addTask(new UpgradeTask()); if(upgradeCount==1 && workerCount>7) ai->addTask(new UpgradeTask()); if(upgradeCount==2 && workerCount>9) ai->addTask(new UpgradeTask()); //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()); if(buildingCount<10 && workerCount>12) ai->addTask(new BuildTask()); //upgrades if(upgradeCount==0 && workerCount>5) ai->addTask(new UpgradeTask()); if(upgradeCount==1 && workerCount>10) ai->addTask(new UpgradeTask()); if(upgradeCount==2 && workerCount>15) ai->addTask(new UpgradeTask()); if(ai->isStableBase()) ai->addTask(new UpgradeTask()); } } } // ===================================================== // class AiRuleBuildOneFarm // ===================================================== AiRuleBuildOneFarm::AiRuleBuildOneFarm(Ai *ai): AiRule(ai) { } bool AiRuleBuildOneFarm::test(){ AiInterface *aiInterface= ai->getAiInterface(); //for all units for(int i=0; igetMyFactionType()->getUnitTypeCount(); ++i){ const UnitType *ut= aiInterface->getMyFactionType()->getUnitType(i); //for all production commands for(int j=0; jgetCommandTypeCount(); ++j){ const CommandType *ct= ut->getCommandType(j); if(ct->getClass()==ccProduce){ const UnitType *producedType= static_cast(ct)->getProducedUnit(); //for all resources for(int k=0; kgetCostCount(); ++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){ farm= ut; 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; } bool AiRuleProduceResourceProducer::test(){ //emergency tasks: resource buildings AiInterface *aiInterface= ai->getAiInterface(); //consumables first for(int i=0; igetTechTree()->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()); bool factionUsesResourceType = aiInterface->factionUsesResourceType(aiInterface->getMyFactionType(), rt); //if(rt->getClass()==rcConsumable && r->getBalance()<0){ if(factionUsesResourceType == true && rt->getClass() == rcConsumable && r->getBalance() < 0) { interval= longInterval; return true; } } //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(), minStaticResources, this->getName().c_str()); if(rt->getClass() == rcStatic && r->getAmount() < minStaticResources) { bool factionUsesResourceType = aiInterface->factionUsesResourceType(aiInterface->getMyFactionType(), rt); if(factionUsesResourceType == true) { interval= longInterval; return true; } } } if(ai->outputAIBehaviourToConsole()) printf("STATIC returning FALSE\n"); 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; } bool AiRuleProduce::test(){ const Task *task= ai->getTask(); if(task==NULL || task->getClass()!=tcProduce){ return false; } produceTask= static_cast(task); return true; } void AiRuleProduce::execute(){ if(produceTask!=NULL){ if(ai->outputAIBehaviourToConsole()) printf("AiRuleProduce producing [%s]\n",(produceTask->getUnitType() != NULL ? produceTask->getUnitType()->getName().c_str() : "null")); //generic produce task, produce random unit that has the skill or produces the resource if(produceTask->getUnitType()==NULL){ produceGeneric(produceTask); } //specific produce task, produce if possible, retry if not enough resources else{ produceSpecific(produceTask); } //remove the task ai->removeTask(produceTask); } } void AiRuleProduce::produceGeneric(const ProduceTask *pt){ typedef vector UnitTypes; UnitTypes ableUnits; AiInterface *aiInterface= ai->getAiInterface(); //for each unit, produce it if possible for(int i=0; igetMyUnitCount(); ++i){ //for each command const UnitType *ut= aiInterface->getMyUnit(i)->getType(); for(int j=0; jgetCommandTypeCount(); ++j){ const CommandType *ct= ut->getCommandType(j); //if the command is produce if(ct->getClass()==ccProduce || ct->getClass()==ccMorph){ const UnitType *producedUnit= static_cast(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().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()){ 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; igetCountOfType(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, ableUnits.size()-1)])); } } void AiRuleProduce::produceSpecific(const ProduceTask *pt){ AiInterface *aiInterface= ai->getAiInterface(); if(ai->outputAIBehaviourToConsole()) printf("produceSpecific aiInterface->reqsOk(pt->getUnitType()) = [%d] Testing AI RULE Name[%s]\n",aiInterface->reqsOk(pt->getUnitType()), this->getName().c_str()); //if unit meets requirements if(aiInterface->reqsOk(pt->getUnitType())){ if(ai->outputAIBehaviourToConsole()) printf("produceSpecific aiInterface->checkCosts(pt->getUnitType()) = [%d] Testing AI RULE Name[%s]\n",aiInterface->checkCosts(pt->getUnitType()), this->getName().c_str()); //if unit doesnt meet resources retry if(!aiInterface->checkCosts(pt->getUnitType())){ ai->retryTask(pt); return; } //produce specific unit vector producers; // Hold a list of units which can produce or morph // then a list of commandtypes for each unit map > producersDefaultCommandType; const CommandType *defCt= NULL; //for each unit for(int i=0; igetMyUnitCount(); ++i){ //for each command const UnitType *ut= aiInterface->getMyUnit(i)->getType(); for(int j=0; jgetCommandTypeCount(); ++j){ const CommandType *ct= ut->getCommandType(j); //if the command is produce if(ct->getClass()==ccProduce || ct->getClass()==ccMorph){ const UnitType *producedUnit= static_cast(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()){ if(ai->outputAIBehaviourToConsole()) printf("produceSpecific producers.empty() = [%d] Testing AI RULE Name[%s]\n",producers.empty(), this->getName().c_str()); if( aiInterface->getControlType() == ctCpuMega || aiInterface->getControlType() == ctNetworkCpuMega) {// mega cpu trys to balance the commands to the producers int randomstart=ai->getRandom()->randRange(0, 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()) { prIndex = (i - producers.size()); } currentProducerIndex=producers[prIndex]; if(currentProducerIndex >= aiInterface->getMyUnitCount()) { char szBuf[1024]=""; printf("In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %d, i = %d,producers.size() = %lu\n",__FILE__,__FUNCTION__,__LINE__,currentProducerIndex,aiInterface->getMyUnitCount(),i,(unsigned long)producers.size()); sprintf(szBuf,"In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %d, i = %d,producers.size() = %lu",__FILE__,__FUNCTION__,__LINE__,currentProducerIndex,aiInterface->getMyUnitCount(),i,(unsigned long)producers.size()); throw runtime_error(szBuf); } if(prIndex >= producers.size()) { char szBuf[1024]=""; printf("In [%s::%s Line: %d] prIndex >= producers.size(), currentProducerIndex = %d, i = %d,producers.size() = %lu \n",__FILE__,__FUNCTION__,__LINE__,prIndex,i,(unsigned long)producers.size()); sprintf(szBuf,"In [%s::%s Line: %d] currentProducerIndex >= producers.size(), currentProducerIndex = %d, i = %d,producers.size() = %lu",__FILE__,__FUNCTION__,__LINE__,currentProducerIndex,i,(unsigned long)producers.size()); throw 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( 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 backupProducers; // find another producer unit which is free and produce any kind of warrior. //for each unit for(int i=0; igetMyUnitCount(); ++i){ const UnitType *ut= aiInterface->getMyUnit(i)->getType(); //for each command for(int j=0; jgetCommandTypeCount(); ++j){ const CommandType *ct= ut->getCommandType(j); //if the command is produce if(ct->getClass() == ccProduce) { const UnitType *unitType= static_cast(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, backupProducers.size()-1); int lowestCommandCount=1000000; int currentProducerIndex=backupProducers[randomstart]; int bestIndex=-1; int currentCommandCount=0; for(unsigned int i=randomstart; i= backupProducers.size()) { prIndex = (i - backupProducers.size()); } currentProducerIndex=backupProducers[prIndex]; if(currentProducerIndex >= aiInterface->getMyUnitCount()) { char szBuf[1024]=""; printf("In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %d, i = %d,backupProducers.size() = %lu\n",__FILE__,__FUNCTION__,__LINE__,currentProducerIndex,aiInterface->getMyUnitCount(),i,(unsigned long)backupProducers.size()); sprintf(szBuf,"In [%s::%s Line: %d] currentProducerIndex >= aiInterface->getMyUnitCount(), currentProducerIndex = %d, aiInterface->getMyUnitCount() = %d, i = %d,backupProducers.size() = %lu",__FILE__,__FUNCTION__,__LINE__,currentProducerIndex,aiInterface->getMyUnitCount(),i,(unsigned long)backupProducers.size()); throw runtime_error(szBuf); } if(prIndex >= backupProducers.size()) { char szBuf[1024]=""; printf("In [%s::%s Line: %d] prIndex >= backupProducers.size(), currentProducerIndex = %d, i = %d,backupProducers.size() = %lu \n",__FILE__,__FUNCTION__,__LINE__,prIndex,i,(unsigned long)backupProducers.size()); sprintf(szBuf,"In [%s::%s Line: %d] currentProducerIndex >= backupProducers.size(), currentProducerIndex = %d, i = %d,backupProducers.size() = %lu",__FILE__,__FUNCTION__,__LINE__,currentProducerIndex,i,(unsigned long)backupProducers.size()); throw 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=currentCommandCount; bestIndex=currentProducerIndex; if(lowestCommandCount==0) break; } } // a good producer is found, lets choose a warrior production vector productionCommandIndexes; const UnitType *ut=aiInterface->getMyUnit(bestIndex)->getType(); for(int j=0; jgetCommandTypeCount(); ++j){ const CommandType *ct= ut->getCommandType(j); //if the command is produce if(ct->getClass()==ccProduce) { const UnitType *unitType= static_cast(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, 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("mega #1 produceSpecific giveCommand to unit [%s] commandType [%s]\n",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),ut->getCommandType(commandIndex)->getName().c_str()); 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 = 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("mega #2 produceSpecific giveCommand to unit [%s] commandType [%s]\n",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),defCt->getName().c_str()); 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 = 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("mega #3 produceSpecific giveCommand to unit [%s] commandType [%s]\n",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),defCt->getName().c_str()); 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 = 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("mega #4 produceSpecific giveCommand to unit [%s] commandType [%s]\n",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),defCt->getName().c_str()); aiInterface->giveCommand(bestIndex, defCt); } } else { int pIndex = ai->getRandom()->randRange(0, producers.size()-1); int producerIndex= producers[pIndex]; defCt = NULL; if(producersDefaultCommandType.find(producerIndex) != producersDefaultCommandType.end()) { //defCt = producersDefaultCommandType[producerIndex]; int bestCommandTypeCount = 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->getName().c_str()); 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(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().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(); typedef vector UnitTypes; UnitTypes buildings; //for each unit for(int i=0; igetMyUnitCount(); ++i){ //for each command const UnitType *ut= aiInterface->getMyUnit(i)->getType(); for(int j=0; jgetCommandTypeCount(); ++j){ const CommandType *ct= ut->getCommandType(j); //if the command is build if(ct->getClass()==ccBuild){ const BuildCommandType *bct= static_cast(ct); //for each building for(int k=0; kgetBuildingCount(); ++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)){ buildings.push_back(building); } } } } } } //add specific build task buildBestBuilding(buildings); } void AiRuleBuild::buildBestBuilding(const vector &buildings){ 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; jgetCountOfType(building)<=i+1 && isDefensive(building)) { ai->addTask(new BuildTask(building)); buildingFound= true; } } //Warrior producers next for(unsigned int j=0; jgetCountOfType(building)<=i+1 && isWarriorProducer(building)) { ai->addTask(new BuildTask(building)); buildingFound= true; } } //Resource producers next for(unsigned int j=0; jgetCountOfType(building)<=i+1 && isResourceProducer(building)) { ai->addTask(new BuildTask(building)); buildingFound= true; } } } //Any building for(unsigned int j=0; jgetCountOfType(building)<=i) { ai->addTask(new BuildTask(building)); buildingFound= true; } } } } } void AiRuleBuild::buildSpecific(const BuildTask *bt) { AiInterface *aiInterface= ai->getAiInterface(); //if reqs ok if(aiInterface->reqsOk(bt->getUnitType())) { //retry if not enough resources if(aiInterface->checkCosts(bt->getUnitType()) == false) { ai->retryTask(bt); return; } vector builders; // Hold a list of units which can build // then a list of build commandtypes for each unit map > 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(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, 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 enemies; ai->getAiInterface()->getWorld()->getUnitUpdater()->findEnemiesForCell(searchPos,bt->getUnitType()->getSize(),enemySightDistanceToAvoid,ai->getAiInterface()->getMyFaction(),enemies,true); if(enemies.size() > 0) { for(int i1 = 0; i1 < 25 && enemies.size() > 0; ++i1) { for(int j1 = 0; j1 < 25 && enemies.size() > 0; ++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.size() <= 0) { searchPos = tryPos; } } } } } if(enemies.size() > 0) { for(int i1 = -1; i1 >= -25 && enemies.size() > 0; --i1) { for(int j1 = -1; j1 >= -25 && enemies.size() > 0; --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.size() <= 0) { 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 = 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; } } } } bool AiRuleBuild::isDefensive(const UnitType *building){ if(ai->outputAIBehaviourToConsole()) printf("BUILD isDefensive check for Unit Name[%s] result = %d\n",building->getName().c_str(),building->hasSkillClass(scAttack)); return building->hasSkillClass(scAttack); } bool AiRuleBuild::isResourceProducer(const UnitType *building){ for(int i= 0; igetCostCount(); i++){ if(building->getCost(i)->getAmount()<0){ if(ai->outputAIBehaviourToConsole()) printf("BUILD isResourceProducer check for Unit Name[%s] result = true\n",building->getName().c_str()); return true; } } if(ai->outputAIBehaviourToConsole()) printf("BUILD isResourceProducer check for Unit Name[%s] result = false\n",building->getName().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(ct)->getProducedUnit(); if(ut->isOfClass(ucWarrior)){ if(ai->outputAIBehaviourToConsole()) printf("BUILD isWarriorProducer check for Unit Name[%s] result = true\n",building->getName().c_str()); return true; } } } if(ai->outputAIBehaviourToConsole()) printf("BUILD isWarriorProducer check for Unit Name[%s] result = false\n",building->getName().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(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 UpgradeTypes; AiInterface *aiInterface= ai->getAiInterface(); //find upgrades that can be upgraded UpgradeTypes upgrades; //for each upgrade, upgrade it if possible for(int i=0; igetMyUnitCount(); ++i){ //for each command const UnitType *ut= aiInterface->getMyUnit(i)->getType(); for(int j=0; jgetCommandTypeCount(); ++j){ const CommandType *ct= ut->getCommandType(j); //if the command is upgrade if(ct->getClass()==ccUpgrade){ const UpgradeCommandType *upgct= static_cast(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, 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())){ ai->retryTask(upgt); return; } //for each unit for(int i=0; igetMyUnitCount(); ++i){ //for each command const UnitType *ut= aiInterface->getMyUnit(i)->getType(); for(int j=0; jgetCommandTypeCount(); ++j){ const CommandType *ct= ut->getCommandType(j); //if the command is upgrade if(ct->getClass()==ccUpgrade){ const UpgradeCommandType *uct= static_cast(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 (u->getPos().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