while I am waiting with patience some feedback about my request
I will explain what I want to make:
MapBlock entity has a new attribute odds to reduce probability to choose a maps
(it is the opposite of frequency)
RuleTerrain entity has new attribute such as original largeBlockLimit it was the max number of maps of size 20x20
in mine proposal it drive maps of size 20x10 and 10x20 too
I would add new attribute
_largeBlockLimit30to40 to set the max number of rectangular maps that have at least one dimension equal to 30 or 40
(10x30, 30x30, 40x10, 40x20, and so on)
I would add new attribute
_largeBlockLimit50orMore to set the max number of rectangular maps that have at least one dimension greater or equal to 50
(50x20, 60x60, 30x50 TFTD ships, 30x70, and so on)
the original source code fragment ,
to support rectangular any sized maps,
in my opinion,
could be update to:
int maxNum = _terrain->getLargeBlockLimit50orMore();
if(maxNum)
AddMaps( _terrain, _mapsize_x, _mapsize_y, 50, 200, maxNum, blocks, landingzone, dummy, blocksToDo);
maxNum = _terrain->getLargeBlockLimit30to40();
if(maxNum)
AddMaps( _terrain, _mapsize_x, _mapsize_y, 30, 40, maxNum, blocks, landingzone, dummy, blocksToDo);
maxNum = _terrain->getLargeBlockLimit10to20();
AddMaps( _terrain, _mapsize_x, _mapsize_y, 10, 20, maxNum, blocks, landingzone, dummy, blocksToDo);
where AddMaps was the core algorithm updated:
void AddMaps
(
RuleTerrain* _terrain, int _mapsize_x, int _mapsize_y,
int minDim, int maxDim, int maxNum,
std::vector< std::vector<MapBlock*> > & blocks, std::vector< std::vector<bool> > & landingzone,
MapBlock* dummy, int& blocksToDo
)
{
int curNum = 0;
int tries = 0;
while (curNum != maxNum && tries <= 50)
{
MapBlock* m = _terrain->getRandomMapBlock(minDim, maxDim, MT_DEFAULT);
if(!m) return;
int mx = (m->getSizeX() / 10);
int my = (m->getSizeY() / 10);
int randX = RNG::generate(0, (_mapsize_x/10) - mx);
int randY = RNG::generate(0, (_mapsize_y/10) - my);
if (
IsFree(blocks, randX, randY, mx, my) &&
IsFree(landingzone, randX, randY, mx, my)
)
{
AddMap(blocks, randX, randY, mx, my, m, dummy, blocksToDo);
curNum++;
}
tries++;
}
}
and minor functions are
bool IsFree(const std::vector< std::vector<MapBlock*> > & blk, int x, int y, int mx, int my)
{
for (int i = x; i < x+mx; i++)
{
for (int j = y; j < y+my; j++)
{
if (blk[i][j])
return false;
}
}
return true;
}
bool IsFree(std::vector< std::vector<bool> > & landingzone, int x, int y, int mx, int my)
{
for (int i = x; i < x+mx; i++)
{
for (int j = y; j < y+my; j++)
{
if (landingzone[i][j])
return false;
}
}
return true;
}
void AddMap(std::vector< std::vector<MapBlock*> > & blk, int x, int y, int mx, int my, MapBlock* m, MapBlock* dummy, int& blocksToDo)
{
for (int i = x; i < x+mx; i++)
{
for (int j = y; j < y+my; j++)
{
blk[i][j] = dummy;
blocksToDo--;
}
}
blk[x][y] = m;
if (m->getType() == MT_DEFAULT)
m->markUsed();
}
and
MapBlock* RuleTerrain::getRandomMapBlock(int minsize, int maxsize, MapBlockType type)
{
std::vector<MapBlock*> compliantMapBlocks;
for (std::vector<MapBlock*>::const_iterator i = _mapBlocks.begin(); i != _mapBlocks.end(); ++i)
{
if (
(*i)->getSizeX() <= maxsize && (*i)->getSizeX() >= minsize &&
(*i)->getSizeY() <= maxsize && (*i)->getSizeY() >= minsize &&
(
(*i)->getSizeX() > minsize || (*i)->getSizeY() > minsize
) &&
((*i)->getType() == type || (*i)->getSubType() == type)
)
{
int odds = RNG::generate(0,99);
if ((*i)->getOdds() > odds)
{
for (int j = 0; j != (*i)->getRemainingUses(); ++j)
{
compliantMapBlocks.push_back((*i));
}
}
}
}
if (compliantMapBlocks.empty()) return 0;
size_t n = RNG::generate(0, compliantMapBlocks.size() - 1);
return compliantMapBlocks[n];
}