Wit

An interactive script

Author a gamebook page where character stats, a wounded check and an inventory are data and logic in the document — not hand-edited for every state.

Step 1 — Character state as data

A record holds the stats; a collection holds the inventory. A record value may hold commas and may itself be a list.

#hero: { name: Vera, gold: 12, status: wounded } !!
#pack: [ torch, rope, a letter you should have burned ] !!

Step 2 — Scene vocabulary as definitions

Each definition declares its parameters in a header, so a use can pass them by position. None has a ::body:: slot, so uses need no close.

#scene(title)
(h2 ::title:: h2)
scene#

#warn(text)
(aside ⚔ ::text:: aside)
warn#

#choice(goto, text)
(li → ::text:: (to ::goto::) li)
choice#

Step 3 — Scene heading and prose

Put a stat into a sentence with a dot path.

@scene(The Crossroads)

@hero.name, the road forks beneath a broken signpost. You are carrying @hero.gold gold.

Step 4 — A conditional beat

(if @hero.status is wounded)
@warn(You are wounded — the dark path may kill you.)
(end)

Step 5 — Choices and inventory

*Choose:*

@ul
@choice(village, Take the lit path)
@choice(tower, Take the dark path)
ul@

*Pack:*

@ul
(each @pack as item)
(li @item li)
(end)
ul@

Build

wit build scene.wit --fragment

Result.

<h2>The Crossroads</h2>
<p>Vera, the road forks beneath a broken signpost. You are carrying 12 gold.</p>
<aside><p>⚔ You are wounded — the dark path may kill you.</p></aside>
<p><strong>Choose:</strong></p>
<ul><li>→ Take the lit path (to village)</li><li>→ Take the dark path (to tower)</li></ul>
<p><strong>Pack:</strong></p>
<ul><li>torch</li><li>rope</li><li>a letter you should have burned</li></ul>

Pitfalls

  • One comparison: is. A condition is a bare subject (true when defined, non-empty, not false, null or 0) or @x is value. There is no less-than, not, and or or — put such logic in a <% … %> script, or store the result as a field.
  • Model status as text. (if @hero.hp is low) compares against the text low; it will never match the number 8. Store status: wounded, or a flag.
  • Placeholders live in definitions. ::name:: fills only inside a definition body. In prose, use a dot path: @hero.name.
  • A comma in a positional value. @choice(tower, Climb, then wait) is E_TOO_MANY_ARGUMENTS. Name the values: @choice(goto: tower, text: Climb, then wait).

Variations

Gate a choice on a flag such as (if @hero.has_key); emit several scenes from a master file, as in A manuscript in chapters.

See also

Conditionals and Iteration cover the logic in full; Creative writing covers flat scenes.