Cell.cpp 7.8 KB

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