Advertisement
Guest User

PathFinder

a guest
Dec 30th, 2018
748
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.88 KB | None | 0 0
  1. //PathFinder by Fleynaro for Industrial RPG
  2.  
  3. #if defined _PathFinder_included
  4. #endinput
  5. #endif
  6. #define _PathFinder_included
  7.  
  8. #define PF:: PF_
  9.  
  10. //Settings
  11. #define PF_PATH_SIZE 512
  12. #define PF_SIDE_SIZE_X 128
  13. #define PF_SIDE_SIZE_Y 128
  14. #define PF_CELL_SIZE_DEFAULT 1.5
  15. #define PF_WALL_UP_MAX 1.0
  16. #define PF_WALL_DOWN_MAX 7.0
  17.  
  18. //System
  19. #define PF_NULL 0
  20. #define PF_SetParent(%0,%1,%2,%3) PF_CoordPlane[%0][%1] = PF_CoordPlane[%0][%1] & ~0xFFFF | (%2 | (%3 << 8))
  21. #define PF_GetParentX(%0,%1) (PF_CoordPlane[%0][%1] & 0xFF)
  22. #define PF_GetParentY(%0,%1) (PF_CoordPlane[%0][%1] >> 8 & 0xFF)
  23. #define PF_GetSavedZ(%0,%1) (float(PF_CoordPlaneZ[%0][%1]) / 1000.0)
  24. #define PF_SaveZ(%0,%1,%2) (PF_CoordPlaneZ[%0][%1] = floatround(%2 * 1000))
  25. #define PF_SetG(%0,%1,%2) PF_CoordPlane[%0][%1] = PF_CoordPlane[%0][%1] & ~(0b11111111111 << 16) | (%2 << 16)
  26. #define PF_GetG(%0,%1) (PF_CoordPlane[%0][%1] >> 16 & 0b11111111111)
  27. #define PF_SetRecheck(%0,%1,%2) PF_CoordPlane[%0][%1] = PF_CoordPlane[%0][%1] & ~(0b1 << 30) | (%2 << 30)
  28. #define PF_IsRecheck(%0,%1) (PF_CoordPlane[%0][%1] >> 30 & 0b1)
  29. #define PF_SetClosed(%0,%1) PF_CoordPlane[%0][%1] = PF_CoordPlane[%0][%1] & ~(0b1 << 31) | (1 << 31)
  30. #define PF_IsClosed(%0,%1) (PF_CoordPlane[%0][%1] >> 31 & 0b1)
  31. #define PF_IsOpen(%0,%1) (PF_CoordPlane[%0][%1] != PF_NULL)
  32. #define PF_IsValid(%0,%1) (0 <= %0 < PF_SIDE_SIZE_X && 0 <= %1 < PF_SIDE_SIZE_Y)
  33.  
  34. #define PF_ABS(%0) ((%0 < 0) ? -(%0) : (%0))
  35.  
  36. #define PF_NOT_COORD 0xFFFFFFFF
  37. #define PF_SetCoord(%0,%1,%2) %0 = (%1 + 1) | ((%2 + 1) << 8)
  38. #define PF_GetCoordX(%0) ((%0 & 0xFF) - 1)
  39. #define PF_GetCoordY(%0) ((%0 >> 8 & 0xFF) - 1)
  40. #define PF_IsCoord(%0) (%0 != 0)
  41.  
  42. //Arrays
  43. new PF_CoordPlane[PF_SIDE_SIZE_X][PF_SIDE_SIZE_Y],
  44. PF_CoordPlaneZ[PF_SIDE_SIZE_X][PF_SIDE_SIZE_Y],
  45. Float: PF_Path[PF_PATH_SIZE][3],
  46. PF_PathSize,
  47. PF_BeginX, PF_BeginY,
  48. PF_FinalX, PF_FinalY;
  49.  
  50. new Float: PF_CellSize,
  51. PF_EndType;
  52. #define PF_END_TYPE_POINT 1
  53. #define PF_END_TYPE_LINE 2
  54. #define PF_END_TYPE_CIRCLE 3
  55. #define PF_END_TYPE_SQUARE 4
  56.  
  57. new Float: PF_StartPos[3],
  58. Float: PF_EndPos[4];
  59. #define PF_SetStart(%0,%1,%2) (PF_StartPos[0] = %0, PF_StartPos[1] = %1, PF_StartPos[2] = %2)
  60. #define PF_SetEndAsPoint(%0,%1,%2) (PF_EndType = PF_END_TYPE_POINT, PF_EndPos[0] = %0, PF_EndPos[1] = %1, PF_EndPos[2] = %2)
  61. #define PF_SetEndAsLine(%0,%1,%2,%3) (PF_EndType = PF_END_TYPE_LINE, PF_EndPos[0] = %0, PF_EndPos[1] = %1, PF_EndPos[2] = %2, PF_EndPos[3] = %3)
  62. #define PF_SetEndAsCircle(%0,%1,%2) (PF_EndType = PF_END_TYPE_CIRCLE, PF_EndPos[0] = %0, PF_EndPos[1] = %1, PF_EndPos[2] = %2)
  63. #define PF_SetEndAsSquare(%0,%1,%2,%3) (PF_EndType = PF_END_TYPE_SQUARE, PF_EndPos[0] = %0, PF_EndPos[1] = %1, PF_EndPos[2] = %2, PF_EndPos[3] = %3)
  64. #define PF_foreach() for ( new pointI = PF_PathSize - 1; pointI != -1; pointI -- )
  65.  
  66. #define PF_RESULT_SUCCESS 1
  67. #define PF_RESULT_SUCCESS_NOT_FULL 2
  68. #define PF_RESULT_FAIL 3
  69. new PF_RESULT;
  70.  
  71. //Stocks
  72. stock PF::CoordPlaneInit()
  73. {
  74. for ( new x; x < PF::SIDE_SIZE_X; x ++ ) {
  75. for ( new y; y < PF::SIDE_SIZE_Y; y ++ ) {
  76. PF::CoordPlane[x][y] = PF::NULL;
  77. PF::CoordPlaneZ[x][y] = 0;
  78. }
  79. }
  80. PF::PathSize = 0;
  81. //PF::EndType = PF::END_TYPE_POINT;
  82. //PF::CellSize = PF::CELL_SIZE_DEFAULT;
  83. PF::RESULT = 0;
  84. return 1;
  85. }
  86.  
  87. //Stocks
  88. stock PF::SetBeginPointDefault()
  89. {
  90. PF::BeginX = PF::SIDE_SIZE_X / 2,
  91. PF::BeginY = PF::SIDE_SIZE_Y / 2;
  92. return 1;
  93. }
  94.  
  95. stock PF::SetBeginPointRelOf(Float: x, Float: y, width = 10, height = 10)
  96. {
  97. PF::SetBeginPointDefault();
  98. if ( x - PF::StartPos[0] > PF::SIDE_SIZE_X * PF::CellSize ) {
  99. PF::BeginX = width;
  100. } else if ( PF::StartPos[0] - x > PF::SIDE_SIZE_X * PF::CellSize ) {
  101. PF::BeginX = PF::SIDE_SIZE_X - width;
  102. }
  103. if ( y - PF::StartPos[1] > PF::SIDE_SIZE_Y * PF::CellSize ) {
  104. PF::BeginY = height;
  105. } else if ( PF::StartPos[1] - y > PF::SIDE_SIZE_Y * PF::CellSize ) {
  106. PF::BeginY = PF::SIDE_SIZE_Y - height;
  107. }
  108. return 1;
  109. }
  110.  
  111.  
  112. //http://qiao.github.io/PathFinding.js/visual/
  113. stock PF::FindPath()
  114. {
  115. PF::CoordPlaneInit();
  116. new X = PF::BeginX,
  117. Y = PF::BeginY,
  118. Float: Z = PF::StartPos[2];
  119.  
  120. /*new Float: x2, Float: y2;
  121. PF::GetGlobalCoord(0, 0, x2, y2);
  122. SetPlayerMapIcon(0, 0, x2, y2, 100.0, 0, 0xFF0000FF, MAPICON_GLOBAL);
  123. PF::GetGlobalCoord(0, 255, x2, y2);
  124. SetPlayerMapIcon(0, 1, x2, y2, 100.0, 0, 0xFF0000FF, MAPICON_GLOBAL);
  125. PF::GetGlobalCoord(255, 0, x2, y2);
  126. SetPlayerMapIcon(0, 2, x2, y2, 100.0, 0, 0xFF0000FF, MAPICON_GLOBAL);
  127. PF::GetGlobalCoord(255, 255, x2, y2);
  128. SetPlayerMapIcon(0, 3, x2, y2, 100.0, 0, 0xFF0000FF, MAPICON_GLOBAL);*/
  129.  
  130. //printf("PF::StartPos[0] = %f, PF::StartPos[1] = %f", PF::StartPos[0], PF::StartPos[1]);
  131. //printf("PF::EndPos[0] = %f, PF::EndPos[1] = %f, PF::CellSize = %f", PF::EndPos[0], PF::EndPos[1], PF::CellSize);
  132. /*new x22 = PF::BeginX + floatround((PF::EndPos[0] - PF::StartPos[0]) / PF::CellSize),
  133. y22 = PF::BeginY + floatround((PF::EndPos[1] - PF::StartPos[1]) / PF::CellSize);
  134. printf("%i <=> %i (%f)", x22, y22, (PF::EndPos[0] - PF::StartPos[0]) / PF::CellSize);*/
  135. PF::FinalX = PF::BeginX + floatround((PF::EndPos[0] - PF::StartPos[0]) / PF::CellSize),
  136. PF::FinalY = PF::BeginY + floatround((PF::EndPos[1] - PF::StartPos[1]) / PF::CellSize);
  137. //printf("PF::FinalX = %i, PF::FinalY = %i", PF::FinalX, PF::FinalY);
  138.  
  139. //new restCount = 0;
  140. while ( !PF::IsFinish(X, Y/*, Z*/) )
  141. {
  142. //PF::GetGlobalCoord(X, Y, x2, y2);
  143. //CreateDynamicPickup(1241, 23, x2, y2, Z);
  144. /*new str[27];
  145. format(str, 27, "%i) %i,%i (%i) | %i,%i", restCount, X, Y, PF::GetF(X, Y), PF::GetParentX(X, Y), PF::GetParentY(X, Y));
  146. CreateDynamic3DTextLabel(str, 0xFFFFFFFF, x2, y2, Z, 30.0);*/
  147. PF::SetClosed(X, Y);
  148. PF::SaveZ(X, Y, Z);
  149. //printf("%i) X, Y, Z = %i,%i,%f", restCount, X, Y, PF::GetSavedZ(X, Y));
  150. new ceils[8],
  151. bool: found = false;
  152. ceils = PF::OpenCeils(X, Y);
  153.  
  154. for ( new i; i < 8 && PF::IsCoord(ceils[i]); i ++ ) {
  155. new Float: curZ,
  156. curX = PF::GetCoordX(ceils[i]),
  157. curY = PF::GetCoordY(ceils[i]);
  158. if ( PF::CheckWall(X, Y, Z, curX, curY, curZ) ) {
  159. if ( PF::IsRecheck(curX, curY) ) {
  160. new px = PF::GetParentX(curX, curY),
  161. py = PF::GetParentY(curX, curY),
  162. Float: zz;
  163. if ( !PF::CheckWall(px, py, PF::GetSavedZ(px,py), curX, curY, zz) ) {
  164. PF::SetParent(curX, curY, X, Y);
  165. PF::SetG(curX, curY, PF::GetG(X, Y) + 1);
  166. }
  167. //printf("check!");
  168. }
  169. X = curX,
  170. Y = curY,
  171. Z = curZ;
  172. found = true;
  173. break;
  174. }
  175. }
  176. if ( !found ) {
  177. if ( X == PF::BeginX && Y == PF::BeginY ) {
  178. PF::RESULT = PF::RESULT_FAIL;
  179. return 0;
  180. }
  181. new px = PF::GetParentX(X, Y);
  182. Y = PF::GetParentY(X, Y);
  183. X = px;
  184. Z = PF::GetSavedZ(X, Y);
  185. //printf("===> Go to parent X, Y, Z = %i,%i,%f", X, Y, Z);
  186. }
  187. //if ( restCount == 120 ) return 0;
  188. //restCount ++;
  189. }
  190. //printf("restCount = %i", restCount);
  191.  
  192. PF::SaveZ(X, Y, Z);
  193. return PF::CreatePath(X, Y);
  194. }
  195.  
  196. //return: make path
  197. stock PF::CreatePath(curX, curY)
  198. {
  199. while ( PF::PathSize < PF::PATH_SIZE ) {
  200. if ( curX == PF::BeginX && curY == PF::BeginY ) {
  201. if ( !PF::RESULT ) {
  202. PF::RESULT = PF::RESULT_SUCCESS;
  203. }
  204. return 1;
  205. }
  206. PF::GetGlobalCoord(curX, curY, PF::Path[PF::PathSize][0], PF::Path[PF::PathSize][1]);
  207. PF::Path[PF::PathSize ++][2] = PF::GetSavedZ(curX, curY);
  208. //printf(">>>>>> X = %i, Y = %i ||||||>>>>> Z = %i, %f", curX, curY, PF::CoordPlaneZ[curX][curY], PF::GetSavedZ(curX, curY));
  209.  
  210. new tempX = curX;
  211. curX = PF::GetParentX(curX, curY),
  212. curY = PF::GetParentY(tempX, curY);
  213. }
  214. PF::RESULT = PF::RESULT_FAIL;
  215. return 0;
  216. }
  217.  
  218. //return: boolean
  219. stock PF::IsFinish(x, y/*, Float: z*/)
  220. {
  221. if ( x == PF::SIDE_SIZE_X - 1 || y == PF::SIDE_SIZE_Y - 1 ) {
  222. PF::RESULT = PF::RESULT_SUCCESS_NOT_FULL;
  223. return 1;
  224. }
  225. new Float: globalX, Float: globalY;
  226. PF::GetGlobalCoord(x, y, globalX, globalY);
  227.  
  228. switch ( PF::EndType )
  229. {
  230. case PF::END_TYPE_POINT: {
  231. if ( x == PF::FinalX && y == PF::FinalY ) {
  232. return 1;
  233. }
  234. }
  235. case PF::END_TYPE_CIRCLE: {
  236. if ( floatpower(globalX - PF::EndPos[0], 2) + floatpower(globalY - PF::EndPos[1], 2) <= floatpower(PF::EndPos[2], 2) ) {
  237. return 1;
  238. }
  239. }
  240. }
  241. return 0;
  242. }
  243.  
  244. //return: boolean
  245. stock PF::CheckWall(parentX, parentY, Float: parentZ, ceilX, ceilY, &Float: ceilZ)
  246. {
  247. new Float: StartX = parentX,
  248. Float: StartY = parentY,
  249. Float: EndX,
  250. Float: EndY,
  251. Float: x, Float: y, Float: z;
  252. PF::GetGlobalCoord(parentX, parentY, StartX, StartY);
  253. PF::GetGlobalCoord(ceilX, ceilY, EndX, EndY);
  254. return ( CA_RayCastLine_(EndX, EndY, parentZ + PF::WALL_UP_MAX, EndX, EndY, parentZ - PF::WALL_DOWN_MAX, x, y, ceilZ) != 0 && (-PF::WALL_DOWN_MAX <= (ceilZ - parentZ) <= PF::WALL_UP_MAX) && CA_RayCastLine_(StartX, StartY, parentZ + 0.5, EndX, EndY, ceilZ + 0.5, x, y, z) == 0 );
  255. }
  256.  
  257. //return: 1
  258. stock PF::GetGlobalCoord(x, y, &Float: resultX, &Float: resultY)
  259. {
  260. resultX = PF::StartPos[0] + (x - PF::BeginX) * PF::CellSize;
  261. resultY = PF::StartPos[1] + (y - PF::BeginY) * PF::CellSize;
  262. return 1;
  263. }
  264.  
  265. //return: ceil coord
  266. stock PF::OpenCeils(curX, curY)
  267. {
  268. new ceils[8],
  269. ceilsCount;
  270.  
  271. for ( new rX = -1; rX <= 1; rX ++ ) {
  272. for ( new rY = -1; rY <= 1; rY ++ ) {
  273. if ( rX == 0 && rY == 0 ) continue;
  274. new x = curX + rX,
  275. y = curY + rY;
  276.  
  277. if ( PF::IsValid(x, y) && !PF::IsClosed(x, y) ) {
  278. new G = PF::GetG(curX, curY) + 1,
  279. Float: z;
  280. if ( !PF::IsOpen(x, y) || (G <= PF::GetG(x, y) && PF::CheckWall(PF::GetParentX(x, y), PF::GetParentY(x, y), PF::GetSavedZ(PF::GetParentX(x, y),PF::GetParentY(x, y)), x, y, z)) ) {
  281. PF::SetParent(x, y, curX, curY);
  282. PF::SetG(x, y, G);
  283. PF::SetRecheck(x, y, 0);
  284. //printf("child = %i,%i with G = %i, F = %i", x, y, G, PF::GetF(x, y));
  285. } else {
  286. if ( G > PF::GetG(x, y) ) {
  287. PF::SetRecheck(x, y, 1);
  288. }
  289. }
  290. ceils = PF::AddCeilToSortArray(x, y, ceils, ceilsCount ++);
  291. }
  292. }
  293. }
  294.  
  295. return ceils;
  296. }
  297.  
  298. //return: add to ceil array and sort
  299. stock PF::AddCeilToSortArray(x, y, array[8], ceilsCount)
  300. {
  301. new F = PF::GetF(x, y);
  302. for ( new i; i < sizeof(array) && PF::IsCoord(array[i]); i ++ ) {
  303. if ( F < PF::GetF(PF::GetCoordX(array[i]), PF::GetCoordY(array[i])) ) {
  304. for ( new j = ceilsCount - 1; j != i - 1; j -- ) {
  305. array[j + 1] = array[j];
  306. }
  307. PF::SetCoord(array[i], x, y);
  308.  
  309. //для рандома
  310. if ( i > 0 && PF::GetF(PF::GetCoordX(array[i - 1]), PF::GetCoordY(array[i - 1])) == F ) {
  311. if ( random(2) == 1 ) {
  312. new temp = array[i - 1];
  313. array[i - 1] = array[i];
  314. array[i] = temp;
  315. }
  316. }
  317.  
  318. return array;
  319. }
  320. }
  321. PF::SetCoord(array[ceilsCount], x, y);
  322. return array;
  323. }
  324.  
  325. //return: F of a ceil
  326. stock PF::GetF(x, y)
  327. {
  328. new H = 0;
  329. if ( PF::EndType != PF::END_TYPE_LINE ) {
  330. H = PF::ABS(PF::FinalX - x) + PF::ABS(PF::FinalY - y);
  331. }
  332. return (PF::GetG(x, y) + H);
  333. }
  334.  
  335. //return: needed axis (0 - x, 1 - y)
  336. stock PF::NeededAxis(x, y)
  337. {
  338. return PF::ABS(PF::FinalX - x) > PF::ABS(PF::FinalY - y);
  339. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement