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

📄 aaibuildtable.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 "AAIBuildTable.h"

#include "AAI.h"

// all the static vars
const UnitDef** AAIBuildTable::unitList = 0;
list<int>* AAIBuildTable::units_of_category[MOBILE_CONSTRUCTOR+1];
int AAIBuildTable::aai_instances = 0; 
float* AAIBuildTable::avg_cost[MOBILE_CONSTRUCTOR+1]; 
float* AAIBuildTable::avg_buildtime[MOBILE_CONSTRUCTOR+1];
float* AAIBuildTable::avg_value[MOBILE_CONSTRUCTOR+1];
float* AAIBuildTable::max_cost[MOBILE_CONSTRUCTOR+1]; 
float* AAIBuildTable::max_buildtime[MOBILE_CONSTRUCTOR+1];
float* AAIBuildTable::max_value[MOBILE_CONSTRUCTOR+1];
float* AAIBuildTable::min_cost[MOBILE_CONSTRUCTOR+1]; 
float* AAIBuildTable::min_buildtime[MOBILE_CONSTRUCTOR+1];
float* AAIBuildTable::min_value[MOBILE_CONSTRUCTOR+1];
float**	AAIBuildTable::avg_speed;
float**	AAIBuildTable::min_speed;
float**	AAIBuildTable::max_speed;
float**	AAIBuildTable::group_speed;
float** AAIBuildTable::attacked_by_category[2];
float*** AAIBuildTable::mod_usefulness;
vector<UnitTypeStatic> AAIBuildTable::units_static;
vector<vector<double> >AAIBuildTable::def_power;
vector<double>AAIBuildTable::max_pplant_eff;
float* AAIBuildTable::max_builder_buildtime;
float* AAIBuildTable::max_builder_cost;
float* AAIBuildTable::max_builder_buildspeed;
vector< vector< vector<float> > > AAIBuildTable::avg_eff;
vector< vector< vector<float> > > AAIBuildTable::max_eff;
vector< vector< vector<float> > > AAIBuildTable::min_eff;
vector< vector< vector<float> > > AAIBuildTable::total_eff;
vector< vector<float> > AAIBuildTable::fixed_eff;

AAIBuildTable::AAIBuildTable(IAICallback *cb, AAI* ai)
{
	this->cb = cb;
	this->ai = ai;

	initialized = false;
	numOfUnits = 0;

	numOfSides = cfg->SIDES;
	startUnits.resize(numOfSides);
	sideNames.resize(numOfSides+1);
	sideNames[0] = "Neutral";
	
	const UnitDef *temp;

	for(int i = 0; i < numOfSides; i++)
	{
		temp = cb->GetUnitDef(cfg->START_UNITS[i]);

		if(temp)
			startUnits[i] = temp->id;
		else
		{
			startUnits[i] = -1;

			char c[120];
			sprintf(c, "Error: starting unit %s not found\n", cfg->START_UNITS[i]);
			cb->SendTextMsg(c,0);
			fprintf(ai->file, c);
		}

		sideNames[i+1].assign(cfg->SIDE_NAMES[i]);
	}	

	// add assault categories
	assault_categories.push_back(GROUND_ASSAULT);
	assault_categories.push_back(AIR_ASSAULT);
	assault_categories.push_back(HOVER_ASSAULT);
	assault_categories.push_back(SEA_ASSAULT);
	assault_categories.push_back(SUBMARINE_ASSAULT);

	//ass_categories = (int)assault_categories.size();
	//combat_categories = ass_categories + 1;

	// one more instance
	++aai_instances;

	ai->aai_instance = aai_instances;

	// only set up static things if first aai intsance is iniatialized
	if(aai_instances == 1)
	{
		for(int i = 0; i <= MOBILE_CONSTRUCTOR; ++i)
		{
			// set up the unit lists
			units_of_category[i] = new list<int>[numOfSides];

			// statistical values (mod sepcific)
			avg_cost[i] = new float[numOfSides];
			avg_buildtime[i] = new float[numOfSides];
			avg_value[i] = new float[numOfSides];
			max_cost[i] = new float[numOfSides];
			max_buildtime[i] = new float[numOfSides];
			max_value[i] = new float[numOfSides];
			min_cost[i] = new float[numOfSides];
			min_buildtime[i] = new float[numOfSides];
			min_value[i] = new float[numOfSides];

			for(int s = 0; s < numOfSides; ++s)
			{
				avg_cost[i][s] = -1;
				avg_buildtime[i][s] = -1;
				avg_value[i][s] = -1;
				max_cost[i][s] = -1;
				max_buildtime[i][s] = -1;
				max_value[i][s] = -1;
				min_cost[i][s] = -1;
				min_buildtime[i][s] = -1;
				min_value[i][s] = -1;
			}
		}

		// statistical values for builders (map specific)
		max_builder_buildtime = new float[numOfSides];
		max_builder_cost = new float[numOfSides];
		max_builder_buildspeed = new float[numOfSides];

		for(int s = 0; s < numOfSides; ++s)
		{
			max_builder_buildtime[s] = -1;
			max_builder_cost[s] = -1;
			max_builder_buildspeed[s] = -1;
		}

		// set up speed and attacked_by table
		avg_speed = new float*[combat_categories];
		max_speed = new float*[combat_categories];
		min_speed = new float*[combat_categories];
		group_speed = new float*[combat_categories];

		attacked_by_category[0] = new float*[combat_categories];
		attacked_by_category[1] = new float*[combat_categories];

		for(int i = 0; i < combat_categories; ++i)
		{
			avg_speed[i] = new float[numOfSides];
			max_speed[i] = new float[numOfSides];
			min_speed[i] = new float[numOfSides];
			group_speed[i] = new float[numOfSides];

			attacked_by_category[0][i] = new float[4];
			attacked_by_category[1][i] = new float[4];
		}

		// set up mod_usefulness 
		mod_usefulness = new float**[assault_categories.size()];

		for(int i = 0; i < assault_categories.size(); ++i)
		{
			mod_usefulness[i] = new float*[cfg->SIDES];

			for(int j = 0; j < cfg->SIDES; ++j)
				mod_usefulness[i][j] = new float[WATER_MAP+1];
		}

		// init eff stats
		avg_eff.resize(numOfSides, vector< vector<float> >(combat_categories, vector<float>(combat_categories, 1)));
		max_eff.resize(numOfSides, vector< vector<float> >(combat_categories, vector<float>(combat_categories, 1)));
		min_eff.resize(numOfSides, vector< vector<float> >(combat_categories, vector<float>(combat_categories, 1)));
		total_eff.resize(numOfSides, vector< vector<float> >(combat_categories, vector<float>(combat_categories, 1)));
	}
}

