CPathfinder.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "stdafx.h"
  2. #include "global.h"
  3. #include "CPathfinder.h"
  4. #include "CGameInfo.h"
  5. #include "hch\CAmbarCendamo.h"
  6. #include "mapHandler.h"
  7. using namespace boost::logic;
  8. int3 CPath::startPos()
  9. {
  10. return int3(nodes[nodes.size()-1].coord.x,nodes[nodes.size()-1].coord.y,nodes[nodes.size()-1].coord.z);
  11. }
  12. int3 CPath::endPos()
  13. {
  14. return int3(nodes[0].coord.x,nodes[0].coord.y,nodes[0].coord.z);
  15. }
  16. CPath * CPathfinder::getPath(int3 src, int3 dest, const CGHeroInstance * hero, unsigned char type) //TODO: test it (seems to be finished, but relies on unwritten functions :()
  17. {
  18. //check input
  19. if ((src.x < 0)||(src.y < 0)||(src.z < 0)||(dest.x < 0)||(dest.y < 0)||(dest.z < 0))
  20. {
  21. return NULL;
  22. }
  23. if ((src.x >= CGI->mh->sizes.x)||(src.y >= CGI->mh->sizes.y)||(src.z >= CGI->mh->sizes.z)
  24. ||(dest.x >= CGI->mh->sizes.x)||(dest.y >= CGI->mh->sizes.y)||(dest.z >= CGI->mh->sizes.z))
  25. {
  26. return NULL;
  27. }
  28. int3 hpos = hero->getPosition(false);
  29. tribool blockLandSea; //true - blocks sea, false - blocks land, indeterminate - allows all
  30. if (!hero->canWalkOnSea())
  31. {
  32. if (CGI->mh->ttiles[hpos.x][hpos.y][hpos.z].terType==EterrainType::water)
  33. blockLandSea=false;
  34. else
  35. blockLandSea=true;
  36. }
  37. else
  38. {
  39. blockLandSea = indeterminate;
  40. }
  41. //graph initialization
  42. graph.resize(CGI->ac->map.width);
  43. for(int i=0; i<graph.size(); ++i)
  44. {
  45. graph[i].resize(CGI->ac->map.height);
  46. for(int j=0; j<graph[i].size(); ++j)
  47. {
  48. graph[i][j] = new CPathNode;
  49. graph[i][j]->accesible = !CGI->mh->ttiles[i][j][src.z].blocked;
  50. if(i==dest.x && j==dest.y && CGI->mh->ttiles[i][j][src.z].visitable)
  51. graph[i][j]->accesible = true; //for allowing visiting objects
  52. graph[i][j]->dist = -1;
  53. graph[i][j]->theNodeBefore = NULL;
  54. graph[i][j]->visited = false;
  55. graph[i][j]->coord.x = i;
  56. graph[i][j]->coord.y = j;
  57. graph[i][j]->coord.z = dest.z;
  58. if (CGI->mh->ttiles[i][j][src.z].terType==EterrainType::rock)
  59. graph[i][j]->accesible = false;
  60. if ((blockLandSea) && (CGI->mh->ttiles[i][j][src.z].terType==EterrainType::water))
  61. graph[i][j]->accesible = false;
  62. else if ((!blockLandSea) && (CGI->mh->ttiles[i][j][src.z].terType!=EterrainType::water))
  63. graph[i][j]->accesible = false;
  64. }
  65. }
  66. //graph initialized
  67. graph[src.x][src.y]->dist = 0;
  68. std::queue<CPathNode *> mq;
  69. mq.push(graph[src.x][src.y]);
  70. unsigned int curDist = 4000000000;
  71. while(!mq.empty())
  72. {
  73. CPathNode * cp = mq.front();
  74. mq.pop();
  75. if ((cp->coord.x == dest.x) && (cp->coord.y==dest.y))
  76. {
  77. if (cp->dist < curDist)
  78. curDist=cp->dist;
  79. }
  80. else
  81. {
  82. if (cp->dist > curDist)
  83. continue;
  84. }
  85. if(cp->coord.x>0)
  86. {
  87. CPathNode * dp = graph[cp->coord.x-1][cp->coord.y];
  88. if((dp->dist==-1 || (dp->dist > cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x-1, cp->coord.y, src.z), hero))) && dp->accesible)
  89. {
  90. dp->dist = cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x-1, cp->coord.y, src.z), hero);
  91. dp->theNodeBefore = cp;
  92. mq.push(dp);
  93. }
  94. }
  95. if(cp->coord.y>0)
  96. {
  97. CPathNode * dp = graph[cp->coord.x][cp->coord.y-1];
  98. if((dp->dist==-1 || (dp->dist > cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x, cp->coord.y-1, src.z), hero))) && dp->accesible)
  99. {
  100. dp->dist = cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x-1, cp->coord.y, src.z), hero);
  101. dp->theNodeBefore = cp;
  102. mq.push(dp);
  103. }
  104. }
  105. if(cp->coord.x>0 && cp->coord.y>0)
  106. {
  107. CPathNode * dp = graph[cp->coord.x-1][cp->coord.y-1];
  108. if((dp->dist==-1 || (dp->dist > cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x-1, cp->coord.y-1, src.z), hero))) && dp->accesible)
  109. {
  110. dp->dist = cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x-1, cp->coord.y-1, src.z), hero);
  111. dp->theNodeBefore = cp;
  112. mq.push(dp);
  113. }
  114. }
  115. if(cp->coord.x<graph.size()-1)
  116. {
  117. CPathNode * dp = graph[cp->coord.x+1][cp->coord.y];
  118. if((dp->dist==-1 || (dp->dist > cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x+1, cp->coord.y, src.z), hero))) && dp->accesible)
  119. {
  120. dp->dist = cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x+1, cp->coord.y, src.z), hero);
  121. dp->theNodeBefore = cp;
  122. mq.push(dp);
  123. }
  124. }
  125. if(cp->coord.y<graph[0].size()-1)
  126. {
  127. CPathNode * dp = graph[cp->coord.x][cp->coord.y+1];
  128. if((dp->dist==-1 || (dp->dist > cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x, cp->coord.y+1, src.z), hero))) && dp->accesible)
  129. {
  130. dp->dist = cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x, cp->coord.y+1, src.z), hero);
  131. dp->theNodeBefore = cp;
  132. mq.push(dp);
  133. }
  134. }
  135. if(cp->coord.x<graph.size()-1 && cp->coord.y<graph[0].size()-1)
  136. {
  137. CPathNode * dp = graph[cp->coord.x+1][cp->coord.y+1];
  138. if((dp->dist==-1 || (dp->dist > cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x+1, cp->coord.y+1, src.z), hero))) && dp->accesible)
  139. {
  140. dp->dist = cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x+1, cp->coord.y+1, src.z), hero);
  141. dp->theNodeBefore = cp;
  142. mq.push(dp);
  143. }
  144. }
  145. if(cp->coord.x>0 && cp->coord.y<graph[0].size()-1)
  146. {
  147. CPathNode * dp = graph[cp->coord.x-1][cp->coord.y+1];
  148. if((dp->dist==-1 || (dp->dist > cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x-1, cp->coord.y+1, src.z), hero))) && dp->accesible)
  149. {
  150. dp->dist = cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x-1, cp->coord.y+1, src.z), hero);
  151. dp->theNodeBefore = cp;
  152. mq.push(dp);
  153. }
  154. }
  155. if(cp->coord.x<graph.size()-1 && cp->coord.y>0)
  156. {
  157. CPathNode * dp = graph[cp->coord.x+1][cp->coord.y-1];
  158. if((dp->dist==-1 || (dp->dist > cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x+1, cp->coord.y-1, src.z), hero))) && dp->accesible)
  159. {
  160. dp->dist = cp->dist + CGI->mh->getCost(int3(cp->coord.x, cp->coord.y, src.z), int3(cp->coord.x+1, cp->coord.y-1, src.z), hero);
  161. dp->theNodeBefore = cp;
  162. mq.push(dp);
  163. }
  164. }
  165. }
  166. CPathNode * curNode = graph[dest.x][dest.y];
  167. CPath * ret = new CPath;
  168. while(curNode!=graph[src.x][src.y] && curNode != NULL)
  169. {
  170. ret->nodes.push_back(*curNode);
  171. curNode = curNode->theNodeBefore;
  172. }
  173. ret->nodes.push_back(*graph[src.x][src.y]);
  174. for(int i=0; i<graph.size(); ++i)
  175. {
  176. for(int j=0; j<graph[0].size(); ++j)
  177. delete graph[i][j];
  178. }
  179. return ret;
  180. }
  181. void CPathfinder::convertPath(CPath * path, unsigned int mode) //mode=0 -> from 'manifest' to 'object'
  182. {
  183. if (mode==0)
  184. {
  185. for (int i=0;i<path->nodes.size();i++)
  186. {
  187. path->nodes[i].coord = CGHeroInstance::convertPosition(path->nodes[i].coord,true);
  188. }
  189. }
  190. }