Status: built. Intensity is a per-reference "how much" dial that flows into a generator and changes
what it renders. It adds three things to DPL: an argument on the {#name} token,
intensity conditions on lines (next to weights), and a natural-language keyword the prompt text
can interpolate. The engine also auto-scales probability gates and counts by intensity.
Two dials now. Intensity has a sibling, focus (see
focus-design.md). Because the two percents look identical, the dial carries a mandatoryi(intensity) orf(focus) prefix:{#name i25% f80%},[i<10%],[f<40%]. The prefix is required — an unprefixed25%/<10%is not dial syntax (a bare[10]is still a weight). The keyword tokens also moved off the{…}braces (which mean{list}) to a$sigil, and since the dial is a percent,$intensityrenders50%(there is no separate%form) — see §4.
The guiding line is unchanged: DPL stays data, not code. Intensity is one number the author compares
against ([<10%]) or drops into text ({intensity}); the engine does the scaling. No variables, no state.
1. The token argument — {#name NN%}
A {#name} reference may carry an i-prefixed intensity percent (and/or an f-prefixed focus percent):
{#great-bridge i25%} ; render great-bridge at 25% intensity
{#weather i80%} ; weather at 80% intensity
{#beach i25% f80%} ; 25% intensity AND 80% focus (order-free)
{#weather 80%} ; NOT dial syntax — the prefix is required (left literal)
{#knight} ; no percent → the default, 50%
- The percent is 1–100.
0%is treated as 1% (never zero). Values above 100 clamp to 100. - Default when unspecified: 50%. A bare
{#name}— at the top level or nested inside another generator — runs at 50%. (Intensity does not auto-inherit from a parent; a nested{#weather}with no percent is 50%, regardless of the parent's dial. To pass a parent's level down, write it explicitly, e.g.{#weather 80%}.) The default lives in one constant (DEFAULT_INTENSITY) so it is trivial to retune. - The percent is parsed in the
{#…}resolver (engine/core/stages/block.js) and handed to the generator as the 4th argument:mod.default(settings, imageSettings, upscaleSettings, intensity, focus)(focus is the 5th). Compiled.dplfiles expose them asctx.intensity/ctx.focus;.jssidecars read the 4th / 5th parameter.
2. Intensity conditions on a line — [<10%], [100|<10%]
A line/bullet can carry an intensity condition in the same square-bracket slot as a weight. The line is rendered only when the condition holds against the current intensity:
[i<10%] - grass ; only when intensity < 10%
- [i>50%] dense undergrowth ; only when intensity > 50%
- [i=50%] a balanced scene ; only at exactly 50%
(An f-prefixed condition — [f<40%] — reads the focus dial instead; see
focus-design.md. An unprefixed [<10%] is not a condition and is left as
payload text — the prefix is required.)
Operators: <, <=, >, >=, = (also ==), !=. The value is a percent (10%, 12.5%).
Stacking weight and condition — inside one bracket, separated by a pipe or a space (the space reads more naturally), either order:
- [100 i<10%] sparse detail ; weight 100 AND only when intensity < 10%
- [i<10% 100] sparse detail ; identical (either order)
- [100 i<10% f>40%] sparse detail ; weight + an intensity AND a focus condition
The bracket may sit before or after the bullet dash ([<10%] - grass and - [<10%] grass both work).
A condition is a hard include/exclude evaluated before any probability roll — it is deterministic, not
a gate. A bracket whose contents are not a valid weight/condition spec (e.g. [[castle]], [deemph],
[a:b:0.5], the salt literal) is left untouched as payload, exactly as before.
3. Auto-scaling (the engine's part)
On top of the explicit conditions, intensity scales the probabilistic machinery so one dial thins or thickens a whole generator:
- Gates — every probability gate is multiplied by
intensity/100. A50%bullet at40%intensity rolls20%; a default-bullet (50%) at the default 50% intensity rolls 25%. At100%intensity gates fire exactly as authored. Not scaled: plain (always-on) lines, and theotherwiseelse-branch (it still runs whenever its paired gate failed). An explicitotherwise NN% chance:is scaled (it is a real probability). - Counts —
repeat N times,repeat A to B times,one of, andN ofscale their counts byround(count × intensity/100).repeat 3 times→ 2 copies at 50%, 3 at 100%.one ofsurvives at the default (round(1×0.5)=1) but can resolve to nothing at low intensity (round(1×0.3)=0) — intended: low intensity means less of everything. Counts never go negative or exceed the option pool.
Auto-scaling is multiplicative with the conditions and weights, not a replacement: a line can be weighted, conditioned, and scaled at once.
Note on the default. Because the default intensity is 50% and gates auto-scale, an un-dialed generator renders lighter than a hypothetical "100% = as-authored" default would. This is deliberate (50% = a neutral middle the author can dial up or down). If a different feel is wanted, retune
DEFAULT_INTENSITY.
4. The keyword tokens — $intensity (note the $ sigil)
So the text can react too (not just the structure), intensity is interpolable inline in any .dpl
payload. The tokens use a $ sigil (not {…}, which means {list}):
| Token | Expands to | Example at 50% |
|---|---|---|
$intensity |
the percent (the dial is inherently a percent) | 50% |
$intensity-word |
the magnitude word | normal |
(There is no $intensity% — the dial is already a percent, so the bare $intensity carries the %.)
$intensity-word amount of grass ; "normal amount of grass" at 50%, "ultra-tiny" at 20%, "immense" at 85
a $intensity-word cluster of clouds
detail level $intensity ; "detail level 50%"
The matching $focus, $focus-word tokens read the focus dial (see
focus-design.md).
The word scale. $intensity-word is a 100-step scale — one word per percent, least → most,
centred on 50 ≈ normal. It runs barely-there / near-zero / speck at the bottom, through the
tiny family and normal in the middle, up to huge / colossal / mega / beyond measure at the
top (curated to size / amount / scale / proportion terms). The full list is the INTENSITY_WORDS array
in engine/core/dpl/dpl.js — edit it there to retune a word.
These tokens are resolved in the DPL inline renderer (where intensity is known), so they only carry meaning inside a generator — not in the raw prompt box, which has no single intensity.
4a. Relative / derived intensity — ±NN%
A generator often wants to base a value off the intensity it was handed, not just echo the one number.
Any intensity reference may carry a signed modifier — a percent of the value (+25 → ×1.25, -25
→ ×0.75 — "25% more / less of the intensity"), clamped to 1–100:
$intensity-word +25% ; the word for 25% more intensity (62→large at base 50)
$intensity -10% ; the percent, 10% less (45% at base 50)
$intensity +50% ; the percent, 50% more (75% at base 50)
{#weather i+25%} ; render weather at 25% MORE than this generator's intensity
{#clouds i-40%} ; clouds at 40% less
{#clouds f+25%} ; relative on the FOCUS dial
Relative refs ({#name i+25%} / {#name f-25%}) are converted to an absolute, prefixed
{#name iNN% fNN%} inside the DPL renderer (which knows the base), so the flat downstream resolver only ever
sees absolute, prefixed percents. An absolute {#name i80%} (no sign) passes straight through. Relative
modifiers are a DPL-authoring feature; they have no meaning in the raw prompt box.
5. Coverage / edge cases
{#name}with no percent, top-level or nested → 50%.0%→ 1%;>100%→ 100%.- A condition that fails removes the line deterministically (before the gate).
[[castle]],[deemph],[a:b:0.5],[1234567890](salt) → unchanged payload (not weight/condition).- JS sidecars (
script:,{js:},insert js:) receive intensity / focus as the 4th / 5th argument.
See also
focus-design.md— the sibling dial (f-prefix,[f<NN%],$focus).layering-design.md— global single-layer auto-merge / dedup + thestackingflag.dpl-design.md— the base language this extends.engine/core/dpl/dpl.js— renderer (conditions, scaling,$intensity/$focustokens).engine/core/stages/block.js—{#name iNN% fNN%}parsing + threading + dedup.