A die decides a fight. A local LLM stages it. MiniMax H3 renders it as a shot with sound.
You give it three pictures — your hero, the opponent, the place — declare what you attempt and how hard you're willing to push, and hit Run. The dice fall, and you find out what happened by watching it.
## The LLM does not roll the dice
That's the part that matters. The roll happens in ComfyUI nodes, before the model is ever asked anything. The referee is handed a number it cannot change and cannot argue with. It only decides how that number looks on screen.
Ask a language model to roll a die and it won't give you a distribution — it'll give you whatever feels dramatically appropriate. That's fine for a story and useless for a game. Here the model has no say in whether you win.
## How it works
1. A Seed node on randomize produces a fresh number every run.
2. A Math Expression turns it into 2d6, keeping the highest.
3. That number, your declared action and your position go to the LLM as text.
4. The LLM applies the outcome table and writes the shot as a scene description, in JSON.
5. MiniMax H3 renders it with native audio — impacts, breath, shouts.
## The rules
Roll 2d6, keep the highest.
- 6 — full success. It lands exactly as intended.
- 4-5 — success at a cost. It works, but it takes something from you: a wound, a broken weapon, ground lost.
- 1-3 — failure. It turns against you.
Position sets how hard the cost bites, never whether you succeeded. Controlled, and a failure just pushes you back. Desperate, and a failure drops you.
Three outcome tiers instead of hit/miss is a deliberate choice: a clean success has no tension and a clean failure is boring to watch. "You won, and here's what it cost you" is the one that makes a good five seconds of film.
Adapted from the Forged in the Dark SRD. In the original, the size of the dice pool comes from a character's action rating; here it's fixed at 2d6, because there's no character sheet.
```
This work is based on Blades in the Dark (found at http://www.bladesinthedark.com/),
product of One Seven Design, developed and authored by John Harper, and licensed for
our use under the Creative Commons Attribution 3.0 Unported license.
```
## Is the die actually fair?
max((a % 6) + 1, (round((a - (a % 6)) / 6) % 6) + 1)
Both dice come out of one random number. The first is the remainder mod 6; the second is what's left after dividing by 6. Since a - (a % 6) is always a multiple of 6, that round is exact division and rounds nothing.
The pattern repeats every 36 values and hits all 36 combinations once each, so the result comes out 1/3/5/7/9/11 in 36 — which is exactly the distribution of the highest of two six-sided dice.
## What you set
| | |
|---|---|
| Hero | <Picture 1>. Your character. |
| Opponent | <Picture 2>. |
| Location | <Picture 3>. |
| Your action | What you attempt, plus a line Position: controlled / risky / desperate. |
| The die | Leave the Seed on randomize. That's it. |
| Extra video prompt | Camera and grade. The referee never sees this, so it can't fold your camera notes into the fight. |
Four outputs: the video, the roll, the referee's raw JSON, and the exact prompt MiniMax received. The roll and the JSON sit side by side on purpose — one glance tells you whether the referee obeyed the die.
## Requirements
- ComfyUI, recent enough for MiniMaxH3ReferenceToVideo and subgraphs.
- [comfyui-ollama](https://github.com/stavsap/comfyui-ollama) — the only custom node pack needed. In the ComfyUI Manager.
- [Ollama](https://ollama.com) with a vision-capable model pulled. It has to look at three reference images.
Everything else is ComfyUI core. No attention patches, no cache nodes, no upscalers.
> If Ollama Chat shows up as a missing node, your comfyui-ollama is behind. That node was added upstream without a version bump, so the Manager can report you as up to date when you're not. Update from git and restart.
## Models
From [Comfy-Org/MiniMax-H3](https://huggingface.co/Comfy-Org/MiniMax-H3):
```
ComfyUI/models/
├── diffusion_models/
│ └── minimax_h3_ref2va_pruned_int8_convrot.safetensors
├── text_encoders/
│ └── qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors
└── vae/
├── minimax_h3_video_vae_fp16.safetensors
└── minimax_h3_audio_vae_fp32.safetensors
```
This is the ref2va checkpoint, not the fl2va one used by the t2v/i2v templates.
## Notes
- No memory, by design. Reset memory ships true. One roll, one fight, one video. Set it false only if you want the referee to remember earlier fights.
- The failure mode to watch isn't the model cheating — it can't. It's the model contradicting the die: narrating a win on a 2. Small models do this. The roll preview next to the raw JSON makes it obvious immediately, and repeating the constraint just before the output format helps, since the last thing a model reads carries the most weight.
Description
Version 1 for demo purposes.
Comments (8)
Damn thats a very good idea...
We're limited by the hardware we own... because of nvidia-amd-intel being greedy bastards.
I really hope in like 5-10 years we'll be able to buy 750-900$ gpus that have 64+gb of vram so that most gamers can run models like this no problem and can use them with decent speed... nowadays if you want to run a model like this with good speed thats actually usable, you need a 3000$+ gpu, its ridiculous.
Ever heard of GGUFs, TripleKsamplers and 4-steps LoRAs? 🤣
What we need is REAL competition and the country in the best position to offer that is China.
@Keroro_Gunso China is not your friend, China is Hollywood's enemy. Understand the difference.
@sheepinthebigcity Okay.
Great idea, thanks for sharing 🙌
Die is the singular form of dice. You can roll dice, but you can't roll a dice. You can only roll a die.
@Alberist Thank you, I didn't know that was irregular ❤️