/*
* 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 : OUNITAAT.CPP
//Description : Object UnitArray - part 2
#include
#include
#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
//------ static variables for attacking ------//
// ATTACK_DIR is defined in OUNIT.H
#define MAX_TARGET_SIZE 4
#define MAX_UNIT_SURROUND_SIZE MAX_TARGET_SIZE+2 // handle the case up to target size 4x4
#define SHIFT_ADJUST 1 // since the upper left offset position is (-1, -1)
static short *unit_processed_array; // store those processed unit sprite_recno
static short unit_processed_count; // count the number processed units
static short *dir_array_ptr[ATTACK_DIR]; // store units' sprite_recno in each direction
static short dir_array_count[ATTACK_DIR]; // num of unit in each direction
static char unreachable_table[MAX_UNIT_SURROUND_SIZE][MAX_UNIT_SURROUND_SIZE]; // table shared for all attackers
//************* debug ***************//
#ifdef DEBUG
//--------------------------------------------------------------------------------//
// resultNum - the num of free space around the target
// width - width of target
// height - height of target
//--------------------------------------------------------------------------------//
static void debug_analyse_result_check(int resultNum, int width, int height)
{
int count=0, i, j;
for(i=0; i targetWidth - target width
// targetHeight - target height
//
char UnitArray::get_target_surround_loc(int targetWidth, int targetHeight)
{
static char surround_loc[MAX_TARGET_SIZE][MAX_TARGET_SIZE] // width, height
= { { 8, 10, 12, 14}, {10, 12, 14, 16}, {12, 14, 16, 18}, {14, 16, 18, 20}};
return surround_loc[targetWidth-1][targetHeight-1];
}
//----------- End of function UnitArray::get_target_surround_loc -----------//
//--------- Begin of function UnitArray::update_unreachable_table ---------//
// check target surroundig to drop those unreachable location
//
// targetXLoc - target x location
// targetYLoc - target y location
// targetWidth - target width
// targetHeight - target height
// mobileType - mobile type of the attacker
// analyseResult - reference for returning num of reachable location
//
void UnitArray::update_unreachable_table(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight,
char mobileType, int &analyseResult)
{
int xLoc1, yLoc1, xLoc2, yLoc2, i;
//----------------------------------------------------------------------//
// checking for left & right edges, calculate location and counter
//----------------------------------------------------------------------//
xLoc1 = targetXLoc-1;
xLoc2 = targetXLoc+targetWidth;
if(targetYLoc==0)
{
i = targetHeight+1;
yLoc1=targetYLoc;
}
else
{
i = targetHeight+2;
yLoc1=targetYLoc-1;
}
if(targetYLoc+targetHeight>=MAX_WORLD_Y_LOC)
i--;
for(yLoc2=yLoc1-targetYLoc+SHIFT_ADJUST; i>0; i--, yLoc1++, yLoc2++)
{
//---- left edge ----//
if(xLoc1>=0 && !unreachable_table[0][yLoc2] && !world.get_loc(xLoc1, yLoc1)->can_move(mobileType))
{
unreachable_table[0][yLoc2] = 1;
analyseResult--;
}
//----- right edge -----//
if(xLoc2can_move(mobileType))
{
unreachable_table[targetWidth+1][yLoc2] = 1;
analyseResult--;
}
if(!analyseResult)
return;
}
//----------------------------------------------------------------------//
// checking for the top and bottom edges
//----------------------------------------------------------------------//
yLoc1 = targetYLoc-1;
yLoc2 = targetYLoc+targetHeight;
for(i=0, xLoc1=targetXLoc, xLoc2=xLoc1-targetXLoc+SHIFT_ADJUST; i=0 && !unreachable_table[xLoc2][0] && !world.get_loc(xLoc1, yLoc1)->can_move(mobileType))
{
unreachable_table[xLoc2][0] = 1;
analyseResult--;
}
//----- bottom edge -----//
if(yLoc2can_move(mobileType))
{
unreachable_table[xLoc2][targetHeight+1] = 1;
analyseResult--;
}
if(!analyseResult)
return;
}
debug_result_check(analyseResult, targetWidth, targetHeight);
err_when(analyseResult<0);
}
//----------- End of function UnitArray::update_unreachable_table -----------//
//--------- Begin of function UnitArray::attack ---------//
//
// Order the unit to attack a specific location.
//
// targetXLoc, targetYLoc - target location
// divided - whether the units are divided
// 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)
// targetUnitRecno - if it is unit, pass the unit recno, otherwise 0
//
void UnitArray::attack(int targetXLoc, int targetYLoc, int divided, short* selectedUnitArray, int selectedCount, char remoteAction, int targetUnitRecno)
{
err_when(targetXLoc<0 || targetYLoc<0 || targetXLoc>=MAX_WORLD_X_LOC || targetYLoc>=MAX_WORLD_Y_LOC);
// ######## patch begin Gilbert 5/8 #########//
int targetNationRecno = 0;
if( targetUnitRecno == 0 )
{
// unit determined from the location
int tmpMobileType;
Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
targetUnitRecno = locPtr->get_any_unit(tmpMobileType) ;
}
else
{
// location determined by the unit
Unit *unitPtr;
if( !unit_array.is_deleted(targetUnitRecno)
&& (unitPtr = unit_array[targetUnitRecno])
&& unitPtr->is_visible() )
{
targetXLoc = unitPtr->next_x_loc();
targetYLoc = unitPtr->next_y_loc();
if( unitPtr->unit_id != UNIT_EXPLOSIVE_CART ) // attacking own porcupine is allowed
targetNationRecno = unitPtr->nation_recno;
}
else
targetUnitRecno = 0;
}
if( targetUnitRecno == 0 )
{
//--- set the target coordination to the top left position of the town/firm ---//
Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
//---- if there is a firm on this location -----//
if( locPtr->is_firm() )
{
Firm* firmPtr = firm_array[locPtr->firm_recno()];
targetXLoc = firmPtr->loc_x1;
targetYLoc = firmPtr->loc_y1;
targetNationRecno = firmPtr->nation_recno;
}
//---- if there is a town on this location -----//
else if( locPtr->is_town() )
{
Town* townPtr = town_array[locPtr->town_recno()];
targetXLoc = townPtr->loc_x1;
targetYLoc = townPtr->loc_y1;
targetNationRecno = townPtr->nation_recno;
}
else
return;
}
// ######## patch end Gilbert 5/8 #########//
//--------- AI debug code ---------//
//--- AI attacking a nation which its NationRelation::should_attack is 0 ---//
Unit* attackUnit = unit_array[ selectedUnitArray[0] ];
if( attackUnit->nation_recno && targetNationRecno )
{
if( nation_array[attackUnit->nation_recno]->get_relation(targetNationRecno)->should_attack==0 )
return;
}
//-------- if it's a multiplayer game --------//
if( !remoteAction && remote.is_enable() )
{
short* shortPtr = (short*) remote.new_send_queue_msg(MSG_UNIT_ATTACK, sizeof(short) * (5+selectedCount) );
shortPtr[0] = targetXLoc;
shortPtr[1] = targetYLoc;
shortPtr[2] = targetUnitRecno;
shortPtr[3] = selectedCount;
shortPtr[4] = divided;
memcpy( shortPtr+5, selectedUnitArray, sizeof(short) * selectedCount );
}
else
{
if(!divided)
{
divide_array(targetXLoc, targetYLoc, selectedUnitArray, selectedCount, 1); // 1 for excluding the recno in target location
Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
int targetMobileType = locPtr->has_any_unit();
if(selected_land_unit_count)
attack_call(targetXLoc, targetYLoc, UNIT_LAND, targetMobileType, 1, selected_land_unit_array, selected_land_unit_count, targetUnitRecno);
if(selected_sea_unit_count)
attack_call(targetXLoc, targetYLoc, UNIT_SEA, targetMobileType, 1, selected_sea_unit_array, selected_sea_unit_count, targetUnitRecno);
if(selected_air_unit_count)
attack_call(targetXLoc, targetYLoc, UNIT_AIR, targetMobileType, 1, selected_air_unit_array, selected_air_unit_count, targetUnitRecno);
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
err_here();
}
}
//----------- End of function UnitArray::attack -----------//
//--------- Begin of function UnitArray::attack_call ---------//
// targetXLoc - target x location
// targetYLoc - target y location
// mobileType - attacker's mobile type
// targetMobileType - target mobile type
// divided - whether the units are divided
// selectedUnitArray - selected units' recno.
// selectedCount - num of selected units
//
void UnitArray::attack_call(int targetXLoc, int targetYLoc, char mobileType, char targetMobileType, int divided, short* selectedUnitArray, int selectedCount, int targetUnitRecno)
{
//------------- attack now -------------//
err_when( selectedCount > 10000 );
Location* locPtr = world.get_loc(targetXLoc, targetYLoc);
err_when(!locPtr);
// ##### patch begin Gilbert 5/8 ######//
//if(targetMobileType)
if( targetUnitRecno && !unit_array.is_deleted(targetUnitRecno) )
{
//---------------- attack unit --------------//
//Unit *targetUnit = unit_array[locPtr->unit_recno(targetMobileType)];
Unit *targetUnit = unit_array[targetUnitRecno];
if(!targetUnit->is_visible() || targetUnit->hit_points<=0)
return;
// short targetUnitRecno = targetUnit->sprite_recno;
attack_unit(targetXLoc, targetYLoc, targetUnitRecno, selectedUnitArray, selectedCount);
}
// ##### patch end Gilbert 5/8 ######//
else if(locPtr->is_firm())
{
//------------------ attack firm -------------------//
Firm *firmPtr = firm_array[locPtr->firm_recno()];
err_when(!firmPtr);
if(firmPtr->hit_points<=0)
return;
attack_firm(targetXLoc, targetYLoc, firmPtr->firm_recno, selectedUnitArray, selectedCount);
}
else if(locPtr->is_town())
{
//-------------------- attack town -------------------//
Town *townPtr = town_array[locPtr->town_recno()];
err_when(!townPtr);
attack_town(targetXLoc, targetYLoc, townPtr->town_recno, selectedUnitArray, selectedCount);
}
else if(locPtr->is_wall())
{
//------------------ attack wall ---------------------//
attack_wall(targetXLoc, targetYLoc, selectedUnitArray, selectedCount);
}
else
return; // no target for attacking
}
//----------- End of function UnitArray::attack_call -----------//
//--------- Begin of function UnitArray::attack_unit ---------//
// targetXLoc, targetYLoc - the unit upper left location
// targetunitRecno - the unit recno
//
// Note : this attack function only for attackers with size 1x1.
//
void UnitArray::attack_unit(int targetXLoc, int targetYLoc, short targetUnitRecno, short* selectedUnitArray, int selectedCount)
{
err_when(selectedCount<=0);
if(selectedCount==1)
{
Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
unitPtr->unit_group_id = unit_array.cur_group_id++;
unitPtr->attack_unit(targetXLoc, targetYLoc);
return;
}
//********************** improve later begin **************************//
//---------------------------------------------------------------------//
// codes for differnt territory or different mobile_type attacking should
// be added in the future.
//---------------------------------------------------------------------//
Unit *firstUnitPtr = unit_array[selectedUnitArray[0]];
Unit *targetPtr2 = unit_array[targetUnitRecno];
if( (world.get_loc(targetXLoc, targetYLoc)->region_id !=
world.get_loc(firstUnitPtr->next_x_loc(), firstUnitPtr->next_y_loc())->region_id) ||
(targetPtr2->mobile_type!=firstUnitPtr->mobile_type) )
{
Unit *unitPtr;
set_group_id(selectedUnitArray, selectedCount);
for(int i=0; iattack_unit(targetXLoc, targetYLoc);
}
return;
}
//*********************** improve later end ***************************//
//----------- initialize local parameters ------------//
Unit *targetPtr = unit_array[targetUnitRecno];
int targetWidth = targetPtr->sprite_info->loc_width;
int targetHeight = targetPtr->sprite_info->loc_height;
int targetXLoc2 = targetXLoc + targetWidth - 1;
int targetYLoc2 = targetYLoc + targetHeight - 1;
char surroundLoc = get_target_surround_loc(targetWidth, targetHeight);
char *xOffsetPtr = get_target_x_offset(targetWidth, targetHeight, 0);
char *yOffsetPtr = get_target_y_offset(targetWidth, targetHeight, 0);
//---------------------------------------------------------------------//
// construct data structure
//---------------------------------------------------------------------//
int tempVar = sizeof(short)*selectedCount;
memset(dir_array_count, 0, sizeof(dir_array_count));
int count;
for(count=0; countmobile_type);
debug_result_check(analyseResult, targetWidth, targetHeight);
err_when(analyseResult<0);
if(!analyseResult) // 0 if all surround location is not accessible
{
//------------------------------------------------------------//
// special handling for this case
//------------------------------------------------------------//
handle_attack_target_totally_blocked(targetXLoc, targetYLoc, targetUnitRecno, selectedUnitArray, selectedCount, 1);
for(count=0; count=surroundLoc)
{
destCount = 0;
xOffsetPtr = get_target_x_offset(targetWidth, targetHeight, count);
yOffsetPtr = get_target_y_offset(targetWidth, targetHeight, count);
xOffset = *xOffsetPtr;
yOffset = *yOffsetPtr;
}
else
{
xOffset = *(++xOffsetPtr);
yOffset = *(++yOffsetPtr);
}
if(!unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST])
break;
}
}
err_when(unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST]);
//------------------------------------------------------------//
// find the closest attacker
//------------------------------------------------------------//
err_when(unprocessed>2000 || unprocessed <0);
xLoc = targetXLoc + xOffset;
yLoc = targetYLoc + yOffset;
err_when(!world.get_loc(xLoc, yLoc)->can_move(targetPtr->mobile_type));
for(i=0, minDist=0x7FFFFFF; inext_x_loc());
yDist = abs(yLoc-unitPtr->next_y_loc());
dist = (xDist >= yDist) ? xDist*10+yDist : yDist*10+xDist;
if(dist < minDist)
{
minDist = dist;
unitPos = i;
}
}
unitPtr = (Unit*) get_ptr(curArrayPtr[unitPos]);
curArrayPtr[unitPos] = curArrayPtr[--unprocessed]; // move the units in the back to the front
err_when(unitPtr->action_mode2!=ACTION_ATTACK_WALL &&
unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0);
seek_path.set_status(PATH_WAIT);
err_when(seek_path.path_status==PATH_NODE_USED_UP);
unitPtr->attack_unit(targetXLoc, targetYLoc, xOffset, yOffset);
//------------------------------------------------------------//
// store the unit sprite_recno in the array
//------------------------------------------------------------//
unit_processed_array[unit_processed_count++] = unitPtr->sprite_recno;
//------------------------------------------------------------//
// set the flag if unreachable
//------------------------------------------------------------//
if(seek_path.path_status==PATH_NODE_USED_UP)
{
unreachable_table[xLoc-targetXLoc+SHIFT_ADJUST][yLoc-targetYLoc+SHIFT_ADJUST] = 1;
analyseResult--;
debug_result_check(analyseResult, targetWidth, targetHeight);
err_when(analyseResult<0);
//------------------------------------------------------------//
// the nearby location should also be unreachable
//------------------------------------------------------------//
check_nearby_location(targetXLoc, targetYLoc, xOffset, yOffset, targetWidth, targetHeight,
targetPtr->mobile_type, analyseResult);
}
update_unreachable_table(targetXLoc, targetYLoc, targetWidth, targetHeight, unitPtr->mobile_type, analyseResult);
#ifdef DEBUG
for(int di=0; di=1 && di<=targetWidth && dj>=1 && dj<=targetHeight)
continue;
int debugXLoc = targetXLoc+di-SHIFT_ADJUST;
int debugYLoc = targetYLoc+dj-SHIFT_ADJUST;
if(debugXLoc<0 || debugXLoc>=MAX_WORLD_X_LOC || debugYLoc<0 || debugYLoc>=MAX_WORLD_Y_LOC)
continue;
Location *dlPtr = world.get_loc(debugXLoc, debugYLoc);
err_when(!dlPtr->can_move(targetPtr->mobile_type) && unreachable_table[di][dj]==0);
}
}
#endif
}
}
//---------------------------------------------------------------------//
// set the unreachable flag for each units
//---------------------------------------------------------------------//
//-************** codes here ***************-//
//---------------------------------------------------------------------//
// destruct data structure
//---------------------------------------------------------------------//
for(count=0; count targetXLoc, targetYLoc - the firm upper left location
// firmRecno - the firm recno
//
// try to calculate the best location for each unit to move to the
// surrounding of the firm for attacking
//
void UnitArray::attack_firm(int targetXLoc, int targetYLoc, short firmRecno, short* selectedUnitArray, int selectedCount)
{
err_when(selectedCount<=0);
if(selectedCount==1)
{
Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
unitPtr->unit_group_id = unit_array.cur_group_id++;
unitPtr->attack_firm(targetXLoc, targetYLoc);
return;
}
//********************** improve later begin **************************//
//---------------------------------------------------------------------//
// codes for differnt territory or different mobile_type attacking should
// be added in the future.
//---------------------------------------------------------------------//
Unit *firstUnitPtr = unit_array[selectedUnitArray[0]];
if(world.get_loc(targetXLoc, targetYLoc)->region_id !=
world.get_loc(firstUnitPtr->next_x_loc(), firstUnitPtr->next_y_loc())->region_id)
{
Unit *unitPtr;
set_group_id(selectedUnitArray, selectedCount);
for(int i=0; iattack_firm(targetXLoc, targetYLoc);
}
return;
}
//*********************** improve later end ***************************//
//----------- initialize local parameters ------------//
Firm *firmPtr = firm_array[firmRecno];
FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
int firmWidth = firmInfo->loc_width;
int firmHeight = firmInfo->loc_height;
int targetXLoc2 = targetXLoc + firmWidth - 1; // the lower right corner of the firm
int targetYLoc2 = targetYLoc + firmHeight -1;
char *xOffsetPtr, *yOffsetPtr;
//---------------------------------------------------------------------//
// construct data structure
//---------------------------------------------------------------------//
int tempVar = sizeof(short)*selectedCount;
memset(dir_array_count, 0, sizeof(dir_array_count));
int count;
for(count=0; countmobile_type);
debug_result_check(analyseResult, firmWidth, firmHeight);
err_when(analyseResult<0);
if(!analyseResult) // 0 if all surround location is not accessible
{
//------------------------------------------------------------//
// special handling for this case
//------------------------------------------------------------//
handle_attack_target_totally_blocked(targetXLoc, targetYLoc, firmRecno, selectedUnitArray, selectedCount, 2);
for(count=0; count2000 || unprocessed <0);
while(unprocessed)
{
//-----------------------------------------------------//
// find a reachable location, or not searched location
//-----------------------------------------------------//
err_when(analyseResult<0);
if(!analyseResult)
{
handle_attack_target_totally_blocked(targetXLoc, targetYLoc, firmRecno, selectedUnitArray, selectedCount, 2);
for(count=0; count=surroundLoc)
{
destCount = 0;
xOffsetPtr = get_target_x_offset(firmWidth, firmHeight, count);
yOffsetPtr = get_target_y_offset(firmWidth, firmHeight, count);
xOffset = *xOffsetPtr;
yOffset = *yOffsetPtr;
}
else
{
xOffset = *(++xOffsetPtr);
yOffset = *(++yOffsetPtr);
}
if(!unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST])
break;
}
}
err_when(unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST]);
//------------------------------------------------------------//
// find the closest attacker
//------------------------------------------------------------//
err_when(unprocessed>2000 || unprocessed <0);
xLoc = targetXLoc + xOffset;
yLoc = targetYLoc + yOffset;
err_when(!world.get_loc(xLoc, yLoc)->can_move(unitPtr->mobile_type));
for(i=0, minDist=0x7FFFFFF; inext_x_loc());
yDist = abs(yLoc-unitPtr->next_y_loc());
dist = (xDist >= yDist) ? xDist*10+yDist : yDist*10+xDist;
if(dist < minDist)
{
minDist = dist;
unitPos = i;
}
}
unitPtr = (Unit*) get_ptr(curArrayPtr[unitPos]);
curArrayPtr[unitPos] = curArrayPtr[--unprocessed]; // move the units in the back to the front
err_when(unitPtr->action_mode2!=ACTION_ATTACK_WALL &&
unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0);
seek_path.set_status(PATH_WAIT);
err_when(seek_path.path_status==PATH_NODE_USED_UP);
unitPtr->attack_firm(targetXLoc, targetYLoc, xOffset, yOffset);
//------------------------------------------------------------//
// set the flag if unreachable
//------------------------------------------------------------//
if(seek_path.path_status==PATH_NODE_USED_UP)
{
unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST] = 1;
analyseResult--;
debug_result_check(analyseResult, firmWidth, firmHeight);
err_when(analyseResult<0);
//------------------------------------------------------------//
// the nearby location should also be unreachable
//------------------------------------------------------------//
check_nearby_location(targetXLoc, targetYLoc, xOffset, yOffset, firmWidth, firmHeight,
unitPtr->mobile_type, analyseResult);
}
update_unreachable_table(targetXLoc, targetYLoc, firmWidth, firmHeight, unitPtr->mobile_type, analyseResult);
#ifdef DEBUG
for(int di=0; di=1 && di<=firmWidth && dj>=1 && dj<=firmHeight)
continue;
int debugXLoc = targetXLoc+di-SHIFT_ADJUST;
int debugYLoc = targetYLoc+dj-SHIFT_ADJUST;
if(debugXLoc<0 || debugXLoc>=MAX_WORLD_X_LOC || debugYLoc<0 || debugYLoc>=MAX_WORLD_Y_LOC)
continue;
Location *dlPtr = world.get_loc(debugXLoc, debugYLoc);
err_when(!dlPtr->can_move(unitPtr->mobile_type) && unreachable_table[di][dj]==0);
}
}
#endif
}
}
//---------------------------------------------------------------------//
// set the unreachable flag for each units
//---------------------------------------------------------------------//
//-************** codes here ***************-//
//---------------------------------------------------------------------//
// destruct data structure
//---------------------------------------------------------------------//
for(count=0; count targetXLoc, targetYLoc - the town upper left location
// townRecno - the town recno
//
// try to calculate the best location for each unit to move to the
// surrounding of the town for attacking
//
void UnitArray::attack_town(int targetXLoc, int targetYLoc, short townRecno, short* selectedUnitArray, int selectedCount)
{
err_when(selectedCount<=0);
if(selectedCount==1)
{
Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
unitPtr->unit_group_id = unit_array.cur_group_id++;
unitPtr->attack_town(targetXLoc, targetYLoc);
return;
}
//********************** improve later begin **************************//
//---------------------------------------------------------------------//
// codes for differnt territory or different mobile_type attacking should
// be added in the future.
//---------------------------------------------------------------------//
Unit *firstUnitPtr = unit_array[selectedUnitArray[0]];
if(world.get_loc(targetXLoc, targetYLoc)->region_id !=
world.get_loc(firstUnitPtr->next_x_loc(), firstUnitPtr->next_y_loc())->region_id)
{
Unit *unitPtr;
set_group_id(selectedUnitArray, selectedCount);
for(int i=0; iattack_town(targetXLoc, targetYLoc);
}
return;
}
//*********************** improve later end ***************************//
//----------- initialize local parameters ------------//
int targetXLoc2 = targetXLoc + STD_TOWN_LOC_WIDTH - 1; // the lower right corner of the firm
int targetYLoc2 = targetYLoc + STD_TOWN_LOC_HEIGHT - 1;
char *xOffsetPtr, *yOffsetPtr;
//---------------------------------------------------------------------//
// construct data structure
//---------------------------------------------------------------------//
int tempVar = sizeof(short)*selectedCount;
memset(dir_array_count, 0, sizeof(dir_array_count));
int count;
for(count=0; countmobile_type);
debug_result_check(analyseResult, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT);
err_when(analyseResult<0);
if(!analyseResult) // 0 if all surround location is not accessible
{
//------------------------------------------------------------//
// special handling for this case
//------------------------------------------------------------//
handle_attack_target_totally_blocked(targetXLoc, targetYLoc, townRecno, selectedUnitArray, selectedCount, 3);
for(count=0; count=surroundLoc)
{
destCount = 0;
xOffsetPtr = get_target_x_offset(STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, count);
yOffsetPtr = get_target_y_offset(STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, count);
xOffset = *xOffsetPtr;
yOffset = *yOffsetPtr;
}
else
{
xOffset = *(++xOffsetPtr);
yOffset = *(++yOffsetPtr);
}
if(!unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST])
break;
}
}
err_when(unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST]);
//------------------------------------------------------------//
// find the closest attacker
//------------------------------------------------------------//
err_when(unprocessed>2000 || unprocessed <0);
xLoc = targetXLoc + xOffset;
yLoc = targetYLoc + yOffset;
err_when(!world.get_loc(xLoc, yLoc)->can_move(unitPtr->mobile_type));
for(i=0, minDist=0x7FFFFFF; inext_x_loc());
yDist = abs(yLoc-unitPtr->next_y_loc());
dist = (xDist >= yDist) ? xDist*10+yDist : yDist*10+xDist;
if(dist < minDist)
{
minDist = dist;
unitPos = i;
}
}
unitPtr = (Unit*) get_ptr(curArrayPtr[unitPos]);
curArrayPtr[unitPos] = curArrayPtr[--unprocessed]; // move the units in the back to the front
err_when(unitPtr->action_mode2!=ACTION_ATTACK_WALL &&
unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0);
seek_path.set_status(PATH_WAIT);
err_when(seek_path.path_status==PATH_NODE_USED_UP);
unitPtr->attack_town(targetXLoc, targetYLoc, xOffset, yOffset);
//------------------------------------------------------------//
// set the flag if unreachable
//------------------------------------------------------------//
if(seek_path.path_status==PATH_NODE_USED_UP)
{
unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST] = 1;
analyseResult--;
debug_result_check(analyseResult, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT);
err_when(analyseResult<0);
//------------------------------------------------------------//
// the nearby location should also be unreachable
//------------------------------------------------------------//
check_nearby_location(targetXLoc, targetYLoc, xOffset, yOffset, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT,
unitPtr->mobile_type, analyseResult);
}
update_unreachable_table(targetXLoc, targetYLoc, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, unitPtr->mobile_type, analyseResult);
#ifdef DEBUG
Location *dlPtr;
for(int di=0; di=1 && di<=STD_TOWN_LOC_WIDTH && dj>=1 && dj<=STD_TOWN_LOC_HEIGHT)
continue;
int debugXLoc = targetXLoc+di-SHIFT_ADJUST;
int debugYLoc = targetYLoc+dj-SHIFT_ADJUST;
if(debugXLoc<0 || debugXLoc>=MAX_WORLD_X_LOC || debugYLoc<0 || debugYLoc>=MAX_WORLD_Y_LOC)
continue;
dlPtr = world.get_loc(debugXLoc, debugYLoc);
err_when(!dlPtr->can_move(unitPtr->mobile_type) && unreachable_table[di][dj]==0);
}
}
#endif
}
}
//---------------------------------------------------------------------//
// set the unreachable flag for each units
//---------------------------------------------------------------------//
//-************** codes here ***************-//
//---------------------------------------------------------------------//
// destruct data structure
//---------------------------------------------------------------------//
for(count=0; count targetXLoc - x location of the wall
// targetYLoc - y location of the wall
//
void UnitArray::attack_wall(int targetXLoc, int targetYLoc, short* selectedUnitArray, int selectedCount)
{
err_when(selectedCount<=0);
if(selectedCount==1)
{
Unit *unitPtr = (Unit*) get_ptr(selectedUnitArray[0]);
unitPtr->unit_group_id = unit_array.cur_group_id++;
unitPtr->attack_wall(targetXLoc, targetYLoc);
return;
}
//********************** improve later begin **************************//
//---------------------------------------------------------------------//
// codes for differnt territory or different mobile_type attacking should
// be added in the future.
//---------------------------------------------------------------------//
Unit *firstUnitPtr = unit_array[selectedUnitArray[0]];
if(world.get_loc(targetXLoc, targetYLoc)->region_id !=
world.get_loc(firstUnitPtr->next_x_loc(), firstUnitPtr->next_y_loc())->region_id)
{
Unit *unitPtr;
set_group_id(selectedUnitArray, selectedCount);
for(int i=0; iattack_wall(targetXLoc, targetYLoc);
}
return;
}
//*********************** improve later end ***************************//
//----------- initialize local parameters ------------//
char *xOffsetPtr, *yOffsetPtr;
//---------------------------------------------------------------------//
// construct data structure
//---------------------------------------------------------------------//
int tempVar = sizeof(short)*selectedCount;
memset(dir_array_count, 0, sizeof(dir_array_count));
int count;
for(count=0; countmobile_type);
debug_result_check(analyseResult, 1, 1);
err_when(analyseResult<0);
if(!analyseResult) // 0 if all surround location is not accessible
{
//------------------------------------------------------------//
// special handling for this case
//------------------------------------------------------------//
handle_attack_target_totally_blocked(targetXLoc, targetYLoc, 0, selectedUnitArray, selectedCount, 0);
for(count=0; count=surroundLoc)
{
destCount = 0;
xOffsetPtr = get_target_x_offset(1, 1, count);
yOffsetPtr = get_target_y_offset(1, 1, count);
xOffset = *xOffsetPtr;
yOffset = *yOffsetPtr;
}
else
{
xOffset = *(++xOffsetPtr);
yOffset = *(++yOffsetPtr);
}
if(!unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST])
break;
}
}
err_when(unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST]);
//------------------------------------------------------------//
// find the closest attacker
//------------------------------------------------------------//
err_when(unprocessed>2000 || unprocessed <0);
xLoc = targetXLoc + xOffset;
yLoc = targetYLoc + yOffset;
err_when(!world.get_loc(xLoc, yLoc)->can_move(unitPtr->mobile_type));
for(i=0, minDist=0x7FFFFFF; inext_x_loc());
yDist = abs(yLoc-unitPtr->next_y_loc());
dist = (xDist >= yDist) ? xDist*10+yDist : yDist*10+xDist;
if(dist < minDist)
{
minDist = dist;
unitPos = i;
}
}
unitPtr = (Unit*) get_ptr(curArrayPtr[unitPos]);
curArrayPtr[unitPos] = curArrayPtr[--unprocessed]; // move the units in the back to the front
err_when(unitPtr->action_mode2!=ACTION_ATTACK_WALL &&
unitPtr->cur_action==SPRITE_ATTACK && unitPtr->action_para==0);
seek_path.set_status(PATH_WAIT);
err_when(seek_path.path_status==PATH_NODE_USED_UP);
unitPtr->attack_wall(targetXLoc, targetYLoc, xOffset, yOffset);
//------------------------------------------------------------//
// set the flag if unreachable
//------------------------------------------------------------//
if(seek_path.path_status==PATH_NODE_USED_UP)
{
unreachable_table[xOffset+SHIFT_ADJUST][yOffset+SHIFT_ADJUST] = 1;
analyseResult--;
debug_result_check(analyseResult, 1, 1);
err_when(analyseResult<0);
//------------------------------------------------------------//
// the nearby location should also be unreachable
//------------------------------------------------------------//
check_nearby_location(targetXLoc, targetYLoc, xOffset, yOffset, 1, 1, unitPtr->mobile_type, analyseResult);
}
update_unreachable_table(targetXLoc, targetYLoc, 1, 1, unitPtr->mobile_type, analyseResult);
#ifdef DEBUG
for(int di=0; di<3; di++)
{
for(int dj=0; dj<3; dj++)
{
if(di==1 && dj==1)
continue;
int debugXLoc = targetXLoc+di-SHIFT_ADJUST;
int debugYLoc = targetYLoc+dj-SHIFT_ADJUST;
if(debugXLoc<0 || debugXLoc>=MAX_WORLD_X_LOC || debugYLoc<0 || debugYLoc>=MAX_WORLD_Y_LOC)
continue;
Location *dlPtr = world.get_loc(debugXLoc, debugYLoc);
err_when(!dlPtr->can_move(unitPtr->mobile_type) && unreachable_table[di][dj]==0);
}
}
#endif
}
}
//---------------------------------------------------------------------//
// set the unreachable flag for each units
//---------------------------------------------------------------------//
//-************** codes here ***************-//
//---------------------------------------------------------------------//
// destruct data structure
//---------------------------------------------------------------------//
for(count=0; count xLoc1 - top left x location of the target
// yLoc1 - top left y location of the target
// xLoc2 - bottom right x location of the target
// yLoc2 - bottom right y location of the target
// selectedUnitArray - recno. of selected units
// selectedCount - count of selected units
// unitGroupId - group id for the selected units
//
// targetType - 0 for wall, 1 for unit, 2 for firm, 3 for town
//
void UnitArray::arrange_units_in_group(int xLoc1, int yLoc1, int xLoc2, int yLoc2, short* selectedUnitArray,
int selectedCount, DWORD unitGroupId, int targetType)
{
Unit *unitPtr;
int curXLoc, curYLoc;
for(int i=0; iunit_group_id = unitGroupId; // set unit_group_id
err_when(unitPtr->cur_action==SPRITE_IDLE && (unitPtr->cur_x!=unitPtr->next_x || unitPtr->cur_y!=unitPtr->next_y));
if(unitPtr->cur_action==SPRITE_IDLE)
unitPtr->set_ready();
curXLoc = unitPtr->next_x_loc();
curYLoc = unitPtr->next_y_loc();
if(curXLoc>=xLoc1-1 && curXLoc<=xLoc2+1 && curYLoc>=yLoc1-1 && curYLoc<=yLoc2+1)
{
//------------- already in the target surrounding ----------------//
switch(targetType)
{
case 0: unitPtr->attack_wall(xLoc1, yLoc1);
break;
case 1: unitPtr->attack_unit(xLoc1, yLoc1);
break;
case 2: unitPtr->attack_firm(xLoc1, yLoc1);
break;
case 3: unitPtr->attack_town(xLoc1, yLoc1);
break;
}
continue;
}
//---- the attacker need to call searching to reach the target ----//
if(curXLoc < xLoc1)
{
if(curYLoc < yLoc1) // 8
dir_array_ptr[7][dir_array_count[7]++] = selectedUnitArray[i];
else if(curYLoc > yLoc2)// 2
dir_array_ptr[1][dir_array_count[1]++] = selectedUnitArray[i];
else // 1
dir_array_ptr[0][dir_array_count[0]++] = selectedUnitArray[i];
}
else if(curXLoc > xLoc2)
{
if(curYLoc < yLoc1) // 6
dir_array_ptr[5][dir_array_count[5]++] = selectedUnitArray[i];
else if(curYLoc > yLoc2)// 4
dir_array_ptr[3][dir_array_count[3]++] = selectedUnitArray[i];
else // 5
dir_array_ptr[4][dir_array_count[4]++] = selectedUnitArray[i];
}
else // curXLoc==targetXLoc2
{
if(curYLoc < yLoc1) // 7
dir_array_ptr[6][dir_array_count[6]++] = selectedUnitArray[i];
else if(curYLoc > yLoc2)// 3
dir_array_ptr[2][dir_array_count[2]++] = selectedUnitArray[i];
else // curXLoc==xLoc2 && curYLoc==yLoc2
{
// target is one of the selected unit, error
err_here();
}
}
}
}
//----------- End of function UnitArray::arrange_units_in_group -----------//
//--------- Begin of function UnitArray::analyse_surround_location ---------//
// return the number of accessible surrounding location of the target
//
// targetXLoc - target x location
// targetYLoc - target y location
// targetWidth - target width
// targetHeight - target height
// mobileType - target mobile type
//
int UnitArray::analyse_surround_location(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, char mobileType)
{
static char xIncreTable[4] = { 1, 0, -1, 0};
static char yIncreTable[4] = { 0, 1, 0, -1};
err_when(targetWidth<1 || targetWidth>4);
Location *locPtr;
int xLoc = targetXLoc-1;
int yLoc = targetYLoc-1;
int targetXLoc2 = targetXLoc + targetWidth - 1;
int targetYLoc2 = targetYLoc + targetHeight - 1;
int bound = 2*(targetWidth + targetHeight) + 4; // (x+2)*(y+2) - xy
int increCount=4, xIncre, yIncre, found=0;
err_when(targetWidth==3 && targetHeight==3 && bound!=16);
for(int i=0; i=MAX_WORLD_X_LOC || yLoc<0 || yLoc>=MAX_WORLD_Y_LOC)
unreachable_table[xLoc-targetXLoc+SHIFT_ADJUST][yLoc-targetYLoc+SHIFT_ADJUST] = 1;
else
{
locPtr = world.get_loc(xLoc, yLoc);
if(!locPtr->can_move(mobileType))
unreachable_table[xLoc-targetXLoc+SHIFT_ADJUST][yLoc-targetYLoc+SHIFT_ADJUST] = 1;
else
found++;
}
if((xLoc==targetXLoc-1 || xLoc==targetXLoc2+1) && (yLoc==targetYLoc-1 || yLoc==targetYLoc2+1)) // at the corner
{
if((++increCount)>=4)
increCount = 0;
xIncre = xIncreTable[increCount];
yIncre = yIncreTable[increCount];
}
xLoc += xIncre;
yLoc += yIncre;
}
return found;
}
//----------- End of function UnitArray::analyse_surround_location -----------//
//--------- Begin of function UnitArray::check_nearby_location ---------//
// check the target location to find out how many of its surrounding location
// is not blocked
//
// targetXLoc - target x location
// targetYLoc - target y location
// xOffset - x offset from target x location
// yOffset - y offset from target y location
// targetWidth - target width
// targetHeight - target height
// targetMobileType - target mobile type
// analyseResult - reference for returning
//
void UnitArray::check_nearby_location(int targetXLoc, int targetYLoc, char xOffset, char yOffset,
int targetWidth, int targetHeight, char targetMobileType, int& analyseResult)
{
#ifdef DEBUG
int backupAnalyseResult = analyseResult;
char debugUnreachableTable[MAX_UNIT_SURROUND_SIZE][MAX_UNIT_SURROUND_SIZE];
memcpy(debugUnreachableTable, unreachable_table, sizeof(char)*MAX_UNIT_SURROUND_SIZE*MAX_UNIT_SURROUND_SIZE);
#endif
debug_result_check(analyseResult, targetWidth, targetHeight);
static char leftXIncreTable[4] = { 1, 0, -1, 0};
static char leftYIncreTable[4] = { 0, 1, 0, -1};
static char rightXIncreTable[4] = { -1, 0, 1, 0};
static char rightYIncreTable[4] = { 0, 1, 0, -1};
err_when(targetWidth<1 || targetWidth>4);
Location *locPtr;
int targetXLoc2 = targetXLoc + targetWidth - 1;
int targetYLoc2 = targetYLoc + targetHeight - 1;
int bound = 2*(targetWidth + targetHeight) + 4; // (x+2)*(y+2) - xy
int leftXLoc ,leftYLoc, leftContinue=1;
int leftXIncre, leftYIncre, leftIncreCount;
int rightXLoc, rightYLoc, rightContinue=1;
int rightXIncre, rightYIncre, rightIncreCount=1;
//-------------------------------------------------------------------------------------//
// determine the initial situation
//-------------------------------------------------------------------------------------//
if((xOffset==-1 || xOffset==targetWidth) && (yOffset==-1 || yOffset==targetHeight)) // at the corner
{
if(xOffset==-1)
{
if(yOffset==-1) // upper left corner
{
leftXIncre = 1;
leftYIncre = 0;
leftIncreCount = 0;
rightXIncre = 0;
rightYIncre = 1;
rightIncreCount = 1;
}
else // lower left corner
{
leftXIncre = 0;
leftYIncre = -1;
leftIncreCount = 3;
rightXIncre = 1;
rightYIncre = 0;
rightIncreCount = 2;
}
}
else
{
if(yOffset==-1) // upper right corner
{
leftXIncre = 0;
leftYIncre = 1;
leftIncreCount = 1;
rightXIncre = -1;
rightYIncre = 0;
rightIncreCount = 0;
}
else // lower right corner
{
leftXIncre = -1;
leftYIncre = 0;
leftIncreCount = 2;
rightXIncre = 0;
rightYIncre = -1;
rightIncreCount = 3;
}
}
}
else // at the edge
{
if(xOffset==-1) // left edge
{
leftXIncre = 0;
leftYIncre = -1;
leftIncreCount = 3;
rightXIncre = 0;
rightYIncre = 1;
rightIncreCount = 1;
}
else if(xOffset==targetWidth) // right edge
{
leftXIncre = 0;
leftYIncre = 1;
leftIncreCount = 1;
rightXIncre = 0;
rightYIncre = -1;
rightIncreCount = 3;
}
else if(yOffset==-1) // upper edge
{
leftXIncre = 1;
leftYIncre = 0;
leftIncreCount = 0;
rightXIncre = -1;
rightYIncre = 0;
rightIncreCount = 0;
}
else if(yOffset==targetHeight) // lower edge
{
leftXIncre = -1;
leftYIncre = 0;
leftIncreCount = 2;
rightXIncre = 1;
rightYIncre = 0;
rightIncreCount = 2;
}
}
leftXLoc = rightXLoc = targetXLoc + xOffset;
leftYLoc = rightYLoc = targetYLoc + yOffset;
int canReach;
int outBoundary; // true if out of map boundary
//-------------------------------------------------------------------------------------//
// count the reachable location
//-------------------------------------------------------------------------------------//
for(int i=1; i=4)
leftIncreCount = 0;
leftXIncre = leftXIncreTable[leftIncreCount];
leftYIncre = leftYIncreTable[leftIncreCount];
}
if(leftXLoc>=0 && leftXLoc=0 && leftYLoccan_move(targetMobileType))
canReach = 1;
}
}
else
outBoundary = 1;
if(canReach)
leftContinue = 0;
else if(!outBoundary)
{
err_when(unreachable_table[leftXLoc-targetXLoc+SHIFT_ADJUST][leftYLoc-targetYLoc+SHIFT_ADJUST]);
unreachable_table[leftXLoc-targetXLoc+SHIFT_ADJUST][leftYLoc-targetYLoc+SHIFT_ADJUST] = 1;
analyseResult--;
debug_result_check(analyseResult, targetWidth, targetHeight);
err_when(analyseResult<0);
}
#ifdef DEBUG
else
err_when(!unreachable_table[leftXLoc-targetXLoc+SHIFT_ADJUST][leftYLoc-targetYLoc+SHIFT_ADJUST]);
#endif
i++;
}
//------------------------------------------------------------//
// process right hand side checking
//------------------------------------------------------------//
if(rightContinue)
{
canReach = 0;
outBoundary = 0;
rightXLoc += rightXIncre;
rightYLoc += rightYIncre;
if((rightXLoc==targetXLoc-1 || rightXLoc==targetXLoc2+1) && (rightYLoc==targetYLoc-1 || rightYLoc==targetYLoc2+1))
{
if((++rightIncreCount)>=4)
rightIncreCount = 0;
rightXIncre = rightXIncreTable[rightIncreCount];
rightYIncre = rightYIncreTable[rightIncreCount];
}
if(rightXLoc>=0 && rightXLoc=0 && rightYLoccan_move(targetMobileType))
canReach = 1;
}
}
else
outBoundary = 1;
if(canReach)
rightContinue = 0;
else if(!outBoundary)
{
err_when(unreachable_table[rightXLoc-targetXLoc+SHIFT_ADJUST][rightYLoc-targetYLoc+SHIFT_ADJUST]);
unreachable_table[rightXLoc-targetXLoc+SHIFT_ADJUST][rightYLoc-targetYLoc+SHIFT_ADJUST] = 1;
analyseResult--;
debug_result_check(analyseResult, targetWidth, targetHeight);
err_when(analyseResult<0);
}
#ifdef DEBUG
else
err_when(!unreachable_table[rightXLoc-targetXLoc+SHIFT_ADJUST][rightYLoc-targetYLoc+SHIFT_ADJUST]);
#endif
}
if(!leftContinue && !rightContinue)
break;
}
}
//----------- End of function UnitArray::check_nearby_location -----------//
//--------- Begin of function UnitArray::handle_attack_target_totally_blocked ---------//
// handle attacking while the target is totally blocked
//
// targetXLoc - target x loc
// targetYLoc - target y loc
// targetRecno - target recno
// selectedUnitArray - selected units' recno
// selectedCount - num of selected unit
// targetType - 0 for wall, 1 for unit, 2 for firm, 3 for town
//
void UnitArray::handle_attack_target_totally_blocked(int targetXLoc, int targetYLoc, short targetRecno,
short *selectedUnitArray, short selectedCount, int targetType)
{
if(unit_processed_count>0) // some units can reach the target surrounding
{
Unit *processedPtr, *unitPtr;
int proCount = unit_processed_count - 1;
int unproCount = selectedCount - proCount - 1; // number of unprocessed
int sCount = selectedCount-1;
int found, i, recno;
#ifdef DEBUG
int debugCount;
#endif
//------------------------------------------------------------------------------------//
// use the result of those processed units as a reference of those unprocessed units
//------------------------------------------------------------------------------------//
while(unproCount)
{
err_when(unit_array.is_deleted(unit_processed_array[proCount]));
processedPtr = (Unit*) get_ptr(unit_processed_array[proCount]);
#ifdef DEBUG
debugCount = 0;
#endif
err_when(sCount<0);
do
{
#ifdef DEBUG
debugCount++;
err_when(debugCount>1000);
#endif
found = 0;
recno = selectedUnitArray[sCount];
for(i=0; iselectedCount);
sCount--;
}while(found);
unitPtr = (Unit *) get_ptr(recno);
unitPtr->move_to(processedPtr->move_to_x_loc, processedPtr->move_to_y_loc);
switch(targetType)
{
case 0: // wall
unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_WALL;
err_when(targetRecno);
break;
case 1: // unit
unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_UNIT;
err_when(!targetRecno);
break;
case 2: // firm
unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_FIRM;
err_when(!targetRecno);
break;
case 3: // town
unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_TOWN;
err_when(!targetRecno);
break;
}
unitPtr->action_para = unitPtr->action_para2 = targetRecno;
unitPtr->action_x_loc = unitPtr->action_x_loc2 = targetXLoc;
unitPtr->action_y_loc = unitPtr->action_y_loc2 = targetYLoc;
proCount--;
if(proCount<0)
proCount = unit_processed_count - 1;
unproCount--;
}
}
else // none of the units reaches the target surrounding
{
//----------------------------------------------------------------//
// handle the case for 1x1 units now, no 2x2 units
//----------------------------------------------------------------//
//-*********** improve later ************-//
int unprocessed = selectedCount;
Unit *firstPtr = (Unit *) get_ptr(selectedUnitArray[unprocessed-1]);
switch(targetType)
{
case 0: firstPtr->attack_wall(targetXLoc, targetYLoc);
break;
case 1: firstPtr->attack_unit(targetXLoc, targetYLoc);
break;
case 2: firstPtr->attack_firm(targetXLoc, targetYLoc);
break;
case 3: firstPtr->attack_town(targetXLoc, targetYLoc);
break;
}
int moveToXLoc = firstPtr->move_to_x_loc;
int moveToYLoc = firstPtr->move_to_y_loc;
/*if(seek_path.path_status==PATH_NODE_USED_UP)
{
int debug = 0;
}*/
Unit *unitPtr;
while(unprocessed)
{
unitPtr = (Unit *) get_ptr(selectedUnitArray[unprocessed-1]);
unitPtr->move_to(moveToXLoc, moveToYLoc);
switch(targetType)
{
case 0: // wall
unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_WALL;
unitPtr->action_para = unitPtr->action_para2 = 0;
break;
case 1: // unit
unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_UNIT;
unitPtr->action_para = unitPtr->action_para2 = targetRecno;
break;
case 2: // firm
unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_FIRM;
unitPtr->action_para = unitPtr->action_para2 = targetRecno;
break;
case 3: // town
unitPtr->action_mode = unitPtr->action_mode2 = ACTION_ATTACK_TOWN;
unitPtr->action_para = unitPtr->action_para2 = targetRecno;
break;
}
unitPtr->action_x_loc = unitPtr->action_x_loc2 = targetXLoc;
unitPtr->action_y_loc = unitPtr->action_y_loc2 = targetYLoc;
unprocessed--;
}
}
}
//----------- End of function UnitArray::handle_attack_target_totally_blocked -----------//