//--------- 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(); } }
//--------- 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(); }
//--------- 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(); }
//------------- 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; }
//--------- 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()); }
//------------- 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()); }
//--------- 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; }
//------ 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 }
//--------- 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(); } } } } }
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; }
//--------- 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; } } }
//------ 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)); }