This works fine, and is even reproduceable (based on a common seed) if the nextInt() calls are always in the same order. The issue is that in my game, the world is generated on demand, based on the player's location. This means, that if I explore the map differently, and the chunks of the map are generated in a different order, the randomness is no longer consistent.

How can I get this sort of randomness to be consistent, independent of call order?

2 Answers
2

This is simple, create a new Random() object for each chunk, using that chunk's position as the seed.

If you think of Random as a really (really) long series of numbers, the seed is just where to start iterating through. So, if you always set the seed before generating the chunk, you'll always get the same integers, in the same order.

EDIT

But how do you ensure that each chunk gets a unique seed?

It's not too critical to get a unique seed for each chunk, unless you want to try to guarantee that each chunk is unique from the last. I say try because even if each seed is unique it doesn't necessarily guarantee the random numbers you get will be different. If your world has a maximum size, you can get a unique long from each position in the world with a method like this:

Then you can do additional things to strive for unique seeds, like add the distance from the center of the world.

I should mention how I do this in my game. Since I'm generating terrain shape along with terrain type, I wanted to ensure that I'd have continuity between chunks. I did that by using a single world seed. Then the Perlin noise function takes the absolute world position as an input. This makes the transition between chunks seemless, which will not be the case if you're randomly generating each chunk distinct from the others.

But how do you ensure that each chunk gets a unique seed? Or does that even matter?
–
nbadalJun 25 '12 at 3:31

@nickbadal "This is simple, create a new Random() object for each chunk, using that chunk's position as the seed. " Two chunks cannot have the same position, so their seed will be unique.
–
doppelgreenerJun 25 '12 at 4:04

@JonathanHobbs That's true, but it has to be converted into a single number in some way. I'm blanking on a way to do that for an arbitrary position, but I added a method for when the world has a maximum. The second would fail fairly often I think, for example 0:0:1, 1:0:0 and 0:1:0
–
Byte56♦Jun 25 '12 at 4:08

@Byte56 I guess so. You also can't just do simple addition because for any set of three coordinates, any combination will produce the same seed (edit: which it seems you've noticed!)
–
doppelgreenerJun 25 '12 at 4:15

I'm not sure if there's any commonly practiced method of accomplishing this, but here's what I usually do for things like this:

Since you are already using a Perlin noise function, you can simply use Perlin noise to get the seed for each chunk. Whenever you need to generate a new chunk, simply feed that chunk's coordinates into the Perlin function, and use the returned value as the seed for that chunk. This means you'll need to reseed your random number generator every time a chunk is generated, or you can simply create a new instance of the generator if it's a class.

Essentially, whenever I need to generate consistent data in arbitrary positions, I use a Perlin noise function because it's reasonably fast and consistent.