Cell.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include "../include/Cell.h"
  2. #include "../include/units/unit.h"
  3. #include <string>
  4. #include <queue>
  5. #include <vector>
  6. #include <map>
  7. #include <iostream>
  8. class EffectsForCell{
  9. public:
  10. void OperateOnCell(Cell*){}
  11. };
  12. Cell::Cell(Unit* character) {
  13. leftUp_ = left_ = leftDown_ = nullptr;
  14. rightUp_ = right_ = rightDown_ = nullptr;
  15. character_ = character;
  16. clearCell_();
  17. AddedToQuery_ = true;
  18. col_ = row_ = 0;
  19. }
  20. Cell * Cell::getleftUp() {
  21. return leftUp_;
  22. }
  23. void Cell::setleftUp(Cell * t) {
  24. leftUp_ = t;
  25. }
  26. Cell * Cell::getleft() {
  27. return left_;
  28. }
  29. void Cell::setleft(Cell * t) {
  30. left_ = t;
  31. }
  32. Cell * Cell::getleftDown() {
  33. return leftDown_;
  34. }
  35. void Cell::setleftDown(Cell * t) {
  36. leftDown_ = t;
  37. }
  38. Cell * Cell::getrightUp() {
  39. return rightUp_;
  40. }
  41. void Cell::setrightUp(Cell * t) {
  42. rightUp_ = t;
  43. }
  44. Cell * Cell::getright() {
  45. return right_;
  46. }
  47. void Cell::setright(Cell * t) {
  48. right_ = t;
  49. }
  50. Cell * Cell::getrightDown() {
  51. return rightDown_;
  52. }
  53. void Cell::setrightDown(Cell * t) {
  54. rightDown_ = t;
  55. }
  56. Unit * Cell::getCharacter() {
  57. return character_;
  58. }
  59. void Cell::setCharacter(Unit * t) {
  60. character_ = t;
  61. }
  62. int Cell::getdistance_barrier(){
  63. return distance_barrier_;
  64. }
  65. void Cell::setdistance_barrier(int distance_barrier){
  66. distance_barrier_ = distance_barrier;
  67. }
  68. int Cell::getdistance_through(){
  69. return distance_through_;
  70. }
  71. void Cell::setdistance_through(int distance_through){
  72. distance_through_ = distance_through;
  73. }
  74. bool Cell::getisMoveAble(){
  75. return isMoveAble_;
  76. }
  77. void Cell::setisMoveAble(bool isMoveAble){
  78. isMoveAble_ = isMoveAble;
  79. }
  80. bool Cell::getisMeleeAttackAble(){
  81. return isMeleeAttackAble_;
  82. }
  83. void Cell::setisMeleeAttackAble(bool isMeleeAttackAble){
  84. isMeleeAttackAble_ = isMeleeAttackAble;
  85. }
  86. bool Cell::getisRangeAttackAble(){
  87. return isRangeAttackAble_;
  88. }
  89. void Cell::setisRangeAttackAble(bool isRangeAttackAble){
  90. isRangeAttackAble_ = isRangeAttackAble;
  91. }
  92. bool Cell::isEmpty() {
  93. return character_ == nullptr;
  94. }
  95. void Cell::recalculateAllEffectsList(){
  96. for(std::vector<EffectsForCell*>::iterator it = beginIteratorEffectsList();
  97. it != endIteratorEffectsList();++it){
  98. (*it)->OperateOnCell(this);
  99. }
  100. }
  101. void Cell::add(EffectsForCell* effect){
  102. if(effect == nullptr)
  103. throw new int(228);
  104. effects_list_.push_back(effect);
  105. }
  106. void Cell::remove(std::vector<EffectsForCell*>::iterator it){
  107. if(beginIteratorEffectsList() <= it && it < endIteratorEffectsList()){
  108. effects_list_.erase(it);
  109. }
  110. }
  111. void Cell::remove(EffectsForCell* effect){
  112. for(std::vector<EffectsForCell*>::iterator it = beginIteratorEffectsList();
  113. it != endIteratorEffectsList();++it){
  114. if((*it) == effect){
  115. remove(it);
  116. return;
  117. }
  118. }
  119. }
  120. std::vector<EffectsForCell*>::iterator Cell::beginIteratorEffectsList(){
  121. return effects_list_.begin();
  122. }
  123. std::vector<EffectsForCell*>::iterator Cell::endIteratorEffectsList(){
  124. return effects_list_.end();
  125. }
  126. void Cell::RecalculateTableWithCenterThisPoint() {
  127. clearTable_();
  128. std::queue<Cell*> qWithUnMoveable;
  129. updateMoveableCells_(qWithUnMoveable);
  130. updateUnMovealeCells_(qWithUnMoveable);
  131. }
  132. std::vector <Cell*> Cell::actualPath(Cell* to) {
  133. if (!to || !to->getisMoveAble())return std::vector<Cell*>();
  134. auto ret = std::vector<Cell*>(1, to);
  135. while (to != this) {
  136. Cell * parent = nullptr;
  137. auto f = [&parent](Cell * TestParent, Cell * Now) {
  138. if (TestParent && TestParent->getdistance_barrier() + 1 == Now->getdistance_barrier()
  139. && TestParent->getisMoveAble()) {
  140. parent = TestParent;
  141. }
  142. };
  143. if(parent == nullptr)throw std::string("Don`t recalculated");
  144. f(to->getleftUp(), to);
  145. f(to->getleft(), to);
  146. f(to->getleftDown(), to);
  147. f(to->getrightUp(), to);
  148. f(to->getright(), to);
  149. f(to->getrightDown(), to);
  150. to = parent;
  151. ret.push_back(to);
  152. }
  153. return ret;
  154. }
  155. void Cell::clearCell_() {
  156. setdistance_barrier(-1);
  157. setdistance_through(-1);
  158. setisMeleeAttackAble(false);
  159. setisMoveAble(false);
  160. setisRangeAttackAble(false);
  161. }
  162. void Cell::clearTable_() {
  163. std::queue<Cell*> q;
  164. q.push(this);
  165. clearCell_();
  166. setdistance_through(0);
  167. this->AddedToQuery_ = false;
  168. auto f = [&q](Cell * t, Cell * parent, int delta_col, int delta_row) {
  169. if (t && t->AddedToQuery_ == true) {
  170. q.push(t);
  171. t->col_ = parent->col_ + delta_col;
  172. t->row_ = parent->row_ + delta_row;
  173. t->setdistance_through(
  174. parent->getdistance_through() + 1
  175. );
  176. t->AddedToQuery_ = false;
  177. }
  178. };
  179. while (!q.empty()) {
  180. Cell * Now = q.front();
  181. q.pop();
  182. Now->clearCell_();
  183. f(Now->getleftUp(), Now, -1, 0);
  184. f(Now->getleft(), Now, 0, -1);
  185. f(Now->getleftDown(), Now, 1, -1);
  186. f(Now->getrightUp(), Now, -1, 1);
  187. f(Now->getright(), Now, 0, 1);
  188. f(Now->getrightDown(), Now, 1, 0);
  189. }
  190. }
  191. void Cell::recalcAttackable_(Cell * Now,bool isReached){
  192. if(Now == nullptr)return;
  193. if (!isEmpty() && !Now->isEmpty() &&
  194. getCharacter()->canAttackForDistance("Melee", Now->getdistance_barrier())
  195. ) {
  196. Now->setisMeleeAttackAble(isReached);
  197. }
  198. if (!isEmpty() && !Now->isEmpty() &&
  199. getCharacter()->canAttackForDistance("Range", Now->getdistance_barrier())
  200. ) {
  201. Now->setisRangeAttackAble(true);
  202. }
  203. }
  204. void Cell::recalcMoveable_(Cell * Now, bool isReached){
  205. if(Now == nullptr || Now->isEmpty() || isEmpty())return;
  206. if(!isEmpty() && Now->isEmpty() &&
  207. getCharacter()->canMoveForDistance(Now->getdistance_barrier())){
  208. Now->setisMoveAble(isReached);
  209. }
  210. }
  211. void Cell::updateMoveableCells_(std::queue<Cell*> & Q) {
  212. std::queue<Cell*> q;
  213. q.push(this);
  214. setdistance_barrier(0);
  215. auto f = [&q, &Q](Cell * t, Cell * parent) {
  216. if (t && !t->AddedToQuery_) {
  217. t->AddedToQuery_ = true;
  218. if (t->getCharacter() != NULL) {
  219. Q.push(t);
  220. return;
  221. }
  222. q.push(t);
  223. t->setdistance_barrier(
  224. parent->getdistance_barrier() + 1
  225. );
  226. }
  227. };
  228. while (!q.empty()) {
  229. Cell * Now = q.front();
  230. q.pop();
  231. recalcMoveable_(Now, true);
  232. recalcAttackable_(Now, true);
  233. f(Now->getleftUp(), Now);
  234. f(Now->getleft(), Now);
  235. f(Now->getleftDown(), Now);
  236. f(Now->getrightUp(), Now);
  237. f(Now->getright(), Now);
  238. f(Now->getrightDown(), Now);
  239. }
  240. }
  241. void Cell::updateUnMovealeCells_(std::queue<Cell*> & Q) {
  242. auto f = [&Q](Cell * t, Cell * parent) {
  243. if (t && !t->AddedToQuery_) {
  244. t->AddedToQuery_ = true;
  245. Q.push(t);
  246. }
  247. };
  248. while (!Q.empty()) {
  249. Cell * Now = Q.front();
  250. recalcMoveable_(Now, false);
  251. recalcAttackable_(Now, false);
  252. Q.pop();
  253. f(Now->getleftUp(), Now);
  254. f(Now->getleft(), Now);
  255. f(Now->getleftDown(), Now);
  256. f(Now->getrightUp(), Now);
  257. f(Now->getright(), Now);
  258. f(Now->getrightDown(), Now);
  259. }
  260. }
  261. Cell* Cell::getRealShootTarget(Cell* next){
  262. if(next == this){
  263. return next;
  264. }
  265. int next_col = next->col_;
  266. int next_row = next->row_;
  267. if(next_col - col_ == next_row - row_){//GoMainDiagonal
  268. if(next_col > col_){
  269. return getrightDown()->getright();
  270. }
  271. if(next_col < col_){
  272. return getleftUp()->getleft();
  273. }
  274. throw std::string("Don`t recalculated");
  275. }
  276. if(-2 * (next_col - col_) == (next_row - row_)){//GoSecondaryDiagonal
  277. if(next_col < col_){
  278. return getrightUp()->getright();
  279. }
  280. if(next_col > col_){
  281. return getleftDown()->getleft();
  282. }
  283. throw std::string("Don`t recalculated");
  284. }
  285. if(next_col - col_ == -2 * (next_row - row_)){//GoUp
  286. if(next_col < col_){
  287. return (getleftUp() != nullptr ? getleftUp()->getrightUp() : getrightUp()->getleftUp());
  288. }
  289. if(next_col > col_){
  290. return (getleftDown() != nullptr ? getleftDown()->getrightDown() : getrightDown()->getleftDown());
  291. }
  292. throw std::string("Don`t recalculated");
  293. }
  294. int row_secondary_diag = row_ - 2 * (next_col - col_);
  295. int row_main_diag = row_ + next_col - col_;
  296. int twice_row_up_line = 2 * row_ + col_ - next_col;
  297. if(next_col > col_){
  298. if(next_row < row_main_diag)return getleft();
  299. if(2 * next_row < twice_row_up_line)return getleftUp();
  300. if(next_row < row_secondary_diag)return getrightUp();
  301. return getright();
  302. }
  303. else{
  304. if(next_row < row_secondary_diag)return getleft();
  305. if(2 * next_row < twice_row_up_line)return getleftDown();
  306. if(next_row < row_main_diag)return getrightDown();
  307. return getright();
  308. }
  309. }