/*
* 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 : OUNITI.CPP
//Description : Object Unit idle processing
//Owner : Alex
#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
//-------------- define static variables -----------//
static char idle_detect_has_unit;
static char idle_detect_has_firm;
static char idle_detect_has_town;
static char idle_detect_has_wall;
static short idle_detect_target_unit_recno;
static short idle_detect_target_firm_recno;
static short idle_detect_target_town_recno;
static short idle_detect_target_wall_x1;
static short idle_detect_target_wall_y1;
static int idle_detect_default_mode;
static int help_mode;
static short help_attack_target_recno;
//--------- Begin of function Unit::process_idle ---------//
// process actions for idle units
//
void Unit::process_idle()
{
err_when(result_path_dist || result_node_array);
//---- if the unit is defending the town ----//
switch( unit_mode )
{
case UNIT_MODE_REBEL:
if(action_mode2==ACTION_STOP)
{
process_rebel(); // redirect to process_rebel for rebel units
return;
}
break;
case UNIT_MODE_MONSTER:
if(action_mode2==ACTION_STOP)
{
if(unit_mode_para)
{
if(!firm_array.is_deleted(unit_mode_para))
{
//-------- return to monster firm -----------//
FirmMonster *monsterFirmPtr = (FirmMonster*) firm_array[unit_mode_para];
assign(monsterFirmPtr->loc_x1, monsterFirmPtr->loc_y1);
return;
}
else
unit_mode_para = 0;
}
}
break;
}
//------------- process way point ------------//
if(action_mode==ACTION_STOP && action_mode2==ACTION_STOP && way_point_count)
{
err_when(way_point_count < 0);
if(way_point_count==1)
reset_way_point_array();
else
process_way_point();
return;
}
//-------- randomize direction --------//
err_when(result_node_array!=NULL);
//-------------------------------------------------------//
// when the unit is idle, the following should be always true
// move_to_x_loc == next_x_loc()
// move_to_y_loc == next_y_loc()
//-------------------------------------------------------//
err_when(move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc());
//move_to_x_loc = next_x_loc(); //***************BUGHERE
//move_to_y_loc = next_y_loc();
err_when(next_x!=cur_x || next_y!=cur_y);
if(match_dir())
{
if(!is_guarding() && race_id ) // only these units can move
{
if(!m.random(150)) // change direction randomly
set_dir(m.random(8));
}
}
else
return;
err_when(turn_delay);
//------- call Sprite::process_idle() -------//
Sprite::process_idle();
//-*********************** simulate ship movment ***************************-//
/*if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP)
{
unit_group_id = 1;
if(cur_action==SPRITE_IDLE)
{
if(m.random(50))
return;
}
else if(cur_action!=SPRITE_READY_TO_MOVE)
{
if(m.random(30)==0)
return;
}
int xOffset = m.random(30)*(m.random(2) ? 1 : -1);
int yOffset = m.random(30)*(m.random(2) ? 1 : -1);
int curXLoc = next_x_loc();
int curYLoc = next_y_loc();
int destXLoc = curXLoc+xOffset;
int destYLoc = curYLoc+yOffset;
if(destXLoc<0) destXLoc = 0;
else if(destXLoc>=MAX_WORLD_X_LOC) destXLoc = MAX_WORLD_X_LOC-1;
if(destYLoc<0) destYLoc = 0;
else if(destYLoc>=MAX_WORLD_Y_LOC) destYLoc = MAX_WORLD_Y_LOC-1;
Location *locPtr = world.get_loc(destXLoc, destYLoc);
int tempX, tempY;
if(terrain_res[locPtr->terrain_id]->average_type==TERRAIN_OCEAN)
move_to(destXLoc, destYLoc);
else
ship_to_beach(destXLoc, destYLoc, tempX, tempY);
Nation *nationPtr = nation_array[nation_recno];
if(nationPtr->cash<5000)
nationPtr->cash += 10000;
if(nationPtr->food<5000)
nationPtr->food += 10000;
if(hit_points=ACTION_ATTACK_UNIT && action_mode<=ACTION_ATTACK_WALL)
{
if(unit_array.idle_blocked_unit_reset_count && *(long*)blocked_edge)
{
unit_array.idle_blocked_unit_reset_count = 0;
memset(blocked_edge, 0, sizeof(char)*4);
err_when(blocked_edge[0] || blocked_edge[1] || blocked_edge[2] || blocked_edge[3]);
}
}
err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
//--------- reactivate action -----------//
if(reactivate_idle_action())
{
err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
return; // true if an action is reactivated
}
//-**************** simulate aat ********************-//
#ifdef DEBUG
if(debug_sim_game_type==2)
{
//int curXLoc = next_x_loc();
//int curYLoc = next_y_loc();
//int destXLoc, destYLoc;
if(m.random(30))
move_to(m.random(MAX_WORLD_X_LOC), m.random(MAX_WORLD_Y_LOC));
Nation *nationPtr = nation_array[nation_recno];
if(nationPtr->cash<2000)
nationPtr->cash += 8000;
if(nationPtr->food<2000)
nationPtr->food += 8000;
return;
}
#endif
//-**************** simulate aat ********************-//
err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
//----------- for ai unit idle -----------//
if( action_mode != ACTION_STOP || action_mode2 != ACTION_STOP ) // only detect attack when the unit is really idle
return;
if( !can_attack() )
return; // cannot attack
err_when(!can_attack());
err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
//--- only detect attack if in aggressive mode or the unit is a monster ---//
UnitInfo* unitInfo = unit_res[unit_id];
if( unitInfo->unit_class == UNIT_CLASS_MONSTER || aggressive_mode )
{
//----------- detect target to attack -----------//
if( idle_detect_attack() )
{
err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
return; // target detected
}
err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
}
//------------------------------------------------------------------//
// wander around for monster
//------------------------------------------------------------------//
if( unitInfo->unit_class == UNIT_CLASS_MONSTER )
{
if(m.random(500)==0)
{
#define WANDER_DIST 20
int xOffset = m.random(WANDER_DIST)-WANDER_DIST/2;
int yOffset = m.random(WANDER_DIST)-WANDER_DIST/2;
int destX = next_x_loc()+xOffset;
int destY = next_y_loc()+yOffset;
if(destX<0) destX = 0;
else if(destX>=MAX_WORLD_X_LOC) destX = MAX_WORLD_X_LOC-1;
if(destY<0) destY = 0;
else if(destY>=MAX_WORLD_Y_LOC) destY = MAX_WORLD_Y_LOC-1;
move_to(destX, destY);
}
}
}
//----------- End of function Unit::process_idle -----------//
//--------- Begin of function Unit::reactivate_idle_action --------//
// resume actions for idle units
//
// return 1 if an action is reactivated
// return 0 otherwise
//
int Unit::reactivate_idle_action()
{
if(action_mode2==ACTION_STOP)
return 0; // return for no idle action
if(!is_dir_correct())
return 1; // cheating for turning the direction
//------------------- declare parameters ----------------------//
Location *locPtr;
Firm *firmPtr;
FirmInfo *firmInfo;
Unit *unitPtr;
UnitMarine *shipPtr;
SpriteInfo *spriteInfo;
int canMove = 1;
int returnFlag = 0;
int curXLoc = move_to_x_loc;
int curYLoc = move_to_y_loc;
int dummyX, dummyY;
int hasSearch = 0;
int validSearch = seek_path.is_valid_searching();
seek_path.set_status(PATH_WAIT);
err_when(seek_path.path_status==PATH_NODE_USED_UP);
switch(action_mode2)
{
case ACTION_STOP:
case ACTION_DIE:
return 0; // do nothing
case ACTION_ATTACK_UNIT:
if(unit_array.is_deleted(action_para2))
stop2();
else
{
unitPtr = unit_array[action_para2];
spriteInfo = unitPtr->sprite_info;
if(space_for_attack(action_x_loc2, action_y_loc2, unitPtr->mobile_type, spriteInfo->loc_width, spriteInfo->loc_height))
{
//------ there should be place for this unit to attack the target, attempts to attack it ------//
attack_unit(action_para2, 0, 0, 0); // last 0 for not reset blocked_edge
hasSearch++;
returnFlag = 1;
break;
}
}
break;
case ACTION_ATTACK_FIRM:
locPtr = world.get_loc(action_x_loc2, action_y_loc2);
if(!locPtr->is_firm())
stop2(); // stop since target is already destroyed
else
{
firmPtr = firm_array[action_para2];
firmInfo = firm_res[firmPtr->firm_id];
if(space_for_attack(action_x_loc2, action_y_loc2, UNIT_LAND, firmInfo->loc_width, firmInfo->loc_height))
{
//-------- attack target since space is found for this unit to move to ---------//
attack_firm(action_x_loc2, action_y_loc2, 0, 0, 0); // last 0 for not reset blocked_edge
hasSearch++;
returnFlag = 1;
break;
}
}
break;
case ACTION_ATTACK_TOWN:
locPtr = world.get_loc(action_x_loc2, action_y_loc2);
if(!locPtr->is_town())
stop2(); // stop since target is deleted
else if(space_for_attack(action_x_loc2, action_y_loc2, UNIT_LAND, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
{
//---------- attack target --------//
attack_town(action_x_loc2, action_y_loc2, 0, 0, 0); // last 0 for not reset blocked_edge
hasSearch++;
returnFlag = 1;
break;
}
break;
case ACTION_ATTACK_WALL:
locPtr = world.get_loc(action_x_loc2, action_y_loc2);
if(!locPtr->is_wall())
stop2(); // stop since target doesn't exist
else if(space_for_attack(action_x_loc2, action_y_loc2, UNIT_LAND, 1, 1))
{
//----------- attack target -----------//
attack_wall(action_x_loc2, action_y_loc2, 0, 0, 0); // last 0 for not reset blocked_edge
hasSearch++;
returnFlag = 1;
break;
}
break;
case ACTION_ASSIGN_TO_FIRM:
case ACTION_ASSIGN_TO_TOWN:
case ACTION_ASSIGN_TO_VEHICLE:
//---------- resume assign actions -------------//
err_when(action_x_loc2==-1 || action_y_loc2==-1 || !action_para2);
assign(action_x_loc2, action_y_loc2);
hasSearch++;
waiting_term = 0;
returnFlag = 1;
break;
case ACTION_ASSIGN_TO_SHIP:
//------------ try to assign to marine ------------//
err_when(action_x_loc2==-1 || action_y_loc2==-1 || !action_para2);
assign_to_ship(action_x_loc2, action_y_loc2, action_para2);
hasSearch++;
waiting_term = 0;
returnFlag = 1;
break;
case ACTION_BUILD_FIRM:
//-------------- build again ----------------//
err_when(action_x_loc2==-1 || action_y_loc2==-1 || !action_para2);
build_firm(action_x_loc2, action_y_loc2, action_para2, COMMAND_AUTO);
hasSearch++;
waiting_term = 0;
returnFlag = 1;
break;
case ACTION_SETTLE:
//------------- try again to settle -----------//
err_when(action_x_loc2==-1 || action_y_loc2==-1 || action_para2);
settle(action_x_loc2, action_y_loc2);
hasSearch++;
waiting_term = 0;
returnFlag = 1;
break;
case ACTION_BURN:
//---------------- resume burn action -----------------//
err_when(action_x_loc2==-1 || action_y_loc2==-1 || action_para2);
burn(action_x_loc2, action_y_loc2, COMMAND_AUTO);
hasSearch++;
waiting_term = 0;
returnFlag = 1;
break;
case ACTION_MOVE:
//if(!avail_node_enough_for_search())
//{
// returnFlag = 1;
// break;
//}
if(move_to_x_loc!=action_x_loc2 || move_to_y_loc!=action_y_loc2)
{
//------- move since the unit has not reached its destination --------//
move_to(action_x_loc2, action_y_loc2, 1);
hasSearch++;
returnFlag = 1;
break;
}
waiting_term = 0;
break;
case ACTION_AUTO_DEFENSE_ATTACK_TARGET:
if(unit_search_node_used<500) // limit the no. of nods to reactivate idle process
{
//---------- resume action -----------//
process_auto_defense_attack_target();
hasSearch++;
}
returnFlag = 1;
break;
case ACTION_AUTO_DEFENSE_DETECT_TARGET:
process_auto_defense_detect_target();
returnFlag = 1;
break;
case ACTION_AUTO_DEFENSE_BACK_CAMP:
process_auto_defense_back_camp();
hasSearch++;
returnFlag = 1;
break;
case ACTION_DEFEND_TOWN_ATTACK_TARGET:
process_defend_town_attack_target();
hasSearch++;
returnFlag = 1;
break;
case ACTION_DEFEND_TOWN_DETECT_TARGET:
process_defend_town_detect_target();
returnFlag = 1;
break;
case ACTION_DEFEND_TOWN_BACK_TOWN:
process_defend_town_back_town();
hasSearch++;
returnFlag = 1;
break;
case ACTION_MONSTER_DEFEND_ATTACK_TARGET:
process_monster_defend_attack_target();
hasSearch++;
returnFlag = 1;
break;
case ACTION_MONSTER_DEFEND_DETECT_TARGET:
process_monster_defend_detect_target();
returnFlag = 1;
break;
case ACTION_MONSTER_DEFEND_BACK_FIRM:
process_monster_defend_back_firm();
hasSearch++;
returnFlag = 1;
break;
case ACTION_SHIP_TO_BEACH:
shipPtr = (UnitMarine*) this;
if(!shipPtr->in_beach || shipPtr->extra_move_in_beach==EXTRA_MOVE_FINISH)
{
//----------- the ship has not reached inlet, so move again --------------//
ship_to_beach(action_x_loc2, action_y_loc2, dummyX, dummyY);
hasSearch++;
}
returnFlag = 1;
break;
case ACTION_GO_CAST_POWER:
go_cast_power(action_x_loc2, action_y_loc2, ((UnitGod*)this)->cast_power_type, COMMAND_AUTO);
returnFlag = 1;
break;
default: err_here();
break;
}
if(validSearch && hasSearch && seek_path.path_status==PATH_NODE_USED_UP &&
next_x_loc()==move_to_x_loc && next_y_loc()==move_to_y_loc)
{
//-------------------------------------------------------------------------//
// abort actions since the unit trys to move and move no more.
//-------------------------------------------------------------------------//
stop2(KEEP_DEFENSE_MODE);
return 1;
}
int abort=0;
if(returnFlag)
{
if(curXLoc==move_to_x_loc && curYLoc==move_to_y_loc && seek_path.path_status==PATH_NODE_USED_UP)
{
//---------------------------------------------------------------------------------//
// insufficient nodes for searching
//---------------------------------------------------------------------------------//
if(action_mode2==ACTION_ASSIGN_TO_SHIP || action_mode2==ACTION_SHIP_TO_BEACH || in_any_defense_mode())
return 1;
//------- number of nodes is not enough to find the destination -------//
if(action_misc!=ACTION_MISC_STOP)
{
if(action_misc==ACTION_MISC_PRE_SEARCH_NODE_USED_UP)
{
if(action_misc_para<20)
{
action_misc_para++;
return 0;
}
else
action_misc_para++;
}
abort++; // assume destination unreachable, abort action
}
else
{
action_misc = ACTION_MISC_PRE_SEARCH_NODE_USED_UP;
action_misc_para = 0;
}
}
else // action resumed, return true
return 1;
}
if(!returnFlag || abort)
{
stop2(KEEP_DEFENSE_MODE);
}
return 0;
}
//----------- End of function Unit::reactivate_idle_action -----------//
//--------- Begin of function Unit::idle_detect_attack --------//
// detect target for idle units
//
// [int] startLoc - (default = 0), used to select region of the square
// for checking
// [int] dimensionInput - (default = 0), the detected size is calculated as
// 2*dimensionInput+1. this unit is located in
// the center of the square.
// [char] defenseMode - true for defensive mode on.
//
// return 1 if any target is detected
// return 0 otherwise
//
int Unit::idle_detect_attack(int startLoc, int dimensionInput, char defenseMode)
{
err_when(attack_count==0);
//---------------------------------------------------//
// Set detectDelay.
//
// The larger its value, the less CPU time it will takes,
// but it will also take longer to detect enemies.
//---------------------------------------------------//
int detectDelay = 1+unit_array.packed_size()/10;
Location *locPtr;
Unit *unitPtr;
//Unit *unitPtr, *targetUnitPtr;
//Firm *firmPtr, *targetFirmPtr;
//Town *townPtr, *targetTownPtr;
//int targetWallXLoc, targetWallYLoc;
//char hasUnit=0, hasFirm=0, hasTown=0, hasWall=0;
char targetMobileType;
int dimension, countLimit;
short targetRecno, i;
int xOffset, yOffset, checkXLoc, checkYLoc;
idle_detect_default_mode = (!startLoc && !dimensionInput && !defenseMode); //----- true when all zero
idle_detect_has_unit = idle_detect_has_firm = idle_detect_has_town = idle_detect_has_wall = 0;
help_mode = HELP_NOTHING;
err_when(idle_detect_default_mode!=0 && idle_detect_default_mode!=1);
//-----------------------------------------------------------------------------------------------//
// adjust waiting_term for default_mode
//-----------------------------------------------------------------------------------------------//
int lowestBit = (++waiting_term)%detectDelay;
if(action_mode2==ACTION_STOP)
{
err_when(action_mode!=ACTION_STOP);
waiting_term = lowestBit;
}
(dimension = (dimensionInput ? dimensionInput : ATTACK_DETECT_DISTANCE)<<1)++;
countLimit = dimension*dimension;
i = startLoc ? startLoc : 1+lowestBit;
int incAmount = (idle_detect_default_mode) ? detectDelay : 1;
//-----------------------------------------------------------------------------------------------//
// check the location around the unit
//
// The priority to choose target is (value of targetType)
// 1) Unit, 2) firm, 3) wall
//-----------------------------------------------------------------------------------------------//
err_when(defenseMode && action_mode2!=ACTION_AUTO_DEFENSE_DETECT_TARGET &&
action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET && action_mode2!=ACTION_MONSTER_DEFEND_DETECT_TARGET);
err_when(incAmount<1 || incAmount>100000);
for(; i<=countLimit; i+=incAmount) // 1 is the self location
{
m.cal_move_around_a_point(i, dimension, dimension, xOffset, yOffset);
checkXLoc = move_to_x_loc+xOffset;
checkYLoc = move_to_y_loc+yOffset;
if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
continue;
//------------------ verify location ---------------//
locPtr = world.get_loc(checkXLoc, checkYLoc);
if(defenseMode && action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET)
{
if(action_mode2==ACTION_AUTO_DEFENSE_DETECT_TARGET)
if(locPtr->power_nation_recno!=nation_recno && locPtr->power_nation_recno)
continue; // skip this location because it is not neutral nation or our nation
}
//----------------------------------------------------------------------------//
// checking the target type
//----------------------------------------------------------------------------//
if((targetMobileType=locPtr->has_any_unit(i==1 ? mobile_type : UNIT_LAND)) &&
(targetRecno=locPtr->unit_recno(targetMobileType)) && !unit_array.is_deleted(targetRecno))
{
//=================== is unit ======================//
if(idle_detect_has_unit || (action_para==targetRecno && action_mode==ACTION_ATTACK_UNIT &&
checkXLoc==action_x_loc && checkYLoc==action_y_loc))
continue; // same target as before
unitPtr = unit_array[targetRecno];
if(nation_recno && unitPtr->nation_recno==nation_recno && help_mode!=HELP_ATTACK_UNIT)
idle_detect_helper_attack(targetRecno); // help our troop
else if((help_mode==HELP_ATTACK_UNIT && help_attack_target_recno==targetRecno) ||
(unitPtr->nation_recno!=nation_recno && idle_detect_unit_checking(targetRecno)))
{
idle_detect_target_unit_recno = targetRecno;
idle_detect_has_unit++;
break; // break with highest priority
}
}
else if(locPtr->is_firm() && (targetRecno = locPtr->firm_recno()))
{
//=============== is firm ===============//
if(idle_detect_has_firm || (action_para==targetRecno && action_mode==ACTION_ATTACK_FIRM &&
action_x_loc==checkXLoc && action_y_loc==checkYLoc))
continue; // same target as before
if(idle_detect_firm_checking(targetRecno))
{
idle_detect_target_firm_recno = targetRecno;
idle_detect_has_firm++;
}
}
/*else if(locPtr->is_town() && (targetRecno = locPtr->town_recno()))
{
//=============== is town ===========//
if(idle_detect_has_town || (action_para==targetRecno && action_mode==ACTION_ATTACK_TOWN &&
action_x_loc==checkXLoc && action_y_loc==checkYLoc))
continue; // same target as before
if(idle_detect_town_checking(targetRecno))
{
idle_detect_target_town_recno = targetRecno;
idle_detect_has_town++;
}
}
else if(locPtr->is_wall())
{
//================ is wall ==============//
if(idle_detect_has_wall || (action_mode==ACTION_ATTACK_WALL && action_para==targetRecno &&
action_x_loc==checkXLoc && action_y_loc==checkYLoc))
continue; // same target as before
if(idle_detect_wall_checking(checkXLoc, checkYLoc))
{
idle_detect_target_wall_x1 = checkXLoc;
idle_detect_target_wall_y1 = checkYLoc;
idle_detect_has_wall++;
}
}*/
//if(hasUnit && hasFirm && hasTown && hasWall)
//if(hasUnit && hasFirm && hasWall)
// break; // there is target for attacking
}
return idle_detect_choose_target(defenseMode);
}
//----------- End of function Unit::idle_detect_attack -----------//
//--------- Begin of function Unit::idle_detect_unit_checking --------//
// check whether to attack the unit with recno = targetRecno
//
// targetRecno - recno of unit being checked
//
// return 1 if situation is suitable for attacking
// return 0 otherwise
//
int Unit::idle_detect_unit_checking(short targetRecno)
{
Unit *targetUnitPtr = unit_array[targetRecno];
if(targetUnitPtr->unit_id == UNIT_CARAVAN)
return 0;
//###### trevor 15/10 #######//
//-------------------------------------------//
// If the target is moving, don't attack it.
// Only attack when the unit stands still or
// is attacking.
//-------------------------------------------//
if( targetUnitPtr->cur_action != SPRITE_ATTACK &&
targetUnitPtr->cur_action != SPRITE_IDLE )
{
return 0;
}
//-------------------------------------------//
// If the target is a spy of our own and the
// notification flag is set to 0, then don't
// attack.
//-------------------------------------------//
if( targetUnitPtr->spy_recno ) // if the target unit is our spy, don't attack
{
Spy* spyPtr = spy_array[targetUnitPtr->spy_recno];
if( spyPtr->true_nation_recno == nation_recno &&
spyPtr->notify_cloaked_nation_flag == 0 )
{
return 0;
}
}
if( spy_recno ) // if this unit is our spy, don't attack own units
{
Spy* spyPtr = spy_array[spy_recno];
if( spyPtr->true_nation_recno == targetUnitPtr->nation_recno &&
spyPtr->notify_cloaked_nation_flag == 0 )
{
return 0;
}
}
//###### trevor 15/10 #######//
SpriteInfo *spriteInfo = targetUnitPtr->sprite_info;
Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
short targetNationRecno = targetUnitPtr->nation_recno;
//-------------------------------------------------------------------//
// checking nation relationship
//-------------------------------------------------------------------//
if(nation_recno)
{
if(targetNationRecno)
{
//------- don't attack own units and non-hostile units -------//
err_when(targetNationRecno==nation_recno);
//--------------------------------------------------------------//
// if the unit is hostile, only attack if should_attack flag to
// that nation is true or the unit is attacking somebody or something.
//--------------------------------------------------------------//
NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
return 0;
}
else if(!targetUnitPtr->independent_nation_can_attack(nation_recno))
return 0;
}
else if(!independent_nation_can_attack(targetNationRecno)) // independent unit
return 0;
//---------------------------------------------//
if(space_for_attack(targetUnitPtr->next_x_loc(), targetUnitPtr->next_y_loc(), targetUnitPtr->mobile_type,
spriteInfo->loc_width, spriteInfo->loc_height))
return 1;
else
return 0;
}
//----------- End of function Unit::idle_detect_unit_checking -----------//
//--------- Begin of function Unit::idle_detect_firm_checking --------//
// check whether to attack the firm
//
// targetRecno - recno of the firm being checked
//
// return 1 if situation is suitable
// return 0 otherwise
//
int Unit::idle_detect_firm_checking(short targetRecno)
{
Firm *firmPtr = firm_array[targetRecno];
//------------ code to select firm for attacking -----------//
switch(firmPtr->firm_id)
{
case FIRM_CAMP:case FIRM_BASE: case FIRM_WAR_FACTORY:
break;
default: return 0;
}
Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
short targetNationRecno = firmPtr->nation_recno;
char targetMobileType = mobile_type==UNIT_SEA ? UNIT_SEA : UNIT_LAND;
//-------------------------------------------------------------------------------//
// checking nation relationship
//-------------------------------------------------------------------------------//
if(nation_recno)
{
if(targetNationRecno)
{
//------- don't attack own units and non-hostile units -------//
if( targetNationRecno==nation_recno )
return 0;
//--------------------------------------------------------------//
// if the unit is hostile, only attack if should_attack flag to
// that nation is true or the unit is attacking somebody or something.
//--------------------------------------------------------------//
NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
return 0;
}
else // independent firm
{
FirmMonster *monsterFirmPtr = (FirmMonster*) firm_array[targetRecno];
if(!monsterFirmPtr->is_hostile_nation(nation_recno))
return 0;
}
}
else if(!independent_nation_can_attack(targetNationRecno)) // independent town
return 0;
FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
if(space_for_attack(firmPtr->loc_x1, firmPtr->loc_y1, UNIT_LAND, firmInfo->loc_width, firmInfo->loc_height))
return 1;
else
return 0;
}
//----------- End of function Unit::idle_detect_firm_checking -----------//
//--------- Begin of function Unit::idle_detect_town_checking --------//
// check town to attack
//
// targetRecno - recno of town
//
// return 1 if situation is suitable for attacking
// return 0 otherwise
//
int Unit::idle_detect_town_checking(short targetRecno)
{
Town *townPtr = town_array[targetRecno];
Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
short targetNationRecno = townPtr->nation_recno;
//-------------------------------------------------------------------------------//
// checking nation relationship
//-------------------------------------------------------------------------------//
if(nation_recno)
{
if(targetNationRecno)
{
//------- don't attack own units and non-hostile units -------//
if( targetNationRecno==nation_recno )
return 0;
//--------------------------------------------------------------//
// if the unit is hostile, only attack if should_attack flag to
// that nation is true or the unit is attacking somebody or something.
//--------------------------------------------------------------//
NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
return 0;
}
else if(!townPtr->is_hostile_nation(nation_recno))
return 0; // false if the indepentent unit don't want to attack us
}
else if(!independent_nation_can_attack(targetNationRecno)) // independent town
return 0;
if(space_for_attack(townPtr->loc_x1, townPtr->loc_y1, UNIT_LAND, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
return 1;
else
return 0;
}
//----------- End of function Unit::idle_detect_town_checking -----------//
//--------- Begin of function Unit::idle_detect_wall_checking --------//
// check wall to attack
//
// targetXLoc - wall x location
// targetYLoc - wall y location
//
// return 1 if situation is suitable for attacking
// return 0 otherwise
//
int Unit::idle_detect_wall_checking(int targetXLoc, int targetYLoc)
{
Location *locPtr = world.get_loc(targetXLoc, targetYLoc);
Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
short targetNationRecno = locPtr->wall_nation_recno();
//-------------------------------------------------------------------------------//
// checking nation relationship
//-------------------------------------------------------------------------------//
if(nation_recno)
{
if(targetNationRecno)
{
//------- don't attack own units and non-hostile units -------//
if( targetNationRecno==nation_recno )
return 0;
//--------------------------------------------------------------//
// if the unit is hostile, only attack if should_attack flag to
// that nation is true or the unit is attacking somebody or something.
//--------------------------------------------------------------//
NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
return 0;
}
else
return 0;
}
else if(!independent_nation_can_attack(targetNationRecno)) // independent town
return 0;
if(space_for_attack(targetXLoc, targetYLoc, UNIT_LAND, 1, 1))
return 1;
else
return 0;
}
//----------- End of function Unit::idle_detect_wall_checking -----------//
//--------- Begin of function Unit::idle_detect_choose_target --------//
//
// defenseMode - indicate whether defensive mode is on
//
int Unit::idle_detect_choose_target(char defenseMode)
{
//-----------------------------------------------------------------------------------------------//
// Decision making for choosing target to attack
//-----------------------------------------------------------------------------------------------//
if(defenseMode)
{
if(action_mode2==ACTION_AUTO_DEFENSE_DETECT_TARGET)
{
//----------- defense units allow to attack units and firms -----------//
err_when(!in_auto_defense_mode());
if(idle_detect_has_unit)
defense_attack_unit(idle_detect_target_unit_recno);
else if(idle_detect_has_firm)
{
Firm *targetFirmPtr = firm_array[idle_detect_target_firm_recno];
defense_attack_firm(targetFirmPtr->loc_x1, targetFirmPtr->loc_y1);
}
/*else if(idle_detect_has_town)
{
TownPtr *targetTownPtr = town_array[idle_detect_target_town_recno];
defense_attack_town(targetTownPtr->loc_x1, targetTownPtr->loc_y1);
}
else if(idle_detect_has_wall)
defense_attack_wall(idle_detect_target_wall_x1, idle_detect_target_wall_y1);*/
else
return 0;
return 1;
}
else if(action_mode2==ACTION_DEFEND_TOWN_DETECT_TARGET)
{
//----------- town units only attack units ------------//
err_when(!in_defend_town_mode());
if(idle_detect_has_unit)
defend_town_attack_unit(idle_detect_target_unit_recno);
else
return 0;
return 1;
}
else if(action_mode2==ACTION_MONSTER_DEFEND_DETECT_TARGET)
{
//---------- monsters can attack units and firms -----------//
err_when(!in_monster_defend_mode());
if(idle_detect_has_unit)
monster_defend_attack_unit(idle_detect_target_unit_recno);
else if(idle_detect_has_firm)
{
Firm *targetFirmPtr = firm_array[idle_detect_target_firm_recno];
monster_defend_attack_firm(targetFirmPtr->loc_x1, targetFirmPtr->loc_y1);
}
/*else if(idle_detect_has_town)
{
Town *targetTownPtr = town_array[idle_detect_target_town_recno];
monster_defend_attack_town(targetTownPtr->loc_x1, targetTownPtr->loc_y1);
}
else if(idle_detect_has_wall)
monster_defend_attack_wall(idle_detect_target_wall_x1, idle_detect_target_wall_y1);*/
else
return 0;
return 1;
}
else
err_here();
}
else // default mode
{
//#### begin trevor 9/10 ####//
int rc = 0;
if(idle_detect_has_unit)
{
attack_unit(idle_detect_target_unit_recno);
//--- set the original position of the target, so the unit won't chase too far away ---//
Unit* unitPtr = unit_array[idle_detect_target_unit_recno];
original_target_x_loc = unitPtr->next_x_loc();
original_target_y_loc = unitPtr->next_y_loc();
rc = 1;
}
else if(help_mode==HELP_ATTACK_UNIT)
{
attack_unit(help_attack_target_recno);
//--- set the original position of the target, so the unit won't chase too far away ---//
Unit* unitPtr = unit_array[help_attack_target_recno];
original_target_x_loc = unitPtr->next_x_loc();
original_target_y_loc = unitPtr->next_y_loc();
rc = 1;
}
else if(idle_detect_has_firm)
{
Firm *targetFirmPtr = firm_array[idle_detect_target_firm_recno];
attack_firm(targetFirmPtr->loc_x1, targetFirmPtr->loc_y1);
}
/*else if(idle_detect_has_town)
{
Town *targetTownPtr = town_array[idle_detect_target_town_recno];
attack_town(targetTownPtr->loc_x1, targetTownPtr->loc_y1);
}
else if(idle_detect_has_wall)
attack_wall(idle_detect_target_wall_x1, idle_detect_target_wall_y1);*/
else
return 0;
//---- set original action vars ----//
if( rc && original_action_mode==0 )
{
original_action_mode = ACTION_MOVE;
original_action_para = 0;
original_action_x_loc = next_x_loc();
original_action_y_loc = next_y_loc();
}
return 1;
//#### end trevor 9/10 ####//
}
return 0;
}
//----------- End of function Unit::idle_detect_choose_target -----------//
//--------- Begin of function Unit::idle_detect_helper_attack --------//
// check the action_mode of the unit being checked, which has same nation
// recno as this unit. If the unit attacks other unit, this unit help to
// attack the same target.
//
// unitRecno - recno of the unit of nation recno same as this unit
//
void Unit::idle_detect_helper_attack(short unitRecno)
{
#define HELP_DISTANCE 15
Unit *unitPtr = unit_array[unitRecno];
if(unitPtr->unit_id == UNIT_CARAVAN)
return;
//char actionMode;
short actionPara;
//short actionXLoc, actionYLoc;
char isUnit = 0;
//------------- is the unit attacking other unit ------------//
switch(unitPtr->action_mode2)
{
case ACTION_ATTACK_UNIT:
actionPara = unitPtr->action_para2;
isUnit++;
break;
default:
switch(unitPtr->action_mode)
{
case ACTION_ATTACK_UNIT:
actionPara = unitPtr->action_para;
isUnit++;
break;
}
}
if(isUnit && !unit_array.is_deleted(actionPara))
{
Unit *targetUnit = unit_array[actionPara];
if(targetUnit->nation_recno==nation_recno)
return;
if(m.points_distance(next_x_loc(), next_y_loc(), targetUnit->next_x_loc(), targetUnit->next_y_loc())