Handy LSL Functions and Snippets

Table of Contents

This is just a page of handy scripts or snippets for LSL:

fxyLCG - Seedable RNG

The following is a seedable random number generator that uses a LCG algorithm. This is mostly useful if you need something that generates numbers differently than llFrand() with similar performance.

Do not use this for cryptography!

// Generate a loosely random seedable number using a 
// Linear Congruential Generator algorithm
// Useful if you need numbers generated differently
// than llFrand().
integer lcgCurrent;
integer fxyLCG(integer seed)
{
    if (lcgCurrent == 0)
        return lcgCurrent = ((0x7A31C7 * (seed << 16) + (integer)llGetTime()) & 0x7FFFFFFF) >> 16;
    else
        return lcgCurrent = ((0x7A31C7 * (lcgCurrent << 16) + (integer)llGetTime()) & 0x7FFFFFFF) >> 16;
}

fxyLCG Performance

Performance of fxyLCG with a predetermined seed is on par with that of LLFrand(), by using llGetUnixTime() for added entropy the execution time is roughly on par with another common lsl seedable PRNG's base form.

fxyLCG Performance Test:
...
Generated 10 llFrand() Randoms in: 0.021487
...
Generated 10 fxyLCG Randoms seeded with 1234567890 in: 0.021986
...
Generated 10 fxyLCG Randoms seeded with llGetUnixTime() in: 0.044595
...
Generated 10 Kyrah Abattoir MDF Randoms seeded with 1234567890 in: 0.044434
...
Generated 10 Kyrah Abattoir MDF Randoms seeded with llGetUnixTime() in: 0.065022

full raw test script output is below

Test Script

// Generate a loosely random seedable number using a 
// Linear Congruential Generator algorithm
// Useful if you need numbers generated differently
// than llFrand().
integer lcgCurrent;
integer fxyLCG(integer seed)
{
    if (lcgCurrent == 0)
        return lcgCurrent = ((0x7A31C7 * (seed << 16) + (integer)llGetTime()) & 0x7FFFFFFF) >> 16;
    else
        return lcgCurrent = ((0x7A31C7 * (lcgCurrent << 16) + (integer)llGetTime()) & 0x7FFFFFFF) >> 16;
}

// Kyrah Abattoir MDF PRNG 
string kamdf_seed = "";//Any String you want as your initial seed.
 
//this version will pull a random int from 0 to max int
integer KAMDF_NextInt()
{
	kamdf_seed = llMD5String(kamdf_seed,0);
	integer value = (integer)("0x"+llGetSubString(kamdf_seed,0,6));
	return value;
}

default
{
    state_entry()
    {        
        llSay(0, "\n\n\n\n\n"); // put a break in the log
        llSleep(2.);

        // Perf test llFrand()
        integer i;
        llSay(0, "Numbers generated using llFrand():");
        llResetTime();
        do
            llSay(0, (string)((integer)llFrand(0x7A31C7)));            
        while (++i < 10);
        llSay(0, "Generated 10 llFrand() Randoms in: " + (string)llGetTime());
        llSleep(2.); //Avoid chat spam throttles
        
        // Perf test fxyLCG without llGetUnixTime();
        i = 0;
        llResetTime();
        llSay(0, "Numbers generated using fxyLCG with 1234567890 as seed:");
        integer tmpSeed = 1234567890;
        do
            llSay(0, (string)fxyLCG(tmpSeed));
        while (++i < 10);
        llSay(0, "Generated 10 fxyLCG Randoms seeded with 1234567890 in: " + (string)llGetTime());
        llSleep(2.); //Avoid chat spam throttles

        // Perf test fxyLCG with llGetUnixTime();
        i = 0;
        llResetTime();
        llSay(0, "Numbers generated using fxyLCG with llGetUnixTime() as seed:");
        tmpSeed = llGetUnixTime();
        do
            llSay(0, (string)fxyLCG(tmpSeed));
        while (++i < 10);
        llSay(0, "Generated 10 fxyLCG Randoms seeded with llGetUnixTime() in: " + (string)llGetTime());
        llSleep(2.); //Avoid chat spam throttles

        // Perf test Kyrah Abattoir MDF PRNG without llGetUnixTime();
        i = 0;
        llResetTime();
        llSay(0, "Numbers generated using Kyrah Abattoir MDF PRNG with with 1234567890 as seed:");
        kamdf_seed = "1234567890";
        do
            llSay(0, (string)KAMDF_NextInt());
        while (++i < 10);
        llSay(0, "Generated 10 Kyrah Abattoir MDF Randoms seeded with 1234567890 in: " + (string)llGetTime());
        llSleep(2.); //Avoid chat spam throttles

        // Perf test Kyrah Abattoir MDF PRNG with llGetUnixTime();
        i = 0;
        llResetTime();
        llSay(0, "Numbers generated using Kyrah Abattoir MDF PRNG with with llGetUnixTime() as seed:");
        kamdf_seed = (string)llGetUnixTime();
        do
            llSay(0, (string)KAMDF_NextInt());
        while (++i < 10);
        llSay(0, "Generated 10 Kyrah Abattoir MDF Randoms seeded with llGetUnixTime() in: " + (string)llGetTime());
        llSleep(2.); //Avoid chat spam throttles

    }
}

Raw Test Script Output

This test was run on a empty region.

fxyLCG Performance Test:

Numbers generated using llFrand():
5427187
7436121
7519734
2176519
1833335
3435436
5605460
6086016
5157341
933955
Generated 10 llFrand() Randoms in: 0.021487

Numbers generated using fxyLCG with 1234567890 as seed:
25406
818
3550
17810
1662
10738
27934
4178
25022
22706
Generated 10 fxyLCG Randoms seeded with 1234567890 in: 0.021986

Numbers generated using fxyLCG with llGetUnixTime() as seed:
1118
25362
29950
3954
21406
15826
16446
20018
23262
8338
Generated 10 fxyLCG Randoms seeded with llGetUnixTime() in: 0.044595

Numbers generated using Kyrah Abattoir MDF PRNG with with 1234567890 as seed:
22283616
93764486
136378371
126468879
107330489
110601446
216168010
105188454
39219666
217439020
Generated 10 Kyrah Abattoir MDF Randoms seeded with 1234567890 in: 0.044434

Numbers generated using Kyrah Abattoir MDF PRNG with with llGetUnixTime() as seed:
135446205
44552377
170278642
206944082
113205871
79825045
200267315
179795429
80214094
129770495
Generated 10 Kyrah Abattoir MDF Randoms seeded with llGetUnixTime() in: 0.065022