Dice Stats

Contains all the documentation for the files under /src/dice_stats.

Magic Mixins

Magic methods for Dice class.

These add different types of magic methods to the dice class. Given the amount of magic methods I found it to be clearer to split out the definitions. This means numeric comparisons are located in the numeric.py file.

Magic Mixins:

Internal Types

Generic types used across the project.

Dice

High level dice helper functions.

class dice_stats.dice.Dice(chances=None, total_chance=Fraction(1, 1))

Dice class.

apply_dice(chances, default=None)

Change chances to provided dice.

This changes the values of the host dice, to the values of the provided dice. It does so by changing the provided dice to the correct chance.

Parameters
Return type

Dice

Returns

A new Dice that acts as if these multiple dice rolls happen in one throw.

Say we’re playing a game where you roll a die to attack people. You normally do 1-6 damage, however sometimes there’s a chance to do 1-4 - say you had bad footing. To determine what dice you use use throw a d3 before using either the d6 or the d4. On a 1 you use the d4, otherwise it’s the d6. To find the chances is easy with this function.

print(
    Dice.from_dice(3)
        .apply_dice(
            {(1,): Dice.from_dice(4)},
            Dice.from_dice(6),
        )
)
Dice[1](
  1: 19.4%  7/36
  2: 19.4%  7/36
  3: 19.4%  7/36
  4: 19.4%  7/36
  5: 11.1%  1/9
  6: 11.1%  1/9
)
apply_functions(chances, default=None, apply=<function Dice.<lambda>>)

Apply a callback to the provided chances.

This is the more complex version dice_stats.Dice.apply_dice(). With this version you can pass a callback that mutates the segment of the dice provided.

This callback is given a segment of the host dice, this means that the callback has all the information that it should need, as this dice would have all the Chances Value and Chances Chance it needs. The Total Chance will also be the correct for that segment of the dice results.

The callback then has to return a dice object that that segment gets mutated to. For example if you’re using this to reroll dice, then one function would return the segment provided, where the other would return the host dice of sorts.

Parameters
  • chances (Dict[Iterable[Union[Real, Integral]], Callable[[Dice], Dice]]) – The mapping that holds the outputs.

  • default (Optional[Callable[[Dice], Dice]]) – The function to apply if there are missing values.

  • apply (Callable[[Dice], Dice]) – A function to mutate each dice segment before they reach the chances callback.

Return type

Dice

Returns

New dice that’s been fully mutated by the callbacks.

To expand on the previous example, if we have a d6 and we’re allowed to reroll 1s once, then we could use the following code.

Note

This functionality is already builtin to the dice_stats.Dice class. You can instead use the dice_stats.Dice.reroll() method to do this.

print(
    Dice.from_dice(6)
        .apply_functions(
            {(1,): lambda d: Dice.from_dice(6) @ d},
            lambda d: d,
        )
)
Dice[1](
  1:  2.8%  1/36
  2: 19.4%  7/36
  3: 19.4%  7/36
  4: 19.4%  7/36
  5: 19.4%  7/36
  6: 19.4%  7/36
)
as_total_chance(total_chance)

Change Total Chance.

This adjusts each Chances Chance by the scale of the old and new Total Chance.

Parameters

total_chance (Union[Fraction, Dice, int]) – Desired Total Chance.

Return type

Dice

Returns

A new dice with the specified Total Chance.

For example, say we have a d3 which has a 100% Total Chance, however it should be a 200% Total Chance. Then we use this function to change it. It will also change all the Chances Chance from 1/3 to 2/3.

d3 = Dice.from_dice(3)
print(d3)
print(d3.as_total_chance(Fraction(2, 1)))
Dice[1](
  1: 33.3%  1/3
  2: 33.3%  1/3
  3: 33.3%  1/3
)
Dice[2](
  1: 66.7%  2/3
  2: 66.7%  2/3
  3: 66.7%  2/3
)
classmethod from_dice(sides, total_chance=Fraction(1, 1))

Make a dice from a number of sides.

This is a very useful convenience function, this is the most common way to build dice as it builds dice with an equal chance to land on all faces.

Parameters
Return type

Dice

Returns

A fair n-sided dice.

Below is an example of some of the smaller dice you can create with this.

print(Dice.from_dice(1))
print(Dice.from_dice(2))
print(Dice.from_dice(3))
print(Dice.from_dice(6))
Dice[1](
  1: 100.0%  1/1
)
Dice[1](
  1: 50.0%  1/2
  2: 50.0%  1/2
)
Dice[1](
  1: 33.3%  1/3
  2: 33.3%  1/3
  3: 33.3%  1/3
)
Dice[1](
  1: 16.7%  1/6
  2: 16.7%  1/6
  3: 16.7%  1/6
  4: 16.7%  1/6
  5: 16.7%  1/6
  6: 16.7%  1/6
)
classmethod from_external(chances, total_chance)

Create a dice from the Chances form.

This doesn’t use the Internal Chances form, and so eases use when not using that form.

