/*
* 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 : OUNITAT3.CPP
//Description : Object Unit's decision making functions for attacking same or different type of target and reactivating
// idle unit that are ordered to attack
//Owner : Alex
#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
//--------- Begin of function Unit::move_try_to_range_attack ---------//
// return 1 if it is possible to reach a location to attack the target
// return 0 otherwise
//
// targetUnit - pointer to target unit
//
int Unit::move_try_to_range_attack(Unit* targetUnit)
{
int curXLoc = next_x_loc();
int curYLoc = next_y_loc();
int targetXLoc = targetUnit->next_x_loc();
int targetYLoc = targetUnit->next_y_loc();
if(world.get_loc(curXLoc, curYLoc)->region_id==world.get_loc(targetXLoc, targetYLoc)->region_id)
{
//------------ for same region id, search now ---------------//
if(search(targetXLoc, targetYLoc, 1, SEARCH_MODE_TO_ATTACK, action_para))
return 1;
else // search failure,
{
stop2(KEEP_DEFENSE_MODE);
return 0;
}
}
else
{
//--------------- different territory ------------------//
int targetWidth = targetUnit->sprite_info->loc_width;
int targetHeight = targetUnit->sprite_info->loc_height;
int maxRange = max_attack_range();
if(possible_place_for_range_attack(targetXLoc, targetYLoc, targetWidth, targetHeight, maxRange))
{
//---------------------------------------------------------------------------------//
// space is found, attack target now
//---------------------------------------------------------------------------------//
if(move_to_range_attack(targetXLoc, targetYLoc, targetUnit->sprite_id, SEARCH_MODE_ATTACK_UNIT_BY_RANGE, maxRange))
return 1;
else
{
stop2(KEEP_DEFENSE_MODE);
return 0;
}
return 1;
}
else
{
//---------------------------------------------------------------------------------//
// unable to find location to attack the target, stop or move to the target
//---------------------------------------------------------------------------------//
if(action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET &&
action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET)
move_to(targetXLoc, targetYLoc, 1); // abort attacking, just call move_to() instead
else
stop2(KEEP_DEFENSE_MODE);
return 0;
}
}
return 0;
}
//----------- End of function Unit::move_try_to_range_attack -----------//
//--------- Begin of function Unit::move_to_range_attack ---------//
// search and attack target
//
// targetXLoc - target x location
// targetYLoc - target y location
// miscNo - is sprite_id if target is a unit
// is firm_id if target is a firm
// is 0 if target is a town or a wall
// searchMode - search mode being used
// maxRange - max attack range of this unit
//
int Unit::move_to_range_attack(int targetXLoc, int targetYLoc, short miscNo, short searchMode, short maxRange)
{
//---------------------------------------------------------------------------------//
// part 1, searching
//---------------------------------------------------------------------------------//
seek_path.set_attack_range_para(maxRange);
search(targetXLoc, targetYLoc, 1, searchMode, miscNo);
seek_path.reset_attack_range_para();
//search(targetXLoc, targetYLoc, 1, searchMode, maxRange);
if(result_node_array==NULL || result_node_count==0)
return 0;
//---------------------------------------------------------------------------------//
// part 2, editing result path
//---------------------------------------------------------------------------------//
Location *locPtr = world.get_loc(next_x_loc(), next_y_loc());
err_when(!locPtr);
int regionId = locPtr->region_id; // the region_id this unit in
//----------------------------------------------------//
err_when(result_node_count<2);
ResultNode* editNode1 = result_node_array + result_node_count - 1;
ResultNode* editNode2 = editNode1-1;
int vecX = editNode1->node_x - editNode2->node_x;
int vecY = editNode1->node_y - editNode2->node_y;
if(vecX)
vecX = ((vecX>0) ? 1 : -1)*move_step_magn();
if(vecY)
vecY = ((vecY>0) ? 1 : -1)*move_step_magn();
int x = editNode1->node_x;
int y = editNode1->node_y;
int i, found=0, removedStep=0, preX, preY;
for(i=result_node_count; i>1; i--)
{
while(x!=editNode2->node_x || y!=editNode2->node_y)
{
locPtr = world.get_loc(x, y);
if(locPtr->region_id == regionId)
{
found = i;
preX = x;
preY = y;
break;
}
x -= vecX;
y -= vecY;
removedStep++;
}
if(found)
break;
editNode1 = editNode2;
editNode2--;
vecX = editNode1->node_x - editNode2->node_x;
vecY = editNode1->node_y - editNode2->node_y;
if(vecX)
vecX = ((vecX>0) ? 1 : -1)*move_step_magn();
if(vecY)
vecY = ((vecY>0) ? 1 : -1)*move_step_magn();
x = editNode1->node_x;
y = editNode1->node_y;
}
//---------------------------------------------------------------------------//
// update unit parameters
//---------------------------------------------------------------------------//
if(found)
{
result_node_count = found;
ResultNode* lastNode = result_node_array + result_node_count - 1;
int goX = go_x>>ZOOM_X_SHIFT_COUNT;
int goY = go_y>>ZOOM_Y_SHIFT_COUNT;
//---------------------------------------------------------------------//
// note: build?Loc-1, build?Loc+width, build?Loc+height may <0 or
// >MAX_WORLD_?_LOC. To prevent errors from occuring, goX, goY
// must not be outside the map boundary
//---------------------------------------------------------------------//
if(goX==editNode1->node_x && goY==editNode1->node_y)
{
go_x = preX*ZOOM_LOC_WIDTH;
go_y = preY*ZOOM_LOC_HEIGHT;
}
else if(result_node_count==2)
{
int magnCG = m.points_distance(cur_x, cur_y, go_x, go_y);
int magnNG = m.points_distance(next_x, next_y, go_x, go_y);
err_when(magnCG==0 && magnNG==0);
if(magnCG && magnNG)
{
//---------- lie on the same line -----------//
if( (go_x-cur_x)/magnCG==(go_x-next_x)/magnNG && (go_y-cur_y)/magnCG==(go_y-next_y)/magnNG )
{
go_x = preX*ZOOM_LOC_WIDTH;
go_y = preY*ZOOM_LOC_HEIGHT;
}
}
}
lastNode->node_x = preX;
lastNode->node_y = preY;
move_to_x_loc = lastNode->node_x;
move_to_y_loc = lastNode->node_y;
result_path_dist -= (removedStep)*move_step_magn();
err_when((cur_x!=next_x || cur_y!=next_y) && // is not blocked
(check_unit_dir1=get_dir(cur_x, cur_y, next_x, next_y))!=(check_unit_dir2=get_dir(cur_x, cur_y, go_x, go_y)));
}
return found;
}
//----------- End of function Unit::move_to_range_attack -----------//
//--------- Begin of function Unit::can_attack_different_type_target ---------//
// return 1 if able to use range_attack
// return 0 otherwise
//
int Unit::can_attack_different_target_type()
{
int maxRange = max_attack_range();
if(mobile_type==UNIT_LAND && !maxRange)
return 0; // unable to do range attack or cannot attack
if(maxRange>1)
return maxRange;
else
return 0;
}
//----------- End of function Unit::can_attack_different_type_target -----------//
//--------- Begin of function Unit::possible_place_for_range_attack ---------//
// check whether there is any place for this unit to attack the target
//
// targetXLoc - target x location
// targetYLoc - target y location
// targetWidth - target width
// targetHeight - target height
// maxRange - max attack range of this unit
//
// return 1 if place found
// return 0 otherwise
//
int Unit::possible_place_for_range_attack(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, int maxRange)
{
err_when(targetXLoc<0 || targetXLoc>=MAX_WORLD_X_LOC || targetYLoc<0 || targetYLoc>=MAX_WORLD_Y_LOC);
err_when(maxRange==0);
if(mobile_type==UNIT_AIR)
return 1; // air unit can reach any region
int curXLoc = next_x_loc();
int curYLoc = next_y_loc();
if(abs(curXLoc-targetXLoc)<=maxRange && abs(curYLoc-targetYLoc)<=maxRange) // inside the attack range
return 1;
//----------------- init parameters -----------------//
Location *locPtr = world.get_loc(curXLoc, curYLoc);
int regionId = locPtr->region_id;
int xLoc1 = max(targetXLoc-maxRange, 0);
int yLoc1 = max(targetYLoc-maxRange, 0);
int xLoc2 = min(targetXLoc+targetWidth-1+maxRange, MAX_WORLD_X_LOC-1);
int yLoc2 = min(targetYLoc+targetHeight-1+maxRange, MAX_WORLD_Y_LOC-1);
int checkXLoc, checkYLoc;
//--------- do adjustment for UNIT_SEA and UNIT_AIR ---------//
if(mobile_type!=UNIT_LAND)
{
if(xLoc1%2)
xLoc1++;
if(yLoc1%2)
yLoc1++;
if(xLoc2%2)
xLoc2--;
if(yLoc2%2)
yLoc2--;
}
//-------- checking for surrounding location ----------//
switch(mobile_type)
{
case UNIT_LAND:
for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++)
{
locPtr = world.get_loc(checkXLoc, yLoc1);
if(locPtr->region_id==regionId && locPtr->is_accessible(mobile_type))
return 1;
locPtr = world.get_loc(checkXLoc, yLoc2);
if(locPtr->region_id==regionId && locPtr->is_accessible(mobile_type))
return 1;
}
for(checkYLoc=yLoc1+1; checkYLocregion_id==regionId && locPtr->is_accessible(mobile_type))
return 1;
locPtr = world.get_loc(xLoc2, checkYLoc);
if(locPtr->region_id==regionId && locPtr->is_accessible(mobile_type))
return 1;
}
break;
case UNIT_SEA:
for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++)
{
if(checkXLoc%2==0 && yLoc1%2==0)
{
locPtr = world.get_loc(checkXLoc, yLoc1);
if(locPtr->region_id==regionId && locPtr->is_accessible(mobile_type))
return 1;
}
if(checkXLoc%2==0 && yLoc2%2==0)
{
locPtr = world.get_loc(checkXLoc, yLoc2);
if(locPtr->region_id==regionId && locPtr->is_accessible(mobile_type))
return 1;
}
}
for(checkYLoc=yLoc1+1; checkYLocregion_id==regionId && locPtr->is_accessible(mobile_type))
return 1;
}
if(xLoc2%2==0 && checkYLoc%2==0)
{
locPtr = world.get_loc(xLoc2, checkYLoc);
if(locPtr->region_id==regionId && locPtr->is_accessible(mobile_type))
return 1;
}
}
break;
case UNIT_AIR:
for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++)
{
if(checkXLoc%2==0 && yLoc1%2==0)
{
locPtr = world.get_loc(checkXLoc, yLoc1);
if(locPtr->is_accessible(mobile_type))
return 1;
}
if(checkXLoc%2==0 && yLoc2%2==0)
{
locPtr = world.get_loc(checkXLoc, yLoc2);
if(locPtr->is_accessible(mobile_type))
return 1;
}
}
for(checkYLoc=yLoc1+1; checkYLocis_accessible(mobile_type))
return 1;
}
if(xLoc2%2==0 && checkYLoc%2==0)
{
locPtr = world.get_loc(xLoc2, checkYLoc);
if(locPtr->is_accessible(mobile_type))
return 1;
}
}
break;
default: err_here();
break;
}
return 0;
}
//----------- End of function Unit::possible_place_for_range_attack -----------//
//=====================================================================================//
//--------- Begin of function Unit::space_for_attack ---------//
// check whether there is any place for the unit to attack target.
//
// targetXLoc - target x location
// targetYLoc - target y location
// targetMobileType - target mobile type
// targetWidth - target width
// targetHeight - target height
//
int Unit::space_for_attack(int targetXLoc, int targetYLoc, char targetMobileType, int targetWidth, int targetHeight)
{
if(mobile_type==UNIT_LAND && targetMobileType==UNIT_LAND)
return space_around_target(targetXLoc, targetYLoc, targetWidth, targetHeight);
if((mobile_type==UNIT_SEA && targetMobileType==UNIT_SEA) ||
(mobile_type==UNIT_AIR && targetMobileType==UNIT_AIR))
return space_around_target_ver2(targetXLoc, targetYLoc, targetWidth, targetHeight);
//-------------------------------------------------------------------------//
// mobile_type is differet from that of target unit
//-------------------------------------------------------------------------//
Location *locPtr = world.get_loc(next_x_loc(), next_y_loc());
if(mobile_type==UNIT_LAND && targetMobileType==UNIT_SEA &&
!can_attack_different_target_type() &&
ship_surr_has_free_land(targetXLoc, targetYLoc, locPtr->region_id))
return 1;
int maxRange = max_attack_range();
if(maxRange==1)
return 0;
if(free_space_for_range_attack(targetXLoc, targetYLoc, targetWidth, targetHeight, targetMobileType, maxRange))
return 1;
return 0;
}
//----------- End of function Unit::space_for_attack -----------//
//--------- Begin of function Unit::space_around_target ---------//
// check the surroundung location around a square, and the result is
// stored in the blocked_edge[] by bit
//
// squareXLoc - upper left x location of target
// squareYLoc - upper left y location of target
// width - target width
// height - target height
//
// return 1 if the surrounding location that can_move is not equal to
// the result in the blocked_edge stored previously.
// return 0 otherwise (i.e. all location situation is same as before)
//
int Unit::space_around_target(int squareXLoc, int squareYLoc, int width, int height)
{
err_when(width<=0 || height<=0);
// edge 1
// 1 1 4
// edge 2 2 x 4 edge 4
// 2 3 3
// edge3
Location *locPtr;
Unit *unitPtr;
char sum, locWeight;
int testXLoc, testYLoc, i, equal=1;
//------------------ top edge ---------------//
sum = 0;
if((testYLoc=squareYLoc-1) >= 0)
{
if(squareXLoc>=1) // have upper left corner
{
i=-1;
locWeight = 1;
}
else
{
i = 0;
locWeight = 2;
}
for(; ican_move(mobile_type))
sum ^= locWeight;
else if(locPtr->has_unit(mobile_type))
{
unitPtr = unit_array[locPtr->unit_recno(mobile_type)];
if(unitPtr->cur_action!=SPRITE_ATTACK)
sum ^= locWeight;
}
}
}
if(blocked_edge[0]!=sum)
{
blocked_edge[0] = sum;
equal = 0;
}
//----------------- left edge -----------------//
sum = 0;
if((testXLoc=squareXLoc-1) >= 0)
{
if(squareYLoc+height<=MAX_WORLD_Y_LOC-1) // have lower left corner
{
i = height;
locWeight = 1;
}
else
{
i = height - 1;
locWeight = 2;
}
for(; i>=0; i--, locWeight<<=1)
{
locPtr = world.get_loc(testXLoc, squareYLoc+i);
if(locPtr->can_move(mobile_type))
sum ^= locWeight;
else if(locPtr->has_unit(mobile_type))
{
unitPtr = unit_array[locPtr->unit_recno(mobile_type)];
if(unitPtr->cur_action!=SPRITE_ATTACK)
sum ^= locWeight;
}
}
}
if(blocked_edge[1]!=sum)
{
blocked_edge[1] = sum;
equal = 0;
}
//------------------- bottom edge ------------------//
sum = 0;
if((testYLoc=squareYLoc+height) <= MAX_WORLD_Y_LOC-1)
{
if(squareXLoc+width<=MAX_WORLD_X_LOC-1) // have lower right corner
{
i = width;
locWeight = 1;
}
else
{
i = width - 1;
locWeight = 2;
}
for(; i>=0; i--, locWeight<<=1)
{
locPtr = world.get_loc(squareXLoc+i, testYLoc);
if(locPtr->can_move(mobile_type))
sum ^= locWeight;
else if(locPtr->has_unit(mobile_type))
{
unitPtr = unit_array[locPtr->unit_recno(mobile_type)];
if(unitPtr->cur_action!=SPRITE_ATTACK)
sum ^= locWeight;
}
}
}
if(blocked_edge[2]!=sum)
{
blocked_edge[2] = sum;
equal = 0;
}
//---------------------- right edge ----------------------//
sum = 0;
if((testXLoc=squareXLoc+width) <= MAX_WORLD_X_LOC-1)
{
if(squareYLoc>=1) // have upper right corner
{
i = -1;
locWeight = 1;
}
else
{
i = 0;
locWeight = 2;
}
for(; ican_move(mobile_type))
sum ^= locWeight;
else if(locPtr->has_unit(mobile_type))
{
unitPtr = unit_array[locPtr->unit_recno(mobile_type)];
if(unitPtr->cur_action!=SPRITE_ATTACK)
sum ^= locWeight;
}
}
}
if(blocked_edge[3]!=sum)
{
blocked_edge[3] = sum;
equal = 0;
}
return !equal;
}
//----------- End of function Unit::space_around_target -----------//
//--------- Begin of function Unit::space_around_target_ver2 ---------//
// similar function as space_around_target()
// This version is for sea unit and air unit only
//
int Unit::space_around_target_ver2(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight)
{
err_when(targetWidth<=0 || targetHeight<=0);
Location *locPtr;
Unit *unitPtr;
char sum, locWeight;
int xLoc1, yLoc1, xLoc2, yLoc2;
int i, equal=1;
//int testXLoc, testYLoc,
xLoc1 = targetXLoc%2 ? targetXLoc-1 : targetXLoc-2;
yLoc1 = targetYLoc%2 ? targetYLoc-1 : targetYLoc-2;
xLoc2 = (targetXLoc+targetWidth-1)%2 ? targetXLoc+targetWidth : targetXLoc+targetWidth+1;
yLoc2 = (targetYLoc+targetHeight-1)%2 ? targetYLoc+targetHeight : targetYLoc+targetHeight+1;
//------------------------ top edge ------------------------//
sum = 0;
if(yLoc1>=0)
{
if(xLoc1>=0)
{
i = xLoc1;
locWeight = 1;
}
else
{
i = xLoc1 + 2;
err_when(i<0);
locWeight = 2;
}
for(; i<=xLoc2; i+=2, locWeight<<=1)
{
locPtr = world.get_loc(i, yLoc1);
if(locPtr->can_move(mobile_type))
sum ^= locWeight;
else if(locPtr->has_unit(mobile_type))
{
unitPtr = unit_array[locPtr->unit_recno(mobile_type)];
if(unitPtr->cur_action!=SPRITE_ATTACK)
sum ^= locWeight;
}
}
}
if(blocked_edge[0]!=sum)
{
blocked_edge[0] = sum;
equal = 0;
}
//---------------------- left edge -----------------------//
sum = 0;
if(xLoc1>=0)
{
if(yLoc2<=MAX_WORLD_Y_LOC-1)
{
i = yLoc2;
locWeight = 1;
}
else
{
i = yLoc2-2;
err_when(i>=MAX_WORLD_Y_LOC);
locWeight = 2;
}
for(; i>yLoc1; i-=2, locWeight<<=1)
{
locPtr = world.get_loc(xLoc1, i);
if(locPtr->can_move(mobile_type))
sum ^= locWeight;
else if(locPtr->has_unit(mobile_type))
{
unitPtr = unit_array[locPtr->unit_recno(mobile_type)];
if(unitPtr->cur_action!=SPRITE_ATTACK)
sum ^= locWeight;
}
}
}
if(blocked_edge[1]!=sum)
{
blocked_edge[1] = sum;
equal = 0;
}
//----------------------- bottom edge ---------------------------//
sum = 0;
if(yLoc2<=MAX_WORLD_Y_LOC-1)
{
if(xLoc2<=MAX_WORLD_X_LOC-1)
{
i = xLoc2;
locWeight = 1;
}
else
{
i = xLoc2-2;
err_when(i>=MAX_WORLD_X_LOC);
locWeight = 2;
}
for(; i>xLoc1; i-=2, locWeight<<=1)
{
locPtr = world.get_loc(i, yLoc2);
if(locPtr->can_move(mobile_type))
sum ^= locWeight;
else if(locPtr->has_unit(mobile_type))
{
unitPtr = unit_array[locPtr->unit_recno(mobile_type)];
if(unitPtr->cur_action!=SPRITE_ATTACK)
sum ^= locWeight;
}
}
}
if(blocked_edge[2]!=sum)
{
blocked_edge[2] = sum;
equal = 0;
}
//---------------------- right edge ------------------------//
sum = 0;
if(xLoc2<=MAX_WORLD_X_LOC-1)
{
if(yLoc1>=0)
{
i = yLoc1;
locWeight = 1;
}
else
{
i = yLoc1+2;
err_when(i<0);
locWeight = 2;
}
for(; ican_move(mobile_type))
sum ^= locWeight;
else if(locPtr->has_unit(mobile_type))
{
unitPtr = unit_array[locPtr->unit_recno(mobile_type)];
if(unitPtr->cur_action!=SPRITE_ATTACK)
sum ^= locWeight;
}
}
}
if(blocked_edge[3]!=sum)
{
blocked_edge[3] = sum;
equal = 0;
}
return !equal;
}
//----------- End of function Unit::space_around_target_ver2 -----------//
//--------- Begin of function Unit::ship_surr_has_free_land ---------//
// check surrounding place for close attack by land units
//
// targetXLoc - target x loc
// targetYLoc - target y loc
// regionId - region id
//
// return 1 if there is space for the land unit to move to ship surrounding for close attack
// return 0 otherwise
//
int Unit::ship_surr_has_free_land(int targetXLoc, int targetYLoc, UCHAR regionId)
{
err_when(mobile_type!=UNIT_LAND);
Location *locPtr;
int xShift, yShift, checkXLoc, checkYLoc;
for(int i=2; i<9; i++)
{
m.cal_move_around_a_point(i, 3, 3, xShift, yShift);
checkXLoc = targetXLoc+xShift;
checkYLoc = targetYLoc+yShift;
if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
continue;
locPtr = world.get_loc(checkXLoc, checkYLoc);
if(locPtr->region_id==regionId && locPtr->can_move(mobile_type))
return 1;
}
return 0;
}
//----------- End of function Unit::ship_surr_has_free_land -----------//
//--------- Begin of function Unit::free_space_for_range_attack ---------//
// similar to possible_place_for_range_attack() but checking can_move() rather than is_accessible()
//
int Unit::free_space_for_range_attack(int targetXLoc, int targetYLoc, int targetWidth, int targetHeight, int targetMobileType, int maxRange)
{
err_when(targetXLoc<0 || targetXLoc>=MAX_WORLD_X_LOC || targetYLoc<0 || targetYLoc>=MAX_WORLD_Y_LOC);
err_when(maxRange==0);
//if(mobile_type==UNIT_AIR)
// return 1; // air unit can reach any region
int curXLoc = next_x_loc();
int curYLoc = next_y_loc();
if(abs(curXLoc-targetXLoc)<=maxRange && abs(curYLoc-targetYLoc)<=maxRange) // inside the attack range
return 1;
Location *locPtr = world.get_loc(curXLoc, curYLoc);
int regionId = locPtr->region_id;
int xLoc1 = max(targetXLoc-maxRange, 0);
int yLoc1 = max(targetYLoc-maxRange, 0);
int xLoc2 = min(targetXLoc+targetWidth-1+maxRange, MAX_WORLD_X_LOC-1);
int yLoc2 = min(targetYLoc+targetHeight-1+maxRange, MAX_WORLD_Y_LOC-1);
int checkXLoc, checkYLoc;
//--------- do adjustment for UNIT_SEA and UNIT_AIR ---------//
if(mobile_type!=UNIT_LAND)
{
if(xLoc1%2)
xLoc1++;
if(yLoc1%2)
yLoc1++;
if(xLoc2%2)
xLoc2--;
if(yLoc2%2)
yLoc2--;
}
//-------- checking for surrounding location ----------//
switch(mobile_type)
{
case UNIT_LAND:
for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++)
{
locPtr = world.get_loc(checkXLoc, yLoc1);
if(locPtr->region_id==regionId && locPtr->can_move(mobile_type))
return 1;
locPtr = world.get_loc(checkXLoc, yLoc2);
if(locPtr->region_id==regionId && locPtr->can_move(mobile_type))
return 1;
}
for(checkYLoc=yLoc1+1; checkYLocregion_id==regionId && locPtr->can_move(mobile_type))
return 1;
locPtr = world.get_loc(xLoc2, checkYLoc);
if(locPtr->region_id==regionId && locPtr->can_move(mobile_type))
return 1;
}
break;
case UNIT_SEA:
for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++)
{
if(checkXLoc%2==0 && yLoc1%2==0)
{
locPtr = world.get_loc(checkXLoc, yLoc1);
if(locPtr->region_id==regionId && locPtr->can_move(mobile_type))
return 1;
}
if(checkXLoc%2==0 && yLoc2%2==0)
{
locPtr = world.get_loc(checkXLoc, yLoc2);
if(locPtr->region_id==regionId && locPtr->can_move(mobile_type))
return 1;
}
}
for(checkYLoc=yLoc1+1; checkYLocregion_id==regionId && locPtr->can_move(mobile_type))
return 1;
}
if(xLoc2%2==0 && checkYLoc%2==0)
{
locPtr = world.get_loc(xLoc2, checkYLoc);
if(locPtr->region_id==regionId && locPtr->can_move(mobile_type))
return 1;
}
}
break;
case UNIT_AIR:
for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++)
{
if(checkXLoc%2==0 && yLoc1%2==0)
{
locPtr = world.get_loc(checkXLoc, yLoc1);
if(locPtr->can_move(mobile_type))
return 1;
}
if(checkXLoc%2==0 && yLoc2%2==0)
{
locPtr = world.get_loc(checkXLoc, yLoc2);
if(locPtr->can_move(mobile_type))
return 1;
}
}
for(checkYLoc=yLoc1+1; checkYLoccan_move(mobile_type))
return 1;
}
if(xLoc2%2==0 && checkYLoc%2==0)
{
locPtr = world.get_loc(xLoc2, checkYLoc);
if(locPtr->can_move(mobile_type))
return 1;
}
}
break;
default: err_here();
break;
}
return 0;
}
//----------- End of function Unit::free_space_for_range_attack -----------//