FolioTier 1
variables
Project state — how Folio variables are typed, declared, and referenced.
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"
Identifier rules: lowercase, dot- and hyphen-friendly
(emma-affection, stats.love). The full pattern is
[A-Za-z_][A-Za-z0-9_.-]*. Subsystem references like stats.love
share the same identifier shape but resolve through the subsystem
registry rather than the bare variable table.
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 - Membership:
in - Subsystem references —
stats.<name>,inventory.has(<id>)(Phase 6)
The grammar is intentionally narrow. Expressions are pure — no
function calls (except subsystem accessors like inventory.has),
no side-effecting operations, no __getattr__ trapdoors. If you
can't write what you need, the answer is a new subsystem accessor or
verb, not an escape hatch.
Scope
Variables in v1 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.
Subsystem state (Phase 6 — Stats, Locations, Time) gets its own
scope inside its subsystem and is referenced as stats.<name> /
locations.<name> / time.<unit> rather than as bare variables.
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 migration report surfaces any
identifier that couldn't be migrated cleanly.