|
| 1 | +--- |
| 2 | +title: Dice Expressions |
| 3 | +description: The full dice syntax Encounter+ understands — dice, arithmetic, and every modifier (kh, kl, dh, dl, r, ro, !, !o, cs, cf, df, sf). |
| 4 | +--- |
| 5 | + |
| 6 | +Every roll in Encounter+ goes through the same parser, so the syntax on this page works wherever a |
| 7 | +formula is accepted. For how rolling fits into play — the roller, roll tables, rolls in text — see |
| 8 | +[Dice & Roll Tables](/guides/dice/). |
| 9 | + |
| 10 | +## Where expressions are accepted |
| 11 | + |
| 12 | +| Place | Notes | |
| 13 | +| --- | --- | |
| 14 | +| The dice roller's custom formula field | The full syntax | |
| 15 | +| Dice in rendered text | Found automatically, or written as `[2d6+3](roll)` — see [Writing Content](/guides/writing-content/#dice) | |
| 16 | +| A roll table's first column name | `d100`, `d20` — decides how rows are matched | |
| 17 | +| Hit point formulas on a creature | `4d8+12` rolls average or random hit points | |
| 18 | +| Initiative formulas | From the game system's initiative configuration | |
| 19 | +| The web client chat | `/roll 2d6+3` or `/r 2d6+3` — see [Remote Play](/guides/remote-play/) | |
| 20 | +| Roll links in content | `/roll/<formula>/<name>/<type>` | |
| 21 | + |
| 22 | +Expressions are case-insensitive and whitespace is ignored, so `2D6 + 3` and `2d6+3` are the same. |
| 23 | + |
| 24 | +## Dice |
| 25 | + |
| 26 | +``` |
| 27 | +[count]d<faces>[modifier] |
| 28 | +``` |
| 29 | + |
| 30 | +`count` is optional and defaults to 1, so `d20` and `1d20` are identical. `faces` is required. |
| 31 | + |
| 32 | +``` |
| 33 | +d20 one twenty-sided die |
| 34 | +4d6 four six-sided dice, summed |
| 35 | +2d10 two ten-sided dice |
| 36 | +100d6 one hundred six-sided dice |
| 37 | +``` |
| 38 | + |
| 39 | +Any number of faces works, not just the physical dice — `d7`, `d3` and `d1000` are all valid. |
| 40 | + |
| 41 | +### The bare modifier shorthand |
| 42 | + |
| 43 | +An expression that is *only* a signed number is read as a d20 roll with that modifier — the common |
| 44 | +case of tapping a `+7` in a stat block. |
| 45 | + |
| 46 | +``` |
| 47 | ++7 → d20 + 7 |
| 48 | +-2 → d20 - 2 |
| 49 | +``` |
| 50 | + |
| 51 | +## Arithmetic |
| 52 | + |
| 53 | +Dice and numbers can be combined with the usual operators: |
| 54 | + |
| 55 | +| Operator | Meaning | |
| 56 | +| --- | --- | |
| 57 | +| `+` | Add | |
| 58 | +| `-` | Subtract | |
| 59 | +| `*`, `x`, `×` | Multiply | |
| 60 | +| `/`, `÷` | Divide | |
| 61 | +| `(` `)` | Group | |
| 62 | + |
| 63 | +Multiplication and division bind tighter than addition and subtraction, and brackets override that. |
| 64 | + |
| 65 | +``` |
| 66 | +2d6 + 3 |
| 67 | +1d8 + 1d6 + 4 |
| 68 | +(1d6 + 3) * 2 |
| 69 | +d6 x (100 + d6) |
| 70 | +4d6 / 2 |
| 71 | +``` |
| 72 | + |
| 73 | +:::note[Whole numbers only] |
| 74 | +Everything is integer arithmetic. Division truncates — `7/2` is `3` — and a division by zero is not |
| 75 | +evaluated at all. |
| 76 | +::: |
| 77 | + |
| 78 | +## Modifiers |
| 79 | + |
| 80 | +A modifier is written directly after the die, with no space. Most take an optional |
| 81 | +[comparison](#comparison-operators) and a number; where one is omitted the default in the table |
| 82 | +applies. |
| 83 | + |
| 84 | +| Modifier | Name | Default | What it does | |
| 85 | +| --- | --- | --- | --- | |
| 86 | +| `kh[n]` | Keep highest | `kh1` | Keeps the `n` highest dice, discards the rest | |
| 87 | +| `kl[n]` | Keep lowest | `kl1` | Keeps the `n` lowest dice, discards the rest | |
| 88 | +| `dh[n]` | Drop highest | `dh1` | Discards the `n` highest dice | |
| 89 | +| `dl[n]` | Drop lowest | `dl1` | Discards the `n` lowest dice | |
| 90 | +| `r[cmp]<n>` | Reroll | `r1` | Rerolls any matching die, repeatedly, until it no longer matches | |
| 91 | +| `ro[cmp]<n>` | Reroll once | `ro1` | Rerolls any matching die exactly once, keeping the new value whatever it is | |
| 92 | +| `![cmp]<n>` | Explode | max face | Adds an extra die for every matching die, and keeps going while the new die also matches | |
| 93 | +| `!o[cmp]<n>` | Explode once | max face | Adds one extra die for every matching die, and stops there | |
| 94 | +| `cs[cmp]<n>` | Count successes | `cs1` | The result becomes the *number* of matching dice, not their sum | |
| 95 | +| `cf[cmp]<n>` | Count failures | `cf1` | The result becomes the number of matching dice, counted as failures | |
| 96 | +| `df[cmp]<n>` | Deduct failures | `df1` | Sums the dice, then subtracts 1 from the total for each matching die | |
| 97 | +| `sf[cmp]<n>` | Subtract failures | `sf1` | Sums the dice, with each matching die subtracted instead of added | |
| 98 | + |
| 99 | +Discarded and rerolled dice are not thrown away in the display — they stay in the roll detail with a |
| 100 | +`☓` beside them, so you can see what the dice actually did. |
| 101 | + |
| 102 | +### Comparison operators |
| 103 | + |
| 104 | +`r`, `ro`, `!`, `!o`, `cs`, `cf`, `df` and `sf` all take an optional comparison in front of their |
| 105 | +number: |
| 106 | + |
| 107 | +| Written | Matches | |
| 108 | +| --- | --- | |
| 109 | +| `=` or nothing | Equal to | |
| 110 | +| `>` | Greater than | |
| 111 | +| `>=` | Greater than or equal | |
| 112 | +| `<` | Less than | |
| 113 | +| `<=` | Less than or equal | |
| 114 | + |
| 115 | +So `r1` and `r=1` are the same, and `r<3` rerolls anything under 3. |
| 116 | + |
| 117 | +### Examples |
| 118 | + |
| 119 | +``` |
| 120 | +2d20kh1 advantage — roll two d20, keep the higher |
| 121 | +2d20kl1 disadvantage |
| 122 | +4d6dl1 ability score — roll four d6, drop the lowest |
| 123 | +4d6r1 great weapon fighting — reroll 1s until they are not 1s |
| 124 | +4d6ro<3 reroll 1s and 2s, once each |
| 125 | +2d6! exploding sixes, chaining |
| 126 | +2d6!o one extra die per six, no chain |
| 127 | +1d10!>=8 explode on 8, 9 or 10 |
| 128 | +6d10cs>=7 count how many dice rolled 7 or better — a result of 3 is three successes |
| 129 | +10d6sf<3 sum the dice, subtracting any that rolled under 3 |
| 130 | +``` |
| 131 | + |
| 132 | +:::caution[One modifier per die] |
| 133 | +A die group takes a single modifier. `4d6dl1kh2` is not stacked — parsing stops at the second |
| 134 | +modifier and the rest of the expression is dropped. Combine dice in separate groups instead, or pick |
| 135 | +the one modifier that expresses what you want. |
| 136 | +::: |
| 137 | + |
| 138 | +## Advantage, disadvantage and criticals |
| 139 | + |
| 140 | +The roller can upgrade an expression rather than making you rewrite it: |
| 141 | + |
| 142 | +| Upgrade | Effect | |
| 143 | +| --- | --- | |
| 144 | +| **Advantage** | Every `d20` in the expression becomes `2d20kh1`; other dice are untouched | |
| 145 | +| **Disadvantage** | Every `d20` becomes `2d20kl1` | |
| 146 | +| **Critical** | Every die's count is doubled — `2d6+3` becomes `4d6+3` | |
| 147 | + |
| 148 | +Advantage and disadvantage replace any modifier already on the d20, so a formula written with `kh` |
| 149 | +by hand and then rolled with advantage does not compound. |
| 150 | + |
| 151 | +## Roll names and types |
| 152 | + |
| 153 | +A roll can carry a label and a type, which is what lets the roll log tell one roll from another and |
| 154 | +what selects the dice theme it is rolled with. |
| 155 | + |
| 156 | +The types are `attack`, `damage`, `heal`, `check` and `save`. |
| 157 | + |
| 158 | +In Markdown, the label is the link title and the full form is a path: |
| 159 | + |
| 160 | +```markdown |
| 161 | +[2d6+3](roll "fire damage") |
| 162 | +[+7](/roll/d20+7/Longsword/attack) |
| 163 | +``` |
| 164 | + |
| 165 | +In the web client chat, the label goes in brackets, optionally with the type after a colon: |
| 166 | + |
| 167 | +``` |
| 168 | +/roll 2d6+3 [Fire damage] |
| 169 | +/roll d20+7 [Longsword: attack] |
| 170 | +``` |
| 171 | + |
| 172 | +Under D&D 5E the app also guesses the type when none is given — a leading `+` reads as an attack, a |
| 173 | +`d20` as a check, and a formula near the word *damage* as damage. |
| 174 | + |
| 175 | +## Limits and edge cases |
| 176 | + |
| 177 | +- **Dice count and faces** are each capped at 1,000,000. |
| 178 | +- **Rerolling and exploding** stop after about 100 extra dice per die, so `d6!` on a run of sixes |
| 179 | + terminates rather than hanging. |
| 180 | +- **Roll detail** — a group of more than 10 dice reports only its total; the individual rolls are not |
| 181 | + listed or sent to players. |
| 182 | +- **Thousands separators** in a number are ignored: `1,000d6` is a thousand d6. |
| 183 | +- **Automatic detection in text is narrower than the parser.** Prose is scanned for the plain |
| 184 | + `2d6+3` shape only, so an expression with `!`, `r`, `cs` or brackets in it has to be written as an |
| 185 | + explicit [`(roll)` link](/guides/writing-content/#writing-a-roll-yourself) to become tappable. |
| 186 | +- **An unparseable expression** produces no roll at all rather than a partial one — in chat it comes |
| 187 | + back as *Invalid expression*. |
| 188 | + |
| 189 | +## Where to go next |
| 190 | + |
| 191 | +- [Dice & Roll Tables](/guides/dice/) — the roller, rolls in content, and roll tables. |
| 192 | +- [Writing Content](/guides/writing-content/) — dice inside Markdown, and links to your own content. |
| 193 | +- [Dice Roller Settings](/settings/dice-roller/) — rollers, random generator, sound and themes. |
| 194 | +- [URL Scheme](/reference/url-scheme/) — opening the app with a link. |
0 commit comments