AAIBuildTable::~AAIBuildTable(void)
{
	// one instance less
	--aai_instances;

	// delete common data only if last aai instace has gone
	if(aai_instances == 0)
	{	

		delete [] unitList;

		for(int i = 0; i <= MOBILE_CONSTRUCTOR; ++i)
		{
			delete [] units_of_category[i];
			
			delete [] avg_cost[i];
			delete [] avg_buildtime[i];
			delete [] avg_value[i];
			delete [] max_cost[i];
			delete [] max_buildtime[i];
			delete [] max_value[i];
			delete [] min_cost[i];
			delete [] min_buildtime[i];
			delete [] min_value[i];
		}

		delete [] max_builder_buildtime;
		delete [] max_builder_cost;
		delete [] max_builder_buildspeed;

		for(int i = 0; i < combat_categories; ++i)
		{
			delete [] avg_speed[i];
			delete [] max_speed[i];
			delete [] min_speed[i];
			delete [] group_speed[i];

			delete [] attacked_by_category[0][i];
			delete [] attacked_by_category[1][i];
		}

		delete [] avg_speed;
		delete [] max_speed;
		delete [] min_speed;
		delete [] group_speed;

		delete [] attacked_by_category[0];
		delete [] attacked_by_category[1];

		// clean up mod usefulness	
		for(int i = 0; i < assault_categories.size(); ++i)
		{
			for(int j = 0; j < cfg->SIDES; ++j)
				delete [] mod_usefulness[i][j];
		
			delete [] mod_usefulness[i];
		}

		delete [] mod_usefulness;

		avg_eff.clear();
		max_eff.clear();
		min_eff.clear();
		total_eff.clear();
	}
}

void AAIBuildTable::Init()
{
	float max_cost = 0, min_cost = 1000000, eff;

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

	// get number of units and alloc memory for unit list
	numOfUnits = cb->GetNumUnitDefs();

	// one more than needed because 0 is dummy object (so UnitDef->id can be used to adress that unit in the array) 
	units_dynamic.resize(numOfUnits+1);

	for(int i = 0; i <= numOfUnits; i++)
	{
		units_dynamic[i].active = 0;
		units_dynamic[i].requested = 0;
		units_dynamic[i].buildersAvailable = 0;
		units_dynamic[i].buildersRequested = 0;
	}

	// get unit defs from game
	if(!unitList)
	{
		unitList = new const UnitDef*[numOfUnits];
		cb->GetUnitDefList(unitList);
	}

	// Try to load buildtable, if not possible create new one
	if(!LoadBuildTable())
	{	
		// one more than needed because 0 is dummy object (so UnitDef->id can be used to adress that unit in the array) 
		units_static.resize(numOfUnits+1);
		fixed_eff.resize(numOfUnits+1, vector<float>(combat_categories));
		
		// temporary list to sort air unit in air only mods
		list<int> *temp_list;
		temp_list = new list<int>[numOfSides];

		units_static[0].def_id = 0;
		units_static[0].side = 0;

		// add units to buildtable
		for(int i = 1; i <= numOfUnits; ++i)
		{
			// get id 
			units_static[i].def_id = unitList[i-1]->id;
			units_static[i].cost = (unitList[i-1]->metalCost + (unitList[i-1]->energyCost / 75.0f)) / 10.0f;

			if(units_static[i].cost > max_cost)
				max_cost = units_static[i].cost;

			if(units_static[i].cost < min_cost)
				min_cost = units_static[i].cost;
			
			units_static[i].builder_cost = 0; // will be added later when calculating the buildtree
	
			// side has not been assigned - will be done later
			units_static[i].side = 0;
			units_static[i].range = 0;
			
			units_static[i].category = UNKNOWN;

			units_static[i].unit_type = 0;
		
			// get build options
			for(map<int, string>::const_iterator j = unitList[i-1]->buildOptions.begin(); j != unitList[i-1]->buildOptions.end(); ++j)
			{
				units_static[i].canBuildList.push_back(cb->GetUnitDef(j->second.c_str())->id);
			}
		}

		// now set the sides and create buildtree
		for(int s = 0; s < numOfSides; s++)
		{
			// set side of the start unit (eg commander) and continue recursively
			units_static[startUnits[s]].side = s+1;
			CalcBuildTree(startUnits[s]);
		}

		// now calculate efficiency of combat units and get max range
		for(int i = 1; i <= numOfUnits; i++)
		{
			// effiency has starting value of 1
			if(!unitList[i-1]->weapons.empty())
			{
				// get range
				units_static[i].range = GetMaxRange(i);

				// get memory for eff
//				units_static[i].efficiency = new float[combat_categories];
				units_static[i].efficiency.resize(combat_categories);

				eff = 5 + 25 * (units_static[i].cost - min_cost)/(max_cost - min_cost);
				
				for(int k = 0; k < combat_categories; ++k)
				{
					units_static[i].efficiency[k] = eff;
					fixed_eff[i][k] = eff;
				}
			}
			else
			{
				units_static[i].range = 0;
				
				// get memory for eff
//				units_static[i].efficiency = new float[combat_categories];
				units_static[i].efficiency.resize(combat_categories);
				
				for(int k = 0; k < combat_categories; ++k)
					units_static[i].efficiency[k] = -1;
			}
		}
	
		//
		// determine movement type 
		//
		for(int i = 1; i <= numOfUnits; i++)
		{
			units_static[i].movement_type = 0;	

			if(unitList[i-1]->movedata)
			{
				if(unitList[i-1]->movedata->moveType == MoveData::Ground_Move)
					units_static[i].movement_type |= MOVE_TYPE_GROUND;
				else if(unitList[i-1]->movedata->moveType == MoveData::Hover_Move)
					units_static[i].movement_type |= MOVE_TYPE_HOVER;	
				// ship
				else if(unitList[i-1]->movedata->moveType == MoveData::Ship_Move)
				{
					units_static[i].movement_type |= MOVE_TYPE_SEA;	

					if(unitList[i-1]->categoryString.find("UNDERWATER") != string::npos)
						units_static[i].movement_type |= MOVE_TYPE_UNDERWATER;
					else
						units_static[i].movement_type |= MOVE_TYPE_FLOATER;
				}
			}
			// aircraft
			else if(unitList[i-1]->canfly) 
				units_static[i].movement_type |= MOVE_TYPE_AIR;		
			// stationary
			else	
			{
				units_static[i].movement_type |= MOVE_TYPE_STATIC;

				if(unitList[i-1]->minWaterDepth <= 0)
				{
					units_static[i].movement_type |= MOVE_TYPE_STATIC_LAND;
				}
				else
				{
					units_static[i].movement_type |= MOVE_TYPE_STATIC_WATER;

					if(unitList[i-1]->floater)
						units_static[i].movement_type |= MOVE_TYPE_FLOATER;

⌨️ 快捷键说明

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