Переглянути джерело

Updated Cell. Need to add in branch dev

GeorgeKolog 6 роки тому
батько
коміт
c755e2695c
2 змінених файлів з 276 додано та 123 видалено
  1. 156 73
      Cell.cpp
  2. 120 50
      Cell.h

+ 156 - 73
Cell.cpp

@@ -1,12 +1,38 @@
 #include "Cell.h"
-#include "unit.h"
+#include <assert.h>
+#include <string>
+#include <string.h>
+//#include "unit.h"
 #include <queue>
 #include <vector>
 
-Cell::Cell(Unit * character) {
+class Unit{
+public:
+    bool CanMoveForDistance(int distance){
+        return true;
+    }
+    /*
+    template<std::string AttackType>
+    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;
+	character_ = character;
 	clearCell_();
 	AddedToQuery_ = true;
 }
@@ -17,42 +43,36 @@ Cell * Cell::getleftUp() {
 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_;
 }
@@ -60,45 +80,122 @@ void Cell::setCharacter(Unit * t) {
 	character_ = t;
 }
 
-bool Cell::getisMoveable() {
-	return isMoveable_;
+int Cell::getdistance_barrier(){
+    return distance_barrier_;
 }
-void Cell::setisMoveable(bool t) {
-	isMoveable_ = t;
+void Cell::setdistance_barrier(int distance_barrier){
+    distance_barrier_ = distance_barrier;
 }
-
-bool Cell::getisAttackable() {
-	return isAttackable_;
+int Cell::getdistance_through(){
+    return distance_through_;
 }
-void Cell::setisAttackable(bool t) {
-	isAttackable_ = t;
+void Cell::setdistance_through(int distance_through){
+    distance_through_ = distance_through;
 }
 
-int Cell::getDistance() {
-	return distance_;
+bool Cell::getisMoveAble(){
+    return isMoveAble_;
+}
+void Cell::setisMoveAble(bool isMoveAble){
+    isMoveAble_ = isMoveAble;
+}
+bool Cell::getisMeleeAttackAble(){
+    return isMeleeAttackAble_;
 }
-void Cell::setDistance(int t) {
-	distance_ = t;
+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<EffectsForCell*>::iterator it = beginIteratorEffectsList();
+            it != endIteratorEffectsList();++it){
+        (*it)->OperateOnCell(this);
+    }
+}
+void Cell::add(EffectsForCell* effect){
+    effects_list_.push_back(effect);
+}
+void Cell::remove(std::vector<EffectsForCell*>::iterator it){
+    if(beginIteratorEffectsList() <= it && it < endIteratorEffectsList()){
+        effects_list_.erase(it);
+    }
+}
+void Cell::remove(EffectsForCell* effect){
+    for(std::vector<EffectsForCell*>::iterator it = beginIteratorEffectsList();
+            it != endIteratorEffectsList();++it){
+        if((*it) == effect){
+            remove(it);
+            return;
+        }
+    }
+}
+std::vector<EffectsForCell*>::iterator Cell::beginIteratorEffectsList(){
+    return effects_list_.begin();
+}
+std::vector<EffectsForCell*>::iterator Cell::endIteratorEffectsList(){
+    return effects_list_.end();
+}
+
+void Cell::RecalculateTableWithCenterThisPoint() {
+    clearTable_();
+    std::queue<Cell*> qWithoutMoveable;
+    updateMoveableCells_(qWithoutMoveable);
+    updateUnMovealeCells_(qWithoutMoveable);
+}
+std::vector <Cell*> Cell::actualPath(Cell* to) {
+    if (!to || !to->getisMoveAble())return std::vector<Cell*>();
+    auto ret = std::vector<Cell*>(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_() {
-	setisMoveable(false);
-	setisAttackable(false);
-	setDistance(-1);
+    setdistance_barrier(-1);
+    setdistance_through(-1);
+    setisMeleeAttackAble(false);
+    setisMoveAble(false);
+    setisRangeAttackAble(false);
 }
 
 void Cell::clearTable_() {
 	std::queue<Cell*> q;
 	q.push(this);
 	clearCell_();
+	setdistance_through(0);
 	this->AddedToQuery_ = false;
-	auto f = [&q](Cell * t) {
+	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;
 		}
 	};
@@ -106,40 +203,55 @@ void Cell::clearTable_() {
 		Cell * Now = q.front();
 		q.pop();
 		Now->clearCell_();
-		f(Now->getleftUp());
-		f(Now->getleft());
-		f(Now->getleftDown());
-		f(Now->getrightUp());
-		f(Now->getright());
-		f(Now->getrightDown());
+		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::handleAllMoveableCellsAndUnmoveableCells_(std::queue<Cell*> & Q) {
+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<Cell*> & Q) {
 	std::queue<Cell*> q;
 	q.push(this);
-	setDistance(0);
+	setdistance_barrier(0);
 	auto f = [&q, &Q](Cell * t, Cell * parent) {
 		if (t && !t->AddedToQuery_) {
 			t->AddedToQuery_ = true;
 			if (t->getCharacter() != NULL) {
-				t->setisMoveable(false);
 				Q.push(t);
 				return;
 			}
 			q.push(t);
-			t->setDistance(parent->getDistance() + 1);
+			t->setdistance_barrier(
+			        parent->getdistance_barrier() + 1
+            );
 		}
 	};
 	while (!q.empty()) {
 		Cell * Now = q.front();
-		Now->setisMoveable(true);
-		if (getCharacter() != NULL && getCharacter()->СanAttack(Now->getDistance())) {
-			Now->setisAttackable(true);
-		}
-		else {
-			Now->setisAttackable(false);
-		}
+		Now->setisMoveAble();
+		recalcAttackable_(Now);
 		q.pop();
 		f(Now->getleftUp(), Now);
 		f(Now->getleft(), Now);
@@ -150,7 +262,7 @@ void Cell::handleAllMoveableCellsAndUnmoveableCells_(std::queue<Cell*> & Q) {
 	}
 }
 
-void Cell::handleAllUnmoveableCells_(std::queue<Cell*> & Q) {
+void Cell::updateUnMovealeCells_(std::queue<Cell*> & Q) {
 	auto f = [&Q](Cell * t, Cell * parent) {
 		if (t && !t->AddedToQuery_) {
 			t->AddedToQuery_ = true;
@@ -170,32 +282,3 @@ void Cell::handleAllUnmoveableCells_(std::queue<Cell*> & Q) {
 		f(Now->getrightDown(), Now);
 	}
 }
-
-void Cell::RecalculateTableWithCenterThisPoint() {
-	clearTable_();
-	std::queue<Cell*> qWithoutMoveable;
-	handleAllMoveableCellsAndUnmoveableCells_(qWithoutMoveable);
-	handleAllUnmoveableCells_(qWithoutMoveable);
-}
-
-std::vector <Cell*> Cell::actualPath(Cell* to) {//std::vector<Cell*> âêëþ÷àåòñÿ â ñåáÿ è this, è end
-	if (!to || !to->getisMoveable())return std::vector<Cell*>();
-	auto ret = std::vector<Cell*>(1, to);
-	while (to != this) {
-		Cell * parent = NULL;
-		auto f = [&parent](Cell * TestParent, Cell * Now) {
-			if (TestParent && TestParent->getDistance() + 1 == Now->getDistance() && TestParent->getisMoveable()) {
-				parent = TestParent;
-			}
-		};
-		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;
-}

+ 120 - 50
Cell.h

@@ -1,70 +1,140 @@
 #pragma once
 #include <queue>
 #include <vector>
-
+/*
+ * Решили, что метод canAttackForDistance(int) имеет шаблон, который обозначает тип атаки
+ * Melee - без учёта препятствий
+ * Range - с учётом препятствий
+ * Шаблон - строка. При такой реализации можно добавить новый вид атаки
+ * Необходимо в Unit добавить метод bool isCharacter() - является ли данный юнит персонажем
+ */
 class Unit;
+/*
+ * Этот класс Игоря ждёт своей реализации
+ * (Название неточное)
+ * Необходимо добавить методы:
+ * OperateOnCell(Cell*)
+ * OperateOnUnit(Unit*)
+ */
+class EffectsForCell;
 
 class Cell {
-
 private:
-	Cell * leftUp_;
-	Cell *left_;
-	Cell * leftDown_;
-
-	Cell *rightUp_;
-	Cell *right_;
-	Cell *rightDown_;
-
-	Unit *character_;
-
-	bool isMoveable_;
-	bool  isAttackable_;
-
-	int distance_;
+	/*
+	 * Соседние клетки к текущей
+	 * nullptr, если ее не существует
+	*/
+	Cell* leftUp_;
+	Cell* left_;
+	Cell* leftDown_;
+	Cell* rightUp_;
+	Cell* right_;
+	Cell* rightDown_;
+	/*
+	 * Ссылка на любую дичь, который находится на клетке
+	 * nullptr, клетка пустая
+	 */
+	Unit* character_;
+	/*
+	 * Список всех эффектов, применённых к этой клетке
+	 * Работа с этим списком в методах ниже
+	 * Добавление, удаление, указатель на начало и конец
+	 */
+	std::vector<EffectsForCell*> effects_list_;
+	/*
+	 * isMoveAble - Можно ли попасть в данную клетку из точки пересчета
+	 * переходя только по клеткам без юнитов
+	 * isMeleeAttackAble - Можно ли атаковать данную клетку
+	 * isRangeAttackAble_;
+	 */
+	bool isMoveAble_;
+	bool isMeleeAttackAble_;
+	bool isRangeAttackAble_;
+	/*
+	 * Расстояние от точки пересчёта до текущей точки
+	 * distance_barrier - расстояние с учетом других препятствий
+	 * distance_through - расстояние без учета препятствий
+	 * -1, если недостижимо
+	 */
+	int distance_barrier_;
+	int distance_through_;
+private:
+    /*
+     * Локальные методы и переменные
+     */
 	bool AddedToQuery_;
-
 	void clearTable_();
 	void clearCell_();
-
-	void handleAllMoveableCellsAndUnmoveableCells_(std::queue<Cell*> & Q);
-	void handleAllUnmoveableCells_(std::queue<Cell*> & Q);
+	void recalcAttackable_();
+	void recalcMoveable_();
+	/*
+	 * BFS Moveable Cells And Find Unmoveable Cells
+	 */
+	void updateMoveableCells_(std::queue<Cell *> &Q);
+	/*
+	 * BFS UnMoveable Cells
+	 */
+	void updateUnMovealeCells_(std::queue<Cell *> &Q);
 
 public:
 
 	explicit Cell(Unit * character);
-
-	Cell * getleftUp();
-	void setleftUp(Cell *);
-
-	Cell * getleft();
-	void setleft(Cell *);
-	
-	Cell * getleftDown();
-	void setleftDown(Cell *);
-	
-	Cell * getrightUp();
-	void setrightUp(Cell *);
-	
-	Cell * getright();
-	void setright(Cell *);
-	
-	Cell * getrightDown();
+	/*
+	 * Геттеры и сеттеры соседних клеток и персонажа
+	 */
+	Cell* getleftUp();
+	void setleftUp(Cell*);
+	Cell* getleft();
+	void setleft(Cell*);
+	Cell* getleftDown();
+	void setleftDown(Cell*);
+	Cell* getrightUp();
+	void setrightUp(Cell*);
+	Cell* getright();
+	void setright(Cell*);
+	Cell* getrightDown();
 	void setrightDown(Cell *);
-	
-	Unit * getCharacter();
+	Unit* getCharacter();
 	void setCharacter(Unit *);
-	
-	bool getisMoveable();
-	void setisMoveable(bool);
-	
-	bool getisAttackable();
-	void setisAttackable(bool);
-	
-	int getDistance();
-	void setDistance(int);
-	
+	/*
+	 * Ещё геттеры и сеттеры
+	 */
+    int getdistance_barrier();
+    void setdistance_barrier(int);
+    int getdistance_through();
+    void setdistance_through(int);
+    /*
+     * Нужно больше геттеров и сеттеров
+     */
+    bool getisMoveAble();
+	void setisMoveAble(bool);
+	bool getisMeleeAttackAble();
+	void setisMeleeAttackAble(bool);
+	bool getisRangeAttackAble();
+	void setisRangeAttackAble(bool);
+	/*
+	 * Содержит ли текущая клетка unit
+	 */
 	bool isEmpty();
-
+	/*
+	 * Методы для работы с эффектами
+	 */
+	void recalculateAllEffectsList();
+	void add(EffectsForCell*);
+	void remove(std::vector<EffectsForCell*>::iterator);
+	void remove(EffectsForCell*);
+	std::vector<EffectsForCell*>::iterator beginIteratorEffectsList();
+	std::vector<EffectsForCell*>::iterator endIteratorEffectsList();
+	/*
+	 * Пересчитывает ВСЁ поле, делая текущую клетку - точкой пересчета
+	 */
 	void RecalculateTableWithCenterThisPoint();
+	/*
+	 * Работает корректно только в случае, если текущая - точка пересчета
+	 * Возвращает список всех клеток от параметра до точки пересчета
+	 * Включает в себя и начало, и конец
+	 * При этом список составлен в порядке прохода, начиная с последнего
+	 * Если пути нету, то вернется пустой список
+	 */
 	std::vector <Cell*> actualPath(Cell*);
 };