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

📄 aaimap.cpp

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

// Released under GPL license: see LICENSE.html for more information.
// -------------------------------------------------------------------------

#include "AAIMap.h"
#include "AAI.h"
#include "AAISector.h"
#include "AAIBuildTable.h"

// all the static vars
int AAIMap::aai_instances = 0;
int AAIMap::xMapSize;
int AAIMap::yMapSize;				
int AAIMap::xDefMapSize;
int AAIMap::yDefMapSize;		
int AAIMap::xSectors;
int AAIMap::ySectors;				
int AAIMap::xSectorSize; 
int AAIMap::ySectorSize;		
int AAIMap::xSectorSizeMap; 
int AAIMap::ySectorSizeMap;

list<AAIMetalSpot>  AAIMap::metal_spots;

bool AAIMap::metalMap;
MapType AAIMap::mapType;	

vector< vector<int> > AAIMap::team_sector_map;
vector<int> AAIMap::buildmap;	
vector<int> AAIMap::blockmap;	
vector<float> AAIMap::plateau_map;

list<UnitCategory> AAIMap::map_categories;
list<int> AAIMap::map_categories_id;
vector<vector<float> > AAIMap::map_usefulness;



AAIMap::AAIMap(AAI *ai)
{
	// initialize random numbers generator
	srand ( time(NULL) );

	this->ai = ai;
	bt = ai->bt;
	cb = ai->cb;

	initialized = false;

	unitsInLos.resize(cfg->MAX_UNITS);

	// set all values to 0 (to be able to detect num. of enemies in los later
	for(int i = 0; i < cfg->MAX_UNITS; i++)
		unitsInLos[i] = 0;

	/*map_usefulness.resize(bt->assault_categories.size());

	for(int i = 0; i < bt->assault_categories.size(); ++i)
		map_usefulness[i].resize(cfg->SIDES);*/

	units_spotted.resize(bt->combat_categories);
}

AAIMap::~AAIMap(void)
{
	--aai_instances;

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

		// save map data
		char filename[500];
		char buffer[500];
		strcpy(buffer, MAIN_PATH);
		strcat(buffer, MAP_LEARN_PATH);
		strcat(buffer, cb->GetMapName());
		ReplaceExtension(buffer, filename, sizeof(filename), "_");
		strcat(filename, cb->GetModName());
		ReplaceExtension(filename, buffer, sizeof(filename), ".dat");

		ai->cb->GetValue(AIVAL_LOCATE_FILE_W, buffer);
	
		FILE *save_file = fopen(buffer, "w+");

		fprintf(save_file, "%s \n",MAP_FILE_VERSION);

		// save map type
		fprintf(save_file, "%s \n", GetMapTypeString(mapType));

		// save units map_usefulness
		float sum;

		for(int i = 0; i < cfg->SIDES; ++i)
		{
			// rebalance map_usefulness
			if(mapType == LAND_MAP)
			{
				sum = map_usefulness[0][i] + map_usefulness[2][i];
				map_usefulness[0][i] *= (100.0/sum);
				map_usefulness[2][i] *= (100.0/sum);
			}
			else if(mapType == LAND_WATER_MAP)
			{
				sum = map_usefulness[0][i] + map_usefulness[2][i] + map_usefulness[3][i] + map_usefulness[4][i];
				map_usefulness[0][i] *= (100.0/sum);
				map_usefulness[2][i] *= (100.0/sum);
				map_usefulness[3][i] *= (100.0/sum);
				map_usefulness[4][i] *= (100.0/sum);
			}
			else if(mapType == WATER_MAP)
			{
				sum = map_usefulness[2][i] + map_usefulness[3][i] + map_usefulness[4][i];
				map_usefulness[2][i] *= (100.0/sum);
				map_usefulness[3][i] *= (100.0/sum);
				map_usefulness[4][i] *= (100.0/sum);
			}

			// save
			for(int j = 0; j < bt->assault_categories.size(); ++j)
				fprintf(save_file, "%f ", map_usefulness[j][i]);
		}

		fprintf(save_file, "\n");

		for(int y = 0; y < ySectors; y++)
		{
			for(int x = 0; x < xSectors; x++)
			{
				// save sector data
				fprintf(save_file, "%f %f %f", sector[x][y].flat_ratio, sector[x][y].water_ratio, sector[x][y].importance_this_game);
				// save combat data
				for(int cat = 0; cat < bt->assault_categories.size(); ++cat)
					fprintf(save_file, "%f %f ", sector[x][y].attacked_by_this_game[cat], sector[x][y].combats_this_game[cat]);
			}

			fprintf(save_file, "\n");
		}

		fclose(save_file);

		buildmap.clear();
		blockmap.clear();
		defence_map.clear();
		air_defence_map.clear();
		plateau_map.clear();
	}
}

