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

📄 aaibrain.cpp

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

#include "AAIBrain.h"
#include "AAI.h"
#include "AAIMap.h"

AAIBrain::AAIBrain(AAI *ai)
{
	this->ai = ai;
	this->map = ai->map;
	cb = ai->cb;
	bt = ai->bt;
	execute = 0;
	freeBaseSpots = false;
	expandable = true;

	// initialize random numbers generator
	srand ( time(NULL) );

	max_distance = ai->map->xSectors + ai->map->ySectors - 2;
//	sectors = new list<AAISector*>[max_distance];
	sectors.resize(max_distance);

	base_center = ZeroVector;

//	max_units_spotted = new float[bt->combat_categories];
	max_units_spotted.resize(bt->combat_categories);
//	attacked_by = new float[bt->combat_categories];
	attacked_by.resize(bt->combat_categories);
//	defence_power_vs = new float[bt->combat_categories];
	defence_power_vs.resize(bt->combat_categories);

	for(int i = 0; i < bt->combat_categories; ++i)
	{
		max_units_spotted[i] = 0;
		attacked_by[i] = 0;
		defence_power_vs[i] = 0;
	}
}

AAIBrain::~AAIBrain(void)
{
//	delete [] sectors;
//	delete [] max_units_spotted;
//	delete [] attacked_by;
//	delete [] defence_power_vs;
}


AAISector* AAIBrain::GetAttackDest(bool land, bool water, AttackType type)
{
	float best_rating = 0, my_rating;
	AAISector *dest = 0, *sector;

	int side = ai->side-1;
	
	float ground = map->map_usefulness[0][side]/100.0f;
	float air = map->map_usefulness[1][side]/100.0f;
	float hover = map->map_usefulness[2][side]/100.0f;
	float sea = map->map_usefulness[3][side]/100.0f;
	float submarine = map->map_usefulness[4][side]/100.0f;

	// TODO: improve destination sector selection
	for(int x = 0; x < map->xSectors; x++)
	{
		for(int y = 0; y < map->ySectors; y++)
		{
			sector = &map->sector[x][y];

			if(sector->distance_to_base == 0 || sector->enemy_structures == 0)
					my_rating = 0;
			else if(type == BASE_ATTACK)
			{
				if(land && sector->water_ratio < 0.35)
				{
					my_rating = sector->enemy_structures / (2 * sector->GetThreatTo(ground, air, hover, sea, submarine) + pow(sector->GetLostUnits(ground, air, hover, sea, submarine) + 1, 1.5f) + 1);
					my_rating /= (8 + sector->distance_to_base);
				}
				else if(water && sector->water_ratio > 0.65)
				{
					my_rating = sector->enemy_structures / (2 * sector->GetThreatTo(ground, air, hover, sea, submarine) + pow(sector->GetLostUnits(ground, air, hover, sea, submarine) + 1, 1.5f) + 1);
					my_rating /= (8 + sector->distance_to_base);
				}
				else 
					my_rating = 0;
			}
			else if(type == OUTPOST_ATTACK)
			{
				if(land && sector->water_ratio < 0.35)
				{
					my_rating = 1 / (1 + pow(sector->GetThreatTo(ground, air, hover, sea, submarine), 2.0f) + pow(sector->GetLostUnits(ground, air, hover, sea, submarine) + 1, 1.5f));
					my_rating /= (2 + sector->distance_to_base);
				}
				else if(water && sector->water_ratio > 0.65)
				{
					my_rating = 1 / (1 + pow(sector->GetThreatTo(ground, air, hover, sea, submarine), 2.0f) + pow(sector->GetLostUnits(ground, air, hover, sea, submarine) + 1, 1.5f));
					my_rating /= (2 + sector->distance_to_base);
				}	
				else 
					my_rating = 0;	
			}

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

	return dest;
}

AAISector* AAIBrain::GetNextAttackDest(AAISector *current_sector, bool land, bool water)
{
	float best_rating = 0, my_rating, dist;
	AAISector *dest = 0, *sector;

	int side = ai->side-1;
	
	float ground = map->map_usefulness[0][side]/100.0f;
	float air = map->map_usefulness[1][side]/100.0f;
	float hover = map->map_usefulness[2][side]/100.0f;
	float sea = map->map_usefulness[3][side]/100.0f;
	float submarine = map->map_usefulness[4][side]/100.0f;

	// TODO: improve destination sector selection
	for(int x = 0; x < map->xSectors; x++)
	{
		for(int y = 0; y < map->ySectors; y++)
		{
			sector = &map->sector[x][y];

			if(sector->distance_to_base == 0 || sector->enemy_structures == 0)
					my_rating = 0;
			else 
			{
				if(land && sector->water_ratio < 0.35)
				{
					dist = sqrt( pow((float)sector->x - current_sector->x, 2) + pow((float)sector->y - current_sector->y , 2) );
					
					my_rating = 1 / (1 + pow(sector->GetThreatTo(ground, air, hover, sea, submarine), 2.0f) + pow(sector->GetLostUnits(ground, air, hover, sea, submarine) + 1, 1.5f));
				
				}
				else if(water && sector->water_ratio > 0.65)
				{
					dist = sqrt( pow((float)(sector->x - current_sector->x), 2) + pow((float)(sector->y - current_sector->y), 2) );

					my_rating = 1 / (1 + pow(sector->GetThreatTo(ground, air, hover, sea, submarine), 2.0f) + pow(sector->GetLostUnits(ground, air, hover, sea, submarine) + 1, 1.5f));
					my_rating /= (1 + dist);
				}	
				else 
					my_rating = 0;	
			}

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

	return dest;
}

AAISector* AAIBrain::GetNewScoutDest(int scout)
{
	// TODO: take scouts pos into account
	float my_rating, best_rating = 0;
	AAISector *scout_sector = 0, *sector;
	
	const UnitDef *def = cb->GetUnitDef(scout);
	
	for(int x = 0; x < map->xSectors; x++)
	{
		for(int y = 0; y < map->ySectors; y++)
		{
			sector = &map->sector[x][y];
			
			if(sector->distance_to_base > 0)
			{
				// land sector
				if(sector->water_ratio > 0.7)
				{
					if(! (bt->units_static[def->id].movement_type & MOVE_TYPE_GROUND))
					{
						my_rating = sector->importance_this_game * sector->last_scout;
						++sector->last_scout;
					}
					else
						my_rating = 0;
				}
				// water sector
				else if(sector->water_ratio < 0.3)
				{
					if(! (bt->units_static[def->id].movement_type & MOVE_TYPE_SEA))
					{
						my_rating = sector->importance_this_game * sector->last_scout;
						++sector->last_scout;
					}
					else
						my_rating = 0;
				}
				// land/water sector
				else
				{
					my_rating = sector->importance_this_game * sector->last_scout;
					++sector->last_scout;
				}

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

	// set dest sector as visited
	if(scout_sector)
		scout_sector->last_scout = 1;
	
	return scout_sector;
}

bool AAIBrain::MetalForConstr(int unit, int workertime)
{
	// check index 
	if(unit >= bt->numOfUnits)
	{
		fprintf(ai->file, "ERROR: MetalForConstr(): index %i out of range, max units are: %i\n", unit, bt->numOfSides);
		return false;
	}

	int metal = (bt->unitList[unit-1]->buildTime/workertime) * (cb->GetMetalIncome()-(cb->GetMetalUsage()) + cb->GetMetal());
	int total_cost = bt->unitList[unit-1]->metalCost;
	
	if(metal > total_cost)
		return true;
	
	return false;
}

bool AAIBrain::EnergyForConstr(int unit, int wokertime)
{
	// check index 
	if(unit >= bt->numOfUnits)
	{
		fprintf(ai->file, "ERROR: EnergyForConstr(): index %i out of range, max units are: %i\n", unit, bt->numOfSides);
		return false;
	}

	// check energy
	int energy =  bt->unitList[unit-1]->buildTime * (cb->GetEnergyIncome()-(cb->GetEnergyUsage()/2));

	return true;
	//return (energy > bt->unitList[unit-1]->energyCost);
}

bool AAIBrain::RessourcesForConstr(int unit, int wokertime)
{
	// check metal and energy
	/*if(MetalForConstr(unit) && EnergyForConstr(unit))
			return true;
	
	return false;*/
	return true;
}

void AAIBrain::AddSector(AAISector *sector)
{
	sectors[0].push_back(sector);
	
	sector->SetBase(true);
}

void AAIBrain::DefendCommander(int attacker)
{
	float3 pos = cb->GetUnitPos(ai->ut->cmdr);
	float importance = 120;
	Command c;

	// evacuate cmdr
	/*if(ai->cmdr->task != BUILDING)
	{
		AAISector *sector = GetSafestSector();

		if(sector != 0)
		{
			pos = sector->GetCenter();

			if(pos.x > 0 && pos.z > 0)
			{
				pos.y = cb->GetElevation(pos.x, pos.z);
				execute->moveUnitTo(ai->cmdr->unit_id, &pos);
			}
		}
	}*/
}

void AAIBrain::UpdateBaseCenter()
{
	base_center = ZeroVector;

	for(list<AAISector*>::iterator sector = sectors[0].begin(); sector != sectors[0].end(); ++sector)
	{
		base_center.x += (0.5 + (*sector)->x) * map->xSectorSize;
		base_center.z += (0.5 + (*sector)->y) * map->ySectorSize;
	}

	base_center.x /= sectors[0].size();
	base_center.z /= sectors[0].size();
}

void AAIBrain::UpdateNeighbouringSectors()
{
	int x,y,neighbours;

	// delete old values
	for(x = 0; x < map->xSectors; ++x)
	{
		for(y = 0; y < map->ySectors; ++y)
		{
			if(map->sector[x][y].distance_to_base > 0)
				map->sector[x][y].distance_to_base = -1;
		}
	}

	for(int i = 1; i < max_distance; ++i)
	{
		// delete old sectors
		sectors[i].clear();
		neighbours = 0;

		for(list<AAISector*>::iterator sector = sectors[i-1].begin(); sector != sectors[i-1].end(); ++sector)
		{
			x = (*sector)->x;
			y = (*sector)->y;

			// check left neighbour 
			if(x > 0 && map->sector[x-1][y].distance_to_base == -1)
			{
				map->sector[x-1][y].distance_to_base = i;
				sectors[i].push_back(&map->sector[x-1][y]);
				++neighbours;
			}
			// check right neighbour
			if(x < (ai->map->xSectors - 1) && ai->map->sector[x+1][y].distance_to_base == -1)
			{

⌨️ 快捷键说明

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