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

📄 aaiexecute.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// -------------------------------------------------------------------------
// AAI
//
// A skirmish AI for the TA Spring engine.
// Copyright Alexander Seizinger
// 
// Released under GPL license: see LICENSE.html for more information.
// -------------------------------------------------------------------------

#include "AAIExecute.h"
#include "AAIBuildTable.h"

// all the static vars
float AAIExecute::current = 0.5;
float AAIExecute::learned = 2.5;


AAIExecute::AAIExecute(AAI *ai, AAIBrain *brain)
{
	this->ai = ai;
	this->cb = ai->cb;
	this->bt = ai->bt;
	this->brain = brain;
	this->map = ai->map;
	this->ut = ai->ut;

	brain->execute = this;

//	buildques = 0;
//	factory_table = 0;
	unitProductionRate = 1;

	futureRequestedMetal = 0;
	futureRequestedEnergy = 0;
	futureAvailableMetal = 0;
	futureAvailableEnergy = 0;
	futureStoredMetal = 0;
	futureStoredEnergy = 0;
	averageMetalUsage = 0;
	averageEnergyUsage = 0;
	averageMetalSurplus = 0;
	averageEnergySurplus = 0;
	disabledMMakers = 0;

	next_defence = 0;
	def_category = UNKNOWN;

	for(int i = 0; i <= METAL_MAKER; ++i)
		urgency[i] = 0;

	for(int i = 0; i < 8; i++)
	{
		metalSurplus[i] = 0;
		energySurplus[i] = 0;
	}

	counter = 0;

	srand( time(NULL) );
}

AAIExecute::~AAIExecute(void)
{
//	if(buildques)
//	{
//		for(int i = 0; i < numOfFactories; ++i)
//			buildques[i].clear();

//		delete [] buildques;
//	}

//	if(factory_table)
//		delete [] factory_table;
}

void AAIExecute::moveUnitTo(int unit, float3 *position)
{
	Command c;

	c.id = CMD_MOVE;

	c.params.resize(3);
	c.params[0] = position->x;
	c.params[1] = position->y;
	c.params[2] = position->z;

	cb->GiveOrder(unit, &c);
	ut->SetUnitStatus(unit, MOVING);
}

void AAIExecute::stopUnit(int unit)
{
	Command c;
	c.id = CMD_STOP;

	cb->GiveOrder(unit, &c);
	ut->SetUnitStatus(unit, UNIT_IDLE);
}

// returns true if unit is busy
bool AAIExecute::IsBusy(int unit)
{
	const CCommandQueue* commands = cb->GetCurrentUnitCommands(unit);

	if(commands->empty())
		return false;
	return true;
}

// adds a unit to the group of attackers
void AAIExecute::AddUnitToGroup(int unit_id, int def_id, UnitCategory category)
{
	UnitType unit_type = bt->GetUnitType(def_id);

	for(list<AAIGroup*>::iterator group = ai->group_list[category].begin(); group != ai->group_list[category].end(); ++group)
	{
		if((*group)->AddUnit(unit_id, def_id, unit_type))
		{
			ai->ut->units[unit_id].group = *group;
			return;
		}
	}

	// end of grouplist has been reached and unit has not been assigned to any group
	// -> create newone
	AAIGroup *new_group;

	try
	{
		new_group = new AAIGroup(cb, ai, bt->unitList[def_id-1], unit_type);
	}
	catch(...) //catches everything
	{
		fprintf(ai->file, "Exception thrown when allocating memory for new group");
		return;
	}

	ai->group_list[category].push_back(new_group);
	new_group->AddUnit(unit_id, def_id, unit_type);
	ai->ut->units[unit_id].group = new_group;
}

void AAIExecute::UpdateRecon()
{
	float3 pos;

	// update units in los
	ai->map->UpdateRecon();

	// explore map -> send scouts to different sectors, build new scouts if needed etc.
	// check number of scouts and order new ones if necessary
	if(ai->activeScouts + ai->futureScouts < cfg->MAX_SCOUTS)
	{
		int scout = 0;

		
		float cost; 
		float los;

		int period = brain->GetGamePeriod();

		if(period == 0)
		{
			cost = 2;
			los = 0.5;
		}
		else if(period == 1)
		{
			cost = 1;
			los = 2;
		}
		else 
		{
			cost = 0.5;
			los = 4.0;
		}

		// determine movement type of scout based on map
		unsigned int allowed_movement_types = 0;
	
		allowed_movement_types |= MOVE_TYPE_AIR;
		
		if(map->mapType == LAND_MAP)
		{
			allowed_movement_types |= MOVE_TYPE_GROUND;
			allowed_movement_types |= MOVE_TYPE_HOVER;
		}
		else if(map->mapType == LAND_WATER_MAP)
		{
			allowed_movement_types |= MOVE_TYPE_GROUND;
			allowed_movement_types |= MOVE_TYPE_SEA;
			allowed_movement_types |= MOVE_TYPE_HOVER;
		}
		else if(map->mapType == WATER_MAP)
		{
			allowed_movement_types |= MOVE_TYPE_SEA;
			allowed_movement_types |= MOVE_TYPE_HOVER;
		}

		// request cloakable scouts from time to time
		if(rand()%5 == 1)
			scout = bt->GetScout(ai->side, los, cost, allowed_movement_types, 10, true, true);
		else
			scout = bt->GetScout(ai->side, los, cost, allowed_movement_types, 10, false, true);

		if(scout)
		{
			if(AddUnitToBuildque(scout, 1, false))
			{
				++ai->futureScouts;
				++bt->units_dynamic[scout].requested;

				//char c[120];
				//sprintf(c, "requested scout: %i", ai->futureScouts); 
				//cb->SendTextMsg(c, 0);
			}
		}
	}

	AAISector *dest;
	int scout_x, scout_y;

	// get idle scouts and let them explore the map
	for(list<int>::iterator scout = ai->scouts.begin(); scout != ai->scouts.end(); ++scout)
	{
		if(!IsBusy(*scout))
		{
			// get scout dest
			dest = brain->GetNewScoutDest(*scout);

			// get sector of scout
			pos = cb->GetUnitPos(*scout);
			scout_x = pos.x/map->xSectorSize;
			scout_y = pos.z/map->xSectorSize;

			if(dest->x > scout_x)
				pos.x = (dest->left + 7 * dest->right)/8;
			else if(dest->x < scout_x)
				pos.x = (7 * dest->left + dest->right)/8;
			else
				pos.x = (dest->left + dest->right)/2;

			if(dest->y > scout_y)
				pos.z = (7 * dest->bottom + dest->top)/8;
			else if(dest->y < scout_y)
				pos.z = (dest->bottom + 7 * dest->top)/8;
			else
				pos.z = (dest->bottom + dest->top)/2;

			pos.y = cb->GetElevation(pos.x, pos.z);

			moveUnitTo(*scout, &pos);

		}
	}
}

float3 AAIExecute::GetBuildsite(int builder, int building, UnitCategory category)
{
	float3 pos;
	float3 builder_pos;
	const UnitDef *def = bt->unitList[building-1];

	// check the sector of the builder
	builder_pos = cb->GetUnitPos(builder);
	// look in the builders sector first
	int x = builder_pos.x/ai->map->xSectorSize;
	int y = builder_pos.z/ai->map->ySectorSize;

	if(ai->map->sector[x][y].distance_to_base == 0)
	{
		pos = ai->map->sector[x][y].GetBuildsite(building);

		// if suitable location found, return pos...
		if(pos.x)	
			return pos;
	}

	// look in any of the base sectors
	for(list<AAISector*>::iterator s = brain->sectors[0].begin(); s != brain->sectors[0].end(); ++s)
	{	
		pos = (*s)->GetBuildsite(building);

		// if suitable location found, return pos...
		if(pos.x)	
			return pos;
	}

	pos.x = pos.y = pos.z = 0;
	return pos;
}

float3 AAIExecute::GetUnitBuildsite(int builder, int unit)
{
	float3 builder_pos = cb->GetUnitPos(builder);
	float3 pos = ZeroVector, best_pos = ZeroVector;
	float min_dist = 1000000, dist;

	for(list<AAISector*>::iterator s = brain->sectors[1].begin(); s != brain->sectors[1].end(); ++s)
	{	
		bool water = false;

		if(bt->IsSea(unit))
			water = true;

		pos = (*s)->GetBuildsite(unit, water);

		if(pos.x)
		{
			dist = sqrt( pow(pos.x - best_pos.x ,2.0f) + pow(pos.z - best_pos.z, 2.0f) );

			if(dist < min_dist)
			{
				min_dist = dist;
				best_pos = pos;
			}
		}
	}

	return best_pos;
}

AAIMetalSpot* AAIExecute::FindMetalSpot(bool land, bool water)
{
	// prevent crashes on smaller maps 
	int max_distance = min(cfg->MAX_MEX_DISTANCE, brain->max_distance);

	for(int sector_dist = 0; sector_dist < max_distance; ++sector_dist)
	{
		for(list<AAISector*>::iterator sector = brain->sectors[sector_dist].begin();sector != brain->sectors[sector_dist].end(); sector++)
		{
			if(sector_dist == 0)
			{
				if((*sector)->freeMetalSpots)
				{
					for(list<AAIMetalSpot*>::iterator spot = (*sector)->metalSpots.begin(); spot != (*sector)->metalSpots.end(); ++spot)
					{
						if(!(*spot)->occupied)	
						{
							if( (land && (*spot)->pos.y >= 0) ||(water && (*spot)->pos.y < 0) )
								return *spot;
						}
					}
				}
			}
			else
			{
				if((*sector)->freeMetalSpots && brain->IsSafeSector(*sector) && map->team_sector_map[(*sector)->x][(*sector)->y] == -1 )
				{
					for(list<AAIMetalSpot*>::iterator spot = (*sector)->metalSpots.begin(); spot != (*sector)->metalSpots.end(); ++spot)
					{
						if(!(*spot)->occupied)	
						{
							if( (land && (*spot)->pos.y >= 0) ||(water && (*spot)->pos.y < 0) )
								return *spot;
						}
					}
				}
			}
		}
	}

	return 0;
}

