Skip to content

Vaynerov Technologies

We don't just develop — we conjure every line of code & pixel.

All articlesDeep dives

Chess in Four Dimensions: Inside the Tesseract Engine

Tesseract went live in the Lab today: full chess on a 5×5×5×5 board, with two species of pawn, pieces that slide through planes and hyperplanes, a deterministic engine running in a Web Worker, and a puzzle pack whose solutions are proved by search before they ship. This is what it took.

Vaynerov TechnologiesThe studio
Published 9 min read
On this page
  1. A board with 625 squares
  2. Eighty directions of attack
  3. An opening position that is a theorem
  4. Counting every move, twice
  5. Making four dimensions legible
  6. An opponent that fits in a Web Worker
  7. Puzzles with machine-checked solutions
  8. Four-dimensional chess over an untrusted wire

Chess variants usually add a gimmick to a board everyone understands. We wanted the opposite: keep the rules recognizably chess, and change the space — from two dimensions to four. The result is Tesseract, the thirteenth game in our Lab, and by some distance the most mathematically demanding thing we have shipped in a browser.

Four dimensions sounds like marketing until you try to write the move generator. Then it becomes very literal: a rook here attacks along eight rays, not four. A bishop attacks along twenty-four. There are two new sliding pieces because 4D space has two new kinds of diagonal, and there are two kinds of pawn because a pawn needs a forward axis and the board now has two spare ones. Every one of those statements had to survive an independently written verifier before we believed it ourselves.

625
cells — 5⁴ lattice
80
attack directions
226
legal opening moves
11.66M
perft(3) nodes, 0 mismatches

Tesseract's search space, verified 2026-07-26 against an independently written generator.

A board with 625 squares

The board is a 5×5×5×5 lattice — 625 cells, coordinates (x, y, z, w) each running 1 to 5. Internally a cell is one integer: idx = (x−1) + 5(y−1) + 25(z−1) + 125(w−1). The renderer uses the same packing, so a cell index crosses the engine/renderer boundary without translation — no coordinate bugs at the seam, because there is no seam.

The classic engine problem of falling off the board gets worse in 4D: every sliding ray has to know where the edge is in eighty directions. Classical 2D engines solve this with a mailbox — a padded board whose border cells are marked invalid — and it turns out the idea generalizes beautifully. Tesseract uses a 9⁴ mailbox: 6,561 32-bit entries, about 26 KB, where the playable 5⁴ board sits two cells clear of every border — exactly a knight's reach. Off-board detection becomes a single array lookup. The alternative, per-square ray tables, would have cost around 350 KB and a lot more cache misses.

Eighty directions of attack

In n dimensions, the natural generalization of chess movement is the set of non-zero direction vectors with components in {−1, 0, 1}. In 4D that gives 3⁴ − 1 = 80 directions, and they split by how many axes move at once: 8 directions change one axis, 24 change two, 32 change three, 16 change all four.

Those four classes are the piece set. The rook keeps class one. The bishop keeps class two — the familiar diagonals, of which there are now twenty-four. Class three belongs to the unicorn, a piece borrowed from Raumschach, the 1907 three-dimensional chess variant — it slides through space diagonals that don't exist on a flat board. Class four belongs to the dragon, our name for the piece that moves along the true 4-agonals, the directions where all four coordinates change at once. Queen and king take all eighty. The knight generalizes too: a (2, 1, 0, 0) leap in any axis pair and sign combination — 48 distinct jumps.

The 80 slide directions of 4D chess, grouped by how many axes move at once. Each class is one piece's territory: rook (8), bishop (24), unicorn (32), dragon (16).

Intuition fails in interesting ways here, so we counted. Summing legal moves for one piece over every empty-board cell: the rook manages 10,000; the bishop 18,000. On a flat board the rook is the stronger slider; in four dimensions the bishop simply has more room. The dragon, lord of the most exotic direction class, musters only 5,664 — the 4-agonals are short and few from most cells — which is why the pair sits on the plate's third row rather than holding a corner. These are not vibes; they are frozen constants in the engine's self-check, and the build fails if the move generator ever disagrees with them.

PieceDirectionsEmpty-board moves (all 625 cells)
Queen8049,664
King8027,936
Bishop2418,000
Unicorn3216,000
Knight48 jumps14,400
Rook810,000
Dragon165,664

Total mobility by piece, summed over every cell of an empty 5⁴ board. In 4D the bishop out-ranges the rook — the reverse of flat chess.

An opening position that is a theorem

Designing a starting position for a board nobody has ever played is a trap: how do you know White isn't mated in four, or that a pawn wall doesn't make the game a draw by construction? We made the position provable instead of plausible. Black's army is the exact point reflection of White's — every piece maps through σ: p → 6−p on all four coordinates. Point symmetry guarantees perfect material and positional balance, and it has a quieter consequence we like even more: nothing starts attacked. If any White piece attacked a Black piece at move zero, symmetry would make the reverse attack exist too, and the position would be a tactical mess. It isn't, and that's checkable.

The opening position is a theorem, not a convention — its balance follows from point symmetry, and the engine verifies it on every build.

The twelve major pieces sit on a 5×5 plate at y=1, w=1 (the king at the center of the first row, the dragon pair on the third), and the pawns answer the strangest design question on the board: which way is forward? Tesseract has Y-pawns that advance along the y axis and W-pawns that advance along w, and both species sit on the two central hyperplanes — the only band of the board where a White pawn stands exactly opposite its Black mirror image. Three army sizes ship (light, standard, dense) by widening the pawn band; standard is 32 pieces a side, the same census as classical chess, which felt right.

