In response to Garthor
And when you add identical turfs to a blank map does BYOND optimize or is every turf an individual piece of memory.
In response to Obs
Adding new turfs at runtime won't result in a long-term performance hit compared to them being in the .dmm file at compile-time.
In response to Garthor
So it's exactly the same? How do you layer two turfs together?


What's the limit on the number of turfs anyway?
In response to Obs
In the map editor, placing a turf on top of another turf will add the previous turf's icon to itself as an underlay, if it would show through. I don't think there's any good way at runtime to determine whether one icon will show through another one, though, but you can still add the old turf's icon to the new turf's underlays, assuming that you know it will show through.

There is a limit of 65,535 unique turfs (turfs with the same variables are counted as one towards this limit), but also an absolute upper bound of 224 (16.7 million) turfs.
Here is my map generator (using diamond square):

var/worldGen/w = new()

turf
proc
setHeight(height) w.setHeight(x, y, height)
getHeight() return w.getHeight(x, y)

worldGen
var
minHeight = 1
maxHeight = 256
roughness = 1
heightMap = null

proc
getHeight(x, y) return heightMap[x][y]
setHeight(x, y, height) heightMap[x][y] = height
start()
resetHeightMap()
generateHeightMap(1, world.maxy, world.maxx, world.maxy, world.maxx, 1, 1, 1, sqrt((world.maxx-1)**2)*2)
layTerrain()

layTerrain()
for(var/x = 1, x <= world.maxx, x ++)
for(var/y = 1, y <= world.maxy, y ++)
var/height = heightMap[x][y]

if(height <= 50) new/turf/water(locate(x, y, 1))
else if(height <= 200) new/turf/grass(locate(x, y, 1))
else if(height <= 230) new/turf/mountain(locate(x, y, 1))
else new/turf/mountainTop(locate(x, y, 1))

resetHeightMap()
heightMap = new/list(world.maxx, world.maxy)

for(var/x = 1, x <= world.maxx, x ++) for(var/y = 1, y <= world.maxy, y ++) heightMap[x][y] = 1

heightMap[1][world.maxy] = rand(minHeight, maxHeight)
heightMap[world.maxx][world.maxy] = rand(minHeight, maxHeight)
heightMap[world.maxx][1] = rand(minHeight, maxHeight)
heightMap[1][1] = rand(minHeight, maxHeight)

generateHeightMap(ax, ay, bx, by, cx, cy, dx, dy, size)
size /= 2

if(size < 2) return

world << size
sleep(1)

var
abx = (ax + bx) / 2
aby = (ay + by) / 2
bcx = (bx + cx) / 2
bcy = (by + cy) / 2
cdx = (cx + dx) / 2
cdy = (cy + dy) / 2
dax = (dx + ax) / 2
day = (dy + ay) / 2
abcdx = (ax + cx) / 2
abcdy = (ay + cy) / 2

setHeight(abx, aby, min(maxHeight, max(minHeight, (heightMap[ax][ay] + heightMap[bx][by]) / 2)))
setHeight(bcx, bcy, min(maxHeight, max(minHeight, (heightMap[bx][by] + heightMap[cx][cy]) / 2)))
setHeight(cdx, cdy, min(maxHeight, max(minHeight, (heightMap[cx][cy] + heightMap[dx][dy]) / 2)))
setHeight(dax, day, min(maxHeight, max(minHeight, (heightMap[dx][dy] + heightMap[ax][ay]) / 2)))
setHeight(abcdx, abcdy, min(maxHeight, max(minHeight, (heightMap[ax][ay] + heightMap[bx][by] + heightMap[cx][cy] + heightMap[dx][dy]) / 4) + rand(-size, size) * roughness))

generateHeightMap(ax, ay, abx, aby, abcdx, abcdy, dax, day, size)
generateHeightMap(abx, aby, bx, by, bcx, bcy, abcdx, abcdy, size)
generateHeightMap(dax, day, abcdx, abcdy, cdx, cdy, dx, dy, size)
generateHeightMap(abcdx, abcdy, bcx, bcy, cx, cy, cdx, cdy, size)
Over at Dungeon Crawlers there's been a lot of great discussion on the forums about map generation, and we could always use more. Even non-members can post to those forums, so by all means stop by.

Granted you're doing an overworld map, which is rather different than an underground dungeon setting, but there's a lot of useful stuff to check out, plus links to sites with more on this topic.

As far as dynamically making new maps, remember you can change world.maxz at runtime. New Z-levels will fill in with default turfs. However, 500×500 is a pretty big map so you should make your map generator sensitive to this fact so it doesn't bog down the server during generation. (I.e., put in a lot of sleep() calls.)

Lummox JR
Page: 1 2