# tongue.book — Hernsew, and the phrasebook that grows
`require("tongue.book")`
Hernsew is the tongue the herons of Yowe Fen speak, and this module is all of
it: twelve glyphs, one rule of grammar, five calls built out of them, and the
phrasebook the Lingster fills in as the run goes on.
It is a **model**. It draws nothing. `screens` renders what is in here.
## The tongue
Twelve morphemes. Six are **roots** — things. Six are **affixes** that hang on
a root and change it. A word is built by one rule:
```
[prefix-] root [-suffix]
```
and a phrase is words in the order they are meant.
| | | |
|---|---|---|
| `kraa` | water | the tide, the sea coming in |
| `sinn` | bird | a hernsew; a bird says it of itself |
| `wold` | walker | the two-legs. You. |
| `mell` | flock | the many |
| `thrup` | stands | a standing-place, a stage-post |
| `gis` | shelter | a fold of stone; the high ground |
| `-eth` | rises | that thing rises, comes, grows |
| `-ok` | falls | the mirror of `-eth` |
| `-un` | not | alone, with nothing to hang on: *no* |
| `-ar` | ? | makes a question of the phrase |
| `ha-` | my | belonging to the speaker |
| `ne-` | your | belonging to the one spoken to |
So `ha-kraa-eth` is *my-water-rises*, and it can be read by anyone who has met
`ha-`, `kraa` and `-eth` separately. That is the whole design: **meaning
composes, so a fifth glyph can be reasoned about from four.**
The Lingster begins the run knowing `kraa`, `sinn`, `wold` and `-eth`. The rest
are earned at the posts.
## The five posts
| post | call | teaches |
|---|---|---|
| The Reedgate | `Sinn thrup. Kraa-eth.` | `thrup` |
| The Sluice | `Mell-ok. Kraa-eth.` | `mell`, `-ok` |
| The Drownway | `Ha-thrup. Ne-mell-ok.` | `ha-`, `ne-` |
| The Eelbank | `Ha-kraa-eth. Ne-thrup-ok.` | **nothing new** |
| The Last Post | `Wold. Kraa-eth. Ha-gis ne-gis-ar?` | `gis`, `-ar` |
The Eelbank is the point of the game. Every scrap of that call was earned at
the three posts before it, so the reading is *deducible* rather than
remembered — and a player who gets it can say why.
## The glyphs are marks, not letters
Roots are pictographic — `kraa` is two running waves, `wold` is two legs under a
head, `gis` is a roof over a base, `sinn` is a bill, an S-neck, a body and two
legs. Affixes are single strokes: a rise, a fall, a cross, a hook, a stem with
one dot or two.
Every glyph record carries the mark two ways:
- **`svg`** — a complete SVG document, already stroked in the phrasebook's ink.
Hand it straight to an `svg` widget: `{ type = "svg", props = { svg = g.svg } }`.
It carries only a `viewBox` (120 × 150), so it scales to whatever box it is
dropped into. In a gloss, an **unearned** glyph's `svg` comes back dimmed —
it is on the page, and it is the thing the player cannot read yet.
- **`path`** — the bare path data in a 0–100 box, for restyling. It is meant to
be **stroked**, never filled. `Book.glyphSvg(id, { stroke, width, size,
opacity })` builds the document with your own ink.
An open encounter carries `glyphs` — the marks of the call, in order, as full
glyph records — and `glyphIds`, the same list as bare ids.
## The interface
```lua
local Book = require("tongue.book")
Book.open(stationId) -- open the beat at a post -> Encounter?
Book.answer(optionId) -- give a reading -> boolean (true = right)
Book.close() -- drop the open encounter
Book.current() -- what is open, or nil
Book.gloss(enc?) -- word by word, with `?` where a glyph is unearned
Book.learned() -- the phrasebook, in the order earned
Book.alphabet() -- every glyph, `known` flagged
Book.glyph(id) -- one glyph
Book.glyphSvg(id, o) -- one mark as a ready-to-draw SVG document
Book.knows(id) -- boolean
Book.encounters() -- all five, unopened, for the voice bake
Book.state() -- { encounter, learned, attempts, total }
Book.reset() -- back to the starting phrasebook
```
A **right** answer teaches that post's glyphs, closes the beat and raises
`ANSWERED(stationId, true)`. A **wrong** one raises `ANSWERED(stationId,
false)`, marks the option tried and **leaves the post open** — the bird is
still in the way, and the tide has just cost you. After two wrong readings the
encounter's `hint` is worth putting on screen.
`Book.gloss()` is what a screen draws: one entry per word, each carrying its
glyph parts, their marks, and `meaning = nil` where the player has not earned
the glyph yet. That hole is the puzzle.
## What it writes
`Rules.state[Rules.KEY.ENCOUNTER]` — the open station id, or nil.
`Rules.state[Rules.KEY.LEARNED]` — how many glyphs are in the phrasebook.