// ============================================================== // 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 #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) { 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(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(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(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(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(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; } 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(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(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((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; 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) { 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; 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()); 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(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(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& 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 &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 &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(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 UnitTypes; UnitTypes ableUnits; AiInterface *aiInterface= ai->getAiInterface(); if(pt->getResourceType() != NULL) { if(aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcResourceProducerUnits).size() > 0) { const std::vector &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 &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 &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(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; igetMyUnitCount(); ++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; 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)){ if(ctypeForCostCheck == NULL || ct->getClass() == ccMorph) { if(ctypeForCostCheck != NULL && ct->getClass() == ccMorph) { const MorphCommandType *mct = dynamic_cast(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 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){ 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; 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() == 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 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() == ctCpuMega || aiInterface->getControlType() == ctNetworkCpuMega) {// mega 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()) { 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 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, (int)backupProducers.size()-1); int lowestCommandCount=1000000; int currentProducerIndex=backupProducers[randomstart]; int bestIndex=-1; for(unsigned int i=randomstart; 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 productionCommandIndexes; if(bestIndex >= 0) { 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, (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("mega #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,"mega #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("mega #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,"mega #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); } 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("mega #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,"mega #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); } 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("mega #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,"mega #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); } 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); } 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(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 UnitTypes; UnitTypes buildings; if(bt->getResourceType() != NULL) { if(aiInterface->getMyFactionType()->getAIBehaviorUnits(aibcResourceProducerUnits).size() > 0) { const std::vector &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 &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; 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)){ 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 &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; jgetCountOfType(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; jgetCountOfType(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; jgetCountOfType(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 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, (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 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; igetCostCount(); 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(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(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; if(aiInterface->getMyFactionType()->getAIBehaviorUpgrades().size() > 0) { const std::vector &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(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; 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, (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; 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->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