00001
00011 #ifndef __MATRIX__H__
00012 #define __MATRIX__H__
00013
00014 #include <list>
00015 #include <algorithm>
00016 #include <limits>
00017
00018 #include "common.h"
00019 #include "objects/Object.h"
00020 #include "objects/ObjectFixed.h"
00021 #include "objects/ObjectTransferable.h"
00022 #include "objects/ObjectAgent.h"
00023 #include "objects/ObjectTrail.h"
00024 #include "configs/ConfigMatrix.h"
00025
00034 class Matrix {
00035 public:
00039 typedef size_t SizeType;
00040
00041 public:
00042 friend class iterator;
00043
00048 class iterator {
00049 public:
00054 typedef Matrix::SizeType SizeType;
00055
00062 iterator(const Matrix * matrix, SizeType xIndex = 0, SizeType yIndex = 0):
00063 m(matrix), x(xIndex), y(yIndex) {}
00064
00069 iterator(const iterator &iter) {
00070 *this = iter;
00071 }
00072
00076 ~iterator() {}
00077
00082 Object & operator *();
00083
00088 Object * operator ->();
00089
00093 iterator & operator ++();
00094
00100 iterator operator ++(int);
00101
00106 iterator & operator =(const iterator & iter);
00107
00115 friend bool operator ==(const iterator & iter1, const iterator & iter2);
00116
00124 friend bool operator !=(const iterator & iter1, const iterator & iter2);
00125
00126 private:
00128 const Matrix * m;
00130 SizeType x;
00132 SizeType y;
00133 };
00134
00135 public:
00140 explicit Matrix(const ConfigMatrix & config);
00141
00145 ~Matrix();
00146
00150 iterator begin();
00151
00155 iterator end() {
00156 return iterator(this, 0, height);
00157 }
00158
00169 bool PutObject(Object * object, SizeType xIndex, SizeType yIndex);
00170
00179 bool MoveObject(SizeType xFrom, SizeType yFrom, SizeType xTo, SizeType yTo);
00180
00189 bool DestroyObject(SizeType xIndex, SizeType yIndex);
00190
00199 bool IsThereObject(SizeType xIndex, SizeType yIndex) const;
00200
00211 bool IsEditableByUser(SizeType xIndex, SizeType yIndex) const;
00212
00216 void MakeStep();
00217
00224 ConfigMatrix * GetConfigMatrix() const;
00225
00226 private:
00232 void SendCollisions(Object * firstObject, Object * secondObject);
00233
00239 void PerformActions();
00240
00247 void PerformSpecificOperations();
00248
00249 private:
00257 class SecondIndex {
00258 public:
00259 friend class Matrix;
00260
00265 SecondIndex(Matrix * matrix): m(matrix) {}
00266
00275 Object & operator [](SizeType secondIndex);
00276
00277 private:
00279 Matrix * m;
00281 SizeType x;
00282
00283
00284 SecondIndex(const SecondIndex &);
00285
00286 SecondIndex & operator =(const SecondIndex &);
00287
00288 ~SecondIndex() {}
00289 };
00290
00291 public:
00298 SecondIndex & operator [](SizeType firstIndex);
00299
00300 private:
00307 class CallSpecificMethods: public std::unary_function<Object *, void> {
00308 public:
00313 void operator ()(Object * object) const {
00314 object->ChooseNextAction();
00315 }
00316 };
00317
00324 class RemoveSpecificObjects: public std::unary_function<Object *, bool> {
00325 public:
00330 bool operator ()(const Object * object) const {
00331 return object->GetAction().GetAction() == Object::Action::EXPIRED_REMOVE;
00332 }
00333 };
00334
00338 class SaveObjectIntoConfig: public std::unary_function<Object *, void> {
00339 public:
00346 explicit SaveObjectIntoConfig(ConfigMatrix * config,
00347 SizeType xIndex, SizeType yIndex):
00348 x(xIndex), y(yIndex), matrixConfig(config)
00349 {}
00350
00355 void operator ()(const Object * object) const {
00356 matrixConfig->AddConfigCell(new ConfigMatrix::ConfigCell(
00357 x, y, object->CreateObjectConfig()));
00358 }
00359
00360 private:
00362 const SizeType x;
00364 const SizeType y;
00366 ConfigMatrix * const matrixConfig;
00367 };
00368
00375 class Item {
00376 public:
00381 typedef std::list<Object *> Container;
00382
00387 typedef Container::size_type SizeType;
00388
00392 Item() {}
00393
00397 ~Item() {
00398 RemoveAllObjects(true);
00399 }
00400
00406 Object * GetTopObject() const {
00407 return (!container.empty() ? *container.begin() : 0);
00408 }
00409
00417 void AddObject(Object *object);
00418
00428 bool RemoveObject(Object::Priority priority, bool freeMemory = true);
00429
00435 bool RemoveTopObject(bool freeMemory = true);
00436
00441 void RemoveAllObjects(bool freeMemory = true);
00442
00446 bool IsThereObject() const {
00447 return !container.empty();
00448 }
00449
00455 template <class Function>
00456 void ApplyFunctionToEachObject(Function func, bool reversedPass = false) {
00457 if (reversedPass) {
00458 std::for_each(container.rbegin(), container.rend(), func);
00459 }
00460 else {
00461 std::for_each(container.begin(), container.end(), func);
00462 }
00463 }
00464
00469 template <class Predicate>
00470 void RemoveObjectsAccToPredicate(Predicate pred) {
00471 Container::iterator i = container.begin();
00472 while (i != container.end()) {
00473 if (pred(*i)) {
00474 delete *i;
00475 Container::iterator old = i;
00476 ++i;
00477 container.erase(old);
00478 }
00479 else {
00480 ++i;
00481 }
00482 }
00483 }
00484
00485 private:
00487 Container container;
00488 };
00489
00490 public:
00492 SizeType GetWidth() const { return width; }
00493
00495 SizeType GetHeight() const { return height; }
00496
00498 static SizeType GetMinWidth() { return MIN_WIDTH; }
00499
00501 static SizeType GetMinHeight() { return MIN_HEIGHT; }
00502
00504 static SizeType GetDefaultWidth() { return DEFAULT_WIDTH; }
00505
00507 static SizeType GetDefaultHeight() { return DEFAULT_HEIGHT; }
00508
00510 static SizeType GetMaxWidth() { return MAX_WIDTH; }
00511
00513 static SizeType GetMaxHeight() { return MAX_HEIGHT; }
00514
00515 private:
00517 SizeType width;
00519 SizeType height;
00521 static const SizeType MIN_WIDTH;
00523 static const SizeType MIN_HEIGHT;
00525 static const SizeType DEFAULT_WIDTH;
00527 static const SizeType DEFAULT_HEIGHT;
00529 static const SizeType MAX_WIDTH;
00531 static const SizeType MAX_HEIGHT;
00533 static const SizeType WIDTH_INCREMENT;
00535 static const SizeType HEIGHT_INCREMENT;
00536
00537 private:
00539 Item ** matrix;
00541 SecondIndex secIndex;
00543 Object::TicketSize ticketNumber;
00545 static const Object::TicketSize STARTING_TICKET_NUMBER = 0;
00546
00547 private:
00555 void IncreaseMatrixSizeForBorders();
00556
00562 void CreateEmptyMatrix();
00563
00567 void CreateWallsAroundMatrix();
00568
00573 void LoadObjectsFromConfig(const ConfigMatrix & config);
00574
00578 void GenerateNextTicketNumber() {
00579 ticketNumber++;
00580 }
00581
00587 bool IsOutOfRange(SizeType xIndex, SizeType yIndex) const {
00588 return (xIndex >= GetWidth() || yIndex >= GetHeight());
00589 }
00590
00596 string CreateOutOfRangeMessage(SizeType xIndex, SizeType yIndex) const;
00597
00603 bool IndexExists(SizeType xIndex, SizeType yIndex) const {
00604 return (xIndex < GetWidth() && yIndex < GetHeight());
00605 }
00606
00617 void GetIndexOfNextPlace(SizeType xFrom, SizeType yFrom, const Direction & direction,
00618 SizeType & xTo, SizeType & yTo);
00619
00634 bool GetIndexOfNextFreePlace(SizeType xFrom, SizeType yFrom,
00635 SizeType & xTo, SizeType & yTo, Direction & direction);
00636
00644 bool IsFreePlace(SizeType xIndex, SizeType yIndex) const {
00645 return (!IsThereObject(xIndex, yIndex) ||
00646 matrix[yIndex * GetWidth() + xIndex]->GetTopObject()->IsImaginary());
00647 }
00648
00656 bool OnBorder(SizeType xIndex, SizeType yIndex) const {
00657 return (xIndex == 0 || yIndex == 0 ||
00658 xIndex == (GetWidth() - 1) || yIndex == (GetHeight() - 1));
00659 }
00660
00669 bool CanBeAdded(const Object * object, SizeType xIndex, SizeType yIndex) const {
00670 return (!IsOutOfRange(xIndex, yIndex) && !OnBorder(xIndex, yIndex) &&
00671 (!IsThereObject(xIndex, yIndex) ||
00672 object->IsImaginary() ||
00673 matrix[yIndex * GetWidth() + xIndex]->GetTopObject()->IsImaginary()));
00674 }
00675
00682 void InternalMoveObject(SizeType xFrom, SizeType yFrom, const Direction & direction);
00683
00691 void InternalMoveObject(SizeType xFrom, SizeType yFrom, SizeType xTo, SizeType yTo);
00692
00693 private:
00701 bool PerformActionTakeObject(Object * object, SizeType xIndex, SizeType yIndex);
00702
00710 bool PerformActionDropObject(Object * object, SizeType xIndex, SizeType yIndex);
00711
00719 bool PerformActionPutTrail(Object * object, SizeType xIndex, SizeType yIndex);
00720 };
00721
00722 #endif
00723
00724