Factorio Resource Generation

or, "Why does choosing large ore patches result in so many small patches?"

I occasionally see folks lamenting that they got some small ore patches even though they asked the game to generate large ones. The Factorio wiki does try to answer this question, but I think an interactive explanation would help.

For this demo I've copied a lot from Amit Patel's interactive demos on Red Blob Games.

Make some noise

The first step is to draw a wiggly line using random numbers. We use something called a "noise function" to do this. A noise function takes some random numbers and uses them to draw a curve that has nice aesthetic properties. Of course it would be simpler to draw the random numbers directly, but the result wouldn't be very pleasant.

There are many types of noise functions. This webpage uses a classic function called Perlin noise; Factorio probably uses something similar.

In a computer program such as Factorio, or such as this webpage, we can call the noise function like this:

function height(x) { noise(x); }

This function is called once for every x coordinate on this graph, and returns the height that the graph should have at that point. Factorio obviously uses 2D noise that is based on both the x and y coordinates, but everything else will be the same.

I'm leaving out many details about how the noise is created, and what parameters a game developer can use to customize the overall look of the noise. These parameters are fairly complicated, and can be used to turn a simple noise function into a wide variety of pleasing shapes and patterns. With some work, they can reproduce wood grain, the flocking patterns of birds, fire and smoke, terrain elevation, stock prices, or virtually any other thing you can think of. Part of the artistry of writing a game like Factorio is using noise functions effectively. For the purposes of this demo, I've kept the noise function fairly simple.

Threshold it

The next step is to treat the height of the curve as the amount of ore in that spot. Since the amount of ore in a tile cannot be negative, we treat all negative numbers as zero ore. This effectively clips the curve at zero.

This is not something that Factorio will show you, but for demonstration purposes we'll keep showing the negative values so that you can see how they are modified by the later steps.

Stretch it

The first option Factorio gives you is control over the frequency of ore patches. Higher frequency means that there is less distance between patches, lower frequency means a longer distance between patches.

As you scrub back and forth below, watch how this also affects the width of each patch. At higher frequencies, the patches can become quite narrow, but some wide patches may still exist. At low frequencies each patch will be much wider than normal, but some will still be quite narrow.

function height(x) { noise(x * ); }

Here we see how this is implemented. By multiplying the x coordinate by the frequency, we step further along the noise function for each step we take in the x direction. This squezes the noise function into a smaller amount of terrain. When the frequency is less than 1.0, this squeeze becomes a stretch.

Add to it

The next option Factorio gives is the size of the patches. This is intended to control the width of the patches without changing the distance between them. However, as you scrub the size value below, notice how new patches can appear between the existing ones. The existing patches have gotten larger, but these new patches will be smaller.

function height(x) { noise(x) + ; }

As you can see from the implementation, all we're doing is adding a constant value at every point along the graph. This has the effect of raising or lowering the graph as a whole. This is much clearer when the whole graph is visible, as you can see ahead of time where the next peak will rise above the threshold.

You'll also notice that the threshold starts out negative. This to make ore rare enough to make a fun game. If the offset were zero, then about half the map would be ore.

Scale it

Finally, Factorio gives us control over the richness of each patch. This is implemented by multiplying each ore amount by a constant factor, exagerating the peaks. However, even this can create new patches between existing ones, as peaks that were beneath the threshold are now pushed above it.

function height(x) { * noise(x); }

Seed it

Of course it wouldn't be much fun if the ore was all in the same places every time you played. Thus Factorio chooses a random seed value when you start a new game, and arranges for each seed value to result in a different output from the noise function. Try some different seed values here to see this in action.

set_seed();

Factorio can use any of billions of different seed values, but for this demo I've limited them to just zero through 100. If you turn off clipping, you'll be able to see just how much the noise function changes shape with different seeds.

Because the "random" numbers used by the noise function depend on the seed value, you can start a Factorio map with a specific seed value and get the same map every time. This especially helps in multiplayer, as the server can send the seed value to each player and know that they will generate the same terrain as the server. Of course, anything the players build must still be communicated to all players, but the underlying terrain need not be. This can save considerable bandwidth during a game.

Putting it all together

Of course Factorio doesn't make you pick just one of these four options; you can use them all simultaneously.

set_seed();
function height(x) { * noise(x * ) + ; }