コード例 #1
0
ファイル: OUNITHB.cpp プロジェクト: brianV/7kaa
//--------- Begin of function Unit::handle_blocked_attack_wall ---------//
// handle the case that the way of this unit to the target wall is blocked by
// another unit
//
// <Unit*> unitPtr	- the blocking unit
//
void Unit::handle_blocked_attack_wall(Unit *unitPtr)
{
	if(action_x_loc==unitPtr->action_x_loc && action_y_loc==unitPtr->action_y_loc && action_mode==unitPtr->action_mode)
	{
		//------------- both attacks the same wall ------------//
		Location *locPtr = world.get_loc(action_x_loc, action_y_loc);
		if(!locPtr->is_wall())
			stop2(KEEP_DEFENSE_MODE);	// stop since wall is deleted
		else if(space_for_attack(action_x_loc, action_y_loc, UNIT_LAND, 1, 1))
		{
			//------------ found surrounding place to attack the wall -------------//
			if(mobile_type==UNIT_LAND)
				set_move_to_surround(action_x_loc, action_y_loc, 1, 1, BUILDING_TYPE_WALL); // search for a unit only, not for a group
			else
				attack_wall(action_x_loc, action_y_loc);
		}
		else // no surrounding place found, stop now
			stop(KEEP_PRESERVE_ACTION); // no space available, so stop to wait for space to attack the wall
	}
	else
	{
		if(action_x_loc==-1 || action_y_loc==-1)
			stop();
		else
			set_wait();
	}
}
コード例 #2
0
ファイル: OUNITHB.cpp プロジェクト: brianV/7kaa
//--------- Begin of function Unit::handle_blocked_attack_firm ---------//
// handle the case that the way of this unit to the target firm is blocked by
// another unit
//
// <Unit*> unitPtr	- the blocking unit
//
void Unit::handle_blocked_attack_firm(Unit *unitPtr)
{
	if(action_x_loc==unitPtr->action_x_loc && action_y_loc==unitPtr->action_y_loc && action_para==unitPtr->action_para &&
		action_mode==unitPtr->action_mode)
	{
		//------------- both attacks the same firm ------------//
		Location *locPtr = world.get_loc(action_x_loc, action_y_loc);
		if(!locPtr->is_firm())
			stop2(KEEP_DEFENSE_MODE);	// stop since firm is deleted
		else
		{
			Firm *firmPtr = firm_array[action_para];
			FirmInfo *firmInfo = firm_res[firmPtr->firm_id];

			if(space_for_attack(action_x_loc, action_y_loc, UNIT_LAND, firmInfo->loc_width, firmInfo->loc_height))
			{
				//------------ found surrounding place to attack the firm -------------//
				if(mobile_type==UNIT_LAND)
					set_move_to_surround(firmPtr->loc_x1, firmPtr->loc_y1, firmInfo->loc_width, firmInfo->loc_height, BUILDING_TYPE_FIRM_MOVE_TO);
				else
					attack_firm(firmPtr->loc_x1, firmPtr->loc_y1);
			}
			else // no surrounding place found, stop now
				stop(KEEP_PRESERVE_ACTION);
		}
	}
	else // let process_idle() handle it
		stop();
}
コード例 #3
0
ファイル: OUNITHB.cpp プロジェクト: brianV/7kaa
//--------- Begin of function Unit::handle_blocked_attack_town ---------//
// handle the case that the way of this unit to the target town is blocked by
// another unit
//
// <Unit*> unitPtr	- the blocking unit
//
void Unit::handle_blocked_attack_town(Unit *unitPtr)
{
	if(action_x_loc==unitPtr->action_x_loc && action_y_loc==unitPtr->action_y_loc && action_para==unitPtr->action_para &&
		action_mode==unitPtr->action_mode)
	{
		//---------------- both attacks the same town ----------------------//
		Location *locPtr = world.get_loc(action_x_loc, action_y_loc);
		if(!locPtr->is_town())
			stop2(KEEP_DEFENSE_MODE);	// stop since town is deleted
		else if(space_for_attack(action_x_loc, action_y_loc, UNIT_LAND, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
		{
			//------------ found surrounding place to attack the town -------------//
			Town *townPtr = town_array[action_para];
			{
				if(mobile_type==UNIT_LAND)
					set_move_to_surround(townPtr->loc_x1, townPtr->loc_y1, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, BUILDING_TYPE_TOWN_MOVE_TO);
				else
					attack_town(townPtr->loc_x1, townPtr->loc_y1);
			}
		}
		else // no surrounding place found, stop now
			stop(KEEP_PRESERVE_ACTION);
	}
	else
		stop();
}
コード例 #4
0
ファイル: OUNITD.cpp プロジェクト: AMDmi3/7kaa
//------------- Begin of function Unit::defend_town_follow_target --------------//
// check the unit should follow the target or not
//
// return 0 if aborting attack the current target and go back to military camp
// return 1 otherwise
//
int Unit::defend_town_follow_target()
{
	err_when(unit_mode!=UNIT_MODE_DEFEND_TOWN);

	if(cur_action==SPRITE_ATTACK)
		return 1;

	if(town_array.is_deleted(unit_mode_para))
	{
		stop2(); //**** BUGHERE
		set_mode(0); //***BUGHERE
		return 0;
	}

	int curXLoc = next_x_loc();
	int curYLoc = next_y_loc();

	Town *townPtr = town_array[unit_mode_para];
	if((curXLoc<townPtr->center_x-UNIT_DEFEND_TOWN_DISTANCE) || (curXLoc>townPtr->center_x+UNIT_DEFEND_TOWN_DISTANCE) ||
		(curYLoc<townPtr->center_y-UNIT_DEFEND_TOWN_DISTANCE) || (curYLoc>townPtr->center_y+UNIT_DEFEND_TOWN_DISTANCE))
	{
		defend_town_back_town(unit_mode_para);
		return 0;
	}

	return 1;
}
コード例 #5
0
ファイル: OUNITD.cpp プロジェクト: AMDmi3/7kaa
//--------- Begin of function Unit::process_auto_defense_back_camp ---------//
// process action for the units to return camp
//
void Unit::process_auto_defense_back_camp()
{
	int	clearDefenseMode = 0;
	if(action_mode!=ACTION_ASSIGN_TO_FIRM) // the unit may become idle or unable to reach firm, reactivate it
	{
		Firm	*firmPtr;
		if(action_misc!=ACTION_MISC_DEFENSE_CAMP_RECNO || !action_misc_para || firm_array.is_deleted(action_misc_para))
			clearDefenseMode++;
		else
		{
			firmPtr = firm_array[action_misc_para];
			if(firmPtr->firm_id!=FIRM_CAMP || firmPtr->nation_recno!=nation_recno)
				clearDefenseMode++;
			else
			{
				defense_back_camp(firmPtr->loc_x1, firmPtr->loc_y1); // go back to the military camp
				err_when(action_mode2!=ACTION_AUTO_DEFENSE_BACK_CAMP);
				return;
			}
		}
	}
	else if(cur_action==SPRITE_IDLE)
	{
		if(firm_array.is_deleted(action_misc_para))
			clearDefenseMode++;
		else
		{
			Firm *firmPtr = firm_array[action_misc_para];
			defense_back_camp(firmPtr->loc_x1, firmPtr->loc_y1);
			err_when(action_mode2!=ACTION_AUTO_DEFENSE_BACK_CAMP);
			return;
		}
	}

	err_when(!clearDefenseMode);
	//----------------------------------------------------------------//
	// clear order if the camp is deleted
	//----------------------------------------------------------------//
	stop2();
	reset_action_misc_para();
	err_when(in_auto_defense_mode());
}
コード例 #6
0
ファイル: OUNITD.cpp プロジェクト: AMDmi3/7kaa
//------------- Begin of function Unit::process_defend_town_back_town --------------//
// process action to go back town
//
void Unit::process_defend_town_back_town()
{
	int	clearDefenseMode = 0;
	if(action_mode!=ACTION_ASSIGN_TO_TOWN) // the unit may become idle or unable to reach town, reactivate it
	{
		Town	*townPtr;
		if(action_misc!=ACTION_MISC_DEFEND_TOWN_RECNO || !action_misc_para || town_array.is_deleted(action_misc_para))
			clearDefenseMode++;
		else
		{
			townPtr = town_array[action_misc_para];
			if(townPtr->nation_recno!=nation_recno)
				clearDefenseMode++;
			else
			{
				defend_town_back_town(action_misc_para); // go back to the town
				err_when(action_mode2!=ACTION_DEFEND_TOWN_BACK_TOWN);
				return;
			}
		}
	}
	else if(cur_action==SPRITE_IDLE)
	{
		if(town_array.is_deleted(action_misc_para))
			clearDefenseMode++;
		else
		{
			defend_town_back_town(action_misc_para);
			err_when(action_mode2!=ACTION_DEFEND_TOWN_BACK_TOWN);
			return;
		}
	}

	err_when(!clearDefenseMode);
	//----------------------------------------------------------------//
	// clear order if the town is deleted
	//----------------------------------------------------------------//
	stop2();
	reset_action_misc_para();
	err_when(in_defend_town_mode());
}
コード例 #7
0
ファイル: OUNITAI.cpp プロジェクト: MicroVirus/7kaa
//--------- Begin of function Unit::ai_handle_seek_path_fail --------//
//
// This function is used for handling cases when AI units are not
// able to seek a path successfully.
//
int Unit::ai_handle_seek_path_fail()
{
	if( seek_path_fail_count < 5 )		// wait unit it has failed many times
		return 0;

	//----- try to move to a new location -----//

	if( seek_path_fail_count==5 )
	{
		stop2();		// stop the unit and think for new action
		return 0;
	}

	//--- if the seek path has failed too many times, resign the unit ---//

	int resignFlag = 0;

	if( rank_id == RANK_SOLDIER && !leader_unit_recno )
	{
		if( seek_path_fail_count>=7 )
			resignFlag = 1;
	}
	else if( rank_id == RANK_GENERAL )
	{
		if( seek_path_fail_count >= 7+skill.skill_level/10 )
			resignFlag = 1;
	}

	if( resignFlag && is_visible() )
	{
		resign(COMMAND_AI);
		return 1;
	}
	else
		return 0;
}
コード例 #8
0
ファイル: OUNITHB.cpp プロジェクト: brianV/7kaa
//------ Begin of function Unit::handle_blocked_same_target_attack ---------//
// the target of the blocked unit and this unit are same
//
// <Unit*>	unitPtr		-	pointer to blocking uit
// <Unit*>	targetPtr	-	pointer to target unit
//
void Unit::handle_blocked_same_target_attack(Unit* unitPtr, Unit* targetPtr)
{
	//----------------------------------------------------------//
	// this unit is now waiting and the unit pointed by unitPtr
	// is attacking the unit pointed by targetPtr
	//----------------------------------------------------------//
	err_when(cur_x%ZOOM_LOC_WIDTH || cur_y%ZOOM_LOC_HEIGHT);
	err_when(cur_x!=next_x || cur_y!=next_y);
	err_when(cur_x==go_x && cur_y==go_y);

	if(space_for_attack(action_x_loc, action_y_loc, targetPtr->mobile_type, targetPtr->sprite_info->loc_width, targetPtr->sprite_info->loc_height))
	{
		err_when(action_x_loc!=action_x_loc2 || action_y_loc!=action_y_loc2);
		search_or_stop(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_TO_ATTACK, targetPtr->sprite_recno);
		//search(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_TO_ATTACK, targetPtr->sprite_recno);
	}
	else if(in_any_defense_mode())
	{
		err_when(action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET &&
					action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET);

		general_defend_mode_detect_target();
	}
	else if(m.points_distance(next_x_loc(), next_y_loc(), action_x_loc, action_y_loc)<ATTACK_DETECT_DISTANCE)
	{
		//------------------------------------------------------------------------//
		// if the target is within the detect range, stop the unit's action to detect
		// another target if any exist. In case, there is no other target, the unit
		// will still attack the original target since it is the only target in the
		// detect range
		//------------------------------------------------------------------------//
		stop2(KEEP_DEFENSE_MODE);
	}
	else
		set_wait(); // set wait to stop the movement
}
コード例 #9
0
ファイル: OUNITAI.cpp プロジェクト: MicroVirus/7kaa
//--------- Begin of function Unit::process_ai --------//
//
// [int] forceExecute - whether force execute all AI functions
//								without checking day interavals.
//							   (default: 0)
//
void Unit::process_ai()
{
	err_when( !nation_recno );

	//-*********** simulate aat ************-//
	#ifdef DEBUG
		if(debug_sim_game_type)
			return;
	#endif
	//-*********** simulate aat ************-//

	//------ the aggressive_mode of AI units is always 1 ------//

	aggressive_mode = 1;

	//------- handle Seek Path failures ------//

	if( ai_handle_seek_path_fail() )
		return;

	//--- if it's a spy from other nation, don't control it ---//

	if( spy_recno && true_nation_recno() != nation_recno )
	{
		//--- a random chance of the AI catching the spy and resign it ---//

		if( is_visible() && misc.random(365 * FRAMES_PER_DAY)==0 )		// if the unit stay outside for one year, it will get caught
		{
			stop2();
			resign(COMMAND_AI);
			return;
		}

		if( !spy_array[spy_recno]->notify_cloaked_nation_flag )		// if notify_cloaked_nation_flag is 1, the nation will take it as its own spies
			return;
	}

	//----- think about rewarding this unit -----//

	if( race_id && rank_id != RANK_KING &&
		 info.game_date%5 == sprite_recno%5 )
	{
		think_reward();
	}

	//-----------------------------------------//

	if( !is_visible() )
		return;

	//--- if the unit has stopped, but ai_action_id hasn't been reset ---//

	if( cur_action==SPRITE_IDLE && action_mode==ACTION_STOP &&
		 action_mode2==ACTION_STOP && ai_action_id )
	{
		nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);

		err_when( ai_action_id );		// it should have been reset
	}

	//---- King flees under attack or surrounded by enemy ---//

	if( race_id && rank_id==RANK_KING )
	{
		if( think_king_flee() )
			return;
	}

	//---- General flees under attack or surrounded by enemy ---//

	if( race_id && rank_id==RANK_GENERAL &&
		 info.game_date%7 == sprite_recno%7 )
	{
		if( think_general_flee() )
			return;
	}

	//-- let Unit::next_day() process it process original_action_mode --//

	if( original_action_mode )
		return;

	//------ if the unit is not stop right now ------//

	if( !is_ai_all_stop() )
	{
		think_stop_chase();
		return;
	}

	//-----------------------------------------//

	if( mobile_type==UNIT_LAND )
	{
		if( ai_escape_fire() )
			return;
	}

	//---------- if this is your spy --------//

	if( spy_recno && true_nation_recno()==nation_recno )
		think_spy_action();

	//------ if this unit is from a camp --------//

	if( home_camp_firm_recno )
	{
		Firm* firmCamp = firm_array[home_camp_firm_recno];
		int   rc;

		if( rank_id == RANK_SOLDIER )
			rc = firmCamp->worker_count < MAX_WORKER;
		else
			rc = !firmCamp->overseer_recno;

		if( rc )
		{
			if( return_camp() )
				return;
		}

		home_camp_firm_recno = 0;		// the camp is already occupied by somebody
	}

	//----------------------------------------//

	if( race_id && rank_id==RANK_KING )
	{
		think_king_action();
	}
	else if( race_id && rank_id==RANK_GENERAL )
	{
		think_general_action();
	}
	else
	{
		if( unit_res[unit_id]->unit_class == UNIT_CLASS_WEAPON )
		{
			if( info.game_date%15 == sprite_recno%15 )	// don't call too often as the action may fail and it takes a while to call the function each time
			{
				think_weapon_action();	//-- ships AI are called in UnitMarine --//
			}
		}
		else if( race_id )
		{
			//--- if previous attempts for new action failed, don't call think_normal_human_action() so frequently then ---//

			if( ai_no_suitable_action )
			{
				if( info.game_date%15 != sprite_recno%15 )	// don't call too often as the action may fail and it takes a while to call the function each time
					return;
			}

			//---------------------------------//

			if( !think_normal_human_action() )
			{
				ai_no_suitable_action = 1; 	// set this flag so think_normal_human_action() won't be called continously

				if( !leader_unit_recno )		// only when the unit is not led by a commander
				{
					resign(COMMAND_AI);
				}
				else
				{
					ai_move_to_nearby_town();
				}
			}
		}
	}
}
コード例 #10
0
ファイル: OUNITAI.cpp プロジェクト: MicroVirus/7kaa
int Unit::think_stop_chase()
{
	//-----------------------------------------------------//
	//
	// Stop the chase if the target is being far away from
	// its original attacking location.
	//
	//-----------------------------------------------------//

	if( !(action_mode==ACTION_ATTACK_UNIT && ai_original_target_x_loc>=0) )
		return 0;

	if( unit_array.is_deleted(action_para) )
	{
		stop2();
		return 1;
	}

	Unit* targetUnit = unit_array[action_para];

	if( !targetUnit->is_visible() )
	{
		stop2();
		return 1;
	}

	//----------------------------------------//

	int aiChaseDistance = 10 + nation_array[nation_recno]->pref_military_courage/20;		// chase distance: 10 to 15

	int curDistance = misc.points_distance( targetUnit->next_x_loc(), targetUnit->next_y_loc(),
							ai_original_target_x_loc, ai_original_target_y_loc );

	if( curDistance <= aiChaseDistance )
		return 0;

	//--------- stop the unit ----------------//

	stop2();

	//--- if this unit leads a troop, stop the action of all troop members as well ---//

	int leaderUnitRecno;

	if( leader_unit_recno )
		leaderUnitRecno = leader_unit_recno;
	else
		leaderUnitRecno = sprite_recno;

	TeamInfo* teamInfo = unit_array[leaderUnitRecno]->team_info;

	if( teamInfo )
	{
		for( int i=teamInfo->member_count-1 ; i>=0 ; i-- )
		{
			int unitRecno = teamInfo->member_unit_array[i];

			if( unit_array.is_deleted(unitRecno) )
				continue;

			unit_array[unitRecno]->stop2();
		}
	}

	return 1;
}
コード例 #11
0
ファイル: OUNITS.cpp プロジェクト: Stummi/7kaa
//--------- Begin of function Unit::process_assign_to_ship ---------//
// process unit action of assigning units to ship
//
void Unit::process_assign_to_ship()
{
	err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
	
	//---------------------------------------------------------------------------//
	// clear unit's action if situation is changed
	//---------------------------------------------------------------------------//
	UnitMarine *shipPtr;
	if(unit_array.is_deleted(action_para2))
	{
		stop2();
		return; // stop the unit as the ship is deleted
	}
	else
	{
		shipPtr = (UnitMarine*) unit_array[action_para2];
		if(shipPtr->nation_recno != nation_recno)
		{
			stop2();
			return; // stop the unit as the ship's nation_recno != the unit's nation_recno
		}
	}

	if(shipPtr->action_mode2!=ACTION_SHIP_TO_BEACH)
	{
		stop2(); // the ship has changed its action
		return;
	}

	int curXLoc = next_x_loc();
	int curYLoc = next_y_loc();
	int shipXLoc = shipPtr->next_x_loc();
	int shipYLoc = shipPtr->next_y_loc();

	if(shipPtr->cur_x==shipPtr->next_x && shipPtr->cur_y==shipPtr->next_y &&
		abs(shipXLoc-curXLoc)<=1 && abs(shipYLoc-curYLoc)<=1)
	{
		//----------- assign the unit now -----------//
		if(abs(cur_x-next_x)<sprite_info->speed && abs(cur_y-next_y)<sprite_info->speed)
		{
			if(ai_action_id)
				nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);

			stop2();
			set_dir(curXLoc, curYLoc, shipXLoc, shipYLoc);
			shipPtr->load_unit(sprite_recno);
			return;
		}
	}
	else if(cur_action==SPRITE_IDLE)
		set_dir(curXLoc, curYLoc, shipPtr->move_to_x_loc, shipPtr->move_to_y_loc);

	//---------------------------------------------------------------------------//
	// update location to embark
	//---------------------------------------------------------------------------//
	int shipActionXLoc = shipPtr->action_x_loc2;
	int shipActionYLoc = shipPtr->action_y_loc2;
	if(abs(shipActionXLoc-action_x_loc2)>1 || abs(shipActionYLoc-action_y_loc2)>1)
	{
		if(shipActionXLoc!=action_x_loc2 || shipActionYLoc!=action_y_loc2)
		{
			Location *unitLocPtr = world.get_loc(curXLoc, curYLoc);
			Location *shipActionLocPtr = world.get_loc(shipActionXLoc, shipActionYLoc);
			if(unitLocPtr->region_id != shipActionLocPtr->region_id)
			{
				stop2();
				return;
			}

			assign_to_ship(shipActionXLoc, shipActionYLoc, action_para2);
			return;
		}
	}
}
コード例 #12
0
ファイル: OUNITHB.cpp プロジェクト: brianV/7kaa
//------ Begin of function Unit::handle_blocked_move_s11 -------//
// both blocked and blocking are size 1
//
void Unit::handle_blocked_move_s11(Unit *unitPtr)
{
	err_when( world.get_unit_recno(next_x_loc(), next_y_loc(), mobile_type) != sprite_recno );
	err_when( world.get_unit_recno(unitPtr->next_x_loc(), unitPtr->next_y_loc(), unitPtr->mobile_type) != unitPtr->sprite_recno );
	err_when(cur_x!=next_x || cur_y!=next_y);

	int waitTerm;
	int moveStep = move_step_magn();

	switch(unitPtr->cur_action)
	{
		//------------------------------------------------------------------------------------//
		// handle blocked for units belonging to the same nation.  For those belonging to other
		// nations, wait for it moving to other locations or search for another path.
		//------------------------------------------------------------------------------------//
		case SPRITE_WAIT: // the blocking unit is waiting
				err_when(unitPtr->go_x==unitPtr->cur_x && unitPtr->go_y==unitPtr->cur_y);
		
		case SPRITE_TURN:
				if(unitPtr->nation_recno==nation_recno)
					handle_blocked_wait(unitPtr); // check for cycle wait for our nation
				else if(waiting_term>=MAX_WAITING_TERM_DIFF)
				{
					search_or_stop(move_to_x_loc, move_to_y_loc, 1); // recall searching
					waiting_term = 0;
				}
				else // wait
					set_wait();
				return;

		//------------------------------------------------------------------------------------//
		// We know from the cur_action of the blocking unit it is moving to another locations,
		// the blocked unit wait for a number of terms or search again.
		//------------------------------------------------------------------------------------//
		case SPRITE_MOVE:
		case SPRITE_READY_TO_MOVE:
		case SPRITE_SHIP_EXTRA_MOVE:
				if(unit_id!=UNIT_CARAVAN && unitPtr->unit_id==UNIT_CARAVAN) // don't wait for caravans, and caravans don't wait for other units
				{
					search(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_A_UNIT_IN_GROUP);
				}
				else
				{
					waitTerm = (nation_recno==unitPtr->nation_recno) ? MAX_WAITING_TERM_SAME : MAX_WAITING_TERM_DIFF;
					if(waiting_term>=waitTerm)
					{
						search_or_wait();
						waiting_term = 0;
					}
					else
						set_wait();
				}
				return;

		//------------------------------------------------------------------------------------//
		// handling blocked for idle unit
		//------------------------------------------------------------------------------------//
		case SPRITE_IDLE:
				err_when(unitPtr->result_node_array!=NULL);
				if(unitPtr->action_mode==ACTION_SHIP_TO_BEACH)
				{
					//----------------------------------------------------------------------//
					// the blocking unit is trying to move to beach, so wait a number of terms,
					// or call searching again
					//----------------------------------------------------------------------//
					if(abs(unitPtr->next_x_loc()-unitPtr->action_x_loc2)<=moveStep &&
						abs(unitPtr->next_y_loc()-unitPtr->action_y_loc2)<=moveStep &&
						terrain_res[world.get_loc(unitPtr->action_x_loc2, unitPtr->action_y_loc2)->terrain_id]->average_type
						!=TERRAIN_OCEAN)
					{
						if(action_mode2==ACTION_SHIP_TO_BEACH && action_x_loc2==unitPtr->action_x_loc2 &&
							action_y_loc2==unitPtr->action_y_loc2)
						{
							int tempX, tempY;
							ship_to_beach(action_x_loc2, action_y_loc2, tempX, tempY);
						}
						else
						{
							waitTerm = (nation_recno==unitPtr->nation_recno) ? MAX_WAITING_TERM_SAME : MAX_WAITING_TERM_DIFF;
							if(waiting_term>=waitTerm)
								stop2();
							else
								set_wait();
						}
						return;
					}
				}

				if(unitPtr->nation_recno==nation_recno) //-------- same nation
				{
					//------------------------------------------------------------------------------------//
					// units from our nation
					//------------------------------------------------------------------------------------//
					if(unitPtr->unit_group_id==unit_group_id)
					{
						//--------------- from the same group -----------------//
						if(way_point_count && !unitPtr->way_point_count)
						{
							//------------ reset way point --------------//
							stop2();
							reset_way_point_array();
						}
						else if((unitPtr->next_x_loc() != move_to_x_loc || unitPtr->next_y_loc() != move_to_y_loc) &&
							(unitPtr->cur_action==SPRITE_IDLE && unitPtr->action_mode2==ACTION_STOP))
							move_to_my_loc(unitPtr); // push the blocking unit and exchange their destination
						else if(unitPtr->action_mode == ACTION_SETTLE)
							set_wait(); // wait for the settler
						else if(waiting_term>MAX_WAITING_TERM_SAME)
						{
							//---------- stop if wait too long ----------//
							terminate_move();
							waiting_term = 0;
						}
						else
							set_wait();
					}
					else if(unitPtr->action_mode2==ACTION_STOP)
						handle_blocked_by_idle_unit(unitPtr);
					else if(way_point_count && !unitPtr->way_point_count)
					{
						stop2();
						reset_way_point_array();
					}
					else
						search_or_stop(move_to_x_loc, move_to_y_loc, 1); // recall A* algorithm by default mode
				}
				else // different nation
				{
					//------------------------------------------------------------------------------------//
					// units from other nations
					//------------------------------------------------------------------------------------//
					if(unitPtr->next_x_loc() == move_to_x_loc && unitPtr->next_y_loc() == move_to_y_loc)
					{  
						terminate_move(); // destination occupied by other unit

						if(action_mode==ACTION_ATTACK_UNIT && unitPtr->nation_recno!=nation_recno && unitPtr->sprite_recno==action_para)
						{
							err_when(action_x_loc!=unitPtr->next_x_loc() || action_y_loc!=unitPtr->next_y_loc());
							err_when(action_mode2!=ACTION_ATTACK_UNIT && action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET &&
										action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET && action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET);
							err_when(action_para2!=action_para);
							err_when(action_x_loc!=action_x_loc2 || action_y_loc!=action_y_loc2);
							
							set_dir(next_x, next_y, unitPtr->next_x, unitPtr->next_y);
							if(is_dir_correct())
								attack_unit(action_para);
							else
								set_turn();
							cur_frame  = 1;
						}
					}
					else
						search_or_stop(move_to_x_loc, move_to_y_loc, 1); // recall A* algorithm by default mode
				}
				return;

		//------------------------------------------------------------------------------------//
		// don't wait for attackers from other nations, search for another path.
		//------------------------------------------------------------------------------------//
		case SPRITE_ATTACK:
				//----------------------------------------------------------------//
				// don't wait for other nation unit, call searching again
				//----------------------------------------------------------------//
				if(nation_recno!=unitPtr->nation_recno)
				{
					search_or_stop(move_to_x_loc, move_to_y_loc, 1);
					return;
				}

				//------------------------------------------------------------------------------------//
				// for attackers owned by our commander, handled blocked case by case as follows.
				//------------------------------------------------------------------------------------//
				switch(unitPtr->action_mode)
				{
					case ACTION_ATTACK_UNIT:
							if(action_para && !unit_array.is_deleted(action_para))
							{
								Unit *targetPtr = unit_array[action_para];
								handle_blocked_attack_unit(unitPtr, targetPtr);
							}
							else
								search_or_stop(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_A_UNIT_IN_GROUP);
							break;

					case ACTION_ATTACK_FIRM:
							if(!unitPtr->action_para || firm_array.is_deleted(unitPtr->action_para))
								set_wait();
							else
								handle_blocked_attack_firm(unitPtr);
							break;

					case ACTION_ATTACK_TOWN:
							if(!unitPtr->action_para || town_array.is_deleted(unitPtr->action_para))
								set_wait();
							else
								handle_blocked_attack_town(unitPtr);
							break;

					case ACTION_ATTACK_WALL:
							if(unitPtr->action_para)
								set_wait();
							else
								handle_blocked_attack_wall(unitPtr);
							break;

					case ACTION_GO_CAST_POWER:
							set_wait();
							break;

					default: err_here();
								break;
				}
				return;

		//------------------------------------------------------------------------------------//
		// the blocked unit can pass after the blocking unit disappears in air.
		//------------------------------------------------------------------------------------//
		case SPRITE_DIE:
				set_wait();	// assume this unit will not wait too long
				return;

		default:
				err_here();
				break;
	}
	
	err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
}