예제 #1
0
void AAIAttackManager::LaunchAttack()
{
	//////////////////////////////////////////////////////////////////////////////////////////////
	// get all available combat/aa/arty groups for attack
	//////////////////////////////////////////////////////////////////////////////////////////////
	int total_combat_groups = 0;

	for(list<UnitCategory>::iterator category = ai->Getbt()->assault_categories.begin(); category != ai->Getbt()->assault_categories.end(); ++category)
	{
		for(list<AAIGroup*>::iterator group = ai->Getgroup_list()[*category].begin(); group != ai->Getgroup_list()[*category].end(); ++group)
		{
			if( (*group)->AvailableForAttack() )
			{
				if((*group)->group_movement_type & MOVE_TYPE_CONTINENT_BOUND)
				{
					if((*group)->group_unit_type == ASSAULT_UNIT)
					{
						available_combat_groups_continent[(*group)->continent].push_back(*group);
						++total_combat_groups;
					}
					else
						available_aa_groups_continent[(*group)->continent].push_back(*group);
				}
				else
				{
					if((*group)->group_unit_type == ASSAULT_UNIT)
					{
						available_combat_groups_global.push_back(*group);
						++total_combat_groups;
					}
					else
						available_aa_groups_global.push_back(*group);
				}
			}
		}
	}

	// stop planing an attack if there are no combat groups available at the moment
	if(total_combat_groups == 0)
		return;

	//////////////////////////////////////////////////////////////////////////////////////////////
	// calculate max attack power for each continent
	//////////////////////////////////////////////////////////////////////////////////////////////
	fill(attack_power_global.begin(), attack_power_global.end(), 0.0f);

	for(list<AAIGroup*>::iterator group = available_combat_groups_global.begin(); group != available_combat_groups_global.end(); ++group)
		(*group)->GetCombatPower( &attack_power_global );

	for(size_t continent = 0; continent < available_combat_groups_continent.size(); ++continent)
	{
		fill(attack_power_continent[continent].begin(), attack_power_continent[continent].end(), 0.0f);

		for(list<AAIGroup*>::iterator group = available_combat_groups_continent[continent].begin(); group != available_combat_groups_continent[continent].end(); ++group)
			(*group)->GetCombatPower( &(attack_power_continent[continent]) );
	}

	// determine max lost units
	float max_lost_units = 0.0f;

	for(int x = 0; x < ai->Getmap()->xSectors; ++x)
	{
		for(int y = 0; y < ai->Getmap()->ySectors; ++y)
		{
			float lost_units = ai->Getmap()->sector[x][y].GetLostUnits(1.0f, 1.0f, 1.0f, 1.0f, 1.0f);

			if(lost_units > max_lost_units)
				max_lost_units = lost_units;
		}
	}

	//////////////////////////////////////////////////////////////////////////////////////////////
	// determine attack sector
	//////////////////////////////////////////////////////////////////////////////////////////////
	float def_power;
	float att_power;
	float best_rating = 0.0f;
	AAISector* sector;
	AAISector* dest = NULL;

	for(int x = 0; x < ai->Getmap()->xSectors; ++x)
	{
		for(int y = 0; y < ai->Getmap()->ySectors; ++y)
		{
			sector = &ai->Getmap()->sector[x][y];

			float my_rating;

			// max_lost_units check to prevent SIGFPE, later on
			if(sector->distance_to_base == 0 || sector->enemy_structures < 0.0001 || max_lost_units <= 0.0f)
				my_rating = 0.0f;
			else
			{
				if(ai->Getmap()->continents[sector->continent].water)
				{
					def_power = sector->GetEnemyDefencePower(0.0f, 0.0f, 0.5f, 1.0f, 1.0f) + 0.01;
					att_power = attack_power_global[5] + attack_power_continent[sector->continent][5];
				}
				else
				{
					def_power = sector->GetEnemyDefencePower(1.0f, 0.0f, 0.5f, 0.0f, 0.0f) + 0.01;
					att_power = attack_power_global[5] + attack_power_continent[sector->continent][5];
				}

				my_rating = (1.0f - sector->GetLostUnits(1.0f, 1.0f, 1.0f, 1.0f, 1.0f) / max_lost_units) * sector->enemy_structures * att_power / ( def_power * (float)(2 + sector->distance_to_base) );

				//if(SufficientAttackPowerVS(dest, &combat_available, 2))
			}

			if(my_rating > best_rating)
			{
				dest = sector;
				best_rating = my_rating;
			}
		}
	}

	//////////////////////////////////////////////////////////////////////////////////////////////
	// order attack
	//////////////////////////////////////////////////////////////////////////////////////////////

	if(dest)
	{
		AAIAttack *attack = new AAIAttack(ai);
		attacks.push_back(attack);

		// add combat groups
		for(list<AAIGroup*>::iterator group = available_combat_groups_continent[dest->continent].begin(); group != available_combat_groups_continent[dest->continent].end(); ++group)
			attack->AddGroup(*group);

		for(list<AAIGroup*>::iterator group = available_combat_groups_global.begin(); group != available_combat_groups_global.end(); ++group)
			attack->AddGroup(*group);

		// add anti-air defence
		int aa_added = 0, max_aa;

		// check how much aa sensible
		if(ai->Getbrain()->max_combat_units_spotted[1] < 0.2)
			max_aa = 0;
		else
			max_aa = 1;

		for(list<AAIGroup*>::iterator group = available_aa_groups_continent[dest->continent].begin(); group != available_aa_groups_continent[dest->continent].end(); ++group)
		{
			if(aa_added >= max_aa)
				break;

			attack->AddGroup(*group);
			++aa_added;
		}

		for(list<AAIGroup*>::iterator group = available_aa_groups_global.begin(); group != available_aa_groups_global.end(); ++group)
		{
			if(aa_added >= max_aa)
				break;

			attack->AddGroup(*group);
			++aa_added;
		}

		// rally attacking groups
		//RallyGroups(attack);

		// start the attack
		attack->AttackSector(dest);
	}
}
void AAIAttackManager::LaunchAttack()
{
	AAISector *dest;
	AttackType a_type;
	bool suitable, land, water;

	// determine attack sector

	// todo: improve decision when to attack base or outposts
	a_type = OUTPOST_ATTACK;
	
	if(cfg->AIR_ONLY_MOD)
	{
		land = true;
		water = true;
	}
	else
	{
		if(map->mapType == LAND_MAP)
		{
			land = true;
			water = false;
		}
		else if(map->mapType == LAND_WATER_MAP)
		{
			land = true;
			water = true;
		}
		else if(map->mapType == WATER_MAP)
		{
			land = false;
			water = true;
		}
		else
		{
			land = true;
			water = false;
		}
	}
	
	// get target sector
	dest = ai->brain->GetAttackDest(land, water, a_type);

	if(dest)
	{
		// get all available combat/aa/arty groups for attack
		set<AAIGroup*> combat_available;
		set<AAIGroup*> aa_available;

		if(cfg->AIR_ONLY_MOD)
		{
			for(list<UnitCategory>::iterator category = bt->assault_categories.begin(); category != bt->assault_categories.end(); ++category)
			{
				for(list<AAIGroup*>::iterator group = ai->group_list[*category].begin(); group != ai->group_list[*category].end(); ++group)
				{		
					if(!(*group)->attack && (*group)->SufficientAttackPower())
						combat_available.insert(*group);
				}
			}
		}
		else	// non air only mods must take movement type into account
		{
			// todo: improve by checking how to reach that sector
			if(dest->water_ratio > 0.65)
			{
				land = false;
				water = true;
			}
			else 
			{
				water = false;
				land = true;
			}

			for(list<UnitCategory>::iterator category = bt->assault_categories.begin(); category != bt->assault_categories.end(); ++category)
			{
				for(list<AAIGroup*>::iterator group = ai->group_list[*category].begin(); group != ai->group_list[*category].end(); ++group)
				{
					// check movement type first
					suitable = true;
	
					if(land && (*group)->group_movement_type & MOVE_TYPE_SEA)
						suitable = false;

					if(water && (*group)->group_movement_type & MOVE_TYPE_GROUND)
						suitable = false;

					if(suitable && !(*group)->attack && (*group)->task == GROUP_IDLE )
					{
						if((*group)->group_unit_type == ASSAULT_UNIT && (*group)->SufficientAttackPower())
							combat_available.insert(*group);
						else if((*group)->group_unit_type == ANTI_AIR_UNIT)
							aa_available.insert(*group);
					}
				}
			}
		}

		if((combat_available.size() > 0 && SufficientAttackPowerVS(dest, &combat_available, 2)) ||  combat_available.size() > 10)
		{
			AAIAttack *attack;
			
			try
			{
				attack = new AAIAttack(ai);
			}
			catch(...)
			{
				fprintf(ai->file, "Exception thrown when allocating memory for AAIAttack");
				return;
			}

			attacks.push_back(attack);

			attack->land = land;
			attack->water = water;

			// add combat groups
			for(set<AAIGroup*>::iterator group = combat_available.begin(); group != combat_available.end(); ++group)
				attack->AddGroup(*group);
			
			// add antiair defence
			if(!aa_available.empty())
			{
				int aa_added = 0, max_aa;

				// check how much aa sensible
				if(brain->max_units_spotted[1] < 0.2)
					max_aa = 0;
				else 
					max_aa = 1;


				for(set<AAIGroup*>::iterator group = aa_available.begin(); group != aa_available.end(); ++group)
				{
					attack->AddGroup(*group);

					++aa_added;

					if(aa_added >= max_aa)
						break;
				}
			}

			// rally attacking groups
			//this->RallyGroups(attack);

			// start the attack
			attack->AttackSector(dest, a_type);
		}

		// clean up
		aa_available.clear();
		combat_available.clear();
	}
}