//--------- 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(); } } } } }
void Unit::think_spy_action() { ai_move_to_nearby_town(); // just move it to one of our towns }
//--------- Begin of function Unit::betray ---------// // // If this unit is a spy, this function betray() will be // called by Unit::spy_change_nation() or Firm::capture_firm(). // // If this is not a spy, this function will only be called // by think_betray() and other nation deinit functions. // int Unit::betray(int newNationRecno) { //----- if this is a spy, call spy_change_nation -----// if( spy_recno && spy_array[spy_recno]->cloaked_nation_recno != newNationRecno ) // cloaked_nation_recno == newNationRecno if betray() is called by spy_change_nation() already { spy_change_nation(newNationRecno, COMMAND_AUTO); return 1; } //-------------------------------// err_when( newNationRecno && nation_array[newNationRecno]->is_human() && // monsters in firms should not betray to humans is_monster() && unit_mode == UNIT_MODE_OVERSEE ); int unitRecno = sprite_recno; err_when( unit_array.is_truly_deleted(unitRecno) ); err_when( rank_id == RANK_KING ); if( nation_recno == newNationRecno ) return 0; if( unit_mode == UNIT_MODE_CONSTRUCT_FIRM || // don't change nation when the unit is constructing a firm unit_mode == UNIT_MODE_CONSTRUCT_TOWN || unit_mode == UNIT_MODE_ON_SHIP ) // don't change nation when the unit is constructing a firm { return 0; } //--- special case: units in Monster Fortress cannot change nation ---// if( unit_mode == UNIT_MODE_OVERSEE && firm_array[unit_mode_para]->firm_id == FIRM_FORTRESS ) { return 0; } //---------- add news -----------// if( nation_recno == nation_array.player_recno || newNationRecno == nation_array.player_recno ) { //--- if this is a spy, don't display news message for betrayal as it is already displayed in Unit::spy_change_nation() ---// if( !spy_recno ) news_array.unit_betray(sprite_recno, newNationRecno); } //------ change nation now ------// err_when( unit_array.is_truly_deleted(unitRecno) ); change_nation(newNationRecno); err_when( unit_array.is_truly_deleted(unitRecno) ); //-------- set the loyalty of the unit -------// if( nation_recno ) { Nation* nationPtr = nation_array[nation_recno]; loyalty = UNIT_BETRAY_LOYALTY + 10 + m.random(20); if( nationPtr->reputation > 0 ) change_loyalty( (int) nationPtr->reputation ); if( race_res.is_same_race( nationPtr->race_id, race_id ) ) change_loyalty( 30 ); err_when( loyalty < 0 || loyalty > 100 ); update_loyalty(); // update target loyalty } else //------ if change to independent rebel -------// { loyalty = 0; // no loyalty needed } //--- if this unit is a general, change nation for the units he commands ---// if( rank_id==RANK_GENERAL ) { err_when( !team_info ); for( int i=0 ; i<team_info->member_count ; i++ ) { int memberUnitRecno = team_info->member_unit_array[i]; if( memberUnitRecno == unitRecno ) // this is the unit itself continue; Unit* unitPtr = unit_array[memberUnitRecno]; if( !unitPtr->is_visible() ) continue; if( unitPtr->spy_recno ) // if the unit is a spy unitPtr->spy_change_nation(newNationRecno, COMMAND_AUTO); else unitPtr->change_nation(newNationRecno); } } err_when( unit_array.is_truly_deleted(unitRecno) ); //------ go to meet the new master -------// if( is_visible() && nation_recno ) { if( !spy_recno || spy_array[spy_recno]->notify_cloaked_nation_flag ) { if( is_civilian() ) ai_move_to_nearby_town(); else ai_move_to_nearby_firm(FIRM_CAMP, FIRM_FORT); } } err_when( unit_array.is_truly_deleted(unitRecno) ); return 1; }
//--------- Begin of function Unit::think_independent_hero --------// // void Unit::think_independent_hero() { //------ think about go to serve a kingdom -------// int bestNationRecno=0, curRating; int bestRating = (skill_level() + combat_level()/2) / 3; if( item.id ) bestRating += (item_res.rareness(item.id)+1) * 10; //------------------------------------------------// int i; for( i=nation_array.size() ; i>0 ; i-- ) { if( nation_array.is_deleted(i) ) continue; Nation* nationPtr = nation_array[i]; curRating = (int) nationPtr->reputation + nationPtr->overall_rating; if( sprite_recno%2==0 ) // some heroes look at kill_monster_score, but some don't curRating += (int) nationPtr->kill_monster_score/10; if( race_id == nationPtr->race_id ) curRating += 10; if( curRating > bestRating ) { bestRating = curRating; bestNationRecno = i; } } if( bestNationRecno ) { //------ change nation now --------// if( !betray(bestNationRecno) ) return; //---- the unit moves close to the newly joined nation ----// ai_move_to_nearby_town(); return; } //---- randomly locate a destination to walk to ----// int xLoc, yLoc, regionId = region_id(); for( i=100 ; i>0 ; i-- ) { xLoc = m.random(MAX_WORLD_X_LOC); yLoc = m.random(MAX_WORLD_Y_LOC); Location* locPtr = world.get_loc(xLoc, yLoc); if( locPtr->walkable() && locPtr->region_id == regionId ) break; } if( i==0 ) return; move(xLoc, yLoc); }
//--------- Begin of function Unit::process_ai --------// // // [int] forceExecute - whether force execute all AI functions // without checking day interavals. // (default: 0) // void Unit::process_ai() { if( unit_mode ) // let functions in OUN_MODE.CPP process units in specific modes return; err_when( !nation_recno ); //------ the behavior_mode of AI units is aggressive ------// behavior_mode = UNIT_AGGRESSIVE; //------- 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 { 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; //----- think about using items -------// if( think_use_item() ) return; //---- 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; } //---- stop attacking a town with zero resistance ----// if( cur_order.mode==UNIT_ATTACK && nation_recno) { if( !base_obj_array.is_deleted(cur_order.para) ) { BaseObj* baseObj = base_obj_array[cur_order.para]; if( baseObj->cast_to_Town() && baseObj->cast_to_Town()->nation_recno==0 && baseObj->cast_to_Town()->resistance(nation_recno) < 1 ) { stop_order(); return; } } } //------ if the unit is not stop right now ------// if( !is_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 on a attack mission ----// if( is_all_stop() && in_ai_attack_mission ) { if( ai_attack_next_target() ) return; } //------ if this unit is from a camp --------// if( home_camp_firm_recno ) { FirmCamp* firmCamp; FirmMonsterFortress* firmMonsterFortress; int rc = 0; if( firm_array.is_deleted(home_camp_firm_recno) ) { rc = 0; } if( (firmCamp = firm_array[home_camp_firm_recno]->cast_to_FirmCamp()) ) { if( rank_id == RANK_SOLDIER ) rc = firmCamp->soldier_count < MAX_SOLDIER; else rc = !firmCamp->overseer_recno; } else if( (firmMonsterFortress = firm_array[home_camp_firm_recno]->cast_to_FirmMonsterFortress()) ) { rc = (unit_id == firmMonsterFortress->support_unit_id && !firmMonsterFortress->is_extra_builder_full()) || !firmMonsterFortress->is_soldier_full(); } else { err_here(); } if( rc ) { if( return_camp() ) return; } home_camp_firm_recno = 0; // the camp is already occupied by somebody } //------- if the unit is idle ------------// if( is_all_stop() ) { if( race_id && rank_id==RANK_KING ) { if( is_human() ) think_king_action(); else think_normal_monster_action(); } else if( race_id && rank_id==RANK_GENERAL ) { think_general_action(); } else { int unitClass = unit_res[unit_id]->unit_class; //------ if this unit is a weapon ------// // ######### begin Gilbert 24/3 ########// // BUGHERE : monster weapon was UNIT_CLASS_MONSTER but now UNIT_CLASS_MONS_WEAPON if( unitClass == UNIT_CLASS_WEAPON || unitClass == UNIT_CLASS_MONS_WEAPON ) // ######### end Gilbert 24/3 ########// { 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 --// } } //------ if this unit is a monster ------// else if( unitClass == UNIT_CLASS_MONSTER || unitClass == UNIT_CLASS_INSECT || unitClass == UNIT_CLASS_ANIMAL ) { //--- 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_monster_action() ) { ai_no_suitable_action = true; // set this flag so think_normal_human_action() won't be called continously ai_move_to_nearby_firm(FIRM_LAIR); } } //------ if this unit is a human ------// else if( unitClass == UNIT_CLASS_HUMAN ) { //--- 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 = true; // 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(); } } //---- if this unit is a wagon -----// else if( unitClass == UNIT_CLASS_WAGON ) { think_assign_human_to_town(); } } } }