1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #ifndef NL_WORLD_MAP_H
23 #define NL_WORLD_MAP_H
25 #include "nel/misc/types_nl.h"
26 #include "nel/misc/time_nl.h"
27 #include "nel/misc/debug.h"
28 #include "nel/misc/stream.h"
30 #include "nel/pacs/u_global_position.h"
31 #include "nel/misc/vectord.h"
33 #include "16x16_layer.h"
36 #include "ai_vector.h"
41 namespace RYPACSCRUNCH
48 namespace RYAI_MAP_CRUNCH
58 GroundFlags
= WaterAndNogo
61 const std::string
& toString(TAStarFlag flag
);
62 TAStarFlag
toAStarFlag(const std::string
& str
);
64 uint
const WorldMapGridSize
= 256;
65 double const WorldGridResolution
= 1.;
66 NLMISC::CVectorD
const WorldStartOffset
= NLMISC::CVectorD(0., 0., 0.);
71 //////////////////////////////////////////////////////////////////////////////
74 * Slot for the 3 map layer (corresponding to 3 heights of deplacement)
75 * \author Stephane le Dorze
76 * \author Nevrax France
89 explicit CSlot(uint slot
);
91 bool isValid() const { return _Slot
!=INVALID_SLOT
; }
92 void setSlot(CSlot
const& slot
) { _Slot
= slot
._Slot
; }
94 bool operator ==(CSlot
const& slot
) const { return _Slot
==slot
._Slot
; }
95 bool operator !=(CSlot
const& slot
) const { return _Slot
!=slot
._Slot
; }
97 bool operator >(CSlot
const& slot
) const { return _Slot
>slot
._Slot
; }
98 bool operator <(CSlot
const& slot
) const { return _Slot
<slot
._Slot
; }
100 bool operator >=(CSlot
const& slot
) const { return _Slot
>=slot
._Slot
; }
101 bool operator <=(CSlot
const& slot
) const { return _Slot
<=slot
._Slot
; }
103 CSlot
const& operator ++();
105 uint8
slot() const { return _Slot
; }
113 : _Slot(INVALID_SLOT
)
118 CSlot::CSlot(uint slot
)
122 nlassert(slot
>=0 && slot
<=3);
127 CSlot
const& CSlot::operator ++()
131 nlassert(_Slot
<=INVALID_SLOT
);
136 //////////////////////////////////////////////////////////////////////////////
139 * Compressed link set for the 4 cardinal directions
140 * \author Benjamin Legros
141 * \author Nevrax France
145 // pass CCellLinkage parameters by references. (anyway) and remove validation checks. (big update to come).
151 SouthSlotMask
= 0x03,
155 NorthSlotMask
= 0x30,
161 CCellLinkage(uint8 links
= 0xff);
163 CSlot
SSlot() const { return CSlot((_Links
& SouthSlotMask
) >> SouthSlotOffset
); }
164 CSlot
ESlot() const { return CSlot((_Links
& EastSlotMask
) >> EastSlotOffset
); }
165 CSlot
NSlot() const { return CSlot((_Links
& NorthSlotMask
) >> NorthSlotOffset
); }
166 CSlot
WSlot() const { return CSlot((_Links
& WestSlotMask
) >> WestSlotOffset
); }
168 bool isSSlotValid() const { return (_Links
&SouthSlotMask
)!=SouthSlotMask
; }
169 bool isESlotValid() const { return (_Links
&EastSlotMask
)!=EastSlotMask
; }
170 bool isNSlotValid() const { return (_Links
&NorthSlotMask
)!=NorthSlotMask
; }
171 bool isWSlotValid() const { return (_Links
&WestSlotMask
)!=WestSlotMask
; }
173 void setSSlot(CSlot
const& slot
);
174 void setESlot(CSlot
const& slot
);
175 void setNSlot(CSlot
const& slot
);
176 void setWSlot(CSlot
const& slot
);
178 CCellLinkage
& operator |=(uint8 links
);
180 bool used() const { return _Links
!=0xff; }
182 uint8
getLinks() const { return _Links
; }
184 void serial(NLMISC::IStream
&f
);
191 CCellLinkage::CCellLinkage(uint8 links
)
197 void CCellLinkage::setSSlot(CSlot
const& slot
)
199 _Links
= (_Links
& (~SouthSlotMask
)) + (slot
.slot() << SouthSlotOffset
);
203 void CCellLinkage::setESlot(CSlot
const& slot
)
205 _Links
= (_Links
& (~EastSlotMask
)) + (slot
.slot() << EastSlotOffset
);
209 void CCellLinkage::setNSlot(CSlot
const& slot
)
211 _Links
= (_Links
& (~NorthSlotMask
)) + (slot
.slot() << NorthSlotOffset
);
215 void CCellLinkage::setWSlot(CSlot
const& slot
)
217 _Links
= (_Links
& (~WestSlotMask
)) + (slot
.slot() << WestSlotOffset
);
221 CCellLinkage
& CCellLinkage::operator |=(uint8 links
)
228 void CCellLinkage::serial(NLMISC::IStream
&f
)
233 //////////////////////////////////////////////////////////////////////////////
237 friend class CWorldMap
;
241 HALF_TURN_LEFT
= 1, // 45 degres
242 HALF_TURN_RIGHT
= -1, // -45 degres
243 TURN_LEFT
= 2, // 90 degres
244 TURN_RIGHT
= -2, // -90 degres
245 HALF_TURN
= 4 // 180 degres
271 SHIFT_UNDEFINED
= 256 // be aware, if you use a byte, it makes 0.
283 explicit CDirection();
284 CDirection(CDirection
const& dir
);
285 explicit CDirection(TDirection dir
);
287 /// @name user interface assuming the y inversion (sorry).
289 explicit CDirection(int deltax
, int deltay
, bool toCalculate
);
291 // initialisation with a direction depending on deltas (-1,0 or 1)
292 explicit CDirection(int deltax
, int deltay
);
294 // initialisation with a direction depending on deltas (-1,0 or 1)
295 explicit CDirection(CAngle
const& angle
);
301 void dxdy(int& dx
, int& dy
);
304 bool isValid() { return _value
!=UNDEFINED
; }
306 // add a number of 45 turn
307 void addStep(TDeltaDirection step
);
309 NLMISC::CVector2f
getDirFloat() const;
311 TDirection
getVal() const;
313 TMotifDirection
getShift() const;
315 bool operator !=(TDirection dir
) const;
317 bool operator != (CDirection
const& dir
) const;
319 struct CDirectionData
325 static CDirectionData
const directionDatas
[];
326 static TDirection
const table
[];
328 // used in pacs (nothing to do here but i haven't enought time to rewrite much code)
331 static void getDirectionAround(CAngle
const& Angle
, CDirection
& Dir0
, CDirection
& Dir1
);
334 void setDxDy(int deltax
, int deltay
);
340 CDirection::CDirection()
346 CDirection::CDirection(CDirection
const& dir
)
352 CDirection::CDirection(TDirection dir
)
356 nlassert(dir
>=E
&& dir
<=UNDEFINED
);
361 CDirection::CDirection(int deltax
, int deltay
, bool toCalculate
)
364 nlassert(deltax
!=0 || deltay
!=0);
366 uint absDeltax
= abs(deltax
);
367 uint absDeltay
= abs(deltay
);
369 if (deltax
!=0 && deltay
!=0)
371 float ratio
= (float)((float)absDeltax
/(float)absDeltay
);
372 if (ratio
>=0.4141 && ratio
<=2.4145) // cos(PI/8)/sin(PI/8) ou sin(PI/8)/cos(PI/8)
374 setDxDy(deltax
>0?1:-1, deltay
>0?1:-1);
379 if (absDeltax
>absDeltay
)
380 setDxDy(deltax
>0?1:-1, 0);
382 setDxDy(0, deltay
>0?1:-1);
386 CDirection::CDirection(int deltax
, int deltay
)
388 setDxDy(deltax
, deltay
);
392 CDirection::CDirection(CAngle
const& angle
)
394 _value
= (TDirection
)((((sint32
)angle
.asRawSint16()+65536+4096)/8192)&7); // add 4096 to have a correct angle magnet.
398 CAngle
CDirection::getAngle()
403 return CAngle(_value
*8192);
407 sint
CDirection::dx() const
409 return directionDatas
[_value
].dx
;
413 sint
CDirection::dy() const
415 return directionDatas
[_value
].dy
;
419 void CDirection::dxdy(int& dx
, int& dy
)
421 CDirectionData
const& direction
= directionDatas
[_value
];
427 void CDirection::addStep(TDeltaDirection step
)
432 _value
= (TDirection
)((_value
+step
)&7);
436 NLMISC::CVector2f
CDirection::getDirFloat() const
438 return NLMISC::CVector2f((float)dx(), (float)dy());
442 CDirection::TDirection
CDirection::getVal() const
448 CDirection::TMotifDirection
CDirection::getShift() const
450 return (TMotifDirection
)(1<<_value
);
454 bool CDirection::operator !=(TDirection dir
) const
460 bool CDirection::operator != (CDirection
const& dir
) const
462 return _value
!=dir
._value
;
466 uint32
CDirection::getWeight()
468 return directionDatas
[_value
].weight
;
472 void CDirection::getDirectionAround(CAngle
const& Angle
, CDirection
& Dir0
, CDirection
& Dir1
)
474 sint value
= Angle
.asRawSint16()&(~16383); //8191);
475 Dir0
= CDirection(CAngle(value
));
476 value
+= 16384; //8192;
477 Dir1
= CDirection(CAngle(value
));
481 void CDirection::setDxDy(int deltax
, int deltay
)
484 nlassert( deltax
>=-1 && deltax
<=1 && deltay
>=-1 && deltay
<=1);
486 _value
= table
[1+deltax
+(1+deltay
)*3];
488 nlassert(dx()==deltax
&& dy()==deltay
);
492 //////////////////////////////////////////////////////////////////////////////
495 * A map of accessible positions near a given position
496 * \author Benjamin Legros
497 * \author Nevrax France
503 /// One bit per direction
504 bool isValid(CDirection::TDirection dir
) const;
505 bool isValid(CDirection
const& dir
) const;
506 void set(CDirection::TDirection dir
);
510 CNeighbourhood(uint32 neighb
);
512 /// 8 bits for 8 directions
517 bool CNeighbourhood::isValid(CDirection::TDirection dir
) const
519 return (Neighb
&CDirection(dir
).getShift())!=0;
523 bool CNeighbourhood::isValid(CDirection
const& dir
) const
525 return (Neighb
&dir
.getShift())!=0;
529 void CNeighbourhood::set(CDirection::TDirection dir
)
531 Neighb
|=CDirection(dir
).getShift();
535 CNeighbourhood::CNeighbourhood()
541 CNeighbourhood::CNeighbourhood(uint32 neighb
)
546 //////////////////////////////////////////////////////////////////////////////
549 * A slot, defining pacs position and linkage to other slots
550 * \author Benjamin Legros
551 * \author Nevrax France
557 // 12 bits 0-11 : instance id
558 // 12 bits 12-23 : surface id
559 // 2 bits 24-25 : north link
560 // 2 bits 26-27 : east link
561 // 2 bits 28-29 : south link
562 // 2 bits 30-31 : west link
565 InstanceIdOffset
= 0,
566 InstanceIdMask
= 0x00000fff,
567 InstanceIdMax
= 4096,
569 SurfaceIdOffset
= 12,
570 SurfaceIdMask
= 0x00fff000,
574 SlotMask
= 0xff000000
577 // 6 bits 0-5 topology
578 // 2 bits 6-7 gabarit
589 // 13 bits 3-15 height
592 InteriorMask
= 0x0001,
600 /// @name Constructors
602 explicit CUnitSlot();
603 explicit CUnitSlot(uint instanceId
, uint surfaceId
);
604 explicit CUnitSlot(NLPACS::UGlobalPosition
const& pos
);
608 uint
instanceId() const { return (_Id
&InstanceIdMask
) >> InstanceIdOffset
; }
609 uint
surfaceId () const { return (_Id
&SurfaceIdMask
) >> SurfaceIdOffset
; }
610 uint
height () const { return _Height
>> HeightShift
; }
612 CCellLinkage
& cellLink() { return *((CCellLinkage
*)(((char*)&_Id
)+3)); }
613 CCellLinkage
getCellLink() const { return *((CCellLinkage
*)(((char*)&_Id
)+3)); }
614 uint
topology() const { return (_Topology
& TopologyMask
); }
615 uint
gabarit() const { return (_Topology
& GabaritMask
) >> GabaritShift
; }
616 bool interior() const { return (_Height
& InteriorMask
) != 0; }
617 bool water() const { return (_Height
& WaterMask
) != 0; }
618 bool nogo() const { return (_Height
& NoGoMask
) != 0; }
622 void setInstanceId(uint instanceId
);
623 void setSurface(uint surfaceId
);
624 void setTopology(uint topology
);
625 void setGabarit(uint gabarit
);
626 void setHeight(sint height
);
627 void setInterior(bool interior
);
628 void setWater(bool water
);
629 void setNoGo(bool nogo
);
634 bool hasSameSurface(const CUnitSlot
&slot
) const;
636 void serial(NLMISC::IStream
&f
);
639 // _Id is divided this way
640 // bits 0-11 : instance id
641 // bits 12-23 : surface id
642 // bits 24-25 : north link
643 // bits 26-27 : east link
644 // bits 28-29 : south link
645 // bits 30-31 : west link
648 // 6 bits 0-5 topology
649 // 2 bits 6-7 gabarit
655 // 13 bits 3-15 height
658 // a cell is composed of units of 3 slots
659 typedef CUnitSlot TCellUnit
[3];
662 CUnitSlot::CUnitSlot()
670 CUnitSlot::CUnitSlot(uint instanceId
, uint surfaceId
)
675 nlassert(instanceId
<InstanceIdMax
);
676 nlassert(surfaceId
<SurfaceIdMax
);
678 _Id
= SlotMask
+ (instanceId
<< InstanceIdOffset
) + (surfaceId
<< SurfaceIdOffset
);
682 CUnitSlot::CUnitSlot(NLPACS::UGlobalPosition
const& pos
)
687 nlassert(pos
.InstanceId
< InstanceIdMax
);
688 nlassert(pos
.LocalPosition
.Surface
< SurfaceIdMax
);
690 _Id
=SlotMask
+(pos
.InstanceId
<<InstanceIdOffset
)+(pos
.LocalPosition
.Surface
<<SurfaceIdOffset
);
694 void CUnitSlot::setInstanceId(uint instanceId
)
697 nlassert(instanceId
< InstanceIdMax
);
699 _Id
= (_Id
& (~InstanceIdMask
)) + (instanceId
<< InstanceIdOffset
);
703 void CUnitSlot::setSurface(uint surfaceId
)
706 nlassert(surfaceId
< SurfaceIdMax
);
708 _Id
= (_Id
& (~SurfaceIdMask
)) + (surfaceId
<< SurfaceIdOffset
);
712 void CUnitSlot::setTopology(uint topology
)
715 nlassert(topology
< 63);
717 _Topology
= (_Topology
& (~TopologyMask
)) + (uint8
)topology
;
721 void CUnitSlot::setGabarit(uint gabarit
)
724 nlassert(gabarit
< 4);
726 _Topology
= (_Topology
& (~GabaritMask
)) | (uint8
)(gabarit
<< GabaritShift
);
730 void CUnitSlot::setHeight(sint height
)
733 nlassert(height
>= -4096 && height
<= 4095);
735 _Height
= (_Height
& (~HeightMask
)) | (sint16
)(height
<< HeightShift
);
739 void CUnitSlot::setInterior(bool interior
)
742 _Height
|= InteriorMask
;
744 _Height
&= ~InteriorMask
;
748 void CUnitSlot::setWater(bool water
)
751 _Height
|= WaterMask
;
753 _Height
&= ~WaterMask
;
757 void CUnitSlot::setNoGo(bool nogo
)
762 _Height
&= ~NoGoMask
;
766 void CUnitSlot::reset()
774 bool CUnitSlot::used() const
776 return _Id
!= 0xffffffff;
780 bool CUnitSlot::hasSameSurface(const CUnitSlot
&slot
) const
782 return ((slot
._Id
^ _Id
) & (~SlotMask
)) == 0;
786 void CUnitSlot::serial(NLMISC::IStream
&f
)
793 //////////////////////////////////////////////////////////////////////////////
797 typedef sint32 TMapCoordType
;
800 * A simple 1 axis coordinate
801 * \author Benjamin Legros
802 * \author Nevrax France
807 friend class CMapPosition
;
809 explicit CMapCoord(uint scellId
, uint cellId
, uint unitId
);
812 explicit CMapCoord() : c(0) { }
813 explicit CMapCoord(CAICoord
const& aiCoord
) : c((sint
)(floor(aiCoord
.asDouble()+0.5))) { }
814 explicit CMapCoord(sint cc
) : c(cc
) { }
816 uint
cellIdMask(uint val
) const;
817 uint
fullCellIdMask(uint val
) const;
819 uint
toUnitId(uint val
) const;
820 uint
toCellId(uint val
) const;
821 uint
toSuperCellId(uint val
) const;
823 uint
unitIdToUInt(uint val
) const;
824 uint
cellIdToUInt(uint val
) const;
825 uint
superCellIdToUInt(uint val
) const;
826 uint
fullCellIdToUInt(uint val
) const;
828 TMapCoordType
& cRef();
831 uint
getUnitId () const { return unitIdToUInt(c
); }
832 uint
getCellId () const { return cellIdToUInt(c
); }
833 uint
getSuperCellId () const { return superCellIdToUInt(c
); }
834 uint
getFullCellId () const { return fullCellIdToUInt(c
); }
836 void setUnitId(uint id
) { c
= fullCellIdMask(c
) | toUnitId(id
); }
837 void setCellId(uint id
) { c
= cellIdMask(c
) | toCellId(id
); }
839 bool operator ==(CMapCoord
const& cc
) const { return c
== cc
.c
; }
840 bool operator !=(CMapCoord
const& cc
) const { return c
!= cc
.c
; }
841 CMapCoord
operator -(CMapCoord
const& cc
) const { return CMapCoord(c
-cc
.c
); }
843 TMapCoordType
const& get() const { return c
; }
851 CMapCoord::CMapCoord(uint scellId
, uint cellId
, uint unitId
)
852 : c(toSuperCellId(scellId
) + toCellId(cellId
) + toUnitId(unitId
))
855 nlassert(scellId
< 256);
860 uint
CMapCoord::cellIdMask(uint val
) const
866 uint
CMapCoord::fullCellIdMask(uint val
) const
868 return val
&0x0fffffff0;
872 uint
CMapCoord::toUnitId(uint val
) const
878 uint
CMapCoord::toCellId(uint val
) const
880 return (val
<<4)&0x0f0;
884 uint
CMapCoord::toSuperCellId(uint val
) const
886 return (val
<<8)&0x0ffff;
890 uint
CMapCoord::unitIdToUInt(uint val
) const
896 uint
CMapCoord::cellIdToUInt(uint val
) const
902 uint
CMapCoord::superCellIdToUInt(uint val
) const
904 return (val
>>8)&0x0ff;
908 uint
CMapCoord::fullCellIdToUInt(uint val
) const
910 return (val
>>4)&0x0fff;
914 TMapCoordType
& CMapCoord::cRef()
919 //////////////////////////////////////////////////////////////////////////////
922 * A map position, consisting of 2 axis coordinates
923 * \author Benjamin Legros
924 * \author Nevrax France
929 friend class RYPACSCRUNCH::CPacsCruncher
;
932 CMapPosition(sint x
, sint y
);
933 CMapPosition(CMapCoord
const& x
, CMapCoord
const& y
);
934 CMapPosition(CMapPosition
const& pos
);
935 CMapPosition(NLMISC::CVectorD
const& pos
);
936 CMapPosition(CAIVector
const& pos
);
937 CMapPosition(CAICoord
const& x
, CAICoord
const& y
);
939 NLMISC::CVectorD
toVectorD() const;
940 NLMISC::CVector2d
toVector2d() const;
941 CAIVector
toAIVector() const;
943 std::string
toString() const;
945 void setUnitId(uint
const xId
, uint
const yId
);
946 void setNullUnitId();
948 CMapPosition
stepCell(sint dx
, sint dy
) const;
950 bool hasSameFullCellId(CMapPosition
const& other
) const;
952 CMapPosition
operator -(CMapPosition
const& other
) const;
953 bool operator ==(CMapPosition
const& cc
) const;
954 bool operator !=(CMapPosition
const& cc
) const;
956 CMapCoord
const& xCoord() const { return _x
; }
957 CMapCoord
const& yCoord() const { return _y
; }
959 TMapCoordType
const& x() const { return _x
.get(); }
960 TMapCoordType
const& y() const { return _y
.get(); }
962 uint32
superCellFastIndex() const;
963 uint32
rootCellFastIndex() const;
964 uint32
cellUnitFastIndex() const;
966 CMapPosition
step(sint dx
, sint dy
) const;
968 CMapPosition
getStepS() const { return step(0, -1); }
969 CMapPosition
getStepN() const { return step(0, +1); }
970 CMapPosition
getStepE() const { return step(+1, 0); }
971 CMapPosition
getStepW() const { return step(-1, 0); }
974 // return if we have changed of RootCell ..
975 bool stepS() { _y
.cRef()-=1; return ((_y
.cRef()&0xf)==0xf); }
976 bool stepN() { _y
.cRef()+=1; return ((_y
.cRef()&0xf)==0x0); }
977 bool stepW() { _x
.cRef()-=1; return ((_x
.cRef()&0xf)==0xf); }
978 bool stepE() { _x
.cRef()+=1; return ((_x
.cRef()&0xf)==0x0); }
986 CMapPosition::CMapPosition(sint x
, sint y
)
993 CMapPosition::CMapPosition(CMapCoord
const& x
, CMapCoord
const& y
)
1000 CMapPosition::CMapPosition(CMapPosition
const& pos
)
1007 CMapPosition::CMapPosition(NLMISC::CVectorD
const& pos
)
1008 : _x((uint
)floor((pos
.x
- WorldStartOffset
.x
)/WorldGridResolution
+ 0.5))
1009 , _y((uint
)floor((pos
.y
- WorldStartOffset
.y
)/WorldGridResolution
+ 0.5))
1014 CMapPosition::CMapPosition(CAIVector
const& pos
)
1021 CMapPosition::CMapPosition(CAICoord
const& x
, CAICoord
const& y
)
1028 NLMISC::CVectorD
CMapPosition::toVectorD() const
1030 return NLMISC::CVectorD(WorldStartOffset
.x
+ _x
.get()*WorldGridResolution
, WorldStartOffset
.y
+ _y
.get()*WorldGridResolution
, 0.0);
1034 NLMISC::CVector2d
CMapPosition::toVector2d() const
1036 return NLMISC::CVector2d(WorldStartOffset
.x
+ _x
.get()*WorldGridResolution
, WorldStartOffset
.y
+ _y
.get()*WorldGridResolution
);
1040 CAIVector
CMapPosition::toAIVector() const
1042 return CAIVector(WorldStartOffset
.x
+ _x
.get()*WorldGridResolution
, WorldStartOffset
.y
+ _y
.get()*WorldGridResolution
);
1046 std::string
CMapPosition::toString() const
1048 return toAIVector().toString();
1052 void CMapPosition::setUnitId(uint
const xId
, uint
const yId
)
1059 void CMapPosition::setNullUnitId()
1066 CMapPosition
CMapPosition::stepCell(sint dx
, sint dy
) const
1068 CMapPosition
newMapPos(xCoord().get()+(dx
<<4),yCoord().get()+(dy
<<4));
1069 newMapPos
.setNullUnitId();
1074 bool CMapPosition::hasSameFullCellId(CMapPosition
const& other
) const
1076 return ( _x
.getFullCellId()==other
._x
.getFullCellId() && _y
.getFullCellId()==other
._y
.getFullCellId() );
1080 CMapPosition
CMapPosition::operator -(CMapPosition
const& other
) const
1082 return CMapPosition(_x
-other
._x
,_y
-other
._y
);
1086 bool CMapPosition::operator ==(CMapPosition
const& cc
) const
1088 return _x
==cc
._x
&& _y
==cc
._y
;
1092 bool CMapPosition::operator !=(CMapPosition
const& cc
) const
1094 return _x
!=cc
._x
|| _y
!=cc
._y
;
1098 uint32
CMapPosition::superCellFastIndex() const
1100 return ((((uint
)y())&(0x0ff<<8)) + xCoord().getSuperCellId());
1104 uint32
CMapPosition::rootCellFastIndex() const
1106 return ((((uint
)y())&0x0f<<4) + xCoord().getCellId());
1110 uint32
CMapPosition::cellUnitFastIndex() const
1112 return ((yCoord().getUnitId()<<4) + xCoord().getUnitId());
1116 CMapPosition
CMapPosition::step(sint dx
, sint dy
) const
1118 return CMapPosition(_x
.get() + dx
, _y
.get() + dy
);
1121 //////////////////////////////////////////////////////////////////////////////
1124 * Motion map interface
1125 * \author Benjamin Legros
1126 * \author Nevrax France
1129 class CGridDirectionLayer
1130 : public I16x16Layer
1133 CDirection
getDirection(int y
, int x
) const;
1134 CDirection
getDirection(CMapPosition
const& pos
) const;
1136 void setDirection(int y
, int x
, CDirection dir
);
1140 CDirection
CGridDirectionLayer::getDirection(int y
, int x
) const
1142 return CDirection((CDirection::TDirection
)get(y
, x
));
1146 CDirection
CGridDirectionLayer::getDirection(CMapPosition
const& pos
) const
1148 return CDirection((CDirection::TDirection
)get(pos
.yCoord().getUnitId(), pos
.xCoord().getUnitId()));
1152 void CGridDirectionLayer::setDirection(int y
, int x
, CDirection dir
)
1154 this->set((uint
)y
, (uint
)x
, (sint
)dir
.getVal());
1157 //////////////////////////////////////////////////////////////////////////////
1159 class CDirectionLayer
1164 void serial(NLMISC::IStream
& f
);
1166 CGridDirectionLayer
* getGridLayer(int y
, int x
);
1167 void setGridLayer(int y
, int x
, I16x16Layer
* layer
);
1172 // Grid[1][1] is central cell
1173 I16x16Layer
*Grid
[3][3];
1177 CDirectionLayer::CDirectionLayer()
1186 CGridDirectionLayer
* CDirectionLayer::getGridLayer(int y
, int x
)
1188 return static_cast<CGridDirectionLayer
*>(Grid
[y
][x
]);
1192 void CDirectionLayer::setGridLayer(int y
, int x
, I16x16Layer
* layer
)
1198 void CDirectionLayer::dump()
1200 char output
[16*3][16*3];
1201 for (sint i
=2; i
>=0; --i
)
1202 for (sint j
=0; j
<3; ++j
)
1203 for (sint y
=15; y
>=0; --y
)
1204 for (sint x
=0; x
<16; ++x
)
1206 CGridDirectionLayer
* gridDirectionLayer
= getGridLayer(i
,j
);
1209 if (gridDirectionLayer
)
1210 motion
= gridDirectionLayer
->getDirection(y
,x
);
1214 switch (motion
.getVal())
1228 case CDirection::NE
:
1231 case CDirection::SW
:
1234 case CDirection::NW
:
1237 case CDirection::SE
:
1247 output
[y
+i
*16][x
+j
*16] = c
;
1251 nlinfo(" \t0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF");
1253 for (sint i
=47; i
>=0; --i
)
1256 for (j
=0; j
<48; ++j
)
1257 op
[j
] = output
[i
][j
];
1259 nlinfo("%04X\t%s", (i
&15), op
);
1263 //////////////////////////////////////////////////////////////////////////////
1268 CDirectionLayer
* Layers
[3];
1272 void serial(NLMISC::IStream
& f
);
1278 CDirectionMap::CDirectionMap()
1286 void CDirectionMap::dump()
1288 for (uint i
=0; i
<3; ++i
)
1290 nlinfo("Layer %d", i
);
1291 if (Layers
[i
] != NULL
)
1298 //////////////////////////////////////////////////////////////////////////////
1302 class CWorldPosition
;
1308 /// A topology Id, representing cell and topology
1314 UNDEFINED_TOPOLOGY
= 0xffffffff
1318 explicit TTopologyId();
1319 explicit TTopologyId(CMapPosition
const& pos
, uint topology
);
1321 explicit TTopologyId(uint32 id
);
1323 bool haveSameCellPos(TTopologyId
const& other
) const;
1325 CMapPosition
getMapPosition() const;
1326 uint
getTopologyIndex() const;
1328 bool isValid() const;
1330 bool operator <(TTopologyId
const& other
) const;
1331 bool operator ==(TTopologyId
const& other
) const;
1332 bool operator !=(TTopologyId
const& other
) const;
1334 void serial(NLMISC::IStream
& f
);
1336 uint32
getVal() const;
1343 : public TTopologyId
1345 friend class CWorldPosition
;
1347 TTopologyRef(CWorldPosition
const& pos
);
1349 explicit TTopologyRef(TTopologyId
const& id
, CRootCell
* rootCell
);
1350 CTopology
const& getCstTopologyNode() const;
1351 void setRootCell(CRootCell
* rootCell
);
1353 void serial(NLMISC::IStream
& f
);
1354 CRootCell
const* getRootCell() const;
1357 TTopologyRef(CWorldPosition
const& pos
, CRootCell
const* rootCell
);
1358 CRootCell
const* _RootCell
;
1361 /// A link to a neighbour, including mean distance to it
1362 class CNeighbourLink
1365 explicit CNeighbourLink();
1366 explicit CNeighbourLink(TTopologyRef
const& ref
, float distance
);
1367 CNeighbourLink(CNeighbourLink
const& other
);
1369 void serial(NLMISC::IStream
& f
);
1371 TTopologyRef
const& getTopologyRef() const;
1373 void updateTopologyRef(CWorldMap
* worldMapPtr
);
1375 float getDistance() const;
1382 void updateTopologyRef(CWorldMap
* worldMapPtr
);
1384 bool isInInterior() const { return (Flags
& Interior
) != 0; }
1385 bool isInWater() const { return (Flags
& Water
) != 0; }
1386 bool isInNogo() const { return (Flags
& NoGo
) != 0; }
1388 TAStarFlag
getFlags() const { return (TAStarFlag
)Flags
; }
1390 uint32
getMasterTopo(TAStarFlag
const& flags
) const;
1392 uint32
getMasterTopo(bool allowWater
, bool allowNoGo
) const;
1394 uint32
& getMasterTopoRef(bool allowWater
, bool allowNoGo
);
1396 bool isCompatible(bool allowWater
, bool allowNoGo
) const;
1398 /// The Id of this topology
1400 /// The direction map to access this topology
1401 CDirectionMap
* DirectionMap
;
1402 /// The neighbour topologies that have access to this topology
1403 std::vector
<CNeighbourLink
> Neighbours
;
1404 /// Flags of the topology
1405 uint16 Flags
; // why doing this (uint16), its not align so no gain in memory and it causes access cost !
1406 /// Master topologies
1407 uint32 MasterTopL
; // only landscape
1408 uint32 MasterTopLW
; // landscape and water
1409 uint32 MasterTopLN
; // landscape and nogo
1410 uint32 MasterTopLNW
; // landscape and water and nogo
1412 /// Topology center, for A* purpose
1413 NLMISC::CVector Position
;
1417 void serial(NLMISC::IStream
& f
);
1421 CTopology::TTopologyId::TTopologyId()
1422 : _value(UNDEFINED_TOPOLOGY
)
1427 CTopology::TTopologyId::TTopologyId(CMapPosition
const& pos
, uint topology
)
1430 nlassert(topology
< 256);
1432 _value
= (pos
.yCoord().getFullCellId() << 20) + (pos
.xCoord().getFullCellId() << 8) + topology
;
1436 CTopology::TTopologyId::TTopologyId(uint32 id
)
1442 bool CTopology::TTopologyId::haveSameCellPos(TTopologyId
const& other
) const
1444 return ((other
._value
^_value
)&0x0ffffff00)==0;
1448 CMapPosition
CTopology::TTopologyId::getMapPosition() const
1450 return CMapPosition((_value
&0x000fff00) >> (8-4),(_value
&0xfff00000) >> (20-4));
1454 uint
CTopology::TTopologyId::getTopologyIndex() const
1456 return _value
&0x000000ff;
1460 bool CTopology::TTopologyId::isValid() const
1462 return _value
!=UNDEFINED_TOPOLOGY
;
1466 bool CTopology::TTopologyId::operator <(TTopologyId
const& other
) const
1468 return _value
<other
._value
;
1472 bool CTopology::TTopologyId::operator ==(TTopologyId
const& other
) const
1474 return _value
==other
._value
;
1478 bool CTopology::TTopologyId::operator !=(TTopologyId
const& other
) const
1480 return _value
!=other
._value
;
1484 void CTopology::TTopologyId::serial(NLMISC::IStream
& f
)
1490 uint32
CTopology::TTopologyId::getVal() const
1496 CTopology::TTopologyRef::TTopologyRef()
1503 CTopology::TTopologyRef::TTopologyRef(TTopologyId
const& id
, CRootCell
* rootCell
)
1506 setRootCell(rootCell
);
1510 void CTopology::TTopologyRef::setRootCell(CRootCell
* rootCell
)
1512 _RootCell
= rootCell
;
1516 void CTopology::TTopologyRef::serial(NLMISC::IStream
& f
)
1518 TTopologyId::serial(f
);
1522 CRootCell
const* CTopology::TTopologyRef::getRootCell() const
1528 CTopology::CNeighbourLink::CNeighbourLink()
1534 CTopology::CNeighbourLink::CNeighbourLink(TTopologyRef
const& ref
, float distance
)
1536 , _Distance(distance
)
1541 CTopology::CNeighbourLink::CNeighbourLink(CNeighbourLink
const& other
)
1543 , _Distance(other
._Distance
)
1548 void CTopology::CNeighbourLink::serial(NLMISC::IStream
& f
)
1550 f
.serial(_Ref
, _Distance
);
1554 CTopology::TTopologyRef
const& CTopology::CNeighbourLink::getTopologyRef() const
1560 float CTopology::CNeighbourLink::getDistance() const
1566 void CTopology::updateTopologyRef(CWorldMap
* worldMapPtr
)
1568 std::vector
<CNeighbourLink
>::iterator it
=Neighbours
.begin(), itEnd
=Neighbours
.end();
1571 (*it
).updateTopologyRef(worldMapPtr
);
1577 uint32
CTopology::getMasterTopo(TAStarFlag
const& flags
) const
1579 switch (flags
&WaterAndNogo
)
1589 return MasterTopLNW
;
1594 uint32
CTopology::getMasterTopo(bool allowWater
, bool allowNoGo
) const
1599 return MasterTopLNW
;
1608 uint32
& CTopology::getMasterTopoRef(bool allowWater
, bool allowNoGo
)
1613 return MasterTopLNW
;
1622 bool CTopology::isCompatible(bool allowWater
, bool allowNoGo
) const
1624 return (allowWater
|| !isInWater()) && (allowNoGo
|| !isInNogo());
1628 CTopology::CTopology()
1630 , DirectionMap(NULL
)
1632 , MasterTopL(TTopologyId::UNDEFINED_TOPOLOGY
)
1633 , MasterTopLW(TTopologyId::UNDEFINED_TOPOLOGY
)
1634 , MasterTopLN(TTopologyId::UNDEFINED_TOPOLOGY
)
1635 , MasterTopLNW(TTopologyId::UNDEFINED_TOPOLOGY
)
1639 // convert a 2 characters string to uint16
1640 #ifdef NL_LITTLE_ENDIAN
1641 # define NELID16(x) (uint16((x[0] << 8) | (x[1])))
1643 # define NELID16(x) (uint16((x[1] << 8) | (x[0])))
1649 void CTopology::serial(NLMISC::IStream
& f
)
1654 uint16 check
= NELID16("Tp");
1657 if (check
!= NELID16("TP"))
1659 nlassert(check
== NELID16("Tp"));
1660 version
= f
.serialVersion(3);
1667 delete DirectionMap
;
1668 DirectionMap
= NULL
;
1671 bool present
= (DirectionMap
!= NULL
);
1677 DirectionMap
= new CDirectionMap();
1679 nlassert(DirectionMap
);
1680 f
.serial(*DirectionMap
);
1683 f
.serialCont(Neighbours
);
1691 f
.serial(MasterTopL
);
1692 f
.serial(MasterTopLW
);
1693 f
.serial(MasterTopLN
);
1694 f
.serial(MasterTopLNW
);
1698 nlassert(f
.isReading());
1725 //////////////////////////////////////////////////////////////////////////////
1728 * CWorldPosition, position referenced by a map position and a slot
1729 * \author Benjamin Legros
1730 * \author Nevrax France
1733 class CWorldPosition
1734 : public CMapPosition
1737 friend class CWorldMap
;
1738 friend class RYPACSCRUNCH::CPacsCruncher
;
1740 explicit CWorldPosition();
1741 explicit CWorldPosition(sint x
, sint y
);
1743 // resumes that the RootCell is valid;
1744 CRootCell
const* getRootCell() const { return _RootCell
; }
1747 sint32
getMetricHeight() const;
1748 sint32
h() const { return getMetricHeight(); }
1750 CCellLinkage
const& getCellLinkage() const { return _cellLinkage
; }
1752 CTopology::TTopologyRef
getTopologyRef() const;
1754 bool isInInterior() const;
1756 CTopology
const& getTopologyNode() const;
1758 TAStarFlag
getFlags() const;
1760 /// Get a vector position from a world position
1761 NLMISC::CVectorD
getPosition() const;
1763 bool operator ==(CWorldPosition
const& cc
) const { return CSlot::operator ==(cc
) && CMapPosition::operator ==(cc
); }
1764 bool operator !=(CWorldPosition
const& cc
) const { return CSlot::operator !=(cc
) || CMapPosition::operator !=(cc
); }
1767 CWorldPosition
getPosS() const;
1768 CWorldPosition
getPosN() const;
1769 CWorldPosition
getPosE() const;
1770 CWorldPosition
getPosW() const;
1772 void setPosS(CWorldPosition
& pos
) const;
1773 void setPosN(CWorldPosition
& pos
) const;
1774 void setPosE(CWorldPosition
& pos
) const;
1775 void setPosW(CWorldPosition
& pos
) const;
1787 CRootCell
const* _RootCell
;
1788 CCellLinkage _cellLinkage
;
1790 explicit CWorldPosition(CRootCell
const* cell
, CMapPosition
const& pos
, CSlot
const& slot
);
1791 explicit CWorldPosition(CRootCell
const* cell
, CMapPosition
const& pos
, CSlot
const& slot
, bool generationOnly
);
1795 CWorldPosition::CWorldPosition()
1804 CWorldPosition::CWorldPosition(sint x
, sint y
)
1805 : CMapPosition(x
, y
)
1813 CTopology::TTopologyRef
CWorldPosition::getTopologyRef() const
1815 return CTopology::TTopologyRef(*this, getRootCell());
1819 bool CWorldPosition::isInInterior() const
1821 return getTopologyRef().getCstTopologyNode().isInInterior();
1825 CTopology
const& CWorldPosition::getTopologyNode() const
1827 return getTopologyRef().getCstTopologyNode();
1831 TAStarFlag
CWorldPosition::getFlags() const
1833 return getTopologyRef().getCstTopologyNode().getFlags(); //Flags;
1836 //////////////////////////////////////////////////////////////////////////////
1838 class CCompatibleResult
1841 CCompatibleResult(TAStarFlag movementFlags
= Interior
, uint32 choosenMasterTopo
= ~0);
1842 void set(TAStarFlag movementFlags
, uint32 choosenMasterTopo
);
1843 void setValid(bool valid
= true);
1844 TAStarFlag
const& movementFlags() const;
1845 uint32
const& choosenMasterTopo() const;
1846 bool const& isValid() const;
1849 TAStarFlag _MovementFlags
;
1850 uint32 _ChoosenMasterTopo
;
1855 CCompatibleResult::CCompatibleResult(TAStarFlag movementFlags
, uint32 choosenMasterTopo
)
1856 : _MovementFlags(movementFlags
)
1857 , _ChoosenMasterTopo(choosenMasterTopo
)
1863 void CCompatibleResult::set(TAStarFlag movementFlags
, uint32 choosenMasterTopo
)
1865 _MovementFlags
= movementFlags
;
1866 _ChoosenMasterTopo
= choosenMasterTopo
;
1870 void CCompatibleResult::setValid(bool valid
)
1876 TAStarFlag
const& CCompatibleResult::movementFlags() const
1878 return _MovementFlags
;
1882 uint32
const& CCompatibleResult::choosenMasterTopo() const
1884 return _ChoosenMasterTopo
;
1888 bool const& CCompatibleResult::isValid() const
1893 //////////////////////////////////////////////////////////////////////////////
1896 @relates CWorldPosition
1898 void areCompatiblesWithoutStartRestriction(CWorldPosition
const& startPos
, CWorldPosition
const& endPos
, TAStarFlag
const& denyflags
, CCompatibleResult
& res
, bool allowStartRestriction
= false);
1900 //////////////////////////////////////////////////////////////////////////////
1903 * CRootCell, interface for all 16x16 cells in world map
1904 * derivated into CComputeCell (for map computation only), into CSingleLayerCell and CMultiLayerCell
1905 * \author Benjamin Legros
1906 * \author Nevrax France
1922 CRootCell(CWorldMap
const& worldMapPtr
);
1924 virtual ~CRootCell() { }
1926 void setFlag(uint32
const flag
) { _flag
= flag
; }
1927 uint32
getFlag() const { return _flag
; }
1929 sint32
getMetricHeight(CWorldPosition
const& wpos
) const;
1931 CWorldMap
const& getWorldMapPtr() const { return _WorldMapPtr
; }
1933 // mutator (only for build purpose)
1934 CTopology
& getTopologyNode(uint topology
);
1935 CTopology
const& getCstTopologyNode(uint topology
) const;
1937 CTopology::TTopologyId
getTopologyId(CWorldPosition
const& wpos
) const;
1939 CTopology::TTopologyRef
getTopologyRef(const CWorldPosition
&pos
) const;
1941 CTopology
const& getCstTopologyNode(CTopology::TTopologyId
const& id
) const;
1943 std::vector
<CTopology
>& getTopologiesNodes() { return _TopologiesNodes
; }
1944 std::vector
<CTopology
> const& getTopologiesNodes() const { return _TopologiesNodes
; }
1945 void setTopologiesNodes(std::vector
<CTopology
> const& nodes
) { _TopologiesNodes
= nodes
; }
1947 CDirectionMap
const* getDirectionMap(uint topology
) const;
1948 void setDirectionMap(CDirectionMap
* map
, uint topology
);
1950 void updateTopologyRef(CWorldMap
* worldMap
);
1952 CWorldPosition
const& getWorldPosition(uint ind
) const;
1954 void setWorldPosition(CWorldPosition
const& pos
, uint ind
);
1956 virtual CCellLinkage
getCellLink(CWorldPosition
const& wpos
) const = 0;
1958 virtual uint32
nbUsedSlots(CMapPosition
const& pos
) const = 0;
1959 virtual sint32
maxUsedSlot(CMapPosition
const& pos
) const = 0;
1960 virtual bool isSlotUsed(CMapPosition
const& pos
, CSlot
const& slot
) const = 0;
1962 virtual uint
getTopology(CWorldPosition
const& wpos
) const = 0;
1964 virtual sint
getHeight(CWorldPosition
const& wpos
) const = 0;
1967 virtual void clearHeightMap() = 0;
1970 virtual void serial(NLMISC::IStream
& f
) = 0;
1973 static CRootCell
* load(NLMISC::IStream
& f
, CWorldMap
const& worldMap
);
1976 static void save(NLMISC::IStream
& f
, CRootCell
* cell
);
1979 CWorldMap
const& _WorldMapPtr
; // his owner map;
1980 std::vector
<CTopology
> _TopologiesNodes
;
1981 CWorldPosition _WorldPosition
[4]; // 4 random positions for each slots.
1986 CRootCell::CRootCell(CWorldMap
const& worldMapPtr
)
1987 : _WorldMapPtr(worldMapPtr
)
1993 sint32
CRootCell::getMetricHeight(CWorldPosition
const& wpos
) const
1995 // check if wpos valid
1996 if (!wpos
.isValid())
1999 sint32
const z
= (getHeight(wpos
)*2000 - 1000)&(~3);
2000 uint
const top
= getTopology(wpos
);
2001 if (top
<_TopologiesNodes
.size() && _TopologiesNodes
[top
].isInInterior())
2007 CTopology
& CRootCell::getTopologyNode(uint topology
)
2009 if (topology
>= _TopologiesNodes
.size())
2010 _TopologiesNodes
.resize(topology
+1);
2012 return _TopologiesNodes
[topology
];
2016 CTopology
const& CRootCell::getCstTopologyNode(uint topology
) const
2019 nlassert(topology
< _TopologiesNodes
.size());
2021 return _TopologiesNodes
[topology
];
2025 CTopology::TTopologyId
CRootCell::getTopologyId(CWorldPosition
const& wpos
) const
2027 return CTopology::TTopologyId(wpos
, getTopology(wpos
));
2031 CTopology::TTopologyRef
CRootCell::getTopologyRef(const CWorldPosition
&pos
) const
2034 nlassert(pos
.getRootCell()!=this);
2036 return CTopology::TTopologyRef(pos
);
2040 CTopology
const& CRootCell::getCstTopologyNode(CTopology::TTopologyId
const& id
) const
2042 return getCstTopologyNode(id
.getTopologyIndex());
2046 CDirectionMap
const* CRootCell::getDirectionMap(uint topology
) const
2048 return (topology
<_TopologiesNodes
.size()) ? getCstTopologyNode(topology
).DirectionMap
: NULL
;
2052 void CRootCell::setDirectionMap(CDirectionMap
* map
, uint topology
)
2054 getTopologyNode(topology
).DirectionMap
= map
;
2058 void CRootCell::updateTopologyRef(CWorldMap
* worldMap
)
2060 std::vector
<CTopology
>::iterator it
=_TopologiesNodes
.begin(), itEnd
=_TopologiesNodes
.end();
2063 (*it
).updateTopologyRef(worldMap
);
2069 CWorldPosition
const& CRootCell::getWorldPosition(uint ind
) const
2074 return _WorldPosition
[ind
];
2078 void CRootCell::setWorldPosition(CWorldPosition
const& pos
, uint ind
)
2083 _WorldPosition
[ind
] = pos
;
2086 //////////////////////////////////////////////////////////////////////////////
2089 * A computed 16x16 cell
2090 * \author Benjamin Legros
2091 * \author Nevrax France
2098 CComputeCell(CWorldMap
const& worldMapPtr
);
2100 CCellLinkage
getCellLink(CWorldPosition
const& wpos
) const;
2102 uint32
nbUsedSlots(CMapPosition
const& pos
) const;
2104 sint32
maxUsedSlot(CMapPosition
const& pos
) const;
2106 bool isSlotUsed(CMapPosition
const& pos
, CSlot
const& slot
) const;
2108 uint
getTopology(CWorldPosition
const& wpos
) const;
2110 sint
getHeight(CWorldPosition
const& wpos
) const;
2112 TCellUnit
const& getCellUnitCst(CMapPosition
const& pos
) const;
2114 CUnitSlot
const& getUnitSlotCst(CWorldPosition
const& wpos
) const;
2116 TCellUnit
& getCellUnit(CMapPosition
const& pos
);
2118 CUnitSlot
& getUnitSlot(CWorldPosition
const& wpos
);
2120 void serial(NLMISC::IStream
& f
);
2122 void clearHeightMap() { }
2125 TCellUnit
const& getCellUnitCst(CWorldPosition
const& wpos
) const;
2127 // a cell is a grid of 16x16 units
2128 TCellUnit _Grid
[16*16];
2132 CComputeCell::CComputeCell(CWorldMap
const& worldMapPtr
)
2133 : CRootCell(worldMapPtr
)
2138 CCellLinkage
CComputeCell::getCellLink(CWorldPosition
const& wpos
) const
2140 return getUnitSlotCst(wpos
).getCellLink();
2144 uint32
CComputeCell::nbUsedSlots(CMapPosition
const& pos
) const
2146 TCellUnit
const& cellUnit
= getCellUnitCst(pos
);
2148 for (uint slot
=0; slot
<3; ++slot
)
2149 if (cellUnit
[slot
].getCellLink().used())
2155 sint32
CComputeCell::maxUsedSlot(CMapPosition
const& pos
) const
2157 TCellUnit
const& cellUnit
= getCellUnitCst(pos
);
2159 for (uint slot
=0; slot
<3; ++slot
)
2160 if (cellUnit
[slot
].getCellLink().used())
2166 bool CComputeCell::isSlotUsed(CMapPosition
const& pos
, CSlot
const& slot
) const
2168 TCellUnit
const& cellUnit
= getCellUnitCst(pos
);
2169 return slot
.isValid() ? cellUnit
[slot
.slot()].getCellLink().used() : false;
2173 uint
CComputeCell::getTopology(CWorldPosition
const& wpos
) const
2175 return getUnitSlotCst(wpos
).topology();
2179 sint
CComputeCell::getHeight(CWorldPosition
const& wpos
) const
2181 return getUnitSlotCst(wpos
).height();
2185 TCellUnit
const& CComputeCell::getCellUnitCst(CMapPosition
const& pos
) const
2187 return _Grid
[pos
.cellUnitFastIndex()];
2191 CUnitSlot
const& CComputeCell::getUnitSlotCst(CWorldPosition
const& wpos
) const
2194 nlassert(wpos
.isValid());
2196 return getCellUnitCst(wpos
)[wpos
.slot()];
2200 TCellUnit
& CComputeCell::getCellUnit(CMapPosition
const& pos
)
2202 return _Grid
[pos
.cellUnitFastIndex()];
2206 CUnitSlot
& CComputeCell::getUnitSlot(CWorldPosition
const& wpos
)
2209 nlassert(wpos
.isValid());
2211 return getCellUnit(wpos
)[wpos
.slot()];
2215 TCellUnit
const& CComputeCell::getCellUnitCst(CWorldPosition
const& wpos
) const
2217 return _Grid
[wpos
.cellUnitFastIndex()];
2220 //////////////////////////////////////////////////////////////////////////////
2223 * A Single layer 16x16 cell that has not walk constraint (map is completely white)
2224 * \author Benjamin Legros
2225 * \author Nevrax France
2232 CWhiteCell(CWorldMap
const& worldMapPtr
);
2234 CCellLinkage
getCellLink(CWorldPosition
const& wpos
) const;
2236 uint32
nbUsedSlots(CMapPosition
const& pos
) const;
2238 sint32
maxUsedSlot(CMapPosition
const& pos
) const;
2240 bool isSlotUsed(CMapPosition
const& pos
, CSlot
const& slot
) const;
2242 uint
getTopology(CWorldPosition
const& wpos
) const;
2244 sint
getHeight(CWorldPosition
const& wpos
) const;
2246 void serial(NLMISC::IStream
& f
);
2248 void clearHeightMap();
2250 void setHeightMap(I16x16Layer
* heightMap
);
2253 I16x16Layer
* _HeightMap
;
2257 CWhiteCell::CWhiteCell(CWorldMap
const& worldMapPtr
)
2258 : CRootCell(worldMapPtr
), _HeightMap(NULL
)
2263 CCellLinkage
CWhiteCell::getCellLink(CWorldPosition
const& wpos
) const
2265 return CCellLinkage(0);
2269 uint32
CWhiteCell::nbUsedSlots(CMapPosition
const& pos
) const
2275 sint32
CWhiteCell::maxUsedSlot(CMapPosition
const& pos
) const
2281 bool CWhiteCell::isSlotUsed(CMapPosition
const& pos
, CSlot
const& slot
) const
2283 return slot
.slot() == 0;
2287 uint
CWhiteCell::getTopology(CWorldPosition
const& wpos
) const
2293 sint
CWhiteCell::getHeight(CWorldPosition
const& wpos
) const
2295 return (_HeightMap
!= NULL
) ? _HeightMap
->get(wpos
.yCoord().getUnitId(), wpos
.xCoord().getUnitId()) : 0;
2299 void CWhiteCell::serial(NLMISC::IStream
& f
)
2301 f
.serialCheck(NELID16("WC"));
2303 _HeightMap
= I16x16Layer::load(f
);
2305 I16x16Layer::save(f
, _HeightMap
);
2309 void CWhiteCell::clearHeightMap()
2317 void CWhiteCell::setHeightMap(I16x16Layer
* heightMap
)
2319 _HeightMap
= heightMap
;
2322 //////////////////////////////////////////////////////////////////////////////
2325 * A Single layer 16x16 cell
2326 * \author Benjamin Legros
2327 * \author Nevrax France
2330 class CSingleLayerCell
2334 bool testPos(uint i
, uint j
) const { return (_Map
[i
] & _MaskMap
[j
]) != 0; }
2335 void setPos(uint i
, uint j
, bool p
) { _Map
[i
] = (p
? (_Map
[i
] | _MaskMap
[j
]) : (_Map
[i
] & (~_MaskMap
[j
]))); }
2338 CSingleLayerCell(CWorldMap
const& worldMapPtr
);
2340 CCellLinkage
getCellLink(CWorldPosition
const& wpos
) const;
2342 uint32
nbUsedSlots(CMapPosition
const& pos
) const;
2344 sint32
maxUsedSlot(CMapPosition
const& pos
) const;
2346 bool isSlotUsed(CMapPosition
const& pos
, CSlot
const& slot
) const;
2348 uint
getTopology(CWorldPosition
const& wpos
) const;
2350 sint
getHeight(CWorldPosition
const& wpos
) const;
2352 bool testPos(CMapPosition
const& pos
) const;
2354 void setPos(CMapPosition
const& pos
, bool p
);
2356 void setSLink(uint i
, bool p
) { _SLinks
= p
? (_SLinks
| _MaskMap
[i
]) : (_SLinks
& (~_MaskMap
[i
])); }
2357 void setNLink(uint i
, bool p
) { _NLinks
= p
? (_NLinks
| _MaskMap
[i
]) : (_NLinks
& (~_MaskMap
[i
])); }
2358 void setELink(uint i
, bool p
) { _ELinks
= p
? (_ELinks
| _MaskMap
[i
]) : (_ELinks
& (~_MaskMap
[i
])); }
2359 void setWLink(uint i
, bool p
) { _WLinks
= p
? (_WLinks
| _MaskMap
[i
]) : (_WLinks
& (~_MaskMap
[i
])); }
2361 void setTopologies(I16x16Layer
* topology
);
2363 void setHeightMap(I16x16Layer
* heightMap
);
2365 virtual void serial(NLMISC::IStream
& f
);
2367 void clearHeightMap();
2370 /// The map of accessible positions
2372 /// The north links, true if north position is accessible
2379 I16x16Layer
* _Topologies
;
2382 I16x16Layer
* _HeightMap
;
2384 static uint16 _MaskMap
[16];
2385 static bool _Initialized
;
2389 CSingleLayerCell::CSingleLayerCell(CWorldMap
const& worldMapPtr
)
2390 : CRootCell(worldMapPtr
)
2392 for (uint i
=0; i
<16; ++i
)
2404 for (uint i
=0; i
<16; ++i
)
2405 _MaskMap
[i
] = (1 << (15-i
));
2406 _Initialized
= true;
2411 CCellLinkage
CSingleLayerCell::getCellLink(CWorldPosition
const& wpos
) const
2413 uint xi
= wpos
.xCoord().getUnitId();
2414 uint yi
= wpos
.yCoord().getUnitId();
2418 l
|= ((xi
> 0 && testPos(yi
, xi
-1)) || (xi
== 0 && (_WLinks
&_MaskMap
[yi
]))) ? 0 : CCellLinkage::WestSlotMask
;
2419 l
|= ((xi
< 15 && testPos(yi
, xi
+1)) || (xi
== 15 && (_ELinks
&_MaskMap
[yi
]))) ? 0 : CCellLinkage::EastSlotMask
;
2420 l
|= ((yi
> 0 && testPos(yi
-1, xi
)) || (yi
== 0 && (_SLinks
&_MaskMap
[xi
]))) ? 0 : CCellLinkage::SouthSlotMask
;
2421 l
|= ((yi
< 15 && testPos(yi
+1, xi
)) || (yi
== 15 && (_NLinks
&_MaskMap
[xi
]))) ? 0 : CCellLinkage::NorthSlotMask
;
2427 uint32
CSingleLayerCell::nbUsedSlots(CMapPosition
const& pos
) const
2429 return testPos(pos
) ? 1 : 0;
2433 sint32
CSingleLayerCell::maxUsedSlot(CMapPosition
const& pos
) const
2435 return testPos(pos
) ? 0 : -1;
2439 bool CSingleLayerCell::isSlotUsed(CMapPosition
const& pos
, CSlot
const& slot
) const
2441 return slot
.slot() == 0 && testPos(pos
);
2445 uint
CSingleLayerCell::getTopology(CWorldPosition
const& wpos
) const
2447 return (_Topologies
!= NULL
) ? _Topologies
->get(wpos
.yCoord().getUnitId(), wpos
.xCoord().getUnitId()) : 0;
2451 sint
CSingleLayerCell::getHeight(CWorldPosition
const& wpos
) const
2453 return (_HeightMap
!= NULL
) ? _HeightMap
->get(wpos
.yCoord().getUnitId(), wpos
.xCoord().getUnitId()) : 0;
2457 bool CSingleLayerCell::testPos(CMapPosition
const& pos
) const
2459 return testPos(pos
.yCoord().getUnitId(), pos
.xCoord().getUnitId());
2463 void CSingleLayerCell::setPos(CMapPosition
const& pos
, bool p
)
2465 setPos(pos
.yCoord().getUnitId(), pos
.xCoord().getUnitId(), p
);
2469 void CSingleLayerCell::setTopologies(I16x16Layer
* topology
)
2472 _Topologies
= topology
;
2476 void CSingleLayerCell::setHeightMap(I16x16Layer
* heightMap
)
2480 _HeightMap
= heightMap
;
2484 void CSingleLayerCell::clearHeightMap()
2490 //////////////////////////////////////////////////////////////////////////////
2493 * A Multiple layer 16x16 cell (maximum 3 layers)
2494 * \author Benjamin Legros
2495 * \author Nevrax France
2498 class CMultiLayerCell
2504 friend class CMultiLayerCell
; // for build features.
2506 CCellLinkage
const& getCellLinkage(CMapPosition
const& pos
) const;
2507 uint8
getTopology(CMapPosition
const& pos
) const;
2508 I16x16Layer
* getHeightMap() { return _HeightMap
; }
2511 CCellLinkage
& cellLinkage(CMapPosition
const& pos
);
2514 CCellLinkage _Layer
[16*16];
2515 uint8 _Topology
[16*16];
2516 I16x16Layer
* _HeightMap
;
2520 CMultiLayerCell(CWorldMap
const& worldMapPtr
);
2521 virtual ~CMultiLayerCell();
2523 CCellLinkage
getCellLink(CWorldPosition
const& wpos
) const;
2524 uint32
nbUsedSlots(CMapPosition
const& pos
) const;
2525 sint32
maxUsedSlot(CMapPosition
const& pos
) const;
2526 bool isSlotUsed(CMapPosition
const& pos
, CSlot
const& slot
) const;
2527 uint
getTopology(CWorldPosition
const& wpos
) const;
2528 sint
getHeight(CWorldPosition
const& wpos
) const;
2530 virtual void serial(NLMISC::IStream
& f
);
2532 void setLinks(CWorldPosition
const& wpos
, CCellLinkage links
);
2533 void setTopology(CWorldPosition
const& wpos
, uint topology
);
2534 void setHeightMap(CSlot
const& slot
, I16x16Layer
* heightMap
);
2535 void clearHeightMap();
2538 // each layer is allocated in memory
2539 // the 3 layers available
2540 CCellLayer
* _Layers
[3];
2544 CCellLinkage
const& CMultiLayerCell::CCellLayer::getCellLinkage(CMapPosition
const& pos
) const
2546 return _Layer
[pos
.cellUnitFastIndex()]; //yCoord().getUnitId()][pos.xCoord().getUnitId()];
2550 uint8
CMultiLayerCell::CCellLayer::getTopology(CMapPosition
const& pos
) const
2552 return _Topology
[pos
.cellUnitFastIndex()]; //yCoord().getUnitId()][pos.xCoord().getUnitId()];
2556 CCellLinkage
& CMultiLayerCell::CCellLayer::cellLinkage(CMapPosition
const& pos
)
2558 return _Layer
[pos
.cellUnitFastIndex()]; //yCoord().getUnitId()][pos.xCoord().getUnitId()];
2562 CMultiLayerCell::CMultiLayerCell(CWorldMap
const& worldMapPtr
)
2563 : CRootCell(worldMapPtr
)
2571 CMultiLayerCell::~CMultiLayerCell()
2573 delete [] _Layers
[0];
2574 delete [] _Layers
[1];
2575 delete [] _Layers
[2];
2579 CCellLinkage
CMultiLayerCell::getCellLink(CWorldPosition
const& wpos
) const
2582 nlassert(wpos
.isValid());
2584 CCellLayer
* cellLayerPt
=_Layers
[wpos
.slot()];
2585 return (!cellLayerPt
) ? CCellLinkage() : cellLayerPt
->getCellLinkage(wpos
);
2589 uint32
CMultiLayerCell::nbUsedSlots(CMapPosition
const& pos
) const
2592 for (uint32 slot
=0; slot
<3; ++slot
)
2594 CCellLayer
* cellLayerPt
=_Layers
[slot
];
2595 if (cellLayerPt
&& cellLayerPt
->cellLinkage(pos
).used())
2602 sint32
CMultiLayerCell::maxUsedSlot(CMapPosition
const& pos
) const
2605 for (uint32 slot
=0; slot
<3; ++slot
)
2607 CCellLayer
* cellLayerPt
=_Layers
[slot
];
2608 if (cellLayerPt
&& cellLayerPt
->cellLinkage(pos
).used())
2615 bool CMultiLayerCell::isSlotUsed(CMapPosition
const& pos
, CSlot
const& slot
) const
2617 if (!slot
.isValid())
2619 CCellLayer
* cellLayerPt
= _Layers
[slot
.slot()];
2620 return (cellLayerPt
&& cellLayerPt
->cellLinkage(pos
).used());
2624 uint
CMultiLayerCell::getTopology(CWorldPosition
const& wpos
) const
2627 nlassert(wpos
.isValid());
2629 CCellLayer
* cellLayerPt
= _Layers
[wpos
.slot()];
2630 return (!cellLayerPt
) ? 0 : cellLayerPt
->getTopology(wpos
);
2634 sint
CMultiLayerCell::getHeight(CWorldPosition
const& wpos
) const
2637 nlassert(wpos
.isValid());
2639 CCellLayer
* cellLayerPt
= _Layers
[wpos
.slot()];
2640 return (!cellLayerPt
|| !cellLayerPt
->getHeightMap()) ? 0 : cellLayerPt
->getHeightMap()->get(wpos
.yCoord().getUnitId(), wpos
.xCoord().getUnitId());
2644 void CMultiLayerCell::setLinks(CWorldPosition
const& wpos
, CCellLinkage links
)
2647 nlassert(wpos
.isValid());
2649 CCellLayer
* cellLayerPt
= _Layers
[wpos
.slot()];
2652 cellLayerPt
= new CCellLayer();
2653 _Layers
[wpos
.slot()] = cellLayerPt
;
2655 for (uint i
=0; i
<16*16; ++i
)
2656 cellLayerPt
->_Topology
[i
] = 0;
2657 cellLayerPt
->_HeightMap
= NULL
;
2660 nlassert(cellLayerPt
);
2662 cellLayerPt
->cellLinkage(wpos
)=links
;
2666 void CMultiLayerCell::setTopology(CWorldPosition
const& wpos
, uint topology
)
2669 nlassert(topology
< 256);
2670 nlassert(wpos
.isValid());
2672 CCellLayer
* cellLayerPt
= _Layers
[wpos
.slot()];
2675 nlassert(cellLayerPt
);
2677 cellLayerPt
->_Topology
[wpos
.cellUnitFastIndex()]=(uint8
)topology
;
2681 void CMultiLayerCell::setHeightMap(CSlot
const& slot
, I16x16Layer
* heightMap
)
2684 nlassert(slot
.isValid());
2686 CCellLayer
* cellLayerPt
= _Layers
[slot
.slot()];
2689 nlassert(cellLayerPt
);
2691 if (cellLayerPt
->_HeightMap
)
2692 delete cellLayerPt
->_HeightMap
;
2693 cellLayerPt
->_HeightMap
= heightMap
;
2697 void CMultiLayerCell::clearHeightMap()
2699 for (CSlot
i(0); i
.isValid(); ++i
)
2701 CCellLayer
* cellLayerPt
= _Layers
[i
.slot()];
2704 delete cellLayerPt
->_HeightMap
;
2705 cellLayerPt
->_HeightMap
=NULL
;
2710 //////////////////////////////////////////////////////////////////////////////
2713 * A CSuperCell of basically 16x16 CCells
2714 * \author Benjamin Legros
2715 * \author Nevrax France
2721 CSuperCell(CWorldMap
const& worldMap
);
2722 virtual ~CSuperCell();
2724 // get a const cell (might be NULL)
2725 CRootCell
const* getRootCellCst(CMapPosition
const& pos
) const;
2726 // get a const cell (might be NULL)
2727 CRootCell
* getRootCell(CMapPosition
const& pos
);
2729 void updateTopologyRef(CWorldMap
* worldMap
);
2730 void countCells(uint
& compute
, uint
& white
, uint
& simple
, uint
& multi
, uint
& other
) const;
2733 void setRootCell(CMapPosition
const& pos
, CRootCell
* cell
);
2736 // compute cell selectors
2740 CComputeCell
* getComputeCell(CMapPosition
const& pos
);
2742 CComputeCell
const* getComputeCell(CMapPosition
const& pos
) const;
2744 // get a slot in a cell
2745 CUnitSlot
getUnitSlot(CWorldPosition
const& wpos
) const;
2746 // get a slot in super cell
2747 CUnitSlot
& getUnitSlot(CWorldPosition
const& wpos
);
2748 TCellUnit
& getCellUnit(CMapPosition
const& pos
);
2750 void serial(NLMISC::IStream
& f
);
2752 void markRootCell(uint32
const flag
) const;
2755 // a super cell is composed of 16x16 pointers to cells, initially NULL
2756 CRootCell
* _Grid
[16*16];
2757 CWorldMap
const& _WorldMap
;
2761 CSuperCell::CSuperCell(CWorldMap
const& worldMap
)
2762 : _WorldMap(worldMap
)
2764 for (uint i
=0;i
<16*16;i
++)
2769 CSuperCell::~CSuperCell()
2771 for (uint i
=0;i
<16*16;i
++)
2777 CRootCell
const* CSuperCell::getRootCellCst(CMapPosition
const& pos
) const
2779 return _Grid
[pos
.rootCellFastIndex()];
2783 CRootCell
* CSuperCell::getRootCell(CMapPosition
const& pos
)
2785 return _Grid
[pos
.rootCellFastIndex()];
2789 void CSuperCell::setRootCell(CMapPosition
const& pos
, CRootCell
* cell
)
2791 CRootCell
*& rootCell
= _Grid
[pos
.rootCellFastIndex()];
2799 CComputeCell
* CSuperCell::getComputeCell(CMapPosition
const& pos
)
2801 CRootCell
*& rootCell
= _Grid
[pos
.rootCellFastIndex()];
2803 rootCell
= new CComputeCell(_WorldMap
);
2807 nlassert(dynamic_cast<CComputeCell
*>(rootCell
));
2809 return static_cast<CComputeCell
*>(rootCell
);
2813 CComputeCell
const* CSuperCell::getComputeCell(CMapPosition
const& pos
) const
2815 CRootCell
const* const& rootCell
= _Grid
[pos
.rootCellFastIndex()];
2819 nlassert(dynamic_cast<CComputeCell
const*>(rootCell
));
2821 return static_cast<CComputeCell
const*>(rootCell
);
2825 CUnitSlot
CSuperCell::getUnitSlot(CWorldPosition
const& wpos
) const
2827 CComputeCell
const* cell
= getComputeCell(wpos
);
2828 return !cell
? CUnitSlot() : cell
->getUnitSlotCst(wpos
);
2832 CUnitSlot
& CSuperCell::getUnitSlot(CWorldPosition
const& wpos
)
2834 CComputeCell
* cell
= getComputeCell(wpos
);
2835 return cell
->getUnitSlot(wpos
);
2839 TCellUnit
& CSuperCell::getCellUnit(CMapPosition
const& pos
)
2841 CComputeCell
* cell
= getComputeCell(pos
);
2842 return cell
->getCellUnit(pos
);
2846 void CSuperCell::markRootCell(uint32
const flag
) const
2848 for (uint32 i
=0; i
<256; ++i
)
2851 _Grid
[i
]->setFlag(flag
);
2855 //////////////////////////////////////////////////////////////////////////////
2858 * The A* Path structure, computed by the WorldMap
2859 * \author Benjamin Legros
2860 * \author Nevrax France
2865 friend class CWorldMap
;
2867 std::vector
<CTopology::TTopologyRef
> const& topologiesPath() const { return _TopologiesPath
; }
2868 std::vector
<CTopology::TTopologyRef
>& topologiesPathForCalc() { return _TopologiesPath
; }
2870 CWorldPosition
const& getStartPos() const { return _Start
; }
2871 void setStartPos(CWorldPosition
const& pos
) { _Start
= pos
; }
2873 CWorldPosition
const& getEndPos() const { return _End
; }
2874 void setEndPos(CWorldPosition
const& pos
) { _End
= pos
; }
2877 std::vector
<CTopology::TTopologyRef
> _TopologiesPath
;
2878 CWorldPosition _Start
;
2879 CWorldPosition _End
;
2882 //////////////////////////////////////////////////////////////////////////////
2885 * The Inside A* Path structure, computed by the WorldMap
2886 * \author Benjamin Legros
2887 * \author Nevrax France
2890 class CInsideAStarPath
2892 friend class CWorldMap
;
2894 CWorldPosition
const& getStartPos() const { return _Start
; }
2895 void setStartPos(CWorldPosition
const& pos
) { _Start
= pos
; }
2897 CWorldPosition
const& getEndPos() const { return _End
; }
2898 void setEndPos(CWorldPosition
const& pos
) { _End
= pos
; }
2899 std::vector
<CDirection
>& getStepPathForCalc() { return _StepPath
; }
2902 CWorldPosition _Start
;
2903 CWorldPosition _End
;
2904 std::vector
<CDirection
> _StepPath
;
2907 //////////////////////////////////////////////////////////////////////////////
2910 * A template Heap implementation
2911 * \author Benjamin Legros
2912 * \author Nevrax France
2915 template <typename T
, typename V
>
2919 typedef std::pair
<T
, V
> THeapNode
;
2925 void clear() { _Heap
.resize(1); }
2927 /// test heap is empty or not
2928 bool empty() const { return _Heap
.size() <= 1; }
2930 /// push a value in heap and sort it
2931 void push(T key
, V
const& value
);
2933 /// pop the minimal value of the heap
2936 void backwardLeveling(uint index
);
2938 void forwardLeveling(uint index
);
2940 /// auto check of the internal heap state
2943 uint32
size() { return _Heap
.size(); }
2945 std::vector
<THeapNode
>& heapAsVector() { return _Heap
; }
2948 std::vector
<THeapNode
> _Heap
;
2951 template <typename T
, typename V
>
2952 CHeap
<T
, V
>::CHeap()
2954 // node 0 unused (daniel's trick)
2958 template <typename T
, typename V
>
2959 void CHeap
<T
, V
>::push(T key
, V
const& value
)
2961 _Heap
.push_back(THeapNode(key
, value
));
2963 backwardLeveling((uint
)_Heap
.size()-1);
2966 template <typename T
, typename V
>
2967 V CHeap
<T
, V
>::pop()
2970 nlassert(_Heap
.size() > 1);
2973 // return best value
2974 V ret
= _Heap
[1].second
;
2976 // if only 1 node in heap, pop it and leave
2977 if (_Heap
.size() == 2)
2983 // for more than 1 object, copy last at top and pop last
2984 _Heap
[1] = _Heap
.back();
2987 forwardLeveling (1);
2991 template <typename T
, typename V
>
2992 void CHeap
<T
, V
>::backwardLeveling(uint index
)
2994 while (index
!= 1 && _Heap
[index
].first
< _Heap
[index
/2].first
)
2996 swap(_Heap
[index
], _Heap
[index
/2]);
3001 template <typename T
, typename V
>
3002 void CHeap
<T
, V
>::forwardLeveling(uint index
)
3006 uint min_index
= 2*index
;
3008 // if object has no child, leave
3009 if (min_index
> _Heap
.size()-1)
3012 // choose left or right child
3013 if (min_index
+1 <= _Heap
.size()-1 && _Heap
[min_index
].first
>_Heap
[min_index
+1].first
)
3016 // if swap needed, swap and step one more, else leave
3017 if (_Heap
[index
].first
> _Heap
[min_index
].first
)
3019 swap(_Heap
[index
], _Heap
[min_index
]);
3029 template <typename T
, typename V
>
3030 void CHeap
<T
, V
>::check()
3032 for (uint index
=1; index
<=_Heap
.size()-1; ++index
)
3034 if (2*index
<= _Heap
.size()-1)
3035 nlassert(_Heap
[index
].first
<= _Heap
[2*index
].first
);
3036 if (2*index
+1 <= _Heap
.size()-1)
3037 nlassert(_Heap
[index
].first
<= _Heap
[2*index
+1].first
);
3041 //////////////////////////////////////////////////////////////////////////////
3045 * \author Benjamin Legros
3046 * \author Nevrax France
3052 friend class RYPACSCRUNCH::CPacsCruncher
;
3053 friend class CWorldPosition
;
3054 friend class CTopology::CNeighbourLink
;
3059 // serial -- beware, this method merges, use clear() before to load only one world map
3060 void serial(NLMISC::IStream
& f
);
3062 /// \name User Interface, path finding and complex moves
3064 /// Finds an A* path
3065 bool findAStarPath(CWorldPosition
const& start
, CWorldPosition
const& end
, std::vector
<CTopology::TTopologyRef
>& path
, TAStarFlag denyflags
= Nothing
) const;
3067 /// Finds an A* path
3068 bool findAStarPath(CTopology::TTopologyId
const& start
, CTopology::TTopologyId
const& end
, CAStarPath
& path
, TAStarFlag denyflags
= Nothing
) const;
3070 /// Finds an A* inside a topoly
3071 bool findInsideAStarPath(CWorldPosition
const& start
, CWorldPosition
const& end
, std::vector
<CDirection
>& stepPath
, TAStarFlag denyflags
= Nothing
) const;
3073 /// Moves to given topology, returns false if failed
3074 bool moveTowards(CWorldPosition
& pos
, CTopology::TTopologyRef
const& topology
) const;
3076 /// Moves according a to a given path, returns false if failed
3077 bool move(CWorldPosition
& pos
, CAStarPath
& path
, uint
& currentstep
) const;
3079 /// Moves from a position to another
3080 bool move(CWorldPosition
& pos
, CMapPosition
const& end
, TAStarFlag
const denyFlags
) const;
3083 bool customCheckDiagMove(CWorldPosition
const& pos
, CDirection
const& direction
, RYAI_MAP_CRUNCH::TAStarFlag denyFlags
) const;
3088 void setFlagOnPosAndRadius(CMapPosition
const& pos
, float radius
, uint32 flag
);
3091 CNeighbourhood
neighbours(CWorldPosition
const& wpos
) const;
3093 /// Moves in neighbourhood
3094 bool move(CWorldPosition
& pos
, CDirection
const& direction
) const;
3096 /// Moves in neighbourhood (corner moves don't avoid collision)
3097 bool moveSecure(CWorldPosition
& pos
, CDirection
const& direction
, uint16 maskFlags
= 0xffff) const;
3099 /// Moves in neighbourhood with diag test on both sides
3100 bool moveDiagTestBothSide(CWorldPosition
& pos
, CDirection
const& direction
) const;
3102 CTopology::TTopologyId
getTopologyId(CWorldPosition
const& wpos
) const;
3105 CTopology
const& getTopologyNode(CTopology::TTopologyId
const& id
) const;
3107 CTopology
& getTopologyNode(CTopology::TTopologyId
const& id
);
3109 CGridDirectionLayer
const* getGridDirectionLayer(CWorldPosition
const& pos
, CTopology::TTopologyRef
const& topologyRef
) const;
3111 /// Get CWorldPosition from a CMapPosition and a CSlot
3112 CWorldPosition
getWorldPosition(CMapPosition
const& mapPos
, CSlot
const& slot
) const;
3115 * Get CWorldPosition from a CMapPosition and a TLevel
3116 * Assumes that 0 is the highest level at the given CMapPosition, and greater the level is, lower the height is.
3118 CWorldPosition
getWorldPosition(CMapPosition
const& mapPos
, TLevel level
) const;
3120 // do not initialise a bot with the position & the world position (or u must assume that pos have no fraction).
3121 bool setWorldPosition(AITYPES::TVerticalPos verticalPos
, CWorldPosition
& wpos
, CAIVector
const& pos
, CRootCell
const* originCell
= NULL
) const;
3123 // Alternate setWorldPosition(), with real z instead of TVerticalPos, in millimeters
3124 bool setWorldPosition(sint32 z
, CWorldPosition
& wpos
, CAIVector
const& pos
, CRootCell
const* originCell
= NULL
) const;
3125 // Double version isn't tested !!! Verify it's the same than above sint32 version !
3126 bool setWorldPosition(double z
, CWorldPosition
& wpos
, CAIVector
const& pos
, CRootCell
const* originCell
= NULL
) const;
3128 CTopology::TTopologyRef
getTopologyRef(CTopology::TTopologyId
const& id
) const;
3130 void buildMasterTopo(bool allowWater
, bool allowNogo
);
3132 // checks motion layers
3133 void checkMotionLayer();
3135 void countSuperTopo();
3137 CRootCell
const* getRootCellCst(CMapPosition
const& pos
) const;
3139 CSuperCell
const* getSuperCellCst(CMapPosition
const& pos
) const;
3141 void getBounds(CMapPosition
& min
, CMapPosition
& max
);
3143 CWorldPosition
getSafeWorldPosition(CMapPosition
const& mapPos
, CSlot
const& slot
) const;
3146 CWorldPosition
getWorldPositionGeneration(CMapPosition
const& mapPos
, CSlot
const& slot
) const;
3149 /// Get a world position from a vector position
3151 CWorldPosition
getWorldPosition(T
const& pos
) const
3154 CMapPosition
const mapPos(pos
);
3156 CRootCell
const* cell
= getRootCellCst(mapPos
);
3162 for (uint32 s
=0; s
<3; ++s
)
3164 CSlot
const sslot
= CSlot(s
);
3165 if (!cell
->isSlotUsed(mapPos
, sslot
))
3167 double const sh
= cell
->getHeight(CWorldPosition(cell
,mapPos
,sslot
))*2.0 + 1.0;
3175 return CWorldPosition(cell
,mapPos
,slot
);
3179 // only for generation.
3180 CSuperCell
* getSuperCell(CMapPosition
const& pos
);
3182 CComputeCell
* getComputeCell(CMapPosition
const& pos
);
3184 CRootCell
* getRootCell(CMapPosition
const& pos
);
3186 bool exist(CMapPosition
const& pos
) const;
3188 uint32
nbUsedSlots(CMapPosition
const& pos
) const;
3190 sint32
maxUsedSlot(CMapPosition
const& pos
) const;
3192 bool isSlotUsed(CMapPosition
const& pos
, CSlot slot
) const;
3194 // used in build process.
3195 uint
getTopology(CWorldPosition
const& wpos
) const;
3197 void countCells(uint
& compute
, uint
& white
, uint
& simple
, uint
& multi
, uint
& other
) const;
3200 void setRootCell(CMapPosition
const& pos
, CRootCell
* cell
);
3203 void clearHeightMap();
3206 // compute cell selectors
3209 TCellUnit
& getCellUnit(CMapPosition
const& pos
);
3211 CUnitSlot
& getUnitSlot(CWorldPosition
const& wpos
);
3213 CComputeCell
const* getComputeCellCst(CMapPosition
const& pos
) const;
3215 void resetUnitSlotNLink(CWorldPosition
const& wpos
) { getUnitSlot(wpos
).cellLink().setNSlot(CSlot()); }
3216 void resetUnitSlotSLink(CWorldPosition
const& wpos
) { getUnitSlot(wpos
).cellLink().setSSlot(CSlot()); }
3217 void resetUnitSlotWLink(CWorldPosition
const& wpos
) { getUnitSlot(wpos
).cellLink().setWSlot(CSlot()); }
3218 void resetUnitSlotELink(CWorldPosition
const& wpos
) { getUnitSlot(wpos
).cellLink().setESlot(CSlot()); }
3220 void resetUnitSlot(CWorldPosition
const& wpos
);
3223 CSuperCell
* _GridFastAccess
[256*256];
3226 /// \name Path finding related error handling
3228 enum TFindAStarPathReason
3230 FASPR_NO_REASON
= -1,
3232 FASPR_INVALID_START_POS
,
3233 FASPR_INVALID_END_POS
,
3234 FASPR_INVALID_START_TOPO
,
3235 FASPR_INVALID_END_TOPO
,
3236 FASPR_INCOMPATIBLE_POSITIONS
,
3239 mutable TFindAStarPathReason _LastFASPReason
;
3240 static std::string
toString(TFindAStarPathReason reason
);
3241 enum TFindInsideAStarPathReason
3243 FIASPR_NO_REASON
= -1,
3245 FIASPR_INVALID_START_POS
,
3246 FIASPR_INVALID_END_POS
,
3247 FIASPR_DIFFERENT_TOPO
,
3250 mutable TFindInsideAStarPathReason _LastFIASPReason
;
3251 static std::string
toString(TFindInsideAStarPathReason reason
);
3256 CWorldPosition::CWorldPosition(const CRootCell
*cell
, const CMapPosition
&pos
, const CSlot
&slot
) : CMapPosition(pos
), CSlot(slot
), _RootCell(cell
)
3258 _cellLinkage
=_RootCell
->getCellLink(*this);
3262 CWorldPosition::CWorldPosition(const CRootCell
*cell
, const CMapPosition
&pos
, const CSlot
&slot
,bool generationOnly
) : CMapPosition(pos
), CSlot(slot
), _RootCell(cell
)
3267 CWorldPosition
CWorldPosition::getPosS() const
3269 CWorldPosition
wp(*this);
3275 CWorldPosition
CWorldPosition::getPosN() const
3277 CWorldPosition
wp(*this);
3283 CWorldPosition
CWorldPosition::getPosE() const
3285 CWorldPosition
wp(*this);
3291 CWorldPosition
CWorldPosition::getPosW() const
3293 CWorldPosition
wp(*this);
3299 void CWorldPosition::setPosS(CWorldPosition
& pos
) const
3306 void CWorldPosition::setPosN(CWorldPosition
& pos
) const
3313 void CWorldPosition::setPosE(CWorldPosition
& pos
) const
3320 void CWorldPosition::setPosW(CWorldPosition
& pos
) const
3327 void CWorldPosition::stepS()
3330 nlassert(_RootCell
);
3332 setSlot(_cellLinkage
.SSlot());
3334 nlassert(CSlot::isValid());
3337 if (CMapPosition::stepS()) // check if we have to recalculate the RootCell ..
3339 _RootCell
= getRootCell()->getWorldMapPtr().getRootCellCst(*this); // obtain the new _RootCell pointer
3341 _cellLinkage
= _RootCell
->getCellLink(*this);
3345 void CWorldPosition::stepN()
3348 nlassert(_RootCell
);
3350 setSlot(_cellLinkage
.NSlot());
3352 nlassert(CSlot::isValid());
3355 if (CMapPosition::stepN()) // check if we have to recalculate the RootCell ..
3357 _RootCell
= getRootCell()->getWorldMapPtr().getRootCellCst(*this); // obtain the new _RootCell pointer
3359 _cellLinkage
= _RootCell
->getCellLink(*this);
3363 void CWorldPosition::stepE()
3366 nlassert(_RootCell
);
3368 setSlot(_cellLinkage
.ESlot());
3370 nlassert(CSlot::isValid());
3373 if (CMapPosition::stepE()) // check if we have to recalculate the RootCell ..
3375 _RootCell
= getRootCell()->getWorldMapPtr().getRootCellCst(*this); // obtain the new _RootCell pointer
3377 _cellLinkage
= _RootCell
->getCellLink(*this);
3381 void CWorldPosition::stepW()
3384 nlassert(_RootCell
);
3386 setSlot(_cellLinkage
.WSlot());
3388 nlassert(CSlot::isValid());
3391 if (CMapPosition::stepW()) // check if we have to recalculate the RootCell ..
3393 _RootCell
= getRootCell()->getWorldMapPtr().getRootCellCst(*this); // obtain the new _RootCell pointer
3395 _cellLinkage
= _RootCell
->getCellLink(*this);
3399 bool CWorldPosition::moveS()
3401 if (getCellLinkage().isSSlotValid())
3410 bool CWorldPosition::moveN()
3412 if (getCellLinkage().isNSlotValid())
3421 bool CWorldPosition::moveE()
3423 if (getCellLinkage().isESlotValid())
3432 bool CWorldPosition::moveW()
3434 if (getCellLinkage().isWSlotValid())
3443 NLMISC::CVectorD
CWorldPosition::getPosition() const
3445 NLMISC::CVectorD ret
= toVectorD();
3446 CRootCell
const* cell
= getRootCell();
3448 ret
.z
= cell
->getHeight(*this)*2.0 + 1.0;
3453 sint32
CWorldPosition::getMetricHeight() const
3456 return _RootCell
->getMetricHeight(*this);
3461 CTopology
const& CTopology::TTopologyRef::getCstTopologyNode() const
3464 nlassert(_RootCell
);
3466 return _RootCell
->getCstTopologyNode(getTopologyIndex());
3470 CTopology::TTopologyRef::TTopologyRef(CWorldPosition
const& pos
, CRootCell
const* rootCell
)
3471 : TTopologyId(pos
, rootCell
->getTopology(pos
))
3472 , _RootCell(rootCell
)
3477 // TESTTOREMOVE TODO
3479 nlassert(&_RootCell
->getCstTopologyNode(getTopologyIndex())!=NULL
);
3484 CTopology::TTopologyRef::TTopologyRef(CWorldPosition
const& pos
)
3485 : TTopologyId(pos
, pos
.getRootCell()->getTopology(pos
))
3486 , _RootCell(pos
.getRootCell())
3488 // TESTTOREMOVE TODO
3490 nlassert(&_RootCell
->getCstTopologyNode(getTopologyIndex())!=NULL
);
3495 void CTopology::CNeighbourLink::updateTopologyRef(CWorldMap
* worldMapPtr
)
3497 _Ref
.setRootCell(worldMapPtr
->getRootCell(_Ref
.getMapPosition()));
3498 // TESTTOREMOVE TODO
3500 nlassert(&_Ref
.getCstTopologyNode()!=NULL
);
3505 CWorldMap::CWorldMap()
3507 for (uint i
=0; i
<65536; ++i
)
3508 _GridFastAccess
[i
]=NULL
;
3512 CWorldMap::~CWorldMap()
3514 for (uint i
=0; i
<65536; ++i
)
3515 if (_GridFastAccess
[i
])
3516 delete _GridFastAccess
[i
];
3520 CTopology::TTopologyId
CWorldMap::getTopologyId(CWorldPosition
const& wpos
) const
3522 CRootCell
const* cell
= getRootCellCst(wpos
);
3523 return !cell
? CTopology::TTopologyId() : CTopology::TTopologyId(wpos
, cell
->getTopology(wpos
));
3527 CTopology
const& CWorldMap::getTopologyNode(CTopology::TTopologyId
const& id
) const
3529 CMapPosition pos
= id
.getMapPosition();
3530 uint topo
= id
.getTopologyIndex();
3532 CRootCell
const* cell
= getRootCellCst(pos
);
3536 return cell
->getCstTopologyNode(topo
);
3540 CTopology
& CWorldMap::getTopologyNode(CTopology::TTopologyId
const& id
)
3542 CMapPosition pos
= id
.getMapPosition();
3543 uint topo
= id
.getTopologyIndex();
3545 CRootCell
* cell
= getRootCell(pos
);
3549 return cell
->getTopologyNode(topo
);
3553 CGridDirectionLayer
const* CWorldMap::getGridDirectionLayer(CWorldPosition
const& pos
, CTopology::TTopologyRef
const& topologyRef
) const
3558 CMapPosition tpos
= topologyRef
.getMapPosition();
3560 sint dx
= pos
.xCoord().getFullCellId()-tpos
.xCoord().getFullCellId();
3561 sint dy
= pos
.yCoord().getFullCellId()-tpos
.yCoord().getFullCellId();
3563 if (abs(dx
) > 1 || abs(dy
) > 1)
3566 CTopology
const& node
= topologyRef
.getCstTopologyNode();
3568 if (!node
.DirectionMap
)
3571 CDirectionLayer
* directionLayer
= node
.DirectionMap
->Layers
[pos
.slot()];
3572 if (!directionLayer
)
3575 return directionLayer
->getGridLayer(dy
+1,dx
+1);
3579 CWorldPosition
CWorldMap::getWorldPosition(CMapPosition
const& mapPos
, CSlot
const& slot
) const
3581 return CWorldPosition(getRootCellCst(mapPos
), mapPos
, slot
);
3585 CWorldPosition
CWorldMap::getWorldPosition(CMapPosition
const& mapPos
, TLevel level
) const
3587 CRootCell
const* cell
= getRootCellCst(mapPos
);
3589 std::vector
<sint32
> slots
;
3592 // go through all slots and get their height
3593 for (uint s
=0; s
<3; ++s
)
3597 if (!cell
->isSlotUsed(mapPos
, slot
))
3600 CWorldPosition wPos
= CWorldPosition(cell
, mapPos
, slot
);
3601 slots
.push_back((cell
->getHeight(wPos
) << 2) + s
);
3604 // sort them, from the lowest to the heightest
3605 std::sort(slots
.begin(), slots
.end());
3607 // get heightest slot
3608 level
= (RYAI_MAP_CRUNCH::TLevel
)(slots
.size()-1) - level
;
3610 // if slot exists, return it or invalid position
3611 return (level
< 0 && level
>= (sint
)slots
.size()) ? CWorldPosition() : CWorldPosition(cell
, mapPos
, CSlot(slots
[level
]&3));
3615 bool CWorldMap::setWorldPosition(AITYPES::TVerticalPos verticalPos
, CWorldPosition
& wpos
, CAIVector
const& pos
, CRootCell
const* originCell
) const
3618 CMapPosition
const mapPos(pos
);
3620 CRootCell
const* cell
= originCell
? originCell
: getRootCellCst(mapPos
);
3623 wpos
= CWorldPosition(cell
, mapPos
, slot
, true);
3624 // addon (not agree but no choice).
3628 std::map
<double, CSlot
> orderedSlots
;
3630 for (uint32 s
=0; s
<3; ++s
)
3632 if (!cell
->isSlotUsed(mapPos
, CSlot(s
)))
3635 CSlot
const sslot
= CSlot(s
);
3636 double const sh
= cell
->getHeight(CWorldPosition(cell
,mapPos
,sslot
));
3637 orderedSlots
.insert(std::make_pair(sh
, sslot
));
3640 if (!orderedSlots
.empty())
3642 if (verticalPos
== AITYPES::vp_auto
)
3644 double h
= orderedSlots
.rbegin()->first
;
3645 slot
= orderedSlots
.rbegin()->second
;
3647 else if (verticalPos
== AITYPES::vp_upper
)
3649 double h
= orderedSlots
.rbegin()->first
;
3650 slot
= orderedSlots
.rbegin()->second
;
3652 else if (verticalPos
== AITYPES::vp_lower
)
3654 double h
= orderedSlots
.begin()->first
;
3655 slot
= orderedSlots
.begin()->second
;
3657 else if (verticalPos
== AITYPES::vp_middle
)
3659 if (orderedSlots
.size() > 1)
3661 orderedSlots
.erase(orderedSlots
.rbegin()->first
);
3662 double h
= orderedSlots
.rbegin()->first
;
3663 slot
= orderedSlots
.rbegin()->second
;
3667 double h
= orderedSlots
.begin()->first
;
3668 slot
= orderedSlots
.begin()->second
;
3673 nlwarning("invalid vertical pos type !");
3677 if (!slot
.isValid())
3679 wpos
= CWorldPosition(cell
,mapPos
,slot
,true);
3683 wpos
= CWorldPosition(cell
,mapPos
,slot
);
3688 CTopology::TTopologyRef
CWorldMap::getTopologyRef(CTopology::TTopologyId
const& id
) const
3690 return CTopology::TTopologyRef(id
, const_cast<CRootCell
*>(getRootCellCst(id
.getMapPosition())));
3694 CRootCell
const* CWorldMap::getRootCellCst(CMapPosition
const& pos
) const
3696 CSuperCell
const* scell
= getSuperCellCst(pos
);
3697 return !scell
? NULL
: scell
->getRootCellCst(pos
);
3701 CSuperCell
const* CWorldMap::getSuperCellCst(CMapPosition
const& pos
) const
3703 return _GridFastAccess
[pos
.superCellFastIndex()];
3707 CWorldPosition
CWorldMap::getWorldPositionGeneration(CMapPosition
const& mapPos
, CSlot
const& slot
) const
3709 return CWorldPosition(getRootCellCst(mapPos
),mapPos
,slot
,true); // without assuring cellLink is valid .. :(
3713 CWorldPosition
CWorldMap::getSafeWorldPosition(CMapPosition
const& mapPos
, CSlot
const& slot
) const
3715 CRootCell
const* cell
= getRootCellCst(mapPos
);
3716 return (cell
&& cell
->isSlotUsed(mapPos
, slot
)) ? CWorldPosition(getRootCellCst(mapPos
),mapPos
,slot
) : CWorldPosition(); // without assuring cellLink is valid .. :(
3720 CSuperCell
* CWorldMap::getSuperCell(CMapPosition
const& pos
)
3722 CSuperCell
* superCellPtr
= _GridFastAccess
[pos
.superCellFastIndex()];
3725 _GridFastAccess
[pos
.superCellFastIndex()] = superCellPtr
=new CSuperCell(*this);
3728 nlassert(superCellPtr
);
3730 return superCellPtr
;
3734 CComputeCell
* CWorldMap::getComputeCell(CMapPosition
const& pos
)
3736 return getSuperCell(pos
)->getComputeCell(pos
);
3740 CRootCell
* CWorldMap::getRootCell(CMapPosition
const& pos
)
3742 CSuperCell
* scell
= getSuperCell(pos
);
3743 return !scell
? NULL
: scell
->getRootCell(pos
);
3747 bool CWorldMap::exist(CMapPosition
const& pos
) const
3749 return getRootCellCst(pos
)!=NULL
;
3753 uint32
CWorldMap::nbUsedSlots(CMapPosition
const& pos
) const
3755 CRootCell
const* cell
= getRootCellCst(pos
);
3756 return !cell
? 0:cell
->nbUsedSlots(pos
);
3760 sint32
CWorldMap::maxUsedSlot(CMapPosition
const& pos
) const
3762 CRootCell
const* cell
= getRootCellCst(pos
);
3763 return !cell
? -1 : cell
->maxUsedSlot(pos
);
3767 bool CWorldMap::isSlotUsed(CMapPosition
const& pos
, CSlot slot
) const
3769 CRootCell
const* cell
= getRootCellCst(pos
);
3770 return !cell
? false : cell
->isSlotUsed(pos
, slot
);
3774 uint
CWorldMap::getTopology(CWorldPosition
const& wpos
) const
3776 CRootCell
const* cell
= wpos
.getRootCell(); //getRootCellCst(wpos);
3777 return !cell
? 0 : cell
->getTopology(wpos
);
3781 void CWorldMap::setRootCell(CMapPosition
const& pos
, CRootCell
* cell
)
3783 getSuperCell(pos
)->setRootCell(pos
, cell
);
3787 TCellUnit
& CWorldMap::getCellUnit(CMapPosition
const& pos
)
3789 return getComputeCell(pos
)->getCellUnit(pos
);
3793 CUnitSlot
& CWorldMap::getUnitSlot(CWorldPosition
const& wpos
)
3795 return getComputeCell(wpos
)->getUnitSlot(wpos
);
3799 CComputeCell
const* CWorldMap::getComputeCellCst(CMapPosition
const& pos
) const
3801 CSuperCell
const* scell
= getSuperCellCst(pos
);
3802 return !scell
? NULL
: scell
->getComputeCell(pos
);
3806 void CWorldMap::resetUnitSlot(CWorldPosition
const& wpos
)
3808 CUnitSlot
& us
= getUnitSlot(wpos
);
3810 if (us
.getCellLink().isNSlotValid()) resetUnitSlotSLink(wpos
.getPosN());
3811 if (us
.getCellLink().isSSlotValid()) resetUnitSlotNLink(wpos
.getPosS());
3812 if (us
.getCellLink().isWSlotValid()) resetUnitSlotELink(wpos
.getPosW());
3813 if (us
.getCellLink().isESlotValid()) resetUnitSlotWLink(wpos
.getPosE());
3819 std::string
CWorldMap::toString(TFindAStarPathReason reason
)
3823 case FASPR_NO_ERROR
:
3824 return "FASPR_NO_ERROR";
3825 case FASPR_INVALID_START_POS
:
3826 return "FASPR_INVALID_START_POS";
3827 case FASPR_INVALID_END_POS
:
3828 return "FASPR_INVALID_END_POS";
3829 case FASPR_INVALID_START_TOPO
:
3830 return "FASPR_INVALID_START_TOPO";
3831 case FASPR_INVALID_END_TOPO
:
3832 return "FASPR_INVALID_END_TOPO";
3833 case FASPR_INCOMPATIBLE_POSITIONS
:
3834 return "FASPR_INCOMPATIBLE_POSITIONS";
3835 case FASPR_NOT_FOUND
:
3836 return "FIASPR_NOT_FOUND";
3838 return "UnknownReason(" + NLMISC::toString((int)reason
) + ")";
3843 std::string
CWorldMap::toString(TFindInsideAStarPathReason reason
)
3847 case FIASPR_NO_ERROR
:
3848 return "FIASPR_NO_ERROR";
3849 case FIASPR_INVALID_START_POS
:
3850 return "FIASPR_INVALID_START_POS";
3851 case FIASPR_INVALID_END_POS
:
3852 return "FIASPR_INVALID_END_POS";
3853 case FIASPR_DIFFERENT_TOPO
:
3854 return "FIASPR_DIFFERENT_TOPO";
3855 case FIASPR_NOT_FOUND
:
3856 return "FIASPR_NOT_FOUND";
3858 return "UnknownReason(" + NLMISC::toString((int)reason
) + ")";
3864 //////////////////////////////////////////////////////////////////////////////
3866 class CTimeEstimator
3869 CTimeEstimator(uint total
);
3871 void step(char const* str
);
3874 NLMISC::TTime _StartTime
;
3875 NLMISC::TTime _LastTime
;
3878 uint _CurrentCounter
;
3881 double _AverageSpeed
;
3883 std::string
secToString(sint sec
);
3887 CTimeEstimator::CTimeEstimator(uint total
)
3888 : _TotalCounter(total
)
3889 , _CurrentCounter(0)
3891 , _AverageSpeed(-1.0)
3893 _StartTime
= NLMISC::CTime::getLocalTime();
3894 _LastTime
= _StartTime
;
3898 void CTimeEstimator::step(char const* str
)
3902 NLMISC::TTime currentTime
= NLMISC::CTime::getLocalTime();
3904 if (currentTime
-_LastTime
> 2000)
3906 NLMISC::TTime dt
= currentTime
-_LastTime
;
3907 double speed
= 1000.0*(_CurrentCounter
-_LastCounter
)/dt
;
3909 _AverageSpeed
= (_AverageSpeed
< 0.0 ? speed
: _AverageSpeed
*0.98 + speed
*0.02);
3911 uint remaining
= _TotalCounter
-_CurrentCounter
;
3913 NLMISC::TTime ellapsedTime
= currentTime
-_StartTime
;
3914 NLMISC::TTime remainingTime
= (NLMISC::TTime
)(remaining
*1000/_AverageSpeed
);
3916 double percent
= 100.0*_CurrentCounter
/_TotalCounter
;
3917 uint maxpercent
= (percent
> 100.0 ? 100 : (uint
)percent
);
3918 uint linesize
= maxpercent
/5;
3920 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());
3922 _LastCounter
= _CurrentCounter
;
3923 _LastTime
= currentTime
;
3928 std::string
CTimeEstimator::secToString(sint sec
)
3930 return NLMISC::toString(sec
/60)+"m"+NLMISC::toString(sec
%60)+"s";