Counting every move, twice

A chess engine is only as trustworthy as its move generator, and a 4D move generator has failure modes no human will spot on sight — nobody's intuition flags a missing unicorn pin along a triagonal. So Tesseract is verified the way serious engines are verified: perft, the exhaustive count of leaf nodes reachable at a given depth, computed twice by two generators that share nothing.

The fast generator is legal, not pseudo-legal: it computes checkers and pins once per node by scanning outward from the king, then emits only moves that survive — double check yields king moves only, single check yields capture-or-block, a pinned piece may travel only along its pin ray. The naive generator is deliberately dumb and slow. They agreed on 50,618 cross-validated nodes with zero mismatches; full perft(3) from the opening is 11,661,294 nodes. A separate pawn laboratory — a position built to exercise double-steps, both capture axes, en passant and promotion — adds 559,319 more agreed nodes. And because the whole engine is integer-only with zero floating point in game logic, a frozen 40-ply script must land on the same Zobrist hash in every browser, every build. Determinism isn't a nice-to-have; it is what makes the online mode possible at all.

Making four dimensions legible

The hardest problem was never the engine. It was the screen. A 4D position has to land on a 2D monitor without lying about geometry, and the standard trick — draw a pretty rotating shadow of a tesseract — is useless for actually playing. Our answer is almost embarrassingly flat: draw the 5⁴ lattice as a 5×5 grid of 5×5 boards. The x and y axes live inside each small board; z and w select which board. The mapping is worldX = (w−3)·PITCH + (x−3)·CELL, and the crucial property is that it is affine in all four coordinates: every 4D straight line — a rook ray, a unicorn triagonal, a dragon 4-agonal — projects to a straight line of highlighted cells on screen. Straightness is how your eye learns the geometry.

One affine map, no perspective: x and y live inside each sub-board, z and w select the sub-board. 4D rays stay straight on screen — which is how the geometry becomes learnable.

The camera is orthographic on purpose — perspective would bend that affinity, and it would also break picking, which here is a closed-form inverse of the projection rather than a GPU raycast. The whole field renders as one textured quad (all 25 checkerboards baked into a single canvas texture), sixteen instanced meshes for the armies, five for highlights: about 24 draw calls at worst, on a frameloop="demand" canvas that renders exactly zero frames while you think. For the moments you want the honest shape of the thing, a second view draws the true tesseract — inner cube at w=1, outer at w=5, spinning through an isoclinic rotation — and hands the geometry lesson back to your eyes.

An opponent that fits in a Web Worker

The opening position has 226 legal moves, against twenty in classical chess, and that is the measured branching factor the search has to live with. Search at that width has to be humble and it has to be off the main thread; the master tier thinks for up to 3.5 seconds, which would freeze the tab if it ran where React lives. So the engine runs fail-soft negamax with iterative deepening in a Web Worker, leaning hard on null-move pruning, late-move reductions and futility pruning to survive the width. Four difficulty tiers ship, from an instant 60 ms opponent with deliberately noisy evaluation to a 16 MB-table master that reaches depth six. Even the AI's randomness is deterministic — root move jitter comes from a seeded generator keyed to the game record, so a replayed game replays identically.

Puzzles with machine-checked solutions

Every chess app has puzzles; most have a few broken ones. In four dimensions a broken puzzle would be unfixable by user report — nobody can eyeball a 4D mate-in-3 refutation. So no puzzle ships on our word. Each of the twelve studies in the pack must pass three machine checks: exactness (search to twice the claimed depth finds mate in exactly N, starting with the stated key move), uniqueness (no other first move mates as fast), and forcedness (every defender reply still loses). The guided tutorial gets the same treatment — its eight lessons are proved winnable by playing every legal move of the lesson piece through the real engine. If a lesson can be failed, the build fails first.

Four-dimensional chess over an untrusted wire

Online play runs over a realtime broadcast channel, and we treat that channel as exactly what it is: an untrusted relay. Peers agree a key via ECDH, and every move crosses the wire authenticated — an HMAC over a canonical serialization that includes the protocol version, the match id, the sender's bound 128-bit identity and a ply sequence number. Then comes the check that makes the rest almost decorative: the receiving client re-validates every incoming move against its own legal-move generator. A forged or corrupted move isn't argued with; it is simply illegal, and the deterministic engine means both boards either agree perfectly or detect the desync by Zobrist hash on the very next move.

// A move on the wire: eight digits (from-xyzw, to-xyzw) + optional promotion.
const WIRE_MOVE = /^[1-5]{8}[QRBNUD]?$/;

"22132313";  // Y-pawn at (2,2,1,3) steps forward along y to (2,3,1,3)
"24132513Q"; // the same pawn reaching y=5 promotes: Q R B N U or D

The wire format is deliberately dumb. Legality is never parsed from the network — it is recomputed locally, every move.

Tesseract took the platform we built across thirteen games — the shared quality tiers, the audio synth, the fullscreen contract, the one-canvas rule — and pointed all of it at a single question: can a browser teach a human to see in four dimensions? After a week of losing to our own novice tier, we think the honest answer is: slowly, and that's the fun.