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_loveemma-love) per the same rule used for scene IDs. The migration report surfaces any identifier that couldn't be migrated cleanly.

See also

  • set — assignment verb
  • if — conditional routing on a variable expression