Well, looks like that either defeated everyone or failed to interest anyone!
Luckily I managed to work it out on my own. Here's the code if it helps anyone. This will generate a fractal landscape which wraps from east to west but not north to south. It does it on an array of 1025*513 and on my computer takes two seconds. You can fiddle with the map size, though it is temperamental. You can also play with the "grain" and "valuemod#" values to change the scale and roughness of the terrain.
// Project: Fractal
// Created: 2017-11-30
// show all errors
SetErrorMode(2)
// set window properties
SetWindowTitle( "Worlds" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
global width=1024
global height=512
global maxheight=255
global dim map[width,height]
time=generateterrain()
mapmove=0
do
print( "Generated in "+str(time)+" seconds." )
print( "Left/right to move map. Space to generate a new map." )
moving=0
if getrawkeystate(32)=1
print( "Generating new map..." )
drawmap(0,200)
sync()
time=generateterrain()
endif
if getrawkeystate(37)=1
mapmove=mapmove+1
moving=1
endif
if getrawkeystate(39)=1
mapmove=mapmove-1
moving=1
endif
if mapmove>20 then mapmove=20
if mapmove<-20 then mapmove=-20
if mapmove<>0
shift(map,width,height,mapmove)
endif
if moving=0 then mapmove=0
drawmap(0,200)
sync()
loop
` This function draws the map.
function drawmap(offsetx, offsety)
for i=1 to width
for j=1 to height
dotx=i+offsetx ` x coordinate of the dot we're drawing
doty=j+offsety ` y coordinate of the dot we're drawing
heightpoint=map[i,j] ` Height of the map at this point
colour=heightpoint
drawline (dotx,doty,dotx,doty,colour,colour,colour)
next j
next i
endfunction
` This function wraps a value between 0 and a maximum.
Function wrap(value, max)
value = mod( value, max )
if value < 0 then value = max+value
EndFunction value
` This function generates the global terrain.
function generateterrain()
resettimer()
` First clear the map array.
for i=0 to width
for j=0 to height
map[i,j]=0
next j
next i
grain=4 ` Determines the "scale" of the map. Should be a power of 2.
valuemod#=1.0 ` Determines the roughness of the map. Anything below 1 will be weirdly smooth, anything over 2 will be very rough.
createfractal(map,width,height,grain,valuemod#)
time=timer()
endfunction time
` My attempt at my own fractal map generator.
function createfractal(array ref as integer [][],awidth,aheight,grain,valuemod#)
newfractalinit(array,awidth,aheight,grain)
newfractal(array,awidth,aheight,grain,valuemod#)
endfunction
` Initialises the random values for the fractal map generator.
function newfractalinit(array ref as integer [][],awidth,aheight,grain)
s=(aheight+1)/grain
for i=0 to awidth step s
for j=0 to aheight step s
array[i,j]=random(1,maxheight)
next j
next i
endfunction
` This is the main fractal generating function.
function newfractal(array ref as integer [][],awidth,aheight,grain,valuemod#)
s=(aheight+1)/grain
while s<>-1 ` This loop will repeat, with s halving in size each time until it gets to 1.
value=s*valuemod# ` This is the amount we will vary each new pixel by. The smaller the tile, the smaller this value should be.
` First we go over the whole map doing the square step.
for z=0 to awidth+s step s
i=z
if i>awidth
i=wrap(i,awidth)
endif
ss=s/2
ii=i+ss
if ii>awidth
ii=wrap(ii,awidth)
endif
for j=0 to aheight step s
jj=j+ss
newheight=square(array,awidth,aheight,s,ii,jj,value)
if jj<=aheight
array[ii,jj]=newheight
endif
next j
next z
` Now we go over the whole map again, doing the diamond step.
for z=0 to awidth+s step s
i=z
if i>awidth
i=wrap(i,awidth)
endif
ss=s/2
ii=i+ss
if ii>awidth
ii=wrap(ii,awidth)
endif
for j=0 to aheight step s
jj=j+ss
for n=1 to 2 ` We have to do the diamond step twice for each tile.
if n=1
ii=i+ss
jj=j
endif
if n=2
ii=i
jj=j+ss
endif
if ii>awidth
ii=wrap(ii,awidth)
endif
if jj=>0 and jj<=aheight
newheight=diamond(array,awidth,aheight,s,ii,jj,value)
array[ii,jj]=newheight
endif
next n
next j
next z
if s>2 ` Now halve the size of the tiles.
s=s/2
else
s=-1
endif
endwhile
endfunction
` This does the square part of the fractal.
function square(array ref as integer [][],awidth,aheight,s,x,y,value)
dist=s/2
total=0
crount=0
dim coords[3,1]
coords[0,0]=x-dist
coords[0,1]=y-dist
coords[1,0]=x+dist
coords[1,1]=y-dist
coords[2,0]=x+dist
coords[2,1]=y+dist
coords[3,0]=x-dist
coords[3,1]=y+dist
for n=0 to 3
if coords[n,1]=>0 and coords[n,1]<=aheight
coords[n,0]=wrap(coords[n,0],awidth)
total=total+array[coords[n,0],coords[n,1]]
crount=crount+1
endif
next n
total=total/crount
difference=randomsign(random(0,value))
total=total+difference
if total>maxheight then total=maxheight
if total<1 then total=1
endfunction total
` This does the diamond part of the fractal.
function diamond(array ref as integer [][],awidth,aheight,s,x,y,value)
dist=s/2
total=0
crount=0
dim coords[3,1]
coords[0,0]=x
coords[0,1]=y-dist
coords[1,0]=x+dist
coords[1,1]=y
coords[2,0]=x
coords[2,1]=y+dist
coords[3,0]=x-dist
coords[3,1]=y
for n=0 to 3
if coords[n,1]=>0 and coords[n,1]<=aheight
coords[n,0]=wrap(coords[n,0],awidth)
total=total+array[coords[n,0],coords[n,1]]
crount=crount+1
endif
next n
total=total/crount
difference=randomsign(random(0,value))
total=total+difference
if total>maxheight then total=maxheight
if total<1 then total=1
endfunction total
` This function shifts everything in an array to the left by a given number of pixels.
function shift(map ref as integer[][],width,height,offset)
dim dummy[width,height] ` First create a dummy array that's a copy of the main one.
for i=0 to width
for j=0 to height
dummy[i,j]=map[i,j]
next j
next i
for i=0 to width
ii=wrap(i+offset,width)
for j=0 to height
map[i,j]=dummy[ii,j]
next j
next i
undim dummy[]
endfunction