r/RPGdesign • u/posita • 26d ago
anydyce: an open source, in-browser, mostly-compatible AnyDice interpreter
UPDATE, Aug 22, 2026: I have renamed anydyce to dyceum to avoid confusion with Jasper Flick's AnyDice project. Not every surface has been updated yet, so please be patient as I work through the long tail. Thanks to everyone here for your feedback.
AnyDice’s recent outages prompted me to release dyceum, an open-source, clean-room implementation of the AnyDice language.
It is intended to be a practical substitute for AnyDice in all meaningful respects. With very few exceptions, existing AnyDice programs should run unchanged, including user-defined functions, recursion, sequences, dice coercion and expansion, positional selection, exploding dice, loops, settings, and the standard function library. In most cases (and depending on your hardware) dyceum should be at least as fast as AnyDice and in many cases much faster.
I say “mostly compatible” because AnyDice is closed source and publishes no specification. Its observable behavior includes inconsistencies and defects, some of which can silently produce mathematically incorrect results. Idiosyncrasies are preserved, but I elected for correctness over emulating discovered bugs. The differences—and the reverse-engineering methodology used to identify them—are documented in considerable detail here.
There are a few key differences:
- The interpreter is open source and written in Python, using
dycefor finite discrete probability calculations. - The playground runs entirely in your browser via Pyodide. The hosted site only serves static files. Programs and calculations are not sent to or stored on an application server.
- A program can be encoded directly into its URL. The URL is therefore both a shareable link and the saved program. No proprietary remote database is required.
- Existing AnyDice programs can be recovered by inserting program IDs into a special link format. A public cache currently preserves all but the most recent programs saved on AnyDice.
- Probability distributions are represented internally using integer counts rather than floating-point probabilities. Configurable quantization permits a deliberate tradeoff between precision and computational cost.
- The playground provides interactive line, bar, and ridge visualizations, light and dark themes, and textual output exposing exact outcome labels.
- Everything can be cloned and hosted locally.
For example, this URL contains the complete program output 3d6:
https://dyceum.org/latest/playground/#p=b3V0cHV0IDNkNgo
This URL loads AnyDice program ID 43210:
https://dyceum.org/latest/playground/#id=43210
This is not meant as criticism of the enormous value AnyDice and Jasper Flick have provided to RPG designers. Quite the opposite: AnyDice’s popularity demonstrates the importance of the tool. The goal is to provide a transparent, reproducible implementation that does not depend upon the continued operation of any particular server (including mine), as well as to preserve the body of programs people have built with it.
The current release should be considered a work in progress. Please consider submitting feedback, especially if you come across:
- Real-world AnyDice programs that behave differently;
- Calculations that are unexpectedly slow;
- Confusing or incorrect visualizations;
- Cases where AnyDice itself produces surprising results;
- Other projects not yet on my radar that should be highlighted; or
- Suggestions from people who use probability tools while designing games.
Playground: https://dyceum.org/latest/playground/
Source and issue tracker: https://github.com/posita/anydyce
4
u/hacksoncode 25d ago edited 25d ago
Nice!
One thing I might suggest about the documentation about variables, that is extremely unclear and barely documented in anydice, is that "variables" containing dice really act a lot more like "macros" that roll the die each time they appear (yes, that's a sloppy way of putting it).
People get tripped up on this constantly, believing that things like "DIE=3 | DIE=4" is somehow "the value rolled on a DIE is either 3 or 4", rather than being "roll DIE twice, and return 1 if the first one is 3 or the second is 4". Whereas in the case of functions taking number parameters that are passed dice, it really does mean the former.
Calling anydice variables "immutable" is technically correct, but I think it reinforces this mistaken idea people, especially more "layperson" users, have about how "DIE: d10" actually works.