Released v0.8.0

SAGBAL
— a stratum on Kimetron Isle

A movement-arbitration layer.
Physical truth below, destination meaning above.

Open the GitHub repo

There was no layer in between.

What Kimetron Isle knows is only whether something can be placed here, and what it would overlap — the physical truth of placement and collision. By absolute rule, it is never taught what a "destination", a "gate", or a "priority" means.

But what an app actually wants to know comes after that: who goes first, whether it is jammed right now, who yielded, who is about to blow. In other words — the events of movement. With nothing in between, you either write all the semantics into your app, or teach meaning to a physics engine.

SAGBAL is the layer that sits in the middle. Stacked on top of Kimetron's truth, it gathers every unit's "I want this step" each tick, auctions the overlaps, detects deadlocks, and eases jams — assembling the phenomena of movement and handing them upward as facts.

Facts flow up, decisions flow down

App ──API──▶ SAGBAL ──API──▶ Kimetron. What each layer owns is cleanly separated.

  • App — meaning Destinations, priorities, detours. What a "gate", a "street", or a "cul-de-sac" is exists only here — routes are handed down as Goal.via lists
  • SAGBAL — phenomena Intent registration, score auctions, yield hysteresis, deadlock detection and mutual sidesteps, diffusion out of full blockage, crowd-density facts
  • Kimetron — truth The physics of placement, collision, occupancy. Whether two units may overlap or a wall can be crossed is decided only here — and since every move ends in tryMove, the truth is the same for everyone

Raw engine events are never swallowed by the layer — they pass through to the app untouched. What SAGBAL returns are denser facts, not imposed interpretations.

What happens inside the layer

  • Intents and the consensus Every tick, each unit's desired step is collected; where desired space overlaps, scores bid for it. The consensus expresses priority — it never bends physics
  • Yield hysteresis The losing side is suppressed for a while and steps back — the winner threads the gap it opened
  • Keep-side traffic (a world rule) A jammed pair sidesteps to a fixed side of each one's own heading. Not a per-pair negotiation but a traffic convention, so opposing flows settle into lanes (Policy.keepSide)
  • Head-ons go to a vote Mutual deadlocks never bypass the auction — with a score gap only the loser sidesteps; on a tie, both retreat symmetrically
  • Full blockage diffuses A unit that wants to move but finds every direction blocked broadcasts a boxed signal — nearby units are gently pushed away by a distance-decaying repulsion field (diffuse)
  • Crowd facts Rising local density surfaces as crowded, and an unresolvable one as full. What to do with the fact stays app-side
  • The player joins the auction A drag registers as an intent via setIntent — wanderers yield to your hand like any other mover. The layer never moves the external hand itself
  • Stress and explosion A chronically jammed unit accumulates stress and explodes past a threshold — a +100 score bonus that wins the next auction outright. Moving again bleeds stress off and re-arms it
  • Individual strides Units do not all move at the same speed. Give a goal a Goal.step and the unit pursuing it walks at its own stride — wounded, hauling, elderly; what it means stays app-side, the layer just carries the number. Intents, sidesteps and the repulsion shove all respect each unit's own stride

The street-grid demo

Six slimes run between destination posts through a maze of streets left by a 3×3 block of buildings — head-ons in the corridors, yielding at junctions, diffusion in the cul-de-sacs. The event log shows it all, color-coded by layer.

SAGBAL demo: slimes roaming a street grid with a three-color event log

In the second half of the clip, the player P is dragged into the middle of a street and parked. Wanderers treat the hand like any other mover — watch uE blocked by uP pile up until one of them finally explodes and pushes through.

The name

SAGBAL fuses the Sumerian sag (front, first) and bal (to cross, to switch) — the layer that crosses whoever goes first. The passing-each-other is built into the word itself.

If Kimetron is ki (place) plus metron (measure) — the measuring ground — then SAGBAL is the stratum of crossings laid on top of that ground. A stratum on the isle.

Honest status

v0.8.0 is usable as a movement-arbitration layer — it is not a game engine, and the remaining gaps are listed honestly.

  • Rendering, input, and pathfinding are app-side The layer owns arbitration and event assembly only — the demo's local routing (a rollout a few bodies ahead, to the next junction) is app code
  • Measured up to hundreds of agents Contention and density scans are neighborhood-limited via a spatial grid (v0.7.0 — wake rushes no longer stall the frame). A dense point-crowd still costs local-quadratic work, and hundreds-scale production use is only lightly tested
  • No swept collision Placement validation is Kimetron's correct answer — a mover that travels more than a body-length per tick can tunnel through walls. By design
  • Not on npm Vendored in the repo for now; packaging waits on demand

Source

MIT licensed. TypeScript + React, a framework-agnostic middle layer.

github.com/cuculhart/sagbal