2

I found a great post about world generation, which can be found here.

It does a good job describing what needs to be done, but I'm having trouble figuring out how to do it in python. I believe it was done in as3, but I'm not sure for certain. Any way, I also found a libtcod function for perlin noise:

noise2d=libtcod.noise_new(2)
value = libtcod.noise_turbulence_perlin(noise2d,[0.5,0.7],32.0)

I don't really know how to implement this, and then assign characters based on the height.

If someone could help me translate the steps from the article to python, I'd really appreciate it. Thanks

Jeremy Darrach
  • 273
  • 1
  • 6
  • 18
  • Some years ago a wrote a rogulike prototype with different dungeon/world generators, using litcod/noise. You can find it [here](https://bitbucket.org/BigYellowCactus/domeriarl) (beware that it uses an older litcod version), especially [`worldgenerator.py`](https://bitbucket.org/BigYellowCactus/domeriarl/src/d9a99e7ca119d12d4251b4741034e631c23d991f/src/world/worldgenerator.py?at=default). – sloth May 07 '13 at 10:17
  • Thanks Dominic, this is really great! Tell me if I got this right: you create a heightmap, add noise to it, then assign tiles according to the height of each position? – Jeremy Darrach May 07 '13 at 19:44

1 Answers1

2

Here's a class I wrote some years ago that creates a world map for my roguelike prototype DomeriaRL. The relevant part is in the __generate method.

It applies noise to a heightmap, normalizes it, and creates the tiles based on the values of the heightmap.

I'm using a color map to create smooth transitions from one tile kind to another.

from constants.constant import *
from world import World
from worldtile import WorldTile

class WorldGenerator(object):
  """Randomly generates a new world with terrain and objects"""

  def regular(self):
    """Randomly generate a new world with some water, swamps, hills, some objects etc"""

    idx = [ 0 , 15, 75, 90, 101 ] # indexes of the keys 
    col = [ T.Color(0,100,100),
            T.Color(0,75,0), 
            T.Color(50,150,0), 
            T.Color(150,120,80), 
            T.Color(180,180,180)]

    map=T.color_gen_map(col,idx)

    tiles = zip(idx, [[SWAMP, PLAINS],
                      [PLAINS, FOREST], 
                      [HILLS, FOREST],
                      [HILLS, HILLS, MOUNTAINS],
                      [HILLS, MOUNTAINS,MOUNTAINS]])

    world = self.__generate(map, tiles)
    return world

  def __generate(self, colormap, mtiles, noise_zoom=1, noise_octaves=10):
    hm = T.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT)
    hm1 = T.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT)
    hm2 = T.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT)

    noise = T.noise_new(2)
    T.heightmap_add_fbm(hm1, noise, noise_zoom, noise_zoom, 0.0, 0.0, noise_octaves, 0.0, 1.0)
    T.heightmap_add_fbm(hm2, noise, noise_zoom*2, noise_zoom*2, 0.0, 0.0, noise_octaves/2, 0.0, 1.0)

    T.heightmap_multiply_hm(hm1, hm2, hm)
    T.heightmap_normalize(hm, mi=0.0, ma=1)

    tiles = {}

    # 0...100 -> value from noised heightmap
    for x in xrange(0, 101):
      lower = [c for c in mtiles if c[0] <= x][-1] # tile is between lower and upper color
      upper = [c for c in mtiles if c[0] > x][0]

      # calculating percentage
      lower_c = x - lower[0]
      upper_c = upper[0] - x
      count = lower_c + upper_c

      tiles[x] = colormap[x], lower[1], int(upper_c * 1.0 / count * 100), upper[1] 

    # generate world grid
    grid = []
    for x in xrange(WORLD_WIDTH):
      grid.append([])
      for y in xrange(WORLD_HEIGHT):
        hm_v = T.heightmap_get_value(hm, x, y)
        grid[x].append(WorldTile(*tiles[int(hm_v * 100)]))

    T.heightmap_delete(hm)
    T.heightmap_delete(hm1)
    T.heightmap_delete(hm2)

    objects = []
    while len(objects) < 5:
      for x in xrange(WORLD_WIDTH):
        for y in xrange(WORLD_HEIGHT):
          r = random.randrange(0, 10000)
          pos = [wo for wo in WORLDOBJECTS if wo.chance >= r and grid[x][y].tile in wo.tiles]
          if pos:
            o = random.choice(pos).create(x, y)
            objects.append(o)

    return World(grid, objects)

An example world map looks like this:

enter image description here

Note that this game uses libtcod 1.5.1b1, and some function names changed in newer releases.

sloth
  • 99,095
  • 21
  • 171
  • 219
  • This looks really good. however, I looked over it, and i'm not sure how to implement this into my current design. I'm following [this tutorial for making a python roguelike.](http://roguebasin.roguelikedevelopment.org/index.php?title=Complete_Roguelike_Tutorial,_using_python%2Blibtcod) – Jeremy Darrach May 08 '13 at 19:48
  • Maybe i'll expand that tutorial in the near future. – sloth May 09 '13 at 06:52
  • okay, that would be good. thanks again for all your help so far – Jeremy Darrach May 09 '13 at 19:47