Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Seedable RNG?

Jaxx Tardis
Registered User
Join date: 9 Oct 2006
Posts: 11
10-15-2008 14:28
Does anyone have a seedable Random Number Generator routine in LSL? I'd like a way to generate the same set of "random" numbers every time based off a given seed value.
Faust Vollmar
llSetAgentSanity(FALSE);
Join date: 3 Feb 2007
Posts: 87
10-15-2008 15:37
From: Jaxx Tardis
Does anyone have a seedable Random Number Generator routine in LSL? I'd like a way to generate the same set of "random" numbers every time based off a given seed value.


Hewee Zetkin kindly provided me with this when I asked. :D

integer SeededRand(string Seed)
{
string Hash = llMD5String(Seed);
integer I1 = (integer)("0x"+llGetSubString(Hash, 0, 7));
integer I2 = (integer)("0x"+llGetSubString(Hash, 8, 15));
integer I3 = (integer)("0x"+llGetSubString(Hash, 16, 23));
integer I4 = (integer)("0x"+llGetSubString(Hash, 24, 31));
return I1^I2^I3^I4;
}

Typed from memory so it may need syntax fixes.

EDIT: Of course, you can stick any other string manipulation you'd like on the Seed if you want to make the generator a little more in depth... As for making it within a specific range, I wouldn't know where to start. XD

EDIT2: It uses MD5String because I needed to generate based on an AV UUID when I asked for a Seedable PsuedoRandom. The same Concept of making integers from MD5String Bits also works for generating strings, though its better to XOR 2 Seed Strings for that.
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
10-16-2008 14:22
Caveat: I've translated this from a different programming language - one where floats have a defined precision, and can actually be relied on :) - so, I'm not completely confident that LSL math is accurate enough to give a true result. However, it superficially seems to work. I leave it to anyone who is interested (and more knowledgeable than me) to test if the numbers pass some kind of pseudo random number test.

In any case, following a script reset, and for a given seed value, it should give you the same numbers each time.

CODE

float seed = 0.5; // 0.000000000 to 0.999999999 [1]
integer lo = 1; // 0 - 999999 [1]
integer hi = 10; // 0 - 999999 (must be greater than lo) [1]

// [1] these ranges are what were supported in the 'original' code
// I have no idea if LSL can handle them or not.

integer generate()
{
integer random;
integer range = hi - lo + 1;
seed = (seed * 9821) + 0.211327;
seed = seed - (integer)seed;
random = (integer)(range * seed) + lo;
return random;
}

default
{
touch_start(integer total_number)
{
llOwnerSay((string)generate());
}
}


(assuming it does work) just don't ask me why it works. :D
bobbyb30 Swashbuckler
Registered User
Join date: 8 Sep 2008
Posts: 46
10-16-2008 17:54
From: Pale Spectre
Caveat: I've translated this from a different programming language - one where floats have a defined precision, and can actually be relied on :) - so, I'm not completely confident that LSL math is accurate enough to give a true result. However, it superficially seems to work. I leave it to anyone who is interested (and more knowledgeable than me) to test if the numbers pass some kind of pseudo random number test.

In any case, following a script reset, and for a given seed value, it should give you the same numbers each time.

CODE

float seed = 0.5; // 0.000000000 to 0.999999999 [1]
integer lo = 1; // 0 - 999999 [1]
integer hi = 10; // 0 - 999999 (must be greater than lo) [1]

// [1] these ranges are what were supported in the 'original' code
// I have no idea if LSL can handle them or not.

integer generate()
{
integer random;
integer range = hi - lo + 1;
seed = (seed * 9821) + 0.211327;
seed = seed - (integer)seed;
random = (integer)(range * seed) + lo;
return random;
}

default
{
touch_start(integer total_number)
{
llOwnerSay((string)generate());
}
}


(assuming it does work) just don't ask me why it works. :D


I don't get whats random in there?
_____________________
Large supporter and contributer of LSL Editor available at lsleditor.org
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
10-16-2008 18:33
Well, what happened when you put the script in a cube and kept clicking it?

Bear in mind that the original request was for: "a way to generate the same set of "random" numbers every time based off a given seed value."

You might also try changing the seed value. :)
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
10-16-2008 22:00
This should provide you with a good fast SRNG that won't loop anytime soon and will be impossible to determine the underlying inputs.

CODE

integer srng_int = you_decide;
string srng_str = you_decide;
string srng_secret = you_decide;

integer SRNG()
{
integer i = srng_int & 31;
integer j = (integer)("0x"+llGetSubString(srng_str = llMD5String(srng_str + srng_secret, srng_int), i - 7, i);
srng_int = srng_int ^ j;
return j;
}


The alg is designed so that it can only loop if the inputs of the MD5 function have been seen before or if the MD5 output collides and the i values match. Further crypt analysis needs to be done to ensure the the floating shift does not expose some number of predictable bits in the result.

srng_secret greatly reduces the probability of the MD5 inputs being guessed. It's value does not need to change.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
10-19-2008 00:23
From: Faust Vollmar
Hewee Zetkin kindly provided me with this when I asked. :D

integer SeededRand(string Seed)
{
string Hash = llMD5String(Seed);
integer I1 = (integer)("0x"+llGetSubString(Hash, 0, 7));
integer I2 = (integer)("0x"+llGetSubString(Hash, 8, 15));
integer I3 = (integer)("0x"+llGetSubString(Hash, 16, 23));
integer I4 = (integer)("0x"+llGetSubString(Hash, 24, 31));
return I1^I2^I3^I4;
}

Typed from memory so it may need syntax fixes.

EDIT: Of course, you can stick any other string manipulation you'd like on the Seed if you want to make the generator a little more in depth... As for making it within a specific range, I wouldn't know where to start. XD

EDIT2: It uses MD5String because I needed to generate based on an AV UUID when I asked for a Seedable PsuedoRandom. The same Concept of making integers from MD5String Bits also works for generating strings, though its better to XOR 2 Seed Strings for that.

Note that that logic was intented for the hashing of an input string. You'll need something a little more like Strife's algorithm to generate a sequence of seeded pseudo-random values, though I suppose if you passed a value calculated from the above function's output back to the function it could serve.
Haravikk Mistral
Registered User
Join date: 8 Oct 2005
Posts: 2,482
10-19-2008 03:53
I created a Mersenne Twister implementation for LSL which gives good random number distribution, only the top 3 functions are required for it to work, you then simply pick which of the helper functions you want/need and copy/paste them into your script as well.

http://wiki.secondlife.com/wiki/Pseudo_Random_Number_Generator
_____________________
Computer (Mac Pro):
2 x Quad Core 3.2ghz Xeon
10gb DDR2 800mhz FB-DIMMS
4 x 750gb, 32mb cache hard-drives (RAID-0/striped)
NVidia GeForce 8800GT (512mb)