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

📄 aaimap.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		metalMap = true;
		metal_spots.clear();
		fprintf(ai->file, "Map is considered to be a metal map\n",0);
	}
	else
	{
		metalMap = false;

		// debug
		/*for(list<AAIMetalSpot>::iterator spot = metal_spots.begin(); spot != metal_spots.end(); spot++)
		{
			cb->DrawUnit("ARMMEX", spot->pos, 0.0f, 200000, cb->GetMyAllyTeam(), false, true);
		}*/
	}


	delete [] MexArrayA;
	delete [] MexArrayB;
	delete [] TempAverage;
}

void AAIMap::GetMapData()
{
}

void AAIMap::UpdateRecon()
{
	const UnitDef *def;
	int team, my_team = cb->GetMyAllyTeam();
	float3 pos;
	int x, y;
	AAIAirTarget target;
	int combat_category_id;
	AAISector *sector;
	UnitCategory cat;

	// prevent aai from wasting too much time with checking too many targets
	int targets_checked = 0;

	// reset number of friendly units per sector && decrease mobile combat power (to reflect possible movement the units)
	for(x = 0; x < xSectors; ++x)
	{
		for(y = 0; y < ySectors; ++y)
		{
			unitsInSector[x+y*xSectors] = 0;

			for(int i = 0; i < bt->combat_categories; ++i)
			{
				this->sector[x][y].mobile_combat_power[i] *= 0.98f;

				if(this->sector[x][y].mobile_combat_power[i] < 0.5f)
					this->sector[x][y].mobile_combat_power[i] = 0;
			}
		}
	}

	// reset spotted units
	fill(units_spotted.begin(), units_spotted.end(), 0);

	// first update all sectors with friendly units
	cb->GetFriendlyUnits(&(unitsInLos.front()));

	// go through the list
	for(int i = 0; i < cfg->MAX_UNITS; ++i)
	{
		// if 0 end of array reached
		if(unitsInLos[i])
		{
			pos = cb->GetUnitPos(unitsInLos[i]);

			if(pos.x != 0)
			{
				// calculate in which sector unit is located
				x = pos.x/xSectorSize;
				y = pos.z/ySectorSize;

				if(x >= 0 && y >= 0 && x < xSectors && y < ySectors)
				{
					sector = &this->sector[x][y];

					// we have a unit in that sector, reset values if not already done
					if(unitsInSector[x+y*xSectors] == 0)
					{
						++unitsInSector[x+y*xSectors];
						
						fill(sector->enemyUnitsOfType.begin(), sector->enemyUnitsOfType.end(), 0);
						fill(sector->stat_combat_power.begin(), sector->stat_combat_power.end(), 0);
						fill(sector->mobile_combat_power.begin(), sector->mobile_combat_power.end(), 0);
				
						sector->threat = 0;
						sector->allied_structures = 0;
						sector->enemy_structures = 0;
						sector->own_structures = 0;
					}

					// check if building
					def = cb->GetUnitDef(unitsInLos[i]);

					if(def && bt->units_static[def->id].category <= METAL_MAKER)
					{
						team = cb->GetUnitTeam(unitsInLos[i]);

						if(team == my_team)
							sector->own_structures += bt->units_static[def->id].cost;
						else
							sector->allied_structures += bt->units_static[def->id].cost;
					}
				}
			}

			unitsInLos[i] = 0;
		}
		else 	// end of array reached
			break;
	}

	// get all enemies in los
	cb->GetEnemyUnits(&(unitsInLos.front()));

	// go through the list
	for(int i = 0; i < cfg->MAX_UNITS; ++i)
	{
		// if 0 end of array reached
		if(unitsInLos[i])
		{
			pos = cb->GetUnitPos(unitsInLos[i]);

			// calculate in which sector unit is located
			sector = GetSectorOfPos(&pos);

			if(sector)
			{
				if(unitsInSector[sector->x + sector->y*xSectors])
				{
					def = cb->GetUnitDef(unitsInLos[i]);
					cat = bt->units_static[def->id].category;
					combat_category_id = (int) bt->GetIDOfAssaultCategory(cat);

					sector->enemyUnitsOfType[(int)cat] += 1;

					// check if combat unit
					if(combat_category_id >= 0)
					{
						sector->threat += 1;
						units_spotted[combat_category_id] += 1;

						// count combat power of combat units
						for(int i = 0; i < bt->combat_categories; ++i)
							sector->mobile_combat_power[i] += bt->units_static[def->id].efficiency[i];
					}
					else	// building or scout etc.
					{
						// check if promising bombing target
						if(targets_checked < 3 && ( cat ==  EXTRACTOR || cat == STATIONARY_CONSTRUCTOR || cat == STATIONARY_ARTY || cat == STATIONARY_LAUNCHER ) )
						{
							// dont check targets that are already on bombing list
							if(ai->ut->units[unitsInLos[i]].status != BOMB_TARGET)
							{
								ai->af->CheckBombTarget(unitsInLos[i], def->id);
								targets_checked += 1;

								cb->SendTextMsg("Checking target", 0);
							}
						}

						// count combat power of stat defences
						if(cat == STATIONARY_DEF)
						{
							for(int i = 0; i < bt->ass_categories; ++i)
								sector->stat_combat_power[i] += bt->units_static[def->id].efficiency[i];
						}

						// add enemy buildings
						if(cat <= METAL_MAKER)
							sector->enemy_structures += bt->units_static[def->id].cost;
					}
				}
			}
			unitsInLos[i] = 0;
		}
		else 	// end of arry reached
			break;
	}

	ai->brain->UpdateMaxCombatUnitsSpotted(units_spotted);
}

