- added a new pathfinder to test to see if it performs better than the old one
This commit is contained in:
parent
3b9f799d26
commit
771ff91c1c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,150 @@
|
||||||
|
/*!
|
||||||
|
// ==============================================================
|
||||||
|
// This file is part of Glest (www.glest.org)
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012 Mark Vejvoda
|
||||||
|
//
|
||||||
|
// You can redistribute this code and/or modify it under
|
||||||
|
// the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2 of the
|
||||||
|
// License, or (at your option) any later version
|
||||||
|
// ==============================================================
|
||||||
|
|
||||||
|
** Copyright (c) 2007 by John W. Ratcliff mailto:jratcliff@infiniplex.net
|
||||||
|
**
|
||||||
|
** Portions of this source has been released with the PhysXViewer application, as well as
|
||||||
|
** Rocket, CreateDynamics, ODF, and as a number of sample code snippets.
|
||||||
|
**
|
||||||
|
** If you find this code useful or you are feeling particularily generous I would
|
||||||
|
** ask that you please go to http://www.amillionpixels.us and make a donation
|
||||||
|
** to Troy DeMolay.
|
||||||
|
**
|
||||||
|
** DeMolay is a youth group for young men between the ages of 12 and 21.
|
||||||
|
** It teaches strong moral principles, as well as leadership skills and
|
||||||
|
** public speaking. The donations page uses the 'pay for pixels' paradigm
|
||||||
|
** where, in this case, a pixel is only a single penny. Donations can be
|
||||||
|
** made for as small as $4 or as high as a $100 block. Each person who donates
|
||||||
|
** will get a link to their own site as well as acknowledgement on the
|
||||||
|
** donations blog located here http://www.amillionpixels.blogspot.com/
|
||||||
|
**
|
||||||
|
** If you wish to contact me you can use the following methods:
|
||||||
|
**
|
||||||
|
** Skype Phone: 636-486-4040 (let it ring a long time while it goes through switches)
|
||||||
|
** Skype ID: jratcliff63367
|
||||||
|
** Yahoo: jratcliff63367
|
||||||
|
** AOL: jratcliff1961
|
||||||
|
** email: jratcliff@infiniplex.net
|
||||||
|
|
||||||
|
A* Algorithm Implementation using STL is
|
||||||
|
Copyright (C)2001-2005 Justin Heyes-Jones
|
||||||
|
|
||||||
|
FixedSizeAllocator class
|
||||||
|
Copyright 2001 Justin Heyes-Jones
|
||||||
|
|
||||||
|
This class is a constant time O(1) memory manager for objects of
|
||||||
|
a specified type. The type is specified using a template class.
|
||||||
|
|
||||||
|
Memory is allocated from a fixed size buffer which you can specify in the
|
||||||
|
class constructor or use the default.
|
||||||
|
|
||||||
|
Using GetFirst and GetNext it is possible to iterate through the elements
|
||||||
|
one by one, and this would be the most common use for the class.
|
||||||
|
|
||||||
|
I would suggest using this class when you want O(1) add and delete
|
||||||
|
and you don't do much searching, which would be O(n). Structures such as binary
|
||||||
|
trees can be used instead to get O(logn) access time.
|
||||||
|
|
||||||
|
**
|
||||||
|
** The MIT license:
|
||||||
|
**
|
||||||
|
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
** of this software and associated documentation files (the "Software"), to deal
|
||||||
|
** in the Software without restriction, including without limitation the rights
|
||||||
|
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
** copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
** to do so, subject to the following conditions:
|
||||||
|
**
|
||||||
|
** The above copyright notice and this permission notice shall be included in all
|
||||||
|
** copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FAST_ASTAR_H
|
||||||
|
|
||||||
|
#define FAST_ASTAR_H
|
||||||
|
|
||||||
|
//*** IMPORTANT : READ ME FIRST !!
|
||||||
|
//***
|
||||||
|
//*** This source code simply provides a C++ wrapper for the AStar Algorithm Implementation in STL written by Justin Heyes-Jones
|
||||||
|
//*** There is nothing wrong with Justin's code in any way, except that he uses templates. My personal programming style is
|
||||||
|
//*** to use virtual interfaces and the PIMPLE paradigm to hide the details of the implementation.
|
||||||
|
//***
|
||||||
|
//*** To use my wrapper you simply have your own path node inherit the pure virtual interface 'AI_Node' and implement the
|
||||||
|
//*** following four methods.
|
||||||
|
//***
|
||||||
|
//***
|
||||||
|
//** virtual float getDistance(const AI_Node *node) = 0; // Return the distance between two nodes
|
||||||
|
//** virtual float getCost(void) = 0; // return the relative 'cost' of a node. Default should be 1.
|
||||||
|
//** virtual unsigned int getEdgeCount(void) const = 0; // Return the number of edges in a node.
|
||||||
|
//** virtual AI_Node * getEdge(int index) const = 0; // Return a pointer to the node a particular edge is connected to.
|
||||||
|
//**
|
||||||
|
//** That's all there is to it.
|
||||||
|
//**
|
||||||
|
//** Here is an example usage:
|
||||||
|
//**
|
||||||
|
//** FastAstar *fa = createFastAstar();
|
||||||
|
//** astarStartSearch(fq,fromNode,toNode);
|
||||||
|
//** for (int i=0; i<10000; i++)
|
||||||
|
//** {
|
||||||
|
//** bool finished = astarSearchStep(fa);
|
||||||
|
//** if ( finished ) break;
|
||||||
|
//** }
|
||||||
|
//**
|
||||||
|
//** unsigned int count;
|
||||||
|
//** AI_Node **solution = getSolution(fa,count);
|
||||||
|
//**
|
||||||
|
//** ... do something you want with the answer
|
||||||
|
//**
|
||||||
|
//** releaseFastAstar(fa);
|
||||||
|
//**
|
||||||
|
//*******************************
|
||||||
|
|
||||||
|
|
||||||
|
class AI_Node
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual float getDistance(const AI_Node *node,void *userData) = 0;
|
||||||
|
virtual float getCost(void *userData) = 0;
|
||||||
|
virtual unsigned int getEdgeCount(void *userData) const = 0;
|
||||||
|
virtual AI_Node * getEdge(int index,void *userData) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SearchState {
|
||||||
|
SEARCH_STATE_NOT_INITIALISED,
|
||||||
|
SEARCH_STATE_SEARCHING,
|
||||||
|
SEARCH_STATE_SUCCEEDED,
|
||||||
|
SEARCH_STATE_FAILED,
|
||||||
|
SEARCH_STATE_OUT_OF_MEMORY,
|
||||||
|
SEARCH_STATE_INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
class FastAstar;
|
||||||
|
|
||||||
|
FastAstar * createFastAstar(void); // Create an instance of the FastAstar utility.
|
||||||
|
void astarStartSearch(FastAstar *astar,AI_Node *from,AI_Node *to, void *userData); // start a search.
|
||||||
|
|
||||||
|
bool astarSearchStep(FastAstar *astar,unsigned int &searchCount); // step the A star algorithm one time. Return true if the search is completed.
|
||||||
|
SearchState getLastSearchState(FastAstar *astar);
|
||||||
|
|
||||||
|
AI_Node ** getSolution(FastAstar *astar,unsigned int &count); // retrieve the solution. If this returns a null pointer and count of zero, it means no solution could be found.
|
||||||
|
void releaseFastAstar(FastAstar *astar); // Release the intance of the FastAstar utility.
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -21,6 +21,7 @@
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "faction.h"
|
#include "faction.h"
|
||||||
#include "randomgen.h"
|
#include "randomgen.h"
|
||||||
|
#include "fast_path_finder.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -49,8 +50,10 @@ const int PathFinder::pathFindExtendRefreshNodeCountMin = 40;
|
||||||
const int PathFinder::pathFindExtendRefreshNodeCountMax = 40;
|
const int PathFinder::pathFindExtendRefreshNodeCountMax = 40;
|
||||||
|
|
||||||
PathFinder::PathFinder() {
|
PathFinder::PathFinder() {
|
||||||
|
minorDebugPathfinder = false;
|
||||||
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
|
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
|
||||||
factions.push_back(FactionState());
|
factions.push_back(FactionState());
|
||||||
|
//factions.resize(GameConstants::maxPlayers);
|
||||||
}
|
}
|
||||||
map=NULL;
|
map=NULL;
|
||||||
}
|
}
|
||||||
|
@ -61,8 +64,10 @@ int PathFinder::getPathFindExtendRefreshNodeCount(int factionIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PathFinder::PathFinder(const Map *map) {
|
PathFinder::PathFinder(const Map *map) {
|
||||||
|
minorDebugPathfinder = false;
|
||||||
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
|
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
|
||||||
factions.push_back(FactionState());
|
factions.push_back(FactionState());
|
||||||
|
//factions.resize(GameConstants::maxPlayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
map=NULL;
|
map=NULL;
|
||||||
|
@ -82,6 +87,9 @@ void PathFinder::init(const Map *map) {
|
||||||
PathFinder::~PathFinder() {
|
PathFinder::~PathFinder() {
|
||||||
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
|
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
|
||||||
factions[i].nodePool.clear();
|
factions[i].nodePool.clear();
|
||||||
|
|
||||||
|
releaseFastAstar(factions[i].fa);
|
||||||
|
factions[i].fa = NULL;
|
||||||
}
|
}
|
||||||
factions.clear();
|
factions.clear();
|
||||||
map=NULL;
|
map=NULL;
|
||||||
|
@ -110,6 +118,8 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
||||||
throw megaglest_runtime_error("map == NULL");
|
throw megaglest_runtime_error("map == NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unit->setCurrentPathFinderDesiredFinalPos(finalPos);
|
||||||
|
|
||||||
if(frameIndex >= 0) {
|
if(frameIndex >= 0) {
|
||||||
clearUnitPrecache(unit);
|
clearUnitPrecache(unit);
|
||||||
}
|
}
|
||||||
|
@ -208,207 +218,639 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
||||||
maxNodeCount= PathFinder::pathFindNodesAbsoluteMax;
|
maxNodeCount= PathFinder::pathFindNodesAbsoluteMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
ts = aStar(unit, finalPos, false, frameIndex, maxNodeCount);
|
int unitFactionIndex = unit->getFactionIndex();
|
||||||
|
|
||||||
//post actions
|
minorDebugPathfinder = false;
|
||||||
switch(ts) {
|
bool enableFastPathfinder = true;
|
||||||
case tsBlocked:
|
if(enableFastPathfinder == true) {
|
||||||
case tsArrived:
|
if(minorDebugPathfinder) printf("Fast Pathfind Unit [%d - %s] from = %s to = %s frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),unit->getPos().getString().c_str(),finalPos.getString().c_str(),frameIndex);
|
||||||
|
|
||||||
// The unit is stuck (not only blocked but unable to go anywhere for a while)
|
ts = aStarFast(unit, finalPos, false, frameIndex, maxNodeCount);
|
||||||
// We will try to bail out of the immediate area
|
|
||||||
if( ts == tsBlocked && unit->getInBailOutAttempt() == false &&
|
|
||||||
path->isStuck() == true) {
|
|
||||||
|
|
||||||
//printf("$$$$ Unit START BAILOUT ATTEMPT for [%d - %s]\n",unit->getId(),unit->getFullName().c_str());
|
//post actions
|
||||||
|
switch(ts) {
|
||||||
|
case tsBlocked:
|
||||||
|
case tsArrived:
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
// The unit is stuck (not only blocked but unable to go anywhere for a while)
|
||||||
char szBuf[4096]="";
|
// We will try to bail out of the immediate area
|
||||||
sprintf(szBuf,"[attempting to BAIL OUT] finalPos [%s] ts [%d]",
|
if( ts == tsBlocked && unit->getInBailOutAttempt() == false &&
|
||||||
finalPos.getString().c_str(),ts);
|
path->isStuck() == true) {
|
||||||
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(wasStuck != NULL) {
|
//printf("$$$$ Unit START BAILOUT ATTEMPT for [%d - %s]\n",unit->getId(),unit->getFullName().c_str());
|
||||||
*wasStuck = true;
|
if(minorDebugPathfinder) printf("Fast Pathfind Unit [%d - %s] START BAILOUT ATTEMPT frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),frameIndex);
|
||||||
}
|
|
||||||
unit->setInBailOutAttempt(true);
|
|
||||||
|
|
||||||
bool useBailoutRadius = Config::getInstance().getBool("EnableBailoutPathfinding","true");
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
||||||
if(useBailoutRadius == true) {
|
char szBuf[4096]="";
|
||||||
|
sprintf(szBuf,"[attempting to BAIL OUT] finalPos [%s] ts [%d]",
|
||||||
|
finalPos.getString().c_str(),ts);
|
||||||
|
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
||||||
|
}
|
||||||
|
|
||||||
//!!!
|
if(wasStuck != NULL) {
|
||||||
bool unitImmediatelyBlocked = false;
|
*wasStuck = true;
|
||||||
|
}
|
||||||
|
unit->setInBailOutAttempt(true);
|
||||||
|
|
||||||
// First check if unit currently blocked all around them, if so don't try to pathfind
|
bool useBailoutRadius = Config::getInstance().getBool("EnableBailoutPathfinding","true");
|
||||||
const bool showConsoleDebugInfo = Config::getInstance().getBool("EnablePathfinderDistanceOutput","false");
|
if(useBailoutRadius == true) {
|
||||||
const Vec2i unitPos = unit->getPos();
|
|
||||||
int failureCount = 0;
|
|
||||||
int cellCount = 0;
|
|
||||||
|
|
||||||
for(int i = -1; i <= 1; ++i) {
|
//!!!
|
||||||
for(int j = -1; j <= 1; ++j) {
|
bool unitImmediatelyBlocked = false;
|
||||||
Vec2i pos = unitPos + Vec2i(i, j);
|
|
||||||
if(pos != unitPos) {
|
// First check if unit currently blocked all around them, if so don't try to pathfind
|
||||||
bool canUnitMoveToCell = map->aproxCanMove(unit, unitPos, pos);
|
const bool showConsoleDebugInfo = Config::getInstance().getBool("EnablePathfinderDistanceOutput","false");
|
||||||
if(canUnitMoveToCell == false) {
|
const Vec2i unitPos = unit->getPos();
|
||||||
failureCount++;
|
int failureCount = 0;
|
||||||
|
int cellCount = 0;
|
||||||
|
|
||||||
|
for(int i = -1; i <= 1; ++i) {
|
||||||
|
for(int j = -1; j <= 1; ++j) {
|
||||||
|
Vec2i pos = unitPos + Vec2i(i, j);
|
||||||
|
if(pos != unitPos) {
|
||||||
|
bool canUnitMoveToCell = map->aproxCanMove(unit, unitPos, pos);
|
||||||
|
if(canUnitMoveToCell == false) {
|
||||||
|
failureCount++;
|
||||||
|
}
|
||||||
|
cellCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unitImmediatelyBlocked = (failureCount == cellCount);
|
||||||
|
|
||||||
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld unitImmediatelyBlocked = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),unitImmediatelyBlocked,failureCount);
|
||||||
|
if(showConsoleDebugInfo && unitImmediatelyBlocked) {
|
||||||
|
printf("**Check if src blocked [%d], unit [%d - %s] from [%s] to [%s] unitImmediatelyBlocked = %d, failureCount = %d [%d]\n",
|
||||||
|
unitImmediatelyBlocked, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), unitImmediatelyBlocked,failureCount,cellCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(unitImmediatelyBlocked == false) {
|
||||||
|
// // First check if final destination blocked
|
||||||
|
// failureCount = 0;
|
||||||
|
// cellCount = 0;
|
||||||
|
//
|
||||||
|
// for(int i = -1; i <= 1; ++i) {
|
||||||
|
// for(int j = -1; j <= 1; ++j) {
|
||||||
|
// Vec2i pos = finalPos + Vec2i(i, j);
|
||||||
|
// if(pos != finalPos) {
|
||||||
|
// bool canUnitMoveToCell = map->aproxCanMove(unit, pos, finalPos);
|
||||||
|
// if(canUnitMoveToCell == false) {
|
||||||
|
// failureCount++;
|
||||||
|
// }
|
||||||
|
// cellCount++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// unitImmediatelyBlocked = (failureCount == cellCount);
|
||||||
|
//
|
||||||
|
// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld unitImmediatelyBlocked = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),unitImmediatelyBlocked,failureCount);
|
||||||
|
// if(showConsoleDebugInfo && nodeLimitReached) {
|
||||||
|
// printf("**Check if dest blocked [%d - %d], unit [%d - %s] from [%s] to [%s] distance %.2f took msecs: %lld unitImmediatelyBlocked = %d, failureCount = %d [%d]\n",
|
||||||
|
// nodeLimitReached, inBailout, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),unitImmediatelyBlocked,failureCount,cellCount);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//!!!
|
||||||
|
|
||||||
|
if(unitImmediatelyBlocked == false) {
|
||||||
|
int tryRadius = factions[unit->getFactionIndex()].random.randRange(0,1);
|
||||||
|
|
||||||
|
// Try to bail out up to PathFinder::pathFindBailoutRadius cells away
|
||||||
|
if(tryRadius > 0) {
|
||||||
|
for(int bailoutX = -PathFinder::pathFindBailoutRadius; bailoutX <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutX) {
|
||||||
|
for(int bailoutY = -PathFinder::pathFindBailoutRadius; bailoutY <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutY) {
|
||||||
|
const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY);
|
||||||
|
bool canUnitMove = map->canMove(unit, unit->getPos(), newFinalPos);
|
||||||
|
|
||||||
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
||||||
|
char szBuf[4096]="";
|
||||||
|
sprintf(szBuf,"[attempting to BAIL OUT] finalPos [%s] newFinalPos [%s] ts [%d] canUnitMove [%d]",
|
||||||
|
finalPos.getString().c_str(),newFinalPos.getString().c_str(),ts,canUnitMove);
|
||||||
|
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(canUnitMove) {
|
||||||
|
//printf("$$$$ Unit BAILOUT(1) ASTAR ATTEMPT for [%d - %s] newFinalPos = [%s]\n",unit->getId(),unit->getFullName().c_str(),newFinalPos.getString().c_str());
|
||||||
|
|
||||||
|
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
||||||
|
ts= aStarFast(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(int bailoutX = PathFinder::pathFindBailoutRadius; bailoutX >= -PathFinder::pathFindBailoutRadius && ts == tsBlocked; --bailoutX) {
|
||||||
|
for(int bailoutY = PathFinder::pathFindBailoutRadius; bailoutY >= -PathFinder::pathFindBailoutRadius && ts == tsBlocked; --bailoutY) {
|
||||||
|
const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY);
|
||||||
|
bool canUnitMove = map->canMove(unit, unit->getPos(), newFinalPos);
|
||||||
|
|
||||||
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
||||||
|
char szBuf[4096]="";
|
||||||
|
sprintf(szBuf,"[attempting to BAIL OUT] finalPos [%s] newFinalPos [%s] ts [%d] canUnitMove [%d]",
|
||||||
|
finalPos.getString().c_str(),newFinalPos.getString().c_str(),ts,canUnitMove);
|
||||||
|
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(canUnitMove) {
|
||||||
|
//printf("$$$$ Unit BAILOUT(1) ASTAR ATTEMPT for [%d - %s] newFinalPos = [%s]\n",unit->getId(),unit->getFullName().c_str(),newFinalPos.getString().c_str());
|
||||||
|
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
||||||
|
ts= aStarFast(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cellCount++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
unit->setInBailOutAttempt(false);
|
||||||
unitImmediatelyBlocked = (failureCount == cellCount);
|
|
||||||
|
|
||||||
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld unitImmediatelyBlocked = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),unitImmediatelyBlocked,failureCount);
|
//printf("$$$$ Unit END BAILOUT ATTEMPT for [%d - %s] ts = %d\n",unit->getId(),unit->getFullName().c_str(),ts);
|
||||||
if(showConsoleDebugInfo && unitImmediatelyBlocked) {
|
|
||||||
printf("**Check if src blocked [%d], unit [%d - %s] from [%s] to [%s] unitImmediatelyBlocked = %d, failureCount = %d [%d]\n",
|
if(ts == tsBlocked) {
|
||||||
unitImmediatelyBlocked, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), unitImmediatelyBlocked,failureCount,cellCount);
|
unit->setLastStuckFrameToCurrentFrame();
|
||||||
|
unit->setLastStuckPos(finalPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(unitImmediatelyBlocked == false) {
|
if(ts == tsArrived || ts == tsBlocked) {
|
||||||
// // First check if final destination blocked
|
if(frameIndex < 0) {
|
||||||
// failureCount = 0;
|
unit->setCurrSkill(scStop);
|
||||||
// cellCount = 0;
|
}
|
||||||
//
|
}
|
||||||
// for(int i = -1; i <= 1; ++i) {
|
break;
|
||||||
// for(int j = -1; j <= 1; ++j) {
|
case tsMoving:
|
||||||
// Vec2i pos = finalPos + Vec2i(i, j);
|
{
|
||||||
// if(pos != finalPos) {
|
if(dynamic_cast<UnitPathBasic *>(path) != NULL) {
|
||||||
// bool canUnitMoveToCell = map->aproxCanMove(unit, pos, finalPos);
|
UnitPathBasic *basicPath = dynamic_cast<UnitPathBasic *>(path);
|
||||||
// if(canUnitMoveToCell == false) {
|
Vec2i pos;
|
||||||
// failureCount++;
|
if(frameIndex < 0) {
|
||||||
// }
|
pos = basicPath->pop(frameIndex < 0);
|
||||||
// cellCount++;
|
}
|
||||||
// }
|
else {
|
||||||
// }
|
if(factions[unit->getFactionIndex()].precachedPath[unit->getId()].size() <= 0) {
|
||||||
// }
|
throw megaglest_runtime_error("factions[unit->getFactionIndex()].precachedPath[unit->getId()].size() <= 0!");
|
||||||
// unitImmediatelyBlocked = (failureCount == cellCount);
|
|
||||||
//
|
|
||||||
// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld unitImmediatelyBlocked = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),unitImmediatelyBlocked,failureCount);
|
|
||||||
// if(showConsoleDebugInfo && nodeLimitReached) {
|
|
||||||
// printf("**Check if dest blocked [%d - %d], unit [%d - %s] from [%s] to [%s] distance %.2f took msecs: %lld unitImmediatelyBlocked = %d, failureCount = %d [%d]\n",
|
|
||||||
// nodeLimitReached, inBailout, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),unitImmediatelyBlocked,failureCount,cellCount);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//!!!
|
|
||||||
|
|
||||||
if(unitImmediatelyBlocked == false) {
|
|
||||||
int tryRadius = factions[unit->getFactionIndex()].random.randRange(0,1);
|
|
||||||
|
|
||||||
// Try to bail out up to PathFinder::pathFindBailoutRadius cells away
|
|
||||||
if(tryRadius > 0) {
|
|
||||||
for(int bailoutX = -PathFinder::pathFindBailoutRadius; bailoutX <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutX) {
|
|
||||||
for(int bailoutY = -PathFinder::pathFindBailoutRadius; bailoutY <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutY) {
|
|
||||||
const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY);
|
|
||||||
bool canUnitMove = map->canMove(unit, unit->getPos(), newFinalPos);
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
|
||||||
char szBuf[4096]="";
|
|
||||||
sprintf(szBuf,"[attempting to BAIL OUT] finalPos [%s] newFinalPos [%s] ts [%d] canUnitMove [%d]",
|
|
||||||
finalPos.getString().c_str(),newFinalPos.getString().c_str(),ts,canUnitMove);
|
|
||||||
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(canUnitMove) {
|
|
||||||
//printf("$$$$ Unit BAILOUT(1) ASTAR ATTEMPT for [%d - %s] newFinalPos = [%s]\n",unit->getId(),unit->getFullName().c_str(),newFinalPos.getString().c_str());
|
|
||||||
|
|
||||||
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
|
||||||
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pos = factions[unit->getFactionIndex()].precachedPath[unit->getId()][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(map->canMove(unit, unit->getPos(), pos)) {
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
unit->setTargetPos(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
unit->setCurrSkill(scStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minorDebugPathfinder) printf("Fast Pathfind Unit [%d - %s] INT BAILOUT ATTEMPT BLOCKED frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),frameIndex);
|
||||||
|
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)) {
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
advPath->pop();
|
||||||
|
unit->setTargetPos(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
unit->setCurrSkill(scStop);
|
||||||
|
}
|
||||||
|
return tsBlocked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for(int bailoutX = PathFinder::pathFindBailoutRadius; bailoutX >= -PathFinder::pathFindBailoutRadius && ts == tsBlocked; --bailoutX) {
|
throw megaglest_runtime_error("unsupported or missing path finder detected!");
|
||||||
for(int bailoutY = PathFinder::pathFindBailoutRadius; bailoutY >= -PathFinder::pathFindBailoutRadius && ts == tsBlocked; --bailoutY) {
|
}
|
||||||
const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY);
|
}
|
||||||
bool canUnitMove = map->canMove(unit, unit->getPos(), newFinalPos);
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
return ts;
|
||||||
char szBuf[4096]="";
|
}
|
||||||
sprintf(szBuf,"[attempting to BAIL OUT] finalPos [%s] newFinalPos [%s] ts [%d] canUnitMove [%d]",
|
else {
|
||||||
finalPos.getString().c_str(),newFinalPos.getString().c_str(),ts,canUnitMove);
|
if(minorDebugPathfinder) printf("Legacy Pathfind Unit [%d - %s] from = %s to = %s frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),unit->getPos().getString().c_str(),finalPos.getString().c_str(),frameIndex);
|
||||||
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
|
||||||
|
ts = aStar(unit, finalPos, false, frameIndex, maxNodeCount);
|
||||||
|
|
||||||
|
//post actions
|
||||||
|
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) {
|
||||||
|
|
||||||
|
//printf("$$$$ Unit START BAILOUT ATTEMPT for [%d - %s]\n",unit->getId(),unit->getFullName().c_str());
|
||||||
|
if(minorDebugPathfinder) printf("Legacy Pathfind Unit [%d - %s] START BAILOUT ATTEMPT frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),frameIndex);
|
||||||
|
|
||||||
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
||||||
|
char szBuf[4096]="";
|
||||||
|
sprintf(szBuf,"[attempting to BAIL OUT] finalPos [%s] ts [%d]",
|
||||||
|
finalPos.getString().c_str(),ts);
|
||||||
|
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wasStuck != NULL) {
|
||||||
|
*wasStuck = true;
|
||||||
|
}
|
||||||
|
unit->setInBailOutAttempt(true);
|
||||||
|
|
||||||
|
bool useBailoutRadius = Config::getInstance().getBool("EnableBailoutPathfinding","true");
|
||||||
|
if(useBailoutRadius == true) {
|
||||||
|
|
||||||
|
//!!!
|
||||||
|
bool unitImmediatelyBlocked = false;
|
||||||
|
|
||||||
|
// First check if unit currently blocked all around them, if so don't try to pathfind
|
||||||
|
const bool showConsoleDebugInfo = Config::getInstance().getBool("EnablePathfinderDistanceOutput","false");
|
||||||
|
const Vec2i unitPos = unit->getPos();
|
||||||
|
int failureCount = 0;
|
||||||
|
int cellCount = 0;
|
||||||
|
|
||||||
|
for(int i = -1; i <= 1; ++i) {
|
||||||
|
for(int j = -1; j <= 1; ++j) {
|
||||||
|
Vec2i pos = unitPos + Vec2i(i, j);
|
||||||
|
if(pos != unitPos) {
|
||||||
|
bool canUnitMoveToCell = map->aproxCanMove(unit, unitPos, pos);
|
||||||
|
if(canUnitMoveToCell == false) {
|
||||||
|
failureCount++;
|
||||||
|
}
|
||||||
|
cellCount++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unitImmediatelyBlocked = (failureCount == cellCount);
|
||||||
|
|
||||||
if(canUnitMove) {
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld unitImmediatelyBlocked = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),unitImmediatelyBlocked,failureCount);
|
||||||
//printf("$$$$ Unit BAILOUT(1) ASTAR ATTEMPT for [%d - %s] newFinalPos = [%s]\n",unit->getId(),unit->getFullName().c_str(),newFinalPos.getString().c_str());
|
if(showConsoleDebugInfo && unitImmediatelyBlocked) {
|
||||||
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
printf("**Check if src blocked [%d], unit [%d - %s] from [%s] to [%s] unitImmediatelyBlocked = %d, failureCount = %d [%d]\n",
|
||||||
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount);
|
unitImmediatelyBlocked, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), unitImmediatelyBlocked,failureCount,cellCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(unitImmediatelyBlocked == false) {
|
||||||
|
// // First check if final destination blocked
|
||||||
|
// failureCount = 0;
|
||||||
|
// cellCount = 0;
|
||||||
|
//
|
||||||
|
// for(int i = -1; i <= 1; ++i) {
|
||||||
|
// for(int j = -1; j <= 1; ++j) {
|
||||||
|
// Vec2i pos = finalPos + Vec2i(i, j);
|
||||||
|
// if(pos != finalPos) {
|
||||||
|
// bool canUnitMoveToCell = map->aproxCanMove(unit, pos, finalPos);
|
||||||
|
// if(canUnitMoveToCell == false) {
|
||||||
|
// failureCount++;
|
||||||
|
// }
|
||||||
|
// cellCount++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// unitImmediatelyBlocked = (failureCount == cellCount);
|
||||||
|
//
|
||||||
|
// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld unitImmediatelyBlocked = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),unitImmediatelyBlocked,failureCount);
|
||||||
|
// if(showConsoleDebugInfo && nodeLimitReached) {
|
||||||
|
// printf("**Check if dest blocked [%d - %d], unit [%d - %s] from [%s] to [%s] distance %.2f took msecs: %lld unitImmediatelyBlocked = %d, failureCount = %d [%d]\n",
|
||||||
|
// nodeLimitReached, inBailout, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),unitImmediatelyBlocked,failureCount,cellCount);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//!!!
|
||||||
|
|
||||||
|
if(unitImmediatelyBlocked == false) {
|
||||||
|
int tryRadius = factions[unit->getFactionIndex()].random.randRange(0,1);
|
||||||
|
|
||||||
|
// Try to bail out up to PathFinder::pathFindBailoutRadius cells away
|
||||||
|
if(tryRadius > 0) {
|
||||||
|
for(int bailoutX = -PathFinder::pathFindBailoutRadius; bailoutX <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutX) {
|
||||||
|
for(int bailoutY = -PathFinder::pathFindBailoutRadius; bailoutY <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutY) {
|
||||||
|
const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY);
|
||||||
|
bool canUnitMove = map->canMove(unit, unit->getPos(), newFinalPos);
|
||||||
|
|
||||||
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
||||||
|
char szBuf[4096]="";
|
||||||
|
sprintf(szBuf,"[attempting to BAIL OUT] finalPos [%s] newFinalPos [%s] ts [%d] canUnitMove [%d]",
|
||||||
|
finalPos.getString().c_str(),newFinalPos.getString().c_str(),ts,canUnitMove);
|
||||||
|
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(canUnitMove) {
|
||||||
|
//printf("$$$$ Unit BAILOUT(1) ASTAR ATTEMPT for [%d - %s] newFinalPos = [%s]\n",unit->getId(),unit->getFullName().c_str(),newFinalPos.getString().c_str());
|
||||||
|
|
||||||
|
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
||||||
|
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(int bailoutX = PathFinder::pathFindBailoutRadius; bailoutX >= -PathFinder::pathFindBailoutRadius && ts == tsBlocked; --bailoutX) {
|
||||||
|
for(int bailoutY = PathFinder::pathFindBailoutRadius; bailoutY >= -PathFinder::pathFindBailoutRadius && ts == tsBlocked; --bailoutY) {
|
||||||
|
const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY);
|
||||||
|
bool canUnitMove = map->canMove(unit, unit->getPos(), newFinalPos);
|
||||||
|
|
||||||
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
||||||
|
char szBuf[4096]="";
|
||||||
|
sprintf(szBuf,"[attempting to BAIL OUT] finalPos [%s] newFinalPos [%s] ts [%d] canUnitMove [%d]",
|
||||||
|
finalPos.getString().c_str(),newFinalPos.getString().c_str(),ts,canUnitMove);
|
||||||
|
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(canUnitMove) {
|
||||||
|
//printf("$$$$ Unit BAILOUT(1) ASTAR ATTEMPT for [%d - %s] newFinalPos = [%s]\n",unit->getId(),unit->getFullName().c_str(),newFinalPos.getString().c_str());
|
||||||
|
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
||||||
|
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
unit->setInBailOutAttempt(false);
|
||||||
}
|
|
||||||
unit->setInBailOutAttempt(false);
|
|
||||||
|
|
||||||
//printf("$$$$ Unit END BAILOUT ATTEMPT for [%d - %s] ts = %d\n",unit->getId(),unit->getFullName().c_str(),ts);
|
//printf("$$$$ Unit END BAILOUT ATTEMPT for [%d - %s] ts = %d\n",unit->getId(),unit->getFullName().c_str(),ts);
|
||||||
|
|
||||||
if(ts == tsBlocked) {
|
if(ts == tsBlocked) {
|
||||||
unit->setLastStuckFrameToCurrentFrame();
|
unit->setLastStuckFrameToCurrentFrame();
|
||||||
unit->setLastStuckPos(finalPos);
|
unit->setLastStuckPos(finalPos);
|
||||||
}
|
|
||||||
}
|
|
||||||
if(ts == tsArrived || ts == tsBlocked) {
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
unit->setCurrSkill(scStop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case tsMoving:
|
|
||||||
{
|
|
||||||
if(dynamic_cast<UnitPathBasic *>(path) != NULL) {
|
|
||||||
UnitPathBasic *basicPath = dynamic_cast<UnitPathBasic *>(path);
|
|
||||||
Vec2i pos;
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
pos = basicPath->pop(frameIndex < 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pos = factions[unit->getFactionIndex()].precachedPath[unit->getId()][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(map->canMove(unit, unit->getPos(), pos)) {
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
unit->setTargetPos(pos);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
if(ts == tsArrived || ts == tsBlocked) {
|
||||||
if(frameIndex < 0) {
|
if(frameIndex < 0) {
|
||||||
unit->setCurrSkill(scStop);
|
unit->setCurrSkill(scStop);
|
||||||
}
|
}
|
||||||
return tsBlocked;
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if(dynamic_cast<UnitPath *>(path) != NULL) {
|
case tsMoving:
|
||||||
UnitPath *advPath = dynamic_cast<UnitPath *>(path);
|
{
|
||||||
Vec2i pos= advPath->peek();
|
if(dynamic_cast<UnitPathBasic *>(path) != NULL) {
|
||||||
if(map->canMove(unit, unit->getPos(), pos)) {
|
UnitPathBasic *basicPath = dynamic_cast<UnitPathBasic *>(path);
|
||||||
if(frameIndex < 0) {
|
Vec2i pos;
|
||||||
advPath->pop();
|
if(frameIndex < 0) {
|
||||||
unit->setTargetPos(pos);
|
pos = basicPath->pop(frameIndex < 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(factions[unit->getFactionIndex()].precachedPath[unit->getId()].size() <= 0) {
|
||||||
|
throw megaglest_runtime_error("factions[unit->getFactionIndex()].precachedPath[unit->getId()].size() <= 0!");
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = factions[unit->getFactionIndex()].precachedPath[unit->getId()][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(map->canMove(unit, unit->getPos(), pos)) {
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
unit->setTargetPos(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
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)) {
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
advPath->pop();
|
||||||
|
unit->setTargetPos(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
unit->setCurrSkill(scStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minorDebugPathfinder) printf("Legacy Pathfind Unit [%d - %s] INT BAILOUT ATTEMPT BLOCKED frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),frameIndex);
|
||||||
|
return tsBlocked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw megaglest_runtime_error("unsupported or missing path finder detected!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
break;
|
||||||
if(frameIndex < 0) {
|
|
||||||
unit->setCurrSkill(scStop);
|
|
||||||
}
|
|
||||||
return tsBlocked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw megaglest_runtime_error("unsupported or missing path finder detected!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
return ts;
|
||||||
}
|
}
|
||||||
return ts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== PRIVATE ====================
|
// ==================== PRIVATE ====================
|
||||||
|
|
||||||
|
TravelState PathFinder::aStarFast(Unit *unit, Vec2i finalPos, bool inBailout, int frameIndex, int maxNodeCount) {
|
||||||
|
TravelState ts = tsImpossible;
|
||||||
|
|
||||||
|
Chrono chrono;
|
||||||
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
|
||||||
|
|
||||||
|
if(maxNodeCount < 0) {
|
||||||
|
maxNodeCount = factions[unit->getFactionIndex()].useMaxNodeCount;
|
||||||
|
|
||||||
|
//printf("AStar set maxNodeCount = %d\n",maxNodeCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(maxNodeCount >= 1 && unit->getPathfindFailedConsecutiveFrameCount() >= 3) {
|
||||||
|
int orgmaxNodeCount = maxNodeCount;
|
||||||
|
maxNodeCount = 200;
|
||||||
|
//printf("AStar maxpath cut for unit [%d - %s] to %d [orig: %d] [unit->getPathfindFailedConsecutiveFrameCount(): %d]\n",unit->getId(),unit->getFullName().c_str(), maxNodeCount,orgmaxNodeCount,unit->getPathfindFailedConsecutiveFrameCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
UnitPathInterface *path= unit->getPath();
|
||||||
|
int unitFactionIndex = unit->getFactionIndex();
|
||||||
|
factions[unitFactionIndex].nodePoolCount= 0;
|
||||||
|
factions[unitFactionIndex].openNodesList.clear();
|
||||||
|
factions[unitFactionIndex].openPosList.clear();
|
||||||
|
factions[unitFactionIndex].closedNodesList.clear();
|
||||||
|
|
||||||
|
if(frameIndex >= 0) {
|
||||||
|
clearUnitPrecache(unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
finalPos= computeNearestFreePos(unit, finalPos);
|
||||||
|
|
||||||
|
// Start of New Fast AStar
|
||||||
|
FastAINode *fromNode = map->getCellNode(unit->getPos());
|
||||||
|
FastAINode *toNode = map->getCellNode(finalPos);
|
||||||
|
//FastAstar *fa = createFastAstar();
|
||||||
|
FastAstar *fa = factions[unitFactionIndex].fa;
|
||||||
|
astarStartSearch(fa,fromNode,toNode, unit);
|
||||||
|
|
||||||
|
bool pathFound = false;
|
||||||
|
unsigned int nodeSearchCount=0;
|
||||||
|
for(nodeSearchCount=0; pathFound == false && nodeSearchCount < maxNodeCount; ++nodeSearchCount) {
|
||||||
|
unsigned int search_count=0;
|
||||||
|
pathFound = astarSearchStep(fa,search_count);
|
||||||
|
//printf("Fast Pathfind Unit [%d - %s] finished = %d search_count = %d i = %d\n",unit->getId(),unit->getType()->getName().c_str(),finished,search_count,i);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int count=0;
|
||||||
|
AI_Node **solution = getSolution(fa,count);
|
||||||
|
|
||||||
|
if(count <= 1 || getLastSearchState(fa) != SEARCH_STATE_SUCCEEDED) {
|
||||||
|
if(minorDebugPathfinder) printf("Fast Pathfind Unit [%d - %s] NOT FOUND PATH frameIndex = %d nodeSearchCount = %d\n",unit->getId(),unit->getType()->getName().c_str(),frameIndex,nodeSearchCount);
|
||||||
|
|
||||||
|
//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();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Vec2i,int> lastHarvest = unit->getLastHarvestResourceTarget();
|
||||||
|
|
||||||
|
char szBuf[4096]="";
|
||||||
|
sprintf(szBuf,"State: blocked, cmd [%s] pos: [%s], lastHarvest = [%s - %d], reason C= %d, D= %d, F = %d",
|
||||||
|
commandDesc.c_str(),unit->getPos().getString().c_str(), lastHarvest.first.getString().c_str(),lastHarvest.second, path->getBlockCount(), path->isBlocked(), path->isStuck());
|
||||||
|
unit->setCurrentUnitTitle(szBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
unit->setUsePathfinderExtendedMaxNodes(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ts= tsBlocked;
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
path->incBlockCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
||||||
|
char szBuf[4096]="";
|
||||||
|
sprintf(szBuf,"[path for unit BLOCKED] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] ts [%d]",
|
||||||
|
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),ts);
|
||||||
|
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||||
|
|
||||||
|
unit->setLastStuckFrameToCurrentFrame();
|
||||||
|
unit->setLastStuckPos(finalPos);
|
||||||
|
|
||||||
|
// Now see if the unit is eligble for pathfind max nodes boost?
|
||||||
|
if(nodeSearchCount >= maxNodeCount) {
|
||||||
|
unit->incrementPathfindFailedConsecutiveFrameCount();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unit->resetPathfindFailedConsecutiveFrameCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(minorDebugPathfinder) printf("Fast Pathfind Unit [%d - %s] FOUND PATH count = %d frameIndex = %d nodeSearchCount = %d\n",unit->getId(),unit->getType()->getName().c_str(),count,frameIndex,nodeSearchCount);
|
||||||
|
|
||||||
|
ts= tsMoving;
|
||||||
|
|
||||||
|
UnitPathInterface *path= unit->getPath();
|
||||||
|
|
||||||
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
if(maxNodeCount == pathFindNodesAbsoluteMax) {
|
||||||
|
unit->setUsePathfinderExtendedMaxNodes(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unit->setUsePathfinderExtendedMaxNodes(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//store path
|
||||||
|
if(frameIndex < 0) {
|
||||||
|
path->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
UnitPathBasic *basicPathFinder = dynamic_cast<UnitPathBasic *>(path);
|
||||||
|
|
||||||
|
for(int i=0; i < count; ++i) {
|
||||||
|
FastAINode *node = dynamic_cast<FastAINode *>(solution[i]);
|
||||||
|
const Vec2i &nodePos = node->getPos();
|
||||||
|
if(nodePos != unit->getPos()) {
|
||||||
|
if(map->isInside(nodePos) == false || map->isInsideSurface(map->toSurfCoords(nodePos)) == false) {
|
||||||
|
throw megaglest_runtime_error("Pathfinder invalid node path position = " + nodePos.getString() + " i = " + intToStr(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(minorDebugPathfinder) printf("nodePos [%s]\n",nodePos.getString().c_str());
|
||||||
|
|
||||||
|
if(frameIndex >= 0) {
|
||||||
|
factions[unitFactionIndex].precachedPath[unit->getId()].push_back(nodePos);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(i < pathFindRefresh) {
|
||||||
|
//if(i < pathFindRefresh ||
|
||||||
|
// (whileLoopCount >= pathFindExtendRefreshForNodeCount &&
|
||||||
|
// i < getPathFindExtendRefreshNodeCount(unitFactionIndex))) {
|
||||||
|
path->add(nodePos);
|
||||||
|
}
|
||||||
|
//else if(tryLastPathCache == false) {
|
||||||
|
// break;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if(tryLastPathCache == true && basicPathFinder) {
|
||||||
|
if(basicPathFinder) {
|
||||||
|
basicPathFinder->addToLastPathCache(nodePos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||||
|
|
||||||
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
||||||
|
char szBuf[4096]="";
|
||||||
|
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] ts [%d]",
|
||||||
|
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),ts);
|
||||||
|
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
||||||
|
|
||||||
|
string pathToTake = "";
|
||||||
|
for(int i = 0; i < path->getQueueCount(); ++i) {
|
||||||
|
Vec2i &pos = path->getQueue()[i];
|
||||||
|
if(pathToTake != "") {
|
||||||
|
pathToTake += ", ";
|
||||||
|
}
|
||||||
|
pathToTake += pos.getString();
|
||||||
|
}
|
||||||
|
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
||||||
|
sprintf(szBuf,"Path for unit to take = %s",pathToTake.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
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, Queue= %d",commandDesc.c_str(),unit->getPos().getString().c_str(), path->getQueueCount());
|
||||||
|
unit->setCurrentUnitTitle(szBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||||
|
}
|
||||||
|
//releaseFastAstar(fa);
|
||||||
|
|
||||||
|
// End of New Fast AStar
|
||||||
|
|
||||||
|
factions[unitFactionIndex].openNodesList.clear();
|
||||||
|
factions[unitFactionIndex].openPosList.clear();
|
||||||
|
factions[unitFactionIndex].closedNodesList.clear();
|
||||||
|
|
||||||
|
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||||
|
|
||||||
|
if(frameIndex >= 0) {
|
||||||
|
factions[unitFactionIndex].precachedTravelState[unit->getId()] = ts;
|
||||||
|
}
|
||||||
|
//else {
|
||||||
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() >= 1) printf("In [%s::%s Line: %d] fastastar took [%lld] msecs, ts = %d nodeSearchCount = %d.\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),ts,nodeSearchCount);
|
||||||
|
//if(chrono.getMillis() >= 1) printf("In [%s::%s Line: %d] fastastar took [%lld] msecs, ts = %d nodeSearchCount = %d.\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),ts,nodeSearchCount);
|
||||||
|
//}
|
||||||
|
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
bool PathFinder::addToOpenSet(Unit *unit, Node *node,const Vec2i finalPos, Vec2i sucPos, bool &nodeLimitReached,int maxNodeCount,Node **newNodeAdded, bool bypassChecks) {
|
bool PathFinder::addToOpenSet(Unit *unit, Node *node,const Vec2i finalPos, Vec2i sucPos, bool &nodeLimitReached,int maxNodeCount,Node **newNodeAdded, bool bypassChecks) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
|
@ -1152,6 +1594,8 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
|
||||||
//check results of path finding
|
//check results of path finding
|
||||||
ts = tsImpossible;
|
ts = tsImpossible;
|
||||||
if(pathFound == false || lastNode == firstNode) {
|
if(pathFound == false || lastNode == firstNode) {
|
||||||
|
if(minorDebugPathfinder) printf("Legacy Pathfind Unit [%d - %s] NOT FOUND PATH count = %d frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),whileLoopCount,frameIndex);
|
||||||
|
|
||||||
//blocked
|
//blocked
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
||||||
string commandDesc = "none";
|
string commandDesc = "none";
|
||||||
|
@ -1186,6 +1630,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if(minorDebugPathfinder) printf("Legacy Pathfind Unit [%d - %s] FOUND PATH count = %d frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),whileLoopCount,frameIndex);
|
||||||
//on the way
|
//on the way
|
||||||
ts= tsMoving;
|
ts= tsMoving;
|
||||||
|
|
||||||
|
@ -1226,6 +1671,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("nodePos [%s]\n",nodePos.getString().c_str());
|
//printf("nodePos [%s]\n",nodePos.getString().c_str());
|
||||||
|
if(minorDebugPathfinder) printf("nodePos [%s]\n",nodePos.getString().c_str());
|
||||||
|
|
||||||
if(frameIndex >= 0) {
|
if(frameIndex >= 0) {
|
||||||
factions[unitFactionIndex].precachedPath[unit->getId()].push_back(nodePos);
|
factions[unitFactionIndex].precachedPath[unit->getId()].push_back(nodePos);
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "skill_type.h"
|
#include "skill_type.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
|
#include "fast_path_finder.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
@ -111,6 +111,11 @@ public:
|
||||||
//mapFromToNodeList.clear();
|
//mapFromToNodeList.clear();
|
||||||
//lastFromToNodeListFrame = -100;
|
//lastFromToNodeListFrame = -100;
|
||||||
badCellList.clear();
|
badCellList.clear();
|
||||||
|
|
||||||
|
fa = createFastAstar();
|
||||||
|
}
|
||||||
|
~FactionState() {
|
||||||
|
//fa = NULL;
|
||||||
}
|
}
|
||||||
std::map<Vec2i, bool> openPosList;
|
std::map<Vec2i, bool> openPosList;
|
||||||
std::map<float, Nodes> openNodesList;
|
std::map<float, Nodes> openNodesList;
|
||||||
|
@ -127,6 +132,8 @@ public:
|
||||||
//std::map<int, std::map<Vec2i,std::map<Vec2i, bool> > > mapFromToNodeList;
|
//std::map<int, std::map<Vec2i,std::map<Vec2i, bool> > > mapFromToNodeList;
|
||||||
|
|
||||||
std::map<int,std::map<Field,BadUnitNodeList> > badCellList;
|
std::map<int,std::map<Field,BadUnitNodeList> > badCellList;
|
||||||
|
|
||||||
|
FastAstar *fa;
|
||||||
};
|
};
|
||||||
typedef vector<FactionState> FactionStateList;
|
typedef vector<FactionState> FactionStateList;
|
||||||
|
|
||||||
|
@ -145,6 +152,7 @@ private:
|
||||||
|
|
||||||
FactionStateList factions;
|
FactionStateList factions;
|
||||||
const Map *map;
|
const Map *map;
|
||||||
|
bool minorDebugPathfinder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PathFinder();
|
PathFinder();
|
||||||
|
@ -162,6 +170,7 @@ public:
|
||||||
void loadGame(const XmlNode *rootNode);
|
void loadGame(const XmlNode *rootNode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
TravelState aStarFast(Unit *unit, Vec2i finalPos, bool inBailout, int frameIndex, int maxNodeCount=-1);
|
||||||
TravelState aStar(Unit *unit, const Vec2i &finalPos, bool inBailout, int frameIndex, int maxNodeCount=-1);
|
TravelState aStar(Unit *unit, const Vec2i &finalPos, bool inBailout, int frameIndex, int maxNodeCount=-1);
|
||||||
//Node *newNode(FactionState &faction,int maxNodeCount);
|
//Node *newNode(FactionState &faction,int maxNodeCount);
|
||||||
inline static Node *newNode(FactionState &faction, int maxNodeCount) {
|
inline static Node *newNode(FactionState &faction, int maxNodeCount) {
|
||||||
|
|
|
@ -3776,6 +3776,8 @@ void Unit::saveGame(XmlNode *rootNode) {
|
||||||
|
|
||||||
//pathfindFailedConsecutiveFrameCount
|
//pathfindFailedConsecutiveFrameCount
|
||||||
unitNode->addAttribute("pathfindFailedConsecutiveFrameCount",intToStr(pathfindFailedConsecutiveFrameCount), mapTagReplacements);
|
unitNode->addAttribute("pathfindFailedConsecutiveFrameCount",intToStr(pathfindFailedConsecutiveFrameCount), mapTagReplacements);
|
||||||
|
|
||||||
|
unitNode->addAttribute("currentPathFinderDesiredFinalPos",currentPathFinderDesiredFinalPos.getString(), mapTagReplacements);
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit * Unit::loadGame(const XmlNode *rootNode, GameSettings *settings, Faction *faction, World *world) {
|
Unit * Unit::loadGame(const XmlNode *rootNode, GameSettings *settings, Faction *faction, World *world) {
|
||||||
|
@ -4189,6 +4191,10 @@ Unit * Unit::loadGame(const XmlNode *rootNode, GameSettings *settings, Faction *
|
||||||
}
|
}
|
||||||
|
|
||||||
result->meetingPos = Vec2i::strToVec2(unitNode->getAttribute("meetingPos")->getValue());
|
result->meetingPos = Vec2i::strToVec2(unitNode->getAttribute("meetingPos")->getValue());
|
||||||
|
|
||||||
|
if(unitNode->hasAttribute("currentPathFinderDesiredFinalPos")) {
|
||||||
|
result->currentPathFinderDesiredFinalPos = Vec2i::strToVec2(unitNode->getAttribute("currentPathFinderDesiredFinalPos")->getValue());
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -437,6 +437,7 @@ private:
|
||||||
CauseOfDeathType causeOfDeath;
|
CauseOfDeathType causeOfDeath;
|
||||||
|
|
||||||
uint32 pathfindFailedConsecutiveFrameCount;
|
uint32 pathfindFailedConsecutiveFrameCount;
|
||||||
|
Vec2i currentPathFinderDesiredFinalPos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Unit(int id, UnitPathInterface *path, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing);
|
Unit(int id, UnitPathInterface *path, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing);
|
||||||
|
@ -446,6 +447,9 @@ public:
|
||||||
|
|
||||||
static void setGame(Game *value) { game=value;}
|
static void setGame(Game *value) { game=value;}
|
||||||
|
|
||||||
|
void setCurrentPathFinderDesiredFinalPos(const Vec2i &finalPos) { currentPathFinderDesiredFinalPos = finalPos; }
|
||||||
|
Vec2i getCurrentPathFinderDesiredFinalPos() const { return currentPathFinderDesiredFinalPos; }
|
||||||
|
|
||||||
//const std::pair<const SkillType *,std::vector<Unit *> > & getCurrentAttackBoostUnits() const { return currentAttackBoostUnits; }
|
//const std::pair<const SkillType *,std::vector<Unit *> > & getCurrentAttackBoostUnits() const { return currentAttackBoostUnits; }
|
||||||
const UnitAttackBoostEffectOriginator & getAttackBoostOriginatorEffect() const { return currentAttackBoostOriginatorEffect; }
|
const UnitAttackBoostEffectOriginator & getAttackBoostOriginatorEffect() const { return currentAttackBoostOriginatorEffect; }
|
||||||
bool unitHasAttackBoost(const AttackBoost *boost, const Unit *source) const;
|
bool unitHasAttackBoost(const AttackBoost *boost, const Unit *source) const;
|
||||||
|
|
|
@ -279,6 +279,88 @@ void SurfaceCell::loadGame(const XmlNode *rootNode, int index, World *world) {
|
||||||
// class Map
|
// class Map
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
|
FastAINode * FastAINode::getNodeForEdgeIndex(int index,void *userData) const {
|
||||||
|
FastAINode *resultNode = NULL;
|
||||||
|
switch(index) {
|
||||||
|
case 0: // north
|
||||||
|
resultNode = map->getCellNode(pos.x,pos.y-1,false);
|
||||||
|
break;
|
||||||
|
case 1: // north east
|
||||||
|
resultNode = map->getCellNode(pos.x+1,pos.y-1,false);
|
||||||
|
break;
|
||||||
|
case 2: // east
|
||||||
|
resultNode = map->getCellNode(pos.x+1,pos.y,false);
|
||||||
|
break;
|
||||||
|
case 3: // south east
|
||||||
|
resultNode = map->getCellNode(pos.x+1,pos.y+1,false);
|
||||||
|
break;
|
||||||
|
case 4: // south
|
||||||
|
resultNode = map->getCellNode(pos.x,pos.y+1,false);
|
||||||
|
break;
|
||||||
|
case 5: // south west
|
||||||
|
resultNode = map->getCellNode(pos.x-1,pos.y+1,false);
|
||||||
|
break;
|
||||||
|
case 6: // west
|
||||||
|
resultNode = map->getCellNode(pos.x-1,pos.y,false);
|
||||||
|
break;
|
||||||
|
case 7: // north west
|
||||||
|
resultNode = map->getCellNode(pos.x-1,pos.y-1,false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(resultNode != NULL) {
|
||||||
|
Unit *unit = (Unit *)userData;
|
||||||
|
if(resultNode->getPos() != unit->getCurrentPathFinderDesiredFinalPos()) {
|
||||||
|
if(map->aproxCanMoveSoon(unit, pos, resultNode->getPos()) == false) {
|
||||||
|
resultNode = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FastAINode::getDistance(const AI_Node *node,void *userData) {
|
||||||
|
return pos.dist(dynamic_cast<const FastAINode *>(node)->pos);
|
||||||
|
}
|
||||||
|
float FastAINode::getCost(void *userData) {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FastAINode::getEdgeCount(void *userData) const {
|
||||||
|
unsigned int result = 0;
|
||||||
|
for(unsigned int index = 0; index < NODE_EDGE_COUNT; ++index) {
|
||||||
|
FastAINode *resultNode = getNodeForEdgeIndex(index,userData);
|
||||||
|
if(resultNode != NULL) {
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
AI_Node * FastAINode::getEdge(int index,void *userData) const {
|
||||||
|
FastAINode *result = NULL;
|
||||||
|
|
||||||
|
unsigned int edgeCount = getEdgeCount(userData);
|
||||||
|
if(edgeCount < NODE_EDGE_COUNT) {
|
||||||
|
int edgeIndex = -1;
|
||||||
|
|
||||||
|
for(unsigned int index2 = 0; index2 < NODE_EDGE_COUNT; ++index2) {
|
||||||
|
result = getNodeForEdgeIndex(index2,userData);
|
||||||
|
if(result != NULL) {
|
||||||
|
edgeIndex++;
|
||||||
|
|
||||||
|
if(edgeIndex == index) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = getNodeForEdgeIndex(index,userData);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
// ===================== PUBLIC ========================
|
// ===================== PUBLIC ========================
|
||||||
|
|
||||||
const int Map::cellScale= 2;
|
const int Map::cellScale= 2;
|
||||||
|
@ -287,6 +369,7 @@ const int Map::mapScale= 2;
|
||||||
Map::Map() {
|
Map::Map() {
|
||||||
cells= NULL;
|
cells= NULL;
|
||||||
surfaceCells= NULL;
|
surfaceCells= NULL;
|
||||||
|
cellNodes=NULL;
|
||||||
startLocations= NULL;
|
startLocations= NULL;
|
||||||
|
|
||||||
title="";
|
title="";
|
||||||
|
@ -309,6 +392,8 @@ Map::~Map() {
|
||||||
cells = NULL;
|
cells = NULL;
|
||||||
delete [] surfaceCells;
|
delete [] surfaceCells;
|
||||||
surfaceCells = NULL;
|
surfaceCells = NULL;
|
||||||
|
delete [] cellNodes;
|
||||||
|
cellNodes = NULL;
|
||||||
delete [] startLocations;
|
delete [] startLocations;
|
||||||
startLocations = NULL;
|
startLocations = NULL;
|
||||||
}
|
}
|
||||||
|
@ -406,6 +491,14 @@ Checksum Map::load(const string &path, TechTree *techTree, Tileset *tileset) {
|
||||||
|
|
||||||
//cells
|
//cells
|
||||||
cells= new Cell[getCellArraySize()];
|
cells= new Cell[getCellArraySize()];
|
||||||
|
cellNodes = new FastAINode[getCellArraySize()];
|
||||||
|
for(unsigned int x = 0; x < w; ++x) {
|
||||||
|
for(unsigned int y = 0; y < h; ++y) {
|
||||||
|
int arrayIndex = y * w + x;
|
||||||
|
FastAINode &cellNode = cellNodes[arrayIndex];
|
||||||
|
cellNode.setData(Vec2i(x,y),this);
|
||||||
|
}
|
||||||
|
}
|
||||||
surfaceCells= new SurfaceCell[getSurfaceCellArraySize()];
|
surfaceCells= new SurfaceCell[getSurfaceCellArraySize()];
|
||||||
|
|
||||||
//read heightmap
|
//read heightmap
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "selection.h"
|
#include "selection.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "unit_type.h"
|
#include "unit_type.h"
|
||||||
|
#include "fast_path_finder.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,6 +193,35 @@ public:
|
||||||
/// Represents the game map (and loads it from a gbm file)
|
/// Represents the game map (and loads it from a gbm file)
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
|
class FastAINode : public AI_Node {
|
||||||
|
protected:
|
||||||
|
Vec2i pos;
|
||||||
|
const Map *map;
|
||||||
|
static const int NODE_EDGE_COUNT = 8;
|
||||||
|
|
||||||
|
FastAINode * getNodeForEdgeIndex(int index,void *userData) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FastAINode() {
|
||||||
|
this->map = NULL;
|
||||||
|
}
|
||||||
|
FastAINode(Vec2i &pos,const Map *map) {
|
||||||
|
this->pos = pos;
|
||||||
|
this->map = map;
|
||||||
|
}
|
||||||
|
void setData(Vec2i pos, const Map *map) {
|
||||||
|
this->pos = pos;
|
||||||
|
this->map = map;
|
||||||
|
}
|
||||||
|
inline const Vec2i & getPos() const { return pos; }
|
||||||
|
|
||||||
|
virtual float getDistance(const AI_Node *node, void *userData);
|
||||||
|
virtual float getCost(void *userData);
|
||||||
|
virtual unsigned int getEdgeCount(void *userData) const;
|
||||||
|
virtual AI_Node * getEdge(int index, void *userData) const;
|
||||||
|
};
|
||||||
|
|
||||||
class Map {
|
class Map {
|
||||||
public:
|
public:
|
||||||
static const int cellScale; //number of cells per surfaceCell
|
static const int cellScale; //number of cells per surfaceCell
|
||||||
|
@ -210,6 +240,7 @@ private:
|
||||||
int maxPlayers;
|
int maxPlayers;
|
||||||
Cell *cells;
|
Cell *cells;
|
||||||
SurfaceCell *surfaceCells;
|
SurfaceCell *surfaceCells;
|
||||||
|
FastAINode *cellNodes;
|
||||||
Vec2i *startLocations;
|
Vec2i *startLocations;
|
||||||
Checksum checksumValue;
|
Checksum checksumValue;
|
||||||
float maxMapHeight;
|
float maxMapHeight;
|
||||||
|
@ -229,13 +260,20 @@ public:
|
||||||
Checksum load(const string &path, TechTree *techTree, Tileset *tileset);
|
Checksum load(const string &path, TechTree *techTree, Tileset *tileset);
|
||||||
|
|
||||||
//get
|
//get
|
||||||
inline Cell *getCell(int x, int y) const {
|
inline Cell *getCell(int x, int y, bool errorOnInvalid=true) const {
|
||||||
int arrayIndex = y * w + x;
|
int arrayIndex = y * w + x;
|
||||||
if(arrayIndex < 0 || arrayIndex >= getCellArraySize()) {
|
if(arrayIndex < 0 || arrayIndex >= getCellArraySize()) {
|
||||||
|
if(errorOnInvalid == false) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
//abort();
|
//abort();
|
||||||
throw megaglest_runtime_error("arrayIndex >= getCellArraySize(), arrayIndex = " + intToStr(arrayIndex) + " w = " + intToStr(w) + " h = " + intToStr(h));
|
throw megaglest_runtime_error("arrayIndex >= getCellArraySize(), arrayIndex = " + intToStr(arrayIndex) + " w = " + intToStr(w) + " h = " + intToStr(h));
|
||||||
}
|
}
|
||||||
else if(cells == NULL) {
|
else if(cells == NULL) {
|
||||||
|
if(errorOnInvalid == false) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
throw megaglest_runtime_error("cells == NULL");
|
throw megaglest_runtime_error("cells == NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +283,30 @@ public:
|
||||||
return getCell(pos.x, pos.y);
|
return getCell(pos.x, pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//get
|
||||||
|
inline FastAINode *getCellNode(Vec2i pos, bool errorOnInvalid=true) const {
|
||||||
|
return getCellNode(pos.x, pos.y, errorOnInvalid);
|
||||||
|
}
|
||||||
|
inline FastAINode *getCellNode(int x, int y, bool errorOnInvalid=true) const {
|
||||||
|
int arrayIndex = y * w + x;
|
||||||
|
if(arrayIndex < 0 || arrayIndex >= getCellArraySize()) {
|
||||||
|
if(errorOnInvalid == false) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//abort();
|
||||||
|
throw megaglest_runtime_error("arrayIndex >= getCellArraySize(), arrayIndex = " + intToStr(arrayIndex) + " w = " + intToStr(w) + " h = " + intToStr(h));
|
||||||
|
}
|
||||||
|
else if(cellNodes == NULL) {
|
||||||
|
if(errorOnInvalid == false) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw megaglest_runtime_error("cellNodes == NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cellNodes[arrayIndex];
|
||||||
|
}
|
||||||
|
|
||||||
inline int getCellArraySize() const {
|
inline int getCellArraySize() const {
|
||||||
return (w * h);
|
return (w * h);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue