⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aaiexecute.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		{
			if(ai->activeScouts < 2)
			{
				buildque->insert(buildque->begin(), number, def_id);
				return true;
			}
			else
			{
				/*// insert after the last builder
				for(list<int>::iterator unit = buildque->begin(); unit != buildque->end();  ++unit)
				{
					if(!bt->IsBuilder(*unit))
					{
						buildque->insert(unit, number, def_id);
						return true;
					}
				}*/
				buildque->insert(buildque->begin(), number, def_id);
				return true;
			}
		}
		else if(buildque->size() < cfg->MAX_BUILDQUE_SIZE)
		{
			if(urgent)
				buildque->insert(buildque->begin(), number, def_id);
			else
				buildque->insert(buildque->end(), number, def_id);

			//fprintf(ai->file, "Added %s to buildque with length %i\n", bt->unitList[def_id-1]->humanName.c_str(), buildque->size());

			return true;
		}
	}
	//else
	//	fprintf(ai->file, "Could not find builque for %s\n", bt->unitList[def_id-1]->humanName.c_str());

	return false;
}

void AAIExecute::InitBuildques()
{
	// determine number of factories first
	numOfFactories = 0;
	
	// stationary factories
	for(list<int>::iterator cons = bt->units_of_category[STATIONARY_CONSTRUCTOR][ai->side-1].begin(); cons != bt->units_of_category[STATIONARY_CONSTRUCTOR][ai->side-1].end(); ++cons)
	{
		if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
			++numOfFactories;
	}
	// and look for all mobile factories
	for(list<int>::iterator cons = bt->units_of_category[MOBILE_CONSTRUCTOR][ai->side-1].begin(); cons != bt->units_of_category[MOBILE_CONSTRUCTOR][ai->side-1].end(); ++cons)
	{
		if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
			++numOfFactories;
	}
	// and add com
	for(list<int>::iterator cons = bt->units_of_category[COMMANDER][ai->side-1].begin(); cons != bt->units_of_category[COMMANDER][ai->side-1].end(); ++cons)
	{
		if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
			++numOfFactories;
	}

//	buildques = new list<int>[numOfFactories];
	buildques.resize(numOfFactories);

	// set up factory buildque identification
//	factory_table = new int[numOfFactories];
	factory_table.resize(numOfFactories);
	
	int i = 0;

	for(list<int>::iterator cons = bt->units_of_category[STATIONARY_CONSTRUCTOR][ai->side-1].begin(); cons != bt->units_of_category[STATIONARY_CONSTRUCTOR][ai->side-1].end(); ++cons)
	{
		if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
		{
			factory_table[i] = *cons;
			++i;
		}
	}

	for(list<int>::iterator cons = bt->units_of_category[MOBILE_CONSTRUCTOR][ai->side-1].begin(); cons != bt->units_of_category[MOBILE_CONSTRUCTOR][ai->side-1].end(); ++cons)
	{
		if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
		{
			factory_table[i] = *cons;
			++i;
		}
	}

	for(list<int>::iterator cons = bt->units_of_category[COMMANDER][ai->side-1].begin(); cons != bt->units_of_category[COMMANDER][ai->side-1].end(); ++cons)
	{
		if(bt->units_static[*cons].unit_type & UNIT_TYPE_FACTORY)
		{
			factory_table[i] = *cons;
			++i;
		}
	}
}

float3 AAIExecute::GetRallyPoint(UnitCategory category, int min_dist, int max_dist, int random)
{
	AAISector* best_sector = 0;
	float best_rating = 0, my_rating;

	int combat_cat = bt->GetIDOfAssaultCategory(category);

	bool land = true; 
	bool water = true;

	if(!cfg->AIR_ONLY_MOD)
	{
		if(category == GROUND_ASSAULT)
			water = false;
		else if(category == SEA_ASSAULT || category == SUBMARINE_ASSAULT)
			land = false;
	}	

	// check neighbouring sectors
	for(int i = min_dist; i <= max_dist; ++i)
	{
		for(list<AAISector*>::iterator sector = brain->sectors[i].begin(); sector != brain->sectors[i].end(); sector++)
		{
			my_rating = 24.0f / ((*sector)->mobile_combat_power[combat_cat] + 4.0f) + 2 * (*sector)->GetMapBorderDist();
			
			if(land)
				my_rating += 8 * pow((*sector)->flat_ratio, 2);

			if(water)
				my_rating += 8 * pow((*sector)->water_ratio, 2);	

			my_rating += 0.25 * (rand()%random);

			my_rating /= sqrt(10.0f + (*sector)->allied_structures);

			if(my_rating > best_rating)
			{
				best_rating = my_rating;
				best_sector = *sector;
			}
		}
	}

	if(best_sector)
		return best_sector->GetCenter();
	else
		return ZeroVector;	
}

