2012-05-29 13:31:11 +00:00
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
# ifndef NL_WORLD_MAP_H
# define NL_WORLD_MAP_H
# include "nel/misc/types_nl.h"
# include "nel/misc/time_nl.h"
# include "nel/misc/debug.h"
# include "nel/misc/stream.h"
# include "nel/pacs/u_global_position.h"
# include "nel/misc/vectord.h"
# include "16x16_layer.h"
# include "ai_coord.h"
# include "ai_vector.h"
# include "ai_types.h"
class CFollowPath ;
namespace RYPACSCRUNCH
{
class CPacsCruncher ;
}
namespace RYAI_MAP_CRUNCH
{
enum TAStarFlag
{
Nothing = 0 ,
Interior = 1 ,
Water = 2 ,
NoGo = 4 ,
WaterAndNogo = 6 ,
GroundFlags = WaterAndNogo
} ;
const std : : string & toString ( TAStarFlag flag ) ;
TAStarFlag toAStarFlag ( const std : : string & str ) ;
uint const WorldMapGridSize = 256 ;
double const WorldGridResolution = 1. ;
NLMISC : : CVectorD const WorldStartOffset = NLMISC : : CVectorD ( 0. , 0. , 0. ) ;
typedef sint TLevel ;
//////////////////////////////////////////////////////////////////////////////
/**
* Slot for the 3 map layer ( corresponding to 3 heights of deplacement )
* \ author Stephane le Dorze
* \ author Nevrax France
* \ date 2003
*/
class CSlot
{
public :
enum
{
INVALID_SLOT = 3
} ;
public :
explicit CSlot ( ) ;
explicit CSlot ( uint slot ) ;
bool isValid ( ) const { return _Slot ! = INVALID_SLOT ; }
void setSlot ( CSlot const & slot ) { _Slot = slot . _Slot ; }
bool operator = = ( CSlot const & slot ) const { return _Slot = = slot . _Slot ; }
bool operator ! = ( CSlot const & slot ) const { return _Slot ! = slot . _Slot ; }
bool operator > ( CSlot const & slot ) const { return _Slot > slot . _Slot ; }
bool operator < ( CSlot const & slot ) const { return _Slot < slot . _Slot ; }
bool operator > = ( CSlot const & slot ) const { return _Slot > = slot . _Slot ; }
bool operator < = ( CSlot const & slot ) const { return _Slot < = slot . _Slot ; }
CSlot const & operator + + ( ) ;
uint8 slot ( ) const { return _Slot ; }
private :
uint8 _Slot ;
} ;
inline
CSlot : : CSlot ( )
: _Slot ( INVALID_SLOT )
{
}
inline
CSlot : : CSlot ( uint slot )
: _Slot ( slot )
{
# ifdef NL_DEBUG
nlassert ( slot > = 0 & & slot < = 3 ) ;
# endif
}
inline
CSlot const & CSlot : : operator + + ( )
{
+ + _Slot ;
# ifdef NL_DEBUG
nlassert ( _Slot < = INVALID_SLOT ) ;
# endif
return * this ;
}
//////////////////////////////////////////////////////////////////////////////
/**
* Compressed link set for the 4 cardinal directions
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CCellLinkage
// passer les param<61> tres de CCellLinkage en r<> f<EFBFBD> rences. (quand meme) et enlever les tests de validit<69> . (grosse mise <20> jour en perspective).
{
public :
enum
{
SouthSlotOffset = 0 ,
SouthSlotMask = 0x03 ,
EastSlotOffset = 2 ,
EastSlotMask = 0x0c ,
NorthSlotOffset = 4 ,
NorthSlotMask = 0x30 ,
WestSlotOffset = 6 ,
WestSlotMask = 0xc0 ,
} ;
public :
CCellLinkage ( uint8 links = 0xff ) ;
CSlot SSlot ( ) const { return CSlot ( ( _Links & SouthSlotMask ) > > SouthSlotOffset ) ; }
CSlot ESlot ( ) const { return CSlot ( ( _Links & EastSlotMask ) > > EastSlotOffset ) ; }
CSlot NSlot ( ) const { return CSlot ( ( _Links & NorthSlotMask ) > > NorthSlotOffset ) ; }
CSlot WSlot ( ) const { return CSlot ( ( _Links & WestSlotMask ) > > WestSlotOffset ) ; }
bool isSSlotValid ( ) const { return ( _Links & SouthSlotMask ) ! = SouthSlotMask ; }
bool isESlotValid ( ) const { return ( _Links & EastSlotMask ) ! = EastSlotMask ; }
bool isNSlotValid ( ) const { return ( _Links & NorthSlotMask ) ! = NorthSlotMask ; }
bool isWSlotValid ( ) const { return ( _Links & WestSlotMask ) ! = WestSlotMask ; }
void setSSlot ( CSlot const & slot ) ;
void setESlot ( CSlot const & slot ) ;
void setNSlot ( CSlot const & slot ) ;
void setWSlot ( CSlot const & slot ) ;
CCellLinkage & operator | = ( uint8 links ) ;
bool used ( ) const { return _Links ! = 0xff ; }
uint8 getLinks ( ) const { return _Links ; }
void serial ( NLMISC : : IStream & f ) ;
private :
uint8 _Links ;
} ;
inline
CCellLinkage : : CCellLinkage ( uint8 links )
: _Links ( links )
{
}
inline
void CCellLinkage : : setSSlot ( CSlot const & slot )
{
_Links = ( _Links & ( ~ SouthSlotMask ) ) + ( slot . slot ( ) < < SouthSlotOffset ) ;
}
inline
void CCellLinkage : : setESlot ( CSlot const & slot )
{
_Links = ( _Links & ( ~ EastSlotMask ) ) + ( slot . slot ( ) < < EastSlotOffset ) ;
}
inline
void CCellLinkage : : setNSlot ( CSlot const & slot )
{
_Links = ( _Links & ( ~ NorthSlotMask ) ) + ( slot . slot ( ) < < NorthSlotOffset ) ;
}
inline
void CCellLinkage : : setWSlot ( CSlot const & slot )
{
_Links = ( _Links & ( ~ WestSlotMask ) ) + ( slot . slot ( ) < < WestSlotOffset ) ;
}
inline
CCellLinkage & CCellLinkage : : operator | = ( uint8 links )
{
_Links | = links ;
return * this ;
}
inline
void CCellLinkage : : serial ( NLMISC : : IStream & f )
{
f . serial ( _Links ) ;
}
//////////////////////////////////////////////////////////////////////////////
class CDirection
{
friend class CWorldMap ;
public :
enum TDeltaDirection
{
HALF_TURN_LEFT = 1 , // 45 degres
HALF_TURN_RIGHT = - 1 , // -45 degres
TURN_LEFT = 2 , // 90 degres
TURN_RIGHT = - 2 , // -90 degres
HALF_TURN = 4 // 180 degres
} ;
enum TDirection
{
E = 0 ,
NE = 1 ,
N = 2 ,
NW = 3 ,
W = 4 ,
SW = 5 ,
S = 6 ,
SE = 7 ,
UNDEFINED = 8
} ;
enum TMotifDirection
{
SHIFT_E = 1 ,
SHIFT_NE = 2 ,
SHIFT_N = 4 ,
SHIFT_NW = 8 ,
SHIFT_W = 16 ,
SHIFT_SW = 32 ,
SHIFT_S = 64 ,
SHIFT_SE = 128 ,
SHIFT_UNDEFINED = 256 // be aware, if you use a byte, it makes 0.
} ;
enum TCost
{
NO_COST = 0 ,
ORTHO_COST = 2 ,
DIAG_COST = 3 ,
MAX_COST = 3
} ;
public :
explicit CDirection ( ) ;
CDirection ( CDirection const & dir ) ;
explicit CDirection ( TDirection dir ) ;
/// @name user interface assuming the y inversion (sorry).
//@{
explicit CDirection ( int deltax , int deltay , bool toCalculate ) ;
// initialisation with a direction depending on deltas (-1,0 or 1)
explicit CDirection ( int deltax , int deltay ) ;
// initialisation with a direction depending on deltas (-1,0 or 1)
explicit CDirection ( CAngle const & angle ) ;
CAngle getAngle ( ) ;
sint dx ( ) const ;
sint dy ( ) const ;
void dxdy ( int & dx , int & dy ) ;
//@}
bool isValid ( ) { return _value ! = UNDEFINED ; }
// add a number of 45 turn
void addStep ( TDeltaDirection step ) ;
NLMISC : : CVector2f getDirFloat ( ) const ;
TDirection getVal ( ) const ;
TMotifDirection getShift ( ) const ;
bool operator ! = ( TDirection dir ) const ;
bool operator ! = ( CDirection const & dir ) const ;
struct CDirectionData
{
sint dx ;
sint dy ;
TCost weight ;
} ;
static CDirectionData const directionDatas [ ] ;
static TDirection const table [ ] ;
// used in pacs (nothing to do here but i haven't enought time to rewrite much code)
uint32 getWeight ( ) ;
static void getDirectionAround ( CAngle const & Angle , CDirection & Dir0 , CDirection & Dir1 ) ;
private :
void setDxDy ( int deltax , int deltay ) ;
TDirection _value ;
} ;
inline
CDirection : : CDirection ( )
: _value ( UNDEFINED )
{
}
inline
CDirection : : CDirection ( CDirection const & dir )
: _value ( dir . _value )
{
}
inline
CDirection : : CDirection ( TDirection dir )
: _value ( dir )
{
# ifdef NL_DEBUG
nlassert ( dir > = E & & dir < = UNDEFINED ) ;
# endif
}
inline
CDirection : : CDirection ( int deltax , int deltay , bool toCalculate )
{
# ifdef NL_DEBUG
nlassert ( deltax ! = 0 | | deltay ! = 0 ) ;
# endif
uint absDeltax = abs ( deltax ) ;
uint absDeltay = abs ( deltay ) ;
if ( deltax ! = 0 & & deltay ! = 0 )
{
float ratio = ( float ) ( ( float ) absDeltax / ( float ) absDeltay ) ;
if ( ratio > = 0.4141 & & ratio < = 2.4145 ) // cos(PI/8)/sin(PI/8) ou sin(PI/8)/cos(PI/8)
{
setDxDy ( deltax > 0 ? 1 : - 1 , deltay > 0 ? 1 : - 1 ) ;
return ;
}
}
if ( absDeltax > absDeltay )
setDxDy ( deltax > 0 ? 1 : - 1 , 0 ) ;
else
setDxDy ( 0 , deltay > 0 ? 1 : - 1 ) ;
}
inline
CDirection : : CDirection ( int deltax , int deltay )
{
setDxDy ( deltax , deltay ) ;
}
inline
CDirection : : CDirection ( CAngle const & angle )
{
_value = ( TDirection ) ( ( ( ( sint32 ) angle . asRawSint16 ( ) + 65536 + 4096 ) / 8192 ) & 7 ) ; // add 4096 to have a correct angle magnet.
}
inline
CAngle CDirection : : getAngle ( )
{
# ifdef NL_DEBUG
nlassert ( isValid ( ) ) ;
# endif
return CAngle ( _value * 8192 ) ;
}
inline
sint CDirection : : dx ( ) const
{
return directionDatas [ _value ] . dx ;
}
inline
sint CDirection : : dy ( ) const
{
return directionDatas [ _value ] . dy ;
}
inline
void CDirection : : dxdy ( int & dx , int & dy )
{
CDirectionData const & direction = directionDatas [ _value ] ;
dx = direction . dx ;
dy = direction . dy ;
}
inline
void CDirection : : addStep ( TDeltaDirection step )
{
# ifdef NL_DEBUG
nlassert ( isValid ( ) ) ;
# endif
_value = ( TDirection ) ( ( _value + step ) & 7 ) ;
}
inline
NLMISC : : CVector2f CDirection : : getDirFloat ( ) const
{
return NLMISC : : CVector2f ( ( float ) dx ( ) , ( float ) dy ( ) ) ;
}
inline
CDirection : : TDirection CDirection : : getVal ( ) const
{
return _value ;
}
inline
CDirection : : TMotifDirection CDirection : : getShift ( ) const
{
return ( TMotifDirection ) ( 1 < < _value ) ;
}
inline
bool CDirection : : operator ! = ( TDirection dir ) const
{
return _value ! = dir ;
}
inline
bool CDirection : : operator ! = ( CDirection const & dir ) const
{
return _value ! = dir . _value ;
}
inline
uint32 CDirection : : getWeight ( )
{
return directionDatas [ _value ] . weight ;
}
inline
void CDirection : : getDirectionAround ( CAngle const & Angle , CDirection & Dir0 , CDirection & Dir1 )
{
sint value = Angle . asRawSint16 ( ) & ( ~ 16383 ) ; //8191);
Dir0 = CDirection ( CAngle ( value ) ) ;
value + = 16384 ; //8192;
Dir1 = CDirection ( CAngle ( value ) ) ;
}
inline
void CDirection : : setDxDy ( int deltax , int deltay )
{
# ifdef NL_DEBUG
nlassert ( deltax > = - 1 & & deltax < = 1 & & deltay > = - 1 & & deltay < = 1 ) ;
# endif
_value = table [ 1 + deltax + ( 1 + deltay ) * 3 ] ;
# ifdef NL_DEBUG
nlassert ( dx ( ) = = deltax & & dy ( ) = = deltay ) ;
# endif
}
//////////////////////////////////////////////////////////////////////////////
/**
* A map of accessible positions near a given position
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CNeighbourhood
{
public :
/// One bit per direction
bool isValid ( CDirection : : TDirection dir ) const ;
bool isValid ( CDirection const & dir ) const ;
void set ( CDirection : : TDirection dir ) ;
CNeighbourhood ( ) ;
private :
CNeighbourhood ( uint32 neighb ) ;
/// 8 bits for 8 directions
uint32 Neighb ;
} ;
inline
bool CNeighbourhood : : isValid ( CDirection : : TDirection dir ) const
{
return ( Neighb & CDirection ( dir ) . getShift ( ) ) ! = 0 ;
}
inline
bool CNeighbourhood : : isValid ( CDirection const & dir ) const
{
return ( Neighb & dir . getShift ( ) ) ! = 0 ;
}
inline
void CNeighbourhood : : set ( CDirection : : TDirection dir )
{
Neighb | = CDirection ( dir ) . getShift ( ) ;
}
inline
CNeighbourhood : : CNeighbourhood ( )
: Neighb ( 0 )
{
}
inline
CNeighbourhood : : CNeighbourhood ( uint32 neighb )
: Neighb ( neighb )
{
}
//////////////////////////////////////////////////////////////////////////////
/**
* A slot , defining pacs position and linkage to other slots
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CUnitSlot
{
public :
// 12 bits 0-11 : instance id
// 12 bits 12-23 : surface id
// 2 bits 24-25 : north link
// 2 bits 26-27 : east link
// 2 bits 28-29 : south link
// 2 bits 30-31 : west link
enum
{
InstanceIdOffset = 0 ,
InstanceIdMask = 0x00000fff ,
InstanceIdMax = 4096 ,
SurfaceIdOffset = 12 ,
SurfaceIdMask = 0x00fff000 ,
SurfaceIdMax = 4096 ,
SlotOffset = 24 ,
SlotMask = 0xff000000
} ;
// 6 bits 0-5 topology
// 2 bits 6-7 gabarit
enum
{
TopologyMask = 0x3f ,
GabaritMask = 0xc0 ,
GabaritShift = 6 ,
} ;
// 1 bit 0 interior
// 1 bit 1 water
// 1 bit 2 nogo
// 13 bits 3-15 height
enum
{
InteriorMask = 0x0001 ,
WaterMask = 0x0002 ,
NoGoMask = 0x0004 ,
HeightMask = 0xfff8 ,
HeightShift = 3 ,
} ;
public :
/// @name Constructors
//@{
explicit CUnitSlot ( ) ;
explicit CUnitSlot ( uint instanceId , uint surfaceId ) ;
explicit CUnitSlot ( NLPACS : : UGlobalPosition const & pos ) ;
//@}
// Selectors
uint instanceId ( ) const { return ( _Id & InstanceIdMask ) > > InstanceIdOffset ; }
uint surfaceId ( ) const { return ( _Id & SurfaceIdMask ) > > SurfaceIdOffset ; }
uint height ( ) const { return _Height > > HeightShift ; }
CCellLinkage & cellLink ( ) { return * ( ( CCellLinkage * ) ( ( ( char * ) & _Id ) + 3 ) ) ; }
CCellLinkage getCellLink ( ) const { return * ( ( CCellLinkage * ) ( ( ( char * ) & _Id ) + 3 ) ) ; }
uint topology ( ) const { return ( _Topology & TopologyMask ) ; }
uint gabarit ( ) const { return ( _Topology & GabaritMask ) > > GabaritShift ; }
bool interior ( ) const { return ( _Height & InteriorMask ) ! = 0 ; }
bool water ( ) const { return ( _Height & WaterMask ) ! = 0 ; }
bool nogo ( ) const { return ( _Height & NoGoMask ) ! = 0 ; }
/// @name Mutators
//@{
void setInstanceId ( uint instanceId ) ;
void setSurface ( uint surfaceId ) ;
void setTopology ( uint topology ) ;
void setGabarit ( uint gabarit ) ;
void setHeight ( sint height ) ;
void setInterior ( bool interior ) ;
void setWater ( bool water ) ;
void setNoGo ( bool nogo ) ;
void reset ( ) ;
//@}
bool used ( ) const ;
bool hasSameSurface ( const CUnitSlot & slot ) const ;
void serial ( NLMISC : : IStream & f ) ;
private :
// _Id is divided this way
// bits 0-11 : instance id
// bits 12-23 : surface id
// bits 24-25 : north link
// bits 26-27 : east link
// bits 28-29 : south link
// bits 30-31 : west link
uint32 _Id ;
// 6 bits 0-5 topology
// 2 bits 6-7 gabarit
uint8 _Topology ;
// 1 bit 0 interior
// 1 bit 1 water
// 1 bit 2 nogo
// 13 bits 3-15 height
sint16 _Height ;
} ;
// a cell is composed of units of 3 slots
typedef CUnitSlot TCellUnit [ 3 ] ;
inline
CUnitSlot : : CUnitSlot ( )
: _Id ( 0xffffffff )
, _Topology ( 0 )
, _Height ( 0 )
{
}
inline
CUnitSlot : : CUnitSlot ( uint instanceId , uint surfaceId )
: _Topology ( 0 )
, _Height ( 0 )
{
# ifdef NL_DEBUG
nlassert ( instanceId < InstanceIdMax ) ;
nlassert ( surfaceId < SurfaceIdMax ) ;
# endif
_Id = SlotMask + ( instanceId < < InstanceIdOffset ) + ( surfaceId < < SurfaceIdOffset ) ;
}
inline
CUnitSlot : : CUnitSlot ( NLPACS : : UGlobalPosition const & pos )
: _Topology ( 0 )
, _Height ( 0 )
{
# ifdef NL_DEBUG
nlassert ( pos . InstanceId < InstanceIdMax ) ;
nlassert ( pos . LocalPosition . Surface < SurfaceIdMax ) ;
# endif
_Id = SlotMask + ( pos . InstanceId < < InstanceIdOffset ) + ( pos . LocalPosition . Surface < < SurfaceIdOffset ) ;
}
inline
void CUnitSlot : : setInstanceId ( uint instanceId )
{
# ifdef NL_DEBUG
nlassert ( instanceId < InstanceIdMax ) ;
# endif
_Id = ( _Id & ( ~ InstanceIdMask ) ) + ( instanceId < < InstanceIdOffset ) ;
}
inline
void CUnitSlot : : setSurface ( uint surfaceId )
{
# ifdef NL_DEBUG
nlassert ( surfaceId < SurfaceIdMax ) ;
# endif
_Id = ( _Id & ( ~ SurfaceIdMask ) ) + ( surfaceId < < SurfaceIdOffset ) ;
}
inline
void CUnitSlot : : setTopology ( uint topology )
{
# ifdef NL_DEBUG
nlassert ( topology < 63 ) ;
# endif
_Topology = ( _Topology & ( ~ TopologyMask ) ) + ( uint8 ) topology ;
}
inline
void CUnitSlot : : setGabarit ( uint gabarit )
{
# ifdef NL_DEBUG
nlassert ( gabarit < 4 ) ;
# endif
_Topology = ( _Topology & ( ~ GabaritMask ) ) | ( uint8 ) ( gabarit < < GabaritShift ) ;
}
inline
void CUnitSlot : : setHeight ( sint height )
{
# ifdef NL_DEBUG
nlassert ( height > = - 4096 & & height < = 4095 ) ;
# endif
_Height = ( _Height & ( ~ HeightMask ) ) | ( sint16 ) ( height < < HeightShift ) ;
}
inline
void CUnitSlot : : setInterior ( bool interior )
{
if ( interior )
_Height | = InteriorMask ;
else
_Height & = ~ InteriorMask ;
}
inline
void CUnitSlot : : setWater ( bool water )
{
if ( water )
_Height | = WaterMask ;
else
_Height & = ~ WaterMask ;
}
inline
void CUnitSlot : : setNoGo ( bool nogo )
{
if ( nogo )
_Height | = NoGoMask ;
else
_Height & = ~ NoGoMask ;
}
inline
void CUnitSlot : : reset ( )
{
_Id = 0xffffffff ;
_Topology = 0 ;
_Height = 0 ;
}
inline
bool CUnitSlot : : used ( ) const
{
return _Id ! = 0xffffffff ;
}
inline
bool CUnitSlot : : hasSameSurface ( const CUnitSlot & slot ) const
{
return ( ( slot . _Id ^ _Id ) & ( ~ SlotMask ) ) = = 0 ;
}
inline
void CUnitSlot : : serial ( NLMISC : : IStream & f )
{
f . serial ( _Id ) ;
f . serial ( _Topology ) ;
f . serial ( _Height ) ;
}
//////////////////////////////////////////////////////////////////////////////
class CMapPosition ;
typedef sint32 TMapCoordType ;
/**
* A simple 1 axis coordinate
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CMapCoord
{
friend class CMapPosition ;
public :
explicit CMapCoord ( uint scellId , uint cellId , uint unitId ) ;
private :
explicit CMapCoord ( ) : c ( 0 ) { }
explicit CMapCoord ( CAICoord const & aiCoord ) : c ( ( sint ) ( floor ( aiCoord . asDouble ( ) + 0.5 ) ) ) { }
explicit CMapCoord ( sint cc ) : c ( cc ) { }
uint cellIdMask ( uint val ) const ;
uint fullCellIdMask ( uint val ) const ;
uint toUnitId ( uint val ) const ;
uint toCellId ( uint val ) const ;
uint toSuperCellId ( uint val ) const ;
uint unitIdToUInt ( uint val ) const ;
uint cellIdToUInt ( uint val ) const ;
uint superCellIdToUInt ( uint val ) const ;
uint fullCellIdToUInt ( uint val ) const ;
TMapCoordType & cRef ( ) ;
public :
uint getUnitId ( ) const { return unitIdToUInt ( c ) ; }
uint getCellId ( ) const { return cellIdToUInt ( c ) ; }
uint getSuperCellId ( ) const { return superCellIdToUInt ( c ) ; }
uint getFullCellId ( ) const { return fullCellIdToUInt ( c ) ; }
void setUnitId ( uint id ) { c = fullCellIdMask ( c ) | toUnitId ( id ) ; }
void setCellId ( uint id ) { c = cellIdMask ( c ) | toCellId ( id ) ; }
bool operator = = ( CMapCoord const & cc ) const { return c = = cc . c ; }
bool operator ! = ( CMapCoord const & cc ) const { return c ! = cc . c ; }
CMapCoord operator - ( CMapCoord const & cc ) const { return CMapCoord ( c - cc . c ) ; }
TMapCoordType const & get ( ) const { return c ; }
private :
// coordinate
TMapCoordType c ;
} ;
inline
CMapCoord : : CMapCoord ( uint scellId , uint cellId , uint unitId )
: c ( toSuperCellId ( scellId ) + toCellId ( cellId ) + toUnitId ( unitId ) )
{
# ifdef NL_DEBUG
nlassert ( scellId < 256 ) ;
# endif
}
inline
uint CMapCoord : : cellIdMask ( uint val ) const
{
return val & 0xff0f ;
}
inline
uint CMapCoord : : fullCellIdMask ( uint val ) const
{
return val & 0x0fffffff0 ;
}
inline
uint CMapCoord : : toUnitId ( uint val ) const
{
return val & 0x0f ;
}
inline
uint CMapCoord : : toCellId ( uint val ) const
{
return ( val < < 4 ) & 0x0f0 ;
}
inline
uint CMapCoord : : toSuperCellId ( uint val ) const
{
return ( val < < 8 ) & 0x0ffff ;
}
inline
uint CMapCoord : : unitIdToUInt ( uint val ) const
{
return val & 0x0f ;
}
inline
uint CMapCoord : : cellIdToUInt ( uint val ) const
{
return ( val > > 4 ) & 0xf ;
}
inline
uint CMapCoord : : superCellIdToUInt ( uint val ) const
{
return ( val > > 8 ) & 0x0ff ;
}
inline
uint CMapCoord : : fullCellIdToUInt ( uint val ) const
{
return ( val > > 4 ) & 0x0fff ;
}
inline
TMapCoordType & CMapCoord : : cRef ( )
{
return c ;
}
//////////////////////////////////////////////////////////////////////////////
/**
* A map position , consisting of 2 axis coordinates
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CMapPosition
{
friend class RYPACSCRUNCH : : CPacsCruncher ;
public :
CMapPosition ( ) { }
CMapPosition ( sint x , sint y ) ;
CMapPosition ( CMapCoord const & x , CMapCoord const & y ) ;
CMapPosition ( CMapPosition const & pos ) ;
CMapPosition ( NLMISC : : CVectorD const & pos ) ;
CMapPosition ( CAIVector const & pos ) ;
CMapPosition ( CAICoord const & x , CAICoord const & y ) ;
NLMISC : : CVectorD toVectorD ( ) const ;
NLMISC : : CVector2d toVector2d ( ) const ;
CAIVector toAIVector ( ) const ;
std : : string toString ( ) const ;
void setUnitId ( uint const xId , uint const yId ) ;
void setNullUnitId ( ) ;
CMapPosition stepCell ( sint dx , sint dy ) const ;
bool hasSameFullCellId ( CMapPosition const & other ) const ;
CMapPosition operator - ( CMapPosition const & other ) const ;
bool operator = = ( CMapPosition const & cc ) const ;
bool operator ! = ( CMapPosition const & cc ) const ;
CMapCoord const & xCoord ( ) const { return _x ; }
CMapCoord const & yCoord ( ) const { return _y ; }
TMapCoordType const & x ( ) const { return _x . get ( ) ; }
TMapCoordType const & y ( ) const { return _y . get ( ) ; }
uint32 superCellFastIndex ( ) const ;
uint32 rootCellFastIndex ( ) const ;
uint32 cellUnitFastIndex ( ) const ;
CMapPosition step ( sint dx , sint dy ) const ;
CMapPosition getStepS ( ) const { return step ( 0 , - 1 ) ; }
CMapPosition getStepN ( ) const { return step ( 0 , + 1 ) ; }
CMapPosition getStepE ( ) const { return step ( + 1 , 0 ) ; }
CMapPosition getStepW ( ) const { return step ( - 1 , 0 ) ; }
protected :
// return if we have changed of RootCell ..
bool stepS ( ) { _y . cRef ( ) - = 1 ; return ( ( _y . cRef ( ) & 0xf ) = = 0xf ) ; }
bool stepN ( ) { _y . cRef ( ) + = 1 ; return ( ( _y . cRef ( ) & 0xf ) = = 0x0 ) ; }
bool stepW ( ) { _x . cRef ( ) - = 1 ; return ( ( _x . cRef ( ) & 0xf ) = = 0xf ) ; }
bool stepE ( ) { _x . cRef ( ) + = 1 ; return ( ( _x . cRef ( ) & 0xf ) = = 0x0 ) ; }
private :
CMapCoord _x ;
CMapCoord _y ;
} ;
inline
CMapPosition : : CMapPosition ( sint x , sint y )
: _x ( CMapCoord ( x ) )
, _y ( CMapCoord ( y ) )
{
}
inline
CMapPosition : : CMapPosition ( CMapCoord const & x , CMapCoord const & y )
: _x ( x )
, _y ( y )
{
}
inline
CMapPosition : : CMapPosition ( CMapPosition const & pos )
: _x ( pos . _x )
, _y ( pos . _y )
{
}
inline
CMapPosition : : CMapPosition ( NLMISC : : CVectorD const & pos )
: _x ( ( uint ) floor ( ( pos . x - WorldStartOffset . x ) / WorldGridResolution + 0.5 ) )
, _y ( ( uint ) floor ( ( pos . y - WorldStartOffset . y ) / WorldGridResolution + 0.5 ) )
{
}
inline
CMapPosition : : CMapPosition ( CAIVector const & pos )
: _x ( pos . x ( ) )
, _y ( pos . y ( ) )
{
}
inline
CMapPosition : : CMapPosition ( CAICoord const & x , CAICoord const & y )
: _x ( x )
, _y ( y )
{
}
inline
NLMISC : : CVectorD CMapPosition : : toVectorD ( ) const
{
return NLMISC : : CVectorD ( WorldStartOffset . x + _x . get ( ) * WorldGridResolution , WorldStartOffset . y + _y . get ( ) * WorldGridResolution , 0.0 ) ;
}
inline
NLMISC : : CVector2d CMapPosition : : toVector2d ( ) const
{
return NLMISC : : CVector2d ( WorldStartOffset . x + _x . get ( ) * WorldGridResolution , WorldStartOffset . y + _y . get ( ) * WorldGridResolution ) ;
}
inline
CAIVector CMapPosition : : toAIVector ( ) const
{
return CAIVector ( WorldStartOffset . x + _x . get ( ) * WorldGridResolution , WorldStartOffset . y + _y . get ( ) * WorldGridResolution ) ;
}
inline
std : : string CMapPosition : : toString ( ) const
{
return toAIVector ( ) . toString ( ) ;
}
inline
void CMapPosition : : setUnitId ( uint const xId , uint const yId )
{
_x . setUnitId ( xId ) ;
_y . setUnitId ( yId ) ;
}
inline
void CMapPosition : : setNullUnitId ( )
{
_x . setUnitId ( 0 ) ;
_y . setUnitId ( 0 ) ;
}
inline
CMapPosition CMapPosition : : stepCell ( sint dx , sint dy ) const
{
CMapPosition newMapPos ( xCoord ( ) . get ( ) + ( dx < < 4 ) , yCoord ( ) . get ( ) + ( dy < < 4 ) ) ;
newMapPos . setNullUnitId ( ) ;
return newMapPos ;
}
inline
bool CMapPosition : : hasSameFullCellId ( CMapPosition const & other ) const
{
return ( _x . getFullCellId ( ) = = other . _x . getFullCellId ( ) & & _y . getFullCellId ( ) = = other . _y . getFullCellId ( ) ) ;
}
inline
CMapPosition CMapPosition : : operator - ( CMapPosition const & other ) const
{
return CMapPosition ( _x - other . _x , _y - other . _y ) ;
}
inline
bool CMapPosition : : operator = = ( CMapPosition const & cc ) const
{
return _x = = cc . _x & & _y = = cc . _y ;
}
inline
bool CMapPosition : : operator ! = ( CMapPosition const & cc ) const
{
return _x ! = cc . _x | | _y ! = cc . _y ;
}
inline
uint32 CMapPosition : : superCellFastIndex ( ) const
{
return ( ( ( ( uint ) y ( ) ) & ( 0x0ff < < 8 ) ) + xCoord ( ) . getSuperCellId ( ) ) ;
}
inline
uint32 CMapPosition : : rootCellFastIndex ( ) const
{
return ( ( ( ( uint ) y ( ) ) & 0x0f < < 4 ) + xCoord ( ) . getCellId ( ) ) ;
}
inline
uint32 CMapPosition : : cellUnitFastIndex ( ) const
{
return ( ( yCoord ( ) . getUnitId ( ) < < 4 ) + xCoord ( ) . getUnitId ( ) ) ;
}
inline
CMapPosition CMapPosition : : step ( sint dx , sint dy ) const
{
return CMapPosition ( _x . get ( ) + dx , _y . get ( ) + dy ) ;
}
//////////////////////////////////////////////////////////////////////////////
/**
* Motion map interface
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CGridDirectionLayer
: public I16x16Layer
{
public :
CDirection getDirection ( int y , int x ) const ;
CDirection getDirection ( CMapPosition const & pos ) const ;
void setDirection ( int y , int x , CDirection dir ) ;
} ;
inline
CDirection CGridDirectionLayer : : getDirection ( int y , int x ) const
{
return CDirection ( ( CDirection : : TDirection ) get ( y , x ) ) ;
}
inline
CDirection CGridDirectionLayer : : getDirection ( CMapPosition const & pos ) const
{
return CDirection ( ( CDirection : : TDirection ) get ( pos . yCoord ( ) . getUnitId ( ) , pos . xCoord ( ) . getUnitId ( ) ) ) ;
}
inline
void CGridDirectionLayer : : setDirection ( int y , int x , CDirection dir )
{
this - > set ( ( uint ) y , ( uint ) x , ( sint ) dir . getVal ( ) ) ;
}
//////////////////////////////////////////////////////////////////////////////
class CDirectionLayer
{
public :
CDirectionLayer ( ) ;
void serial ( NLMISC : : IStream & f ) ;
CGridDirectionLayer * getGridLayer ( int y , int x ) ;
void setGridLayer ( int y , int x , I16x16Layer * layer ) ;
void dump ( ) ;
private :
// Grid[1][1] is central cell
I16x16Layer * Grid [ 3 ] [ 3 ] ;
} ;
inline
CDirectionLayer : : CDirectionLayer ( )
{
uint i , j ;
for ( i = 0 ; i < 3 ; + + i )
for ( j = 0 ; j < 3 ; + + j )
Grid [ i ] [ j ] = NULL ;
}
inline
CGridDirectionLayer * CDirectionLayer : : getGridLayer ( int y , int x )
{
return static_cast < CGridDirectionLayer * > ( Grid [ y ] [ x ] ) ;
}
inline
void CDirectionLayer : : setGridLayer ( int y , int x , I16x16Layer * layer )
{
Grid [ y ] [ x ] = layer ;
}
inline
void CDirectionLayer : : dump ( )
{
char output [ 16 * 3 ] [ 16 * 3 ] ;
for ( sint i = 2 ; i > = 0 ; - - i )
for ( sint j = 0 ; j < 3 ; + + j )
for ( sint y = 15 ; y > = 0 ; - - y )
for ( sint x = 0 ; x < 16 ; + + x )
{
CGridDirectionLayer * gridDirectionLayer = getGridLayer ( i , j ) ;
CDirection motion ;
if ( gridDirectionLayer )
motion = gridDirectionLayer - > getDirection ( y , x ) ;
char c = ' ' ;
switch ( motion . getVal ( ) )
{
case CDirection : : N :
c = ' ^ ' ;
break ;
case CDirection : : S :
c = ' v ' ;
break ;
case CDirection : : E :
c = ' > ' ;
break ;
case CDirection : : W :
c = ' < ' ;
break ;
case CDirection : : NE :
c = ' 7 ' ;
break ;
case CDirection : : SW :
c = ' L ' ;
break ;
case CDirection : : NW :
c = ' r ' ;
break ;
case CDirection : : SE :
c = ' \\ ' ;
break ;
// case 255:
// c = ' ';
// break;
default :
c = ' o ' ;
break ;
}
output [ y + i * 16 ] [ x + j * 16 ] = c ;
}
char op [ 256 ] ;
nlinfo ( " \t 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF " ) ;
for ( sint i = 47 ; i > = 0 ; - - i )
{
sint j ;
for ( j = 0 ; j < 48 ; + + j )
op [ j ] = output [ i ] [ j ] ;
op [ j ] = ' \0 ' ;
nlinfo ( " %04X \t %s " , ( i & 15 ) , op ) ;
}
}
//////////////////////////////////////////////////////////////////////////////
class CDirectionMap
{
public :
CDirectionLayer * Layers [ 3 ] ;
CDirectionMap ( ) ;
void serial ( NLMISC : : IStream & f ) ;
void dump ( ) ;
} ;
inline
CDirectionMap : : CDirectionMap ( )
{
Layers [ 0 ] = NULL ;
Layers [ 1 ] = NULL ;
Layers [ 2 ] = NULL ;
}
inline
void CDirectionMap : : dump ( )
{
for ( uint i = 0 ; i < 3 ; + + i )
{
nlinfo ( " Layer %d " , i ) ;
if ( Layers [ i ] ! = NULL )
Layers [ i ] - > dump ( ) ;
else
nlinfo ( " Empty " ) ;
}
}
//////////////////////////////////////////////////////////////////////////////
class CWorldMap ;
class CRootCell ;
class CWorldPosition ;
class CTopology
{
public :
/// A topology Id, representing cell and topology
class TTopologyId
{
public :
enum
{
UNDEFINED_TOPOLOGY = 0xffffffff
} ;
public :
explicit TTopologyId ( ) ;
explicit TTopologyId ( CMapPosition const & pos , uint topology ) ;
// For test only
explicit TTopologyId ( uint32 id ) ;
bool haveSameCellPos ( TTopologyId const & other ) const ;
CMapPosition getMapPosition ( ) const ;
uint getTopologyIndex ( ) const ;
bool isValid ( ) const ;
bool operator < ( TTopologyId const & other ) const ;
bool operator = = ( TTopologyId const & other ) const ;
bool operator ! = ( TTopologyId const & other ) const ;
void serial ( NLMISC : : IStream & f ) ;
uint32 getVal ( ) const ;
private :
uint32 _value ;
} ;
class TTopologyRef
: public TTopologyId
{
friend class CWorldPosition ;
public :
TTopologyRef ( CWorldPosition const & pos ) ;
TTopologyRef ( ) ;
explicit TTopologyRef ( TTopologyId const & id , CRootCell * rootCell ) ;
CTopology const & getCstTopologyNode ( ) const ;
void setRootCell ( CRootCell * rootCell ) ;
void serial ( NLMISC : : IStream & f ) ;
CRootCell const * getRootCell ( ) const ;
private :
TTopologyRef ( CWorldPosition const & pos , CRootCell const * rootCell ) ;
CRootCell const * _RootCell ;
} ;
/// A link to a neighbour, including mean distance to it
class CNeighbourLink
{
public :
explicit CNeighbourLink ( ) ;
explicit CNeighbourLink ( TTopologyRef const & ref , float distance ) ;
CNeighbourLink ( CNeighbourLink const & other ) ;
void serial ( NLMISC : : IStream & f ) ;
TTopologyRef const & getTopologyRef ( ) const ;
void updateTopologyRef ( CWorldMap * worldMapPtr ) ;
float getDistance ( ) const ;
private :
TTopologyRef _Ref ;
float _Distance ;
} ;
void updateTopologyRef ( CWorldMap * worldMapPtr ) ;
bool isInInterior ( ) const { return ( Flags & Interior ) ! = 0 ; }
bool isInWater ( ) const { return ( Flags & Water ) ! = 0 ; }
bool isInNogo ( ) const { return ( Flags & NoGo ) ! = 0 ; }
TAStarFlag getFlags ( ) const { return ( TAStarFlag ) Flags ; }
uint32 getMasterTopo ( TAStarFlag const & flags ) const ;
uint32 getMasterTopo ( bool allowWater , bool allowNoGo ) const ;
uint32 & getMasterTopoRef ( bool allowWater , bool allowNoGo ) ;
bool isCompatible ( bool allowWater , bool allowNoGo ) const ;
/// The Id of this topology
TTopologyId Id ;
/// The direction map to access this topology
CDirectionMap * DirectionMap ;
/// The neighbour topologies that have access to this topology
std : : vector < CNeighbourLink > Neighbours ;
/// Flags of the topology
uint16 Flags ; // why doing this (uint16), its not align so no gain in memory and it causes access cost !
/// Master topologies
uint32 MasterTopL ; // only landscape
uint32 MasterTopLW ; // landscape and water
uint32 MasterTopLN ; // landscape and nogo
uint32 MasterTopLNW ; // landscape and water and nogo
/// Topology center, for A* purpose
NLMISC : : CVector Position ;
CTopology ( ) ;
void serial ( NLMISC : : IStream & f ) ;
} ;
inline
CTopology : : TTopologyId : : TTopologyId ( )
: _value ( UNDEFINED_TOPOLOGY )
{
}
inline
CTopology : : TTopologyId : : TTopologyId ( CMapPosition const & pos , uint topology )
{
# ifdef NL_DEBUG
nlassert ( topology < 256 ) ;
# endif
_value = ( pos . yCoord ( ) . getFullCellId ( ) < < 20 ) + ( pos . xCoord ( ) . getFullCellId ( ) < < 8 ) + topology ;
}
inline
CTopology : : TTopologyId : : TTopologyId ( uint32 id )
{
_value = id ;
}
inline
bool CTopology : : TTopologyId : : haveSameCellPos ( TTopologyId const & other ) const
{
return ( ( other . _value ^ _value ) & 0x0ffffff00 ) = = 0 ;
}
inline
CMapPosition CTopology : : TTopologyId : : getMapPosition ( ) const
{
return CMapPosition ( ( _value & 0x000fff00 ) > > ( 8 - 4 ) , ( _value & 0xfff00000 ) > > ( 20 - 4 ) ) ;
}
inline
uint CTopology : : TTopologyId : : getTopologyIndex ( ) const
{
return _value & 0x000000ff ;
}
inline
bool CTopology : : TTopologyId : : isValid ( ) const
{
return _value ! = UNDEFINED_TOPOLOGY ;
}
inline
bool CTopology : : TTopologyId : : operator < ( TTopologyId const & other ) const
{
return _value < other . _value ;
}
inline
bool CTopology : : TTopologyId : : operator = = ( TTopologyId const & other ) const
{
return _value = = other . _value ;
}
inline
bool CTopology : : TTopologyId : : operator ! = ( TTopologyId const & other ) const
{
return _value ! = other . _value ;
}
inline
void CTopology : : TTopologyId : : serial ( NLMISC : : IStream & f )
{
f . serial ( _value ) ;
}
inline
uint32 CTopology : : TTopologyId : : getVal ( ) const
{
return _value ;
}
inline
CTopology : : TTopologyRef : : TTopologyRef ( )
: TTopologyId ( )
, _RootCell ( NULL )
{
}
inline
CTopology : : TTopologyRef : : TTopologyRef ( TTopologyId const & id , CRootCell * rootCell )
: TTopologyId ( id )
{
setRootCell ( rootCell ) ;
}
inline
void CTopology : : TTopologyRef : : setRootCell ( CRootCell * rootCell )
{
_RootCell = rootCell ;
}
inline
void CTopology : : TTopologyRef : : serial ( NLMISC : : IStream & f )
{
TTopologyId : : serial ( f ) ;
}
inline
CRootCell const * CTopology : : TTopologyRef : : getRootCell ( ) const
{
return _RootCell ;
}
inline
CTopology : : CNeighbourLink : : CNeighbourLink ( )
: _Ref ( )
{
}
inline
CTopology : : CNeighbourLink : : CNeighbourLink ( TTopologyRef const & ref , float distance )
: _Ref ( ref )
, _Distance ( distance )
{
}
inline
CTopology : : CNeighbourLink : : CNeighbourLink ( CNeighbourLink const & other )
: _Ref ( other . _Ref )
, _Distance ( other . _Distance )
{
}
inline
void CTopology : : CNeighbourLink : : serial ( NLMISC : : IStream & f )
{
f . serial ( _Ref , _Distance ) ;
}
inline
CTopology : : TTopologyRef const & CTopology : : CNeighbourLink : : getTopologyRef ( ) const
{
return _Ref ;
}
inline
float CTopology : : CNeighbourLink : : getDistance ( ) const
{
return _Distance ;
}
inline
void CTopology : : updateTopologyRef ( CWorldMap * worldMapPtr )
{
std : : vector < CNeighbourLink > : : iterator it = Neighbours . begin ( ) , itEnd = Neighbours . end ( ) ;
while ( it ! = itEnd )
{
( * it ) . updateTopologyRef ( worldMapPtr ) ;
+ + it ;
}
}
inline
uint32 CTopology : : getMasterTopo ( TAStarFlag const & flags ) const
{
switch ( flags & WaterAndNogo )
{
case Nothing :
default :
return MasterTopL ;
case Water :
return MasterTopLW ;
case NoGo :
return MasterTopLN ;
case WaterAndNogo :
return MasterTopLNW ;
}
}
inline
uint32 CTopology : : getMasterTopo ( bool allowWater , bool allowNoGo ) const
{
if ( allowWater )
{
if ( allowNoGo )
return MasterTopLNW ;
return MasterTopLW ;
}
if ( allowNoGo )
return MasterTopLN ;
return MasterTopL ;
}
inline
uint32 & CTopology : : getMasterTopoRef ( bool allowWater , bool allowNoGo )
{
if ( allowWater )
{
if ( allowNoGo )
return MasterTopLNW ;
return MasterTopLW ;
}
if ( allowNoGo )
return MasterTopLN ;
return MasterTopL ;
}
inline
bool CTopology : : isCompatible ( bool allowWater , bool allowNoGo ) const
{
return ( allowWater | | ! isInWater ( ) ) & & ( allowNoGo | | ! isInNogo ( ) ) ;
}
inline
CTopology : : CTopology ( )
: Id ( )
, DirectionMap ( NULL )
, Flags ( Nothing )
, MasterTopL ( TTopologyId : : UNDEFINED_TOPOLOGY )
, MasterTopLW ( TTopologyId : : UNDEFINED_TOPOLOGY )
, MasterTopLN ( TTopologyId : : UNDEFINED_TOPOLOGY )
, MasterTopLNW ( TTopologyId : : UNDEFINED_TOPOLOGY )
{
}
inline
void CTopology : : serial ( NLMISC : : IStream & f )
{
uint version = 0 ;
uint16 check = ( uint16 ) ' Tp ' ;
f . serial ( check ) ;
if ( check ! = ( uint16 ) ' TP ' )
{
nlassert ( check = = ( uint16 ) ' Tp ' ) ;
version = f . serialVersion ( 3 ) ;
}
f . serial ( Id ) ;
if ( f . isReading ( ) )
{
delete DirectionMap ;
DirectionMap = NULL ;
}
bool present = ( DirectionMap ! = NULL ) ;
f . serial ( present ) ;
if ( present )
{
if ( f . isReading ( ) )
DirectionMap = new CDirectionMap ( ) ;
f . serial ( * DirectionMap ) ;
}
f . serialCont ( Neighbours ) ;
f . serial ( Position ) ;
if ( version > = 3 )
{
f . serial ( Flags ) ;
f . serial ( MasterTopL ) ;
f . serial ( MasterTopLW ) ;
f . serial ( MasterTopLN ) ;
f . serial ( MasterTopLNW ) ;
}
else
{
nlassert ( f . isReading ( ) ) ;
Flags = Nothing ;
if ( version > = 1 )
{
bool interior ;
f . serial ( interior ) ;
if ( interior )
Flags | = Interior ;
}
if ( version > = 2 )
{
bool water ;
f . serial ( water ) ;
if ( water )
Flags | = Water ;
}
MasterTopL = 0 ;
MasterTopLW = 0 ;
MasterTopLN = 0 ;
MasterTopLNW = 0 ;
}
}
//////////////////////////////////////////////////////////////////////////////
/**
* CWorldPosition , position referenced by a map position and a slot
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CWorldPosition
: public CMapPosition
, public CSlot
{
friend class CWorldMap ;
friend class RYPACSCRUNCH : : CPacsCruncher ;
public :
explicit CWorldPosition ( ) ;
explicit CWorldPosition ( sint x , sint y ) ;
// resumes that the RootCell is valid;
CRootCell const * getRootCell ( ) const { return _RootCell ; }
/// In millimeters.
sint32 getMetricHeight ( ) const ;
sint32 h ( ) const { return getMetricHeight ( ) ; }
CCellLinkage const & getCellLinkage ( ) const { return _cellLinkage ; }
CTopology : : TTopologyRef getTopologyRef ( ) const ;
bool isInInterior ( ) const ;
CTopology const & getTopologyNode ( ) const ;
TAStarFlag getFlags ( ) const ;
/// Get a vector position from a world position
NLMISC : : CVectorD getPosition ( ) const ;
bool operator = = ( CWorldPosition const & cc ) const { return CSlot : : operator = = ( cc ) & & CMapPosition : : operator = = ( cc ) ; }
bool operator ! = ( CWorldPosition const & cc ) const { return CSlot : : operator ! = ( cc ) | | CMapPosition : : operator ! = ( cc ) ; }
private :
CWorldPosition getPosS ( ) const ;
CWorldPosition getPosN ( ) const ;
CWorldPosition getPosE ( ) const ;
CWorldPosition getPosW ( ) const ;
void setPosS ( CWorldPosition & pos ) const ;
void setPosN ( CWorldPosition & pos ) const ;
void setPosE ( CWorldPosition & pos ) const ;
void setPosW ( CWorldPosition & pos ) const ;
bool moveS ( ) ;
bool moveN ( ) ;
bool moveE ( ) ;
bool moveW ( ) ;
void stepS ( ) ;
void stepN ( ) ;
void stepE ( ) ;
void stepW ( ) ;
CRootCell const * _RootCell ;
CCellLinkage _cellLinkage ;
explicit CWorldPosition ( CRootCell const * cell , CMapPosition const & pos , CSlot const & slot ) ;
explicit CWorldPosition ( CRootCell const * cell , CMapPosition const & pos , CSlot const & slot , bool generationOnly ) ;
} ;
inline
CWorldPosition : : CWorldPosition ( )
: CMapPosition ( )
, CSlot ( )
, _RootCell ( NULL )
, _cellLinkage ( 0 )
{
}
inline
CWorldPosition : : CWorldPosition ( sint x , sint y )
: CMapPosition ( x , y )
, CSlot ( )
, _RootCell ( NULL )
, _cellLinkage ( 0 )
{
}
inline
CTopology : : TTopologyRef CWorldPosition : : getTopologyRef ( ) const
{
return CTopology : : TTopologyRef ( * this , getRootCell ( ) ) ;
}
inline
bool CWorldPosition : : isInInterior ( ) const
{
return getTopologyRef ( ) . getCstTopologyNode ( ) . isInInterior ( ) ;
}
inline
CTopology const & CWorldPosition : : getTopologyNode ( ) const
{
return getTopologyRef ( ) . getCstTopologyNode ( ) ;
}
inline
TAStarFlag CWorldPosition : : getFlags ( ) const
{
return getTopologyRef ( ) . getCstTopologyNode ( ) . getFlags ( ) ; //Flags;
}
//////////////////////////////////////////////////////////////////////////////
class CCompatibleResult
{
public :
CCompatibleResult ( TAStarFlag movementFlags = Interior , uint32 choosenMasterTopo = ~ 0 ) ;
void set ( TAStarFlag movementFlags , uint32 choosenMasterTopo ) ;
void setValid ( bool valid = true ) ;
TAStarFlag const & movementFlags ( ) const ;
uint32 const & choosenMasterTopo ( ) const ;
bool const & isValid ( ) const ;
private :
TAStarFlag _MovementFlags ;
uint32 _ChoosenMasterTopo ;
bool _Valid ;
} ;
inline
CCompatibleResult : : CCompatibleResult ( TAStarFlag movementFlags , uint32 choosenMasterTopo )
: _MovementFlags ( movementFlags )
, _ChoosenMasterTopo ( choosenMasterTopo )
, _Valid ( false )
{
}
inline
void CCompatibleResult : : set ( TAStarFlag movementFlags , uint32 choosenMasterTopo )
{
_MovementFlags = movementFlags ;
_ChoosenMasterTopo = choosenMasterTopo ;
}
inline
void CCompatibleResult : : setValid ( bool valid )
{
_Valid = valid ;
}
inline
TAStarFlag const & CCompatibleResult : : movementFlags ( ) const
{
return _MovementFlags ;
}
inline
uint32 const & CCompatibleResult : : choosenMasterTopo ( ) const
{
return _ChoosenMasterTopo ;
}
inline
bool const & CCompatibleResult : : isValid ( ) const
{
return _Valid ;
}
//////////////////////////////////////////////////////////////////////////////
/**
@ relates CWorldPosition
*/
void areCompatiblesWithoutStartRestriction ( CWorldPosition const & startPos , CWorldPosition const & endPos , TAStarFlag const & denyflags , CCompatibleResult & res , bool allowStartRestriction = false ) ;
//////////////////////////////////////////////////////////////////////////////
/**
* CRootCell , interface for all 16 x16 cells in world map
* derivated into CComputeCell ( for map computation only ) , into CSingleLayerCell and CMultiLayerCell
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CRootCell
{
public :
enum TCellType
{
Root = 0 ,
Compute ,
White ,
SingleLayer ,
MultiLayer
} ;
public :
CRootCell ( CWorldMap const & worldMapPtr ) ;
virtual ~ CRootCell ( ) { }
void setFlag ( uint32 const flag ) { _flag = flag ; }
uint32 getFlag ( ) const { return _flag ; }
sint32 getMetricHeight ( CWorldPosition const & wpos ) const ;
CWorldMap const & getWorldMapPtr ( ) const { return _WorldMapPtr ; }
// mutator (only for build purpose)
CTopology & getTopologyNode ( uint topology ) ;
CTopology const & getCstTopologyNode ( uint topology ) const ;
CTopology : : TTopologyId getTopologyId ( CWorldPosition const & wpos ) const ;
CTopology : : TTopologyRef getTopologyRef ( const CWorldPosition & pos ) const ;
CTopology const & getCstTopologyNode ( CTopology : : TTopologyId const & id ) const ;
std : : vector < CTopology > & getTopologiesNodes ( ) { return _TopologiesNodes ; }
std : : vector < CTopology > const & getTopologiesNodes ( ) const { return _TopologiesNodes ; }
void setTopologiesNodes ( std : : vector < CTopology > const & nodes ) { _TopologiesNodes = nodes ; }
CDirectionMap const * getDirectionMap ( uint topology ) const ;
void setDirectionMap ( CDirectionMap * map , uint topology ) ;
void updateTopologyRef ( CWorldMap * worldMap ) ;
CWorldPosition const & getWorldPosition ( uint ind ) const ;
void setWorldPosition ( CWorldPosition const & pos , uint ind ) ;
virtual CCellLinkage getCellLink ( CWorldPosition const & wpos ) const = 0 ;
virtual uint32 nbUsedSlots ( CMapPosition const & pos ) const = 0 ;
virtual sint32 maxUsedSlot ( CMapPosition const & pos ) const = 0 ;
virtual bool isSlotUsed ( CMapPosition const & pos , CSlot const & slot ) const = 0 ;
virtual uint getTopology ( CWorldPosition const & wpos ) const = 0 ;
virtual sint getHeight ( CWorldPosition const & wpos ) const = 0 ;
// clear height map
virtual void clearHeightMap ( ) = 0 ;
// serial
virtual void serial ( NLMISC : : IStream & f ) = 0 ;
// load a cell
static CRootCell * load ( NLMISC : : IStream & f , CWorldMap const & worldMap ) ;
// save a cell
static void save ( NLMISC : : IStream & f , CRootCell * cell ) ;
private :
CWorldMap const & _WorldMapPtr ; // his owner map;
std : : vector < CTopology > _TopologiesNodes ;
CWorldPosition _WorldPosition [ 4 ] ; // 4 random positions for each slots.
uint32 _flag ;
} ;
inline
CRootCell : : CRootCell ( CWorldMap const & worldMapPtr )
: _WorldMapPtr ( worldMapPtr )
{
_flag = 0 ;
}
inline
sint32 CRootCell : : getMetricHeight ( CWorldPosition const & wpos ) const
{
// check if wpos valid
if ( ! wpos . isValid ( ) )
return 0 ;
sint32 const z = ( getHeight ( wpos ) * 2000 - 1000 ) & ( ~ 3 ) ;
uint const top = getTopology ( wpos ) ;
if ( top < _TopologiesNodes . size ( ) & & _TopologiesNodes [ top ] . isInInterior ( ) )
return z + 2 ;
return z ;
}
inline
CTopology & CRootCell : : getTopologyNode ( uint topology )
{
if ( topology > = _TopologiesNodes . size ( ) )
_TopologiesNodes . resize ( topology + 1 ) ;
return _TopologiesNodes [ topology ] ;
}
inline
CTopology const & CRootCell : : getCstTopologyNode ( uint topology ) const
{
# if !FINAL_VERSION
nlassert ( topology < _TopologiesNodes . size ( ) ) ;
# endif
return _TopologiesNodes [ topology ] ;
}
inline
CTopology : : TTopologyId CRootCell : : getTopologyId ( CWorldPosition const & wpos ) const
{
return CTopology : : TTopologyId ( wpos , getTopology ( wpos ) ) ;
}
inline
CTopology : : TTopologyRef CRootCell : : getTopologyRef ( const CWorldPosition & pos ) const
{
# ifdef NL_DEBUG
nlassert ( pos . getRootCell ( ) ! = this ) ;
# endif
return CTopology : : TTopologyRef ( pos ) ;
}
inline
CTopology const & CRootCell : : getCstTopologyNode ( CTopology : : TTopologyId const & id ) const
{
return getCstTopologyNode ( id . getTopologyIndex ( ) ) ;
}
inline
CDirectionMap const * CRootCell : : getDirectionMap ( uint topology ) const
{
return ( topology < _TopologiesNodes . size ( ) ) ? getCstTopologyNode ( topology ) . DirectionMap : NULL ;
}
inline
void CRootCell : : setDirectionMap ( CDirectionMap * map , uint topology )
{
getTopologyNode ( topology ) . DirectionMap = map ;
}
inline
void CRootCell : : updateTopologyRef ( CWorldMap * worldMap )
{
std : : vector < CTopology > : : iterator it = _TopologiesNodes . begin ( ) , itEnd = _TopologiesNodes . end ( ) ;
while ( it ! = itEnd )
{
( * it ) . updateTopologyRef ( worldMap ) ;
+ + it ;
}
}
inline
CWorldPosition const & CRootCell : : getWorldPosition ( uint ind ) const
{
# ifdef NL_DEBUG
nlassert ( ind < 4 ) ;
# endif
return _WorldPosition [ ind ] ;
}
inline
void CRootCell : : setWorldPosition ( CWorldPosition const & pos , uint ind )
{
# ifdef NL_DEBUG
nlassert ( ind < 4 ) ;
# endif
_WorldPosition [ ind ] = pos ;
}
//////////////////////////////////////////////////////////////////////////////
/**
* A computed 16 x16 cell
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CComputeCell
: public CRootCell
{
public :
CComputeCell ( CWorldMap const & worldMapPtr ) ;
CCellLinkage getCellLink ( CWorldPosition const & wpos ) const ;
uint32 nbUsedSlots ( CMapPosition const & pos ) const ;
sint32 maxUsedSlot ( CMapPosition const & pos ) const ;
bool isSlotUsed ( CMapPosition const & pos , CSlot const & slot ) const ;
uint getTopology ( CWorldPosition const & wpos ) const ;
sint getHeight ( CWorldPosition const & wpos ) const ;
TCellUnit const & getCellUnitCst ( CMapPosition const & pos ) const ;
CUnitSlot const & getUnitSlotCst ( CWorldPosition const & wpos ) const ;
TCellUnit & getCellUnit ( CMapPosition const & pos ) ;
CUnitSlot & getUnitSlot ( CWorldPosition const & wpos ) ;
void serial ( NLMISC : : IStream & f ) ;
void clearHeightMap ( ) { }
private :
TCellUnit const & getCellUnitCst ( CWorldPosition const & wpos ) const ;
// a cell is a grid of 16x16 units
TCellUnit _Grid [ 16 * 16 ] ;
} ;
inline
CComputeCell : : CComputeCell ( CWorldMap const & worldMapPtr )
: CRootCell ( worldMapPtr )
{
}
inline
CCellLinkage CComputeCell : : getCellLink ( CWorldPosition const & wpos ) const
{
return getUnitSlotCst ( wpos ) . getCellLink ( ) ;
}
inline
uint32 CComputeCell : : nbUsedSlots ( CMapPosition const & pos ) const
{
TCellUnit const & cellUnit = getCellUnitCst ( pos ) ;
uint32 count = 0 ;
for ( uint slot = 0 ; slot < 3 ; + + slot )
if ( cellUnit [ slot ] . getCellLink ( ) . used ( ) )
+ + count ;
return count ;
}
inline
sint32 CComputeCell : : maxUsedSlot ( CMapPosition const & pos ) const
{
TCellUnit const & cellUnit = getCellUnitCst ( pos ) ;
sint32 maxs = - 1 ;
for ( uint slot = 0 ; slot < 3 ; + + slot )
if ( cellUnit [ slot ] . getCellLink ( ) . used ( ) )
maxs = slot ;
return maxs ;
}
inline
bool CComputeCell : : isSlotUsed ( CMapPosition const & pos , CSlot const & slot ) const
{
TCellUnit const & cellUnit = getCellUnitCst ( pos ) ;
return slot . isValid ( ) ? cellUnit [ slot . slot ( ) ] . getCellLink ( ) . used ( ) : false ;
}
inline
uint CComputeCell : : getTopology ( CWorldPosition const & wpos ) const
{
return getUnitSlotCst ( wpos ) . topology ( ) ;
}
inline
sint CComputeCell : : getHeight ( CWorldPosition const & wpos ) const
{
return getUnitSlotCst ( wpos ) . height ( ) ;
}
inline
TCellUnit const & CComputeCell : : getCellUnitCst ( CMapPosition const & pos ) const
{
return _Grid [ pos . cellUnitFastIndex ( ) ] ;
}
inline
CUnitSlot const & CComputeCell : : getUnitSlotCst ( CWorldPosition const & wpos ) const
{
# ifdef NL_DEBUG
nlassert ( wpos . isValid ( ) ) ;
# endif
return getCellUnitCst ( wpos ) [ wpos . slot ( ) ] ;
}
inline
TCellUnit & CComputeCell : : getCellUnit ( CMapPosition const & pos )
{
return _Grid [ pos . cellUnitFastIndex ( ) ] ;
}
inline
CUnitSlot & CComputeCell : : getUnitSlot ( CWorldPosition const & wpos )
{
# ifdef NL_DEBUG
nlassert ( wpos . isValid ( ) ) ;
# endif
return getCellUnit ( wpos ) [ wpos . slot ( ) ] ;
}
inline
TCellUnit const & CComputeCell : : getCellUnitCst ( CWorldPosition const & wpos ) const
{
return _Grid [ wpos . cellUnitFastIndex ( ) ] ;
}
//////////////////////////////////////////////////////////////////////////////
/**
* A Single layer 16 x16 cell that has not walk constraint ( map is completely white )
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CWhiteCell
: public CRootCell
{
public :
CWhiteCell ( CWorldMap const & worldMapPtr ) ;
CCellLinkage getCellLink ( CWorldPosition const & wpos ) const ;
uint32 nbUsedSlots ( CMapPosition const & pos ) const ;
sint32 maxUsedSlot ( CMapPosition const & pos ) const ;
bool isSlotUsed ( CMapPosition const & pos , CSlot const & slot ) const ;
uint getTopology ( CWorldPosition const & wpos ) const ;
sint getHeight ( CWorldPosition const & wpos ) const ;
void serial ( NLMISC : : IStream & f ) ;
void clearHeightMap ( ) ;
void setHeightMap ( I16x16Layer * heightMap ) ;
private :
I16x16Layer * _HeightMap ;
} ;
inline
CWhiteCell : : CWhiteCell ( CWorldMap const & worldMapPtr )
: CRootCell ( worldMapPtr ) , _HeightMap ( NULL )
{
}
inline
CCellLinkage CWhiteCell : : getCellLink ( CWorldPosition const & wpos ) const
{
return CCellLinkage ( 0 ) ;
}
inline
uint32 CWhiteCell : : nbUsedSlots ( CMapPosition const & pos ) const
{
return 1 ;
}
inline
sint32 CWhiteCell : : maxUsedSlot ( CMapPosition const & pos ) const
{
return 0 ;
}
inline
bool CWhiteCell : : isSlotUsed ( CMapPosition const & pos , CSlot const & slot ) const
{
return slot . slot ( ) = = 0 ;
}
inline
uint CWhiteCell : : getTopology ( CWorldPosition const & wpos ) const
{
return 0 ;
}
inline
sint CWhiteCell : : getHeight ( CWorldPosition const & wpos ) const
{
return ( _HeightMap ! = NULL ) ? _HeightMap - > get ( wpos . yCoord ( ) . getUnitId ( ) , wpos . xCoord ( ) . getUnitId ( ) ) : 0 ;
}
inline
void CWhiteCell : : serial ( NLMISC : : IStream & f )
{
f . serialCheck ( ( uint16 ) ' WC ' ) ;
if ( f . isReading ( ) )
_HeightMap = I16x16Layer : : load ( f ) ;
else
I16x16Layer : : save ( f , _HeightMap ) ;
}
inline
void CWhiteCell : : clearHeightMap ( )
{
if ( _HeightMap )
delete _HeightMap ;
_HeightMap = NULL ;
}
inline
void CWhiteCell : : setHeightMap ( I16x16Layer * heightMap )
{
_HeightMap = heightMap ;
}
//////////////////////////////////////////////////////////////////////////////
/**
* A Single layer 16 x16 cell
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CSingleLayerCell
: public CRootCell
{
protected :
bool testPos ( uint i , uint j ) const { return ( _Map [ i ] & _MaskMap [ j ] ) ! = 0 ; }
void setPos ( uint i , uint j , bool p ) { _Map [ i ] = ( p ? ( _Map [ i ] | _MaskMap [ j ] ) : ( _Map [ i ] & ( ~ _MaskMap [ j ] ) ) ) ; }
public :
CSingleLayerCell ( CWorldMap const & worldMapPtr ) ;
CCellLinkage getCellLink ( CWorldPosition const & wpos ) const ;
uint32 nbUsedSlots ( CMapPosition const & pos ) const ;
sint32 maxUsedSlot ( CMapPosition const & pos ) const ;
bool isSlotUsed ( CMapPosition const & pos , CSlot const & slot ) const ;
uint getTopology ( CWorldPosition const & wpos ) const ;
sint getHeight ( CWorldPosition const & wpos ) const ;
bool testPos ( CMapPosition const & pos ) const ;
void setPos ( CMapPosition const & pos , bool p ) ;
void setSLink ( uint i , bool p ) { _SLinks = p ? ( _SLinks | _MaskMap [ i ] ) : ( _SLinks & ( ~ _MaskMap [ i ] ) ) ; }
void setNLink ( uint i , bool p ) { _NLinks = p ? ( _NLinks | _MaskMap [ i ] ) : ( _NLinks & ( ~ _MaskMap [ i ] ) ) ; }
void setELink ( uint i , bool p ) { _ELinks = p ? ( _ELinks | _MaskMap [ i ] ) : ( _ELinks & ( ~ _MaskMap [ i ] ) ) ; }
void setWLink ( uint i , bool p ) { _WLinks = p ? ( _WLinks | _MaskMap [ i ] ) : ( _WLinks & ( ~ _MaskMap [ i ] ) ) ; }
void setTopologies ( I16x16Layer * topology ) ;
void setHeightMap ( I16x16Layer * heightMap ) ;
virtual void serial ( NLMISC : : IStream & f ) ;
void clearHeightMap ( ) ;
private :
/// The map of accessible positions
uint16 _Map [ 16 ] ;
/// The north links, true if north position is accessible
uint16 _SLinks ;
uint16 _NLinks ;
uint16 _ELinks ;
uint16 _WLinks ;
// topology layer
I16x16Layer * _Topologies ;
// height map
I16x16Layer * _HeightMap ;
static uint16 _MaskMap [ 16 ] ;
static bool _Initialized ;
} ;
inline
CSingleLayerCell : : CSingleLayerCell ( CWorldMap const & worldMapPtr )
: CRootCell ( worldMapPtr )
{
for ( uint i = 0 ; i < 16 ; + + i )
_Map [ i ] = 0 ;
_SLinks = 0 ;
_NLinks = 0 ;
_ELinks = 0 ;
_WLinks = 0 ;
_Topologies = NULL ;
_HeightMap = NULL ;
if ( ! _Initialized )
{
for ( uint i = 0 ; i < 16 ; + + i )
_MaskMap [ i ] = ( 1 < < ( 15 - i ) ) ;
_Initialized = true ;
}
}
inline
CCellLinkage CSingleLayerCell : : getCellLink ( CWorldPosition const & wpos ) const
{
uint xi = wpos . xCoord ( ) . getUnitId ( ) ;
uint yi = wpos . yCoord ( ) . getUnitId ( ) ;
CCellLinkage l ( 0 ) ;
l | = ( ( xi > 0 & & testPos ( yi , xi - 1 ) ) | | ( xi = = 0 & & ( _WLinks & _MaskMap [ yi ] ) ) ) ? 0 : CCellLinkage : : WestSlotMask ;
l | = ( ( xi < 15 & & testPos ( yi , xi + 1 ) ) | | ( xi = = 15 & & ( _ELinks & _MaskMap [ yi ] ) ) ) ? 0 : CCellLinkage : : EastSlotMask ;
l | = ( ( yi > 0 & & testPos ( yi - 1 , xi ) ) | | ( yi = = 0 & & ( _SLinks & _MaskMap [ xi ] ) ) ) ? 0 : CCellLinkage : : SouthSlotMask ;
l | = ( ( yi < 15 & & testPos ( yi + 1 , xi ) ) | | ( yi = = 15 & & ( _NLinks & _MaskMap [ xi ] ) ) ) ? 0 : CCellLinkage : : NorthSlotMask ;
return l ;
}
inline
uint32 CSingleLayerCell : : nbUsedSlots ( CMapPosition const & pos ) const
{
return testPos ( pos ) ? 1 : 0 ;
}
inline
sint32 CSingleLayerCell : : maxUsedSlot ( CMapPosition const & pos ) const
{
return testPos ( pos ) ? 0 : - 1 ;
}
inline
bool CSingleLayerCell : : isSlotUsed ( CMapPosition const & pos , CSlot const & slot ) const
{
return slot . slot ( ) = = 0 & & testPos ( pos ) ;
}
inline
uint CSingleLayerCell : : getTopology ( CWorldPosition const & wpos ) const
{
return ( _Topologies ! = NULL ) ? _Topologies - > get ( wpos . yCoord ( ) . getUnitId ( ) , wpos . xCoord ( ) . getUnitId ( ) ) : 0 ;
}
inline
sint CSingleLayerCell : : getHeight ( CWorldPosition const & wpos ) const
{
return ( _HeightMap ! = NULL ) ? _HeightMap - > get ( wpos . yCoord ( ) . getUnitId ( ) , wpos . xCoord ( ) . getUnitId ( ) ) : 0 ;
}
inline
bool CSingleLayerCell : : testPos ( CMapPosition const & pos ) const
{
return testPos ( pos . yCoord ( ) . getUnitId ( ) , pos . xCoord ( ) . getUnitId ( ) ) ;
}
inline
void CSingleLayerCell : : setPos ( CMapPosition const & pos , bool p )
{
setPos ( pos . yCoord ( ) . getUnitId ( ) , pos . xCoord ( ) . getUnitId ( ) , p ) ;
}
inline
void CSingleLayerCell : : setTopologies ( I16x16Layer * topology )
{
delete _Topologies ;
_Topologies = topology ;
}
inline
void CSingleLayerCell : : setHeightMap ( I16x16Layer * heightMap )
{
if ( _HeightMap )
delete _HeightMap ;
_HeightMap = heightMap ;
}
inline
void CSingleLayerCell : : clearHeightMap ( )
{
delete _HeightMap ;
_HeightMap = NULL ;
}
//////////////////////////////////////////////////////////////////////////////
/**
* A Multiple layer 16 x16 cell ( maximum 3 layers )
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CMultiLayerCell
: public CRootCell
{
protected :
class CCellLayer
{
friend class CMultiLayerCell ; // for build features.
public :
CCellLinkage const & getCellLinkage ( CMapPosition const & pos ) const ;
uint8 getTopology ( CMapPosition const & pos ) const ;
I16x16Layer * getHeightMap ( ) { return _HeightMap ; }
private :
CCellLinkage & cellLinkage ( CMapPosition const & pos ) ;
private :
CCellLinkage _Layer [ 16 * 16 ] ;
uint8 _Topology [ 16 * 16 ] ;
I16x16Layer * _HeightMap ;
} ;
public :
CMultiLayerCell ( CWorldMap const & worldMapPtr ) ;
virtual ~ CMultiLayerCell ( ) ;
CCellLinkage getCellLink ( CWorldPosition const & wpos ) const ;
uint32 nbUsedSlots ( CMapPosition const & pos ) const ;
sint32 maxUsedSlot ( CMapPosition const & pos ) const ;
bool isSlotUsed ( CMapPosition const & pos , CSlot const & slot ) const ;
uint getTopology ( CWorldPosition const & wpos ) const ;
sint getHeight ( CWorldPosition const & wpos ) const ;
virtual void serial ( NLMISC : : IStream & f ) ;
void setLinks ( CWorldPosition const & wpos , CCellLinkage links ) ;
void setTopology ( CWorldPosition const & wpos , uint topology ) ;
void setHeightMap ( CSlot const & slot , I16x16Layer * heightMap ) ;
void clearHeightMap ( ) ;
private :
// each layer is allocated in memory
// the 3 layers available
CCellLayer * _Layers [ 3 ] ;
} ;
inline
CCellLinkage const & CMultiLayerCell : : CCellLayer : : getCellLinkage ( CMapPosition const & pos ) const
{
return _Layer [ pos . cellUnitFastIndex ( ) ] ; //yCoord().getUnitId()][pos.xCoord().getUnitId()];
}
inline
uint8 CMultiLayerCell : : CCellLayer : : getTopology ( CMapPosition const & pos ) const
{
return _Topology [ pos . cellUnitFastIndex ( ) ] ; //yCoord().getUnitId()][pos.xCoord().getUnitId()];
}
inline
CCellLinkage & CMultiLayerCell : : CCellLayer : : cellLinkage ( CMapPosition const & pos )
{
return _Layer [ pos . cellUnitFastIndex ( ) ] ; //yCoord().getUnitId()][pos.xCoord().getUnitId()];
}
inline
CMultiLayerCell : : CMultiLayerCell ( CWorldMap const & worldMapPtr )
: CRootCell ( worldMapPtr )
{
_Layers [ 0 ] = NULL ;
_Layers [ 1 ] = NULL ;
_Layers [ 2 ] = NULL ;
}
inline
CMultiLayerCell : : ~ CMultiLayerCell ( )
{
delete [ ] _Layers [ 0 ] ;
delete [ ] _Layers [ 1 ] ;
delete [ ] _Layers [ 2 ] ;
}
inline
CCellLinkage CMultiLayerCell : : getCellLink ( CWorldPosition const & wpos ) const
{
# ifdef NL_DEBUG
nlassert ( wpos . isValid ( ) ) ;
# endif
CCellLayer * cellLayerPt = _Layers [ wpos . slot ( ) ] ;
return ( ! cellLayerPt ) ? CCellLinkage ( ) : cellLayerPt - > getCellLinkage ( wpos ) ;
}
inline
uint32 CMultiLayerCell : : nbUsedSlots ( CMapPosition const & pos ) const
{
uint32 ns = 0 ;
for ( uint32 slot = 0 ; slot < 3 ; + + slot )
{
CCellLayer * cellLayerPt = _Layers [ slot ] ;
if ( cellLayerPt & & cellLayerPt - > cellLinkage ( pos ) . used ( ) )
+ + ns ;
}
return ns ;
}
inline
sint32 CMultiLayerCell : : maxUsedSlot ( CMapPosition const & pos ) const
{
sint32 maxs = - 1 ;
for ( uint32 slot = 0 ; slot < 3 ; + + slot )
{
CCellLayer * cellLayerPt = _Layers [ slot ] ;
if ( cellLayerPt & & cellLayerPt - > cellLinkage ( pos ) . used ( ) )
maxs = slot ;
}
return maxs ;
}
inline
bool CMultiLayerCell : : isSlotUsed ( CMapPosition const & pos , CSlot const & slot ) const
{
if ( ! slot . isValid ( ) )
return false ;
CCellLayer * cellLayerPt = _Layers [ slot . slot ( ) ] ;
return ( cellLayerPt & & cellLayerPt - > cellLinkage ( pos ) . used ( ) ) ;
}
inline
uint CMultiLayerCell : : getTopology ( CWorldPosition const & wpos ) const
{
# ifdef NL_DEBUG
nlassert ( wpos . isValid ( ) ) ;
# endif
CCellLayer * cellLayerPt = _Layers [ wpos . slot ( ) ] ;
return ( ! cellLayerPt ) ? 0 : cellLayerPt - > getTopology ( wpos ) ;
}
inline
sint CMultiLayerCell : : getHeight ( CWorldPosition const & wpos ) const
{
# ifdef NL_DEBUG
nlassert ( wpos . isValid ( ) ) ;
# endif
CCellLayer * cellLayerPt = _Layers [ wpos . slot ( ) ] ;
return ( ! cellLayerPt | | ! cellLayerPt - > getHeightMap ( ) ) ? 0 : cellLayerPt - > getHeightMap ( ) - > get ( wpos . yCoord ( ) . getUnitId ( ) , wpos . xCoord ( ) . getUnitId ( ) ) ;
}
inline
void CMultiLayerCell : : setLinks ( CWorldPosition const & wpos , CCellLinkage links )
{
# ifdef NL_DEBUG
nlassert ( wpos . isValid ( ) ) ;
# endif
CCellLayer * cellLayerPt = _Layers [ wpos . slot ( ) ] ;
if ( ! cellLayerPt )
{
cellLayerPt = new CCellLayer ( ) ;
_Layers [ wpos . slot ( ) ] = cellLayerPt ;
for ( uint i = 0 ; i < 16 * 16 ; + + i )
cellLayerPt - > _Topology [ i ] = 0 ;
cellLayerPt - > _HeightMap = NULL ;
}
# ifdef NL_DEBUG
nlassert ( cellLayerPt ) ;
# endif
cellLayerPt - > cellLinkage ( wpos ) = links ;
}
inline
void CMultiLayerCell : : setTopology ( CWorldPosition const & wpos , uint topology )
{
# ifdef NL_DEBUG
nlassert ( topology < 256 ) ;
nlassert ( wpos . isValid ( ) ) ;
# endif
CCellLayer * cellLayerPt = _Layers [ wpos . slot ( ) ] ;
# ifdef NL_DEBUG
nlassert ( cellLayerPt ) ;
# endif
cellLayerPt - > _Topology [ wpos . cellUnitFastIndex ( ) ] = ( uint8 ) topology ;
}
inline
void CMultiLayerCell : : setHeightMap ( CSlot const & slot , I16x16Layer * heightMap )
{
# ifdef NL_DEBUG
nlassert ( slot . isValid ( ) ) ;
# endif
CCellLayer * cellLayerPt = _Layers [ slot . slot ( ) ] ;
# ifdef NL_DEBUG
nlassert ( cellLayerPt ) ;
# endif
if ( cellLayerPt - > _HeightMap )
delete cellLayerPt - > _HeightMap ;
cellLayerPt - > _HeightMap = heightMap ;
}
inline
void CMultiLayerCell : : clearHeightMap ( )
{
for ( CSlot i ( 0 ) ; i . isValid ( ) ; + + i )
{
CCellLayer * cellLayerPt = _Layers [ i . slot ( ) ] ;
if ( cellLayerPt )
{
delete cellLayerPt - > _HeightMap ;
cellLayerPt - > _HeightMap = NULL ;
}
}
}
//////////////////////////////////////////////////////////////////////////////
/**
* A CSuperCell of basically 16 x16 CCells
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CSuperCell
{
public :
CSuperCell ( CWorldMap const & worldMap ) ;
virtual ~ CSuperCell ( ) ;
// get a const cell (might be NULL)
CRootCell const * getRootCellCst ( CMapPosition const & pos ) const ;
// get a const cell (might be NULL)
CRootCell * getRootCell ( CMapPosition const & pos ) ;
void updateTopologyRef ( CWorldMap * worldMap ) ;
void countCells ( uint & compute , uint & white , uint & simple , uint & multi , uint & other ) const ;
// set a cell
void setRootCell ( CMapPosition const & pos , CRootCell * cell ) ;
//
// compute cell selectors
//
// get a cell
CComputeCell * getComputeCell ( CMapPosition const & pos ) ;
// get a const cell
CComputeCell const * getComputeCell ( CMapPosition const & pos ) const ;
// get a slot in a cell
CUnitSlot getUnitSlot ( CWorldPosition const & wpos ) const ;
// get a slot in super cell
CUnitSlot & getUnitSlot ( CWorldPosition const & wpos ) ;
TCellUnit & getCellUnit ( CMapPosition const & pos ) ;
void serial ( NLMISC : : IStream & f ) ;
void markRootCell ( uint32 const flag ) const ;
private :
// a super cell is composed of 16x16 pointers to cells, initially NULL
CRootCell * _Grid [ 16 * 16 ] ;
CWorldMap const & _WorldMap ;
} ;
inline
CSuperCell : : CSuperCell ( CWorldMap const & worldMap )
: _WorldMap ( worldMap )
{
for ( uint i = 0 ; i < 16 * 16 ; i + + )
_Grid [ i ] = NULL ;
}
inline
CSuperCell : : ~ CSuperCell ( )
{
for ( uint i = 0 ; i < 16 * 16 ; i + + )
if ( _Grid [ i ] )
delete _Grid [ i ] ;
}
inline
CRootCell const * CSuperCell : : getRootCellCst ( CMapPosition const & pos ) const
{
return _Grid [ pos . rootCellFastIndex ( ) ] ;
}
inline
CRootCell * CSuperCell : : getRootCell ( CMapPosition const & pos )
{
return _Grid [ pos . rootCellFastIndex ( ) ] ;
}
inline
void CSuperCell : : setRootCell ( CMapPosition const & pos , CRootCell * cell )
{
CRootCell * & rootCell = _Grid [ pos . rootCellFastIndex ( ) ] ;
if ( rootCell = = cell )
return ;
delete rootCell ;
rootCell = cell ;
}
inline
CComputeCell * CSuperCell : : getComputeCell ( CMapPosition const & pos )
{
CRootCell * & rootCell = _Grid [ pos . rootCellFastIndex ( ) ] ;
if ( ! rootCell )
rootCell = new CComputeCell ( _WorldMap ) ;
# ifdef NL_DEBUG
nlassert ( rootCell ) ;
nlassert ( dynamic_cast < CComputeCell * > ( rootCell ) ) ;
# endif
return static_cast < CComputeCell * > ( rootCell ) ;
}
inline
CComputeCell const * CSuperCell : : getComputeCell ( CMapPosition const & pos ) const
{
CRootCell const * const & rootCell = _Grid [ pos . rootCellFastIndex ( ) ] ;
if ( ! rootCell )
return NULL ;
# ifdef NL_DEBUG
nlassert ( dynamic_cast < CComputeCell const * > ( rootCell ) ) ;
# endif
return static_cast < CComputeCell const * > ( rootCell ) ;
}
inline
CUnitSlot CSuperCell : : getUnitSlot ( CWorldPosition const & wpos ) const
{
CComputeCell const * cell = getComputeCell ( wpos ) ;
return ! cell ? CUnitSlot ( ) : cell - > getUnitSlotCst ( wpos ) ;
}
inline
CUnitSlot & CSuperCell : : getUnitSlot ( CWorldPosition const & wpos )
{
CComputeCell * cell = getComputeCell ( wpos ) ;
return cell - > getUnitSlot ( wpos ) ;
}
inline
TCellUnit & CSuperCell : : getCellUnit ( CMapPosition const & pos )
{
CComputeCell * cell = getComputeCell ( pos ) ;
return cell - > getCellUnit ( pos ) ;
}
inline
void CSuperCell : : markRootCell ( uint32 const flag ) const
{
for ( uint32 i = 0 ; i < 256 ; + + i )
{
if ( _Grid [ i ] )
_Grid [ i ] - > setFlag ( flag ) ;
}
}
//////////////////////////////////////////////////////////////////////////////
/**
* The A * Path structure , computed by the WorldMap
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CAStarPath
{
friend class CWorldMap ;
public :
std : : vector < CTopology : : TTopologyRef > const & topologiesPath ( ) const { return _TopologiesPath ; }
std : : vector < CTopology : : TTopologyRef > & topologiesPathForCalc ( ) { return _TopologiesPath ; }
CWorldPosition const & getStartPos ( ) const { return _Start ; }
void setStartPos ( CWorldPosition const & pos ) { _Start = pos ; }
CWorldPosition const & getEndPos ( ) const { return _End ; }
void setEndPos ( CWorldPosition const & pos ) { _End = pos ; }
private :
std : : vector < CTopology : : TTopologyRef > _TopologiesPath ;
CWorldPosition _Start ;
CWorldPosition _End ;
} ;
//////////////////////////////////////////////////////////////////////////////
/**
* The Inside A * Path structure , computed by the WorldMap
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CInsideAStarPath
{
friend class CWorldMap ;
public :
CWorldPosition const & getStartPos ( ) const { return _Start ; }
void setStartPos ( CWorldPosition const & pos ) { _Start = pos ; }
CWorldPosition const & getEndPos ( ) const { return _End ; }
void setEndPos ( CWorldPosition const & pos ) { _End = pos ; }
std : : vector < CDirection > & getStepPathForCalc ( ) { return _StepPath ; }
private :
CWorldPosition _Start ;
CWorldPosition _End ;
std : : vector < CDirection > _StepPath ;
} ;
//////////////////////////////////////////////////////////////////////////////
/**
* A template Heap implementation
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
template < typename T , typename V >
class CHeap
{
public :
typedef std : : pair < T , V > THeapNode ;
public :
CHeap ( ) ;
/// clear Heap
void clear ( ) { _Heap . resize ( 1 ) ; }
/// test heap is empty or not
bool empty ( ) const { return _Heap . size ( ) < = 1 ; }
/// push a value in heap and sort it
void push ( T key , V const & value ) ;
/// pop the minimal value of the heap
V pop ( ) ;
void backwardLeveling ( uint index ) ;
void forwardLeveling ( uint index ) ;
/// auto check of the internal heap state
void check ( ) ;
uint32 size ( ) { return _Heap . size ( ) ; }
std : : vector < THeapNode > & heapAsVector ( ) { return _Heap ; }
private :
std : : vector < THeapNode > _Heap ;
} ;
template < typename T , typename V >
CHeap < T , V > : : CHeap ( )
{
// node 0 unused (daniel's trick)
clear ( ) ;
}
template < typename T , typename V >
void CHeap < T , V > : : push ( T key , V const & value )
{
_Heap . push_back ( THeapNode ( key , value ) ) ;
backwardLeveling ( ( uint ) _Heap . size ( ) - 1 ) ;
}
template < typename T , typename V >
V CHeap < T , V > : : pop ( )
{
# ifdef NL_DEBUG
nlassert ( _Heap . size ( ) > 1 ) ;
# endif
// return best value
V ret = _Heap [ 1 ] . second ;
// if only 1 node in heap, pop it and leave
if ( _Heap . size ( ) = = 2 )
{
_Heap . pop_back ( ) ;
return ret ;
}
// for more than 1 object, copy last at top and pop last
_Heap [ 1 ] = _Heap . back ( ) ;
_Heap . pop_back ( ) ;
forwardLeveling ( 1 ) ;
return ret ;
}
template < typename T , typename V >
void CHeap < T , V > : : backwardLeveling ( uint index )
{
while ( index ! = 1 & & _Heap [ index ] . first < _Heap [ index / 2 ] . first )
{
swap ( _Heap [ index ] , _Heap [ index / 2 ] ) ;
index / = 2 ;
}
}
template < typename T , typename V >
void CHeap < T , V > : : forwardLeveling ( uint index )
{
while ( true )
{
uint min_index = 2 * index ;
// if object has no child, leave
if ( min_index > _Heap . size ( ) - 1 )
break ;
// choose left or right child
if ( min_index + 1 < = _Heap . size ( ) - 1 & & _Heap [ min_index ] . first > _Heap [ min_index + 1 ] . first )
+ + min_index ;
// if swap needed, swap and step one more, else leave
if ( _Heap [ index ] . first > _Heap [ min_index ] . first )
{
swap ( _Heap [ index ] , _Heap [ min_index ] ) ;
index = min_index ;
}
else
{
break ;
}
}
}
template < typename T , typename V >
void CHeap < T , V > : : check ( )
{
for ( uint index = 1 ; index < = _Heap . size ( ) - 1 ; + + index )
{
if ( 2 * index < = _Heap . size ( ) - 1 )
nlassert ( _Heap [ index ] . first < = _Heap [ 2 * index ] . first ) ;
if ( 2 * index + 1 < = _Heap . size ( ) - 1 )
nlassert ( _Heap [ index ] . first < = _Heap [ 2 * index + 1 ] . first ) ;
}
}
//////////////////////////////////////////////////////////////////////////////
/**
* The world mapping
* \ author Benjamin Legros
* \ author Nevrax France
* \ date 2003
*/
class CWorldMap
{
friend class RYPACSCRUNCH : : CPacsCruncher ;
friend class CWorldPosition ;
friend class CTopology : : CNeighbourLink ;
public :
CWorldMap ( ) ;
~ CWorldMap ( ) ;
// serial -- beware, this method merges, use clear() before to load only one world map
void serial ( NLMISC : : IStream & f ) ;
/// \name User Interface, path finding and complex moves
// @{
/// Finds an A* path
bool findAStarPath ( CWorldPosition const & start , CWorldPosition const & end , std : : vector < CTopology : : TTopologyRef > & path , TAStarFlag denyflags = Nothing ) const ;
/// Finds an A* path
bool findAStarPath ( CTopology : : TTopologyId const & start , CTopology : : TTopologyId const & end , CAStarPath & path , TAStarFlag denyflags = Nothing ) const ;
/// Finds an A* inside a topoly
bool findInsideAStarPath ( CWorldPosition const & start , CWorldPosition const & end , std : : vector < CDirection > & stepPath , TAStarFlag denyflags = Nothing ) const ;
/// Moves to given topology, returns false if failed
bool moveTowards ( CWorldPosition & pos , CTopology : : TTopologyRef const & topology ) const ;
/// Moves according a to a given path, returns false if failed
bool move ( CWorldPosition & pos , CAStarPath & path , uint & currentstep ) const ;
/// Moves from a position to another
bool move ( CWorldPosition & pos , CMapPosition const & end , TAStarFlag const denyFlags ) const ;
// @}
bool customCheckDiagMove ( CWorldPosition const & pos , CDirection const & direction , RYAI_MAP_CRUNCH : : TAStarFlag denyFlags ) const ;
// clean
void clear ( ) ;
void setFlagOnPosAndRadius ( CMapPosition const & pos , float radius , uint32 flag ) ;
// to remove.
CNeighbourhood neighbours ( CWorldPosition const & wpos ) const ;
/// Moves in neighbourhood
bool move ( CWorldPosition & pos , CDirection const & direction ) const ;
/// Moves in neighbourhood (corner moves don't avoid collision)
bool moveSecure ( CWorldPosition & pos , CDirection const & direction , uint16 maskFlags = 0xffff ) const ;
/// Moves in neighbourhood with diag test on both sides
bool moveDiagTestBothSide ( CWorldPosition & pos , CDirection const & direction ) const ;
CTopology : : TTopologyId getTopologyId ( CWorldPosition const & wpos ) const ;
// LastRemoved
CTopology const & getTopologyNode ( CTopology : : TTopologyId const & id ) const ;
CTopology & getTopologyNode ( CTopology : : TTopologyId const & id ) ;
CGridDirectionLayer const * getGridDirectionLayer ( CWorldPosition const & pos , CTopology : : TTopologyRef const & topologyRef ) const ;
/// Get CWorldPosition from a CMapPosition and a CSlot
CWorldPosition getWorldPosition ( CMapPosition const & mapPos , CSlot const & slot ) const ;
/**
* Get CWorldPosition from a CMapPosition and a TLevel
* Assumes that 0 is the highest level at the given CMapPosition , and greater the level is , lower the height is .
*/
CWorldPosition getWorldPosition ( CMapPosition const & mapPos , TLevel level ) const ;
// do not initialise a bot with the position & the world position (or u must assume that pos have no fraction).
bool setWorldPosition ( AITYPES : : TVerticalPos verticalPos , CWorldPosition & wpos , CAIVector const & pos , CRootCell const * originCell = NULL ) const ;
// Alternate setWorldPosition(), with real z instead of TVerticalPos, in millimeters
bool setWorldPosition ( sint32 z , CWorldPosition & wpos , CAIVector const & pos , CRootCell const * originCell = NULL ) const ;
// Double version isn't tested !!! Verify it's the same than above sint32 version !
bool setWorldPosition ( double z , CWorldPosition & wpos , CAIVector const & pos , CRootCell const * originCell = NULL ) const ;
CTopology : : TTopologyRef getTopologyRef ( CTopology : : TTopologyId const & id ) const ;
void buildMasterTopo ( bool allowWater , bool allowNogo ) ;
// checks motion layers
void checkMotionLayer ( ) ;
void countSuperTopo ( ) ;
CRootCell const * getRootCellCst ( CMapPosition const & pos ) const ;
CSuperCell const * getSuperCellCst ( CMapPosition const & pos ) const ;
void getBounds ( CMapPosition & min , CMapPosition & max ) ;
CWorldPosition getSafeWorldPosition ( CMapPosition const & mapPos , CSlot const & slot ) const ;
protected :
CWorldPosition getWorldPositionGeneration ( CMapPosition const & mapPos , CSlot const & slot ) const ;
/// Get a world position from a vector position
template < class T >
CWorldPosition getWorldPosition ( T const & pos ) const
{
CSlot slot ;
CMapPosition const mapPos ( pos ) ;
CRootCell const * cell = getRootCellCst ( mapPos ) ;
if ( cell )
{
double bd = 1.0e10 ;
// find best slot
for ( uint32 s = 0 ; s < 3 ; + + s )
{
CSlot const sslot = CSlot ( s ) ;
if ( ! cell - > isSlotUsed ( mapPos , sslot ) )
continue ;
double const sh = cell - > getHeight ( CWorldPosition ( cell , mapPos , sslot ) ) * 2.0 + 1.0 ;
if ( fabs ( sh ) < bd )
{
bd = fabs ( sh ) ;
slot = sslot ;
}
}
}
return CWorldPosition ( cell , mapPos , slot ) ;
}
// only for generation.
CSuperCell * getSuperCell ( CMapPosition const & pos ) ;
CComputeCell * getComputeCell ( CMapPosition const & pos ) ;
CRootCell * getRootCell ( CMapPosition const & pos ) ;
bool exist ( CMapPosition const & pos ) const ;
uint32 nbUsedSlots ( CMapPosition const & pos ) const ;
sint32 maxUsedSlot ( CMapPosition const & pos ) const ;
bool isSlotUsed ( CMapPosition const & pos , CSlot slot ) const ;
// used in build process.
uint getTopology ( CWorldPosition const & wpos ) const ;
void countCells ( uint & compute , uint & white , uint & simple , uint & multi , uint & other ) const ;
// mutators
void setRootCell ( CMapPosition const & pos , CRootCell * cell ) ;
// clear height map
void clearHeightMap ( ) ;
//
// compute cell selectors
//
TCellUnit & getCellUnit ( CMapPosition const & pos ) ;
CUnitSlot & getUnitSlot ( CWorldPosition const & wpos ) ;
CComputeCell const * getComputeCellCst ( CMapPosition const & pos ) const ;
void resetUnitSlotNLink ( CWorldPosition const & wpos ) { getUnitSlot ( wpos ) . cellLink ( ) . setNSlot ( CSlot ( ) ) ; }
void resetUnitSlotSLink ( CWorldPosition const & wpos ) { getUnitSlot ( wpos ) . cellLink ( ) . setSSlot ( CSlot ( ) ) ; }
void resetUnitSlotWLink ( CWorldPosition const & wpos ) { getUnitSlot ( wpos ) . cellLink ( ) . setWSlot ( CSlot ( ) ) ; }
void resetUnitSlotELink ( CWorldPosition const & wpos ) { getUnitSlot ( wpos ) . cellLink ( ) . setESlot ( CSlot ( ) ) ; }
void resetUnitSlot ( CWorldPosition const & wpos ) ;
private :
CSuperCell * _GridFastAccess [ 256 * 256 ] ;
public :
/// \name Path finding related error handling
// @{
enum TFindAStarPathReason
{
FASPR_NO_REASON = - 1 ,
FASPR_NO_ERROR ,
FASPR_INVALID_START_POS ,
FASPR_INVALID_END_POS ,
FASPR_INVALID_START_TOPO ,
FASPR_INVALID_END_TOPO ,
FASPR_INCOMPATIBLE_POSITIONS ,
FASPR_NOT_FOUND
} ;
mutable TFindAStarPathReason _LastFASPReason ;
static std : : string toString ( TFindAStarPathReason reason ) ;
enum TFindInsideAStarPathReason
{
FIASPR_NO_REASON = - 1 ,
FIASPR_NO_ERROR ,
FIASPR_INVALID_START_POS ,
FIASPR_INVALID_END_POS ,
FIASPR_DIFFERENT_TOPO ,
FIASPR_NOT_FOUND
} ;
mutable TFindInsideAStarPathReason _LastFIASPReason ;
static std : : string toString ( TFindInsideAStarPathReason reason ) ;
// @}
} ;
inline
CWorldPosition : : CWorldPosition ( const CRootCell * cell , const CMapPosition & pos , const CSlot & slot ) : CMapPosition ( pos ) , CSlot ( slot ) , _RootCell ( cell )
{
_cellLinkage = _RootCell - > getCellLink ( * this ) ;
}
inline
CWorldPosition : : CWorldPosition ( const CRootCell * cell , const CMapPosition & pos , const CSlot & slot , bool generationOnly ) : CMapPosition ( pos ) , CSlot ( slot ) , _RootCell ( cell )
{
}
inline
CWorldPosition CWorldPosition : : getPosS ( ) const
{
CWorldPosition wp ( * this ) ;
wp . stepS ( ) ;
return wp ;
}
inline
CWorldPosition CWorldPosition : : getPosN ( ) const
{
CWorldPosition wp ( * this ) ;
wp . stepN ( ) ;
return wp ;
}
inline
CWorldPosition CWorldPosition : : getPosE ( ) const
{
CWorldPosition wp ( * this ) ;
wp . stepE ( ) ;
return wp ;
}
inline
CWorldPosition CWorldPosition : : getPosW ( ) const
{
CWorldPosition wp ( * this ) ;
wp . stepW ( ) ;
return wp ;
}
inline
void CWorldPosition : : setPosS ( CWorldPosition & pos ) const
{
pos = * this ;
pos . stepS ( ) ;
}
inline
void CWorldPosition : : setPosN ( CWorldPosition & pos ) const
{
pos = * this ;
pos . stepN ( ) ;
}
inline
void CWorldPosition : : setPosE ( CWorldPosition & pos ) const
{
pos = * this ;
pos . stepE ( ) ;
}
inline
void CWorldPosition : : setPosW ( CWorldPosition & pos ) const
{
pos = * this ;
pos . stepW ( ) ;
}
inline
void CWorldPosition : : stepS ( )
{
# ifdef NL_DEBUG
nlassert ( _RootCell ) ;
# endif
setSlot ( _cellLinkage . SSlot ( ) ) ;
# ifdef NL_DEBUG
nlassert ( CSlot : : isValid ( ) ) ;
# endif
if ( CMapPosition : : stepS ( ) ) // check if we have to recalculate the RootCell ..
{
_RootCell = getRootCell ( ) - > getWorldMapPtr ( ) . getRootCellCst ( * this ) ; // obtain the new _RootCell pointer
}
_cellLinkage = _RootCell - > getCellLink ( * this ) ;
}
inline
void CWorldPosition : : stepN ( )
{
# ifdef NL_DEBUG
nlassert ( _RootCell ) ;
# endif
setSlot ( _cellLinkage . NSlot ( ) ) ;
# ifdef NL_DEBUG
nlassert ( CSlot : : isValid ( ) ) ;
# endif
if ( CMapPosition : : stepN ( ) ) // check if we have to recalculate the RootCell ..
{
_RootCell = getRootCell ( ) - > getWorldMapPtr ( ) . getRootCellCst ( * this ) ; // obtain the new _RootCell pointer
}
_cellLinkage = _RootCell - > getCellLink ( * this ) ;
}
inline
void CWorldPosition : : stepE ( )
{
# ifdef NL_DEBUG
nlassert ( _RootCell ) ;
# endif
setSlot ( _cellLinkage . ESlot ( ) ) ;
# ifdef NL_DEBUG
nlassert ( CSlot : : isValid ( ) ) ;
# endif
if ( CMapPosition : : stepE ( ) ) // check if we have to recalculate the RootCell ..
{
_RootCell = getRootCell ( ) - > getWorldMapPtr ( ) . getRootCellCst ( * this ) ; // obtain the new _RootCell pointer
}
_cellLinkage = _RootCell - > getCellLink ( * this ) ;
}
inline
void CWorldPosition : : stepW ( )
{
# ifdef NL_DEBUG
nlassert ( _RootCell ) ;
# endif
setSlot ( _cellLinkage . WSlot ( ) ) ;
# ifdef NL_DEBUG
nlassert ( CSlot : : isValid ( ) ) ;
# endif
if ( CMapPosition : : stepW ( ) ) // check if we have to recalculate the RootCell ..
{
_RootCell = getRootCell ( ) - > getWorldMapPtr ( ) . getRootCellCst ( * this ) ; // obtain the new _RootCell pointer
}
_cellLinkage = _RootCell - > getCellLink ( * this ) ;
}
inline
bool CWorldPosition : : moveS ( )
{
if ( getCellLinkage ( ) . isSSlotValid ( ) )
{
stepS ( ) ;
return true ;
}
return false ;
}
inline
bool CWorldPosition : : moveN ( )
{
if ( getCellLinkage ( ) . isNSlotValid ( ) )
{
stepN ( ) ;
return true ;
}
return false ;
}
inline
bool CWorldPosition : : moveE ( )
{
if ( getCellLinkage ( ) . isESlotValid ( ) )
{
stepE ( ) ;
return true ;
}
return false ;
}
inline
bool CWorldPosition : : moveW ( )
{
if ( getCellLinkage ( ) . isWSlotValid ( ) )
{
stepW ( ) ;
return true ;
}
return false ;
}
inline
NLMISC : : CVectorD CWorldPosition : : getPosition ( ) const
{
NLMISC : : CVectorD ret = toVectorD ( ) ;
CRootCell const * cell = getRootCell ( ) ;
if ( cell )
ret . z = cell - > getHeight ( * this ) * 2.0 + 1.0 ;
return ret ;
}
inline
sint32 CWorldPosition : : getMetricHeight ( ) const
{
if ( _RootCell )
return _RootCell - > getMetricHeight ( * this ) ;
return 0 ;
}
inline
CTopology const & CTopology : : TTopologyRef : : getCstTopologyNode ( ) const
{
# ifdef NL_DEBUG
nlassert ( _RootCell ) ;
# endif
return _RootCell - > getCstTopologyNode ( getTopologyIndex ( ) ) ;
}
inline
CTopology : : TTopologyRef : : TTopologyRef ( CWorldPosition const & pos , CRootCell const * rootCell )
: TTopologyId ( pos , rootCell - > getTopology ( pos ) )
, _RootCell ( rootCell )
{
# ifdef NL_DEBUG
nlassert ( rootCell ) ;
# endif
// TESTTOREMOVE TODO
# if !FINAL_VERSION
nlassert ( & _RootCell - > getCstTopologyNode ( getTopologyIndex ( ) ) ! = NULL ) ;
# endif
}
inline
CTopology : : TTopologyRef : : TTopologyRef ( CWorldPosition const & pos )
: TTopologyId ( pos , pos . getRootCell ( ) - > getTopology ( pos ) )
, _RootCell ( pos . getRootCell ( ) )
{
// TESTTOREMOVE TODO
# if !FINAL_VERSION
nlassert ( & _RootCell - > getCstTopologyNode ( getTopologyIndex ( ) ) ! = NULL ) ;
# endif
}
inline
void CTopology : : CNeighbourLink : : updateTopologyRef ( CWorldMap * worldMapPtr )
{
_Ref . setRootCell ( worldMapPtr - > getRootCell ( _Ref . getMapPosition ( ) ) ) ;
// TESTTOREMOVE TODO
# if !FINAL_VERSION
nlassert ( & _Ref . getCstTopologyNode ( ) ! = NULL ) ;
# endif
}
inline
CWorldMap : : CWorldMap ( )
{
for ( uint i = 0 ; i < 65536 ; + + i )
_GridFastAccess [ i ] = NULL ;
}
inline
CWorldMap : : ~ CWorldMap ( )
{
for ( uint i = 0 ; i < 65536 ; + + i )
if ( _GridFastAccess [ i ] )
delete _GridFastAccess [ i ] ;
}
inline
CTopology : : TTopologyId CWorldMap : : getTopologyId ( CWorldPosition const & wpos ) const
{
CRootCell const * cell = getRootCellCst ( wpos ) ;
return ! cell ? CTopology : : TTopologyId ( ) : CTopology : : TTopologyId ( wpos , cell - > getTopology ( wpos ) ) ;
}
inline
CTopology const & CWorldMap : : getTopologyNode ( CTopology : : TTopologyId const & id ) const
{
CMapPosition pos = id . getMapPosition ( ) ;
uint topo = id . getTopologyIndex ( ) ;
CRootCell const * cell = getRootCellCst ( pos ) ;
# ifdef NL_DEBUG
nlassert ( cell ) ;
# endif
return cell - > getCstTopologyNode ( topo ) ;
}
inline
CTopology & CWorldMap : : getTopologyNode ( CTopology : : TTopologyId const & id )
{
CMapPosition pos = id . getMapPosition ( ) ;
uint topo = id . getTopologyIndex ( ) ;
CRootCell * cell = getRootCell ( pos ) ;
# ifdef NL_DEBUG
nlassert ( cell ) ;
# endif
return cell - > getTopologyNode ( topo ) ;
}
inline
CGridDirectionLayer const * CWorldMap : : getGridDirectionLayer ( CWorldPosition const & pos , CTopology : : TTopologyRef const & topologyRef ) const
{
if ( ! pos . isValid ( ) )
return NULL ;
CMapPosition tpos = topologyRef . getMapPosition ( ) ;
sint dx = pos . xCoord ( ) . getFullCellId ( ) - tpos . xCoord ( ) . getFullCellId ( ) ;
sint dy = pos . yCoord ( ) . getFullCellId ( ) - tpos . yCoord ( ) . getFullCellId ( ) ;
if ( abs ( dx ) > 1 | | abs ( dy ) > 1 )
return NULL ;
CTopology const & node = topologyRef . getCstTopologyNode ( ) ;
if ( ! node . DirectionMap )
return NULL ;
CDirectionLayer * directionLayer = node . DirectionMap - > Layers [ pos . slot ( ) ] ;
if ( ! directionLayer )
return NULL ;
return directionLayer - > getGridLayer ( dy + 1 , dx + 1 ) ;
}
inline
CWorldPosition CWorldMap : : getWorldPosition ( CMapPosition const & mapPos , CSlot const & slot ) const
{
return CWorldPosition ( getRootCellCst ( mapPos ) , mapPos , slot ) ;
}
inline
CWorldPosition CWorldMap : : getWorldPosition ( CMapPosition const & mapPos , TLevel level ) const
{
CRootCell const * cell = getRootCellCst ( mapPos ) ;
std : : vector < sint32 > slots ;
slots . reserve ( 4 ) ;
// go through all slots and get their height
for ( uint s = 0 ; s < 3 ; + + s )
{
CSlot slot ( s ) ;
if ( ! cell - > isSlotUsed ( mapPos , slot ) )
continue ;
CWorldPosition wPos = CWorldPosition ( cell , mapPos , slot ) ;
slots . push_back ( ( cell - > getHeight ( wPos ) < < 2 ) + s ) ;
}
// sort them, from the lowest to the heightest
std : : sort ( slots . begin ( ) , slots . end ( ) ) ;
// get heightest slot
level = ( RYAI_MAP_CRUNCH : : TLevel ) ( slots . size ( ) - 1 ) - level ;
// if slot exists, return it or invalid position
return ( level < 0 & & level > = ( sint ) slots . size ( ) ) ? CWorldPosition ( ) : CWorldPosition ( cell , mapPos , CSlot ( slots [ level ] & 3 ) ) ;
}
inline
bool CWorldMap : : setWorldPosition ( AITYPES : : TVerticalPos verticalPos , CWorldPosition & wpos , CAIVector const & pos , CRootCell const * originCell ) const
{
CSlot slot ;
CMapPosition const mapPos ( pos ) ;
CRootCell const * cell = originCell ? originCell : getRootCellCst ( mapPos ) ;
if ( ! cell )
{
wpos = CWorldPosition ( cell , mapPos , slot , true ) ;
// addon (not agree but no choice).
return false ;
}
std : : map < double , CSlot > orderedSlots ;
// find best slot
for ( uint32 s = 0 ; s < 3 ; + + s )
{
if ( ! cell - > isSlotUsed ( mapPos , CSlot ( s ) ) )
continue ;
CSlot const sslot = CSlot ( s ) ;
double const sh = cell - > getHeight ( CWorldPosition ( cell , mapPos , sslot ) ) ;
orderedSlots . insert ( std : : make_pair ( sh , sslot ) ) ;
}
if ( ! orderedSlots . empty ( ) )
{
if ( verticalPos = = AITYPES : : vp_auto )
{
double h = orderedSlots . rbegin ( ) - > first ;
slot = orderedSlots . rbegin ( ) - > second ;
}
else if ( verticalPos = = AITYPES : : vp_upper )
{
double h = orderedSlots . rbegin ( ) - > first ;
slot = orderedSlots . rbegin ( ) - > second ;
}
else if ( verticalPos = = AITYPES : : vp_lower )
{
double h = orderedSlots . begin ( ) - > first ;
slot = orderedSlots . begin ( ) - > second ;
}
else if ( verticalPos = = AITYPES : : vp_middle )
{
if ( orderedSlots . size ( ) > 1 )
{
orderedSlots . erase ( orderedSlots . rbegin ( ) - > first ) ;
double h = orderedSlots . rbegin ( ) - > first ;
slot = orderedSlots . rbegin ( ) - > second ;
}
else
{
double h = orderedSlots . begin ( ) - > first ;
slot = orderedSlots . begin ( ) - > second ;
}
}
else
{
nlwarning ( " invalid vertical pos type ! " ) ;
}
}
if ( ! slot . isValid ( ) )
{
wpos = CWorldPosition ( cell , mapPos , slot , true ) ;
return false ;
}
wpos = CWorldPosition ( cell , mapPos , slot ) ;
return true ;
}
inline
CTopology : : TTopologyRef CWorldMap : : getTopologyRef ( CTopology : : TTopologyId const & id ) const
{
return CTopology : : TTopologyRef ( id , const_cast < CRootCell * > ( getRootCellCst ( id . getMapPosition ( ) ) ) ) ;
}
inline
CRootCell const * CWorldMap : : getRootCellCst ( CMapPosition const & pos ) const
{
CSuperCell const * scell = getSuperCellCst ( pos ) ;
return ! scell ? NULL : scell - > getRootCellCst ( pos ) ;
}
inline
CSuperCell const * CWorldMap : : getSuperCellCst ( CMapPosition const & pos ) const
{
return _GridFastAccess [ pos . superCellFastIndex ( ) ] ;
}
inline
CWorldPosition CWorldMap : : getWorldPositionGeneration ( CMapPosition const & mapPos , CSlot const & slot ) const
{
return CWorldPosition ( getRootCellCst ( mapPos ) , mapPos , slot , true ) ; // without assuring cellLink is valid .. :(
}
inline
CWorldPosition CWorldMap : : getSafeWorldPosition ( CMapPosition const & mapPos , CSlot const & slot ) const
{
CRootCell const * cell = getRootCellCst ( mapPos ) ;
return ( cell & & cell - > isSlotUsed ( mapPos , slot ) ) ? CWorldPosition ( getRootCellCst ( mapPos ) , mapPos , slot ) : CWorldPosition ( ) ; // without assuring cellLink is valid .. :(
}
inline
CSuperCell * CWorldMap : : getSuperCell ( CMapPosition const & pos )
{
CSuperCell * superCellPtr = _GridFastAccess [ pos . superCellFastIndex ( ) ] ;
if ( ! superCellPtr )
_GridFastAccess [ pos . superCellFastIndex ( ) ] = superCellPtr = new CSuperCell ( * this ) ;
# ifdef NL_DEBUG
nlassert ( superCellPtr ) ;
# endif
return superCellPtr ;
}
inline
CComputeCell * CWorldMap : : getComputeCell ( CMapPosition const & pos )
{
return getSuperCell ( pos ) - > getComputeCell ( pos ) ;
}
inline
CRootCell * CWorldMap : : getRootCell ( CMapPosition const & pos )
{
CSuperCell * scell = getSuperCell ( pos ) ;
return ! scell ? NULL : scell - > getRootCell ( pos ) ;
}
inline
bool CWorldMap : : exist ( CMapPosition const & pos ) const
{
return getRootCellCst ( pos ) ! = NULL ;
}
inline
uint32 CWorldMap : : nbUsedSlots ( CMapPosition const & pos ) const
{
CRootCell const * cell = getRootCellCst ( pos ) ;
return ! cell ? 0 : cell - > nbUsedSlots ( pos ) ;
}
inline
sint32 CWorldMap : : maxUsedSlot ( CMapPosition const & pos ) const
{
CRootCell const * cell = getRootCellCst ( pos ) ;
return ! cell ? - 1 : cell - > maxUsedSlot ( pos ) ;
}
inline
bool CWorldMap : : isSlotUsed ( CMapPosition const & pos , CSlot slot ) const
{
CRootCell const * cell = getRootCellCst ( pos ) ;
return ! cell ? false : cell - > isSlotUsed ( pos , slot ) ;
}
inline
uint CWorldMap : : getTopology ( CWorldPosition const & wpos ) const
{
CRootCell const * cell = wpos . getRootCell ( ) ; //getRootCellCst(wpos);
return ! cell ? 0 : cell - > getTopology ( wpos ) ;
}
inline
void CWorldMap : : setRootCell ( CMapPosition const & pos , CRootCell * cell )
{
getSuperCell ( pos ) - > setRootCell ( pos , cell ) ;
}
inline
TCellUnit & CWorldMap : : getCellUnit ( CMapPosition const & pos )
{
return getComputeCell ( pos ) - > getCellUnit ( pos ) ;
}
inline
CUnitSlot & CWorldMap : : getUnitSlot ( CWorldPosition const & wpos )
{
return getComputeCell ( wpos ) - > getUnitSlot ( wpos ) ;
}
inline
CComputeCell const * CWorldMap : : getComputeCellCst ( CMapPosition const & pos ) const
{
CSuperCell const * scell = getSuperCellCst ( pos ) ;
return ! scell ? NULL : scell - > getComputeCell ( pos ) ;
}
inline
void CWorldMap : : resetUnitSlot ( CWorldPosition const & wpos )
{
CUnitSlot & us = getUnitSlot ( wpos ) ;
if ( us . getCellLink ( ) . isNSlotValid ( ) ) resetUnitSlotSLink ( wpos . getPosN ( ) ) ;
if ( us . getCellLink ( ) . isSSlotValid ( ) ) resetUnitSlotNLink ( wpos . getPosS ( ) ) ;
if ( us . getCellLink ( ) . isWSlotValid ( ) ) resetUnitSlotELink ( wpos . getPosW ( ) ) ;
if ( us . getCellLink ( ) . isESlotValid ( ) ) resetUnitSlotWLink ( wpos . getPosE ( ) ) ;
us . reset ( ) ;
}
inline
std : : string CWorldMap : : toString ( TFindAStarPathReason reason )
{
switch ( reason )
{
case FASPR_NO_ERROR :
return " FASPR_NO_ERROR " ;
case FASPR_INVALID_START_POS :
return " FASPR_INVALID_START_POS " ;
case FASPR_INVALID_END_POS :
return " FASPR_INVALID_END_POS " ;
case FASPR_INVALID_START_TOPO :
return " FASPR_INVALID_START_TOPO " ;
case FASPR_INVALID_END_TOPO :
return " FASPR_INVALID_END_TOPO " ;
case FASPR_INCOMPATIBLE_POSITIONS :
return " FASPR_INCOMPATIBLE_POSITIONS " ;
case FASPR_NOT_FOUND :
return " FIASPR_NOT_FOUND " ;
default :
return " UnknownReason( " + NLMISC : : toString ( ( int ) reason ) + " ) " ;
}
}
inline
std : : string CWorldMap : : toString ( TFindInsideAStarPathReason reason )
{
switch ( reason )
{
case FIASPR_NO_ERROR :
return " FIASPR_NO_ERROR " ;
case FIASPR_INVALID_START_POS :
return " FIASPR_INVALID_START_POS " ;
case FIASPR_INVALID_END_POS :
return " FIASPR_INVALID_END_POS " ;
case FIASPR_DIFFERENT_TOPO :
return " FIASPR_DIFFERENT_TOPO " ;
case FIASPR_NOT_FOUND :
return " FIASPR_NOT_FOUND " ;
default :
return " UnknownReason( " + NLMISC : : toString ( ( int ) reason ) + " ) " ;
}
}
}
//////////////////////////////////////////////////////////////////////////////
class CTimeEstimator
{
public :
CTimeEstimator ( uint total ) ;
void step ( char const * str ) ;
private :
NLMISC : : TTime _StartTime ;
NLMISC : : TTime _LastTime ;
uint _TotalCounter ;
uint _CurrentCounter ;
uint _LastCounter ;
double _AverageSpeed ;
std : : string secToString ( sint sec ) ;
} ;
inline
CTimeEstimator : : CTimeEstimator ( uint total )
: _TotalCounter ( total )
, _CurrentCounter ( 0 )
, _LastCounter ( 0 )
, _AverageSpeed ( - 1.0 )
{
_StartTime = NLMISC : : CTime : : getLocalTime ( ) ;
_LastTime = _StartTime ;
}
inline
void CTimeEstimator : : step ( char const * str )
{
+ + _CurrentCounter ;
NLMISC : : TTime currentTime = NLMISC : : CTime : : getLocalTime ( ) ;
if ( currentTime - _LastTime > 2000 )
{
NLMISC : : TTime dt = currentTime - _LastTime ;
double speed = 1000.0 * ( _CurrentCounter - _LastCounter ) / dt ;
_AverageSpeed = ( _AverageSpeed < 0.0 ? speed : _AverageSpeed * 0.98 + speed * 0.02 ) ;
uint remaining = _TotalCounter - _CurrentCounter ;
NLMISC : : TTime ellapsedTime = currentTime - _StartTime ;
NLMISC : : TTime remainingTime = ( NLMISC : : TTime ) ( remaining * 1000 / _AverageSpeed ) ;
double percent = 100.0 * _CurrentCounter / _TotalCounter ;
uint maxpercent = ( percent > 100.0 ? 100 : ( uint ) percent ) ;
uint linesize = maxpercent / 5 ;
nlinfo ( " %s: %.1f%% [ellapsed:%s, togo:%s, total:%s] " , str , percent , secToString ( ( uint ) ( ellapsedTime / 1000 ) ) . c_str ( ) , secToString ( ( uint ) ( remainingTime / 1000 ) ) . c_str ( ) , secToString ( ( uint ) ( ( remainingTime + ellapsedTime ) / 1000 ) ) . c_str ( ) ) ;
_LastCounter = _CurrentCounter ;
_LastTime = currentTime ;
}
}
inline
std : : string CTimeEstimator : : secToString ( sint sec )
{
return NLMISC : : toString ( sec / 60 ) + " m " + NLMISC : : toString ( sec % 60 ) + " s " ;
}
# endif