API Reference

die

die.

Classes to represent various dice, dice rolls, and stats on same.

Flexibility has priority over speed.

All dice share die.Die.rng (default the random module) as their source of randomness; assign it, e.g. die.Die.rng = random.Random(seed), to affect every die at once. Pass rng to an individual die to override; del obj.rng reverts an overridden die to the class-wide rng.

Die Classes

  • die.Die (base class, roll your own)

  • die.Standard

  • die.Numeric

  • die.NumericBased

  • die.Constant

  • die.Exploding

  • die.Rerolling

  • die.Symbolic

Ready-made Dice

  • die.d0 (null die, always rolls 0)

  • die.d09 (d10 read 0-9, ‘0’ counts as 0 not 10)

  • die.d3d6 (Roll, three d6 summed)

  • die.d4d6dl (Roll, D&D ability score: four d6, drop lowest, summed)

  • die.d66 (Roll, two d6 read as tens/ones digits, e.g. rolling 4 then 3 gives 43)

  • die.d1…die.d20 (every value), plus die.d24, die.d30, die.d100, die.d1000, die.d10000

  • Exploding: die.d2x…die.d20x, plus die.d24x, die.d30x, die.d100x, die.d1000x, die.d10000x

  • Hackmaster penetrating: die.d2p…die.d100p

  • Rolemaster open-ended: die.d100rm (both ends), die.d100ho (high only), die.d100lo (low only)

  • Coin flip: die.coin (heads=1, tails=0)

  • Fudge die: die.dF (Fudge/FATE: +=1, blank=0, -=-1)

  • Backgammon doubling die: die.doubling (2/4/8/16/32/64)

  • Averaging die: die.averaging (2/3/3/4/4/5, mean 3.5)

  • Compass rose: die.compass4 (N/E/S/W), die.compass8 (N/NE/E/SE/S/SW/W/NW); values are compass bearing in degrees

  • FFG narrative dice (Genesys, Star Wars): die.gsys_boost, die.gsys_setback, die.gsys_ability, die.gsys_difficulty, die.gsys_proficiency, die.gsys_challenge, die.gsys_force; each face value is a Counter of symbols (success/advantage/failure/threat/triumph/despair/light/dark)

  • Warhammer 40k: die.scatter (HIT/arrow), die.blast (2/4/6/8/10/MISFIRE)

Roll Classes

  • die.Roll

Composition

Die and Roll compose via plus/minus/times/div/mod methods, each returning a new Roll; chains bind tight, left to right. keep_highest/keep_lowest/drop_highest/ drop_lowest keep/drop the n highest/lowest die values, summing the kept; successes/failures count die values >= / <= a target:

die.d6.times(2).plus(3).div(die.d6)  # the Roll (d6*2+3)/d6
die.parse('4d6').drop_lowest()       # the Roll 4d6dl
die.parse('6d10').successes(7)       # the Roll 6d10>=7

die.parse accepts the same expressions in dice notation (standard operator precedence, keep/drop suffixes kh/kl/dh/dl, counting suffixes >=/<=):

die.parse('(d6*2+3)/d6')
die.parse('4d6dl')
die.parse('2d20kh')
die.parse('6d10>=7')

Support

  • die.Statistic

  • die.charts (ASCII histogram/scatter charts, Vega-Lite spec emitters)

  • die.parse

  • die.roll

  • die.Odds, die.Rolled (namedtuples returned by Roll.odds and Roll.history)

  • die.Result (namedtuple in Die.history)

class die.Constant(value, rng=None)[source]

One-faced die that always rolls value; never consumes randomness.

The “2” in ‘d6+2’::

die.Constant(2)

Composed and parsed numeric constants (d6.plus(2), parse('d6+2')) are Constant instances.

Parameters:
  • value – Number the die always rolls; also its notation.

  • rng – Source of randomness, accepted for signature consistency; never used.

Raises:

ValueError – If value is not a number.

class die.Die(notation, faces, rng=None)[source]

Base Die class.

A standard six sided die::

die.Die(‘d6’, ((‘1’, 1), (‘2’, 2), (‘3’, 3), (‘4’, 4), (‘5’, 5), (‘6’, 6)))

Rolling:
  • obj.roll() and obj() roll the die count times (default 1) and return func (default sum) applied to the list of rolled values.

  • The default sum raises TypeError on a non-numeric die (numeric is True when every face value is a number); pass a func that handles the values, or use Symbolic, which overrides the default (see Symbolic.roll).

  • The die retains every roll. Subscript it to reach older rolls’ values (obj[-1] is the most recent, matching value, obj[0] the first); slicing and iteration (for value in obj, list(obj), sum(obj)) yield them in roll order. The history property holds the full Result(face, value) namedtuples instead. Empty until the first roll, so obj[0] raises IndexError before then. len(obj) is the number of retained rolls; clear() empties the history.

Operators (every one rolls):
  • str(obj), int(obj), float(obj) roll the die and return the coerced result.

  • +, -, , /, //, %, * roll the die and use that result; they only reliably succeed when the die is numeric.

  • >, >=, <, <=, ==, != also roll — equality included. Consequences: Die are not hashable; comparing or sorting dice gives unstable, unrepeatable results. Compare items for structural (identical faces) equality.

Composing (does NOT roll):
  • plus, minus, times, div, mod each return a new Roll combining this die with a Die, Roll, or number, e.g. d6.times(2).plus(3).div(d6) is the Roll ((d6*2)+3)/d6. Chains bind tight, left to right. See Roll for details.

  • keep_highest, keep_lowest, drop_highest, drop_lowest each return a new Roll keeping/dropping the n (default 1) highest/lowest die values and summing the kept. See Roll for details.

  • successes, failures each return a new Roll counting rolled values >= / <= a target. See Roll for details.

  • chance returns the cumulative percentage chance of a roll at or above (gte=) / at or below (lte=) a value. See Roll.chance.

Properties (all read only):
  • notation: short textual identifier; use this, not str(obj), for the notation text, since str(obj) rolls.

  • description: textual description.

  • faces: list of face texts.

  • items: list of (face, value) tuples.

  • numeric: [boolean] True if all of die’s faces map to numeric values.

  • sides: number of sides die has.

  • values: list of face values.

  • history: list of past-roll Result(face, value) records, empty until the first roll.

Properties tracking the most recent roll (all read only, raise RuntimeError until roll() or any operator that implicitly rolls has been called):

  • result: (face, value) of the most recently rolled face.

  • face: face text of the most recently rolled face.

  • value: value of the most recently rolled face.

Attributes:
  • name: free-text label (plain read/write attribute, default ‘’); shown by repr(), never parsed, independent of notation.

Class attributes:
  • rng: Source of randomness shared by every Die instance; default is the random module. Assign e.g. die.Die.rng = random.Random(seed) to affect every die at once. Overridden per-instance by the rng constructor param; del obj.rng reverts an overridden die to the class-wide rng.

