- 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:
Mark Vejvoda 2010-10-17 06:34:42 +00:00
parent 2a805240b4
commit 55b4f0bd2b
7 changed files with 182 additions and 53 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -66,8 +66,8 @@ namespace Shared { namespace PlatformCommon {
namespace Private {
bool shouldBeFullscreen = false;
int ScreenWidth;
int ScreenHeight;
int ScreenWidth = 800;
int ScreenHeight = 600;
}