Example #1
0
int Nation::think_attack_monster()
{
	if( config.monster_type == OPTION_MONSTER_NONE )		// no monsters in the game
		return 0;

	//--- if the AI has run out of money and is currently cheating, it will have a urgent need to attack monsters to get money ---//

	int useAllCamp = income_365days(INCOME_CHEAT) > 0;

	if( !useAllCamp )		// use all camps to attack the monster
	{
		if( !is_at_war() )
		{
			if( cash < 500 && military_rank_rating() >= 75-pref_attack_monster/4 )		//  50 to 75
				useAllCamp = 1 ;
		}
	}

	if( !useAllCamp )
	{
		if( military_rank_rating() < 50-pref_attack_monster/4 )		// don't attack if the military strength is too low, 25 to 50
			return 0;
	}

	//------- select a monster target ---------//

	int targetCombatLevel;

	int targetFirmRecno = think_monster_target(targetCombatLevel);

	if( !targetFirmRecno )
		return 0;

	targetCombatLevel = targetCombatLevel * 150 / 100;		// X 150%

	//--- we need to use veteran soldiers to attack powerful monsters ---//

	FirmMonster* targetFirm = (FirmMonster*) firm_array[targetFirmRecno];

	int monsterLevel = monster_res[targetFirm->monster_id]->level;

	int attackerMinCombatLevel = 0;

	if( targetCombatLevel > 100 )			// if the nation's cash runs very low, it will attack anyway
		attackerMinCombatLevel = 20 + monsterLevel*3;

	//--- call ai_attack_target() to attack the target town ---//

	return ai_attack_target(targetFirm->loc_x1, targetFirm->loc_y1, targetCombatLevel, 0, 0, attackerMinCombatLevel, 0, useAllCamp );
}
Example #2
0
//--------- Begin of function Nation::should_use_cash_to_capture --------//
//
int Nation::should_use_cash_to_capture()
{
	//--- if we have plenty of cash, use cash to decrease the resistance of the villagers ---//

	return military_rank_rating() < 50+pref_peacefulness/5 &&		// 50 to 70
			 ai_should_spend(pref_loyalty_concern/4);
}
Example #3
0
//----- 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->never_accept_until_date_array[TALK_GIVE_TRIBUTE-1] )
		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->set_never_accept_until_date(TALK_GIVE_TRIBUTE, 180);
		return 1;
	}

	return 0;
}
Example #4
0
//----- 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;
}
Example #5
0
//----- Begin of function Nation::ai_should_spend_war -----//
//
// This function returns whether the nation should spend money
// or war.
//
// <int> enemyMilitaryRating - the military_rank_rating() of the enemy
// [int] considerCeaseFire	  - whether this function is called when considering ceasing fire
//										 (default:0)
//
int Nation::ai_should_spend_war(int enemyMilitaryRating, int considerCeaseFire)
{
	int importanceRating = 30 + pref_military_development/5;		// 30 to 50

	importanceRating += military_rank_rating() - enemyMilitaryRating*2;

	if( considerCeaseFire )    	// only when we are very powerful, we will start a battle. So won't cease fire too soon after declaring war
		importanceRating += 20;		// less eary to return 0, for cease fire

	return ai_should_spend(importanceRating);
}
Example #6
0
//----- 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);
	}
}
Example #7
0
//----- 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 >= RELATION_FRIENDLY )		// no need to handle RELATION_ALLIANCE separately as ai_overall_relation_relation() has already taken it into account
		acceptRating += 100;

	return fromRelationRating - againstRelationRating > acceptRating;
}
Example #8
0
//----- 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;
}
Example #9
0
//----- 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;
}
Example #10
0
//----- Begin of function Nation::think_demand_tribute_aid -----//
//
// Demand tribute when the nation's economy is good and its
// military is weak.
//
int Nation::think_demand_tribute_aid()
{
	if( info.game_date < info.game_start_date + 180 + nation_recno*50 )		// don't ask for tribute too soon, as in the beginning, the ranking are all the same for all nations
		return 0;

	//--------------------------------------//

	Nation* nationPtr;
	int	  totalNation=nation_array.size();
	int	  nationRecno=m.random(totalNation)+1;
	int	  curRating, requestRating;
	int	  talkId;
	int	  ourMilitary = military_rank_rating();
	int	  ourEconomy  = economic_rank_rating();

	for( int i=totalNation ; i>0 ; i-- )
	{
		if( ++nationRecno > totalNation )
			nationRecno = 1;

		if( nation_array.is_deleted(nationRecno) || nationRecno==nation_recno )
			continue;

		nationPtr = nation_array[nationRecno];

		//-- only demand tribute from non-friendly nations --//

		if( get_relation(nationRecno)->status <= RELATION_NEUTRAL )
			talkId = TALK_DEMAND_TRIBUTE;
		else
			talkId = TALK_DEMAND_AID;

		//-----------------------------------------------//

		float fixedExpense = fixed_expense_365days();

		if( talkId == TALK_DEMAND_TRIBUTE )
		{
			if( !should_diplomacy_retry(talkId, nationRecno) )
				continue;

			curRating = ourMilitary - nationPtr->military_rank_rating();

			//---- if this is a Fryhtan nation, the tendency to request tribute is higher -----//

			if( is_monster() && nationPtr->is_human() )	// and the target is a human nation
			{
				curRating *= 2;

				//-- if we are running low of live points, it's time to kill somebody --//

				if( live_points < 500 * (100+pref_live_points_reserve) / 100 )
					curRating *= 2;
			}

			if( curRating < 0 )
				continue;

			//----------------------------------------------//
			//
			// Some nation will actually consider the ability
			// of the target nation to pay tribute, so nation
			// will not and just ask anyway.
			//
			//----------------------------------------------//

			if( pref_economic_development > 50 )
			{
				int addRating = nationPtr->economic_rank_rating()-ourEconomy;

				if( addRating > 0 )
					curRating += addRating;
			}

			requestRating = 20 + trade_rating(nationRecno)/2 +
								(100-pref_peacefulness)/3;

			if( cash < fixedExpense && fixedExpense != 0 )
				requestRating -= int( (float) requestRating * cash / fixedExpense);

		}
		else
		{
			if( cash >= fixedExpense )
				continue;

			if( cash > fixedExpense * (50+pref_cash_reserve) / 300 &&		// if the nation is runing short of cash, don't wait a while until next retry, retry immediately
				 !should_diplomacy_retry(talkId, nationRecno) )
			{
				continue;
			}

			//----- only ask for aid when the nation is short of cash ----//

			curRating = (ourMilitary - nationPtr->military_rank_rating())/2 +
							( nationPtr->economic_rank_rating()-ourEconomy );

			requestRating = 20 + 50 * (int)(cash / fixedExpense);
		}

		//----- if the target is a human player's nation -----//

		if( !nationPtr->is_ai() )
		{
			switch( config.ai_aggressiveness )
			{
				case OPTION_NONE:
					requestRating += 60;		// don't go against the player too easily
					break;

				case OPTION_LOW:
					requestRating += 40;		// don't go against the player too easily
					break;

				case OPTION_HIGH:
					requestRating -= 20;
					break;

				case OPTION_VERY_HIGH:
					requestRating -= 40;
					break;
			}

			//--- if the nation has plenty of cash, demand from it ----//

			if( nationPtr->cash > cash && config.ai_aggressiveness >= OPTION_HIGH )
			{
				requestRating -= (int) (nationPtr->cash - cash)/500;
			}
		}

		//--------------------------------------//

		if( curRating > requestRating )
		{
			int tributeAmount;

			if( curRating - requestRating > 120 )
				tributeAmount = 4000;

			else if( curRating - requestRating > 80 )
				tributeAmount = 3000;

			else if( curRating - requestRating > 40 )
				tributeAmount = 2000;

			else if( curRating - requestRating > 20 )
				tributeAmount = 1000;

			else
				tributeAmount = 500;

			//------ stop in here if in tutorial mode -----//
			if( game.game_mode != GAME_TUTORIAL )
			{	
				cash += tributeAmount;
				return 0;
			}

			talk_res.ai_send_talk_msg(nationRecno, nation_recno, talkId, tributeAmount);

			return 1;
		}
	}

	return 0;
}
Example #11
0
//----- Begin of function Nation::think_give_tribute_aid -----//
//
// This function is called when a nation rejected our request
// which is important to us and we want to give tribute to the
// nation so it may accept next time.
//
// <TalkMsg*> rejectedMsg - the TalkMsg that has been rejected.
//
int Nation::think_give_tribute_aid(TalkMsg* rejectedMsg)
{
	//-----------get the talk id. ------------//

	int talkId;
	int talkNationRecno = rejectedMsg->to_nation_recno;
	int rejectedTalkId  = rejectedMsg->talk_id;
	NationRelation* nationRelation = get_relation(talkNationRecno);

	if( nationRelation->status >= RELATION_FRIENDLY )
		talkId = TALK_GIVE_AID;
	else
		talkId = TALK_GIVE_TRIBUTE;

	//-------- don't give tribute too frequently -------//

	if( info.game_date < nationRelation->never_accept_until_date_array[talkId-1] )
		return 0;

	//---- think if the nation should spend money now ----//

	static short tributeAmountArray[] = { 500, 1000 };
	int tributeAmount = tributeAmountArray[m.random(2)];

	if( !ai_should_spend(0, (float) tributeAmount) )		// importance rating is 0
		return 0;

	//--------------------------------------//

	Nation* talkNation = nation_array[talkNationRecno];
	int	  rc;

	if( rejectedTalkId == TALK_PROPOSE_TRADE_TREATY )
	{
		rc = ai_trade_with_rating(talkNationRecno) > 100-pref_trading_tendency/2;
	}

	else if ( rejectedTalkId == TALK_PROPOSE_FRIENDLY_TREATY ||
				 rejectedTalkId == TALK_PROPOSE_ALLIANCE_TREATY )
	{
		int curRating = talkNation->trade_rating(talkNationRecno) +
							 ai_trade_with_rating(talkNationRecno) +
							 talkNation->overall_rating - overall_rating;

		int acceptRating = 200-pref_trading_tendency/4
									 -pref_allying_tendency/4;

		rc = curRating >= acceptRating;
	}

	//--------------------------------------//

	else if( rejectedTalkId == TALK_REQUEST_CEASE_WAR )
	{
		rc = talkNation->military_rank_rating() >
			  military_rank_rating() + (100-pref_peacefulness)/2;
	}

	//--------------------------------------//

	if( rc )
	{
		//------ give tribute --------//

		talk_res.ai_send_talk_msg(talkNationRecno, nation_recno, talkId, tributeAmount);

		nationRelation->set_never_accept_until_date(talkId, 100);		// don't offer tribute too often

		//------ request again after giving tribute ----//

		nationRelation->last_talk_reject_date_array[rejectedTalkId-1] = 0;		// reset the rejected talk id.
		nationRelation->never_accept_until_date_array[rejectedTalkId-1] = 0;		// reset the rejected talk id.

		talk_res.ai_send_talk_msg(talkNationRecno, nation_recno, rejectedTalkId, rejectedMsg->talk_para1, rejectedMsg->talk_para2 );
	}

	return rc;
}
Example #12
0
//--------- Begin of function Nation::think_capture_enemy_town_target --------//
//
// <Town*> capturerTown - our town to capture enemy towns.
//
// Motives for attacking another nation:
//
// 1. Capture towns
// 2. Conquer land
// 3. Defeat enemies
//
Town* Nation::think_capture_enemy_town_target(Town* capturerTown)
{
	int   townRecno, curRating;
	Town* targetTown, *bestTown=NULL;
	Firm* firmPtr;
	int   ourMilitary = military_rank_rating();
	Nation* ownNation = nation_array[nation_recno];
	int   bestRating = -1000;
	int  	hasWar;
	int   neededCombatLevel=0;

	for( townRecno=town_array.size() ; townRecno>0 ; townRecno-- )
	{
		if( town_array.is_deleted(townRecno) )
			continue;

		targetTown = town_array[townRecno];

		if( targetTown->nation_recno == 0 ||
			 targetTown->nation_recno == nation_recno )
		{
			continue;
		}

		if( targetTown->region_id != capturerTown->region_id )
			continue;

		//----- if we have already built a camp next to this town -----//

		if( targetTown->has_linked_camp(nation_recno, 0) )		//0-count both camps with or without overseers
			continue;

		//--------- only attack enemies -----------//

		NationRelation* nationRelation = get_relation(targetTown->nation_recno);

		int rc=0;

		if( nationRelation->status == NATION_HOSTILE )
			rc = 1;

		else if( nationRelation->ai_relation_level < 10 )			// even if the relation is not hostile, if the ai_relation_level is < 10, attack anyway
			rc = 1;

		else if( nationRelation->status <= NATION_NEUTRAL &&
			 targetTown->nation_recno == nation_array.max_overall_nation_recno &&		// if this is our biggest enemy
			 nationRelation->ai_relation_level < 30 )
		{
			rc = 1;
		}

		if( !rc )
			continue;

		//----- if this town does not have any linked camps, capture this town immediately -----//

		if( targetTown->has_linked_camp(targetTown->nation_recno, 0) )		//0-count both camps with or without overseers
			return targetTown;

		//--- if the enemy is very powerful overall, don't attack it yet ---//

		if( nation_array[targetTown->nation_recno]->military_rank_rating() >
			 ourMilitary * (80+pref_military_courage/2) / 100 )
		{
			continue;
		}

		//------ only attack if we have enough money to support the war ----//

		if( !ai_should_spend_war( nation_array[targetTown->nation_recno]->military_rank_rating() ) )
			continue;

		//-------------------------------------------------------//

		int townCombatLevel = enemy_town_combat_level(targetTown, 1, hasWar);		// 1-return a rating if there is war with the town

		if( townCombatLevel == -1 )      // do not attack this town because a battle is already going on
			continue;

		//------- calculate the rating --------------//

		curRating = world.distance_rating(capturerTown->center_x, capturerTown->center_y,
						targetTown->center_x, targetTown->center_y);

		curRating -= townCombatLevel/10;

		curRating -= targetTown->average_loyalty();

		curRating += targetTown->population;		// put a preference on capturing villages with large population

		//----- the power of between the nation also affect the rating ----//

		curRating += 2 * (ourMilitary - nation_array[targetTown->nation_recno]->military_rank_rating());

		//-- AI Aggressive is set above Low, than the AI will try to capture the player's town first ---//

		if( !targetTown->ai_town )
		{
			if( game.game_mode == GAME_TUTORIAL )		// next attack the player in a tutorial game
			{
				continue;
			}
			else
			{
				switch( config.ai_aggressiveness )
				{
					case OPTION_MODERATE:
						curRating += 100;
						break;

					case OPTION_HIGH:
						curRating += 300;
						break;

					case OPTION_VERY_HIGH:
						curRating += 500;
						break;
				}
			}
		}

		//--- if there are mines linked to this town, increase its rating ---//

		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 )
				continue;

			if( firmPtr->firm_id == FIRM_MINE )
			{
				//--- if this mine's raw materials is one that we don't have --//

				if( raw_count_array[ ((FirmMine*)firmPtr)->raw_id-1 ]==0 )
					curRating += 150 * (int) ((FirmMine*)firmPtr)->reserve_qty / MAX_RAW_RESERVE_QTY;
			}
		}

		//--- more linked towns increase the attractiveness rating ---//

		curRating += targetTown->linked_firm_count*5;

		//-------- compare with the current best rating ---------//

		if( curRating > bestRating )
		{
			bestRating    = curRating;
			bestTown      = targetTown;
			neededCombatLevel = townCombatLevel;
		}
	}

	return bestTown;
}
Example #13
0
//----- 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 != RELATION_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;
}