//----- Begin of function Nation::think_eliminate_enemy_unit -----// // // This function is called to eliminate remaining enemy firms // when all enemy towns have been destroyed. // int Nation::think_eliminate_enemy_unit(int enemyNationRecno) { Unit *unitPtr; int hasWar; for( int i=unit_array.size() ; i>0 ; i-- ) { if( unit_array.is_deleted(i) ) continue; unitPtr = unit_array[i]; if( unitPtr->nation_recno != enemyNationRecno ) continue; if( !unitPtr->is_visible() || unitPtr->mobile_type != UNIT_LAND ) // only deal with land units now continue; //--- only attack if we have any base town in the enemy unit's region ---// if( base_town_count_in_region(unitPtr->region_id()) == 0 ) continue; //----- take into account of the mobile units around this town -----// int mobileCombatLevel = mobile_defense_combat_level(unitPtr->next_x_loc(), unitPtr->next_y_loc(), unitPtr->nation_recno, 1, hasWar); if( mobileCombatLevel == -1 ) // do not attack this town because a battle is already going on continue; return ai_attack_target(unitPtr->next_x_loc(), unitPtr->next_y_loc(), mobileCombatLevel + (int) unitPtr->unit_power()); } return 0; }
//--------- Begin of function Nation::attack_enemy_town_defense --------// // // Attack enemy's defending forces on the target town. // // <Town*> targetTown - the pointer to the target town. // [int] useAllCamp - whether use troops in all camps to attack the enemy town // (default: 0) // // return: <int> 1 - a troop has been sent to attack the target. // 0 - we don't have sufficient troops for attacking the target. // -1 - no defense on the target town, no attacking is needed. // int Nation::attack_enemy_town_defense(Town* targetTown, int useAllCamp) { err_when( targetTown->nation_recno == nation_recno ); // cannot attack itself if( targetTown->nation_recno == 0 ) return -1; //--- if there are any command bases linked to the town, attack them first ---// int campCombatLevel, maxCampCombatLevel= -1; Firm *firmPtr, *bestTargetFirm=NULL; for( int i=targetTown->linked_firm_count-1 ; i>=0 ; i-- ) { firmPtr = firm_array[ targetTown->linked_firm_array[i] ]; if( firmPtr->nation_recno == targetTown->nation_recno && firmPtr->firm_id == FIRM_CAMP ) { campCombatLevel = ((FirmCamp*)firmPtr)->total_combat_level(); if( campCombatLevel > maxCampCombatLevel ) { maxCampCombatLevel = campCombatLevel; bestTargetFirm = firmPtr; } } } //----- get the defense combat level of the mobile units around the town ----// int hasWar; int townMobileCombatLevel = mobile_defense_combat_level(targetTown->center_x, targetTown->center_y, targetTown->nation_recno, 0, hasWar); int totalDefenseCombatLevel = maxCampCombatLevel + townMobileCombatLevel; //----------------------------------------// if( bestTargetFirm ) { Nation* targetNation = nation_array[bestTargetFirm->nation_recno]; if( targetNation->is_at_war() ) // use all camps force if the nation is at war useAllCamp = 1; return ai_attack_target(bestTargetFirm->loc_x1, bestTargetFirm->loc_y1, totalDefenseCombatLevel, 0, 0, 0, 0, useAllCamp ); } else { //--- if there are any mobile defense force around the town ----// if( townMobileCombatLevel > 0 ) return ai_attack_target(targetTown->center_x, targetTown->center_y, totalDefenseCombatLevel, 0, 1 ); // 1-just all move there and wait for the units to attack the enemies automatically } return -1; }
//--------- Begin of function Nation::think_monster_target --------// // // Think about the best monster target in the given region. // // <int&> targetCombatLevel - var for returning the total combat level of the target firm. // int Nation::think_monster_target(int& targetCombatLevel) { if( !largest_town_recno ) return 0; Town* largestTown = town_array[largest_town_recno]; Firm* firmPtr; int combatLevel; int curRating, bestRating= -10000, bestFirmRecno=0, hasWar; for( int firmRecno=firm_array.size() ; firmRecno>0 ; firmRecno-- ) { if( firm_array.is_deleted(firmRecno) ) continue; firmPtr = firm_array[firmRecno]; if( firmPtr->firm_id != FIRM_MONSTER || firmPtr->region_id != largestTown->region_id ) { continue; } //----- take into account of the mobile units around this town -----// int mobileCombatLevel = mobile_defense_combat_level(firmPtr->center_x, firmPtr->center_y, firmPtr->nation_recno, 1, hasWar); if( mobileCombatLevel == -1 ) // do not attack this town because a battle is already going on continue; curRating = 3 * misc.points_distance( largestTown->center_x, largestTown->center_y, firmPtr->center_x, firmPtr->center_y ); combatLevel = mobileCombatLevel + ((FirmMonster*)firmPtr)->total_combat_level(); curRating -= combatLevel; //---------------------------------// if( curRating > bestRating ) { targetCombatLevel = combatLevel; bestRating = curRating; bestFirmRecno = firmRecno; } } return bestFirmRecno; }
//----- Begin of function Nation::think_eliminate_enemy_firm -----// // // This function is called to eliminate remaining enemy firms // when all enemy towns have been destroyed. // int Nation::think_eliminate_enemy_firm(int enemyNationRecno) { //---- look for enemy firms to attack ----// int hasWar; Firm *firmPtr; for( int i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) ) continue; firmPtr = firm_array[i]; if( firmPtr->nation_recno != enemyNationRecno ) continue; //--- only attack if we have any base town in the enemy firm's region ---// if( base_town_count_in_region(firmPtr->region_id)==0 ) continue; //----- take into account of the mobile units around this town -----// int mobileCombatLevel = mobile_defense_combat_level(firmPtr->center_x, firmPtr->center_y, firmPtr->nation_recno, 1, hasWar); if( mobileCombatLevel == -1 ) // do not attack this town because a battle is already going on continue; //---- calculate the combat level of this target firm ----// int firmCombatLevel; if( firmPtr->firm_id == FIRM_CAMP ) // other civilian firms firmCombatLevel = ((FirmCamp*)firmPtr)->total_combat_level(); else firmCombatLevel = firmPtr->worker_count * 10; // civilian firms have very low combat level return ai_attack_target(firmPtr->loc_x1, firmPtr->loc_y1, mobileCombatLevel + firmCombatLevel); } return 0; }
//--------- Begin of function Nation::enemy_town_combat_level --------// // // <Town*> targetTown - the target town // <int> returnIfWar - return -1 if there is any war around the town // <int&> hasWar - a reference var for returning whether there is any war // // return: <int> the enemy's total defense combat level minus the player's // combat level. /// return -1 if there is war and returnIfWar is 1 // int Nation::enemy_town_combat_level(Town* targetTown, int returnIfWar, int hasWar) { int enemyCombatLevel = mobile_defense_combat_level(targetTown->center_x, targetTown->center_y, targetTown->nation_recno, returnIfWar, hasWar); //0-don't return even there are wars around the town if( enemyCombatLevel < 0 ) // there is a war going on return -1; //---- calculate the attack rating of this target town ----// // enemyCombatLevel += targetTown->jobless_population * 5; //**BUGHERE //--- calculate the combat level of enemy camps linked to this town ---// Firm* firmPtr; for( int i=targetTown->linked_firm_count-1 ; i>=0 ; i-- ) { firmPtr = firm_array[ targetTown->linked_firm_array[i] ]; if( firmPtr->nation_recno == targetTown->nation_recno && firmPtr->firm_id == FIRM_CAMP ) { enemyCombatLevel += ((FirmCamp*)firmPtr)->total_combat_level(); } } /* //----- add this and neighbor town's needed combat level ----// Town* townPtr; for( i=targetTown->linked_town_count-1 ; i>=0 ; i-- ) { townPtr = town_array[ targetTown->linked_town_array[i] ]; if( townPtr->nation_recno == targetTown->nation_recno ) //**BUGHERE enemyCombatLevel += townPtr->jobless_population * 5; } */ return enemyCombatLevel; }
//----- Begin of function Nation::think_eliminate_enemy_town -----// // // This function is called to eliminate remaining enemy firms // when all enemy towns have been destroyed. // int Nation::think_eliminate_enemy_town(int enemyNationRecno) { //---- look for enemy firms to attack ----// int hasWar; Town *townPtr; for( int i=town_array.size() ; i>0 ; i-- ) { if( town_array.is_deleted(i) ) continue; townPtr = town_array[i]; if( townPtr->nation_recno != enemyNationRecno ) continue; //--- only attack if we have any base town in the enemy town's region ---// if( base_town_count_in_region(townPtr->region_id)==0 ) continue; //----- take into account of the mobile units around this town -----// int mobileCombatLevel = mobile_defense_combat_level(townPtr->center_x, townPtr->center_y, townPtr->nation_recno, 1, hasWar); if( mobileCombatLevel == -1 ) // do not attack this town because a battle is already going on continue; //---- calculate the combat level of this target town ----// int townCombatLevel = townPtr->protection_available(); return ai_attack_target(townPtr->loc_x1, townPtr->loc_y1, mobileCombatLevel + townCombatLevel); } return 0; }
//--------- Begin of function Nation::enemy_firm_combat_level --------// // // <Firm*> targetFirm - the target firm // <int> returnIfWar - return -1 if there is any war around the town // <int&> hasWar - a reference var for returning whether there is any war // // return: <int> the enemy's total defense combat level minus the player's // combat level. /// return -1 if there is war and returnIfWar is 1 // int Nation::enemy_firm_combat_level(Firm* targetFirm, int returnIfWar, int hasWar) { int enemyCombatLevel = mobile_defense_combat_level(targetFirm->center_x, targetFirm->center_y, targetFirm->nation_recno, returnIfWar, hasWar); //0-don't return even there are wars around the town if( enemyCombatLevel < 0 ) // there is a war going on return -1; //--- calculate the combat level of enemy camps linked to this towns that are linked to this mine ---// Town* linkedTown; Firm* firmPtr; int targetNationRecno = targetFirm->nation_recno; //---- scan towns linked to this mine -----// for( int i=targetFirm->linked_town_count-1 ; i>=0 ; i-- ) { linkedTown = town_array[ targetFirm->linked_town_array[i] ]; if( linkedTown->nation_recno != targetNationRecno ) continue; //------ scan firms linked to this town -------// for( int j=linkedTown->linked_firm_count-1 ; j>=0 ; j-- ) { firmPtr = firm_array[ linkedTown->linked_firm_array[j] ]; if( firmPtr->nation_recno == targetNationRecno && firmPtr->firm_id == FIRM_CAMP ) { enemyCombatLevel += ((FirmCamp*)firmPtr)->total_combat_level(); } } } return enemyCombatLevel; }
//--------- Begin of function Nation::think_destroy_raw_site_guard --------// // int Nation::think_destroy_raw_site_guard() { Site* sitePtr; Location* locPtr; Unit* unitPtr; for( int i=site_array.size() ; i>0 ; i-- ) { if( site_array.is_deleted(i) ) continue; sitePtr = site_array[i]; //--- if there is already a mine built on this raw site ---// if( sitePtr->has_mine ) continue; //----- if there is a unit standing on this site -----// locPtr = world.get_loc( sitePtr->map_x_loc, sitePtr->map_y_loc ); if( !locPtr->unit_recno(UNIT_LAND) ) continue; unitPtr = unit_array[ locPtr->unit_recno(UNIT_LAND) ]; if( unitPtr->cur_action != SPRITE_IDLE ) // only attack if this unit is idle continue; if( unitPtr->nation_recno == nation_recno ) // don't attack our own units continue; //------ check if we have a presence in this region ----// if( is_human() && base_town_count_in_region(sitePtr->region_id) == 0 ) continue; //------ check the relationship with this unit ------// // // If we are friendly with this nation, don't attack it. // //---------------------------------------------------// if( get_relation_status(unitPtr->nation_recno) >= RELATION_FRIENDLY ) continue; //--------- attack the enemy unit ---------// int hasWar; int enemyCombatLevel = mobile_defense_combat_level( sitePtr->map_x_loc, sitePtr->map_y_loc, unitPtr->nation_recno, 1, hasWar ); if( enemyCombatLevel == - 1 ) // a war is going on here, don't attack this target continue; if( ai_attack_target(sitePtr->map_x_loc, sitePtr->map_y_loc, enemyCombatLevel, 0, 0, 0, 0, 1) ) // 1-use all camps return 1; } return 0; }
void Nation::think_capturing_enemy_town() { if( !ai_capture_enemy_town_recno ) return; if( town_array.is_deleted(ai_capture_enemy_town_recno) || town_array[ai_capture_enemy_town_recno]->nation_recno == nation_recno ) // this town has been captured already { ai_capture_enemy_town_recno = 0; return; } //--- check the enemy's mobile defense combat level around the town ---// Town* targetTown = town_array[ai_capture_enemy_town_recno]; int hasWar; int mobileCombatLevel = mobile_defense_combat_level(targetTown->center_x, targetTown->center_y, targetTown->nation_recno, 0, hasWar); // 0-don't return immediately even if there is war around this town //---- if we haven't started attacking the town yet -----// if( !ai_capture_enemy_town_start_attack_date ) { if( hasWar==2 ) // we are at war with the nation now ai_capture_enemy_town_start_attack_date = info.game_date; if( info.game_date > ai_capture_enemy_town_plan_date + 90 ) // when 3 months have gone and there still hasn't been any attack on the town, there must be something bad happened to our troop, cancel the entire action ai_capture_enemy_town_recno = 0; return; // do nothing if the attack hasn't started yet } //--------- check if we need reinforcement --------// //-----------------------------------------------------------// // Check how long we have started attacking because only // when the it has been started for a while, our force // will reach the target and the offensive and defensive force // total can be calculated accurately. //-----------------------------------------------------------// if( info.game_date - ai_capture_enemy_town_start_attack_date >= 15 ) { //-------- check if we need any reinforcement --------// if( mobileCombatLevel > 0 && hasWar==2 ) // we are still in war with the enemy { ai_attack_target(targetTown->center_x, targetTown->center_y, mobileCombatLevel, 0, 1 ); // 1-just all move there and wait for the units to attack the enemies automatically return; } } //----- there is currently no war at the town -----// // // - either we are defeated or we have destroyed their command base. // //--------------------------------------------------// if( hasWar != 2 ) { //---- attack enemy's defending forces on the target town ----// int rc = attack_enemy_town_defense(targetTown, ai_capture_enemy_town_use_all_camp); if( rc == 1 ) // 1 means a troop has been sent to attack the town { ai_capture_enemy_town_start_attack_date = 0; return; } //---------- reset the vars --------// ai_capture_enemy_town_recno = 0; ai_capture_enemy_town_start_attack_date = 0; //--------- other situations --------// if( rc == -1 ) // -1 means no defense on the target town, no attacking is needed. { start_capture( targetTown->town_recno ); // call AI functions in OAI_CAPT.CPP to capture the town } // 0 means we don't have enough troop to attack the enemy } }
//----- Begin of function Nation::consider_military_aid -----// // int Nation::consider_military_aid(TalkMsg* talkMsg) { Nation* fromNation = nation_array[talkMsg->from_nation_recno]; NationRelation* fromRelation = get_relation(talkMsg->from_nation_recno); //----- don't aid too frequently ------// if( info.game_date < fromRelation->last_military_aid_date + 200 - pref_allying_tendency ) return 0; //------- only when the AI relation >= 60 --------// if( fromRelation->ai_relation_level < 60 ) return 0; //--- if the requesting nation is not at war now ----// if( !fromNation->is_at_war() ) return 0; //---- can't aid if we are at war ourselves -----// if( is_at_war() ) return 0; //--- if the nation is having a financial difficulty, it won't agree ---// if( cash < 2000 * pref_cash_reserve / 100 ) return 0; //----- can't aid if we are too weak ourselves ---// if( ai_general_count*10 + total_human_count + total_monster_count < 100-pref_military_courage/2 ) { return 0; } //----- see what units are attacking the nation -----// if( unit_array.is_deleted(fromNation->last_attacker_obj_recno) ) return 0; BaseObj* baseObj = base_obj_array[ fromNation->last_attacker_obj_recno ]; if( baseObj->nation_recno == nation_recno ) // if it's our own units return 0; if( baseObj->nation_recno == 0 ) return 0; if( !baseObj->is_visible() ) return 0; //------ only attack if it's a common enemy to us and our ally -----// if( get_relation(baseObj->nation_recno)->status != RELATION_HOSTILE ) return 0; //------- calculate the combat level of the target units there ------// int hasWar; int targetCombatLevel = mobile_defense_combat_level( baseObj->obj_loc_x1(), baseObj->obj_loc_y1(), baseObj->nation_recno, 0, hasWar ); if( ai_attack_target(baseObj->obj_loc_x1(), baseObj->obj_loc_y1(), targetCombatLevel, 0, 1 ) ) //0-not defense mode, 1-just move to flag { fromRelation->last_military_aid_date = info.game_date; return 1; } return 0; }