void AAIMap::UpdateSectors()
{
	for(int x = 0; x < xSectors; ++x)
	{
		for(int y = 0; y < ySectors; ++y)
			sector[x][y].Update();
	}
}


void AAIMap::UpdateCategoryUsefulness(const UnitDef *killer_def, int killer, const UnitDef *killed_def, int killed)
{
	// filter out aircraft
	if(killer == 1 || killed == 1)
		return;

	UnitTypeStatic *killer_type = &bt->units_static[killer_def->id];
	UnitTypeStatic *killed_type = &bt->units_static[killed_def->id];

	float change =  killed_type->cost / killer_type->cost;

	change /= 4;

	if(change > 4)
		change = 4;
	else if(change < 0.2)
		change = 0.2f;

	if(killer < 5)
	{
		bt->mod_usefulness[killer][killer_type->side-1][mapType] += change;
		map_usefulness[killer][killer_type->side-1] += change;
	}

	if(killed < 5)
	{
		map_usefulness[killed][killed_type->side-1] -= change;
		bt->mod_usefulness[killed][killed_type->side-1][mapType] -= change;

		if(map_usefulness[killed][killed_type->side-1] < 1)
			map_usefulness[killed][killed_type->side-1] = 1;

		if(bt->mod_usefulness[killed][killed_type->side-1][mapType] < 1)
			bt->mod_usefulness[killed][killed_type->side-1][mapType] = 1;
	}
}


char* AAIMap::GetMapTypeString(int mapType)
{
	if(mapType == 1)
		return "LAND_MAP";
	else if(mapType == 2)
		return "AIR_MAP";
	else if(mapType == 3)
		return "LAND_WATER_MAP";
	else if(mapType == 4)
		return "WATER_MAP";
	else
		return "UNKNOWN_MAP";
}

char* AAIMap::GetMapTypeTextString(int mapType)
{
	if(mapType == 1)
		return "land map";
	else if(mapType == 2)
		return "air map";
	else if(mapType == 3)
		return "land-water map";
	else if(mapType == 4)
		return "water map";
	else
		return "unknown map type";
}


bool AAIMap::ValidSector(int x, int y)
{
	if(x >= 0 && y >= 0 && x < xSectors && y < ySectors)
		return true;
	else
		return false;
}

