Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / ai_service / ai_entity_matrix.h
blob729ce7d5d1d3efd698319ec2e9c99eda88525b74
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef RYAI_ENTITY_MATRIX_H
20 #define RYAI_ENTITY_MATRIX_H
22 #include "nel/misc/types_nl.h"
23 #include "nel/misc/common.h"
24 #include "nel/misc/debug.h"
25 #include "nel/misc/command.h"
27 #include <map>
28 #include <vector>
29 #include <string>
31 #include "ai_share/ai_entity_physical_list_link.h"
32 #include "ai_pos.h"
34 //--------------------------------------------------------------------------
35 // The CAIEntityMatrixIteratorTblLinear class
36 //--------------------------------------------------------------------------
37 // This class uses a vector of horizontal run lengths to represent
38 // the aea to be scanned.
39 // The form represented by the data is assumed to be symetrical in both x and y.
40 // Linear tables use a better RAM access patern than random access tables
41 // and should be used whenever possible
43 class CAIEntityMatrixIteratorTblLinear
45 public:
46 struct STblEntry
48 STblEntry() {}
49 STblEntry(uint32 runLength, sint32 previousRunLength)
51 RunLength=(uint16)(runLength-1); // we assume all runs are at least 1 unit long - this is the excess
52 StartDx=(sint16)(-(previousRunLength/2)-(((sint32)runLength)/2));
54 #ifdef NL_DEBUG
55 nlassert(runLength>0); // runs must be at least 1 unit long
56 nlassert(runLength<32768); // this is the limit where StartDx runs out of bits
57 nlassert(previousRunLength>=0);
58 nlassert(previousRunLength<32768);
59 #endif
62 uint16 RunLength;
63 sint16 StartDx;
65 typedef std::vector<STblEntry> TTbl;
66 typedef TTbl::iterator iterator;
68 inline CAIEntityMatrixIteratorTblLinear();
69 inline CAIEntityMatrixIteratorTblLinear(uint32 *runLengths,uint32 count);
71 inline void push_back(uint32 runLength, sint32 previousRunLength);
72 inline const STblEntry &operator[](uint32 idx) const;
73 inline const iterator begin() const;
74 inline const iterator end() const;
75 inline uint32 size() const;
77 private:
78 TTbl _tbl;
82 //--------------------------------------------------------------------------
83 // The CAIEntityMatrixIteratorTblRandom class
84 //--------------------------------------------------------------------------
85 // This class uses a vector of xy offsets to apply to the 'read position' ptr
86 // as it iterates across the grid.
87 // The first xy offset is applied at initalisation time in order to allow for
88 // the use of tables that do not scan the '0,0' cell.
89 // These tables use a less efficient RAM access pattern than Linear tables but
90 // benefit from a higher degree of control over the area scanned and the order
91 // of scanning.
93 class CAIEntityMatrixIteratorTblRandom
95 public:
96 struct STblEntry
98 STblEntry() {}
99 STblEntry(sint32 dxdy) { dxdy=dxdy; }
100 STblEntry(sint16 dx, sint16 dy) { dx=dx; dy=dy; }
101 union
103 struct { sint16 dx, dy; };
104 uint32 dxdy;
107 typedef std::vector<STblEntry> TTbl;
108 typedef TTbl::iterator iterator;
110 inline CAIEntityMatrixIteratorTblRandom();
112 inline void push_back(sint16 dx,sint16 dy);
113 inline const STblEntry &operator[](uint32 idx) const;
114 inline const iterator begin() const;
115 inline const iterator end() const;
116 inline uint32 size() const;
118 private:
119 TTbl _tbl;
123 //--------------------------------------------------------------------------
124 // The CAIEntityMatrix class
125 //--------------------------------------------------------------------------
127 template <class T>
128 class CAIEntityMatrix :
129 public NLMISC::CDbgRefCount<CAIEntityMatrix<T> >
131 public:
133 -----------------------------------------------------------------------------------------------------
134 class CAIEntityMatrix<T>::CCellTblIteratorRandom
136 This class provides an iterator for iterating across the cells of a matrix '_matrix' following the
137 pattern described by a cell iteration table '_tbl'
139 An iterator '_it' refferences the current position in '_tbl'
141 A compact coordinate pair '_xy' reffernces the current position in '_matrix'
142 Note that because the matrix super imposes coordinates with the same low byte, the upper bytes of
143 the '_xy' coordinates is needed for position proximity tests
144 -----------------------------------------------------------------------------------------------------
146 class CCellTblIteratorRandom
148 public:
150 inline CCellTblIteratorRandom():
151 _matrix(NULL), _tbl(NULL), _x(0), _y(0)
155 inline CCellTblIteratorRandom(const CAIEntityMatrix<T> *matrix,const CAIEntityMatrixIteratorTblRandom *tbl,const CAIVector &pos):
156 _matrix(matrix), _tbl(tbl), _x((uint16)pos.x().asInt16Meters()), _y((uint16)pos.y().asInt16Meters())
158 _it=_tbl->begin();
159 // apply the first entry in the iterator table in order to setup the start position correctly
160 ++*this;
163 inline const CEntityListLink<T> * operator*() const
165 const typename CAIEntityMatrix<T>::SMatrixLine &line =(*_matrix)[_yl];
166 const CEntityListLink<T> &cellEntityListLink=line[_xl];
167 return &cellEntityListLink;
170 inline const CCellTblIteratorRandom &operator++()
172 #ifdef NL_DEBUG
173 // make sure we aren't trying to access an uninitialised iterator
174 nlassert(_it!=_tbl->end());
175 #endif
177 _x+=(*_it).dx;
178 _y+=(*_it).dy;
179 ++_it;
181 return *this;
184 inline const CCellTblIteratorRandom &operator=(const CCellTblIteratorRandom &other)
186 _xy= other._xy;
187 _matrix= other._matrix;
188 _tbl= other._tbl;
189 _it= other._it;
191 return *this;
194 inline bool end() const
196 return _it==_tbl->end();
199 inline const uint32 &xy() const { return _xy; }
200 inline const uint16 &x() const { return _x; }
201 inline const uint16 &y() const { return _y; }
202 inline const uint8 &xl() const { return _xl; }
203 inline const uint8 &xh() const { return _xh; }
204 inline const uint8 &yl() const { return _yl; }
205 inline const uint8 &yh() const { return _yh; }
207 inline const CAIEntityMatrix<T> *matrix() const
209 return _matrix;
212 private:
213 union
215 uint32 _xy;
216 struct { uint16 _x, _y; };
217 struct { uint8 _xl, _xh, _yl, _yh; };
219 const CAIEntityMatrix<T> *_matrix;
220 const CAIEntityMatrixIteratorTblRandom *_tbl;
221 CAIEntityMatrixIteratorTblRandom::iterator _it;
225 -----------------------------------------------------------------------------------------------------
226 class CAIEntityMatrix<T>::CCellTblIteratorLinear
228 This class provides an iterator for iterating across the cells of a matrix '_matrix' following the
229 pattern described by a cell iteration table '_tbl'
231 An iterator '_it' refferences the current position in '_tbl'
232 The _runLengthRemaining property is setup each time the iterator _it is advanced by the ++operator.
233 Subsequent calls to operator++() will only increment _it if _runLengthRemaining==0
235 A compact coordinate pair '_xy' reffernces the current position in '_matrix'
236 Note that because the matrix super imposes coordinates with the same low byte, the upper bytes of
237 the '_xy' coordinates is needed for position proximity tests
238 -----------------------------------------------------------------------------------------------------
240 class CCellTblIteratorLinear
242 public:
243 inline CCellTblIteratorLinear():
244 _x(0), _y(0), _matrix(NULL), _tbl(NULL), _runLengthRemaining(0)
248 inline CCellTblIteratorLinear(const CAIEntityMatrix<T> *matrix,const CAIEntityMatrixIteratorTblLinear *tbl,const CAIVector &pos):
249 _x((uint16)pos.x().asInt16Meters()), _y((uint16)pos.y().asInt16Meters()), _matrix(matrix), _tbl(tbl)
251 #ifdef NL_DEBUG
252 nlassert(_tbl!=NULL);
253 nlassert(_tbl->size()>0);
254 nlassert(_tbl->size()<32768); // a numeric over-run limit
255 nlassert(_matrix!=NULL);
256 #endif
258 // setup the iterator to point to the strat of the iterator table and setup properties accordingly
259 _it=_tbl->begin();
260 _runLengthRemaining=(*_tbl)[0].RunLength;
261 _x-=(sint16)(_runLengthRemaining/2);
262 _y-=(sint16)(_tbl->size()/2);
265 inline const CEntityListLink<T> *operator*() const
267 return &(*_matrix)[_yl][_xl];
270 inline const CCellTblIteratorLinear &operator++()
272 #ifdef NL_DEBUG
273 // make sure we aren't trying to access an uninitialised iterator
274 nlassert(_it!=_tbl->end());
275 #endif
277 // if we're not at the end of the current run continue run else move on to next line
278 if (_runLengthRemaining!=0)
280 --_runLengthRemaining;
281 ++_x;
283 else
285 ++_it;
286 if (_it==_tbl->end())
287 return *this;
289 _runLengthRemaining=(*_it).RunLength;
290 _x+=(*_it).StartDx;
291 ++_y;
294 return *this;
297 inline const CCellTblIteratorLinear &operator=(const CCellTblIteratorLinear &other)
299 _xy= other._xy;
300 _matrix= other._matrix;
301 _tbl= other._tbl;
302 _it= other._it;
303 _runLengthRemaining= other._runLengthRemaining;
305 return *this;
308 inline bool end() const
310 return _it==_tbl->end();
313 inline const uint32 &xy() const { return _xy; }
314 inline const uint16 &x() const { return _x; }
315 inline const uint16 &y() const { return _y; }
316 inline const uint8 &xl() const { return _xl; }
317 inline const uint8 &xh() const { return _xh; }
318 inline const uint8 &yl() const { return _yl; }
319 inline const uint8 &yh() const { return _yh; }
321 inline const CAIEntityMatrix<T> *matrix() const
323 return _matrix;
326 private:
327 union
329 uint32 _xy;
330 struct { uint16 _x, _y; };
331 struct { uint8 _xl, _xh, _yl, _yh; };
333 const CAIEntityMatrix<T> *_matrix;
334 const CAIEntityMatrixIteratorTblLinear *_tbl;
335 CAIEntityMatrixIteratorTblLinear::iterator _it;
336 uint32 _runLengthRemaining;
340 -----------------------------------------------------------------------------------------------------
341 class CAIEntityMatrix<T>::CEntityIteratorTemplate
342 class CAIEntityMatrix<T>::CEntityIteratorLinear
343 class CAIEntityMatrix<T>::CEntityIteratorRandom
345 This class provides an iterator for iterating across the entities listed in the cells of a matrix
346 '_matrix' following the pattern described by a cell iteration table '_tbl'
348 The class is composed of a CCellTblIteratorLinear '_cellIt' responsible for iterating across the matrix
349 and an entity pointer '_entity' used for iterating over the entities in each matrix cell
351 Note that unlinking, moving or deleting the entity refferenced by a CEntityIteratorLinear iterator
352 invalidates it.
353 -----------------------------------------------------------------------------------------------------
356 template <class CIt,class CTbl>
357 class CEntityIteratorTemplate
359 public:
361 inline CEntityIteratorTemplate() : _cellIt()
363 _entity=NULL;
366 inline CEntityIteratorTemplate(const CAIEntityMatrix<T> *matrix,const CTbl *tbl,const CAIVector &pos) : _cellIt(matrix,tbl,pos)
368 // get a pointer to the list link for the first entity in the cell
369 // _entity=(*_cellIt)->next();
371 _entity=(*_cellIt);
372 ++*this;
374 // if the cell is empty then start iterating to find a non-empty cell
375 // if (_entity->unlinked())
376 // ++*this;
379 inline CEntityIteratorTemplate(const CAIEntityMatrix<T> *matrix,const CTbl *tbl,const T *entity) : _cellIt(matrix,tbl,entity->pos())
381 // get a poniter to the list link for the first entity in the same cell as the given entity
382 // _entity=(*_cellIt)->next();
384 _entity=(*_cellIt);
385 ++*this;
388 inline T &operator*()
390 #ifdef NL_DEBUG
391 // make sure we aren't trying to access passed the end of list
392 nlassert(!end());
393 #endif
395 return *NLMISC::safe_cast<T *>(_entity->entity());
398 inline const CEntityIteratorTemplate &operator++()
400 #ifdef NL_DEBUG
402 // if you are on a breakpoint here it is because you've tried to do a ++ on an iterator
403 // that has reached its end marker
404 nlassert(!_cellIt.end());
406 // make sure the entity is in the cell that the iterator reffers to
407 // if you are on a breakpoint here it is because you've moved or removed an entity
408 // and have invalidated this iterator
409 // nlassert(_entity->xyCellAsInt()==_cellIt.xy());
410 #endif
411 // repeat the following loop until either we come to the end of the cell iterator or we find an entity with
412 // xy coords that match our own
415 // try to get the next entity in the cell
416 _entity=_entity->next();
417 if (_entity==*_cellIt)
419 // we're at the end of the entity list for this cell so try to find another cell with a valid entity
422 ++_cellIt;
424 while ( !_cellIt.end()
425 && (*_cellIt)->unlinked());
427 if (_cellIt.end())
428 return *this;
429 _entity=(*_cellIt)->next();
433 while ( !_cellIt.end()
434 && ( _entity->unlinked()
435 || !_entity->entity()->isAt16MetersPos(_cellIt.x(),_cellIt.y())) );
436 // as cells are tiled over the world, we need to check if our entity have a real good match with the scanned position.
437 return *this;
440 inline const CEntityIteratorTemplate<CIt,CTbl> &operator=(const CEntityIteratorTemplate<CIt,CTbl> & other)
442 _cellIt= other._cellIt;
443 _entity= other._entity;
444 return *this;
447 // method for testing iterator for end of current sequence
448 inline bool end()
450 // the following can only happen if there are no more entites in cell and no more deltas in cell iterator tbl
451 return _cellIt.end();
454 private:
455 CIt _cellIt; // the cell iterator
456 const CEntityListLink<T> *_entity; // which entity are we pointing at (within the cell)
459 typedef CEntityIteratorTemplate<CCellTblIteratorLinear,CAIEntityMatrixIteratorTblLinear> CEntityIteratorLinear;
460 typedef CEntityIteratorTemplate<CCellTblIteratorRandom,CAIEntityMatrixIteratorTblRandom> CEntityIteratorRandom;
464 -----------------------------------------------------------------------------------------------------
465 class CAIEntityMatrix<T>::SMatrixLine
467 The class used to represent a matrix row
468 -----------------------------------------------------------------------------------------------------
471 struct SMatrixLine
473 // data
474 CEntityListLink<T> Line[256];
476 // one and only accessor
477 inline CEntityListLink<T> &operator[](uint8 x) const { return const_cast<CEntityListLink<T> &>(Line[x]); }
481 -----------------------------------------------------------------------------------------------------
482 class CAIEntityMatrix methods
483 -----------------------------------------------------------------------------------------------------
486 public:
487 // ctor
488 inline CAIEntityMatrix();
490 // table lookup operator - should be used as myMatrix[y][x]
491 inline SMatrixLine &operator[](uint8 y) const;
493 // methods for initialising iterators
494 inline const typename CAIEntityMatrix<T>::CCellTblIteratorRandom beginCells(const CAIEntityMatrixIteratorTblRandom *tbl,const CAIVector &pos) const;
495 inline const typename CAIEntityMatrix<T>::CEntityIteratorRandom beginEntities(const CAIEntityMatrixIteratorTblRandom *tbl,const CAIVector &pos) const;
497 inline const typename CAIEntityMatrix<T>::CCellTblIteratorLinear beginCells(const CAIEntityMatrixIteratorTblLinear *tbl,const CAIVector &pos) const;
498 inline const typename CAIEntityMatrix<T>::CEntityIteratorLinear beginEntities(const CAIEntityMatrixIteratorTblLinear *tbl,const CAIVector &pos) const;
501 private:
503 -----------------------------------------------------------------------------------------------------
504 class CAIEntityMatrix data
505 -----------------------------------------------------------------------------------------------------
508 SMatrixLine _matrix[256];
511 //--------------------------------------------------------------------------
512 // The CAIEntityMatrix inlines
513 //--------------------------------------------------------------------------
514 template <class T>
515 inline CAIEntityMatrix<T>::CAIEntityMatrix()
519 template <class T>
520 inline typename CAIEntityMatrix<T>::SMatrixLine &CAIEntityMatrix<T>::operator[](uint8 y) const
522 return const_cast<typename CAIEntityMatrix<T>::SMatrixLine &>(_matrix[y]);
525 template <class T>
526 inline const typename CAIEntityMatrix<T>::CCellTblIteratorRandom CAIEntityMatrix<T>::beginCells(const CAIEntityMatrixIteratorTblRandom *tbl, const CAIVector &pos) const
528 return CCellTblIteratorRandom(this,tbl,pos);
531 template <class T>
532 inline const typename CAIEntityMatrix<T>::CEntityIteratorRandom CAIEntityMatrix<T>::beginEntities(const CAIEntityMatrixIteratorTblRandom *tbl, const CAIVector &pos) const
534 CEntityIteratorRandom newIt(this,tbl,pos);
535 return newIt;
538 template <class T>
539 inline const typename CAIEntityMatrix<T>::CCellTblIteratorLinear CAIEntityMatrix<T>::beginCells(const CAIEntityMatrixIteratorTblLinear *tbl, const CAIVector &pos) const
541 return CCellTblIteratorLinear(this,tbl,pos);
544 template <class T>
545 inline const typename CAIEntityMatrix<T>::CEntityIteratorLinear CAIEntityMatrix<T>::beginEntities(const CAIEntityMatrixIteratorTblLinear *tbl, const CAIVector &pos) const
547 CEntityIteratorLinear newIt(this,tbl,pos);
548 return newIt;
552 //--------------------------------------------------------------------------
553 // The CAIEntityMatrixIteratorTblRandom inlines
554 //--------------------------------------------------------------------------
556 inline CAIEntityMatrixIteratorTblRandom::CAIEntityMatrixIteratorTblRandom()
560 inline void CAIEntityMatrixIteratorTblRandom::push_back(sint16 dx,sint16 dy)
562 _tbl.push_back(CAIEntityMatrixIteratorTblRandom::STblEntry(dx,dy));
565 inline const CAIEntityMatrixIteratorTblRandom::STblEntry &CAIEntityMatrixIteratorTblRandom::operator[](uint32 idx) const
567 #ifdef NL_DEBUG
568 nlassert(idx<_tbl.size());
569 #endif
571 return _tbl[idx];
574 inline const CAIEntityMatrixIteratorTblRandom::iterator CAIEntityMatrixIteratorTblRandom::begin() const
576 return const_cast<TTbl&>(_tbl).begin();
579 inline const CAIEntityMatrixIteratorTblRandom::iterator CAIEntityMatrixIteratorTblRandom::end() const
581 return const_cast<TTbl&>(_tbl).end();
584 inline uint32 CAIEntityMatrixIteratorTblRandom::size() const
586 return (uint32)_tbl.size();
590 //--------------------------------------------------------------------------
591 // The CAIEntityMatrixIteratorTblLinear inlines
592 //--------------------------------------------------------------------------
594 inline CAIEntityMatrixIteratorTblLinear::CAIEntityMatrixIteratorTblLinear()
598 inline CAIEntityMatrixIteratorTblLinear::CAIEntityMatrixIteratorTblLinear(uint32 *runLengths,uint32 count)
600 uint32 lastRun=0;
601 for(uint i=0;i<count;++i)
603 push_back(runLengths[i],lastRun);
604 lastRun=runLengths[i];
608 inline void CAIEntityMatrixIteratorTblLinear::push_back(uint32 runLength, sint32 previousRunLength)
610 _tbl.push_back(CAIEntityMatrixIteratorTblLinear::STblEntry(runLength,previousRunLength));
613 inline const CAIEntityMatrixIteratorTblLinear::STblEntry &CAIEntityMatrixIteratorTblLinear::operator[](uint32 idx) const
615 #ifdef NL_DEBUG
616 nlassert(idx<_tbl.size());
617 #endif
619 return _tbl[idx];
622 inline const CAIEntityMatrixIteratorTblLinear::iterator CAIEntityMatrixIteratorTblLinear::begin() const
624 return const_cast<TTbl&>(_tbl).begin();
627 inline const CAIEntityMatrixIteratorTblLinear::iterator CAIEntityMatrixIteratorTblLinear::end() const
629 return const_cast<TTbl&>(_tbl).end();
632 inline uint32 CAIEntityMatrixIteratorTblLinear::size() const
634 return (uint32)_tbl.size();
638 //--------------------------------------------------------------------------
639 #endif