void AAIMap::Init()
{
	++aai_instances;

	// all static vars are only initialized by the first aai instance 
	if(aai_instances == 1)
	{
		// get size
		xMapSize = cb->GetMapWidth();
		yMapSize = cb->GetMapHeight();

		xDefMapSize = xMapSize / 2;
		yDefMapSize = yMapSize / 2;

		// calculate number of sectors
		xSectors = floor(0.5f + ((float) xMapSize)/cfg->SECTOR_SIZE);
		ySectors = floor(0.5f + ((float) yMapSize)/cfg->SECTOR_SIZE);

		// calculate effective sector size
		xSectorSizeMap = floor( ((float) xMapSize) / ((float) xSectors) );
		ySectorSizeMap = floor( ((float) yMapSize) / ((float) ySectors) );

		xSectorSize = 8 * xSectorSizeMap;
		ySectorSize = 8 * ySectorSizeMap;

		blockmap.resize(xMapSize*yMapSize, 0);
		plateau_map.resize(xMapSize*yMapSize / 4, 0);
		
		// create map that stores which aai player has occupied which sector (visible to all aai players)
		team_sector_map.resize(xSectors);

		for(int x = 0; x < xSectors; ++x)
			team_sector_map[x].resize(ySectors, -1);

		ReadCacheFile();
	}

	// create field of sectors
	sector.resize(xSectors);

	for(int x = 0; x < xSectors; ++x)
		sector[x].resize(ySectors);

	for(int j = 0; j < ySectors; ++j)
	{
		for(int i = 0; i < xSectors; ++i)
			// provide ai callback to sectors & set coordinates of the sectors
			sector[i][j].Init(ai, i, j, xSectorSize*i, xSectorSize*(i+1), ySectorSize * j, ySectorSize * (j+1));
	}

	// add metalspots to their sectors
	int k, l;
	for(list<AAIMetalSpot>::iterator spot = metal_spots.begin(); spot != metal_spots.end(); ++spot)
	{
		k = spot->pos.x/xSectorSize;
		l = spot->pos.z/ySectorSize;

		if(k < xSectors && l < ySectors)
			sector[k][l].AddMetalSpot(&(*spot));
	}

	ReadMapLearnFile(true);

	// for scouting
	unitsInSector.resize(xSectors*ySectors);

	// create defence
	defence_map.resize(xDefMapSize*yDefMapSize, 0);
	air_defence_map.resize(xDefMapSize*yDefMapSize, 0); 

	initialized = true;

	// for log file
	fprintf(ai->file, "Map: %s\n",cb->GetMapName());
	fprintf(ai->file, "Mapsize is %i x %i\n", cb->GetMapWidth(),cb->GetMapHeight());
	fprintf(ai->file, "%i sectors in x direction\n", xSectors);
	fprintf(ai->file, "%i sectors in y direction\n", ySectors);
	fprintf(ai->file, "x-sectorsize is %i (Map %i)\n", xSectorSize, xSectorSizeMap);
	fprintf(ai->file, "y-sectorsize is %i (Map %i)\n", ySectorSize, ySectorSizeMap);
	fprintf(ai->file, "%i metal spots found \n \n",metal_spots.size());

	//debug
	/*float3 my_pos;
	for(int x = 0; x < xMapSize; x+=2)
	{
		for(int y = 0; y < yMapSize; y+=2)
		{
			if(buildmap[x + y*xMapSize] == 1 || buildmap[x + y*xMapSize] == 5)
			{
				my_pos.x = x * 8;
				my_pos.z = y * 8;
				my_pos.y = cb->GetElevation(my_pos.x, my_pos.z);
				cb->DrawUnit("ARMMINE1", my_pos, 0.0f, 8000, cb->GetMyAllyTeam(), true, true);
			}
		}
	}*/
}

void AAIMap::ReadCacheFile()
{
	// try to read cache file
	bool loaded = false;
	char filename[500];
	char buffer[500];
	strcpy(buffer, MAIN_PATH);
	strcat(buffer, MAP_CACHE_PATH);
	strcat(buffer, cb->GetMapName());
	ReplaceExtension(buffer, filename, sizeof(filename), ".dat");

	ai->cb->GetValue(AIVAL_LOCATE_FILE_R, filename);

	FILE *file;

	if(file = fopen(filename, "r"))
	{
		// check if correct version
		fscanf(file, "%s ", buffer);

		if(strcmp(buffer, MAP_DATA_VERSION))
		{
			cb->SendTextMsg("Mapcache out of date - creating new one", 0);
			fprintf(ai->file, "Map cache-file out of date - new one has been created\n");
		}
		else
		{
			int temp;
			float temp_float;

			// load if its a metal map
			fscanf(file, "%i ", &temp);
			metalMap = (bool)temp;

			// load buildmap 
			for(int i = 0; i < xMapSize*yMapSize; ++i)
			{
				//fread(&temp, sizeof(int), 1, file);
				fscanf(file, "%i ", &temp); 
				buildmap.push_back(temp);
			}
		
			// load plateau map
			for(int i = 0; i < xMapSize*yMapSize/4; ++i)
			{
				//fread(&temp_float, sizeof(float), 1, file);
				fscanf(file, "%f ", &temp_float); 
				buildmap.push_back(temp_float);
			}

			AAIMetalSpot spot;
			fscanf(file, "%i ", &temp);

			// load mex spots
			for(int i = 0; i < temp; ++i)
			{
				fscanf(file, "%f %f %f %f ", &(spot.pos.x), &(spot.pos.y), &(spot.pos.z), &(spot.amount));
				spot.occupied = false;
				metal_spots.push_back(spot);
			}

			fprintf(ai->file, "Map cache file succesfully loaded\n");

			loaded = true;

			fclose(file);
		}
	}
	if(!loaded)  // create new map data
	{
		buildmap.resize(xMapSize*yMapSize, 0);

		// look for metalspots
		SearchMetalSpots();
	
		AnalyseMap();

		strcpy(buffer, MAIN_PATH);
		strcat(buffer, MAP_CACHE_PATH);
		strcat(buffer, cb->GetMapName());
		ReplaceExtension(buffer, filename, sizeof(filename), ".dat");

		ai->cb->GetValue(AIVAL_LOCATE_FILE_W, filename);

		// save data
		file = fopen(filename, "w+");

		fprintf(file, "%s\n",  MAP_DATA_VERSION);

		// save if its a metal map
		fprintf(file, "%i\n", (int)metalMap);

		// save buildmap
		for(int i = 0; i < xMapSize*yMapSize; ++i)
		//	fwrite(&buildmap[i], sizeof(int), 1, file);
			fprintf(file, "%i ", buildmap[i]); 
		
		// save plateau map
		for(int i = 0; i < xMapSize*yMapSize/4; ++i)
		//	fwrite(&plateau_map[i], sizeof(float), 1, file);
			fprintf(file, "%f ", plateau_map[i]); 

		// save mex spots
		fprintf(file, "\n %i \n", metal_spots.size());

		for(list<AAIMetalSpot>::iterator spot = metal_spots.begin(); spot != metal_spots.end(); spot++)
			fprintf(file, "%f %f %f %f \n", spot->pos.x, spot->pos.y, spot->pos.z, spot->amount);

		fclose(file);

		fprintf(ai->file, "New map cache-file created\n");
	}

	// determine map type
	loaded = true;
	strcpy(buffer, MAIN_PATH);
	strcat(buffer, MAP_CFG_PATH);
	strcat(buffer, cb->GetMapName());
	ReplaceExtension(buffer, filename, sizeof(filename), ".cfg");

	ai->cb->GetValue(AIVAL_LOCATE_FILE_R, filename);

	if(file = fopen(filename, "r"))
	{
		// read map type
		fscanf(file, "%s ", buffer);

		if(!strcmp(buffer, "LAND_MAP"))
			mapType = LAND_MAP;
		else if(!strcmp(buffer, "AIR_MAP"))
			mapType = AIR_MAP;
		else if(!strcmp(buffer, "LAND_WATER_MAP"))
			mapType = LAND_WATER_MAP;
		else if(!strcmp(buffer, "WATER_MAP"))
			mapType = WATER_MAP;
		else
			mapType = UNKNOWN_MAP;

		if(mapType >= 0 && mapType <= WATER_MAP)
		{
			this->mapType = (MapType) mapType;

			// logging
			sprintf(buffer, "%s detected", GetMapTypeTextString(mapType));
			fprintf(ai->file, "\nLoading map type:\n");
			fprintf(ai->file, buffer);
			fprintf(ai->file, "\n\n");

			if(bt->aai_instances == 1)
				ai->cb->SendTextMsg(buffer, 0);
		}
		else
			loaded = false;

		fclose(file);
	}
	else
		loaded = false;

	if(!loaded)
	{
		float water_ratio = 0;

		for(int x = 0; x < xMapSize; ++x)
		{
			for(int y = 0; y < yMapSize; ++y)
			{
				if(buildmap[x + y*xMapSize] == 4)
					++water_ratio;
			}
		}

		water_ratio = water_ratio / ((float)(xMapSize*yMapSize));

		if(water_ratio > 0.80f)
			this->mapType = WATER_MAP;
		else if(water_ratio > 0.25f)
			this->mapType = LAND_WATER_MAP;
		else
			this->mapType = LAND_MAP;


		// logging
		sprintf(buffer, "%s detected", GetMapTypeTextString(this->mapType));
		ai->cb->SendTextMsg(buffer, 0);
		fprintf(ai->file, "\nAutodetecting map type:\n");
		fprintf(ai->file, buffer);
		fprintf(ai->file, "\n\n");

		// save results to cfg file
		strcpy(buffer, MAIN_PATH);
		strcat(buffer, MAP_CFG_PATH);
		strcat(buffer, cb->GetMapName());
		ReplaceExtension(buffer, filename, sizeof(filename), ".cfg");

		ai->cb->GetValue(AIVAL_LOCATE_FILE_W, filename);

		file = fopen(filename, "w+");
		fprintf(file, "%s\n", GetMapTypeString(this->mapType));
		fclose(file);
	}

	// determine important unit categories on this map
	if(cfg->AIR_ONLY_MOD)
	{
		map_categories.push_back(GROUND_ASSAULT);
		map_categories.push_back(AIR_ASSAULT);
		map_categories.push_back(HOVER_ASSAULT);
		map_categories.push_back(SEA_ASSAULT);

		map_categories_id.push_back(0);
		map_categories_id.push_back(1);
		map_categories_id.push_back(2);
		map_categories_id.push_back(3);
	}
	else
	{
		if(mapType == LAND_MAP)
		{
			map_categories.push_back(GROUND_ASSAULT);
			map_categories.push_back(AIR_ASSAULT);
			map_categories.push_back(HOVER_ASSAULT);

			map_categories_id.push_back(0);
			map_categories_id.push_back(1);
			map_categories_id.push_back(2);
		}
		else if(mapType == LAND_WATER_MAP)
		{
			map_categories.push_back(GROUND_ASSAULT);
			map_categories.push_back(AIR_ASSAULT);
			map_categories.push_back(HOVER_ASSAULT);
			map_categories.push_back(SEA_ASSAULT);
			map_categories.push_back(SUBMARINE_ASSAULT);

			map_categories_id.push_back(0);
			map_categories_id.push_back(1);
			map_categories_id.push_back(2);
			map_categories_id.push_back(3);
			map_categories_id.push_back(4);
		}
		else if(mapType == WATER_MAP)
		{
			map_categories.push_back(AIR_ASSAULT);
			map_categories.push_back(HOVER_ASSAULT);
			map_categories.push_back(SEA_ASSAULT);
			map_categories.push_back(SUBMARINE_ASSAULT);

			map_categories_id.push_back(1);
			map_categories_id.push_back(2);
			map_categories_id.push_back(3);
			map_categories_id.push_back(4);
		}
		else
		{
			map_categories.push_back(AIR_ASSAULT);

			map_categories_id.push_back(1);
		}
	}
}

void AAIMap::ReadMapLearnFile(bool auto_set)
{
	// get filename
	char filename[500];
	char buffer[500];

	strcpy(buffer, MAIN_PATH);
	strcat(buffer, MAP_LEARN_PATH);
	strcat(buffer, cb->GetMapName());
	ReplaceExtension(buffer, filename, sizeof(filename), "_");
	strcpy(buffer, filename);
	strcat(buffer, cb->GetModName());
	ReplaceExtension(buffer, filename, sizeof(filename), ".dat");

	ai->cb->GetValue(AIVAL_LOCATE_FILE_R, filename);

	// open learning files
	FILE *load_file = fopen(filename, "r");

	// check if correct map file version
	if(load_file)
	{
		fscanf(load_file, "%s", buffer);

		// file version out of date
		if(strcmp(buffer, MAP_FILE_VERSION))
		{
			cb->SendTextMsg("Map learning file version out of date, creating new one", 0);
			fclose(load_file);
			load_file = 0;
		}
		else
		{
			// check if map type matches (aai will recreate map learn files if maptype has changed)
			fscanf(load_file, "%s", buffer);

			// map type does not match

⌨️ 快捷键说明

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