User guide Tutorial Cookbook Open playground

Dice standard library

This reference lists everything built into .dice scripts beyond basic Starlark (variables, for loops, lists). New here? Work through the tutorial first—it introduces notation like 2d6 and 4d6dl1, which the playground expands into the functions below.

Naming: face matching (keep / remove / convert / ignore), count, and pool p_* methods follow API conventions.

Core ideas

DieRoll — a finished numeric roll (or total) with exact chances for each possible result. Example: 2d6 is a DieRoll; so is 4d6dl1. Use output("name", roll) to print its table in the playground.

DicePool — several dice rolled together but not added yet. Use this when the rule cares about individual faces (highest die, count successes, Blades-style pools). Call .sum() on the pool when you only need the total.

Outcomes — chances for named outcome bands (miss / partial / hit, crit fail / success, and so on) instead of raw numbers.

Combining rolls (operators)

You writeMeaning at the table
a + bTwo independent rolls added together (e.g. 1d6 + 1d6 or 2d6 + 1d4).
roll + 5Flat modifier added to every outcome of roll (same as shift(roll, 5)).
roll - 3Subtract 3 from every outcome.
a - bIndependent rolls subtracted (less common; niche mechanics).
roll * 10Multiply each outcome (e.g. tens die reading).
roll // 2Halve each outcome, round down (typical “half damage on save”).

Dice notation (1d20, 3d6kh2, …) is sugar for these functions—see the dice notation lesson.

Builtin functions (by topic)

Building dice and totals

Start here for ordinary dice, custom faces, and summed pools.

d

def d(sides: int) -> DieRoll

One fair die with faces 1 through sides, each equally likely.

Parameters

Details

Same idea as 1d6 or 1d20 in dice notation. Example: d(6) for a d6, d(20) for a d20.



die_faces

def die_faces(faces: list[int]) -> DieRoll

A die with custom face values (listed in order; duplicates count as extra weight).

Parameters

Details

Use for dice that are not uniform—die_faces([1, 2, 2, 3]) is twice as likely to show 2 as 1 or 3.


die_faces.bucket

def die_faces.bucket(scale: Scale, *bands) -> Outcomes

Label numeric totals using bands on scale, or pass cut list / bands to override.


die_faces.cdf

def die_faces.cdf(value: int) -> float

Chance the total is this number or lower (cumulative from the bottom).

Parameters

Details

Less common than p_ge for “beat the DC” checks; useful when rules ask “at most X”.


die_faces.clamp

def die_faces.clamp(min: int, max: int) -> DieRoll

Cap every outcome at min and max (inclusive), merging probability at the bounds.

Parameters

Details

Example: (3d6 + 5).clamp(3, 18) for a boosted roll that cannot exceed 18.


die_faces.convert

def die_faces.convert(spec, to: int) -> DieRoll

Remap matching faces to to; other faces unchanged.


die_faces.ignore

def die_faces.ignore(spec) -> DieRoll

Remap matching faces to 0 (convert(spec, 0)).


die_faces.keep

def die_faces.keep(spec) -> DieRoll

Keep only faces matching spec; drop others and renormalize. Not .p_ge() on totals.


die_faces.mean

def die_faces.mean() -> float

Average result if you rolled this distribution many times—the mean on the output table.


die_faces.p_ge

def die_faces.p_ge(value: int) -> float

Chance of meeting or beating a target number—your go-to for “need 15+ on 2d10”.

Parameters

Details

Example: output("success", (2d10 + 3).p_ge(15)).


die_faces.pmf

def die_faces.pmf(value: int) -> float

Chance of rolling exactly this number (one outcome, not “this or higher”).

Parameters

Details

Example: output("pct_seven", 2d6.pmf(7)) for the probability of a 7 on 2d6.


die_faces.remove

def die_faces.remove(spec) -> DieRoll

Drop faces matching spec; renormalize the rest.


die_faces.support_size

def die_faces.support_size() -> int

How many different totals can occur with non-zero chance (size of the result table).


dice_pool

def dice_pool(count: int, sides: int) -> DicePool

Roll count separate fair dice—not added together yet.

Parameters

Details

Use when the rule looks at individual results (highest die, count 10s, etc.). Add with .sum() or the sum(...) function when you only need the total. Example: dice_pool(4, 6) for four d6s.


dice_pool.bucket

def dice_pool.bucket(scale: Scale, *spec) -> Outcomes

Label the pool total using bands on scale (sums first).


dice_pool.convert

def dice_pool.convert(spec, to: int) -> DicePool

Remap matching faces to to on every die.


dice_pool.count

def dice_pool.count(spec) -> DieRoll

Distribution of how many dice match spec.


dice_pool.ignore

def dice_pool.ignore(spec) -> DicePool

Remap matching faces to 0 on every die.


dice_pool.keep

def dice_pool.keep(spec) -> DicePool

Keep only matching faces on every die; drop others and renormalize each die.


dice_pool.middle_of

def dice_pool.middle_of(keep: int) -> DieRoll

dice_pool.order_stat

def dice_pool.order_stat(k: int) -> DieRoll

dice_pool.p_any

def dice_pool.p_any(*spec) -> float

P(at least one die matches the optional face spec).


dice_pool.p_at_least

def dice_pool.p_at_least(k: int, *spec) -> float

P(at least k dice match the optional face spec).


dice_pool.p_none

def dice_pool.p_none(*spec) -> float

P(no die matches the optional face spec).


dice_pool.remove

def dice_pool.remove(spec) -> DicePool

Drop matching faces on every die; renormalize each die.


dice_pool.sum

def dice_pool.sum() -> DieRoll

Add every die in the pool into one total—turns dice_pool(4, 6) into the same idea as 4d6.


sum

def sum(value) -> DieRoll

Total a dice pool, or leave a DieRoll unchanged.

sum(dice_pool(4, 6)) is the distribution of 4d6 summed—equivalent to 4d6 notation. If you already have a DieRoll, sum returns it as-is.



drop_lowest

drop_lowest

def drop_lowest(count: int, sides: int, drop: int) -> DieRoll

Roll several dice, drop the lowest results, sum the rest—4d6 drop lowest 1 is drop_lowest(4, 6, 1).

Parameters

Details

Same as 4d6dl1 in dice notation.


drop_highest

drop_highest

def drop_highest(count: int, sides: int, drop: int) -> DieRoll

Roll dice, drop the highest results, sum the rest (4d6dh1 notation).

Parameters


keep_highest

keep_highest

def keep_highest(count: int, sides: int, keep: int) -> DieRoll

Roll dice, keep only the highest few, sum those—4d6 keep highest 3 is keep_highest(4, 6, 3) (4d6kh3).

Parameters


keep_lowest

keep_lowest

def keep_lowest(count: int, sides: int, keep: int) -> DieRoll

Roll dice, keep only the lowest few, sum those (4d6kl3 notation).

Parameters


explode

def explode(dist: DieRoll, max_depth: int = 2) -> DieRoll

Exploding die: on the highest face, roll again and add, up to max_depth extra rolls (default 2).

Parameters

Details

Common in games where max on a die triggers another die (Savage Worlds–style). Example: explode(d(4)) for one exploding d4.



open_ended_d100

def open_ended_d100(max_chain: int = 8) -> DieRoll

Rolemaster open-ended roll on 1–100 (d100): low open on 01–05, high open on 96–00; rerolls chain on 96–00 only. max_chain caps consecutive 96–00 rerolls (default 8).


open_ended_d100.bucket

def open_ended_d100.bucket(scale: Scale, *bands) -> Outcomes

Label numeric totals using bands on scale, or pass cut list / bands to override.


open_ended_d100.cdf

def open_ended_d100.cdf(value: int) -> float

Chance the total is this number or lower (cumulative from the bottom).

Parameters

Details

Less common than p_ge for “beat the DC” checks; useful when rules ask “at most X”.


open_ended_d100.clamp

def open_ended_d100.clamp(min: int, max: int) -> DieRoll

Cap every outcome at min and max (inclusive), merging probability at the bounds.

Parameters

Details

Example: (3d6 + 5).clamp(3, 18) for a boosted roll that cannot exceed 18.


open_ended_d100.convert

def open_ended_d100.convert(spec, to: int) -> DieRoll

Remap matching faces to to; other faces unchanged.


open_ended_d100.ignore

def open_ended_d100.ignore(spec) -> DieRoll

Remap matching faces to 0 (convert(spec, 0)).


open_ended_d100.keep

def open_ended_d100.keep(spec) -> DieRoll

Keep only faces matching spec; drop others and renormalize. Not .p_ge() on totals.


open_ended_d100.mean

def open_ended_d100.mean() -> float

Average result if you rolled this distribution many times—the mean on the output table.


open_ended_d100.p_ge

def open_ended_d100.p_ge(value: int) -> float

Chance of meeting or beating a target number—your go-to for “need 15+ on 2d10”.

Parameters

Details

Example: output("success", (2d10 + 3).p_ge(15)).


open_ended_d100.pmf

def open_ended_d100.pmf(value: int) -> float

Chance of rolling exactly this number (one outcome, not “this or higher”).

Parameters

Details

Example: output("pct_seven", 2d6.pmf(7)) for the probability of a 7 on 2d6.


open_ended_d100.remove

def open_ended_d100.remove(spec) -> DieRoll

Drop faces matching spec; renormalize the rest.


open_ended_d100.support_size

def open_ended_d100.support_size() -> int

How many different totals can occur with non-zero chance (size of the result table).


shift

def shift(dist: DieRoll, delta: int) -> DieRoll

Add a flat modifier to every outcome—**+3 to the roll** without rolling another die.

Parameters

Details

Same effect as roll + 3 when roll is a DieRoll. Prefer roll + 3 in scripts when it reads clearer.


through

def through(lo: int, hi: int) -> IntBand

Inclusive closed integer interval (same as desugared 6..94).


at_most

def at_most(hi: int) -> IntBand

All integers at or below hi (desugared ..hi).


at_least

def at_least(lo: int) -> IntBand

All integers at or above lo (desugared lo..).


Inclusive ranges

Integer bands for face filters and bucketing. In .dice scripts you can also write 6..94, ..6, and 10.. (inclusive endpoints).

through

def through(lo: int, hi: int) -> IntBand

Inclusive closed integer interval (same as desugared 6..94).


at_most

def at_most(hi: int) -> IntBand

All integers at or below hi (desugared ..hi).


at_least

def at_least(lo: int) -> IntBand

All integers at or above lo (desugared lo..).


Pool rules (faces still matter)

These need a DicePool from dice_pool before you total the dice.

count

def count(pool: DicePool, spec) -> DieRoll

How many dice in the pool match a face spec?

Parameters

Details

The result is a DieRoll over counts (0, 1, 2, …). Same as pool.count(spec).



order_stat

def order_stat(pool: DicePool, k: int) -> DieRoll

The kth highest die in the pool (k = 1 is the highest, 2 is second-highest, …).

Parameters

Details

Blades in the Dark and similar games use the highest die; some rules use second-highest.


order_stat.bucket

def order_stat.bucket(scale: Scale, *bands) -> Outcomes

Label numeric totals using bands on scale, or pass cut list / bands to override.


order_stat.cdf

def order_stat.cdf(value: int) -> float

Chance the total is this number or lower (cumulative from the bottom).

Parameters

Details

Less common than p_ge for “beat the DC” checks; useful when rules ask “at most X”.


order_stat.clamp

def order_stat.clamp(min: int, max: int) -> DieRoll

Cap every outcome at min and max (inclusive), merging probability at the bounds.

Parameters

Details

Example: (3d6 + 5).clamp(3, 18) for a boosted roll that cannot exceed 18.


order_stat.convert

def order_stat.convert(spec, to: int) -> DieRoll

Remap matching faces to to; other faces unchanged.


order_stat.ignore

def order_stat.ignore(spec) -> DieRoll

Remap matching faces to 0 (convert(spec, 0)).


order_stat.keep

def order_stat.keep(spec) -> DieRoll

Keep only faces matching spec; drop others and renormalize. Not .p_ge() on totals.


order_stat.mean

def order_stat.mean() -> float

Average result if you rolled this distribution many times—the mean on the output table.


order_stat.p_ge

def order_stat.p_ge(value: int) -> float

Chance of meeting or beating a target number—your go-to for “need 15+ on 2d10”.

Parameters

Details

Example: output("success", (2d10 + 3).p_ge(15)).


order_stat.pmf

def order_stat.pmf(value: int) -> float

Chance of rolling exactly this number (one outcome, not “this or higher”).

Parameters

Details

Example: output("pct_seven", 2d6.pmf(7)) for the probability of a 7 on 2d6.


order_stat.remove

def order_stat.remove(spec) -> DieRoll

Drop faces matching spec; renormalize the rest.


order_stat.support_size

def order_stat.support_size() -> int

How many different totals can occur with non-zero chance (size of the result table).


middle_of

def middle_of(pool: DicePool, keep: int) -> DieRoll

Sum the middle keep dice after sorting the pool low to high.

Parameters

Details

Niche rules that drop extremes from both ends; less common than keep-highest / drop-lowest.


middle_of.bucket

def middle_of.bucket(scale: Scale, *bands) -> Outcomes

Label numeric totals using bands on scale, or pass cut list / bands to override.


middle_of.cdf

def middle_of.cdf(value: int) -> float

Chance the total is this number or lower (cumulative from the bottom).

Parameters

Details

Less common than p_ge for “beat the DC” checks; useful when rules ask “at most X”.


middle_of.clamp

def middle_of.clamp(min: int, max: int) -> DieRoll

Cap every outcome at min and max (inclusive), merging probability at the bounds.

Parameters

Details

Example: (3d6 + 5).clamp(3, 18) for a boosted roll that cannot exceed 18.


middle_of.convert

def middle_of.convert(spec, to: int) -> DieRoll

Remap matching faces to to; other faces unchanged.


middle_of.ignore

def middle_of.ignore(spec) -> DieRoll

Remap matching faces to 0 (convert(spec, 0)).


middle_of.keep

def middle_of.keep(spec) -> DieRoll

Keep only faces matching spec; drop others and renormalize. Not .p_ge() on totals.


middle_of.mean

def middle_of.mean() -> float

Average result if you rolled this distribution many times—the mean on the output table.


middle_of.p_ge

def middle_of.p_ge(value: int) -> float

Chance of meeting or beating a target number—your go-to for “need 15+ on 2d10”.

Parameters

Details

Example: output("success", (2d10 + 3).p_ge(15)).


middle_of.pmf

def middle_of.pmf(value: int) -> float

Chance of rolling exactly this number (one outcome, not “this or higher”).

Parameters

Details

Example: output("pct_seven", 2d6.pmf(7)) for the probability of a 7 on 2d6.


middle_of.remove

def middle_of.remove(spec) -> DieRoll

Drop faces matching spec; renormalize the rest.


middle_of.support_size

def middle_of.support_size() -> int

How many different totals can occur with non-zero chance (size of the result table).


pool_map

def pool_map(pool: DicePool, map_fn) -> DieRoll

Custom rule: for every way the pool can land, run your function on the list of faces and use its integer result.

Parameters

Details

Advanced—use when no built-in pool helper fits (e.g. “sum only dice that matched another die”). The function receives one argument: the list of rolled values, sorted as the engine stores them.


pool_map.bucket

def pool_map.bucket(scale: Scale, *bands) -> Outcomes

Label numeric totals using bands on scale, or pass cut list / bands to override.


pool_map.cdf

def pool_map.cdf(value: int) -> float

Chance the total is this number or lower (cumulative from the bottom).

Parameters

Details

Less common than p_ge for “beat the DC” checks; useful when rules ask “at most X”.


pool_map.clamp

def pool_map.clamp(min: int, max: int) -> DieRoll

Cap every outcome at min and max (inclusive), merging probability at the bounds.

Parameters

Details

Example: (3d6 + 5).clamp(3, 18) for a boosted roll that cannot exceed 18.


pool_map.convert

def pool_map.convert(spec, to: int) -> DieRoll

Remap matching faces to to; other faces unchanged.


pool_map.ignore

def pool_map.ignore(spec) -> DieRoll

Remap matching faces to 0 (convert(spec, 0)).


pool_map.keep

def pool_map.keep(spec) -> DieRoll

Keep only faces matching spec; drop others and renormalize. Not .p_ge() on totals.


pool_map.mean

def pool_map.mean() -> float

Average result if you rolled this distribution many times—the mean on the output table.


pool_map.p_ge

def pool_map.p_ge(value: int) -> float

Chance of meeting or beating a target number—your go-to for “need 15+ on 2d10”.

Parameters

Details

Example: output("success", (2d10 + 3).p_ge(15)).


pool_map.pmf

def pool_map.pmf(value: int) -> float

Chance of rolling exactly this number (one outcome, not “this or higher”).

Parameters

Details

Example: output("pct_seven", 2d6.pmf(7)) for the probability of a 7 on 2d6.


pool_map.remove

def pool_map.remove(spec) -> DieRoll

Drop faces matching spec; renormalize the rest.


pool_map.support_size

def pool_map.support_size() -> int

How many different totals can occur with non-zero chance (size of the result table).


success_pool

def success_pool(
    count: int,
    sides: int,
    mode: str = "baseline",
) -> DieRoll

Count successes on a dice pool (Storyteller / WoD-style d10 pools and variants).

Parameters

Details

Returns a DieRoll over how many successes you rolled. mode controls 1s and 10s: "baseline" (default), "ones_cancel", "ones_remove", or "implode".


success_pool.bucket

def success_pool.bucket(scale: Scale, *bands) -> Outcomes

Label numeric totals using bands on scale, or pass cut list / bands to override.


success_pool.cdf

def success_pool.cdf(value: int) -> float

Chance the total is this number or lower (cumulative from the bottom).

Parameters

Details

Less common than p_ge for “beat the DC” checks; useful when rules ask “at most X”.


success_pool.clamp

def success_pool.clamp(min: int, max: int) -> DieRoll

Cap every outcome at min and max (inclusive), merging probability at the bounds.

Parameters

Details

Example: (3d6 + 5).clamp(3, 18) for a boosted roll that cannot exceed 18.


success_pool.convert

def success_pool.convert(spec, to: int) -> DieRoll

Remap matching faces to to; other faces unchanged.


success_pool.ignore

def success_pool.ignore(spec) -> DieRoll

Remap matching faces to 0 (convert(spec, 0)).


success_pool.keep

def success_pool.keep(spec) -> DieRoll

Keep only faces matching spec; drop others and renormalize. Not .p_ge() on totals.


success_pool.mean

def success_pool.mean() -> float

Average result if you rolled this distribution many times—the mean on the output table.


success_pool.p_ge

def success_pool.p_ge(value: int) -> float

Chance of meeting or beating a target number—your go-to for “need 15+ on 2d10”.

Parameters

Details

Example: output("success", (2d10 + 3).p_ge(15)).


success_pool.pmf

def success_pool.pmf(value: int) -> float

Chance of rolling exactly this number (one outcome, not “this or higher”).

Parameters

Details

Example: output("pct_seven", 2d6.pmf(7)) for the probability of a 7 on 2d6.


success_pool.remove

def success_pool.remove(spec) -> DieRoll

Drop faces matching spec; renormalize the rest.


success_pool.support_size

def success_pool.support_size() -> int

How many different totals can occur with non-zero chance (size of the result table).


Named outcomes

Turn numeric totals or special roll rules into labeled results.

scale

def scale() -> Scale

Start an ordered outcome scale; chain .step(label) or .step(label, band) on the result.

Overlapping bands are allowed: early=True steps match first, then other steps (declaration order). Declaration order still defines ladder rank for p_at_least / p_at_most. (with is reserved in Starlark.) Example: scale().step("MISS", ..6).step("PARTIAL", 7..9).



bucket

def bucket(dist: DieRoll, scale: Scale, *spec) -> Outcomes

Split a numeric total into named bands.

Parameters

Details

With bands on scale (from scale().step(..., band)), call bucket(roll, scale) or roll.bucket(scale). Overlapping bands: early=True steps first, then other steps in order. Otherwise pass N−1 cut ints or N explicit bands (override).



classify

def classify(dist: DieRoll, scale: Scale, classify) -> Outcomes

Label each exact roll value with your own rule—natural 1s, natural 20s, custom crits.

Parameters

Details

Your function takes the numeric result and returns one of the strings on scale. Example: map only 1 and 20 to special labels, bucket everything else by total.



joint_classify

def joint_classify(
    d1: DieRoll,
    d2: DieRoll,
    scale: Scale,
    classify,
) -> Outcomes

Label outcomes that depend on two dice together—advantage, disadvantage, or paired rolls.

Parameters

Details

Every combination of d1 and d2 is classified by your (left, right) -> str function.


joint_classify.p_at_least

def joint_classify.p_at_least(label: str) -> float

Chance of this outcome or any better one on the scale—e.g. “partial success or full success”.


joint_classify.p_at_most

def joint_classify.p_at_most(label: str) -> float

Chance of this outcome or any worse one—e.g. “failure or partial failure”.


joint_classify.pmf

def joint_classify.pmf(label: str) -> float

Chance of landing on exactly this named outcome (one band on the ladder).


Showing results

Always end scripts with output so the playground prints tables and charts.

output

def output(*args) -> None

Send a result to the playground Output panel (text, json, and graph tabs).

Almost every script should call this at least once. Pass a name and a value: a full distribution (DieRoll), named outcomes (Outcomes), a probability (float), or a table (prob_table(...)). One argument works but naming outputs helps you read results.


prob_table

def prob_table(rows: list) -> ProbTable

One table of labeled probabilities—grids of “chance to hit DC X at modifier Y”.

Parameters

Details

Each row is (description, probability). Rows are independent (they do not have to add to 100%). Build a list in a loop, then pass it here once: output("grid", prob_table(rows)).


DieRoll methods

Ask questions about a numeric DieRoll after you build it (often inside output(..., roll.p_ge(15))).

mean

def mean() -> float

Average result if you rolled this distribution many times—the mean on the output table.


pmf

def pmf(value: int) -> float

Chance of rolling exactly this number (one outcome, not “this or higher”).

Parameters

Details

Example: output("pct_seven", 2d6.pmf(7)) for the probability of a 7 on 2d6.


p_ge

p_ge

def p_ge(value: int) -> float

Chance of meeting or beating a target number—your go-to for “need 15+ on 2d10”.

Parameters

Details

Example: output("success", (2d10 + 3).p_ge(15)).


cdf

def cdf(value: int) -> float

Chance the total is this number or lower (cumulative from the bottom).

Parameters

Details

Less common than p_ge for “beat the DC” checks; useful when rules ask “at most X”.


clamp

def clamp(min: int, max: int) -> DieRoll

Cap every outcome at min and max (inclusive), merging probability at the bounds.

Parameters

Details

Example: (3d6 + 5).clamp(3, 18) for a boosted roll that cannot exceed 18.


support_size

support_size

def support_size() -> int

How many different totals can occur with non-zero chance (size of the result table).


keep

def keep(spec) -> DieRoll

Keep only faces matching spec; drop others and renormalize. Not .p_ge() on totals.


remove

def remove(spec) -> DieRoll

Drop faces matching spec; renormalize the rest.


convert

def convert(spec, to: int) -> DieRoll

Remap matching faces to to; other faces unchanged.


ignore

def ignore(spec) -> DieRoll

Remap matching faces to 0 (convert(spec, 0)).


bucket

def bucket(scale: Scale, *bands) -> Outcomes

Label numeric totals using bands on scale, or pass cut list / bands to override.


DicePool methods

Face filters (keep / remove / convert / ignore), match counts (count), pool match probabilities (p_any / p_none / p_at_least), or total the pool. See API conventions.

sum

def sum() -> DieRoll

Add every die in the pool into one total—turns dice_pool(4, 6) into the same idea as 4d6.


keep

def keep(spec) -> DicePool

Keep only matching faces on every die; drop others and renormalize each die.


remove

def remove(spec) -> DicePool

Drop matching faces on every die; renormalize each die.


convert

def convert(spec, to: int) -> DicePool

Remap matching faces to to on every die.


ignore

def ignore(spec) -> DicePool

Remap matching faces to 0 on every die.


count

def count(spec) -> DieRoll

Distribution of how many dice match spec.


order_stat

order_stat

def order_stat(k: int) -> DieRoll

middle_of

middle_of

def middle_of(keep: int) -> DieRoll

p_any

p_any

def p_any(*spec) -> float

P(at least one die matches the optional face spec).


p_none

p_none

def p_none(*spec) -> float

P(no die matches the optional face spec).


p_at_least

p_at_least

def p_at_least(k: int, *spec) -> float

P(at least k dice match the optional face spec).


bucket

def bucket(scale: Scale, *spec) -> Outcomes

Label the pool total using bands on scale (sums first).


Outcomes methods

Query named outcome bands (PbtA moves, graded success, etc.).

pmf

def pmf(label: str) -> float

Chance of landing on exactly this named outcome (one band on the ladder).


p_at_least

p_at_least

def p_at_least(label: str) -> float

Chance of this outcome or any better one on the scale—e.g. “partial success or full success”.


p_at_most

p_at_most

def p_at_most(label: str) -> float

Chance of this outcome or any worse one—e.g. “failure or partial failure”.


Scale methods

Build ordered outcome labels and optional numeric bands after scale().

step

def step(label: str, *band, early: bool = False) -> Scale

Append one outcome label (low → high). With no band, the step is for classify only.

With a band (IntBand or desugared ..6, 7..9, 10..), the step buckets numeric totals. Bands may overlap: early steps (see early=True) are checked first, then other steps, each in declaration order. Declaration order still defines ladder rank for p_at_least / p_at_most.