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 …
💥 Now 100% Bear-ified™! 👌🏾🐻 (Details below.)
dyce
is a pure-Python library for modeling arbitrarily complex dice mechanics.
It strives for compact expression and efficient computation, especially for the most common cases.
Its primary applications are:
- Computing finite discrete probability distributions for:
- Game designers who want to understand or experiment with various dice mechanics and interactions; and
- Design tool developers.
- Generating transparent, weighted random rolls for:
- Game environment developers who want flexible dice mechanic resolution in, e.g., virtual tabletops (VTTs), chat servers, etc.
Beyond those audiences, dyce
may be useful to anyone interested in exploring finite discrete probabilities but not in developing all the low-level math bits from scratch.
dyce
is designed to be immediately and broadly useful with minimal additional investment beyond basic knowledge of Python.
While not as compact as a dedicated grammar, dyce
’s Python-based primitives are quite sufficient, and often more expressive.
Those familiar with various game notations should be able to adapt quickly.
If you’re looking at something on which to build your own grammar or interface, dyce
can serve you well.
dyce
should be able to replicate or replace most other dice probability modeling tools.
It strives to be fully documented and relies heavily on examples to develop understanding.
dyce
is licensed under the MIT License.
See the accompanying LICENSE
file for details.
Non-experimental features should be considered stable (but an unquenchable thirst to increase performance remains).
See the release notes for a summary of version-to-version changes.
Source code is available on GitHub.
If you find it lacking in any way, please don’t hesitate to bring it to my attention.
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,
dyce
is now available asdycelib
dyce
! Thanks to his generosity,millionsdozens of futuredyce
users will be spared from typing superfluous characters. On behalf of myself, those souls, and our keyboards, we salute you, Mr. Eyk. 🙇♂️
dyce
provides several core primitives.
H
objects represent histograms for modeling finite discrete outcomes, like individual dice.
P
objects represent pools (ordered sequences) of histograms.
R
objects (covered elsewhere) represent nodes in arbitrary roller trees useful for translating from proprietary grammars and generating weighted random rolls that “show their work” without the overhead of enumeration.
All support a variety of operations.
>>> from dyce import H
>>> d6 = H(6) # a standard six-sided die
>>> 2@d6 * 3 - 4 # 2d6 × 3 - 4
H({2: 1, 5: 2, 8: 3, 11: 4, 14: 5, 17: 6, 20: 5, 23: 4, 26: 3, 29: 2, 32: 1})
>>> d6.lt(d6) # how often a first six-sided die shows a face less than a second
H({False: 21, True: 15})
>>> abs(d6 - d6) # subtract the least of two six-sided dice from the greatest
H({0: 6, 1: 10, 2: 8, 3: 6, 4: 4, 5: 2})
>>> from dyce import P
>>> p_2d6 = 2@P(d6) # a pool of two six-sided dice
>>> p_2d6.h() # pools can be collapsed into histograms
H({2: 1, 3: 2, 4: 3, 5: 4, 6: 5, 7: 6, 8: 5, 9: 4, 10: 3, 11: 2, 12: 1})
>>> p_2d6 == 2@d6 # pools and histograms are comparable
True
By providing an optional argument to the P.h
method, one can “take” individual dice from pools, ordered least to greatest.
(The H.format
method provides rudimentary visualization for convenience.)
>>> p_2d6.h(0) # take the lowest die of 2d6
H({1: 11, 2: 9, 3: 7, 4: 5, 5: 3, 6: 1})
>>> print(p_2d6.h(0).format())
avg | 2.53
std | 1.40
var | 1.97
1 | 30.56% |###############
2 | 25.00% |############
3 | 19.44% |#########
4 | 13.89% |######
5 | 8.33% |####
6 | 2.78% |#
>>> p_2d6.h(-1) # take the highest die of 2d6
H({1: 1, 2: 3, 3: 5, 4: 7, 5: 9, 6: 11})
>>> print(p_2d6.h(-1).format())
avg | 4.47
std | 1.40
var | 1.97
1 | 2.78% |#
2 | 8.33% |####
3 | 13.89% |######
4 | 19.44% |#########
5 | 25.00% |############
6 | 30.56% |###############
H
objects provide a distribution
method and a distribution_xy
method to ease integration with plotting packages
anydyce
, for example, makes use of these to integrate with matplotlib
.
Source: plot_2d6_lo_hi.py
Interactive version:
--8<-- "docs/assets/plot_2d6_lo_hi.py"
H
objects and P
objects can generate random rolls.
>>> d6 = H(6)
>>> d6.roll() # doctest: SKIP
4
>>> d10 = H(10) - 1
>>> p_6d10 = 6@P(d10)
>>> p_6d10.roll() # doctest: SKIP
(0, 1, 2, 3, 5, 7)
See the tutorials on counting and rolling, as well as the API guide for much more thorough treatments, including detailed examples.
dyce
is fairly low-level by design, prioritizing ergonomics and composability.
It explicitly avoids stochastic simulation, but instead determines outcomes through enumeration and discrete computation.
That’s a highfalutin way of saying it doesn’t guess.
It knows, even if knowing is harder or more limiting.
Which, if we possess a modicum of humility, it often is.
!!! quote
“It’s frightening to think that you might not know something, but more frightening to think that, by and large, the world is run by people who have faith that they know exactly what is going on.”
—Amos Tversky
Because dyce
exposes Python primitives rather than defining a dedicated grammar and interpreter, one can more easily integrate it with other tools.1
It can be installed and run anywhere2, and modified as desired.
On its own, dyce
is completely adequate for casual tinkering.
However, it really shines when used in larger contexts such as with Matplotlib or Jupyter or embedded in a special-purpose application.
In an intentional departure from RFC 1925, § 2.2, dyce
includes some conveniences, such as minor computation optimizations (e.g., the H.lowest_terms
method, various other shorthands, etc.) and formatting conveniences (e.g., the H.distribution
, H.distribution_xy
, and H.format
methods).
The following is a best-effort3 summary of the differences between various available tools in this space. Consider exploring the applications and translations for added color.
dyce Bogosian et al. |
icepool Albert Julius Liu |
dice_roll.py Karonen |
python-dice Robson et al. |
AnyDice Flick |
d20 Curse LLC |
DnDice “LordSembor” |
dice Clements et al. |
dice-notation Garrido |
|
---|---|---|---|---|---|---|---|---|---|
Latest release | 2022 | 2022 | N/A | 2021 | Unknown | 2021 | 2016 | 2021 | 2022 |
Actively maintained and documented | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | |
Combinatorics optimizations | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Suitable as a dependency in other projects | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ||
Discrete outcome enumeration | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ |
Arbitrary expressions | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ||
Arbitrary dice definitions | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
Integrates with other tools | ✅ | ✅ | ✅ | ❌ | ✅ | ||||
Open source (can inspect) | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
Permissive licensing (can use and extend) | ✅ | ✅ | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ |
dyce
is licensed under the MIT License.
See the included LICENSE
file for details.
Source code is available on GitHub.
Installation can be performed via PyPI.
% pip install dyce
...
Alternately, you can download the source and install manually.
% git clone https://github.com/posita/dyce.git
...
% cd dyce
% python -m pip install . # -or- python -c 'from setuptools import setup ; setup()' install .
...
dyce
requires a relatively modern version of Python:
It has the following runtime dependencies:
-
numerary
forproperbest-effort hacking around deficiencies in static and runtime numeric type-checking -
beartype
for yummy runtime type-checking goodness (a dependency ofnumerary
)
dyce
will opportunistically use the following, if available at runtime:
numpy
to supplydyce
with an alternate random number generator implementation
If you use beartype
for type checking your code, but don’t want dyce
or numerary
to use it internally, disable it with numerary
’s NUMERARY_BEARTYPE
environment variable.
See the hacking quick-start for additional development and testing dependencies.
- This could be you! 👋
Do you have a project that uses dyce
?
Let me know, and I’ll promote it here!
And don’t forget to do your part in perpetuating gratuitous badge-ification!
<!-- Markdown -->
As of version 1.1, HighRollin is
[![dyce-powered](https://raw.githubusercontent.com/posita/dyce/latest/docs/dyce-powered.svg)][dyce-powered]!
[dyce-powered]: https://posita.github.io/dyce/ "dyce-powered!"
..
reStructuredText - see https://docutils.sourceforge.io/docs/ref/rst/directives.html#image
As of version 1.1, HighRollin is |dyce-powered|!
.. |dyce-powered| image:: https://raw.githubusercontent.com/posita/dyce/latest/docs/dyce-powered.svg
:align: top
:target: https://posita.github.io/dyce/
:alt: dyce-powered
<!-- HTML -->
As of version 1.1, HighRollin is <a href="https://posita.github.io/dyce/"><img
src="https://raw.githubusercontent.com/posita/dyce/latest/docs/dyce-powered.svg"
alt="dyce-powered"
style="vertical-align: middle;"></a>!
Footnotes
-
You won’t find any lexers, parsers, or tokenizers in
dyce
’s core, other than straight-up Python. That being said, you can always “roll” your own (see what we did there?) and lean ondyce
underneath. It doesn’t mind. It actually kind of likes it. ↩ -
Okay, maybe not literally anywhere, but you’d be surprised. Void where prohibited. Certain restrictions apply. Do not taunt Happy Fun Ball. ↩
-
I have attempted to ensure the above is reasonably accurate, but please consider contributing an issue if you observe discrepancies. ↩
-
Sparsely documented. The author has expressed a desire to release a more polished version. ↩
-
Source can be downloaded and incorporated directly, but there is no packaging, versioning, or dependency tracking. ↩ ↩2
-
Callers must perform their own arithmetic and characterize results in terms of a lightweight die primitive, which may be less accessible to the novice. That being said, the library is remarkably powerful, given its size. ↩
-
Limited arithmetic operations are available. The library also provides game-specific functions. ↩
-
Results only. Input is limited to specialized grammar. ↩ ↩2 ↩3 ↩4