/* * 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 . * */ //Filename : OAI_TALK.CPP //Description: AI routines on diplomacy. #include #include #include #include #include //-------- Declare static functions ---------// static int has_sent_same_msg(TalkMsg* talkMsg); //----- Begin of function Nation::ai_process_talk_msg -----// // // action_para - recno of the message in talk_res.talk_msg_array. // int Nation::ai_process_talk_msg(ActionNode* actionNode) { if( talk_res.is_talk_msg_deleted(actionNode->action_para) ) // if the talk message has been deleted return -1; TalkMsg* talkMsg = talk_res.get_talk_msg(actionNode->action_para); err_when( talkMsg->talk_id < 1 || talkMsg->talk_id > MAX_TALK_TYPE ); err_when( talkMsg->from_nation_recno == nation_recno ); err_when( talkMsg->to_nation_recno != nation_recno ); if( !talkMsg->is_valid_to_reply() ) // if it is no longer valid return -1; //----- call the consider function -------// if( talkMsg->reply_type == REPLY_WAITING ) { int rc = consider_talk_msg(talkMsg); if( rc==1 ) // if rc is not 1 or 0, than the consider function have processed itself, no need to call reply_talk_msg() here talk_res.reply_talk_msg( actionNode->action_para, REPLY_ACCEPT, COMMAND_AI ); else if( rc==0 ) talk_res.reply_talk_msg( actionNode->action_para, REPLY_REJECT, COMMAND_AI ); // don't reply if rc is neither 0 or 1 } else err_here(); return -1; // always return -1 to remove the action from action_array. } //------ End of function Nation::ai_process_talk_msg ------// //----- Begin of function Nation::consider_talk_msg -----// // int Nation::consider_talk_msg(TalkMsg* talkMsg) { //--------------------------------------------// // Whether the nation has already sent out a // message that is the same as the one it received. // If so, accept the message right now. //--------------------------------------------// switch( talkMsg->talk_id ) { case TALK_PROPOSE_TRADE_TREATY: case TALK_PROPOSE_FRIENDLY_TREATY: case TALK_PROPOSE_ALLIANCE_TREATY: case TALK_REQUEST_TRADE_EMBARGO: case TALK_REQUEST_CEASE_WAR: case TALK_REQUEST_DECLARE_WAR: if( has_sent_same_msg(talkMsg) ) return 1; }; //-------------------------------// switch( talkMsg->talk_id ) { case TALK_PROPOSE_TRADE_TREATY: return consider_trade_treaty(talkMsg->from_nation_recno) >= 0; // the returned value is the curRating - acceptRating, if >=0, means it accepts case TALK_PROPOSE_FRIENDLY_TREATY: return consider_friendly_treaty(talkMsg->from_nation_recno) >= 0; case TALK_PROPOSE_ALLIANCE_TREATY: return consider_alliance_treaty(talkMsg->from_nation_recno) >= 0; case TALK_REQUEST_MILITARY_AID: return consider_military_aid(talkMsg); case TALK_REQUEST_TRADE_EMBARGO: return consider_trade_embargo(talkMsg); case TALK_REQUEST_CEASE_WAR: return consider_cease_war(talkMsg->from_nation_recno) >= 0; case TALK_REQUEST_DECLARE_WAR: return consider_declare_war(talkMsg); case TALK_REQUEST_BUY_FOOD: return consider_sell_food(talkMsg); case TALK_GIVE_TRIBUTE: return consider_take_tribute(talkMsg); case TALK_DEMAND_TRIBUTE: return consider_give_tribute(talkMsg); case TALK_GIVE_AID: return consider_take_aid(talkMsg); case TALK_DEMAND_AID: return consider_give_aid(talkMsg); case TALK_GIVE_TECH: return consider_take_tech(talkMsg); case TALK_DEMAND_TECH: return consider_give_tech(talkMsg); case TALK_REQUEST_SURRENDER: return consider_accept_surrender_request(talkMsg); default: err_here(); return 0; } } //------ End of function Nation::consider_talk_msg ------// //----- Begin of function Nation::notify_talk_msg -----// // // Notify the AI for a notification only message (reply not needed.) // // This function is called directly from TalkRes::send_talk_msg_now() // when the message is sent. // void Nation::notify_talk_msg(TalkMsg* talkMsg) { int relationChange=0; NationRelation* nationRelation = get_relation(talkMsg->from_nation_recno); switch( talkMsg->talk_id ) { case TALK_END_TRADE_TREATY: // it's a notification message only, no accept or reject relationChange = -5; nationRelation->last_talk_reject_date_array[TALK_PROPOSE_TRADE_TREATY-1] = info.game_date; break; case TALK_END_FRIENDLY_TREATY: // it's a notification message only, no accept or reject case TALK_END_ALLIANCE_TREATY: relationChange = -5; nationRelation->last_talk_reject_date_array[TALK_PROPOSE_FRIENDLY_TREATY-1] = info.game_date; nationRelation->last_talk_reject_date_array[TALK_PROPOSE_ALLIANCE_TREATY-1] = info.game_date; break; case TALK_DECLARE_WAR: // it already drops to zero when the status is set to hostile break; case TALK_GIVE_TRIBUTE: case TALK_GIVE_AID: //--------------------------------------------------------------// // The less cash the nation, the more it will appreciate the // tribute. // // $1000 for 100 ai relation increase if the nation's cash is 1000. //--------------------------------------------------------------// relationChange = 100 * talkMsg->talk_para1 / max(1000, (int) cash); break; case TALK_GIVE_TECH: //--------------------------------------------------------------// // The lower tech the nation has, the more it will appreciate the // tech giveaway. // // Giving a level 2 weapon which the nation is unknown of // increase the ai relation by 60 if its pref_use_weapon is 100. // (by 30 if its pref_use_weapon is 0). //--------------------------------------------------------------// { int ownLevel = tech_res[talkMsg->talk_para1]->get_nation_tech_level(nation_recno); if( talkMsg->talk_para2 > ownLevel ) relationChange = 30 * (talkMsg->talk_para2-ownLevel) * (100+pref_use_weapon) / 200; break; } case TALK_SURRENDER: break; default: err_here(); } //------- chance relationship now -------// if( relationChange < 0 ) relationChange -= relationChange * pref_forgiveness / 100; if( relationChange != 0 ) change_ai_relation_level( talkMsg->from_nation_recno, relationChange ); } //------ End of function Nation::notify_talk_msg ------// //----- Begin of function Nation::consider_trade_treaty -----// // // Consider agreeing to open up trade with the given nation. // int Nation::consider_trade_treaty(int withNationRecno) { NationRelation* nationRelation = get_relation(withNationRecno); //---- don't accept new trade treaty soon when the trade treaty was terminated not too long ago ----// if( info.game_date < nationRelation->last_talk_reject_date_array[TALK_END_TRADE_TREATY-1] + 365 - pref_forgiveness ) return 0; //-- if we look forward to have a trade treaty with this nation ourselves --// if( nationRelation->ai_demand_trade_treaty ) return 1; return ai_trade_with_rating(withNationRecno) > 0; } //------ End of function Nation::consider_trade_treaty ------// //----- Begin of function Nation::ai_trade_with_rating -----// // // Return a rating from 0 to 100 indicating how important // will be for us to trade with the given nation. // int Nation::ai_trade_with_rating(int withNationRecno) { Nation* nationPtr = nation_array[withNationRecno]; int tradeRating=0; for( int i=0 ; iraw_count_array[i] ) tradeRating += min(30, nationPtr->total_population/3); //--------------------------------------------------------------// // // If the nation has the supply a raw material that we don't // have, then we can import it. // //--------------------------------------------------------------// else if( nationPtr->raw_count_array[i] && !raw_count_array[i] ) tradeRating += 30; } return tradeRating; } //------ End of function Nation::ai_trade_with_rating ------// //----- Begin of function Nation::consider_friendly_treaty -----// // int Nation::consider_friendly_treaty(int withNationRecno) { NationRelation* nationRelation = get_relation(withNationRecno); if( nationRelation->status >= NATION_FRIENDLY ) // already has a friendly relationship return -1; // -1 means don't reply if( nationRelation->ai_relation_level < 20 ) return -1; //------- some consideration first -------// if( !should_consider_friendly(withNationRecno) ) return -1; //------ total import and export amounts --------// int curRating = consider_alliance_rating(withNationRecno); int acceptRating = 60 - pref_allying_tendency/8 - pref_peacefulness/4; // range of acceptRating: 23 to 60 return curRating - acceptRating; } //------ End of function Nation::consider_friendly_treaty ------// //----- Begin of function Nation::consider_alliance_treaty -----// // int Nation::consider_alliance_treaty(int withNationRecno) { NationRelation* nationRelation = get_relation(withNationRecno); if( nationRelation->status >= NATION_ALLIANCE ) // already has a friendly relationship return -1; // -1 means don't reply if( nationRelation->ai_relation_level < 40 ) return -1; //------- some consideration first -------// if( !should_consider_friendly(withNationRecno) ) return -1; //------ total import and export amounts --------// int curRating = consider_alliance_rating(withNationRecno); int acceptRating = 80 - pref_allying_tendency/4 - pref_peacefulness/8; // range of acceptRating: 43 to 80 return curRating - acceptRating; } //------ End of function Nation::consider_alliance_treaty ------// //----- Begin of function Nation::consider_cease_war -----// // // This function is shared by think_request_cease_war(). // int Nation::consider_cease_war(int withNationRecno) { NationRelation* nationRelation = get_relation(withNationRecno); if( nationRelation->status != NATION_HOSTILE ) return -1; // -1 means don't reply //---- if we are attacking the nation, don't cease fire ----// if( ai_attack_target_nation_recno == withNationRecno ) return -1; //---- if we are planning to capture the enemy's town ---// if( ai_capture_enemy_town_recno && !town_array.is_deleted(ai_capture_enemy_town_recno) && town_array[ai_capture_enemy_town_recno]->nation_recno == withNationRecno ) { return -1; } //--- don't cease fire too soon after a war is declared ---// if( info.game_date < nationRelation->last_change_status_date + 60 + (100-pref_peacefulness) ) // more peaceful nation may cease fire sooner (but the minimum is 60 days). return -1; //------ if we're run short of money for war -----// Nation* withNation = nation_array[withNationRecno]; if( !ai_should_spend_war(withNation->military_rank_rating(), 1) ) // if we shouldn't spend any more on war, then return 1 return 1; //------------------------------------------------// int curRating = consider_alliance_rating(withNationRecno); //------------------------------------// // // Tend to be easilier to accept cease-fire if this nation's // military strength is weak. // // If the nation's peacefulness concern is high, it will // also be more likely to accept cease-fire. // //-------------------------------------// //--- if the enemy is more power than us, tend more to request cease-fire ---// curRating += total_enemy_military() - military_rank_rating(); curRating += ai_trade_with_rating(withNationRecno) * (100+pref_trading_tendency) / 300; // when we have excessive supply, we may want to cease-fire with our enemy curRating -= (military_rank_rating()-50)/2; // if our military ranking is high, we may like to continue the war, otherwise the nation should try to cease-fire curRating -= nationRelation->started_war_on_us_count*10; // the number of times this nation has started a war with us, the higher the number, the more unlikely we will accept cease-fire int acceptRating = pref_peacefulness/4; return curRating - acceptRating; } //------ End of function Nation::consider_cease_war ------// //----- Begin of function Nation::consider_sell_food -----// // // talkMsg->talk_para1 - qty of food wanted to buy. // talkMsg->talk_para2 - buying price offered for 10 food. // int Nation::consider_sell_food(TalkMsg* talkMsg) { int relationStatus = get_relation_status(talkMsg->from_nation_recno); if( relationStatus == NATION_HOSTILE ) return 0; //--- if after selling the food, the remaining is not enough for its own consumption for ? years ---// float newFood = food-talkMsg->talk_para1; float yearConsumption = (float) yearly_food_consumption(); int offeredAmount = talkMsg->talk_para2; int relationLevel = get_relation(talkMsg->from_nation_recno)->ai_relation_level; if( newFood < 1000 + 1000 * pref_food_reserve / 100 ) return 0; if( relationLevel >= 50 ) offeredAmount += 5; // increase the chance of selling food else if( relationLevel < 30 ) // decrease the chance of selling food offeredAmount -=5 ; //---- if we run short of cash, we tend to accept the offer ---// float fixedExpense = fixed_expense_365days(); if( cash < fixedExpense ) offeredAmount += (int) (20 * (fixedExpense-cash) / fixedExpense); //---------------------------------// float reserveYears = (float) (100+pref_food_reserve) / 100; // 1 to 2 years if( yearly_food_change() > 0 && newFood > yearConsumption * reserveYears ) { if( offeredAmount >= 10 ) // offered >= $10 { return 1; } else // < $10, only if we have plenty of reserve { if( newFood > yearConsumption * reserveYears * 2 ) return 1; } } else { if( offeredAmount >= 20 ) { if( yearly_food_change() > 0 && newFood > yearConsumption * reserveYears / 2 ) { return 1; } } if( offeredAmount >= 30 ) { return yearly_food_change() > 0 || newFood > yearConsumption * reserveYears; } } return 0; } //------ End of function Nation::consider_sell_food ------// //----- Begin of function Nation::should_consider_friendly -----// // int Nation::should_consider_friendly(int withNationRecno) { Nation* withNation = nation_array[withNationRecno]; //------- if this is a larger nation -------// if( overall_rank_rating() / 100 > 50 ) { //--- big nations don't ally with their biggest opponents ---// int maxOverallRating=0; int biggestOpponentNationRecno=0; for( int i=nation_array.size() ; i>0 ; i-- ) { if( nation_array.is_deleted(i) || i==nation_recno ) continue; int overallRating = nation_array[i]->overall_rating; if( overallRating > maxOverallRating ) { maxOverallRating = overallRating; biggestOpponentNationRecno = i; } } if( biggestOpponentNationRecno == withNationRecno ) return 0; } //--- don't ally with nations with too low reputation ---// return withNation->reputation >= min(20, reputation) - 20; } //------ End of function Nation::should_consider_friendly -----// //----- Begin of function Nation::consider_alliance_rating -----// // // Return a rating from 0 to 100 for whether this nation should ally // with the given nation. // int Nation::consider_alliance_rating(int nationRecno) { Nation* nationPtr = nation_array[nationRecno]; //---- the current relation affect the alliance tendency ---// NationRelation* nationRelation = get_relation(nationRecno); int allianceRating = nationRelation->ai_relation_level-20; //--- if the nation has a bad record of starting wars with us before, decrease the rating ---// allianceRating -= nationRelation->started_war_on_us_count * 20; //------ add the trade rating -------// int tradeRating = trade_rating(nationRecno) + // existing trade amount ai_trade_with_rating(nationRecno)/2; // possible trade allianceRating += tradeRating; //---- if the nation's power is larger than us, it's a plus ----// int powerRating = nationPtr->military_rank_rating() - military_rank_rating(); // if the nation's power is larger than ours, it's good to form treaty with them if( powerRating > 0 ) allianceRating += powerRating; return allianceRating; } //------ End of function Nation::consider_alliance_rating -----// //----- Begin of function Nation::consider_take_tribute -----// // // talkMsg->talk_para1 - amount of the tribute. // int Nation::consider_take_tribute(TalkMsg* talkMsg) { int cashSignificance = 100 * talkMsg->talk_para1 / max(1000, (int) cash); //--- It does not necessarily want the tribute ---// int aiRelationLevel = get_relation(talkMsg->from_nation_recno)->ai_relation_level; if( true_profit_365days() > 0 && cashSignificance < (100-aiRelationLevel)/5 ) { return 0; } //----------- take the tribute ------------// int relationChange = cashSignificance * (100+pref_cash_reserve) / 200; change_ai_relation_level( talkMsg->from_nation_recno, relationChange ); return 1; } //------ End of function Nation::consider_take_tribute ------// //----- Begin of function Nation::consider_take_aid -----// // // talkMsg->talk_para1 - amount of the tribute. // int Nation::consider_take_aid(TalkMsg* talkMsg) { int cashSignificance = 100 * talkMsg->talk_para1 / max(1000, (int) cash); //--- It does not necessarily want the tribute ---// int aiRelationLevel = get_relation(talkMsg->from_nation_recno)->ai_relation_level; if( true_profit_365days() > 0 && cashSignificance < (100-aiRelationLevel)/5 ) { return 0; } //----------- take the tribute ------------// int relationChange = cashSignificance * (100+pref_cash_reserve) / 200; change_ai_relation_level( talkMsg->from_nation_recno, relationChange ); return 1; } //------ End of function Nation::consider_take_aid ------// //-------- Begin of static function has_sent_same_msg --------// // // Whether the nation has already sent out a message that is // the same as the one it received. // static int has_sent_same_msg(TalkMsg* talkMsgPtr) { TalkMsg talkMsg; memcpy( &talkMsg, talkMsgPtr, sizeof(TalkMsg) ); talkMsg.from_nation_recno = talkMsg.to_nation_recno; talkMsg.to_nation_recno = talkMsg.from_nation_recno; return talk_res.is_talk_msg_exist(&talkMsg, 1); // 1-check talk_para1 & talk_para2 } //------ End of static function has_sent_same_msg ------// //----- Begin of function Nation::consider_take_tech -----// // // talkMsg->talk_para1 - id. of the technology. // talkMsg->talk_para2 - level of the technology. // int Nation::consider_take_tech(TalkMsg* talkMsg) { int ourTechLevel = tech_res[talkMsg->talk_para1]->get_nation_tech_level(nation_recno); if( ourTechLevel >= talkMsg->talk_para2 ) return 0; int relationChange = (talkMsg->talk_para2-ourTechLevel) * (15+pref_use_weapon/10); change_ai_relation_level( talkMsg->from_nation_recno, relationChange ); return 1; } //------ End of function Nation::consider_take_tech ------// //----- Begin of function Nation::surplus_supply_rating -----// // // Return a rating from 0 to 100 indicating how much surplus // of supply this nation has in markets. // int Nation::surplus_supply_rating() { FirmMarket* firmMarket; int stockQty, totalStockQty=0, totalStockSlot=0; for( int i=ai_market_count-1; i>=0 ; i-- ) { firmMarket = (FirmMarket*) firm_array[ ai_market_array[i] ]; err_when( firmMarket->firm_id != FIRM_MARKET ); MarketGoods* marketGoods = firmMarket->market_goods_array; for( int j=0 ; jraw_id || marketGoods->product_raw_id ) { stockQty = (int) marketGoods->stock_qty; totalStockQty += stockQty; totalStockSlot++; } } } if( totalStockSlot==0 ) return 0; int avgStockQty = totalStockQty / totalStockSlot; return 100 * avgStockQty / MAX_MARKET_STOCK; } //------ End of function Nation::surplus_supply_rating ------// //----- Begin of function Nation::consider_give_aid -----// // // talkMsg->talk_para1 - amount of the tribute. // int Nation::consider_give_aid(TalkMsg* talkMsg) { //-------- don't give tribute too frequently -------// NationRelation* nationRelation = get_relation(talkMsg->from_nation_recno); if( info.game_date < nationRelation->last_talk_reject_date_array[TALK_GIVE_AID-1] + 365 - pref_allying_tendency ) { return 0; } //--------------------------------------------------// int importanceRating = (int) nationRelation->good_relation_duration_rating; if( nationRelation->status >= NATION_FRIENDLY && ai_should_spend( importanceRating, talkMsg->talk_para1 ) ) // 0-importance is 0 { if( info.game_date > nationRelation->last_change_status_date + 720 - pref_allying_tendency ) // we have allied with this nation for quite some while { nationRelation->last_talk_reject_date_array[TALK_GIVE_AID-1] = info.game_date; return 1; } } return 0; } //------ End of function Nation::consider_give_aid ------// //----- Begin of function Nation::consider_give_tribute -----// // // talkMsg->talk_para1 - amount of the tribute. // int Nation::consider_give_tribute(TalkMsg* talkMsg) { //-------- don't give tribute too frequently -------// NationRelation* nationRelation = get_relation(talkMsg->from_nation_recno); if( info.game_date < nationRelation->last_talk_reject_date_array[TALK_GIVE_TRIBUTE-1] + 365 - pref_allying_tendency ) { return 0; } //---------------------------------------------// int relationStatus = get_relation_status(talkMsg->from_nation_recno); Nation* fromNation = nation_array[talkMsg->from_nation_recno]; if( true_profit_365days() < 0 ) // don't give tribute if we are losing money return 0; int reserveYears = 1 + 3 * pref_cash_reserve / 100; // 1 to 4 years if( cash-talkMsg->talk_para1 < fixed_expense_365days() * reserveYears ) return 0; int militaryDiff = fromNation->military_rank_rating() - military_rank_rating(); if( militaryDiff > 10+pref_military_courage/2 ) { nationRelation->last_talk_reject_date_array[TALK_GIVE_TRIBUTE-1] = info.game_date; return 1; } return 0; } //------ End of function Nation::consider_give_tribute ------// //----- Begin of function Nation::consider_give_tech -----// // // Consider giving the latest level of the technology to the nation. // // talkMsg->talk_para1 - id. of the technology. // int Nation::consider_give_tech(TalkMsg* talkMsg) { //-------- don't give tribute too frequently -------// NationRelation* nationRelation = get_relation(talkMsg->from_nation_recno); if( info.game_date < nationRelation->last_talk_reject_date_array[TALK_GIVE_TECH-1] + 365 - pref_allying_tendency ) { return 0; } //----------------------------------------------------// int importanceRating = (int) nationRelation->good_relation_duration_rating; if( nationRelation->status == NATION_ALLIANCE && importanceRating + pref_allying_tendency/10 > 30 ) { nationRelation->last_talk_reject_date_array[TALK_GIVE_TECH-1] = info.game_date; return 1; } return 0; } //------ End of function Nation::consider_give_tech ------// //----- Begin of function Nation::consider_declare_war -----// // // Consider the request of declaring war on the target nation. // // talk_para1 - the recno nation to declare war with. // int Nation::consider_declare_war(TalkMsg* talkMsg) { //--- if it even won't consider trade embargo, there is no reason that it will consider declaring war ---// if( !consider_trade_embargo(talkMsg) ) return 0; //---------------------------------------// int fromRelationRating = ai_overall_relation_rating(talkMsg->from_nation_recno); int againstRelationRating = ai_overall_relation_rating(talkMsg->talk_para1); Nation* againstNation = nation_array[talkMsg->talk_para1]; NationRelation* fromRelation = get_relation(talkMsg->from_nation_recno); NationRelation* againstRelation = get_relation(talkMsg->talk_para1); //--- if we don't have a good enough relation with the requesting nation, turn down the request ---// if( fromRelation->good_relation_duration_rating < 10 ) return 0; //--- if we are more friendly with the against nation than the requesting nation, turn down the request ---// if( againstRelation->good_relation_duration_rating > fromRelation->good_relation_duration_rating ) { return 0; } //--- if the nation is having a financial difficulty, it won't agree ---// if( cash < 2000 * pref_cash_reserve / 100 ) return 0; //--------------------------------------------// int acceptRating = 100 + againstNation->total_enemy_military() - military_rank_rating(); //--- it won't declare war with a friendly or allied nation easily ---// if( againstRelation->status >= NATION_FRIENDLY ) // no need to handle NATION_ALLIANCE separately as ai_overall_relation_relation() has already taken it into account acceptRating += 100; return fromRelationRating - againstRelationRating > acceptRating; } //------ End of function Nation::consider_declare_war ------// //----- Begin of function Nation::consider_trade_embargo -----// // int Nation::consider_trade_embargo(TalkMsg* talkMsg) { int fromRelationRating = ai_overall_relation_rating(talkMsg->from_nation_recno); int againstRelationRating = ai_overall_relation_rating(talkMsg->talk_para1); NationRelation* fromRelation = get_relation(talkMsg->from_nation_recno); NationRelation* againstRelation = get_relation(talkMsg->talk_para1); //--- if we don't have a good enough relation with the requesting nation, turn down the request ---// if( fromRelation->good_relation_duration_rating < 5 ) return 0; //--- if we are more friendly with the against nation than the requesting nation, turn down the request ---// if( againstRelation->good_relation_duration_rating > fromRelation->good_relation_duration_rating ) { return 0; } //--- if we have a large trade with the against nation or have a larger trade with the against nation than the requesting nation ---// int fromTrade = trade_rating(talkMsg->from_nation_recno); int againstTrade = trade_rating(talkMsg->talk_para1); if( againstTrade > 40 || ( againstTrade > 10 && againstTrade - fromTrade > 15 ) ) { return 0; } //--- if the nation is having a financial difficulty, it won't agree ---// if( cash < 2000 * pref_cash_reserve / 100 ) return 0; //--------------------------------------------// int acceptRating = 75; //--- it won't declare war with a friendly or allied nation easily ---// if( againstRelation->status >= NATION_FRIENDLY ) // no need to handle NATION_ALLIANCE separately as ai_overall_relation_relation() has already taken it into account acceptRating += 100; return fromRelationRating - againstRelationRating > acceptRating; } //------ End of function Nation::consider_trade_embargo ------// //----- 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 < 100-pref_military_courage/2 ) return 0; //----- see what units are attacking the nation -----// if( unit_array.is_deleted(fromNation->last_attacker_unit_recno) ) return 0; Unit* unitPtr = unit_array[ fromNation->last_attacker_unit_recno ]; if( unitPtr->nation_recno == nation_recno ) // if it's our own units return 0; if( unitPtr->nation_recno == 0 ) return 0; if( !unitPtr->is_visible() ) return 0; //------ only attack if it's a common enemy to us and our ally -----// if( get_relation(unitPtr->nation_recno)->status != NATION_HOSTILE ) return 0; //------- calculate the combat level of the target units there ------// int hasWar; int targetCombatLevel = mobile_defense_combat_level( unitPtr->next_x_loc(), unitPtr->next_y_loc(), unitPtr->nation_recno, 0, hasWar ); if( ai_attack_target(unitPtr->next_x_loc(), unitPtr->next_y_loc(), targetCombatLevel, 0, 1 ) ) //0-not defense mode, 1-just move to flag { fromRelation->last_military_aid_date = info.game_date; return 1; } return 0; } //------ End of function Nation::consider_military_aid ------// //----- Begin of function Nation::consider_accept_surrender_request -----// // // Consider accepting the cash offer and sell the throne to another kingdom. // // talkMsg->talk_para1 - the amount offered. // int Nation::consider_accept_surrender_request(TalkMsg* talkMsg) { Nation* nationPtr = nation_array[talkMsg->from_nation_recno]; int offeredAmt = talkMsg->talk_para1 * 10; // *10 to restore its original value which has been divided by 10 to cope with upper limit //---- don't surrender to the player if the player is already the most powerful nation ---// if( !nationPtr->is_ai() && config.ai_aggressiveness >= OPTION_HIGH ) { if( nation_array.max_overall_nation_recno == nationPtr->nation_recno ) return 0; } // If our economy is good, then it is harder to convince us // to surrender. But when we are running out of cash, // we ignore all normal thinking in the following block. if( !(cash < 100 && profit_365days() < 0) ) { //----- never surrender to a weaker nation ------// if( nationPtr->overall_rank_rating() < overall_rank_rating() ) return 0; //------ don't surrender if we are still strong -----// if( overall_rank_rating() > 30 + pref_peacefulness/4 ) // 30 to 55 return 0; //---- don't surrender if our cash is more than the amount they offered ----// if( offeredAmt < cash * (75+pref_cash_reserve/2) / 100 ) // 75% to 125% return 0; //-- if there are only two nations left, don't surrender if we still have some power --// if( nation_array.nation_count == 2 ) { if( overall_rank_rating() > 20 - 10 * pref_military_courage / 100 ) return 0; } } //-------------------------------------// int surrenderToRating = ai_surrender_to_rating(talkMsg->from_nation_recno); surrenderToRating += 100 * offeredAmt / 13000; int acceptRating = overall_rank_rating()*13 + 100; //------ AI aggressiveness effects -------// switch( config.ai_aggressiveness ) { case OPTION_HIGH: if( nationPtr->is_ai() ) // tend to accept AI kingdom offer easier acceptRating -= 75; else acceptRating += 75; break; case OPTION_VERY_HIGH: if( nationPtr->is_ai() ) // tend to accept AI kingdom offer easier acceptRating -= 150; else acceptRating += 150; break; } return surrenderToRating > acceptRating; } //------ End of function Nation::consider_accept_surrender_request ------// //----- Begin of function Nation::ai_overall_relation_rating -----// // // Return the overall relation rating of this nation with the // specific nation. // int Nation::ai_overall_relation_rating(int withNationRecno) { NationRelation* nationRelation = get_relation(withNationRecno); Nation* nationPtr = nation_array[withNationRecno]; int overallRating = nationRelation->ai_relation_level + (int) nationRelation->good_relation_duration_rating + (int) nationPtr->reputation + nationPtr->military_rank_rating() + trade_rating(withNationRecno) + ai_trade_with_rating(withNationRecno)/2 + nationPtr->total_alliance_military(); return overallRating; } //------ End of function Nation::ai_overall_relation_rating ------//