FolioTier 1
when
Conditionally run a body of inline steps in place; chain `else when <condition>:` arms and a final `else:` for first-match branching, or end a body with `jump` to route.
Use when to gate a whole run of steps on a single condition instead of tagging every line with its own if. It reads like a normal branch in the script: the condition is checked once, and if it holds, the indented body plays start to finish before the scene continues; if it doesn't, Folio skips straight past the whole block. Reach for it whenever a chunk of dialogue, staging, or audio only makes sense in one state of the story - a callback line that should only fire if the player saw an earlier scene, an alternate sprite/frame pairing for a route flag, that sort of thing.
Chain else when and else off the same when to get first-match branching across mutually exclusive arms, checked top to bottom - the moment one condition is true, later arms are skipped even if their own condition would also hold. else has no condition of its own; it catches whatever every arm above it missed, so it always has to come last.
Under the hood each line in a body gets the block's condition (or accumulated negations, for else when/else) stamped onto it, which is why a body line can carry its own if tail and still be doubly gated - but you rarely want that; write the gate once at the header and let the body inherit it.
If nothing matches and there's no else, the scene simply continues after the block - there's no error for an unhandled case, so double check whether you actually want a fallback arm. End a body with a jump when the branches should route to different labels rather than just play different inline steps in the same scene.
Parameters
| Parameter | Kind | Required | Default | Notes |
|---|---|---|---|---|
| condition | expression | yes | - | Bounded expression evaluated against project state - bare identifier, `not <ident>`, comparison, `and` / `or` (see the `variables` reference for the full grammar). When the condition is true, the body runs in order; when false, the body is skipped and the scene continues past the `when` block. |
| body | identifier | yes | - | One or more indented Folio statements (say / narrate / show / hide / bg / set / music / sound / ...). Each line inherits the `when`'s condition under the hood, so a body line with its own `if` tail evaluates both - but in practice you write the gate once at the `when` header. |
| else when | identifier | no | - | Optional chained arms: any number of `else when <condition>:` lines at the same indent as the `when` header, each followed by its own indented statements. Arms are checked first-match, top to bottom - an arm runs only while every condition above it failed AND its own condition holds (the accumulated negations are stamped on each line under the hood). The final `else:` (if any) must come after every arm. |
| else | identifier | no | - | Optional otherwise-branch: an `else:` line at the same indent as the `when` header, after the body and any `else when` arms, followed by its own indented statements. Those run only while every condition above failed - the negated gates are stamped on each line the same way the body inherits the positive one. No condition of its own; nesting follows indent. |
Canonical example
when day2-basketball:
sprite show day20-dylan-amber frame "189"
say "Sa": "I just can't approve that."
sprite show day20-dylan-amber frame "190"
say "Dy": "She wouldn't have missed a basket."if day2_basketball:
show day20_Dylan_Amber 189
sa "I just can't approve that."
show day20_Dylan_Amber 190
dy "She wouldn't have missed a basket."when is Folio's conditional block. The header when <condition>: opens a block; each indented line is a step that runs
only when the condition evaluates truthy. The scene continues past the
when block either way - falsy conditions skip the body without
branching anywhere.
An optional else: at the same indent opens the otherwise-branch:
its indented lines run only while the condition is false. Both branches
stay inline - the scene flows on past the whole construct.
when gasp:
narrate "You heard it too."
else:
narrate "The room stays quiet."
To make the conditional outcome a jump to a different scene, put a
jump inside the body - and, for a two-way branch, another jump
under else::
when has-key:
jump unlock-door
else:
jump rattle-door
Equivalently, pair a guarded jump <a> if <cond> with a plain
jump <b>. Either shape replaces the old standalone routing
conditional.
Notes
The condition follows the same closed grammar as any Folio guard (see
variables) - bare identifier, not <ident>,
comparison with a bool/numeric literal, or and / or combinations. The
importer's deterministic stage only translates the conservative subset
(no compound and / or, no method calls, no dotted accessors);
unsupported shapes fall through to the AI lane rather than dropping
the guard.
Nesting works the same way a nested Ren'Py if would: a when inside a
when evaluates both conditions before running the inner body. The
runtime expands these at scene-load time so the player's step cursor
never has to descend - each child step's effective condition is the
AND of every surrounding when; an else: line's children get the
NOT of their when's condition (AND-combined with any outer gates).
else: takes no condition, must sit at the same indent as its when,
and belongs to the nearest when at that indent.
when day-saturday:
when invited-to-party:
bg bg-party-night
say "Emma": "I made it."
The importer maps Ren'Py's if <expr>: with an inline body (no elif
/ no else) to a Folio when block on a per-fragment basis (Gap 1,
Phase 8). Ren'Py's if/elif/else chains lower to first-match
guarded arms (each step carries its own condition); a two-arm
if/else whose branches are pure jumps reads back as a when body
jump paired with an else: jump, or as two guarded jumps.