algorithm.cpp.svn-base
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:8k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <math.h>
  4. #include "algorithm.h"
  5. #ifdef __cplusplus
  6. extern "C" {
  7. #endif /* __cplusplus */
  8. #define SOLUTION_MAX 5000
  9. #define FULL_LIST_MAX 480000
  10. #define OPEN_LIST_MAX 160000
  11. #define LOOKUPS_MAX 200000
  12. #ifdef WIN32
  13. #include <windows.h>
  14. #else
  15. #include <sys/time.h>
  16. static unsigned long
  17. GetTickCount ()
  18. {
  19. struct timeval tv;
  20. gettimeofday (&tv, (struct timezone *) NULL);
  21. return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
  22. }
  23. #endif /* WIN32 */
  24. /*******************************************/
  25. static unsigned char *default_weight = NULL;
  26. static inline int
  27. QuickfindFloatMax(QuicksortFloat* a, int val, int lo, int hi)
  28. {
  29. int x = (lo+hi)>>1;
  30. if (val == a[x].val)
  31. return x;
  32. if (x != hi - 1 && val < a[x].val)
  33. return QuickfindFloatMax(a, val, x, hi);
  34. if (x != lo && val > a[x].val)
  35. return QuickfindFloatMax(a, val, lo, x);
  36. if (val < a[x].val)
  37. return x+1;
  38. else
  39. return x;
  40. }
  41. static inline char
  42. CalcPath_getMap(const char *map, unsigned long width, unsigned long height, pos *p) {
  43. if (p->x >= width || p->y >= height) {
  44. return 0;
  45. } else {
  46. return map[(p->y*width)+p->x];
  47. }
  48. }
  49. // Create a new, empty pathfinding session.
  50. // You must initialize it with CalcPath_init()
  51. CalcPath_session *
  52. CalcPath_new ()
  53. {
  54. CalcPath_session *session;
  55. session = (CalcPath_session*) malloc (sizeof (CalcPath_session));
  56. session->first_time = 1;
  57. session->map_sv = NULL;
  58. session->weight_sv = NULL;
  59. return session;
  60. }
  61. // Create a new pathfinding session, or reset an existing session.
  62. // Resetting is preferred over destroying and creating, because it saves
  63. // unnecessary memory allocations, thus improving performance.
  64. CalcPath_session *
  65. CalcPath_init (CalcPath_session *session, const char* map, const unsigned char* weight,
  66. unsigned long width, unsigned long height,
  67. pos * start, pos * dest, unsigned long time_max)
  68. {
  69. if (!session)
  70. session = CalcPath_new ();
  71. pos_list * solution = &session->solution;
  72. pos_ai_list * fullList = &session->fullList;
  73. index_list * openList = &session->openList;
  74. lookups_list * lookup = &session->lookup;
  75. unsigned long i;
  76. int index;
  77. session->width = width;
  78. session->height = height;
  79. if (!session->first_time) {
  80. free (session->start);
  81. free (session->dest);
  82. }
  83. session->start = start;
  84. session->dest = dest;
  85. session->time_max = time_max;
  86. session->map = map;
  87. if (weight)
  88. session->weight = weight;
  89. else {
  90. if (!default_weight) {
  91. default_weight = (unsigned char *) malloc(256);
  92. default_weight[0] = 255;
  93. memset(default_weight + 1, 1, 255);
  94. }
  95. session->weight = (const unsigned char *) default_weight;
  96. }
  97. if (session->first_time) {
  98. session->solution.array = (pos *) malloc(SOLUTION_MAX * sizeof(pos));
  99. session->fullList.array = (pos_ai*) malloc(FULL_LIST_MAX*sizeof(pos_ai));
  100. session->openList.array = (QuicksortFloat*) malloc(OPEN_LIST_MAX*sizeof(QuicksortFloat));
  101. session->lookup.array = (int*) malloc(LOOKUPS_MAX*sizeof(int));
  102. }
  103. solution->size = 0;
  104. openList->size = 1;
  105. fullList->size = 1;
  106. fullList->array[0].p = *start;
  107. fullList->array[0].g = 0;
  108. fullList->array[0].f = abs(start->x - dest->x) + abs(start->y - dest->y);
  109. fullList->array[0].parent = -1;
  110. openList->array[0].val = fullList->array[0].f;
  111. openList->array[0].index = 0;
  112. for (i = 0; i < width * height;i++) {
  113. lookup->array[i] = 999999;
  114. }
  115. index = fullList->array[0].p.y*width + fullList->array[0].p.x;
  116. lookup->array[index] = 0;
  117. lookup->size = width*height;
  118. session->first_time = 0;
  119. return session;
  120. }
  121. /*
  122.  * Return values:
  123.  * -2 = session not initialized (you must call CalcPath_init() first)
  124.  * -1 = failed (no solution found)
  125.  *  0 = timeout (pathfinding not yet complete; run this function again to resume)
  126.  *  1 = finished
  127.  */
  128. int
  129. CalcPath_pathStep(CalcPath_session * session)
  130. {
  131. pos mappos;
  132. int newg;
  133. unsigned char successors_size;
  134. int j, cur, successors_start,suc, found,index;
  135. unsigned long timeout = (unsigned long) GetTickCount();
  136. unsigned int loop = 0;
  137. pos_list * solution = &session->solution;
  138. pos_ai_list *fullList = &session->fullList;
  139. index_list *openList = &session->openList;
  140. lookups_list *lookup = &session->lookup;
  141. const char* map = session->map;
  142. const unsigned char* weight  = session->weight;
  143. unsigned long width = session->width;
  144. unsigned long height = session->height;
  145. pos * start = session->start;
  146. pos * dest = session->dest;
  147. unsigned long time_max = session->time_max;
  148. if (session->first_time) {
  149. return -2;
  150. }
  151. if (start == NULL && dest == NULL) {
  152. return -1;
  153. }
  154. if (CalcPath_getMap(map, width, height, start) == 0 || CalcPath_getMap(map, width, height, dest) ==  0) {
  155. return -1;
  156. }
  157. while (1) {
  158. loop++;
  159. if (loop == 50) {
  160. if (GetTickCount() - timeout > time_max)
  161. return 0;
  162. else
  163. loop = 0;
  164. }
  165. //get next from the list
  166. if (openList->size == 0) {
  167. //failed!
  168. return -1;
  169. }
  170. openList->size--;
  171. cur = openList->array[openList->size].index;
  172. //has higher g value than another with same state?
  173. index = fullList->array[cur].p.y*width + fullList->array[cur].p.x;
  174. if (fullList->array[cur].g > lookup->array[index])
  175. continue;
  176. //check if finished
  177. if (dest->x == fullList->array[cur].p.x && dest->y == fullList->array[cur].p.y) {
  178. do {
  179. solution->array[solution->size] = fullList->array[cur].p;
  180. cur = fullList->array[cur].parent;
  181. solution->size++;
  182. } while (cur != -1);
  183. return 1;
  184. }
  185. //Get successors
  186. successors_start = fullList->size;
  187. successors_size = 0;
  188. mappos.x = fullList->array[cur].p.x-1;
  189. mappos.y = fullList->array[cur].p.y;
  190. if (CalcPath_getMap(map, width, height, &mappos) != 0
  191. && !(fullList->array[cur].parent >= 0 && fullList->array[fullList->array[cur].parent].p.x == mappos.x
  192. && fullList->array[fullList->array[cur].parent].p.y == mappos.y)) {
  193. fullList->array[fullList->size].p = mappos;
  194. fullList->size++;
  195. successors_size++;
  196. }
  197. mappos.x = fullList->array[cur].p.x;
  198. mappos.y = fullList->array[cur].p.y-1;
  199. if (CalcPath_getMap(map, width, height, &mappos) != 0
  200. && !(fullList->array[cur].parent >= 0 && fullList->array[fullList->array[cur].parent].p.x == mappos.x
  201. && fullList->array[fullList->array[cur].parent].p.y == mappos.y)) {
  202. fullList->array[fullList->size].p = mappos;
  203. fullList->size++;
  204. successors_size++;
  205. }
  206. mappos.x = fullList->array[cur].p.x+1;
  207. mappos.y = fullList->array[cur].p.y;
  208. if (CalcPath_getMap(map, width, height, &mappos) != 0
  209. && !(fullList->array[cur].parent >= 0 && fullList->array[fullList->array[cur].parent].p.x == mappos.x
  210. && fullList->array[fullList->array[cur].parent].p.y == mappos.y)) {
  211. fullList->array[fullList->size].p = mappos;
  212. fullList->size++;
  213. successors_size++;
  214. }
  215. mappos.x = fullList->array[cur].p.x;
  216. mappos.y = fullList->array[cur].p.y+1;
  217. if (CalcPath_getMap(map, width, height, &mappos) != 0
  218. && !(fullList->array[cur].parent >= 0 && fullList->array[fullList->array[cur].parent].p.x == mappos.x
  219. && fullList->array[fullList->array[cur].parent].p.y == mappos.y)) {
  220. fullList->array[fullList->size].p = mappos;
  221. fullList->size++;
  222. successors_size++;
  223. }
  224. //do the step
  225. for (j=0;j < successors_size;j++) {
  226. suc = successors_start+j;
  227. newg = fullList->array[cur].g + weight[CalcPath_getMap(map, width, height, &fullList->array[suc].p)];
  228. index = fullList->array[suc].p.y*width + fullList->array[suc].p.x;
  229. if (newg >= lookup->array[index])
  230. continue;
  231. fullList->array[suc].g = newg;
  232. fullList->array[suc].f = newg + abs(fullList->array[suc].p.x - dest->x) + abs(fullList->array[suc].p.y - dest->y);
  233. fullList->array[suc].parent = cur;
  234. lookup->array[index] = fullList->array[suc].g;
  235. if (openList->size > 0)
  236. found = QuickfindFloatMax(openList->array, fullList->array[suc].f, 0, openList->size);
  237. else
  238. found = 0;
  239. if (openList->size - found > 0) {
  240. memmove(openList->array+found+1,openList->array+found, sizeof(QuicksortFloat)*(openList->size - found));
  241. }
  242. openList->array[found].index = suc;
  243. openList->array[found].val = fullList->array[suc].f;
  244. openList->size++;
  245. }
  246. }
  247. return 0;
  248. }
  249. void
  250. CalcPath_destroy (CalcPath_session *session)
  251. {
  252. if (!session->first_time) {
  253. free (session->start);
  254. free (session->dest);
  255. free (session->solution.array);
  256. free (session->fullList.array);
  257. free (session->openList.array);
  258. free (session->lookup.array);
  259. }
  260. free (session);
  261. }
  262. #ifdef __cplusplus
  263. }
  264. #endif /* __cplusplus */