OSPREUSE.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OSPREUSE.CPP
  21. //Description : Object SeekPathReuse
  22. //Owner : Alex
  23. #include <OSPREUSE.h>
  24. #include <OSPATH.h>
  25. #include <ALL.h>
  26. #include <OWORLD.h>
  27. #include <OUNIT.h>
  28. #include <OSYS.h>
  29. #ifdef NO_DEBUG_SEARCH
  30. #undef err_when
  31. #undef err_here
  32. #undef err_if
  33. #undef err_else
  34. #undef err_now
  35. #define err_when(cond)
  36. #define err_here()
  37. #define err_if(cond)
  38. #define err_else
  39. #define err_now(msg)
  40. #undef debug_reuse_check_sub_mode_node
  41. #define debug_reuse_check_sub_mode_node(x, y)
  42. #undef DEBUG
  43. #endif
  44. //--------------------------------------------------------//
  45. // define static variables
  46. //--------------------------------------------------------//
  47. int SeekPathReuse::max_node;
  48. short SeekPathReuse::total_num_of_path;
  49. short SeekPathReuse::cur_path_num;
  50. short SeekPathReuse::unit_size;
  51. DWORD SeekPathReuse::cur_group_id;
  52. char SeekPathReuse::mobile_type;
  53. char SeekPathReuse::unit_nation_recno;
  54. short SeekPathReuse::move_scale;
  55. short SeekPathReuse::search_mode;
  56. short SeekPathReuse::reuse_mode;
  57. short SeekPathReuse::reuse_path_status;
  58. short SeekPathReuse::reuse_path_dist;
  59. short *SeekPathReuse::reuse_node_matrix=NULL;
  60. char SeekPathReuse::reuse_nation_passable[MAX_NATION+1] = {0};
  61. char SeekPathReuse::reuse_search_sub_mode;
  62. //----------------- backup leader path(reference path) ----------------------//
  63. short SeekPathReuse::leader_path_num;
  64. ResultNode *SeekPathReuse::reuse_leader_path_backup;
  65. int SeekPathReuse::reuse_leader_path_node_num;
  66. int SeekPathReuse::leader_path_start_x;
  67. int SeekPathReuse::leader_path_start_y;
  68. int SeekPathReuse::leader_path_dest_x;
  69. int SeekPathReuse::leader_path_dest_y;
  70. //----------- decide which offset method is used ----------//
  71. int SeekPathReuse::start_x_offset;
  72. int SeekPathReuse::start_y_offset;
  73. int SeekPathReuse::dest_x_offset;
  74. int SeekPathReuse::dest_y_offset;
  75. int SeekPathReuse::x_offset;
  76. int SeekPathReuse::y_offset;
  77. int SeekPathReuse::formation_x_offset;
  78. int SeekPathReuse::formation_y_offset;
  79. int SeekPathReuse::start_x;
  80. int SeekPathReuse::start_y;
  81. int SeekPathReuse::dest_x;
  82. int SeekPathReuse::dest_y;
  83. int SeekPathReuse::vir_dest_x;
  84. int SeekPathReuse::vir_dest_y;
  85. //---------- the current constructing result path --------//
  86. ResultNode *SeekPathReuse::path_reuse_result_node_ptr;
  87. int SeekPathReuse::num_of_result_node;
  88. ResultNode *SeekPathReuse::cur_result_node_ptr;
  89. short SeekPathReuse::result_node_array_def_size;
  90. short SeekPathReuse::result_node_array_reset_amount;
  91. //-- determine the current offset difference(leader path information) --//
  92. ResultNode *SeekPathReuse::cur_leader_node_ptr;
  93. int SeekPathReuse::cur_leader_node_num;
  94. short SeekPathReuse::leader_vec_x;
  95. short SeekPathReuse::leader_vec_y;
  96. //----------- for smoothing the result path --------------//
  97. short SeekPathReuse::vec_x;
  98. short SeekPathReuse::vec_y;
  99. short SeekPathReuse::new_vec_x;
  100. short SeekPathReuse::new_vec_y;
  101. int SeekPathReuse::vec_magn;
  102. int SeekPathReuse::new_vec_magn;
  103. int SeekPathReuse::result_vec_x;
  104. int SeekPathReuse::result_vec_y;
  105. //-------- Begin of function SeekPathReuse::init ---------//
  106. void SeekPathReuse::init(int maxNode)
  107. {
  108. //------------------ initialize parameters ----------------//
  109. incomplete_search = 0;
  110. max_node = maxNode;
  111. total_num_of_path = 0;
  112. cur_path_num = 0;
  113. cur_group_id = 0;
  114. mobile_type = 0;
  115. search_mode = 0;
  116. reuse_mode = 0;
  117. reuse_path_status = 0;
  118. reuse_leader_path_backup = NULL;
  119. reuse_leader_path_node_num = 0;
  120. leader_path_start_x = 0;
  121. leader_path_start_y = 0;
  122. leader_path_dest_x = 0;
  123. leader_path_dest_y = 0;
  124. start_x_offset = 0;
  125. start_y_offset = 0;
  126. dest_x_offset = 0;
  127. dest_y_offset = 0;
  128. x_offset = 0;
  129. y_offset = 0;
  130. vir_dest_x = 0;
  131. vir_dest_y = 0;
  132. num_of_result_node = 0;
  133. result_node_array_def_size = 0;
  134. result_node_array_reset_amount = 10; // dafault value is 10
  135. cur_result_node_ptr = NULL;
  136. path_reuse_result_node_ptr = NULL;
  137. cur_leader_node_ptr = NULL;
  138. cur_leader_node_num = 0;
  139. leader_path_num = -1; // valid value is not less than 0
  140. leader_vec_x = 0;
  141. leader_vec_y = 0;
  142. init_reuse_node_matrix(); // initialize node matrix for setting offset path
  143. }
  144. //--------- End of function SeekPathReuse::init ---------//
  145. //-------- Begin of function SeekPathReuse::deinit ---------//
  146. void SeekPathReuse::deinit()
  147. {
  148. deinit_reuse_search(); // destruct data structure
  149. if(reuse_node_matrix)
  150. {
  151. mem_del(reuse_node_matrix);
  152. reuse_node_matrix = NULL;
  153. }
  154. }
  155. //--------- End of function SeekPathReuse::deinit ---------//
  156. //-------- Begin of function SeekPathReuse::init_reuse_node_matrix ---------//
  157. void SeekPathReuse::init_reuse_node_matrix()
  158. {
  159. reuse_node_matrix = (short*) mem_add(sizeof(short)*MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC/4);
  160. }
  161. //--------- End of function SeekPathReuse::init_reuse_node_matrix ---------//
  162. //-------- Begin of function SeekPathReuse::deinit_reuse_search ---------//
  163. // destruct data structure
  164. //
  165. void SeekPathReuse::deinit_reuse_search()
  166. {
  167. if(reuse_leader_path_backup!=NULL)
  168. {
  169. mem_del(reuse_leader_path_backup);
  170. reuse_leader_path_backup = NULL;
  171. }
  172. err_when(reuse_leader_path_backup!=NULL);
  173. reuse_leader_path_node_num = 0;
  174. leader_path_start_x = 0;
  175. leader_path_start_y = 0;
  176. leader_path_dest_x = 0;
  177. leader_path_dest_y = 0;
  178. }
  179. //--------- End of function SeekPathReuse::deinit_reuse_search ---------//
  180. //-------- Begin of function SeekPathReuse::init_reuse_search ---------//
  181. // re-construct data structure and re-initialzie parameters
  182. //
  183. void SeekPathReuse::init_reuse_search()
  184. {
  185. incomplete_search = 0;
  186. cur_path_num = 0;
  187. result_node_array_def_size = 0;
  188. leader_path_num = -1; // set to invalid value -1 after each initialization
  189. cur_result_node_ptr = NULL;
  190. path_reuse_result_node_ptr = NULL;
  191. num_of_result_node = 0;
  192. deinit_reuse_search();
  193. reuse_leader_path_backup = NULL;
  194. reuse_leader_path_node_num = 0;
  195. leader_path_start_x = 0;
  196. leader_path_start_y = 0;
  197. leader_path_dest_x = 0;
  198. leader_path_dest_y = 0;
  199. }
  200. //--------- End of function SeekPathReuse::init_reuse_search ---------//
  201. //-------- Begin of function SeekPathReuse::get_reuse_path_status ---------//
  202. char SeekPathReuse::get_reuse_path_status()
  203. {
  204. return (char) reuse_path_status;
  205. }
  206. //--------- End of function SeekPathReuse::get_reuse_path_status ---------//
  207. //-------- Begin of function SeekPathReuse::bound_check_x ---------//
  208. /*inline void SeekPathReuse::bound_check_x(int& x)
  209. {
  210. if(x<0)
  211. x = 0;
  212. else if(x>=MAX_WORLD_X_LOC)
  213. x = MAX_WORLD_X_LOC-move_scale;
  214. }*/
  215. //--------- End of function SeekPathReuse::bound_check_x ---------//
  216. //-------- Begin of function SeekPathReuse::bound_check_y ---------//
  217. /*inline void SeekPathReuse::bound_check_y(int& y)
  218. {
  219. if(y<0)
  220. y = 0;
  221. else if(y>=MAX_WORLD_X_LOC)
  222. y = MAX_WORLD_X_LOC-move_scale;
  223. }*/
  224. //--------- End of function SeekPathReuse::bound_check_y ---------//
  225. //-------- Begin of function SeekPathReuse::call_seek ---------//
  226. /*inline ResultNode* SeekPathReuse::call_seek(int sx, int sy, int dx, int dy, DWORD groupId, char mobileType,
  227. short searchMode, int& nodeCount)
  228. {
  229. err_when(unit_size!=1);
  230. seek_path.seek(sx, sy, dx, dy, groupId, mobileType, searchMode);
  231. return seek_path.get_result(nodeCount, reuse_path_dist);
  232. }*/
  233. //--------- End of function SeekPathReuse::call_seek ---------//
  234. //-------- Begin of function SeekPathReuse::set_offset_condition ---------//
  235. // store the starting location, destination, offset of each path
  236. //
  237. void SeekPathReuse::set_offset_condition(int startX, int startY, int destX, int destY)
  238. {
  239. //-------------------------------------------------------------//
  240. // the offset is used to determine what the methods is used to
  241. // do the path-reuse
  242. //-------------------------------------------------------------//
  243. err_when(leader_path_num>=cur_path_num);
  244. if(cur_path_num>0)
  245. {
  246. //---- the following value is useless if no valid leader path -------//
  247. start_x_offset = startX - leader_path_start_x;
  248. start_y_offset = startY - leader_path_start_y;
  249. dest_x_offset = destX - leader_path_dest_x;
  250. dest_y_offset = destY - leader_path_dest_y;
  251. }
  252. else // no leader path is available
  253. {
  254. err_when(reuse_path_status != REUSE_PATH_FIRST_SEEK);
  255. start_x_offset = start_y_offset = dest_x_offset = dest_y_offset = 0;
  256. leader_path_start_x = startX;
  257. leader_path_start_y = startY;
  258. leader_path_dest_x = destX;
  259. leader_path_dest_y = destY;
  260. leader_path_num = cur_path_num;
  261. }
  262. }
  263. //--------- End of function SeekPathReuse::set_offset_condition ---------//
  264. //-------- Begin of function SeekPathReuse::set_next_cur_path_num ---------//
  265. // This function may be called outside by Unit::move_to
  266. //
  267. void SeekPathReuse::set_next_cur_path_num()
  268. {
  269. cur_path_num++;
  270. }
  271. //--------- End of function SeekPathReuse::set_next_cur_path_num ---------//
  272. //-------- Begin of function SeekPathReuse::is_node_avail_empty ---------//
  273. // return 1 if node available for search is zero
  274. // return 0 otherwise
  275. //
  276. int SeekPathReuse::is_node_avail_empty()
  277. {
  278. err_when(unit_size!=1);
  279. return seek_path.total_node_avail<MIN_BACKGROUND_NODE_USED_UP;
  280. }
  281. //--------- End of function SeekPathReuse::is_node_avail_empty ---------//
  282. //-------- Begin of function SeekPathReuse::is_leader_path_valid ---------//
  283. // return 1 leader path is valid
  284. // return 0 otherwise
  285. //
  286. int SeekPathReuse::is_leader_path_valid()
  287. {
  288. if(leader_path_num<0 || reuse_leader_path_node_num<2)
  289. {
  290. //---------------------------------------------------------------//
  291. // if no leader path of if the number of node in the leader path < 2.
  292. // A new one will be chosed to be the leader-path.
  293. //---------------------------------------------------------------//
  294. if(reuse_leader_path_backup!=NULL)
  295. {
  296. mem_del(reuse_leader_path_backup);
  297. reuse_leader_path_backup = NULL;
  298. }
  299. err_when(reuse_leader_path_backup!=NULL);
  300. //start_x_offset = start_y_offset = dest_x_offset = dest_y_offset = 0;
  301. leader_path_start_x = start_x;
  302. leader_path_start_y = start_y;
  303. leader_path_dest_x = dest_x;
  304. leader_path_dest_y = dest_y;
  305. leader_path_num = cur_path_num; // set leader path number
  306. if(is_node_avail_empty())
  307. {
  308. incomplete_search++;
  309. reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH;
  310. return 0;
  311. }
  312. path_reuse_result_node_ptr = call_seek(start_x, start_y, vir_dest_x, vir_dest_y, cur_group_id, mobile_type,
  313. SEARCH_MODE_IN_A_GROUP, num_of_result_node);
  314. //------------------------------------------------------------------------//
  315. // checking for incomplete searching
  316. //------------------------------------------------------------------------//
  317. if(!path_reuse_result_node_ptr || !num_of_result_node)
  318. {
  319. incomplete_search = 1;
  320. reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH;
  321. return 0;
  322. }
  323. err_when(!path_reuse_result_node_ptr || !num_of_result_node);
  324. ResultNode *lastNodePtr = path_reuse_result_node_ptr + num_of_result_node - 1;
  325. if(lastNodePtr->node_x!=vir_dest_x || lastNodePtr->node_y!=vir_dest_y)
  326. {
  327. err_when(unit_size!=1);
  328. if(seek_path.path_status==PATH_NODE_USED_UP)
  329. {
  330. incomplete_search++;
  331. reuse_path_status = REUSE_PATH_INCOMPLETE_SEARCH;
  332. }
  333. }
  334. return 0;
  335. }
  336. return 1;
  337. }
  338. //--------- End of function SeekPathReuse::is_leader_path_valid ---------//
  339. //-------- Begin of function SeekPathReuse::set_nation_passable ---------//
  340. void SeekPathReuse::set_nation_passable(char nationPassable[])
  341. {
  342. memcpy(reuse_nation_passable+1, nationPassable, sizeof(char)*MAX_NATION);
  343. }
  344. //--------- End of function SeekPathReuse::set_nation_passable ---------//
  345. //-------- Begin of function SeekPathReuse::set_sub_mode ---------//
  346. void SeekPathReuse::set_sub_mode(char subMode)
  347. {
  348. reuse_search_sub_mode = subMode;
  349. }
  350. //--------- End of function SeekPathReuse::set_sub_mode ---------//
  351. //-------- Begin of function SeekPathReuse::set_status ---------//
  352. void SeekPathReuse::set_status(char newStatus)
  353. {
  354. reuse_path_status = newStatus;
  355. }
  356. //--------- End of function SeekPathReuse::set_status ---------//
  357. //-------- Begin of function SeekPathReuse::count_path_dist ---------//
  358. short SeekPathReuse::count_path_dist(ResultNode* nodeArray, int nodeNum)
  359. {
  360. if(!nodeArray || !nodeNum)
  361. return 0;
  362. err_when(nodeNum<2);
  363. ResultNode *preNode = nodeArray;
  364. ResultNode *curNode = preNode+1;
  365. int processed = 1;
  366. int xDist, yDist;
  367. short pathDist = 0;
  368. while(processed++ < nodeNum)
  369. {
  370. xDist = abs(preNode->node_x - curNode->node_x);
  371. yDist = abs((preNode++)->node_y - (curNode++)->node_y);
  372. err_when((!xDist && !yDist) || (xDist && yDist && xDist!=yDist));
  373. pathDist += (xDist) ? xDist : yDist;
  374. }
  375. err_when(mobile_type!=UNIT_LAND && pathDist%2);
  376. return pathDist;
  377. }
  378. //--------- End of function SeekPathReuse::count_path_dist ---------//
  379. //-------- Begin of function SeekPathReuse::add_result ---------//
  380. // add the result node in the reuse result node array and resize
  381. // the array size if default size is not large enough to hold the
  382. // data
  383. //
  384. void SeekPathReuse::add_result(int x, int y)
  385. {
  386. debug_reuse_check_sub_mode_node(x, y);
  387. if(num_of_result_node>=result_node_array_def_size) // the array is not enough to hold the data
  388. {
  389. result_node_array_def_size += result_node_array_reset_amount;
  390. path_reuse_result_node_ptr = (ResultNode*) mem_resize(path_reuse_result_node_ptr, sizeof(ResultNode)* result_node_array_def_size);
  391. cur_result_node_ptr = path_reuse_result_node_ptr+num_of_result_node;
  392. }
  393. cur_result_node_ptr->node_x = x;
  394. cur_result_node_ptr->node_y = y;
  395. cur_result_node_ptr++;
  396. num_of_result_node++;
  397. }
  398. //--------- End of function SeekPathReuse::add_result ---------//
  399. //-------- Begin of function SeekPathReuse::set_index_in_node_matrix ---------//
  400. // Generally speaking, the value of the node in node matrix is less than max_node.
  401. // In order to set a offset path in the node matrix and not conflict the shortest
  402. // path searching, value > max_node is chosed.
  403. //
  404. // In this method, 4 value(max_node+k, where k is 1,..,4) is used for 2x2 node.
  405. // The value k indicate which point in the node will be chosen to be the connection
  406. // point to the offset path.
  407. //
  408. void SeekPathReuse::set_index_in_node_matrix(int xLoc, int yLoc)
  409. {
  410. short *curLocInNodeMatrix;
  411. int x = xLoc;
  412. int y = yLoc;
  413. //-------------------- boundary checking ---------------//
  414. bound_check_x(x);
  415. bound_check_y(y);
  416. err_when(unit_size!=1);
  417. curLocInNodeMatrix = reuse_node_matrix + MAX_WORLD_X_LOC/2*(y/2) + (x/2);
  418. //-------------------------------------------------------------------------//
  419. // the location is changed into 2x2 node format.
  420. // -- -- In fact, the location is in one of the 4 points in the node.
  421. // |1 |2 | The value k is shown in the figure. The value in the
  422. // -- -- node_matrix is set to max_node+k.
  423. // |3 |4 |
  424. // -- -- The value will be set again if two points is available in the
  425. // node and the last one will be chosen.
  426. //-------------------------------------------------------------------------//
  427. if(mobile_type==UNIT_LAND)
  428. *curLocInNodeMatrix = max_node + 1 + (x%2) + 2*(y%2);
  429. else
  430. *curLocInNodeMatrix = max_node + 1 + (x%4!=0) + 2*(y%4!=0);
  431. }
  432. //--------- End of function SeekPathReuse::set_index_in_node_matrix ---------//
  433. //-------- Begin of function SeekPathReuse::move_within_map ---------//
  434. // locations (preX, preY) and (curX, curY) both are inside the map
  435. //
  436. // add one point
  437. //
  438. void SeekPathReuse::move_within_map(int preX, int preY, int curX, int curY)
  439. {
  440. err_when(preX<0 || preX>=MAX_WORLD_X_LOC || preY<0 || preY>=MAX_WORLD_Y_LOC);
  441. err_when(curX<0 || curX>=MAX_WORLD_X_LOC || curY<0 || curY>=MAX_WORLD_Y_LOC);
  442. add_result(curX, curY);
  443. }
  444. //--------- End of function SeekPathReuse::move_within_map ---------//
  445. //-------- Begin of function SeekPathReuse::move_outside_map ---------//
  446. // location (preX, preY) is inside the map while location (curX, curY)
  447. // is outside the map
  448. //
  449. // add one/two points
  450. //
  451. void SeekPathReuse::move_outside_map(int preX, int preY, int curX, int curY)
  452. {
  453. err_when(preX<0 || preX>=MAX_WORLD_X_LOC || preY<0 || preY>=MAX_WORLD_Y_LOC);
  454. err_when(curX>=0 && curX<MAX_WORLD_X_LOC && curY>=0 && curY<MAX_WORLD_Y_LOC);
  455. int vecX = curX-preX;
  456. int vecY = curY-preY;
  457. if(vecX!=0) vecX /= abs(vecX);
  458. if(vecY!=0) vecY /= abs(vecY);
  459. int vertical=0; // 1 for upper edge, 2 for lower edge
  460. int horizontal=0; // 1 for left edge, 2 for right edge
  461. int xStep, yStep;
  462. if(curX<0)
  463. {
  464. xStep = preX;
  465. horizontal = 1;
  466. }
  467. else if(curX>=MAX_WORLD_X_LOC)
  468. {
  469. xStep = MAX_WORLD_X_LOC-preX-1;
  470. horizontal = 2;
  471. }
  472. else
  473. err_here();
  474. if(curY<0)
  475. {
  476. yStep = preY;
  477. vertical = 1;
  478. }
  479. else if(curY>=MAX_WORLD_Y_LOC)
  480. {
  481. yStep = MAX_WORLD_Y_LOC-preY-1;
  482. vertical = 2;
  483. }
  484. else
  485. err_here();
  486. err_when(xStep!=yStep);
  487. int addXLoc = preX+xStep*vecX;
  488. int addYLoc = preY+yStep*vecY;
  489. add_result(addXLoc, addYLoc); // add the first point
  490. //-*************** codes here ***************-//
  491. //---------------------------------------------------------------//
  492. // may add the second point if exit at the edge of the map
  493. //---------------------------------------------------------------//
  494. /*if((addXLoc==0 && addYLoc==0) ||
  495. (addXLoc==0 && addYLoc==MAX_WORLD_Y_LOC-1) ||
  496. (addXLoc==MAX_WORLD_X_LOC-1 && addYLoc==0) ||
  497. (addXLoc==MAX_WORLD_X_LOC-1 && addYLoc==MAX_WORLD_Y_LOC-1))
  498. {
  499. err_when(!vertical || !horizontal);
  500. return; // exit at corner
  501. }*/
  502. }
  503. //--------- End of function SeekPathReuse::move_outside_map ---------//
  504. //-------- Begin of function SeekPathReuse::move_inside_map ---------//
  505. // location (preX, preY) is outside the map and location (curX, curY)
  506. // is insode the map
  507. //
  508. // add one/two points
  509. //
  510. void SeekPathReuse::move_inside_map(int preX, int preY, int curX, int curY)
  511. {
  512. err_when(preX>=0 && preX<MAX_WORLD_X_LOC && preY>=0 && preY<MAX_WORLD_Y_LOC);
  513. err_when(curX<0 || curX>=MAX_WORLD_X_LOC || curY<0 || curY>=MAX_WORLD_Y_LOC);
  514. //-*************** codes here ***************-//
  515. }
  516. //--------- End of function SeekPathReuse::move_inside_map ---------//
  517. //-------- Begin of function SeekPathReuse::move_beyond_map ---------//
  518. // locations (preX, preY) and (curX, curY) are both outside the map
  519. //
  520. // add one/two points
  521. void SeekPathReuse::move_beyond_map(int preX, int preY, int curX, int curY)
  522. {
  523. err_when(preX>=0 && preX<MAX_WORLD_X_LOC && preY>=0 && preY<MAX_WORLD_Y_LOC);
  524. err_when(curX>=0 && curX<MAX_WORLD_X_LOC && curY>=0 && curY<MAX_WORLD_Y_LOC);
  525. //-*************** codes here ***************-//
  526. }
  527. //--------- End of function SeekPathReuse::move_beyond_map ---------//
  528. //-------- Begin of function SeekPathReuse::seek ---------//
  529. // searchMode should be 4 (i.e. path reuse searching mode)
  530. // reuseMode GENERAL_GROUP_MOVEMENT for general group movement
  531. // FORMATION_MOVEMENT for formation movement
  532. //
  533. // miscNo == target record no if searchMode==SEARCH_MODE_TO_ATTACK
  534. // == firm ID if searchMode==SEARCH_MODE_TO_FIRM
  535. //
  536. int SeekPathReuse::seek(int sx,int sy,int dx,int dy,short unitSize, DWORD groupId, char mobileType,
  537. short searchMode, short miscID,
  538. short numOfPath, short reuseMode, short pathReuseStatus,
  539. int maxTries,int borderX1, int borderY1, int borderX2, int borderY2)
  540. {
  541. //---------------------- error checking ---------------------//
  542. err_when(numOfPath<0 || searchMode!=4 || numOfPath<1);
  543. err_when(pathReuseStatus!=REUSE_PATH_INITIAL && numOfPath!=total_num_of_path);
  544. //-------------------------------------------------------------//
  545. // initialize parameters
  546. //-------------------------------------------------------------//
  547. total_num_of_path = numOfPath;
  548. reuse_path_status = pathReuseStatus;
  549. if(reuse_path_status == REUSE_PATH_INITIAL)
  550. {
  551. //-------- initialize data structure and then return ---------//
  552. init_reuse_search();
  553. return 1;
  554. }
  555. start_x = sx;
  556. start_y = sy;
  557. dest_x = dx;
  558. dest_y = dy;
  559. vir_dest_x = dest_x;
  560. vir_dest_y = dest_y;
  561. unit_size = unitSize;
  562. cur_group_id = groupId;
  563. mobile_type = mobileType;
  564. search_mode = searchMode;
  565. reuse_mode = reuseMode;
  566. move_scale = (mobile_type==UNIT_LAND) ? 1 : 2;
  567. unit_nation_recno = unit_array[world.get_unit_recno(start_x, start_y, mobile_type)]->nation_recno;
  568. result_node_array_def_size = 0;
  569. num_of_result_node = 0;
  570. cur_result_node_ptr = NULL;
  571. path_reuse_result_node_ptr = NULL;
  572. //-------------------------------------------------------------//
  573. set_offset_condition(sx, sy, dx, dy);
  574. //-------------------------------------------------------------//
  575. if(reuse_path_status == REUSE_PATH_FIRST_SEEK) // first seeking, usually choose to be leader path
  576. {
  577. err_when(cur_path_num != 0);
  578. path_reuse_result_node_ptr = call_seek(sx, sy, dx, dy, cur_group_id, mobileType, SEARCH_MODE_IN_A_GROUP, num_of_result_node);
  579. }
  580. else // it should be REUSE_PATH_SEARCH
  581. {
  582. //-------------------------------------------------------------//
  583. // reuse_mode = GENERAL_GROUP_MOVEMENT
  584. //-------------------------------------------------------------//
  585. if(start_x_offset==dest_x_offset && start_y_offset==dest_y_offset)
  586. {
  587. //----------------------------------------------------------//
  588. // optimal case, starting offset==ending offset, thus, using
  589. // offset method to find the shortest path directly
  590. //----------------------------------------------------------//
  591. x_offset = start_x_offset;
  592. y_offset = start_y_offset;
  593. err_when(cur_path_num==leader_path_num);
  594. seek_path_offset();
  595. }
  596. else
  597. {
  598. //-------------------------------------------------------------//
  599. // the starting location is not the correct offset location,
  600. // using the join-offset-path method
  601. //-------------------------------------------------------------//
  602. x_offset = dest_x_offset;
  603. y_offset = dest_y_offset;
  604. seek_path_join_offset();
  605. }
  606. }
  607. //-------------------------------------------------------------//
  608. // backup the ResultNode of this path
  609. //-------------------------------------------------------------//
  610. if(num_of_result_node && path_reuse_result_node_ptr)
  611. {
  612. #ifdef DEBUG
  613. if(mobile_type==UNIT_LAND && reuse_search_sub_mode==SEARCH_SUB_MODE_PASSABLE && num_of_result_node>1)
  614. {
  615. err_when(mobile_type!=UNIT_LAND);
  616. debug_reuse_check_sub_mode(path_reuse_result_node_ptr, num_of_result_node);
  617. }
  618. #endif
  619. path_reuse_result_node_ptr = smooth_reuse_path(path_reuse_result_node_ptr, num_of_result_node);
  620. #ifdef DEBUG
  621. if(mobile_type==UNIT_LAND && reuse_search_sub_mode==SEARCH_SUB_MODE_PASSABLE && num_of_result_node>1)
  622. {
  623. err_when(mobile_type!=UNIT_LAND);
  624. debug_reuse_check_sub_mode(path_reuse_result_node_ptr, num_of_result_node);
  625. }
  626. #endif
  627. if(leader_path_num==cur_path_num)
  628. {
  629. err_when(num_of_result_node>0 && path_reuse_result_node_ptr==NULL);
  630. reuse_leader_path_backup = (ResultNode*) mem_add(sizeof(ResultNode)*num_of_result_node);
  631. memcpy(reuse_leader_path_backup, path_reuse_result_node_ptr, sizeof(ResultNode)* num_of_result_node);
  632. reuse_leader_path_node_num = num_of_result_node;
  633. }
  634. }
  635. else
  636. {
  637. path_reuse_result_node_ptr = NULL;
  638. num_of_result_node = 0;
  639. if(leader_path_num==cur_path_num)
  640. {
  641. reuse_leader_path_backup = NULL;
  642. reuse_leader_path_node_num = 0;
  643. }
  644. }
  645. set_next_cur_path_num();
  646. err_when(cur_path_num>total_num_of_path+3);
  647. return 1;
  648. }
  649. //--------- End of function SeekPathReuse::seek ---------//
  650. //-------- Begin of function SeekPathReuse::get_result ---------//
  651. // return the final result node path
  652. //ResultNode* SeekPathReuse::get_result(int& resultNodeCount)
  653. //
  654. ResultNode* SeekPathReuse::get_result(int& resultNodeCount, short& pathDist)
  655. {
  656. if(reuse_path_status == REUSE_PATH_FIRST_SEEK)
  657. {
  658. resultNodeCount = num_of_result_node;
  659. reuse_path_dist = count_path_dist(path_reuse_result_node_ptr, num_of_result_node);
  660. pathDist = reuse_path_dist;
  661. return path_reuse_result_node_ptr;
  662. }
  663. else
  664. {
  665. err_when(reuse_path_status!=REUSE_PATH_SEARCH && reuse_path_status!=REUSE_PATH_INCOMPLETE_SEARCH);
  666. if(path_reuse_result_node_ptr!=NULL && num_of_result_node>0)
  667. {
  668. sys_yield(); // update cursor position
  669. if(num_of_result_node<2)
  670. {
  671. mem_del(path_reuse_result_node_ptr);
  672. path_reuse_result_node_ptr = NULL;
  673. num_of_result_node = 0;
  674. }
  675. sys_yield(); // update cursor position
  676. resultNodeCount = num_of_result_node;
  677. reuse_path_dist = count_path_dist(path_reuse_result_node_ptr, num_of_result_node);
  678. pathDist = reuse_path_dist;
  679. }
  680. else
  681. {
  682. num_of_result_node = 0;
  683. if(path_reuse_result_node_ptr!=NULL)
  684. {
  685. mem_del(path_reuse_result_node_ptr);
  686. path_reuse_result_node_ptr = NULL;
  687. }
  688. err_when(num_of_result_node!=0 || path_reuse_result_node_ptr!=NULL);
  689. }
  690. //******************* debug **********************//
  691. #ifdef DEBUG
  692. err_when(mobile_type!=UNIT_LAND && pathDist%2);
  693. if(!path_reuse_result_node_ptr && num_of_result_node>0)
  694. {
  695. //---------------------------------------------------------//
  696. // final checking, error free for the result_path
  697. //---------------------------------------------------------//
  698. ResultNode* debugResultPtr = path_reuse_result_node_ptr;
  699. ResultNode* debugStartNode = path_reuse_result_node_ptr;
  700. ResultNode* debugEndNode = debugStartNode + 1;
  701. int debugCount = num_of_result_node;
  702. int dvX, dvY; // vector direction
  703. int dXLoc, dYLoc;
  704. err_when(mobile_type!=UNIT_LAND && (debugStartNode->node_x%2 || debugStartNode->node_y%2));
  705. for(int d=1; d<debugCount; d++)
  706. {
  707. //------- check x, y vector magnitude ---------//
  708. debugStartNode = path_reuse_result_node_ptr + d-1;
  709. debugEndNode = debugStartNode + d;
  710. err_when(mobile_type!=UNIT_LAND && (debugEndNode->node_x%2 || debugEndNode->node_y%2));
  711. dvX = debugEndNode->node_x - debugStartNode->node_x;
  712. dvY = debugEndNode->node_y - debugStartNode->node_y;
  713. err_when(dvX!=0 && dvY!=0 && abs(dvX)!=abs(dvY));
  714. if(dvX) dvX /= abs(dvX);
  715. if(dvY) dvY /= abs(dvY);
  716. dXLoc = debugStartNode->node_x;
  717. dYLoc = debugStartNode->node_y;
  718. //-------- check accessible ---------//
  719. while(dXLoc!=debugEndNode->node_x || dYLoc!=debugEndNode->node_y)
  720. {
  721. dXLoc += dvX;
  722. dYLoc += dvY;
  723. err_when(unit_size==1 && !can_walk(dXLoc, dYLoc));
  724. err_when(unit_size==2 && !can_walk_s2(dXLoc, dYLoc));
  725. }
  726. }
  727. }
  728. #endif
  729. //******************* debug **********************//
  730. return path_reuse_result_node_ptr;
  731. }
  732. }
  733. //--------- End of function SeekPathReuse::get_result ---------//