Log inGet started
World

The Eighth Ketyl

Branchmain
Branchesmain
Commite99ff0a216

README.md

Conductor

The rules of THE EIGHTH KETYL. One component, on the Game entity, and the only writer of Still.state.

The state machine

title ── "start" ──▶ intro ──(9s, or any control)──▶ play
                                                      │
                       the plate's growths are gone ──▶ cleared
                                                      │      │
             wetness hit maximum ──▶ quenched     ascend     │
                                                      │      │
                             plate 8 went clean ──▶ sealed   │
                                                      ◀──────┘

cleared is a playable phase. The plate is done and the riser is lit, but the ketyl still has to drift to it and commit, so movement, discharge and surge all answer during cleared exactly as they do during play. Still.state.phase distinguishes them so a screen can say "the way up is open" without the game having stopped.

paused remembers what it interrupted and returns to it.

What it emits

phase · runStart · plateEnter · plateCleared · riserOpen · ascend · sealed · quenched · charge · wetness · discharged · surged.

charge and wetness are announced on a real change rather than every frame; a bar that draws every frame should read Still.state directly instead.

What it listens for

EventFromWhat it does with it
uiIntent(name)presentationstart · resume · restart · quitToTitle
growthCount(alive, total)blennomawrites the count; alive == 0 lights the riser
soaked(amount)blennomaamount is wetness points — a pool sends its per-second rate times dt, a droplet sends its whole lump
sodiumTaken(pos)blennomacredits Still.SODIUM_RESTORE charge

It does not know what a blennoma is, where a droplet fell, or what any screen says. A discharge goes out as discharged(pos, dir) and the blennoma slice decides what stood in the arc.

When nobody reports a plate

plateEnter(n) asks the blennoma slice to build plate n's field. If no growthCount arrives within KetylCore.GROWTH_GRACE seconds the plate is treated as empty and the riser opens, so the column stays climbable while that slice is mid-build — and it says so at WARN, because a riser that opens for no reason is otherwise indistinguishable from a plate that was genuinely cleared.

Callable

The same decisions the controls reach, by name, for a test or anything that has to drive the game without a pair of hands:

local cond = Still.anchor("Conductor").component.get("Conductor")
cond:startRun(false)   -- begin a run, skipping the opening
cond:toTitle()
cond:discharge()
cond:surge()
cond:ascend()
cond:togglePause()