Parameters
Return type

Dice

Returns

A dice with the specified chances.

classmethod from_prev_total_chance(chances, chance, prev_chance)

Change a dice from one Total Chance to another.

This is a deprecated function, this is likely better expressed by using dice_stats.Dice.from_external() and dice_stats.Dice.as_total_chance().

Parameters
Return type

Dice

Returns

A dice with new chances.

max(other=None)

Get the maximum result from two dice.

Say you’re playing a game which allows you to roll two dice and take the highest as your result. To do this you would need a cartesian max, which is what this function performs.

Parameters

other (Optional[Dice]) – Another dice to get the maximum value from. If unset then it uses itself.

Return type

Dice

Returns

A new dice of the chances of getting the maximum.

Say you have can roll two d6s and use the maximum, that would simply be:

print(Dice.from_dice(6).max())
Dice[1](
  1:  2.8%  1/36
  2:  8.3%  1/12
  3: 13.9%  5/36
  4: 19.4%  7/36
  5: 25.0%  1/4
  6: 30.6% 11/36
)
partition(values)

Remove multiple Chances Value from the dice.

Split the dice into two. This removes the values provided in the values argument out of the dice, and then returns the rest of the values in a separate dice.

Parameters

values (Iterable[Union[Real, Integral]]) – Selection of Chances Value to remove from the dice.

Return type

Tuple[Dice, Dice]

Returns

Returns two different dice, one with the wanted values, the other with the unwanted values.

For the most part this is used internally when using one of the apply functions or the reroll function. However its existence helps makes these functions possible and easy to implement.

To showcase this we’ll define a basic reroll function using this function.

Note

This functionality is already builtin to the dice_stats.Dice class. You can instead use the dice_stats.Dice.reroll() method to do this.

def reroll(dice, values):
    rerolled, kept = dice.partition(values)
    return Dice.sum([
        kept,
        dice.as_total_chance(rerolled.total_chance),
    ])

print(reroll(Dice.from_dice(6), (1,)))
Dice[1](
  1:  2.8%  1/36
  2: 19.4%  7/36
  3: 19.4%  7/36
  4: 19.4%  7/36
  5: 19.4%  7/36
  6: 19.4%  7/36
)
reroll(values)

Reroll specified values.

Since this is a common operation on dice this is some sugar for it. It should be noted that whilst this handles the simple instances of rerolling, there are some more complex situations that can only be handled through custom functions or the dice_stats.Dice.apply_functions() method.

For the simple situation of being able to reroll a range of values once then this is all you need.

Parameters

values (Iterable[Union[Real, Integral]]) – Collection of Chances Value.

Return type

Dice

Returns

A new dice factoring in rerolls.

print(Dice.from_dice(6).reroll((1,)))
Dice[1](
  1:  2.8%  1/36
  2: 19.4%  7/36
  3: 19.4%  7/36
  4: 19.4%  7/36
  5: 19.4%  7/36
  6: 19.4%  7/36
)
classmethod sum(dice)

Add multiple dice together, increasing their Total Chance.

This is mostly used when you have multiple partial dice that you need to add together only adding the chances together. For example lets say we have a 2/3 chance for our outcome to be a d6 or a 1/3 chance that the outcome is a d4 then the total outcome would be the result of those two dice added together, but not in the common form - d6 + d4.

print(Dice.sum([
    Dice.from_dice(6, total_chance=Fraction(2, 3)),
    Dice.from_dice(4, total_chance=Fraction(1, 3)),
]))

Which correctly results in:

Dice[1](
  1: 19.4%  7/36
  2: 19.4%  7/36
  3: 19.4%  7/36
  4: 19.4%  7/36
  5: 11.1%  1/9
  6: 11.1%  1/9
)

As we can see, the result totals to 100%, and there is a significantly higher chance to get a 1-4 then 5 or 6. This shows pretty clearly that the outcome is only adding the chances together.

For the most part you can normally use a different function than this one if you need to get this sort of output. Lets say the game we’re playing says to roll a d3 to decide between either the d4 or the d6 to be rolled to get the result. On a 1 you roll the d4 otherwise it’s the d6, which could be expressed as:

print(
    Dice.from_dice(3)
        .apply_dice(
            {(1,): Dice.from_dice(4)},
            Dice.from_dice(6)
        )
)
Dice[1](
  1: 19.4%  7/36
  2: 19.4%  7/36
  3: 19.4%  7/36
  4: 19.4%  7/36
  5: 11.1%  1/9
  6: 11.1%  1/9
)
Return type

Dice

Display

Some functions to make displaying dice data easier.

dice_stats.display.plot_wireframes(results_, only_positive=False)

Build a graph from multiple dice results.

Return type

Iterator[Tuple[array, …]]

Range

Build a range using math notation.

class dice_stats.range.Range(start, stop, step)

Range object allowing floating point and infinite ranges.

classmethod from_range(range_)

Build a range from mathematical notation.

Return type

Range