- added a little extra logic for units when pathfinding. We keep temporary lists of bad cells of harvest resources where a unit simply cannot get to. This is kept for small periods of time and then the bad cell list is purged when data gets old. This tremendously helps units to be more active when getting stuck in challenging places on maps.
This commit is contained in:
parent
55b4f0bd2b
commit
3d4ccb460c
|
@ -173,10 +173,18 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos) {
|
||||||
throw runtime_error("unsupported or missing path finder detected!");
|
throw runtime_error("unsupported or missing path finder detected!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(ts == tsArrived) {
|
||||||
|
ts = aStar(unit, finalPos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unit->setInBailOutAttempt(false);
|
unit->setInBailOutAttempt(false);
|
||||||
|
|
||||||
|
if(ts == tsArrived) {
|
||||||
|
ts = tsBlocked;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unit->setCurrSkill(scStop);
|
unit->setCurrSkill(scStop);
|
||||||
break;
|
break;
|
||||||
|
@ -230,17 +238,20 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
||||||
|
|
||||||
//if arrived
|
//if arrived
|
||||||
if(finalPos == unit->getPos()) {
|
if(finalPos == unit->getPos()) {
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
Command *command= unit->getCurrCommand();
|
||||||
string commandDesc = "none";
|
if(command == NULL || command->getPos() != unit->getPos()) {
|
||||||
Command *command= unit->getCurrCommand();
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
||||||
if(command != NULL && command->getCommandType() != NULL) {
|
string commandDesc = "none";
|
||||||
commandDesc = command->getCommandType()->toString();
|
Command *command= unit->getCurrCommand();
|
||||||
|
if(command != NULL && command->getCommandType() != NULL) {
|
||||||
|
commandDesc = command->getCommandType()->toString();
|
||||||
|
}
|
||||||
|
char szBuf[1024]="";
|
||||||
|
sprintf(szBuf,"State: arrived#2 at pos: %s, command [%s]",targetPos.getString().c_str(),commandDesc.c_str());
|
||||||
|
unit->setCurrentUnitTitle(szBuf);
|
||||||
}
|
}
|
||||||
char szBuf[1024]="";
|
return tsArrived;
|
||||||
sprintf(szBuf,"State: arrived#2 at pos: %s, command [%s]",targetPos.getString().c_str(),commandDesc.c_str());
|
|
||||||
unit->setCurrentUnitTitle(szBuf);
|
|
||||||
}
|
}
|
||||||
return tsArrived;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//path find algorithm
|
//path find algorithm
|
||||||
|
@ -338,8 +349,10 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
||||||
commandDesc = command->getCommandType()->toString();
|
commandDesc = command->getCommandType()->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<Vec2i,Chrono> lastHarvest = unit->getLastHarvestResourceTarget();
|
||||||
|
|
||||||
char szBuf[1024]="";
|
char szBuf[1024]="";
|
||||||
sprintf(szBuf,"State: blocked, cmd [%s] pos: %s, dest pos: %s, reason A= %d, B= %d, C= %d, D= %d, E= %d, F = %d",commandDesc.c_str(),unit->getPos().getString().c_str(), targetPos.getString().c_str(),pathFound,(lastNode == firstNode),path->getBlockCount(), path->isBlocked(), nodeLimitReached,path->isStuck());
|
sprintf(szBuf,"State: blocked, cmd [%s] pos: [%s], dest pos: [%s], lastHarvest = [%s - %lld], reason A= %d, B= %d, C= %d, D= %d, E= %d, F = %d",commandDesc.c_str(),unit->getPos().getString().c_str(), targetPos.getString().c_str(),lastHarvest.first.getString().c_str(),lastHarvest.second.getMillis(), pathFound,(lastNode == firstNode),path->getBlockCount(), path->isBlocked(), nodeLimitReached,path->isStuck());
|
||||||
unit->setCurrentUnitTitle(szBuf);
|
unit->setCurrentUnitTitle(szBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,7 @@ Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, const UnitType
|
||||||
this->retryCurrCommandCount=0;
|
this->retryCurrCommandCount=0;
|
||||||
this->screenPos = Vec3f(0.0);
|
this->screenPos = Vec3f(0.0);
|
||||||
this->inBailOutAttempt = false;
|
this->inBailOutAttempt = false;
|
||||||
|
this->lastHarvestResourceTarget.first = Vec2i(0);
|
||||||
|
|
||||||
level= NULL;
|
level= NULL;
|
||||||
loadType= NULL;
|
loadType= NULL;
|
||||||
|
@ -245,6 +246,8 @@ Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, const UnitType
|
||||||
Unit::~Unit(){
|
Unit::~Unit(){
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] delete unitid = %d\n",__FILE__,__FUNCTION__,__LINE__,id);
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] delete unitid = %d\n",__FILE__,__FUNCTION__,__LINE__,id);
|
||||||
|
|
||||||
|
badHarvestPosList.clear();
|
||||||
|
|
||||||
//Just to be sure, should already be removed
|
//Just to be sure, should already be removed
|
||||||
if (livingUnits.erase(id)) {
|
if (livingUnits.erase(id)) {
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
@ -1678,6 +1681,75 @@ void Unit::logSynchData(string source) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unit::addBadHarvestPos(const Vec2i &value) {
|
||||||
|
Chrono chron;
|
||||||
|
chron.start();
|
||||||
|
badHarvestPosList.push_back(std::pair<Vec2i,Chrono>(value,chron));
|
||||||
|
cleanupOldBadHarvestPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unit::removeBadHarvestPos(const Vec2i &value) {
|
||||||
|
for(int i = 0; i < badHarvestPosList.size(); ++i) {
|
||||||
|
const std::pair<Vec2i,Chrono> &item = badHarvestPosList[i];
|
||||||
|
if(item.first == value) {
|
||||||
|
badHarvestPosList.erase(badHarvestPosList.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanupOldBadHarvestPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Unit::isBadHarvestPos(const Vec2i &value) {
|
||||||
|
cleanupOldBadHarvestPos();
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
for(int i = 0; i < badHarvestPosList.size(); ++i) {
|
||||||
|
const std::pair<Vec2i,Chrono> &item = badHarvestPosList[i];
|
||||||
|
if(item.first == value) {
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unit::cleanupOldBadHarvestPos() {
|
||||||
|
for(int i = badHarvestPosList.size() - 1; i >= 0; --i) {
|
||||||
|
const std::pair<Vec2i,Chrono> &item = badHarvestPosList[i];
|
||||||
|
|
||||||
|
// If this position has been is the list for longer than 120
|
||||||
|
// seconds remove it so the unit could potentially try it again
|
||||||
|
if(item.second.getMillis() >= 1200000) {
|
||||||
|
badHarvestPosList.erase(badHarvestPosList.begin() + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unit::setLastHarvestResourceTarget(const Vec2i *pos) {
|
||||||
|
if(pos == NULL) {
|
||||||
|
lastHarvestResourceTarget.first = Vec2i(0);
|
||||||
|
//lastHarvestResourceTarget.second = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const Vec2i resourceLocation = *pos;
|
||||||
|
if(resourceLocation != lastHarvestResourceTarget.first) {
|
||||||
|
lastHarvestResourceTarget.first = resourceLocation;
|
||||||
|
|
||||||
|
Chrono chron;
|
||||||
|
chron.start();
|
||||||
|
lastHarvestResourceTarget.second = chron;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If we cannot harvest for > 10 seconds tag the position
|
||||||
|
// as a bad one
|
||||||
|
if(lastHarvestResourceTarget.second.getMillis() > 10000) {
|
||||||
|
addBadHarvestPos(resourceLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string Unit::toString() const {
|
std::string Unit::toString() const {
|
||||||
std::string result = "";
|
std::string result = "";
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
#include "skill_type.h"
|
#include "skill_type.h"
|
||||||
#include "game_constants.h"
|
#include "game_constants.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include "platform_common.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
namespace Glest{ namespace Game{
|
namespace Glest { namespace Game {
|
||||||
|
|
||||||
using Shared::Graphics::ParticleSystem;
|
using Shared::Graphics::ParticleSystem;
|
||||||
using Shared::Graphics::UnitParticleSystem;
|
using Shared::Graphics::UnitParticleSystem;
|
||||||
|
@ -29,6 +30,7 @@ using Shared::Graphics::Vec2f;
|
||||||
using Shared::Graphics::Vec3f;
|
using Shared::Graphics::Vec3f;
|
||||||
using Shared::Graphics::Vec2i;
|
using Shared::Graphics::Vec2i;
|
||||||
using Shared::Graphics::Model;
|
using Shared::Graphics::Model;
|
||||||
|
using Shared::PlatformCommon::Chrono;
|
||||||
|
|
||||||
using std::set;
|
using std::set;
|
||||||
|
|
||||||
|
@ -281,6 +283,13 @@ private:
|
||||||
string currentUnitTitle;
|
string currentUnitTitle;
|
||||||
|
|
||||||
bool inBailOutAttempt;
|
bool inBailOutAttempt;
|
||||||
|
// This buffer stores a list of bad harvest cells, along with the start
|
||||||
|
// time of when it was detected. Typically this may be due to a unit
|
||||||
|
// constantly getting blocked from getting to the resource so this
|
||||||
|
// list may be used to tell areas of the game to ignore those cells for a
|
||||||
|
// period of time
|
||||||
|
std::vector<std::pair<Vec2i,Chrono> > badHarvestPosList;
|
||||||
|
std::pair<Vec2i,Chrono> lastHarvestResourceTarget;
|
||||||
|
|
||||||
static Game *game;
|
static Game *game;
|
||||||
|
|
||||||
|
@ -426,6 +435,16 @@ public:
|
||||||
bool getInBailOutAttempt() const { return inBailOutAttempt; }
|
bool getInBailOutAttempt() const { return inBailOutAttempt; }
|
||||||
void setInBailOutAttempt(bool value) { inBailOutAttempt = value; }
|
void setInBailOutAttempt(bool value) { inBailOutAttempt = value; }
|
||||||
|
|
||||||
|
std::vector<std::pair<Vec2i,Chrono> > getBadHarvestPosList() const { return badHarvestPosList; }
|
||||||
|
void setBadHarvestPosList(std::vector<std::pair<Vec2i,Chrono> > value) { badHarvestPosList = value; }
|
||||||
|
void addBadHarvestPos(const Vec2i &value);
|
||||||
|
void removeBadHarvestPos(const Vec2i &value);
|
||||||
|
bool isBadHarvestPos(const Vec2i &value);
|
||||||
|
void cleanupOldBadHarvestPos();
|
||||||
|
|
||||||
|
void setLastHarvestResourceTarget(const Vec2i *pos);
|
||||||
|
std::pair<Vec2i,Chrono> getLastHarvestResourceTarget() const { return lastHarvestResourceTarget;}
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -249,15 +249,18 @@ bool Map::isInsideSurface(const Vec2i &sPos) const{
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns if there is a resource next to a unit, in "resourcePos" is stored the relative position of the resource
|
//returns if there is a resource next to a unit, in "resourcePos" is stored the relative position of the resource
|
||||||
bool Map::isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resourcePos, int size) const{
|
bool Map::isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resourcePos, int size, Unit *unit) const {
|
||||||
for(int i=-1; i<=size; ++i){
|
for(int i = -1; i <= size; ++i) {
|
||||||
for(int j=-1; j<=size; ++j){
|
for(int j = -1; j <= size; ++j) {
|
||||||
if(isInside(pos.x+i, pos.y+j)){
|
if(isInside(pos.x + i, pos.y + j)) {
|
||||||
Resource *r= getSurfaceCell(toSurfCoords(Vec2i(pos.x+i, pos.y+j)))->getResource();
|
Resource *r= getSurfaceCell(toSurfCoords(Vec2i(pos.x + i, pos.y + j)))->getResource();
|
||||||
if(r!=NULL){
|
if(r != NULL){
|
||||||
if(r->getType()==rt){
|
if(r->getType() == rt) {
|
||||||
resourcePos= pos + Vec2i(i,j);
|
resourcePos= pos + Vec2i(i,j);
|
||||||
return true;
|
|
||||||
|
if(unit == NULL || unit->isBadHarvestPos(resourcePos) == false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,7 @@ public:
|
||||||
bool isInside(const Vec2i &pos) const;
|
bool isInside(const Vec2i &pos) const;
|
||||||
bool isInsideSurface(int sx, int sy) const;
|
bool isInsideSurface(int sx, int sy) const;
|
||||||
bool isInsideSurface(const Vec2i &sPos) const;
|
bool isInsideSurface(const Vec2i &sPos) const;
|
||||||
bool isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resourcePos, int size) const;
|
bool isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resourcePos, int size, Unit *unit=NULL) const;
|
||||||
bool isResourceNear(const Vec2i &pos, int size, const ResourceType *rt, Vec2i &resourcePos) const;
|
bool isResourceNear(const Vec2i &pos, int size, const ResourceType *rt, Vec2i &resourcePos) const;
|
||||||
|
|
||||||
//free cells
|
//free cells
|
||||||
|
|
|
@ -572,7 +572,7 @@ void UnitUpdater::updateBuild(Unit *unit) {
|
||||||
|
|
||||||
// ==================== updateHarvest ====================
|
// ==================== updateHarvest ====================
|
||||||
|
|
||||||
void UnitUpdater::updateHarvest(Unit *unit){
|
void UnitUpdater::updateHarvest(Unit *unit) {
|
||||||
Chrono chrono;
|
Chrono chrono;
|
||||||
chrono.start();
|
chrono.start();
|
||||||
|
|
||||||
|
@ -585,17 +585,17 @@ void UnitUpdater::updateHarvest(Unit *unit){
|
||||||
|
|
||||||
if(unit->getCurrSkill()->getClass() != scHarvest) {
|
if(unit->getCurrSkill()->getClass() != scHarvest) {
|
||||||
//if not working
|
//if not working
|
||||||
if(unit->getLoadCount()==0){
|
if(unit->getLoadCount() == 0) {
|
||||||
//if not loaded go for resources
|
//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(r != NULL && hct->canHarvest(r->getType())) {
|
||||||
//if can harvest dest. pos
|
//if can harvest dest. pos
|
||||||
bool canHarvestDestPos = false;
|
bool canHarvestDestPos = false;
|
||||||
|
|
||||||
switch(this->game->getGameSettings()->getPathFinderType()) {
|
switch(this->game->getGameSettings()->getPathFinderType()) {
|
||||||
case pfBasic:
|
case pfBasic:
|
||||||
canHarvestDestPos = (unit->getPos().dist(command->getPos())<harvestDistance &&
|
canHarvestDestPos = (unit->getPos().dist(command->getPos()) < harvestDistance &&
|
||||||
map->isResourceNear(unit->getPos(), r->getType(), targetPos,unit->getType()->getSize()));
|
map->isResourceNear(unit->getPos(), r->getType(), targetPos,unit->getType()->getSize(),unit));
|
||||||
break;
|
break;
|
||||||
case pfRoutePlanner:
|
case pfRoutePlanner:
|
||||||
canHarvestDestPos = map->isResourceNear(unit->getPos(), unit->getType()->getSize(), r->getType(), targetPos);
|
canHarvestDestPos = map->isResourceNear(unit->getPos(), unit->getType()->getSize(), r->getType(), targetPos);
|
||||||
|
@ -605,22 +605,24 @@ void UnitUpdater::updateHarvest(Unit *unit){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canHarvestDestPos == true) {
|
if (canHarvestDestPos == true) {
|
||||||
//if it finds resources it starts harvesting
|
unit->setLastHarvestResourceTarget(&targetPos);
|
||||||
unit->setCurrSkill(hct->getHarvestSkillType());
|
|
||||||
unit->setTargetPos(targetPos);
|
|
||||||
command->setPos(targetPos);
|
|
||||||
unit->setLoadCount(0);
|
|
||||||
|
|
||||||
switch(this->game->getGameSettings()->getPathFinderType()) {
|
//if it finds resources it starts harvesting
|
||||||
case pfBasic:
|
unit->setCurrSkill(hct->getHarvestSkillType());
|
||||||
unit->setLoadType(map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()))->getResource()->getType());
|
unit->setTargetPos(targetPos);
|
||||||
break;
|
command->setPos(targetPos);
|
||||||
case pfRoutePlanner:
|
unit->setLoadCount(0);
|
||||||
unit->setLoadType(r->getType());
|
|
||||||
break;
|
switch(this->game->getGameSettings()->getPathFinderType()) {
|
||||||
default:
|
case pfBasic:
|
||||||
throw runtime_error("detected unsupported pathfinder type!");
|
unit->setLoadType(map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()))->getResource()->getType());
|
||||||
}
|
break;
|
||||||
|
case pfRoutePlanner:
|
||||||
|
unit->setLoadType(r->getType());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw runtime_error("detected unsupported pathfinder type!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
@ -652,7 +654,7 @@ void UnitUpdater::updateHarvest(Unit *unit){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
//if loaded, return to store
|
//if loaded, return to store
|
||||||
Unit *store= world->nearestStore(unit->getPos(), unit->getFaction()->getIndex(), unit->getLoadType());
|
Unit *store= world->nearestStore(unit->getPos(), unit->getFaction()->getIndex(), unit->getLoadType());
|
||||||
if(store!=NULL) {
|
if(store!=NULL) {
|
||||||
|
@ -702,8 +704,10 @@ void UnitUpdater::updateHarvest(Unit *unit){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
//if working
|
//if working
|
||||||
|
//unit->setLastHarvestResourceTarget(NULL);
|
||||||
|
|
||||||
SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()));
|
SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()));
|
||||||
Resource *r= sc->getResource();
|
Resource *r= sc->getResource();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue