2007-08-08 22:28:56 +03:00
# include "stdafx.h"
2007-08-07 16:49:15 +03:00
# include "global.h"
# include "CPathfinder.h"
2007-08-17 20:42:21 +03:00
# include "CGameInfo.h"
2007-08-30 13:11:53 +03:00
# include "hch\CAmbarCendamo.h"
2007-08-29 15:18:31 +03:00
# include "mapHandler.h"
2007-11-19 00:58:28 +02:00
using namespace boost : : logic ;
2007-09-30 19:16:00 +03:00
int3 CPath : : startPos ( )
2007-09-22 04:16:31 +03:00
{
return int3 ( nodes [ nodes . size ( ) - 1 ] . coord . x , nodes [ nodes . size ( ) - 1 ] . coord . y , nodes [ nodes . size ( ) - 1 ] . coord . z ) ;
}
2007-10-03 22:56:08 +03:00
int3 CPath : : endPos ( )
{
return int3 ( nodes [ 0 ] . coord . x , nodes [ 0 ] . coord . y , nodes [ 0 ] . coord . z ) ;
}
2007-09-22 04:16:31 +03:00
2007-10-27 22:38:48 +03:00
CPath * CPathfinder : : getPath ( int3 src , int3 dest , const CGHeroInstance * hero , unsigned char type ) //TODO: test it (seems to be finished, but relies on unwritten functions :()
2007-08-07 16:49:15 +03:00
{
2007-10-05 21:16:22 +03:00
//check input
if ( ( src . x < 0 ) | | ( src . y < 0 ) | | ( src . z < 0 ) | | ( dest . x < 0 ) | | ( dest . y < 0 ) | | ( dest . z < 0 ) )
{
return NULL ;
}
if ( ( src . x > = CGI - > mh - > sizes . x ) | | ( src . y > = CGI - > mh - > sizes . y ) | | ( src . z > = CGI - > mh - > sizes . z )
| | ( dest . x > = CGI - > mh - > sizes . x ) | | ( dest . y > = CGI - > mh - > sizes . y ) | | ( dest . z > = CGI - > mh - > sizes . z ) )
{
2007-08-07 16:49:15 +03:00
return NULL ;
2007-10-05 21:16:22 +03:00
}
int3 hpos = hero - > getPosition ( false ) ;
tribool blockLandSea ; //true - blocks sea, false - blocks land, indeterminate - allows all
if ( ! hero - > canWalkOnSea ( ) )
{
if ( CGI - > mh - > ttiles [ hpos . x ] [ hpos . y ] [ hpos . z ] . terType = = EterrainType : : water )
blockLandSea = false ;
else
blockLandSea = true ;
}
else
2007-10-03 22:56:08 +03:00
{
2007-10-05 21:16:22 +03:00
blockLandSea = indeterminate ;
2007-10-03 22:56:08 +03:00
}
2007-08-07 16:49:15 +03:00
//graph initialization
graph . resize ( CGI - > ac - > map . width ) ;
for ( int i = 0 ; i < graph . size ( ) ; + + i )
{
graph [ i ] . resize ( CGI - > ac - > map . height ) ;
for ( int j = 0 ; j < graph [ i ] . size ( ) ; + + j )
{
2007-08-12 20:48:05 +03:00
graph [ i ] [ j ] = new CPathNode ;
graph [ i ] [ j ] - > accesible = ! CGI - > mh - > ttiles [ i ] [ j ] [ src . z ] . blocked ;
2007-09-18 20:01:47 +03:00
if ( i = = dest . x & & j = = dest . y & & CGI - > mh - > ttiles [ i ] [ j ] [ src . z ] . visitable )
graph [ i ] [ j ] - > accesible = true ; //for allowing visiting objects
2007-08-12 20:48:05 +03:00
graph [ i ] [ j ] - > dist = - 1 ;
graph [ i ] [ j ] - > theNodeBefore = NULL ;
graph [ i ] [ j ] - > visited = false ;
2007-09-22 04:16:31 +03:00
graph [ i ] [ j ] - > coord . x = i ;
graph [ i ] [ j ] - > coord . y = j ;
graph [ i ] [ j ] - > coord . z = dest . z ;
2007-10-05 23:38:14 +03:00
if ( CGI - > mh - > ttiles [ i ] [ j ] [ src . z ] . terType = = EterrainType : : rock )
graph [ i ] [ j ] - > accesible = false ;
2007-10-05 21:16:22 +03:00
if ( ( blockLandSea ) & & ( CGI - > mh - > ttiles [ i ] [ j ] [ src . z ] . terType = = EterrainType : : water ) )
graph [ i ] [ j ] - > accesible = false ;
else if ( ( ! blockLandSea ) & & ( CGI - > mh - > ttiles [ i ] [ j ] [ src . z ] . terType ! = EterrainType : : water ) )
graph [ i ] [ j ] - > accesible = false ;
2007-08-07 16:49:15 +03:00
}
}
2007-08-12 20:48:05 +03:00
//graph initialized
graph [ src . x ] [ src . y ] - > dist = 0 ;
std : : queue < CPathNode * > mq ;
mq . push ( graph [ src . x ] [ src . y ] ) ;
2007-08-17 20:42:21 +03:00
unsigned int curDist = 4000000000 ;
2007-08-12 20:48:05 +03:00
while ( ! mq . empty ( ) )
2007-08-07 16:49:15 +03:00
{
2007-08-12 20:48:05 +03:00
CPathNode * cp = mq . front ( ) ;
mq . pop ( ) ;
2007-09-22 04:16:31 +03:00
if ( ( cp - > coord . x = = dest . x ) & & ( cp - > coord . y = = dest . y ) )
2007-08-17 20:42:21 +03:00
{
if ( cp - > dist < curDist )
curDist = cp - > dist ;
}
else
{
if ( cp - > dist > curDist )
continue ;
}
2007-09-22 04:16:31 +03:00
if ( cp - > coord . x > 0 )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
CPathNode * dp = graph [ cp - > coord . x - 1 ] [ cp - > coord . y ] ;
if ( ( dp - > dist = = - 1 | | ( dp - > dist > cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x - 1 , cp - > coord . y , src . z ) , hero ) ) ) & & dp - > accesible )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
dp - > dist = cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x - 1 , cp - > coord . y , src . z ) , hero ) ;
2007-08-17 20:42:21 +03:00
dp - > theNodeBefore = cp ;
mq . push ( dp ) ;
2007-08-12 20:48:05 +03:00
}
}
2007-09-22 04:16:31 +03:00
if ( cp - > coord . y > 0 )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
CPathNode * dp = graph [ cp - > coord . x ] [ cp - > coord . y - 1 ] ;
if ( ( dp - > dist = = - 1 | | ( dp - > dist > cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x , cp - > coord . y - 1 , src . z ) , hero ) ) ) & & dp - > accesible )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
dp - > dist = cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x - 1 , cp - > coord . y , src . z ) , hero ) ;
2007-08-17 20:42:21 +03:00
dp - > theNodeBefore = cp ;
mq . push ( dp ) ;
2007-08-12 20:48:05 +03:00
}
}
2007-09-22 04:16:31 +03:00
if ( cp - > coord . x > 0 & & cp - > coord . y > 0 )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
CPathNode * dp = graph [ cp - > coord . x - 1 ] [ cp - > coord . y - 1 ] ;
if ( ( dp - > dist = = - 1 | | ( dp - > dist > cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x - 1 , cp - > coord . y - 1 , src . z ) , hero ) ) ) & & dp - > accesible )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
dp - > dist = cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x - 1 , cp - > coord . y - 1 , src . z ) , hero ) ;
2007-08-17 20:42:21 +03:00
dp - > theNodeBefore = cp ;
mq . push ( dp ) ;
2007-08-12 20:48:05 +03:00
}
}
2007-09-22 04:16:31 +03:00
if ( cp - > coord . x < graph . size ( ) - 1 )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
CPathNode * dp = graph [ cp - > coord . x + 1 ] [ cp - > coord . y ] ;
if ( ( dp - > dist = = - 1 | | ( dp - > dist > cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x + 1 , cp - > coord . y , src . z ) , hero ) ) ) & & dp - > accesible )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
dp - > dist = cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x + 1 , cp - > coord . y , src . z ) , hero ) ;
2007-08-17 20:42:21 +03:00
dp - > theNodeBefore = cp ;
mq . push ( dp ) ;
2007-08-12 20:48:05 +03:00
}
}
2007-09-22 04:16:31 +03:00
if ( cp - > coord . y < graph [ 0 ] . size ( ) - 1 )
2007-08-07 16:49:15 +03:00
{
2007-09-22 04:16:31 +03:00
CPathNode * dp = graph [ cp - > coord . x ] [ cp - > coord . y + 1 ] ;
if ( ( dp - > dist = = - 1 | | ( dp - > dist > cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x , cp - > coord . y + 1 , src . z ) , hero ) ) ) & & dp - > accesible )
2007-08-07 16:49:15 +03:00
{
2007-09-22 04:16:31 +03:00
dp - > dist = cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x , cp - > coord . y + 1 , src . z ) , hero ) ;
2007-08-17 20:42:21 +03:00
dp - > theNodeBefore = cp ;
mq . push ( dp ) ;
2007-08-07 16:49:15 +03:00
}
2007-08-12 20:48:05 +03:00
}
2007-09-22 04:16:31 +03:00
if ( cp - > coord . x < graph . size ( ) - 1 & & cp - > coord . y < graph [ 0 ] . size ( ) - 1 )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
CPathNode * dp = graph [ cp - > coord . x + 1 ] [ cp - > coord . y + 1 ] ;
if ( ( dp - > dist = = - 1 | | ( dp - > dist > cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x + 1 , cp - > coord . y + 1 , src . z ) , hero ) ) ) & & dp - > accesible )
2007-08-07 16:49:15 +03:00
{
2007-09-22 04:16:31 +03:00
dp - > dist = cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x + 1 , cp - > coord . y + 1 , src . z ) , hero ) ;
2007-08-17 20:42:21 +03:00
dp - > theNodeBefore = cp ;
mq . push ( dp ) ;
2007-08-12 20:48:05 +03:00
}
}
2007-09-22 04:16:31 +03:00
if ( cp - > coord . x > 0 & & cp - > coord . y < graph [ 0 ] . size ( ) - 1 )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
CPathNode * dp = graph [ cp - > coord . x - 1 ] [ cp - > coord . y + 1 ] ;
if ( ( dp - > dist = = - 1 | | ( dp - > dist > cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x - 1 , cp - > coord . y + 1 , src . z ) , hero ) ) ) & & dp - > accesible )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
dp - > dist = cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x - 1 , cp - > coord . y + 1 , src . z ) , hero ) ;
2007-08-17 20:42:21 +03:00
dp - > theNodeBefore = cp ;
mq . push ( dp ) ;
2007-08-12 20:48:05 +03:00
}
}
2007-09-22 04:16:31 +03:00
if ( cp - > coord . x < graph . size ( ) - 1 & & cp - > coord . y > 0 )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
CPathNode * dp = graph [ cp - > coord . x + 1 ] [ cp - > coord . y - 1 ] ;
if ( ( dp - > dist = = - 1 | | ( dp - > dist > cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x + 1 , cp - > coord . y - 1 , src . z ) , hero ) ) ) & & dp - > accesible )
2007-08-12 20:48:05 +03:00
{
2007-09-22 04:16:31 +03:00
dp - > dist = cp - > dist + CGI - > mh - > getCost ( int3 ( cp - > coord . x , cp - > coord . y , src . z ) , int3 ( cp - > coord . x + 1 , cp - > coord . y - 1 , src . z ) , hero ) ;
2007-08-17 20:42:21 +03:00
dp - > theNodeBefore = cp ;
mq . push ( dp ) ;
2007-08-07 16:49:15 +03:00
}
}
}
2007-08-12 20:48:05 +03:00
CPathNode * curNode = graph [ dest . x ] [ dest . y ] ;
CPath * ret = new CPath ;
while ( curNode ! = graph [ src . x ] [ src . y ] & & curNode ! = NULL )
{
2007-08-17 20:42:21 +03:00
ret - > nodes . push_back ( * curNode ) ;
2007-08-12 20:48:05 +03:00
curNode = curNode - > theNodeBefore ;
}
2007-08-17 20:42:21 +03:00
ret - > nodes . push_back ( * graph [ src . x ] [ src . y ] ) ;
2007-08-12 20:48:05 +03:00
for ( int i = 0 ; i < graph . size ( ) ; + + i )
{
2007-08-17 20:42:21 +03:00
for ( int j = 0 ; j < graph [ 0 ] . size ( ) ; + + j )
2007-08-12 20:48:05 +03:00
delete graph [ i ] [ j ] ;
}
return ret ;
2007-08-07 16:49:15 +03:00
}
2007-10-05 21:16:22 +03:00
void CPathfinder : : convertPath ( CPath * path , unsigned int mode ) //mode=0 -> from 'manifest' to 'object'
{
if ( mode = = 0 )
{
for ( int i = 0 ; i < path - > nodes . size ( ) ; i + + )
{
2007-10-27 23:14:25 +03:00
path - > nodes [ i ] . coord = CGHeroInstance : : convertPosition ( path - > nodes [ i ] . coord , true ) ;
2007-10-05 21:16:22 +03:00
}
}
}