#include "Cell.h" #include #include #include //#include "unit.h" #include #include class Unit{ public: bool CanMoveForDistance(int distance){ return true; } /* template bool CanAttackForDistance(int distance){ return true; } bool CanAttackForDistance<"Melee">(int distance){ return true; } bool CanAttackForDistance<"Range">(int distance){ return true; }*/ }; class EffectsForCell{ public: void OperateOnCell(Cell*){} }; Cell::Cell(Unit* character) { leftUp_ = left_ = leftDown_ = nullptr; rightUp_ = right_ = rightDown_ = nullptr; character_ = character; clearCell_(); AddedToQuery_ = true; } Cell * Cell::getleftUp() { return leftUp_; } void Cell::setleftUp(Cell * t) { leftUp_ = t; } Cell * Cell::getleft() { return left_; } void Cell::setleft(Cell * t) { left_ = t; } Cell * Cell::getleftDown() { return leftDown_; } void Cell::setleftDown(Cell * t) { leftDown_ = t; } Cell * Cell::getrightUp() { return rightUp_; } void Cell::setrightUp(Cell * t) { rightUp_ = t; } Cell * Cell::getright() { return right_; } void Cell::setright(Cell * t) { right_ = t; } Cell * Cell::getrightDown() { return rightDown_; } void Cell::setrightDown(Cell * t) { rightDown_ = t; } Unit * Cell::getCharacter() { return character_; } void Cell::setCharacter(Unit * t) { character_ = t; } int Cell::getdistance_barrier(){ return distance_barrier_; } void Cell::setdistance_barrier(int distance_barrier){ distance_barrier_ = distance_barrier; } int Cell::getdistance_through(){ return distance_through_; } void Cell::setdistance_through(int distance_through){ distance_through_ = distance_through; } bool Cell::getisMoveAble(){ return isMoveAble_; } void Cell::setisMoveAble(bool isMoveAble){ isMoveAble_ = isMoveAble; } bool Cell::getisMeleeAttackAble(){ return isMeleeAttackAble_; } void Cell::setisMeleeAttackAble(bool isMeleeAttackAble){ isMeleeAttackAble_ = isMeleeAttackAble; } bool Cell::getisRangeAttackAble(){ return isRangeAttackAble_; } void Cell::setisRangeAttackAble(bool isRangeAttackAble){ isRangeAttackAble_ = isRangeAttackAble; } bool Cell::isEmpty() { return character_ == NULL; } void Cell::recalculateAllEffectsList(){ for(std::vector::iterator it = beginIteratorEffectsList(); it != endIteratorEffectsList();++it){ (*it)->OperateOnCell(this); } } void Cell::add(EffectsForCell* effect){ effects_list_.push_back(effect); } void Cell::remove(std::vector::iterator it){ if(beginIteratorEffectsList() <= it && it < endIteratorEffectsList()){ effects_list_.erase(it); } } void Cell::remove(EffectsForCell* effect){ for(std::vector::iterator it = beginIteratorEffectsList(); it != endIteratorEffectsList();++it){ if((*it) == effect){ remove(it); return; } } } std::vector::iterator Cell::beginIteratorEffectsList(){ return effects_list_.begin(); } std::vector::iterator Cell::endIteratorEffectsList(){ return effects_list_.end(); } void Cell::RecalculateTableWithCenterThisPoint() { clearTable_(); std::queue qWithoutMoveable; updateMoveableCells_(qWithoutMoveable); updateUnMovealeCells_(qWithoutMoveable); } std::vector Cell::actualPath(Cell* to) { if (!to || !to->getisMoveAble())return std::vector(); auto ret = std::vector(1, to); while (to != this) { Cell * parent = nullptr; auto f = [&parent](Cell * TestParent, Cell * Now) { if (TestParent && TestParent->getdistance_barrier() + 1 == Now->getdistance_barrier() && TestParent->getisMoveAble()) { parent = TestParent; } }; assert(parent != nullptr); f(to->getleftUp(), to); f(to->getleft(), to); f(to->getleftDown(), to); f(to->getrightUp(), to); f(to->getright(), to); f(to->getrightDown(), to); to = parent; ret.push_back(to); } return ret; } void Cell::clearCell_() { setdistance_barrier(-1); setdistance_through(-1); setisMeleeAttackAble(false); setisMoveAble(false); setisRangeAttackAble(false); } void Cell::clearTable_() { std::queue q; q.push(this); clearCell_(); setdistance_through(0); this->AddedToQuery_ = false; auto f = [&q](Cell * t, Cell * parent) { if (t && t->AddedToQuery_ == true) { q.push(t); t->setdistance_through( parent->getdistance_through() + 1 ); t->AddedToQuery_ = false; } }; while (!q.empty()) { Cell * Now = q.front(); q.pop(); Now->clearCell_(); f(Now->getleftUp(), Now); f(Now->getleft(), Now); f(Now->getleftDown(), Now); f(Now->getrightUp(), Now); f(Now->getright(), Now); f(Now->getrightDown(), Now); } } void Cell::recalcAttackable_(Cell * Now){ if(Now == nullptr)return; if (!isEmpty() && !Now->isEmpty() && getCharacter()->CanAttackForDistance<"Melee">(Now->getdistance_barrier()) ) { Now->setisMeleeAttackAble(true); } if (!isEmpty() && !Now->isEmpty() && getCharacter()->CanAttackForDistance<"Range">(Now->getdistance_barrier()) ) { Now->setisRangeAttackAble(true); } } void Cell::recalcMoveable_(Cell * Now){ if(Now == nullptr || Now->isEmpty() || isEmpty())return; getCharacter()->CanMoveForDistance() } void Cell::updateMoveableCells_(std::queue & Q) { std::queue q; q.push(this); setdistance_barrier(0); auto f = [&q, &Q](Cell * t, Cell * parent) { if (t && !t->AddedToQuery_) { t->AddedToQuery_ = true; if (t->getCharacter() != NULL) { Q.push(t); return; } q.push(t); t->setdistance_barrier( parent->getdistance_barrier() + 1 ); } }; while (!q.empty()) { Cell * Now = q.front(); Now->setisMoveAble(); recalcAttackable_(Now); q.pop(); f(Now->getleftUp(), Now); f(Now->getleft(), Now); f(Now->getleftDown(), Now); f(Now->getrightUp(), Now); f(Now->getright(), Now); f(Now->getrightDown(), Now); } } void Cell::updateUnMovealeCells_(std::queue & Q) { auto f = [&Q](Cell * t, Cell * parent) { if (t && !t->AddedToQuery_) { t->AddedToQuery_ = true; Q.push(t); } }; while (!Q.empty()) { Cell * Now = Q.front(); Now->setisMoveable(false); Now->setisAttackable(false); Q.pop(); f(Now->getleftUp(), Now); f(Now->getleft(), Now); f(Now->getleftDown(), Now); f(Now->getrightUp(), Now); f(Now->getright(), Now); f(Now->getrightDown(), Now); } }