/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OUNITAM.CPP //Description : Object UnitArray - part 2 // // For the detail, see ounitam.txt #include #include #include #include #include #include #include #include #include #ifdef NO_DEBUG_UNIT #undef err_when #undef err_here #undef err_if #undef err_else #undef err_now #define err_when(cond) #define err_here() #define err_if(cond) #define err_else #define err_now(msg) #undef DEBUG #endif //----------- Define static variables -----------// //------ static variables for all actions -------// short UnitArray::selected_land_unit_count; short UnitArray::selected_sea_unit_count; short UnitArray::selected_air_unit_count; short *UnitArray::selected_land_unit_array=NULL; short *UnitArray::selected_sea_unit_array=NULL; short *UnitArray::selected_air_unit_array=NULL; //------ static variables for movement -------// static short square_size, not_tested_loc, rec_height, rec_width; static int move_scale; // use integer for intrgral division static int x, y; static short lower_right_case, upper_left_case; // indicate which case should be used static int *distance, *sorted_member, *sorted_distance; static char *done_flag; //static int rec_x1, rec_y1, rec_x2, rec_y2; // for bondary, corner improvement static short *filtering_unit_array; static int filtering_unit_count; static short *filtered_unit_array; static int filtered_unit_count; //-------------- define static functions -------------// static int cal_rectangle_lower_right_x(int refXLoc) { // the rule: refXLoc + (rec_width/(move_scale*2))*move_scale if(move_scale==1) return refXLoc + rec_width/2; else // move_scale == 2 return refXLoc + (rec_width/4)*2; } static int cal_rectangle_lower_right_y(int refYLoc) { // the rule: refYLoc + ((rec_height-move_scale)/(move_scale*2))*move_scale if(move_scale==1) return refYLoc + (rec_height-1)/2; else // move_scale == 2 return refYLoc + ((rec_height-2)/4)*2; } static int cal_rectangle_upper_left_x(int refXLoc) { // the rule: refXLoc - ((rec_width-move_scale)/(move_scale*2))*move_scale if(move_scale==1) return refXLoc - (rec_width-1)/2; else // move_scale == 2 return refXLoc - ((rec_width-2)/4)*2; } static int cal_rectangle_upper_left_y(int refYLoc) { // the rule: refYLoc - (rec_height/(move_scale*2))*move_scale if(move_scale==1) return refYLoc - rec_height/2; else // move_scale == 2 return refYLoc - (rec_height/4)*2; } //--------- Begin of function UnitArray::move_to ---------// // // Order the unit to move to a specific location following the // shortest path. // // destXLoc, destYLoc - the location of the destination. // divided - whether the units are divided by their mobile type // selectedUnitArray - an array of recno of selected units. // selectedCount - no. of selected units. // [char] remoteAction - whether this is an action carried out by a remote machine or not. // (default: 0) // // Note: the caller function must make sure all units in selectedUnitArray are validate (non-deleted) // void UnitArray::move_to(int destXLoc, int destYLoc, int divided, short* selectedUnitArray, int selectedCount, char remoteAction) { err_when(destXLoc<0 || destYLoc<0 || destXLoc>MAX_WORLD_X_LOC-1 || destYLoc>MAX_WORLD_Y_LOC-1); //-------- if it's a multiplayer game --------// if( !remoteAction && remote.is_enable() ) { short* shortPtr = (short*) remote.new_send_queue_msg(MSG_UNIT_MOVE, sizeof(short) * (4+selectedCount) ); shortPtr[0] = destXLoc; shortPtr[1] = destYLoc; shortPtr[2] = selectedCount; shortPtr[3] = divided; memcpy( shortPtr+4, selectedUnitArray, sizeof(short) * selectedCount ); } else { err_when( selectedCount > 10000 ); // error if(!divided) { //----------- divide units ------------// divide_array(destXLoc, destYLoc, selectedUnitArray, selectedCount); //---------- process group move --------------// // ##### patch begin Gilbert 18/8 ######// if(selected_land_unit_count) move_to(destXLoc, destYLoc, 1, selected_land_unit_array, selected_land_unit_count, COMMAND_AUTO); if(selected_sea_unit_count) { Location *locPtr = world.get_loc(destXLoc, destYLoc); if(terrain_res[locPtr->terrain_id]->average_type == TERRAIN_OCEAN) move_to(destXLoc, destYLoc, 1, selected_sea_unit_array, selected_sea_unit_count, COMMAND_AUTO); else ship_to_beach(destXLoc, destYLoc, 1, selected_sea_unit_array, selected_sea_unit_count, COMMAND_AUTO); } if(selected_air_unit_count) move_to(destXLoc, destYLoc, 1, selected_air_unit_array, selected_air_unit_count, COMMAND_AUTO); // ##### patch end Gilbert 18/8 ######// //---------------- deinit static parameters ------------------// selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0; mem_del(selected_land_unit_array); mem_del(selected_sea_unit_array); mem_del(selected_air_unit_array); return; } else { //---------------------------------------------------------// // set the unit_group_id //---------------------------------------------------------// Unit* unitPtr; DWORD curGroupId = unit_array.cur_group_id++; for(int k=0; kis_visible() || unitPtr->hit_points<=0); unitPtr->unit_group_id = curGroupId; unitPtr->action_mode = ACTION_MOVE; unitPtr->action_para = 0; if(unitPtr->action_mode2!=ACTION_MOVE) { unitPtr->action_mode2 = ACTION_MOVE; unitPtr->action_para2 = 0; unitPtr->action_x_loc2 = unitPtr->action_y_loc2 = -1; }// else keep the data to check whether same action mode is ordered } //--------------------------------------------------------------// // if only the leader unit is moving, no need to use formation // movement although the button is pushed //--------------------------------------------------------------// if(selectedCount==1) { unitPtr = (Unit*) get_ptr(selectedUnitArray[0]); unitPtr->move_to(destXLoc, destYLoc, 1); } else { Unit *firstUnitPtr = operator[](selectedUnitArray[0]); if(firstUnitPtr->mobile_type==UNIT_LAND) { move_to_now_with_filter(destXLoc, destYLoc, selectedUnitArray, selectedCount); seek_path.set_sub_mode(); // reset sub_mode searching seek_path_reuse.set_sub_mode(); //------ reset sub mode of path reuse searching } else move_to_now_with_filter(destXLoc, destYLoc, selectedUnitArray, selectedCount); } } } } //----------- End of function UnitArray::move_to -----------// //----------Begin of function UnitArray::move_to_now_with_filter------------// // the selected units may be in different territory. Group them by their region id // and process searching for each group // // destX - the x location to move to // destY - the y location to move to // selectedUnitArray - recno. of selected units // selectedCount - num of selected units // void UnitArray::move_to_now_with_filter(int destX, int destY, short* selectedUnitArray, int selectedCount) { int destRegionId = world.get_loc(destX, destY)->region_id; Unit *unitPtr = operator[](selectedUnitArray[0]); //-------------- no filtering for unit air --------------------------// if(unitPtr->mobile_type==UNIT_AIR) { move_to_now(destX, destY, selectedUnitArray, selectedCount); return; } //----------------- init data structure --------------// int arraySize = sizeof(short)*selectedCount; filtered_unit_array = (short*) mem_add(arraySize); filtering_unit_array = (short*) mem_add(arraySize); memcpy(filtering_unit_array, selectedUnitArray, arraySize); filtering_unit_count = selectedCount; int unprocessCount = selectedCount; int filterRegionId = destRegionId; int filterDestX = destX, filterDestY = destY; int loopCount, filteringCount, i; //-------------------------------------------------------------------------------// // group the unit by their region id and process group searching for each group //-------------------------------------------------------------------------------// for(loopCount=0; loopCount<=unprocessCount; loopCount++) // checking for unprocessCount+1, plus one for the case that unit not on the same territory of destination { memset(filtered_unit_array, 0, arraySize); filtered_unit_count = 0; filteringCount = filtering_unit_count; filtering_unit_count = 0; //-------------- filter for filterRegionId --------------// for(i=0; inext_x_loc(), unitPtr->next_y_loc())->region_id==filterRegionId) filtered_unit_array[filtered_unit_count++] = filtering_unit_array[i]; else filtering_unit_array[filtering_unit_count++] = filtering_unit_array[i]; } //---- process for filtered_unit_array and prepare for looping ----// if(filtered_unit_count) move_to_now(filterDestX, filterDestY, filtered_unit_array, filtered_unit_count); if(!filtering_unit_count) break; //---------------- update parameters for next checking ------------------// unitPtr = operator[](filtering_unit_array[0]); filterRegionId = world.get_loc(unitPtr->next_x_loc(), unitPtr->next_y_loc())->region_id; filterDestX = destX; filterDestY = destY; unitPtr->different_territory_destination(filterDestX, filterDestY); // reference parameters to get the location the units should move to } mem_del(filtered_unit_array); mem_del(filtering_unit_array); } //----------- End of function UnitArray::move_to_now_with_filter -----------// //--------- Begin of function UnitArray::move_to_now ---------// // // Order the unit to move to a specific location following the // shortest path. // // destXLoc, destYLoc - the location of the destination. // selectedUnitArray - an array of recno of selected units. // selectedCount - no. of selected units. // void UnitArray::move_to_now(int destXLoc, int destYLoc, short* selectedUnitArray, int selectedCount) { err_when(destXLoc<0 || destYLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc>=MAX_WORLD_Y_LOC); err_when( selectedCount > 10000 ); //------------ define vars -----------------------// int unprocessCount;// = selectedCount; // num. of unprocessed sprite int k; // for counting short vecX, vecY; // used to reset x, y short oddCount, evenCount; int j; Unit* unitPtr = unit_array[selectedUnitArray[0]]; DWORD curGroupId = unitPtr->unit_group_id; int mobileType = unitPtr->mobile_type; Location *worldLocMatrix=world.loc_matrix, *locPtr; //int sizeOneSelectedCount=0, sizeTwoSelectedCount=0; int sizeOneSelectedCount = selectedCount; //---------- set Unit::unit_group_id and count the unit by size ----------// int i; for( i=0 ; icur_action==SPRITE_IDLE && (unitPtr->cur_x!=unitPtr->next_x || unitPtr->cur_y!=unitPtr->next_y)); err_when(unitPtr->action_para); // action_para should be set to zero in move_to() if(unitPtr->cur_action==SPRITE_ATTACK) unitPtr->stop(); err_when(unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0); if(unitPtr->cur_action==SPRITE_IDLE) unitPtr->set_ready(); /*switch(unitPtr->sprite_info->loc_width) { case 1: sizeOneSelectedCount++; break; case 2: sizeTwoSelectedCount++; break; default: err_here(); break; }*/ } unprocessCount = sizeOneSelectedCount; //---- construct array to store size one selected unit ----// short* selectedSizeOneUnitArray; if(sizeOneSelectedCount) { selectedSizeOneUnitArray = (short*)mem_add(sizeof(short)*sizeOneSelectedCount); memset(selectedSizeOneUnitArray, 0, sizeof(short)*sizeOneSelectedCount); for(i=0, k=0; isprite_info->loc_width==1) { selectedSizeOneUnitArray[k++] = selectedUnitArray[i]; unprocessCount--; } } } unprocessCount = sizeOneSelectedCount; //----------- variables initialization ---------------// int destX, destY; if(mobileType==UNIT_LAND) { x = destX = destXLoc; y = destY = destYLoc; move_scale = 1; } else // UNIT_AIR, UNIT_SEA { x = destX = (destXLoc/2)*2; y = destY = (destYLoc/2)*2; move_scale = 2; } //if(sizeOneSelectedCount) //{ //----- initialize parameters and construct data structure -----// oddCount =1; evenCount = 3; square_size = not_tested_loc = lower_right_case = upper_left_case = 0; distance = (int*)mem_add(sizeof(int)*sizeOneSelectedCount); // used in the function construct_sorted_array and this function, memset(distance, 0, sizeof(int)*sizeOneSelectedCount); // and allocate/free the memory in this function sorted_distance = (int*)mem_add(sizeof(int)*sizeOneSelectedCount); memset(sorted_distance, 0, sizeof(int)*sizeOneSelectedCount); sorted_member = (int*)mem_add(sizeof(int)*sizeOneSelectedCount); memset(sorted_member, 0, sizeof(int)*sizeOneSelectedCount); done_flag = (char*)mem_add(sizeof(char)*sizeOneSelectedCount); memset(done_flag, 0, sizeof(char)*sizeOneSelectedCount); //--- calculate the rectangle size used to allocate space for the sprites----// unprocessCount = sizeOneSelectedCount; while(unprocessCount) { //============================= // process odd size square //============================= vecX = short(oddCount/4)*move_scale; vecY = vecX; k = 0; for(j=0; j=0 && y>=0 && x=0 && y>=0 && x= (square_size/move_scale)) rec_width -= move_scale; //--- decide to use upper_left_case or lower_right_case, however, it maybe changed for boundary improvement----// x = cal_rectangle_lower_right_x(destX); y = cal_rectangle_lower_right_y(destY); for(i=0; inext_y_loc()next_y_loc()>y) upper_left_case++; } if(lower_right_case==upper_left_case) // in case both values are equal, check by upper_left_case { x = cal_rectangle_upper_left_x(destX); y = cal_rectangle_upper_left_y(destY); lower_right_case = upper_left_case = 0; for(i=0; inext_y_loc()next_y_loc()>y) upper_left_case++; } } //------------ determine x, y and lower_right_case/upper_left_case-----------// determine_position_to_construct_table(selectedCount, destX, destY, mobileType); err_when(x<0 || y<0 || x>=MAX_WORLD_X_LOC || y>=MAX_WORLD_Y_LOC); //------------ construct a table to store distance -------// construct_sorted_array(selectedSizeOneUnitArray, sizeOneSelectedCount); // distance and sorted_member should be initialized first err_when(x<0 || y<0 || x>=MAX_WORLD_X_LOC || y>=MAX_WORLD_Y_LOC); //------------ process the movement -----------// unprocessCount = sizeOneSelectedCount;//selectedCount; k=0; //-******************* auto correct ***********************-// int autoCorrectStartX = x; int autoCorrectStartY = y; //-******************* auto correct ***********************-// if(lower_right_case >= upper_left_case) { while(unprocessCount) { locPtr = worldLocMatrix+y*MAX_WORLD_X_LOC+x; for(i=x; i>x-rec_width && unprocessCount; i-=move_scale, locPtr-=move_scale) { if(locPtr->is_unit_group_accessible(mobileType, curGroupId)) { do { unitPtr = (Unit*) get_ptr(selectedSizeOneUnitArray[sorted_member[k++]]); }while(unitPtr->sprite_info->loc_width>1); err_when(k>sizeOneSelectedCount); if(sizeOneSelectedCount>1) { if(unprocessCount==sizeOneSelectedCount) // the first unit to move { unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL); if(unitPtr->mobile_type==UNIT_LAND && unitPtr->nation_recno) unitPtr->select_search_sub_mode(unitPtr->next_x_loc(), unitPtr->next_y_loc(), i, y, unitPtr->nation_recno, SEARCH_MODE_REUSE); unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK); } else { err_when(unprocessCount==sizeOneSelectedCount); if(unitPtr->mobile_type==UNIT_LAND && unitPtr->nation_recno) unitPtr->select_search_sub_mode(unitPtr->next_x_loc(), unitPtr->next_y_loc(), i, y, unitPtr->nation_recno, SEARCH_MODE_REUSE); unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH); } } else unitPtr->move_to(i, y, 1); unprocessCount--; } } y-=move_scale; //-******************* auto correct ***********************-// #ifdef DEBUG err_when(unprocessCount && y<0); #else if(unprocessCount && y<0) y = autoCorrectStartY; #endif //-******************* auto correct ***********************-// } } else // upper_left_case { while(unprocessCount) { locPtr = worldLocMatrix+y*MAX_WORLD_X_LOC+x; for(i=x; iis_unit_group_accessible(mobileType, curGroupId)) { do { unitPtr = (Unit*) get_ptr(selectedSizeOneUnitArray[sorted_member[k++]]); }while(unitPtr->sprite_info->loc_width>1); err_when(k>sizeOneSelectedCount); if(sizeOneSelectedCount>1) { if(unprocessCount==sizeOneSelectedCount) // the first unit to move { unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL); if(unitPtr->mobile_type==UNIT_LAND && unitPtr->nation_recno) unitPtr->select_search_sub_mode(unitPtr->next_x_loc(), unitPtr->next_y_loc(), i, y, unitPtr->nation_recno, SEARCH_MODE_REUSE); unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK); } else { err_when(unprocessCount==sizeOneSelectedCount); if(unitPtr->mobile_type==UNIT_LAND && unitPtr->nation_recno) unitPtr->select_search_sub_mode(unitPtr->next_x_loc(), unitPtr->next_y_loc(), i, y, unitPtr->nation_recno, SEARCH_MODE_REUSE); unitPtr->move_to(i, y, 1, 4, 0, sizeOneSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH); } } else unitPtr->move_to(i, y, 1); unprocessCount--; } } y+=move_scale; //-******************* auto correct ***********************-// #ifdef DEBUG err_when(unprocessCount && y>=MAX_WORLD_Y_LOC); #else if(unprocessCount && y>=MAX_WORLD_Y_LOC) y = autoCorrectStartY; #endif //-******************* auto correct ***********************-// } } //---------------- destruct data structure --------------// mem_del(done_flag); mem_del(sorted_distance); mem_del(sorted_member); mem_del(distance); mem_del(selectedSizeOneUnitArray); //}// end if (sizeOneSelectedCount) /* //=============================================================================// //----- order sprite with size two to move to a specified position ------------// //=============================================================================// int sizeTwoUnprocessCount = sizeTwoSelectedCount; int surX, surY, suaCount=0; char w, h, blocked=0; if(sizeOneSelectedCount) // mix, size one units have processed { if(rec_width>square_size) square_size = rec_width; if(rec_height>square_size) square_size = rec_height; square_size = ((square_size+1)/2)<<1; // change to multiply of two rec_width = rec_height = square_size; x = destX-rec_width/2+1; y = destY-rec_height/2; } else // all are size 2 units { //-***************** testing ********************-// err_here(); //-***************** testing ********************-// square_size = rec_width = rec_height = 2; x = destX; y = destY; if(x<0) x = 0; else if(x>=MAX_WORLD_X_LOC-1) x = MAX_WORLD_X_LOC-2; if(y<0) y = 0; else if(y>=MAX_WORLD_Y_LOC-1) y = MAX_WORLD_Y_LOC-2; blocked = 0; for(h=0, surY=y; h<2 && !blocked; h++, surY++) { for(w=0, surX=x; w<2 && !blocked; w++, surX++) { locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX; blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId); } } if(!blocked) { do { unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]); }while(unitPtr->sprite_info->loc_width<2); if(sizeTwoSelectedCount>1) { unitPtr->move_to(x, y, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL); unitPtr->move_to(x, y, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK); } else unitPtr->move_to(x, y, 1); sizeTwoUnprocessCount--; } } while(sizeTwoUnprocessCount) { //-***************** testing ********************-// err_here(); //-***************** testing ********************-// int moveToX, moveToY; int boundedX, boundedY; //------------- upper edge --------------// moveToY = y-2; moveToX = x; if(moveToY>=0) { if(x+rec_width+2 > MAX_WORLD_X_LOC-2) boundedX = MAX_WORLD_X_LOC-1; else boundedX = x+rec_width+2; while(moveToX=MAX_WORLD_X_LOC-1 || moveToY>=MAX_WORLD_Y_LOC-1) blocked = 1; else { blocked = 0; for(h=0, surY=moveToY; h<2 && !blocked; h++, surY++) { for(w=0, surX=moveToX; w<2 && !blocked; w++, surX++) { locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX; blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId); } } } if(!blocked) { do { unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]); }while(unitPtr->sprite_info->loc_width<2); if(sizeTwoSelectedCount>1) { if(sizeTwoUnprocessCount==sizeTwoSelectedCount) // the first unit to move { unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL); unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK); } else { err_if(sizeTwoUnprocessCount==sizeTwoSelectedCount) err_here(); unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH); } } else unitPtr->move_to(moveToX, moveToY, 1); sizeTwoUnprocessCount--; } moveToX+=2; } } //------------- right edge --------------// moveToX = x+rec_width; moveToY = y; if(moveToX MAX_WORLD_Y_LOC-2) boundedY = MAX_WORLD_Y_LOC-1; else boundedY = y+rec_height+2; while(moveToY=MAX_WORLD_X_LOC-1 || moveToY>=MAX_WORLD_Y_LOC-1) blocked = 1; else { blocked = 0; for(h=0, surY=moveToY; h<2 && !blocked; h++, surY++) { for(w=0, surX=moveToX; w<2 && !blocked; w++, surX++) { locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX; blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId); } } } if(!blocked) { do { unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]); }while(unitPtr->sprite_info->loc_width<2); if(sizeTwoSelectedCount>1) { if(sizeTwoUnprocessCount==sizeTwoSelectedCount) // the first unit to move { unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL); unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK); } else { err_if(sizeTwoUnprocessCount==sizeTwoSelectedCount) err_here(); unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH); } } else unitPtr->move_to(moveToX, moveToY, 1); sizeTwoUnprocessCount--; } moveToY+=2; } } //------------- lower edge ----------------// moveToX = x+rec_width-2; moveToY = y+rec_height; if(moveToYboundedX && sizeTwoUnprocessCount) { //--------------- is the position blocked? ----------// if(moveToX>=MAX_WORLD_X_LOC-1 || moveToY>=MAX_WORLD_Y_LOC-1) blocked = 1; else { blocked = 0; for(h=0, surY=moveToY; h<2 && !blocked; h++, surY++) { for(w=0, surX=moveToX; w<2 && !blocked; w++, surX++) { locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX; blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId); } } } if(!blocked) { do { unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]); }while(unitPtr->sprite_info->loc_width<2); if(sizeTwoSelectedCount>1) { if(sizeTwoUnprocessCount==sizeTwoSelectedCount) // the first unit to move { unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL); unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK); } else { err_if(sizeTwoUnprocessCount==sizeTwoSelectedCount) err_here(); unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH); } } else unitPtr->move_to(moveToX, moveToY, 1); sizeTwoUnprocessCount--; } moveToX-=2; } } //------------- left edge ---------------// moveToX = x-2; moveToY = y+rec_height-2; if(moveToX>=0) { if(y-3 < 0) boundedY = -1; else boundedY = y-3; while(moveToY>boundedY && sizeTwoUnprocessCount) { //--------------- is the position blocked? ----------// if(moveToX>=MAX_WORLD_X_LOC-1 || moveToY>=MAX_WORLD_Y_LOC-1) blocked = 1; else { blocked = 0; for(h=0, surY=moveToY; h<2 && !blocked; h++, surY++) { for(w=0, surX=moveToX; w<2 && !blocked; w++, surX++) { locPtr = worldLocMatrix+surY*MAX_WORLD_X_LOC+surX; blocked = !locPtr->is_unit_group_accessible(mobileType, curGroupId); } } } if(!blocked) { do { unitPtr = (Unit*) get_ptr(selectedUnitArray[suaCount++]); }while(unitPtr->sprite_info->loc_width<2); if(sizeTwoSelectedCount>1) { if(sizeTwoUnprocessCount==sizeTwoSelectedCount) // the first unit to move { unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_INITIAL); unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_FIRST_SEEK); } else { err_if(sizeTwoUnprocessCount==sizeTwoSelectedCount) err_here(); unitPtr->move_to(moveToX, moveToY, 1, 4, 0, sizeTwoSelectedCount, GENERAL_GROUP_MOVEMENT, REUSE_PATH_SEARCH); } } else unitPtr->move_to(moveToX, moveToY, 1); sizeTwoUnprocessCount--; } moveToY-=2; } } //------- reset square_size, rec_width, rec_height -----------// rec_width+=4; rec_height+=4; x-=2; y-=2; }*/ } //----------- End of function UnitArray::move_to_now -----------// //----------Begin of function UnitArray::construct_sorted_array------------// // // construct a table to store the d(x,y) value from the reference(rectangule // starting) point in group movement control // // For the detail, see ounitam.txt // // // selectedUnitArray - an array of recno of selected units. // selectedCount - no. of selected units. // void UnitArray::construct_sorted_array(short* selectedUnitArray, int selectedCount) { Unit* unitPtr; int min, dist; // for comparison int i, j, k; const int c = 1000; // c value for the d(x,y) function if(lower_right_case >= upper_left_case) { for(i=0; icur_x_loc()+c*abs(unitPtr->cur_y_loc()-y)); // plus/minus x coord difference } } else // upper_left_case { for(i=0; icur_x_loc()-x+c*abs(unitPtr->cur_y_loc()-y)); // plus/minus x coord difference } } //---------------------------------------------------------------// // this part of code using a technique to adjust the distance value // such that the selected group can change from lower right form // to upper left form or upper left form to lower right form in a // better way. //---------------------------------------------------------------// //------ sorting the distance and store in sortedDistance Array -------// for(j=0; j=remainder) { if((index = dist-remainder) < defArraySize) // the case can be handled by this array size { distance[sorted_distance[j]] = rightQuotZ[index] + dist; rightQuotZ[index] += c; } } } } mem_del(leftQuotZ); mem_del(rightQuotZ); //---------- sorting -------------// for(j=0; j destXLoc, destYLoc - the location of the destination. // selectedCount - no. of selected units. // void UnitArray::determine_position_to_construct_table(int selectedCount, int destXLoc, int destYLoc, char mobileType) { //======================================================================// // boundary, corner improvement //======================================================================// int sqrtValue; //======================================================================// // lower right case //======================================================================// if(lower_right_case>=upper_left_case) { //--------- calculate x, y location for lower right case ---------// x = cal_rectangle_lower_right_x(destXLoc); y = cal_rectangle_lower_right_y(destYLoc); if(x=MAX_WORLD_Y_LOC-move_scale) { if(not_tested_loc>=square_size/move_scale) rec_width -= move_scale; x = rec_width-move_scale; y = MAX_WORLD_Y_LOC-move_scale; } //------------- just left edge -------------// else x = rec_width-move_scale; } else if(x>=MAX_WORLD_X_LOC-move_scale) { //============== right edge ==============// //----------- top right corner -----------// if(y=MAX_WORLD_Y_LOC-move_scale) { y = MAX_WORLD_Y_LOC-move_scale; x = MAX_WORLD_X_LOC-move_scale; } //---------- just right edge ---------------// else { int squareSize = square_size/move_scale; if(squareSize*(squareSize-1)>=selectedCount) rec_width -= move_scale; x = MAX_WORLD_X_LOC-move_scale; } } else if(y=MAX_WORLD_Y_LOC-move_scale) { //================== bottom edge ====================// if(not_tested_loc>=square_size/move_scale) rec_width += move_scale; //if(mobileType==UNIT_LAND) // x = destXLoc+(rec_width/2); //else // x = destXLoc+(rec_width/4)*2; x = cal_rectangle_lower_right_x(destXLoc); y = MAX_WORLD_Y_LOC-move_scale; } } //======================================================================// // upper left case //======================================================================// else { //--------- calculate x, y location for upper left case ---------// x = cal_rectangle_upper_left_x(destXLoc); y = cal_rectangle_upper_left_y(destYLoc); if(x<0) { //================= left edge ==================// //------------- top left corner --------------// if(y<0) { sqrtValue = (int)sqrt(selectedCount); if(sqrtValue*sqrtValue != selectedCount) sqrtValue++; if(mobileType!=UNIT_LAND) sqrtValue = sqrtValue<<1; // change to scale 2 rec_width = rec_height = sqrtValue; x = y = 0; } //------------- bottom left corner --------------// else if(y+rec_height>=MAX_WORLD_Y_LOC-move_scale) { lower_right_case = upper_left_case+1; x = rec_width-move_scale; y = MAX_WORLD_Y_LOC-move_scale; } //------------- just left edge ------------------// else { sqrtValue = (int)sqrt(selectedCount); if(sqrtValue*sqrtValue != selectedCount) sqrtValue++; if(mobileType!=UNIT_LAND) sqrtValue = sqrtValue<<1; // change to scale 2 rec_width = rec_height = sqrtValue; x = 0; } } //================ right edge ================// else if(x+rec_width>=MAX_WORLD_X_LOC-move_scale) { //------------- top right corner ------------------// if(y<0) { sqrtValue = (int)sqrt(selectedCount); if(sqrtValue*sqrtValue != selectedCount) sqrtValue++; if(mobileType!=UNIT_LAND) sqrtValue = sqrtValue<<1; // change to scale 2 rec_width = rec_height = sqrtValue; x = MAX_WORLD_X_LOC-rec_width; y = 0; } //------------- bottom right corner ------------------// else if(y+rec_height>=MAX_WORLD_Y_LOC-move_scale) { lower_right_case = upper_left_case+1; x = MAX_WORLD_X_LOC-move_scale; y = MAX_WORLD_Y_LOC-move_scale; } //------------- just right edge ------------------// else { sqrtValue = (int)sqrt(selectedCount); if(sqrtValue*sqrtValue != selectedCount) sqrtValue++; if(mobileType!=UNIT_LAND) sqrtValue = sqrtValue<<1; // change to scale 2 rec_width = rec_height = sqrtValue; int squareSize = square_size/move_scale; if(squareSize*(squareSize-1)>=selectedCount) rec_width -= move_scale; lower_right_case = upper_left_case+1; x = MAX_WORLD_X_LOC-move_scale; //if(mobileType==UNIT_LAND) // y = destYLoc+((rec_height-1)/2); //else // y = destYLoc+((rec_height-2)/4)*2; y = cal_rectangle_lower_right_y(destYLoc); } } //================= top edge ================// else if(y<0) { sqrtValue = (int)sqrt(selectedCount); if(sqrtValue*sqrtValue != selectedCount) sqrtValue++; rec_width = rec_height = sqrtValue; y = 0; } //================= bottom edge ================// else if(y+rec_height>=MAX_WORLD_Y_LOC-move_scale) { if(not_tested_loc>=square_size) rec_width += move_scale; y = MAX_WORLD_Y_LOC-move_scale; } } /*if(lower_right_case>=upper_left_case) { x = cal_rectangle_lower_right_x(destXLoc); y = cal_rectangle_lower_right_y(destYLoc); rec_x1 = x - rec_width + move_scale; rec_y1 = y - rec_height + move_scale; rec_x2 = x; rec_y2 = y; } else { x = cal_rectangle_upper_left_x(destXLoc); y = cal_rectangle_upper_left_y(destYLoc); }*/ } //--- End of function UnitArray::determine_position_to_construct_table -----//