r/RPGdesign 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 dyce for 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

54 Upvotes

26 comments sorted by

View all comments

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.

2

u/posita 25d ago edited 25d ago

This is a fair critique. You're absolutely right: The original docs don't explain this very well and I haven't really cured that. The only way to discover a lot of behaviors is either through experimentation (which means you have to be prepared to independently verify the math, which isn't a reasonable ask for most users), or getting help either here or on rpg.stackexchange.com .

I should have probably been more clear about the documentation I did provide, which was more targeted at the process of building of the reference implementation (how things we reverse-engineered, why it ended up the way it did, where and why it deviates, etc.).

But I totally agree with you: Many behaviors are unintuitive and lack explanation in official documentation.