Worldgen (Fun with noise)


Being a moderately passionate Dwarf Fortress player, I couldn't avoid the temptation to include a complex world generation algorithm into my game. I've been toying with those for a long time, but the current version is actually the best I've ever done. I think.

World

Like many other attempts I've made myself or seen around, my implementation of worldgen involves a liberal use of the Perlin noise function. Many layers of Perlin noise are generated for many different purposes, mixed around, modified and then interpreted as values such as "land", "water", "forest", "mountain", etc.

First, let me show off a couple screenshots of the worlds I've been able to make:



Now, here's the algorithm I came up with:

  1. Generate a Perlin noise map for heights; edit it with a function that pushes its edges downwards, creating an island
  2. Create a separate noise map for temperature; mix it with a vertical gradient so that north is generally colder than south
  3. Create another noise map for humidity; increase it in places where the "heights" are slightly above ground level. That way, there will be a bit more swamps near the water
  4. Create another map for forests; values above a certain threshold will become forests
  5. Take the "heights" noisemap and use it to create a new 2D array - 0s for water (below a certain threshold), 1s for land
  6. Apply 2-3 iterations of cellular automata to the resulting array to smooth out the edges and remove meaningless small islands/holes. Here is a great example of how cellular automata can be used for map making
  7. Using all the noise maps, calculate terrain types:
    1. High enough values become mountains, low enough values become water
    2. Cells with "forest" above a certain threshold become forests
    3. Cells with "humidity" above a certain threshold become swamps
    4. Cells with "temperature" above a certain threshold become snow/snow fore
  8. Now, locations (or areas, as I call them in the code):
    1. Cities are placed in random plain/swamp/forest cells, within a certain distance of each other
    2. Villages are placed in a certain vicinity around each city. The amount of villages depends on how much room is available
    3. Fields are placed around each village. Each adjacent cell has a chance to grow a field, which is halved for snow cells
    4. Caves are placed at random mountain cells with walking access (adjacent non-mountain cells)

Areas

As for areas themselves, I've been able to come up with a relatively quick and dirty way of generating those. Inside each area is a smaller 2D array of cells, each with its own type ("road", "house", etc) and additional properties ("drink_price" for taverns, for instance).

In areas, movement is only vertical and horizontal; this is part homage to MUDs and part practical. See, as you enter a new room in a dungeon, you can see the available paths, but not the rooms those paths lead to. Like this:


I imagine that seeing 5-7 question marks around your character at all times while exploring a dungeon wouldn't be that fun, would it? Seeing 1-4 options, on the other hand, is quite easy to grasp. Besides, it does remind me of the classic 4-directional movement in games like Zork and its derivatives (including MUDs).

So far, there are 3 types of areas in the game: caves, towns and villages. Technically there are also castles, but if I tried entering one - I would get a crash, since they're not actually implemented from the inside. Scary stuff.

Caves

Caves are, simply put, random blobs of connected rooms. Each room has a chance to contain some enemies and some loot the player can pick up. This is a good example of a cave layout:


I generate caves by picking random horizontally/vertically adjacent cells and making them into cave cells, then recursively repeating until a certain size is met. Then, a random cell is turned into an exit ("<" on the picture above).

Town

Gameplay-wise, a town is a network of roads with some buildings in most of the adjacent cells. Here's an example of a town:


Towns are interesting. I've thought about them for a while, and I ended up implementing a rather interesting algorithm that works surprisingly well despite its hackiness. Here's how it works:

  1. Keep track of a list of possible road starting points, like this: [{x: 10, y:10}]
  2. Declare N as the number of roads in the town, and specify minimum and maximum road lengths 
  3. N times, do the following:
    1. Pick a random starting point from the array
    2. Pick a direction to go, east/west/south/north
    3. Build the road in the chosen direction for a length of L (in range between minimum and maximum road length)
    4. For every other cell along the way, add its coordinates to the array of possible road starting points. That way, next time you choose a random point, it might be the one you just passed and an intersection will occur. Every other - to eliminate parallel adjacent roads
  4.  For every road cell with only 1 adjacent road cell (those are dead ends), mark them as exits
  5. For every non-road cell with adjacent road cells, build a random building with a probability based on how many road cells there are nearby. This somewhat biases the town's buildings towards the center, where there are more roads

Villages

Villages are basically smaller towns with a different set of buildings. Here is an example of a village:


Conclusion

There's still much to do before this world generator can be called complete. For example, I'd love to figure out a way to make distinct continents or more realistic mountain ranges. However, I do believe that this implementation is more than enough for now - I'd better focus on actual gameplay, combat mechanics, etc. It's never too late to revisit the world generator and add new content.

Leave a comment

Log in with itch.io to leave a comment.