AAIMetalSpot* AAIExecute::FindMetalSpotClosestToBuilder(int land_mex, int water_mex)
{
	AAIMetalSpot *best_spot = 0;
	float shortest_dist = 10000.0f, dist;
	float3 builder_pos;
	AAIConstructor *builder = 0;

	// prevent crashes on smaller maps 
	int max_distance = min(cfg->MAX_MEX_DISTANCE, brain->max_distance);

	// dont search for too long if possible spot already found
	int min_spot_dist = -1;

	// look for free spots in all sectors within max range
	for(int sector_dist = 0; sector_dist < max_distance; ++sector_dist)
	{
		// skip search if spot already found 
		if(min_spot_dist >= 0 && sector_dist - min_spot_dist > 2)
			return best_spot;

		for(list<AAISector*>::iterator sector = brain->sectors[sector_dist].begin(); sector != brain->sectors[sector_dist].end(); sector++)
		{
			if((*sector)->freeMetalSpots && (*sector)->enemy_structures <= 0  && (*sector)->lost_units[MOBILE_CONSTRUCTOR-COMMANDER]  < 0.5 && (*sector)->threat <= 0)
			{
				for(list<AAIMetalSpot*>::iterator spot = (*sector)->metalSpots.begin(); spot != (*sector)->metalSpots.end(); ++spot)
				{
					if(!(*spot)->occupied)	
					{
						if((*spot)->pos.y > 0)
							builder = ut->FindClosestBuilder(land_mex, (*spot)->pos, true, 10);
						else
							builder = ut->FindClosestBuilder(water_mex, (*spot)->pos, true, 10);

						if(builder)
						{
							// get distance to pos
							builder_pos = cb->GetUnitPos(builder->unit_id);

							dist = sqrt( pow(((*spot)->pos.x - builder_pos.x), 2) + pow(((*spot)->pos.z - builder_pos.z),2) ) / bt->unitList[builder->def_id-1]->speed;

							if(dist < shortest_dist)
							{
								best_spot = *spot;
								shortest_dist = dist;

								min_spot_dist = sector_dist;
							}	
						}
					}	
				}
			}
		}
	}

	return best_spot;
}


float AAIExecute::GetTotalGroundPower()
{
	float power = 0;

	// get ground power of all ground assault units
	for(list<AAIGroup*>::iterator group = ai->group_list[GROUND_ASSAULT].begin(); group != ai->group_list[GROUND_ASSAULT].end(); group++)
		power += (*group)->GetPowerVS(0);
	
	return power;
}

float AAIExecute::GetTotalAirPower()
{
	float power = 0;

	for(list<AAIGroup*>::iterator group = ai->group_list[GROUND_ASSAULT].begin(); group != ai->group_list[GROUND_ASSAULT].end(); group++)
	{
		power += (*group)->GetPowerVS(1);
	}

	return power;
}

list<int>* AAIExecute::GetBuildqueOfFactory(int def_id)
{
	for(int i = 0; i < numOfFactories; ++i)
	{
		if(factory_table[i] == def_id)
			return &buildques[i];
	}

	return 0;
}

bool AAIExecute::AddUnitToBuildque(int def_id, int number, bool urgent)
{
	urgent = false;

	UnitCategory category = bt->units_static[def_id].category;

	if(category == UNKNOWN)
		return false;

	list<int> *buildque = 0, *temp = 0;
	
	float my_rating, best_rating = 0;

	for(list<int>::iterator fac = bt->units_static[def_id].builtByList.begin(); fac != bt->units_static[def_id].builtByList.end(); ++fac)
	{
		if(bt->units_dynamic[*fac].active > 0)
		{
			temp = GetBuildqueOfFactory(*fac);

			if(temp)
			{
				my_rating = (1 + 2 * (float) bt->units_dynamic[*fac].active) / (temp->size() + 3);

				if(map->mapType == WATER_MAP && !bt->CanPlacedWater(*fac))
					my_rating /= 10.0;
			}
			else 
				my_rating = 0;
		}
		else
			my_rating = 0;

		if(my_rating > best_rating)
		{
			best_rating = my_rating;
			buildque = temp;
		}
	}

	

	// determine position
	if(buildque)
	{
		//fprintf(ai->file, "Found builque for %s\n", bt->unitList[def_id-1]->humanName.c_str());

		if(bt->IsBuilder(def_id))
		{	
			buildque->insert(buildque->begin(), number, def_id);
			return true;	
		}
		else if(category == SCOUT)

⌨️ 快捷键说明

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