Parameters:
  • notation – Identifies Die of this type.

  • faces – List of (text, value), one per face.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If notation is empty/None or faces is empty.

chance(gte=None, lte=None)[source]

Cumulative percentage (0.0-100.0) chance of a roll >= gte or <= lte.

Exactly one of gte/lte must be given. See Roll.chance.

property description

Textual description of die faces.

div(other, rounding='half', ndigits=0)[source]

Compose new Roll: this die’s roll divided by other (Die, Roll, or number).

Float division then rounding; see Roll.div for rounding/ndigits behavior.

drop_highest(n=1)[source]

Compose new Roll dropping the n highest of this die’s values, summing the rest.

drop_lowest(n=1)[source]

Compose new Roll dropping the n lowest of this die’s values, summing the rest.

property face

Face text of the most recently rolled face.

property faces

List of face texts.

failures(target)[source]

Compose new Roll counting this die’s rolled values <= target.

property items

List of face (text, value) tuples.

keep_highest(n=1)[source]

Compose new Roll keeping the n highest of this die’s rolled values, summed.

keep_lowest(n=1)[source]

Compose new Roll keeping the n lowest of this die’s rolled values, summed.

minus(other)[source]

Compose new Roll: this die’s roll minus other (Die, Roll, or number).

mod(other)[source]

Compose new Roll: this die’s roll modulo other (Die, Roll, or number).

property notation

Human readable expression of die.

property numeric

True if all of die’s faces map to numeric values.

plus(other)[source]

Compose new Roll: this die’s roll plus other (Die, Roll, or number).

property result

Result(face, value) of the most recently rolled face.

rng = <module 'random' from '/home/docs/.asdf/installs/python/3.14.6/lib/python3.14/random.py'>
property sides

Count of die faces.

successes(target)[source]

Compose new Roll counting this die’s rolled values >= target.

times(other)[source]

Compose new Roll: this die’s roll multiplied by other (Die, Roll, or number).

property value

Value of the most recently rolled face.

property values

List of face values.

class die.Exploding(sides, explode_range=1, explode_to=None, math_correct=False, explode_range_low=0, explode_to_low=None, rng=None)[source]

Die that explodes: rolling into the explode range rolls explode_to again, recursing.

A d6 that explodes on 6, rolling itself again::

die.Exploding(6)

Hackmaster style “math corrected” dice subtract one from every rolled-again value, and may explode down to a smaller die:

die.Exploding(
    20, explode_to=die.Exploding(6, math_correct=True), math_correct=True,
)
Rolemaster style double-ended (open-ended) d100 explodes up on 96-100 (add) and down

on 1-5 (subtract), recursively:: die.Exploding(100, explode_range=5, explode_range_low=5)

Parameters:
  • sides – Number of faces on die, integral and > 0.

  • explode_range – [1] Explode when roll is > (sides - explode_range).

  • explode_to – [None] Die rolled (recursively) again on explosion. None means roll this die again.

  • math_correct – [False] Subtract 1 from every rolled-again (not initial) value. Incompatible with explode_range_low.

  • explode_range_low – [0] Explode (subtracting) when roll is <= explode_range_low. 0 disables low-end explosion.

  • explode_to_low – [None] Die rolled (recursively) again, and subtracted, on low-end explosion. None means roll this die again.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If sides isn’t an integer > 0; explode_to or explode_to_low isn’t a Die or None; explode_range >= sides; explode_range_low < 0; explode_range and explode_range_low combined >= sides; or math_correct is True with explode_range_low > 0.

class die.Numeric(notation, spec, rng=None)[source]

Die with non-sequential, numeric faces, possibly repeating.

A backgammon doubling die::

die.Numeric(‘backgammon’, (2, 4, 8, 16, 32, 64))

Parameters:
  • notation – Uniquely identifies dice of this type.

  • spec – List of numbers, one per face of die.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If spec is not iterable of numbers.

class die.NumericBased(notation, spec, rng=None)[source]

Die with possibly non-numeric face texts, but each face has an associated numeric value.

Fudge (www.fudgerpg.com) die::

die.NumericBased(‘dF’, ((‘+’, 1, 2), (‘’, 0, 2), (‘-’, -1, 2)))

Parameters:
  • notation – Identifies dice of this type.

  • spec – List of tuples (facetext, value, count).

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If spec is malformed or any value is non-numeric or count < 1.

class die.Odds(value, ways, probability)

Create new instance of Odds(value, ways, probability)

probability

Alias for field number 2

value

Alias for field number 0

ways

Alias for field number 1

class die.Rerolling(sides, reroll_range=1, once=True, rng=None)[source]

Die that rerolls low values: rolling into the reroll range rolls again.

A d6 that rerolls 1s once, keeping the second roll (D&D Great Weapon Fighting)::

die.Rerolling(6)

A d6 that rerolls 1s and 2s until it rolls a 3 or better::

die.Rerolling(6, reroll_range=2, once=False)

Only the kept roll enters the roll history; rerolled-away values are discarded, so each roll() adds exactly one entry. die.Rerolling(6, reroll_range=2, once=False) that rolls/rerolls 1, 2, 1, 5 keeps only 5 – len(obj) == 1, obj[-1] is 5, and obj.history[-1] is ('5', 5).

Parameters:
  • sides – Number of faces on die, integral and > 0.

  • reroll_range – [1] Reroll when roll is <= reroll_range.

  • once – [True] Reroll a single time, keeping the second roll even if it is also in the reroll range; False rerolls until the roll is out of the range.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If sides isn’t an integer > 0, or reroll_range isn’t an integer with 1 <= reroll_range < sides.

class die.Result(face, value)

Create new instance of Result(face, value)

face

Alias for field number 0

value

Alias for field number 1

class die.Roll(dice=(), func=<built-in function sum>, name='')[source]

Groups a set of Die instances into a single roll.

Two six-sided dice, summed::

die.Roll([die.Standard(6), die.Standard(6)])

One six-sided die, multiplied by 2, composed from a ready-made die::

die.d6.times(2)

A Roll’s dice are fixed at construction; there is no in-place mutation. To change the dice, compose a new Roll (obj.plus(die)) or rebuild one (Roll(obj.dice + (die,)) — but note that only carries over dice, not func/name, and a compose-built Roll rebuilt this way loses its operator structure, e.g. rebuilding a times(2) Roll yields a plain summed Roll).

obj() and obj.roll(count, func ) both roll every die count times (default 1) and return the outer func (default sum) applied to the list of count results, each of which is the constructor’s func applied to that roll’s individual die values.

Roll retains every roll. Subscript it to reach older rolls’ aggregate values (obj[-1] is the most recent, matching value, obj[0] the first); slicing and iteration (for value in obj, list(obj), sum(obj)) yield them in roll order. The history property holds the full Rolled(results, value) namedtuples instead (results the per-die (face, value) tuple, value the aggregate; history[-1] matches the results/value properties). Empty until the first roll, so obj[0] raises IndexError before then. len(obj) is the number of retained rolls; clear() empties the history.

