Someone may have come up with something like this before, wouldn’t really surprise me. But after trying to figure out a way to get random number per location (for generating terrain), and experimenting with creating per location seeds for Java.Random I realized this could probably be done much better with a home-brew variation on Xorshift. The idea is really simple, use the coords as the basis for (extra) shifts (along with hopefully good ones, just for safety):
The basis is like this:
/**
* Should produce a random long from seed at coordinates x and y
*
* @param seed
* @param x
* @param y
* @return
*/
public static long longFromSeed(long seed, int x, int y) {
long out = seed + (12338621L * (long)x) + (15485863L * (long)y);
out ^= lshift(out, (x % 19) + 7);
out ^= rshift(out, (y % 13) + 31);
out ^= lshift(out, 4);
return out;
}
/**
* Should produce a random long from seed at coordinates x, y, t
*
* @param seed
* @param x
* @param y
* @param t a fake iteration
* @return
*/
public static long longFromSeed(long seed, int x, int y, int t) {
long out = seed + (5443 * (long)t)
+ (12338621L * (long)x)
+ (15485863L * (long)y);
out ^= lshift(out, (x % 19) + 7);
out ^= rshift(out, (y % 13) + 31);
out ^= lshift(out, 4);
out ^= rshift(out, (t % 5) + 23);
return out;
}
/**
* should generate num long values using longFromSeed.
*
* @param seed
* @param x
* @param y
* @param num
* @return
*/
public static long[] longsFromSeed(long seed, int x, int y, int num) {
long[] out = new long[num];
out[0] = longFromSeed(seed, x, y);
for(int i = 1; i < num; i++) {
out[i] = longFromSeed(out[i-1], x, y);
}
return out;
}
/*=============================*
* INTERNAL UNTILITY METHODS *
==============================*/
/**
* Performs left bit shift (<<) with wrap-around.
*
* @param in
* @param dist
* @return
*/
private static long lshift(long in, long dist) {
long out = in << dist;
out += (in >>> (64 - dist));
return out;
}
/**
* Performs right bit shift (>>) with wrap-around.
*
* @param in
* @param dist
* @return
*/
private static long rshift(long in, long dist) {
long out = in >>> dist;
out += (in << (64 - dist));
return out;
}
}
The second method is for creating fake sequence, with using “t” as a kind of fake iteration of calls (obviously, does not get the same number as call t time, but not the point). The third is to get a bunch of number by using traditional repetition of getting the next number.
Beyond that the full class does include methods for deriving other types, as well as instance methods that use a pre-store seed. (For terrain gen, only one is needed per world, as however it might be devided up into sub-section, all you need are the coords.)
The full class, which I plan on using in a project I’m working on (with further development), I’ve put on pastebin to keep this short.
http://pastebin.com/9qXZhS45