AAISector* AAIMap::GetSectorOfPos(float3 *pos)
{
	int x = pos->x/xSectorSize;
	int y = pos->z/ySectorSize;

	if(ValidSector(x,y))
		return &(sector[x][y]);
	else
		return 0;
}

void AAIMap::AddDefence(float3 *pos, int defence)
{
	int range = bt->units_static[defence].range / 16;
	int cell;

	float power;
	float air_power;

	if(cfg->AIR_ONLY_MOD)
	{
		power = bt->fixed_eff[defence][0] + bt->fixed_eff[defence][1];
		air_power = bt->fixed_eff[defence][2] + bt->fixed_eff[defence][3];
	}
	else
	{
		if(bt->unitList[defence-1]->minWaterDepth > 0)
			power = bt->fixed_eff[defence][3] + bt->fixed_eff[defence][4];
		else
			power = bt->fixed_eff[defence][0];
		
		air_power = bt->fixed_eff[defence][1];
	}

	int xPos = pos->x / 16;
	int yPos = pos->z / 16;

	// x range will change from line to line 
	int xStart;
	int xEnd;
	int xRange;

	// y range is const
	int yStart = yPos - range;
	int yEnd = yPos + range;

	if(yStart < 0)
		yStart = 0;
	if(yEnd >= yDefMapSize)
		yEnd = yDefMapSize-1;

	for(int y = yStart; y <= yEnd; ++y)
	{
		// determine x-range
		xRange = (int) floor( sqrt( (float) ( range * range - (y - yPos) * (y - yPos) ) ) + 0.5f );
		
		xStart = xPos - xRange;
		xEnd = xPos + xRange;

		if(xStart < 0)
			xStart = 0;
		if(xEnd > xDefMapSize)
			xEnd = xDefMapSize;

		for(int x = xStart; x < xEnd; ++x)
		{
			cell = x + xDefMapSize*y;

			defence_map[cell] += power;
			air_defence_map[cell] += air_power;
		}	
	}

	// further increase values close around the bulding (to prevent aai from packing buildings too close together)
	// y range is const
	yStart = yPos - 6;
	yEnd = yPos + 6;

	if(yStart < 0)
		yStart = 0;
	if(yEnd >= yDefMapSize)
		yEnd = yDefMapSize-1;

	for(int y = yStart; y <= yEnd; ++y)
	{
		// determine x-range
		xRange = (int) floor( sqrt( (float) ( 36 - (y - yPos) * (y - yPos) ) ) + 0.5f );
		
		xStart = xPos - xRange;
		xEnd = xPos + xRange;

		if(xStart < 0)
			xStart = 0;
		if(xEnd > xDefMapSize)
			xEnd = xDefMapSize;

		for(int x = xStart; x < xEnd; ++x)
		{
			cell = x + xDefMapSize*y;
			
			defence_map[cell] += 128.0f;
			air_defence_map[cell] += 128.0f;
		}
	}
}

