FolioTier 1
variables
Project state - how Folio variables are typed, declared, and referenced.
Variables are how your project remembers things between scenes. You create one by assigning it an initial value with set, and Folio infers its type from that value - a number literal makes it a numeric variable, true or false makes it a boolean. After the first assignment, the same set verb updates it, and you reference it by name anywhere a value is expected, including the right-hand side of another set.
Reach for variables whenever a story fact needs to outlive the current moment - a relationship score that climbs across many scenes, a flag that marks whether the player found a hidden item, a chapter counter that controls which ending plays. The when verb tests a variable's current value to drive branching, so the combination of set and when is the foundation of almost every meaningful choice in a Folio project.
Folio determines a variable's type at its first assignment and enforces that type afterward, so decide upfront whether a tracker is a number you will do arithmetic on or a flag you will check as true or false. Mixing uses - say, later comparing a boolean with a number - produces a type error. Variable names follow the same hyphen-separated convention shown in has-key; a name with spaces will not parse. Variables are project-scoped, meaning a value you set early in act one is still readable in the final scene, which is exactly the intent for persistent state like relationship scores. Because of that global reach, avoid reusing the same name for unrelated purposes in different parts of the script.
Reference page - variables aren't a verb. This page collects the
rules that govern how set writes them and how if (and other
condition tails) reads them.
Declaration
Variables are declared by first use. The first set against a name
fixes its type - the value 0 makes love a number; true makes
has-key a boolean; a quoted string makes it a string. Subsequent
writes must match the declared type. There is no separate var or
declare step.
set love = 0
set has-key = true
set greeting = "hello"
The first set fixes the type, not the initial value. At project
boot and on Start over, every variable holds its type's default -
0 for numbers, false for booleans, "" for strings. The set
value applies when the scene cursor reaches that set step.
Once a variable is set, it stays set across normal navigation. The HUD back button (undo) restores the variable's value from before the most recent advance, but scrubbing the Forge timeline to an earlier step does not roll back variables - the cursor moves but the variable keeps its current value. Only an explicit Start over clears variables back to their type-defaults.
Identifier rules: lowercase, dot- and hyphen-friendly
(emma-affection, weapon-charge). The full pattern is
[A-Za-z_][A-Za-z0-9_.-]*.
Expressions
Both the right-hand side of set and the condition slot of if (and
the trailing if <cond> tail on most verbs) accept a bounded
expression grammar:
- Numeric literals (
0,42,3.14) - Boolean literals (
true,false) - String literals (
"text") - Identifiers - references to other variables
- Arithmetic:
+,-,*,/ - Comparison:
==,!=,<,<=,>,>= - Boolean:
and,or,not
The grammar is intentionally narrow. Expressions are pure - no
function calls, no side-effecting operations, no __getattr__
trapdoors. If you can't write what you need, the answer is a new
verb, not an escape hatch.
Scope
Variables are project-wide. The runtime carries them across scene
transitions, saves, and loads. There is no per-scene scope and no
per-character scope - character-specific state (emma-affection) is
just a variable whose name encodes the binding.
Notes
The importer maps Ren'Py's default love = 0 and top-level
$ love = 0 lines to set at scene entry. Renames Python's
snake_case → Folio's kebab-case (emma_love → emma-love) per
the same rule used for scene IDs. The read-only migration report flags
inline any identifier that couldn't be migrated cleanly.