OpenXcom Forum

Contributions => Programming => Topic started by: davide on July 16, 2014, 07:05:35 pm

Title: [PROPOSAL] to extend engine to support terrain map blocks of any rect size
Post by: davide on July 16, 2014, 07:05:35 pm
I have this doubt on

BattlescapeGenerator::generateMap() [at line 1283]

Code: [Select]
int maxLarge = _terrain->getLargeBlockLimit();
int curLarge = 0;
int tries = 0;
while (curLarge != maxLarge && tries <= 50)
{
int randX = RNG::generate(0, (_mapsize_x/10)- 2);
int randY = RNG::generate(0, (_mapsize_y/10)- 2);

if (
   !blocks[randX][randY]
&& !blocks[randX + 1][randY]
&& !blocks[randX + 1][randY + 1]
&& !blocks[randX][randY + 1]

&& !landingzone[randX][randY]
&& !landingzone[randX + 1][randY]
&& !landingzone[randX][randY + 1]
&& !landingzone[randX + 1][randY + 1])
{
blocks[randX][randY] = _terrain->getRandomMapBlock(20, MT_DEFAULT, true);
blocksToDo--;
https:// mark mapblocks as used
blocks[randX + 1][randY] = dummy;
blocksToDo--;
blocks[randX + 1][randY + 1] = dummy;
blocksToDo--;
blocks[randX][randY + 1] = dummy;
blocksToDo--;

curLarge++;
}
tries++;
}

Only Maps of square size 20 are found by this line:

_terrain->getRandomMapBlock(20, MT_DEFAULT, true);

Is it right ?

May I fix it ?

I plan to add some position constraints on map block selection and the code is the same

Title: Re: do engine support terrain map block of size over 20x20
Post by: Warboy1982 on July 17, 2014, 03:16:33 am
just wait, we have to change up a bunch of stuff in the map generator for tftd anyway.
Title: Re: do engine support terrain map block of size over 20x20
Post by: davide on July 17, 2014, 10:44:57 am
may I help ?

As you know I am interesting to TFTD too and I analized its terrains:


Some other very skilled people are interesting to use these features on modding.

I  can follow your additional requirements/needs  too if you have time to involve me.

Title: [PROPOSAL] to extend engine to support terrain map blocks of any rect size
Post by: davide on July 26, 2014, 01:34:14 am
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:

Code: [Select]
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:

Code: [Select]
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

Code: [Select]
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

Code: [Select]
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];
}

Title: Re: [PROPOSAL] to extend engine to support terrain map blocks of any rect size
Post by: davide on July 28, 2014, 01:07:10 am
I add some bugs fix