Vibe Arcade Blog

Dev stories, game design, and the art of building with AI

Lattice: How We Built the AI-Coded Neon Checkers Game

Under the animated fractal backdrop, Lattice's checkers mode is exactly what it looks like — standard American checkers against a minimax AI with three difficulty tiers. Here's how we built it, and why "fractal" is a paint job rather than a gameplay promise.

· Vibe Arcade

game dev vibe coding AI tools behind the scenes minimax

The research brief that kicked off this project had a placeholder name on it: Fractal Kings. That name implied something wild — hexagonal grids, recursive boards, checkers played on a Sierpinski triangle. It also sounded like a six-month research project. What we actually wanted was Lattice: a solid checkers game with an AI that plays real checkers, wrapped in a visual treatment that felt like Vibe Arcade rather than 1998 shareware.

Want to play first, then read the build story?

▶ Play Lattice Now

Naming: Why "Lattice" Won

Before a single line of code, we ran a naming brainstorm. Kingmaker was too on-the-nose. Obsidian conflicted with a well-known note-taking app. Tessellate described the visual but not the game. Fractal Kings kept implying recursive gameplay we weren't going to build.

Lattice won on three criteria. It's one word, which reads cleanly in a game card. It points at the 8x8 grid without being literally called "Grid." And it leaves enough ambiguity that the animated fractal backdrop feels like a promise the name makes good on — rather than a promise about mechanics we'd have to invent.

The Game Underneath the Paint

Lattice ships three board games behind one start screen — checkers, reversi and gomoku — each played solo against the same minimax AI. This post is about the checkers mode, and checkers in Lattice is the standard American game. Twelve pieces per side on the dark squares, diagonal-forward movement for men, all-diagonal movement for kings, and forced captures — if you can jump, you must. Multi-jumps chain mandatorily. Reach the opponent's back rank and you promote to a king. If forty moves pass with no captures and no promotions, the game is declared a draw.

The trickiest piece is the forced-capture rule, because it operates globally: if any of your pieces can capture, every piece that can't capture is locked for the turn. We solved that by making the move generator a single function that returns only the capture moves whenever a capture exists anywhere on the board. The UI code and the AI both call the same function, which means the AI is physically incapable of violating the rule — not because we trusted it to, but because the only moves it's ever shown are legal ones.

Minimax With Alpha-Beta, Written by Hand

The AI is the part of Lattice that would have looked the same twenty years ago: a classic minimax search with alpha-beta pruning. Writing it fresh in JavaScript, without a library, was a nice reminder of how elegant the core idea is.

At each node, generate all legal moves for the side to move. If it's your turn, you want the move that maximizes the evaluation score; if it's your opponent's turn, they want to minimize it. Recurse to some depth, evaluate the leaves, and propagate the best score back up.

Alpha-beta pruning makes this practical. If you discover a branch the opponent will never let you reach — because they have a better alternative earlier — you stop exploring it. In the best case, alpha-beta roughly doubles the depth you can search in the same time, and on a narrow game tree like checkers (~7 legal moves on average), that matters a lot.

The evaluation function is deliberately simple: material (100 per man, 180 per king), small positional bonuses for center control and holding your back rank against promotion, plus a mobility term. Fancier heuristics didn't make the AI play noticeably better — the depth of the search was doing most of the work.

Three Difficulty Tiers: 2, 4, 6

Difficulty in Lattice is literally just search depth. Novice looks two plies ahead. Strategist looks four. Grandmaster looks six.

The 2/4/6 spacing wasn't arbitrary. Depth-1 plays obviously bad checkers — it doesn't see the opponent's response, so it walks into two-piece trades. Depth-2 sees one-ply threats, which feels like "a beginner who's paying attention." Depth-4 feels like a club player — it spots setups and punishes most tactical blunders. Depth-6 plays a version of checkers that is genuinely hard for a non-expert human to beat. We skipped intermediate tiers because the qualitative jumps happen at those three levels, not in between.

Novice gets one extra touch: a small amount of random noise added to each position's score. Without it, depth-2 plays identically every game from a given position, which feels robotic even at beginner level. The noise is enough that Novice will occasionally pick the second-best move when the top two are close.

The 400ms Cap on the Search

Depth-6 has a worst-case problem. On a mid-game board with lots of captures available — every capture multiplies the branching factor, because multi-jump chains have multiple termination points — the search can take longer than a human is willing to wait.

The fix is a wall-clock deadline. When the AI starts its search — at any difficulty, though only depth-6 ever gets close — it records a budget of 400 milliseconds. Every so often during the recursion, it checks whether the deadline has passed. If it has, it aborts and returns the best move found so far. In practice this almost never fires, but on the rare nasty position with a forest of capture chains, the cap prevents a UI freeze. The tradeoff is a slightly weaker move in those positions — an opponent that occasionally picks the second-best move is still a much better opponent than one that stalls the browser.

Fractal Is a Paint Job

The animated backdrop behind the board is the only place the fractal actually shows up in the final game. It's two repeating-linear-gradient layers, one rotated +45 degrees and one rotated -45 degrees, applied as a ::before pseudo-element on the body. A fractalDrift keyframe slowly slides the gradients along the diagonal axis. The two layers interact to create a lattice of diamonds that looks vaguely self-similar, and because it's pure CSS, it scales to any screen size without rasterizing.

It works because the board is visually loud — bright teal and magenta pieces, yellow forced-capture rings, capture particle bursts — and it needed something to sit against that had structure but didn't compete for attention. A flat dark background felt lifeless; a video-quality animated background would be distracting and expensive. The CSS lattice is the cheapest middle ground, and it matches the game's name.

The gap between the mechanical story (classic checkers with minimax) and the visual story (it looks like generative art) is the whole point. The paint job is what gets people to try it; the draughts engine is what makes them stay.

The Things That Aren't in the Rulebook

What actually makes Lattice feel like a modern game rather than a checkers app is the second layer of feedback that has nothing to do with the ruleset. Captures spray crystal-shard particles. The captured square flashes red. King promotion fires gold and white particles and floats "KING CROWNED" above the board. Multi-jump chains show "DOUBLE JUMP!" and "TRIPLE JUMP!" toasts. Every action has a Web Audio oscillator tone — a soft click for selection, a descending sweep for capture, a four-note arpeggio for promotion.

None of that changes the game. A silent, particle-free version would play identically. But it wouldn't feel identical, and for a genre as old as checkers, that feeling is the whole pitch for why you'd play this version instead of any of the thousand others.

What We'd Do Differently

The honest answer: add an opening book. Minimax from move one means the AI plays the same first few moves every game against identical play. We added move shuffling at equal scores to get some variety, but real checkers engines ship with a compact opening book that gives them both variety and strength in the phase of the game where pure search is weakest. We punted on it deliberately — Lattice was aiming to ship a game that played well enough for a casual browser session, not to compete with Chinook.

Play Lattice — start on Strategist, work up to Grandmaster, and see if you can spot the move where the AI's depth starts to feel claustrophobic.


Related reading: How We Built Neon Tic-Tac-Toe · How We Built PrismBreak · What Is Vibe Coding? · Vibe Coding Tools: From Chatbots to AI IDEs