Compose methods plus, minus, times, div, mod (on Die too) each return a NEW Roll combining this roll with a Die, Roll, or number; chains bind tight, left to right:

die.d6.times(2).plus(3).div(die.d6)  # ((d6*2)+3)/d6

Keep/drop compose methods keep_highest, keep_lowest, drop_highest, drop_lowest each return a NEW Roll over the same dice keeping/dropping the n (default 1) highest/lowest die values and summing the kept:

die.parse('4d6').drop_lowest()   # 4d6dl, sum of the 3 highest
die.d20.plus(die.d20).keep_highest()  # (d20+d20)kh, single highest

Counting compose methods successes, failures each return a NEW Roll over the same dice counting die values >= / <= a target (dice pools):

die.parse('6d10').successes(7)   # 6d10>=7, count of dice rolling 7+
die.parse('6d10').failures(1)    # 6d10<=1, count of dice rolling 1

chance (on Die too) reports the cumulative percentage (0.0-100.0) chance of a roll at or above / at or below a value; exactly one of gte/lte is given:

die.parse('2d6').chance(gte=10)  # percent chance of rolling 10 or higher
die.d20.chance(lte=5)            # percent chance of rolling 5 or lower
Operators (every one rolls, same as Die):
  • str(obj), int(obj), float(obj) roll all dice and return the coerced result.

  • +, -, , /, //, %, * roll all dice and use that result; they only reliably succeed when the Roll is numeric (numeric is True when every die is).

  • >, >=, <, <=, ==, != also roll — equality included. Consequences: Roll are not hashable; comparing or sorting rolls gives unstable, unrepeatable results. Compare dice/notation for structural equality.

Properties (all read only):
  • notation: dice notation derived from the Roll’s contents; use this, not str(obj), for the notation text, since str(obj) rolls. For a plain summed Roll it is composed from the contained dice, grouped (e.g. ‘3d6+2’); for a Roll built by the compose methods it is the composed expression (e.g. ‘(d6*2+3)/d6’). '<unsupported>' when underivable: an empty Roll, or a constructor-supplied custom func. When every die’s notation is itself parseable, Roll.from_notation(obj.notation) recreates an equivalent Roll (same dice multiset and odds), with caveats: dice may be reordered by grouping, and dice with custom configuration behind a standard notation (e.g. Exploding with a custom explode_to) are recreated with defaults.

  • description: textual description composed from the contained dice descriptions.

  • dice: tuple of Die instances in Roll.

  • numeric: [boolean] True if all Die in Roll can be numerically summed.

  • odds: list of Odds(value, ways, probability), one per distinct result.

  • history: list of past-roll Rolled(results, value) records, empty until the first roll.

Attributes:
  • name: free-text label (plain read/write attribute, default ‘’); shown by repr(), never parsed, independent of notation.

Properties tracking the most recent roll (all read only, raise RuntimeError until roll(), or any operator that implicitly rolls has been called):

  • results: tuple of (face, value), one per die, from the most recent roll.

  • value: aggregated (func-applied) result of the most recent roll.

Differences from Die:
  • No faces, values, items, or sides properties (all possible results); use dice (tuple of component Die instances) instead.

  • __init__ does not raise on an empty/default dice=(), unlike Die which requires at least one face.

Parameters:
  • dice – List of dice this roll is composed of.

  • func – [sum] Combines this roll’s rolled dice values into one result, func([…]).

  • name – [‘’] Free-text label.

chance(gte=None, lte=None)[source]

Cumulative percentage (0.0-100.0) chance of a roll at or beyond a bound.

Exactly one of gte/lte must be given: gte is the chance of rolling that value or higher, lte that value or lower. Computed from odds, so it carries the same caveat: probabilities come from the dice’s face values and are wrong for dice whose rolls don’t (Exploding, Rerolling). An empty Roll has no outcomes, so its chance is 0.0.

Parameters:
  • gte – Chance a roll is >= this value (“value or higher”).

  • lte – Chance a roll is <= this value (“value or lower”).

Returns:

Percentage, a float in 0.0-100.0.

Raises:
  • ValueError – If neither or both of gte/lte are given.

  • TypeError – If the given bound is not a number, or the Roll is non-numeric.

property description

Textual description composed from the contained Die descriptions.

property dice

Tuple of Die instances in Roll.

Includes composed-in constants (Constant dice): d6.plus(2).dice is (d6, 2).

div(other, rounding='half', ndigits=0)[source]

Compose new Roll: this roll’s result divided by other’s, then rounded.

Division is float (true) division; the quotient is then rounded to ndigits decimal places per rounding:

  • 'half' (default): round half up. Fractions of exactly .5 round toward positive infinity (2.5 -> 3, -2.5 -> -2); everything else rounds to nearest.

  • 'up': fractions round up; quotient is ceiled at ndigits places (2.01 -> 3, -2.99 -> -2 at ndigits=0).

  • 'down': fractions round down; quotient is floored at ndigits places (2.99 -> 2, -2.01 -> -3 at ndigits=0). div(x, rounding='down') is floor (//) division.

With ndigits=0 (the default) results are ints; with ndigits > 0, floats rounded to that many decimal places. ndigits=None skips rounding entirely and results are raw float quotients (rounding is then meaningless and raises).

Parameters:
  • other – Die, Roll, or number.

  • rounding – [‘half’] How fractions round: ‘half’, ‘up’, or ‘down’.

  • ndigits – [0] Decimal places rounded to; None for no rounding.

Returns:

New Roll; neither operand is modified.

Raises:
  • TypeError – If other is not a Die, Roll, or number.

  • ValueError – If rounding is not ‘half’, ‘up’, or ‘down’; rounding is not ‘half’ with ndigits=None; or ndigits is not None or a non-negative integer.

drop_highest(n=1)[source]

Compose new Roll: this roll’s die values with the n highest dropped, summed.

results of the new Roll still reports every die; value is the kept sum.

Parameters:

n – [1] Number of dice dropped.

Returns:

New Roll; this roll is not modified.

Raises:
  • TypeError – If Roll is non-numeric or not a plain summed pool.

  • ValueError – If n is not a positive integer or not fewer than the number of dice.

drop_lowest(n=1)[source]

Compose new Roll: this roll’s die values with the n lowest dropped, summed.

results of the new Roll still reports every die; value is the kept sum.

Parameters:

n – [1] Number of dice dropped.

Returns:

New Roll; this roll is not modified.

Raises:
  • TypeError – If Roll is non-numeric or not a plain summed pool.

  • ValueError – If n is not a positive integer or not fewer than the number of dice.

failures(target)[source]

Compose new Roll: how many of this roll’s die values are <= target.

Counterpart of successes for counting botches/failures. results of the new Roll still reports every die; value is the count.

Parameters:

target – Number a die value must equal or fall below to count.

Returns:

New Roll; this roll is not modified.

Raises:

TypeError – If Roll is non-numeric, not a plain summed pool, or target is not a number.

classmethod from_notation(notation)[source]

Create a Roll from standard dice notation.

Parameters:

notation – Dice notation string, e.g. '3d6+2'.

Returns:

New Roll instance.

Raises:

ValueError – If notation cannot be parsed.

keep_highest(n=1)[source]

Compose new Roll: the n highest of this roll’s die values, summed.

results of the new Roll still reports every die; value is the kept sum.

Parameters:

n – [1] Number of dice kept.

Returns:

New Roll; this roll is not modified.

Raises:
  • TypeError – If Roll is non-numeric or not a plain summed pool.

  • ValueError – If n is not a positive integer or exceeds the number of dice.

keep_lowest(n=1)[source]

Compose new Roll: the n lowest of this roll’s die values, summed.

results of the new Roll still reports every die; value is the kept sum.

Parameters:

n – [1] Number of dice kept.

Returns:

New Roll; this roll is not modified.

Raises:
  • TypeError – If Roll is non-numeric or not a plain summed pool.

  • ValueError – If n is not a positive integer or exceeds the number of dice.

minus(other)[source]

Compose new Roll: this roll’s result minus other’s.

Parameters:

other – Die, Roll, or number.

Returns:

New Roll; neither operand is modified.

Raises:

TypeError – If other is not a Die, Roll, or number.

mod(other)[source]

Compose new Roll: this roll’s result modulo other’s.

Parameters:

other – Die, Roll, or number.

Returns:

New Roll; neither operand is modified.

Raises:

TypeError – If other is not a Die, Roll, or number.

property notation

Dice notation derived from the Roll’s contents; ‘<unsupported>’ when underivable.

property numeric

True if all Die in Roll are numeric, and so can be numerically summed.

property odds

List of Odds(value, ways, probability), one per distinct result.

Computed from each die’s face values, so odds are wrong for dice whose rolls don’t come straight from their faces (Exploding, Rerolling).

plus(other)[source]

Compose new Roll: this roll’s result plus other’s.

Parameters:

other – Die, Roll, or number.

Returns:

New Roll; neither operand is modified.

Raises:

TypeError – If other is not a Die, Roll, or number.

property results

Tuple of (face, value), one per die, from the most recent roll.

successes(target)[source]

Compose new Roll: how many of this roll’s die values are >= target.

The success-counting dice pool of World of Darkness, Shadowrun, and kin. results of the new Roll still reports every die; value is the count.

Parameters:

target – Number a die value must equal or exceed to count.

Returns:

New Roll; this roll is not modified.

Raises:

TypeError – If Roll is non-numeric, not a plain summed pool, or target is not a number.

times(other)[source]

Compose new Roll: this roll’s result multiplied by other’s.

Parameters:

other – Die, Roll, or number.

Returns:

New Roll; neither operand is modified.

Raises:

TypeError – If other is not a Die, Roll, or number.

property value

Aggregated (func-applied) result of the most recent roll.

class die.Rolled(results, value)

Create new instance of Rolled(results, value)

results

Alias for field number 0

value

Alias for field number 1

class die.Standard(sides, rng=None)[source]

Die with sequential, numeric faces.

The common six sided die::

die.Standard(6)

Parameters:
  • sides – Number of faces die has, integral and > 0.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If sides is not a positive integer.

class die.Symbolic(notation, spec, rng=None)[source]

Die with “faces”, and “values” that aren’t necessarily numeric.

A coin flip::

die.Symbolic(‘coin’, ((‘H’, ‘heads’, 1), (‘T’, ‘tails’, 1)))

Parameters:
  • notation – Uniquely identifies dice of this type.

  • spec – die specification; list of tuples (face_text, face_value, count). face_value must be convertible into string but otherwise is free to get funky, count is number of faces with these text/value.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If spec is malformed or any count < 1.

roll(count=1, func=None)[source]

Roll count times.

When the die is numeric, behaves exactly like Die.roll() (func defaults to sum). When it isn’t, func instead defaults to returning the single value at count=1, or a list of values otherwise, since the values aren’t summable.

Parameters:
  • count – [1] Number of times to roll.

  • func – [None] Applied to the list of count rolled values.

Returns:

func applied to list of roll values.

die.parse(notation, rng=None)[source]

Parse dice notation into a Roll instance.

Notation is arithmetic over dice terms with standard operator precedence: *, /, //, % bind tighter than +, -; parentheses override. A term is NdS (N S-sided dice), NdF (N Fudge dice), or an integer constant. NdS may carry an x (exploding) or p (penetrating) suffix, building an Exploding instead of Standard, or an r (reroll once) or rr (reroll until out of range) suffix with optional range (default 1), building a Rerolling; none are valid on Fudge dice. A keep/drop suffix kh, kl, dh, dl with optional count (default 1) may follow a dice term or parenthesized group, keeping/dropping the N highest/lowest die values and summing the kept. A counting suffix >=N or <=N may likewise follow, counting die values >= / <= N (successes/failures) instead of summing. Suffixes bind tightest:

parse('3d6')
parse('2d10+5')
parse('3d6+2d4-1')
parse('(d6*2+3)/d6')
parse('4d6dl')     # 4d6 drop lowest
parse('2d20kh')    # 2d20 keep highest
parse('(3d6+2d4)kh2')
parse('d6x')       # exploding d6
parse('3d6p')      # three penetrating (Hackmaster math-corrected) d6, summed
parse('4d6xkh3')   # four exploding d6, keep highest 3
parse('4d6r')      # four d6, each rerolling 1s once
parse('d10rr2')    # d10, rerolling 1s and 2s until it rolls 3+
parse('6d10>=7')   # six d10, count of dice rolling 7 or higher
parse('6d10<=1')   # six d10, count of dice rolling 1

/ is Roll.div() with defaults (float division rounded half up to an int); // is Roll.div(rounding='down') (floor division). d and f are case-insensitive, whitespace is tolerated. The result is built with the Roll compose methods, so it is identical to the equivalent method chain, e.g. parse('(d6*2+3)/d6') and d6.times(2).plus(3).div(d6).

Parameters:
  • notation – Dice notation string.

  • rng – Source of randomness given to created dice, overriding class-wide Die.rng.

Returns:

Roll whose notation is the normalized notation string.

Raises:

ValueError – If notation cannot be parsed.

die.roll(notation, rng=None)[source]

Parse dice notation, roll it once.

Convenience for parse(notation).roll(); parsing anew each call, prefer parse() when making the same roll repeatedly.

Parameters:
  • notation – Dice notation string, e.g. '3d6+2'.

  • rng – Source of randomness given to created dice, overriding class-wide Die.rng.

Returns:

Result of the roll.

Raises:

ValueError – If notation cannot be parsed.

die.die

Die classes: base, standard, numeric, constant, exploding, and symbolic.

class die.die.Constant(value, rng=None)[source]

Bases: Numeric

One-faced die that always rolls value; never consumes randomness.

The “2” in ‘d6+2’::

die.Constant(2)

Composed and parsed numeric constants (d6.plus(2), parse('d6+2')) are Constant instances.

Parameters:
  • value – Number the die always rolls; also its notation.

  • rng – Source of randomness, accepted for signature consistency; never used.

Raises:

ValueError – If value is not a number.

class die.die.Die(notation, faces, rng=None)[source]

Bases: _Rollable

Base Die class.

A standard six sided die::

die.Die(‘d6’, ((‘1’, 1), (‘2’, 2), (‘3’, 3), (‘4’, 4), (‘5’, 5), (‘6’, 6)))

Rolling:
  • obj.roll() and obj() roll the die count times (default 1) and return func (default sum) applied to the list of rolled values.

  • The default sum raises TypeError on a non-numeric die (numeric is True when every face value is a number); pass a func that handles the values, or use Symbolic, which overrides the default (see Symbolic.roll).

  • The die retains every roll. Subscript it to reach older rolls’ values (obj[-1] is the most recent, matching value, obj[0] the first); slicing and iteration (for value in obj, list(obj), sum(obj)) yield them in roll order. The history property holds the full Result(face, value) namedtuples instead. Empty until the first roll, so obj[0] raises IndexError before then. len(obj) is the number of retained rolls; clear() empties the history.

Operators (every one rolls):
  • str(obj), int(obj), float(obj) roll the die and return the coerced result.

  • +, -, , /, //, %, * roll the die and use that result; they only reliably succeed when the die is numeric.

  • >, >=, <, <=, ==, != also roll — equality included. Consequences: Die are not hashable; comparing or sorting dice gives unstable, unrepeatable results. Compare items for structural (identical faces) equality.

Composing (does NOT roll):
  • plus, minus, times, div, mod each return a new Roll combining this die with a Die, Roll, or number, e.g. d6.times(2).plus(3).div(d6) is the Roll ((d6*2)+3)/d6. Chains bind tight, left to right. See Roll for details.

  • keep_highest, keep_lowest, drop_highest, drop_lowest each return a new Roll keeping/dropping the n (default 1) highest/lowest die values and summing the kept. See Roll for details.

  • successes, failures each return a new Roll counting rolled values >= / <= a target. See Roll for details.

  • chance returns the cumulative percentage chance of a roll at or above (gte=) / at or below (lte=) a value. See Roll.chance.

Properties (all read only):
  • notation: short textual identifier; use this, not str(obj), for the notation text, since str(obj) rolls.

  • description: textual description.

  • faces: list of face texts.

  • items: list of (face, value) tuples.

  • numeric: [boolean] True if all of die’s faces map to numeric values.

  • sides: number of sides die has.

  • values: list of face values.

  • history: list of past-roll Result(face, value) records, empty until the first roll.

Properties tracking the most recent roll (all read only, raise RuntimeError until roll() or any operator that implicitly rolls has been called):

  • result: (face, value) of the most recently rolled face.

  • face: face text of the most recently rolled face.

  • value: value of the most recently rolled face.

Attributes:
  • name: free-text label (plain read/write attribute, default ‘’); shown by repr(), never parsed, independent of notation.

Class attributes:
  • rng: Source of randomness shared by every Die instance; default is the random module. Assign e.g. die.Die.rng = random.Random(seed) to affect every die at once. Overridden per-instance by the rng constructor param; del obj.rng reverts an overridden die to the class-wide rng.

Parameters:
  • notation – Identifies Die of this type.

  • faces – List of (text, value), one per face.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If notation is empty/None or faces is empty.

chance(gte=None, lte=None)[source]

Cumulative percentage (0.0-100.0) chance of a roll >= gte or <= lte.

Exactly one of gte/lte must be given. See Roll.chance.

property description

Textual description of die faces.

div(other, rounding='half', ndigits=0)[source]

Compose new Roll: this die’s roll divided by other (Die, Roll, or number).

Float division then rounding; see Roll.div for rounding/ndigits behavior.

drop_highest(n=1)[source]

Compose new Roll dropping the n highest of this die’s values, summing the rest.

drop_lowest(n=1)[source]

Compose new Roll dropping the n lowest of this die’s values, summing the rest.

property face

Face text of the most recently rolled face.

property faces

List of face texts.

failures(target)[source]

Compose new Roll counting this die’s rolled values <= target.

property items

List of face (text, value) tuples.

keep_highest(n=1)[source]

Compose new Roll keeping the n highest of this die’s rolled values, summed.

keep_lowest(n=1)[source]

Compose new Roll keeping the n lowest of this die’s rolled values, summed.

minus(other)[source]

Compose new Roll: this die’s roll minus other (Die, Roll, or number).

mod(other)[source]

Compose new Roll: this die’s roll modulo other (Die, Roll, or number).

property notation

Human readable expression of die.

property numeric

True if all of die’s faces map to numeric values.

plus(other)[source]

Compose new Roll: this die’s roll plus other (Die, Roll, or number).

property result

Result(face, value) of the most recently rolled face.

rng = <module 'random' from '/home/docs/.asdf/installs/python/3.14.6/lib/python3.14/random.py'>
property sides

Count of die faces.

successes(target)[source]

Compose new Roll counting this die’s rolled values >= target.

times(other)[source]

Compose new Roll: this die’s roll multiplied by other (Die, Roll, or number).

property value

Value of the most recently rolled face.

property values

List of face values.

class die.die.Exploding(sides, explode_range=1, explode_to=None, math_correct=False, explode_range_low=0, explode_to_low=None, rng=None)[source]

Bases: Standard

Die that explodes: rolling into the explode range rolls explode_to again, recursing.

A d6 that explodes on 6, rolling itself again::

die.Exploding(6)

Hackmaster style “math corrected” dice subtract one from every rolled-again value, and may explode down to a smaller die:

die.Exploding(
    20, explode_to=die.Exploding(6, math_correct=True), math_correct=True,
)
Rolemaster style double-ended (open-ended) d100 explodes up on 96-100 (add) and down

on 1-5 (subtract), recursively:: die.Exploding(100, explode_range=5, explode_range_low=5)

Parameters:
  • sides – Number of faces on die, integral and > 0.

  • explode_range – [1] Explode when roll is > (sides - explode_range).

  • explode_to – [None] Die rolled (recursively) again on explosion. None means roll this die again.

  • math_correct – [False] Subtract 1 from every rolled-again (not initial) value. Incompatible with explode_range_low.

  • explode_range_low – [0] Explode (subtracting) when roll is <= explode_range_low. 0 disables low-end explosion.

  • explode_to_low – [None] Die rolled (recursively) again, and subtracted, on low-end explosion. None means roll this die again.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If sides isn’t an integer > 0; explode_to or explode_to_low isn’t a Die or None; explode_range >= sides; explode_range_low < 0; explode_range and explode_range_low combined >= sides; or math_correct is True with explode_range_low > 0.

class die.die.Numeric(notation, spec, rng=None)[source]

Bases: NumericBased

Die with non-sequential, numeric faces, possibly repeating.

A backgammon doubling die::

die.Numeric(‘backgammon’, (2, 4, 8, 16, 32, 64))

Parameters:
  • notation – Uniquely identifies dice of this type.

  • spec – List of numbers, one per face of die.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If spec is not iterable of numbers.

class die.die.NumericBased(notation, spec, rng=None)[source]

Bases: Die

Die with possibly non-numeric face texts, but each face has an associated numeric value.

Fudge (www.fudgerpg.com) die::

die.NumericBased(‘dF’, ((‘+’, 1, 2), (‘’, 0, 2), (‘-’, -1, 2)))

Parameters:
  • notation – Identifies dice of this type.

  • spec – List of tuples (facetext, value, count).

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If spec is malformed or any value is non-numeric or count < 1.

class die.die.Rerolling(sides, reroll_range=1, once=True, rng=None)[source]

Bases: Standard

Die that rerolls low values: rolling into the reroll range rolls again.

A d6 that rerolls 1s once, keeping the second roll (D&D Great Weapon Fighting)::

die.Rerolling(6)

A d6 that rerolls 1s and 2s until it rolls a 3 or better::

die.Rerolling(6, reroll_range=2, once=False)

Only the kept roll enters the roll history; rerolled-away values are discarded, so each roll() adds exactly one entry. die.Rerolling(6, reroll_range=2, once=False) that rolls/rerolls 1, 2, 1, 5 keeps only 5 – len(obj) == 1, obj[-1] is 5, and obj.history[-1] is ('5', 5).

Parameters:
  • sides – Number of faces on die, integral and > 0.

  • reroll_range – [1] Reroll when roll is <= reroll_range.

  • once – [True] Reroll a single time, keeping the second roll even if it is also in the reroll range; False rerolls until the roll is out of the range.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If sides isn’t an integer > 0, or reroll_range isn’t an integer with 1 <= reroll_range < sides.

class die.die.Result(face, value)

Bases: tuple

Create new instance of Result(face, value)

face

Alias for field number 0

value

Alias for field number 1

class die.die.Standard(sides, rng=None)[source]

Bases: Numeric

Die with sequential, numeric faces.

The common six sided die::

die.Standard(6)

Parameters:
  • sides – Number of faces die has, integral and > 0.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If sides is not a positive integer.

class die.die.Symbolic(notation, spec, rng=None)[source]

Bases: Die

Die with “faces”, and “values” that aren’t necessarily numeric.

A coin flip::

die.Symbolic(‘coin’, ((‘H’, ‘heads’, 1), (‘T’, ‘tails’, 1)))

Parameters:
  • notation – Uniquely identifies dice of this type.

  • spec – die specification; list of tuples (face_text, face_value, count). face_value must be convertible into string but otherwise is free to get funky, count is number of faces with these text/value.

  • rng – Source of randomness for this die only, overriding class-wide Die.rng.

Raises:

ValueError – If spec is malformed or any count < 1.

roll(count=1, func=None)[source]

Roll count times.

When the die is numeric, behaves exactly like Die.roll() (func defaults to sum). When it isn’t, func instead defaults to returning the single value at count=1, or a list of values otherwise, since the values aren’t summable.

Parameters:
  • count – [1] Number of times to roll.

  • func – [None] Applied to the list of count rolled values.

Returns:

func applied to list of roll values.

die.notation

Parse standard dice notation into Roll objects.

die.notation.parse(notation, rng=None)[source]

Parse dice notation into a Roll instance.

Notation is arithmetic over dice terms with standard operator precedence: *, /, //, % bind tighter than +, -; parentheses override. A term is NdS (N S-sided dice), NdF (N Fudge dice), or an integer constant. NdS may carry an x (exploding) or p (penetrating) suffix, building an Exploding instead of Standard, or an r (reroll once) or rr (reroll until out of range) suffix with optional range (default 1), building a Rerolling; none are valid on Fudge dice. A keep/drop suffix kh, kl, dh, dl with optional count (default 1) may follow a dice term or parenthesized group, keeping/dropping the N highest/lowest die values and summing the kept. A counting suffix >=N or <=N may likewise follow, counting die values >= / <= N (successes/failures) instead of summing. Suffixes bind tightest:

parse('3d6')
parse('2d10+5')
parse('3d6+2d4-1')
parse('(d6*2+3)/d6')
parse('4d6dl')     # 4d6 drop lowest
parse('2d20kh')    # 2d20 keep highest
parse('(3d6+2d4)kh2')
parse('d6x')       # exploding d6
parse('3d6p')      # three penetrating (Hackmaster math-corrected) d6, summed
parse('4d6xkh3')   # four exploding d6, keep highest 3
parse('4d6r')      # four d6, each rerolling 1s once
parse('d10rr2')    # d10, rerolling 1s and 2s until it rolls 3+
parse('6d10>=7')   # six d10, count of dice rolling 7 or higher
parse('6d10<=1')   # six d10, count of dice rolling 1

/ is Roll.div() with defaults (float division rounded half up to an int); // is Roll.div(rounding='down') (floor division). d and f are case-insensitive, whitespace is tolerated. The result is built with the Roll compose methods, so it is identical to the equivalent method chain, e.g. parse('(d6*2+3)/d6') and d6.times(2).plus(3).div(d6).

Parameters:
  • notation – Dice notation string.

  • rng – Source of randomness given to created dice, overriding class-wide Die.rng.

Returns:

Roll whose notation is the normalized notation string.

Raises:

ValueError – If notation cannot be parsed.

die.notation.roll(notation, rng=None)[source]

Parse dice notation, roll it once.

Convenience for parse(notation).roll(); parsing anew each call, prefer parse() when making the same roll repeatedly.

Parameters:
  • notation – Dice notation string, e.g. '3d6+2'.

  • rng – Source of randomness given to created dice, overriding class-wide Die.rng.

Returns:

Result of the roll.

Raises:

ValueError – If notation cannot be parsed.

die.rolls

Group Die instances into a single roll.

class die.rolls.Odds(value, ways, probability)

Create new instance of Odds(value, ways, probability)

probability

Alias for field number 2

value

Alias for field number 0

ways

Alias for field number 1

class die.rolls.Roll(dice=(), func=<built-in function sum>, name='')[source]

Groups a set of Die instances into a single roll.

Two six-sided dice, summed::

die.Roll([die.Standard(6), die.Standard(6)])

One six-sided die, multiplied by 2, composed from a ready-made die::

die.d6.times(2)

A Roll’s dice are fixed at construction; there is no in-place mutation. To change the dice, compose a new Roll (obj.plus(die)) or rebuild one (Roll(obj.dice + (die,)) — but note that only carries over dice, not func/name, and a compose-built Roll rebuilt this way loses its operator structure, e.g. rebuilding a times(2) Roll yields a plain summed Roll).

obj() and obj.roll(count, func ) both roll every die count times (default 1) and return the outer func (default sum) applied to the list of count results, each of which is the constructor’s func applied to that roll’s individual die values.

Roll retains every roll. Subscript it to reach older rolls’ aggregate values (obj[-1] is the most recent, matching value, obj[0] the first); slicing and iteration (for value in obj, list(obj), sum(obj)) yield them in roll order. The history property holds the full Rolled(results, value) namedtuples instead (results the per-die (face, value) tuple, value the aggregate; history[-1] matches the results/value properties). Empty until the first roll, so obj[0] raises IndexError before then. len(obj) is the number of retained rolls; clear() empties the history.

Compose methods plus, minus, times, div, mod (on Die too) each return a NEW Roll combining this roll with a Die, Roll, or number; chains bind tight, left to right:

die.d6.times(2).plus(3).div(die.d6)  # ((d6*2)+3)/d6

Keep/drop compose methods keep_highest, keep_lowest, drop_highest, drop_lowest each return a NEW Roll over the same dice keeping/dropping the n (default 1) highest/lowest die values and summing the kept:

die.parse('4d6').drop_lowest()   # 4d6dl, sum of the 3 highest
die.d20.plus(die.d20).keep_highest()  # (d20+d20)kh, single highest

Counting compose methods successes, failures each return a NEW Roll over the same dice counting die values >= / <= a target (dice pools):

die.parse('6d10').successes(7)   # 6d10>=7, count of dice rolling 7+
die.parse('6d10').failures(1)    # 6d10<=1, count of dice rolling 1

chance (on Die too) reports the cumulative percentage (0.0-100.0) chance of a roll at or above / at or below a value; exactly one of gte/lte is given:

die.parse('2d6').chance(gte=10)  # percent chance of rolling 10 or higher
die.d20.chance(lte=5)            # percent chance of rolling 5 or lower
Operators (every one rolls, same as Die):
  • str(obj), int(obj), float(obj) roll all dice and return the coerced result.

  • +, -, , /, //, %, * roll all dice and use that result; they only reliably succeed when the Roll is numeric (numeric is True when every die is).

  • >, >=, <, <=, ==, != also roll — equality included. Consequences: Roll are not hashable; comparing or sorting rolls gives unstable, unrepeatable results. Compare dice/notation for structural equality.

Properties (all read only):
  • notation: dice notation derived from the Roll’s contents; use this, not str(obj), for the notation text, since str(obj) rolls. For a plain summed Roll it is composed from the contained dice, grouped (e.g. ‘3d6+2’); for a Roll built by the compose methods it is the composed expression (e.g. ‘(d6*2+3)/d6’). '<unsupported>' when underivable: an empty Roll, or a constructor-supplied custom func. When every die’s notation is itself parseable, Roll.from_notation(obj.notation) recreates an equivalent Roll (same dice multiset and odds), with caveats: dice may be reordered by grouping, and dice with custom configuration behind a standard notation (e.g. Exploding with a custom explode_to) are recreated with defaults.

  • description: textual description composed from the contained dice descriptions.

  • dice: tuple of Die instances in Roll.

  • numeric: [boolean] True if all Die in Roll can be numerically summed.

  • odds: list of Odds(value, ways, probability), one per distinct result.

  • history: list of past-roll Rolled(results, value) records, empty until the first roll.

Attributes:
  • name: free-text label (plain read/write attribute, default ‘’); shown by repr(), never parsed, independent of notation.

Properties tracking the most recent roll (all read only, raise RuntimeError until roll(), or any operator that implicitly rolls has been called):

  • results: tuple of (face, value), one per die, from the most recent roll.

  • value: aggregated (func-applied) result of the most recent roll.

Differences from Die:
  • No faces, values, items, or sides properties (all possible results); use dice (tuple of component Die instances) instead.

  • __init__ does not raise on an empty/default dice=(), unlike Die which requires at least one face.

Parameters:
  • dice – List of dice this roll is composed of.

  • func – [sum] Combines this roll’s rolled dice values into one result, func([…]).

  • name – [‘’] Free-text label.

chance(gte=None, lte=None)[source]

Cumulative percentage (0.0-100.0) chance of a roll at or beyond a bound.

Exactly one of gte/lte must be given: gte is the chance of rolling that value or higher, lte that value or lower. Computed from odds, so it carries the same caveat: probabilities come from the dice’s face values and are wrong for dice whose rolls don’t (Exploding, Rerolling). An empty Roll has no outcomes, so its chance is 0.0.

Parameters:
  • gte – Chance a roll is >= this value (“value or higher”).

  • lte – Chance a roll is <= this value (“value or lower”).

Returns:

Percentage, a float in 0.0-100.0.

Raises:
  • ValueError – If neither or both of gte/lte are given.

  • TypeError – If the given bound is not a number, or the Roll is non-numeric.

property description

Textual description composed from the contained Die descriptions.

property dice

Tuple of Die instances in Roll.

Includes composed-in constants (Constant dice): d6.plus(2).dice is (d6, 2).

div(other, rounding='half', ndigits=0)[source]

Compose new Roll: this roll’s result divided by other’s, then rounded.

Division is float (true) division; the quotient is then rounded to ndigits decimal places per rounding:

  • 'half' (default): round half up. Fractions of exactly .5 round toward positive infinity (2.5 -> 3, -2.5 -> -2); everything else rounds to nearest.

  • 'up': fractions round up; quotient is ceiled at ndigits places (2.01 -> 3, -2.99 -> -2 at ndigits=0).

  • 'down': fractions round down; quotient is floored at ndigits places (2.99 -> 2, -2.01 -> -3 at ndigits=0). div(x, rounding='down') is floor (//) division.

With ndigits=0 (the default) results are ints; with ndigits > 0, floats rounded to that many decimal places. ndigits=None skips rounding entirely and results are raw float quotients (rounding is then meaningless and raises).

Parameters:
  • other – Die, Roll, or number.

  • rounding – [‘half’] How fractions round: ‘half’, ‘up’, or ‘down’.

  • ndigits – [0] Decimal places rounded to; None for no rounding.

Returns:

New Roll; neither operand is modified.

Raises:
  • TypeError – If other is not a Die, Roll, or number.

  • ValueError – If rounding is not ‘half’, ‘up’, or ‘down’; rounding is not ‘half’ with ndigits=None; or ndigits is not None or a non-negative integer.

drop_highest(n=1)[source]

Compose new Roll: this roll’s die values with the n highest dropped, summed.

results of the new Roll still reports every die; value is the kept sum.

Parameters:

n – [1] Number of dice dropped.

Returns:

New Roll; this roll is not modified.

Raises:
  • TypeError – If Roll is non-numeric or not a plain summed pool.

  • ValueError – If n is not a positive integer or not fewer than the number of dice.

drop_lowest(n=1)[source]

Compose new Roll: this roll’s die values with the n lowest dropped, summed.

results of the new Roll still reports every die; value is the kept sum.

Parameters:

n – [1] Number of dice dropped.

Returns:

New Roll; this roll is not modified.

Raises:
  • TypeError – If Roll is non-numeric or not a plain summed pool.

  • ValueError – If n is not a positive integer or not fewer than the number of dice.

failures(target)[source]

Compose new Roll: how many of this roll’s die values are <= target.

Counterpart of successes for counting botches/failures. results of the new Roll still reports every die; value is the count.

Parameters:

target – Number a die value must equal or fall below to count.

Returns:

New Roll; this roll is not modified.

Raises:

TypeError – If Roll is non-numeric, not a plain summed pool, or target is not a number.

classmethod from_notation(notation)[source]

Create a Roll from standard dice notation.

Parameters:

notation – Dice notation string, e.g. '3d6+2'.

Returns:

New Roll instance.

Raises:

ValueError – If notation cannot be parsed.

keep_highest(n=1)[source]

Compose new Roll: the n highest of this roll’s die values, summed.

results of the new Roll still reports every die; value is the kept sum.

Parameters:

n – [1] Number of dice kept.

Returns:

New Roll; this roll is not modified.

Raises:
  • TypeError – If Roll is non-numeric or not a plain summed pool.

  • ValueError – If n is not a positive integer or exceeds the number of dice.

keep_lowest(n=1)[source]

Compose new Roll: the n lowest of this roll’s die values, summed.

results of the new Roll still reports every die; value is the kept sum.

Parameters:

n – [1] Number of dice kept.

Returns:

New Roll; this roll is not modified.

Raises:
  • TypeError – If Roll is non-numeric or not a plain summed pool.

  • ValueError – If n is not a positive integer or exceeds the number of dice.

minus(other)[source]

Compose new Roll: this roll’s result minus other’s.

Parameters:

other – Die, Roll, or number.

Returns:

New Roll; neither operand is modified.

Raises:

TypeError – If other is not a Die, Roll, or number.

mod(other)[source]

Compose new Roll: this roll’s result modulo other’s.

Parameters:

other – Die, Roll, or number.

Returns:

New Roll; neither operand is modified.

Raises:

TypeError – If other is not a Die, Roll, or number.

property notation

Dice notation derived from the Roll’s contents; ‘<unsupported>’ when underivable.

property numeric

True if all Die in Roll are numeric, and so can be numerically summed.

property odds

List of Odds(value, ways, probability), one per distinct result.

Computed from each die’s face values, so odds are wrong for dice whose rolls don’t come straight from their faces (Exploding, Rerolling).

plus(other)[source]

Compose new Roll: this roll’s result plus other’s.

Parameters:

other – Die, Roll, or number.

Returns:

New Roll; neither operand is modified.

Raises:

TypeError – If other is not a Die, Roll, or number.

property results

Tuple of (face, value), one per die, from the most recent roll.

successes(target)[source]

Compose new Roll: how many of this roll’s die values are >= target.

The success-counting dice pool of World of Darkness, Shadowrun, and kin. results of the new Roll still reports every die; value is the count.

Parameters:

target – Number a die value must equal or exceed to count.

Returns:

New Roll; this roll is not modified.

Raises:

TypeError – If Roll is non-numeric, not a plain summed pool, or target is not a number.

times(other)[source]

Compose new Roll: this roll’s result multiplied by other’s.

Parameters:

other – Die, Roll, or number.

Returns:

New Roll; neither operand is modified.

Raises:

TypeError – If other is not a Die, Roll, or number.

property value

Aggregated (func-applied) result of the most recent roll.

class die.rolls.Rolled(results, value)

Create new instance of Rolled(results, value)

results

Alias for field number 0

value

Alias for field number 1

die.stats

Roll dice repeatedly and calculate statistics.

die.charts

Chart dice probabilities and rolled results.

ASCII charts (histogram, scatter) return multi-line strings for terminals. Vega-Lite emitters (vega, vega_scatter, vega_compare) return spec dicts; json.dumps() one and render it with any Vega-Lite tool (https://vega.github.io/editor, VSCode, JupyterLab, vl-convert for PNG/SVG).

Chart functions take a Roll or Die (theoretical probabilities, from odds) or a Statistic (observed frequencies, from a simulation):

die.charts.histogram(die.parse('3d6'))                     # theoretical curve
die.charts.histogram(die.Statistic(die.d3d6).run(10_000))  # observed
die.charts.histogram(source, width=60)[source]

ASCII bar chart of probability per value: the probability curve of source.

One line per distinct value: value, bar, percent. Bars scale so the most probable value spans width characters.

Parameters:
  • source – Statistic (observed), or Roll/Die (theoretical).

  • width – [60] Character width of the longest bar.

Returns:

Multi-line string, no trailing newline.

Raises:
  • ValueError – If width < 1, or source has nothing to chart.

  • TypeError – If source is not a Statistic, Roll, or Die.

die.charts.scatter(stat, width=60, height=20)[source]

ASCII scatter plot of a Statistic’s rolled results: roll order (x) vs value (y).

Parameters:
  • statStatistic whose run() has been called.

  • width – [60] Plot width in characters.

  • height – [20] Plot height in lines.

Returns:

Multi-line string, no trailing newline.

Raises:
die.charts.vega(source, kind='bar')[source]

Vega-Lite spec of probability per value: the probability curve of source.

Parameters:
  • source – Statistic (observed), or Roll/Die (theoretical).

  • kind – [‘bar’] Mark type: ‘bar’ or ‘line’.

Returns:

Vega-Lite v5 spec dict, data inline.

Raises:
  • ValueError – If kind is not ‘bar’ or ‘line’, or source has nothing to chart.

  • TypeError – If source is not a Statistic, Roll, or Die.

die.charts.vega_compare(stat)[source]

Vega-Lite spec overlaying observed frequencies (bars) with theoretical odds (line).

Note Roll.odds is computed from face values, so the theoretical line is wrong for dice whose rolls don’t come straight from their faces (Exploding, Rerolling); the observed bars show the real distribution.

Parameters:

statStatistic whose run() has been called.

Returns:

Layered Vega-Lite v5 spec dict, data inline.

Raises:
die.charts.vega_scatter(stat)[source]

Vega-Lite scatter spec of a Statistic’s rolled results: roll order (x) vs value (y).

Parameters:

statStatistic whose run() has been called.

Returns:

Vega-Lite v5 spec dict, data inline.

Raises: