1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024 |
- /*
- * Seven Kingdoms: Ancient Adversaries
- *
- * Copyright 1997,1998 Enlight Software Ltd.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OAI_GRAN.CPP
- //Description: AI grand plans
- #include <OCONFIG.h>
- #include <OTALKRES.h>
- #include <ORACERES.h>
- #include <OREGIONS.h>
- #include <OF_CAMP.h>
- #include <ONATION.h>
- //----- Begin of function Nation::think_grand_plan -----//
- //
- void Nation::think_grand_plan()
- {
- think_deal_with_all_enemy();
- think_against_mine_monopoly();
- think_ally_against_big_enemy();
- }
- //------ End of function Nation::think_grand_plan ------//
- //----- Begin of function Nation::total_alliance_military -----//
- //
- // Return the total power of this nation and its friendly/allied
- // nation.
- //
- int Nation::total_alliance_military()
- {
- int totalPower = military_rank_rating();
- for( int i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) || i==nation_recno )
- continue;
- switch( get_relation_status(i) )
- {
- case NATION_ALLIANCE:
- totalPower += nation_array[i]->military_rank_rating() * 3 / 4; // 75%
- break;
- /*
- case NATION_FRIENDLY:
- totalPower += nation_array[i]->military_rank_rating() / 2; //50%
- break;
- */
- }
- }
- return totalPower;
- }
- //------ End of function Nation::total_alliance_military ------//
- //----- Begin of function Nation::total_enemy_military -----//
- //
- // Return the total power of this nation's enemies and potential
- // enemies.
- //
- int Nation::total_enemy_military()
- {
- Nation *nationPtr;
- int totalPower=0, relationStatus;
- // int relationStatus2, enemyRelationStatus;
- for( int i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) || i==nation_recno )
- continue;
- nationPtr = nation_array[i];
- relationStatus = get_relation_status(i);
- if( relationStatus == NATION_HOSTILE )
- {
- totalPower += nationPtr->military_rank_rating();
- }
- /*
- else
- {
- //--- check this nation's status with our enemies ---//
- enemyRelationStatus = 0;
- for( int j=nation_array.size() ; j>0 ; j-- )
- {
- if( nation_array.is_deleted(j) || j==nation_recno )
- continue;
- if( get_relation_status(j) != NATION_HOSTILE ) // only if this is one of our enemies.
- continue;
- //--- check if it is allied or friendly to any of our enemies ---//
- relationStatus2 = nationPtr->get_relation_status(j);
- if( relationStatus2 > enemyRelationStatus ) // Friendly will replace none, Alliance will replace Friendly
- enemyRelationStatus = relationStatus2;
- }
- if( enemyRelationStatus == NATION_ALLIANCE )
- totalPower += nationPtr->military_rank_rating() * 3 / 4; // 75%
- else if( enemyRelationStatus == NATION_FRIENDLY )
- totalPower += nationPtr->military_rank_rating() / 2; // 50%
- }
- */
- }
- return totalPower;
- }
- //------ End of function Nation::total_enemy_military ------//
- //----- Begin of function Nation::total_enemy_count -----//
- //
- int Nation::total_enemy_count()
- {
- int totalEnemy=0;
- for( int i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) || i==nation_recno )
- continue;
- if( get_relation_status(i) == NATION_HOSTILE )
- totalEnemy++;
- }
- return totalEnemy;
- }
- //------ End of function Nation::total_enemy_count ------//
- //----- Begin of function Nation::think_deal_with_all_enemy -----//
- //
- // Think about dealing with the enemy. The following are the
- // actions a nation can take to deal with its enemies.
- //
- // >ask our allies to attack the enemy.
- //
- // >try to break the enemy's existing alliance/friendly treaty with other
- // nations - to reduce its alliance strength.
- //
- // >convert enemy's allies to ours.
- //
- // >ask other nations to impose trade embargos on the enemy.
- //
- void Nation::think_deal_with_all_enemy()
- {
- Nation* nationPtr;
- int ourMilitary = military_rank_rating();
- int enemyCount = total_enemy_count();
- for( int i=1 ; i<=nation_array.size() ; i++ )
- {
- if( nation_array.is_deleted(i) || nation_recno == i )
- continue;
- if( get_relation_status(i) != NATION_HOSTILE )
- continue;
- nationPtr = nation_array[i];
- //------- think about eliminating the enemy ------//
- int rc = 0;
- if( nationPtr->total_population==0 ) // the enemy has no towns left
- rc = 1;
- if( enemyCount==1 &&
- ourMilitary > 100-pref_military_courage/5 ) // 80 to 100
- {
- int enemyMilitary = nationPtr->military_rank_rating();
- if( enemyMilitary < 20 && ai_should_spend_war(enemyMilitary) )
- rc = 1;
- }
- if( rc )
- {
- if( think_eliminate_enemy_firm(i) )
- continue;
- if( think_eliminate_enemy_town(i) )
- continue;
- think_eliminate_enemy_unit(i);
- continue;
- }
- //----- think about dealing with the enemy with diplomacy -----//
- think_deal_with_one_enemy(i);
- }
- }
- //------ End of function Nation::think_deal_with_all_enemy ------//
- //----- Begin of function Nation::think_deal_with_one_enemy -----//
- //
- void Nation::think_deal_with_one_enemy(int enemyNationRecno)
- {
- Nation* nationPtr;
- NationRelation* nationRelation;
- for( int i=1 ; i<=nation_array.size() ; i++ )
- {
- if( nation_array.is_deleted(i) || nation_recno == i )
- continue;
- nationPtr = nation_array[i];
- nationRelation = nationPtr->get_relation(nation_recno);
- //--- if this nation is already allied to us, request it to declare war with the enemy ---//
- if( nationRelation->status == NATION_ALLIANCE &&
- nationPtr->get_relation_status(enemyNationRecno) != NATION_HOSTILE )
- {
- if( should_diplomacy_retry(TALK_REQUEST_DECLARE_WAR, i) )
- {
- talk_res.ai_send_talk_msg(i, nation_recno, TALK_REQUEST_DECLARE_WAR, enemyNationRecno);
- continue;
- }
- }
- //---- if this nation is not friendly or alliance to our enemy ----//
- if( nationPtr->get_relation_status(enemyNationRecno) < NATION_FRIENDLY )
- {
- //--- and this nation is neutral or friendly with us ---//
- if( nationRelation->status >= NATION_NEUTRAL &&
- nationPtr->get_relation(enemyNationRecno)->trade_treaty )
- {
- //--- ask it to join a trade embargo on the enemy ---//
- if( should_diplomacy_retry(TALK_REQUEST_TRADE_EMBARGO, i) )
- talk_res.ai_send_talk_msg(i, nation_recno, TALK_REQUEST_TRADE_EMBARGO, enemyNationRecno );
- }
- }
- else //---- if this nation is friendly or alliance to our enemy ----//
- {
- //----- and this nation is not at war with us -----//
- if( nationRelation->status != NATION_HOSTILE )
- {
- //--- if we do not have trade treaty with this nation, propose one ---//
- if( !nationRelation->trade_treaty )
- {
- if( should_diplomacy_retry(TALK_PROPOSE_TRADE_TREATY, i) )
- talk_res.ai_send_talk_msg(i, nation_recno, TALK_PROPOSE_TRADE_TREATY );
- }
- else //--- if we already have a trade treaty with this nation ---//
- {
- // if this nation is already friendly to us, propose an alliance treaty now --//
- if( nationRelation->status == NATION_FRIENDLY )
- {
- if( should_diplomacy_retry(TALK_PROPOSE_ALLIANCE_TREATY, i) )
- talk_res.ai_send_talk_msg(i, nation_recno, TALK_PROPOSE_ALLIANCE_TREATY );
- }
- //-- if the nation has significiant trade with us, propose a friendly treaty now --//
- else if( nationPtr->trade_rating(nation_recno) > 10 ||
- nationPtr->ai_trade_with_rating(nation_recno) >= 50 ) // or if the product complement each other very well
- {
- if( should_diplomacy_retry(TALK_PROPOSE_FRIENDLY_TREATY, i) )
- talk_res.ai_send_talk_msg(i, nation_recno, TALK_PROPOSE_FRIENDLY_TREATY );
- }
- }
- }
- }
- }
- }
- //------ End of function Nation::think_deal_with_one_enemy ------//
- //----- Begin of function Nation::think_surrender -----//
- //
- int Nation::think_surrender()
- {
- //--- don't surrender if the nation still has a town ---//
- int rc=0;
- if( total_population == 0 )
- rc = 1;
- if( cash <= 0 && income_365days()==0 )
- rc = 1;
- if( !rc )
- return 0;
- //---- see if there is any nation worth getting our surrender ---//
- Nation* nationPtr;
- int curRating, bestRating=0, bestNationRecno=0;
- if( !king_unit_recno ) // if there is no successor to the king, the nation will tend more to surrender
- bestRating = -100;
- for( int i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) || i==nation_recno )
- continue;
- nationPtr = nation_array[i];
- if( nationPtr->cash <= 300 ) // don't surrender to an ecnomically handicapped nation
- continue;
- curRating = ai_surrender_to_rating(i);
- //--- if the nation will tend to surrender if there is only a small number of units left ---//
- curRating += 50 - total_unit_count*5;
- if( curRating > bestRating )
- {
- bestRating = curRating;
- bestNationRecno = i;
- }
- }
- //---------------------------------------//
- if( bestNationRecno )
- {
- surrender(bestNationRecno);
- return 1;
- }
- return 0;
- }
- //------ End of function Nation::think_surrender ------//
- //----- Begin of function Nation::think_unite_against_big_enemy -----//
- //
- int Nation::think_unite_against_big_enemy()
- {
- if( info.game_date - info.game_start_date <
- 365 * 3 * (100+pref_military_development) / 100 ) // only do this after 3 to 6 years into the game
- {
- return 0;
- }
- //-----------------------------------------------//
- if( config.ai_aggressiveness < OPTION_HIGH )
- return 0;
- if( config.ai_aggressiveness == OPTION_HIGH )
- {
- if( m.random(10)!=0 )
- return 0;
- }
- else // OPTION_VERY_HIGH
- {
- if( m.random(5)!=0 )
- return 0;
- }
- //---------------------------------------//
- int enemyNationRecno = nation_array.max_overall_nation_recno;
- if( !enemyNationRecno )
- return 0;
- Nation* enemyNation = nation_array[enemyNationRecno];
- //----- only against human players -----//
- if( enemyNation->is_ai() )
- return 0;
- //---- find the overall rank rating of the second most powerful computer kingdom ---//
- Nation* nationPtr;
- int secondBestOverall=0, secondBestNationRecno=0;
- for( int i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) || i==enemyNationRecno )
- continue;
- nationPtr = nation_array[i];
- if( !nationPtr->is_ai() ) // don't count human players
- continue;
- if( nationPtr->overall_rank_rating() > secondBestOverall )
- {
- secondBestOverall = nationPtr->overall_rank_rating();
- secondBestNationRecno = i;
- }
- }
- if( !secondBestNationRecno || secondBestNationRecno==nation_recno )
- return 0;
- //------- don't surrender to hostile nation -------//
- if( get_relation_status(secondBestNationRecno) < NATION_NEUTRAL )
- return 0;
- //--- if all AI kingdoms are way behind the human players, unite to against the human player ---//
- int compareRating;
- if( config.ai_aggressiveness == OPTION_HIGH )
- compareRating = 50;
- else // OPTION_VERY_AGGRESSIVE
- compareRating = 80;
- if( secondBestOverall < compareRating &&
- secondBestNationRecno != nation_recno )
- {
- surrender(secondBestNationRecno);
- return 1;
- }
- return 0;
- }
- //------ End of function Nation::think_unite_against_big_enemy ------//
- //----- Begin of function Nation::ai_surrender_to_rating -----//
- //
- // return a rating on how much the nation will tend to surrender
- // to the specific nation.
- //
- int Nation::ai_surrender_to_rating(int nationRecno)
- {
- Nation* nationPtr = nation_array[nationRecno];
- NationRelation* nationRelation = get_relation(nationRecno);
- //--- higher tendency to surrender to a powerful nation ---//
- int curRating = nationPtr->overall_rank_rating() - overall_rank_rating();
- curRating += (nationRelation->ai_relation_level-40);
- curRating += (int) nationRelation->good_relation_duration_rating*3;
- curRating += (int) nationPtr->reputation/2;
- //------ shouldn't surrender to an enemy --------//
- if( nationRelation->status == NATION_HOSTILE )
- curRating -= 100;
- //--- if the race of the kings are the same, the chance is higher ---//
- if( race_res.is_same_race( nationPtr->race_id, race_id ) )
- curRating += 20;
- return curRating;
- }
- //------ End of function Nation::ai_surrender_to_rating ------//
- //----- 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;
- }
- //------ End of function Nation::think_eliminate_enemy_town ------//
- //----- 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;
- }
- //------ End of function Nation::think_eliminate_enemy_firm ------//
- //----- 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;
- }
- //------ End of function Nation::think_eliminate_enemy_unit ------//
- //----- Begin of function Nation::think_ally_against_big_enemy -----//
- //
- // Think about allying against a big enemy
- //
- int Nation::think_ally_against_big_enemy()
- {
- if( info.game_date < info.game_start_date + 365 + nation_recno*70 ) // don't ask for tribute too soon, as in the beginning, the ranking are all the same for all nations
- return 0;
- //---------------------------------------//
- int enemyNationRecno = nation_array.max_overall_nation_recno;
- if( enemyNationRecno == nation_recno )
- return 0;
- //-- if AI aggressiveness > high, only deal against the player, but not other kingdoms ---//
- if( config.ai_aggressiveness >= OPTION_HIGH )
- {
- if( nation_array[enemyNationRecno]->is_ai() )
- return 0;
- }
- //-- if AI aggressiveness is low, don't do this against the human player --//
- else if( config.ai_aggressiveness == OPTION_LOW )
- {
- if( !nation_array[enemyNationRecno]->is_ai() )
- return 0;
- }
- //--- increase the ai_relation_level towards other nations except the enemy so we can ally against the enemy ---//
- Nation* enemyNation = nation_array[enemyNationRecno];
- int incRelationLevel = (100-overall_rank_rating())/10;
- int i;
- for( i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) )
- continue;
- if( i==nation_recno || i==enemyNationRecno )
- continue;
- int thisIncLevel = incRelationLevel * (100-get_relation(i)->ai_relation_level) / 100;
- change_ai_relation_level( i, thisIncLevel );
- }
- //---- don't have all nations doing it the same time ----//
- if( m.random(nation_array.ai_nation_count)==0 )
- return 0;
- //---- if the trade rating is high, stay war-less with it ----//
- if( trade_rating(enemyNationRecno) +
- ai_trade_with_rating(enemyNationRecno) > 100 - pref_trading_tendency/3 )
- {
- return 0;
- }
- //---- if the nation relation level is still high, then request aid/tribute ----//
- NationRelation* nationRelation = get_relation(enemyNationRecno);
- if( nationRelation->ai_relation_level > 30 )
- {
- int talkId;
- if( nationRelation->status >= NATION_FRIENDLY )
- talkId = TALK_DEMAND_AID;
- else
- talkId = TALK_DEMAND_TRIBUTE;
- if( should_diplomacy_retry(talkId, enemyNationRecno) )
- {
- static short aidAmountArray[] = { 500, 1000, 2000 };
- int aidAmount = aidAmountArray[m.random(3)];
- talk_res.ai_send_talk_msg(enemyNationRecno, nation_recno, talkId, aidAmount);
- }
- return 0;
- }
- //-------------------------------------//
- Nation* nationPtr;
- NationRelation *ourNationRelation, *enemyNationRelation;
- for( i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) )
- continue;
- if( i==nation_recno || i==enemyNationRecno )
- continue;
- nationPtr = nation_array[i];
- ourNationRelation = get_relation(i);
- enemyNationRelation = enemyNation->get_relation(i);
- }
- return 0;
- }
- //------ End of function Nation::think_ally_against_big_enemy ------//
- //----- Begin of function Nation::ai_should_attack_friendly -----//
- //
- // This function returns whether this nation should attack
- // the given friendly nation.
- //
- // <int> friendlyNationRecno - the nation recno of the friendly nation.
- // <int> attackTemptation - a rating from 0 to 100 indicating
- // temptation of attacking the target.
- //
- int Nation::ai_should_attack_friendly(int friendlyNationRecno, int attackTemptation)
- {
- Nation *friendlyNation = nation_array[friendlyNationRecno];
- NationRelation *nationRelation = get_relation(friendlyNationRecno);
- //--- don't change terminate treaty too soon ---//
- if( info.game_date < nationRelation->last_change_status_date+60+pref_honesty/2 ) // only after 60 to 110 days
- return 0;
- //------------------------------------------------//
- int resistanceRating = friendlyNation->military_rank_rating()
- - military_rank_rating();
- resistanceRating += nationRelation->ai_relation_level - 50;
- resistanceRating += trade_rating(friendlyNationRecno);
- return attackTemptation > resistanceRating;
- }
- //------ End of function Nation::ai_should_attack_friendly ------//
- //----- Begin of function Nation::ai_end_treaty -----//
- //
- // Terminate the treaty with the given nation.
- //
- // <int> nationRecno - the nation to terminate treaty with.
- //
- void Nation::ai_end_treaty(int nationRecno)
- {
- NationRelation *nationRelation = get_relation(nationRecno);
- err_when( nationRelation->status < NATION_FRIENDLY );
- if( nationRelation->status == NATION_FRIENDLY )
- {
- talk_res.ai_send_talk_msg(nationRecno, nation_recno, TALK_END_FRIENDLY_TREATY, 0, 0, 1); // 1-force send
- }
- else if( nationRelation->status == NATION_ALLIANCE )
- {
- talk_res.ai_send_talk_msg(nationRecno, nation_recno, TALK_END_ALLIANCE_TREATY, 0, 0, 1);
- }
- err_when( nationRelation->status >= NATION_FRIENDLY ); // when the status is still friendly or alliance
- }
- //------ End of function Nation::ai_end_treaty ------//
- //----- Begin of function Nation::ai_has_enough_food -----//
- //
- // return whether this nation has enough food or not.
- //
- int Nation::ai_has_enough_food()
- {
- return food > 2000 + 2000 * pref_food_reserve / 100
- || yearly_food_change() > 0;
- }
- //------ End of function Nation::ai_has_enough_food ------//
- //----- Begin of function Nation::think_attack_enemy_firm -----//
- //
- // Think about attacking a specific type of firm of a specific enemy.
- //
- int Nation::think_attack_enemy_firm(int enemyNationRecno, int firmId)
- {
- if( !largest_town_recno )
- return 0;
- Town* ourLargestTown = town_array[largest_town_recno];
- Nation *nationPtr = nation_array[enemyNationRecno];
- Firm *firmPtr, *targetFirm=NULL;
- int curRating, bestRating=0, targetCombatLevel, hasWar;
- for( int i=firm_array.size() ; i>0 ; i-- )
- {
- if( firm_array.is_deleted(i) )
- continue;
- firmPtr = firm_array[i];
- if( firmPtr->firm_id != firmId ||
- firmPtr->nation_recno != enemyNationRecno )
- {
- continue;
- }
- int combatLevel = enemy_firm_combat_level(firmPtr, 1, hasWar);
- if( combatLevel==0 ) // no protection with this mine
- {
- targetFirm = firmPtr;
- targetCombatLevel = combatLevel;
- break;
- }
- curRating = world.distance_rating( firmPtr->center_x, firmPtr->center_y,
- ourLargestTown->center_x, ourLargestTown->center_y );
- curRating += 1000 - combatLevel/5;
- if( curRating > bestRating )
- {
- bestRating = curRating;
- targetFirm = firmPtr;
- targetCombatLevel = combatLevel;
- }
- }
- if( !targetFirm )
- return 0;
- //---------------------------------------------//
- int useAllCamp=1;
- return ai_attack_target( targetFirm->loc_x1, targetFirm->loc_y1,
- targetCombatLevel, 0, 0, 0, 0, useAllCamp );
- }
- //------ End of function Nation::think_attack_enemy_firm ------//
- //----- Begin of function Nation::think_against_mine_monopoly -----//
- //
- int Nation::think_against_mine_monopoly()
- {
- //-- only think this after the game has been running for at least one year --//
- if( config.ai_aggressiveness < OPTION_HIGH ) // only attack if aggressiveness >= high
- return 0;
- if( info.game_date - info.game_start_date > 365 )
- return 0;
- if( profit_365days() > 0 ) // if we are making a profit, don't attack
- return 0;
- //-- for high aggressiveness, it will check cash before attack, for very high aggressiveness, it won't check cash before attack ---//
- if( config.ai_aggressiveness < OPTION_VERY_HIGH ) // only attack if aggressiveness >= high
- {
- if( cash > 2000 + 1000 * pref_cash_reserve / 100 ) // only attack if we run short of cash
- return 0;
- }
- //--------------------------------------------------------//
- if( !largest_town_recno )
- return 0;
- //--------------------------------------------------//
- int baseRegionId = town_array[largest_town_recno]->region_id;
- // ##### patch begin Gilbert 16/3 ########//
- //#ifdef AMPLUS
- // no region stat (region is too small), don't care
- if( !region_array[baseRegionId]->region_stat_id )
- return 0;
- //#endif
- // ##### end begin Gilbert 16/3 ########//
- RegionStat* regionStat = region_array.get_region_stat(baseRegionId);
- //---- if we already have a mine in this region ----//
- if( regionStat->mine_nation_count_array[nation_recno-1] > 0 )
- return 0;
- //----- if there is no mine in this region -----//
- if( regionStat->raw_count == 0 )
- return 0;
- //----- if enemies have occupied all mines -----//
- int mineCount, totalMineCount=0;
- int curRating, bestRating=0, targetNationRecno=0;
- int i;
- for( i=nation_array.size() ; i>0 ; i-- )
- {
- if( nation_array.is_deleted(i) )
- continue;
- //------ only deal with human players ------//
- if( nation_array[i]->is_ai() || i==nation_recno )
- continue;
- //------------------------------------------//
- mineCount = regionStat->mine_nation_count_array[i-1];
- totalMineCount += mineCount;
- curRating = mineCount * 100
- - get_relation(i)->ai_relation_level
- - trade_rating(i);
- if( curRating > bestRating )
- {
- bestRating = curRating;
- targetNationRecno = i;
- }
- }
- if( !targetNationRecno )
- return 0;
- //--- if the relationship with this nation is still good, don't attack yet, ask for aid first ---//
- NationRelation* nationRelation = get_relation(targetNationRecno);
- if( nationRelation->ai_relation_level > 30 )
- {
- int talkId;
- if( nationRelation->status >= NATION_FRIENDLY )
- talkId = TALK_DEMAND_AID;
- else
- talkId = TALK_DEMAND_TRIBUTE;
- if( should_diplomacy_retry(talkId, targetNationRecno) )
- {
- static short aidAmountArray[] = { 500, 1000, 2000 };
- int aidAmount = aidAmountArray[m.random(3)];
- talk_res.ai_send_talk_msg(targetNationRecno, nation_recno, talkId, aidAmount);
- }
- return 0;
- }
- //------- attack one of the target enemy's mines -------//
- Firm* firmPtr;
- for( i=firm_array.size() ; i>0 ; i-- )
- {
- if( firm_array.is_deleted(i) )
- continue;
- firmPtr = firm_array[i];
- if( firmPtr->firm_id != FIRM_MINE ||
- firmPtr->nation_recno != targetNationRecno ||
- firmPtr->region_id != baseRegionId )
- {
- continue;
- }
- //--------------------------------------------//
- int hasWar;
- int targetCombatLevel = enemy_firm_combat_level(firmPtr, 1, hasWar);
- return ai_attack_target( firmPtr->loc_x1, firmPtr->loc_y1,
- targetCombatLevel, 0, 0, 0, 0, 1 ); // 1-use all camps
- }
- return 0;
- }
- //------ End of function Nation::think_against_mine_monopoly ------//
|