Sign in to follow this  
Ravnock

Atomic, persistent, pseudorandom generator in GameSparks

Recommended Posts

This will allow you to share a pseudo random number generator between several users. To use it during  a Real time match you just have to send the request from your RT event.

It needs a runtime collection to store the seed related to the current session, it's called "MatchSeed", that's completely managed from the following module, MODULE_ATOMIC_RANDOM. The module has functions to retrieve, update and remove the seeds from the collection. Just create a Cloud Code's Module and copy the following code.

Edit: I have included the option of peeking the next random numbers: One interesting thing about pseudo random numbers is, given a seed, the sequence of random numbers is predictable, so you can know what are the next numbers in the sequence. I completely forgot to add the posibility of peeking the next numbers in my "Atomic, Peristent and Pseudo Random Number Generator". I've modified the event, adding one parameter "numPeeks". Now in the scriptData you have a key "numPeeks" with the numPeeks returned (is limited to 10 for security reasons) and one key per num peeked: "peek1", "peek2", and so on. 

/////////////////////////////////////////////////////////
// File MODULE_ATOMIC_RANDOM
//////////////////////////////////////////////////////////
function GetMatchSeed(sessionId)
{
    var matchSeedCollection = Spark.runtimeCollection("MatchSeed");
    var result = undefined;
    var matchSeed = matchSeedCollection.findOne({"sessionId":sessionId});
  
    if (matchSeed != null && matchSeed != undefined)
    {
        result = matchSeed["seed"];
    }
  
    return result;
}

function SetMatchSeed(sessionId, seed)
{
    var matchSeedCollection = Spark.runtimeCollection("MatchSeed");
    var query = {
        "sessionId": sessionId
    };

    var newObject = {
        "sessionId": sessionId,
        "seed": seed
    };

    var success = matchSeedCollection.update(query, newObject, true, false ); //upsert: true, multi: false
    return success;
}

function RemoveMatchSeed(sessionId)
{
    var matchSeedCollection = Spark.runtimeCollection("MatchSeed");
    var query = {
        "sessionId": sessionId
    };
  
    var success = matchSeedCollection.remove(query);
    return success;
}

And here you have the event's code you need to get your Atomic,Persistent, Pseudo Random-Generator:

require("MODULE_ATOMIC_RANDOM");

//Based on: http://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript

/* We pass an object because we want the changes on the seed to be an output parameter
   That way we can store the seed in a runtime collection and use it again when needed, 
   keeping the sequence of random numbers from one event execution to another event execution.*/
var PseudoRandomSeed = function(obj) {
    return function() { //if peek true we will only look the value, but  seed won't be modified
        
        var newSeed = Math.sin(obj.seed) * 10000;
        var result = newSeed - Math.floor(newSeed);
        
        obj.seed = newSeed;
        
        return result;
    };
};

var sessionId   = Spark.getData().sessionId;
var numPeeks    = Spark.getData().numPeeks;

//Mutex: We don't want other user to get a random while this is running
Spark.lockKey("AtomicRandom", 100);

var seedFromDB = GetMatchSeed(sessionId);
var lastSeed = undefined;
    
//If there is no seed get the session ID as the prime seed
if (seedFromDB == null || seedFromDB == undefined)
{
    lastSeed = parseInt(sessionId, 16); //I'm supossing the sessionID is an hexadecimal number
}
else //Otherwise, we used the stored seed
{
    lastSeed = seedFromDB;
}
   
var myObj = {
    seed: lastSeed
};
    
var PseudoRandom = PseudoRandomSeed(myObj);

//Generate randomNumber and store it in the scriptData
var randomNumber        = PseudoRandom();
var setMatchSeedSuccess = SetMatchSeed(sessionId, myObj.seed);

Spark.setScriptData("randomNumber", randomNumber);

//Generate peeks for the next randoms
if (numPeeks != null && numPeeks != undefined)
{
    if (numPeeks > 10) //security check: Max peeks allowed is 10
        numPeeks = 10;
    
    Spark.setScriptData("numPeeks", numPeeks);
    
    for (i = 0; i < numPeeks; ++i)
    { 
        Spark.setScriptData("peek" + i , PseudoRandom());
    }
}

Spark.unlockKey("AtomicRandom"); 

I hope you find it useful or interesting. Check my blog for more stuff:

http://davidorejuela.blogspot.com.es

Edited by Ravnock

Share this post


Link to post
Share on other sites
Sign in to follow this