Building a puzzle that never rolls a die: in SilkWard every move produces the same outcome
A deterministic puzzle on a node-and-edge board, offline-first; one TypeScript core feeds 36+6 levels to both web and mobile.
What it does today
Lets the player solve 36 levels + 6 hidden levels on a node-and-edge board through fully deterministic moves, with no luck or reflexes involved; a single TypeScript core drives both the web (PWA) and mobile (iOS/Android) client at once. Playable in the browser at silkward.com.
- Started
- September 2026 — September 2026
- Left Labs
Form
Technologies
Turn-based puzzles filled a gap Hitman GO left for me: few rules, zero luck, the feeling of building an outcome by thinking it through. I built SilkWard into that gap — a puzzle that moves across a node-and-edge graph, told mostly without words.
No luck, no reflexes, no surprise rule
These three principles sum up the game’s design philosophy. Every move you make on the node-and-edge graph also triggers the enemies’ next step, and that step follows the same deterministic rule. Lose a level and the reason is never a bad roll — it is the move itself. 36 levels + 6 hidden levels span three acts.
One core, two platforms
The rules engine was written with zero dependencies: it knows neither the DOM nor React Native, only plain TypeScript. That purity lets the web client (a Next.js-based PWA) and the mobile client (Expo) share one behavior instead of two — the rules engine and the solver live in one shared core package, level data lives in a separate data package, and interface text lives in its own language package; only the interface layer is platform-specific.
How a level gets calibrated
A new level is not done once a single file is written: it is designed with an editor tool first, then exported into the data package as a level definition. The level’s minimum move count is never guessed by hand — it is the number a BFS-based solver tool finds, and level design is then calibrated against that number. A validation command re-checks that this number is still correct on every change, so the “par” value never quietly drifts out of date.
The rules engine itself is held to the same discipline: the core package bans access to a random number generator or the system clock — determinism is enforced by a build-chain constraint, not a code comment. An optional AI art pipeline also sits outside the core code, confined to a separate development-tools directory; it was tried, but its output never passed review, so it never shipped — the art in the playable build is fully procedural, and the game’s runtime carries no AI client at all.
A game that almost never touches the network
The first load caches SilkWard’s shell (interface, code, art); from then on
play makes no network request. The one exception is sound: the 26 audio
files are not preloaded — each one is downloaded once the first time it
plays and cached permanently, so the airplane-mode guarantee only holds from
the second session onward; with no network on the very first session, the
game just plays silently instead of crashing. That is not an “offline mode”
bolted on afterward; it was a constraint set from the start: fetch is
banned by lint rules in the core and app layers, and XMLHttpRequest use is
caught by a separate source-scanning test — the constraint lives in the code
rather than being an honor-system promise.
The record sits here as halted: the game is playable today at silkward.com, but no further development is happening on it.