This release is a pre-release and may not be stable for production use.
Copyright and other protections apply.
Please see the accompanying LICENSE file for rights and restrictions governing use of this software.
All rights not expressly waived or licensed are reserved.
If that file is missing or appears to be modified from its original, then please contact the author before viewing or using this software in any capacity.
Now you’re playing with …
dyce
dyce is a Python library for dice mechanics and other problems with a finite set of possible outcomes.
It counts how many ways each outcome can occur, then calculates exact probabilities.
Suggested audiences and applications:
- Game designers for crafting and compare game mechanics
- Tool developers for using calculations in higher level tooling
Overview
Hrepresents possible outcomes and their weights as integer counts. A fair, six-sided die can be represented asH({1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1}), or the shorthandH((1, 2, 3, 4, 5, 6)), or simplyH(6). The sum of three six-sided dice can be represented as3 @ H(6).Prepresents an ordered sequence of histograms. A pool of three separate six-sided dice can be represented as3 @ P(H(6)), or the shorthand3 @ P(6).Ps keep each die separate, so you can select any die or group of dice and calculate the distribution of their summed results.P.surveyandexpandare experimental interfaces useful for modeling mechanics where an outcome of one die affects how others are included. Examples include: exploding dice, conditional re-rolls, or damage that depends on whether an attack hits.- Optional Matplotlib and Plotly helpers support visualization.
Example: d20 versus a “target number”
Consider a mechanic popularized by one of the world’s roll playing games1 where a roll on a (typically dodecahedral) twenty-sided die “succeeds” when it is greater than or equal to a specific value (a “target number”). This example compares the outcome distributions for one d20, the higher of two d20s (“advantage”), and the lower of two d20s (“disadvantage”).
>>> from dyce import H, P
>>> d20 = H(20) # shorthand for an evenly-weighted 20-sided die
>>> d20
H({1: 1, 2: 1, 3: 1, ..., 18: 1, 19: 1, 20: 1})
>>> p2d20 = 2 @ P(d20) # a pool of two such dice
>>> d20_advantage = p2d20.at(-1) # right-most index (-1) selects highest
>>> d20_disadvantage = p2d20.at(0) # left-most index (0) selects lowest
>>> d20_advantage
H({1: 1, 2: 3, 3: 5, ..., 18: 35, 19: 37, 20: 39})
>>> d20_disadvantage
H({1: 39, 2: 37, 3: 35, ..., 18: 5, 19: 3, 20: 1})
With a single d20, the chance of rolling a 15 or higher is 30%. With advantage, it climbs to 51%. With disadvantage, it drops to 9%.
>>> target_number = 15
>>> # How often a d20 is greater than or equal to target_number
>>> d20_vs_target = d20.ge(target_number)
>>> print(d20_vs_target.format()) # built-in text formatting
avg | 0.30
std | 0.46
False | 70.00% |#################################
True | 30.00% |##############
>>> d20_advantage_vs_target = d20_advantage.ge(target_number)
>>> print(d20_advantage_vs_target.format_short())
{avg: 0.51, False: 49.00%, True: 51.00%}
>>> d20_disadvantage_vs_target = d20_disadvantage.ge(target_number)
>>> print(d20_disadvantage_vs_target.format_short())
{avg: 0.09, False: 91.00%, True: 9.00%}
Run this example in JupyterLite:
As one might expect, with a single d20, each outcome is equally likely, with 10.5 being the average. With advantage, one is likely to roll at least a 15 over half the time, and one is nearly twice as likely to roll a 20. With disadvantage, one is likely to roll at most a 6 over half the time, and one is nearly twice as likely to roll a 1.
Installation
python -m pip install dyce
dyce supports CPython 3.11–3.15 and PyPy 3.11-3.12.
It depends on optype for static and runtime type-checking.
dyce is available under the MIT License.
dyce will opportunistically use the following, if available:
- Beartype for runtime type checking 👌🏾🐻
- Matplotlib for basic visualization helpers via
dyce.viz.matplotlib - NumPy for random number generation
Explore further
- Consult the glossary for important terms used in this documentation.
- Read about
dyce’s core concepts and operations. - See examples for worked examples.
- Browse the API reference.
- Read the contribution guide to report an issue or contribute a change.
- See the release notes for changes between releases.
- Browse the source code.
Other efforts
dyce does not stand alone.
Other works include:
- The OG
dice_roll.pyby Ilmari Karonen icepoolby Albert Julius Liu- GNOLL by Ian Hunter
- lea by Pierre Denis
- dice by Sam Clements
- ossuary by B. Szonye
- PythonDice by Ar-Kareem
- dice-notation by Bernardo Martinez Garrido
- Avrae’s d20 by Andrew Zhu
- python-dice by Mark Robson
- DnDice by “LordSembor”
- AnyDice (closed source) by Jasper Flick
Please consider contributing an issue if you observe discrepancies or think something should be added to the list.
Donors
When one worries that the flickering light of humanity may be snuffed out at any moment, when one’s heart breaks at the perverse celebration of judgment, vengeance, and death and the demonizing of empathy, compassion, and love, sometimes all that is needed is the kindness of a single stranger to reinvigorate one’s faith that—while all may not be right in the world—there is hope for us human beings.
- David Eyk not only inspires others to explore creative writing, but has graciously ceded his PyPI project dedicated to his own prior work under a similar name.
As such,
dyceis now available asdycelibdyce! Thanks to his generosity,millionsdozens of futuredyceusers will be spared from typing superfluous characters. On behalf of myself, those souls, and our keyboards, we salute you, Mr. Eyk. 🫡
-
Hat tip (or profuse apologies) to the Angry GM who is not only one of the world’s greatest role playing game masters, but a remarkably reflective human being for whom I have a tremendous amount of respect and gratitude. ↩
Metadata
Release files for dyce 0.7.0rc12
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dyce-0.7.0rc12.tar.gz | 1.0 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dyce-0.7.0rc12-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.1 MB
Release files / dyce-0.7.0rc12.tar.gz
| Download URL | dyce-0.7.0rc12.tar.gz |
|---|---|
| Size | 1.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
297d71341720a49493e8c82a3df228f1c67c890ce4f910700581ad1b88ac538c
|
|
BLAKE2b-256 checksum How to use checksums |
5fa3af61ca7a9801b41d81ee34e55e8cf41ff76feab88003cbfd983d25ca11f6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logRelease files / dyce-0.7.0rc12-py3-none-any.whl
| Download URL | dyce-0.7.0rc12-py3-none-any.whl |
|---|---|
| Size | 70.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9859db42debfe4fa3183f28c36bd66c6e823975f0fe1a061f9553942760b2bbc
|
|
BLAKE2b-256 checksum How to use checksums |
8abf16dad5bc750ab70de38af9013617b5a34ece5cdcc53e511d12658c573b92
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency log