Skip to content

Rea Language — Cheat Sheet

Plain text is valid content. Just write.

Two Core Symbols

The entire Rea language builds on two characters:

SymbolPurposeRemember
{ }Commands — everything that "does" (logic, variables, control)Curly = code
[ ]References — everything that "points" (links, media, anchors)Square = link

Everything else is story text.


Text & Formatting

rea
Plain text. Just write.

_italic_     *bold*     _*bold italic*_     `monospace`
{underline begin}underlined{end underline}
{strike begin}strikethrough{end strike}

Structure:

rea
# Chapter        ## Section       ### Scene
= centered      > right-aligned  < forced left
| blockquote     || nested quote
---              Horizontal rule (1–5 dashes = 5 weights)

The first character after [ determines the type:

PrefixTypeExample
(none)Link[Continue > #forest]
!Image[!Forest map < media/map.jpg]
>Video[>Intro < media/intro.mp4]
?Audio[?Rain < media/rain.ogg, volume=0.5, loop]
#Anchor (define)[#forest]
[[Part gate[[ story/0005-forest.rea ]] (ends the part)

For a link ([text > target]), the first character of the target (after >) picks the destination:

Target prefixTypeExample
#Anchor[back > #forest]
(file/path)Part[on > story/0004-kingdom.rea]
^Footnote[dialect > ^Old Elvish, nearly lost.]
*Hint[the tower > *A nudge.**A firmer hint.]

Arrow direction: > = where the link goes, < = where the source comes from.


Variables & Printing {set} {name}

rea
{set player.gold = 100}              Number
{set player.name = "Aria"}           String (always double-quoted)
{set player.items = ["sword", "map"]} Array
{set stats = [hp=100, dex=8]}        Named items

Hello, {player.name}! You have {player.gold} gold.
{player.gold > 50 ? "rich" : "poor"}

Domain prefixes (read-only platform data): reader.* story.* world.* device.* group.*


Control Flow

rea
{if player.gold > 10 begin}         {for item in player.items begin}
  You have enough gold.                - {item}
{else if player.gold > 0}           {end for}
  Still have something.
{else}                               {while fuel > 0 begin}
  Broke.                               Keep going...
{end if}                               {set fuel = fuel - 1}
                                     {end while}
{switch weapon begin}
  {case "sword"} Melee.              {case "bow"} Ranged.
  {default} Fists.
{end switch}

Choices & Branching

rea
* [One-time choice]                  Disappears after selection
  Text after choosing.

+ [Sticky choice]                    Always available
  Text after choosing.

* {player.gold >= 10} [Buy potion]   Conditional choice
  {set player.gold = player.gold - 10}

* * [Nested choice]                  Second level

- Gather point                       Branches reconverge here
-> anchor_name                       Divert (jump)
->-> section_name                    Tunnel (jump + auto-return)
* ->                                 Fallback (auto-selected when nothing remains)

* hidden [&card_id] ...              Hidden choice — no button; fires via free-text or scan/mark/listen

{menu select=2 begin}                Exploration menu — waits for 2 picks
* hidden [&qr_door] ...              Hidden option — no button, wakes only by activation
{end menu}

{storylet bench_secret begin}        Triggered storylet — the world deals the card
  trigger: scan                        Input kind: scan, listen, text, nfc, ... (open set)
  match: "^REAST-BENCH-.*"             Optional regex on the input value
  ...                                  Plays as a side path, returns to the main story
{end storylet}

Functions

rea
{function greet(name, title = "adventurer") begin}
  Hello, {name} the {title}!
{end function}

{greet("Aria")}                      Call (renders text)
{set dmg = damage(10, 1.5)}         Call (returns value)

Built-ins: abs min max round random(1,6) clamp length upper lower trim contains replace split join append remove shuffle sort


Extensions (.rext)

rea
{use "extensions/inventory" as inv}   Import a bundled extension (path omits .rext)
{inv.total_weight()}                  Call an exported function
{use "std/dice" as dice}              Standard library — always available, offline
{dice.roll(2, 6)}                     std/dice: d(sides) roll(n,sides) advantage/disadvantage

See When rules differ in .rext files for the language rules inside a .rext, and the engine's .reast package format reference for archive mechanics.


Localization & Dates

rea
{plural(count, one="{} coin", other="{} coins")}   CLDR plural, host locale
{select(pronoun, he="his", she="her", other="their")}
{ordinal(3)}                          "3rd" (en only); other locales get "3"
{formatNumber(1234567, "sk")}         Locale number format (2nd arg = locale)
{formatDate(world.date, "long")}      style: iso | short | medium | long | full
{formatTime(now(), "short")}   {formatDateTime(now(), "iso")}

The host supplies locale and formatting policy. calendar() is specified but not yet implemented.


Dialogue

rea
@elena: "Follow me!"                Speaker attribution (with quotes)
@narrator: The path grew dark.      Narrator (no quotes needed)

Narrative Tools

rea
{once begin} First visit. {then} Return visit. {end once}

{first|second|third}                 Sequence (stops at last)
{&a|b|c}                            Cycle (loops forever)
{!once|twice|done}                   Once-only (then empty)
{~opt1|opt2|opt3}                    Shuffle (random)

Cooperative Reading

rea
{define role scout begin}            Role definition
  max: 1
{end define}

{vote timeout=60 begin}              Group voting
  * [Go left]   * [Go right]
{end vote}

{whisper to="captain" begin}         Secret message
  I see guards.
{end whisper}

{broadcast begin} Everyone hears. {end broadcast}
{wait readers=all begin} Waiting... {end wait}
{set shared.score = shared.score + 1}  Shared variable

Real-World Interactions

rea
{require gps}                        Require sensor
{require nfc optional}               Optional sensor

{waypoint bridge, @@48.14;17.10/50 begin}
  You stand on the old bridge.
{end waypoint}

{timer duration=30, on_expire="-> timeout" begin}
  Hurry!
{end timer}

Voice & Audio

rea
{voice speed=5, pitch=5, emotion="whisper" begin}
  The cave echoed with whispers.
{end voice}

{stop ambient_music}

Cards (Characters, Items)

rea
{define character elena begin}
  name: Elena Voss
  image: media/elena.png
{end define}

[@elena]                    Character reference
[$golden_key]               Item reference
{give golden_key}           Give item to reader
{take golden_key}           Remove item from reader
{play ability_card}         Play a card → runs its on_use hook
rea
{coins gold="Dukát" silver="Groš" bronze="Halier"}  Rename coin tiers
{coins silver_per_gold=5 bronze_per_silver=4}        Redefine ratios
{earn gold 2}               Add 2 gold (1 gold = 10 silver = 100 bronze)
{spend bronze 3}            Spend 3 bronze (breaks higher coins as needed)
{if reader.coins.total >= 100 begin} ... {end if}    Check wallet value
rea
{define cardset ability begin}   Declare a custom card set/category
  name: Ability Cards
  use: Play to apply the bonus.
  {on_use begin}                 Hook runs for every card of the set
    {set ability_count = ability_count + 1}
  {end on_use}
{end define}

{define ability spinach begin}   A card belonging to the set
  name: Spinach
  strength: +2
{end define}
rea
{define action door begin}       Real-world activation fields
  scan: ^REAST-DOOR-.*             QR/barcode payload (regex)
  mark: emb1:Zk3q…                 Drawn mark signature (opaque — never hand-edit)
  listen: open the door            Speech transcript (regex)
{end define}

Input & Interaction

rea
{input name=player_name, placeholder="Your name"}
{input name=guess, type="number", min=1, max=100}
{input type="action", placeholder="What do you do?"}   Free text matched to the pending choices
{button label="Continue", target=next_chapter}

Comments & Author Tools

rea
{// Single-line comment}
{comment begin}
  Multi-line comment — readers never see this.
{end comment}

\{not a command\}                    Backslash escaping
{raw begin} Everything literal. {end raw}

{todo: Fix this scene}               Warning in dev mode
{strict on}                          Show all warnings

Rules to Remember

  1. { } = action, [ ] = reference — that's the whole language
  2. begin / end — all block commands use this pair
  3. Single = for comparison (not ==), assignment is always {set x = ...}
  4. Domain prefixes separate author variables (player.*) from platform (reader.*)
  5. * = one-time choice, + = sticky choice, - = gather (reconverge)
  6. -> = jump, ->-> = tunnel (jump + automatic return)
  7. First char in [ ] decides media/anchor: ! image, > video, ? audio, # anchor; in a link, the target prefix ^ = footnote, * = hint
  8. Plain text is a valid story — you add syntax only when you need it