Here it is, in a nutshell, plus methods I use to generate dice rolls. Look how tiny it is!
Note that this is a slightly modified version of the original. For one, it specifically takes the first
64 bits of an MD5 hashcode to seed the generator. Secondly, it uses signed integers -- but since
the algorithm operates on 32 bit numbers, this should be ok if your system uses 64 bit longs.
Note that this is a slightly modified version of the original. For one, it specifically takes the first
64 bits of an MD5 hashcode to seed the generator. Secondly, it uses signed integers -- but since
the algorithm operates on 32 bit numbers, this should be ok if your system uses 64 bit longs.
Code:
use Digest::MD5 qw/md5_hex/;
#################################################################
#
# As seen on http://www.burtleburtle.net/bob/rand/smallprng.html
#
#################################################################
use integer;
my ($a, $b, $c, $d);
sub rot { ($_[0] << $_[1]) | ($_[0] >> (32-$_[1])) }
sub randint
{
my $e = ( $a - rot( $b, 27 ) );
$a = $b ^ rot( $c, 17 );
$b = ( $c + $d );
$c = ( $d + $e );
$d = ( $e + $a );
return $d;
}
#################################################################
#
# t5srand(): Seeds the random number generator with a string.
#
# For world-building, I suggest the following format:
#
# <galaxy>/<arm>/<sector>/<hex>
#
# Examples:
#
# t5srand( "Faraway/1010" );
# => hex 1010 in the Faraway sector
#
# t5srand( "Orion/X411/1910" );
# => hex 1910 in sector X411 of the Orion arm
#
# t5srand( "MW1/012F/B9900/3201" );
# => hex 3210, sector B9900, arm 012F, galaxy MW1
#
#################################################################
sub t5srand
{
my $UID = shift;
my $hash = '0x' . substr( md5_hex( $UID ), 0, 16 ); # 64 bits
$a = 0xf1ea5eed;
$b = $c = $d = eval $hash;
randint() for 0..19;
}
#################################################################
#
# Dice-rolling-specific methods.
# Each of these methods use only *one* call to the RN Generator.
#
#################################################################
sub rand1d { return 1 + ((abs randint()) % 6) }
sub rand2d { my $num = abs randint(); return 2 + ($num % 6) + (($num/6) % 6); }
sub flux { return rand2d() - 7 }
sub rand1d10 { return ((abs randint()) % 10) } # 0 thru 9
sub rand1d9 { return ((abs randint()) % 9)+1 } # 1 thru 9
sub rand3d
{
my $num = abs randint();
return 3 + ($num % 6) + (($num/6) % 6) + (($num/36) % 6);
}
#################################################################
#
# Extracts 8 d6 rolls, returned in a list, from one random number
#
#################################################################
sub rand8
{
my $num = abs randint();
return 1+($num % 6),
1+(($num/6) % 6),
1+(($num/36) % 6),
1+(($num/216) % 6),
1+(($num/1_296) % 6),
1+(($num/7_776) % 6),
1+(($num/46_656) % 6),
1+(($num/279_936) % 6);
}
Last edited: