OUNITM.cpp 95 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025
  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 : OUNITM.CPP
  21. //Description : Object Unit movement
  22. //Owner : Alex
  23. #include <ALL.h>
  24. #include <OWORLD.h>
  25. #include <OF_HARB.h>
  26. #include <OGAME.h>
  27. #include <ONATION.h>
  28. #include <OU_MARI.h>
  29. #include <OSPATH.h>
  30. #include <OSPREUSE.h>
  31. #include <OSERES.h>
  32. #include <OLOG.h>
  33. #include <OEFFECT.h>
  34. #ifdef NO_DEBUG_UNIT
  35. #undef err_when
  36. #undef err_here
  37. #undef err_if
  38. #undef err_else
  39. #undef err_now
  40. #define err_when(cond)
  41. #define err_here()
  42. #define err_if(cond)
  43. #define err_else
  44. #define err_now(msg)
  45. #undef DEBUG
  46. #endif
  47. //-*********** simulate aat ************-//
  48. #ifdef DEBUG
  49. #include <OSYS.h>
  50. #endif
  51. //-*********** simulate aat ************-//
  52. //--- Define no. of pixels per direction move (N, NE, E, SE, S, SW, W, NW) ---//
  53. static short move_x_pixel_array[] = { 0, ZOOM_LOC_WIDTH, ZOOM_LOC_WIDTH, ZOOM_LOC_WIDTH, 0, -ZOOM_LOC_WIDTH, -ZOOM_LOC_WIDTH, -ZOOM_LOC_WIDTH };
  54. static short move_y_pixel_array[] = { -ZOOM_LOC_HEIGHT, -ZOOM_LOC_HEIGHT, 0, ZOOM_LOC_HEIGHT, ZOOM_LOC_HEIGHT, ZOOM_LOC_HEIGHT, 0, -ZOOM_LOC_HEIGHT };
  55. static short cycle_wait_unit_index;
  56. static short *cycle_wait_unit_array;
  57. static short cycle_wait_unit_array_def_size;
  58. static short cycle_wait_unit_array_multipler;
  59. static char move_action_call_flag=0; // avoid calling move_to_my_loc() if this function is called from move_to() chain
  60. //--------- Begin of function Unit::reset_action_para ---------//
  61. // reset action parameters when action is finished or cancelled
  62. // for action_mode
  63. //
  64. void Unit::reset_action_para()
  65. {
  66. action_mode = ACTION_STOP;
  67. action_x_loc = action_y_loc = -1;
  68. action_para = 0;
  69. }
  70. //----------- End of function Unit::reset_action_para -----------//
  71. //--------- Begin of function Unit::reset_action_para2 ---------//
  72. // reset action parameters when action is finished or cancelled
  73. //
  74. // <int> keepMode - use to keep action
  75. //
  76. void Unit::reset_action_para2(int keepMode)
  77. {
  78. if(keepMode!=KEEP_DEFENSE_MODE || !in_any_defense_mode())
  79. {
  80. action_mode2 = ACTION_STOP;
  81. action_para2 = 0;
  82. action_x_loc2 = action_y_loc2 = -1;
  83. }
  84. else
  85. {
  86. switch(unit_mode)
  87. {
  88. case UNIT_MODE_DEFEND_TOWN:
  89. if(action_mode2!=ACTION_AUTO_DEFENSE_DETECT_TARGET)
  90. defend_town_detect_target();
  91. break;
  92. case UNIT_MODE_REBEL:
  93. if(action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET)
  94. defense_detect_target();
  95. break;
  96. case UNIT_MODE_MONSTER:
  97. if(action_mode2!=ACTION_MONSTER_DEFEND_DETECT_TARGET)
  98. monster_defend_detect_target();
  99. break;
  100. }
  101. }
  102. }
  103. //----------- End of function Unit::reset_action_para2 -----------//
  104. //--------- Begin of function Unit::reset_action_misc_para ---------//
  105. // reset miscellaneous action parameters
  106. //
  107. void Unit::reset_action_misc_para()
  108. {
  109. action_misc = ACTION_MISC_STOP;
  110. action_misc_para = 0;
  111. }
  112. //----------- End of function Unit::reset_action_misc_para -----------//
  113. //--------- Begin of function Unit::stop ---------//
  114. // stop unit action
  115. //
  116. // [int] preserveAction - preserve the current action or not.
  117. // (default: 0)
  118. //
  119. void Unit::stop(int preserveAction)
  120. {
  121. //------------- reset vars ------------//
  122. if(action_mode2!=ACTION_MOVE)
  123. reset_way_point_array();
  124. reset_path();
  125. err_when(result_node_array!=NULL);
  126. //-------------- keep action or not --------------//
  127. switch(preserveAction)
  128. {
  129. case 0: case KEEP_DEFENSE_MODE:
  130. reset_action_para();
  131. range_attack_x_loc = range_attack_y_loc = -1; // should set here or reset for attack
  132. break;
  133. case KEEP_PRESERVE_ACTION:
  134. break;
  135. /*case 3: err_when(action_mode!=ACTION_ATTACK_UNIT);
  136. go_x = next_x; // combine move_to_attack() into move_to()
  137. go_y = next_y;
  138. move_to_x_loc = next_x_loc();
  139. move_to_y_loc = next_y_loc();
  140. return;*/
  141. }
  142. waiting_term = 0; // for idle_detect_attack(), oscillate between 0 and 1
  143. err_when(cur_dir<0 || cur_dir>MAX_SPRITE_DIR_TYPE);
  144. err_when(final_dir<0 || final_dir>MAX_SPRITE_DIR_TYPE);
  145. UnitMarine *shipPtr;
  146. //----------------- update parameters ----------------//
  147. switch( cur_action )
  148. {
  149. //----- if the unit is moving right now, ask it to stop as soon as possible -----//
  150. case SPRITE_READY_TO_MOVE:
  151. set_idle();
  152. break;
  153. case SPRITE_TURN:
  154. case SPRITE_WAIT:
  155. go_x = next_x;
  156. go_y = next_y;
  157. move_to_x_loc = next_x_loc();
  158. move_to_y_loc = next_y_loc();
  159. final_dir = cur_dir;
  160. turn_delay = 0;
  161. set_idle();
  162. break;
  163. case SPRITE_SHIP_EXTRA_MOVE:
  164. shipPtr = (UnitMarine*) this;
  165. switch(shipPtr->extra_move_in_beach)
  166. {
  167. case NO_EXTRA_MOVE:
  168. if(cur_x==next_x && cur_y==next_y)
  169. {
  170. go_x = next_x;
  171. go_y = next_y;
  172. move_to_x_loc = next_x_loc();
  173. move_to_y_loc = next_y_loc();
  174. set_idle();
  175. return;
  176. }
  177. break;
  178. case EXTRA_MOVING_IN:
  179. if(cur_x==next_x && cur_y==next_y && (cur_x!=go_x || cur_y!=go_y))
  180. {
  181. shipPtr->extra_move_in_beach = NO_EXTRA_MOVE; // not yet move although location is chosed
  182. err_when(next_x_loc()%2 || next_y_loc()%2); // in even location
  183. }
  184. else
  185. err_when(next_x_loc()%2==0 && next_y_loc()%2==0); // in even location
  186. break;
  187. case EXTRA_MOVING_OUT:
  188. if(cur_x==next_x && cur_y==next_y && (cur_x!=go_x || cur_y!=go_y))
  189. {
  190. shipPtr->extra_move_in_beach = EXTRA_MOVE_FINISH; // not yet move although location is chosed
  191. err_when(next_x_loc()%2==0 && next_y_loc()%2==0); // not in even location
  192. }
  193. else
  194. err_when(next_x_loc()%2 || next_y_loc()%2); // in even location
  195. break;
  196. case EXTRA_MOVE_FINISH:
  197. break;
  198. }
  199. go_x = next_x;
  200. go_y = next_y;
  201. move_to_x_loc = next_x_loc();
  202. move_to_y_loc = next_y_loc();
  203. break;
  204. case SPRITE_MOVE:
  205. go_x = next_x;
  206. go_y = next_y;
  207. move_to_x_loc = next_x_loc();
  208. move_to_y_loc = next_y_loc();
  209. if(cur_x==next_x && cur_y==next_y)
  210. set_idle();
  211. break;
  212. //--- if its current action is SPRITE_ATTACK, stop immediately ---//
  213. case SPRITE_ATTACK:
  214. set_next(cur_x, cur_y, 0, 1); //********** BUGHERE
  215. go_x = next_x;
  216. go_y = next_y;
  217. move_to_x_loc = next_x_loc();
  218. move_to_y_loc = next_y_loc();
  219. set_idle();
  220. #ifdef DEBUG
  221. char h, w, blocked=0;
  222. short x, y;
  223. for(h=0, y=next_y_loc(); h<sprite_info->loc_height&&!blocked; h++, y++)
  224. {
  225. for(w=0, x=next_x_loc(); w<sprite_info->loc_width&&!blocked; w++, x++)
  226. err_when(world.get_unit_recno(x, y, mobile_type) != sprite_recno);
  227. }
  228. #endif
  229. cur_frame = 1;
  230. break;
  231. }
  232. }
  233. //----------- End of function Unit::stop -----------//
  234. //--------- Begin of function Unit::stop2 ---------//
  235. // stop unit action
  236. //
  237. // preserverAction can be
  238. // 0, KEEP_PRESERVE_ACTION, KEEP_DEFENSE_MODE (default 0)
  239. //
  240. void Unit::stop2(int preserveAction)
  241. {
  242. stop(preserveAction);
  243. reset_action_para2(preserveAction);
  244. //----------------------------------------------------------//
  245. // set the original location of the attacking target when
  246. // the attack() function is called, action_x_loc2 & action_y_loc2
  247. // will change when the unit move, but these two will not.
  248. //----------------------------------------------------------//
  249. //##### begin trevor 13/10 #####//
  250. force_move_flag = 0;
  251. ai_no_suitable_action = 0;
  252. if( preserveAction==0 )
  253. {
  254. original_action_mode = 0;
  255. ai_original_target_x_loc = -1;
  256. if( ai_action_id )
  257. nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
  258. }
  259. //##### end trevor 13/10 #####//
  260. }
  261. //----------- End of function Unit::stop2 -----------//
  262. //######## begin trevor 26/4 ###########//
  263. //--------- Begin of function Unit::set_search_tries ---------//
  264. // used to limit the number of nodes in searching
  265. //
  266. // <int> tries - number of nodes used in searhcing
  267. //
  268. void Unit::set_search_tries(int tries)
  269. {
  270. unit_search_tries = tries;
  271. unit_search_tries_flag++;
  272. }
  273. //----------- End of function Unit::set_search_tries -----------//
  274. //--------- Begin of function Unit::reset_search_tries ---------//
  275. // reset the number of node to default value
  276. //
  277. void Unit::reset_search_tries()
  278. {
  279. unit_search_tries = 0; // 0 for reset
  280. unit_search_tries_flag = 0;
  281. }
  282. //----------- End of function Unit::reset_search_tries -----------//
  283. //######## end trevor 26/4 ###########//
  284. //-------- Begin of function Unit::abort_searching --------//
  285. //
  286. // <int> reuseSetNext - condition flag for updating parameters
  287. // of path_reuse
  288. //
  289. void Unit::abort_searching(int reuseSetNext)
  290. {
  291. if(reuseSetNext) // to avoid error in path-reuse
  292. seek_path_reuse.set_next_cur_path_num();
  293. if(unit_search_tries_flag)
  294. reset_search_tries();
  295. }
  296. //-------- End of function Unit::abort_searching ---------//
  297. //--------- Begin of function Unit::enable_force_move ---------//
  298. void Unit::enable_force_move()
  299. {
  300. force_move_flag = 1;
  301. }
  302. //-------- End of function Unit::enable_force_move ---------//
  303. //--------- Begin of function Unit::disable_force_move ---------//
  304. void Unit::disable_force_move()
  305. {
  306. force_move_flag = 0;
  307. }
  308. //-------- End of function Unit::disable_force_move ---------//
  309. //--------- Begin of function Unit::move_to ---------//
  310. // Main function for action_mode = ACTION_MOVE
  311. //
  312. // Order the unit to move to a specific location following the shortest path.
  313. //
  314. // <int> destX - x location of the destination
  315. // <int> destY - y location of the destination
  316. // [int] preserveAction - preserve the current action or not (default: 0)
  317. // [short] searchMode - the search mode used (default: SEARCH_MODE_IN_A_GROUP)
  318. // [short] miscNo - = target record no if search_mode=SEARCH_MODE_TO_ATTACK
  319. // = firm ID if search_mode=SEARCH_MODE_TO_FIRM (default: 0)
  320. // [short] numOfPath - num of path, used in path reuse, (default: 1)
  321. // [short] reuseMode - path reuse mode (default: GENERAL_GROUP_MOVEMENT)
  322. // [short] pathReuseStatus - path reuse status (default: 0)
  323. //
  324. void Unit::move_to(int destX, int destY, int preserveAction, short searchMode, short miscNo, short numOfPath, short reuseMode, short pathReuseStatus)
  325. {
  326. err_when(destX<0 || destX>=MAX_WORLD_X_LOC || destY<0 || destY>=MAX_WORLD_Y_LOC);
  327. if(!seek_path.total_node_avail)
  328. {
  329. //-------- insufficient nodes for searching, return now ----------//
  330. stop(KEEP_PRESERVE_ACTION);
  331. action_mode = action_mode2 = ACTION_MOVE;
  332. action_para = action_para2 = 0;
  333. action_x_loc = action_x_loc2 = destX;
  334. action_y_loc = action_y_loc2 = destY;
  335. return; // for later searching
  336. }
  337. //int useClosestNode = (seek_path.total_node_avail>=MIN_BACKGROUND_NODE_USED_UP);
  338. //---------- reset way point array since new action is assigned --------//
  339. if(way_point_count)
  340. {
  341. ResultNode *nodePtr = way_point_array;
  342. if(nodePtr->node_x!=destX || nodePtr->node_y!=destY)
  343. reset_way_point_array();
  344. }
  345. //----------------------------------------------------------------//
  346. // calculate new destination if trying to move to different territory
  347. //----------------------------------------------------------------//
  348. int curXLoc = next_x_loc();
  349. int curYLoc = next_y_loc();
  350. Location *locPtr = world.get_loc(curXLoc, curYLoc);
  351. Location *destLocPtr = world.get_loc(destX, destY);
  352. int destXLoc = destX;
  353. int destYLoc = destY;
  354. if(locPtr->region_id!=destLocPtr->region_id && mobile_type!=UNIT_AIR) // different territory
  355. different_territory_destination(destXLoc, destYLoc);
  356. //----------------------------------------------------------------//
  357. // for path_reuse initialization
  358. //----------------------------------------------------------------//
  359. if(numOfPath!=1 && pathReuseStatus==REUSE_PATH_INITIAL) // for path-reuse only
  360. {
  361. search(destXLoc, destYLoc, preserveAction, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
  362. return;
  363. }
  364. //----------------------------------------------------------------//
  365. // return if the unit is dead
  366. //----------------------------------------------------------------//
  367. if(is_unit_dead())
  368. {
  369. abort_searching(searchMode==SEARCH_MODE_REUSE && numOfPath>1);
  370. return;
  371. }
  372. //-----------------------------------------------------------------------------------//
  373. // The codes here is used to check for equal action in movement.
  374. //
  375. // mainly checked by action_mode2. If previous action is ACTION_MOVE, action_mode2,
  376. // action_para2, action_x_loc2 and action_x_loc2 need to be kept for this checking.
  377. //
  378. // If calling from unit_array.move_to(), action_mode is set to ACTION_MOVE, action_para
  379. // is set to 0 while action_x_loc and action_y_loc are kept as original value for checking.
  380. // Meanwhile, action_mode2, action_para2, action_x_loc2 and action_y_loc2 are kept if
  381. // the condition is fulfilled (action_mode2==ACTION_MOVE)
  382. //-----------------------------------------------------------------------------------//
  383. if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
  384. {
  385. //------ previous action is ACTION_MOVE -------//
  386. err_when(action_para2 || action_para);
  387. if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
  388. {
  389. //-------- equal order --------//
  390. action_x_loc = action_x_loc2;
  391. action_y_loc = action_y_loc2;
  392. if(cur_action!=SPRITE_IDLE)
  393. {
  394. //-------- the old order is processing --------//
  395. abort_searching(searchMode==SEARCH_MODE_REUSE && numOfPath>1);
  396. if(result_node_array==NULL) // cannot move
  397. {
  398. err_when(result_path_dist);
  399. if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP)
  400. {
  401. if(cur_action!=SPRITE_SHIP_EXTRA_MOVE)
  402. {
  403. err_when(result_node_count || result_node_recno);
  404. if(cur_x!=next_x || cur_y!=next_y)
  405. set_move();
  406. else
  407. set_idle();
  408. }
  409. //else keep extra_moving
  410. }
  411. else
  412. {
  413. err_when(result_node_count || result_node_recno);
  414. if(cur_x!=next_x || cur_y!=next_y)
  415. set_move();
  416. else
  417. set_idle();
  418. }
  419. }
  420. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  421. return;
  422. }//else action is hold due to some problems, re-activiate again
  423. }
  424. }//else, new order or searching is required
  425. move_action_call_flag++; // set flag to avoid calling move_to_my_loc()
  426. seek_path_reuse.set_status(PATH_WAIT);
  427. err_when(seek_path_reuse.get_reuse_path_status()==REUSE_PATH_INCOMPLETE_SEARCH);
  428. action_mode2 = ACTION_MOVE;
  429. action_para2 = 0;
  430. int enoughNode = search(destXLoc, destYLoc, preserveAction, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
  431. move_action_call_flag = 0; // clear the flag
  432. //----------------------------------------------------------------//
  433. // store new order in action parameters
  434. //----------------------------------------------------------------//
  435. action_mode = ACTION_MOVE;
  436. action_para = 0;
  437. if(!enoughNode || (searchMode==SEARCH_MODE_REUSE && seek_path_reuse.get_reuse_path_status()==REUSE_PATH_INCOMPLETE_SEARCH))
  438. {
  439. action_x_loc = action_x_loc2 = destXLoc;
  440. action_y_loc = action_y_loc2 = destYLoc;
  441. }
  442. else // enough node for search
  443. {
  444. action_x_loc = action_x_loc2 = move_to_x_loc;
  445. action_y_loc = action_y_loc2 = move_to_y_loc;
  446. }
  447. #ifdef DEBUG
  448. if(result_node_array && result_node_count)
  449. {
  450. ResultNode *debugPtr = result_node_array + result_node_count - 1;
  451. err_when(debugPtr->node_x != move_to_x_loc || debugPtr->node_y != move_to_y_loc);
  452. }
  453. else
  454. {
  455. UnitInfo* unitInfo = unit_res[unit_id];
  456. if( unitInfo->unit_class == UNIT_CLASS_SHIP )
  457. {
  458. UnitMarine *shipPtr = (UnitMarine*) this;
  459. if(shipPtr->extra_move_in_beach==NO_EXTRA_MOVE)
  460. err_when(curXLoc!=move_to_x_loc || curYLoc!=move_to_y_loc);
  461. }
  462. else
  463. {
  464. err_when(curXLoc!=move_to_x_loc || curYLoc!=move_to_y_loc);
  465. }
  466. }
  467. #endif
  468. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  469. err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
  470. err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
  471. err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
  472. err_when(action_mode2==ACTION_MOVE && (action_x_loc2==-1 || action_y_loc2==-1));
  473. }
  474. //----------- End of function Unit::move_to -----------//
  475. //--------- Begin of function Unit::search ---------//
  476. // This function is only used to find the shorest path for
  477. // searching. Action parameters should not be changed in
  478. // this function.
  479. //
  480. // <int> destX - x coordinate of destination
  481. // <int> destY - y coordinate of destination
  482. // <int> preserveAction - used to keep action in calling stop()
  483. // <short> searchMode - search mode being used
  484. // <short> miscNo - see move_to()
  485. // <short> numOfPath - num of path
  486. // <short> reuseMode - path reuse mode being used
  487. // <short> pathReuseStatus - path reuse status
  488. //
  489. // return 1 for normal operation process
  490. // return 0 otherwise or there is not enough node for searching
  491. //
  492. int Unit::search(int destXLoc, int destYLoc, int preserveAction, short searchMode, short miscNo, short numOfPath, short reuseMode, short pathReuseStatus)
  493. {
  494. #ifdef DEBUG
  495. err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
  496. err_when(searchMode==SEARCH_MODE_TO_FIRM && miscNo!=FIRM_HARBOR && mobile_type!=UNIT_AIR &&
  497. world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(destXLoc, destYLoc)->region_id);
  498. err_when(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE);
  499. #else
  500. if(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC || hit_points<=0 ||
  501. action_mode==ACTION_DIE || cur_action==SPRITE_DIE || searchMode<=0 || searchMode>MAX_SEARCH_MODE_TYPE)
  502. {
  503. stop2(KEEP_DEFENSE_MODE); //-********** BUGHERE, err_handling for retailed version
  504. return 1;
  505. }
  506. #endif
  507. //----------------------------------------------------------------//
  508. // for path_reuse initialization
  509. //----------------------------------------------------------------//
  510. if(numOfPath!=1 && pathReuseStatus==REUSE_PATH_INITIAL) // for path-reuse only
  511. {
  512. seek_path_reuse.seek(next_x_loc(), next_y_loc(), move_to_x_loc, move_to_y_loc, sprite_info->loc_width,
  513. unit_group_id, mobile_type, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
  514. return 1;
  515. }
  516. int result=0;
  517. if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP)
  518. {
  519. UnitMarine *shipPtr = (UnitMarine*) this;
  520. switch(shipPtr->extra_move_in_beach)
  521. {
  522. case NO_EXTRA_MOVE:
  523. result = searching(destXLoc, destYLoc, preserveAction, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
  524. break;
  525. case EXTRA_MOVING_IN:
  526. err_when(next_x_loc()%2==0 && next_y_loc()%2==0);
  527. if(pathReuseStatus==REUSE_PATH_SEARCH || pathReuseStatus==REUSE_PATH_FIRST_SEEK)
  528. seek_path_reuse.set_next_cur_path_num();
  529. return 0;
  530. case EXTRA_MOVING_OUT:
  531. err_when(next_x_loc()%2 || next_y_loc()%2);
  532. if(pathReuseStatus==REUSE_PATH_SEARCH || pathReuseStatus==REUSE_PATH_FIRST_SEEK)
  533. seek_path_reuse.set_next_cur_path_num();
  534. return 0;
  535. case EXTRA_MOVE_FINISH:
  536. err_when(next_x_loc()%2==0 && next_y_loc()%2==0);
  537. if(pathReuseStatus==REUSE_PATH_SEARCH || pathReuseStatus==REUSE_PATH_FIRST_SEEK)
  538. seek_path_reuse.set_next_cur_path_num();
  539. ship_leave_beach(next_x_loc(), next_y_loc());
  540. break;
  541. default: err_here();
  542. break;
  543. }
  544. }
  545. else
  546. result = searching(destXLoc, destYLoc, preserveAction, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
  547. if(way_point_count && !result_node_array) // can move no more
  548. reset_way_point_array();
  549. if(!result)
  550. return 0; // not enough node or extra_move_in_beach!=NO_EXTRA_MOVE
  551. else
  552. return 1;
  553. }
  554. //----------- End of function Unit::search -----------//
  555. //--------- Begin of function Unit::select_search_sub_mode ---------//
  556. // select searching sub_mode
  557. //
  558. // <int> sx - start location x
  559. // <int> sy - start location y
  560. // <int> dx - x coordinate of destination
  561. // <int> dy - y coordinate of destination
  562. // <short> nationRecno - nation recno of the unit
  563. // <short> searchMode - search mode being used
  564. //
  565. void Unit::select_search_sub_mode(int sx, int sy, int dx, int dy, short nationRecno, short searchMode)
  566. {
  567. //seek_path.set_sub_mode(); // cancel the selection
  568. //return;
  569. err_when(mobile_type!=UNIT_LAND);
  570. if(!nation_recno || ignore_power_nation)
  571. {
  572. seek_path.set_sub_mode(); // always using normal mode for independent unit
  573. seek_path_reuse.set_sub_mode();
  574. return;
  575. }
  576. //--------------------------------------------------------------------------------//
  577. // Checking for starting location and destination to determine sub_mode used
  578. // N - not hostile, H - hostile
  579. // 1) N -> N, using normal mode
  580. // 2) N -> H, H -> N, H -> H, using sub_mode SEARCH_SUB_MODE_PASSABLE
  581. //--------------------------------------------------------------------------------//
  582. Location *startLocPtr = world.get_loc(sx, sy);
  583. Location *destLocPtr = world.get_loc(dx, dy);
  584. Nation *nationPtr = nation_array[nationRecno];
  585. int subModeOn = 1;
  586. if((startLocPtr->power_nation_recno && !nationPtr->get_relation_passable(startLocPtr->power_nation_recno)) ||
  587. (destLocPtr->power_nation_recno && !nationPtr->get_relation_passable(destLocPtr->power_nation_recno)))
  588. subModeOn = 0;
  589. if(subModeOn) // true only when both start and end locations are passable for this nation
  590. {
  591. seek_path.set_nation_passable(nationPtr->relation_passable_array);
  592. seek_path.set_sub_mode(SEARCH_SUB_MODE_PASSABLE);
  593. }
  594. else
  595. seek_path.set_sub_mode(); //----- normal sub mode, normal searching
  596. //----------- set sub_mode of path-reuse if more than one unit are selected -----------//
  597. if(subModeOn && searchMode==SEARCH_MODE_REUSE)
  598. {
  599. seek_path_reuse.set_nation_passable(nationPtr->relation_passable_array);
  600. seek_path_reuse.set_sub_mode(SEARCH_SUB_MODE_PASSABLE);
  601. }
  602. else
  603. seek_path_reuse.set_sub_mode();
  604. }
  605. //----------- End of function Unit::select_search_sub_mode -----------//
  606. //--------- Begin of function Unit::searching ---------//
  607. int Unit::searching(int destXLoc, int destYLoc, int preserveAction, short searchMode, short miscNo, short numOfPath, short reuseMode, short pathReuseStatus)
  608. {
  609. stop(preserveAction); // stop the unit as soon as possible
  610. int startXLocLoc=next_x_loc(); // next location the sprite is moving towards
  611. int startYLocLoc=next_y_loc();
  612. int totalAvailableNode = seek_path.total_node_avail;
  613. if(!avail_node_enough_for_search(startXLocLoc, startYLocLoc, destXLoc, destYLoc))
  614. {
  615. abort_searching(searchMode==4 && numOfPath>1);
  616. return 0; // not enough node for searching
  617. }
  618. //stop(preserveAction); // stop the unit as soon as possible
  619. //---------------------------------------------------------------------------//
  620. // adjust the destination for unit size
  621. //---------------------------------------------------------------------------//
  622. /*err_when(sprite_info->loc_width!=sprite_info->loc_height);
  623. if(sprite_info->loc_width>1) // not size 1x1
  624. {
  625. destXLoc = move_to_x_loc = min(destXLoc, MAX_WORLD_X_LOC-sprite_info->loc_width);
  626. destYLoc = move_to_y_loc = min(destYLoc, MAX_WORLD_Y_LOC-sprite_info->loc_height);
  627. }
  628. else
  629. {*/
  630. move_to_x_loc = destXLoc;
  631. move_to_y_loc = destYLoc;
  632. //}
  633. //------------------------------------------------------------//
  634. // fast checking for destination == current location
  635. //------------------------------------------------------------//
  636. //if(startXLocLoc==move_to_x_loc && startYLocLoc==move_to_y_loc) // already here
  637. if(startXLocLoc==destXLoc && startYLocLoc==destYLoc) // already here
  638. {
  639. if(cur_x!=next_x || cur_y!=next_y)
  640. set_move();
  641. else
  642. set_idle();
  643. err_when(move_to_x_loc!=startXLocLoc || move_to_y_loc!=startYLocLoc);
  644. err_when(result_node_array!=NULL);
  645. abort_searching(searchMode==SEARCH_MODE_REUSE && numOfPath>1);
  646. return 1;
  647. }
  648. //------------------------ find the shortest path --------------------------//
  649. //
  650. // Note: seek() will never return PATH_SEEKING as the maxTries==max_node in
  651. // calling seek()
  652. //
  653. // decide the searching to use according to the unit size
  654. // assume the unit size is always 1x1, 2x2, 3x3 and so on
  655. // i.e. sprite_info->loc_width == sprite_info->loc_height
  656. //--------------------------------------------------------------------------//
  657. result_node_recno = result_node_count = 0;
  658. err_when(result_node_array!=NULL);
  659. seek_path.set_nation_recno(nation_recno);
  660. int seekResult;
  661. #ifdef DEBUG
  662. unsigned long seekPathStartTime = m.get_time();
  663. #endif
  664. /*switch(sprite_info->loc_width)
  665. {
  666. case 1:*/
  667. if(searchMode!=SEARCH_MODE_REUSE || numOfPath==1) // no need to call path_reuse
  668. {
  669. if(mobile_type==UNIT_LAND)
  670. select_search_sub_mode(startXLocLoc, startYLocLoc, destXLoc, destYLoc, nation_recno, searchMode);
  671. seekResult = seek_path.seek(startXLocLoc, startYLocLoc, destXLoc, destYLoc, unit_group_id,
  672. mobile_type, searchMode, miscNo, numOfPath, unit_search_tries);
  673. result_node_array = seek_path.get_result(result_node_count, result_path_dist);
  674. seek_path.set_sub_mode(); // reset sub_mode searching
  675. }
  676. else // use path_reuse
  677. {
  678. err_when(reuseMode!=GENERAL_GROUP_MOVEMENT);
  679. seekResult = seek_path_reuse.seek(startXLocLoc, startYLocLoc, destXLoc, destYLoc, 1, unit_group_id,
  680. mobile_type, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
  681. result_node_array = seek_path_reuse.get_result(result_node_count, result_path_dist);
  682. }
  683. #ifdef DEBUG
  684. seek_path_profile_time = m.get_time() - seekPathStartTime;
  685. #endif
  686. /* break;
  687. default: err_here();
  688. break;
  689. }*/
  690. if(seekResult==PATH_IMPOSSIBLE)
  691. {
  692. reset_path();
  693. err_when(result_node_array || result_node_count);
  694. }
  695. //####### begin trevor 15/10 ########//
  696. //-----------------------------------------------------------------------//
  697. // update ignore_power_nation,seek_path_fail_count
  698. //-----------------------------------------------------------------------//
  699. if(ai_unit)
  700. {
  701. //----- set seek_path_fail_count ------//
  702. if( seekResult==PATH_IMPOSSIBLE ||
  703. (seekResult==PATH_NODE_USED_UP && // if all the nodes have been used up and the number of nodes original available is >= VALID_BACKGROUND_SEARCH_NODE
  704. totalAvailableNode >= VALID_BACKGROUND_SEARCH_NODE) )
  705. {
  706. if( seek_path_fail_count < 100 ) // prevent numeric overflow
  707. seek_path_fail_count++;
  708. }
  709. else
  710. seek_path_fail_count=0;
  711. //------- set ignore_power_nation -------//
  712. if( seekResult==PATH_IMPOSSIBLE )
  713. {
  714. switch(ignore_power_nation)
  715. {
  716. case 0: ignore_power_nation = 1;
  717. break;
  718. case 1: ignore_power_nation = 2;
  719. break;
  720. case 2: break;
  721. default: err_here();
  722. break;
  723. }
  724. }
  725. else
  726. {
  727. if( ignore_power_nation==1 )
  728. ignore_power_nation = 0;
  729. }
  730. }
  731. //######## end trevor 15/10 ########//
  732. //-----------------------------------------------------------------------//
  733. // if closest node is returned, the destination should not be the real
  734. // location to go to. Thus, move_to_?_loc should be adjusted
  735. //-----------------------------------------------------------------------//
  736. if(result_node_array && result_node_count)
  737. {
  738. ResultNode* lastNode = result_node_array + result_node_count - 1;
  739. move_to_x_loc = lastNode->node_x; // adjust move_to_?_loc
  740. move_to_y_loc = lastNode->node_y;
  741. result_node_recno = 1; // skip the first node which is the current location
  742. if(cur_action != SPRITE_MOVE) // check if the unit is moving right now, wait until it reaches the nearest complete tile.
  743. {
  744. err_when(cur_action!=SPRITE_SHIP_EXTRA_MOVE && (cur_x!=next_x || cur_y!=next_y));
  745. #ifdef DEBUG
  746. int moveToXLoc = move_to_x_loc;
  747. int moveToYLoc = move_to_y_loc;
  748. #endif
  749. ResultNode *nextNode = result_node_array + 1;
  750. //set_dir(next_x_loc(), next_y_loc(), nextNode->node_x, nextNode->node_y);
  751. set_dir(startXLocLoc, startYLocLoc, nextNode->node_x, nextNode->node_y);
  752. next_move();
  753. #ifdef DEBUG
  754. err_when(move_action_call_flag && (moveToXLoc!=move_to_x_loc || moveToYLoc!=move_to_y_loc));
  755. #endif
  756. }
  757. }
  758. else // stay in the current location
  759. {
  760. err_when(result_node_array!=NULL);
  761. move_to_x_loc = startXLocLoc; // adjust move_to_?_loc
  762. move_to_y_loc = startYLocLoc;
  763. err_when(move_to_x_loc!=startXLocLoc || move_to_y_loc!=startYLocLoc);
  764. if(cur_x!=next_x || cur_y!=next_y)
  765. set_move();
  766. else
  767. set_idle();
  768. }
  769. err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
  770. err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
  771. err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
  772. //-------------------------------------------------------//
  773. // PATH_NODE_USED_UP happens when:
  774. // Exceed the object's max's node limitation, the closest path
  775. // is returned. Get to the closest path first and continue
  776. // to seek the path in the background.
  777. //-------------------------------------------------------//
  778. return 1;
  779. }
  780. //----------- End of function Unit::searching -----------//
  781. //--------- Begin of function Unit::move_to_firm_surround ---------//
  782. // order unit to move to firm surrounding
  783. //
  784. // <int> destXLoc, destYLoc - destination
  785. // <int> width - unit width
  786. // <int> height - unit height
  787. // <int> miscNo - the firm id (default 0)
  788. // <int> readyDist - similar to that in set_move_to_surround()
  789. // (default 0)
  790. //
  791. // Note: the firm should exist in the location (destXloc, destYLoc)
  792. // this function can be called by unit with size 1x1, 2x2,
  793. //
  794. void Unit::move_to_firm_surround(int destXLoc, int destYLoc, int width, int height, int miscNo, int readyDist)
  795. {
  796. err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
  797. //----------------------------------------------------------------//
  798. // calculate new destination if trying to move to different territory
  799. //----------------------------------------------------------------//
  800. Location *locPtr = world.get_loc(destXLoc, destYLoc);
  801. if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP && miscNo==FIRM_HARBOR)
  802. {
  803. err_when(!locPtr->is_firm());
  804. Firm *firmPtr = firm_array[locPtr->firm_recno()];
  805. FirmHarbor *harborPtr = (FirmHarbor*) firmPtr;
  806. if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=harborPtr->sea_region_id)
  807. {
  808. move_to(destXLoc, destYLoc);
  809. return;
  810. }
  811. }
  812. else
  813. {
  814. if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id)
  815. {
  816. move_to(destXLoc, destYLoc);
  817. return;
  818. }
  819. }
  820. //----------------------------------------------------------------//
  821. // return if the unit is dead
  822. //----------------------------------------------------------------//
  823. if(is_unit_dead())
  824. return;
  825. //----------------------------------------------------------------//
  826. // check for equal actions
  827. //----------------------------------------------------------------//
  828. if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
  829. {
  830. //------ previous action is ACTION_MOVE -------//
  831. err_when(action_para2 || action_para);
  832. if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
  833. {
  834. //-------- equal order --------//
  835. action_x_loc = action_x_loc2;
  836. action_y_loc = action_y_loc2;
  837. if(cur_action!=SPRITE_IDLE)
  838. {
  839. //-------- the old order is processing --------//
  840. if(result_node_array==NULL) // cannot move
  841. {
  842. err_when(result_node_count || result_node_recno);
  843. set_idle();
  844. }
  845. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  846. return;
  847. }//else action is hold due to some problems, re-activiate again
  848. }
  849. }//else, new order or searching is required
  850. int destX = max(0, ((width>1) ? destXLoc : destXLoc - width + 1));
  851. int destY = max(0, ((height>1) ? destYLoc : destYLoc - height + 1));
  852. FirmInfo *firmInfo = firm_res[miscNo];
  853. stop();
  854. set_move_to_surround(destX, destY, firmInfo->loc_width, firmInfo->loc_height, BUILDING_TYPE_FIRM_MOVE_TO, miscNo);
  855. //----------------------------------------------------------------//
  856. // store new order in action parameters
  857. //----------------------------------------------------------------//
  858. action_mode = action_mode2 = ACTION_MOVE;
  859. action_para = action_para2 = 0;
  860. action_x_loc = action_x_loc2 = move_to_x_loc;
  861. action_y_loc = action_y_loc2 = move_to_y_loc;
  862. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  863. err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
  864. err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
  865. err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
  866. #ifdef DEBUG
  867. if(unit_res[unit_id]->unit_class!=UNIT_CLASS_SHIP || ((UnitMarine*)this)->extra_move_in_beach==NO_EXTRA_MOVE)
  868. err_when(result_node_array==NULL && (next_x!=go_x || next_y!=go_y));
  869. #endif
  870. }
  871. //----------- End of function Unit::move_to_firm_surround -----------//
  872. //--------- Begin of function Unit::move_to_town_surround ---------//
  873. // move to town surrounding
  874. //
  875. // <int> destXLoc, destYLoc - destination
  876. // <int> width - unit width
  877. // <int> height - unit height
  878. // <int> miscNo - reserved (default 0)
  879. // <int> readyDist - similar to that in set_move_to_surround()
  880. // (default 0)
  881. //
  882. // Note: assume the town exists
  883. // this function can be called by unit with size 1x1, 2x2,
  884. //
  885. void Unit::move_to_town_surround(int destXLoc, int destYLoc, int width, int height, int miscNo, int readyDist)
  886. {
  887. err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
  888. //----------------------------------------------------------------//
  889. // calculate new destination if trying to move to different territory
  890. //----------------------------------------------------------------//
  891. Location *locPtr = world.get_loc(destXLoc, destYLoc);
  892. if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id)
  893. {
  894. move_to(destXLoc, destYLoc);
  895. return;
  896. }
  897. //----------------------------------------------------------------//
  898. // return if the unit is dead
  899. //----------------------------------------------------------------//
  900. if(is_unit_dead())
  901. return;
  902. //----------------------------------------------------------------//
  903. // check for equal actions
  904. //----------------------------------------------------------------//
  905. if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
  906. {
  907. //------ previous action is ACTION_MOVE -------//
  908. err_when(action_para2 || action_para);
  909. if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
  910. {
  911. //-------- equal order --------//
  912. action_x_loc = action_x_loc2;
  913. action_y_loc = action_y_loc2;
  914. if(cur_action!=SPRITE_IDLE)
  915. {
  916. //-------- the old order is processing --------//
  917. if(result_node_array==NULL) // cannot move
  918. {
  919. err_when(result_node_count || result_node_recno);
  920. set_idle();
  921. }
  922. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  923. return;
  924. }//else action is hold due to some problems, re-activiate again
  925. }
  926. }//else, new order or searching is required
  927. int destX = max(0, ((width>1) ? destXLoc : destXLoc - width + 1));
  928. int destY = max(0, ((height>1) ? destYLoc : destYLoc - height + 1));
  929. stop();
  930. set_move_to_surround(destX, destY, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, BUILDING_TYPE_TOWN_MOVE_TO);
  931. //----------------------------------------------------------------//
  932. // store new order in action parameters
  933. //----------------------------------------------------------------//
  934. action_mode = action_mode2 = ACTION_MOVE;
  935. action_para = action_para2 = 0;
  936. action_x_loc = action_x_loc2 = move_to_x_loc;
  937. action_y_loc = action_y_loc2 = move_to_y_loc;
  938. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  939. err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
  940. err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
  941. err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
  942. err_when(result_node_array==NULL && (next_x!=go_x || next_y!=go_y));
  943. }
  944. //----------- End of function Unit::move_to_town_surround -----------//
  945. //--------- Begin of function Unit::move_to_wall_surround ---------//
  946. // move to wall surrounding
  947. //
  948. // <int> destXLoc, destYLoc - destination
  949. // <int> width - unit width
  950. // <int> height - unit height
  951. // <int> miscNo - reserved (default 0)
  952. // <int> readyDist - similar to that in set_move_to_surround()
  953. // (default 0)
  954. //
  955. // Note: assume the wall exists
  956. // this function can be called by unit with size 1x1, 2x2,
  957. //
  958. void Unit::move_to_wall_surround(int destXLoc, int destYLoc, int width, int height, int miscNo, int readyDist)
  959. {
  960. err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
  961. //----------------------------------------------------------------//
  962. // calculate new destination if trying to move to different territory
  963. //----------------------------------------------------------------//
  964. Location *locPtr = world.get_loc(destXLoc, destYLoc);
  965. if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id)
  966. {
  967. move_to(destXLoc, destYLoc);
  968. return;
  969. }
  970. //----------------------------------------------------------------//
  971. // return if the unit is dead
  972. //----------------------------------------------------------------//
  973. if(is_unit_dead())
  974. return;
  975. //----------------------------------------------------------------//
  976. // check for equal actions
  977. //----------------------------------------------------------------//
  978. if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
  979. {
  980. //------ previous action is ACTION_MOVE -------//
  981. err_when(action_para2 || action_para);
  982. if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
  983. {
  984. //-------- equal order --------//
  985. action_x_loc = action_x_loc2;
  986. action_y_loc = action_y_loc2;
  987. if(cur_action!=SPRITE_IDLE)
  988. {
  989. //-------- the old order is processing --------//
  990. if(result_node_array==NULL) // cannot move
  991. {
  992. err_when(result_node_count || result_node_recno);
  993. set_idle();
  994. }
  995. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  996. return;
  997. }//else action is hold due to some problems, re-activiate again
  998. }
  999. }//else, new order or searching is required
  1000. int destX = max(0, ((width>1) ? destXLoc : destXLoc - width + 1));
  1001. int destY = max(0, ((height>1) ? destYLoc : destYLoc - height + 1));
  1002. stop();
  1003. set_move_to_surround(destX, destY, 1, 1, BUILDING_TYPE_WALL);
  1004. //----------------------------------------------------------------//
  1005. // store new order in action parameters
  1006. //----------------------------------------------------------------//
  1007. action_mode = action_mode2 = ACTION_MOVE;
  1008. action_para = action_para2 = 0;
  1009. action_x_loc = action_x_loc2 = move_to_x_loc;
  1010. action_y_loc = action_y_loc2 = move_to_y_loc;
  1011. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  1012. err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
  1013. err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
  1014. err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
  1015. err_when(result_node_array==NULL && (next_x!=go_x || next_y!=go_y));
  1016. }
  1017. //----------- End of function Unit::move_to_wall_surround -----------//
  1018. //--------- Begin of function Unit::move_to_unit_surround ---------//
  1019. // move to unit surrounding
  1020. //
  1021. // <int> destXLoc, destYLoc - destination
  1022. // <int> width - unit width
  1023. // <int> height - unit height
  1024. // <int> miscNo - vehicle unit_recno (default 0)
  1025. // <int> readyDist - similar to that in set_move_to_surround()
  1026. // (default 0)
  1027. //
  1028. // Note: assume the vehicle exists
  1029. // this function can be called by unit with size 1x1, 2x2,
  1030. //
  1031. void Unit::move_to_unit_surround(int destXLoc, int destYLoc, int width, int height, int miscNo, int readyDist)
  1032. {
  1033. err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
  1034. //----------------------------------------------------------------//
  1035. // calculate new destination if trying to move to different territory
  1036. //----------------------------------------------------------------//
  1037. Location *locPtr = world.get_loc(destXLoc, destYLoc);
  1038. if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id)
  1039. {
  1040. move_to(destXLoc, destYLoc);
  1041. return;
  1042. }
  1043. //----------------------------------------------------------------//
  1044. // return if the unit is dead
  1045. //----------------------------------------------------------------//
  1046. if(is_unit_dead())
  1047. return;
  1048. //----------------------------------------------------------------//
  1049. // check for equal actions
  1050. //----------------------------------------------------------------//
  1051. if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
  1052. {
  1053. //------ previous action is ACTION_MOVE -------//
  1054. err_when(action_para2 || action_para);
  1055. if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
  1056. {
  1057. //-------- equal order --------//
  1058. action_x_loc = action_x_loc2;
  1059. action_y_loc = action_y_loc2;
  1060. if(cur_action!=SPRITE_IDLE)
  1061. {
  1062. //-------- the old order is processing --------//
  1063. if(result_node_array==NULL) // cannot move
  1064. {
  1065. err_when(result_node_count || result_node_recno);
  1066. set_idle();
  1067. }
  1068. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  1069. return;
  1070. }//else action is hold due to some problems, re-activiate again
  1071. }
  1072. }//else, new order or searching is required
  1073. int destX = max(0, ((width>1) ? destXLoc : destXLoc - width + 1));
  1074. int destY = max(0, ((height>1) ? destYLoc : destYLoc - height + 1));
  1075. err_when(unit_array.is_deleted(miscNo));
  1076. Unit *unitPtr = unit_array[miscNo];
  1077. SpriteInfo *spriteInfo = unitPtr->sprite_info;
  1078. stop();
  1079. set_move_to_surround(destX, destY, spriteInfo->loc_width, spriteInfo->loc_height, BUILDING_TYPE_VEHICLE);
  1080. //----------------------------------------------------------------//
  1081. // store new order in action parameters
  1082. //----------------------------------------------------------------//
  1083. action_mode = action_mode2 = ACTION_MOVE;
  1084. action_para = action_para2 = 0;
  1085. action_x_loc = action_x_loc2 = move_to_x_loc;
  1086. action_y_loc = action_y_loc2 = move_to_y_loc;
  1087. err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
  1088. err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
  1089. err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
  1090. err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
  1091. err_when(result_node_array==NULL && (next_x!=go_x || next_y!=go_y));
  1092. }
  1093. //----------- End of function Unit::move_to_unit_surround -----------//
  1094. //--------- Begin of function Unit::different_territory_destination ---------//
  1095. // calculate a reachable destination if the unit is ordered to move to unreachable
  1096. // location on different territory
  1097. //
  1098. // <int&> destX, destY - reference to return destination
  1099. //
  1100. void Unit::different_territory_destination(int& destX, int& destY)
  1101. {
  1102. int curXLoc = next_x_loc();
  1103. int curYLoc = next_y_loc();
  1104. Location *locPtr = world.get_loc(curXLoc, curYLoc);
  1105. int regionId = locPtr->region_id;
  1106. int xStep = destX-curXLoc;
  1107. int yStep = destY-curYLoc;
  1108. int absXStep = abs(xStep);
  1109. int absYStep = abs(yStep);
  1110. int count = (absXStep>=absYStep) ? absXStep : absYStep;
  1111. int x, y;
  1112. long int sameTerr = 0;
  1113. //------------------------------------------------------------------------------//
  1114. // draw a line from the unit location to the destination, find the last location
  1115. // with the same region id.
  1116. //------------------------------------------------------------------------------//
  1117. for(long int i=1; i<=count; i++)
  1118. {
  1119. x = curXLoc + int((i*xStep)/count);
  1120. y = curYLoc + int((i*yStep)/count);
  1121. locPtr = world.get_loc(x, y);
  1122. if(locPtr->region_id==regionId)
  1123. sameTerr = i;
  1124. }
  1125. if(sameTerr)
  1126. {
  1127. destX = curXLoc + int((sameTerr*xStep)/count);
  1128. destY = curYLoc + int((sameTerr*yStep)/count);
  1129. }
  1130. else
  1131. {
  1132. destX = curXLoc;
  1133. destY = curYLoc;
  1134. }
  1135. }
  1136. //----------- End of function Unit::different_territory_destination -----------//
  1137. //--------- Begin of function Unit::next_move ---------//
  1138. //
  1139. // If there is unprocessed node(s) in the result_node_array,
  1140. // then next unprocessed node will be set to be the next location
  1141. // to move to. (i.e. go_? = location of the unprocessed node)
  1142. //
  1143. void Unit::next_move()
  1144. {
  1145. if(result_node_array == NULL || !result_node_count || !result_node_recno)
  1146. return;
  1147. if( ++result_node_recno > result_node_count )
  1148. {
  1149. //------------ all nodes are visited --------------//
  1150. err_when(cur_x!=next_x || cur_y!=next_y);
  1151. err_when(next_x_loc()!=move_to_x_loc || next_y_loc()!=move_to_y_loc);
  1152. mem_del(result_node_array);
  1153. result_node_array = NULL;
  1154. set_idle();
  1155. if(action_mode2==ACTION_MOVE) //--------- used to terminate action_mode==ACTION_MOVE
  1156. {
  1157. force_move_flag = 0;
  1158. //------- reset ACTION_MOVE parameters ------//
  1159. reset_action_para();
  1160. if(move_to_x_loc==action_x_loc2 && move_to_y_loc==action_y_loc2)
  1161. reset_action_para2();
  1162. }
  1163. return;
  1164. }
  1165. //---- order the unit to move to the next checkpoint following the path ----//
  1166. ResultNode* resultNode = result_node_array+result_node_recno-1;
  1167. #ifdef DEBUG
  1168. err_when(cur_x==move_to_x_loc*ZOOM_LOC_WIDTH && cur_y==move_to_y_loc*ZOOM_LOC_HEIGHT);
  1169. err_when(!resultNode);
  1170. #endif
  1171. sprite_move( resultNode->node_x*ZOOM_LOC_WIDTH, resultNode->node_y*ZOOM_LOC_HEIGHT );
  1172. err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
  1173. }
  1174. //----------- End of function Unit::next_move -----------//
  1175. //--------- Begin of function Unit::reset_path ---------//
  1176. // Cancel all movement.
  1177. //
  1178. void Unit::reset_path()
  1179. {
  1180. if( result_node_array )
  1181. {
  1182. mem_del(result_node_array);
  1183. result_node_array = NULL;
  1184. }
  1185. result_path_dist = result_node_count = result_node_recno = 0;
  1186. }
  1187. //----------- End of function Unit::reset_path -----------//
  1188. //--------- Begin of function Unit::pre_process ---------//
  1189. // process unit's action
  1190. //
  1191. void Unit::pre_process()
  1192. {
  1193. //-*********** simulate aat ************-//
  1194. #ifdef DEBUG
  1195. if(debug_sim_game_type==2)
  1196. {
  1197. if(hit_points!=max_hit_points)
  1198. hit_points = max_hit_points;
  1199. Nation *nationPtr = nation_array[nation_recno];
  1200. if(nationPtr->cash<4000)
  1201. nationPtr->cash += 10000;
  1202. if(nationPtr->food<4000)
  1203. nationPtr->food += 10000;
  1204. }
  1205. #endif
  1206. //-*********** simulate aat ************-//
  1207. #if defined(DEBUG) && defined(ENABLE_LOG)
  1208. String logStr;
  1209. logStr = " begin unit ";
  1210. logStr += sprite_recno;
  1211. // ########## begin Gilbert 6/9 #######//
  1212. logStr += " nation=";
  1213. logStr += nation_recno;
  1214. logStr += "(";
  1215. logStr += true_nation_recno();
  1216. logStr += ")";
  1217. // ########## end Gilbert 6/9 #######//
  1218. logStr += " pre_process(), action_mode=";
  1219. logStr += action_mode;
  1220. logStr += " action_mode2=";
  1221. logStr += action_mode2;
  1222. LOG_MSG(logStr);
  1223. logStr = "action_para=";
  1224. logStr += action_para;
  1225. logStr += " action_para2=";
  1226. logStr += action_para2;
  1227. logStr += " cur_action=";
  1228. logStr += cur_action;
  1229. logStr += " cur_x/y=";
  1230. logStr += cur_x;
  1231. logStr += "/";
  1232. logStr += cur_y;
  1233. logStr += " next_x/y=";
  1234. logStr += next_x;
  1235. logStr += "/";
  1236. logStr += next_y;
  1237. LOG_MSG(logStr);
  1238. #endif
  1239. //------ if all the hit points are lost, die now ------//
  1240. if(hit_points <= 0 && action_mode != ACTION_DIE)
  1241. {
  1242. set_die();
  1243. if(ai_action_id)
  1244. nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
  1245. return;
  1246. }
  1247. #ifdef DEBUG
  1248. int debugActionMode = action_mode;
  1249. int debugActionPatra = action_para;
  1250. int debugCurAction = cur_action;
  1251. #endif
  1252. if( config.fog_of_war )
  1253. {
  1254. if( is_own() ||
  1255. (nation_recno && nation_array[nation_recno]->is_allied_with_player) )
  1256. {
  1257. world.visit(next_x_loc(), next_y_loc(), next_x_loc()+sprite_info->loc_width-1,
  1258. next_y_loc()+sprite_info->loc_height-1, unit_res[unit_id]->visual_range,
  1259. unit_res[unit_id]->visual_extend);
  1260. }
  1261. }
  1262. //--------- process action corresponding to action_mode ----------//
  1263. #ifdef DEBUG
  1264. unsigned long startTime;
  1265. #endif
  1266. switch(action_mode)
  1267. {
  1268. case ACTION_ATTACK_UNIT:
  1269. #ifdef DEBUG
  1270. startTime = m.get_time();
  1271. #endif
  1272. //------------------------------------------------------------------//
  1273. // if unit is in defense mode, check situation to follow the target
  1274. // or return back to camp
  1275. //------------------------------------------------------------------//
  1276. if(action_mode!=action_mode2)
  1277. {
  1278. if(action_mode2==ACTION_AUTO_DEFENSE_ATTACK_TARGET)
  1279. {
  1280. if(!defense_follow_target()) // false if abort attacking
  1281. break; // cancel attack and go back to military camp
  1282. }
  1283. else if(action_mode2==ACTION_DEFEND_TOWN_ATTACK_TARGET)
  1284. {
  1285. if(!defend_town_follow_target())
  1286. break;
  1287. }
  1288. else if(action_mode2==ACTION_MONSTER_DEFEND_ATTACK_TARGET)
  1289. {
  1290. if(!monster_defend_follow_target())
  1291. break;
  1292. }
  1293. else
  1294. err_here();
  1295. }
  1296. process_attack_unit();
  1297. #ifdef DEBUG
  1298. unit_attack_profile_time += m.get_time() - startTime;
  1299. #endif
  1300. break;
  1301. case ACTION_ATTACK_FIRM:
  1302. process_attack_firm();
  1303. break;
  1304. case ACTION_ATTACK_TOWN:
  1305. process_attack_town();
  1306. break;
  1307. case ACTION_ATTACK_WALL:
  1308. process_attack_wall();
  1309. break;
  1310. case ACTION_ASSIGN_TO_FIRM:
  1311. case ACTION_ASSIGN_TO_TOWN:
  1312. case ACTION_ASSIGN_TO_VEHICLE:
  1313. #ifdef DEBUG
  1314. startTime = m.get_time();
  1315. #endif
  1316. process_assign();
  1317. #ifdef DEBUG
  1318. unit_assign_profile_time += m.get_time() - startTime;
  1319. #endif
  1320. break;
  1321. case ACTION_ASSIGN_TO_SHIP:
  1322. process_assign_to_ship();
  1323. break;
  1324. case ACTION_BUILD_FIRM:
  1325. process_build_firm();
  1326. break;
  1327. case ACTION_BURN:
  1328. process_burn();
  1329. break;
  1330. case ACTION_SETTLE:
  1331. process_settle();
  1332. break;
  1333. case ACTION_SHIP_TO_BEACH:
  1334. process_ship_to_beach();
  1335. break;
  1336. case ACTION_GO_CAST_POWER:
  1337. process_go_cast_power();
  1338. break;
  1339. }
  1340. //-****** don't add code here, the unit may be removed after the above function call*******-//
  1341. // ###### begin Gilbert 20/6 ########//
  1342. #ifdef DEBUG
  1343. // do not read data member
  1344. LOG_MSG( " end Unit::pre_process()" );
  1345. LOG_MSG( m.get_random_seed() );
  1346. #endif
  1347. // ###### end Gilbert 20/6 ########//
  1348. }
  1349. //----------- End of function Unit::pre_process -----------//
  1350. //--------- Begin of function Unit::process_die ---------//
  1351. // process unit die
  1352. //
  1353. // return 1 if die frame is counting
  1354. // return 0 otherwise
  1355. //
  1356. int Unit::process_die()
  1357. {
  1358. //-*********** simulate aat ************-//
  1359. #ifdef DEBUG
  1360. if(debug_sim_game_type)
  1361. {
  1362. cur_action = SPRITE_IDLE;
  1363. hit_points = max_hit_points;
  1364. stop2();
  1365. return 0;
  1366. }
  1367. #endif
  1368. //-*********** simulate aat ************-//
  1369. //--------- voice ------------//
  1370. se_res.sound(cur_x_loc(), cur_y_loc(), cur_frame, 'S',sprite_id,"DIE");
  1371. // ####### begin Gilbert 14/7 ###########//
  1372. //------------- add die effect on first frame --------- //
  1373. if( cur_frame == 1 && unit_res[unit_id]->die_effect_id)
  1374. {
  1375. Effect::create(unit_res[unit_id]->die_effect_id, cur_x, cur_y,
  1376. SPRITE_DIE, cur_dir, mobile_type == UNIT_AIR ? 8 : 2, 0);
  1377. }
  1378. // ####### end Gilbert 14/7 ###########//
  1379. //--------- next frame ---------//
  1380. if( ++cur_frame > sprite_info->die.frame_count )
  1381. return 1;
  1382. return 0;
  1383. }
  1384. //----------- End of function Unit::process_die -----------//
  1385. //--------- Begin of function Unit::process_rebel ---------//
  1386. //
  1387. // Unit::process_rebel() is in OREBEL.CPP
  1388. //
  1389. //----------- End of function Unit::process_rebel ---------//
  1390. //--------- Begin of function Unit::avail_node_enough_for_search --------//
  1391. // decide whether the available number of nodes enough for a valid path searching
  1392. //
  1393. // <short> x1, y1 - start location
  1394. // <short> x2, y2 - end location
  1395. //
  1396. // return 1 if num of nodes is enough
  1397. // return 0 otherwise
  1398. //
  1399. int Unit::avail_node_enough_for_search(short x1, short y1, short x2, short y2)
  1400. {
  1401. short dispX = abs(x1-x2);
  1402. short dispY = abs(y1-y2);
  1403. short majDist = dispX>dispY ? dispX : dispY;
  1404. short minDist = abs(dispX-dispY);
  1405. int nodeRequire = min(VALID_BACKGROUND_SEARCH_NODE, majDist<<5); // *32
  1406. int totalNode = seek_path.total_node_avail;
  1407. if(totalNode < nodeRequire)
  1408. {
  1409. if(totalNode>=MIN_BACKGROUND_NODE_USED_UP)
  1410. seek_path.total_node_avail = MIN_BACKGROUND_NODE_USED_UP-1;
  1411. return 0;
  1412. }
  1413. return 1;
  1414. }
  1415. //----------- End of function Unit::avail_node_enough_for_search -----------//
  1416. //--------- Begin of function Unit::process_move --------//
  1417. // process unit movement
  1418. //
  1419. void Unit::process_move()
  1420. {
  1421. //----- if the sprite has reach the destintion ----//
  1422. //--------------------------------------------------------//
  1423. // if the unit reach its destination, then
  1424. // cur_? == next_? == go_?
  1425. //--------------------------------------------------------//
  1426. err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
  1427. if(cur_x==go_x && cur_y==go_y)
  1428. {
  1429. if(result_node_array)
  1430. {
  1431. next_move();
  1432. if( cur_action != SPRITE_MOVE ) // if next_move() is not successful, the movement has been stopped
  1433. return;
  1434. //---------------------------------------------------------------------------//
  1435. // If (1) the unit is blocked at cur_? == go_? and go_? != destination and
  1436. // (2) a new path is generated if calling the previous next_move(),
  1437. // then cur_? still equal to go_?.
  1438. //
  1439. // The following Sprite::process_move() call will set the unit to SPRITE_IDLE
  1440. // since cur_? == go_?. Thus, the unit terminates its move although it has not
  1441. // reached its destination.
  1442. //
  1443. // (note: if it has reached its destination, cur_? == go_? and cur_action =
  1444. // SPRITE_IDLE)
  1445. //
  1446. // if the unit is still moving and cur_? == go_?, call next_move() again to reset
  1447. // the go_?.
  1448. //---------------------------------------------------------------------------//
  1449. if(cur_action==SPRITE_MOVE && cur_x==go_x && cur_y==go_y)
  1450. next_move();
  1451. }
  1452. }
  1453. err_when(result_node_array && result_node_count==result_node_recno &&
  1454. (result_node_array[result_node_count-1].node_x!=go_x>>ZOOM_X_SHIFT_COUNT ||
  1455. result_node_array[result_node_count-1].node_y!=go_y>>ZOOM_Y_SHIFT_COUNT));
  1456. //--------- process the move, update sprite position ---------//
  1457. //--------------------------------------------------------//
  1458. // if the unit is moving, cur_?!=go_? and
  1459. // if next_? != cur_?, the direction from cur_? to next_?
  1460. // should equal to that from cur_? to go_?
  1461. //--------------------------------------------------------//
  1462. err_when((cur_x%ZOOM_LOC_WIDTH==0 && cur_y%ZOOM_LOC_HEIGHT==0) && (cur_x!=next_x || cur_y!=next_y) &&
  1463. ((check_unit_dir1=get_dir(cur_x, cur_y, go_x, go_y))!=(check_unit_dir2=get_dir(cur_x, cur_y, next_x, next_y))));
  1464. #ifdef DEBUG
  1465. int debugCurX = cur_x;
  1466. int debugCurY = cur_y;
  1467. int debugNextX = next_x;
  1468. int debugNextY = next_y;
  1469. int debugGoX = go_x;
  1470. int debugGoY = go_y;
  1471. #endif
  1472. err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));
  1473. err_when(result_path_dist && result_node_array==NULL);
  1474. Sprite::process_move();
  1475. err_when( cur_x < 0 || cur_y < 0 || cur_x >= ZOOM_X_PIXELS || cur_y >= ZOOM_Y_PIXELS );
  1476. if(cur_x==go_x && cur_y==go_y && cur_action==SPRITE_IDLE) // the sprite has reached its destination
  1477. {
  1478. move_to_x_loc = next_x_loc();
  1479. move_to_y_loc = next_y_loc();
  1480. }
  1481. //--------------------------------------------------------//
  1482. // after Sprite::process_move(), if the unit is blocked, its
  1483. // cur_action is set to SPRITE_WAIT. Otherwise, its cur_action
  1484. // is still SPRITE_MOVE. Then cur_? != next_? if the unit
  1485. // has not reached its destination.
  1486. //--------------------------------------------------------//
  1487. err_when(cur_action==SPRITE_MOVE && (cur_x!=go_x || cur_y!=go_y) && (cur_x==next_x && cur_y==next_y));
  1488. }
  1489. //---------- End of function Unit::process_move ----------//
  1490. //--------- Begin of function Unit::process_wait ---------//
  1491. // process unit's waiting
  1492. //
  1493. void Unit::process_wait()
  1494. {
  1495. err_when((check_unit_dir1=get_dir(cur_x, cur_y, go_x, go_y))!=final_dir);
  1496. if(!match_dir())
  1497. return;
  1498. //-----------------------------------------------------//
  1499. // If the unit is moving to the destination and was
  1500. // blocked by something. If it is now no longer blocked,
  1501. // continue the movement.
  1502. //-----------------------------------------------------//
  1503. //
  1504. // When this funciton is called:
  1505. //
  1506. // (next_x, next_y)==(cur_x, cur_y), it's the location of the sprite.
  1507. //
  1508. //-----------------------------------------------------//
  1509. //--- find out the next location which the sprite should be moving towards ---//
  1510. //-----------------------------------------------------//
  1511. // If the unit is waiting,
  1512. // go_? != cur_?
  1513. // go_? != next_?
  1514. //
  1515. // If the unit is not under swapping, the next_?_loc()
  1516. // is always the move_to_?_loc. Thus, the unit is ordered
  1517. // to stop.
  1518. //-----------------------------------------------------//
  1519. err_when( (go_x>>ZOOM_X_SHIFT_COUNT!=move_to_x_loc || go_y>>ZOOM_Y_SHIFT_COUNT!=move_to_y_loc) &&
  1520. ( (cur_x==go_x && cur_y==go_y) || (cur_x!=next_x || cur_y!=next_y) ) );
  1521. if(next_x_loc()==move_to_x_loc && next_y_loc()==move_to_y_loc && !swapping)
  1522. {
  1523. terminate_move();
  1524. return; // terminate since already in destination
  1525. }
  1526. int stepMagn = move_step_magn();
  1527. int nextX = cur_x+stepMagn*move_x_pixel_array[final_dir];
  1528. int nextY = cur_y+stepMagn*move_y_pixel_array[final_dir];
  1529. /*short w, h, blocked=0;
  1530. short x, y, blockedX, blockedY;
  1531. Location* locPtr;
  1532. //---------- check whether the unit is blocked -----------//
  1533. for(h=0, y=nextY>>ZOOM_Y_SHIFT_COUNT; h<sprite_info->loc_height && !blocked; h++, y++)
  1534. {
  1535. for(w=0, x=nextX>>ZOOM_X_SHIFT_COUNT; w<sprite_info->loc_width && !blocked; w++, x++)
  1536. {
  1537. locPtr = world.get_loc(x, y);
  1538. blocked = ( (!locPtr->is_accessible(mobile_type)) || (locPtr->has_unit(mobile_type) &&
  1539. locPtr->unit_recno(mobile_type)!=sprite_recno) );
  1540. if(blocked)
  1541. {
  1542. blockedX = x;
  1543. blockedY = y;
  1544. }
  1545. }
  1546. }*/
  1547. short x = nextX>>ZOOM_X_SHIFT_COUNT;
  1548. short y = nextY>>ZOOM_Y_SHIFT_COUNT;
  1549. Location *locPtr = world.get_loc(x, y);
  1550. short blocked = ( (!locPtr->is_accessible(mobile_type)) || (locPtr->has_unit(mobile_type) &&
  1551. locPtr->unit_recno(mobile_type)!=sprite_recno) );
  1552. if(!blocked || move_action_call_flag)
  1553. {
  1554. //--------- not blocked, continue to move --------//
  1555. waiting_term = 0;
  1556. set_move();
  1557. cur_frame = 1;
  1558. set_next(nextX, nextY, -stepMagn, 1);
  1559. }
  1560. else
  1561. {
  1562. //------- blocked, call handle_blocked_move() ------//
  1563. //locPtr = world.get_loc(blockedX, blockedY);
  1564. err_when(cur_x!=next_x || cur_y!=next_y);
  1565. handle_blocked_move(locPtr);
  1566. }
  1567. err_when(cur_action==SPRITE_MOVE && (cur_x!=go_x || cur_y!=go_y) && (cur_x==next_x && cur_y==next_y));
  1568. err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
  1569. }
  1570. //----------- End of function Unit::process_wait -----------//
  1571. //--------- Begin of function Unit::set_next --------//
  1572. // set the next coordinates to move to
  1573. //
  1574. // <int> newNextX, newNextY - next coordinate to move to
  1575. // <int> para - used to count the result_path_dist
  1576. // <int> blockedChecked - whether the next location specified is checked to be
  1577. // non-blocked. 1 checked for non-blocked, 0 for not checked
  1578. //
  1579. void Unit::set_next(int newNextX, int newNextY, int para, int blockedChecked)
  1580. {
  1581. int curNextXLoc = next_x_loc();
  1582. int curNextYLoc = next_y_loc();
  1583. int newNextXLoc = newNextX >> ZOOM_X_SHIFT_COUNT;
  1584. int newNextYLoc = newNextY >> ZOOM_Y_SHIFT_COUNT;
  1585. #ifdef DEBUG
  1586. int debugStepMagn = move_step_magn();
  1587. err_when(abs(curNextXLoc-newNextXLoc)>debugStepMagn || abs(curNextYLoc-newNextYLoc)>debugStepMagn);
  1588. #endif
  1589. if(curNextXLoc!=newNextXLoc || curNextYLoc!=newNextYLoc)
  1590. {
  1591. if(!match_dir())
  1592. {
  1593. set_wait();
  1594. return;
  1595. }
  1596. }
  1597. //short w, h, blocked=0;
  1598. //short x, y, blockedX, blockedY;
  1599. short w, h, blocked=0;
  1600. short x, y;
  1601. #ifdef DEBUG
  1602. for(h=0, y=curNextYLoc; h<sprite_info->loc_height; h++, y++)
  1603. for(w=0, x=curNextXLoc; w<sprite_info->loc_width; w++, x++)
  1604. err_when( world.get_unit_recno(x, y, mobile_type) != sprite_recno ); // it must be 0 to put the sprite in this location
  1605. #endif
  1606. if( curNextXLoc != newNextXLoc || curNextYLoc != newNextYLoc )
  1607. {
  1608. //------- if the next location is blocked ----------//
  1609. Location* locPtr;
  1610. if(!blockedChecked)
  1611. {
  1612. /*for(h=0, y=newNextYLoc; h<sprite_info->loc_height && !blocked; h++, y++)
  1613. {
  1614. for(w=0, x=newNextXLoc; w<sprite_info->loc_width && !blocked; w++, x++)
  1615. {
  1616. locPtr = world.get_loc(x, y);
  1617. blocked = ( (!locPtr->is_accessible(mobile_type)) || (locPtr->has_unit(mobile_type) &&
  1618. locPtr->unit_recno(mobile_type)!=sprite_recno) );
  1619. if(blocked)
  1620. {
  1621. blockedX = x;
  1622. blockedY = y;
  1623. }
  1624. }
  1625. }*/
  1626. x = newNextXLoc;
  1627. y = newNextYLoc;
  1628. locPtr = world.get_loc(x, y);
  1629. blocked = ( (!locPtr->is_accessible(mobile_type)) || (locPtr->has_unit(mobile_type) &&
  1630. locPtr->unit_recno(mobile_type)!=sprite_recno) );
  1631. }//else, then blockedChecked = 0
  1632. //--- no change to next_x & next_y if the new next location is blocked ---//
  1633. if(blocked)
  1634. {
  1635. set_cur(next_x, next_y); // align the sprite to 32x32 location when it stops
  1636. //------ avoid infinitely looping in calling handle_blocked_move() ------//
  1637. if(blocked_by_member || move_action_call_flag)
  1638. {
  1639. set_wait();
  1640. blocked_by_member = 0;
  1641. }
  1642. else
  1643. {
  1644. locPtr = world.get_loc(x, y);
  1645. handle_blocked_move(locPtr);
  1646. }
  1647. #ifdef DEBUG
  1648. for(h=0, y=next_y_loc(); h<sprite_info->loc_height; h++, y++)
  1649. {
  1650. for(w=0, x=next_x_loc(); w<sprite_info->loc_width; w++, x++)
  1651. err_when( world.get_unit_recno(x, y, mobile_type) != sprite_recno ); // it must be 0 to put the sprite in this location
  1652. }
  1653. #endif
  1654. }
  1655. else
  1656. {
  1657. err_when(mobile_type!=UNIT_LAND && (abs(para)!=2 || result_path_dist%2));
  1658. if(para)
  1659. {
  1660. #ifdef DEBUG
  1661. int count=0, ii;
  1662. int dist;
  1663. int curXLoc = next_x_loc();
  1664. int curYLoc = next_y_loc();
  1665. ResultNode *curNode = result_node_array + result_node_recno -1;
  1666. ResultNode *nextNode;
  1667. dist = m.points_distance(curXLoc, curYLoc, curNode->node_x, curNode->node_y);
  1668. if(result_node_recno>1)
  1669. count += dist;
  1670. else
  1671. count -= dist;
  1672. for(ii=result_node_recno, nextNode=curNode+1; ii<result_node_count; ii++, curNode++, nextNode++)
  1673. {
  1674. dist = m.points_distance(nextNode->node_x, nextNode->node_y, curNode->node_x, curNode->node_y);
  1675. count += dist;
  1676. }
  1677. err_when(result_path_dist!=count);
  1678. #endif
  1679. //----------------------------------------------------------------------------//
  1680. // calculate the result_path_dist as the unit move from one tile to another
  1681. //----------------------------------------------------------------------------//
  1682. result_path_dist += para;
  1683. }
  1684. next_x = newNextX;
  1685. next_y = newNextY;
  1686. swapping = blocked_by_member = 0;
  1687. //---- move sprite_recno to the next location ------//
  1688. for(h=0, y=curNextYLoc; h<sprite_info->loc_height; h++, y++)
  1689. {
  1690. for(w=0, x=curNextXLoc; w<sprite_info->loc_width; w++, x++)
  1691. world.set_unit_recno(x, y, mobile_type, 0);
  1692. }
  1693. for(h=0, y=next_y_loc(); h<sprite_info->loc_height; h++, y++)
  1694. {
  1695. for(w=0, x=next_x_loc(); w<sprite_info->loc_width; w++, x++)
  1696. world.set_unit_recno(x, y, mobile_type, sprite_recno);
  1697. }
  1698. //--------- explore land ----------//
  1699. // ###### begin Gilbert 24/5 ######//
  1700. if( !config.explore_whole_map && is_own() )
  1701. // ###### end Gilbert 24/5 ######//
  1702. {
  1703. int xLoc1 = max(0,newNextXLoc-EXPLORE_RANGE);
  1704. int yLoc1 = max(0,newNextYLoc-EXPLORE_RANGE);
  1705. int xLoc2 = min(MAX_WORLD_X_LOC-1, newNextXLoc+EXPLORE_RANGE);
  1706. int yLoc2 = min(MAX_WORLD_Y_LOC-1, newNextYLoc+EXPLORE_RANGE);
  1707. int exploreWidth = move_step_magn()-1;
  1708. if( newNextYLoc < curNextYLoc ) // if move upwards, explore upper area
  1709. world.explore(xLoc1, yLoc1, xLoc2, yLoc1+exploreWidth);
  1710. else if( newNextYLoc > curNextYLoc ) // if move downwards, explore lower area
  1711. world.explore(xLoc1, yLoc2-exploreWidth, xLoc2, yLoc2);
  1712. if( newNextXLoc < curNextXLoc ) // if move towards left, explore left area
  1713. world.explore(xLoc1, yLoc1, xLoc1+exploreWidth, yLoc2);
  1714. else if( newNextXLoc > curNextXLoc ) // if move towards right, explore right area
  1715. world.explore(xLoc2-exploreWidth, yLoc1, xLoc2, yLoc2);
  1716. }
  1717. }
  1718. }
  1719. err_when(cur_x!=next_x && cur_y!=next_y && // is not blocked
  1720. (check_unit_dir1=get_dir(cur_x, cur_y, next_x, next_y))!=(check_unit_dir2=get_dir(cur_x, cur_y, go_x, go_y)));
  1721. }
  1722. //---------- End of function Unit::set_next ----------//
  1723. //------ Begin of function Unit::blocked_move_new_handle -------//
  1724. /*int Unit::blocked_move_new_handle()
  1725. {
  1726. //------------------------------------------------------------------//
  1727. // new handling for blocked move
  1728. //------------------------------------------------------------------//
  1729. static int counter = 0;
  1730. int checkXLoc1, checkYLoc1, checkXLoc2, checkYLoc2;
  1731. int curXLoc = next_x_loc(), curYLoc = next_y_loc();
  1732. Location *locPtr;
  1733. counter++;
  1734. switch(final_dir)
  1735. {
  1736. case DIR_N:
  1737. checkXLoc1 = min(curXLoc+1, MAX_WORLD_X_LOC-1);
  1738. checkYLoc1 = checkYLoc2 = max(curYLoc-1, 0);
  1739. checkXLoc2 = max(curXLoc-1, 0);
  1740. break;
  1741. case DIR_NE:
  1742. checkXLoc1 = min(curXLoc+1, MAX_WORLD_X_LOC-1);
  1743. checkYLoc1 = curYLoc;
  1744. checkXLoc2 = curXLoc;
  1745. checkYLoc2 = max(curYLoc-1, 0);
  1746. break;
  1747. case DIR_E:
  1748. checkXLoc1 = checkXLoc2 = min(curXLoc+1, MAX_WORLD_X_LOC-1);
  1749. checkYLoc1 = min(curYLoc+1, MAX_WORLD_Y_LOC-1);
  1750. checkYLoc2 = max(curYLoc-1, 0);
  1751. break;
  1752. case DIR_SE:
  1753. checkXLoc1 = curXLoc;
  1754. checkYLoc1 = min(curYLoc+1, MAX_WORLD_Y_LOC-1);
  1755. checkXLoc2 = min(curXLoc+1, MAX_WORLD_X_LOC-1);
  1756. checkYLoc2 = curYLoc;
  1757. break;
  1758. case DIR_S:
  1759. checkXLoc1 = max(curXLoc-1, 0);
  1760. checkYLoc1 = checkYLoc2 = min(curYLoc+1, MAX_WORLD_Y_LOC-1);
  1761. checkXLoc2 = min(curXLoc+1, MAX_WORLD_X_LOC-1);
  1762. break;
  1763. case DIR_SW:
  1764. checkXLoc1 = max(curXLoc-1, 0);
  1765. checkYLoc1 = curYLoc;
  1766. checkXLoc2 = curXLoc;
  1767. checkYLoc2 = min(curYLoc, MAX_WORLD_Y_LOC-1);
  1768. break;
  1769. case DIR_W:
  1770. checkXLoc1 = checkXLoc2 = max(curXLoc-1, 0);
  1771. checkYLoc1 = max(curYLoc-1, 0);
  1772. checkYLoc2 = min(curYLoc+1, MAX_WORLD_Y_LOC-1);
  1773. break;
  1774. case DIR_NW:
  1775. checkXLoc1 = curXLoc;
  1776. checkYLoc1 = max(curYLoc-1, 0);
  1777. checkXLoc2 = max(curXLoc-1, 0);
  1778. checkYLoc2 = curYLoc;
  1779. break;
  1780. }
  1781. locPtr = world.get_loc(checkXLoc1, checkYLoc1);
  1782. if(locPtr->can_move(mobile_type))
  1783. set_path_to(checkXLoc1, checkYLoc1);
  1784. else
  1785. {
  1786. locPtr = world.get_loc(checkXLoc2, checkYLoc2);
  1787. if(locPtr->can_move(mobile_type))
  1788. set_path_to(checkXLoc2, checkYLoc2);
  1789. else
  1790. return 0;
  1791. }
  1792. return 1;
  1793. }*/
  1794. //------- End of function Unit::blocked_move_new_handle --------//
  1795. //------ Begin of function Unit::set_path_to -------//
  1796. /*void Unit::set_path_to(int destXLoc, int destYLoc)
  1797. {
  1798. //reset_path();
  1799. terminate_move();
  1800. result_node_array = (ResultNode*) mem_add(2*sizeof(ResultNode));
  1801. ResultNode *curNodePtr = result_node_array;
  1802. curNodePtr->node_x = next_x_loc();
  1803. curNodePtr->node_y = next_y_loc();
  1804. curNodePtr++;
  1805. curNodePtr->node_x = destXLoc;
  1806. curNodePtr->node_y = destYLoc;
  1807. result_node_count = 2;
  1808. result_node_recno = 1;
  1809. result_path_dist = 1;
  1810. move_to_x_loc = destXLoc;
  1811. move_to_y_loc = destYLoc;
  1812. go_x = destXLoc*ZOOM_LOC_WIDTH;
  1813. go_y = destYLoc*ZOOM_LOC_HEIGHT;
  1814. //set_dir(cur_x, cur_y, go_x, go_y);
  1815. //set_wait();
  1816. next_move();
  1817. }*/
  1818. //------- End of function Unit::set_path_to --------//
  1819. //------ Begin of function Unit::handle_blocked_move -------//
  1820. // Note: it assumes the given location is blocked, it makes no
  1821. // further attempt to verify it.
  1822. //
  1823. // <Location*> blockedLoc - blocked location
  1824. //
  1825. // return : <int> 1 - handled successfully
  1826. // 0 - cannot be handled, the movement must be terminated
  1827. //
  1828. void Unit::handle_blocked_move(Location* blockedLoc)
  1829. {
  1830. //--- check if the tile we are moving at is blocked by a building ---//
  1831. if(blockedLoc->is_firm() || blockedLoc->is_town() || blockedLoc->is_wall())
  1832. {
  1833. //------------------------------------------------//
  1834. // firm/town/wall is on the blocked location
  1835. //------------------------------------------------//
  1836. reset_path();
  1837. search_or_stop(move_to_x_loc, move_to_y_loc, 1);
  1838. //search(move_to_x_loc, move_to_y_loc, 1);
  1839. return;
  1840. }
  1841. if(next_x_loc()==move_to_x_loc && next_y_loc()==move_to_y_loc && !swapping)
  1842. {
  1843. terminate_move(); // terminate since already reaching destination
  1844. return;
  1845. }
  1846. if(!blockedLoc->is_accessible(mobile_type))
  1847. {
  1848. terminate_move(); // the location is not accessible
  1849. err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
  1850. return;
  1851. }
  1852. //-----------------------------------------------------------------------------------//
  1853. // there is another sprite on the move_to location, check the combination of both sizes
  1854. //-----------------------------------------------------------------------------------//
  1855. blocked_by_member = 1;
  1856. err_when(!blockedLoc->unit_recno(mobile_type));
  1857. Unit* unitPtr = unit_array[blockedLoc->unit_recno(mobile_type)];
  1858. //if(unitPtr->sprite_info->loc_width>1 || sprite_info->loc_width>1)
  1859. //{
  1860. // set_wait();
  1861. // return;
  1862. //}
  1863. //else
  1864. handle_blocked_move_s11(unitPtr); //------ both units size 1x1
  1865. err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
  1866. return;
  1867. }
  1868. //------- End of function Unit::handle_blocked_move --------//
  1869. //------ Begin of function Unit::handle_blocked_by_idle_unit ---------//
  1870. // handle the case blocked by idle unit
  1871. //
  1872. // <Unit*> unitPtr - the unit blocking this unit
  1873. //
  1874. void Unit::handle_blocked_by_idle_unit(Unit *unitPtr)
  1875. {
  1876. #define TEST_DIMENSION 10
  1877. #define TEST_LIMIT TEST_DIMENSION*TEST_DIMENSION
  1878. char notLandUnit = (mobile_type!=UNIT_LAND);
  1879. int unitXLoc = unitPtr->next_x_loc();
  1880. int unitYLoc = unitPtr->next_y_loc();
  1881. int xShift, yShift;
  1882. int checkXLoc, checkYLoc;
  1883. Location *locPtr;
  1884. int xSign = m.random(2) ? 1 : -1;
  1885. int ySign = m.random(2) ? 1 : -1;
  1886. for(int i=2; i<=TEST_LIMIT; i++)
  1887. {
  1888. m.cal_move_around_a_point(i, TEST_DIMENSION, TEST_DIMENSION, xShift, yShift);
  1889. xShift *= xSign;
  1890. yShift *= ySign;
  1891. if(notLandUnit)
  1892. {
  1893. checkXLoc = unitXLoc + xShift*2;
  1894. checkYLoc = unitYLoc + yShift*2;
  1895. }
  1896. else
  1897. {
  1898. checkXLoc = unitXLoc + xShift;
  1899. checkYLoc = unitYLoc + yShift;
  1900. }
  1901. if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
  1902. continue;
  1903. locPtr = world.get_loc(checkXLoc , checkYLoc);
  1904. if(!locPtr->can_move(unitPtr->mobile_type))
  1905. continue;
  1906. if(on_my_path(checkXLoc, checkYLoc))
  1907. continue;
  1908. unitPtr->move_to(checkXLoc, checkYLoc);
  1909. set_wait();
  1910. return;
  1911. }
  1912. stop(KEEP_DEFENSE_MODE);
  1913. //--------------------------------------------------------------------------------//
  1914. // improved version!!!
  1915. //--------------------------------------------------------------------------------//
  1916. /*int testResult = 0, worstCase=0;
  1917. int worstXLoc=-1, worstYLoc=-1;
  1918. int startCount, endCount;
  1919. int i, j;
  1920. for(j=0; j<2; j++)
  1921. {
  1922. //----------- set the startCount and endCount ------------//
  1923. if(j==0)
  1924. {
  1925. startCount = 2;
  1926. endCount = 9;
  1927. }
  1928. else
  1929. {
  1930. startCount = 10;
  1931. endCount = TEST_LIMIT;
  1932. }
  1933. for(i=startCount; i<=endCount; i++)
  1934. {
  1935. m.cal_move_around_a_point(i, TEST_DIMENSION, TEST_DIMENSION, xShift, yShift);
  1936. if(notLandUnit)
  1937. {
  1938. checkXLoc = unitXLoc + xShift*2;
  1939. checkYLoc = unitYLoc + yShift*2;
  1940. }
  1941. else
  1942. {
  1943. checkXLoc = unitXLoc + xShift;
  1944. checkYLoc = unitYLoc + yShift;
  1945. }
  1946. if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
  1947. continue;
  1948. locPtr = world.get_loc(checkXLoc , checkYLoc);
  1949. if(!locPtr->can_move(unitPtr->mobile_type))
  1950. continue;
  1951. //-------------------------------------------------------------------//
  1952. // a possible location
  1953. //-------------------------------------------------------------------//
  1954. testResult = on_my_path(checkXLoc, checkYLoc);
  1955. if(testResult)
  1956. {
  1957. if(j==0 && !worstCase)
  1958. {
  1959. worstCase++;
  1960. worstXLoc = checkXLoc;
  1961. worstYLoc = checkYLoc;
  1962. }
  1963. continue;
  1964. }
  1965. unitPtr->move_to(checkXLoc, checkYLoc):
  1966. set_wait();
  1967. return;
  1968. }
  1969. }
  1970. //-------------------------------------------------------------------//
  1971. if(worstCase)
  1972. {
  1973. unitPtr->move_to(worstXLoc, worstYLoc);
  1974. set_wait();
  1975. }
  1976. else
  1977. stop(KEEP_DEFENSE_MODE);*/
  1978. }
  1979. //------- End of function Unit::handle_blocked_by_idle_unit --------//
  1980. //------ Begin of function Unit::on_my_path ---------//
  1981. // This function is used to check whether a location
  1982. // (checkXLoc, checkYLoc) is on the unit path, result_node_array.
  1983. //
  1984. // return 1 if true
  1985. // return 0 otherwise
  1986. //
  1987. int Unit::on_my_path(short checkXLoc, short checkYLoc)
  1988. {
  1989. err_when(result_node_count<2);
  1990. ResultNode* curNodePtr = result_node_array+result_node_recno-2;
  1991. ResultNode* nextNodePtr = curNodePtr+1;
  1992. for(int i=result_node_recno-1; i<result_node_count; i++, curNodePtr++, nextNodePtr++)
  1993. {
  1994. if((curNodePtr->node_x-checkXLoc)*(checkYLoc-nextNodePtr->node_y)==
  1995. (curNodePtr->node_y-checkYLoc)*(checkXLoc-nextNodePtr->node_x)) // point of division
  1996. return 1;
  1997. }
  1998. return 0;
  1999. }
  2000. //------- End of function Unit::on_my_path --------//
  2001. //------ Begin of function Unit::handle_blocked_wait ---------//
  2002. //
  2003. // this function is worked for unit size 1x1 only to handle case that
  2004. // blocked by waiting unit
  2005. //
  2006. // <Unit*> unitPtr - unit blocking this unit
  2007. //
  2008. void Unit::handle_blocked_wait(Unit* unitPtr)
  2009. {
  2010. err_when(sprite_info->loc_width>1 || unitPtr->sprite_info->loc_width>1);
  2011. int stepMagn = move_step_magn();
  2012. short cycleWait = 0;
  2013. Location *locPtr;
  2014. if(is_dir_correct())
  2015. {
  2016. Unit *blockedUnitPtr = unitPtr;
  2017. SpriteInfo *unitSpriteInfo = unitPtr->sprite_info;
  2018. int nextX, nextY, loop = 0, i;
  2019. short blocked=0;
  2020. //---------------------------------------------------------------//
  2021. // construct a cycle_waiting array to store the sprite_recno of
  2022. // those units in cycle_waiting in order to prevent forever looping
  2023. // in the checking
  2024. //---------------------------------------------------------------//
  2025. int arraySize = 20;
  2026. cycle_wait_unit_array_def_size = arraySize;
  2027. cycle_wait_unit_index = 0;
  2028. cycle_wait_unit_array_multipler = 1;
  2029. cycle_wait_unit_array = (short*)mem_add(sizeof(short)*cycle_wait_unit_array_def_size);
  2030. memset(cycle_wait_unit_array, 0, sizeof(short)*cycle_wait_unit_array_def_size);
  2031. //---------------------------------------------------------------//
  2032. // don't handle the case blocked by size 2x2 unit in this moment
  2033. //---------------------------------------------------------------//
  2034. while(!cycleWait && blockedUnitPtr->cur_action==SPRITE_WAIT)
  2035. {
  2036. if(unitSpriteInfo->loc_width>1)
  2037. break; // don't handle unit size > 1
  2038. if(!blockedUnitPtr->is_dir_correct())
  2039. break;
  2040. //----------------------------------------------------------------------------------------//
  2041. // cur_x, cur_y of unit pointed by blockedUnitPtr should be exactly inside a tile
  2042. //----------------------------------------------------------------------------------------//
  2043. nextX = blockedUnitPtr->cur_x+stepMagn*move_x_pixel_array[blockedUnitPtr->final_dir];
  2044. nextY = blockedUnitPtr->cur_y+stepMagn*move_y_pixel_array[blockedUnitPtr->final_dir];
  2045. //---------- calculate location blocked unit attempts to move to ---------//
  2046. nextX >>= ZOOM_X_SHIFT_COUNT;
  2047. nextY >>= ZOOM_Y_SHIFT_COUNT;
  2048. locPtr = world.get_loc(nextX, nextY);
  2049. blocked = locPtr->has_unit(mobile_type);
  2050. //---------------- the unit is also waiting ---------------//
  2051. if(blocked && (blockedUnitPtr->move_to_x_loc!=blockedUnitPtr->cur_x_loc() ||
  2052. blockedUnitPtr->move_to_y_loc!=blockedUnitPtr->cur_y_loc()))
  2053. {
  2054. if(locPtr->unit_recno(mobile_type) == sprite_recno)
  2055. cycleWait = 1;
  2056. else
  2057. {
  2058. for(i=0; i<cycle_wait_unit_index; i++)
  2059. {
  2060. //---------- checking for forever loop ----------------//
  2061. if(cycle_wait_unit_array[i] == blockedUnitPtr->sprite_recno)
  2062. {
  2063. loop = 1;
  2064. break;
  2065. }
  2066. }
  2067. if(loop)
  2068. break;
  2069. //------------------------------------------------------//
  2070. // resize array if required size is larger than arraySize
  2071. //------------------------------------------------------//
  2072. if(cycle_wait_unit_index >= arraySize)
  2073. {
  2074. cycle_wait_unit_array_multipler++;
  2075. arraySize = cycle_wait_unit_array_def_size*cycle_wait_unit_array_multipler;
  2076. cycle_wait_unit_array = (short*) mem_resize(cycle_wait_unit_array, sizeof(short)*arraySize);
  2077. }
  2078. else
  2079. {
  2080. //-------- store recno of next blocked unit ----------//
  2081. cycle_wait_unit_array[cycle_wait_unit_index++] = blockedUnitPtr->sprite_recno;
  2082. locPtr = world.get_loc(nextX, nextY);
  2083. err_when(blockedUnitPtr->mobile_type!=mobile_type);
  2084. blockedUnitPtr = unit_array[locPtr->unit_recno(mobile_type)];
  2085. unitSpriteInfo = blockedUnitPtr->sprite_info;
  2086. }
  2087. }
  2088. }
  2089. else
  2090. break;
  2091. }
  2092. //---------- deinit data structure -------//
  2093. mem_del(cycle_wait_unit_array);
  2094. cycle_wait_unit_array = NULL;
  2095. }
  2096. if(cycleWait)
  2097. {
  2098. //----------------------------------------------------------------------//
  2099. // shift the recno of all the unit in the cycle
  2100. //----------------------------------------------------------------------//
  2101. err_when(!is_dir_correct());
  2102. short backupSpriteRecno;
  2103. world.set_unit_recno(cur_x_loc(), cur_y_loc(), mobile_type, 0); // empty the firt node in the cycle
  2104. cycle_wait_shift_recno(this, unitPtr); // shift all the unit in the cycle
  2105. backupSpriteRecno = world.get_unit_recno(cur_x_loc(), cur_y_loc(), mobile_type);
  2106. world.set_unit_recno(cur_x_loc(), cur_y_loc(), mobile_type, sprite_recno);
  2107. set_next(unitPtr->cur_x, unitPtr->cur_y, -stepMagn, 1);
  2108. set_move();
  2109. world.set_unit_recno(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), mobile_type, sprite_recno);
  2110. world.set_unit_recno(cur_x_loc(), cur_y_loc(), mobile_type, backupSpriteRecno);
  2111. swapping = 1;
  2112. }
  2113. else // not in a cycle
  2114. {
  2115. set_wait();
  2116. //if(waiting_term>=MAX_WAITING_TERM_SAME)
  2117. if(waiting_term>=MAX_WAITING_TERM_SAME*move_step_magn())
  2118. {
  2119. //-----------------------------------------------------------------//
  2120. // codes used to speed up frame rate
  2121. //-----------------------------------------------------------------//
  2122. locPtr = world.get_loc(move_to_x_loc, move_to_y_loc);
  2123. if(!locPtr->can_move(mobile_type) && action_mode2!=ACTION_MOVE)
  2124. stop(KEEP_PRESERVE_ACTION); // let reactivate..() call searching later
  2125. else
  2126. search_or_wait();
  2127. waiting_term = 0;
  2128. }
  2129. }
  2130. }
  2131. //-------- End of function Unit::handle_blocked_wait ---------//
  2132. //------ Begin of function Unit::cycle_wait_shift_recno ---------//
  2133. // copy recno of curUnit to location where nextUnit on
  2134. //
  2135. // <Unit*> curUnit -
  2136. // <Unit*> nextUnit -
  2137. //
  2138. void Unit::cycle_wait_shift_recno(Unit* curUnit, Unit* nextUnit)
  2139. {
  2140. err_when(!curUnit->is_dir_correct() || !nextUnit->is_dir_correct());
  2141. int stepMagn = move_step_magn();
  2142. Unit *blockedUnitPtr;
  2143. Location *locPtr;
  2144. //----------- find the next location ------------//
  2145. int nextX = nextUnit->cur_x+stepMagn*move_x_pixel_array[nextUnit->final_dir];
  2146. int nextY = nextUnit->cur_y+stepMagn*move_y_pixel_array[nextUnit->final_dir];
  2147. nextX >>= ZOOM_X_SHIFT_COUNT;
  2148. nextY >>= ZOOM_Y_SHIFT_COUNT;
  2149. if(nextX != cur_x_loc() || nextY != cur_y_loc())
  2150. {
  2151. locPtr = world.get_loc(nextX, nextY);
  2152. blockedUnitPtr = unit_array[locPtr->unit_recno(nextUnit->mobile_type)];
  2153. }
  2154. else
  2155. blockedUnitPtr = this;
  2156. if(blockedUnitPtr != this)
  2157. {
  2158. cycle_wait_shift_recno(nextUnit, blockedUnitPtr);
  2159. nextUnit->set_next(blockedUnitPtr->cur_x, blockedUnitPtr->cur_y, -stepMagn, 1);
  2160. nextUnit->set_move();
  2161. world.set_unit_recno(blockedUnitPtr->cur_x_loc(), blockedUnitPtr->cur_y_loc(), nextUnit->mobile_type, nextUnit->sprite_recno);
  2162. world.set_unit_recno(nextUnit->cur_x_loc(), nextUnit->cur_y_loc(), nextUnit->mobile_type, 0);
  2163. nextUnit->swapping = 1;
  2164. }
  2165. else // the cycle shift is ended
  2166. {
  2167. err_when(blockedUnitPtr != this);
  2168. err_when(nextUnit->cur_x!=nextUnit->next_x || nextUnit->cur_y!=nextUnit->next_y);
  2169. err_when(nextUnit->cur_action != SPRITE_WAIT);
  2170. nextUnit->set_next(cur_x, cur_y, -stepMagn, 1);
  2171. nextUnit->set_move();
  2172. world.set_unit_recno(cur_x_loc(), cur_y_loc(), nextUnit->mobile_type, nextUnit->sprite_recno);
  2173. world.set_unit_recno(nextUnit->cur_x_loc(), nextUnit->cur_y_loc(), nextUnit->mobile_type, 0);
  2174. nextUnit->swapping = 1;
  2175. }
  2176. }
  2177. //-------- End of function Unit::cycle_wait_shift_recno ---------//
  2178. //------ Begin of function Unit::opposite_direction_blocked ---------//
  2179. // the two units are oppositely blocked, handle swapping
  2180. //
  2181. void Unit::opposite_direction_blocked(short vecX, short vecY, short unitPtrVecX, short unitPtrVecY, Unit* unitPtr)
  2182. {
  2183. //---------------------------------------------------------------------------//
  2184. // processing swapping only when both units are exactly in the tiles
  2185. //---------------------------------------------------------------------------//
  2186. if(unitPtr->cur_action!=SPRITE_IDLE)
  2187. {
  2188. if(unitPtr->move_to_x_loc!=move_to_x_loc || unitPtr->move_to_y_loc!=move_to_y_loc)
  2189. {
  2190. int stepMagn = move_step_magn();
  2191. world.set_unit_recno(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), mobile_type, 0);
  2192. err_when(!is_dir_correct());
  2193. set_next(unitPtr->cur_x, unitPtr->cur_y, -stepMagn, -1);
  2194. world.set_unit_recno(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), mobile_type, unitPtr->sprite_recno);
  2195. world.set_unit_recno(cur_x_loc(), cur_y_loc(), unitPtr->mobile_type, 0);
  2196. err_when(!unitPtr->is_dir_correct());
  2197. unitPtr->set_next(cur_x, cur_y, -stepMagn, 1);
  2198. world.set_unit_recno(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), mobile_type, sprite_recno);
  2199. world.set_unit_recno(cur_x_loc(), cur_y_loc(), unitPtr->mobile_type, unitPtr->sprite_recno);
  2200. set_move();
  2201. unitPtr->set_move();
  2202. swapping = 1;
  2203. unitPtr->swapping = 1;
  2204. #ifdef DEBUG
  2205. ResultNode* curNode;
  2206. curNode = result_node_array + result_node_count - 1;
  2207. err_when(curNode->node_x!=move_to_x_loc || curNode->node_y!=move_to_y_loc);
  2208. curNode = unitPtr->result_node_array + unitPtr->result_node_count - 1;
  2209. err_when(curNode->node_x!=unitPtr->move_to_x_loc || curNode->node_y!=unitPtr->move_to_y_loc);
  2210. #endif
  2211. }
  2212. else
  2213. terminate_move();
  2214. }
  2215. else
  2216. {
  2217. //----------------------------------------------------------------------//
  2218. // If the unit pointed by unitPtr (unit B) has the same unit_id, rank_id
  2219. // and both are in the same group, this unit will order the other unit to
  2220. // move to its location and this unit will occupy the location of the unit B.
  2221. //
  2222. // If the above condition is not fulfilled, swapping is processed.
  2223. //----------------------------------------------------------------------//
  2224. if(unit_id!=unitPtr->unit_id || rank_id!=unitPtr->rank_id || unit_group_id!=unitPtr->unit_group_id)
  2225. {
  2226. if(unitPtr->move_to_x_loc!=move_to_x_loc || unitPtr->move_to_y_loc!=move_to_y_loc)
  2227. {
  2228. //----------------- process swapping ---------------//
  2229. set_wait();
  2230. unitPtr->set_dir(unitPtr->next_x, unitPtr->next_y, next_x, next_y);
  2231. set_dir(next_x, next_y, unitPtr->next_x, unitPtr->next_y);
  2232. err_when(unitPtr->result_node_array!=NULL);
  2233. unitPtr->result_node_array = (ResultNode*)mem_add(sizeof(ResultNode)*2);
  2234. ResultNode* nodePtr = unitPtr->result_node_array;
  2235. err_when(next_x_loc()!= cur_x_loc() || next_y_loc()!=cur_y_loc());
  2236. nodePtr->node_x = next_x_loc();
  2237. nodePtr->node_y = next_y_loc();
  2238. nodePtr++;
  2239. nodePtr->node_x = unitPtr->next_x_loc();
  2240. nodePtr->node_y = unitPtr->next_y_loc();
  2241. unitPtr->result_node_count = 2;
  2242. unitPtr->result_node_recno = 1;
  2243. unitPtr->set_wait();
  2244. unitPtr->go_x = next_x;
  2245. unitPtr->go_y = next_y;
  2246. unitPtr->result_path_dist = 2;
  2247. err_when((check_unit_dir1=get_dir(cur_x, cur_y, go_x, go_y))!=final_dir);
  2248. swapping = 1;
  2249. unitPtr->swapping = 1;
  2250. }
  2251. else
  2252. terminate_move();
  2253. }
  2254. else
  2255. {
  2256. //------------ process move_to_my_loc or terminate the movement -----------//
  2257. if(unitPtr->move_to_x_loc!=move_to_x_loc || unitPtr->move_to_y_loc!=move_to_y_loc)
  2258. move_to_my_loc(unitPtr);
  2259. else
  2260. terminate_move();
  2261. }
  2262. #ifdef DEBUG
  2263. ResultNode* curNode;
  2264. if(result_node_array!=NULL)
  2265. {
  2266. curNode = result_node_array + result_node_count - 1;
  2267. err_when(curNode->node_x!=move_to_x_loc || curNode->node_y!=move_to_y_loc);
  2268. }
  2269. if(unitPtr->result_node_array!=NULL)
  2270. {
  2271. curNode = unitPtr->result_node_array + unitPtr->result_node_count - 1;
  2272. err_when(curNode->node_x!=unitPtr->move_to_x_loc || curNode->node_y!=unitPtr->move_to_y_loc);
  2273. }
  2274. #endif
  2275. }
  2276. }
  2277. //-------- End of function Unit::opposite_direction_blocked ---------//
  2278. //------ Begin of function Unit::terminate_move -------//
  2279. //
  2280. // When the sprite has finished moving the next tile in
  2281. // the path. If the following tile is blocked and the whole
  2282. // movement need to be terminated, this function is called.
  2283. //
  2284. // When SPRITE_IDLE:
  2285. //
  2286. // (next_x, next_y) must be == (cur_x, cur_y), it's the location of the sprite.
  2287. //
  2288. void Unit::terminate_move()
  2289. {
  2290. #ifdef DEBUG
  2291. err_when( next_x != cur_x || next_y != cur_y );
  2292. short h, y;
  2293. for(h=0, y=cur_y_loc(); h<sprite_info->loc_height; h++, y++)
  2294. for(short w=0, x=cur_x_loc(); w<sprite_info->loc_width; w++, x++)
  2295. err_when( world.get_unit_recno(x, y, mobile_type) != sprite_recno );
  2296. #endif
  2297. go_x = next_x;
  2298. go_y = next_y;
  2299. move_to_x_loc = next_x_loc();
  2300. move_to_y_loc = next_y_loc();
  2301. #ifdef DEBUG
  2302. char blocked=0;
  2303. for(h=0, y=next_y_loc(); h<sprite_info->loc_height&&!blocked; h++, y++)
  2304. for(short w=0, x=next_x_loc(); w<sprite_info->loc_width&&!blocked; w++, x++)
  2305. blocked = world.get_unit_recno(x,y,mobile_type) != sprite_recno;
  2306. err_when(blocked);
  2307. #endif
  2308. cur_frame = 1;
  2309. reset_path();
  2310. set_idle();
  2311. err_when(result_node_array!=NULL);
  2312. }
  2313. //------- End of function Unit::terminate_move --------//
  2314. //------------- Begin of function Unit::move_to_my_loc --------------//
  2315. //
  2316. // This function is used as this unit Unit A is blocked by another
  2317. // IDLE unit Unit B. Then Unit A will move to the location of Unit B
  2318. // and Unit B will move to the location of Unit A want to move to.
  2319. //
  2320. // Note: action_?_loc2 of both units can be different from their
  2321. // move_to_?_loc
  2322. //
  2323. void Unit::move_to_my_loc(Unit* unitPtr)
  2324. {
  2325. int unitDestX, unitDestY;
  2326. if(unitPtr->action_mode2==ACTION_MOVE)
  2327. {
  2328. unitDestX = unitPtr->action_x_loc2;
  2329. unitDestY = unitPtr->action_y_loc2;
  2330. err_when(unitDestX==-1 || unitDestY==-1);
  2331. }
  2332. else
  2333. {
  2334. unitDestX = unitPtr->move_to_x_loc;
  2335. unitDestY = unitPtr->move_to_y_loc;
  2336. }
  2337. //--------------- init parameters ---------------//
  2338. int unitCurX = unitPtr->next_x_loc();
  2339. int unitCurY = unitPtr->next_y_loc();
  2340. int destX = action_x_loc2;
  2341. int destY = action_y_loc2;
  2342. int curX = next_x_loc();
  2343. int curY = next_y_loc();
  2344. int moveScale = move_step_magn();
  2345. err_when(curX != cur_x_loc() || curY != cur_y_loc());
  2346. err_when(mobile_type!=unitPtr->mobile_type);
  2347. //------------------------------------------------------------------//
  2348. // setting for unit pointed by unitPtr
  2349. //------------------------------------------------------------------//
  2350. if(result_node_array==NULL) //************BUGHERE
  2351. {
  2352. err_when(unitPtr->cur_action!=SPRITE_IDLE);
  2353. unitPtr->move_to(destX, destY, 1); // unit pointed by unitPtr is idle before calling searching
  2354. err_when(unitPtr->cur_action!=SPRITE_DIE && unitPtr->action_mode2!=ACTION_MOVE);
  2355. }
  2356. else
  2357. {
  2358. err_when(result_node_recno<1 || unitPtr->result_node_array!=NULL);
  2359. ResultNode* resultNode = result_node_array+result_node_recno-1;
  2360. if(go_x == unitPtr->next_x && go_y == unitPtr->next_y)
  2361. {
  2362. //------ Unit B is in one of the node of the result_node_array ---//
  2363. unitPtr->result_node_count = result_node_count-result_node_recno+1; // at least there are 2 nodes
  2364. unitPtr->result_node_array = (ResultNode*)mem_add(sizeof(ResultNode)*(unitPtr->result_node_count));
  2365. memcpy(unitPtr->result_node_array, resultNode, sizeof(ResultNode)*(unitPtr->result_node_count));
  2366. }
  2367. else
  2368. {
  2369. //----- Unit B is in the middle of two nodes in the result_node_array -----//
  2370. unitPtr->result_node_count = result_node_count-result_node_recno+2;
  2371. unitPtr->result_node_array = (ResultNode*)mem_add(sizeof(ResultNode)*(unitPtr->result_node_count));
  2372. ResultNode* curNode = unitPtr->result_node_array;
  2373. curNode->node_x = unitCurX;
  2374. curNode->node_y = unitCurY;
  2375. curNode++;
  2376. memcpy(curNode, resultNode, sizeof(ResultNode)*(unitPtr->result_node_count-1));
  2377. }
  2378. err_when(unitPtr->result_node_count<2);
  2379. //--------------- set unit action ---------------//
  2380. if(unitPtr->action_mode2==ACTION_STOP || unitPtr->action_mode2==ACTION_MOVE) // unitPtr is idle now
  2381. {
  2382. //---------- activate unit pointed by unitPtr now ------------//
  2383. unitPtr->action_mode = unitPtr->action_mode2 = ACTION_MOVE;
  2384. unitPtr->action_para = unitPtr->action_para2 = 0;
  2385. if(destX!=-1 && destY!=-1)
  2386. {
  2387. unitPtr->action_x_loc = unitPtr->action_x_loc2 = destX;
  2388. unitPtr->action_y_loc = unitPtr->action_y_loc2 = destY;
  2389. }
  2390. else
  2391. {
  2392. ResultNode *lastNodePtr = unitPtr->result_node_array + unitPtr->result_node_count - 1;
  2393. unitPtr->action_x_loc = unitPtr->action_x_loc2 = lastNodePtr->node_x;
  2394. unitPtr->action_y_loc = unitPtr->action_y_loc2 = lastNodePtr->node_y;
  2395. }
  2396. }
  2397. //----------------- set unit movement parameters -----------------//
  2398. unitPtr->result_node_recno = 1;
  2399. unitPtr->result_path_dist = result_path_dist-moveScale;
  2400. unitPtr->move_to_x_loc = move_to_x_loc;
  2401. unitPtr->move_to_y_loc = move_to_y_loc;
  2402. err_when( next_x != cur_x || next_y != cur_y );
  2403. unitPtr->next_move();
  2404. #ifdef DEBUG
  2405. if(unitPtr->result_node_array!=NULL)
  2406. {
  2407. ResultNode* curNode1 = unitPtr->result_node_array + unitPtr->result_node_recno - 1;
  2408. err_when(curNode1->node_x!=unitPtr->go_x>>ZOOM_X_SHIFT_COUNT || curNode1->node_y!=unitPtr->go_y>>ZOOM_Y_SHIFT_COUNT);
  2409. }
  2410. #endif
  2411. }
  2412. //------------------------------------------------------------------//
  2413. // setting for this unit
  2414. //------------------------------------------------------------------//
  2415. int shouldWait = 0;
  2416. if(next_x==unitPtr->cur_x && next_y==unitPtr->cur_y)
  2417. {
  2418. reset_path();
  2419. result_path_dist = 0;
  2420. }
  2421. else
  2422. {
  2423. terminate_move();
  2424. shouldWait++;
  2425. result_path_dist = moveScale;
  2426. }
  2427. go_x = unitPtr->cur_x;
  2428. go_y = unitPtr->cur_y;
  2429. move_to_x_loc = unitCurX;
  2430. move_to_y_loc = unitCurY;
  2431. if(action_mode2==ACTION_MOVE)
  2432. {
  2433. action_x_loc = action_x_loc2 = unitDestX;
  2434. action_y_loc = action_y_loc2 = unitDestY;
  2435. }
  2436. //---------- note: the cur_dir is already the correct direction ---------------//
  2437. err_when(result_node_array!=NULL);
  2438. result_node_array = (ResultNode*)mem_add(sizeof(ResultNode)*2);
  2439. ResultNode* nodePtr = result_node_array;
  2440. nodePtr->node_x = curX;
  2441. nodePtr->node_y = curY;
  2442. nodePtr++;
  2443. nodePtr->node_x = unitCurX;
  2444. nodePtr->node_y = unitCurY;
  2445. result_node_count = 2;
  2446. result_node_recno = 2;
  2447. if(shouldWait)
  2448. set_wait(); // wait for the blocking unit to move first
  2449. #ifdef DEBUG
  2450. if(result_node_array!=NULL)
  2451. {
  2452. ResultNode* curNode2 = result_node_array + result_node_recno - 1;
  2453. err_when(curNode2->node_x!=go_x>>ZOOM_X_SHIFT_COUNT || curNode2->node_y!=go_y>>ZOOM_Y_SHIFT_COUNT);
  2454. }
  2455. #endif
  2456. err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
  2457. err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
  2458. err_when(unitPtr->cur_action==SPRITE_IDLE && (unitPtr->move_to_x_loc!=unitPtr->next_x_loc() ||
  2459. unitPtr->move_to_y_loc!=unitPtr->next_y_loc()));
  2460. }
  2461. //----------------- End of function Unit::move_to_my_loc ----------------//
  2462. //###### begin trevor 25/6 #######//
  2463. /*
  2464. //------------- Begin of function Unit::change_relation --------------//
  2465. void Unit::change_relation(short nation1, short nation2, int relationType)
  2466. {
  2467. if(!nation1 || !nation2 || nation1==nation2)
  2468. return; // return if either is neutral nation or same nation
  2469. nation_array[nation1]->set_relation_status(nation2, relationType);
  2470. }
  2471. //----------------- End of function Unit::change_relation ----------------//
  2472. */
  2473. //####### end trevor 25/6 ########//
  2474. //------------- Begin of function Unit::set_idle --------------//
  2475. // set parameters for unit idle
  2476. //
  2477. void Unit::set_idle()
  2478. {
  2479. /*err_when(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP &&
  2480. (((UnitMarine*)this)->extra_move_in_beach==EXTRA_MOVING_IN ||
  2481. ((UnitMarine*)this)->extra_move_in_beach==EXTRA_MOVING_OUT));*/
  2482. err_when(cur_x<0);
  2483. err_when(move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc());
  2484. err_when(cur_x!=next_x || cur_y!=next_y || next_x!=go_x || next_y!=go_y);
  2485. err_when(cur_x%ZOOM_LOC_WIDTH || cur_y%ZOOM_LOC_HEIGHT);
  2486. err_when(result_path_dist || result_node_array);
  2487. err_when(cur_dir<0 || cur_dir>MAX_SPRITE_DIR_TYPE);
  2488. final_dir = cur_dir;
  2489. turn_delay = 0;
  2490. cur_action = SPRITE_IDLE;
  2491. }
  2492. //----------------- End of function Unit::set_idle ----------------//
  2493. //------------- Begin of function Unit::set_ready --------------//
  2494. // set parameters for unit ready to move
  2495. //
  2496. void Unit::set_ready()
  2497. {
  2498. err_when(cur_x<0);
  2499. err_when(move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc());
  2500. err_when(cur_x!=next_x || cur_y!=next_y || next_x!=go_x || next_y!=go_y);
  2501. err_when(cur_x%ZOOM_LOC_WIDTH || cur_y%ZOOM_LOC_HEIGHT);
  2502. err_when(cur_dir<0 || cur_dir>MAX_SPRITE_DIR_TYPE);
  2503. final_dir = cur_dir;
  2504. turn_delay = 0;
  2505. cur_action = SPRITE_READY_TO_MOVE;
  2506. }
  2507. //----------------- End of function Unit::set_ready ----------------//
  2508. //------------- Begin of function Unit::set_move --------------//
  2509. // set parameters for unit movement
  2510. //
  2511. void Unit::set_move()
  2512. {
  2513. err_when(cur_x<0);
  2514. err_when(cur_dir!=final_dir);
  2515. cur_action = SPRITE_MOVE;
  2516. }
  2517. //----------------- End of function Unit::set_move ----------------//
  2518. //------------- Begin of function Unit::set_wait --------------//
  2519. // Set the unit to waiting status.
  2520. // When SPRITE_WAIT:
  2521. // (next_x, next_y) must be == (cur_x, cur_y), it's the location of the sprite.
  2522. //
  2523. void Unit::set_wait()
  2524. {
  2525. err_when(cur_x<0);
  2526. #ifdef DEBUG
  2527. err_when(go_x==cur_x && go_y==cur_y);
  2528. err_when( next_x != cur_x || next_y != cur_y );
  2529. short w, h, x, y;
  2530. for(h=0, y=cur_y_loc(); h<sprite_info->loc_height; h++, y++)
  2531. for(w=0, x=cur_x_loc(); w<sprite_info->loc_width; w++, x++)
  2532. err_when( world.get_unit_recno(x, y, mobile_type) != sprite_recno );
  2533. err_when((check_unit_dir1=get_dir(cur_x, cur_y, go_x, go_y))!=final_dir);
  2534. #endif
  2535. cur_action = SPRITE_WAIT;
  2536. cur_frame = 1;
  2537. waiting_term++;
  2538. }
  2539. //----------------- End of function Unit::set_wait ----------------//
  2540. //------------- Begin of function Unit::set_attack --------------//
  2541. // set parameters for unit attack
  2542. //
  2543. void Unit::set_attack()
  2544. {
  2545. err_when(cur_x<0);
  2546. err_when(next_x!=cur_x || next_y!=cur_y);
  2547. err_when(cur_dir<0 || cur_dir>=MAX_SPRITE_DIR_TYPE || turn_delay);
  2548. final_dir = cur_dir;
  2549. turn_delay = 0;
  2550. cur_action = SPRITE_ATTACK;
  2551. }
  2552. //----------------- End of function Unit::set_attack ----------------//
  2553. //------------- Begin of function Unit::set_turn --------------//
  2554. // set parameters for unit turning
  2555. //
  2556. void Unit::set_turn()
  2557. {
  2558. err_when(cur_x<0);
  2559. err_when(next_x!=cur_x || next_y!=cur_y);
  2560. cur_action = SPRITE_TURN;
  2561. }
  2562. //----------------- End of function Unit::set_turn ----------------//
  2563. //------------- Begin of function Unit::set_ship_extra_move --------------//
  2564. // set parameters for ship extra moving in inlet
  2565. //
  2566. void Unit::set_ship_extra_move()
  2567. {
  2568. err_when(cur_x<0);
  2569. cur_action = SPRITE_SHIP_EXTRA_MOVE;
  2570. }
  2571. //----------------- End of function Unit::set_ship_extra_move ----------------//
  2572. //------------- Begin of function Unit::set_die --------------//
  2573. // set parameters for unit die
  2574. //
  2575. void Unit::set_die()
  2576. {
  2577. if( action_mode == ACTION_DIE )
  2578. return;
  2579. err_when(hit_points>0);
  2580. action_mode = ACTION_DIE;
  2581. cur_action = SPRITE_DIE;
  2582. cur_frame = 1;
  2583. //##### begin trevor 19/7 #####//
  2584. //---- if this unit is led by a leader, only mobile units has leader_unit_recno assigned to a leader -----//
  2585. if( leader_unit_recno && !unit_array.is_deleted(leader_unit_recno) ) // the leader unit may have been killed at the same time
  2586. {
  2587. unit_array[leader_unit_recno]->del_team_member(sprite_recno);
  2588. leader_unit_recno = 0;
  2589. }
  2590. //##### end trevor 19/7 #####//
  2591. }
  2592. //----------------- End of function Unit::set_die ----------------//