📄 aaimap.cpp
字号:
if(strcmp(buffer, GetMapTypeString(mapType)))
{
cb->SendTextMsg("Map type has changed - creating new map learning file", 0);
fclose(load_file);
load_file = 0;
}
else
{
if(auto_set && aai_instances == 1)
{
map_usefulness.resize(bt->assault_categories.size());
for(int i = 0; i < bt->assault_categories.size(); ++i)
map_usefulness[i].resize(cfg->SIDES);
// load units map_usefulness
for(int i = 0; i < cfg->SIDES; ++i)
{
for(int j = 0; j < bt->assault_categories.size(); ++j)
fscanf(load_file, "%f ", &map_usefulness[j][i]);
}
}
else
{
// pseudo-load to make sure to be at the right spot in the file
float dummy;
for(int i = 0; i < cfg->SIDES; ++i)
{
for(int j = 0; j < bt->assault_categories.size(); ++j)
fscanf(load_file, "%f ", &dummy);
}
}
}
}
}
if(!load_file && aai_instances == 1)
{
map_usefulness.resize(bt->assault_categories.size());
for(int i = 0; i < bt->assault_categories.size(); ++i)
map_usefulness[i].resize(cfg->SIDES);
for(int i = 0; i < cfg->SIDES; ++i)
{
for(int j = 0; j < bt->assault_categories.size(); ++j)
map_usefulness[j][i] = bt->mod_usefulness[j][i][mapType];
}
}
// load sector data from file or init with default values
if(load_file)
{
for(int j = 0; j < ySectors; ++j)
{
for(int i = 0; i < xSectors; ++i)
{
// load sector data
fscanf(load_file, "%f %f %f", §or[i][j].flat_ratio, §or[i][j].water_ratio, §or[i][j].importance_learned);
if(sector[i][j].importance_learned <= 1)
sector[i][j].importance_learned += (rand()%5)/20.0;
// load combat data
for(int cat = 0; cat < bt->assault_categories.size(); cat++)
fscanf(load_file, "%f %f ", §or[i][j].attacked_by_learned[cat], §or[i][j].combats_learned[cat]);
if(auto_set)
{
sector[i][j].importance_this_game = sector[i][j].importance_learned;
for(int cat = 0; cat < bt->assault_categories.size(); ++cat)
{
sector[i][j].attacked_by_this_game[cat] = sector[i][j].attacked_by_learned[cat];
sector[i][j].combats_this_game[cat] = sector[i][j].combats_learned[cat];
}
}
}
}
}
else
{
for(int j = 0; j < ySectors; ++j)
{
for(int i = 0; i < xSectors; ++i)
{
sector[i][j].importance_learned = 1 + (rand()%5)/20.0;
sector[i][j].flat_ratio = sector[i][j].GetFlatRatio();
sector[i][j].water_ratio = sector[i][j].GetWaterRatio();
if(auto_set)
{
sector[i][j].importance_this_game = sector[i][j].importance_learned;
for(int cat = 0; cat < bt->assault_categories.size(); ++cat)
{
sector[i][j].attacked_by_this_game[cat] = sector[i][j].attacked_by_learned[cat];
sector[i][j].combats_this_game[cat] = sector[i][j].combats_learned[cat];
}
}
}
}
}
if(load_file)
fclose(load_file);
else
cb->SendTextMsg("New map-learning file created", 0);
}
void AAIMap::Learn()
{
AAISector *sector;
for(int y = 0; y < ySectors; ++y)
{
for(int x = 0; x < xSectors; ++x)
{
sector = &this->sector[x][y];
sector->importance_this_game = 0.93f * (sector->importance_this_game + 3.0f * sector->importance_learned)/4.0f;
if(sector->importance_this_game < 1)
sector->importance_this_game = 1;
for(int cat = 0; cat < bt->assault_categories.size(); ++cat)
{
sector->attacked_by_this_game[cat] = 0.90f * (sector->attacked_by_this_game[cat] + 3.0f * sector->attacked_by_learned[cat])/4.0f;
sector->combats_this_game[cat] = 0.90f * (sector->combats_this_game[cat] + 3.0f * sector->combats_learned[cat])/4.0f;
}
}
}
}
// converts unit positions to cell coordinates
void AAIMap::Pos2BuildMapPos(float3 *pos, const UnitDef* def)
{
// get cell index of middlepoint
pos->x = (int) (pos->x/SQUARE_SIZE);
pos->z = (int) (pos->z/SQUARE_SIZE);
// shift to the leftmost uppermost cell
pos->x -= def->xsize/2;
pos->z -= def->ysize/2;
// check if pos is still in that map, otherwise retun 0
if(pos->x < 0 && pos->z < 0)
pos->x = pos->z = 0;
}
void AAIMap::BuildMapPos2Pos(float3 *pos, const UnitDef *def)
{
// shift to middlepoint
pos->x += def->xsize/2;
pos->z += def->ysize/2;
// back to unit coordinates
pos->x *= SQUARE_SIZE;
pos->z *= SQUARE_SIZE;
}
bool AAIMap::SetBuildMap(int xPos, int yPos, int xSize, int ySize, int value, int ignore_value)
{
//float3 my_pos;
if(xPos+xSize <= xMapSize && yPos+ySize <= yMapSize)
{
for(int x = xPos; x < xSize+xPos; x++)
{
for(int y = yPos; y < ySize+yPos; y++)
{
if(buildmap[x+y*xMapSize] != ignore_value)
{
buildmap[x+y*xMapSize] = value;
// debug
/*if(x%2 == 0 && y%2 == 0)
{
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, 1500, cb->GetMyAllyTeam(), true, true);
}*/
}
}
}
return true;
}
return false;
}
float3 AAIMap::GetBuildSiteInRect(const UnitDef *def, int xStart, int xEnd, int yStart, int yEnd, bool water)
{
float3 pos;
// get required cell-size of the building
int xSize, ySize, xPos, yPos;
GetSize(def, &xSize, &ySize);
// check rect
for(yPos = yStart; yPos < yEnd; yPos += 2)
{
for(xPos = xStart; xPos < xEnd; xPos += 2)
{
// check if buildmap allows construction
if(CanBuildAt(xPos, yPos, xSize, ySize, water))
{
if(bt->IsFactory(def->id))
yPos += 8;
pos.x = xPos;
pos.z = yPos;
// buildmap allows construction, now check if otherwise blocked
BuildMapPos2Pos(&pos, def);
Pos2FinalBuildPos(&pos, def);
if(ai->cb->CanBuildAt(def, pos))
{
int x = pos.x/xSectorSize;
int y = pos.z/ySectorSize;
if(x < xSectors && x >= 0 && y < ySectors && y >= 0)
return pos;
}
}
}
}
return ZeroVector;
}
float3 AAIMap::GetHighestBuildsite(const UnitDef *def, int xStart, int xEnd, int yStart, int yEnd)
{
float3 best_pos = ZeroVector, pos;
// get required cell-size of the building
int xSize, ySize, xPos, yPos, x, y;
GetSize(def, &xSize, &ySize);
// go through rect
for(xPos = xStart; xPos < xEnd; xPos += 2)
{
for(yPos = yStart; yPos < yEnd; yPos += 2)
{
if(CanBuildAt(xPos, yPos, xSize, ySize))
{
pos.x = xPos;
pos.z = yPos;
// buildmap allows construction, now check if otherwise blocked
BuildMapPos2Pos(&pos, def);
Pos2FinalBuildPos(&pos, def);
if(ai->cb->CanBuildAt(def, pos))
{
x = pos.x/xSectorSize;
y = pos.z/ySectorSize;
if(x < xSectors && x >= 0 && y < ySectors && y >= 0)
{
pos.y = cb->GetElevation(pos.x, pos.z);
if(pos.y > best_pos.y)
best_pos = pos;
}
}
}
}
}
return best_pos;
}
float3 AAIMap::GetCenterBuildsite(const UnitDef *def, int xStart, int xEnd, int yStart, int yEnd, bool water)
{
float3 pos, temp_pos;
bool vStop = false, hStop = false;
int vCenter = yStart + (yEnd-yStart)/2;
int hCenter = xStart + (xEnd-xStart)/2;
int hIterator = 1, vIterator = 1;
// get required cell-size of the building
int xSize, ySize;
GetSize(def, &xSize, &ySize);
// check rect
while(!vStop || !hStop)
{
pos.z = vCenter - vIterator;
pos.x = hCenter - hIterator;
if(!vStop)
{
while(pos.x < hCenter+hIterator)
{
// check if buildmap allows construction
if(CanBuildAt(pos.x, pos.z, xSize, ySize, water))
{
temp_pos.x = pos.x;
temp_pos.y = 0;
temp_pos.z = pos.z;
if(bt->IsFactory(def->id))
temp_pos.z += 8;
// buildmap allows construction, now check if otherwise blocked
BuildMapPos2Pos(&temp_pos, def);
Pos2FinalBuildPos(&temp_pos, def);
if(ai->cb->CanBuildAt(def, temp_pos))
{
int x = temp_pos.x/xSectorSize;
int y = temp_pos.z/ySectorSize;
if(x < xSectors && x >= 0 && y < ySectors && y >= 0)
return temp_pos;
}
}
else if(CanBuildAt(pos.x, pos.z + 2 * vIterator, xSize, ySize, water))
{
temp_pos.x = pos.x;
temp_pos.y = 0;
temp_pos.z = pos.z + 2 * vIterator;
if(bt->IsFactory(def->id))
temp_pos.z += 8;
// buildmap allows construction, now check if otherwise blocked
BuildMapPos2Pos(&temp_pos, def);
Pos2FinalBuildPos(&temp_pos, def);
if(ai->cb->CanBuildAt(def, temp_pos))
{
int x = temp_pos.x/xSectorSize;
int y = temp_pos.z/ySectorSize;
if(x < xSectors && x >= 0 && y < ySectors && y >= 0)
return temp_pos;
}
}
pos.x += 2;
}
}
if (!hStop)
{
hIterator += 2;
if (hCenter - hIterator < xStart || hCenter + hIterator > xEnd)
{
hStop = true;
hIterator -= 2;
}
}
if(!hStop)
{
while(pos.z < vCenter+vIterator)
{
// check if buildmap allows construction
if(CanBuildAt(pos.x, pos.z, xSize, ySize, water))
{
temp_pos.x = pos.x;
temp_pos.y = 0;
temp_pos.z = pos.z;
if(bt->IsFactory(def->id))
temp_pos.z += 8;
// buildmap allows construction, now check if otherwise blocked
BuildMapPos2Pos(&temp_pos, def);
Pos2FinalBuildPos(&temp_pos, def);
if(ai->cb->CanBuildAt(def, temp_pos))
{
int x = temp_pos.x/xSectorSize;
int y = temp_pos.z/ySectorSize;
if(x < xSectors || x >= 0 || y < ySectors || y >= 0)
return temp_pos;
}
}
else if(CanBuildAt(pos.x + 2 * hIterator, pos.z, xSize, ySize, water))
{
temp_pos.x = pos.x + 2 * hIterator;
temp_pos.y = 0;
temp_pos.z = pos.z;
if(bt->IsFactory(def->id))
temp_pos.z += 8;
// buildmap allows construction, now check if otherwise blocked
BuildMapPos2Pos(&temp_pos, def);
Pos2FinalBuildPos(&temp_pos, def);
if(ai->cb->CanBuildAt(def, temp_pos))
{
int x = temp_pos.x/xSectorSize;
int y = temp_pos.z/ySectorSize;
if(x < xSectors && x >= 0 && y < ySectors && y >= 0)
return temp_pos;
}
}
pos.z += 2;
}
}
vIterator += 2;
if(vCenter - vIterator < yStart || vCenter + vIterator > yEnd)
vStop = true;
}
return ZeroVector;
}
float3 AAIMap::GetRandomBuildsite(const UnitDef *def, int xStart, int xEnd, int yStart, int yEnd, int tries, bool water)
{
float3 pos;
// get required cell-size of the building
int xSize, ySize;
GetSize(def, &xSize, &ySize);
for(int i = 0; i < tries; i++)
{
// get random pos within rectangle
if(xEnd - xStart - xSize < 1)
pos.x = xStart;
else
pos.x = xStart + rand()%(xEnd - xStart - xSize);
if(yEnd - yStart - ySize < 1)
pos.z = yStart;
else
pos.z = yStart + rand()%(yEnd - yStart - ySize);
// check if buildmap allows construction
if(CanBuildAt(pos.x, pos.z, xSize, ySize, water))
{
if(bt->IsFactory(def->id))
pos.z += 8;
// buildmap allows construction, now check if otherwise blocked
BuildMapPos2Pos(&pos, def);
Pos2FinalBuildPos(&pos, def);
if(ai->cb->CanBuildAt(def, pos))
{
int x = pos.x/xSectorSize;
int y = pos.z/ySectorSize;
if(x < xSectors && x >= 0 && y < ySectors && y >= 0)
return pos;
}
}
}
return ZeroVector;
}
float3 AAIMap::GetClosestBuildsite(const UnitDef *def, float3 pos, int max_distance, bool water)
{
Pos2BuildMapPos(&pos, def);
int xStart = pos.x - max_distance;
int xEnd = pos.x + max_distance;
int yStart = pos.z - max_distance;
int yEnd = pos.z + max_distance;
if(xStart < 0)
xStart = 0;
if(xEnd >= xSectors * xSectorSizeMap)
xEnd = xSectors * xSectorSizeMap - 1;
if(yStart < 0)
yStart = 0;
if(yEnd >= ySectors * ySectorSizeMap)
yEnd = ySectors * ySectorSizeMap - 1;
return GetCenterBuildsite(def, xStart, xEnd, yStart, yEnd, water);
}
bool AAIMap::CanBuildAt(int xPos, int yPos, int xSize, int ySize, bool water)
{
if(xPos+xSize <= xMapSize && yPos+ySize <= yMapSize)
{
// check if all squares the building needs are empty
for(int x = xPos; x < xSize+xPos; ++x)
{
for(int y = yPos; y < ySize+yPos; ++y)
{
// check if cell already blocked by something
if(!water && buildmap[x+y*xMapSize] != 0)
return false;
else if(water && buildmap[x+y*xMapSize] != 4)
return false;
}
}
return true;
}
else
return false;
}
void AAIMap::CheckRows(int xPos, int yPos, int xSize, int ySize, bool add, bool water)
{
bool insert_space;
int cell;
int building;
if(water)
building = 5;
else
building = 1;
// check horizontal space
if(xPos+xSize+cfg->MAX_XROW <= xMapSize && xPos - cfg->MAX_XROW >= 0)
{
for(int y = yPos; y < yPos + ySize; y++)
{
if(y>= yMapSize)
{
fprintf(ai->file, "ERROR: y = %i index out of range when checking horizontal rows", y);
return;
}
// check to the right
insert_space = true;
for(int x = xPos+xSize; x < xPos+xSize+cfg->MAX_XROW; x++)
{
if(buildmap[x+y*xMapSize] != building)
{
insert_space = false;
break;
}
}
// check to the left
if(!insert_space)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -