Skip to content

Instantly share code, notes, and snippets.

@canemacchina
Created September 10, 2018 02:03
Show Gist options
  • Save canemacchina/7abef3d9555a638106402510490847e9 to your computer and use it in GitHub Desktop.
Save canemacchina/7abef3d9555a638106402510490847e9 to your computer and use it in GitHub Desktop.
Dice is a tiny JS object that makes it possible to roll RPG dice using the window.crypto library.
/*
* Dice is a tiny JS object that makes it possible to roll
* cryptographically safe RPG style dice.
*
* Examples:
* Dice.d6();
* Dice.d8.times(3);
* Dice.roll("2d6 + 2d10 + 2");
*
* Make a coin toss:
* Dice.d2 = make_die(2);
* Dice.d2();
*/
function make_die(sides) {
var die = function(){
var r = 1;
// Can use a cryptographically safe random generator?
if(typeof window.crypto == 'object'){
var request_bytes = Math.ceil(Math.log2(sides) / 8);
if(request_bytes){ // No randomness required
var maxNum = Math.pow(256, request_bytes);
var ar = new Uint8Array(request_bytes);
while(true){
window.crypto.getRandomValues(ar);
var val = 0;
for(var i = 0;i < request_bytes;i++){
val = (val << 8) + ar[i];
}
if(val + sides - (val % sides) < maxNum){
r = 1 + (val % sides);
break;
}
}
}
}else{ // Not as random, but good enough
r = (Math.random() * sides | 0) + 1;
}
return r;
};
die.times = function(count){
var rolls = [];
for(var i = 0 ; i < count ; i++){
rolls.push(this());
}
return rolls;
};
return die;
}
var Dice = {
d4: make_die(4),
d6: make_die(6),
d8: make_die(8),
d10: make_die(10),
d12: make_die(12),
d20: make_die(20),
d100: make_die(100),
roll: function(expression){
var self = this, rolls = [];
expression.toLowerCase().replace(/(\d+)(d\d+)?/g, function(_, count, die){
if(die){
rolls = rolls.concat(self[die].times(+count));
}else{
rolls.push(+count);
}
});
return rolls.reduce(function(sum, roll){
return sum + roll;
});
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment