Rule systems
The dice language
The formulas behind every sentence: dice notation, values a roll can read, how a roll is read, with recipes for common mechanics.
One small language under every sentence
Every number in a rule system is either a plain number or a formula in one small language: the dice a check rolls, a target, a track's maximum, a stat's modifier, an enemy's health by tier, an amount on a rule card. You rarely need to write one: the sentence editor, the composer and Hob write them for you. The Advanced tab shows them all when you want to.
It is deliberately small. It is not a programming language: no loops, no reaching outside the values it's handed, nothing that can misbehave. A formula that doesn't make sense is refused when you save, in a sentence saying what's wrong.


Dice
| Write | Means | Example |
|---|---|---|
d20 | One twenty-sided die | 13 |
3d6 | Three six-sided dice, added | 4 + 2 + 6 = 12 |
2d20kh1 | Two d20s, keep the highest one (advantage) | (7, 16) → 16 |
2d20kl1 | Keep the lowest one (disadvantage) | (19, 7) → 7 |
4d6kh3 | Four d6s, keep the best three | (5, 2, 6, 3) → 14 |
(@stat)d6 | As many dice as a value says | Prowl 3 → 3d6 |
6d10>=6 | Count the dice at or over 6: the value is the count | (2, 6, 9, 10, 1, 7) → 4 |
3d6! | Exploding: a top face rolls another die | (6, 2, 4) + 5 → 17 |
4dF | Fate dice: each −1, 0 or +1 | (+, 0, −, +) → +1 |
d100 | Percentile; d% is the same | 47 |
d100t(1) | Percentile with a bonus tens die (keep the better tens); t(-1) a penalty die | (4 or 7, 3) → 43 |
d12[Hope] | A die with a name: shown with its name, and readable by rule cards | Hope d12 (9) |
Every face is kept in the roll's record, so the dice tray can replay it and the roll chip can show it. All dice roll from a seed: the same roll, rolled again for the same turn, gives the same faces.
Numbers and logic
- Arithmetic
+ - * /and brackets:floor((@str - 10) / 2)- Comparisons
> >= < <= == !=, giving 1 or 0:@hp < 5- Logic
and,or,not:@cond.blessed > 0 and @nerve >= 3- Choices
if … then … else …:if @level >= 5 then 2 else 1. Only the branch taken is worked out, so only its dice are rolled.- Functions
floor ceil round abs min max clamp:clamp(@edge + @cond.edge, -1, 1)
Values a formula can read
| Write | What it is | Where |
|---|---|---|
@str | A stat's value (by its id) | Anywhere |
@str.mod | A stat's modifier: its value when it has none | Anywhere |
@stat | The stat being rolled; @stat.mod its modifier | A check's roll and target |
@hp | A track's current value; @hp.max its maximum | Anywhere |
@proficiency | A derived value (by its id) | Anywhere |
@level | The character's level; @xp their xp | Anywhere |
@difficulty | The number behind the word the storyteller picked for a label (Hard → 20). Every label is readable by its id: @edge, @position. | A check's roll and target |
@spend_push | 1 if the player paid that spend before the roll, else 0 | A check's roll |
@cond.edge | What the sheet's conditions add up to as edge; @cond.mod as a bonus or penalty | A check's roll |
@cond.poisoned | A condition's level (0 when absent); @cond.poisoned.left its ticks left | Anywhere |
@opp.insight.mod | The opponent's stat or modifier, when a roll is aimed at someone present; @opp.tier their tier | A check's opposed targets |
@defence | The defender's defence | The attack check |
@tier | The enemy's tier, 1 to 6 | Enemy templates |
@this | The stat itself; @linked the stat it leans on | A stat's modifier |
@group.Hope.high | A named die's highest face; also .tops (top faces), .ones, .successes, .value | Outcomes and rule cards after a roll |
@total | The roll's total; also @target, @margin (total − target), @measure | Outcomes and rule cards after a roll |
@event.amount | The damage of the blow that set off the card | Damage cards |
@thing.ship.hull | A value on the character's first thing of a kind | Anywhere |
How a roll is read
A check has a roll and a way of reading it. The reading turns the dice into the outcome bands' measure:
| Reading | Measure | Options |
|---|---|---|
| Total against a target | A degree: −1 fumble, 0 failure, 1 success, 2 critical | steps: beat the target by this much for a critical, miss by it for a fumble (PF2e: 10). naturals: a top or bottom face on the first die sets or shifts the degree. |
| Total into bands | The total itself | Bands by range: 10+, 7-9, 6- (PbtA). |
| Roll under | A grade: −1 fumble, 0 failure, 1 success, 2 hard, 3 extreme | grades (fractions of the target), what counts as a critical (a 1, rolling exactly the target, doubles), what fumbles, faces that always pass or fail, success levels instead of grades. |
| Highest die | The best face; several top faces count one higher | Forged in the Dark. |
| Count successes | The count | Pairs of a face as extra successes and a critical (tens in a d10 pool). |
On top of any reading, a check can compare two named dice (Hope against Fear): which came up higher adds a word to the outcome and its own effects; equal dice can be a critical.
Recipes
Fifth-edition advantage, with conditions and exhaustion
(if @edge + clamp(@cond.edge + (if @exhaustion >= 1 then -1 else 0), -1, 1) > 0 then 2d20kh1 else if @edge + clamp(@cond.edge + (if @exhaustion >= 1 then -1 else 0), -1, 1) < 0 then 2d20kl1 else d20) + @stat.mod + @cond.mod
Classic d20's ability check: any number of disadvantages and advantages count once either way.
Pushing yourself for an extra die
if @stat + @spend_push <= 0 then 2d6kl1 else (@stat + @spend_push)d6
Forged in the Dark: zero dots rolls two and keeps the lower; paying the “push” spend (2 Stress) adds a die.
Hope, Fear, and a d6 if you spend Hope
d12[Hope] + d12[Fear] + @stat + (if @spend_hope > 0 then d6 else 0)
Percentile with bonus and penalty dice
d100t(@edge) read: roll under, target @stat.mod * @difficulty
A hunger pool: some dice are dangerous
(@stat - @hunger)d10>=6 + (@hunger)d10[Hunger]>=6
Count successes across both groups; then a rule card reads @group.Hunger.ones to turn a failure with a 1 on a Hunger die into something worse.
Degrees of success by ten
roll: d20 + @stat.mod read: total against @difficulty, steps 10, naturals 20 / 1 shift the degree
An opposed lie
opposed: { "deception": "10 + @opp.insight.mod" }A lie told to someone present is rolled against their passive Insight instead of a difficulty.