- Incremented version to next major release # so new work can begin.
- some initial work to assist units from getting stuck when given commands. This is for both AI and human players and deals with the pathfinder and units getting constantly blocked from their destination.
This commit is contained in:
parent
2a805240b4
commit
55b4f0bd2b
|
@ -19,6 +19,7 @@
|
|||
#include "unit.h"
|
||||
#include "unit_type.h"
|
||||
#include "platform_common.h"
|
||||
#include "command.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -35,8 +36,10 @@ namespace Glest{ namespace Game{
|
|||
// ===================== PUBLIC ========================
|
||||
|
||||
const int PathFinder::maxFreeSearchRadius= 10;
|
||||
const int PathFinder::pathFindNodesMax= 400;
|
||||
const int PathFinder::pathFindRefresh= 10;
|
||||
//const int PathFinder::pathFindNodesMax= 400;
|
||||
const int PathFinder::pathFindNodesMax= 500;
|
||||
//const int PathFinder::pathFindRefresh= 10;
|
||||
const int PathFinder::pathFindRefresh= 5;
|
||||
|
||||
|
||||
PathFinder::PathFinder() {
|
||||
|
@ -80,6 +83,18 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos){
|
|||
if(finalPos == unit->getPos()) {
|
||||
//if arrived
|
||||
unit->setCurrSkill(scStop);
|
||||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
||||
string commandDesc = "none";
|
||||
Command *command= unit->getCurrCommand();
|
||||
if(command != NULL && command->getCommandType() != NULL) {
|
||||
commandDesc = command->getCommandType()->toString();
|
||||
}
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"State: arrived#1 at pos: %s, command [%s]",finalPos.getString().c_str(),commandDesc.c_str());
|
||||
unit->setCurrentUnitTitle(szBuf);
|
||||
}
|
||||
|
||||
return tsArrived;
|
||||
}
|
||||
else {
|
||||
|
@ -116,6 +131,53 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos){
|
|||
switch(ts) {
|
||||
case tsBlocked:
|
||||
case tsArrived:
|
||||
// The unit is stuck (not only blocked but unable to go anywhere for a while)
|
||||
// We will try to bail out of the immediate area
|
||||
if( ts == tsBlocked && unit->getInBailOutAttempt() == false &&
|
||||
path->isStuck() == true) {
|
||||
unit->setInBailOutAttempt(true);
|
||||
|
||||
// Try to bail out up to 20 cells away
|
||||
for(int bailoutX = -20; bailoutX <= 20 && ts == tsBlocked; ++bailoutX) {
|
||||
for(int bailoutY = -20; bailoutY <= 20 && ts == tsBlocked; ++bailoutY) {
|
||||
const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY);
|
||||
if(map->canMove(unit, unit->getPos(), newFinalPos)) {
|
||||
ts= aStar(unit, newFinalPos);
|
||||
if(ts == tsMoving) {
|
||||
unit->setInBailOutAttempt(false);
|
||||
|
||||
if(dynamic_cast<UnitPathBasic *>(path) != NULL) {
|
||||
UnitPathBasic *basicPath = dynamic_cast<UnitPathBasic *>(path);
|
||||
Vec2i pos= basicPath->pop();
|
||||
if(map->canMove(unit, unit->getPos(), pos)) {
|
||||
unit->setTargetPos(pos);
|
||||
}
|
||||
else {
|
||||
unit->setCurrSkill(scStop);
|
||||
return tsBlocked;
|
||||
}
|
||||
}
|
||||
else if(dynamic_cast<UnitPath *>(path) != NULL) {
|
||||
UnitPath *advPath = dynamic_cast<UnitPath *>(path);
|
||||
Vec2i pos= advPath->peek();
|
||||
if(map->canMove(unit, unit->getPos(), pos)) {
|
||||
advPath->pop();
|
||||
unit->setTargetPos(pos);
|
||||
}
|
||||
else {
|
||||
unit->setCurrSkill(scStop);
|
||||
return tsBlocked;
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw runtime_error("unsupported or missing path finder detected!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unit->setInBailOutAttempt(false);
|
||||
}
|
||||
unit->setCurrSkill(scStop);
|
||||
break;
|
||||
case tsMoving:
|
||||
|
@ -168,6 +230,16 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
|||
|
||||
//if arrived
|
||||
if(finalPos == unit->getPos()) {
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
||||
string commandDesc = "none";
|
||||
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);
|
||||
}
|
||||
return tsArrived;
|
||||
}
|
||||
|
||||
|
@ -175,7 +247,11 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
|||
|
||||
//a) push starting pos into openNodes
|
||||
Node *firstNode= newNode();
|
||||
assert(firstNode!=NULL);;
|
||||
assert(firstNode != NULL);
|
||||
if(firstNode == NULL) {
|
||||
throw runtime_error("firstNode == NULL");
|
||||
}
|
||||
|
||||
firstNode->next= NULL;
|
||||
firstNode->prev= NULL;
|
||||
const Vec2i unitPos = unit->getPos();
|
||||
|
@ -191,10 +267,10 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
|||
|
||||
//if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||
|
||||
while(!nodeLimitReached){
|
||||
while(nodeLimitReached == false) {
|
||||
|
||||
//b1) is open nodes is empty => failed to find the path
|
||||
if(openNodes.empty()){
|
||||
if(openNodes.empty() == true) {
|
||||
pathFound= false;
|
||||
break;
|
||||
}
|
||||
|
@ -213,8 +289,8 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
|||
//add all succesors that are not in closedNodes or openNodes to openNodes
|
||||
closedNodes.push_back(node);
|
||||
openNodes.erase(it);
|
||||
for(int i=-1; i<=1 && !nodeLimitReached; ++i){
|
||||
for(int j=-1; j<=1 && !nodeLimitReached; ++j){
|
||||
for(int i = -1; i <= 1 && nodeLimitReached == false; ++i) {
|
||||
for(int j = -1; j <= 1 && nodeLimitReached == false; ++j) {
|
||||
Vec2i sucPos= node->pos + Vec2i(i, j);
|
||||
if(openPos(sucPos) == false && map->aproxCanMove(unit, node->pos, sucPos)) {
|
||||
//if node is not open and canMove then generate another node
|
||||
|
@ -240,7 +316,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
|||
Node *lastNode= node;
|
||||
|
||||
//if consumed all nodes find best node (to avoid strange behaviour)
|
||||
if(nodeLimitReached){
|
||||
if(nodeLimitReached == true) {
|
||||
for(Nodes::iterator it= closedNodes.begin(); it != closedNodes.end(); ++it) {
|
||||
if((*it)->heuristic < lastNode->heuristic) {
|
||||
lastNode= *it;
|
||||
|
@ -251,10 +327,22 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
|||
//if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||
|
||||
//check results of path finding
|
||||
TravelState ts;
|
||||
TravelState ts = tsImpossible;
|
||||
UnitPathInterface *path= unit->getPath();
|
||||
if(pathFound == false || lastNode == firstNode) {
|
||||
//blocked
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
||||
string commandDesc = "none";
|
||||
Command *command= unit->getCurrCommand();
|
||||
if(command != NULL && command->getCommandType() != NULL) {
|
||||
commandDesc = command->getCommandType()->toString();
|
||||
}
|
||||
|
||||
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());
|
||||
unit->setCurrentUnitTitle(szBuf);
|
||||
}
|
||||
|
||||
ts= tsBlocked;
|
||||
path->incBlockCount();
|
||||
}
|
||||
|
@ -275,6 +363,18 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
|
|||
for(int i=0; currNode->next != NULL && i < pathFindRefresh; currNode= currNode->next, i++) {
|
||||
path->add(currNode->next->pos);
|
||||
}
|
||||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
||||
string commandDesc = "none";
|
||||
Command *command= unit->getCurrCommand();
|
||||
if(command != NULL && command->getCommandType() != NULL) {
|
||||
commandDesc = command->getCommandType()->toString();
|
||||
}
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"State: moving, cmd [%s] pos: %s dest pos: %s, Queue= %d",commandDesc.c_str(),unit->getPos().getString().c_str(), targetPos.getString().c_str(),path->getQueueCount());
|
||||
unit->setCurrentUnitTitle(szBuf);
|
||||
}
|
||||
}
|
||||
|
||||
if(chrono.getMillis() > 2) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||
|
@ -301,7 +401,6 @@ Vec2i PathFinder::computeNearestFreePos(const Unit *unit, const Vec2i &finalPos)
|
|||
}
|
||||
|
||||
//unit data
|
||||
Vec2i unitPos= unit->getPos();
|
||||
int size= unit->getType()->getSize();
|
||||
Field field= unit->getCurrField();
|
||||
int teamIndex= unit->getTeam();
|
||||
|
@ -312,6 +411,7 @@ Vec2i PathFinder::computeNearestFreePos(const Unit *unit, const Vec2i &finalPos)
|
|||
}
|
||||
|
||||
//find nearest pos
|
||||
Vec2i unitPos= unit->getPos();
|
||||
Vec2i nearestPos= unitPos;
|
||||
float nearestDist= unitPos.dist(finalPos);
|
||||
for(int i= -maxFreeSearchRadius; i <= maxFreeSearchRadius; ++i) {
|
||||
|
@ -344,9 +444,12 @@ float PathFinder::heuristic(const Vec2i &pos, const Vec2i &finalPos){
|
|||
//returns an iterator to the lowest heuristic node
|
||||
PathFinder::Nodes::iterator PathFinder::minHeuristic() {
|
||||
|
||||
Nodes::iterator minNodeIt= openNodes.begin();
|
||||
assert(openNodes.empty() == false);
|
||||
if(openNodes.empty() == true) {
|
||||
throw runtime_error("openNodes.empty() == true");
|
||||
}
|
||||
|
||||
assert(!openNodes.empty());
|
||||
Nodes::iterator minNodeIt = openNodes.begin();
|
||||
|
||||
for(Nodes::iterator it= openNodes.begin(); it != openNodes.end(); ++it) {
|
||||
if((*it)->heuristic < (*minNodeIt)->heuristic){
|
||||
|
|
|
@ -26,7 +26,7 @@ using namespace Shared::Platform;
|
|||
namespace Glest { namespace Game {
|
||||
|
||||
const string mailString = "contact_game@glest.org";
|
||||
const string glestVersionString = "v3.3.7.2";
|
||||
const string glestVersionString = "v3.4.0-dev";
|
||||
const string SVN_Rev = "$Rev$";
|
||||
|
||||
string getCrashDumpFileName(){
|
||||
|
|
|
@ -1602,9 +1602,9 @@ void Game::render2d(){
|
|||
}
|
||||
renderer.renderUnitTitles(coreData.getMenuFontNormal(),Vec3f(1.0f));
|
||||
}
|
||||
else if(renderer.getAllowRenderUnitTitles() == true) {
|
||||
renderer.setAllowRenderUnitTitles(false);
|
||||
}
|
||||
//else if(renderer.getAllowRenderUnitTitles() == true) {
|
||||
// renderer.setAllowRenderUnitTitles(false);
|
||||
//}
|
||||
|
||||
//network status
|
||||
if(renderNetworkStatus == true) {
|
||||
|
|
|
@ -758,6 +758,11 @@ int glestMain(int argc, char** argv){
|
|||
Renderer &renderer= Renderer::getInstance();
|
||||
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] OpenGL Info:\n%s\n",__FILE__,__FUNCTION__,__LINE__,renderer.getGlInfo().c_str());
|
||||
|
||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
||||
renderer.setAllowRenderUnitTitles(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled);
|
||||
SystemFlags::OutputDebug(SystemFlags::debugPathFinder,"In [%s::%s Line: %d] renderer.setAllowRenderUnitTitles = %d\n",__FILE__,__FUNCTION__,__LINE__,SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled);
|
||||
}
|
||||
|
||||
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == true) {
|
||||
//Renderer &renderer= Renderer::getInstance();
|
||||
printf("%s",renderer.getGlInfo().c_str());
|
||||
|
|
|
@ -49,6 +49,10 @@ bool UnitPathBasic::isBlocked() const {
|
|||
return blockCount >= maxBlockCount;
|
||||
}
|
||||
|
||||
bool UnitPathBasic::isStuck() const {
|
||||
return (isBlocked() == true && blockCount >= (maxBlockCount * 2));
|
||||
}
|
||||
|
||||
void UnitPathBasic::clear() {
|
||||
pathQueue.clear();
|
||||
blockCount= 0;
|
||||
|
@ -178,6 +182,7 @@ Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, const UnitType
|
|||
this->visible = true;
|
||||
this->retryCurrCommandCount=0;
|
||||
this->screenPos = Vec3f(0.0);
|
||||
this->inBailOutAttempt = false;
|
||||
|
||||
level= NULL;
|
||||
loadType= NULL;
|
||||
|
@ -1784,6 +1789,8 @@ std::string Unit::toString() const {
|
|||
|
||||
result += "currentUnitTitle = " + currentUnitTitle + "\n";
|
||||
|
||||
result += "inBailOutAttempt = " + intToStr(inBailOutAttempt) + "\n";
|
||||
|
||||
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
return result;
|
||||
|
|
|
@ -104,12 +104,15 @@ public:
|
|||
|
||||
virtual bool isBlocked() const = 0;
|
||||
virtual bool isEmpty() const = 0;
|
||||
virtual bool isStuck() const = 0;
|
||||
|
||||
virtual void clear() = 0;
|
||||
virtual void clearBlockCount() = 0;
|
||||
virtual void incBlockCount() = 0;
|
||||
virtual void add(const Vec2i &path) = 0;
|
||||
//virtual Vec2i pop() = 0;
|
||||
virtual int getBlockCount() const = 0;
|
||||
virtual int getQueueCount() const = 0;
|
||||
|
||||
virtual std::string toString() const = 0;
|
||||
};
|
||||
|
@ -126,12 +129,15 @@ public:
|
|||
UnitPathBasic();
|
||||
virtual bool isBlocked() const;
|
||||
virtual bool isEmpty() const;
|
||||
virtual bool isStuck() const;
|
||||
|
||||
virtual void clear();
|
||||
virtual void clearBlockCount() { blockCount = 0; }
|
||||
virtual void incBlockCount();
|
||||
virtual void add(const Vec2i &path);
|
||||
Vec2i pop();
|
||||
virtual int getBlockCount() const { return blockCount; }
|
||||
virtual int getQueueCount() const { return pathQueue.size(); }
|
||||
|
||||
virtual std::string toString() const;
|
||||
};
|
||||
|
@ -153,6 +159,8 @@ public:
|
|||
UnitPath() : blockCount(0) {} /**< Construct path object */
|
||||
virtual bool isBlocked() const {return blockCount >= maxBlockCount;} /**< is this path blocked */
|
||||
virtual bool isEmpty() const {return list<Vec2i>::empty();} /**< is path empty */
|
||||
virtual bool isStuck() const {return false; }
|
||||
|
||||
int size() const {return list<Vec2i>::size();} /**< size of path */
|
||||
virtual void clear() {list<Vec2i>::clear(); blockCount = 0;} /**< clear the path */
|
||||
virtual void clearBlockCount() { blockCount = 0; }
|
||||
|
@ -172,7 +180,8 @@ public:
|
|||
//virtual Vec2i pop() { Vec2i p= front(); erase(begin()); return p; } /**< pop the next position off the path */
|
||||
void pop() { erase(begin()); } /**< pop the next position off the path */
|
||||
#endif
|
||||
int getBlockCount() const { return blockCount; }
|
||||
virtual int getBlockCount() const { return blockCount; }
|
||||
virtual int getQueueCount() const { return this->size(); }
|
||||
|
||||
virtual std::string toString() const;
|
||||
};
|
||||
|
@ -271,6 +280,8 @@ private:
|
|||
Vec3f screenPos;
|
||||
string currentUnitTitle;
|
||||
|
||||
bool inBailOutAttempt;
|
||||
|
||||
static Game *game;
|
||||
|
||||
public:
|
||||
|
@ -412,6 +423,9 @@ public:
|
|||
|
||||
void exploreCells();
|
||||
|
||||
bool getInBailOutAttempt() const { return inBailOutAttempt; }
|
||||
void setInBailOutAttempt(bool value) { inBailOutAttempt = value; }
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -66,8 +66,8 @@ namespace Shared { namespace PlatformCommon {
|
|||
namespace Private {
|
||||
|
||||
bool shouldBeFullscreen = false;
|
||||
int ScreenWidth;
|
||||
int ScreenHeight;
|
||||
int ScreenWidth = 800;
|
||||
int ScreenHeight = 600;
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue