Guide

Give a character a personality and limits

Three things you author, in one file per level, lw.manifest.json. Everything else is computed. The file is checked when it loads, never at runtime.

Personality

One sentence in plain English becomes temperament and an archetype: guard, owner, elder, child, drifter. The archetype sets defaults for what they reach for; the sentence is written once and never re-read by a model.

"characters": { "Hulda": { "persona": "Innkeeper of the Bannered Mare. Proud of her prices, quick to bar a thief." } }

What they can do: can

A narrowing of the level's verbs. Anything not listed is impossible for that character, permanently: not under fear, not under an order, not inside a plan, not from a scene.

"verbs": [ { "name": "greet" }, { "name": "serve" }, { "name": "report" }, { "name": "refuse_service" }, { "name": "confront" }, { "name": "watch" }, { "name": "say" } ],
"characters": { "Hulda": { "can": ["greet", "serve", "report", "refuse_service", "watch", "say"] } }

Hulda cannot confront, ever, because it is not in her list. A can that names a verb the level does not have is a load error, not a silent grant. No can at all means the archetype's default, and the load report says what was assumed.

What they must never do: never

Rules over four namespaces: self., target., place., slice.. Grammar: and, or, not, parentheses, comparisons. A field your feed does not supply makes the rule false; a rule can never fire on a guess.

"never": [
  { "verb": "confront",   "when": "target.isChild",              "name": "no-confronting-children" },
  { "verb": "draw",       "when": "place.temple",                "name": "no-steel-in-the-temple" },
  { "verb": "leave_post", "when": "slice.morning or slice.noon", "name": "shop-hours" }
]

Places, by type

"places": { "temple": { "loctypes": ["temple"] }, "street": { "default": true } }

loctypes matches every temple in the game in one line. interior and exterior are built in. The full field list is in Manifest.

Check it

lw dev --mock loads the manifest and prints the load report. python -m pipeline.verb_manifest --check lw.manifest.json does the same without starting anything.

Next: Tell characters what happened.