- improved performance for when the AI decides which resource is closest.

This commit is contained in:
Mark Vejvoda 2010-11-07 03:27:06 +00:00
parent ca9cbc6e75
commit 9d9fa0deeb
9 changed files with 177 additions and 21 deletions

View File

@ -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());
}

View File

@ -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; i<map->getW(); ++i){
for(int j=0; j<map->getH(); ++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);
}
}
}
}

View File

@ -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;

View File

@ -1092,24 +1092,24 @@ AiRuleExpand::AiRuleExpand(Ai *ai):
bool AiRuleExpand::test() {
AiInterface *aiInterface = ai->getAiInterface();
for(int i= 0; i<aiInterface->getTechTree()->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<int> (u->getPos().dist(expandPos));
if(distance < minDistance) {
minDistance = distance;
}

View File

@ -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());
}
}

View File

@ -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<Vec2i> 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<Vec2i,int>::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<Vec2i> *deleteListPtr) {
if(Config::getInstance().getBool("DisableCaching","false") == false) {
if(cacheResourceTargetList.size() > 0) {

View File

@ -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<Vec2i> *deleteListPtr);
void deletePixels();

View File

@ -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());
}
}

View File

@ -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() {