float3 AAIExecute::GetRallyPointCloseTo(UnitCategory category, float3 pos, int min_dist, int max_dist)
{
	AAISector* best_sector = 0;
	float best_rating = 0, my_rating;
	float3 center;

	int combat_cat = bt->GetIDOfAssaultCategory(category);

	bool land = true; 
	bool water = true;

	if(!cfg->AIR_ONLY_MOD)
	{
		if(category == GROUND_ASSAULT)
			water = false;
		else if(category == SEA_ASSAULT || category == SUBMARINE_ASSAULT)
			land = false;
	}	

	// check neighbouring sectors
	for(int i = min_dist; i <= max_dist; i++)
	{
		for(list<AAISector*>::iterator sector = brain->sectors[i].begin(); sector != brain->sectors[i].end(); sector++)
		{
			my_rating = 24.0f / ((*sector)->mobile_combat_power[combat_cat] + 4.0f);
			
			if(land)
				my_rating += 8 * pow((*sector)->flat_ratio, 2.0f);

			if(water)
				my_rating += 8 * pow((*sector)->water_ratio, 2.0f);

			center = (*sector)->GetCenter();

			my_rating /= sqrt( sqrt( pow( pos.x - center.x , 2.0f) + pow( pos.z - center.z , 2.0f) ) );

			if(my_rating > best_rating)
			{
				best_rating = my_rating;
				best_sector = *sector;
			}
		}
	}

	if(best_sector)
		return best_sector->GetCenter();
	else
		return ZeroVector;		
}


// ****************************************************************************************************
// all building functions
// ****************************************************************************************************

