OSPRESMO.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  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. #include <OSPREUSE.h>
  21. #include <OUNIT.h>
  22. #ifdef NO_DEBUG_SEARCH
  23. #undef err_when
  24. #undef err_here
  25. #undef err_if
  26. #undef err_else
  27. #undef err_now
  28. #define err_when(cond)
  29. #define err_here()
  30. #define err_if(cond)
  31. #define err_else
  32. #define err_now(msg)
  33. #undef debug_reuse_check_path
  34. #undef debug_reuse_check_xy_magn
  35. #define debug_reuse_check_path()
  36. #define debug_reuse_check_xy_magn(x1, y1, x2, y2)
  37. #undef DEBUG
  38. #endif
  39. //------ Begin of function SeekPathReuse::remove_duplicate_node ---------//
  40. // this function is used to remove duplicate node
  41. //
  42. void SeekPathReuse::remove_duplicate_node(ResultNode resultList[], int& nodeCount)
  43. {
  44. //------------------------------------------------------------//
  45. // remove duplicate node
  46. //------------------------------------------------------------//
  47. ResultNode* curNodePtr = resultList+1;
  48. ResultNode* preNodePtr = resultList;
  49. ResultNode* writeNodePtr = resultList;
  50. int count = 0;
  51. err_when(mobile_type!=UNIT_LAND && (preNodePtr->node_x%2 || preNodePtr->node_y%2));
  52. for(int i=1; i<nodeCount; i++)
  53. {
  54. err_when(mobile_type!=UNIT_LAND && (curNodePtr->node_x%2 || curNodePtr->node_y%2));
  55. if(i%40==0)
  56. sys_yield(); // update cursor position
  57. if(curNodePtr->node_x!=preNodePtr->node_x || curNodePtr->node_y!=preNodePtr->node_y)
  58. {
  59. writeNodePtr->node_x = preNodePtr->node_x;
  60. writeNodePtr->node_y = preNodePtr->node_y;
  61. #ifdef DEBUG
  62. ResultNode *debugPtr;
  63. int vX, vY;
  64. if(i>1)
  65. {
  66. debugPtr = writeNodePtr;
  67. vX = debugPtr->node_x - writeNodePtr->node_x;
  68. vY = debugPtr->node_y - writeNodePtr->node_y;
  69. }
  70. err_when(i>1 && vX!=0 && vY!=0 && abs(vX)!=abs(vY));
  71. #endif
  72. writeNodePtr++;
  73. preNodePtr = curNodePtr;
  74. curNodePtr++;
  75. count++;
  76. }
  77. else
  78. curNodePtr++;
  79. }
  80. writeNodePtr->node_x = preNodePtr->node_x;
  81. writeNodePtr->node_y = preNodePtr->node_y;
  82. count++;
  83. nodeCount = count;
  84. }
  85. //-------- End of function SeekPathReuse::remove_duplicate_node ---------//
  86. //-------- Begin of function SeekPathReuse::smooth_reuse_path ---------//
  87. ResultNode* SeekPathReuse::smooth_reuse_path(ResultNode* resultPath, int& resultNodeNum)
  88. {
  89. //------------------------------------------------------------//
  90. // to handle all the unexpected case in turning direction or
  91. // reverse direction in reuse path. Finally, a well-shaped
  92. // path will be returned.
  93. //------------------------------------------------------------//
  94. //-----------------------------------------------------------//
  95. // remove duplicate node
  96. //-----------------------------------------------------------//
  97. remove_duplicate_node(resultPath, resultNodeNum);
  98. if(mobile_type==UNIT_LAND)
  99. resultPath = smooth_path(resultPath, resultNodeNum);
  100. else
  101. resultPath = smooth_path2(resultPath, resultNodeNum);
  102. return resultPath;
  103. }
  104. //--------- End of function SeekPathReuse::smooth_reuse_path ---------//
  105. //-------- Begin of function SeekPathReuse::smooth_path ---------//
  106. ResultNode* SeekPathReuse::smooth_path(ResultNode* resultPath, int& resultNodeNum)
  107. {
  108. err_when(mobile_type!=UNIT_LAND);
  109. #define UNKNOWN_FACTOR 5
  110. //----------------------------------------------------------------------------//
  111. // to handle all the unexpected case in turning direction or reverse direction
  112. // in reuse path. Finally, a well-shaped path will be returned.
  113. //----------------------------------------------------------------------------//
  114. ResultNode *preNodePtr;
  115. ResultNode *writeNodePtr;
  116. ResultNode *curNodePtr;
  117. ResultNode *oldPreNodePtr;
  118. ResultNode *wellShapedNodePtr;
  119. short changed = 1;
  120. int count = 0, i;
  121. //int resultVectorX, resultVectorY;
  122. int tempXLoc, tempYLoc;
  123. int necessaryPoint, type;
  124. //------------------------------------------------------------//
  125. // smoothing the path
  126. //------------------------------------------------------------//
  127. while(changed)
  128. {
  129. oldPreNodePtr = resultPath; // may point to writeNodePtr or tempReuseResultPtr list
  130. preNodePtr = resultPath+1; // may point to writeNodePtr or tempReuseResultPtr list
  131. curNodePtr = resultPath+2; // always point to the tempReuseResultPtr list
  132. count = 0;
  133. changed = 0;
  134. if(resultNodeNum>2)
  135. {
  136. wellShapedNodePtr = (ResultNode*)mem_add(resultNodeNum*UNKNOWN_FACTOR*sizeof(ResultNode*)); //********BUGHERE
  137. memset(wellShapedNodePtr, 0, resultNodeNum*UNKNOWN_FACTOR*sizeof(ResultNode*)); // num of ResultNode may not be enough for use
  138. writeNodePtr = wellShapedNodePtr; //---------- write the beginning node ---------//
  139. *writeNodePtr = *oldPreNodePtr;
  140. count++;
  141. i = 2;
  142. do
  143. {
  144. //-------------------------------------------------//
  145. // calculate the vector offset and vector magnitude
  146. //-------------------------------------------------//
  147. vec_x = preNodePtr->node_x-oldPreNodePtr->node_x;
  148. vec_y = preNodePtr->node_y-oldPreNodePtr->node_y;
  149. err_when(vec_x==0 && vec_y==0);
  150. vec_magn = (vec_x!=0) ? abs(vec_x) : abs(vec_y);
  151. vec_x /= vec_magn;
  152. vec_y /= vec_magn;
  153. new_vec_x = curNodePtr->node_x - preNodePtr->node_x;
  154. new_vec_y = curNodePtr->node_y - preNodePtr->node_y;
  155. err_when(new_vec_x==0 && new_vec_y==0);
  156. new_vec_magn = (new_vec_x!=0)?abs(new_vec_x):abs(new_vec_y);
  157. new_vec_x /= new_vec_magn;
  158. new_vec_y /= new_vec_magn;
  159. //----------------------------------------------//
  160. // (1) same direction
  161. //----------------------------------------------//
  162. if(vec_x==new_vec_x && vec_y==new_vec_y)
  163. {
  164. preNodePtr = curNodePtr;
  165. curNodePtr++;
  166. err_when(oldPreNodePtr->node_x==preNodePtr->node_x && oldPreNodePtr->node_y==preNodePtr->node_y);
  167. continue;
  168. }
  169. //----------------------------------------------//
  170. // (2) reverse direction
  171. //----------------------------------------------//
  172. if(vec_x==-new_vec_x && vec_y==-new_vec_y)
  173. {
  174. //--- old vector magnitude != new vector magnitude ----//
  175. if(vec_magn!=new_vec_magn)
  176. {
  177. preNodePtr = curNodePtr;
  178. curNodePtr++;
  179. err_when(i+1!=resultNodeNum && preNodePtr->node_x==curNodePtr->node_x && preNodePtr->node_y==curNodePtr->node_y);
  180. }
  181. else if(i+2<resultNodeNum) //------ not the end of the array ------//
  182. {
  183. //------------ both magnitudes are equal ----------//
  184. oldPreNodePtr = curNodePtr;
  185. preNodePtr = oldPreNodePtr+1;
  186. curNodePtr = preNodePtr+1;
  187. changed++;
  188. i++;
  189. }
  190. else if(i+1<resultNodeNum)
  191. {
  192. preNodePtr = curNodePtr+1; // for writing the last node
  193. changed++;
  194. i++;
  195. }
  196. else
  197. break;
  198. err_when(oldPreNodePtr->node_x==preNodePtr->node_x && oldPreNodePtr->node_y==preNodePtr->node_y);
  199. continue;
  200. }
  201. result_vec_x = vec_x+new_vec_x;
  202. result_vec_y = vec_y+new_vec_y;
  203. necessaryPoint = 0;
  204. //----------------------------------------------//
  205. // (3) turn 45 degree
  206. //----------------------------------------------//
  207. if(abs(result_vec_x)<=move_scale && abs(result_vec_y)<=move_scale && (result_vec_x==0 || result_vec_y==0))
  208. {
  209. err_when(result_vec_x>=2*move_scale || result_vec_y>=2*move_scale);
  210. if((vec_x==0 || vec_y==0) && vec_magn>move_scale)
  211. {
  212. //--------- choose the farther location if possible --------------//
  213. tempXLoc = preNodePtr->node_x - 2*vec_x;
  214. tempYLoc = preNodePtr->node_y - 2*vec_y;
  215. if(vec_magn>2*move_scale) // add a new point
  216. {
  217. oldPreNodePtr->node_x = tempXLoc;
  218. oldPreNodePtr->node_y = tempYLoc;
  219. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  220. writeNodePtr++;
  221. writeNodePtr->node_x = oldPreNodePtr->node_x;
  222. writeNodePtr->node_y = oldPreNodePtr->node_y;
  223. count++;
  224. }//else vec_magn==2*move_scale, do nothing
  225. }
  226. else
  227. {
  228. //------------------------------------------------------------------------------------//
  229. // 1) the vector direction is not horizontal or vertical (only one step is checked), or
  230. // 2) the direction is matched but vec_magn==move_scale
  231. //------------------------------------------------------------------------------------//
  232. if(vec_magn>move_scale)
  233. {
  234. oldPreNodePtr->node_x = preNodePtr->node_x-vec_x;
  235. oldPreNodePtr->node_y = preNodePtr->node_y-vec_y;
  236. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  237. writeNodePtr++;
  238. writeNodePtr->node_x = oldPreNodePtr->node_x;
  239. writeNodePtr->node_y = oldPreNodePtr->node_y;
  240. count++;
  241. }
  242. }
  243. if(new_vec_magn>move_scale)
  244. {
  245. preNodePtr->node_x += new_vec_x;
  246. preNodePtr->node_y += new_vec_y;
  247. debug_reuse_check_xy_magn(preNodePtr->node_x, preNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  248. writeNodePtr++;
  249. writeNodePtr->node_x = preNodePtr->node_x;
  250. writeNodePtr->node_y = preNodePtr->node_y;
  251. count++;
  252. oldPreNodePtr = preNodePtr;
  253. }
  254. preNodePtr = curNodePtr;
  255. curNodePtr++;
  256. changed++;
  257. continue;
  258. }
  259. //----------------------------------------------//
  260. // (4) turn 90 degree
  261. //----------------------------------------------//
  262. if(vec_x*new_vec_x+vec_y*new_vec_y==0)
  263. {
  264. type = (vec_x==0 || vec_y==0) ? 0 : 1; // 0 for + case, 1 for x case
  265. if(type==1) // x case
  266. {
  267. err_when(new_vec_x-vec_x!=0 && new_vec_y-vec_y!=0);
  268. tempXLoc = preNodePtr->node_x+(new_vec_x-vec_x)/2;
  269. tempYLoc = preNodePtr->node_y+(new_vec_y-vec_y)/2;
  270. if(can_walk(tempXLoc, tempYLoc))
  271. {
  272. if(vec_magn>move_scale)
  273. {
  274. oldPreNodePtr->node_x = preNodePtr->node_x-vec_x;
  275. oldPreNodePtr->node_y = preNodePtr->node_y-vec_y;
  276. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  277. writeNodePtr++;
  278. writeNodePtr->node_x = oldPreNodePtr->node_x;
  279. writeNodePtr->node_y = oldPreNodePtr->node_y;
  280. count++;
  281. }
  282. if(new_vec_magn>move_scale)
  283. {
  284. oldPreNodePtr->node_x = preNodePtr->node_x+new_vec_x;
  285. oldPreNodePtr->node_y = preNodePtr->node_y+new_vec_y;
  286. err_when(oldPreNodePtr->node_x==curNodePtr->node_x && oldPreNodePtr->node_y==curNodePtr->node_y);
  287. err_when(oldPreNodePtr->node_x==preNodePtr->node_x && oldPreNodePtr->node_y==preNodePtr->node_y);
  288. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  289. writeNodePtr++;
  290. writeNodePtr->node_x = oldPreNodePtr->node_x;
  291. writeNodePtr->node_y = oldPreNodePtr->node_y;
  292. count++;
  293. }
  294. preNodePtr = curNodePtr;
  295. curNodePtr++;
  296. }
  297. else
  298. necessaryPoint = 1;
  299. }
  300. else // + case
  301. {
  302. if(vec_magn>move_scale && new_vec_magn>move_scale)
  303. {
  304. tempXLoc = preNodePtr->node_x+new_vec_x-vec_x;
  305. tempYLoc = preNodePtr->node_y+new_vec_y-vec_y;
  306. if(can_walk(tempXLoc, tempYLoc))
  307. {
  308. if(vec_magn>2*move_scale)
  309. {
  310. oldPreNodePtr->node_x = preNodePtr->node_x-2*vec_x;
  311. oldPreNodePtr->node_y = preNodePtr->node_y-2*vec_y;
  312. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  313. writeNodePtr++;
  314. writeNodePtr->node_x = oldPreNodePtr->node_x;
  315. writeNodePtr->node_y = oldPreNodePtr->node_y;
  316. count++;
  317. }
  318. if(new_vec_magn>2*move_scale)
  319. {
  320. oldPreNodePtr->node_x = preNodePtr->node_x+2*new_vec_x;
  321. oldPreNodePtr->node_y = preNodePtr->node_y+2*new_vec_y;
  322. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  323. writeNodePtr++;
  324. writeNodePtr->node_x = oldPreNodePtr->node_x;
  325. writeNodePtr->node_y = oldPreNodePtr->node_y;
  326. count++;
  327. }
  328. preNodePtr = curNodePtr;
  329. curNodePtr++;
  330. }
  331. else
  332. necessaryPoint = 1;
  333. }
  334. else // not both vector magnitude>move_scale
  335. {
  336. if(vec_magn>move_scale)
  337. {
  338. oldPreNodePtr->node_x = preNodePtr->node_x-vec_x;
  339. oldPreNodePtr->node_y = preNodePtr->node_y-vec_y;
  340. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  341. writeNodePtr++;
  342. writeNodePtr->node_x = oldPreNodePtr->node_x;
  343. writeNodePtr->node_y = oldPreNodePtr->node_y;
  344. count++;
  345. }
  346. if(new_vec_magn>move_scale)
  347. {
  348. preNodePtr->node_x += new_vec_x;
  349. preNodePtr->node_y += new_vec_y;
  350. debug_reuse_check_xy_magn(preNodePtr->node_x, preNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  351. writeNodePtr++;
  352. writeNodePtr->node_x = preNodePtr->node_x;
  353. writeNodePtr->node_y = preNodePtr->node_y;
  354. count++;
  355. oldPreNodePtr = preNodePtr;
  356. }
  357. preNodePtr = curNodePtr;
  358. curNodePtr++;
  359. }
  360. }
  361. if(!necessaryPoint)
  362. {
  363. changed++;
  364. continue;
  365. }
  366. }
  367. //--------------------------------------------------//
  368. // (5) this point is necessary for the reuse-path
  369. //--------------------------------------------------//
  370. debug_reuse_check_xy_magn(preNodePtr->node_x, preNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  371. writeNodePtr++;
  372. writeNodePtr->node_x = preNodePtr->node_x;
  373. writeNodePtr->node_y = preNodePtr->node_y;
  374. count++;
  375. oldPreNodePtr = preNodePtr;
  376. preNodePtr = curNodePtr;
  377. curNodePtr++;
  378. err_when(oldPreNodePtr->node_x==preNodePtr->node_x && oldPreNodePtr->node_y==preNodePtr->node_y);
  379. }while(++i<resultNodeNum);
  380. debug_reuse_check_xy_magn(preNodePtr->node_x, preNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  381. writeNodePtr++; //------- write the end node -----------//
  382. writeNodePtr->node_x = preNodePtr->node_x;
  383. writeNodePtr->node_y = preNodePtr->node_y;
  384. count++;
  385. resultNodeNum = count;
  386. mem_del(resultPath);
  387. resultPath = wellShapedNodePtr;
  388. wellShapedNodePtr = NULL;
  389. }
  390. }
  391. return resultPath;
  392. }
  393. //--------- End of function SeekPathReuse::smooth_path ---------//
  394. //-------- Begin of function SeekPathReuse::smooth_path2 ---------//
  395. // another version of smooth_path(). This version is for unit's
  396. // mobile_type == UNIT_SEA or UNIT_AIR
  397. //
  398. ResultNode* SeekPathReuse::smooth_path2(ResultNode* resultPath, int& resultNodeNum)
  399. {
  400. err_when(mobile_type!=UNIT_SEA && mobile_type!=UNIT_AIR);
  401. #define UNKNOWN_FACTOR 5
  402. #ifdef DEBUG
  403. //------------------------------------------------------------------------//
  404. // used to debug for the path of UNIT_SEA
  405. //------------------------------------------------------------------------//
  406. if(mobile_type==UNIT_SEA && resultNodeNum>1)
  407. {
  408. ResultNode *debugPtr1 = resultPath;
  409. ResultNode *debugPtr2 = resultPath+1;
  410. int di=1, dj, dvecX, dvecY, magn;
  411. while(di<resultNodeNum)
  412. {
  413. dvecX = debugPtr2->node_x-debugPtr1->node_x;
  414. dvecY = debugPtr2->node_y-debugPtr1->node_y;
  415. magn = (abs(dvecX) > abs(dvecY)) ? abs(dvecX) : abs(dvecY);
  416. dvecX /= magn;
  417. dvecY /= magn;
  418. for(dj=1; dj<=magn; dj++)
  419. if(mobile_type==UNIT_SEA)
  420. err_when(!world.get_loc(debugPtr1->node_x+dvecX*dj, debugPtr1->node_y+dvecY*dj)->sailable());
  421. di++;
  422. debugPtr1++;
  423. debugPtr2++;
  424. }
  425. }
  426. #endif
  427. //----------------------------------------------------------------------------//
  428. // to handle all the unexpected case in turning direction or reverse direction
  429. // in reuse path. Finally, a well-shaped path will be returned.
  430. //----------------------------------------------------------------------------//
  431. ResultNode *preNodePtr;
  432. ResultNode *writeNodePtr;
  433. ResultNode *curNodePtr;
  434. ResultNode *oldPreNodePtr;
  435. ResultNode *wellShapedNodePtr;
  436. short changed = 1;
  437. int count = 0, i;
  438. int tempXLoc, tempYLoc, tempVectorX, tempVectorY;
  439. int necessaryPoint, type;
  440. //------------------------------------------------------------//
  441. // smoothing the path
  442. //------------------------------------------------------------//
  443. while(changed)
  444. {
  445. oldPreNodePtr = resultPath; // may point to writeNodePtr or tempReuseResultPtr list
  446. preNodePtr = resultPath+1; // may point to writeNodePtr or tempReuseResultPtr list
  447. curNodePtr = resultPath+2; // always point to the tempReuseResultPtr list
  448. count = 0;
  449. changed = 0;
  450. if(resultNodeNum>2)
  451. {
  452. wellShapedNodePtr = (ResultNode*)mem_add(resultNodeNum*UNKNOWN_FACTOR*sizeof(ResultNode*)); //********BUGHERE
  453. memset(wellShapedNodePtr, 0, resultNodeNum*UNKNOWN_FACTOR*sizeof(ResultNode*)); // num of ResultNode may not be enough for use
  454. writeNodePtr = wellShapedNodePtr; //---------- write the beginning node ---------//
  455. writeNodePtr->node_x = oldPreNodePtr->node_x;
  456. writeNodePtr->node_y = oldPreNodePtr->node_y;
  457. count++;
  458. i = 2;
  459. do
  460. {
  461. //-------------------------------------------------//
  462. // calculate the vector offset and vector magnitude
  463. //-------------------------------------------------//
  464. vec_x = preNodePtr->node_x-oldPreNodePtr->node_x;
  465. vec_y = preNodePtr->node_y-oldPreNodePtr->node_y;
  466. err_when(vec_x==0 && vec_y==0);
  467. vec_magn = (vec_x!=0) ? abs(vec_x) : abs(vec_y);
  468. (vec_x /= vec_magn) *= move_scale;
  469. (vec_y /= vec_magn) *= move_scale;
  470. new_vec_x = curNodePtr->node_x-preNodePtr->node_x;
  471. new_vec_y = curNodePtr->node_y-preNodePtr->node_y;
  472. err_when(new_vec_x==0 && new_vec_y==0);
  473. new_vec_magn = (new_vec_x!=0) ? abs(new_vec_x) : abs(new_vec_y);
  474. (new_vec_x /= new_vec_magn) *= move_scale;
  475. (new_vec_y /= new_vec_magn) *= move_scale;
  476. //----------------------------------------------//
  477. // (1) same direction
  478. //----------------------------------------------//
  479. if(vec_x==new_vec_x && vec_y==new_vec_y)
  480. {
  481. preNodePtr = curNodePtr;
  482. curNodePtr++;
  483. err_when(oldPreNodePtr->node_x==preNodePtr->node_x && oldPreNodePtr->node_y==preNodePtr->node_y);
  484. continue;
  485. }
  486. //----------------------------------------------//
  487. // (2) reverse direction
  488. //----------------------------------------------//
  489. if(vec_x==-new_vec_x && vec_y==-new_vec_y)
  490. {
  491. //--- old vector magnitude != new vector magnitude ----//
  492. if(vec_magn!=new_vec_magn)
  493. {
  494. preNodePtr = curNodePtr;
  495. curNodePtr++;
  496. err_when(i+1!=resultNodeNum && preNodePtr->node_x==curNodePtr->node_x && preNodePtr->node_y==curNodePtr->node_y);
  497. }
  498. else if(i+2<resultNodeNum) //------ not the end of the array ------//
  499. {
  500. //------------ both magnitudes are equal ----------//
  501. oldPreNodePtr = curNodePtr;
  502. preNodePtr = oldPreNodePtr+1;
  503. curNodePtr = preNodePtr+1;
  504. changed++;
  505. i++;
  506. }
  507. else if(i+1<resultNodeNum)
  508. {
  509. preNodePtr = curNodePtr+1; // for writing the last node
  510. changed++;
  511. i++;
  512. }
  513. else
  514. break;
  515. err_when(oldPreNodePtr->node_x==preNodePtr->node_x && oldPreNodePtr->node_y==preNodePtr->node_y);
  516. continue;
  517. }
  518. result_vec_x = vec_x+new_vec_x;
  519. result_vec_y = vec_y+new_vec_y;
  520. err_when(result_vec_x%2 || result_vec_y%2);
  521. necessaryPoint = 0;
  522. //----------------------------------------------//
  523. // (3) turn 45 degree
  524. //----------------------------------------------//
  525. if(abs(result_vec_x)<=move_scale && abs(result_vec_y)<=move_scale && (result_vec_x==0 || result_vec_y==0))
  526. {
  527. err_when(result_vec_x>=2*move_scale || result_vec_y>=2*move_scale);
  528. if((vec_x==0 || vec_y==0) && vec_magn>move_scale)
  529. {
  530. //-------------------------------------------------------------------------------------------//
  531. // check one more point if the entering vector direction is horizontal or vertical
  532. //-------------------------------------------------------------------------------------------//
  533. tempXLoc = preNodePtr->node_x - 2*vec_x;
  534. tempYLoc = preNodePtr->node_y - 2*vec_y;
  535. tempVectorX = vec_x + result_vec_x;
  536. tempVectorY = vec_y + result_vec_y;
  537. err_when((tempXLoc+tempVectorX/2)%2==0 && (tempYLoc+tempVectorY/2)%2==0);
  538. if(can_walk(tempXLoc+tempVectorX/2, tempYLoc+tempVectorY/2))
  539. {
  540. //------- checking for the farther point -------//
  541. if(vec_magn>2*move_scale) // add a new point
  542. {
  543. oldPreNodePtr->node_x = tempXLoc;
  544. oldPreNodePtr->node_y = tempYLoc;
  545. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  546. writeNodePtr++;
  547. writeNodePtr->node_x = oldPreNodePtr->node_x;
  548. writeNodePtr->node_y = oldPreNodePtr->node_y;
  549. count++;
  550. }
  551. }
  552. else if(can_walk(preNodePtr->node_x+(new_vec_x-vec_x)/2, preNodePtr->node_y+(new_vec_y-vec_y)/2))
  553. {
  554. //-------------------------------------------------------------------------------------------//
  555. // 1) the vector entering direction is not horizontal or vetical (only one can be processed), or
  556. // 2) the vector entering direction is matched, but vec_magn==move_scale
  557. //-------------------------------------------------------------------------------------------//
  558. if(vec_magn>move_scale)
  559. {
  560. oldPreNodePtr->node_x = preNodePtr->node_x-vec_x;
  561. oldPreNodePtr->node_y = preNodePtr->node_y-vec_y;
  562. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  563. writeNodePtr++;
  564. writeNodePtr->node_x = oldPreNodePtr->node_x;
  565. writeNodePtr->node_y = oldPreNodePtr->node_y;
  566. count++;
  567. }
  568. }
  569. else
  570. necessaryPoint = 1; //--- failure checking in the near point ----//
  571. }
  572. else
  573. {
  574. //------------------------------------------------------------------------------------//
  575. // 1) the vector direction is not horizontal or vertical (only one step is checked), or
  576. // 2) the direction is matched but vec_magn==move_scale
  577. //------------------------------------------------------------------------------------//
  578. if(can_walk(preNodePtr->node_x+(new_vec_x-vec_x)/2, preNodePtr->node_y+(new_vec_y-vec_y)/2))
  579. {
  580. if(vec_magn>move_scale)
  581. {
  582. oldPreNodePtr->node_x = preNodePtr->node_x-vec_x;
  583. oldPreNodePtr->node_y = preNodePtr->node_y-vec_y;
  584. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  585. writeNodePtr++;
  586. writeNodePtr->node_x = oldPreNodePtr->node_x;
  587. writeNodePtr->node_y = oldPreNodePtr->node_y;
  588. count++;
  589. }
  590. }
  591. else
  592. necessaryPoint = 1;
  593. }
  594. if(!necessaryPoint)
  595. {
  596. if(new_vec_magn>move_scale)
  597. {
  598. preNodePtr->node_x += new_vec_x;
  599. preNodePtr->node_y += new_vec_y;
  600. debug_reuse_check_xy_magn(preNodePtr->node_x, preNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  601. writeNodePtr++;
  602. writeNodePtr->node_x = preNodePtr->node_x;
  603. writeNodePtr->node_y = preNodePtr->node_y;
  604. count++;
  605. oldPreNodePtr = preNodePtr;
  606. }
  607. preNodePtr = curNodePtr;
  608. curNodePtr++;
  609. changed++;
  610. continue;
  611. }
  612. }
  613. //----------------------------------------------//
  614. // (4) turn 90 degree
  615. //----------------------------------------------//
  616. if(!necessaryPoint && vec_x*new_vec_x+vec_y*new_vec_y==0)
  617. {
  618. type = (vec_x==0 || vec_y==0) ? 0 : 1; // 0 for + case, 1 for x case
  619. if(type==1) // x case
  620. {
  621. tempXLoc = preNodePtr->node_x+(new_vec_x-vec_x)/2;
  622. tempYLoc = preNodePtr->node_y+(new_vec_y-vec_y)/2;
  623. if(can_walk(tempXLoc, tempYLoc) && can_walk(tempXLoc-result_vec_x/4, tempYLoc-result_vec_y/4) &&
  624. can_walk(tempXLoc+result_vec_x/4, tempYLoc+result_vec_y/4))
  625. {
  626. if(vec_magn>move_scale)
  627. {
  628. oldPreNodePtr->node_x = preNodePtr->node_x-vec_x;
  629. oldPreNodePtr->node_y = preNodePtr->node_y-vec_y;
  630. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  631. writeNodePtr++;
  632. writeNodePtr->node_x = oldPreNodePtr->node_x;
  633. writeNodePtr->node_y = oldPreNodePtr->node_y;
  634. count++;
  635. }
  636. if(new_vec_magn>move_scale)
  637. {
  638. oldPreNodePtr->node_x = preNodePtr->node_x+new_vec_x;
  639. oldPreNodePtr->node_y = preNodePtr->node_y+new_vec_y;
  640. err_when(oldPreNodePtr->node_x==curNodePtr->node_x && oldPreNodePtr->node_y==curNodePtr->node_y);
  641. err_when(oldPreNodePtr->node_x==preNodePtr->node_x && oldPreNodePtr->node_y==preNodePtr->node_y);
  642. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  643. writeNodePtr++;
  644. writeNodePtr->node_x = oldPreNodePtr->node_x;
  645. writeNodePtr->node_y = oldPreNodePtr->node_y;
  646. count++;
  647. }
  648. preNodePtr = curNodePtr;
  649. curNodePtr++;
  650. }
  651. else
  652. necessaryPoint = 1;
  653. }
  654. else // + case
  655. {
  656. tempVectorX = new_vec_x-vec_x;
  657. tempVectorY = new_vec_y-vec_y;
  658. tempXLoc = preNodePtr->node_x+tempVectorX/2;
  659. tempYLoc = preNodePtr->node_y+tempVectorY/2;
  660. err_when(tempXLoc%2==0 || tempYLoc%2==0);
  661. if(can_walk(tempXLoc, tempYLoc))
  662. {
  663. if(vec_magn>move_scale)
  664. {
  665. oldPreNodePtr->node_x = preNodePtr->node_x-vec_x;
  666. oldPreNodePtr->node_y = preNodePtr->node_y-vec_y;
  667. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  668. writeNodePtr++;
  669. writeNodePtr->node_x = oldPreNodePtr->node_x;
  670. writeNodePtr->node_y = oldPreNodePtr->node_y;
  671. count++;
  672. }
  673. if(new_vec_magn>move_scale)
  674. {
  675. oldPreNodePtr->node_x = preNodePtr->node_x+new_vec_x;
  676. oldPreNodePtr->node_y = preNodePtr->node_y+new_vec_y;
  677. debug_reuse_check_xy_magn(oldPreNodePtr->node_x, oldPreNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  678. writeNodePtr++;
  679. writeNodePtr->node_x = oldPreNodePtr->node_x;
  680. writeNodePtr->node_y = oldPreNodePtr->node_y;
  681. count++;
  682. }
  683. preNodePtr = curNodePtr;
  684. curNodePtr++;
  685. }
  686. else
  687. necessaryPoint = 1;
  688. }
  689. if(!necessaryPoint)
  690. {
  691. changed++;
  692. continue;
  693. }
  694. }
  695. //--------------------------------------------------//
  696. // (5) this point is necessary for the reuse-path
  697. //--------------------------------------------------//
  698. debug_reuse_check_xy_magn(preNodePtr->node_x, preNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  699. writeNodePtr++;
  700. writeNodePtr->node_x = preNodePtr->node_x;
  701. writeNodePtr->node_y = preNodePtr->node_y;
  702. count++;
  703. oldPreNodePtr = preNodePtr;
  704. preNodePtr = curNodePtr;
  705. curNodePtr++;
  706. err_when(oldPreNodePtr->node_x==preNodePtr->node_x && oldPreNodePtr->node_y==preNodePtr->node_y);
  707. }while(++i<resultNodeNum);
  708. debug_reuse_check_xy_magn(preNodePtr->node_x, preNodePtr->node_y, writeNodePtr->node_x, writeNodePtr->node_y);//**** debug checking
  709. writeNodePtr++; //------- write the end node -----------//
  710. writeNodePtr->node_x = preNodePtr->node_x;
  711. writeNodePtr->node_y = preNodePtr->node_y;
  712. count++;
  713. resultNodeNum = count;
  714. mem_del(resultPath);
  715. resultPath = wellShapedNodePtr;
  716. wellShapedNodePtr = NULL;
  717. }
  718. }
  719. #ifdef DEBUG
  720. //------------------------------------------------------------------------//
  721. // used to debug for the path of UNIT_SEA
  722. //------------------------------------------------------------------------//
  723. if(mobile_type==UNIT_SEA && resultNodeNum>1)
  724. {
  725. ResultNode *debugPtr1 = resultPath;
  726. ResultNode *debugPtr2 = resultPath+1;
  727. int di=1, dj, dvecX, dvecY, magn;
  728. while(di<resultNodeNum)
  729. {
  730. dvecX = debugPtr2->node_x-debugPtr1->node_x;
  731. dvecY = debugPtr2->node_y-debugPtr1->node_y;
  732. magn = (abs(dvecX) > abs(dvecY)) ? abs(dvecX) : abs(dvecY);
  733. dvecX /= magn;
  734. dvecY /= magn;
  735. for(dj=1; dj<=magn; dj++)
  736. err_when(!world.get_loc(debugPtr1->node_x+dvecX*dj, debugPtr1->node_y+dvecY*dj)->sailable());
  737. di++;
  738. debugPtr1++;
  739. debugPtr2++;
  740. }
  741. }
  742. #endif
  743. return resultPath;
  744. }
  745. //--------- End of function SeekPathReuse::smooth_path2 ---------//