From bc7ba297fd780d663e18a9e9609a51707e04c7ee Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Wed, 20 Oct 2010 20:40:29 +0000 Subject: [PATCH] - more tweaking for units harvesting, this hopefully cleans up segfaults and makes things more stable. --- source/glest_game/ai/path_finder.cpp | 23 +++++----- source/glest_game/type_instances/faction.cpp | 47 ++++++++++++-------- source/glest_game/type_instances/faction.h | 5 +-- source/glest_game/world/map.cpp | 16 ++++--- source/glest_game/world/unit_updater.cpp | 39 +++++++++------- 5 files changed, 77 insertions(+), 53 deletions(-) diff --git a/source/glest_game/ai/path_finder.cpp b/source/glest_game/ai/path_finder.cpp index f69a5609..6e4bfec7 100644 --- a/source/glest_game/ai/path_finder.cpp +++ b/source/glest_game/ai/path_finder.cpp @@ -128,18 +128,21 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu } TravelState ts = tsImpossible; - std::vector cachedPath = unit->getFaction()->findCachedPath(finalPos, unit); - if(cachedPath.size() > 0) { - path->clear(); + //route cache miss + ts = aStar(unit, finalPos, false); - for(int i=0; i < cachedPath.size() && i < pathFindRefresh; ++i) { - path->add(cachedPath[i]); + if(ts == tsBlocked) { + std::vector cachedPath = unit->getFaction()->findCachedPath(finalPos, unit); + if(cachedPath.size() > 0) { + path->clear(); + + for(int i=0; i < cachedPath.size() && i < pathFindRefresh; ++i) { + path->add(cachedPath[i]); + } + ts = tsMoving; + + unit->addCurrentTargetPathTakenCell(Vec2i(-1),Vec2i(-1)); } - ts = tsMoving; - } - else { - //route cache miss - ts = aStar(unit, finalPos, false); } //post actions diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index 52b4df88..23ffeee9 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -584,19 +584,19 @@ void Faction::resetResourceAmount(const ResourceType *rt){ assert(false); } -void Faction::addResourceTypeTargetToCache(const ResourceType *type, const Vec2i &pos) { +void Faction::addResourceTargetToCache(const Vec2i &pos) { bool duplicateEntry = false; - if(cacheResourceTypeTargetList.size() > 0) { - for(int i = 0; i < cacheResourceTypeTargetList.size(); ++i) { - std::pair &cache = cacheResourceTypeTargetList[i]; - if(cache.first == type && cache.second == pos) { + if(cacheResourceTargetList.size() > 0) { + for(int i = 0; i < cacheResourceTargetList.size(); ++i) { + const Vec2i &cache = cacheResourceTargetList[i]; + if(cache == pos) { duplicateEntry = true; break; } } } if(duplicateEntry == false) { - cacheResourceTypeTargetList.push_back(make_pair(type,pos)); + cacheResourceTargetList.push_back(pos); } cleanupResourceTypeTargetCache(); @@ -604,14 +604,18 @@ void Faction::addResourceTypeTargetToCache(const ResourceType *type, const Vec2i Vec2i Faction::getClosestResourceTypeTargetFromCache(Unit *unit, const ResourceType *type) { Vec2i result(-1); - if(cacheResourceTypeTargetList.size() > 0) { - for(int i = 0; i < cacheResourceTypeTargetList.size(); ++i) { - std::pair &cache = cacheResourceTypeTargetList[i]; + if(cacheResourceTargetList.size() > 0) { + const Map *map = world->getMap(); + for(int i = 0; i < cacheResourceTargetList.size(); ++i) { + const Vec2i &cache = cacheResourceTargetList[i]; - Resource *resource = world->getMap()->getSurfaceCell(world->getMap()->toSurfCoords(cache.second))->getResource(); - if(resource != NULL && cache.first == type) { - if(result.x < 0 || unit->getPos().dist(cache.second) < unit->getPos().dist(result)) { - result = cache.second; + 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 || unit->getPos().dist(cache) < unit->getPos().dist(result)) { + result = cache; + } } } } @@ -623,13 +627,18 @@ Vec2i Faction::getClosestResourceTypeTargetFromCache(Unit *unit, const ResourceT } void Faction::cleanupResourceTypeTargetCache() { - if(cacheResourceTypeTargetList.size() > 0) { - for(int i = cacheResourceTypeTargetList.size() - 1; i >= 0; --i) { - std::pair &cache = cacheResourceTypeTargetList[i]; + if(cacheResourceTargetList.size() > 0) { + for(int i = cacheResourceTargetList.size() - 1; i >= 0; --i) { + const Vec2i &cache = cacheResourceTargetList[i]; - Resource *resource = world->getMap()->getSurfaceCell(world->getMap()->toSurfCoords(cache.second))->getResource(); - if(resource == NULL) { - cacheResourceTypeTargetList.erase(cacheResourceTypeTargetList.begin() + i); + if(world->getMap()->getSurfaceCell(world->getMap()->toSurfCoords(cache)) != NULL) { + Resource *resource = world->getMap()->getSurfaceCell(world->getMap()->toSurfCoords(cache))->getResource(); + if(resource == NULL) { + cacheResourceTargetList.erase(cacheResourceTargetList.begin() + i); + } + } + else { + cacheResourceTargetList.erase(cacheResourceTargetList.begin() + i); } } } diff --git a/source/glest_game/type_instances/faction.h b/source/glest_game/type_instances/faction.h index 46ba68c1..d7d8e979 100644 --- a/source/glest_game/type_instances/faction.h +++ b/source/glest_game/type_instances/faction.h @@ -84,7 +84,7 @@ private: bool thisFaction; std::map > successfulPathFinderTargetList; - std::vector > cacheResourceTypeTargetList; + std::vector cacheResourceTargetList; public: Faction(); @@ -156,8 +156,7 @@ public: std::vector findCachedPath(const Vec2i &target, Unit *unit); void addCachedPath(const Vec2i &target, Unit *unit); - //std::map cacheResourceTypeTargetList; - void addResourceTypeTargetToCache(const ResourceType *type, const Vec2i &pos); + void addResourceTargetToCache(const Vec2i &pos); Vec2i getClosestResourceTypeTargetFromCache(Unit *unit, const ResourceType *type); void cleanupResourceTypeTargetCache(); diff --git a/source/glest_game/world/map.cpp b/source/glest_game/world/map.cpp index 614c1c67..33f30c26 100644 --- a/source/glest_game/world/map.cpp +++ b/source/glest_game/world/map.cpp @@ -256,7 +256,7 @@ bool Map::isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resour for(int j = -1; j <= size; ++j) { if(isInside(pos.x + i, pos.y + j)) { Resource *r= getSurfaceCell(toSurfCoords(Vec2i(pos.x + i, pos.y + j)))->getResource(); - if(r != NULL){ + if(r != NULL) { if(r->getType() == rt) { resourcePos= pos + Vec2i(i,j); @@ -270,20 +270,23 @@ bool Map::isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resour } if(fallbackToPeersHarvestingSameResource == true && unit != NULL) { + // Look for another unit that is currently harvesting the same resource + // type right now for(int i = 0; i < unit->getFaction()->getUnitCount(); ++i) { Unit *peerUnit = unit->getFaction()->getUnit(i); if( peerUnit != NULL && peerUnit->getId() != unit->getId() && peerUnit->getType()->getSize() <= unit->getType()->getSize()) { - if( peerUnit->getCurrSkill()->getClass() == scHarvest && + if( peerUnit->getCurrSkill() != NULL && + peerUnit->getCurrSkill()->getClass() == scHarvest && peerUnit->getLoadType() == rt && peerUnit->getCurrCommand() != NULL) { if(unit->getPos().dist(peerUnit->getCurrCommand()->getPos()) <= 40) { - if(i == 0 || (unit->getPos().dist(peerUnit->getCurrCommand()->getPos()) < unit->getPos().dist(resourcePos))) { + if( i == 0 || + (unit->getPos().dist(peerUnit->getCurrCommand()->getPos()) < unit->getPos().dist(resourcePos))) { resourcePos = peerUnit->getCurrCommand()->getPos(); } if(unit->getPos().dist(peerUnit->getCurrCommand()->getPos()) <= 5) { - resourcePos = peerUnit->getCurrCommand()->getPos(); return true; } } @@ -291,15 +294,18 @@ bool Map::isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resour } } + + // Check the faction cache for a known position where we can harvest + // this resource type Vec2i result = unit->getFaction()->getClosestResourceTypeTargetFromCache(unit, rt); if(result.x >= 0) { resourcePos = result; - if(unit->getPos().dist(resourcePos) <= 5) { return true; } } } + return false; } diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index c479b228..847fe241 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -578,7 +578,7 @@ void UnitUpdater::updateHarvest(Unit *unit) { Command *command= unit->getCurrCommand(); const HarvestCommandType *hct= static_cast(command->getCommandType()); - Vec2i targetPos; + Vec2i targetPos(-1); TravelState tsValue = tsImpossible; UnitPathInterface *path= unit->getPath(); @@ -587,17 +587,21 @@ void UnitUpdater::updateHarvest(Unit *unit) { //if not working if(unit->getLoadCount() == 0) { //if not loaded go for resources - Resource *r= map->getSurfaceCell(Map::toSurfCoords(command->getPos()))->getResource(); + Resource *r = map->getSurfaceCell(Map::toSurfCoords(command->getPos()))->getResource(); if(r != NULL && hct->canHarvest(r->getType())) { //if can harvest dest. pos bool canHarvestDestPos = false; - targetPos.x = -1; - targetPos.y = -1; switch(this->game->getGameSettings()->getPathFinderType()) { case pfBasic: - canHarvestDestPos = (unit->getPos().dist(command->getPos()) < harvestDistance && - map->isResourceNear(unit->getPos(), r->getType(), targetPos,unit->getType()->getSize(),unit)); + { + bool isNearResource = map->isResourceNear(unit->getPos(), r->getType(), targetPos,unit->getType()->getSize(),unit); + if(isNearResource == true) { + if((unit->getPos().dist(command->getPos()) < harvestDistance || unit->getPos().dist(targetPos) < harvestDistance) && isNearResource == true) { + canHarvestDestPos = true; + } + } + } break; case pfRoutePlanner: canHarvestDestPos = map->isResourceNear(unit->getPos(), unit->getType()->getSize(), r->getType(), targetPos); @@ -616,11 +620,11 @@ void UnitUpdater::updateHarvest(Unit *unit) { unit->setTargetPos(targetPos); command->setPos(targetPos); unit->setLoadCount(0); - unit->getFaction()->addResourceTypeTargetToCache(r->getType(), targetPos); + unit->getFaction()->addResourceTargetToCache(targetPos); switch(this->game->getGameSettings()->getPathFinderType()) { case pfBasic: - unit->setLoadType(map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()))->getResource()->getType()); + unit->setLoadType(r->getType()); break; case pfRoutePlanner: unit->setLoadType(r->getType()); @@ -653,11 +657,17 @@ void UnitUpdater::updateHarvest(Unit *unit) { throw runtime_error("detected unsupported pathfinder type!"); } - if(wasStuck == true) { + if(wasStuck == true && unit->isAlive() == true) { switch(this->game->getGameSettings()->getPathFinderType()) { case pfBasic: - canHarvestDestPos = (unit->getPos().dist(command->getPos()) < harvestDistance && - map->isResourceNear(unit->getPos(), r->getType(), targetPos,unit->getType()->getSize(),unit, true)); + { + bool isNearResource = map->isResourceNear(unit->getPos(), r->getType(), targetPos,unit->getType()->getSize(),unit); + if(isNearResource == true) { + if((unit->getPos().dist(command->getPos()) < harvestDistance || unit->getPos().dist(targetPos) < harvestDistance) && isNearResource == true) { + canHarvestDestPos = true; + } + } + } break; case pfRoutePlanner: canHarvestDestPos = map->isResourceNear(unit->getPos(), unit->getType()->getSize(), r->getType(), targetPos); @@ -676,14 +686,11 @@ void UnitUpdater::updateHarvest(Unit *unit) { unit->setTargetPos(targetPos); command->setPos(targetPos); unit->setLoadCount(0); - unit->getFaction()->addResourceTypeTargetToCache(r->getType(), targetPos); + unit->getFaction()->addResourceTargetToCache(targetPos); switch(this->game->getGameSettings()->getPathFinderType()) { case pfBasic: - { - const ResourceType *loadType = map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()))->getResource()->getType(); - unit->setLoadType(loadType); - } + unit->setLoadType(r->getType()); break; case pfRoutePlanner: unit->setLoadType(r->getType());