Beispiel #1
0
//--------- Begin of function Nation::capture_expected_resistance --------//
//
// The lowest resistance can be expected if we are going to capture the
// town.
//
int Nation::capture_expected_resistance(int townRecno, int *captureUnitRecno)
{
	//--- we have plenty of cash, use cash to decrease the resistance of the villagers ---//

	*captureUnitRecno = 0;

	if( should_use_cash_to_capture() )
		return 0;			// return zero resistance

	//----- the average resistance determines the captureRating ------//

	int	captureRating = 0;
	Town* townPtr = town_array[townRecno];

	int averageResistance;

	if( townPtr->nation_recno )
		averageResistance = townPtr->average_loyalty();
	else
		averageResistance = townPtr->average_resistance(nation_recno);

	//---- see if there are general available for capturing this town ---//

	int majorityRace = townPtr->majority_race();
	int targetResistance;

	*captureUnitRecno = find_best_capturer(townRecno, majorityRace, /*out*/ targetResistance);
	if( !(*captureUnitRecno) )
		return 100;

	int resultResistance =
		( targetResistance * townPtr->race_pop_array[majorityRace-1] +
		  averageResistance * (townPtr->population - townPtr->race_pop_array[majorityRace-1]) )
		/ townPtr->population;

	return resultResistance;
}
Beispiel #2
0
//--------- Begin of function Nation::think_capture_independent --------//
//
// Think about capturing independent towns.
//
int Nation::think_capture_independent()
{
	//------- Capture target choices -------//

	std::priority_queue<CaptureTown> captureTownQueue;

	//--- find the town that makes most sense to capture ---//

	int 	townRecno;
	Town* townPtr;

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

		townPtr = town_array[townRecno];

		if( townPtr->nation_recno )		// only capture independent towns
			continue;

		if( townPtr->no_neighbor_space )		// if there is no space in the neighbor area for building a new firm.
			continue;

		if( townPtr->rebel_recno )			// towns controlled by rebels will not drop in resistance even if a command base is present
			continue;

		//------ only if we have a presence/a base town in this region -----//

		if( !has_base_town_in_region(townPtr->region_id) )
			continue;

		//---- check if there are already camps linked to this town ----//

		int i;
		for( i=townPtr->linked_firm_count-1 ; i>=0 ; i-- )
		{
			Firm* firmPtr = firm_array[ townPtr->linked_firm_array[i] ];

			if( firmPtr->firm_id != FIRM_CAMP )
				continue;

			//------ if we already have a camp linked to this town -----//

			if( firmPtr->nation_recno == nation_recno )
				break;

			//--- if there is an overseer with high leadership and right race in the opponent's camp, don't bother to compete with him ---//

			if( firmPtr->overseer_recno )
			{
				Unit* unitPtr = unit_array[firmPtr->overseer_recno];

				if( unitPtr->skill.skill_level >= 70 &&
					 unitPtr->race_id == townPtr->majority_race() )
				{
					break;
				}
			}
		}

		if( i>=0 )			// there is already a camp linked to this town and we don't want to get involved with its capturing plan
			continue;

		//------ no linked camps interfering with potential capture ------//

		int captureUnitRecno;
		int targetResistance  = capture_expected_resistance(townRecno, &captureUnitRecno);
		int averageResistance = townPtr->average_resistance(nation_recno);
		int minResistance 	 = MIN( averageResistance, targetResistance );

		if( minResistance < 50 - pref_peacefulness/5 )		// 30 to 50 depending on
		{
			captureTownQueue.push({townRecno, minResistance, captureUnitRecno});
		}
	}

	//------- try to capture the town in their resistance order ----//

	const bool needToCheckDistance = !config.explore_whole_map && info.game_date-info.game_start_date >
					MAX(MAX_WORLD_X_LOC, MAX_WORLD_Y_LOC) * (5-config.ai_aggressiveness) / 5;    // 3 to 5 / 5

	while( captureTownQueue.size() > 0 )
	{
		int captureRecno = captureTownQueue.top().town_recno;
		int captureUnitRecno = captureTownQueue.top().capture_unit_recno;
		captureTownQueue.pop();

		err_when( town_array.is_deleted(captureRecno) );

		//-------------------------------------------//
		// If the map is set to unexplored, wait for a
		// reasonable amount of time before moving out
		// to build the camp.
		//-------------------------------------------//

		if( needToCheckDistance )
		{
			Town* targetTown = town_array[ captureRecno ];

			int j;
			for( j=0 ; j<ai_town_count ; j++ )
			{
				Town* ownTown = town_array[ ai_town_array[j] ];

				int townDistance = misc.points_distance(targetTown->center_x, targetTown->center_y,
										 ownTown->center_x, ownTown->center_y);

				if( info.game_date-info.game_start_date >
					 townDistance * (5-config.ai_aggressiveness) / 5 )		// 3 to 5 / 5
				{
					break;
				}
			}

			if( j==ai_town_count )
				continue;
		}

		if( start_capture( captureRecno, captureUnitRecno ) )
			return 1;
	}

	return 0;
}
Beispiel #3
0
//--------- Begin of function Nation::capture_build_camp --------//
//
int Nation::capture_build_camp(int townRecno, int raceId, int captureUnitRecno)
{
	Town* captureTown = town_array[townRecno];

	//------- locate a place to build the camp -------//

	short buildXLoc, buildYLoc;

	if( !find_best_firm_loc(FIRM_CAMP, captureTown->loc_x1, captureTown->loc_y1, buildXLoc, buildYLoc) )
	{
		captureTown->no_neighbor_space = 1;
		return 0;
	}

	//---- find the best available general for the capturing action ---//

	int unitRecno = captureUnitRecno;
	int targetResistance;

	if ( !unitRecno )
		unitRecno = find_best_capturer(townRecno, raceId, targetResistance);

	if( !unitRecno )
		unitRecno = hire_best_capturer(townRecno, raceId);

	if( !unitRecno )
	{
		//--- if we have plenty of cash and can use cash to decrease the resistance of the independent villagers ---//

		if( should_use_cash_to_capture() )
		{
			char resultFlag;

			Unit* skilledUnit = find_skilled_unit(SKILL_LEADING, raceId,
									  captureTown->center_x, captureTown->center_y, resultFlag);

			if( skilledUnit )
				unitRecno = skilledUnit->sprite_recno;
		}

		if( !unitRecno )
			return 0;
	}

	//--- if the picked unit is an overseer of an existng camp ---//

	if( !mobilize_capturer(unitRecno) )
		return 0;

	//---------- add the action to the queue now ----------//

	err_when( captureTown->nation_recno==0 &&
				 unit_array[unitRecno]->race_id != captureTown->majority_race() );

	int actionRecno = add_action( buildXLoc, buildYLoc, captureTown->loc_x1, captureTown->loc_y1,
							ACTION_AI_BUILD_FIRM, FIRM_CAMP, 1, unitRecno );

	if( actionRecno )
		process_action(actionRecno);

	return 1;
}
Beispiel #4
0
//--------- Begin of function Nation::think_capture_independent --------//
//
// Think about capturing independent towns.
//
int Nation::think_capture_independent()
{
	//------- Capture target choices -------//

	#define MAX_CAPTURE_TOWN	30

	CaptureTown capture_town_array[MAX_CAPTURE_TOWN];
	short 		capture_town_count=0;

	//--- find the town that makes most sense to capture ---//

	int 	townRecno;
	Town* townPtr;

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

		townPtr = town_array[townRecno];

		if( townPtr->nation_recno )		// only capture independent towns
			continue;

		if( townPtr->no_neighbor_space )		// if there is no space in the neighbor area for building a new firm.
			continue;

		if( townPtr->rebel_recno )			// towns controlled by rebels will not drop in resistance even if a command base is present
			continue;

		//------ only if we have a presence/a base town in this region -----//

		if( !has_base_town_in_region(townPtr->region_id) )
			continue;

		//---- check if there are already camps linked to this town ----//

		int i;
		for( i=townPtr->linked_firm_count-1 ; i>=0 ; i-- )
		{
			Firm* firmPtr = firm_array[ townPtr->linked_firm_array[i] ];

			if( firmPtr->firm_id != FIRM_CAMP )
				continue;

			//------ if we already have a camp linked to this town -----//

			if( firmPtr->nation_recno == nation_recno )
				break;

			//--- if there is an overseer with high leadership and right race in the opponent's camp, do bother to compete with him ---//

			if( firmPtr->overseer_recno )
			{
				Unit* unitPtr = unit_array[firmPtr->overseer_recno];

				if( unitPtr->skill.skill_level >= 70 &&
					 unitPtr->race_id == townPtr->majority_race() )
				{
					break;
				}
			}
		}

		if( i>=0 )			// there is already a camp linked to this town and we don't want to get involved with its capturing plan
			continue;

		//-- if the town has linked military camps of the same nation --//

		int targetResistance  = capture_expected_resistance(townRecno);
		int averageResistance = townPtr->average_resistance(nation_recno);
		int minResistance 	 = MIN( averageResistance, targetResistance );

		if( minResistance < 50 - pref_peacefulness/5 )		// 30 to 50 depending on
		{
			capture_town_array[capture_town_count].town_recno 	   = townRecno;
			capture_town_array[capture_town_count].min_resistance = minResistance;

			capture_town_count++;
		}
	}

	//------ sort the capture target choices by min_resistance ----//

	qsort( &capture_town_array, capture_town_count, sizeof(capture_town_array[0]), sort_capture_town_function );

	//------- try to capture the town in their resistance order ----//

	for( int i=0 ; i<capture_town_count ; i++ )
	{
		err_when( town_array.is_deleted(capture_town_array[i].town_recno) );

		//-------------------------------------------//
		// If the map is set to unexplored, wait for a
		// reasonable amount of time before moving out
		// to build the mine.
		//-------------------------------------------//

		if( !config.explore_whole_map )
		{
			Town* targetTown = town_array[ capture_town_array[i].town_recno ];

			int j;
			for( j=0 ; j<ai_town_count ; j++ )
			{
				Town* ownTown = town_array[ ai_town_array[j] ];

				int townDistance = m.points_distance(targetTown->center_x, targetTown->center_y, 
										 ownTown->center_x, ownTown->center_y);

				if( info.game_date-info.game_start_date >
					 townDistance * (5-config.ai_aggressiveness) / 5 )		// 3 to 5 / 5
				{
					break;
				}
			}

			if( j==ai_town_count )
				continue;
		}

		if( start_capture( capture_town_array[i].town_recno ) )
			return 1;
	}

	return 0;
}
Beispiel #5
0
//--------- Begin of function Nation::optimize_town_race_region --------//
//
// Optimize the distribution of different races in different towns in
// a single region.
//
void Nation::optimize_town_race_region(int regionId)
{
	//---- reckon the minority jobless pop of each race ----//

	int racePopArray[MAX_RACE];

	memset( racePopArray, 0, sizeof(racePopArray) );

	int 	i, j, majorityRace;
	Town* townPtr;

	for( i=0 ; i<ai_town_count ; i++ )
	{
		townPtr = town_array[ ai_town_array[i] ];

		if( townPtr->region_id != regionId )
			continue;

		majorityRace = townPtr->majority_race();

		for( j=0 ; j<MAX_RACE ; j++ )
		{
			if( j+1 != majorityRace )
				racePopArray[j] += townPtr->jobless_race_pop_array[j];
		}
	}

	//--- locate for towns with minority being majority and those minority race can move to ---//

	Town* destTown;

	for( int raceId=0 ; raceId<MAX_RACE ; raceId++ )
	{
		if( racePopArray[raceId-1] == 0 )		// we don't have any minority of this race
			continue;

		destTown = NULL;

		for( i=0 ; i<ai_town_count ; i++ )
		{
			townPtr = town_array[ ai_town_array[i] ];

			if( townPtr->region_id != regionId )
				continue;

			if( !townPtr->is_base_town )
				continue;

			if( townPtr->majority_race() == raceId &&
				 townPtr->population < MAX_TOWN_POPULATION )
			{
				destTown = townPtr;
				break;
			}
		}

		if( !destTown )
			continue;

		//---- if there is a suitable town for minority to move to ---//

		for( i=0 ; i<ai_town_count ; i++ )
		{
			townPtr = town_array[ ai_town_array[i] ];

			if( townPtr->region_id != regionId )
				continue;

			//---- move minority units from towns -----//

			int joblessCount = townPtr->jobless_race_pop_array[raceId-1];

			if( joblessCount > 0 &&
				 townPtr->majority_race() != raceId )
			{
				int migrateCount = MIN(8, joblessCount);		// migrate a maximum of 8 units at a time

				add_action( destTown->loc_x1, destTown->loc_y1,
					townPtr->loc_x1, townPtr->loc_y1, ACTION_AI_SETTLE_TO_OTHER_TOWN, 0, migrateCount);
			}
		}
	}
}
Beispiel #6
0
//------- Begin of function Town::think_split_town -------//
//
// Split the town into two, migrating some population to the new
// town.
//
int Town::think_split_town()
{
	if( jobless_population==0 )			// cannot move if we don't have any mobilizable unit
		return 0;

	//--- split when the population is close to its limit ----//

	Nation* nationPtr = nation_array[nation_recno];

	if( population < 45 + nationPtr->pref_territorial_cohesiveness / 10 )
		return 0;

	//-------- think about which race to move --------//

	int mostRaceId1, mostRaceId2, raceId=0;

	get_most_populated_race(mostRaceId1, mostRaceId2);

	if( mostRaceId2 && jobless_race_pop_array[mostRaceId2-1] > 0 && can_recruit(mostRaceId2) )
		raceId = mostRaceId2;

	else if( mostRaceId1 && jobless_race_pop_array[mostRaceId1-1] > 0 && can_recruit(mostRaceId1) )
		raceId = mostRaceId1;

	else
		raceId = pick_random_race(0, 1);			// 0-recruitable only, 1-also pick spy.

	if( !raceId )
	{
		//---- if the racial mix favors a split of town -----//
		//
		// This is when there are two major races, both of significant
		// population in the town. This is a good time for us to move
		// the second major race to a new town.
		//
		//---------------------------------------------------//

		if( mostRaceId2 && jobless_race_pop_array[mostRaceId2] > 0 &&
			 race_pop_array[mostRaceId2] >= population/3 &&		// the race's has at least 1/3 of the town's total population
			 can_recruit(mostRaceId2) )
		{
			raceId = mostRaceId2;
		}
	}

	if( !raceId )
		return 0;

	//---- check if there is already a town of this race with low population linked to this town, then don't split a new one ---//

	Town* townPtr;

	for( int i=0 ; i<linked_town_count ; i++ )
	{
		townPtr = town_array[ linked_town_array[i] ];

		if( townPtr->nation_recno == nation_recno &&
			 townPtr->population < 20 &&
			 townPtr->majority_race() == raceId )
		{
			return 0;
		}
	}

	//-------- settle to a new town ---------//

	return ai_settle_new(raceId);
}