Don't click here unless you want to be banned.

LSL Wiki : LibraryPseudoRandomGenerator

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are ec2-54-237-32-10.compute-1.amazonaws.com

Pseudo-Random Number Generator


Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.

One of the big problems in LSL is communication security. It is next to impossible to keep communcations secure if they are on a fixed channel. For this reason, I have writen this function that can be used to generate pseudo-random numbers. They aren't really random, but are difficult to predict without the original algorithm. Using this function to secure your script systems does not compromise them because the range of inputs is so large that it would be impossible to calculate all the solutions in a timely fashion.

The idea is to use a slice of the MD5 hash of a string and convert that to an integer. MD5 does a nice job of shaking up the bits. If this is used for channel hopping (like in the example) it would be very difficult to gather enough information to crunch the numbers to start predicting the channels.

Function:
integer pseudo_random(string text, integer nonce, integer start, integer end)
{//(c)(cc-by) Strife Onizuka, http://creativecommons.org/licenses/by/3.0/
    return (integer)("0x"+llGetSubString(llMD5String(text, nonce), start, end));
}

integer pseudo_random_float_a(string text, integer nonce, integer start, integer end, float max)
{//(c)(cc-by) Strife Onizuka, http://creativecommons.org/licenses/by/3.0/
    if(text = llGetSubString(llMD5String(text, nonce), start, end))
        max *= (float)("0x"+text) / 
            (float)("0x"+llGetSubString("ffffffffffffffffffffffffffffffff", start, end));
    return max * !(text == "");
}//0 <= result <= max

integer pseudo_random_float_b(string text, integer nonce, integer start, integer end, float max)
{//(c)(cc-by) Strife Onizuka, http://creativecommons.org/licenses/by/3.0/
    return max * (float)("0x"+text+"p-"+(string)(llStringLength(text = llGetSubString(llMD5String(text, nonce), start, end))<<2));
}//0 <= result < max

integer pseudo_random_float_c(string text, integer nonce, integer start, integer end, float max)
{//(c)(cc-by) Strife Onizuka, http://creativecommons.org/licenses/by/3.0/
    return iuf((integer)("0x"+llGetSubString(llMD5String(text, nonce), start, end)) & 0x3FFFFFFF) * max;
}//0 <= result < max

float iuf(integer a)
{//union integer to float
    return ((float)("0x1p"+(string)((a | !a) - 150))) * ((!!(a = (0xff & (a >> 23))) << 23) | ((a & 0x7fffff))) * (1 | (a >> 31));
}//will crash if the raw exponent == 0xff; reason for crash deviates from float standard; though a crash is warented.

Example Listen:
integer pseudo_random(string text, integer nonce, integer start, integer end)
{//(c)(cc-by) Strife Onizuka, http://creativecommons.org/licenses/by/3.0/
    return (integer)("0x"+llGetSubString(llMD5String(text, nonce), start, end));
}

list handles;
integer last;
//Used in the generation of the hash, best to make this at least 64 characters.
string feed = "How much wood would a wood chuck chuck if a wood chuck could chuck wood?";

default
{
    state_entry()
    {
        integer now = 30 * ((integer)llGetGMTclock() / 30);
        integer count = 0;
        while(count < 2)//number of channels to hold open at any one time.
        {//if you have problems with missed message do to a lagged sim increase the number
            handles += llListen(pseudo_random(feed, (last = now), 0, 7), "", "", "");
            now += 30;
            ++count
        }
        llSetTimerEvent(10); //this is so if there is a nasty time dilation
    }
    state_exit()
    {
        handles = [];
    }
    timer()
    {
        integer next = 30 * ((integer)llGetGMTclock() / 30) + 30; 
        if(next > last)
        {
            last = next;
            llListenRemove(llList2Integer(handles, 0));
            handles = llList2List(handles, 1, -1) +
                [llListen(next = pseudo_random(feed, next, 0, 7), "", "", "")];
//            llOwnerSay(llList2CSV([last, next]));
        }
    }
    listen(integer a, string b, key c, string d)
    {
        b = llGetTimestamp();
        float e = (float)llGetSubString(b,17,-1) - (float)llGetSubString(d,17,-1);
        if(e < 0.0)
            e+=60.0;
        llOwnerSay((string)e);
    }
}

Example speak:
integer pseudo_random(string text, integer nonce, integer start, integer end)
{//(c)(cc-by) Strife Onizuka, http://creativecommons.org/licenses/by/3.0/
    return (integer)("0x"+llGetSubString(llMD5String(text, nonce), start, end));
}

string feed = "How much wood would a wood chuck chuck if a wood chuck could chuck wood?";

default
{
    state_entry()
    {
    }

    touch_start(integer next)
    {
        string time = llGetTimestamp();
        next = pseudo_random(feed, 30 * ((integer)llGetGMTclock() / 30), 0, 7);
        llSay(next, time);
//        llOwnerSay((string)next);
    }
}


Functions of interest:
integer Key2Integer(string input, integer start, integer end)
{
    return (integer)("0x"+llGetSubString(
            (string)llParseString2List(input,["-"],[]),
        start, end));
}

integer timestamp_to_unixtime(string timestamp) {
    integer year    = (integer) llGetSubString(timestamp,  0,  3);
    integer month   = (integer) llGetSubString(timestamp,  5,  6);
    
    return
    (
        (year - 1970) * 365
        + (year - 1969) / 4 - (year - 2001) / 100 + (year - 2001) / 400
        + llList2Integer( 
            [ 0, -1,  30, 58, 89, 119, 150, 180,  211, 242, 272, 303, 333 ], 
            month )
        + (integer) llGetSubString(timestamp,  8,  9)
        + (month>2) * (!(year % 4) - !(year % 100) + !(year % 400))
    )
    * 86400
    + (integer) llGetSubString(timestamp, 11, 12) * 3600
    + (integer) llGetSubString(timestamp, 14, 15) * 60
    + (integer) llGetSubString(timestamp, 17, 18);
}
There are 5 comments on this page. [Display comments/form]