API Reference

ndice - A dice rolling library for games.

class ndice.Dice(*args: Any, **kwargs: Any)

A single term in a dice expression like 2d6 or -2.

Instances of Dice are immutable. Dice instances are also interned, meaning each unique instance is cached and reused instead of creating duplicates.

classmethod die(sides: int) Dice

Return a Dice instance that represents a single die.

Parameters:

sides (int) – The number of sides on the die. Must be >= 0.

>>> Dice.die(12)
Dice(1, 12)

d() is an alias for Dice.die().

>>> d(8)
Dice(1, 8)
classmethod mod(value: int, op: Op = Op.PLUS) Dice

Return a Dice instance that represents a modifier.

Parameters:
  • value (int) – The magnitude of the modifier.

  • op (Op) – The operation of the modifier.

Mods are represented as Dice instances where number is the constant value of the mod and sides is 1.

>>> Dice.mod(2)
Dice(2, 1)
>>> Dice.mod(2, Op.MINUS)
Dice(2, 1, Op.MINUS)

If value is negative and op is Op.PLUS or Op.MINUS, then op and the sign of value are inverted. If op is Op.TIMES then value must be non-negative.

>>> Dice.mod(-2)
Dice(2, 1, Op.MINUS)
>>> Dice.mod(-3, Op.MINUS)
Dice(3, 1)
>>> Dice.mod(-4, Op.PLUS)
Dice(4, 1, Op.MINUS)

mod() is an alias for Dice.mod().

>>> mod(10, Op.TIMES)
Dice(10, 1, Op.TIMES)
classmethod n_dice(number: int, sides: int | Dice) Dice

Return a Dice instance that represents a number of dice.

Parameters:
  • number (int) – The number of dice. Must be >= 0.

  • sides (int | Dice) – The number of sides on each die. Must be >= 0.

>>> Dice.n_dice(2, 8)
Dice(2, 8)

If the sides argument is a Dice instance instead of an int, its sides attribute is used for the returned Dice instance and its other attributes are ignored.

>>> from ndice import d4
>>> Dice.n_dice(2, d4)
Dice(2, 4)

nd() is an alias for Dice.n_dice().

>>> nd(4, 6)
Dice(4, 6)
to_minus() Dice

Return a new Dice instance with the operation set to Op.MINUS.

to_plus() Dice

Return a new Dice instance with the operation set to Op.PLUS.

to_times() Dice

Return a new Dice instance with the operation set to Op.TIMES.

property is_mod: bool

Is this dice term a modifier?

A modifier (mod) will always evaluate to a constant value. Mods like +1, -2 and x5 are represented as Dice instances where number is the constant value of the mod and sides is 1.

Dice with number or sides equal to zero are also considered mods and always evaluate to zero.

number: int

The number of dice to roll; must be zero or greater.

op: Op

The operation before this term in a dice expression.

sides: int

The number of sides of each die; must be zero or greater.

class ndice.Op(*values)

Operations applied to terms in dice expressions.

An Op is a binary operation applied to two int values. Three Op cases are defined: PLUS, MINUS, and TIMES. Op cases are sortable and ordered, with PLUS first and TIMES last.

>>> Op.PLUS < Op.MINUS < Op.TIMES
True

Each Op case has two attributes: symbol and f.

The symbol attribute is a str containing a single character: '+', '-' or 'x' respectively. Note that the symbol for Op.TIMES is the letter x rather than the symbol *.

The f attribute contains a function that implements the binary operation.

Op cases are also callable, executing f on the provided arguments.

>>> Op.PLUS(1, 2)
3
MINUS = ('-', <slot wrapper '__sub__' of 'int' objects>)

The subtraction operation

PLUS = ('+', <slot wrapper '__add__' of 'int' objects>)

The addition operation

TIMES = ('x', <slot wrapper '__mul__' of 'int' objects>)

The multiplication operation

class ndice.SequenceRNG(*values: int)

A fake number generator that returns values from a given sequence.

SequenceRNG instances are callable objects that match the RNG type alias.

>>> srng = SequenceRNG(2, 5, 1, 4)
>>> [srng(6) for _ in range(3)]
[2, 5, 1]

You can check if all values in the SequenceRNG have been consumed using the is_empty property.

