proc
Plasma_Generate(iWidth,iHeight)
var/c1
var/c2
var/c3
var/c4
c1 = rand(0,10)/10 // Creates A's height //A B
c2 = rand(0,10)/10 // Creates B's height
c3 = rand(0,10)/10 // Creates C's height
c4 = rand(0,10)/10 // Creates D's height //C D
DivideGrid(0, 0, iWidth, iHeight,c1,c2,c3,c4)
DivideGrid(x, y, width, height,c1,c2,c3,c4)
var/e1
var/e2
var/e3
var/e4
var/m
var/newWidth = width / 2
var/newHeight = height / 2
if(width > 1 || height > 1)
m = (c1+c2+c3+c4) / 4 + Displace(newWidth + newHeight)
e1 = ((c1 + c2) / 2)
e2 = ((c2 + c3) / 2)
e3 = ((c3 + c4) / 2)
e4 = ((c4 + c1) / 2)
if(m < 0)
m = 0
else if(m > 1.0)
m = 1.0
DivideGrid(x, y, newWidth, newHeight, c1,e1 ,m ,e4)
DivideGrid(x + newWidth, y, newWidth, newHeight, e1, c2 ,e2 ,m)
DivideGrid(x + newWidth, y + newHeight, newWidth, newHeight, m, e2 ,c3 , e3)
DivideGrid(x, y + newHeight, newWidth, newHeight, e4, ,m , e3, c4)
else
var c = (c1 + c2 + c3 + c4) / 4
var/turf/newturf
if(c >= 0.6)
newturf = new/turf/snow(locate(x, y, 1))
else if(c >= 0.5)
newturf = new/turf/stone(locate(x, y , 1))
else if(c >= 0.4)
newturf = new/turf/dirt(locate(x, y, 1))
else if(c >= 0.3)
newturf = new/turf/sand(locate(x, y, 1))
else if(c >= 0.2)
newturf = new/turf/water(locate(x, y , 1))
else if(c >= 0.1)
newturf = new/turf/deepwater(locate(x, y , 1))
newturf.name = "[newturf.name] - [c]"
Displace(num)
var/Max = num / (world.maxx + world.maxy) * 3
return (rand(0,10)/10 - 0.5) * Max
Problem description:
Ok so i was playing dwarf fortress and i was like: "i wonder how they randomly generate this?" so i searched it up and it lead me to making a height map out of plasma fractals, so i searched it up a bunch and tried to piece together my own code, didnt turn out as well, above is what i DID get but the problem is is that when i run it(i have a verb that calls it) it puts together this mashed up map of random tiles, somewhere in there i made each tile say what "height" it was at or "c" and they all correspond to eachother pretty well but its all jumpy, could anyone provide an explanation to what im doing wrong? or what error i made if i was doing it right( doubt it )?? Please and thank you!
By the way, hello fellow Armokian! Mind your cats.
This is a FANTASTIC first attempt at this problem. Complete breath of fresh air on this board.
First, a few pointers:
Simplify:
AKA:
There's this, as well:
Switches are going to give you a much-needed speed boost.
Becomes:
I'd also heavily suggest widening your ranges based on what you want to consider to be ideal map usage.
In my opinion, you should probably have about 30% of your map covered by water, and all but the very shores should probably be deep water, so a very narrow shelf.
Then, to open up the map, sand should be relatively narrow as well, and dirt/grass should be about 30-50% of your map, depending on how much you want to focus gameplay on dwarfy cliffs.
Let's just... Take a look at these new numbers:
is slower than, but does roughly the same thing as:
You should also note that Dwarf fortress uses multiple maps to get values against, so you can generate a stratified map where the equator is near the center increasing the value of c as you get closer to the center along the y axis, but having the north/south edges scale in from 0. This will give you both elevation and temperature to choose from when generating your terrain.
I think Dwarf Fortress uses 4 or 5 values to generate its worlds: Elevation, Temperature, Volcanism, and Evil are the ones I know about for sure though.
Alright, so let's actually talk about the actual algorithm you are using.
You are essentially using fractal subdivision. It's really simplistic, but it's going to give you a lot of jagged edges until you apply a smoothing algorithm. This can be interpolation, or it can be a physical erosion simulator like Dwarf Fortress uses.
I'm not sure, but your math might be off here:
That * 3 is a little wonky. Not really sure what it's doing in there.
I'm pretty sure that Max should be roughly:
That * 3 is going to increase the displacement factor quite a lot and make things really disjointed.
Last, I'd strongly recommend not using locate() like you currently are. Better to grab the entire area before generating, and then stash the positions of the objects in a list prior to initializing the new turfs.
Now, instead of doing new/turf/deepwater(locate()), you can do this:
new/turf/deepwater(turfs[(y-1)*world.maxx + x])
This will speed up your generator a LOT.
Another point here, though, generating down to w=1/w=h might give you some granularity issues. You might want to stop generating a a higher subdivision, and then interpolate the heights from the corners of your displacement subdivision.
This will give you vaguely smoother results.
Interpolation:
Show us some results of your generator next time. It'd be quite nice to see.