(Please note, I am aware that the generation is not truly random and relies on mathematical equations, and that my language of choice is C++)

So I've been learning programming for a while now and I'm looking to make a top down 2D game. I want this game to generate random terrain pretty much like Dwarf Fortress but with sprites, however for this question let's just say that there just ASCII characters. I want it to generate mountains, rivers, inland lakes etc. I know of algorithms but have not been able to find a list of them all. The ones i know of are:

Perlin Noise, Diamond Square, Midpoint Displacement and some other minor ones.

However I don't know which one to use and struggle to find a good article on any of them. Is there one right for the job, or does it just come down to personal opinion? And if you can find a list of all the algorithms and maybe a good article on one it would really help. Thanks!

  • \$\begingroup\$ Some days ago I made this. I know it's probably not what you are looking for, but maybe you can make it more complex to fit what you need: drive.google.com/open?id=0B5yRPbmIAqr0X2wwX1BwNTZZMHc. It's a really simple algorithm (I use it to generate a random tiled background for my game) \$\endgroup\$ – Liuka Sep 7 '16 at 8:11
  • \$\begingroup\$ Thats actually pretty cool. I made a purely random terrain generator, so it was horrible, trees in the ocean etc. Do you have a link to a good explanation of the algorithm? \$\endgroup\$ – Harry the hacker Sep 7 '16 at 8:56
  • \$\begingroup\$ Actually I created this from scratch, so I'll post the code, trying to explain how it work and how you can edit it \$\endgroup\$ – Liuka Sep 7 '16 at 9:16
  • 1
    \$\begingroup\$ Sounds like you already know: there are tons of different ways to generate terrain. Listing every one isn't really practical for an answer (there will always be more that we miss) and each has different pros/cons so we can't really recommend one "best" approach, at least not without knowing more about what specific features you want to generate. I'd consider this question too broad currently. I recommend picking a method that makes sense to you, implementing it, and updating your question if it's not giving the results you want — that way you can narrow in on exactly what you want to change. \$\endgroup\$ – DMGregory Sep 7 '16 at 11:05
  • \$\begingroup\$ I would write this as an answer but unfortunately the question is on hold. Not correct I think because I read it as asking help to explain how to use coherent noise. However, here is my answer: Read the really excellent LibNoise documentation at libnoise.sourceforge.net. Read the excellent "What is coherent noise" article first, then work or read through the tutorials. This should answer your questions. \$\endgroup\$ – Ian Macintosh Sep 7 '16 at 20:29

This is the code that generate this kind of terrain (background for my "platform" game): https://drive.google.com/open?id=0B5yRPbmIAqr0X2wwX1BwNTZZMHc

(I hate python so sorry if this is an horrible code, and english is not my main language, so be patient pls)

import sys
import random
import pprint
import math
w = 350 #width of the terrain
h = 350 #height "  "    "

sz = 10 #size of a tile

sz_x = w / sz
sz_y = h / sz
area = sz_x*sz_y

bkg = [[' ' for x  in range(sz_x)] for y in range(sz_y)] #initialinzing background matrix

plates = [' ', '/', '.', 'I', '#'] #tile types
#each plates has it own probability to be "spawned", the following array is
#defined as couples of (total_previous_probability + this_probability / 2, (this_probability / 2) ^2)
probability = [[2.5, 2.5**2], [35, 30**2], [72.5, 7.5**2], [85, 5**2], [95, 5**2]] #5, 60, 15, 10, 10
temp_probability = [0, 0, 0, 0, 0]
nm_plates = [0,0,0,0,0] #for debug purpose

def get_random_plate(temp_prob):
    plate = 0
    max_prob = 0
    i = random.randint(0, 100)
    for p in range(len(plates)):
       prob = -(i - probability[p][0])**2 + probability[p][1] + math.sqrt(temp_prob[p] / 9);
    if(prob > 0 and prob + temp_prob[p] > max_prob):
        max_prob = prob+ temp_prob[p]
        plate = p
return plate

#list of predefined point (x, y, types), you can make this random
#in the link you can see five different "big areas" of one types built around theese point
#you can have a lot more of this points, more points of the same time you
#have in a little area more this area will be filled with the type of that points
sp_point = [
[10, 10, 0],
[27, 5, 0],
[15, 25, 2],
[25, 25, 2],
[5, 29, 3],
[16, 16, 4],

def create_bkg(temp_prob):
for y in range(sz_y):
    for x in range(sz_x):
        temp_prob = [0, 0, 0, 0, 0]
        for p in sp_point:
            sqrDist = (x - p[0])**2 + (y - p[1])**2
            temp_prob[p[2]] += (area / (sqrDist + 0.1))**3

        plate = get_random_plate(temp_prob)
        nm_plates[plate] += 1
        bkg[x][y] = plates[plate]

def print_bkg():
    for y in range(sz_y):
        for x in range(sz_x):
        print ''    
    print '\n'

This generates the tile map, then I think you can create something like an height map: you read each tile of the matrix and "make it higher or lower" (I don't know how to say that) based on the surrounding tiles:

#pseudo code
if (this_tile_is_a_mountain) count mountain tiles in an area of x tile;
this_height += (number_of_mountain_tiles_found * x)^y / z
#and so on, same for lakes

In the code above you can edit some line to change the behaviour of the algorithm:

temp_prob[p[2]] += (area / (sqrDist + 0.1))**3 #you can change how temp_prob is computed

#more higher it is more "dense" will be the "one type" areas
#or you can reduce the effect it has on the result editing the following lines:
prob = -(i - probability[p][0])**2 + probability[p][1] + math.sqrt(temp_prob[p] / 9); #change this nine, remove the sqrt, add another sqrt sqrt(sqrt(x))
if(prob > 0 and prob + temp_prob[p] > max_prob): //add a here: sqrt(temp_prob[p])
    max_prob = prob+ temp_prob[p] //or add it here, or both
    plate = p

Just try

(I really need someone who can rewrite this in real english...)

  • \$\begingroup\$ i dont really know python but thanks! \$\endgroup\$ – Harry the hacker Sep 7 '16 at 10:42
  • \$\begingroup\$ It's like c++ but you dont have do declare variables and "for p in range(x)" is like for each member of x and "for p in range(len(y))" means "do from 0 to y) \$\endgroup\$ – Liuka Sep 7 '16 at 11:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.