Cell.cpp 8.3 KB

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