//------- Begin of function FirmHarbor::think_build_firm -----------// // void FirmHarbor::think_build_firm() { Nation* ownNation = nation_array[nation_recno]; if( ownNation->cash < 2000 ) // don't build if the cash is too low return; if( ownNation->true_profit_365days() < (50-ownNation->pref_use_marine)*20 ) // -1000 to +1000 return; //----- think about building markets ------// if( ownNation->pref_trading_tendency >= 60 ) { if( ai_build_firm(FIRM_MARKET) ) return; } //----- think about building camps ------// if( ownNation->pref_military_development/2 + (linked_firm_count + ownNation->ai_ship_count + ship_count) * 10 + ownNation->total_jobless_population*2 > 150 ) { ai_build_firm(FIRM_CAMP); } }
int Unit::think_normal_monster_action() { if( home_camp_firm_recno ) return 0; //--- if the entire nation does not have any lairs ----// Nation* nationPtr = nation_array[nation_recno]; if( nationPtr->is_monster() && ( nationPtr->ai_camp_count==0 || //---- If there are more units than the existing lairs can hold ---// nationPtr->total_camp_unit_space(0) <= nationPtr->total_unit_count ) ) { return ai_build_firm(); } //---- try to assign units to existing lairs -----// if( leader_unit_recno && unit_array[leader_unit_recno]->is_visible() ) // if the unit is led by a commander, let the commander makes the decision. If the leader has been assigned to a firm, don't consider it as a leader anymore { return 0; } return think_assign_soldier_to_camp(); }
int Unit::think_normal_human_action() { if( home_camp_firm_recno ) return 0; //-- if we also don't have any existing camps in this region --// Nation* nationPtr = nation_array[nation_recno]; if( nationPtr->ai_camp_count==0 || nationPtr->total_camp_unit_space(0) <= nationPtr->total_unit_count ) // If there are more units than the existing forts can hold { if( ai_build_firm() ) return 1; } //--- the following are actions that are only performed if the unit is not led by a commander ---// if( leader_unit_recno && unit_array[leader_unit_recno]->is_visible() ) // if the unit is led by a commander, let the commander makes the decision. If the leader has been assigned to a firm, don't consider it as a leader anymore { return 0; } err_when( !race_id ); err_when( !nation_recno ); //--- if this is a military unit, think about assigning it to a camp or fort ---// if( !is_civilian() ) { if( think_assign_soldier_to_camp() ) return 1; } else { if( think_assign_human_to_town() ) return 1; } return 0; }
//------- Begin of function Nation::process_action --------// // // [int] priorityActionRecno - if this is given, this specific action will // be processed first. Otherwise it will process // actions in the array in a sequential order. // // [int] processActionMode - if this is given, only message of this type // will be processed and all messages in the queued of this // type will be processed. // // Note: priorityActionRecno and processActionMode couldn't be used at // the same time. // // return: <int> 1 - all messages of the specific action mode are processed or all messages are processed // or the priority message has been processed. // int Nation::process_action(int priorityActionRecno, int processActionMode) { err_when( priorityActionRecno && processActionMode ); int actionRecno, rc, delFlag, doneFlag=0; int thisSessionProcessCount=0; // actions processed in this call session ActionNode* actionNode; int divider = 1-config.ai_aggressiveness; // the more nations there, the less process count int nationRecno = nation_recno; int maxSessionProcessCount = 70 / nation_array.nation_count / max(divider,1); for( actionRecno=1 ; actionRecno<=action_count() && (thisSessionProcessCount < maxSessionProcessCount || processActionMode) && !doneFlag ; // if processActionMode has been specific, then all messages in the queue of this type will be processed actionRecno++ ) { //----- priority action ------// if( priorityActionRecno ) { actionRecno = priorityActionRecno; doneFlag = 1; // mark it done, so if the function "continue" to the next loop, the function will end } if( is_action_deleted(actionRecno) ) continue; actionNode = get_action(actionRecno); //----- if only process specific action mode -----// if( processActionMode && actionNode->action_mode != processActionMode ) continue; //--- if the AI action is about processing diplomatic message ---// if( actionNode->action_mode == ACTION_AI_PROCESS_TALK_MSG && processActionMode != ACTION_AI_PROCESS_TALK_MSG ) { if( m.random(10) > 0 ) // 1/10 chance of processing the diplomatic messages continue; } //----------------------------------------------// if( actionNode->processing_instance_count == actionNode->instance_count ) { //---------------------------------------------// // // If this action has been marked processing for over 6 months // and we still haven't received finishing notifications, // then there may be some accidents (or bugs) happened, and // we will need to delete the action. // //---------------------------------------------// if( info.game_date > actionNode->add_date + 30 * 6 ) { del_action(actionRecno); actionRecno--; // stay in this array position as the current one has been deleted, the following one replace the current one's position } continue; } err_when( actionNode->processing_instance_count > actionNode->instance_count ); if( info.game_date < actionNode->next_retry_date && !priorityActionRecno ) // priorityAction bypass retry date checking continue; if( actionNode->retry_count==0 ) // the actionNode may still exist even when retry_count==0, waiting for processed_count to reach processing_count continue; //---- if the assigned unit has been deleted, cancel the action ----// if( actionNode->unit_recno && unit_array.is_deleted(actionNode->unit_recno) ) { del_action(actionRecno); actionRecno--; // stay in this array position as the current one has been deleted, the following one replace the current one's position continue; } //-- there is an unprocessing action in this waiting node --// switch( actionNode->action_mode ) { case ACTION_AI_BUILD_FIRM: rc = ai_build_firm(actionNode); break; case ACTION_AI_ASSIGN_OVERSEER: rc = ai_assign_overseer(actionNode); break; case ACTION_AI_ASSIGN_SOLDIER: rc = ai_assign_soldier(actionNode); break; case ACTION_AI_ASSIGN_SPY: rc = ai_assign_spy(actionNode); break; case ACTION_AI_SCOUT: rc = ai_scout(actionNode); break; case ACTION_AI_BUILD_TOWN: rc = ai_build_town(actionNode); break; case ACTION_AI_SETTLE_TOWN: rc = ai_settle_town(actionNode); break; case ACTION_AI_PROCESS_TALK_MSG: rc = ai_process_talk_msg(actionNode); break; /* case ACTION_AI_SEA_TRAVEL: err_here(); rc = ai_sea_travel(actionNode); break; case ACTION_AI_SEA_TRAVEL2: err_here(); rc = ai_sea_travel2(actionNode); break; case ACTION_AI_SEA_TRAVEL3: err_here(); rc = ai_sea_travel3(actionNode); break; */ } if( nation_array.is_deleted(nationRecno) ) // diplomatic option can result in surrendering return 0; thisSessionProcessCount++; //------ check the return result -------// delFlag = 0; if( rc==1 ) // the action has been processed, but not sure whether it is complete or not { actionNode->processing_instance_count++; //---------------------------------------------------// // for ACTION_DYNAMIC, the action is immediately // deleted when processing_instance_count == instance_count. //---------------------------------------------------// if( actionNode->action_type == ACTION_DYNAMIC ) { if( actionNode->processing_instance_count > actionNode->instance_count ) delFlag = 1; } } else if( rc==0 ) // action failed, retry { if( actionNode->unit_recno ) // if the action is associated with a unit, delete the action if it fails as the associated the unit will do anything before the next try and the action will become invalid { delFlag = 1; } else { actionNode->next_retry_date = info.game_date + 7; // try again one week later if( --actionNode->retry_count==0 ) delFlag = 1; err_when( actionNode->retry_count < 0 ); } } else if( rc== -1 ) // action failed, remove immediately if return -1 { actionNode->retry_count = 0; delFlag = 1; } //-----------------------------------------// if( delFlag && actionNode->processing_instance_count == actionNode->processed_instance_count ) // if processing_count > processed_count, do not remove this ActionNode, as there are some unit using this actionNode, when they finish or fail the action, processed_count will increase and processing_count will reach processed_count { del_action(actionRecno); actionRecno--; // stay in this array position as the current one has been deleted, the following one replace the current one's position } } return actionRecno > action_count() || doneFlag; }
int Unit::think_assign_human_to_town() { if( !is_human() ) return 0; //---- look for towns to assign to -----// Nation* ownNation = nation_array[nation_recno]; int curRating, bestRating=0; int hasTownInRegion=0; Town *townPtr, *bestTown=NULL; int regionId = world.get_region_id( next_x_loc(), next_y_loc() ); int curXLoc = next_x_loc(), curYLoc = next_y_loc(); for( int i=town_array.size() ; i>0 ; i-- ) // can't use ai_town_array[] because this function will be called by Unit::betray() when a unit defected to the player's kingdom { if( town_array.is_deleted(i) ) continue; townPtr = town_array[i]; if( townPtr->nation_recno != nation_recno ) continue; if( townPtr->region_id != regionId ) continue; if( !townPtr->can_accept_assign(sprite_recno) ) continue; hasTownInRegion = 1; //--- only assign to towns of the same race ---// if( ownNation->pref_town_defense > 50 ) { if( townPtr->majority_race() != race_id ) continue; } //-------- calculate the rating ---------// curRating = world.distance_rating(curXLoc, curYLoc, townPtr->center_x, townPtr->center_y ); curRating += MAX_TOWN_POPULATION - townPtr->population; //-------------------------------------// if( curRating > bestRating ) { bestRating = curRating; bestTown = townPtr; } } if( bestTown ) { assign(bestTown->loc_x1, bestTown->loc_y1); return 1; } //----- if we don't have any existing towns in this region ----// if( !hasTownInRegion ) { //--- if region is too small don't consider this area, stay in the island forever --// if( region_array[regionId]->region_stat_id == 0 ) return 0; //-- if we also don't have any existing camps in this region --// if( region_array.get_region_stat(regionId)->camp_nation_count_array[nation_recno-1]==0 ) { //---- try to build one if this unit can ----// if( !leader_unit_recno ) // if this unit is commanded by a leader, let the leader build the camp ai_build_firm(); } else // if there is already a camp in this region, try to settle a new town next to the camp { ai_settle_new_town(); } return 1; // if we don't have any town in this region, return 1, so this unit won't be resigned and so it can wait for other units to set up camps and villages later ---// } return 0; }