Randomly generating terrains

… aka “When the Creator misplaces a parenthesis”. :)

So my first attempt to write a program to generate random but pleasing landforms for my Sim on a Stick did not go quite as expected.

When the Creator God misplaces a paren...

Bit spikey, for instance.

But then I found a misplaced parenthesis! And things got better.

Ah, much better

I think I am liking the algorithm…

Landforms from the RNG

For the curious, here is the basic (recursive, self-similar) routine, in everyone’s favorite language: Python. (Squished down to fit in the weblog here, not guaranteed to compile as-is.)

def fill_in_terrain(t,lowx,lowy,maxx,maxy):
   ''' Takes the input terrain, where the low-by-max '''
   ''' corners are already filled in, and fills in '''
   ''' everything inside those corners, by the '''
   ''' Magic of Recursion. '''
   if maxx-lowx<2: return t
   if maxy-lowy<2: return t
   xmid = int((lowx+maxx)/2)    
   ymid = int((lowy+maxy)/2)
   hscale = (maxx - lowx) * HSCALE
   # first the corners
   if t[lowx][ymid] is None:
     t[lowx][ymid] = (t[lowx][lowy] + t[lowx][maxy]) / 2 
       + hscale - math.floor(2*hscale*random.random())
   if t[maxx][ymid] is None:
     t[maxx][ymid] = (t[maxx][lowy] + t[maxx][maxy]) / 2 
       + hscale - math.floor(2*hscale*random.random())
   if t[xmid][lowy] is None:
     t[xmid][lowy] = (t[lowx][lowy] + t[maxx][lowy]) / 2 
       + hscale - math.floor(2*hscale*random.random())
   if t[xmid][maxy] is None:
     t[xmid][maxy] = (t[lowx][maxy] + t[maxx][maxy]) / 2 
       + hscale - math.floor(2*hscale*random.random())
   # then the center
   if t[xmid][ymid] is None:
     t[xmid][ymid] = (t[lowx][ymid]+t[maxx][ymid]
                     + t[xmid][lowy]+[xmid][maxy])/4 
                     + hscale - math.floor(2*hscale*random.random())
   # and recurse on the four quadrants
   t = fill_in_terrain(t,lowx,lowy,xmid,ymid)
   t = fill_in_terrain(t,lowx,ymid,xmid,maxy)
   t = fill_in_terrain(t,xmid,lowy,maxx,ymid)
   t = fill_in_terrain(t,xmid,ymid,maxx,maxy)
   return t

def get_terrain(x,y):
   ''' returns an [x][y] array of floats representing a terrain; '''
   ''' range unpredictable '''
   ''' x and y ought to be powers of two, for best results.  '''
   ''' oh, and equal I suppose '''
   answer = [ [None for a in range(y+1)] for b in range(x+1) ]
   answer[0][0] = 0
   answer[x][0] = 0
   answer[0][y] = 0
   answer[x][y] = 0
   answer = fill_in_terrain(answer,0,0,x,y)
   return answer

Fun that all these pretty hills and things come out of that little bit of (also pretty) code…


Get every new post delivered to your Inbox.

Join 74 other followers