# Basic procedural generated content works, but how could I do the same in reverse?

My 2D world is made up of blocks. At the moment, I create a block and assign it a number between 1 and 4. The number assigned to the nth block is always the same (i.e if the player walks backwards or restarts the game.) and is generated in the function below. (Image shows a small portion of the game, in practice there are much more blocks)

As shown here by this animation, the colours represent the number.

function generate_data(n)
math.randomseed(n) -- resets the random so that the 'random' number for n is always the same
math.random() -- fixes lua random bug
local no = math.random(4)
--print(no, n)
return no
end


Now I want to limit the next block's number - a block of 1 will always have a block 2 after it, while block 2 will either have a block 1,2 or 3 after it, etc. The next block's number is taken at random from the next table:

{
[1] = {next = {2}},
[2] = {next = {1,2,3}},
[3] = {next = {4}},
[4] = {next = {1,3,4}},
}


Before, all the blocks data was randomly generated, initially, and then saved. This data was then loaded and used instead of being randomly called. While working this way, I could specify what the next block would be easily and it would be saved for consistency. I have now removed this saving/loading in favour of procedural generation as I realised that save whiles would get very big after travelling.

Back to the present. While travelling forward (to the right), it is easy to limit what the next blocks number will be. I can generate it at the same time as the other data.

The problem is when travelling backwards (to the left) I can not think of a way to load the previous block so that it is always the same.

Does anyone have any ideas on how I could sort this out?

• When you say that a block can only have a block with a certain value after it do you then mean only in the left to right direction? Also, are the blocks in 2D or 1D as in the animation? – Mikael Högström Aug 30 '12 at 17:34
• The block's value I am asking only applies when travelling to the right. The blocks only expand in the X axis, there is no Y transitioning. – user14992 Aug 30 '12 at 17:42
• You might skip the random component and use a deterministic pseudorandom generator, like 1D Perlin noise. Direction becomes irrelevant and you don't have to store anything. – 3Dave Aug 30 '12 at 20:30
• My first thought was to calculate sort of a hash value for every block and use it as aseed to generate the same block every time but I don't really see a way to do that when there is only a rule for transitioning from left to right. If you could change the ruleset to go in two directions somehow then it might be easier but I expect there's a reason behind your current scheme... – Mikael Högström Aug 31 '12 at 10:41
• I want the world to be the same each time, the limiting rule would give me more control over the world – user14992 Aug 31 '12 at 12:09

If I understand your question correctly you'd like that each block be random, but blocks beside each other are related. In terms of a game, the sequence of rooms is random, but neighbouring rooms have to be compatible in some way. Going right isn't a problem since you have the current room and can easily apply the contsraint to the next room. Going left is a problem since you can't be certain which room was there.

Instead of trying to generate a specific block number instead think about the transitions between the blocks. Your random generator will produce a transition delta between the rooms. The delta value for a given block will be random, but based on a fixed seed (thus constant for a particular game). You then apply this delta to the player's current room number to get the new block. If you are going right you add the delta, and if going left your subtract the delta.

That is, you are currently in Block X with a value of V. Let's say the left-delta of block X uses X as a seed and the right transitions uses X+1. To go right you calculate the transition of X+1 and add it to V. To go left you calculate the delta at X and subtract it from V.

An example with values, say the delta values are [ 0, 1, -1, 0 ].

1. You start at block 0, which we give value 4 (random number)
2. To walk right we get delta X+1 = 1
3. You are now at Block 1 with a value 4+1 = 5
4. Right again, Block 2 with a value 5-1 = 4
5. Right again, Block 3 with a value 4+0 = 4
6. Walk left, delta X = -1
7. You are now at Block 2 with a value 4-(-1) = 5
8. Left again, Block 1 with a value 5-1 = 4
9. Left again, Block 0 with a value 4-0 = 4

You can see that walking both left and right will result in the same value produced for each block.

The fixed seed idea is the way to go, but you can keep it very simple.

If you concern is the save game size, just save the seed for each level and re-generate it entirely at game startup, in you own fixed order (e.g. for a row of blocks, from -1000 to +1000).

Oh, and maybe this save game size isn't an issue after all. Think about how big the Minecraft world is, and I'm pretty sure at least a good part of it is saved:

• This isn't really answering the question of how to determine room X-1, given a known room X, and the rules on adjacent rooms. – Kylotan Aug 30 '12 at 12:52
• Well, at least I tried something more elaborated than YAGNI ;) – Laurent Couvidou Aug 30 '12 at 13:32