OUNITAAT.cpp 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996
  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 : OUNITAAT.CPP
  21. //Description : Object UnitArray - part 2
  22. #include <ALL.h>
  23. #include <OVGA.h>
  24. #include <OSYS.h>
  25. #include <OSTR.h>
  26. #include <OREMOTE.h>
  27. #include <OWORLD.h>
  28. #include <ONATION.h>
  29. #include <OFIRM.h>
  30. #include <OTOWN.h>
  31. #include <OTERRAIN.h>
  32. #include <OU_MARI.h>
  33. #ifdef NO_DEBUG_UNIT
  34. #undef err_when
  35. #undef err_here
  36. #undef err_if
  37. #undef err_else
  38. #undef err_now
  39. #define err_when(cond)
  40. #define err_here()
  41. #define err_if(cond)
  42. #define err_else
  43. #define err_now(msg)
  44. #undef DEBUG
  45. #endif
  46. //------ static variables for attacking ------//
  47. // ATTACK_DIR is defined in OUNIT.H
  48. #define MAX_TARGET_SIZE 4
  49. #define MAX_UNIT_SURROUND_SIZE MAX_TARGET_SIZE+2 // handle the case up to target size 4x4
  50. #define SHIFT_ADJUST 1 // since the upper left offset position is (-1, -1)
  51. static short *unit_processed_array; // store those processed unit sprite_recno
  52. static short unit_processed_count; // count the number processed units
  53. static short *dir_array_ptr[ATTACK_DIR]; // store units' sprite_recno in each direction
  54. static short dir_array_count[ATTACK_DIR]; // num of unit in each direction
  55. static char unreachable_table[MAX_UNIT_SURROUND_SIZE][MAX_UNIT_SURROUND_SIZE]; // table shared for all attackers
  56. //************* debug ***************//
  57. #ifdef DEBUG
  58. //--------------------------------------------------------------------------------//
  59. // <int> resultNum - the num of free space around the target
  60. // <int> width - width of target
  61. // <int> height - height of target
  62. //--------------------------------------------------------------------------------//
  63. static void debug_analyse_result_check(int resultNum, int width, int height)
  64. {
  65. int count=0, i, j;
  66. for(i=0; i<width+2; i++)
  67. {
  68. if(unreachable_table[i][0]==0)
  69. count++;
  70. }
  71. i = width+1;
  72. for(j=1; j<height+2; j++)
  73. {
  74. if(unreachable_table[i][j]==0)
  75. count++;
  76. }
  77. for(j=1; j<height+2; j++)
  78. {
  79. if(unreachable_table[0][j]==0)
  80. count++;
  81. }
  82. j = height+1;
  83. for(i=1; i<width+1; i++)
  84. {
  85. if(unreachable_table[i][j]==0)
  86. count++;
  87. }
  88. err_when(count!=resultNum);
  89. }
  90. #endif
  91. #ifdef DEBUG
  92. #define debug_result_check(resultNum, width, height) debug_analyse_result_check(resultNum, width, height)
  93. #else
  94. #define debug_result_check(resultNum, width, height)
  95. #endif
  96. //************* debug ***************//
  97. //--------- Begin of function UnitArray::get_target_surround_loc ---------//
  98. // <int> targetWidth - target width
  99. // <int> targetHeight - target height
  100. //
  101. char UnitArray::get_target_surround_loc(int targetWidth, int targetHeight)
  102. {
  103. static char surround_loc[MAX_TARGET_SIZE][MAX_TARGET_SIZE] // width, height
  104. = { { 8, 10, 12, 14}, {10, 12, 14, 16}, {12, 14, 16, 18}, {14, 16, 18, 20}};
  105. return surround_loc[targetWidth-1][targetHeight-1];
  106. }
  107. //----------- End of function UnitArray::get_target_surround_loc -----------//
  108. //--------- Begin of function UnitArray::update_unreachable_table ---------//
  109. // check target surroundig to drop those unreachable location
  110. //
  111. // <int> targetXLoc - target x location
  112. // <int> targetYLoc - target y location
  113. // <int> targetWidth - target width
  114. // <int> targetHeight - target height
  115. // <char> mobileType - mobile type of the attacker
  116. // <int&> analyseResult - reference for returning num of reachable location
  117. //
  118. void UnitArray::update_unreachable_table(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight,
  119. char mobileType, int &analyseResult)
  120. {
  121. int xLoc1, yLoc1, xLoc2, yLoc2, i;
  122. //----------------------------------------------------------------------//
  123. // checking for left & right edges, calculate location and counter
  124. //----------------------------------------------------------------------//
  125. xLoc1 = targetXLoc-1;
  126. xLoc2 = targetXLoc+targetWidth;
  127. if(targetYLoc==0)
  128. {
  129. i = targetHeight+1;
  130. yLoc1=targetYLoc;
  131. }
  132. else
  133. {
  134. i = targetHeight+2;
  135. yLoc1=targetYLoc-1;
  136. }
  137. if(targetYLoc+targetHeight>=MAX_WORLD_Y_LOC)
  138. i--;
  139. for(yLoc2=yLoc1-targetYLoc+SHIFT_ADJUST; i>0; i--, yLoc1++, yLoc2++)
  140. {
  141. //---- left edge ----//
  142. if(xLoc1>=0 && !unreachable_table[0][yLoc2] && !world.get_loc(xLoc1, yLoc1)->can_move(mobileType))
  143. {
  144. unreachable_table[0][yLoc2] = 1;
  145. analyseResult--;
  146. }
  147. //----- right edge -----//
  148. if(xLoc2<MAX_WORLD_X_LOC && !unreachable_table[targetWidth+1][yLoc2] &&
  149. !world.get_loc(xLoc2, yLoc1)->can_move(mobileType))
  150. {
  151. unreachable_table[targetWidth+1][yLoc2] = 1;
  152. analyseResult--;
  153. }
  154. if(!analyseResult)
  155. return;
  156. }
  157. //----------------------------------------------------------------------//
  158. // checking for the top and bottom edges
  159. //----------------------------------------------------------------------//
  160. yLoc1 = targetYLoc-1;
  161. yLoc2 = targetYLoc+targetHeight;
  162. for(i=0, xLoc1=targetXLoc, xLoc2=xLoc1-targetXLoc+SHIFT_ADJUST; i<targetWidth; i++, xLoc1++, xLoc2++)
  163. {
  164. //---- top edge ----//
  165. if(yLoc1>=0 && !unreachable_table[xLoc2][0] && !world.get_loc(xLoc1, yLoc1)->can_move(mobileType))
  166. {
  167. unreachable_table[xLoc2][0] = 1;
  168. analyseResult--;
  169. }
  170. //----- bottom edge -----//
  171. if(yLoc2<MAX_WORLD_Y_LOC && !unreachable_table[xLoc2][targetHeight+1] &&
  172. !world.get_loc(xLoc1, yLoc2)->can_move(mobileType))
  173. {
  174. unreachable_table[xLoc2][targetHeight+1] = 1;
  175. analyseResult--;
  176. }
  177. if(!analyseResult)
  178. return;
  179. }
  180. debug_result_check(analyseResult, targetWidth, targetHeight);
  181. err_when(analyseResult<0);
  182. }
  183. //----------- End of function UnitArray::update_unreachable_table -----------//
  184. //--------- Begin of function UnitArray::attack ---------//
  185. //
  186. // Order the unit to attack a specific location.
  187. //
  188. // <int> targetXLoc, targetYLoc - target location
  189. // <int> divided - whether the units are divided
  190. // <short*> selectedUnitArray - an array of recno of selected units.
  191. // <int> selectedCount - no. of selected units.
  192. // [char] remoteAction - whether this is an action carried out by a remote machine or not.
  193. // (default: 0)
  194. // <int> targetUnitRecno - if it is unit, pass the unit recno, otherwise 0
  195. //
  196. void UnitArray::attack(int targetXLoc, int targetYLoc, int divided, short* selectedUnitArray, int selectedCount, char remoteAction, int targetUnitRecno)
  197. {
  198. err_when(targetXLoc<0 || targetYLoc<0 || targetXLoc>=MAX_WORLD_X_LOC || targetYLoc>=MAX_WORLD_Y_LOC);
  199. // ######## patch begin Gilbert 5/8 #########//
  200. int targetNationRecno = 0;
  201. if( targetUnitRecno == 0 )
  202. {
  203. // unit determined from the location
  204. int tmpMobileType;
  205. Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
  206. targetUnitRecno = locPtr->get_any_unit(tmpMobileType) ;
  207. }
  208. else
  209. {
  210. // location determined by the unit
  211. Unit *unitPtr;
  212. if( !unit_array.is_deleted(targetUnitRecno)
  213. && (unitPtr = unit_array[targetUnitRecno])
  214. && unitPtr->is_visible() )
  215. {
  216. targetXLoc = unitPtr->next_x_loc();
  217. targetYLoc = unitPtr->next_y_loc();
  218. if( unitPtr->unit_id != UNIT_EXPLOSIVE_CART ) // attacking own porcupine is allowed
  219. targetNationRecno = unitPtr->nation_recno;
  220. }
  221. else
  222. targetUnitRecno = 0;
  223. }
  224. if( targetUnitRecno == 0 )
  225. {
  226. //--- set the target coordination to the top left position of the town/firm ---//
  227. Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
  228. //---- if there is a firm on this location -----//
  229. if( locPtr->is_firm() )
  230. {
  231. Firm* firmPtr = firm_array[locPtr->firm_recno()];
  232. targetXLoc = firmPtr->loc_x1;
  233. targetYLoc = firmPtr->loc_y1;
  234. targetNationRecno = firmPtr->nation_recno;
  235. }
  236. //---- if there is a town on this location -----//
  237. else if( locPtr->is_town() )
  238. {
  239. Town* townPtr = town_array[locPtr->town_recno()];
  240. targetXLoc = townPtr->loc_x1;
  241. targetYLoc = townPtr->loc_y1;
  242. targetNationRecno = townPtr->nation_recno;
  243. }
  244. else
  245. return;
  246. }
  247. // ######## patch end Gilbert 5/8 #########//
  248. //--------- AI debug code ---------//
  249. //--- AI attacking a nation which its NationRelation::should_attack is 0 ---//
  250. Unit* attackUnit = unit_array[ selectedUnitArray[0] ];
  251. if( attackUnit->nation_recno && targetNationRecno )
  252. {
  253. if( nation_array[attackUnit->nation_recno]->get_relation(targetNationRecno)->should_attack==0 )
  254. return;
  255. }
  256. //-------- if it's a multiplayer game --------//
  257. if( !remoteAction && remote.is_enable() )
  258. {
  259. short* shortPtr = (short*) remote.new_send_queue_msg(MSG_UNIT_ATTACK, sizeof(short) * (5+selectedCount) );
  260. shortPtr[0] = targetXLoc;
  261. shortPtr[1] = targetYLoc;
  262. shortPtr[2] = targetUnitRecno;
  263. shortPtr[3] = selectedCount;
  264. shortPtr[4] = divided;
  265. memcpy( shortPtr+5, selectedUnitArray, sizeof(short) * selectedCount );
  266. }
  267. else
  268. {
  269. if(!divided)
  270. {
  271. divide_array(targetXLoc, targetYLoc, selectedUnitArray, selectedCount, 1); // 1 for excluding the recno in target location
  272. Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
  273. int targetMobileType = locPtr->has_any_unit();
  274. if(selected_land_unit_count)
  275. attack_call(targetXLoc, targetYLoc, UNIT_LAND, targetMobileType, 1, selected_land_unit_array, selected_land_unit_count, targetUnitRecno);
  276. if(selected_sea_unit_count)
  277. attack_call(targetXLoc, targetYLoc, UNIT_SEA, targetMobileType, 1, selected_sea_unit_array, selected_sea_unit_count, targetUnitRecno);
  278. if(selected_air_unit_count)
  279. attack_call(targetXLoc, targetYLoc, UNIT_AIR, targetMobileType, 1, selected_air_unit_array, selected_air_unit_count, targetUnitRecno);
  280. selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0;
  281. mem_del(selected_land_unit_array);
  282. mem_del(selected_sea_unit_array);
  283. mem_del(selected_air_unit_array);
  284. return;
  285. }
  286. else
  287. err_here();
  288. }
  289. }
  290. //----------- End of function UnitArray::attack -----------//
  291. //--------- Begin of function UnitArray::attack_call ---------//
  292. // <int> targetXLoc - target x location
  293. // <int> targetYLoc - target y location
  294. // <char> mobileType - attacker's mobile type
  295. // <char> targetMobileType - target mobile type
  296. // <int> divided - whether the units are divided
  297. // <short*> selectedUnitArray - selected units' recno.
  298. // <int> selectedCount - num of selected units
  299. //
  300. void UnitArray::attack_call(int targetXLoc, int targetYLoc, char mobileType, char targetMobileType, int divided, short* selectedUnitArray, int selectedCount, int targetUnitRecno)
  301. {
  302. //------------- attack now -------------//
  303. err_when( selectedCount > 10000 );
  304. Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
  305. err_when(!locPtr);
  306. // ##### patch begin Gilbert 5/8 ######//
  307. //if(targetMobileType)
  308. if( targetUnitRecno && !unit_array.is_deleted(targetUnitRecno) )
  309. {
  310. //---------------- attack unit --------------//
  311. //Unit *targetUnit = unit_array[locPtr->unit_recno(targetMobileType)];
  312. Unit *targetUnit = unit_array[targetUnitRecno];
  313. if(!targetUnit->is_visible() || targetUnit->hit_points<=0)
  314. return;
  315. // short targetUnitRecno = targetUnit->sprite_recno;
  316. attack_unit(targetXLoc, targetYLoc, targetUnitRecno, selectedUnitArray, selectedCount);
  317. }
  318. // ##### patch end Gilbert 5/8 ######//
  319. else if(locPtr->is_firm())
  320. {
  321. //------------------ attack firm -------------------//
  322. Firm *firmPtr = firm_array[locPtr->firm_recno()];
  323. err_when(!firmPtr);
  324. if(firmPtr->hit_points<=0)
  325. return;
  326. attack_firm(targetXLoc, targetYLoc, firmPtr->firm_recno, selectedUnitArray, selectedCount);
  327. }
  328. else if(locPtr->is_town())
  329. {
  330. //-------------------- attack town -------------------//
  331. Town *townPtr = town_array[locPtr->town_recno()];
  332. err_when(!townPtr);
  333. attack_town(targetXLoc, targetYLoc, townPtr->town_recno, selectedUnitArray, selectedCount);
  334. }
  335. else if(locPtr->is_wall())
  336. {
  337. //------------------ attack wall ---------------------//
  338. attack_wall(targetXLoc, targetYLoc, selectedUnitArray, selectedCount);
  339. }
  340. else
  341. return; // no target for attacking
  342. }
  343. //----------- End of function UnitArray::attack_call -----------//
  344. //--------- Begin of function UnitArray::attack_unit ---------//
  345. // <int> targetXLoc, targetYLoc - the unit upper left location
  346. // <short> targetunitRecno - the unit recno
  347. //
  348. // Note : this attack function only for attackers with size 1x1.
  349. //
  350. void UnitArray::attack_unit(int targetXLoc, int targetYLoc, short targetUnitRecno, short* selectedUnitArray, int selectedCount)
  351. {
  352. err_when(selectedCount<=0);
  353. if(selectedCount==1)
  354. {
  355. Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
  356. unitPtr->unit_group_id = unit_array.cur_group_id++;
  357. unitPtr->attack_unit(targetXLoc, targetYLoc);
  358. return;
  359. }
  360. //********************** improve later begin **************************//
  361. //---------------------------------------------------------------------//
  362. // codes for differnt territory or different mobile_type attacking should
  363. // be added in the future.
  364. //---------------------------------------------------------------------//
  365. Unit *firstUnitPtr = unit_array[selectedUnitArray[0]];
  366. Unit *targetPtr2 = unit_array[targetUnitRecno];
  367. if( (world.get_loc(targetXLoc, targetYLoc)->region_id !=
  368. world.get_loc(firstUnitPtr->next_x_loc(), firstUnitPtr->next_y_loc())->region_id) ||
  369. (targetPtr2->mobile_type!=firstUnitPtr->mobile_type) )
  370. {
  371. Unit *unitPtr;
  372. set_group_id(selectedUnitArray, selectedCount);
  373. for(int i=0; i<selectedCount; i++)
  374. {
  375. unitPtr = (Unit*) get_ptr(selectedUnitArray[i]);
  376. unitPtr->attack_unit(targetXLoc, targetYLoc);
  377. }
  378. return;
  379. }
  380. //*********************** improve later end ***************************//
  381. //----------- initialize local parameters ------------//
  382. Unit *targetPtr = unit_array[targetUnitRecno];
  383. int targetWidth = targetPtr->sprite_info->loc_width;
  384. int targetHeight = targetPtr->sprite_info->loc_height;
  385. int targetXLoc2 = targetXLoc + targetWidth - 1;
  386. int targetYLoc2 = targetYLoc + targetHeight - 1;
  387. char surroundLoc = get_target_surround_loc(targetWidth, targetHeight);
  388. char *xOffsetPtr = get_target_x_offset(targetWidth, targetHeight, 0);
  389. char *yOffsetPtr = get_target_y_offset(targetWidth, targetHeight, 0);
  390. //---------------------------------------------------------------------//
  391. // construct data structure
  392. //---------------------------------------------------------------------//
  393. int tempVar = sizeof(short)*selectedCount;
  394. memset(dir_array_count, 0, sizeof(dir_array_count));
  395. int count;
  396. for(count=0; count<ATTACK_DIR; count++)
  397. {
  398. dir_array_ptr[count] = (short*) mem_add(tempVar);
  399. memset(dir_array_ptr[count], 0, tempVar);
  400. }
  401. unit_processed_array = (short *)mem_add(tempVar);
  402. unit_processed_count = 0;
  403. //---------------------------------------------------------------------//
  404. // divide the units into each region
  405. //---------------------------------------------------------------------//
  406. Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
  407. err_when(!unitPtr);
  408. DWORD groupId = unit_array.cur_group_id++;
  409. arrange_units_in_group(targetXLoc, targetYLoc, targetXLoc2, targetYLoc2, selectedUnitArray, selectedCount, groupId, 1);
  410. //---------------------------------------------------------------------//
  411. // now the attackers are divided into 8 groups to attack the target
  412. //---------------------------------------------------------------------//
  413. int xLoc, yLoc; // actual target surrounding location to move to
  414. int xOffset, yOffset; // offset location of the target
  415. int unprocessed; // number of units in this group
  416. int dist, xDist, yDist, minDist;
  417. int destCount;
  418. short unitPos; // store the position of the unit with minDist
  419. short *curArrayPtr;
  420. int i;
  421. for(i=0; i<MAX_UNIT_SURROUND_SIZE; i++)
  422. memset(unreachable_table[i], 0, sizeof(char)*MAX_UNIT_SURROUND_SIZE);
  423. //---------------------------------------------------------------------//
  424. // anaylse the surrounding location of the target
  425. //---------------------------------------------------------------------//
  426. int analyseResult = analyse_surround_location(targetXLoc, targetYLoc, targetWidth, targetHeight, targetPtr->mobile_type);
  427. debug_result_check(analyseResult, targetWidth, targetHeight);
  428. err_when(analyseResult<0);
  429. if(!analyseResult) // 0 if all surround location is not accessible
  430. {
  431. //------------------------------------------------------------//
  432. // special handling for this case
  433. //------------------------------------------------------------//
  434. handle_attack_target_totally_blocked(targetXLoc, targetYLoc, targetUnitRecno, selectedUnitArray, selectedCount, 1);
  435. for(count=0; count<ATTACK_DIR; count++)
  436. mem_del(dir_array_ptr[count]);
  437. mem_del(unit_processed_array);
  438. return;
  439. }
  440. //---------------------------------------------------------------------//
  441. // let the units move to the rest accessible location
  442. //---------------------------------------------------------------------//
  443. for(count=0; count<ATTACK_DIR; count++) // for each array/group
  444. {
  445. //--------- initialize for each group --------//
  446. unprocessed = dir_array_count[count]; // get the number of units in this region
  447. if(!unprocessed)
  448. continue;
  449. destCount = surroundLoc-1;
  450. curArrayPtr = dir_array_ptr[count]; // get the recno of units in this region
  451. xOffsetPtr = get_target_x_offset(targetWidth, targetHeight, count);
  452. yOffsetPtr = get_target_y_offset(targetWidth, targetHeight, count);
  453. xOffset = *xOffsetPtr;
  454. yOffset = *yOffsetPtr;
  455. //-----------------------------------------------------------------//
  456. // determine a suitable location for the attacker to move to
  457. //-----------------------------------------------------------------//
  458. while(unprocessed)
  459. {
  460. //-----------------------------------------------------//
  461. // find a reachable location, or not searched location
  462. //-----------------------------------------------------//
  463. err_when(analyseResult<0);
  464. if(!analyseResult)
  465. {
  466. handle_attack_target_totally_blocked(targetXLoc, targetYLoc, targetUnitRecno, selectedUnitArray, selectedCount, 1);
  467. for(count=0; count<ATTACK_DIR; count++)
  468. mem_del(dir_array_ptr[count]);
  469. mem_del(unit_processed_array);
  470. return;
  471. }
  472. else
  473. {
  474. for(i=0; i<surroundLoc; i++)
  475. {
  476. if((++destCount)>=surroundLoc)
  477. {
  478. destCount = 0;
  479. xOffsetPtr = get_target_x_offset(targetWidth, targetHeight, count);
  480. yOffsetPtr = get_target_y_offset(targetWidth, targetHeight, count);
  481. xOffset = *xOffsetPtr;
  482. yOffset = *yOffsetPtr;
  483. }
  484. else
  485. {
  486. xOffset = *(++xOffsetPtr);
  487. yOffset = *(++yOffsetPtr);
  488. }
  489. if(!unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST])
  490. break;
  491. }
  492. }
  493. err_when(unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST]);
  494. //------------------------------------------------------------//
  495. // find the closest attacker
  496. //------------------------------------------------------------//
  497. err_when(unprocessed>2000 || unprocessed <0);
  498. xLoc = targetXLoc + xOffset;
  499. yLoc = targetYLoc + yOffset;
  500. err_when(!world.get_loc(xLoc, yLoc)->can_move(targetPtr->mobile_type));
  501. for(i=0, minDist=0x7FFFFFF; i<unprocessed; i++)
  502. {
  503. unitPtr = (Unit*) get_ptr(curArrayPtr[i]);
  504. xDist = abs(xLoc-unitPtr->next_x_loc());
  505. yDist = abs(yLoc-unitPtr->next_y_loc());
  506. dist = (xDist >= yDist) ? xDist*10+yDist : yDist*10+xDist;
  507. if(dist < minDist)
  508. {
  509. minDist = dist;
  510. unitPos = i;
  511. }
  512. }
  513. unitPtr = (Unit*) get_ptr(curArrayPtr[unitPos]);
  514. curArrayPtr[unitPos] = curArrayPtr[--unprocessed]; // move the units in the back to the front
  515. err_when(unitPtr->action_mode2!=ACTION_ATTACK_WALL &&
  516. unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0);
  517. seek_path.set_status(PATH_WAIT);
  518. err_when(seek_path.path_status==PATH_NODE_USED_UP);
  519. unitPtr->attack_unit(targetXLoc, targetYLoc, xOffset, yOffset);
  520. //------------------------------------------------------------//
  521. // store the unit sprite_recno in the array
  522. //------------------------------------------------------------//
  523. unit_processed_array[unit_processed_count++] = unitPtr->sprite_recno;
  524. //------------------------------------------------------------//
  525. // set the flag if unreachable
  526. //------------------------------------------------------------//
  527. if(seek_path.path_status==PATH_NODE_USED_UP)
  528. {
  529. unreachable_table[xLoc-targetXLoc+SHIFT_ADJUST][yLoc-targetYLoc+SHIFT_ADJUST] = 1;
  530. analyseResult--;
  531. debug_result_check(analyseResult, targetWidth, targetHeight);
  532. err_when(analyseResult<0);
  533. //------------------------------------------------------------//
  534. // the nearby location should also be unreachable
  535. //------------------------------------------------------------//
  536. check_nearby_location(targetXLoc, targetYLoc, xOffset, yOffset, targetWidth, targetHeight,
  537. targetPtr->mobile_type, analyseResult);
  538. }
  539. update_unreachable_table(targetXLoc, targetYLoc, targetWidth, targetHeight, unitPtr->mobile_type, analyseResult);
  540. #ifdef DEBUG
  541. for(int di=0; di<targetWidth+2; di++)
  542. {
  543. for(int dj=0; dj<targetHeight+2; dj++)
  544. {
  545. if(di>=1 && di<=targetWidth && dj>=1 && dj<=targetHeight)
  546. continue;
  547. int debugXLoc = targetXLoc+di-SHIFT_ADJUST;
  548. int debugYLoc = targetYLoc+dj-SHIFT_ADJUST;
  549. if(debugXLoc<0 || debugXLoc>=MAX_WORLD_X_LOC || debugYLoc<0 || debugYLoc>=MAX_WORLD_Y_LOC)
  550. continue;
  551. Location *dlPtr = world.get_loc(debugXLoc, debugYLoc);
  552. err_when(!dlPtr->can_move(targetPtr->mobile_type) && unreachable_table[di][dj]==0);
  553. }
  554. }
  555. #endif
  556. }
  557. }
  558. //---------------------------------------------------------------------//
  559. // set the unreachable flag for each units
  560. //---------------------------------------------------------------------//
  561. //-************** codes here ***************-//
  562. //---------------------------------------------------------------------//
  563. // destruct data structure
  564. //---------------------------------------------------------------------//
  565. for(count=0; count<ATTACK_DIR; count++)
  566. mem_del(dir_array_ptr[count]);
  567. mem_del(unit_processed_array);
  568. }
  569. //----------- End of function UnitArray::attack_unit -----------//
  570. //--------- Begin of function UnitArray::attack_firm ---------//
  571. // <int> targetXLoc, targetYLoc - the firm upper left location
  572. // <short> firmRecno - the firm recno
  573. //
  574. // try to calculate the best location for each unit to move to the
  575. // surrounding of the firm for attacking
  576. //
  577. void UnitArray::attack_firm(int targetXLoc, int targetYLoc, short firmRecno, short* selectedUnitArray, int selectedCount)
  578. {
  579. err_when(selectedCount<=0);
  580. if(selectedCount==1)
  581. {
  582. Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
  583. unitPtr->unit_group_id = unit_array.cur_group_id++;
  584. unitPtr->attack_firm(targetXLoc, targetYLoc);
  585. return;
  586. }
  587. //********************** improve later begin **************************//
  588. //---------------------------------------------------------------------//
  589. // codes for differnt territory or different mobile_type attacking should
  590. // be added in the future.
  591. //---------------------------------------------------------------------//
  592. Unit *firstUnitPtr = unit_array[selectedUnitArray[0]];
  593. if(world.get_loc(targetXLoc, targetYLoc)->region_id !=
  594. world.get_loc(firstUnitPtr->next_x_loc(), firstUnitPtr->next_y_loc())->region_id)
  595. {
  596. Unit *unitPtr;
  597. set_group_id(selectedUnitArray, selectedCount);
  598. for(int i=0; i<selectedCount; i++)
  599. {
  600. unitPtr = (Unit*) get_ptr(selectedUnitArray[i]);
  601. unitPtr->attack_firm(targetXLoc, targetYLoc);
  602. }
  603. return;
  604. }
  605. //*********************** improve later end ***************************//
  606. //----------- initialize local parameters ------------//
  607. Firm *firmPtr = firm_array[firmRecno];
  608. FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
  609. int firmWidth = firmInfo->loc_width;
  610. int firmHeight = firmInfo->loc_height;
  611. int targetXLoc2 = targetXLoc + firmWidth - 1; // the lower right corner of the firm
  612. int targetYLoc2 = targetYLoc + firmHeight -1;
  613. char *xOffsetPtr, *yOffsetPtr;
  614. //---------------------------------------------------------------------//
  615. // construct data structure
  616. //---------------------------------------------------------------------//
  617. int tempVar = sizeof(short)*selectedCount;
  618. memset(dir_array_count, 0, sizeof(dir_array_count));
  619. int count;
  620. for(count=0; count<ATTACK_DIR; count++)
  621. {
  622. dir_array_ptr[count] = (short*) mem_add(tempVar);
  623. memset(dir_array_ptr[count], 0, tempVar);
  624. }
  625. unit_processed_array = (short *)mem_add(tempVar);
  626. unit_processed_count = 0;
  627. //---------------------------------------------------------------------//
  628. // divide the units into each region
  629. //---------------------------------------------------------------------//
  630. Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
  631. err_when(!unitPtr);
  632. DWORD groupId = unit_array.cur_group_id++;
  633. arrange_units_in_group(targetXLoc, targetYLoc, targetXLoc2, targetYLoc2, selectedUnitArray, selectedCount, groupId, 2);
  634. //---------------------------------------------------------------------//
  635. // now the attackers are divided into 8 groups to attack the target
  636. //---------------------------------------------------------------------//
  637. int xLoc, yLoc; // actual target surrounding location to move to
  638. int xOffset, yOffset; // offset location of the target
  639. int unprocessed; // number of units in this group
  640. int destCount;
  641. int dist, xDist, yDist, minDist;
  642. short unitPos; // store the position of the unit with minDist
  643. short *curArrayPtr;
  644. char surroundLoc = get_target_surround_loc(firmWidth, firmHeight);
  645. int i;
  646. for(i=0; i<MAX_UNIT_SURROUND_SIZE; i++)
  647. memset(unreachable_table[i], 0, sizeof(char)*MAX_UNIT_SURROUND_SIZE);
  648. //---------------------------------------------------------------------//
  649. // analyse the surrounding location of the target
  650. //---------------------------------------------------------------------//
  651. int analyseResult = analyse_surround_location(targetXLoc, targetYLoc, firmWidth, firmHeight, unitPtr->mobile_type);
  652. debug_result_check(analyseResult, firmWidth, firmHeight);
  653. err_when(analyseResult<0);
  654. if(!analyseResult) // 0 if all surround location is not accessible
  655. {
  656. //------------------------------------------------------------//
  657. // special handling for this case
  658. //------------------------------------------------------------//
  659. handle_attack_target_totally_blocked(targetXLoc, targetYLoc, firmRecno, selectedUnitArray, selectedCount, 2);
  660. for(count=0; count<ATTACK_DIR; count++)
  661. mem_del(dir_array_ptr[count]);
  662. mem_del(unit_processed_array);
  663. return;
  664. }
  665. //---------------------------------------------------------------------//
  666. // let the units move to the rest accessible location
  667. //---------------------------------------------------------------------//
  668. for(count=0; count<ATTACK_DIR; count++) // for each array/group
  669. {
  670. //--------- initialize for each group --------//
  671. unprocessed = dir_array_count[count]; // get the number of units in this region
  672. curArrayPtr = dir_array_ptr[count]; // get the recno of units in this region
  673. destCount = surroundLoc - 1;
  674. xOffsetPtr = get_target_x_offset(firmWidth, firmHeight, count);
  675. yOffsetPtr = get_target_y_offset(firmWidth, firmHeight, count);
  676. xOffset = *xOffsetPtr;
  677. yOffset = *yOffsetPtr;
  678. //-----------------------------------------------------------------//
  679. // determine a suitable location for the attacker to move to
  680. //-----------------------------------------------------------------//
  681. err_when(unprocessed>2000 || unprocessed <0);
  682. while(unprocessed)
  683. {
  684. //-----------------------------------------------------//
  685. // find a reachable location, or not searched location
  686. //-----------------------------------------------------//
  687. err_when(analyseResult<0);
  688. if(!analyseResult)
  689. {
  690. handle_attack_target_totally_blocked(targetXLoc, targetYLoc, firmRecno, selectedUnitArray, selectedCount, 2);
  691. for(count=0; count<ATTACK_DIR; count++)
  692. mem_del(dir_array_ptr[count]);
  693. mem_del(unit_processed_array);
  694. return;
  695. }
  696. else
  697. {
  698. for(i=0; i<surroundLoc; i++)
  699. {
  700. if((++destCount)>=surroundLoc)
  701. {
  702. destCount = 0;
  703. xOffsetPtr = get_target_x_offset(firmWidth, firmHeight, count);
  704. yOffsetPtr = get_target_y_offset(firmWidth, firmHeight, count);
  705. xOffset = *xOffsetPtr;
  706. yOffset = *yOffsetPtr;
  707. }
  708. else
  709. {
  710. xOffset = *(++xOffsetPtr);
  711. yOffset = *(++yOffsetPtr);
  712. }
  713. if(!unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST])
  714. break;
  715. }
  716. }
  717. err_when(unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST]);
  718. //------------------------------------------------------------//
  719. // find the closest attacker
  720. //------------------------------------------------------------//
  721. err_when(unprocessed>2000 || unprocessed <0);
  722. xLoc = targetXLoc + xOffset;
  723. yLoc = targetYLoc + yOffset;
  724. err_when(!world.get_loc(xLoc, yLoc)->can_move(unitPtr->mobile_type));
  725. for(i=0, minDist=0x7FFFFFF; i<unprocessed; i++)
  726. {
  727. unitPtr = (Unit*) get_ptr(curArrayPtr[i]);
  728. xDist = abs(xLoc-unitPtr->next_x_loc());
  729. yDist = abs(yLoc-unitPtr->next_y_loc());
  730. dist = (xDist >= yDist) ? xDist*10+yDist : yDist*10+xDist;
  731. if(dist < minDist)
  732. {
  733. minDist = dist;
  734. unitPos = i;
  735. }
  736. }
  737. unitPtr = (Unit*) get_ptr(curArrayPtr[unitPos]);
  738. curArrayPtr[unitPos] = curArrayPtr[--unprocessed]; // move the units in the back to the front
  739. err_when(unitPtr->action_mode2!=ACTION_ATTACK_WALL &&
  740. unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0);
  741. seek_path.set_status(PATH_WAIT);
  742. err_when(seek_path.path_status==PATH_NODE_USED_UP);
  743. unitPtr->attack_firm(targetXLoc, targetYLoc, xOffset, yOffset);
  744. //------------------------------------------------------------//
  745. // set the flag if unreachable
  746. //------------------------------------------------------------//
  747. if(seek_path.path_status==PATH_NODE_USED_UP)
  748. {
  749. unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST] = 1;
  750. analyseResult--;
  751. debug_result_check(analyseResult, firmWidth, firmHeight);
  752. err_when(analyseResult<0);
  753. //------------------------------------------------------------//
  754. // the nearby location should also be unreachable
  755. //------------------------------------------------------------//
  756. check_nearby_location(targetXLoc, targetYLoc, xOffset, yOffset, firmWidth, firmHeight,
  757. unitPtr->mobile_type, analyseResult);
  758. }
  759. update_unreachable_table(targetXLoc, targetYLoc, firmWidth, firmHeight, unitPtr->mobile_type, analyseResult);
  760. #ifdef DEBUG
  761. for(int di=0; di<firmWidth+2; di++)
  762. {
  763. for(int dj=0; dj<firmHeight+2; dj++)
  764. {
  765. if(di>=1 && di<=firmWidth && dj>=1 && dj<=firmHeight)
  766. continue;
  767. int debugXLoc = targetXLoc+di-SHIFT_ADJUST;
  768. int debugYLoc = targetYLoc+dj-SHIFT_ADJUST;
  769. if(debugXLoc<0 || debugXLoc>=MAX_WORLD_X_LOC || debugYLoc<0 || debugYLoc>=MAX_WORLD_Y_LOC)
  770. continue;
  771. Location *dlPtr = world.get_loc(debugXLoc, debugYLoc);
  772. err_when(!dlPtr->can_move(unitPtr->mobile_type) && unreachable_table[di][dj]==0);
  773. }
  774. }
  775. #endif
  776. }
  777. }
  778. //---------------------------------------------------------------------//
  779. // set the unreachable flag for each units
  780. //---------------------------------------------------------------------//
  781. //-************** codes here ***************-//
  782. //---------------------------------------------------------------------//
  783. // destruct data structure
  784. //---------------------------------------------------------------------//
  785. for(count=0; count<ATTACK_DIR; count++)
  786. mem_del(dir_array_ptr[count]);
  787. mem_del(unit_processed_array);
  788. }
  789. //----------- End of function UnitArray::attack_firm -----------//
  790. //--------- Begin of function UnitArray::attack_town ---------//
  791. // <int> targetXLoc, targetYLoc - the town upper left location
  792. // <short> townRecno - the town recno
  793. //
  794. // try to calculate the best location for each unit to move to the
  795. // surrounding of the town for attacking
  796. //
  797. void UnitArray::attack_town(int targetXLoc, int targetYLoc, short townRecno, short* selectedUnitArray, int selectedCount)
  798. {
  799. err_when(selectedCount<=0);
  800. if(selectedCount==1)
  801. {
  802. Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
  803. unitPtr->unit_group_id = unit_array.cur_group_id++;
  804. unitPtr->attack_town(targetXLoc, targetYLoc);
  805. return;
  806. }
  807. //********************** improve later begin **************************//
  808. //---------------------------------------------------------------------//
  809. // codes for differnt territory or different mobile_type attacking should
  810. // be added in the future.
  811. //---------------------------------------------------------------------//
  812. Unit *firstUnitPtr = unit_array[selectedUnitArray[0]];
  813. if(world.get_loc(targetXLoc, targetYLoc)->region_id !=
  814. world.get_loc(firstUnitPtr->next_x_loc(), firstUnitPtr->next_y_loc())->region_id)
  815. {
  816. Unit *unitPtr;
  817. set_group_id(selectedUnitArray, selectedCount);
  818. for(int i=0; i<selectedCount; i++)
  819. {
  820. unitPtr = (Unit*) get_ptr(selectedUnitArray[i]);
  821. unitPtr->attack_town(targetXLoc, targetYLoc);
  822. }
  823. return;
  824. }
  825. //*********************** improve later end ***************************//
  826. //----------- initialize local parameters ------------//
  827. int targetXLoc2 = targetXLoc + STD_TOWN_LOC_WIDTH - 1; // the lower right corner of the firm
  828. int targetYLoc2 = targetYLoc + STD_TOWN_LOC_HEIGHT - 1;
  829. char *xOffsetPtr, *yOffsetPtr;
  830. //---------------------------------------------------------------------//
  831. // construct data structure
  832. //---------------------------------------------------------------------//
  833. int tempVar = sizeof(short)*selectedCount;
  834. memset(dir_array_count, 0, sizeof(dir_array_count));
  835. int count;
  836. for(count=0; count<ATTACK_DIR; count++)
  837. {
  838. dir_array_ptr[count] = (short*) mem_add(tempVar);
  839. memset(dir_array_ptr[count], 0, tempVar);
  840. }
  841. unit_processed_array = (short *)mem_add(tempVar);
  842. unit_processed_count = 0;
  843. //---------------------------------------------------------------------//
  844. // divide the units into each region
  845. //---------------------------------------------------------------------//
  846. Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
  847. err_when(!unitPtr);
  848. DWORD groupId = unit_array.cur_group_id++;
  849. arrange_units_in_group(targetXLoc, targetYLoc, targetXLoc2, targetYLoc2, selectedUnitArray, selectedCount, groupId, 3);
  850. //---------------------------------------------------------------------//
  851. // now the attackers are divided into 8 groups to attack the target
  852. //---------------------------------------------------------------------//
  853. int xLoc, yLoc; // actual target surrounding location to move to
  854. int xOffset, yOffset; // offset location of the target
  855. int unprocessed; // number of units in this group
  856. int dist, xDist, yDist, minDist;
  857. int destCount;
  858. short unitPos; // store the position of the unit with minDist
  859. short *curArrayPtr;
  860. char surroundLoc = get_target_surround_loc(STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT);
  861. int i;
  862. for(i=0; i<MAX_UNIT_SURROUND_SIZE; i++)
  863. memset(unreachable_table[i], 0, sizeof(char)*MAX_UNIT_SURROUND_SIZE);
  864. //---------------------------------------------------------------------//
  865. // analyse the surrounding location of the target
  866. //---------------------------------------------------------------------//
  867. int analyseResult = analyse_surround_location(targetXLoc, targetYLoc, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, unitPtr->mobile_type);
  868. debug_result_check(analyseResult, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT);
  869. err_when(analyseResult<0);
  870. if(!analyseResult) // 0 if all surround location is not accessible
  871. {
  872. //------------------------------------------------------------//
  873. // special handling for this case
  874. //------------------------------------------------------------//
  875. handle_attack_target_totally_blocked(targetXLoc, targetYLoc, townRecno, selectedUnitArray, selectedCount, 3);
  876. for(count=0; count<ATTACK_DIR; count++)
  877. mem_del(dir_array_ptr[count]);
  878. mem_del(unit_processed_array);
  879. return;
  880. }
  881. //---------------------------------------------------------------------//
  882. // let the units move to the rest accessible location
  883. //---------------------------------------------------------------------//
  884. for(count=0; count<ATTACK_DIR; count++) // for each array/group
  885. {
  886. //--------- initialize for each group --------//
  887. unprocessed = dir_array_count[count]; // get the number of units in this region
  888. curArrayPtr = dir_array_ptr[count]; // get the recno of units in this region
  889. destCount = surroundLoc-1;
  890. xOffsetPtr = get_target_x_offset(STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, count);
  891. yOffsetPtr = get_target_y_offset(STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, count);
  892. xOffset = *xOffsetPtr;
  893. yOffset = *yOffsetPtr;
  894. //-----------------------------------------------------------------//
  895. // determine a suitable location for the attacker to move to
  896. //-----------------------------------------------------------------//
  897. while(unprocessed)
  898. {
  899. //-----------------------------------------------------//
  900. // find a reachable location, or not searched location
  901. //-----------------------------------------------------//
  902. if(!analyseResult)
  903. {
  904. handle_attack_target_totally_blocked(targetXLoc, targetYLoc, townRecno, selectedUnitArray, selectedCount, 3);
  905. for(count=0; count<ATTACK_DIR; count++)
  906. mem_del(dir_array_ptr[count]);
  907. mem_del(unit_processed_array);
  908. return;
  909. }
  910. else
  911. {
  912. for(i=0; i<surroundLoc; i++)
  913. {
  914. if((++destCount)>=surroundLoc)
  915. {
  916. destCount = 0;
  917. xOffsetPtr = get_target_x_offset(STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, count);
  918. yOffsetPtr = get_target_y_offset(STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, count);
  919. xOffset = *xOffsetPtr;
  920. yOffset = *yOffsetPtr;
  921. }
  922. else
  923. {
  924. xOffset = *(++xOffsetPtr);
  925. yOffset = *(++yOffsetPtr);
  926. }
  927. if(!unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST])
  928. break;
  929. }
  930. }
  931. err_when(unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST]);
  932. //------------------------------------------------------------//
  933. // find the closest attacker
  934. //------------------------------------------------------------//
  935. err_when(unprocessed>2000 || unprocessed <0);
  936. xLoc = targetXLoc + xOffset;
  937. yLoc = targetYLoc + yOffset;
  938. err_when(!world.get_loc(xLoc, yLoc)->can_move(unitPtr->mobile_type));
  939. for(i=0, minDist=0x7FFFFFF; i<unprocessed; i++)
  940. {
  941. unitPtr = (Unit*) get_ptr(curArrayPtr[i]);
  942. xDist = abs(xLoc-unitPtr->next_x_loc());
  943. yDist = abs(yLoc-unitPtr->next_y_loc());
  944. dist = (xDist >= yDist) ? xDist*10+yDist : yDist*10+xDist;
  945. if(dist < minDist)
  946. {
  947. minDist = dist;
  948. unitPos = i;
  949. }
  950. }
  951. unitPtr = (Unit*) get_ptr(curArrayPtr[unitPos]);
  952. curArrayPtr[unitPos] = curArrayPtr[--unprocessed]; // move the units in the back to the front
  953. err_when(unitPtr->action_mode2!=ACTION_ATTACK_WALL &&
  954. unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0);
  955. seek_path.set_status(PATH_WAIT);
  956. err_when(seek_path.path_status==PATH_NODE_USED_UP);
  957. unitPtr->attack_town(targetXLoc, targetYLoc, xOffset, yOffset);
  958. //------------------------------------------------------------//
  959. // set the flag if unreachable
  960. //------------------------------------------------------------//
  961. if(seek_path.path_status==PATH_NODE_USED_UP)
  962. {
  963. unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST] = 1;
  964. analyseResult--;
  965. debug_result_check(analyseResult, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT);
  966. err_when(analyseResult<0);
  967. //------------------------------------------------------------//
  968. // the nearby location should also be unreachable
  969. //------------------------------------------------------------//
  970. check_nearby_location(targetXLoc, targetYLoc, xOffset, yOffset, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT,
  971. unitPtr->mobile_type, analyseResult);
  972. }
  973. update_unreachable_table(targetXLoc, targetYLoc, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, unitPtr->mobile_type, analyseResult);
  974. #ifdef DEBUG
  975. Location *dlPtr;
  976. for(int di=0; di<STD_TOWN_LOC_WIDTH+2; di++)
  977. {
  978. for(int dj=0; dj<STD_TOWN_LOC_HEIGHT+2; dj++)
  979. {
  980. if(di>=1 && di<=STD_TOWN_LOC_WIDTH && dj>=1 && dj<=STD_TOWN_LOC_HEIGHT)
  981. continue;
  982. int debugXLoc = targetXLoc+di-SHIFT_ADJUST;
  983. int debugYLoc = targetYLoc+dj-SHIFT_ADJUST;
  984. if(debugXLoc<0 || debugXLoc>=MAX_WORLD_X_LOC || debugYLoc<0 || debugYLoc>=MAX_WORLD_Y_LOC)
  985. continue;
  986. dlPtr = world.get_loc(debugXLoc, debugYLoc);
  987. err_when(!dlPtr->can_move(unitPtr->mobile_type) && unreachable_table[di][dj]==0);
  988. }
  989. }
  990. #endif
  991. }
  992. }
  993. //---------------------------------------------------------------------//
  994. // set the unreachable flag for each units
  995. //---------------------------------------------------------------------//
  996. //-************** codes here ***************-//
  997. //---------------------------------------------------------------------//
  998. // destruct data structure
  999. //---------------------------------------------------------------------//
  1000. for(count=0; count<ATTACK_DIR; count++)
  1001. mem_del(dir_array_ptr[count]);
  1002. mem_del(unit_processed_array);
  1003. }
  1004. //----------- End of function UnitArray::attack_town -----------//
  1005. //--------- Begin of function UnitArray::attack_wall ---------//
  1006. // <int> targetXLoc - x location of the wall
  1007. // <int> targetYLoc - y location of the wall
  1008. //
  1009. void UnitArray::attack_wall(int targetXLoc, int targetYLoc, short* selectedUnitArray, int selectedCount)
  1010. {
  1011. err_when(selectedCount<=0);
  1012. if(selectedCount==1)
  1013. {
  1014. Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
  1015. unitPtr->unit_group_id = unit_array.cur_group_id++;
  1016. unitPtr->attack_wall(targetXLoc, targetYLoc);
  1017. return;
  1018. }
  1019. //********************** improve later begin **************************//
  1020. //---------------------------------------------------------------------//
  1021. // codes for differnt territory or different mobile_type attacking should
  1022. // be added in the future.
  1023. //---------------------------------------------------------------------//
  1024. Unit *firstUnitPtr = unit_array[selectedUnitArray[0]];
  1025. if(world.get_loc(targetXLoc, targetYLoc)->region_id !=
  1026. world.get_loc(firstUnitPtr->next_x_loc(), firstUnitPtr->next_y_loc())->region_id)
  1027. {
  1028. Unit *unitPtr;
  1029. set_group_id(selectedUnitArray, selectedCount);
  1030. for(int i=0; i<selectedCount; i++)
  1031. {
  1032. unitPtr = (Unit*) get_ptr(selectedUnitArray[i]);
  1033. unitPtr->attack_wall(targetXLoc, targetYLoc);
  1034. }
  1035. return;
  1036. }
  1037. //*********************** improve later end ***************************//
  1038. //----------- initialize local parameters ------------//
  1039. char *xOffsetPtr, *yOffsetPtr;
  1040. //---------------------------------------------------------------------//
  1041. // construct data structure
  1042. //---------------------------------------------------------------------//
  1043. int tempVar = sizeof(short)*selectedCount;
  1044. memset(dir_array_count, 0, sizeof(dir_array_count));
  1045. int count;
  1046. for(count=0; count<ATTACK_DIR; count++)
  1047. {
  1048. dir_array_ptr[count] = (short*) mem_add(tempVar);
  1049. memset(dir_array_ptr[count], 0, tempVar);
  1050. }
  1051. unit_processed_array = (short *)mem_add(tempVar);
  1052. unit_processed_count = 0;
  1053. //---------------------------------------------------------------------//
  1054. // divide the units into each region
  1055. //---------------------------------------------------------------------//
  1056. Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
  1057. err_when(!unitPtr);
  1058. DWORD groupId = unit_array.cur_group_id++;
  1059. arrange_units_in_group(targetXLoc, targetYLoc, targetXLoc, targetYLoc, selectedUnitArray, selectedCount, groupId, 0);
  1060. //---------------------------------------------------------------------//
  1061. // now the attackers are divided into 8 groups to attack the target
  1062. //---------------------------------------------------------------------//
  1063. int xLoc, yLoc; // actual target surrounding location to move to
  1064. int xOffset, yOffset; // offset location of the target
  1065. int unprocessed; // number of units in this group
  1066. int dist, xDist, yDist, minDist;
  1067. int destCount;
  1068. short unitPos; // store the position of the unit with minDist
  1069. short *curArrayPtr;
  1070. char surroundLoc = get_target_surround_loc(1, 1);
  1071. int i;
  1072. for(i=0; i<MAX_UNIT_SURROUND_SIZE; i++)
  1073. memset(unreachable_table[i], 0, sizeof(char)*MAX_UNIT_SURROUND_SIZE);
  1074. //---------------------------------------------------------------------//
  1075. // analyse the surrounding location of the target
  1076. //---------------------------------------------------------------------//
  1077. int analyseResult = analyse_surround_location(targetXLoc, targetYLoc, 1, 1, unitPtr->mobile_type);
  1078. debug_result_check(analyseResult, 1, 1);
  1079. err_when(analyseResult<0);
  1080. if(!analyseResult) // 0 if all surround location is not accessible
  1081. {
  1082. //------------------------------------------------------------//
  1083. // special handling for this case
  1084. //------------------------------------------------------------//
  1085. handle_attack_target_totally_blocked(targetXLoc, targetYLoc, 0, selectedUnitArray, selectedCount, 0);
  1086. for(count=0; count<ATTACK_DIR; count++)
  1087. mem_del(dir_array_ptr[count]);
  1088. mem_del(unit_processed_array);
  1089. return;
  1090. }
  1091. //---------------------------------------------------------------------//
  1092. // let the units move to the rest accessible location
  1093. //---------------------------------------------------------------------//
  1094. for(count=0; count<ATTACK_DIR; count++) // for each array/group
  1095. {
  1096. //--------- initialize for each group --------//
  1097. unprocessed = dir_array_count[count]; // get the number of units in this region
  1098. curArrayPtr = dir_array_ptr[count]; // get the recno of units in this region
  1099. destCount = surroundLoc-1;
  1100. xOffsetPtr = get_target_x_offset(1, 1, count);
  1101. yOffsetPtr = get_target_y_offset(1, 1, count);
  1102. xOffset = *xOffsetPtr;
  1103. yOffset = *yOffsetPtr;
  1104. //-----------------------------------------------------------------//
  1105. // determine a suitable location for the attacker to move to
  1106. //-----------------------------------------------------------------//
  1107. while(unprocessed)
  1108. {
  1109. //-----------------------------------------------------//
  1110. // find a reachable location, or not searched location
  1111. //-----------------------------------------------------//
  1112. if(!analyseResult)
  1113. {
  1114. handle_attack_target_totally_blocked(targetXLoc, targetYLoc, 0, selectedUnitArray, selectedCount, 0);
  1115. for(count=0; count<ATTACK_DIR; count++)
  1116. mem_del(dir_array_ptr[count]);
  1117. mem_del(unit_processed_array);
  1118. return;
  1119. }
  1120. else
  1121. {
  1122. for(i=0; i<surroundLoc; i++)
  1123. {
  1124. if((++destCount)>=surroundLoc)
  1125. {
  1126. destCount = 0;
  1127. xOffsetPtr = get_target_x_offset(1, 1, count);
  1128. yOffsetPtr = get_target_y_offset(1, 1, count);
  1129. xOffset = *xOffsetPtr;
  1130. yOffset = *yOffsetPtr;
  1131. }
  1132. else
  1133. {
  1134. xOffset = *(++xOffsetPtr);
  1135. yOffset = *(++yOffsetPtr);
  1136. }
  1137. if(!unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST])
  1138. break;
  1139. }
  1140. }
  1141. err_when(unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST]);
  1142. //------------------------------------------------------------//
  1143. // find the closest attacker
  1144. //------------------------------------------------------------//
  1145. err_when(unprocessed>2000 || unprocessed <0);
  1146. xLoc = targetXLoc + xOffset;
  1147. yLoc = targetYLoc + yOffset;
  1148. err_when(!world.get_loc(xLoc, yLoc)->can_move(unitPtr->mobile_type));
  1149. for(i=0, minDist=0x7FFFFFF; i<unprocessed; i++)
  1150. {
  1151. unitPtr = (Unit*) get_ptr(curArrayPtr[i]);
  1152. xDist = abs(xLoc-unitPtr->next_x_loc());
  1153. yDist = abs(yLoc-unitPtr->next_y_loc());
  1154. dist = (xDist >= yDist) ? xDist*10+yDist : yDist*10+xDist;
  1155. if(dist < minDist)
  1156. {
  1157. minDist = dist;
  1158. unitPos = i;
  1159. }
  1160. }
  1161. unitPtr = (Unit*) get_ptr(curArrayPtr[unitPos]);
  1162. curArrayPtr[unitPos] = curArrayPtr[--unprocessed]; // move the units in the back to the front
  1163. err_when(unitPtr->action_mode2!=ACTION_ATTACK_WALL &&
  1164. unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0);
  1165. seek_path.set_status(PATH_WAIT);
  1166. err_when(seek_path.path_status==PATH_NODE_USED_UP);
  1167. unitPtr->attack_wall(targetXLoc, targetYLoc, xOffset, yOffset);
  1168. //------------------------------------------------------------//
  1169. // set the flag if unreachable
  1170. //------------------------------------------------------------//
  1171. if(seek_path.path_status==PATH_NODE_USED_UP)
  1172. {
  1173. unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST] = 1;
  1174. analyseResult--;
  1175. debug_result_check(analyseResult, 1, 1);
  1176. err_when(analyseResult<0);
  1177. //------------------------------------------------------------//
  1178. // the nearby location should also be unreachable
  1179. //------------------------------------------------------------//
  1180. check_nearby_location(targetXLoc, targetYLoc, xOffset, yOffset, 1, 1, unitPtr->mobile_type, analyseResult);
  1181. }
  1182. update_unreachable_table(targetXLoc, targetYLoc, 1, 1, unitPtr->mobile_type, analyseResult);
  1183. #ifdef DEBUG
  1184. for(int di=0; di<3; di++)
  1185. {
  1186. for(int dj=0; dj<3; dj++)
  1187. {
  1188. if(di==1 && dj==1)
  1189. continue;
  1190. int debugXLoc = targetXLoc+di-SHIFT_ADJUST;
  1191. int debugYLoc = targetYLoc+dj-SHIFT_ADJUST;
  1192. if(debugXLoc<0 || debugXLoc>=MAX_WORLD_X_LOC || debugYLoc<0 || debugYLoc>=MAX_WORLD_Y_LOC)
  1193. continue;
  1194. Location *dlPtr = world.get_loc(debugXLoc, debugYLoc);
  1195. err_when(!dlPtr->can_move(unitPtr->mobile_type) && unreachable_table[di][dj]==0);
  1196. }
  1197. }
  1198. #endif
  1199. }
  1200. }
  1201. //---------------------------------------------------------------------//
  1202. // set the unreachable flag for each units
  1203. //---------------------------------------------------------------------//
  1204. //-************** codes here ***************-//
  1205. //---------------------------------------------------------------------//
  1206. // destruct data structure
  1207. //---------------------------------------------------------------------//
  1208. for(count=0; count<ATTACK_DIR; count++)
  1209. mem_del(dir_array_ptr[count]);
  1210. mem_del(unit_processed_array);
  1211. }
  1212. //----------- End of function UnitArray::attack_wall -----------//
  1213. //--------- Begin of function UnitArray::arrange_units_in_group ---------//
  1214. // <int> xLoc1 - top left x location of the target
  1215. // <int> yLoc1 - top left y location of the target
  1216. // <int> xLoc2 - bottom right x location of the target
  1217. // <int> yLoc2 - bottom right y location of the target
  1218. // <short*> selectedUnitArray - recno. of selected units
  1219. // <int> selectedCount - count of selected units
  1220. // <DWORD> unitGroupId - group id for the selected units
  1221. //
  1222. // <int> targetType - 0 for wall, 1 for unit, 2 for firm, 3 for town
  1223. //
  1224. void UnitArray::arrange_units_in_group(int xLoc1, int yLoc1, int xLoc2, int yLoc2, short* selectedUnitArray,
  1225. int selectedCount, DWORD unitGroupId, int targetType)
  1226. {
  1227. Unit *unitPtr;
  1228. int curXLoc, curYLoc;
  1229. for(int i=0; i<selectedCount; i++)
  1230. {
  1231. unitPtr = (Unit*) get_ptr(selectedUnitArray[i]);
  1232. err_when(!unitPtr);
  1233. unitPtr->unit_group_id = unitGroupId; // set unit_group_id
  1234. err_when(unitPtr->cur_action==SPRITE_IDLE && (unitPtr->cur_x!=unitPtr->next_x || unitPtr->cur_y!=unitPtr->next_y));
  1235. if(unitPtr->cur_action==SPRITE_IDLE)
  1236. unitPtr->set_ready();
  1237. curXLoc = unitPtr->next_x_loc();
  1238. curYLoc = unitPtr->next_y_loc();
  1239. if(curXLoc>=xLoc1-1 && curXLoc<=xLoc2+1 && curYLoc>=yLoc1-1 && curYLoc<=yLoc2+1)
  1240. {
  1241. //------------- already in the target surrounding ----------------//
  1242. switch(targetType)
  1243. {
  1244. case 0: unitPtr->attack_wall(xLoc1, yLoc1);
  1245. break;
  1246. case 1: unitPtr->attack_unit(xLoc1, yLoc1);
  1247. break;
  1248. case 2: unitPtr->attack_firm(xLoc1, yLoc1);
  1249. break;
  1250. case 3: unitPtr->attack_town(xLoc1, yLoc1);
  1251. break;
  1252. }
  1253. continue;
  1254. }
  1255. //---- the attacker need to call searching to reach the target ----//
  1256. if(curXLoc < xLoc1)
  1257. {
  1258. if(curYLoc < yLoc1) // 8
  1259. dir_array_ptr[7][dir_array_count[7]++] = selectedUnitArray[i];
  1260. else if(curYLoc > yLoc2)// 2
  1261. dir_array_ptr[1][dir_array_count[1]++] = selectedUnitArray[i];
  1262. else // 1
  1263. dir_array_ptr[0][dir_array_count[0]++] = selectedUnitArray[i];
  1264. }
  1265. else if(curXLoc > xLoc2)
  1266. {
  1267. if(curYLoc < yLoc1) // 6
  1268. dir_array_ptr[5][dir_array_count[5]++] = selectedUnitArray[i];
  1269. else if(curYLoc > yLoc2)// 4
  1270. dir_array_ptr[3][dir_array_count[3]++] = selectedUnitArray[i];
  1271. else // 5
  1272. dir_array_ptr[4][dir_array_count[4]++] = selectedUnitArray[i];
  1273. }
  1274. else // curXLoc==targetXLoc2
  1275. {
  1276. if(curYLoc < yLoc1) // 7
  1277. dir_array_ptr[6][dir_array_count[6]++] = selectedUnitArray[i];
  1278. else if(curYLoc > yLoc2)// 3
  1279. dir_array_ptr[2][dir_array_count[2]++] = selectedUnitArray[i];
  1280. else // curXLoc==xLoc2 && curYLoc==yLoc2
  1281. {
  1282. // target is one of the selected unit, error
  1283. err_here();
  1284. }
  1285. }
  1286. }
  1287. }
  1288. //----------- End of function UnitArray::arrange_units_in_group -----------//
  1289. //--------- Begin of function UnitArray::analyse_surround_location ---------//
  1290. // return the number of accessible surrounding location of the target
  1291. //
  1292. // <int> targetXLoc - target x location
  1293. // <int> targetYLoc - target y location
  1294. // <int> targetWidth - target width
  1295. // <int> targetHeight - target height
  1296. // <char> mobileType - target mobile type
  1297. //
  1298. int UnitArray::analyse_surround_location(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, char mobileType)
  1299. {
  1300. static char xIncreTable[4] = { 1, 0, -1, 0};
  1301. static char yIncreTable[4] = { 0, 1, 0, -1};
  1302. err_when(targetWidth<1 || targetWidth>4);
  1303. Location *locPtr;
  1304. int xLoc = targetXLoc-1;
  1305. int yLoc = targetYLoc-1;
  1306. int targetXLoc2 = targetXLoc + targetWidth - 1;
  1307. int targetYLoc2 = targetYLoc + targetHeight - 1;
  1308. int bound = 2*(targetWidth + targetHeight) + 4; // (x+2)*(y+2) - xy
  1309. int increCount=4, xIncre, yIncre, found=0;
  1310. err_when(targetWidth==3 && targetHeight==3 && bound!=16);
  1311. for(int i=0; i<bound; i++)
  1312. {
  1313. if(xLoc<0 || xLoc>=MAX_WORLD_X_LOC || yLoc<0 || yLoc>=MAX_WORLD_Y_LOC)
  1314. unreachable_table[xLoc-targetXLoc+SHIFT_ADJUST][yLoc-targetYLoc+SHIFT_ADJUST] = 1;
  1315. else
  1316. {
  1317. locPtr = world.get_loc(xLoc, yLoc);
  1318. if(!locPtr->can_move(mobileType))
  1319. unreachable_table[xLoc-targetXLoc+SHIFT_ADJUST][yLoc-targetYLoc+SHIFT_ADJUST] = 1;
  1320. else
  1321. found++;
  1322. }
  1323. if((xLoc==targetXLoc-1 || xLoc==targetXLoc2+1) && (yLoc==targetYLoc-1 || yLoc==targetYLoc2+1)) // at the corner
  1324. {
  1325. if((++increCount)>=4)
  1326. increCount = 0;
  1327. xIncre = xIncreTable[increCount];
  1328. yIncre = yIncreTable[increCount];
  1329. }
  1330. xLoc += xIncre;
  1331. yLoc += yIncre;
  1332. }
  1333. return found;
  1334. }
  1335. //----------- End of function UnitArray::analyse_surround_location -----------//
  1336. //--------- Begin of function UnitArray::check_nearby_location ---------//
  1337. // check the target location to find out how many of its surrounding location
  1338. // is not blocked
  1339. //
  1340. // <int> targetXLoc - target x location
  1341. // <int> targetYLoc - target y location
  1342. // <char> xOffset - x offset from target x location
  1343. // <char> yOffset - y offset from target y location
  1344. // <int> targetWidth - target width
  1345. // <int> targetHeight - target height
  1346. // <char> targetMobileType - target mobile type
  1347. // <int&> analyseResult - reference for returning
  1348. //
  1349. void UnitArray::check_nearby_location(int targetXLoc, int targetYLoc, char xOffset, char yOffset,
  1350. int targetWidth, int targetHeight, char targetMobileType, int& analyseResult)
  1351. {
  1352. #ifdef DEBUG
  1353. int backupAnalyseResult = analyseResult;
  1354. char debugUnreachableTable[MAX_UNIT_SURROUND_SIZE][MAX_UNIT_SURROUND_SIZE];
  1355. memcpy(debugUnreachableTable, unreachable_table, sizeof(char)*MAX_UNIT_SURROUND_SIZE*MAX_UNIT_SURROUND_SIZE);
  1356. #endif
  1357. debug_result_check(analyseResult, targetWidth, targetHeight);
  1358. static char leftXIncreTable[4] = { 1, 0, -1, 0};
  1359. static char leftYIncreTable[4] = { 0, 1, 0, -1};
  1360. static char rightXIncreTable[4] = { -1, 0, 1, 0};
  1361. static char rightYIncreTable[4] = { 0, 1, 0, -1};
  1362. err_when(targetWidth<1 || targetWidth>4);
  1363. Location *locPtr;
  1364. int targetXLoc2 = targetXLoc + targetWidth - 1;
  1365. int targetYLoc2 = targetYLoc + targetHeight - 1;
  1366. int bound = 2*(targetWidth + targetHeight) + 4; // (x+2)*(y+2) - xy
  1367. int leftXLoc ,leftYLoc, leftContinue=1;
  1368. int leftXIncre, leftYIncre, leftIncreCount;
  1369. int rightXLoc, rightYLoc, rightContinue=1;
  1370. int rightXIncre, rightYIncre, rightIncreCount=1;
  1371. //-------------------------------------------------------------------------------------//
  1372. // determine the initial situation
  1373. //-------------------------------------------------------------------------------------//
  1374. if((xOffset==-1 || xOffset==targetWidth) && (yOffset==-1 || yOffset==targetHeight)) // at the corner
  1375. {
  1376. if(xOffset==-1)
  1377. {
  1378. if(yOffset==-1) // upper left corner
  1379. {
  1380. leftXIncre = 1;
  1381. leftYIncre = 0;
  1382. leftIncreCount = 0;
  1383. rightXIncre = 0;
  1384. rightYIncre = 1;
  1385. rightIncreCount = 1;
  1386. }
  1387. else // lower left corner
  1388. {
  1389. leftXIncre = 0;
  1390. leftYIncre = -1;
  1391. leftIncreCount = 3;
  1392. rightXIncre = 1;
  1393. rightYIncre = 0;
  1394. rightIncreCount = 2;
  1395. }
  1396. }
  1397. else
  1398. {
  1399. if(yOffset==-1) // upper right corner
  1400. {
  1401. leftXIncre = 0;
  1402. leftYIncre = 1;
  1403. leftIncreCount = 1;
  1404. rightXIncre = -1;
  1405. rightYIncre = 0;
  1406. rightIncreCount = 0;
  1407. }
  1408. else // lower right corner
  1409. {
  1410. leftXIncre = -1;
  1411. leftYIncre = 0;
  1412. leftIncreCount = 2;
  1413. rightXIncre = 0;
  1414. rightYIncre = -1;
  1415. rightIncreCount = 3;
  1416. }
  1417. }
  1418. }
  1419. else // at the edge
  1420. {
  1421. if(xOffset==-1) // left edge
  1422. {
  1423. leftXIncre = 0;
  1424. leftYIncre = -1;
  1425. leftIncreCount = 3;
  1426. rightXIncre = 0;
  1427. rightYIncre = 1;
  1428. rightIncreCount = 1;
  1429. }
  1430. else if(xOffset==targetWidth) // right edge
  1431. {
  1432. leftXIncre = 0;
  1433. leftYIncre = 1;
  1434. leftIncreCount = 1;
  1435. rightXIncre = 0;
  1436. rightYIncre = -1;
  1437. rightIncreCount = 3;
  1438. }
  1439. else if(yOffset==-1) // upper edge
  1440. {
  1441. leftXIncre = 1;
  1442. leftYIncre = 0;
  1443. leftIncreCount = 0;
  1444. rightXIncre = -1;
  1445. rightYIncre = 0;
  1446. rightIncreCount = 0;
  1447. }
  1448. else if(yOffset==targetHeight) // lower edge
  1449. {
  1450. leftXIncre = -1;
  1451. leftYIncre = 0;
  1452. leftIncreCount = 2;
  1453. rightXIncre = 1;
  1454. rightYIncre = 0;
  1455. rightIncreCount = 2;
  1456. }
  1457. }
  1458. leftXLoc = rightXLoc = targetXLoc + xOffset;
  1459. leftYLoc = rightYLoc = targetYLoc + yOffset;
  1460. int canReach;
  1461. int outBoundary; // true if out of map boundary
  1462. //-------------------------------------------------------------------------------------//
  1463. // count the reachable location
  1464. //-------------------------------------------------------------------------------------//
  1465. for(int i=1; i<bound; i++) // exclude the starting location
  1466. {
  1467. debug_result_check(analyseResult, targetWidth, targetHeight);
  1468. #ifdef DEBUG
  1469. int debugLeftXLoc = leftXLoc;
  1470. int debugLeftYloc = leftYLoc;
  1471. int debugRightXLoc = rightXLoc;
  1472. int debugRightYLoc = rightYLoc;
  1473. int debugLeftIncreCount = leftIncreCount;
  1474. int debugRightIncreCount = rightIncreCount;
  1475. char debugUnreachableTable2[MAX_UNIT_SURROUND_SIZE][MAX_UNIT_SURROUND_SIZE];
  1476. memcpy(debugUnreachableTable2, unreachable_table, sizeof(char)*MAX_UNIT_SURROUND_SIZE*MAX_UNIT_SURROUND_SIZE);
  1477. for(int i=0; i<MAX_UNIT_SURROUND_SIZE; i++)
  1478. {
  1479. for(int j=0; j<MAX_UNIT_SURROUND_SIZE; j++)
  1480. {
  1481. if(debugUnreachableTable2[i][j] && debugUnreachableTable2[i][j]==1)
  1482. debugUnreachableTable2[i][j] = 2; // plus 1 to distinguish the original table
  1483. }
  1484. }
  1485. #endif
  1486. //------------------------------------------------------------//
  1487. // process left hand side checking
  1488. //------------------------------------------------------------//
  1489. if(leftContinue)
  1490. {
  1491. canReach = 0;
  1492. outBoundary = 0;
  1493. leftXLoc += leftXIncre;
  1494. leftYLoc += leftYIncre;
  1495. if((leftXLoc==targetXLoc-1 || leftXLoc==targetXLoc2+1) && (leftYLoc==targetYLoc-1 || leftYLoc==targetYLoc2+1))
  1496. {
  1497. if((++leftIncreCount)>=4)
  1498. leftIncreCount = 0;
  1499. leftXIncre = leftXIncreTable[leftIncreCount];
  1500. leftYIncre = leftYIncreTable[leftIncreCount];
  1501. }
  1502. if(leftXLoc>=0 && leftXLoc<MAX_WORLD_X_LOC && leftYLoc>=0 && leftYLoc<MAX_WORLD_Y_LOC)
  1503. {
  1504. if(unreachable_table[leftXLoc-targetXLoc+SHIFT_ADJUST][leftYLoc-targetYLoc+SHIFT_ADJUST])
  1505. canReach = 1; // concept incorrect, but it is used to terminate this part of checking
  1506. else
  1507. {
  1508. locPtr = world.get_loc(leftXLoc, leftYLoc);
  1509. if(locPtr->can_move(targetMobileType))
  1510. canReach = 1;
  1511. }
  1512. }
  1513. else
  1514. outBoundary = 1;
  1515. if(canReach)
  1516. leftContinue = 0;
  1517. else if(!outBoundary)
  1518. {
  1519. err_when(unreachable_table[leftXLoc-targetXLoc+SHIFT_ADJUST][leftYLoc-targetYLoc+SHIFT_ADJUST]);
  1520. unreachable_table[leftXLoc-targetXLoc+SHIFT_ADJUST][leftYLoc-targetYLoc+SHIFT_ADJUST] = 1;
  1521. analyseResult--;
  1522. debug_result_check(analyseResult, targetWidth, targetHeight);
  1523. err_when(analyseResult<0);
  1524. }
  1525. #ifdef DEBUG
  1526. else
  1527. err_when(!unreachable_table[leftXLoc-targetXLoc+SHIFT_ADJUST][leftYLoc-targetYLoc+SHIFT_ADJUST]);
  1528. #endif
  1529. i++;
  1530. }
  1531. //------------------------------------------------------------//
  1532. // process right hand side checking
  1533. //------------------------------------------------------------//
  1534. if(rightContinue)
  1535. {
  1536. canReach = 0;
  1537. outBoundary = 0;
  1538. rightXLoc += rightXIncre;
  1539. rightYLoc += rightYIncre;
  1540. if((rightXLoc==targetXLoc-1 || rightXLoc==targetXLoc2+1) && (rightYLoc==targetYLoc-1 || rightYLoc==targetYLoc2+1))
  1541. {
  1542. if((++rightIncreCount)>=4)
  1543. rightIncreCount = 0;
  1544. rightXIncre = rightXIncreTable[rightIncreCount];
  1545. rightYIncre = rightYIncreTable[rightIncreCount];
  1546. }
  1547. if(rightXLoc>=0 && rightXLoc<MAX_WORLD_X_LOC && rightYLoc>=0 && rightYLoc<MAX_WORLD_Y_LOC)
  1548. {
  1549. if(unreachable_table[rightXLoc-targetXLoc+SHIFT_ADJUST][rightYLoc-targetYLoc+SHIFT_ADJUST])
  1550. canReach = 1; // concept incorrect, but it is used to terminate this part of checking
  1551. else
  1552. {
  1553. locPtr = world.get_loc(rightXLoc, rightYLoc);
  1554. if(locPtr->can_move(targetMobileType))
  1555. canReach = 1;
  1556. }
  1557. }
  1558. else
  1559. outBoundary = 1;
  1560. if(canReach)
  1561. rightContinue = 0;
  1562. else if(!outBoundary)
  1563. {
  1564. err_when(unreachable_table[rightXLoc-targetXLoc+SHIFT_ADJUST][rightYLoc-targetYLoc+SHIFT_ADJUST]);
  1565. unreachable_table[rightXLoc-targetXLoc+SHIFT_ADJUST][rightYLoc-targetYLoc+SHIFT_ADJUST] = 1;
  1566. analyseResult--;
  1567. debug_result_check(analyseResult, targetWidth, targetHeight);
  1568. err_when(analyseResult<0);
  1569. }
  1570. #ifdef DEBUG
  1571. else
  1572. err_when(!unreachable_table[rightXLoc-targetXLoc+SHIFT_ADJUST][rightYLoc-targetYLoc+SHIFT_ADJUST]);
  1573. #endif
  1574. }
  1575. if(!leftContinue && !rightContinue)
  1576. break;
  1577. }
  1578. }
  1579. //----------- End of function UnitArray::check_nearby_location -----------//
  1580. //--------- Begin of function UnitArray::handle_attack_target_totally_blocked ---------//
  1581. // handle attacking while the target is totally blocked
  1582. //
  1583. // <int> targetXLoc - target x loc
  1584. // <int> targetYLoc - target y loc
  1585. // <short> targetRecno - target recno
  1586. // <short*> selectedUnitArray - selected units' recno
  1587. // <short> selectedCount - num of selected unit
  1588. // <int> targetType - 0 for wall, 1 for unit, 2 for firm, 3 for town
  1589. //
  1590. void UnitArray::handle_attack_target_totally_blocked(int targetXLoc, int targetYLoc, short targetRecno,
  1591. short *selectedUnitArray, short selectedCount, int targetType)
  1592. {
  1593. if(unit_processed_count>0) // some units can reach the target surrounding
  1594. {
  1595. Unit *processedPtr, *unitPtr;
  1596. int proCount = unit_processed_count - 1;
  1597. int unproCount = selectedCount - proCount - 1; // number of unprocessed
  1598. int sCount = selectedCount-1;
  1599. int found, i, recno;
  1600. #ifdef DEBUG
  1601. int debugCount;
  1602. #endif
  1603. //------------------------------------------------------------------------------------//
  1604. // use the result of those processed units as a reference of those unprocessed units
  1605. //------------------------------------------------------------------------------------//
  1606. while(unproCount)
  1607. {
  1608. err_when(unit_array.is_deleted(unit_processed_array[proCount]));
  1609. processedPtr = (Unit*) get_ptr(unit_processed_array[proCount]);
  1610. #ifdef DEBUG
  1611. debugCount = 0;
  1612. #endif
  1613. err_when(sCount<0);
  1614. do
  1615. {
  1616. #ifdef DEBUG
  1617. debugCount++;
  1618. err_when(debugCount>1000);
  1619. #endif
  1620. found = 0;
  1621. recno = selectedUnitArray[sCount];
  1622. for(i=0; i<unit_processed_count; i++)
  1623. {
  1624. if(unit_processed_array[i]==recno)
  1625. {
  1626. found++;
  1627. break;
  1628. }
  1629. }
  1630. err_when(sCount<0 || sCount>selectedCount);
  1631. sCount--;
  1632. }while(found);
  1633. unitPtr = (Unit *) get_ptr(recno);
  1634. unitPtr->move_to(processedPtr->move_to_x_loc, processedPtr->move_to_y_loc);
  1635. switch(targetType)
  1636. {
  1637. case 0: // wall
  1638. unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_WALL;
  1639. err_when(targetRecno);
  1640. break;
  1641. case 1: // unit
  1642. unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_UNIT;
  1643. err_when(!targetRecno);
  1644. break;
  1645. case 2: // firm
  1646. unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_FIRM;
  1647. err_when(!targetRecno);
  1648. break;
  1649. case 3: // town
  1650. unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_TOWN;
  1651. err_when(!targetRecno);
  1652. break;
  1653. }
  1654. unitPtr->action_para = unitPtr->action_para2 = targetRecno;
  1655. unitPtr->action_x_loc = unitPtr->action_x_loc2 = targetXLoc;
  1656. unitPtr->action_y_loc = unitPtr->action_y_loc2 = targetYLoc;
  1657. proCount--;
  1658. if(proCount<0)
  1659. proCount = unit_processed_count - 1;
  1660. unproCount--;
  1661. }
  1662. }
  1663. else // none of the units reaches the target surrounding
  1664. {
  1665. //----------------------------------------------------------------//
  1666. // handle the case for 1x1 units now, no 2x2 units
  1667. //----------------------------------------------------------------//
  1668. //-*********** improve later ************-//
  1669. int unprocessed = selectedCount;
  1670. Unit *firstPtr = (Unit *) get_ptr(selectedUnitArray[unprocessed-1]);
  1671. switch(targetType)
  1672. {
  1673. case 0: firstPtr->attack_wall(targetXLoc, targetYLoc);
  1674. break;
  1675. case 1: firstPtr->attack_unit(targetXLoc, targetYLoc);
  1676. break;
  1677. case 2: firstPtr->attack_firm(targetXLoc, targetYLoc);
  1678. break;
  1679. case 3: firstPtr->attack_town(targetXLoc, targetYLoc);
  1680. break;
  1681. }
  1682. int moveToXLoc = firstPtr->move_to_x_loc;
  1683. int moveToYLoc = firstPtr->move_to_y_loc;
  1684. /*if(seek_path.path_status==PATH_NODE_USED_UP)
  1685. {
  1686. int debug = 0;
  1687. }*/
  1688. Unit *unitPtr;
  1689. while(unprocessed)
  1690. {
  1691. unitPtr = (Unit *) get_ptr(selectedUnitArray[unprocessed-1]);
  1692. unitPtr->move_to(moveToXLoc, moveToYLoc);
  1693. switch(targetType)
  1694. {
  1695. case 0: // wall
  1696. unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_WALL;
  1697. unitPtr->action_para = unitPtr->action_para2 = 0;
  1698. break;
  1699. case 1: // unit
  1700. unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_UNIT;
  1701. unitPtr->action_para = unitPtr->action_para2 = targetRecno;
  1702. break;
  1703. case 2: // firm
  1704. unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_FIRM;
  1705. unitPtr->action_para = unitPtr->action_para2 = targetRecno;
  1706. break;
  1707. case 3: // town
  1708. unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_TOWN;
  1709. unitPtr->action_para = unitPtr->action_para2 = targetRecno;
  1710. break;
  1711. }
  1712. unitPtr->action_x_loc = unitPtr->action_x_loc2 = targetXLoc;
  1713. unitPtr->action_y_loc = unitPtr->action_y_loc2 = targetYLoc;
  1714. unprocessed--;
  1715. }
  1716. }
  1717. }
  1718. //----------- End of function UnitArray::handle_attack_target_totally_blocked -----------//