OSPATH.cpp 105 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291
  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 : OSPATH.CPP
  21. //Description : Object SeekPath
  22. //Owner :
  23. #include <math.h>
  24. #include <stdlib.h>
  25. #include <ALL.h>
  26. #include <OWORLD.h>
  27. #include <OSPATH.h>
  28. #include <OFIRM.h>
  29. #include <OTOWN.h>
  30. #include <OUNIT.h>
  31. #include <OSYS.h>
  32. #include <ONATION.h>
  33. #ifdef NO_DEBUG_SEARCH
  34. #undef err_when
  35. #undef err_here
  36. #undef err_if
  37. #undef err_else
  38. #undef err_now
  39. #define err_when(cond)
  40. #define err_here()
  41. #define err_if(cond)
  42. #define err_else
  43. #define err_now(msg)
  44. #undef DEBUG
  45. #endif
  46. #define ZOOM_LOC_HALF_WIDTH ZOOM_LOC_WIDTH/2
  47. #define ZOOM_LOC_HALF_HEIGHT ZOOM_LOC_HEIGHT/2
  48. //----------- Define static variables -----------//
  49. static Location* world_loc_matrix;
  50. static int cur_stack_pos=0;
  51. static Node* stack_array[MAX_STACK_NUM];
  52. static DWORD group_id;
  53. static short search_mode;
  54. static char mobile_type;
  55. static char seek_nation_recno;
  56. static int attack_range; // used in search_mode = SEARCH_MODE_ATTACK_UNIT_BY_RANGE
  57. static short target_recno; // used in search_mode = SEARCH_MODE_TO_ATTACK or SEARCH_MODE_TO_VEHICLE, get from miscNo
  58. static UCHAR region_id; // used in search_mode = SEARCH_MODE_TO_LAND_FOR_SHIP
  59. static short building_id; // used in search_mode = SEARCH_MODE_TO_FIRM or SEARCH_MODE_TO_TOWN, get from miscNo
  60. //======================================================================//
  61. // 1) if search_mode = SEARCH_MODE_TO_FIRM or SEARCH_MODE_TO_TOWN
  62. // the building top_left to bottom_right positions
  63. // 2) if search_mode = SEARCH_MODE_ATTACK_UNIT_BY_RANGE,
  64. // the effective attacking region top_left to bottom_right positions
  65. //======================================================================//
  66. static int building_x1, building_y1, building_x2, building_y2;
  67. static FirmInfo *search_firm_info;
  68. static int max_node_num;
  69. static short *reuse_node_matrix_ptr;
  70. static Node *reuse_result_node_ptr;
  71. static short final_dest_x; // in search_mode SEARCH_MODE_REUSE, dest_x and dest_y may set to a different value.
  72. static short final_dest_y; // i.e. the value used finally may not be the real dest_? given.
  73. //------- aliasing class member vars for fast access ------//
  74. static SeekPath* cur_seek_path;
  75. static short cur_dest_x, cur_dest_y;
  76. static short* cur_node_matrix;
  77. static Node* cur_node_array;
  78. static short cur_border_x1, cur_border_y1, cur_border_x2, cur_border_y2;
  79. static char nation_passable[MAX_NATION+1] = {0}; // Note: position 0 is not used for faster access
  80. static char search_sub_mode;
  81. //----------- Define static functions -----------//
  82. static void stack_push(Node *nodePtr);
  83. static Node* stack_pop();
  84. //-***************************************************************************-//
  85. //-*************************** for debuging **********************************-//
  86. //-***************************************************************************-//
  87. #ifdef DEBUG
  88. static int is_yielding = 0;
  89. static ResultNode *debugNode1, *debugNode2;
  90. static int dcount;
  91. static int vX, vY; // for debug only
  92. //---------- function debug_check() ------------//
  93. void debug_check(ResultNode *nodeArray, int count)
  94. {
  95. debugNode1 = nodeArray;
  96. debugNode2 = nodeArray+1;
  97. for(dcount=1; dcount<count; dcount++, debugNode1++, debugNode2++)
  98. {
  99. err_when(debugNode1->node_x<0 || debugNode1->node_x>=MAX_WORLD_X_LOC ||
  100. debugNode1->node_y<0 || debugNode1->node_y>=MAX_WORLD_Y_LOC);
  101. vX = debugNode2->node_x - debugNode2->node_x;
  102. vY = debugNode2->node_y - debugNode2->node_y;
  103. err_when(vX!=0 && vY!=0 && (abs(vX)!=abs(vY)));
  104. }
  105. err_when(debugNode1->node_x<0 || debugNode1->node_x>=MAX_WORLD_X_LOC ||
  106. debugNode1->node_y<0 || debugNode1->node_y>=MAX_WORLD_Y_LOC);
  107. }
  108. //----------- function debug_check_smode_exclude_hostile() -------------//
  109. void debug_check_smode_exclude_hostile(ResultNode *nodeArray, int count)
  110. {
  111. ResultNode *curNode = nodeArray;
  112. ResultNode *nextNode = nodeArray+1;
  113. Location *locPtr;
  114. int checkXLoc, checkYLoc, vecX, vecY, magn;
  115. for(int ij=1; ij<count; ij++, curNode++, nextNode++)
  116. {
  117. checkXLoc = curNode->node_x;
  118. checkYLoc = curNode->node_y;
  119. vecX = nextNode->node_x-curNode->node_x;
  120. vecY = nextNode->node_y-curNode->node_y;
  121. magn = (abs(vecX)>=abs(vecY)) ? abs(vecX) : abs(vecY);
  122. if(vecX) vecX /= abs(vecX);
  123. if(vecY) vecY /= abs(vecY);
  124. for(int jk=0; jk<magn; jk++)
  125. {
  126. checkXLoc += vecX;
  127. checkYLoc += vecY;
  128. locPtr = world.get_loc(checkXLoc, checkYLoc);
  129. err_when(locPtr->power_nation_recno && !nation_passable[locPtr->power_nation_recno]);
  130. }
  131. }
  132. }
  133. //-------------- function debug_check_sailable_path() --------------//
  134. void debug_check_sailable_path(ResultNode *nodeArray, int count)
  135. {
  136. ResultNode *debugPtr1 = nodeArray;
  137. ResultNode *debugPtr2 = nodeArray+1;
  138. int di=1, dj, dvecX, dvecY, magn;
  139. while(di<count)
  140. {
  141. dvecX = debugPtr2->node_x-debugPtr1->node_x;
  142. dvecY = debugPtr2->node_y-debugPtr1->node_y;
  143. magn = (abs(dvecX) > abs(dvecY)) ? abs(dvecX) : abs(dvecY);
  144. dvecX /= magn;
  145. dvecY /= magn;
  146. for(dj=1; dj<=magn; dj++)
  147. err_when(!world.get_loc(debugPtr1->node_x+dvecX*dj, debugPtr1->node_y+dvecY*dj)->sailable());
  148. di++;
  149. debugPtr1++;
  150. debugPtr2++;
  151. }
  152. }
  153. #endif
  154. #ifdef DEBUG
  155. #define debug_check_path(nodeArray, count) debug_check((nodeArray), (count))
  156. #define debug_check_sub_mode(nodeArray, count) debug_check_smode_exclude_hostile((nodeArray), (count))
  157. #define debug_check_sea_sailable(nodeArray, count) debug_check_sailable_path((nodeArray), (count))
  158. #else
  159. #define debug_check_path(nodeArray, count)
  160. #define debug_check_sub_mode(nodeArray, count)
  161. #define debug_check_sea_sailable(nodeArray, count)
  162. #endif
  163. //-***************************************************************************-//
  164. //-**************************** end debuging *********************************-//
  165. //-***************************************************************************-//
  166. //------- Begin of static function sys_yield ------//
  167. static void sys_yield()
  168. {
  169. #ifdef DEBUG
  170. is_yielding++;
  171. #endif
  172. //sys.yield();
  173. #ifdef DEBUG
  174. is_yielding = 0;
  175. #endif
  176. }
  177. //-------- End of static function sys_yield ------//
  178. //------- Begin of static function can_move_to ------//
  179. static int can_move_to(int xLoc, int yLoc)
  180. {
  181. Location *locPtr = world_loc_matrix+yLoc*MAX_WORLD_X_LOC+xLoc;
  182. Unit *unitPtr;
  183. short recno;
  184. char powerNationRecno;
  185. UCHAR unitCurAction;
  186. //------ check terrain id. -------//
  187. switch(mobile_type)
  188. {
  189. case UNIT_LAND:
  190. if(search_sub_mode==SEARCH_SUB_MODE_PASSABLE && (powerNationRecno=locPtr->power_nation_recno) &&
  191. !nation_passable[powerNationRecno])
  192. return 0;
  193. if(search_mode<SEARCH_MODE_TO_FIRM) //------ be careful for the checking for search_mode>=SEARCH_MODE_TO_FIRM
  194. {
  195. //------------------------------------------------------------------------//
  196. if(!locPtr->walkable())
  197. return 0;
  198. recno = locPtr->cargo_recno;
  199. if(!recno)
  200. return 1;
  201. switch(search_mode)
  202. {
  203. case SEARCH_MODE_IN_A_GROUP: // group move
  204. case SEARCH_MODE_REUSE: // path-reuse
  205. break;
  206. case SEARCH_MODE_A_UNIT_IN_GROUP: // a unit in a group
  207. unitPtr = unit_array[recno];
  208. return unitPtr->cur_action==SPRITE_MOVE && unitPtr->unit_id!=UNIT_CARAVAN;
  209. case SEARCH_MODE_TO_ATTACK: // to attack target
  210. case SEARCH_MODE_TO_VEHICLE: // move to a vehicle
  211. if(recno==target_recno)
  212. return 1;
  213. break;
  214. case SEARCH_MODE_BLOCKING: // 2x2 unit blocking
  215. unitPtr = unit_array[recno];
  216. return unitPtr->unit_group_id==group_id && (unitPtr->cur_action==SPRITE_MOVE || unitPtr->cur_action==SPRITE_READY_TO_MOVE);
  217. default: err_here();
  218. break;
  219. }
  220. }
  221. else
  222. {
  223. //--------------------------------------------------------------------------------//
  224. // for the following search_mode, location may be treated as walkable although it is not.
  225. //--------------------------------------------------------------------------------//
  226. switch(search_mode)
  227. {
  228. case SEARCH_MODE_TO_FIRM: // move to a firm, (location may be not walkable)
  229. case SEARCH_MODE_TO_TOWN: // move to a town zone, (location may be not walkable)
  230. if(!locPtr->walkable())
  231. return (xLoc>=building_x1 && xLoc<=building_x2 && yLoc>=building_y1 && yLoc<=building_y2);
  232. break;
  233. case SEARCH_MODE_TO_WALL_FOR_GROUP: // move to wall for a group, (location may be not walkable)
  234. if(!locPtr->walkable())
  235. return (xLoc==final_dest_x && yLoc==final_dest_y);
  236. break;
  237. case SEARCH_MODE_TO_WALL_FOR_UNIT: // move to wall for a unit only, (location may be not walkable)
  238. return (locPtr->walkable() && locPtr->cargo_recno==0) || (xLoc==final_dest_x && yLoc==final_dest_y);
  239. case SEARCH_MODE_ATTACK_UNIT_BY_RANGE: // same as that used in SEARCH_MODE_TO_FIRM
  240. case SEARCH_MODE_ATTACK_FIRM_BY_RANGE:
  241. case SEARCH_MODE_ATTACK_TOWN_BY_RANGE:
  242. case SEARCH_MODE_ATTACK_WALL_BY_RANGE:
  243. if(!locPtr->walkable())
  244. return (xLoc>=building_x1 && xLoc<=building_x2 && yLoc>=building_y1 && yLoc<=building_y2);
  245. break;
  246. default: err_here();
  247. break;
  248. }
  249. recno = (mobile_type!=UNIT_AIR) ? locPtr->cargo_recno : locPtr->air_cargo_recno;
  250. if(!recno)
  251. return 1;
  252. }
  253. //------- checking for unit's group_id, cur_action, nation_recno and position --------//
  254. unitPtr = unit_array[recno];
  255. unitCurAction = unitPtr->cur_action;
  256. return (unitPtr->unit_group_id==group_id && unitCurAction!=SPRITE_ATTACK) ||
  257. (unitCurAction==SPRITE_MOVE && unitPtr->cur_x-unitPtr->next_x<=ZOOM_LOC_HALF_WIDTH &&
  258. unitPtr->cur_y-unitPtr->next_y<=ZOOM_LOC_HALF_HEIGHT) ||
  259. (unitPtr->nation_recno==seek_nation_recno && unitCurAction==SPRITE_IDLE);
  260. break;
  261. case UNIT_SEA:
  262. if(search_mode<SEARCH_MODE_TO_FIRM) //--------- be careful for the search_mode>=SEARCH_MODE_TO_FIRM
  263. {
  264. if(!locPtr->sailable())
  265. return 0;
  266. recno = locPtr->cargo_recno;
  267. if(!recno)
  268. return 1;
  269. switch(search_mode)
  270. {
  271. case SEARCH_MODE_IN_A_GROUP: // group move
  272. case SEARCH_MODE_REUSE: // path-reuse
  273. break;
  274. case SEARCH_MODE_A_UNIT_IN_GROUP: // a unit in a group
  275. return unit_array[recno]->cur_action==SPRITE_MOVE;
  276. case SEARCH_MODE_TO_ATTACK:
  277. if(recno==target_recno)
  278. return 1;
  279. break;
  280. default: err_here();
  281. break;
  282. }
  283. }
  284. else
  285. {
  286. //--------------------------------------------------------------------------------//
  287. // for the following search_mode, location may be treated as sailable although it is not.
  288. //--------------------------------------------------------------------------------//
  289. switch(search_mode)
  290. {
  291. case SEARCH_MODE_TO_FIRM: // move to a firm, (location may be not walkable)
  292. case SEARCH_MODE_TO_TOWN: // move to a town zone, (location may be not walkable)
  293. if(!locPtr->sailable())
  294. return (xLoc>=building_x1 && xLoc<=building_x2 && yLoc>=building_y1 && yLoc<=building_y2);
  295. break;
  296. //case SEARCH_MODE_TO_WALL_FOR_GROUP: // move to wall for a group, (location may be not walkable)
  297. //case SEARCH_MODE_TO_WALL_FOR_UNIT: // move to wall for a unit only, (location may be not walkable)
  298. case SEARCH_MODE_ATTACK_UNIT_BY_RANGE: // same as that used in SEARCH_MODE_TO_FIRM
  299. case SEARCH_MODE_ATTACK_FIRM_BY_RANGE:
  300. case SEARCH_MODE_ATTACK_TOWN_BY_RANGE:
  301. case SEARCH_MODE_ATTACK_WALL_BY_RANGE:
  302. if(!locPtr->sailable())
  303. return (xLoc>=building_x1 && xLoc<=building_x2 && yLoc>=building_y1 && yLoc<=building_y2);
  304. break;
  305. case SEARCH_MODE_TO_LAND_FOR_SHIP:
  306. if(locPtr->sailable())
  307. {
  308. recno = locPtr->cargo_recno;
  309. if(!recno)
  310. return 1;
  311. unitPtr = unit_array[recno];
  312. unitCurAction = unitPtr->cur_action;
  313. return (unitPtr->unit_group_id==group_id && unitCurAction!=SPRITE_ATTACK &&
  314. unitPtr->action_mode2!=ACTION_SHIP_TO_BEACH) ||
  315. (unitPtr->unit_group_id!=group_id && unitCurAction==SPRITE_MOVE);
  316. }
  317. else if(locPtr->walkable() && locPtr->region_id==region_id)
  318. return 1;
  319. else
  320. return 0;
  321. default: err_here();
  322. break;
  323. }
  324. recno = locPtr->cargo_recno;
  325. if(!recno)
  326. return 1;
  327. }
  328. //------- checking for unit's group_id, cur_action, nation_recno and position --------//
  329. unitPtr = unit_array[recno];
  330. unitCurAction = unitPtr->cur_action;
  331. return (unitPtr->unit_group_id==group_id && unitCurAction!=SPRITE_ATTACK) ||
  332. unitCurAction==SPRITE_MOVE ||
  333. (unitPtr->nation_recno==seek_nation_recno && unitCurAction==SPRITE_IDLE);
  334. break;
  335. case UNIT_AIR:
  336. recno = locPtr->air_cargo_recno;
  337. if(!recno)
  338. return 1;
  339. switch(search_mode)
  340. {
  341. case SEARCH_MODE_IN_A_GROUP:
  342. case SEARCH_MODE_REUSE:
  343. case SEARCH_MODE_TO_ATTACK:
  344. case SEARCH_MODE_TO_FIRM:
  345. case SEARCH_MODE_TO_TOWN:
  346. case SEARCH_MODE_TO_WALL_FOR_GROUP:
  347. case SEARCH_MODE_TO_WALL_FOR_UNIT:
  348. case SEARCH_MODE_ATTACK_UNIT_BY_RANGE:
  349. case SEARCH_MODE_ATTACK_FIRM_BY_RANGE:
  350. case SEARCH_MODE_ATTACK_TOWN_BY_RANGE:
  351. case SEARCH_MODE_ATTACK_WALL_BY_RANGE:
  352. unitPtr = unit_array[recno];
  353. unitCurAction = unitPtr->cur_action;
  354. return (unitPtr->unit_group_id==group_id && unitCurAction!=SPRITE_ATTACK) ||
  355. unitCurAction==SPRITE_MOVE ||
  356. (unitPtr->nation_recno==seek_nation_recno && unitCurAction==SPRITE_IDLE);
  357. case SEARCH_MODE_A_UNIT_IN_GROUP: // a unit in a group
  358. return unit_array[recno]->cur_action==SPRITE_MOVE;
  359. default: err_here();
  360. break;
  361. }
  362. break;
  363. }
  364. return 0;
  365. }
  366. //-------- End of static function can_move_to ------//
  367. //-------- Begin of function SeekPath::bound_check_x ---------//
  368. inline void SeekPath::bound_check_x(short &paraX)
  369. {
  370. if(paraX<0)
  371. paraX = 0;
  372. else if(paraX>=MAX_WORLD_X_LOC-1)
  373. paraX = MAX_WORLD_X_LOC-1;
  374. }
  375. //-------- End of static function bound_check_x ------//
  376. //-------- Begin of function SeekPath::bound_check_y ---------//
  377. inline void SeekPath::bound_check_y(short &paraY)
  378. {
  379. if(paraY<0)
  380. paraY = 0;
  381. else if(paraY>=MAX_WORLD_Y_LOC-1)
  382. paraY = MAX_WORLD_Y_LOC-1;
  383. }
  384. //-------- End of static function bound_check_y ------//
  385. //-------- Begin of function SeekPath::result_node_distance ---------//
  386. inline short SeekPath::result_node_distance(ResultNode *node1, ResultNode *node2)
  387. {
  388. short xDist = abs(node1->node_x - node2->node_y);
  389. #ifdef DEBUG
  390. short yDist = abs(node1->node_y-node2->node_y);
  391. #endif
  392. if(xDist)
  393. {
  394. err_when(yDist && xDist!=yDist);
  395. return xDist;
  396. }
  397. else // xDist = 0;
  398. {
  399. err_when(yDist==0);
  400. return abs(node1->node_y-node2->node_y);
  401. }
  402. }
  403. //-------- End of static function result_node_distance ------//
  404. //-------- Begin of function SeekPath::init ---------//
  405. void SeekPath::init(int maxNode)
  406. {
  407. max_node = maxNode;
  408. node_array = (Node*) mem_add( max_node * sizeof(Node) );
  409. node_matrix = (short*) mem_add(sizeof(short)*MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC/4);
  410. path_status = PATH_WAIT;
  411. open_node_list.reset_priority_queue();
  412. closed_node_list.reset_priority_queue();
  413. reset_total_node_avail();
  414. }
  415. //--------- End of function SeekPath::init ---------//
  416. //-------- Begin of function SeekPath::deinit ---------//
  417. void SeekPath::deinit()
  418. {
  419. if( node_array )
  420. {
  421. mem_del(node_array);
  422. node_array = NULL;
  423. }
  424. if( node_matrix )
  425. {
  426. mem_del(node_matrix);
  427. node_matrix = NULL;
  428. }
  429. }
  430. //--------- End of function SeekPath::deinit ---------//
  431. //-------- Begin of function SeekPath::set_node_matrix ---------//
  432. void SeekPath::set_node_matrix(short reuseNodeMatrix[])
  433. {
  434. reuse_node_matrix_ptr = reuseNodeMatrix;
  435. }
  436. //--------- End of function SeekPath::set_node_matrix ---------//
  437. //-------- Begin of function SeekPath::reset ---------//
  438. void SeekPath::reset()
  439. {
  440. path_status=PATH_WAIT;
  441. open_node_list.reset_priority_queue();
  442. closed_node_list.reset_priority_queue();
  443. }
  444. //--------- End of function SeekPath::reset ---------//
  445. //-------- Begin of function SeekPath::reset_total_node_used ---------//
  446. void SeekPath::reset_total_node_avail()
  447. {
  448. total_node_avail = MAX_BACKGROUND_NODE;
  449. }
  450. //--------- End of function SeekPath::reset_total_node_used ---------//
  451. //-------- Begin of function SeekPath::set_attack_range_para ---------//
  452. void SeekPath::set_attack_range_para(int attackRange)
  453. {
  454. attack_range = attackRange;
  455. }
  456. //--------- End of function SeekPath::set_attack_range_para ---------//
  457. //-------- Begin of function SeekPath::reset_attack_range_para ---------//
  458. void SeekPath::reset_attack_range_para()
  459. {
  460. attack_range = 0;
  461. }
  462. //--------- End of function SeekPath::reset_attack_range_para ---------//
  463. //-------- Begin of function SeekPath::set_nation_recno ---------//
  464. // store the nation_recno of the unit calling searching
  465. //
  466. void SeekPath::set_nation_recno(char nationRecno)
  467. {
  468. seek_nation_recno = nationRecno;
  469. }
  470. //--------- End of function SeekPath::set_nation_recno ---------//
  471. //-------- Begin of function SeekPath::set_nation_passable ---------//
  472. void SeekPath::set_nation_passable(char nationPassable[])
  473. {
  474. memcpy(nation_passable+1, nationPassable, sizeof(char)*MAX_NATION);
  475. }
  476. //--------- End of function SeekPath::set_nation_passable ---------//
  477. //-------- Begin of function SeekPath::set_sub_mode ---------//
  478. void SeekPath::set_sub_mode(char subMode)
  479. {
  480. search_sub_mode = subMode;
  481. }
  482. //--------- End of function SeekPath::set_sub_mode ---------//
  483. //-------- Begin of function SeekPath::add_result_node ---------//
  484. inline void SeekPath::add_result_node(int x, int y, ResultNode** curPtr, ResultNode** prePtr, int& count)
  485. {
  486. (*curPtr)->node_x = x;
  487. (*curPtr)->node_y = y;
  488. err_when(count>1 && (abs((*curPtr)->node_x-(*prePtr)->node_x)>1 || abs((*curPtr)->node_y-(*prePtr)->node_y)>1));
  489. *prePtr = *curPtr;
  490. (*curPtr)++;
  491. count++;
  492. }
  493. //--------- End of function SeekPath::add_result_node ---------//
  494. //-------- Begin of function SeekPath::seek ---------//
  495. //
  496. // <int> sx, sy - the starting world location.
  497. // <int> dx, dy - the destination world location.
  498. // <DWORD> groupId - unit group id.
  499. // <char> mobileType - mobile type, can be UNIT_AIR, UNIT_LAND or UNIT_SEA
  500. //
  501. // [int] searchMode - 1 SEARCH_MODE_IN_A_GROUP for one group with an unique group id (default)
  502. // 2 SEARCH_MODE_A_UNIT_IN_GROUP for one sprite in a group
  503. // 3 SERACH_MODE_TO_ATTACK for the searching that one sprite is ordered to attack its target
  504. // 4 SEARCH_MODE_REUSE for path-reuse
  505. // 5 SEARCH_MODE_BLOCKING for 2x2 unit blocking search
  506. // 6 SEARCH_MODE_TO_FIRM for moving to a firm
  507. // 7 SEARCH_MODE_TO_TOWN for moving to a town zone
  508. // 8 SEARCH_MODE_TO_VEHICLE for moving to a vehicle
  509. // 9 SEARCH_MODE_TO_WALL_FOR_GROUP for moving to a wall location
  510. // 10 SEARCH_MODE_TO_WALL_FOR_UNIT for moving to a wall location
  511. // 11 SEARCH_MODE_ATTACK_UNIT_BY_RANGE for range attacking target
  512. // 12 SEARCH_MODE_ATTACK_FIRM_BY_RANGE ditto
  513. // 13 SEARCH_MODE_ATTACK_TOWN_BY_RANGE ditto
  514. // 14 SEARCH_MODE_ATTACK_WALL_BY_RANGE ditto
  515. // 15 SEARCH_MODE_TO_LAND_FOR_SHIP for ships to move to land
  516. // (default: 1)
  517. //
  518. // [int] miscNo - if searchMode = SEARCH_MODE_TO_ATTACK, meaning target_recno
  519. // - if searchMode = SEARCH_MODE_TO_FIRM, meaning firm_id
  520. // - if searchMode = SEARCH_MODE_TO_LAND_FOR_SHIP, meaning the region_id of the land moving to
  521. // (default: 0)
  522. //
  523. // [int] numOfPath - for group assign, group settle. It is used to generate more set of virtual
  524. // destination in the firm/town for searching.
  525. //
  526. // [int] maxTries - maximum no. of tries in the first seek action.
  527. // this refer to the maximum no. of nodes created.
  528. // (default : max_node)
  529. //
  530. // [int] borderX1, borderY1, - borders of the seek area in the world map
  531. // borderX2, borderY2 (default: the whole map)
  532. //
  533. // Note: if maxTries==max_node, incremental seek (PATH_SEEKING) won't happen.
  534. //
  535. // return : <int> seekStatus - PATH_FOUND, PATH_SEEKING, PATH_NODE_USED_UP, or PATH_IMPOSSIBLE
  536. // if PATH_FOUND, or PATH_NODE_USED_UP, can call get_result() to retrieve the result.
  537. //
  538. int SeekPath::seek(int sx,int sy,int dx,int dy, DWORD groupId, char mobileType,
  539. short searchMode, short miscNo, short numOfPath, int maxTries,
  540. int borderX1,int borderY1,int borderX2,int borderY2)
  541. {
  542. err_when(is_yielding);
  543. if(total_node_avail<=0)
  544. return PATH_FOUND; // checking
  545. border_x1 = short(borderX1/2); // change to 2x2 node format
  546. border_y1 = short(borderY1/2);
  547. border_x2 = short(borderX2/2);
  548. border_y2 = short(borderY2/2);
  549. //-------- initialize vars --------------//
  550. current_search_node_used = 0; // count the number of nodes used in each searching
  551. path_status = PATH_SEEKING;
  552. world_loc_matrix = world.loc_matrix;
  553. open_node_list.reset_priority_queue();
  554. closed_node_list.reset_priority_queue();
  555. search_mode = searchMode;
  556. group_id = groupId;
  557. mobile_type = mobileType;
  558. err_when(search_mode!=searchMode || group_id!=groupId || mobile_type!=mobileType);
  559. //------------------------------------------------------------------------------//
  560. // using another searching for unit sea or unit air
  561. //------------------------------------------------------------------------------//
  562. if(mobile_type!=UNIT_LAND)
  563. return seek2(sx, sy, dx, dy, miscNo, numOfPath, maxTries); // redirect entry of UNIT_SEA or UNIT_AIR
  564. //------------------------------------------------------------------------------//
  565. // extract informaton from the parameter "miscNo"
  566. //------------------------------------------------------------------------------//
  567. target_recno = building_id = 0;
  568. building_x1 = building_y1 = building_x2 = building_y2 = -1;
  569. switch(search_mode)
  570. {
  571. case SEARCH_MODE_TO_ATTACK:
  572. case SEARCH_MODE_TO_VEHICLE:
  573. target_recno = miscNo;
  574. break;
  575. case SEARCH_MODE_TO_FIRM:
  576. building_id = miscNo;
  577. building_x1 = dx; // upper left corner location
  578. building_y1 = dy;
  579. search_firm_info = firm_res[building_id];
  580. building_x2 = dx+search_firm_info->loc_width-1;
  581. building_y2 = dy+search_firm_info->loc_height-1;
  582. break;
  583. case SEARCH_MODE_TO_TOWN:
  584. building_id = miscNo;
  585. building_x1 = dx; // upper left corner location
  586. building_y1 = dy;
  587. if(miscNo != -1)
  588. {
  589. Location* buildPtr = world.get_loc(dx, dy);
  590. Town* targetTown = town_array[buildPtr->town_recno()];
  591. building_x2 = targetTown->loc_x2;
  592. building_y2 = targetTown->loc_y2;
  593. }
  594. else // searching to settle. Detail explained in function set_move_to_surround()
  595. {
  596. building_x2 = building_x1+STD_TOWN_LOC_WIDTH-1;
  597. building_y2 = building_y1+STD_TOWN_LOC_HEIGHT-1;
  598. }
  599. break;
  600. case SEARCH_MODE_ATTACK_UNIT_BY_RANGE:
  601. case SEARCH_MODE_ATTACK_WALL_BY_RANGE:
  602. building_id = miscNo;
  603. building_x1 = max(dx-attack_range, 0);
  604. building_y1 = max(dy-attack_range, 0);
  605. building_x2 = min(dx+attack_range, MAX_WORLD_X_LOC-1);
  606. building_y2 = min(dy+attack_range, MAX_WORLD_Y_LOC-1);
  607. break;
  608. case SEARCH_MODE_ATTACK_FIRM_BY_RANGE:
  609. building_id = miscNo;
  610. building_x1 = max(dx-attack_range, 0);
  611. building_y1 = max(dy-attack_range, 0);
  612. search_firm_info = firm_res[building_id];
  613. building_x2 = min(dx+search_firm_info->loc_width-1+attack_range, MAX_WORLD_X_LOC-1);
  614. building_y2 = min(dy+search_firm_info->loc_height-1+attack_range, MAX_WORLD_Y_LOC-1);
  615. break;
  616. case SEARCH_MODE_ATTACK_TOWN_BY_RANGE:
  617. building_id = miscNo;
  618. building_x1 = max(dx-attack_range, 0);
  619. building_y1 = max(dy-attack_range, 0);
  620. building_x2 = min(dx+STD_TOWN_LOC_WIDTH-1+attack_range, MAX_WORLD_X_LOC-1);
  621. building_y2 = min(dy+STD_TOWN_LOC_HEIGHT-1+attack_range, MAX_WORLD_Y_LOC-1);
  622. break;
  623. }
  624. //------------------------------------------------------------------------------//
  625. // set start location and destination location
  626. //------------------------------------------------------------------------------//
  627. real_sour_x = sx;
  628. real_sour_y = sy;
  629. //---------- adjust destination for some kind of searching ------------//
  630. int xShift, yShift, area;
  631. short pathNum;
  632. switch(search_mode)
  633. {
  634. case SEARCH_MODE_TO_FIRM:
  635. case SEARCH_MODE_TO_TOWN:
  636. final_dest_x = (building_x1+building_x2)/2; // the destination is set to be the middle of the building
  637. final_dest_y = (building_y1+building_y2)/2;
  638. //---------------------------------------------------------------------------------//
  639. // for group assign/settle, the final destination is adjusted by the value of numOfPath
  640. //---------------------------------------------------------------------------------//
  641. if(search_mode==SEARCH_MODE_TO_TOWN)
  642. area = STD_TOWN_LOC_WIDTH*STD_TOWN_LOC_HEIGHT;
  643. else // search_mode == SEARCH_MODE_TO_FIRM
  644. area = search_firm_info->loc_width*search_firm_info->loc_height;
  645. pathNum = (numOfPath>area) ? (numOfPath-1)%area + 1 : numOfPath;
  646. if(search_mode==SEARCH_MODE_TO_TOWN)
  647. m.cal_move_around_a_point(pathNum, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, xShift, yShift);
  648. else
  649. m.cal_move_around_a_point(pathNum, search_firm_info->loc_width, search_firm_info->loc_height, xShift, yShift);
  650. final_dest_x += xShift;
  651. final_dest_y += yShift;
  652. bound_check_x(final_dest_x);
  653. bound_check_y(final_dest_y);
  654. break;
  655. case SEARCH_MODE_ATTACK_UNIT_BY_RANGE:
  656. case SEARCH_MODE_ATTACK_FIRM_BY_RANGE:
  657. case SEARCH_MODE_ATTACK_TOWN_BY_RANGE:
  658. case SEARCH_MODE_ATTACK_WALL_BY_RANGE:
  659. final_dest_x = (building_x1+building_x2)/2; // the destination is set to be the middle of the building
  660. final_dest_y = (building_y1+building_y2)/2;
  661. break;
  662. default:
  663. final_dest_x = real_dest_x = dx;
  664. final_dest_y = real_dest_y = dy;
  665. break;
  666. }
  667. //--------------------------------------------------------------//
  668. // change to 2x2 node format
  669. //--------------------------------------------------------------//
  670. int sourceX = short(sx/2); // the upper left corner is used
  671. int sourceY = short(sy/2);
  672. dest_x = short(final_dest_x/2);
  673. dest_y = short(final_dest_y/2);
  674. //-----------------------------------------//
  675. // reset node_matrix
  676. //-----------------------------------------//
  677. if(search_mode!=SEARCH_MODE_REUSE)
  678. {
  679. max_node_num = 0xFFFF;
  680. memset(node_matrix, 0, sizeof(short)*MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC/4);
  681. }
  682. else
  683. {
  684. max_node_num = max_node;
  685. memcpy(node_matrix, reuse_node_matrix_ptr, sizeof(short)*MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC/4);
  686. }
  687. //--------- create the first node ---------//
  688. node_count = 0;
  689. result_node_ptr = NULL;
  690. Node *nodePtr = node_array + node_count++;
  691. memset(nodePtr, 0, sizeof(Node));
  692. //-------- store the upper left coordinate of the node ----------//
  693. upper_left_x = sourceX<<1;
  694. upper_left_y = sourceY<<1;
  695. //---------- calculate the node type -----------//
  696. nodePtr->node_type = 0;
  697. nodePtr->node_type = (can_move_to(upper_left_x,upper_left_y))+(can_move_to(upper_left_x+1,upper_left_y)<<1)+
  698. (can_move_to(upper_left_x,upper_left_y+1)<<2)+(can_move_to(upper_left_x+1,upper_left_y+1)<<3);
  699. if(searchMode==SEARCH_MODE_A_UNIT_IN_GROUP || searchMode==SEARCH_MODE_TO_WALL_FOR_UNIT) // plus the self-location
  700. nodePtr->node_type += (real_sour_x>upper_left_x)?2+(real_sour_y-upper_left_y)*6:1+(real_sour_y-upper_left_y)*3;
  701. else
  702. {
  703. /*if(searchMode==SEARCH_MODE_TO_FIRM || searchMode==SEARCH_MODE_TO_TOWN) // plus the self-location
  704. {
  705. if(real_sour_x<building_x1 || real_sour_x>building_x2 ||
  706. real_sour_y<building_y1 || real_sour_y>building_y2)
  707. nodePtr->node_type += (real_sour_x>upper_left_x)?2+(real_sour_y-upper_left_y)*6:1+(real_sour_y-upper_left_y)*3;
  708. }*/
  709. }
  710. err_when(nodePtr->node_type>15 || nodePtr->node_type <0);
  711. int destUpperLeftX = dest_x<<1;
  712. int destUpperLeftY = dest_y<<1;
  713. is_dest_blocked = !((can_move_to(destUpperLeftX,destUpperLeftY))+(can_move_to(destUpperLeftX+1,destUpperLeftY)<<1)+
  714. (can_move_to(destUpperLeftX,destUpperLeftY+1)<<2)+(can_move_to(destUpperLeftX+1,destUpperLeftY+1)<<3));
  715. // whether the destination is blocked, if so, only search till the destination's neighbor locations
  716. nodePtr->node_g = 0;
  717. nodePtr->node_h = (sourceX-dest_x)*(sourceX-dest_x)+(sourceY-dest_y)*(sourceY-dest_y); // should really use sqrt().
  718. nodePtr->node_f = nodePtr->node_g + nodePtr->node_h;
  719. nodePtr->node_x = sourceX;
  720. nodePtr->node_y = sourceY;
  721. nodePtr->enter_direction = 0;
  722. open_node_list.insert_node(nodePtr); // make Open List point to first node
  723. //--- if the destination is the current postion or next to it & the dest is occupied ---//
  724. if( sourceX==dest_x && sourceY==dest_y )
  725. {
  726. path_status = PATH_FOUND;
  727. result_node_ptr = nodePtr;
  728. return path_status;
  729. }
  730. //------------ seek now ------------------//
  731. int maxNode = (!maxTries) ? max_node : maxTries;
  732. return continue_seek(maxNode, 1); // 1-first seek session of the current seek order
  733. }
  734. //-------- End of function SeekPath::seek ---------//
  735. //---- Begin of function SeekPath::continue_seek ---------//
  736. //
  737. // If the last seek operation does not find the whole path,
  738. // continue the search.
  739. //
  740. // <int> maxTries - maximum path seeking tries
  741. // [char] firstSeek - whether it's the first seek session of the seek order.
  742. // (default: 0)
  743. //
  744. // return : <int> seekStatus - PATH_FOUND, PATH_SEEKING, PATH_NODE_USED_UP,
  745. // or PATH_IMPOSSIBLE
  746. //
  747. // You can call get_result() to retrieve the result.
  748. //
  749. int SeekPath::continue_seek(int maxTries, char firstSeek)
  750. {
  751. if( path_status != PATH_SEEKING )
  752. return path_status;
  753. //------- aliasing class member vars for fast access ------//
  754. cur_seek_path = this;
  755. cur_dest_x = dest_x;
  756. cur_dest_y = dest_y;
  757. cur_node_matrix = node_matrix;
  758. cur_node_array = node_array;
  759. cur_border_x1 = border_x1;
  760. cur_border_y1 = border_y1;
  761. cur_border_x2 = border_x2;
  762. cur_border_y2 = border_y2;
  763. //------ seek the path using the A star algorithm -----//
  764. int maxNode = (total_node_avail<maxTries) ? total_node_avail : maxTries;
  765. maxNode -= MAX_CHILD_NODE; // generate_successors() can generate a max of MAX_CHILD_NODE new nodes per call
  766. Node *bestNodePtr;
  767. int i;
  768. for(i=0; i<maxNode; i++)
  769. {
  770. bestNodePtr = return_best_node();
  771. //if(i%20==0)
  772. // sys_yield(); // update cursor position
  773. //---- even if the path is impossible, get the closest path ----//
  774. if( !bestNodePtr )
  775. {
  776. path_status = PATH_IMPOSSIBLE;
  777. break;
  778. }
  779. //----- exceed the object's max's node limitation, return the closest path ----//
  780. if( node_count >= maxNode )
  781. {
  782. path_status = PATH_NODE_USED_UP;
  783. break;
  784. }
  785. //---------------------------------------------------------------//
  786. // If the path is found OR If the destination is blocked,
  787. // consider it done when we are next to it.
  788. //---------------------------------------------------------------//
  789. if( (bestNodePtr->node_x==dest_x && bestNodePtr->node_y==dest_y) ||
  790. ( is_dest_blocked && abs(bestNodePtr->node_x-dest_x)<=0 && abs(bestNodePtr->node_y-dest_y)<=0 ) )
  791. {
  792. path_status = PATH_FOUND;
  793. result_node_ptr = bestNodePtr;
  794. break;
  795. }
  796. //--------- generate successors -------//
  797. if(bestNodePtr->generate_successors(bestNodePtr->enter_direction, real_sour_x, real_sour_y))
  798. {
  799. path_status = PATH_REUSE_FOUND;
  800. result_node_ptr = reuse_result_node_ptr;
  801. break;
  802. }
  803. }
  804. err_when( cur_stack_pos!=0 ); // it should be zero all the times, all pushes should have been poped
  805. current_search_node_used = i+1; // store the number of nodes used in this searching
  806. return path_status;
  807. }
  808. //------ End of function SeekPath::continue_seek ---------//
  809. //---- Begin of function SeekPath::get_result ---------//
  810. //
  811. // Compile the seek result nodes using results processed by
  812. // seek() and continue_seek() and store the results in
  813. // an array of ResultNode.
  814. //
  815. // <int&> resultNodeCount - a reference var for returning the no. of result nodes.
  816. // <short&> pathDist - a reference var for returning the total distance of the result path
  817. //
  818. // return : <ResultNode*> an array of ResultNode.
  819. // the caller function is responsible for
  820. // freeing the memory of the array.
  821. //
  822. ResultNode* SeekPath::get_result(int& resultNodeCount, short& pathDist)
  823. {
  824. if(mobile_type!=UNIT_LAND)
  825. return get_result2(resultNodeCount, pathDist); // redirect entry point for UNIT_SEA or UNIT_AIR
  826. resultNodeCount = pathDist = 0;
  827. if(total_node_avail<=0)
  828. return NULL;
  829. total_node_avail -= current_search_node_used;
  830. short useClosestNode = 0; // indicate whether closest node is returned instead of the actual node
  831. if(!result_node_ptr) // if PATH_IMPOSSIBLE or PATH_NODE_USED_UP, result_node_ptr is NULL, we need to call get_closest_node() to get the closest node.
  832. {
  833. result_node_ptr = return_closest_node();
  834. useClosestNode = 1;
  835. if(!result_node_ptr)
  836. return NULL;
  837. }
  838. //--------------------------------------------------//
  839. // Trace backwards to the starting node, and rationalize
  840. // nodes (i.e. group nodes of the same direction into
  841. // single nodes.)
  842. //--------------------------------------------------//
  843. Node* nodePtr = result_node_ptr; // the node current being processed
  844. Node* baseNodePtr = result_node_ptr; // the first end node for connecting the other end node for the path in that direction.
  845. Node* parentNode = nodePtr->parent_node; // the parent node of nodePtr
  846. Node* childNodePtr = nodePtr; // it should point to the children node of nodePtr
  847. //------------------------------------------------------------------------
  848. // there are only one node, source & destination within the same 2x2 node
  849. //------------------------------------------------------------------------
  850. if(!parentNode) // parentNode==0 when the source location is the desination already
  851. {
  852. if((real_sour_x!=final_dest_x || real_sour_y!=final_dest_y) && abs(real_sour_x-final_dest_x)<=1 &&
  853. abs(real_sour_y-final_dest_y)<=1 && can_move_to(final_dest_x, final_dest_y))
  854. {
  855. pathDist = 1;
  856. ResultNode* resultNodeArray1 = (ResultNode*) mem_add(sizeof(ResultNode)*2);
  857. ResultNode* resultNodePtr1 = resultNodeArray1;
  858. resultNodeCount=2;
  859. resultNodePtr1->node_x = real_sour_x;
  860. resultNodePtr1->node_y = real_sour_y;
  861. resultNodePtr1++;
  862. resultNodePtr1->node_x = final_dest_x;
  863. resultNodePtr1->node_y = final_dest_y;
  864. return resultNodeArray1;
  865. }
  866. else
  867. return NULL;
  868. }
  869. resultNodeCount=1; // including the current node
  870. //===================================
  871. // count the number of 2x2 node
  872. //===================================
  873. int numOfNode=0;
  874. Node* curPtr = result_node_ptr;
  875. while(curPtr != NULL)
  876. {
  877. curPtr = curPtr->parent_node;
  878. numOfNode++;
  879. }
  880. //sys_yield(); // update cursor position
  881. //---------------------------------
  882. // otherwise, there are more than one node
  883. //---------------------------------
  884. node_count=0;
  885. ResultNode* maxSizeResultNodeArray; // store all the result node in the reverse order, the turning point will be extracted later
  886. int nodeAllocated = (numOfNode+1)<<1;//numOfNode*2+2; // the additional 2 is for the starting node
  887. maxSizeResultNodeArray = (ResultNode*) mem_add(nodeAllocated*sizeof(ResultNode));
  888. max_size_result_node_ptr = maxSizeResultNodeArray;
  889. parent_result_node_ptr = maxSizeResultNodeArray;
  890. //----------------------------------
  891. // start from the destination point
  892. //----------------------------------
  893. memset(max_size_result_node_ptr, 0, sizeof(ResultNode)*nodeAllocated);
  894. int upper_left_x = nodePtr->node_x<<1;
  895. int upper_left_y = nodePtr->node_y<<1;
  896. short xCount, yCount; // for counting
  897. if(!useClosestNode && (search_mode==SEARCH_MODE_TO_ATTACK || search_mode==SEARCH_MODE_TO_VEHICLE ||
  898. can_move_to(final_dest_x, final_dest_y)))
  899. {
  900. max_size_result_node_ptr->node_x = final_dest_x;
  901. max_size_result_node_ptr->node_y = final_dest_y;
  902. }
  903. else
  904. { // use closest node
  905. max_size_result_node_ptr->node_x = MAX_WORLD_X_LOC;
  906. max_size_result_node_ptr->node_y = MAX_WORLD_Y_LOC;
  907. int newValue, xSquare, yDiff;
  908. int compareValue = 0x7FFFFFFF; // should > 199^2 + 199^2
  909. for(xCount=upper_left_x+1; xCount>=upper_left_x; xCount--)
  910. {
  911. xSquare = int(final_dest_x-xCount)*(final_dest_x-xCount);
  912. for(yCount=upper_left_y+1, yDiff=final_dest_y-yCount; yCount>=upper_left_y; yCount--, yDiff++)
  913. {
  914. if(can_move_to(xCount, yCount) && (newValue = xSquare + yDiff*yDiff)<compareValue)
  915. {
  916. max_size_result_node_ptr->node_x = xCount;
  917. max_size_result_node_ptr->node_y = yCount;
  918. compareValue = newValue;
  919. }
  920. }
  921. }
  922. err_when(max_size_result_node_ptr->node_x==MAX_WORLD_X_LOC &&
  923. max_size_result_node_ptr->node_y==MAX_WORLD_Y_LOC);
  924. final_dest_x = max_size_result_node_ptr->node_x;
  925. final_dest_y = max_size_result_node_ptr->node_y;
  926. }
  927. xCount = max_size_result_node_ptr->node_x;
  928. yCount = max_size_result_node_ptr->node_y;
  929. max_size_result_node_ptr++; // note: parent_result_node_ptr don't move for this case
  930. node_count++;
  931. //---------------------------------------------------
  932. // process the end node if passing through two points
  933. //---------------------------------------------------
  934. int xLoc, yLoc;
  935. switch(nodePtr->enter_direction)
  936. {
  937. case 1:
  938. if(upper_left_x < xCount)
  939. {
  940. yLoc = can_move_to(upper_left_x, yCount) ? yCount : ((yCount>upper_left_y)?upper_left_y:upper_left_y+1);
  941. add_result_node(upper_left_x, yLoc, &max_size_result_node_ptr, &parent_result_node_ptr, node_count);
  942. }
  943. break;
  944. case 2: if((upper_left_x!=xCount) || ((upper_left_y+1)!=yCount))
  945. add_result_node(upper_left_x, upper_left_y+1, &max_size_result_node_ptr, &parent_result_node_ptr, node_count);
  946. break;
  947. case 3:
  948. if(upper_left_y == yCount)
  949. {
  950. xLoc = can_move_to(xCount,upper_left_y+1) ? xCount : ((xCount>upper_left_x)?upper_left_x:(upper_left_x+1));
  951. add_result_node(xLoc, upper_left_y+1, &max_size_result_node_ptr, &parent_result_node_ptr, node_count);
  952. }
  953. break;
  954. case 4: if(((upper_left_x+1)!=xCount) || ((upper_left_y+1)!=yCount))
  955. add_result_node(upper_left_x+1, upper_left_y+1, &max_size_result_node_ptr, &parent_result_node_ptr, node_count);
  956. break;
  957. case 5:
  958. if(upper_left_x == final_dest_x)
  959. {
  960. yLoc = can_move_to(upper_left_x+1,yCount) ? yCount : ((yCount>upper_left_y)?upper_left_y:(upper_left_y+1));
  961. add_result_node(upper_left_x+1, yLoc, &max_size_result_node_ptr, &parent_result_node_ptr, node_count);
  962. }
  963. break;
  964. case 6: if(((upper_left_x+1)!=xCount) || (upper_left_y!=yCount))
  965. add_result_node(upper_left_x+1, upper_left_y, &max_size_result_node_ptr, &parent_result_node_ptr, node_count);
  966. break;
  967. case 7:
  968. if(upper_left_y != yCount)
  969. {
  970. xLoc = can_move_to(xCount,upper_left_y) ? xCount : ((xCount>upper_left_x)?upper_left_x:(upper_left_x+1));
  971. add_result_node(xLoc, upper_left_y, &max_size_result_node_ptr, &parent_result_node_ptr, node_count);
  972. }
  973. break;
  974. case 8: if((upper_left_x!=xCount) || (upper_left_y!=yCount))
  975. add_result_node(upper_left_x, upper_left_y, &max_size_result_node_ptr, &parent_result_node_ptr, node_count);
  976. break;
  977. default:
  978. err_now("error in processing the end node");
  979. break;
  980. }
  981. nodePtr = nodePtr->parent_node; // next 2x2 node
  982. //preNodeCount = node_count;
  983. err_when(node_count+nodePtr->node_g+2 > nodeAllocated);
  984. //--------------------------------------------------
  985. // get the actual path, process from the second node
  986. //--------------------------------------------------
  987. //int yieldCount = 0;
  988. while( (parentNode=nodePtr->parent_node) != NULL )
  989. {
  990. upper_left_x = nodePtr->node_x<<1;
  991. upper_left_y = nodePtr->node_y<<1;
  992. get_real_result_node(node_count, nodePtr->enter_direction,(childNodePtr->enter_direction+3)%8+1,
  993. nodePtr->node_type, upper_left_x, upper_left_y);
  994. childNodePtr = nodePtr;
  995. nodePtr = parentNode;
  996. err_when(node_count+nodePtr->node_g+2 > nodeAllocated);
  997. //yieldCount++;
  998. //if(yieldCount%30==0)
  999. // sys_yield();
  1000. }
  1001. //sys_yield(); // update cursor position
  1002. //----------------------------------------------------
  1003. // process the starting node
  1004. // nodePtr points at the starting node now
  1005. //----------------------------------------------------
  1006. if(abs(parent_result_node_ptr->node_x-real_sour_x)>1 || abs(parent_result_node_ptr->node_y-real_sour_y)>1)
  1007. { // passing through two points
  1008. upper_left_x = nodePtr->node_x<<1;
  1009. upper_left_y = nodePtr->node_y<<1;
  1010. switch(childNodePtr->enter_direction)
  1011. {
  1012. case 1:
  1013. max_size_result_node_ptr->node_x = upper_left_x+1;
  1014. if((can_move_to(upper_left_x+1, real_sour_y)&&(real_sour_y==upper_left_y)) ||
  1015. (!can_move_to(upper_left_x+1, real_sour_y)&&(real_sour_y>upper_left_y)))
  1016. max_size_result_node_ptr->node_y = upper_left_y;
  1017. else
  1018. max_size_result_node_ptr->node_y = (upper_left_y+1);
  1019. break;
  1020. case 2:
  1021. max_size_result_node_ptr->node_x = upper_left_x+1;
  1022. max_size_result_node_ptr->node_y = upper_left_y;
  1023. break;
  1024. case 3:
  1025. max_size_result_node_ptr->node_y = upper_left_y;
  1026. if((can_move_to(real_sour_x, upper_left_y)&&(real_sour_x==upper_left_x)) ||
  1027. (!can_move_to(real_sour_x, upper_left_y)&&(real_sour_x>upper_left_x)))
  1028. max_size_result_node_ptr->node_x = upper_left_x;
  1029. else
  1030. max_size_result_node_ptr->node_x = upper_left_x+1;
  1031. break;
  1032. case 4:
  1033. max_size_result_node_ptr->node_x = upper_left_x;
  1034. max_size_result_node_ptr->node_y = upper_left_y;
  1035. break;
  1036. case 5:
  1037. max_size_result_node_ptr->node_x = upper_left_x;
  1038. if((can_move_to(upper_left_x, real_sour_y)&&(real_sour_y==upper_left_y)) ||
  1039. (!can_move_to(upper_left_x, real_sour_y)&&(real_sour_y>upper_left_y)))
  1040. max_size_result_node_ptr->node_y = upper_left_y;
  1041. else
  1042. max_size_result_node_ptr->node_y = upper_left_y+1;
  1043. break;
  1044. case 6:
  1045. max_size_result_node_ptr->node_x = upper_left_x;
  1046. max_size_result_node_ptr->node_y = upper_left_y+1;
  1047. break;
  1048. case 7:
  1049. max_size_result_node_ptr->node_y = upper_left_y+1;
  1050. if((can_move_to(real_sour_x, upper_left_y+1)&&(real_sour_x==upper_left_x)) ||
  1051. (!can_move_to(real_sour_x, upper_left_y+1)&&(real_sour_x>upper_left_x)))
  1052. max_size_result_node_ptr->node_x = upper_left_x;
  1053. else
  1054. max_size_result_node_ptr->node_x = upper_left_x+1;
  1055. break;
  1056. case 8:
  1057. max_size_result_node_ptr->node_x = upper_left_x+1;
  1058. max_size_result_node_ptr->node_y = upper_left_y+1;
  1059. break;
  1060. default:
  1061. err_now("error in processing the start node");
  1062. break;
  1063. }
  1064. err_when((max_size_result_node_ptr->node_x==real_sour_x) && (max_size_result_node_ptr->node_y==real_sour_y));
  1065. parent_result_node_ptr++;
  1066. max_size_result_node_ptr++;
  1067. node_count++;
  1068. }
  1069. max_size_result_node_ptr->node_x = real_sour_x;
  1070. max_size_result_node_ptr->node_y = real_sour_y;
  1071. node_count++;
  1072. err_when(nodePtr->node_g || node_count>nodeAllocated);
  1073. debug_check_path(maxSizeResultNodeArray, node_count); //*** debug only
  1074. ResultNode* result_node_pointer;
  1075. maxSizeResultNodeArray = smooth_the_path(maxSizeResultNodeArray, resultNodeCount);
  1076. //sys_yield(); // update cursor position
  1077. debug_check_path(maxSizeResultNodeArray, resultNodeCount); //*** debug only
  1078. //-------------------------------------------------------------------//
  1079. // After the above process, here we will have a link of rationalize
  1080. // nodes. Retrieve them in the backwards order
  1081. //-------------------------------------------------------------------//
  1082. ResultNode *resultNodeArray = (ResultNode*) mem_add( sizeof(ResultNode) * resultNodeCount );
  1083. ResultNode *resultNodePtr = resultNodeArray+resultNodeCount-1;
  1084. int processCount = 1;
  1085. ResultNode *preNodePtr = maxSizeResultNodeArray;
  1086. *resultNodePtr = *preNodePtr;
  1087. resultNodePtr--;
  1088. result_node_pointer = maxSizeResultNodeArray+1;
  1089. err_when(pathDist!=0);
  1090. int xDist, yDist;
  1091. //yieldCount = 0;
  1092. while(processCount++ < resultNodeCount)
  1093. {
  1094. err_when(result_node_pointer->node_x<0 || result_node_pointer->node_x>=MAX_WORLD_X_LOC ||
  1095. result_node_pointer->node_y<0 || result_node_pointer->node_y>=MAX_WORLD_Y_LOC);
  1096. *resultNodePtr = *result_node_pointer;
  1097. resultNodePtr--;
  1098. xDist = abs(result_node_pointer->node_x-preNodePtr->node_x);
  1099. yDist = abs(result_node_pointer->node_y-preNodePtr->node_y);
  1100. err_when((!xDist && !yDist) || (xDist && yDist && xDist!=yDist));
  1101. pathDist += (xDist) ? xDist : yDist;
  1102. preNodePtr++;
  1103. result_node_pointer++;
  1104. //yieldCount++;
  1105. //if(yieldCount%35==0)
  1106. // sys_yield();
  1107. }
  1108. err_when(nodeAllocated<node_count);
  1109. mem_del(maxSizeResultNodeArray);
  1110. //======================================================================//
  1111. #ifdef DEBUG
  1112. if(search_sub_mode==SEARCH_SUB_MODE_PASSABLE && resultNodeCount>1)
  1113. {
  1114. err_when(mobile_type!=UNIT_LAND);
  1115. debug_check_sub_mode(resultNodeArray, resultNodeCount);
  1116. }
  1117. #endif
  1118. //======================================================================//
  1119. return resultNodeArray;
  1120. }
  1121. //------ End of function SeekPath::get_result ---------//
  1122. //---- Begin of function SeekPath::get_real_result_node ---------//
  1123. //
  1124. // called by get_result to extract the point in a 2x2 node that is
  1125. // used in the shortest path
  1126. //
  1127. // <int&> count - a reference var for counting number of node in
  1128. // max_size_result_node_ptr
  1129. //
  1130. void SeekPath::get_real_result_node( int &count, short enterDirection, short exitDirection,
  1131. short nodeType, short xCoord, short yCoord)
  1132. {
  1133. short ma, mb, mc, md; // | a b | four elements of a 2x2 matrix
  1134. // | c d | these values are either 0 or 1
  1135. short mTmp; // used in swapping
  1136. short atEdge; // at_edge = 1 if exitDirection is at the edge, otherwise 0 for corner
  1137. short rotateAngle; // rotate angle clockwisely = its value*90 degree, value ranges from 0 to 3
  1138. short furtherCheck; // indicate further checking is needed in finding a path in the node
  1139. short rotatedEnterDirection; // reference enter direction after rotation
  1140. ma = nodeType&0x1;
  1141. mb = (nodeType&0x2)>>1;
  1142. mc = (nodeType&0x4)>>2;
  1143. md = (nodeType&0x8)>>3;
  1144. err_when((ma+(mb<<1)+(mc<<2)+(md<<3)) != nodeType);
  1145. atEdge = exitDirection%2;
  1146. rotateAngle = short((exitDirection-1)/2);
  1147. furtherCheck = 0; // may be used only if enterDirection and exitDirection are opposite to each other
  1148. int exitArrowLeft = 0;
  1149. int exitArrowRight = 0;
  1150. int enterArrowLeft = 0;
  1151. int enterArrowRight = 0;
  1152. if(atEdge) // exit at the edge
  1153. {
  1154. //---------------------------------------------------------------------//
  1155. // -------
  1156. // exitArrowRight |1 |2 |
  1157. // <--------|-------|
  1158. // exitArrowLeft |3 |4 |
  1159. // -------
  1160. // There are 2 possible choice for the previous node to select. One is
  1161. // the point left of 1, and the other is the point left of 3. Since there
  1162. // are four possible edge exiting cases, it call be represented by rotated
  1163. // the above figure by 90 degree each.
  1164. //
  1165. // if the point left of 1 is chosen, exitArrowRight = 1
  1166. // if the point left of 3 is chosen, exitArrowLeft = 1
  1167. // the flag exitArrowLeft and exitArrowRight is used to generate a better
  1168. // result path shape.
  1169. //---------------------------------------------------------------------//
  1170. switch(exitDirection)
  1171. {
  1172. case 1: if(parent_result_node_ptr->node_y%2)
  1173. exitArrowLeft = 1;
  1174. else
  1175. exitArrowRight = 1;
  1176. break;
  1177. case 3: if(parent_result_node_ptr->node_x%2)
  1178. exitArrowLeft = 1;
  1179. else
  1180. exitArrowRight = 1;
  1181. break;
  1182. case 5: if(parent_result_node_ptr->node_y%2)
  1183. exitArrowRight = 1;
  1184. else
  1185. exitArrowLeft = 1;
  1186. break;
  1187. case 7: if(parent_result_node_ptr->node_x%2)
  1188. exitArrowRight = 1;
  1189. else
  1190. exitArrowLeft = 1;
  1191. break;
  1192. default: err_here();
  1193. break;
  1194. }
  1195. }
  1196. else // exit at edge
  1197. {
  1198. if(enterDirection%2) // enter at the edge
  1199. {
  1200. //---------------------------------------------------------------------//
  1201. // -------
  1202. // enterArrowLeft |1 |2 |
  1203. // -------->|-------|
  1204. // enterArrowRight|3 |4 |
  1205. // -------
  1206. // There are 2 possible choice for the next node to select. One is
  1207. // the point left of 1, and the other is the point left of 3. Since there
  1208. // are four possible edge entering cases, it call be represented by rotated
  1209. // the above figure by 90 degree each time.
  1210. //
  1211. // if the point left of 1 is chosen, enterArrowLeft = 1
  1212. // if the point left of 3 is chosen, enterArrowRight = 1
  1213. // the flag enterArrowLeft and enterArrowRight is used to generate a better
  1214. // result path shape.
  1215. //---------------------------------------------------------------------//
  1216. switch(enterDirection)
  1217. {
  1218. case 1: if(can_move_to(xCoord-1, yCoord))
  1219. enterArrowLeft = 1;
  1220. if(can_move_to(xCoord-1, yCoord+1))
  1221. enterArrowRight = 1;
  1222. break;
  1223. case 3: if(can_move_to(xCoord, yCoord+2))
  1224. enterArrowLeft = 1;
  1225. if(can_move_to(xCoord+1, yCoord+2))
  1226. enterArrowRight = 1;
  1227. break;
  1228. case 5: if(can_move_to(xCoord+2, yCoord+1))
  1229. enterArrowLeft = 1;
  1230. if(can_move_to(xCoord+2, yCoord))
  1231. enterArrowRight = 1;
  1232. break;
  1233. case 7: if(can_move_to(xCoord+1, yCoord-1))
  1234. enterArrowLeft = 1;
  1235. if(can_move_to(xCoord, yCoord-1))
  1236. enterArrowRight = 1;
  1237. break;
  1238. default: err_here();
  1239. break;
  1240. }
  1241. }
  1242. }
  1243. //----------------------------------------------------------------
  1244. // perform rotation such that the exit direction is either 1 or 2
  1245. //----------------------------------------------------------------
  1246. switch(exitDirection)
  1247. { case 1: case 2:
  1248. break;
  1249. case 3: case 4: // rotate clockwise 90 degree
  1250. //(((mTmp = mb), mb = ma), ma = mc), mc = md;
  1251. mTmp = mb;
  1252. mb = ma;
  1253. ma = mc;
  1254. mc = md;
  1255. md = mTmp;
  1256. break;
  1257. case 5: case 6: // rotate clockwise 180 degree
  1258. mTmp = md;
  1259. md = ma;
  1260. ma = mTmp;
  1261. mTmp = mb;
  1262. mb = mc;
  1263. mc = mTmp;
  1264. break;
  1265. case 7: case 8: // rotate clockwise 270 degree
  1266. mTmp = ma;
  1267. ma = mb;
  1268. mb = md;
  1269. md = mc;
  1270. mc = mTmp;
  1271. break;
  1272. default:
  1273. err_now("exitDirection error");
  1274. break;
  1275. }
  1276. rotatedEnterDirection = (enterDirection-(rotateAngle<<1)+7)%8+1; // store angle rotated for reverse rotation later
  1277. err_when(rotatedEnterDirection>8 || rotatedEnterDirection <1);
  1278. //-----------------------------------------
  1279. // set the value of the matrix element to
  1280. // 1 for the possible answer, the rest is 0
  1281. //-----------------------------------------
  1282. if(atEdge) // the case for the exit direction at 1
  1283. { //------------------- at edge ------------------------//
  1284. switch(rotatedEnterDirection)
  1285. {
  1286. case 1:
  1287. err_now("unexpected case at edge");
  1288. break;
  1289. case 2:
  1290. err_when(!mc);
  1291. mc = 1; // must be
  1292. ma = mb = md = 0;
  1293. break;
  1294. case 3:
  1295. // there are two possible paths
  1296. if(mc) // check for the perfered path
  1297. ma = mb = md = 0;
  1298. else
  1299. {
  1300. err_when((!ma) || (!md));
  1301. mb = 0;
  1302. }
  1303. // ma, md should be 1
  1304. break;
  1305. case 4:
  1306. err_when(!md); // md should be 1
  1307. mb = 0;
  1308. err_when((!mc) && (!ma));
  1309. if(exitArrowLeft)
  1310. ma = 1-mc; // either one is used, prefer mc
  1311. else // should be exitArrowRight
  1312. mc = 1-ma; // either one is used, prefer ma
  1313. break;
  1314. case 5:
  1315. if(ma&&mb)
  1316. { // one path (bar state) exists
  1317. if(mc&&md)
  1318. furtherCheck = 1;// both paths exist
  1319. else
  1320. mc = md = 0; // choose ma, mb
  1321. }
  1322. else if(mc&&md)
  1323. ma = mb = 0; // choose mc, md
  1324. else
  1325. err_when(((!ma)&&(!mc)) && ((!mb)&&(!md)));
  1326. // else, only one path exists, do nothing
  1327. break;
  1328. case 6: // similar to case 4
  1329. err_when(!mb); // mb should be 1
  1330. md = 0;
  1331. err_when((!ma)&&(!mc));
  1332. if(exitArrowLeft)
  1333. ma = 1-mc; // either one is used, prefer mc
  1334. else // should be exitArrowRight
  1335. mc = 1-ma; // either one is used, prefer ma
  1336. break;
  1337. case 7: // similar to case 3
  1338. if(ma)
  1339. mb = mc = md = 0;
  1340. else
  1341. {
  1342. err_when((!mb)||(!mc));
  1343. md = 0; // mb, mc should be 1
  1344. }
  1345. break;
  1346. case 8:
  1347. err_when(!ma);
  1348. ma = 1; // must be
  1349. mb = mc = md = 0;
  1350. break;
  1351. default:
  1352. err_now("at edge error");
  1353. break;
  1354. }
  1355. }
  1356. else
  1357. { //---------------------------- at corner-------------------------//
  1358. // the case for the exit direction at 2
  1359. switch(rotatedEnterDirection)
  1360. {
  1361. case 1: case 3:
  1362. err_when(!mc);
  1363. mc = 1; // must be
  1364. ma = mb = md = 0;
  1365. break;
  1366. case 2:
  1367. err_now("unexpected case at corner");
  1368. break;
  1369. case 4:
  1370. err_when((!mc)||(!md));
  1371. mc = md = 1; // must be
  1372. ma = mb = 0;
  1373. break;
  1374. case 5:
  1375. err_when(!mc);
  1376. mc = 1; // must be
  1377. ma = 0;
  1378. err_when((!mb)&&(!md));
  1379. if(!enterArrowLeft) // the enter arrow left location canot be walked
  1380. md = 1-mb; // either one is used, prefer mb
  1381. else
  1382. mb = 1-md; // either one is used, prefer md
  1383. break;
  1384. case 6:
  1385. err_when((!mb)||(!mc));
  1386. mb = mc = 1;
  1387. ma = md = 0;
  1388. break;
  1389. case 7:
  1390. err_when(!mc);
  1391. mc = 1; // must be
  1392. md = 0;
  1393. err_when((!ma)&&(!mb));
  1394. if(!enterArrowRight)
  1395. ma = 1-mb; // either one is used, prefer mb
  1396. else
  1397. mb = 1-ma; // either one is used, prefer ma
  1398. break;
  1399. case 8:
  1400. err_when((!ma)||(!mc));
  1401. ma = mc = 1; // must be
  1402. mb = md = 0;
  1403. break;
  1404. default:
  1405. err_now("at corner error");
  1406. break;
  1407. }
  1408. }
  1409. //--------------------------- reverse rotation ----------------------------//
  1410. switch(exitDirection)
  1411. { case 1: case 2:
  1412. break;
  1413. case 3: case 4: // rotate clockwise 270 degree
  1414. mTmp = ma;
  1415. ma = mb;
  1416. mb = md;
  1417. md = mc;
  1418. mc = mTmp;
  1419. break;
  1420. case 5: case 6: // rotate clockwise 180 degree
  1421. mTmp = md;
  1422. md = ma;
  1423. ma = mTmp;
  1424. mTmp = mb;
  1425. mb = mc;
  1426. mc = mTmp;
  1427. break;
  1428. case 7: case 8: // rotate clockwise 90 degree
  1429. mTmp = mb;
  1430. mb = ma;
  1431. ma = mc;
  1432. mc = md;
  1433. md = mTmp;
  1434. break;
  1435. default:
  1436. err_now("exitDirection error");
  1437. break;
  1438. }
  1439. //------------------- get the answer ----------------------//
  1440. switch(exitDirection)
  1441. {
  1442. case 1:
  1443. if(!furtherCheck)
  1444. {
  1445. add_result_node(xCoord, yCoord+1-ma, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1446. err_when(mb && md);
  1447. if(mb||md) // at most one is 1
  1448. add_result_node(xCoord+1, yCoord+1-mb, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1449. }
  1450. else
  1451. {
  1452. if(parent_result_node_ptr->node_y == yCoord)
  1453. { // use upper path
  1454. add_result_node(xCoord, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1455. add_result_node(xCoord+1, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1456. }
  1457. else
  1458. { // use lower path
  1459. add_result_node(xCoord, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1460. add_result_node(xCoord+1, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1461. }
  1462. }
  1463. break;
  1464. case 2:
  1465. err_when(!mc);
  1466. if(mc)
  1467. add_result_node(xCoord, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1468. // else, error
  1469. err_when(ma+mb+md>1); //(ma&&mb) || (ma&&md) || (mb&&md))
  1470. if(ma||mb||md) // at most one is 1
  1471. add_result_node(xCoord+1-ma, yCoord+md, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1472. break;
  1473. case 3:
  1474. if(!furtherCheck)
  1475. {
  1476. add_result_node(xCoord+1-mc, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1477. err_when(ma&&mb);
  1478. if(ma||mb) // at most one is 1
  1479. add_result_node(xCoord+1-ma, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1480. }
  1481. else
  1482. {
  1483. if(parent_result_node_ptr->node_x == xCoord)
  1484. { // use left path
  1485. add_result_node(xCoord, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1486. add_result_node(xCoord, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1487. }
  1488. else
  1489. { // use right path
  1490. add_result_node(xCoord+1, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1491. add_result_node(xCoord+1, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1492. }
  1493. }
  1494. break;
  1495. case 4:
  1496. err_when(!md);
  1497. if(md)
  1498. add_result_node(xCoord+1, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1499. // else, error
  1500. err_when(ma+mb+mc>1); //(ma&&mb) || (ma&&mc) || (mb&&mc))
  1501. if(ma||mb||mc) // at most one is 1
  1502. add_result_node(xCoord+mb, yCoord+mc, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1503. break;
  1504. case 5:
  1505. if(!furtherCheck)
  1506. {
  1507. add_result_node(xCoord+1, yCoord+1-mb, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1508. err_when(ma&&mc);
  1509. if(ma||mc) // at most one is 1
  1510. add_result_node(xCoord, yCoord+1-ma, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1511. }
  1512. else
  1513. {
  1514. if(parent_result_node_ptr->node_y == yCoord)
  1515. { // use upper path
  1516. add_result_node(xCoord+1, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1517. add_result_node(xCoord, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1518. }
  1519. else
  1520. { // use lower path
  1521. add_result_node(xCoord+1, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1522. add_result_node(xCoord, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1523. }
  1524. }
  1525. break;
  1526. case 6:
  1527. err_when(!mb);
  1528. if(mb)
  1529. add_result_node(xCoord+1, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1530. // else, error
  1531. err_when(ma+mc+md>1);//(ma&&mc) || (ma&&md) || (mc&&md))
  1532. if(ma||mc||md) // at most one is 1
  1533. add_result_node(xCoord+md, yCoord+1-ma, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1534. break;
  1535. case 7:
  1536. if(!furtherCheck)
  1537. {
  1538. add_result_node(xCoord+1-ma, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1539. err_when(mc&&md);
  1540. if(mc||md) // at most one is 1
  1541. add_result_node(xCoord+1-mc, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1542. }
  1543. else
  1544. {
  1545. if(parent_result_node_ptr->node_x == xCoord)
  1546. { // use left path
  1547. add_result_node(xCoord, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1548. add_result_node(xCoord, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1549. }
  1550. else
  1551. { // use right path
  1552. add_result_node(xCoord+1, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1553. add_result_node(xCoord+1, yCoord+1, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1554. }
  1555. }
  1556. break;
  1557. case 8:
  1558. err_when(!ma);
  1559. if(ma)
  1560. add_result_node(xCoord, yCoord, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1561. // else, error
  1562. err_when(mb+mc+md>1);//(mb&&mc) || (mb&&md) || (mc&&md))
  1563. if(mb||mc||md) // at most one is 1
  1564. add_result_node(xCoord+1-mc, yCoord+1-mb, &max_size_result_node_ptr, &parent_result_node_ptr, count);
  1565. break;
  1566. default:
  1567. err_now("error in extracting answer");
  1568. break;
  1569. }
  1570. }
  1571. //------ End of function SeekPath::get_real_result_node ---------//
  1572. //-------- Begin of function SeekPath::smooth_the_path ---------//
  1573. ResultNode* SeekPath::smooth_the_path(ResultNode* nodeArray, int& nodeCount)
  1574. {
  1575. //------------------------------------------------------------//
  1576. // smoothing the path and get the turning point
  1577. //------------------------------------------------------------//
  1578. //---------- declare variables ---------------//
  1579. int i, j, checkedNodeCount, curNodeCount;
  1580. short vectorX, vectorY, newVectorX, newVectorY, newVectorX2, newVectorY2;
  1581. short changed, caseNum, processed;
  1582. ResultNode *curUsefulNodePtr = nodeArray+1;
  1583. ResultNode *preCheckingNodePtr = nodeArray;
  1584. ResultNode *ptr1;
  1585. ResultNode *ptr2;
  1586. ResultNode *ptr3;
  1587. ResultNode *ptr4;
  1588. parent_result_node_ptr = nodeArray;
  1589. max_size_result_node_ptr = nodeArray+1;
  1590. //--------------------------------------------------//
  1591. // to remove the duplicated or useless node near the
  1592. // destination node
  1593. //
  1594. // note: preCheckingNodePtr points at the previous node of
  1595. // max_size_result_node_ptr pointed at
  1596. //--------------------------------------------------//
  1597. i = 1;
  1598. while(abs(parent_result_node_ptr->node_x-max_size_result_node_ptr->node_x)<=1 &&
  1599. abs(parent_result_node_ptr->node_y-max_size_result_node_ptr->node_y)<=1)
  1600. {
  1601. max_size_result_node_ptr++;
  1602. preCheckingNodePtr++;
  1603. i++;
  1604. if(i>=node_count)
  1605. break;
  1606. //if(i%40==0)
  1607. // sys_yield();
  1608. }
  1609. max_size_result_node_ptr = preCheckingNodePtr;
  1610. //--------------------------------------------------//
  1611. // to smooth the path
  1612. //--------------------------------------------------//
  1613. changed = 1;
  1614. checkedNodeCount = 1;
  1615. curNodeCount = node_count-i+2;
  1616. ptr1 = parent_result_node_ptr;
  1617. ptr2 = max_size_result_node_ptr;
  1618. ptr3 = max_size_result_node_ptr+1;
  1619. #ifdef DEBUG
  1620. int countEnterWhile = 0;
  1621. #endif
  1622. //int yieldCount = 0;
  1623. while(changed && curNodeCount>=3)
  1624. {
  1625. #ifdef DEBUG
  1626. countEnterWhile++;
  1627. #endif
  1628. //yieldCount++;
  1629. //if(yieldCount%30==0)
  1630. // sys_yield();
  1631. vectorX = ptr2->node_x - ptr1->node_x;
  1632. vectorY = ptr2->node_y - ptr1->node_y;
  1633. changed = 0;
  1634. curUsefulNodePtr = nodeArray+1;
  1635. checkedNodeCount = 1;
  1636. for(j=1; j<curNodeCount-1; j++)
  1637. {
  1638. processed = 0;
  1639. newVectorX= ptr3->node_x - ptr2->node_x;
  1640. newVectorY= ptr3->node_y - ptr2->node_y;
  1641. //------ turning at 90 degree clockwise / anti-clockwise --------//
  1642. if((vectorX==0 && vectorY!=0 && newVectorX!=0 && newVectorY==0) || // + case
  1643. (vectorX!=0 && vectorY==0 && newVectorX==0 && newVectorY!=0))
  1644. {
  1645. ptr2++;
  1646. err_when(abs(ptr1->node_x-ptr2->node_x)>1 || abs(ptr1->node_y-ptr2->node_y)>1);
  1647. ptr3++;
  1648. err_when(j<curNodeCount-2 && ptr3->node_x && ptr3->node_y &&
  1649. (abs(ptr3->node_x-ptr2->node_x)>1 || abs(ptr3->node_y-ptr2->node_y)>1));
  1650. vectorX = ptr2->node_x - ptr1->node_x;
  1651. vectorY = ptr2->node_y - ptr1->node_y;
  1652. processed = 1;
  1653. continue;
  1654. }
  1655. if((vectorX!=0 && vectorY!=0 && newVectorX!=0 && newVectorY!=0) && // x case
  1656. ((vectorX==newVectorX && vectorY==-newVectorY) || (vectorX==-newVectorX && vectorY==newVectorY)) &&
  1657. can_move_to((ptr1->node_x+ptr3->node_x)/2, (ptr1->node_y+ptr3->node_y)/2))
  1658. {
  1659. err_when(ptr1->node_x==ptr3->node_x && ptr1->node_y==ptr3->node_y);
  1660. ptr2->node_x = (ptr1->node_x+ptr3->node_x)/2;
  1661. ptr2->node_y = (ptr1->node_y+ptr3->node_y)/2;
  1662. *curUsefulNodePtr = *ptr2;
  1663. err_when(abs(ptr1->node_x-curUsefulNodePtr->node_x)>1 || abs(ptr1->node_y-curUsefulNodePtr->node_y)>1);
  1664. curUsefulNodePtr++;
  1665. checkedNodeCount++;
  1666. ptr1 = ptr2;
  1667. ptr2 = ptr3;
  1668. err_when(abs(ptr1->node_x-ptr2->node_x)>1 || abs(ptr1->node_y-ptr2->node_y)>1);
  1669. ptr3++;
  1670. err_when(j<curNodeCount-2 && ptr3->node_x && ptr3->node_y &&
  1671. (abs(ptr3->node_x-ptr2->node_x)>1 || abs(ptr3->node_y-ptr2->node_y)>1));
  1672. vectorX = ptr2->node_x - ptr1->node_x;
  1673. vectorY = ptr2->node_y - ptr1->node_y;
  1674. processed = 1;
  1675. continue;
  1676. }
  1677. if(j<curNodeCount-2) // check for the 4-point case
  1678. {
  1679. ptr4 = ptr3+1;
  1680. newVectorX2 = ptr4->node_x - ptr3->node_x;
  1681. newVectorY2 = ptr4->node_y - ptr3->node_y;
  1682. caseNum = 0;
  1683. if(vectorX==-1 && vectorY==0 && newVectorX==-1 && newVectorX2==0)
  1684. {
  1685. if(newVectorY==1 && newVectorY2==1 && can_move_to(ptr2->node_x, ptr3->node_y))
  1686. caseNum = 1; //-------- (0,0), (-1,0), (-2,1), (-2,2) --------//
  1687. else if(newVectorY==-1 && newVectorY2==-1 && can_move_to(ptr2->node_x, ptr3->node_y))
  1688. caseNum = 5; //-------- (0,0), (-1,0), (-2,-1), (-2,-2) --------//
  1689. }
  1690. else if(vectorX==1 && vectorY==0 && newVectorX==1 && newVectorX2==0)
  1691. {
  1692. if(newVectorY==1 && newVectorY2==1 && can_move_to(ptr2->node_x, ptr3->node_y))
  1693. caseNum = 3; //-------- (0,0), (1,0), (2,1), (2,2) --------//
  1694. else if(newVectorY==-1 && newVectorY2==-1 && can_move_to(ptr2->node_x, ptr3->node_y))
  1695. caseNum = 7; //-------- (0,0), (1,0), (2,-1), (2,-2) --------//
  1696. }
  1697. else if(vectorX==0 && vectorY==-1 && newVectorY==-1 && newVectorY2==0)
  1698. {
  1699. if(newVectorX==1 && newVectorX2==1 && can_move_to(ptr3->node_x, ptr2->node_y))
  1700. caseNum = 2; //-------- (0,0), (0,-1), (1,-2), (2,-2) --------//
  1701. else if(newVectorX==-1 && newVectorX2==-1 && can_move_to(ptr3->node_x, ptr2->node_y))
  1702. caseNum = 4; //-------- (0,0), (0,-1), (-1,-2), (-2,-2) --------//
  1703. }
  1704. else if(vectorX==0 && vectorY==1 && newVectorY==1 && newVectorY2==0)
  1705. {
  1706. if(newVectorX==1 && newVectorX2==1 && can_move_to(ptr3->node_x, ptr2->node_y))
  1707. caseNum = 6; //-------- (0,0), (0,1), (1,2), (2,2) --------//
  1708. else if(newVectorX==-1 && newVectorX2==-1 && can_move_to(ptr3->node_x, ptr2->node_y))
  1709. caseNum = 8; //-------- (0,0), (0,1), (-1,2), (-2,2) --------//
  1710. }
  1711. if(caseNum)
  1712. {
  1713. if(caseNum%2) // case 1, 3, 5 7
  1714. ptr2->node_y = ptr3->node_y;
  1715. else // case 2, 4, 6, 8
  1716. ptr2->node_x = ptr3->node_x;
  1717. ptr3++; //ptr3 = ptr4;
  1718. *curUsefulNodePtr = *ptr2;
  1719. err_when(abs(ptr1->node_x-curUsefulNodePtr->node_x)>1 || abs(ptr1->node_y-curUsefulNodePtr->node_y)>1);
  1720. curUsefulNodePtr++;
  1721. checkedNodeCount++;
  1722. ptr1 = ptr2;
  1723. ptr2 = ptr3;
  1724. err_when(abs(ptr1->node_x-ptr2->node_x)>1 || abs(ptr1->node_y-ptr2->node_y)>1);
  1725. ptr3++;
  1726. err_when(j<curNodeCount-2 && ptr3->node_x && ptr3->node_y &&
  1727. (abs(ptr3->node_x-ptr2->node_x)>1 || abs(ptr3->node_y-ptr2->node_y)>1));
  1728. j++;
  1729. vectorX = ptr2->node_x - ptr1->node_x;
  1730. vectorY = ptr2->node_y - ptr1->node_y;
  1731. processed = 1;
  1732. continue;
  1733. }
  1734. }
  1735. //------ none of the above case ---------//
  1736. if(!processed)
  1737. {
  1738. *curUsefulNodePtr = *ptr2;
  1739. err_when(abs(ptr1->node_x-curUsefulNodePtr->node_x)>1 || abs(ptr1->node_y-curUsefulNodePtr->node_y)>1);
  1740. curUsefulNodePtr++;
  1741. checkedNodeCount++;
  1742. }
  1743. else
  1744. changed = 1;
  1745. ptr1 = ptr2;
  1746. ptr2 = ptr3;
  1747. err_when(abs(ptr1->node_x-ptr2->node_x)>1 || abs(ptr1->node_y-ptr2->node_y)>1);
  1748. ptr3++;
  1749. err_when(j<curNodeCount-2 && ptr3->node_x && ptr3->node_y &&
  1750. (abs(ptr3->node_x-ptr2->node_x)>1 || abs(ptr3->node_y-ptr2->node_y)>1));
  1751. vectorX = ptr2->node_x - ptr1->node_x;
  1752. vectorY = ptr2->node_y - ptr1->node_y;
  1753. }
  1754. //---- end checking and then reset parameters----//
  1755. if(processed)
  1756. changed = 1;
  1757. *curUsefulNodePtr = *ptr2;
  1758. err_when(abs(ptr1->node_x-curUsefulNodePtr->node_x)>1 || abs(ptr1->node_y-curUsefulNodePtr->node_y)>1);
  1759. curUsefulNodePtr++;
  1760. checkedNodeCount++;
  1761. curNodeCount = checkedNodeCount;
  1762. checkedNodeCount = 1;
  1763. ptr1 = parent_result_node_ptr;
  1764. ptr2 = ptr1+1;
  1765. err_when(abs(ptr1->node_x-ptr2->node_x)>1 || abs(ptr1->node_y-ptr2->node_y)>1);
  1766. ptr3 = ptr2+1;
  1767. err_when(j<curNodeCount-2 && ptr3->node_x && ptr3->node_y &&
  1768. (abs(ptr3->node_x-ptr2->node_x)>1 || abs(ptr3->node_y-ptr2->node_y)>1));
  1769. debug_check_path(nodeArray, nodeCount); //*** debug only
  1770. }
  1771. node_count = curNodeCount;
  1772. //--------------------------------------------------//
  1773. // to remove the duplicated destination node
  1774. //--------------------------------------------------//
  1775. parent_result_node_ptr = nodeArray;
  1776. max_size_result_node_ptr = nodeArray+1;
  1777. ResultNode* result_node_pointer = max_size_result_node_ptr;
  1778. //----------------------------------
  1779. // get the turning point
  1780. //----------------------------------
  1781. vectorX = max_size_result_node_ptr->node_x - parent_result_node_ptr->node_x;
  1782. vectorY = max_size_result_node_ptr->node_y - parent_result_node_ptr->node_y;
  1783. for(i=1; i<node_count-1; i++)
  1784. {
  1785. parent_result_node_ptr = max_size_result_node_ptr; // don't use parent_result_node_ptr++, if the above code of removing duplication is used.
  1786. max_size_result_node_ptr++;
  1787. newVectorX=(max_size_result_node_ptr->node_x-parent_result_node_ptr->node_x);
  1788. newVectorY=(max_size_result_node_ptr->node_y-parent_result_node_ptr->node_y);
  1789. err_when(newVectorY!=0 && newVectorX!=0 && abs(newVectorX)!=abs(newVectorY));
  1790. //------ turning to another direction at this point ------//
  1791. if(vectorX!=newVectorX || vectorY!=newVectorY)
  1792. {
  1793. err_when(abs(newVectorX)>1 || abs(newVectorY)>1);// || (newVectorX==0 && newVectorY==0))
  1794. if(newVectorX!=0 || newVectorY!=0)
  1795. {
  1796. *result_node_pointer = *parent_result_node_ptr;
  1797. result_node_pointer++;
  1798. nodeCount++;
  1799. vectorX = newVectorX;
  1800. vectorY = newVectorY;
  1801. }
  1802. }
  1803. //if(i%30==0)
  1804. // sys_yield();
  1805. }
  1806. result_node_pointer->node_x = real_sour_x;
  1807. result_node_pointer->node_y = real_sour_y;
  1808. result_node_pointer++;
  1809. nodeCount++;
  1810. return nodeArray;
  1811. }
  1812. //------- End of function SeekPath::smooth_the_path -------//
  1813. //-------- Begin of function Node::generate_successors ---------//
  1814. // Note: In fact, the cost of the starting node should be 0 or 1
  1815. // and the parentEnterDirection is 0. Now the cost in this
  1816. // case is set to 2. The difference can be ignored as it will
  1817. // not affect the search after generating the second level
  1818. // children.
  1819. // The advantage to ignore this case is that less comparsion
  1820. // effort in checking parentEnterDirection.
  1821. //
  1822. short Node::generate_successors(short parentEnterDirection, short realSourX, short realSourY)
  1823. {
  1824. int hasLeft = node_x > cur_border_x1;
  1825. int hasRight = node_x < cur_border_x2;
  1826. int hasUp = node_y > cur_border_y1;
  1827. int hasDown = node_y < cur_border_y2;
  1828. int upperLeftX,upperLeftY;
  1829. short cost;
  1830. upperLeftX = node_x<<1;
  1831. upperLeftY = node_y<<1;
  1832. //-------------------------------------------
  1833. // enter_direction = (exit_direction+3)%8+1
  1834. //-------------------------------------------
  1835. if( hasLeft )
  1836. {
  1837. //--------- Left, exit_direction=1 --------//
  1838. if ((node_type&0x05) && (can_move_to(upperLeftX-1,upperLeftY) || can_move_to(upperLeftX-1,upperLeftY+1)))
  1839. {
  1840. if(parentEnterDirection==2 || parentEnterDirection==8 ||
  1841. (node_type&0x1 && parentEnterDirection==7) || (node_type&0x4 && parentEnterDirection==3) ||
  1842. (!parentEnterDirection && realSourX == upperLeftX))
  1843. cost = 1;
  1844. else
  1845. cost = 2;
  1846. if(generate_succ(node_x-1,node_y,5,cost))
  1847. return 1;
  1848. }
  1849. if( hasUp )
  1850. {
  1851. //------- Upper-Left, exit_direction=8 ---------//
  1852. if ((node_type&0x1) && can_move_to(upperLeftX-1,upperLeftY-1))
  1853. {
  1854. if(parentEnterDirection==7 || parentEnterDirection==1 ||
  1855. (!parentEnterDirection && realSourX==upperLeftX && realSourY==upperLeftY))
  1856. cost = 1;
  1857. else cost = 2;
  1858. if(generate_succ(node_x-1,node_y-1,4,cost))
  1859. return 1;
  1860. }
  1861. }
  1862. if( hasDown )
  1863. {
  1864. //--------- Lower-Left, exit_direction=2 ----------//
  1865. if ((node_type&0x4) && can_move_to(upperLeftX-1,upperLeftY+2))
  1866. { if(parentEnterDirection==1 || parentEnterDirection==3 ||
  1867. (!parentEnterDirection && realSourX==upperLeftX && realSourY==(upperLeftY+1)))
  1868. cost = 1;
  1869. else cost = 2;
  1870. if(generate_succ(node_x-1,node_y+1,6,cost))
  1871. return 1;
  1872. }
  1873. }
  1874. }
  1875. if( hasRight )
  1876. {
  1877. //----------- Right, exit_direction=5 -----------//
  1878. if ((node_type&0xA) && (can_move_to(upperLeftX+2,upperLeftY) || can_move_to(upperLeftX+2,upperLeftY+1)))
  1879. {
  1880. if(parentEnterDirection==4 || parentEnterDirection==6 ||
  1881. (node_type&0x02 && parentEnterDirection==7) || (node_type&0x08 && parentEnterDirection==3) ||
  1882. (!parentEnterDirection && realSourX==(upperLeftX+1)))
  1883. cost = 1;
  1884. else cost = 2;
  1885. if(generate_succ(node_x+1,node_y,1,cost))
  1886. return 1;
  1887. }
  1888. if( hasUp )
  1889. {
  1890. //-------- Upper-Right, exit_direction=6 ---------//
  1891. if ((node_type&0x2)&&can_move_to(upperLeftX+2,upperLeftY-1))
  1892. {
  1893. if(parentEnterDirection==5 || parentEnterDirection==7 ||
  1894. (!parentEnterDirection && realSourX==(upperLeftX+1) && realSourY==upperLeftY))
  1895. cost = 1;
  1896. else cost = 2;
  1897. if(generate_succ(node_x+1,node_y-1,2,cost))
  1898. return 1;
  1899. }
  1900. }
  1901. if( hasDown )
  1902. {
  1903. //--------- Lower-Right, exit_direction=4 ---------//
  1904. if ((node_type&0x8)&&can_move_to(upperLeftX+2,upperLeftY+2))
  1905. {
  1906. if(parentEnterDirection==3 || parentEnterDirection==5 ||
  1907. (!parentEnterDirection && realSourX==(upperLeftX+1) && realSourY==(upperLeftY+1)))
  1908. cost = 1;
  1909. else cost = 2;
  1910. if(generate_succ(node_x+1,node_y+1,8,cost))
  1911. return 1;
  1912. }
  1913. }
  1914. }
  1915. if( hasUp )
  1916. {
  1917. //---------- Upper, exit_direction=7 -----------//
  1918. if ((node_type&0x03) && (can_move_to(upperLeftX,upperLeftY-1) || can_move_to(upperLeftX+1,upperLeftY-1)))
  1919. {
  1920. if(parentEnterDirection==6 || parentEnterDirection==8 ||
  1921. (node_type&0x01 && parentEnterDirection==1) || (node_type&0x02 && parentEnterDirection==5) ||
  1922. (!parentEnterDirection && realSourY==upperLeftY))
  1923. cost = 1;
  1924. else cost = 2;
  1925. if(generate_succ(node_x,node_y-1,3,cost))
  1926. return 1;
  1927. }
  1928. }
  1929. if( hasDown )
  1930. {
  1931. //---------- Lower, exit_direction=3 -----------//
  1932. if ((node_type&0xC) && ( can_move_to(upperLeftX,upperLeftY+2) || can_move_to(upperLeftX+1,upperLeftY+2) ) )
  1933. {
  1934. if(parentEnterDirection==2 || parentEnterDirection==4 ||
  1935. (node_type&0x4 && parentEnterDirection==1) || (node_type&0x8 && parentEnterDirection==5) ||
  1936. (!parentEnterDirection && realSourY==(upperLeftY+1)))
  1937. cost = 1;
  1938. else cost = 2;
  1939. if(generate_succ(node_x,node_y+1,7,cost))
  1940. return 1;
  1941. }
  1942. }
  1943. return 0;
  1944. }
  1945. //------- End of function Node::generate_successors -------//
  1946. //-------- Begin of function Node::generate_succ ---------//
  1947. short Node::generate_succ(short x, short y, short enter_direct,short cost)
  1948. {
  1949. //----- if it points back to this node's parent ----//
  1950. if( parent_node )
  1951. {
  1952. if( parent_node->node_x==x && parent_node->node_y==y )
  1953. return 0;
  1954. }
  1955. //----- if there is an existing node at the given position ----//
  1956. int upperLeftX, upperLeftY;
  1957. //int cost;
  1958. short c, g = node_g+cost; // g(Successor)=g(BestNode)+cost of getting from BestNode to Successor
  1959. short nodeRecno;
  1960. if( (nodeRecno=cur_node_matrix[y*MAX_WORLD_X_LOC/2+x]) > 0 &&
  1961. nodeRecno<max_node_num)
  1962. {
  1963. Node* oldNode = cur_node_array+nodeRecno-1;
  1964. //------ Add oldNode to the list of BestNode's child_noderen (or Successors).
  1965. for(c=0 ; c<MAX_CHILD_NODE && child_node[c] ; c++);
  1966. child_node[c]=oldNode;
  1967. //---- if our new g value is < oldNode's then reset oldNode's parent to point to BestNode
  1968. if(g < oldNode->node_g)
  1969. {
  1970. oldNode->parent_node = this;
  1971. oldNode->node_g = g;
  1972. oldNode->node_f = g+oldNode->node_h;
  1973. oldNode->enter_direction = (char)enter_direct;
  1974. //-------- if it's a closed node ---------//
  1975. if(oldNode->child_node[0] )
  1976. {
  1977. //-------------------------------------------------//
  1978. // Since we changed the g value of oldNode, we need
  1979. // to propagate this new value downwards, i.e.
  1980. // do a Depth-First traversal of the tree!
  1981. //-------------------------------------------------//
  1982. oldNode->propagate_down();
  1983. //sys_yield();
  1984. }
  1985. }
  1986. }
  1987. else //------------ add a new node -----------//
  1988. {
  1989. Node* succNode = cur_node_array + cur_seek_path->node_count++;
  1990. memset(succNode, 0, sizeof(Node));
  1991. succNode->parent_node = this;
  1992. succNode->node_g = g;
  1993. succNode->node_h = (x-cur_dest_x)*(x-cur_dest_x)+(y-cur_dest_y)*(y-cur_dest_y); // should do sqrt(), but since we don't really
  1994. succNode->node_f = g+succNode->node_h; // care about the distance but just which branch looks
  1995. succNode->node_x = x; // better this should suffice. Anyayz it's faster.
  1996. succNode->node_y = y;
  1997. succNode->enter_direction = (char)enter_direct;
  1998. upperLeftX = x<<1;
  1999. upperLeftY = y<<1;
  2000. succNode->node_type = can_move_to(upperLeftX,upperLeftY)+(can_move_to(upperLeftX+1,upperLeftY)<<1)+
  2001. (can_move_to(upperLeftX,upperLeftY+1)<<2)+(can_move_to(upperLeftX+1,upperLeftY+1)<<3);
  2002. if(search_mode==SEARCH_MODE_REUSE && nodeRecno>max_node_num) // path-reuse node found, but checking of can_walk(final_dest_?) is requested
  2003. {
  2004. int destIndex = nodeRecno - max_node_num;
  2005. switch(destIndex)
  2006. {
  2007. case 1: final_dest_x = x<<1;
  2008. final_dest_y = y<<1;
  2009. break;
  2010. case 2: final_dest_x = (x<<1) + 1;
  2011. final_dest_y = y<<1;
  2012. break;
  2013. case 3: final_dest_x = x<<1;
  2014. final_dest_y = (y<<1) + 1;
  2015. break;
  2016. case 4: final_dest_x = (x<<1) + 1;
  2017. final_dest_y = (y<<1) + 1;
  2018. break;
  2019. default: err_here();
  2020. break;
  2021. }
  2022. if(can_move_to(final_dest_x, final_dest_y)) // can_walk the connection point, accept this case
  2023. {
  2024. reuse_result_node_ptr = succNode;
  2025. return 1;
  2026. } // else continue until reuse node is found and connection point can be walked
  2027. }
  2028. cur_node_matrix[y*MAX_WORLD_X_LOC/2+x] = cur_seek_path->node_count;
  2029. cur_seek_path->open_node_list.insert_node(succNode);
  2030. for(c=0 ; c<MAX_CHILD_NODE && child_node[c] ; c++); // Add oldNode to the list of BestNode's child_noderen (or succNodes).
  2031. child_node[c]=succNode;
  2032. }
  2033. return 0;
  2034. }
  2035. //------- End of function Node::generate_succ -------//
  2036. //-------- Begin of function Node::propagate_down ---------//
  2037. void Node::propagate_down()
  2038. {
  2039. Node *childNode, *fatherNode;
  2040. int c, g=node_g; // alias.
  2041. short cost;
  2042. char xShift, yShift; // the x, y difference between parent and child nodes
  2043. char childEnterDirection;
  2044. char exitDirection;
  2045. char testResult;
  2046. for(c=0;c<8;c++)
  2047. {
  2048. if ((childNode=child_node[c])==NULL) // create alias for faster access.
  2049. break;
  2050. cost = 2; // in fact, may be 1 or 2
  2051. if (g+cost <= childNode->node_g) // first checking
  2052. {
  2053. xShift = childNode->node_x-node_x;
  2054. yShift = childNode->node_y-node_y;
  2055. err_when(abs(xShift)>1 || abs(yShift)>1);
  2056. //---------- calulate the new enter direction ------------//
  2057. switch(yShift)
  2058. {
  2059. case -1:
  2060. childEnterDirection = char(3-xShift);
  2061. break;
  2062. case 0:
  2063. childEnterDirection = char(3-(xShift<<1));
  2064. break;
  2065. case 1:
  2066. childEnterDirection = char(7+xShift);
  2067. break;
  2068. }
  2069. exitDirection = (childEnterDirection+3)%8+1;
  2070. if(enter_direction > exitDirection)
  2071. {
  2072. if((enter_direction==8 && (exitDirection==1 || exitDirection==2)) ||
  2073. (enter_direction==7 && exitDirection==1))
  2074. testResult = exitDirection + 8 - enter_direction;
  2075. else
  2076. testResult = enter_direction - exitDirection;
  2077. }
  2078. else
  2079. {
  2080. if((exitDirection==8 && (enter_direction==1 || enter_direction==2)) ||
  2081. (exitDirection==7 && enter_direction==1))
  2082. testResult = enter_direction + 8 - exitDirection;
  2083. else
  2084. testResult = exitDirection - enter_direction;
  2085. }
  2086. if(exitDirection%2 && testResult==2)
  2087. {
  2088. int upperLeftX = 2*node_x;
  2089. int upperLeftY = 2*node_y;
  2090. // this case only occurs at the edge
  2091. switch(childEnterDirection)
  2092. {
  2093. case 1: if((exitDirection==3 && can_move_to(upperLeftX, upperLeftY+1)) ||
  2094. (exitDirection==7 && can_move_to(upperLeftX, upperLeftY)))
  2095. cost = 1;
  2096. break;
  2097. case 3: if((exitDirection==1 && can_move_to(upperLeftX, upperLeftY+1)) ||
  2098. (exitDirection==5 && can_move_to(upperLeftX+1, upperLeftY+1)))
  2099. cost = 1;
  2100. break;
  2101. case 5: if((exitDirection==3 && can_move_to(upperLeftX+1, upperLeftY+1)) ||
  2102. (exitDirection==7 && can_move_to(upperLeftX+1, upperLeftY)))
  2103. cost = 1;
  2104. break;
  2105. case 7: if((exitDirection==1 && can_move_to(upperLeftX, upperLeftY)) ||
  2106. (exitDirection==5 && can_move_to(upperLeftX+1, upperLeftY)))
  2107. cost = 1;
  2108. break;
  2109. default: err_here();
  2110. break;
  2111. }
  2112. }
  2113. else
  2114. cost = 2 - (testResult <= 1); //if(testResult <= 1) cost = 1;
  2115. err_when(cost>2 || cost<1);
  2116. if(g+cost < childNode->node_g) // second checking, mainly for cost = 2;
  2117. {
  2118. childNode->node_g = g+cost;
  2119. childNode->node_f = childNode->node_g+childNode->node_h;
  2120. childNode->parent_node = this;// reset parent to new path.
  2121. childNode->enter_direction = childEnterDirection;
  2122. stack_push(childNode); // Now the childNode's branch need to be checked out. Remember the new cost must be propagated down.
  2123. }
  2124. }
  2125. }
  2126. while(cur_stack_pos>0)
  2127. {
  2128. fatherNode=stack_pop();
  2129. g = fatherNode->node_g;
  2130. for(c=0;c<8;c++)
  2131. {
  2132. if((childNode=fatherNode->child_node[c])==NULL) // we may stop the propagation 2 ways: either
  2133. break;
  2134. cost = 2; // in fact, may be 1 or 2
  2135. if(g+cost <= childNode->node_g) // first checking
  2136. // there are no children, or that the g value of the child is equal or better than the cost we're propagating
  2137. {
  2138. xShift = childNode->node_x-fatherNode->node_x;
  2139. yShift = childNode->node_y-fatherNode->node_y;
  2140. err_when(abs(xShift)>1 || abs(yShift)>1);
  2141. //---------- calulate the new enter direction ------------//
  2142. switch(yShift)
  2143. {
  2144. case -1:
  2145. childEnterDirection = char(3-xShift);
  2146. break;
  2147. case 0:
  2148. childEnterDirection = char(3-(xShift<<1));
  2149. break;
  2150. case 1:
  2151. childEnterDirection = char(7+xShift);
  2152. break;
  2153. }
  2154. exitDirection = (childEnterDirection+3)%8+1;
  2155. char fatherEnterDirection = fatherNode->enter_direction;
  2156. if(fatherEnterDirection > exitDirection)
  2157. {
  2158. if((fatherEnterDirection==8 && (exitDirection==1 || exitDirection==2)) ||
  2159. (fatherEnterDirection==7 && exitDirection==1))
  2160. testResult = exitDirection + 8 - fatherEnterDirection;
  2161. else
  2162. testResult = fatherEnterDirection - exitDirection;
  2163. }
  2164. else
  2165. {
  2166. if((exitDirection==8 && (fatherEnterDirection==1 || fatherEnterDirection==2)) ||
  2167. (exitDirection==7 && fatherEnterDirection==1))
  2168. testResult = fatherEnterDirection + 8 - exitDirection;
  2169. else
  2170. testResult = exitDirection - fatherEnterDirection;
  2171. }
  2172. if(exitDirection%2 && testResult==2)
  2173. {
  2174. int upperLeftX = 2*fatherNode->node_x;
  2175. int upperLeftY = 2*fatherNode->node_y;
  2176. // this case only occurs at the edge
  2177. switch(childEnterDirection)
  2178. {
  2179. case 1: if((exitDirection==3 && can_move_to(upperLeftX, upperLeftY+1)) ||
  2180. (exitDirection==7 && can_move_to(upperLeftX, upperLeftY)))
  2181. cost = 1;
  2182. break;
  2183. case 3: if((exitDirection==1 && can_move_to(upperLeftX, upperLeftY+1)) ||
  2184. (exitDirection==5 && can_move_to(upperLeftX+1, upperLeftY+1)))
  2185. cost = 1;
  2186. break;
  2187. case 5: if((exitDirection==3 && can_move_to(upperLeftX+1, upperLeftY+1)) ||
  2188. (exitDirection==7 && can_move_to(upperLeftX+1, upperLeftY)))
  2189. cost = 1;
  2190. break;
  2191. case 7: if((exitDirection==1 && can_move_to(upperLeftX, upperLeftY)) ||
  2192. (exitDirection==5 && can_move_to(upperLeftX+1, upperLeftY)))
  2193. cost = 1;
  2194. break;
  2195. default: err_here();
  2196. break;
  2197. }
  2198. }
  2199. else
  2200. cost = 2 - (testResult <= 1); //if(testResult <= 1) cost = 1;
  2201. err_when(cost>2 || cost<1);
  2202. if(g+cost < childNode->node_g) // second checking, mainly for cost = 2;
  2203. {
  2204. childNode->node_g = g+cost;
  2205. childNode->node_f = childNode->node_g+childNode->node_h;
  2206. childNode->parent_node = fatherNode;
  2207. childNode->enter_direction = childEnterDirection;
  2208. stack_push(childNode);
  2209. }
  2210. }
  2211. }
  2212. }
  2213. }
  2214. //------- End of function Node::propagate_down -------//
  2215. //-------- Begin of static function stack_push ---------//
  2216. static void stack_push(Node *nodePtr)
  2217. {
  2218. stack_array[cur_stack_pos++] = nodePtr;
  2219. err_when( cur_stack_pos >= MAX_STACK_NUM );
  2220. }
  2221. //--------- End of static function stack_push ---------//
  2222. //-------- Begin of static function stack_pop ---------//
  2223. static Node* stack_pop()
  2224. {
  2225. return stack_array[--cur_stack_pos];
  2226. }
  2227. //--------- End of static function stack_pop ---------//
  2228. //-********************************************************************************-//
  2229. // for UNIT_SEA and UNIT_AIR, the scale used is double that of UNIT_LAND
  2230. //-********************************************************************************-//
  2231. //-------- Begin of static function SeekPath::seek2 ---------//
  2232. int SeekPath::seek2(int sx, int sy, int dx, int dy, short miscNo, short numOfPath, int maxTries)
  2233. {
  2234. err_when(mobile_type==UNIT_LAND);
  2235. //---------------------------------------------------------------------------//
  2236. // target_recno, building_id is not implemented for this version of seek2()
  2237. //---------------------------------------------------------------------------//
  2238. target_recno = building_id = 0;
  2239. building_x1 = building_y1 = building_x2 = building_y2 = -1;
  2240. switch(search_mode)
  2241. {
  2242. case SEARCH_MODE_TO_FIRM:
  2243. building_id = miscNo;
  2244. building_x1 = dx; // upper left corner location
  2245. building_y1 = dy;
  2246. search_firm_info = firm_res[building_id];
  2247. building_x2 = dx+search_firm_info->loc_width-1;
  2248. building_y2 = dy+search_firm_info->loc_height-1;
  2249. break;
  2250. case SEARCH_MODE_TO_TOWN:
  2251. building_id = miscNo;
  2252. building_x1 = dx; // upper left corner location
  2253. building_y1 = dy;
  2254. if(miscNo != -1)
  2255. {
  2256. Location* buildPtr = world.get_loc(dx, dy);
  2257. Town* targetTown = town_array[buildPtr->town_recno()];
  2258. building_x2 = targetTown->loc_x2;
  2259. building_y2 = targetTown->loc_y2;
  2260. }
  2261. else // searching to settle. Detail explained in function set_move_to_surround()
  2262. {
  2263. building_x2 = building_x1+STD_TOWN_LOC_WIDTH-1;
  2264. building_y2 = building_y1+STD_TOWN_LOC_HEIGHT-1;
  2265. }
  2266. break;
  2267. case SEARCH_MODE_ATTACK_UNIT_BY_RANGE:
  2268. case SEARCH_MODE_ATTACK_WALL_BY_RANGE:
  2269. err_when(attack_range==0);
  2270. building_id = miscNo;
  2271. building_x1 = max(dx-attack_range, 0);
  2272. building_y1 = max(dy-attack_range, 0);
  2273. building_x2 = min(dx+attack_range, MAX_WORLD_X_LOC-1);
  2274. building_y2 = min(dy+attack_range, MAX_WORLD_Y_LOC-1);
  2275. break;
  2276. case SEARCH_MODE_ATTACK_FIRM_BY_RANGE:
  2277. building_id = miscNo;
  2278. building_x1 = max(dx-attack_range, 0);
  2279. building_y1 = max(dy-attack_range, 0);
  2280. search_firm_info = firm_res[building_id];
  2281. building_x2 = min(dx+search_firm_info->loc_width-1+attack_range, MAX_WORLD_X_LOC-1);
  2282. building_y2 = min(dy+search_firm_info->loc_height-1+attack_range, MAX_WORLD_Y_LOC-1);
  2283. break;
  2284. case SEARCH_MODE_ATTACK_TOWN_BY_RANGE:
  2285. building_id = miscNo;
  2286. building_x1 = max(dx-attack_range, 0);
  2287. building_y1 = max(dy-attack_range, 0);
  2288. building_x2 = min(dx+STD_TOWN_LOC_WIDTH-1+attack_range, MAX_WORLD_X_LOC-1);
  2289. building_y2 = min(dy+STD_TOWN_LOC_HEIGHT-1+attack_range, MAX_WORLD_Y_LOC-1);
  2290. break;
  2291. case SEARCH_MODE_TO_LAND_FOR_SHIP:
  2292. region_id = (UCHAR)miscNo;
  2293. break;
  2294. }
  2295. //------------------------------------------------------------------------------//
  2296. // set start location and destination location
  2297. //------------------------------------------------------------------------------//
  2298. real_sour_x = sx;
  2299. real_sour_y = sy;
  2300. //final_dest_x = real_dest_x = dx;
  2301. //final_dest_y = real_dest_y = dy;
  2302. real_dest_x = dx;
  2303. real_dest_y = dy;
  2304. int xShift, yShift, area;
  2305. short pathNum;
  2306. switch(search_mode)
  2307. {
  2308. case SEARCH_MODE_TO_FIRM:
  2309. case SEARCH_MODE_TO_TOWN:
  2310. final_dest_x = (building_x1+building_x2)/2;
  2311. final_dest_y = (building_y1+building_y2)/2;
  2312. //---------------------------------------------------------------------------------//
  2313. // for group assign, the final destination is adjusted by the value of numOfPath
  2314. //---------------------------------------------------------------------------------//
  2315. if(search_mode==SEARCH_MODE_TO_TOWN)
  2316. area = STD_TOWN_LOC_WIDTH*STD_TOWN_LOC_HEIGHT;
  2317. else // search_mode == SEARCH_MODE_TO_FIRM
  2318. area = search_firm_info->loc_width*search_firm_info->loc_height;
  2319. pathNum = (numOfPath>area) ? (numOfPath-1)%area + 1 : numOfPath;
  2320. if(search_mode==SEARCH_MODE_TO_TOWN)
  2321. m.cal_move_around_a_point(pathNum, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, xShift, yShift);
  2322. else
  2323. m.cal_move_around_a_point(pathNum, search_firm_info->loc_width, search_firm_info->loc_height, xShift, yShift);
  2324. final_dest_x += xShift;
  2325. final_dest_y += yShift;
  2326. if(final_dest_x<0)
  2327. final_dest_x = 0;
  2328. else if(final_dest_x>=MAX_WORLD_X_LOC)
  2329. final_dest_x = MAX_WORLD_X_LOC-1;
  2330. if(final_dest_y<0)
  2331. final_dest_y = 0;
  2332. else if(final_dest_y>=MAX_WORLD_Y_LOC)
  2333. final_dest_y = MAX_WORLD_Y_LOC-1;
  2334. break;
  2335. case SEARCH_MODE_ATTACK_UNIT_BY_RANGE:
  2336. case SEARCH_MODE_ATTACK_FIRM_BY_RANGE:
  2337. case SEARCH_MODE_ATTACK_TOWN_BY_RANGE:
  2338. case SEARCH_MODE_ATTACK_WALL_BY_RANGE:
  2339. final_dest_x = (building_x1+building_x2)/2;
  2340. final_dest_y = (building_y1+building_y2)/2;
  2341. break;
  2342. default:
  2343. final_dest_x = real_dest_x;
  2344. final_dest_y = real_dest_y;
  2345. break;
  2346. }
  2347. //--------------------------------------------------------------//
  2348. // change to 2x2 node format
  2349. //--------------------------------------------------------------//
  2350. int sourceX = short(sx/2); // the upper left corner is used
  2351. int sourceY = short(sy/2);
  2352. dest_x = short(final_dest_x/2);
  2353. dest_y = short(final_dest_y/2);
  2354. //-----------------------------------------//
  2355. // reset node_matrix
  2356. //-----------------------------------------//
  2357. if(search_mode!=SEARCH_MODE_REUSE)
  2358. {
  2359. max_node_num = 0xFFFF;
  2360. memset(node_matrix, 0, sizeof(short)*MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC/4);
  2361. }
  2362. else
  2363. {
  2364. max_node_num = max_node;
  2365. memcpy(node_matrix, reuse_node_matrix_ptr, sizeof(short)*MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC/4);
  2366. }
  2367. //--------- create the first node ---------//
  2368. node_count = 0;
  2369. result_node_ptr = NULL;
  2370. Node *nodePtr = node_array + node_count++;
  2371. memset(nodePtr, 0, sizeof(Node));
  2372. //-------- store the upper left coordinate of the node ----------//
  2373. int destUpperLeftX = dest_x<<1;
  2374. int destUpperLeftY = dest_y<<1;
  2375. is_dest_blocked = !can_move_to(destUpperLeftX, destUpperLeftY);
  2376. // whether the destination is blocked, if so, only search till the destination's neighbor locations
  2377. //### begin alex 25/9 ###//
  2378. //------------ do some adjustment for ship to beach if destination is blocked ----------------//
  2379. if(is_dest_blocked && search_mode==SEARCH_MODE_TO_LAND_FOR_SHIP &&
  2380. (final_dest_x%2 || final_dest_y%2)) // either is odd location
  2381. {
  2382. if(final_dest_x%2 && final_dest_y%2==0)
  2383. {
  2384. if(destUpperLeftX+2<MAX_WORLD_X_LOC-1 && can_move_to(destUpperLeftX+2, destUpperLeftY))
  2385. {
  2386. is_dest_blocked = 0;
  2387. destUpperLeftX += 2;
  2388. dest_x++;
  2389. }
  2390. }
  2391. else if(final_dest_x%2==0 && final_dest_y%2)
  2392. {
  2393. if(destUpperLeftY+2<MAX_WORLD_Y_LOC-1 && can_move_to(destUpperLeftX, destUpperLeftY+2))
  2394. {
  2395. is_dest_blocked = 0;
  2396. destUpperLeftY += 2;
  2397. dest_y++;
  2398. }
  2399. }
  2400. else
  2401. {
  2402. if(destUpperLeftX+2<MAX_WORLD_X_LOC-1 && can_move_to(destUpperLeftX+2, destUpperLeftY))
  2403. {
  2404. is_dest_blocked = 0;
  2405. destUpperLeftX += 2;
  2406. dest_x++;
  2407. }
  2408. else if(destUpperLeftX+2<MAX_WORLD_X_LOC-1 && destUpperLeftY+2<MAX_WORLD_Y_LOC-1 &&
  2409. can_move_to(destUpperLeftX+2, destUpperLeftY+2))
  2410. {
  2411. is_dest_blocked = 0;
  2412. destUpperLeftX += 2;
  2413. destUpperLeftY += 2;
  2414. dest_x++;
  2415. dest_y++;
  2416. }
  2417. else if(destUpperLeftY+2<MAX_WORLD_Y_LOC-1 && can_move_to(destUpperLeftX, destUpperLeftY+2))
  2418. {
  2419. is_dest_blocked = 0;
  2420. destUpperLeftY += 2;
  2421. dest_y++;
  2422. }
  2423. }
  2424. }
  2425. //#### end alex 25/9 ####//
  2426. nodePtr->node_g = 0;
  2427. nodePtr->node_h = (sourceX-dest_x)*(sourceX-dest_x)+(sourceY-dest_y)*(sourceY-dest_y); // should really use sqrt().
  2428. nodePtr->node_f = nodePtr->node_g + nodePtr->node_h;
  2429. nodePtr->node_x = sourceX;
  2430. nodePtr->node_y = sourceY;
  2431. open_node_list.insert_node(nodePtr); // make Open List point to first node
  2432. //--- if the destination is the current postion or next to it & the dest is occupied ---//
  2433. if(sourceX==dest_x && sourceY==dest_y)
  2434. {
  2435. path_status = PATH_FOUND;
  2436. result_node_ptr = NULL;
  2437. return path_status;
  2438. }
  2439. //------------ seek now ------------------//
  2440. int maxNode = (!maxTries) ? max_node : maxTries;
  2441. return continue_seek2(maxNode, 1); // 1-first seek session of the current seek order
  2442. }
  2443. //--------- End of static function SeekPath::seek2 ---------//
  2444. //-------- Begin of static function SeekPath::continue_seek2 ---------//
  2445. int SeekPath::continue_seek2(int maxTries, char firstSeek)
  2446. {
  2447. if( path_status != PATH_SEEKING )
  2448. return path_status;
  2449. //------- aliasing class member vars for fast access ------//
  2450. cur_seek_path = this;
  2451. cur_dest_x = dest_x;
  2452. cur_dest_y = dest_y;
  2453. cur_node_matrix = node_matrix;
  2454. cur_node_array = node_array;
  2455. cur_border_x1 = border_x1;
  2456. cur_border_y1 = border_y1;
  2457. cur_border_x2 = border_x2;
  2458. cur_border_y2 = border_y2;
  2459. //------ seek the path using the A star algorithm -----//
  2460. int maxNode = (total_node_avail<maxTries) ? total_node_avail : maxTries;
  2461. maxNode -= MAX_CHILD_NODE; // generate_successors() can generate a max of MAX_CHILD_NODE new nodes per call
  2462. Node *bestNodePtr;
  2463. int i;
  2464. for(i=0; i<maxNode; i++)
  2465. {
  2466. bestNodePtr = return_best_node();
  2467. //if(i%20==0)
  2468. // sys_yield(); // update cursor position
  2469. //---- even if the path is impossible, get the closest path ----//
  2470. if( !bestNodePtr )
  2471. {
  2472. path_status = PATH_IMPOSSIBLE;
  2473. break;
  2474. }
  2475. //----- exceed the object's max's node limitation, return the closest path ----//
  2476. if( node_count >= maxNode )
  2477. //if( i >= maxNode )
  2478. {
  2479. path_status = PATH_NODE_USED_UP;
  2480. break;
  2481. }
  2482. //------------------------------------------//
  2483. // If the path is found OR
  2484. //
  2485. // If the destination is blocked,
  2486. // consider it done when we are next to it.
  2487. //------------------------------------------//
  2488. if( (bestNodePtr->node_x==dest_x && bestNodePtr->node_y==dest_y) ||
  2489. ( is_dest_blocked && abs(bestNodePtr->node_x-dest_x)<=1 && abs(bestNodePtr->node_y-dest_y)<=1 ) )
  2490. {
  2491. path_status = PATH_FOUND;
  2492. result_node_ptr = bestNodePtr;
  2493. break;
  2494. }
  2495. //--------- generate successors -------//
  2496. if(bestNodePtr->generate_successors2(real_sour_x, real_sour_y))
  2497. {
  2498. path_status = PATH_REUSE_FOUND;
  2499. result_node_ptr = reuse_result_node_ptr;
  2500. break;
  2501. }
  2502. }
  2503. err_when( cur_stack_pos!=0 ); // it should be zero all the times, all pushes should have been poped
  2504. current_search_node_used = i+1; // store the number of nodes used in this searching
  2505. return path_status;
  2506. }
  2507. //--------- End of static function SeekPath::continue_seek2 ---------//
  2508. //---- Begin of function SeekPath::get_result2 ---------//
  2509. ResultNode* SeekPath::get_result2(int& resultNodeCount, short& pathDist)
  2510. {
  2511. resultNodeCount = pathDist = 0;
  2512. if(total_node_avail<=0)
  2513. return NULL;
  2514. total_node_avail -= current_search_node_used;
  2515. short useClosestNode = 0; // indicate whether closest node is returned instead of the actual node
  2516. if(!result_node_ptr || !result_node_ptr->parent_node) // if PATH_IMPOSSIBLE or PATH_NODE_USED_UP, result_node_ptr is NULL, we need to call get_closest_node() to get the closest node.
  2517. {
  2518. if(path_status==PATH_FOUND)
  2519. return NULL; // the current location is already the destination
  2520. err_when(path_status==PATH_FOUND);
  2521. result_node_ptr = return_closest_node();
  2522. useClosestNode = 1;
  2523. if(!result_node_ptr)
  2524. return NULL;
  2525. }
  2526. //--------------------------------------------------//
  2527. // Trace backwards to the starting node, and rationalize
  2528. // nodes (i.e. group nodes of the same direction into
  2529. // single nodes.)
  2530. //--------------------------------------------------//
  2531. Node* nodePtr = result_node_ptr; // the node current being processed
  2532. Node* baseNodePtr = result_node_ptr; // the first end node for connecting the other end node for the path in that direction.
  2533. Node* parentNode = nodePtr->parent_node; // the parent node of nodePtr
  2534. if(!parentNode)
  2535. return NULL;
  2536. resultNodeCount=1; // the current node
  2537. err_when( !parentNode ); // the desination node must have a parent node
  2538. //--- if the following nodes are going at the same direction, rationalize them ---//
  2539. short vectorX = parentNode->node_x - nodePtr->node_x; // the vector at which the sprite is going
  2540. short vectorY = parentNode->node_y - nodePtr->node_y;
  2541. short newVectorX, newVectorY;
  2542. nodePtr = parentNode;
  2543. //sys_yield(); // update cursor position
  2544. err_when(vectorX && vectorY && abs(vectorX)!=abs(vectorY));
  2545. while((parentNode=nodePtr->parent_node) != NULL)
  2546. {
  2547. err_when(abs(vectorX)>1 || abs(vectorY)>1);
  2548. //------ turning to another direction at this point ------//
  2549. newVectorX = parentNode->node_x-nodePtr->node_x;
  2550. newVectorY = parentNode->node_y-nodePtr->node_y;
  2551. if(vectorX != newVectorX || vectorY != newVectorY)
  2552. {
  2553. err_when(abs(newVectorX)>1 || abs(newVectorY)>1);
  2554. err_when(newVectorX && newVectorY && abs(newVectorX)!=abs(newVectorY));
  2555. err_when(baseNodePtr->node_x-nodePtr->node_x && baseNodePtr->node_y-nodePtr->node_y &&
  2556. abs(baseNodePtr->node_x-nodePtr->node_x)!=abs(baseNodePtr->node_y-nodePtr->node_y));
  2557. baseNodePtr->parent_node = nodePtr; // skip the in-between ones which are in the same direction
  2558. baseNodePtr = nodePtr; // prepare for the next line.
  2559. resultNodeCount++;
  2560. vectorX = newVectorX;
  2561. vectorY = newVectorY;
  2562. }
  2563. nodePtr = parentNode;
  2564. }
  2565. baseNodePtr->parent_node = nodePtr; // finish off the last one
  2566. resultNodeCount++;
  2567. //----------------------------------------------------------------------------//
  2568. // After the above process, here we will have a link of rationalize nodes.
  2569. // Retrieve them in the backwards order
  2570. //----------------------------------------------------------------------------//
  2571. //sys_yield(); // update cursor position
  2572. ResultNode *resultNodeArray = (ResultNode*) mem_add( sizeof(ResultNode) * resultNodeCount );
  2573. ResultNode *resultNodePtr = resultNodeArray+resultNodeCount-1;
  2574. int processCount = 1;
  2575. Node *preNodePtr = result_node_ptr;
  2576. resultNodePtr->node_x = preNodePtr->node_x;
  2577. resultNodePtr->node_y = preNodePtr->node_y;
  2578. resultNodePtr--;
  2579. Node *curNodePtr = result_node_ptr->parent_node;
  2580. err_when(pathDist!=0);
  2581. int xDist, yDist;
  2582. while(processCount++ < resultNodeCount)
  2583. {
  2584. err_when(curNodePtr->node_x<0 || curNodePtr->node_x>=MAX_WORLD_X_LOC ||
  2585. curNodePtr->node_y<0 || curNodePtr->node_y>=MAX_WORLD_Y_LOC);
  2586. resultNodePtr->node_x = curNodePtr->node_x;
  2587. resultNodePtr->node_y = curNodePtr->node_y;
  2588. resultNodePtr--;
  2589. xDist = abs(curNodePtr->node_x-preNodePtr->node_x);
  2590. yDist = abs(curNodePtr->node_y-preNodePtr->node_y);
  2591. err_when((!xDist && !yDist) || (xDist && yDist && xDist!=yDist));
  2592. pathDist += (xDist) ? xDist : yDist;
  2593. preNodePtr = curNodePtr;
  2594. curNodePtr = curNodePtr->parent_node;
  2595. }
  2596. //sys_yield(); // update cursor position
  2597. //------------------------------------------------//
  2598. // multipy all the node by scale 2
  2599. //------------------------------------------------//
  2600. for(processCount=0, resultNodePtr=resultNodeArray; processCount<resultNodeCount; processCount++, resultNodePtr++)
  2601. {
  2602. resultNodePtr->node_x <<= 1;
  2603. resultNodePtr->node_y <<= 1;
  2604. err_when(resultNodePtr->node_x<0 || resultNodePtr->node_x>=MAX_WORLD_X_LOC ||
  2605. resultNodePtr->node_y<0 || resultNodePtr->node_y>=MAX_WORLD_Y_LOC);
  2606. }
  2607. pathDist <<= 1;
  2608. #ifdef DEBUG
  2609. //------------------------------------------------------------------------//
  2610. // used to debug for the path of UNIT_SEA
  2611. //------------------------------------------------------------------------//
  2612. if(search_mode==SEARCH_MODE_IN_A_GROUP || search_mode==SEARCH_MODE_REUSE || search_mode==SEARCH_MODE_A_UNIT_IN_GROUP)
  2613. if(mobile_type==UNIT_SEA && resultNodeCount>1 && search_mode!=SEARCH_MODE_TO_LAND_FOR_SHIP)
  2614. debug_check_sea_sailable(resultNodeArray, resultNodeCount);
  2615. #endif
  2616. return resultNodeArray;
  2617. }
  2618. //------- End of function SeekPath::get_result2 -------//
  2619. //-------- Begin of function Node::generate_successors2 ---------//
  2620. short Node::generate_successors2(short realSourX, short realSourY)
  2621. {
  2622. int hasLeft = node_x > cur_border_x1;
  2623. int hasRight = node_x < cur_border_x2;
  2624. int hasUp = node_y > cur_border_y1;
  2625. int hasDown = node_y < cur_border_y2;
  2626. int upperLeftX, upperLeftY;
  2627. short cost = 2;
  2628. upperLeftX = node_x<<1;
  2629. upperLeftY = node_y<<1;
  2630. if(hasLeft)
  2631. {
  2632. //--------- Left --------//
  2633. if(can_move_to(upperLeftX-2, upperLeftY) && can_move_to(upperLeftX-1, upperLeftY))
  2634. {
  2635. if(generate_succ2(node_x-1, node_y))
  2636. return 1;
  2637. }
  2638. //------- Upper-Left ---------//
  2639. if(hasUp)
  2640. {
  2641. if(can_move_to(upperLeftX-2, upperLeftY-2) && can_move_to(upperLeftX-1, upperLeftY-1)) // can pass through the tile
  2642. {
  2643. if(generate_succ2(node_x-1, node_y-1))
  2644. return 1;
  2645. }
  2646. }
  2647. //--------- Lower-Left ----------//
  2648. if(hasDown)
  2649. {
  2650. if(can_move_to(upperLeftX-2, upperLeftY+2) && can_move_to(upperLeftX-1, upperLeftY+1))
  2651. {
  2652. if(generate_succ2(node_x-1, node_y+1))
  2653. return 1;
  2654. }
  2655. }
  2656. }
  2657. if(hasRight)
  2658. {
  2659. //----------- Right -----------//
  2660. if(can_move_to(upperLeftX+2, upperLeftY) && can_move_to(upperLeftX+1, upperLeftY))
  2661. {
  2662. if(generate_succ2(node_x+1, node_y))
  2663. return 1;
  2664. }
  2665. //-------- Upper-Right ---------//
  2666. if(hasUp)
  2667. {
  2668. if(can_move_to(upperLeftX+2, upperLeftY-2) && can_move_to(upperLeftX+1, upperLeftY-1))
  2669. {
  2670. if(generate_succ2(node_x+1, node_y-1))
  2671. return 1;
  2672. }
  2673. }
  2674. //--------- Lower-Right ---------//
  2675. if(hasDown)
  2676. {
  2677. if(can_move_to(upperLeftX+2, upperLeftY+2) && can_move_to(upperLeftX+1, upperLeftY+1))
  2678. {
  2679. if(generate_succ2(node_x+1, node_y+1))
  2680. return 1;
  2681. }
  2682. }
  2683. }
  2684. //---------- Upper -----------//
  2685. if(hasUp)
  2686. {
  2687. if(can_move_to(upperLeftX, upperLeftY-2) && can_move_to(upperLeftX, upperLeftY-1))
  2688. {
  2689. if(generate_succ2(node_x, node_y-1))
  2690. return 1;
  2691. }
  2692. }
  2693. //---------- Lower -----------//
  2694. if(hasDown)
  2695. {
  2696. if(can_move_to(upperLeftX, upperLeftY+2) && can_move_to(upperLeftX, upperLeftY+1))
  2697. {
  2698. if(generate_succ2(node_x, node_y+1))
  2699. return 1;
  2700. }
  2701. }
  2702. return 0;
  2703. }
  2704. //------- End of function Node::generate_successors2 -------//
  2705. //-------- Begin of function Node::generate_succ2 ---------//
  2706. short Node::generate_succ2(short x, short y, short cost)
  2707. {
  2708. //----- if it points back to this node's parent ----//
  2709. if(parent_node)
  2710. {
  2711. if(parent_node->node_x==x && parent_node->node_y==y)
  2712. return 0;
  2713. }
  2714. //----- if there is an existing node at the given position ----//
  2715. //int upperLeftX, upperLeftY;
  2716. short c, g = node_g+1; // g(Successor)=g(BestNode)+cost of getting from BestNode to Successor
  2717. short nodeRecno;
  2718. if((nodeRecno=cur_node_matrix[y*MAX_WORLD_X_LOC/2+x]) > 0 && nodeRecno<max_node_num)
  2719. {
  2720. Node* oldNode = cur_node_array+nodeRecno-1;
  2721. //------ Add oldNode to the list of BestNode's child_noderen (or Successors).
  2722. for(c=0 ; c<MAX_CHILD_NODE && child_node[c] ; c++);
  2723. child_node[c]=oldNode;
  2724. //---- if our new g value is < oldNode's then reset oldNode's parent to point to BestNode
  2725. if(g < oldNode->node_g)
  2726. {
  2727. oldNode->parent_node = this;
  2728. oldNode->node_g = g;
  2729. oldNode->node_f = g+oldNode->node_h;
  2730. //-------- if it's a closed node ---------//
  2731. if(oldNode->child_node[0] )
  2732. {
  2733. //-------------------------------------------------//
  2734. // Since we changed the g value of oldNode, we need
  2735. // to propagate this new value downwards, i.e.
  2736. // do a Depth-First traversal of the tree!
  2737. //-------------------------------------------------//
  2738. oldNode->propagate_down();
  2739. //sys_yield();
  2740. }
  2741. }
  2742. }
  2743. else //------------ add a new node -----------//
  2744. {
  2745. Node* succNode = cur_node_array + cur_seek_path->node_count++;
  2746. memset(succNode, 0, sizeof(Node));
  2747. succNode->parent_node = this;
  2748. succNode->node_g = g;
  2749. succNode->node_h = (x-cur_dest_x)*(x-cur_dest_x)+(y-cur_dest_y)*(y-cur_dest_y); // should do sqrt(), but since we don't really
  2750. succNode->node_f = g+succNode->node_h; // care about the distance but just which branch looks
  2751. succNode->node_x = x; // better this should suffice. Anyayz it's faster.
  2752. succNode->node_y = y;
  2753. if(search_mode==SEARCH_MODE_REUSE && nodeRecno>max_node_num) // path-reuse node found, but checking of can_walk(final_dest_?) is requested
  2754. {
  2755. final_dest_x = x<<1;
  2756. final_dest_y = y<<1;
  2757. if(can_move_to(final_dest_x, final_dest_y)) // can_walk the connection point, accept this case
  2758. {
  2759. reuse_result_node_ptr = succNode;
  2760. return 1;
  2761. } // else continue until reuse node is found and connection point can be walked
  2762. }
  2763. cur_node_matrix[y*MAX_WORLD_X_LOC/2+x] = cur_seek_path->node_count;
  2764. cur_seek_path->open_node_list.insert_node(succNode);
  2765. for(c=0 ; c<MAX_CHILD_NODE && child_node[c] ; c++); // Add oldNode to the list of BestNode's child_noderen (or succNodes).
  2766. child_node[c]=succNode;
  2767. }
  2768. return 0;
  2769. }
  2770. //------- End of function Node::generate_succ2 -------//
  2771. //-------- Begin of function Node::propagate_down2 --------//
  2772. void Node::propagate_down2()
  2773. {
  2774. Node* childNode, *fatherNode;
  2775. int c, g=node_g; // alias.
  2776. int cost = 1;
  2777. #ifdef DEBUG
  2778. int middleXLoc, middleYLoc;
  2779. #endif
  2780. for(c=0;c<8;c++)
  2781. {
  2782. if((childNode=child_node[c])==NULL) // create alias for faster access.
  2783. break;
  2784. if(g+cost < childNode->node_g)
  2785. {
  2786. #ifdef DEBUG
  2787. middleXLoc = (node_x + childNode->node_x); // calculate real coordinate
  2788. middleYLoc = (node_y + childNode->node_y);
  2789. if(can_move_to(middleXLoc, middleYLoc))
  2790. #else
  2791. if(can_move_to(node_x+childNode->node_x, node_y+childNode->node_y))
  2792. #endif
  2793. {
  2794. childNode->node_g = g+cost;
  2795. childNode->node_f = childNode->node_g+childNode->node_h;
  2796. childNode->parent_node = this; // reset parent to new path.
  2797. stack_push(childNode); // Now the childNode's branch need to be
  2798. }
  2799. } // checked out. Remember the new cost must be propagated down.
  2800. }
  2801. while(cur_stack_pos>0)
  2802. {
  2803. fatherNode=stack_pop();
  2804. g = fatherNode->node_g;
  2805. for(c=0;c<8;c++)
  2806. {
  2807. if ((childNode=fatherNode->child_node[c])==NULL) // we may stop the propagation 2 ways: either
  2808. break;
  2809. if(g+cost < childNode->node_g) // there are no children, or that the g value of
  2810. { // the child is equal or better than the cost we're propagating
  2811. #ifdef DEBUG
  2812. middleXLoc = (node_x + childNode->node_x); // calculate real coordinate
  2813. middleYLoc = (node_y + childNode->node_y);
  2814. if(can_move_to(middleXLoc, middleYLoc))
  2815. #else
  2816. if(can_move_to(node_x+childNode->node_x, node_y+childNode->node_y))
  2817. #endif
  2818. {
  2819. childNode->node_g = g+cost;
  2820. childNode->node_f = childNode->node_g+childNode->node_h;
  2821. childNode->parent_node = fatherNode;
  2822. stack_push(childNode);
  2823. }
  2824. }
  2825. }
  2826. }
  2827. }
  2828. //------- End of function Node::propagate_down2 -------//