diff --git a/source/glest_game/ai/ai.cpp b/source/glest_game/ai/ai.cpp index 0bb08804..612078f1 100644 --- a/source/glest_game/ai/ai.cpp +++ b/source/glest_game/ai/ai.cpp @@ -311,8 +311,11 @@ void Ai::update() { } } - if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] AI for faction# %d voted %s [%d] factionSwitchTeamRequestCountCurrent [%d] settings->getAiAcceptSwitchTeamPercentChance() [%d]\n",__FILE__,__FUNCTION__,__LINE__,aiInterface->getMyFaction()->getIndex(),(voteResult->allowSwitchTeam ? "Yes" : "No"),allowJoinTeam,factionSwitchTeamRequestCountCurrent,settings->getAiAcceptSwitchTeamPercentChance()); - //printf("AI for faction# %d voted %s [%d] factionSwitchTeamRequestCountCurrent [%d]\n",aiInterface->getMyFaction()->getIndex(),(voteResult->allowSwitchTeam ? "Yes" : "No"),allowJoinTeam,factionSwitchTeamRequestCountCurrent); + char szBuf[8096]=""; + sprintf(szBuf,"AI for faction# %d voted %s [%d] CountCurrent [%d] PercentChance [%d]",aiInterface->getMyFaction()->getIndex(),(voteResult->allowSwitchTeam ? "Yes" : "No"),allowJoinTeam,factionSwitchTeamRequestCountCurrent,settings->getAiAcceptSwitchTeamPercentChance()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf); + + aiInterface->printLog(3, szBuf); aiInterface->giveCommandSwitchTeamVote(aiInterface->getMyFaction(),voteResult); } @@ -397,55 +400,62 @@ const ResourceType *Ai::getNeededResource(int unitIndex) { const ResourceType *rt= tt->getResourceType(i); const Resource *r= aiInterface->getResource(rt); + if( rt->getClass() != rcStatic && rt->getClass() != rcConsumable) { + char szBuf[8096]=""; + sprintf(szBuf,"Examining resource [%s] amount [%d] (previous amount [%d]",rt->getName().c_str(),r->getAmount(),amount); + aiInterface->printLog(3, szBuf); + } + if( rt->getClass() != rcStatic && rt->getClass() != rcConsumable && r->getAmount() < amount) { - // Now MAKE SURE the unit has a harvest command for this resource - // AND that the resource is within eye-sight to avoid units - // standing around doing nothing. - const HarvestCommandType *hct= unit->getType()->getFirstHarvestCommand(rt,unit->getFaction()); + // Only have up to x units going for this resource so we can focus + // on other needed resources for other units + const int maxUnitsToHarvestResource = 5; - Vec2i resPos; - if(hct != NULL && aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), resPos, false)) { - amount= r->getAmount(); - neededResource= rt; + vector unitsGettingResource = findUnitsHarvestingResourceType(rt); + if(unitsGettingResource.size() <= maxUnitsToHarvestResource) { + // Now MAKE SURE the unit has a harvest command for this resource + // AND that the resource is within eye-sight to avoid units + // standing around doing nothing. + const HarvestCommandType *hct= unit->getType()->getFirstHarvestCommand(rt,unit->getFaction()); + Vec2i resPos; + if(hct != NULL && aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), resPos, false)) { + amount= r->getAmount(); + neededResource= rt; + } } } } + + char szBuf[8096]=""; + sprintf(szBuf,"Unit [%d - %s] looking for resources (not static or consumable)",unit->getId(),unit->getType()->getName().c_str()); + aiInterface->printLog(3, szBuf); + sprintf(szBuf,"[resource type count %d] Needed resource [%s].",tt->getResourceTypeCount(),(neededResource != NULL ? neededResource->getName().c_str() : "")); + aiInterface->printLog(3, szBuf); + return neededResource; } bool Ai::beingAttacked(Vec2i &pos, Field &field, int radius){ - const Unit *enemy = aiInterface->getFirstOnSightEnemyUnit(pos, field, radius); return (enemy != NULL); -/* - int count= aiInterface->onSightUnitCount(); - const Unit *unit; - - for(int i=0; igetOnSightUnit(i); - if(!aiInterface->isAlly(unit) && unit->isAlive()){ - pos= unit->getPos(); - field= unit->getCurrField(); - if(pos.dist(aiInterface->getHomeLocation())printLog(2, "Being attacked at pos "+intToStr(pos.x)+","+intToStr(pos.y)+"\n"); - return true; - } - } - } - return false; -*/ } bool Ai::isStableBase() { UnitClass ucWorkerType = ucWorker; if(getCountOfClass(ucWarrior,&ucWorkerType) > minWarriors) { - aiInterface->printLog(4, "Base is stable\n"); + char szBuf[8096]=""; + sprintf(szBuf,"Base is stable [minWarriors = %d found = %d]",minWarriors,ucWorkerType); + aiInterface->printLog(4, szBuf); + return true; } else{ - aiInterface->printLog(4, "Base is not stable\n"); + char szBuf[8096]=""; + sprintf(szBuf,"Base is NOT stable [minWarriors = %d found = %d]",minWarriors,ucWorkerType); + aiInterface->printLog(4, szBuf); + return false; } } @@ -472,6 +482,83 @@ bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly){ } } +vector Ai::findUnitsHarvestingResourceType(const ResourceType *rt) { + vector units; + + Map *map= aiInterface->getMap(); + for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) { + const Unit *unit= aiInterface->getMyUnit(i); + if(unit->getType()->hasCommandClass(ccHarvest)) { + if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccHarvest) { + Command *command= unit->getCurrCommand(); + const HarvestCommandType *hct= dynamic_cast(command->getCommandType()); + if(hct != NULL) { + const Vec2i unitTargetPos = unit->getTargetPos(); + SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unitTargetPos)); + Resource *r= sc->getResource(); + if (r != NULL && r->getType() == rt) { + units.push_back(i); + } + } + } + } + else if(unit->getType()->hasCommandClass(ccProduce)) { + if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccProduce) { + Command *command= unit->getCurrCommand(); + const ProduceCommandType *pct= dynamic_cast(command->getCommandType()); + if(pct != NULL) { + const UnitType *ut = pct->getProducedUnit(); + if(ut != NULL) { + const Resource *r = ut->getCost(rt); + if(r != NULL) { + if (r != NULL && r->getAmount() < 0) { + units.push_back(i); + } + } + } + } + } + } + else if(unit->getType()->hasCommandClass(ccBuild)) { + if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == ccBuild) { + Command *command= unit->getCurrCommand(); + const BuildCommandType *bct= dynamic_cast(command->getCommandType()); + if(bct != NULL) { + for(unsigned int j = 0; j < bct->getBuildingCount(); ++j) { + const UnitType *ut = bct->getBuilding(j); + if(ut != NULL) { + const Resource *r = ut->getCost(rt); + if(r != NULL) { + if (r != NULL && r->getAmount() < 0) { + units.push_back(i); + break; + } + } + } + } + } + } + } + } + + return units; +} + +vector Ai::findUnitsDoingCommand(CommandClass currentCommand) { + vector units; + + for(int i = 0; i < aiInterface->getMyUnitCount(); ++i) { + const Unit *unit= aiInterface->getMyUnit(i); + if(unit->getType()->hasCommandClass(currentCommand)) { + if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass() == currentCommand) { + units.push_back(i); + } + } + } + + return units; +} + bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, CommandClass currentCommand){ vector units; diff --git a/source/glest_game/ai/ai.h b/source/glest_game/ai/ai.h index 5d07d892..c7bdf93b 100644 --- a/source/glest_game/ai/ai.h +++ b/source/glest_game/ai/ai.h @@ -190,6 +190,9 @@ public: bool findPosForBuilding(const UnitType* building, const Vec2i &searchPos, Vec2i &pos); bool findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly); bool findAbleUnit(int *unitIndex, CommandClass ability, CommandClass currentCommand); + vector findUnitsDoingCommand(CommandClass currentCommand); + vector findUnitsHarvestingResourceType(const ResourceType *rt); + bool beingAttacked(Vec2i &pos, Field &field, int radius); //tasks diff --git a/source/glest_game/ai/ai_interface.cpp b/source/glest_game/ai/ai_interface.cpp index 3eb4df6d..a0ab391f 100644 --- a/source/glest_game/ai/ai_interface.cpp +++ b/source/glest_game/ai/ai_interface.cpp @@ -51,18 +51,29 @@ AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex, int useSta logLevel= Config::getInstance().getInt("AiLog"); redir= Config::getInstance().getBool("AiRedir"); + aiLogFile = getLogFilename(); + if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") { + aiLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + aiLogFile; + } + else { + string userData = Config::getInstance().getString("UserData_Root",""); + if(userData != "") { + endPathWithSlash(userData); + } + aiLogFile = userData + aiLogFile; + } + //clear log file - if(logLevel>0){ + if(logLevel > 0) { #ifdef WIN32 - FILE *f= _wfopen(Shared::Platform::utf8_decode(getLogFilename()).c_str(), L"wt"); + fp = _wfopen(Shared::Platform::utf8_decode(aiLogFile).c_str(), L"wt"); #else - FILE *f= fopen(getLogFilename().c_str(), "wt"); + fp = fopen(aiLogFile.c_str(), "wt"); #endif - if(f==NULL){ - throw runtime_error("Can't open file: "+getLogFilename()); + if(fp == NULL) { + throw runtime_error("Can't open file: [" + aiLogFile + "]"); } - fprintf(f, "%s", "MegaGlest AI log file\n\n"); - fclose(f); + fprintf(fp, "MegaGlest AI log file for Tech [%s] Faction [%s] #%d\n\n",this->gameSettings->getTech().c_str(),this->world->getFaction(this->factionIndex)->getType()->getName().c_str(),this->factionIndex); } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } @@ -70,6 +81,11 @@ AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex, int useSta AiInterface::~AiInterface() { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] deleting AI factionIndex = %d, teamIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,this->factionIndex,this->teamIndex); cacheUnitHarvestResourceLookup.clear(); + + if(fp) { + fclose(fp); + fp = NULL; + } } // ==================== main ==================== @@ -81,20 +97,13 @@ void AiInterface::update() { // ==================== misc ==================== void AiInterface::printLog(int logLevel, const string &s){ - if(this->logLevel>=logLevel){ + if(this->logLevel >= logLevel) { string logString= "(" + intToStr(factionIndex) + ") " + s; //print log to file -#ifdef WIN32 - FILE *f= _wfopen(utf8_decode(getLogFilename()).c_str(), L"at"); -#else - FILE *f= fopen(getLogFilename().c_str(), "at"); -#endif - if(f==NULL){ - throw runtime_error("Can't open file: "+getLogFilename()); + if(fp != NULL) { + fprintf(fp, "%s\n", logString.c_str()); } - fprintf(f, "%s\n", logString.c_str()); - fclose(f); //redirect to console if(redir) { diff --git a/source/glest_game/ai/ai_interface.h b/source/glest_game/ai/ai_interface.h index 29f10083..6a696180 100644 --- a/source/glest_game/ai/ai_interface.h +++ b/source/glest_game/ai/ai_interface.h @@ -47,6 +47,9 @@ private: //config bool redir; int logLevel; + std::string aiLogFile; + FILE *fp; + std::map cacheUnitHarvestResourceLookup; public: diff --git a/source/glest_game/ai/ai_rule.cpp b/source/glest_game/ai/ai_rule.cpp index ae49114d..b0570851 100644 --- a/source/glest_game/ai/ai_rule.cpp +++ b/source/glest_game/ai/ai_rule.cpp @@ -400,10 +400,13 @@ void AiRuleAddTasks::execute(){ //standard tasks if(ai->outputAIBehaviourToConsole()) printf("Add a TASK - AiRuleAddTasks adding ProduceTask(ucWorker) workerCount = %d, RULE Name[%s]\n",workerCount,this->getName().c_str()); + //ai->getAiInterface()->printLog(4, "Add a TASK - AiRuleAddTasks adding ProduceTask(ucWorker) workerCount = %d, RULE Name[%s]",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->getAiInterface()->printLog(4, "AAA AiRuleAddTasks adding ProduceTask(ucWorker) workerCount = %d, RULE Name[%s]",workerCount,this->getName().c_str()); + ai->addPriorityTask(new ProduceTask(ucWorker)); } else{ @@ -412,6 +415,8 @@ void AiRuleAddTasks::execute(){ { 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()); + //ai->getAiInterface()->printLog(4, "AAA AiRuleAddTasks adding #1 workerCount = %d[%.2f], buildingCount = %d[%.2f] warriorCount = %d[%.2f] upgradeCount = %d RULE Name[%s]", + // workerCount,workerRatio,buildingCount,buildingRatio,warriorCount,warriorRatio,upgradeCount,this->getName().c_str()); //workers if(workerCount<5) ai->addTask(new ProduceTask(ucWorker)); @@ -455,6 +460,8 @@ void AiRuleAddTasks::execute(){ 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()); + //ai->getAiInterface()->printLog(4, "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)); @@ -481,6 +488,8 @@ void AiRuleAddTasks::execute(){ {// 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()); + //ai->getAiInterface()->printLog(4, "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)); @@ -542,6 +551,8 @@ bool AiRuleBuildOneFarm::test(){ //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()); + //aiInterface->printLog(4, "AiRuleBuildOneFarm returning true, RULE Name[%s]\n",this->getName().c_str()); + return true; } } @@ -577,6 +588,10 @@ bool AiRuleProduceResourceProducer::test(){ 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()); + //aiInterface->printLog(4, "CONSUMABLE [%s][%d] Testing AI RULE Name[%s]",rt->getName().c_str(), r->getBalance(), this->getName().c_str()); + char szBuf[8096]=""; + sprintf(szBuf,"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(rt->getClass()==rcConsumable && r->getBalance()<0){ @@ -587,14 +602,22 @@ bool AiRuleProduceResourceProducer::test(){ } } + int targetStaticResourceCount = minStaticResources; + if(aiInterface->getMyFactionType()->getAIBehaviorMinStaticResourceCount() != INT_MAX) { + targetStaticResourceCount = aiInterface->getMyFactionType()->getAIBehaviorMinStaticResourceCount(); + } + //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(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()); + char szBuf[8096]=""; + sprintf(szBuf,"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() < minStaticResources) { + if(rt->getClass() == rcStatic && r->getAmount() < targetStaticResourceCount) { bool factionUsesResourceType = aiInterface->factionUsesResourceType(aiInterface->getMyFactionType(), rt); if(factionUsesResourceType == true) { interval= longInterval; @@ -604,6 +627,7 @@ bool AiRuleProduceResourceProducer::test(){ } if(ai->outputAIBehaviourToConsole()) printf("STATIC returning FALSE\n"); + aiInterface->printLog(4, "Static Resource check returning FALSE"); interval= shortInterval; return false; @@ -635,18 +659,23 @@ bool AiRuleProduce::test(){ return true; } -void AiRuleProduce::execute(){ - if(produceTask!=NULL){ +void AiRuleProduce::execute() { + AiInterface *aiInterface= ai->getAiInterface(); + if(produceTask!=NULL) { if(ai->outputAIBehaviourToConsole()) printf("AiRuleProduce producing [%s]\n",(produceTask->getUnitType() != NULL ? produceTask->getUnitType()->getName().c_str() : "null")); + //aiInterface->printLog(4, "AiRuleProduce producing [%s]",(produceTask->getUnitType() != NULL ? produceTask->getUnitType()->getName().c_str() : "null")); + char szBuf[8096]=""; + sprintf(szBuf,"AiRuleProduce producing [%s]",(produceTask->getUnitType() != NULL ? produceTask->getUnitType()->getName().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(produceTask->getUnitType() == NULL) { produceGeneric(produceTask); } //specific produce task, produce if possible, retry if not enough resources - else{ + else { produceSpecific(produceTask); } @@ -721,6 +750,7 @@ void AiRuleProduce::produceGeneric(const ProduceTask *pt) { bool produceIt= false; if(ai->outputAIBehaviourToConsole()) printf("produceGeneric [%p] Testing AI RULE Name[%s]\n",pt->getResourceType(), this->getName().c_str()); + //aiInterface->printLog(4, "produceGeneric [%p] Testing AI RULE Name[%s]",pt->getResourceType(), this->getName().c_str()); //if the unit produces the resource if(pt->getResourceType() != NULL) { @@ -728,6 +758,7 @@ void AiRuleProduce::produceGeneric(const ProduceTask *pt) { 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()); + //aiInterface->printLog(4, "produceGeneric r = [%s][%d] Testing AI RULE Name[%s]",r->getDescription().c_str(),r->getAmount(), this->getName().c_str()); } if(r != NULL && r->getAmount() < 0) { @@ -738,6 +769,7 @@ void AiRuleProduce::produceGeneric(const ProduceTask *pt) { 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()); + //aiInterface->printLog(4, "produceGeneric right class = [%d] Testing AI RULE Name[%s]",producedUnit->isOfClass(pt->getUnitClass()), this->getName().c_str()); if(producedUnit->isOfClass(pt->getUnitClass())){ if(aiInterface->reqsOk(ct) && aiInterface->reqsOk(producedUnit)){ @@ -760,6 +792,7 @@ void AiRuleProduce::produceGeneric(const ProduceTask *pt) { 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()); + //aiInterface->printLog(4, "produceGeneric !ableUnits.empty(), ableUnits.size() = [%d] Testing AI RULE Name[%s]",(int)ableUnits.size(), this->getName().c_str()); //priority for non produced units for(unsigned int i=0; i < ableUnits.size(); ++i) { @@ -780,15 +813,24 @@ 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(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()); + char szBuf[8096]=""; + sprintf(szBuf,"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())){ + 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()); + //aiInterface->printLog(4, "produceSpecific aiInterface->checkCosts(pt->getUnitType()) = [%d] Testing AI RULE Name[%s]",aiInterface->checkCosts(pt->getUnitType()), this->getName().c_str()); + sprintf(szBuf,"produceSpecific aiInterface->checkCosts(pt->getUnitType()) = [%d] Testing AI RULE Name[%s]",aiInterface->checkCosts(pt->getUnitType()), this->getName().c_str()); + aiInterface->printLog(4, szBuf); //if unit doesnt meet resources retry - if(!aiInterface->checkCosts(pt->getUnitType())){ + if(aiInterface->checkCosts(pt->getUnitType()) == false) { + sprintf(szBuf,"Check costs FAILED."); + aiInterface->printLog(4, szBuf); + ai->retryTask(pt); return; } @@ -816,6 +858,7 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){ 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()); + //aiInterface->printLog(4, "produceSpecific aiInterface->reqsOk(ct) = [%d] Testing AI RULE Name[%s]",aiInterface->reqsOk(ct), this->getName().c_str()); if(aiInterface->reqsOk(ct)){ defCt= ct; @@ -828,9 +871,32 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){ } //produce from random producer - if(!producers.empty()){ + if(producers.empty() == false) { if(ai->outputAIBehaviourToConsole()) printf("produceSpecific producers.empty() = [%d] Testing AI RULE Name[%s]\n",producers.empty(), this->getName().c_str()); + //aiInterface->printLog(4, "produceSpecific producers.empty() = [%d] Testing AI RULE Name[%s]",producers.empty(), this->getName().c_str()); + sprintf(szBuf,"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[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); + } + + const Unit *unit = aiInterface->getMyUnit(currentProducerIndex); + if(unit->anyCommand() == false) { + idle_producers.push_back(currentProducerIndex); + } + } + if(idle_producers.size() > 0) { + producers = idle_producers; + } if( aiInterface->getControlType() == ctCpuMega || aiInterface->getControlType() == ctNetworkCpuMega) @@ -877,8 +943,9 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){ 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) + 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; @@ -957,6 +1024,10 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){ 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->printLog(4, "mega #1 produceSpecific giveCommand to unit [%s] commandType [%s]",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),ut->getCommandType(commandIndex)->getName().c_str()); + sprintf(szBuf,"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 @@ -973,6 +1044,10 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){ } 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->printLog(4, "mega #2 produceSpecific giveCommand to unit [%s] commandType [%s]",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),defCt->getName().c_str()); + sprintf(szBuf,"mega #2 produceSpecific giveCommand to unit [%s] commandType [%s]",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),defCt->getName().c_str()); + aiInterface->printLog(4, szBuf); + aiInterface->giveCommand(bestIndex, defCt); } } @@ -992,6 +1067,10 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){ } 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->printLog(4, "mega #3 produceSpecific giveCommand to unit [%s] commandType [%s]",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),defCt->getName().c_str()); + sprintf(szBuf,"mega #3 produceSpecific giveCommand to unit [%s] commandType [%s]",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),defCt->getName().c_str()); + 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__); @@ -1006,6 +1085,10 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){ 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->printLog(4, "mega #4 produceSpecific giveCommand to unit [%s] commandType [%s]",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),defCt->getName().c_str()); + sprintf(szBuf,"mega #4 produceSpecific giveCommand to unit [%s] commandType [%s]",aiInterface->getMyUnit(bestIndex)->getType()->getName().c_str(),defCt->getName().c_str()); + aiInterface->printLog(4, szBuf); + aiInterface->giveCommand(bestIndex, defCt); } } @@ -1026,6 +1109,10 @@ void AiRuleProduce::produceSpecific(const ProduceTask *pt){ 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->printLog(4, "produceSpecific giveCommand to unit [%s] commandType [%s]",aiInterface->getMyUnit(producerIndex)->getType()->getName().c_str(),defCt->getName().c_str()); + sprintf(szBuf,"produceSpecific giveCommand to unit [%s] commandType [%s]",aiInterface->getMyUnit(producerIndex)->getType()->getName().c_str(),defCt->getName().c_str()); + aiInterface->printLog(4, szBuf); + aiInterface->giveCommand(producerIndex, defCt); } } @@ -1057,6 +1144,7 @@ bool AiRuleBuild::test(){ 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")); + //aiInterface->printLog(4, "BUILD AiRuleBuild Unit Name[%s]",(buildTask->getUnitType() != NULL ? buildTask->getUnitType()->getName().c_str() : "null")); //generic build task, build random building that can be built if(buildTask->getUnitType() == NULL) { @@ -1318,6 +1406,7 @@ void AiRuleBuild::buildSpecific(const BuildTask *bt) { 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)); + //aiInterface->printLog(4, "BUILD isDefensive check for Unit Name[%s] result = %d",building->getName().c_str(),building->hasSkillClass(scAttack)); return building->hasSkillClass(scAttack); } @@ -1326,10 +1415,13 @@ 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()); + //aiInterface->printLog(4, "BUILD isResourceProducer check for Unit Name[%s] result = true",building->getName().c_str()); return true; } } if(ai->outputAIBehaviourToConsole()) printf("BUILD isResourceProducer check for Unit Name[%s] result = false\n",building->getName().c_str()); + //aiInterface->printLog(4, "BUILD isResourceProducer check for Unit Name[%s] result = false",building->getName().c_str()); + return false; } @@ -1341,11 +1433,14 @@ bool AiRuleBuild::isWarriorProducer(const UnitType *building){ if(ut->isOfClass(ucWarrior)){ if(ai->outputAIBehaviourToConsole()) printf("BUILD isWarriorProducer check for Unit Name[%s] result = true\n",building->getName().c_str()); + //aiInterface->printLog(4, "BUILD isWarriorProducer check for Unit Name[%s] result = true",building->getName().c_str()); return true; } } } if(ai->outputAIBehaviourToConsole()) printf("BUILD isWarriorProducer check for Unit Name[%s] result = false\n",building->getName().c_str()); + //aiInterface->printLog(4, "BUILD isWarriorProducer check for Unit Name[%s] result = false",building->getName().c_str()); + return false; } diff --git a/source/glest_game/types/faction_type.cpp b/source/glest_game/types/faction_type.cpp index e6287de9..1df695a9 100644 --- a/source/glest_game/types/faction_type.cpp +++ b/source/glest_game/types/faction_type.cpp @@ -33,6 +33,7 @@ namespace Glest{ namespace Game{ FactionType::FactionType() { music = NULL; personalityType = fpt_Normal; + aIBehavior_minStaticResourceCount = INT_MAX; } //load a faction, given a directory @@ -41,6 +42,8 @@ void FactionType::load(const string &factionName, const TechTree *techTree, Chec if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + aIBehavior_minStaticResourceCount = INT_MAX; + string techTreePath = techTree->getPath(); string techTreeName=techTree->getName(); string currentPath = ""; @@ -217,6 +220,10 @@ void FactionType::load(const string &factionName, const TechTree *techTree, Chec //read ai behavior if(factionNode->hasChild("ai-behavior") == true) { const XmlNode *aiNode= factionNode->getChild("ai-behavior"); + if(aiNode->hasAttribute("min-static-resource-count") == true) { + aIBehavior_minStaticResourceCount = aiNode->getAttribute("min-static-resource-count")->getIntValue(); + //printf("aIBehavior_minStaticResourceCount = %d\n",aIBehavior_minStaticResourceCount); + } if(aiNode->hasChild("worker-units") == true) { const XmlNode *aiNodeUnits= aiNode->getChild("worker-units"); for(int i = 0; i < aiNodeUnits->getChildCount(); ++i) { diff --git a/source/glest_game/types/faction_type.h b/source/glest_game/types/faction_type.h index 0b2d1736..a58f9b3c 100644 --- a/source/glest_game/types/faction_type.h +++ b/source/glest_game/types/faction_type.h @@ -54,6 +54,7 @@ private: std::map > mapAIBehaviorUnitCategories; std::vector vctAIBehaviorUpgrades; + int aIBehavior_minStaticResourceCount; public: //init @@ -64,6 +65,7 @@ public: const std::vector getAIBehaviorUnits(AIBehaviorUnitCategory category) const; const std::vector getAIBehaviorUpgrades() const { return vctAIBehaviorUpgrades; }; + int getAIBehaviorMinStaticResourceCount() const { return aIBehavior_minStaticResourceCount; } //get int getUnitTypeCount() const {return unitTypes.size();}