void AAIMap::RemoveDefence(float3 *pos, int defence)
{
	int cell;
	int range = bt->units_static[defence].range / 16;

	float power;
	float air_power;

	if(cfg->AIR_ONLY_MOD)
	{
		power = bt->fixed_eff[defence][0] + bt->fixed_eff[defence][1];
		air_power = bt->fixed_eff[defence][2] + bt->fixed_eff[defence][3];
	}
	else
	{
		if(bt->unitList[defence-1]->minWaterDepth > 0)
			power = bt->fixed_eff[defence][3] + bt->fixed_eff[defence][4];
		else
			power = bt->fixed_eff[defence][0];
		
		air_power = bt->fixed_eff[defence][1];
	}
	
	int xPos = pos->x / 16;
	int yPos = pos->z / 16;

	// x range will change from line to line 
	int xStart;
	int xEnd;
	int xRange;

	// further decrease values close around the bulding (to prevent aai from packing buildings too close together)
	// y range is const
	int yStart = yPos - 6;
	int yEnd = yPos + 8;

	if(yStart < 0)
		yStart = 0;
	if(yEnd >= yDefMapSize)
		yEnd = yDefMapSize-1;

	for(int y = yStart; y <= yEnd; ++y)
	{
		// determine x-range
		xRange = (int) floor( sqrt( (float) ( 36 - (y - yPos) * (y - yPos) ) ) + 0.5f );
		
		xStart = xPos - xRange;
		xEnd = xPos + xRange;

		if(xStart < 0)
			xStart = 0;
		if(xEnd > xDefMapSize)
			xEnd = xDefMapSize;

		for(int x = xStart; x < xEnd; ++x)
		{
			cell= x + xDefMapSize*y;
			
			defence_map[cell] -= 128.0f;
			air_defence_map[cell] -= 128.0f;
		}
	}

	// y range is const
	yStart = yPos - range;
	yEnd = yPos + range;

	if(yStart < 0)
		yStart = 0;
	if(yEnd >= yDefMapSize)
		yEnd = yDefMapSize-1;

	for(int y = yStart; y <= yEnd; ++y)
	{
		// determine x-range
		xRange = (int) floor( sqrt( (float) ( range * range - (y - yPos) * (y - yPos) ) ) + 0.5f );
		
		xStart = xPos - xRange;
		xEnd = xPos + xRange;

		if(xStart < 0)
			xStart = 0;
		if(xEnd > xDefMapSize)
			xEnd = xDefMapSize;

		for(int x = xStart; x < xEnd; ++x)
		{
			cell= x + xDefMapSize*y;
			
			defence_map[cell] -= power;
			air_defence_map[cell] -= air_power;

			if(defence_map[cell] < 0)
				defence_map[cell] = 0;
			
			if(air_defence_map[cell] < 0)
				air_defence_map[cell] = 0;
		}
	}
}

float AAIMap::GetDefenceBuildsite(float3 *best_pos, const UnitDef *def, int xStart, int xEnd, int yStart, int yEnd, UnitCategory category, float terrain_modifier, bool water)
{
	float3 pos;
	*best_pos = ZeroVector;
	float my_rating, best_rating = -10000;
	int edge_distance;

	// get required cell-size of the building
	int xSize, ySize, xPos, yPos, cell;
	GetSize(def, &xSize, &ySize);

	vector<float> *map = &defence_map;

	if(cfg->AIR_ONLY_MOD)
	{
		if(category == HOVER_ASSAULT || category == SEA_ASSAULT)
			map = &air_defence_map;
	}
	else if(category == AIR_ASSAULT)
		map = &air_defence_map;

	float range =  bt->units_static[def->id].range / 8.0;

	// check rect
	for(yPos = yStart; yPos < yEnd; yPos += 4)
	{
		for(xPos = xStart; xPos < xEnd; xPos += 4)
		{
			// check if buildmap allows construction
			if(CanBuildAt(xPos, yPos, xSize, ySize, water))
			{
				cell = xPos/2 + xDefMapSize * (yPos/2);

				my_rating = terrain_modifier * plateau_map[cell] - (*map)[cell] + 0.15f * ((float) (rand()%20));

				// determine minimum distance from buildpos to the edges of the map
				edge_distance = xPos;

				if(xMapSize - xPos < edge_distance)
					edge_distance = xMapSize - xPos;

				if(yPos < edge_distance)
					edge_distance = yPos;

				if(yMapSize - yPos < edge_distance)
					edge_distance = yMapSize - yPos;

				// prevent aai from building defences too close to the edges of the map
				if( (float)edge_distance < range)
					my_rating -= (range - (float)edge_distance);	

				if(my_rating > best_rating)
				{
					pos.x = xPos;
					pos.z = yPos;

					// buildmap allows construction, now check if otherwise blocked
					BuildMapPos2Pos(&pos, def);
					Pos2FinalBuildPos(&pos, def);

					if(cb->CanBuildAt(def, pos))
					{
						*best_pos = pos;
						best_rating = my_rating;
					}
				}
			}
		}
	}

	return best_rating;
}

⌨️ 快捷键说明

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