bool AAIExecute::BuildExtractor()
{
	if(ai->activeFactories < 1 && ai->activeUnits[EXTRACTOR] >= 2)
		return true;

	AAIConstructor *builder; 
	AAIMetalSpot *spot = 0;
	float3 pos;
	int land_mex;
	int water_mex;
	bool water;

	float cost = 0.25f + brain->Affordable() / 6.0f;
	float efficiency = 6.0 / (cost + 0.75f);

	// check if metal map
	if(ai->map->metalMap)
	{
		// get id of an extractor and look for suitable builder
		land_mex = bt->GetMex(ai->side, cost, efficiency, false, false, false);

		if(land_mex && bt->units_dynamic[land_mex].buildersAvailable <= 0)
		{
			bt->BuildBuilderFor(land_mex);
			land_mex = bt->GetMex(ai->side, cost, efficiency, false, false, true);
		}

		builder = ut->FindBuilder(land_mex, true, 10);

		if(builder)
		{
			pos = GetBuildsite(builder->unit_id, land_mex, EXTRACTOR);

			if(pos.x != 0)
			{
				builder->GiveConstructionOrder(land_mex, pos, false);
			}
			return true;
		}
		else
		{
			bt->AddBuilder(land_mex);
			return false;
		}
	}
	else // normal map
	{
		// different behaviour dependent on number of builders (to save time in late game)
		if(ut->constructors.size() < 5)
		{
			// get id of an extractor and look for suitable builder
			land_mex = bt->GetMex(ai->side, cost, efficiency, false, false, false);

			if(land_mex && bt->units_dynamic[land_mex].buildersAvailable <= 0)
			{
				bt->BuildBuilderFor(land_mex);
				land_mex = bt->GetMex(ai->side, cost, efficiency, false, false, true);
			}

			water_mex = bt->GetMex(ai->side, cost, efficiency, false, true, false);

			if(water_mex && bt->units_dynamic[water_mex].buildersAvailable <= 0)
			{
				bt->BuildBuilderFor(water_mex);
				water_mex = bt->GetMex(ai->side, cost, efficiency, false, true, true);
			}

			// find metal spot with lowest distance to available builders
			spot = FindMetalSpotClosestToBuilder(land_mex, water_mex);
	
			if(spot)
			{	
				// check if land or sea spot
				if(cb->GetElevation(spot->pos.x, spot->pos.z) < 0)
				{
					water = true;

					// build the water mex instead of land mex
					land_mex = water_mex;	
				}
				else
					water = false;
		
				// look for suitable builder
				int x = spot->pos.x/map->xSectorSize;
				int y = spot->pos.z/map->ySectorSize;

				// only allow commander if spot is close to own base
				if(map->sector[x][y].distance_to_base <= 0 || (brain->sectors[0].size() < 3 && map->sector[x][y].distance_to_base <= 1) )
					builder = ut->FindClosestBuilder(land_mex, spot->pos, true, 10);
				else
					builder = ut->FindClosestBuilder(land_mex, spot->pos, false, 10);
		
				if(builder)
				{
					builder->GiveConstructionOrder(land_mex, spot->pos, water);
					spot->occupied = true;
				}
				else
				{
					bt->AddBuilder(land_mex);
					return false;
				}
			}
			else
			{	

				// request metal makers if no spot found (only if spot was not found due to no buidlers available)
				builder = ut->FindClosestBuilder(land_mex, brain->base_center, true, 10);

				if(!builder)	
					builder = ut->FindClosestBuilder(water_mex, brain->base_center, true, 10);
		
				if(!builder)
				{
					if(map->mapType == WATER_MAP && !cfg->AIR_ONLY_MOD)
						bt->AddBuilder(water_mex);
					else
						bt->AddBuilder(land_mex);
				
					return false;
				}
				else
				{
					if(ai->activeUnits[METAL_MAKER] < cfg->MAX_METAL_MAKERS && urgency[METAL_MAKER] <= GetMetalUrgency() / 2.0f)
						urgency[METAL_MAKER] = GetMetalUrgency() / 2.0f;
				}
			}
		}
		else
		{
			bool land = true, water = true;

			// get next free metal spot
			AAIMetalSpot *spot = FindMetalSpot(land, water);

			if(spot)
			{
				int x = spot->pos.x/map->xSectorSize;
				int y = spot->pos.z/map->ySectorSize;

				if(cb->GetElevation(spot->pos.x, spot->pos.z) > 0) 
					water = false;	
				else
					water = true;
				
				// choose mex dependend on safety
				bool armed = false;

				//if(map->sector[x][y].lost_units[EXTRACTOR-COMMANDER] > 0.01f || map->sector[x][y].distance_to_base > 2)
				if(map->sector[x][y].distance_to_base > 2)
				{
					cost = 6.0f;
					armed = true;
					efficiency = 1.0f;

					// check mex upgrade
					if(ai->futureUnits[EXTRACTOR] < 2)
						CheckMexUpgrade();
				}

				int mex = bt->GetMex(ai->side, cost, efficiency, armed, water, false);

				if(mex && bt->units_dynamic[mex].buildersAvailable <= 0)
				{
					bt->BuildBuilderFor(mex);

					mex = bt->GetMex(ai->side, cost, efficiency, armed, water, true);
				}

				if(mex)
				{
					if(map->sector[x][y].distance_to_base <= 0 || (brain->sectors[0].size() < 3 && map->sector[x][y].distance_to_base <= 1) )
						builder = ut->FindClosestBuilder(mex, brain->base_center, true, 10);
					else
						builder = ut->FindClosestBuilder(mex, brain->base_center, false, 10);

					if(builder)
					{
						builder->GiveConstructionOrder(mex, spot->pos, water);
						spot->occupied = true;
					}
				}
			}
			else
			{	
				// check mex upgrade
				if(ai->futureUnits[EXTRACTOR] < 2)
					CheckMexUpgrade();

				// request metal makers if no spot found
				if(ai->activeUnits[METAL_MAKER] < cfg->MAX_METAL_MAKERS && urgency[METAL_MAKER] <= GetMetalUrgency() / 2.0f)
					urgency[METAL_MAKER] = GetMetalUrgency() / 2.0f;
			}
		}
	}

	return true;
}

