JSFiddle - React, Tailwind, and code Playground
HTML
<div>
<p>Original: http://atomicmonks.com/terrain/world.html</p>
<button type="button" id="go2">Generate</button><br />
<canvas id="map" width="512" height="512" ></canvas>
<ul>
<li><label for="seed">Seed: </label><input type="text" size="10" id="seed" value="42" /> <button type="button" onclick="$('#seed').val(new RNG().nextInt())">Random</button></li>
<li><label for="autogen">New Seed on Run: </label><input type="checkbox" id="autogen" checked="checked" /></li>
<li><label for="width">Width: </label><input type="text" size="3" class="wheelable" value="256" data-exp="7" id="width" /></li>
<li><label for="height">Height: </label><input type="text" size="3" class="wheelable" value="256" data-exp="6" id="height" /></li>
</ul>
<ul id="altitude">
<li><label>Altitude Adjustment: </label><span id="altadjust">0</span></li>
<li>
<button type="button" id="moveup">Move Up</button>
<button type="button" id="center">Center</button>
<button type="button" id="movedown">Move Down</button></li>
<li><label>Render Time: </label><span id="time">0</span>ms</li>
</ul>
<div id="history">
<b>Used Seeds:</b>
</div>
</div>
JavaScript
function RNG(seed) {
var m = 0x100000000, a = 1103515245, c = 12345, state = seed ? seed : Math.floor(Math.random() * (m-1));
this.nextInt = function() {
state = (a * state + c) % m;
return state;
}
this.nextFloat = function() {
return this.nextInt() / (m - 1);
}
this.nextRange = function(start, end) {
var rangeSize = end - start;
var randomUnder1 = this.nextInt() / m;
return start + Math.floor(randomUnder1 * rangeSize);
}
this.choice = function(array) {
return array[this.nextRange(0, array.length-1)];
}
};
function Generate(seed, width, height) {
var grid = [],
rg = width+1,
minh = 255, maxh=0,
altshift = 0;
while(rg--) {
grid.push([]);
var sd = height+1;
while(sd--)
grid[grid.length-1].push({h:0});
}
var rnd = new RNG(seed);
var step = width > height ? height : width;
while(step>1) {
for(var y=0;y<height;y+=step) {
for(var x =0;x<width;x+=step) {
subdivide(x,y,x+step,y+step);
}
}
step = Math.round(step*0.5);
}
var scale = 255/(maxh-minh);
function getheight(z0, z1, d) {
var fc = d*rnd.nextFloat()-d*0.5,
r = (z0+z1)*0.5 + fc;
if(minh>r) minh=r;
if(maxh<r) maxh=r;
return r;
}
function subdivide(x0, y0, x1, y1) {
var xn = Math.round((x0+x1)*0.5), yn = Math.round((y0+y1)*0.5);
grid[xn][y0].h = getheight(grid[x0][y0].h, grid[x1][y0].h, x1-x0);
grid[x0][yn].h = getheight(grid[x0][y0].h, grid[x0][y1].h, y1-y0);
grid[x1][yn].h = getheight(grid[x1][y0].h, grid[x1][y1].h, y1-y0);
grid[xn][y1].h = getheight(grid[x0][y1].h, grid[x1][y1].h, x1-x0);
grid[xn][yn].h = getheight(grid[x0][yn].h, grid[x1][yn].h, x1-x0);
...