>>> srng.is_empty
False
>>> srng(6)
4
>>> srng.is_empty
True

Calling a SequenceRNG instance with no remaining values will raise an exception.

property is_empty: bool

Have all values in the sequence have been produced?

ndice.AscendingRNG(initial_value: int) Callable[[int], int]

Create a fake number generator that returns ascending values.

The returned RNG callable produces an ascending sequence of values, starting with initial_value.

>>> arng = AscendingRNG(2)
>>> [arng(6) for _ in range(3)]
[2, 3, 4]

If the internal value is less than 1 or greater than the sides argument, the RNG will apply the modulus functions so that values wrap to the required range of [1, sides].

>>> arng = AscendingRNG(0)
>>> [arng(6) for _ in range(3)]
[6, 1, 2]
>>> arng = AscendingRNG(7)
>>> [arng(6) for _ in range(3)]
[1, 2, 3]
Parameters:

initial_value (int)

Returns:

a fake number generator that returns ascending values.

ndice.FixedRNG(fixed_value: int) Callable[[int], int]

Create a fake number generator that returns a fixed value.

The returned RNG callable produces values based a fixed value.

>>> always_2 = FixedRNG(2)
>>> [always_2(6) for _ in range(3)]
[2, 2, 2]

If the fixed value is less than 1, 1 is returned.

>>> always_1 = FixedRNG(0)
>>> [always_1(6) for _ in range(3)]
[1, 1, 1]

If the fixed value is greater than the sides argument, sides is returned.

>>> always_6 = FixedRNG(6)
>>> always_6(6)
6
>>> always_6(4)
4
Parameters:

fixed_value (int)

Returns:

a fake number generator that returns a fixed value.

ndice.PRNG(seed: int) Callable[[int], int]

Create a pseudo-random number generator.

The returned RNG callable produces a deterministic sequence of values based on the seed value. The returned number generator is useful when reproducibility is needed, such as for testing.

>>> prng = PRNG(1122334455)
>>> sides = 6
>>> [prng(sides) for _ in range(10)]
[4, 4, 2, 6, 3, 1, 1, 1, 5, 3]
Parameters:

seed (int) – The seed value that selects a the deterministic sequence.

Returns:

a pseudo-random number generator.

ndice.d(sides: int) Dice

Return a Dice instance that represents a single die.

Parameters:

sides (int) – The number of sides on the die. Must be >= 0.

>>> Dice.die(12)
Dice(1, 12)

d() is an alias for Dice.die().

>>> d(8)
Dice(1, 8)
ndice.high(sides: int) int

A fake number generator that always returns the highest roll.

>>> [high(6) for _ in range(3)]
[6, 6, 6]
ndice.low(sides: int) int

A fake number generator that always returns the lowest roll.

>>> [low(6) for _ in range(3)]
[1, 1, 1]

The lowest roll is always 1.

ndice.max_roll(*dice_expression: Dice) int

The maximum total for a dice expression.

>>> from ndice import d6, plus, times
>>> max_roll(d6, plus(2), times(10))
80

This is equivalent to roll(high, ...).

Parameters:

dice_expression (Dice) – A list of dice and modifiers.

Returns:

The maximum total for the dice expression.

ndice.mid(sides: int) int

A fake number generator that always returns the middle roll.

If the number of sides is odd, the middle value in [1, sides] is returned.

>>> [mid(3) for _ in range(3)]
[2, 2, 2]

If the number of sides is even, the lower of the two middle values in [1, sides] is returned.

>>> [mid(6) for _ in range(3)]
[3, 3, 3]
ndice.min_roll(*dice_expression: Dice) int

The minimum total for a dice expression.

>>> from ndice import d6, plus, times
>>> min_roll(d6, plus(2), times(10))
30

This is equivalent to roll(low, ...).

Parameters:

dice_expression (Dice) – A list of dice and modifiers.

Returns:

The minimum total for the dice expression.

ndice.minus(value: int | Dice) Dice

Make a subtractive dice term.

>>> minus(2)
Dice(2, 1, Op.MINUS)
>>> from ndice import d6
>>> minus(d6)
Dice(1, 6, Op.MINUS)
Parameters:

value (int | Dice) – A int mod value or existing Dice instance.

Returns:

A new dice term with operation Op.MINUS.

ndice.mod(value: int, op: Op = Op.PLUS) Dice

Return a Dice instance that represents a modifier.

Parameters:
  • value (int) – The magnitude of the modifier.

  • op (Op) – The operation of the modifier.

Mods are represented as Dice instances where number is the constant value of the mod and sides is 1.

>>> Dice.mod(2)
Dice(2, 1)
>>> Dice.mod(2, Op.MINUS)
Dice(2, 1, Op.MINUS)

If value is negative and op is Op.PLUS or Op.MINUS, then op and the sign of value are inverted. If op is Op.TIMES then value must be non-negative.

>>> Dice.mod(-2)
Dice(2, 1, Op.MINUS)
>>> Dice.mod(-3, Op.MINUS)
Dice(3, 1)
>>> Dice.mod(-4, Op.PLUS)
Dice(4, 1, Op.MINUS)

mod() is an alias for Dice.mod().

>>> mod(10, Op.TIMES)
Dice(10, 1, Op.TIMES)
ndice.nd(number: int, sides: int | Dice) Dice

Return a Dice instance that represents a number of dice.

Parameters:
  • number (int) – The number of dice. Must be >= 0.

  • sides (int | Dice) – The number of sides on each die. Must be >= 0.

>>> Dice.n_dice(2, 8)
Dice(2, 8)

If the sides argument is a Dice instance instead of an int, its sides attribute is used for the returned Dice instance and its other attributes are ignored.

>>> from ndice import d4
>>> Dice.n_dice(2, d4)
Dice(2, 4)

nd() is an alias for Dice.n_dice().

>>> nd(4, 6)
Dice(4, 6)
ndice.plus(value: int | Dice) Dice

Make an additive dice term.

>>> plus(1)
Dice(1, 1)
>>> from ndice import d4
>>> plus(d4)
Dice(1, 4)
Parameters:

value (int | Dice) – A int mod value or existing Dice instance.

Returns:

A new dice term with operation Op.PLUS.

ndice.rng(sides: int) int

A truly random number generator.

>>> assert 1 <= rng(6) <= 6

Uses the global Random.randrange() function.

ndice.roll(rng: Callable[[int], int], *dice_expression: Dice) int

Roll a set of dice and apply modifiers.

An empty dice expression returns zero.

>>> from ndice import mid
>>> roll(mid)
0

Terms in the dice expression are totalled up from left to right. (The Dice.op attribute does not change the order of operations.)

>>> from ndice import d6, minus, times
>>> roll(mid, d6, minus(1), times(10))
20
Parameters:
  • rng (RNG) – A random number generator.

  • dice_expression (Dice) – A list of dice and modifiers.

Returns:

The total rolled for the dice expression.

ndice.roll_each_die(rng: Callable[[int], int], dice: Dice) list[int]

Roll the given dice or mod, returning each die value rolled.

>>> from ndice import mid, three_d6
>>> roll_each_die(mid, three_d6)
[3, 3, 3]

If the dice parameter is a modifier, a list containing the mod value is returned. The dice.op attribute is not applied to the returned value.

>>> from ndice import mod, Op, rng
>>> minus_2 = mod(-2)
>>> roll_each_die(rng, minus_2)
[2]
Parameters:
  • rng (RNG) – A random number generator.

  • dice (Dice) – A dice term or mod.

Returns:

A list of the rolled die values.

ndice.simplify_dice(*expression: Dice) list[Dice]

Join adjacent plus and minus mods together.

Parameters:

expression (list[Dice]) – the dice expression to simplify

Returns:

the simplfied dice expression

>>> from ndice import d6, minus, plus
>>> simplify_dice(d6, plus(3), minus(1))
[Dice(1, 6), Dice(2, 1)]
ndice.times(value: int | Dice) Dice

Make a multiplicative dice term.

>>> times(3)
Dice(3, 1, Op.TIMES)
>>> from ndice import d8
>>> times(d8)
Dice(1, 8, Op.TIMES)
Parameters:

value (int | Dice) – A int mod value or existing Dice instance.

Returns:

A new dice term with operation Op.TIMES.