Role::Random::PerInstance - A role for dealing with random values, per instance


    package Some::Class;
    use Moose;
    with 'Role::Random::PerInstance';

    # later , with an instance of Some::Class
    if ( $self->random < .65 ) {

    # same thing ...

    if ( $self->attempt(.65) ) {


This role allows you to use random numbers, maintaining separate random numbers for each instance.



    if ($self->attempt(0.6)) {
        # 60% chance of success

Perform a random test which has a chance of success based on the $chance value, where $chance is a value between 0 and 1. A $chance value of 0 will always return false, and a $chance value of 1 or more will always return true.

random($min, $max, $step)

    my $gain = $self->random(0.1, 0.5, 0.1 );
    # $gain will contain one of 0.1, 0.2, 0.3, 0.4 or 0.5

    my $even = $self->random(100, 200, 2 );

Generate a random number from $min to $max inclusive, where the resulting random number increments by a value of $step starting from $min. If step is not supplied, this method behaves like rand, but from $min to $max.

By default (if no arguments are passed), this method will work the same as the built in 'rand' function, which is to return a value from 0 to 1, but not including 1. The number includes seven digits after the decimal point (e.g., 0.5273486).


    package Some::Package {
        use Moose;
        with 'Role::Random::PerInstance';
    my $object = Some::Package->new(
        random_seed => $integer_seed

If an object consuming this role passes in an integer random seed to the constructor, all "random" methods in this role will use the deterministic_rand() method instead of the built in rand() function.

In other words, if random_seed is not supplied to the constructor, the random numbers will not be repeatable.


    my $rand = $object->deterministic_rand;
    $rand = $object->deterministic_rand;
    $rand = $object->deterministic_rand;
    $rand = $object->deterministic_rand;

This method returns pseudo-random numbers from 0 to 1, with up to seven digits past the decimal point (e.g., "0.1417026"), but is deterministic. This is not cryptographically secure, but the numbers are evenly distributed.

$self->random_seed must be set in the object constructor to ensure deterministic randomness.

The algorithm is the Linear Congruential Generator.

We've tried merely calling srand(seed), but it turned out to not be as deterministic as promised and also doesn't allow us fine-grained "per instance" control.

random_int($min, $max)

    my @items = qw(one two three four five);
    my $item = $items[ $self->random_int(0, $#items) ];

Generate a random integer from $min to $max inclusive.


    my %weights = (
        foo  => 1,     # 5% chance of being chosen
        bar  => 17,    # 85% chance of being chosen
        baz  => 2,     # 10% chance of being chosen
        quux => 0,     # will never be chosen
    my $choice = $self->weighted_pick( \%weights );    # will usually return 'bar'

This function accepts a hash reference whose keys are the values you wish to choose from and whose values are the relative weights assigned to those values. A single value from the hash will be returned. The higher its "key" value, the more likely it is to be returned. Note that if you wanted an even chance of all values, ensure that all keys have the same value (but at that point, a straight rand() would be more efficient.


The narrative sci-fi game, Tau Station, needed a way to have repeatable random numbers, with different instances of objects creating their own series of random numbers. Perl's rand function is global, and seeding it with srand turns out to not be as deterministic as we had hoped. Math::Random is also global. Hence, our own module.

Not only does this give you repeatable (via random_seed) random numbers, it gives you non-repeatable random numbers (just don't provide a seed) and many useful random utilities.

We implemented a Linear Congruential Generator and you get seven digits after the decimal point, so each number has a 1 in ten million chance of occuring. That is perfect for our needs. It may not be perfect for yours.

Also, while the Linear Congruential Generator is fairly efficient and random, it's not cryptographically secure.


Note that if $Config{use64bitint} (from the Config module) is false, you can still get deterministic "random" numbers, but they may be slightly different than those generated by Perls compiled to use 64 bit integers. Otherwise, the output from this module is portable. See the t/random.t test for examples.


Curtis "Ovid" Poe, <curtis.poe at>


Please report any bugs or feature requests via the Web interface at I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


You can find documentation for this module with the perldoc command.

    perldoc Role::Random::PerInstance

You can also look for information at:


Role::Random::PerInstance was developed for the narrative sci-fi game Tau Station. We like it because the syntax is simple, clear, and intuitive (to us). However, there are a few alternatives on the CPAN that you might find useful:


This code was written to help reduce the complexity of the narrative sci-fi adventure, Tau Station. As of this writing, it's around 1/3 of a million lines of code (counting front-end, back-end, tests, etc.), and anything to reduce that complexity is a huge win.


This software is Copyright (c) 2019 by Curtis "Ovid" Poe.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)