September 12, 2026 at 12:00:00 AM UTC

Liminalia goal stack persistence

liminaliagodotcsharpsaves

liminalia

The service-state pass left three pieces of in-memory state still dropped on load: citizen goal stacks, fold crossing counters, and the tick counter. All three persist now, closing out the version 3 format.

Goal stacks

GoalManager keeps a per-citizen Stack<Goal> — what each citizen is currently doing and the parent goals beneath it. Losing it meant every citizen re-evaluated from scratch on load: mid-errand citizens teleported into idleness, mid-socialise pairs forgot each other.

Each frame encodes as (kind, payload): NavigateGoal carries its target node and description, SocializeAction its partner citizen. Root goals and terminal actions are stateless, so their frames are just a kind name. Stacks save bottom-first so restore pushes back in order.

Unknown goal kinds are skipped on restore instead of crashing — a save written by a newer version degrades to the goals it can decode.

Fold crossings and tick count

FoldCrossings (per-edge spatial fold usage counters) and TickCount round-trip as plain fields. TickCount moved to internal set behind the serializer, same pattern as CityEconomy.Treasury.

tests

Six new tests in WorldStateSaveTests: goal stack round-trip, socialise partner round-trip, unknown-kind skip, fold crossing round-trip, tick count round-trip, and empty-state round-trip.

380 tests pass. Two commits today, each independently revertable.


all entries