From 9d9fa0deeb87336e5ce47bbd40bfcbb99e6fea9a Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Sun, 7 Nov 2010 03:27:06 +0000 Subject: [PATCH] - improved performance for when the AI decides which resource is closest. --- source/glest_game/ai/ai.cpp | 14 ++++ source/glest_game/ai/ai_interface.cpp | 74 +++++++++++++++----- source/glest_game/ai/ai_interface.h | 1 + source/glest_game/ai/ai_rule.cpp | 10 +-- source/glest_game/game/game.cpp | 2 + source/glest_game/type_instances/faction.cpp | 71 +++++++++++++++++++ source/glest_game/type_instances/faction.h | 1 + source/glest_game/world/unit_updater.cpp | 17 +++++ source/glest_game/world/world.cpp | 8 +++ 9 files changed, 177 insertions(+), 21 deletions(-) diff --git a/source/glest_game/ai/ai.cpp b/source/glest_game/ai/ai.cpp index a02a6298..b4cb1f60 100644 --- a/source/glest_game/ai/ai.cpp +++ b/source/glest_game/ai/ai.cpp @@ -141,6 +141,9 @@ Ai::~Ai() { } void Ai::update() { + Chrono chrono; + chrono.start(); + //process ai rules for(int ruleIdx = 0; ruleIdx < aiRules.size(); ++ruleIdx) { AiRule *rule = aiRules[ruleIdx]; @@ -148,12 +151,23 @@ void Ai::update() { throw runtime_error("rule == NULL"); } if((aiInterface->getTimer() % (rule->getTestInterval() * GameConstants::updateFps / 1000)) == 0){ + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] ruleIdx = %d, aiRules.size() = %d, took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,ruleIdx,aiRules.size(),chrono.getMillis()); + if(rule->test()) { + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] ruleIdx = %d, aiRules.size() = %d, took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,ruleIdx,aiRules.size(),chrono.getMillis()); + aiInterface->printLog(3, intToStr(1000 * aiInterface->getTimer() / GameConstants::updateFps) + ": Executing rule: " + rule->getName() + '\n'); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] ruleIdx = %d, aiRules.size() = %d, took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,ruleIdx,aiRules.size(),chrono.getMillis()); + rule->execute(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] ruleIdx = %d, aiRules.size() = %d, took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,ruleIdx,aiRules.size(),chrono.getMillis()); } } } + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } diff --git a/source/glest_game/ai/ai_interface.cpp b/source/glest_game/ai/ai_interface.cpp index c6e1d201..f3f4fd08 100644 --- a/source/glest_game/ai/ai_interface.cpp +++ b/source/glest_game/ai/ai_interface.cpp @@ -371,6 +371,42 @@ const TechTree *AiInterface::getTechTree(){ return world->getTechTree(); } +//returns if there is a resource next to a unit, in "resourcePos" is stored the relative position of the resource +bool AiInterface::isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resourcePos, Faction *faction, bool fallbackToPeersHarvestingSameResource) const { + const Map *map= world->getMap(); + int size = 1; + for(int i = -1; i <= size; ++i) { + for(int j = -1; j <= size; ++j) { + if(map->isInside(pos.x + i, pos.y + j)) { + Resource *r= map->getSurfaceCell(map->toSurfCoords(Vec2i(pos.x + i, pos.y + j)))->getResource(); + if(r != NULL) { + if(r->getType() == rt) { + resourcePos= pos + Vec2i(i,j); + return true; + } + } + } + } + } + + if(fallbackToPeersHarvestingSameResource == true && faction != NULL) { + // Look for another unit that is currently harvesting the same resource + // type right now + + // Check the faction cache for a known position where we can harvest + // this resource type + Vec2i result = faction->getClosestResourceTypeTargetFromCache(pos, rt); + if(result.x >= 0) { + resourcePos = result; + if(pos.dist(resourcePos) <= size) { + return true; + } + } + } + + return false; +} + bool AiInterface::getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos, bool usableResourceTypeOnly) { float tmpDist=0; @@ -381,7 +417,8 @@ bool AiInterface::getNearestSightedResource(const ResourceType *rt, const Vec2i bool canUseResourceType = (usableResourceTypeOnly == false); if(usableResourceTypeOnly == true) { // can any unit harvest this resource yet? - for(int i = 0; i < getMyUnitCount(); ++i) { + int unitCount = getMyUnitCount(); + for(int i = 0; i < unitCount; ++i) { const Unit *unit = getMyUnit(i); const HarvestCommandType *hct= unit->getType()->getFirstHarvestCommand(rt,unit->getFaction()); if(hct != NULL) { @@ -392,23 +429,28 @@ bool AiInterface::getNearestSightedResource(const ResourceType *rt, const Vec2i } if(canUseResourceType == true) { - const Map *map= world->getMap(); + Faction *faction = world->getFaction(factionIndex); + if(isResourceNear(pos, rt, resultPos, faction, true) == true) { + anyResource= true; + } + else { + const Map *map= world->getMap(); + for(int i = 0; i < map->getW(); ++i) { + for(int j = 0; j < map->getH(); ++j) { + Vec2i surfPos= Map::toSurfCoords(Vec2i(i, j)); - for(int i=0; igetW(); ++i){ - for(int j=0; jgetH(); ++j){ - Vec2i surfPos= Map::toSurfCoords(Vec2i(i, j)); - - //if explored cell - if(map->getSurfaceCell(surfPos)->isExplored(teamIndex)){ - Resource *r= map->getSurfaceCell(surfPos)->getResource(); + //if explored cell + if(map->getSurfaceCell(surfPos)->isExplored(teamIndex)) { + Resource *r= map->getSurfaceCell(surfPos)->getResource(); - //if resource cell - if(r != NULL && r->getType() == rt) { - tmpDist= pos.dist(Vec2i(i, j)); - if(tmpDist < nearestDist) { - anyResource= true; - nearestDist= tmpDist; - resultPos= Vec2i(i, j); + //if resource cell + if(r != NULL && r->getType() == rt) { + tmpDist= pos.dist(Vec2i(i, j)); + if(tmpDist < nearestDist) { + anyResource= true; + nearestDist= tmpDist; + resultPos= Vec2i(i, j); + } } } } diff --git a/source/glest_game/ai/ai_interface.h b/source/glest_game/ai/ai_interface.h index 58f07683..111aea71 100644 --- a/source/glest_game/ai/ai_interface.h +++ b/source/glest_game/ai/ai_interface.h @@ -80,6 +80,7 @@ public: const Unit *getOnSightUnit(int unitIndex); const FactionType *getMyFactionType(); const TechTree *getTechTree(); + bool isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resourcePos, Faction *faction, bool fallbackToPeersHarvestingSameResource) const; bool getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos, bool usableResourceTypeOnly); bool isAlly(const Unit *unit) const; bool isAlly(int factionIndex) const; diff --git a/source/glest_game/ai/ai_rule.cpp b/source/glest_game/ai/ai_rule.cpp index dd37ec0c..129b4771 100644 --- a/source/glest_game/ai/ai_rule.cpp +++ b/source/glest_game/ai/ai_rule.cpp @@ -1092,24 +1092,24 @@ AiRuleExpand::AiRuleExpand(Ai *ai): bool AiRuleExpand::test() { AiInterface *aiInterface = ai->getAiInterface(); - for(int i= 0; igetTechTree()->getResourceTypeCount(); ++i){ + int unitCount = aiInterface->getMyUnitCount(); + for(int i = 0; i < aiInterface->getTechTree()->getResourceTypeCount(); ++i) { const ResourceType *rt = aiInterface->getTechTree()->getResourceType(i); - if(rt->getClass() == rcTech){ + if(rt->getClass() == rcTech) { // 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 < aiInterface->getMyUnitCount(); ++j) { + for(int j=0; j < unitCount; ++j) { const Unit *u= aiInterface->getMyUnit(j); - const UnitType *ut= aiInterface->getMyUnit(j)->getType(); + const UnitType *ut= u->getType(); // If this building is a store if(ut->getStore(rt) > 0) { storeType = ut; int distance= static_cast (u->getPos().dist(expandPos)); - if(distance < minDistance) { minDistance = distance; } diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index 372d3b85..66b8beaf 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -697,6 +697,8 @@ void Game::update() { scriptManager.getPlayerModifiers(i)->getAiEnabled() == true) { aiInterfaces[i]->update(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] i = %d, world.getFactionCount() = %d, took msecs: %lld [AI updates]\n",__FILE__,__FUNCTION__,__LINE__,i,world.getFactionCount(),chrono.getMillis()); } } diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index 94bf6678..9d476575 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -806,6 +806,77 @@ Vec2i Faction::getClosestResourceTypeTargetFromCache(Unit *unit, const ResourceT return result; } +Vec2i Faction::getClosestResourceTypeTargetFromCache(const Vec2i &pos, const ResourceType *type) { + Vec2i result(-1); + if(Config::getInstance().getBool("DisableCaching","false") == false) { + if(cacheResourceTargetList.size() > 0) { + std::vector deleteList; + + const int harvestDistance = 5; + const Map *map = world->getMap(); + + bool foundCloseResource = false; + // First look immediately around the given position + for(int j = -harvestDistance; j <= harvestDistance && foundCloseResource == false; ++j) { + for(int k = -harvestDistance; k <= harvestDistance && foundCloseResource == false; ++k) { + Vec2i newPos = pos + Vec2i(j,k); + if(map->isInside(newPos) == true && isResourceTargetInCache(newPos) == false) { + const SurfaceCell *sc = map->getSurfaceCell(map->toSurfCoords(newPos)); + if( sc != NULL && sc->getResource() != NULL) { + const Resource *resource = sc->getResource(); + if(resource->getType() != NULL && resource->getType() == type) { + if(result.x < 0 || pos.dist(newPos) < pos.dist(result)) { + result = newPos; + foundCloseResource = true; + break; + } + } + } + else { + deleteList.push_back(newPos); + } + } + } + } + + if(foundCloseResource == false) { + // Now check the whole cache + for(std::map::iterator iter = cacheResourceTargetList.begin(); + iter != cacheResourceTargetList.end() && foundCloseResource == false; + ++iter) { + const Vec2i &cache = iter->first; + if(map->isInside(cache) == true) { + const SurfaceCell *sc = map->getSurfaceCell(map->toSurfCoords(cache)); + if( sc != NULL && sc->getResource() != NULL) { + const Resource *resource = sc->getResource(); + if(resource->getType() != NULL && resource->getType() == type) { + if(result.x < 0 || pos.dist(cache) < pos.dist(result)) { + result = cache; + // Close enough to our position, no more looking + if(pos.dist(result) <= (harvestDistance * 2)) { + foundCloseResource = true; + break; + } + } + } + } + else { + deleteList.push_back(cache); + } + } + else { + deleteList.push_back(cache); + } + } + } + if(deleteList.size() > 0) { + cleanupResourceTypeTargetCache(&deleteList); + } + } + } + return result; +} + void Faction::cleanupResourceTypeTargetCache(std::vector *deleteListPtr) { if(Config::getInstance().getBool("DisableCaching","false") == false) { if(cacheResourceTargetList.size() > 0) { diff --git a/source/glest_game/type_instances/faction.h b/source/glest_game/type_instances/faction.h index abf7b81c..cf042b83 100644 --- a/source/glest_game/type_instances/faction.h +++ b/source/glest_game/type_instances/faction.h @@ -167,6 +167,7 @@ public: void removeResourceTargetFromCache(const Vec2i &pos); void addCloseResourceTargetToCache(const Vec2i &pos); Vec2i getClosestResourceTypeTargetFromCache(Unit *unit, const ResourceType *type); + Vec2i getClosestResourceTypeTargetFromCache(const Vec2i &pos, const ResourceType *type); void cleanupResourceTypeTargetCache(std::vector *deleteListPtr); void deletePixels(); diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index 18e0d53d..f3bf4784 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -429,6 +429,8 @@ void UnitUpdater::updateBuild(Unit *unit) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + switch (tsValue) { case tsMoving: SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] tsMoving\n",__FILE__,__FUNCTION__,__LINE__); @@ -456,6 +458,8 @@ void UnitUpdater::updateBuild(Unit *unit) { throw runtime_error("detected unsupported pathfinder type!"); } + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + if (canOccupyCell == true) { const UnitType *builtUnitType= command->getUnitType(); CardinalDir facing = command->getFacing(); @@ -474,6 +478,8 @@ void UnitUpdater::updateBuild(Unit *unit) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + Vec2i buildPos = command->getPos(); Unit *builtUnit= new Unit(world->getNextUnitId(unit->getFaction()), newpath, buildPos, builtUnitType, unit->getFaction(), world->getMap(), facing); @@ -501,6 +507,8 @@ void UnitUpdater::updateBuild(Unit *unit) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + switch(this->game->getGameSettings()->getPathFinderType()) { case pfBasic: break; @@ -533,6 +541,7 @@ void UnitUpdater::updateBuild(Unit *unit) { } SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] got BuildingNoPlace\n",__FILE__,__FUNCTION__,__LINE__); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } } break; @@ -545,10 +554,14 @@ void UnitUpdater::updateBuild(Unit *unit) { } break; } + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } else { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] tsArrived unit = %s\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str()); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //if building Unit *builtUnit = map->getCell(unit->getTargetPos())->getUnit(fLand); if(builtUnit == NULL) { @@ -574,6 +587,8 @@ void UnitUpdater::updateBuild(Unit *unit) { else if(builtUnit == NULL || builtUnit->repair()) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //building finished unit->finishCommand(); unit->setCurrSkill(scStop); @@ -586,6 +601,8 @@ void UnitUpdater::updateBuild(Unit *unit) { unit->getCurrVector(), gameCamera->getPos()); } + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } } diff --git a/source/glest_game/world/world.cpp b/source/glest_game/world/world.cpp index 5f1bb359..04ebe86e 100644 --- a/source/glest_game/world/world.cpp +++ b/source/glest_game/world/world.cpp @@ -244,6 +244,9 @@ void World::loadScenario(const string &path, Checksum *checksum){ // ==================== misc ==================== void World::updateAllFactionUnits() { + Chrono chrono; + chrono.start(); + scriptManager->onTimerTriggerEvent(); //units int factionCount = getFactionCount(); @@ -254,6 +257,9 @@ void World::updateAllFactionUnits() { } int unitCount = faction->getUnitCount(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] i = %d, unitCount = %d, took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,i,unitCount,chrono.getMillis()); + for(int j = 0; j < unitCount; ++j) { Unit *unit = faction->getUnit(j); if(unit == NULL) { @@ -263,6 +269,8 @@ void World::updateAllFactionUnits() { unitUpdater.updateUnit(unit); } } + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } void World::underTakeDeadFactionUnits() {