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
21 //Filename : OUNITAM.CPP
22 //Description : Object UnitArray - part 2
23 //
24 // For the detail, see ounitam.txt
25
26 #include <math.h>
27
28 #include <ALL.h>
29 #include <OVGA.h>
30 #include <OSYS.h>
31 #include <OSTR.h>
32 #include <OREMOTE.h>
33 #include <OWORLD.h>
34 #include <OTERRAIN.h>
35 #include <OUNIT.h>
36 #include <dbglog.h>
37
38 DBGLOG_DEFAULT_CHANNEL(Unit);
39
40 #ifdef NO_DEBUG_UNIT
41 #undef err_when
42 #undef err_here
43 #undef err_if
44 #undef err_else
45 #undef err_now
46 #define err_when(cond)
47 #define err_here()
48 #define err_if(cond)
49 #define err_else
50 #define err_now(msg)
51 #undef DEBUG
52 #endif
53
54 //----------- Define static variables -----------//
55
56 //------ static variables for all actions -------//
57 short UnitArray::selected_land_unit_count;
58 short UnitArray::selected_sea_unit_count;
59 short UnitArray::selected_air_unit_count;
60 short *UnitArray::selected_land_unit_array=NULL;
61 short *UnitArray::selected_sea_unit_array=NULL;
62 short *UnitArray::selected_air_unit_array=NULL;
63
64 //------ static variables for movement -------//
65 static short square_size, not_tested_loc, rec_height, rec_width;
66 static int move_scale; // use integer for intrgral division
67 static int x, y;
68 static short lower_right_case, upper_left_case; // indicate which case should be used
69 static int *distance, *sorted_member, *sorted_distance;
70 static char *done_flag;
71
72 //static int rec_x1, rec_y1, rec_x2, rec_y2; // for bondary, corner improvement
73
74 static short *filtering_unit_array;
75 static int filtering_unit_count;
76 static short *filtered_unit_array;
77 static int filtered_unit_count;
78
79 //-------------- define static functions -------------//
cal_rectangle_lower_right_x(int refXLoc)80 static int cal_rectangle_lower_right_x(int refXLoc)
81 {
82 // the rule: refXLoc + (rec_width/(move_scale*2))*move_scale
83 if(move_scale==1)
84 return refXLoc + rec_width/2;
85 else // move_scale == 2
86 return refXLoc + (rec_width/4)*2;
87 }
88
cal_rectangle_lower_right_y(int refYLoc)89 static int cal_rectangle_lower_right_y(int refYLoc)
90 {
91 // the rule: refYLoc + ((rec_height-move_scale)/(move_scale*2))*move_scale
92 if(move_scale==1)
93 return refYLoc + (rec_height-1)/2;
94 else // move_scale == 2
95 return refYLoc + ((rec_height-2)/4)*2;
96 }
97
cal_rectangle_upper_left_x(int refXLoc)98 static int cal_rectangle_upper_left_x(int refXLoc)
99 {
100 // the rule: refXLoc - ((rec_width-move_scale)/(move_scale*2))*move_scale
101 if(move_scale==1)
102 return refXLoc - (rec_width-1)/2;
103 else // move_scale == 2
104 return refXLoc - ((rec_width-2)/4)*2;
105 }
106
cal_rectangle_upper_left_y(int refYLoc)107 static int cal_rectangle_upper_left_y(int refYLoc)
108 {
109 // the rule: refYLoc - (rec_height/(move_scale*2))*move_scale
110 if(move_scale==1)
111 return refYLoc - rec_height/2;
112 else // move_scale == 2
113 return refYLoc - (rec_height/4)*2;
114 }
115
116 //--------- Begin of function UnitArray::move_to ---------//
117 //
118 // Order the unit to move to a specific location following the
119 // shortest path.
120 //
121 // <int> destXLoc, destYLoc - the location of the destination.
122 // <int> divided - whether the units are divided by their mobile type
123 // <short*> selectedUnitArray - an array of recno of selected units.
124 // <int> selectedCount - no. of selected units.
125 // [char] remoteAction - whether this is an action carried out by a remote machine or not.
126 // (default: 0)
127 //
128 // Note: the caller function must make sure all units in selectedUnitArray are validate (non-deleted)
129 //
move_to(int destXLoc,int destYLoc,int divided,short * selectedUnitArray,int selectedCount,char remoteAction)130 void UnitArray::move_to(int destXLoc, int destYLoc, int divided, short* selectedUnitArray, int selectedCount, char remoteAction)
131 {
132 err_when(destXLoc<0 || destYLoc<0 || destXLoc>MAX_WORLD_X_LOC-1 || destYLoc>MAX_WORLD_Y_LOC-1);
133
134 //-------- if it's a multiplayer game --------//
135 if( !remoteAction && remote.is_enable() )
136 {
137 short* shortPtr = (short*) remote.new_send_queue_msg(MSG_UNIT_MOVE,
138 sizeof(short) * (4+selectedCount) );
139
140 shortPtr[0] = destXLoc;
141 shortPtr[1] = destYLoc;
142 shortPtr[2] = selectedCount;
143 shortPtr[3] = divided;
144
145 memcpy( shortPtr+4, selectedUnitArray, sizeof(short) * selectedCount );
146 }
147 else
148 {
149 err_when( selectedCount > 10000 ); // error
150
151 if(!divided)
152 {
153 //----------- divide units ------------//
154 divide_array(destXLoc, destYLoc, selectedUnitArray, selectedCount);
155
156 //---------- process group move --------------//
157 // ##### patch begin Gilbert 18/8 ######//
158 if(selected_land_unit_count)
159 move_to(destXLoc, destYLoc, 1, selected_land_unit_array, selected_land_unit_count, COMMAND_AUTO);
160
161 if(selected_sea_unit_count)
162 {
163 Location *locPtr = world.get_loc(destXLoc, destYLoc);
164 if(terrain_res[locPtr->terrain_id]->average_type == TERRAIN_OCEAN)
165 move_to(destXLoc, destYLoc, 1, selected_sea_unit_array, selected_sea_unit_count, COMMAND_AUTO);
166 else
167 ship_to_beach(destXLoc, destYLoc, 1, selected_sea_unit_array, selected_sea_unit_count, COMMAND_AUTO);
168 }
169
170 if(selected_air_unit_count)
171 move_to(destXLoc, destYLoc, 1, selected_air_unit_array, selected_air_unit_count, COMMAND_AUTO);
172 // ##### patch end Gilbert 18/8 ######//
173
174 //---------------- deinit static parameters ------------------//
175 selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0;
176 mem_del(selected_land_unit_array);
177 mem_del(selected_sea_unit_array);
178 mem_del(selected_air_unit_array);
179 return;
180 }
181 else
182 {
183 //---------------------------------------------------------//
184 // set the unit_group_id
185 //---------------------------------------------------------//
186 Unit* unitPtr;
187 uint32_t curGroupId = unit_array.cur_group_id++;
188
189 for(int k=0; k<selectedCount; k++)
190 {
191 unitPtr = (Unit*) get_ptr(selectedUnitArray[k]);
192 err_when(!unitPtr);
193 err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0);
194
195 unitPtr->unit_group_id = curGroupId;
196
197 unitPtr->action_mode = ACTION_MOVE;
198 unitPtr->action_para = 0;
199
200 if(unitPtr->action_mode2!=ACTION_MOVE)
201 {
202 unitPtr->action_mode2 = ACTION_MOVE;
203 unitPtr->action_para2 = 0;
204 unitPtr->action_x_loc2 = unitPtr->action_y_loc2 = -1;
205 }// else keep the data to check whether same action mode is ordered
206 }
207
208 //--------------------------------------------------------------//
209 // if only the leader unit is moving, no need to use formation
210 // movement although the button is pushed
211 //--------------------------------------------------------------//
212 if(selectedCount==1)
213 {
214 unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
215 unitPtr->move_to(destXLoc, destYLoc, 1);
216 }
217 else
218 {
219 Unit *firstUnitPtr = operator[](selectedUnitArray[0]);
220
221 if(firstUnitPtr->mobile_type==UNIT_LAND)
222 {
223 move_to_now_with_filter(destXLoc, destYLoc, selectedUnitArray, selectedCount);
224 seek_path.set_sub_mode(); // reset sub_mode searching
225 seek_path_reuse.set_sub_mode(); //------ reset sub mode of path reuse searching
226 }
227 else
228 move_to_now_with_filter(destXLoc, destYLoc, selectedUnitArray, selectedCount);
229 }
230 }
231 }
232 }
233 //----------- End of function UnitArray::move_to -----------//
234
235
236 //----------Begin of function UnitArray::move_to_now_with_filter------------//
237 // the selected units may be in different territory. Group them by their region id
238 // and process searching for each group
239 //
240 // <int> destX - the x location to move to
241 // <int> destY - the y location to move to
242 // <short*> selectedUnitArray - recno. of selected units
243 // <int> selectedCount - num of selected units
244 //
move_to_now_with_filter(int destX,int destY,short * selectedUnitArray,int selectedCount)245 void UnitArray::move_to_now_with_filter(int destX, int destY, short* selectedUnitArray, int selectedCount)
246 {
247 int destRegionId = world.get_loc(destX, destY)->region_id;
248 Unit *unitPtr = operator[](selectedUnitArray[0]);
249
250 //-------------- no filtering for unit air --------------------------//
251 if(unitPtr->mobile_type==UNIT_AIR)
252 {
253 move_to_now(destX, destY, selectedUnitArray, selectedCount);
254 return;
255 }
256
257 //----------------- init data structure --------------//
258 int arraySize = sizeof(short)*selectedCount;
259 filtered_unit_array = (short*) mem_add(arraySize);
260 filtering_unit_array = (short*) mem_add(arraySize);
261 memcpy(filtering_unit_array, selectedUnitArray, arraySize);
262 filtering_unit_count = selectedCount;
263
264 int unprocessCount = selectedCount;
265 int filterRegionId = destRegionId;
266 int filterDestX = destX, filterDestY = destY;
267 int loopCount, filteringCount, i;
268
269 //-------------------------------------------------------------------------------//
270 // group the unit by their region id and process group searching for each group
271 //-------------------------------------------------------------------------------//
272 for(loopCount=0; loopCount<=unprocessCount; loopCount++) // checking for unprocessCount+1, plus one for the case that unit not on the same territory of destination
273 {
274 memset(filtered_unit_array, 0, arraySize);
275 filtered_unit_count = 0;
276 filteringCount = filtering_unit_count;
277 filtering_unit_count = 0;
278
279 //-------------- filter for filterRegionId --------------//
280 for(i=0; i<filteringCount; i++)
281 {
282 unitPtr = operator[](filtering_unit_array[i]);
283 if(world.get_loc(unitPtr->next_x_loc(), unitPtr->next_y_loc())->region_id==filterRegionId)
284 filtered_unit_array[filtered_unit_count++] = filtering_unit_array[i];
285 else
286 filtering_unit_array[filtering_unit_count++] = filtering_unit_array[i];
287 }
288
289 //---- process for filtered_unit_array and prepare for looping ----//
290 if(filtered_unit_count)
291 move_to_now(filterDestX, filterDestY, filtered_unit_array, filtered_unit_count);
292
293 if(!filtering_unit_count)
294 break;
295
296 //---------------- update parameters for next checking ------------------//
297 unitPtr = operator[](filtering_unit_array[0]);
298 filterRegionId = world.get_loc(unitPtr->next_x_loc(), unitPtr->next_y_loc())->region_id;
299 filterDestX = destX;
300 filterDestY = destY;
301 unitPtr->different_territory_destination(filterDestX, filterDestY); // reference parameters to get the location the units should move to
302 }
303
304 mem_del(filtered_unit_array);
305 mem_del(filtering_unit_array);
306 }
307 //----------- End of function UnitArray::move_to_now_with_filter -----------//
308
309
310 //--------- Begin of function UnitArray::move_to_now ---------//
311 //
312 // Order the unit to move to a specific location following the
313 // shortest path.
314 //
315 // <int> destXLoc, destYLoc - the location of the destination.
316 // <short*> selectedUnitArray - an array of recno of selected units.
317 // <int> selectedCount - no. of selected units.
318 //
move_to_now(int destXLoc,int destYLoc,short * selectedUnitArray,int selectedCount)319 void UnitArray::move_to_now(int destXLoc, int destYLoc, short* selectedUnitArray, int selectedCount)
320 {
321 err_when(destXLoc<0 || destYLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc>=MAX_WORLD_Y_LOC);
322 err_when( selectedCount > 10000 );
323
324 //------------ define vars -----------------------//
325 int unprocessCount;// = selectedCount; // num. of unprocessed sprite
326 int k; // for counting
327 short vecX, vecY; // used to reset x, y
328 short oddCount, evenCount;
329 int j;
330 Unit* unitPtr = unit_array[selectedUnitArray[0]];
331 uint32_t curGroupId = unitPtr->unit_group_id;
332 int mobileType = unitPtr->mobile_type;
333 Location *worldLocMatrix=world.loc_matrix, *locPtr;
334 //int sizeOneSelectedCount=0, sizeTwoSelectedCount=0;
335 int sizeOneSelectedCount = selectedCount;
336
337 //---------- set Unit::unit_group_id and count the unit by size ----------//
338 int i;
339 for( i=0 ; i<selectedCount ; i++ )
340 {
341 unitPtr = operator[](selectedUnitArray[i]);
342 err_when(unitPtr->cur_action==SPRITE_IDLE && (unitPtr->cur_x!=unitPtr->next_x || unitPtr->cur_y!=unitPtr->next_y));
343 err_when(unitPtr->action_para); // action_para should be set to zero in move_to()
344
345 if(unitPtr->cur_action==SPRITE_ATTACK)
346 unitPtr->stop();
347
348 err_when(unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0);
349 if(unitPtr->cur_action==SPRITE_IDLE)
350 unitPtr->set_ready();
351
352 /*switch(unitPtr->sprite_info->loc_width)
353 {
354 case 1: sizeOneSelectedCount++;
355 break;
356
357 case 2: sizeTwoSelectedCount++;
358 break;
359
360 default: err_here();
361 break;
362 }*/
363 }
364 unprocessCount = sizeOneSelectedCount;
365
366 //---- construct array to store size one selected unit ----//
367 short* selectedSizeOneUnitArray;
368 if(sizeOneSelectedCount)
369 {
370 selectedSizeOneUnitArray = (short*)mem_add(sizeof(short)*sizeOneSelectedCount);
371 memset(selectedSizeOneUnitArray, 0, sizeof(short)*sizeOneSelectedCount);
372 for(i=0, k=0; i<selectedCount && unprocessCount; i++)
373 {
374 unitPtr = operator[](selectedUnitArray[i]);
375 if(unitPtr->sprite_info->loc_width==1)
376 {
377 selectedSizeOneUnitArray[k++] = selectedUnitArray[i];
378 unprocessCount--;
379 }
380 }
381 }
382 unprocessCount = sizeOneSelectedCount;
383
384 //----------- variables initialization ---------------//
385 int destX, destY;
386 if(mobileType==UNIT_LAND)
387 {
388 x = destX = destXLoc;
389 y = destY = destYLoc;
390 move_scale = 1;
391 }
392 else // UNIT_AIR, UNIT_SEA
393 {
394 x = destX = (destXLoc/2)*2;
395 y = destY = (destYLoc/2)*2;
396 move_scale = 2;
397 }
398
399 //if(sizeOneSelectedCount)
400 //{
401 //----- initialize parameters and construct data structure -----//
402 oddCount =1;
403 evenCount = 3;
404 square_size = not_tested_loc = lower_right_case = upper_left_case = 0;
405
406 distance = (int*)mem_add(sizeof(int)*sizeOneSelectedCount); // used in the function construct_sorted_array and this function,
407 memset(distance, 0, sizeof(int)*sizeOneSelectedCount); // and allocate/free the memory in this function
408
409 sorted_distance = (int*)mem_add(sizeof(int)*sizeOneSelectedCount);
410 memset(sorted_distance, 0, sizeof(int)*sizeOneSelectedCount);
411
412 sorted_member = (int*)mem_add(sizeof(int)*sizeOneSelectedCount);
413 memset(sorted_member, 0, sizeof(int)*sizeOneSelectedCount);
414
415 done_flag = (char*)mem_add(sizeof(char)*sizeOneSelectedCount);
416 memset(done_flag, 0, sizeof(char)*sizeOneSelectedCount);
417
418 //--- calculate the rectangle size used to allocate space for the sprites----//
419 unprocessCount = sizeOneSelectedCount;
420 while(unprocessCount)
421 {
422 //=============================
423 // process odd size square
424 //=============================
425 vecX = short(oddCount/4)*move_scale;
426 vecY = vecX;
427 k = 0;
428
429 for(j=0; j<oddCount && unprocessCount; j++)
430 {
431 x = destX+vecX;
432 y = destY+vecY;
433
434 if(x>=0 && y>=0 && x<MAX_WORLD_X_LOC && y<MAX_WORLD_Y_LOC)
435 {
436 if( worldLocMatrix[y*MAX_WORLD_X_LOC+x].is_unit_group_accessible(mobileType, curGroupId) )
437 unprocessCount--;
438 }
439
440 if(k++ < int(oddCount/2)) // reset vecX, vecY
441 vecX -= move_scale;
442 else
443 vecY -= move_scale;
444 }
445 square_size+=move_scale;
446 if(j<oddCount)
447 not_tested_loc = oddCount-j;
448 oddCount+=4;
449
450 if(unprocessCount)
451 {
452 //=============================
453 // process even size square
454 //=============================
455 vecY = (-short(evenCount/4)-1)*move_scale;
456 vecX = vecY+move_scale;
457 k = 0;
458
459 for(j=0; j<evenCount && unprocessCount; j++)
460 {
461 x = destX+vecX;
462 y = destY+vecY;
463
464 if(x>=0 && y>=0 && x<MAX_WORLD_X_LOC && y<MAX_WORLD_Y_LOC)
465 {
466 if(worldLocMatrix[y*MAX_WORLD_X_LOC+x].is_unit_group_accessible(mobileType, curGroupId) )
467 unprocessCount--;
468 }
469
470 if(k++ < int(evenCount/2)) // reset vecX, vecY
471 vecX += move_scale;
472 else
473 vecY += move_scale;
474 }
475 square_size+=move_scale;
476 if(j<evenCount)
477 not_tested_loc = evenCount-j;
478 evenCount+=4;
479 }
480 }
481
482 rec_height = rec_width = square_size; // get the height and width of the rectangle
483 if(not_tested_loc >= (square_size/move_scale))
484 rec_width -= move_scale;
485
486 //--- decide to use upper_left_case or lower_right_case, however, it maybe changed for boundary improvement----//
487 x = cal_rectangle_lower_right_x(destX);
488 y = cal_rectangle_lower_right_y(destY);
489
490 for(i=0; i<sizeOneSelectedCount; i++)
491 {
492 unitPtr = (Unit*) get_ptr(selectedSizeOneUnitArray[i]);
493
494 if(unitPtr->next_y_loc()<y) // lower_right_case or upper_left_case
495 lower_right_case++;
496 else if(unitPtr->next_y_loc()>y)
497 upper_left_case++;
498 }
499
500 if(lower_right_case==upper_left_case) // in case both values are equal, check by upper_left_case
501 {
502 x = cal_rectangle_upper_left_x(destX);
503 y = cal_rectangle_upper_left_y(destY);
504
505 lower_right_case = upper_left_case = 0;
506 for(i=0; i<sizeOneSelectedCount; i++)
507 {
508 unitPtr = (Unit*) get_ptr(selectedSizeOneUnitArray[i]);
509
510 if(unitPtr->next_y_loc()<y) // lower_right_case or upper_left_case
511 lower_right_case++;
512 else if(unitPtr->next_y_loc()>y)
513 upper_left_case++;
514 }
515 }
516
517 //------------ determine x, y and lower_right_case/upper_left_case-----------//
518 determine_position_to_construct_table(selectedCount, destX, destY, mobileType);
519 err_when(x<0 || y<0 || x>=MAX_WORLD_X_LOC || y>=MAX_WORLD_Y_LOC);
520
521 //------------ construct a table to store distance -------//
522 construct_sorted_array(selectedSizeOneUnitArray, sizeOneSelectedCount); // distance and sorted_member should be initialized first
523 err_when(x<0 || y<0 || x>=MAX_WORLD_X_LOC || y>=MAX_WORLD_Y_LOC);
524
525 //------------ process the movement -----------//
526 unprocessCount = sizeOneSelectedCount;//selectedCount;
527 k=0;
528
529 //-******************* auto correct ***********************-//
530 int autoCorrectStartX = x;
531 int autoCorrectStartY = y;
532 //-******************* auto correct ***********************-//
533
534 if(lower_right_case >= upper_left_case)
535 {
536 while(unprocessCount)
537 {
538 locPtr = worldLocMatrix+y*MAX_WORLD_X_LOC+x;
539 for(i=x; i>x-rec_width && unprocessCount; i-=move_scale, locPtr-=move_scale)
540 {
541 if(locPtr->is_unit_group_accessible(mobileType, curGroupId))
542 {
543 do
544 {
545 unitPtr = (Unit*) get_ptr(selectedSizeOneUnitArray[sorted_member[k++]]);
546 }while(unitPtr->sprite_info->loc_width>1);
547
548 err_when(k>sizeOneSelectedCount);
549 if(sizeOneSelectedCount>1)
550 {
551 if(unprocessCount==sizeOneSelectedCount) // the first unit to move
552 {
553 unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL);
554 if(unitPtr->mobile_type==UNIT_LAND && unitPtr->nation_recno)
555 unitPtr->select_search_sub_mode(unitPtr->next_x_loc(), unitPtr->next_y_loc(), i, y, unitPtr->nation_recno, SEARCH_MODE_REUSE);
556 unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK);
557 }
558 else
559 {
560 err_when(unprocessCount==sizeOneSelectedCount);
561 if(unitPtr->mobile_type==UNIT_LAND && unitPtr->nation_recno)
562 unitPtr->select_search_sub_mode(unitPtr->next_x_loc(), unitPtr->next_y_loc(), i, y, unitPtr->nation_recno, SEARCH_MODE_REUSE);
563 unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH);
564 }
565 }
566 else
567 unitPtr->move_to(i, y, 1);
568 unprocessCount--;
569 }
570 }
571 y-=move_scale;
572 //-******************* auto correct ***********************-//
573 #ifdef DEBUG
574 err_when(unprocessCount && y<0);
575 #else
576 if(unprocessCount && y<0)
577 y = autoCorrectStartY;
578 #endif
579 //-******************* auto correct ***********************-//
580 }
581 }
582 else // upper_left_case
583 {
584 while(unprocessCount)
585 {
586 locPtr = worldLocMatrix+y*MAX_WORLD_X_LOC+x;
587 for(i=x; i<x+rec_width && unprocessCount; i+=move_scale, locPtr+=move_scale)
588 {
589 if(locPtr->is_unit_group_accessible(mobileType, curGroupId))
590 {
591 do
592 {
593 unitPtr = (Unit*) get_ptr(selectedSizeOneUnitArray[sorted_member[k++]]);
594 }while(unitPtr->sprite_info->loc_width>1);
595 err_when(k>sizeOneSelectedCount);
596
597 if(sizeOneSelectedCount>1)
598 {
599 if(unprocessCount==sizeOneSelectedCount) // the first unit to move
600 {
601 unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL);
602 if(unitPtr->mobile_type==UNIT_LAND && unitPtr->nation_recno)
603 unitPtr->select_search_sub_mode(unitPtr->next_x_loc(), unitPtr->next_y_loc(), i, y, unitPtr->nation_recno, SEARCH_MODE_REUSE);
604 unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK);
605 }
606 else
607 {
608 err_when(unprocessCount==sizeOneSelectedCount);
609 if(unitPtr->mobile_type==UNIT_LAND && unitPtr->nation_recno)
610 unitPtr->select_search_sub_mode(unitPtr->next_x_loc(), unitPtr->next_y_loc(), i, y, unitPtr->nation_recno, SEARCH_MODE_REUSE);
611 unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH);
612 }
613 }
614 else
615 unitPtr->move_to(i, y, 1);
616 unprocessCount--;
617 }
618 }
619 y+=move_scale;
620 //-******************* auto correct ***********************-//
621 if(unprocessCount && y>=MAX_WORLD_Y_LOC)
622 {
623 MSG("Unit attempted to walk off map...correcting.\n");
624 y = autoCorrectStartY;
625 }
626 //-******************* auto correct ***********************-//
627 }
628 }
629 //---------------- destruct data structure --------------//
630 mem_del(done_flag);
631 mem_del(sorted_distance);
632 mem_del(sorted_member);
633 mem_del(distance);
634 mem_del(selectedSizeOneUnitArray);
635 //}// end if (sizeOneSelectedCount)
636 /*
637 //=============================================================================//
638 //----- order sprite with size two to move to a specified position ------------//
639 //=============================================================================//
640
641 int sizeTwoUnprocessCount = sizeTwoSelectedCount;
642 int surX, surY, suaCount=0;
643 char w, h, blocked=0;
644
645 if(sizeOneSelectedCount) // mix, size one units have processed
646 {
647 if(rec_width>square_size)
648 square_size = rec_width;
649 if(rec_height>square_size)
650 square_size = rec_height;
651 square_size = ((square_size+1)/2)<<1; // change to multiply of two
652 rec_width = rec_height = square_size;
653
654 x = destX-rec_width/2+1;
655 y = destY-rec_height/2;
656 }
657 else // all are size 2 units
658 {
659 //-***************** testing ********************-//
660 err_here();
661 //-***************** testing ********************-//
662
663 square_size = rec_width = rec_height = 2;
664 x = destX;
665 y = destY;
666
667 if(x<0)
668 x = 0;
669 else if(x>=MAX_WORLD_X_LOC-1)
670 x = MAX_WORLD_X_LOC-2;
671
672 if(y<0)
673 y = 0;
674 else if(y>=MAX_WORLD_Y_LOC-1)
675 y = MAX_WORLD_Y_LOC-2;
676
677 blocked = 0;
678 for(h=0, surY=y; h<2 && !blocked; h++, surY++)
679 {
680 for(w=0, surX=x; w<2 && !blocked; w++, surX++)
681 {
682 locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX;
683 blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId);
684 }
685 }
686
687 if(!blocked)
688 {
689 do
690 {
691 unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]);
692 }while(unitPtr->sprite_info->loc_width<2);
693
694 if(sizeTwoSelectedCount>1)
695 {
696 unitPtr->move_to(x, y, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL);
697 unitPtr->move_to(x, y, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK);
698 }
699 else
700 unitPtr->move_to(x, y, 1);
701 sizeTwoUnprocessCount--;
702 }
703 }
704
705 while(sizeTwoUnprocessCount)
706 {
707 //-***************** testing ********************-//
708 err_here();
709 //-***************** testing ********************-//
710
711 int moveToX, moveToY;
712 int boundedX, boundedY;
713
714 //------------- upper edge --------------//
715 moveToY = y-2;
716 moveToX = x;
717 if(moveToY>=0)
718 {
719 if(x+rec_width+2 > MAX_WORLD_X_LOC-2)
720 boundedX = MAX_WORLD_X_LOC-1;
721 else
722 boundedX = x+rec_width+2;
723
724 while(moveToX<boundedX && sizeTwoUnprocessCount)
725 {
726 //--------------- is the position blocked? ----------//
727 if(moveToX>=MAX_WORLD_X_LOC-1 || moveToY>=MAX_WORLD_Y_LOC-1)
728 blocked = 1;
729 else
730 {
731 blocked = 0;
732 for(h=0, surY=moveToY; h<2 && !blocked; h++, surY++)
733 {
734 for(w=0, surX=moveToX; w<2 && !blocked; w++, surX++)
735 {
736 locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX;
737 blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId);
738 }
739 }
740 }
741
742 if(!blocked)
743 {
744 do
745 {
746 unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]);
747 }while(unitPtr->sprite_info->loc_width<2);
748
749 if(sizeTwoSelectedCount>1)
750 {
751 if(sizeTwoUnprocessCount==sizeTwoSelectedCount) // the first unit to move
752 {
753 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL);
754 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK);
755 }
756 else
757 {
758 err_if(sizeTwoUnprocessCount==sizeTwoSelectedCount)
759 err_here();
760
761 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH);
762 }
763 }
764 else
765 unitPtr->move_to(moveToX, moveToY, 1);
766 sizeTwoUnprocessCount--;
767 }
768 moveToX+=2;
769 }
770 }
771
772 //------------- right edge --------------//
773 moveToX = x+rec_width;
774 moveToY = y;
775 if(moveToX<MAX_WORLD_X_LOC-1)
776 {
777 if(y+rec_height+2 > MAX_WORLD_Y_LOC-2)
778 boundedY = MAX_WORLD_Y_LOC-1;
779 else
780 boundedY = y+rec_height+2;
781
782 while(moveToY<boundedY && sizeTwoUnprocessCount)
783 {
784 //--------------- is the position blocked? ----------//
785 if(moveToX>=MAX_WORLD_X_LOC-1 || moveToY>=MAX_WORLD_Y_LOC-1)
786 blocked = 1;
787 else
788 {
789 blocked = 0;
790 for(h=0, surY=moveToY; h<2 && !blocked; h++, surY++)
791 {
792 for(w=0, surX=moveToX; w<2 && !blocked; w++, surX++)
793 {
794 locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX;
795 blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId);
796 }
797 }
798 }
799
800 if(!blocked)
801 {
802 do
803 {
804 unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]);
805 }while(unitPtr->sprite_info->loc_width<2);
806
807 if(sizeTwoSelectedCount>1)
808 {
809 if(sizeTwoUnprocessCount==sizeTwoSelectedCount) // the first unit to move
810 {
811 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL);
812 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK);
813 }
814 else
815 {
816 err_if(sizeTwoUnprocessCount==sizeTwoSelectedCount)
817 err_here();
818
819 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH);
820 }
821 }
822 else
823 unitPtr->move_to(moveToX, moveToY, 1);
824 sizeTwoUnprocessCount--;
825 }
826 moveToY+=2;
827 }
828 }
829
830 //------------- lower edge ----------------//
831 moveToX = x+rec_width-2;
832 moveToY = y+rec_height;
833 if(moveToY<MAX_WORLD_Y_LOC-1)
834 {
835 if(x-3 < 0)
836 boundedX = -1;
837 else
838 boundedX = x-3;
839
840 while(moveToX>boundedX && sizeTwoUnprocessCount)
841 {
842 //--------------- is the position blocked? ----------//
843 if(moveToX>=MAX_WORLD_X_LOC-1 || moveToY>=MAX_WORLD_Y_LOC-1)
844 blocked = 1;
845 else
846 {
847 blocked = 0;
848 for(h=0, surY=moveToY; h<2 && !blocked; h++, surY++)
849 {
850 for(w=0, surX=moveToX; w<2 && !blocked; w++, surX++)
851 {
852 locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX;
853 blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId);
854 }
855 }
856 }
857
858 if(!blocked)
859 {
860 do
861 {
862 unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]);
863 }while(unitPtr->sprite_info->loc_width<2);
864 if(sizeTwoSelectedCount>1)
865 {
866 if(sizeTwoUnprocessCount==sizeTwoSelectedCount) // the first unit to move
867 {
868 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL);
869 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK);
870 }
871 else
872 {
873 err_if(sizeTwoUnprocessCount==sizeTwoSelectedCount)
874 err_here();
875
876 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH);
877 }
878 }
879 else
880 unitPtr->move_to(moveToX, moveToY, 1);
881 sizeTwoUnprocessCount--;
882 }
883 moveToX-=2;
884 }
885 }
886
887 //------------- left edge ---------------//
888 moveToX = x-2;
889 moveToY = y+rec_height-2;
890 if(moveToX>=0)
891 {
892 if(y-3 < 0)
893 boundedY = -1;
894 else
895 boundedY = y-3;
896
897 while(moveToY>boundedY && sizeTwoUnprocessCount)
898 {
899 //--------------- is the position blocked? ----------//
900 if(moveToX>=MAX_WORLD_X_LOC-1 || moveToY>=MAX_WORLD_Y_LOC-1)
901 blocked = 1;
902 else
903 {
904 blocked = 0;
905 for(h=0, surY=moveToY; h<2 && !blocked; h++, surY++)
906 {
907 for(w=0, surX=moveToX; w<2 && !blocked; w++, surX++)
908 {
909 locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX;
910 blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId);
911 }
912 }
913 }
914
915 if(!blocked)
916 {
917 do
918 {
919 unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]);
920 }while(unitPtr->sprite_info->loc_width<2);
921
922 if(sizeTwoSelectedCount>1)
923 {
924 if(sizeTwoUnprocessCount==sizeTwoSelectedCount) // the first unit to move
925 {
926 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL);
927 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK);
928 }
929 else
930 {
931 err_if(sizeTwoUnprocessCount==sizeTwoSelectedCount)
932 err_here();
933
934 unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH);
935 }
936 }
937 else
938 unitPtr->move_to(moveToX, moveToY, 1);
939 sizeTwoUnprocessCount--;
940 }
941 moveToY-=2;
942 }
943 }
944
945 //------- reset square_size, rec_width, rec_height -----------//
946 rec_width+=4;
947 rec_height+=4;
948 x-=2;
949 y-=2;
950 }*/
951 }
952 //----------- End of function UnitArray::move_to_now -----------//
953
954
955 //----------Begin of function UnitArray::construct_sorted_array------------//
956 //
957 // construct a table to store the d(x,y) value from the reference(rectangule
958 // starting) point in group movement control
959 //
960 // For the detail, see ounitam.txt
961 //
962 //
963 // <short*> selectedUnitArray - an array of recno of selected units.
964 // <int> selectedCount - no. of selected units.
965 //
construct_sorted_array(short * selectedUnitArray,int selectedCount)966 void UnitArray::construct_sorted_array(short* selectedUnitArray, int selectedCount)
967 {
968 Unit* unitPtr;
969 int MIN, dist; // for comparison
970 int i, j, k;
971 const int c = 1000; // c value for the d(x,y) function
972
973 if(lower_right_case >= upper_left_case)
974 {
975 for(i=0; i<selectedCount; i++)
976 {
977 unitPtr = (Unit*) get_ptr(selectedUnitArray[i]);
978 // d(x,y)=x+c*|y|
979 distance[i] = MAX_WORLD_X_LOC; // to aviod -ve no. in the following line
980 distance[i] += (x-unitPtr->cur_x_loc()+c*abs(unitPtr->cur_y_loc()-y)); // plus/minus x coord difference
981 }
982 }
983 else // upper_left_case
984 {
985 for(i=0; i<selectedCount; i++)
986 {
987 unitPtr = (Unit*) get_ptr(selectedUnitArray[i]);
988 // d(x,y)=x+c*|y|
989 distance[i] = MAX_WORLD_X_LOC; // to aviod -ve no. in the following line
990 distance[i] += (unitPtr->cur_x_loc()-x+c*abs(unitPtr->cur_y_loc()-y)); // plus/minus x coord difference
991 }
992 }
993
994 //---------------------------------------------------------------//
995 // this part of code using a technique to adjust the distance value
996 // such that the selected group can change from lower right form
997 // to upper left form or upper left form to lower right form in a
998 // better way.
999 //---------------------------------------------------------------//
1000 //------ sorting the distance and store in sortedDistance Array -------//
1001 for(j=0; j<selectedCount; j++)
1002 {
1003 MIN = 0xFFFFFF;
1004 for(i=0; i<selectedCount; i++)
1005 {
1006 if(done_flag[i]==0 && (dist = distance[i])<MIN)
1007 {
1008 MIN = dist;
1009 k = i;
1010 }
1011 }
1012 sorted_distance[j] = k;
1013 done_flag[k] = 1;
1014 }
1015
1016 //----------------- find the minimum value --------------//
1017 #ifdef DEBUG
1018 MIN = 0xFFFFFF;
1019 for(j=0; j<selectedCount; j++)
1020 {
1021 if((dist = distance[j])<MIN)
1022 MIN = dist;
1023 }
1024
1025 err_when(MIN!=distance[sorted_distance[0]]);
1026 #else
1027 MIN = distance[sorted_distance[0]];
1028 #endif
1029
1030 int defArraySize = 5; //****** BUGHERE, 5 is chosen arbitrary
1031 int *leftQuotZ = (int*) mem_add(defArraySize*sizeof(int));
1032 int *rightQuotZ = (int*) mem_add(defArraySize*sizeof(int));
1033 int remainder = MIN%c;
1034 int index;
1035
1036 //-- adjust the value to allow changing form between upper left and lower right shape --//
1037
1038 for(j=0; j<defArraySize; j++)
1039 leftQuotZ[j] = rightQuotZ[j] = MIN-remainder;
1040
1041 for(j=0; j<selectedCount; j++)
1042 {
1043 if((dist = distance[sorted_distance[j]]%c) < remainder)
1044 {
1045 if((index = remainder-dist) <= defArraySize) // the case can be handled by this array size
1046 {
1047 distance[sorted_distance[j]] = leftQuotZ[index-1] + dist;
1048 leftQuotZ[index-1] += c;
1049 }
1050 }
1051 else
1052 {
1053 if(dist>=remainder)
1054 {
1055 if((index = dist-remainder) < defArraySize) // the case can be handled by this array size
1056 {
1057 distance[sorted_distance[j]] = rightQuotZ[index] + dist;
1058 rightQuotZ[index] += c;
1059 }
1060 }
1061 }
1062 }
1063
1064 mem_del(leftQuotZ);
1065 mem_del(rightQuotZ);
1066
1067 //---------- sorting -------------//
1068 for(j=0; j<selectedCount; j++)
1069 {
1070 MIN = 0xFFFFFF;
1071 for(i=0; i<selectedCount; i++)
1072 {
1073 if((dist = distance[i])<MIN)
1074 {
1075 MIN = dist;
1076 k = i;
1077 }
1078 }
1079 sorted_member[j] = k;
1080 distance[k] = 0xFFFFFF;
1081 }
1082 }
1083 //--------End of function UnitArray::construct_sorted_array----------------//
1084
1085
1086 //--- Begin of function UnitArray::determine_position_to_construct_table ---//
1087 //
1088 // determine the position of the rectangule starting point in the two forms
1089 // (i.e. upper left case or lower right case). This point is used to indicate
1090 // the direction to fill the rectangle
1091 //
1092 // <int> destXLoc, destYLoc - the location of the destination.
1093 // <int> selectedCount - no. of selected units.
1094 //
determine_position_to_construct_table(int selectedCount,int destXLoc,int destYLoc,char mobileType)1095 void UnitArray::determine_position_to_construct_table(int selectedCount, int destXLoc, int destYLoc, char mobileType)
1096 {
1097 //======================================================================//
1098 // boundary, corner improvement
1099 //======================================================================//
1100 int sqrtValue;
1101
1102 //======================================================================//
1103 // lower right case
1104 //======================================================================//
1105 if(lower_right_case>=upper_left_case)
1106 {
1107 //--------- calculate x, y location for lower right case ---------//
1108 x = cal_rectangle_lower_right_x(destXLoc);
1109 y = cal_rectangle_lower_right_y(destYLoc);
1110
1111 if(x<rec_width)
1112 {
1113 //================== left edge =================//
1114 sqrtValue = (int)sqrt((float)selectedCount);
1115 if(sqrtValue*sqrtValue != selectedCount)
1116 sqrtValue++;
1117 if(mobileType!=UNIT_LAND)
1118 sqrtValue = sqrtValue<<1; // change to scale 2
1119 rec_width = rec_height = sqrtValue;
1120
1121 //------------- top left corner --------------//
1122 if(y<rec_height)
1123 {
1124 upper_left_case = lower_right_case+1;
1125 x = y = 0;
1126 }
1127 //------------ bottom left corner ---------------//
1128 else if(y>=MAX_WORLD_Y_LOC-move_scale)
1129 {
1130 if(not_tested_loc>=square_size/move_scale)
1131 rec_width -= move_scale;
1132
1133 x = rec_width-move_scale;
1134 y = MAX_WORLD_Y_LOC-move_scale;
1135 }
1136 //------------- just left edge -------------//
1137 else
1138 x = rec_width-move_scale;
1139 }
1140 else if(x>=MAX_WORLD_X_LOC-move_scale)
1141 {
1142 //============== right edge ==============//
1143
1144 //----------- top right corner -----------//
1145 if(y<rec_height)
1146 {
1147 sqrtValue = (int)sqrt((float)selectedCount);
1148 if(sqrtValue*sqrtValue != selectedCount)
1149 sqrtValue++;
1150 if(mobileType!=UNIT_LAND)
1151 sqrtValue = sqrtValue<<1; // change to scale 2
1152 rec_width = rec_height = sqrtValue;
1153
1154 upper_left_case = lower_right_case+1;
1155 x = MAX_WORLD_X_LOC-rec_width;
1156 y = 0;
1157 }
1158 //---------- bottom right corner ------------//
1159 else if(y>=MAX_WORLD_Y_LOC-move_scale)
1160 {
1161 y = MAX_WORLD_Y_LOC-move_scale;
1162 x = MAX_WORLD_X_LOC-move_scale;
1163 }
1164 //---------- just right edge ---------------//
1165 else
1166 {
1167 int squareSize = square_size/move_scale;
1168 if(squareSize*(squareSize-1)>=selectedCount)
1169 rec_width -= move_scale;
1170 x = MAX_WORLD_X_LOC-move_scale;
1171 }
1172 }
1173 else if(y<rec_height)
1174 {
1175 //================= top edge ===============//
1176 sqrtValue = (int)sqrt((float)selectedCount);
1177 if(sqrtValue*sqrtValue != selectedCount)
1178 sqrtValue++;
1179 if(mobileType!=UNIT_LAND)
1180 sqrtValue = sqrtValue<<1; // change to scale 2
1181 rec_width = rec_height = sqrtValue;
1182
1183 upper_left_case = lower_right_case+1;
1184 //if(mobileType==UNIT_LAND)
1185 // x = destXLoc-((rec_width-1)/2);
1186 //else
1187 // x = destXLoc-(rec_width/4)*2;
1188 x = cal_rectangle_upper_left_x(destXLoc);
1189 y = 0;
1190 }
1191 else if(y>=MAX_WORLD_Y_LOC-move_scale)
1192 {
1193 //================== bottom edge ====================//
1194 if(not_tested_loc>=square_size/move_scale)
1195 rec_width += move_scale;
1196
1197 //if(mobileType==UNIT_LAND)
1198 // x = destXLoc+(rec_width/2);
1199 //else
1200 // x = destXLoc+(rec_width/4)*2;
1201 x = cal_rectangle_lower_right_x(destXLoc);
1202 y = MAX_WORLD_Y_LOC-move_scale;
1203 }
1204 }
1205 //======================================================================//
1206 // upper left case
1207 //======================================================================//
1208 else
1209 {
1210 //--------- calculate x, y location for upper left case ---------//
1211 x = cal_rectangle_upper_left_x(destXLoc);
1212 y = cal_rectangle_upper_left_y(destYLoc);
1213
1214 if(x<0)
1215 {
1216 //================= left edge ==================//
1217
1218 //------------- top left corner --------------//
1219 if(y<0)
1220 {
1221 sqrtValue = (int)sqrt((float)selectedCount);
1222 if(sqrtValue*sqrtValue != selectedCount)
1223 sqrtValue++;
1224 if(mobileType!=UNIT_LAND)
1225 sqrtValue = sqrtValue<<1; // change to scale 2
1226 rec_width = rec_height = sqrtValue;
1227 x = y = 0;
1228 }
1229 //------------- bottom left corner --------------//
1230 else if(y+rec_height>=MAX_WORLD_Y_LOC-move_scale)
1231 {
1232 lower_right_case = upper_left_case+1;
1233 x = rec_width-move_scale;
1234 y = MAX_WORLD_Y_LOC-move_scale;
1235 }
1236 //------------- just left edge ------------------//
1237 else
1238 {
1239 sqrtValue = (int)sqrt((float)selectedCount);
1240 if(sqrtValue*sqrtValue != selectedCount)
1241 sqrtValue++;
1242 if(mobileType!=UNIT_LAND)
1243 sqrtValue = sqrtValue<<1; // change to scale 2
1244 rec_width = rec_height = sqrtValue;
1245 x = 0;
1246 }
1247 }
1248 //================ right edge ================//
1249 else if(x+rec_width>=MAX_WORLD_X_LOC-move_scale)
1250 {
1251 //------------- top right corner ------------------//
1252 if(y<0)
1253 {
1254 sqrtValue = (int)sqrt((float)selectedCount);
1255 if(sqrtValue*sqrtValue != selectedCount)
1256 sqrtValue++;
1257 if(mobileType!=UNIT_LAND)
1258 sqrtValue = sqrtValue<<1; // change to scale 2
1259 rec_width = rec_height = sqrtValue;
1260 x = MAX_WORLD_X_LOC-rec_width;
1261 y = 0;
1262 }
1263 //------------- bottom right corner ------------------//
1264 else if(y+rec_height>=MAX_WORLD_Y_LOC-move_scale)
1265 {
1266 lower_right_case = upper_left_case+1;
1267 x = MAX_WORLD_X_LOC-move_scale;
1268 y = MAX_WORLD_Y_LOC-move_scale;
1269 }
1270 //------------- just right edge ------------------//
1271 else
1272 {
1273 sqrtValue = (int)sqrt((float)selectedCount);
1274 if(sqrtValue*sqrtValue != selectedCount)
1275 sqrtValue++;
1276 if(mobileType!=UNIT_LAND)
1277 sqrtValue = sqrtValue<<1; // change to scale 2
1278 rec_width = rec_height = sqrtValue;
1279
1280 int squareSize = square_size/move_scale;
1281 if(squareSize*(squareSize-1)>=selectedCount)
1282 rec_width -= move_scale;
1283 lower_right_case = upper_left_case+1;
1284 x = MAX_WORLD_X_LOC-move_scale;
1285 //if(mobileType==UNIT_LAND)
1286 // y = destYLoc+((rec_height-1)/2);
1287 //else
1288 // y = destYLoc+((rec_height-2)/4)*2;
1289 y = cal_rectangle_lower_right_y(destYLoc);
1290 }
1291 }
1292 //================= top edge ================//
1293 else if(y<0)
1294 {
1295 sqrtValue = (int)sqrt((float)selectedCount);
1296 if(sqrtValue*sqrtValue != selectedCount)
1297 sqrtValue++;
1298
1299 rec_width = rec_height = sqrtValue;
1300 y = 0;
1301 }
1302 //================= bottom edge ================//
1303 else if(y+rec_height>=MAX_WORLD_Y_LOC-move_scale)
1304 {
1305 if(not_tested_loc>=square_size)
1306 rec_width += move_scale;
1307 y = MAX_WORLD_Y_LOC-move_scale;
1308 }
1309 }
1310
1311 /*if(lower_right_case>=upper_left_case)
1312 {
1313 x = cal_rectangle_lower_right_x(destXLoc);
1314 y = cal_rectangle_lower_right_y(destYLoc);
1315
1316 rec_x1 = x - rec_width + move_scale;
1317 rec_y1 = y - rec_height + move_scale;
1318 rec_x2 = x;
1319 rec_y2 = y;
1320 }
1321 else
1322 {
1323 x = cal_rectangle_upper_left_x(destXLoc);
1324 y = cal_rectangle_upper_left_y(destYLoc);
1325 }*/
1326 }
1327 //--- End of function UnitArray::determine_position_to_construct_table -----//
1328