bool AAIExecute::BuildPowerPlant()
{	
	if(ai->futureUnits[POWER_PLANT] > 1)
		return true;
	else if(ai->futureUnits[POWER_PLANT] > 0)
	{
		// try to assist construction of other power plants first
		AAIConstructor *builder;

		for(list<AAIBuildTask*>::iterator task = ai->build_tasks.begin(); task != ai->build_tasks.end(); ++task)
		{
			if((*task)->builder_id >= 0)
				builder = ut->units[(*task)->builder_id].cons;
			else
				builder = 0;
			
			// find the power plant that is already under construction
			if(builder && builder->construction_category == POWER_PLANT)
			{
				// dont build further power plants if already buidling an expensive plant 
				if(bt->units_static[builder->construction_def_id].cost > bt->avg_cost[POWER_PLANT][ai->side-1])
					return true;
				
				// try to assist
				if(builder->assistants.size() < cfg->MAX_ASSISTANTS)
				{
					AAIConstructor *assistant;

					if(bt->unitList[builder->construction_def_id-1]->minWaterDepth > 0)
					{
						if(bt->unitList[builder->construction_def_id-1]->floater)
							assistant = ut->FindClosestAssister(builder->build_pos, 5, true, true, true);
						else
							assistant = ut->FindClosestAssister(builder->build_pos, 5, true, true, false);
					}
						else
							assistant = ut->FindClosestAssister(builder->build_pos, 5, true, false, false);

					if(assistant)
					{
						builder->assistants.insert(assistant->unit_id);
						assistant->AssistConstruction(builder->unit_id, (*task)->unit_id);
						return true;
					}
					else 
						return false;
				}
			}
		}

		// power plant construction has not started -> builder is still on its way to constrcution site, wait until starting a new power plant
		return false;
	}
	else if(ai->activeFactories < 1 && ai->activeUnits[POWER_PLANT] >= 2)
		return true;

	// stop building power plants if already to much available energy
	if(cb->GetEnergyIncome() > 1.5f * cb->GetEnergyUsage() + 200.0)
		return true;

	int ground_plant = 0;
	int water_plant = 0;
	
	AAIConstructor *builder;
	float3 pos;

	float current_energy = cb->GetEnergyIncome();
	bool checkWater, checkGround;
	float urgency;
	float max_power;
	float eff;
	float energy = cb->GetEnergyIncome()+1;

	// check if already one power_plant under construction and energy short 
	if(ai->futureUnits[POWER_PLANT] > 0 && ai->activeUnits[POWER_PLANT] > 9 && averageEnergySurplus < 100)
	{
		urgency = 0.4f + GetEnergyUrgency();
		max_power = 0.5f;
		eff = 2.2f - brain->Affordable() / 4.0f;
	}
	else
	{
		max_power = 0.5f + pow((float) ai->activeUnits[POWER_PLANT], 0.8f);
		eff = 0.5 + 1.0f / (brain->Affordable() + 0.5f);
		urgency = 0.5f + GetEnergyUrgency();
	}

	// sort sectors according to threat level
	learned = 70000.0 / (cb->GetCurrentFrame() + 35000) + 1;
	current = 2.5 - learned;

	if(ai->activeUnits[POWER_PLANT] >= 2)
		brain->sectors[0].sort(suitable_for_power_plant);

	// get water and ground plant
	ground_plant = bt->GetPowerPlant(ai->side, eff, urgency, max_power, energy, false, false, false);
	// currently aai cannot build this building
	if(ground_plant && bt->units_dynamic[ground_plant].buildersAvailable <= 0)
	{
		if( bt->units_dynamic[water_plant].buildersRequested <= 0)
			bt->AddBuilder(ground_plant);

		ground_plant = bt->GetPowerPlant(ai->side, eff, urgency, max_power, energy, false, false, true);
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -