A dice roller for Android where the roll is real: every throw is a rigid-body physics simulation of the actual dice shapes, rendered in 3D. Shake the phone like you would shake a fistful of dice, and read the result off the faces that land up.
Most dice apps draw a random number and show a picture. dInfinity simulates the dice. The number you get is whatever face ends up on top after the dice tumble, collide, and settle in the tray — the same way it works on a table. That makes rolls feel honest, lets you watch the d20 wobble before it stops, and means a die is defined by its shape, not by a lookup table.
Passing one phone around the table beats passing a bag of dice around and hunting for the d12 that rolled under the couch.
▶ design/dInfinity.dc.html — every v1 screen,
live in the browser. Clone the repository and serve the folder — cd design &&
python3 -m http.server 8000, then open
http://localhost:8000/dInfinity.dc.html. GitHub shows you its source, not the
running prototype, and a file opened straight from disk cannot fetch the parts
it imports. It needs no account or sign-in of any kind, only the internet: React
and Babel come from unpkg, pinned (design/README.md).
It is not a picture of the app: the notation parser, the table capacity rule
and the exact outcome graph all run, following the specification in docs/.
Tap dice to build a formula and shake the phone to throw them — in the
prototype, the tray’s own control stands in for the shake. Type 500d6 to see
it refused, 2d20kh1 + 6 for advantage. Physics is faked with a random face and
a tumble; everything else is real.
| design/dInfinity.dc.html | The canvas: every screen and every variant on one board — start here |
| design/dInfinityPhone.dc.html | The phone prototype on its own, without the board around it |
| design/README.md | What each file is, and what the prototype needs to run |
random().3d6 + 1d20 - 4, 2d10kh1, d%, and so on,
and a dice set’s own dice by name: 3{skull-d6}kh1. The whole grammar is in
the app under Notation, with an example on every line you can tap to
try.d% is an alias for d100), and Fudge dice (dF), whose total carries its
sign.https link to an
archive. examples/ is a working set to copy:
every shape, every field commented, blank atlases to draw on.
Five finished ones come installed — marble, steel, green resin, red
glass and a glow-in-the-dark Halloween set with a pumpkin die, from
sample-sets/ — so resin, glass, metal and glowing dice
roll on every shape from the first launch, and stay removed if you remove
them.docs/ is the written specification; the prototype
is the visual one. Each document below links to the screens that realise it.
| Document | Contents |
|---|---|
| docs/STATUS.md | Where the project stands right now: phase, in progress, blocked, pending decisions |
| docs/TODO.md | Open tasks by milestone and open questions |
| docs/build-setup.md | Devcontainer, building, signing keys, running tests, connecting a phone over WiFi |
| docs/architecture.md | Module layout, tech stack, data flow, key decisions |
| docs/physics-and-rendering.md | Simulation, shake input, settling and face detection, whether the dice are fair, stacking avoidance, power-saving mode |
| docs/dice-notation.md | Roll formula grammar, evaluation rules, saved rolls |
| docs/dice-sets.md | Dice set file format, shapes, textures, installing from git forges or archive URLs, validation and sandboxing |
| docs/tables.md | Table (tray) geometry, capacity limits, exchangeable table looks and their textures |
| docs/probability.md | How the outcome graph is computed |
| docs/face-designer.md | The three-step designer: shape; material, colour and edge rounding; finger-drawn faces, the Solid view and saving to a set |
| docs/statistics.md | What is tracked, how it is stored, privacy |
| docs/assets/README.md | The logo files and the die font, how both are generated from Archivo, and the font licence; the photographed room the dice are lit by; the bundled felt and oak textures, their CC0 sources and how they were cut |
| docs/design-handover.md | Where the app and the prototype still differ, and the questions each side is waiting on |
| design/README.md | The prototype: what each file is, how to serve it locally, how to keep it in step with docs/ |
| examples/README.md | The worked dice set: a commented diceset.toml using every catalogue shape, and blank atlases to draw on |
| sample-sets/README.md | Five finished sets to install from a file or a link — marble, steel, green resin, red glass, Halloween — and how their artwork and archives are made and checked |
Implementation. The app rolls dice on a phone, and v0.3.0 is out — a
signed early release, published with its SHA-256, built from this repository by
pushing a tag. Every screen is written and connected; the documents in docs/
and the prototype in design/ are still the specification, and where the two
disagree one of them is a bug.
It is still 0.x because the physics is not finished: 100d4 does not
reliably settle, and a hard sideways shake can run a roll out to its
twelve-second cap, where it gives up rather than invent an answer. See
docs/STATUS.md for where things stand and
docs/TODO.md for what is next.
Everything happens in the devcontainer — it carries the JDK, the Android SDK, Gradle and the linters, and nothing is expected on the host but Docker. Open the repository in a devcontainer-aware editor, or:
docker build -t dinfinity-dev .devcontainer
docker run --rm -it -v "$PWD":/workspace -w /workspace dinfinity-dev \
./gradlew build test lint detekt ktlintCheck assembleDebugAndroidTest
Release and debug APKs land in app/build/outputs/named-apk/<variant>/ as
dInfinityApp-<version>.apk and dInfinityApp-<version>-debug.apk. The
container also carries adb, so a phone attached over WiFi debugging runs the
on-device tests without leaving it.
docs/build-setup.md has the details: signing keys, wireless debugging, static analysis, and what the container contains.
The working agreements — branching, PRs, tests, releases, build naming, how the tracking files are kept tidy — are in .claude/CLAUDE.md. Read it before opening a PR.
minSdk is 36, because Robolectric cannot
start API 37 — decision 17 in
docs/architecture.mdThe app installs dice sets other people wrote, and that is the whole attack surface worth caring about. SECURITY.md sets out the threat model, the defences, and how to report a vulnerability privately.
GPL-2.0-or-later. See LICENSE.
Dice sets, tables and saved-roll collections you create with the app are yours; the app does not impose a license on them. Sets downloaded from the internet carry whatever license their author chose, shown in the set details.