← Back to projects
Passion Projects

Bootleggers

A board game for up to four people, played in the browser in prohibition-era Chicago, at night, to its own noir jazz: claim lots, open speakeasies, trade dice and territory, and take over what somebody else built.

The 60-second trailer: the real game against a real server, recorded one frame at a time and cut to the beat of its own noir jazz.
Chicago, 1925 — the city's gone dry, and the money hasn't.
Chicago, 1925 — the city's gone dry, and the money hasn't.1 / 7

Bootleggers is a full adaptation of the board game Lords of Vegas, re-themed to 1925 Chicago — speakeasies instead of casinos, rebrands, shake-ups, and a Don. Up to four players, in a browser, with bots filling any empty seat.

The server decides everything. The browser draws the board and sends intentions; every rule is resolved on the server, which is what stops a player from inventing a legal move. Rooms survive a refresh and a dropped connection, there is a room browser and spectator links, and a scripted tutorial for anyone who has not played the original.

The bots are the part I kept going back to. There are four tiers, and the top one does not follow heuristics — it lists every action available to it and ranks them by simulating how much each would change its position. Its worst bug was never found by playing it: I noticed that its successful builds plus its rejected actions came out roughly equal to the tier below's builds, which meant it wanted the same purchases and was losing four in ten of them to a rule it had not modelled.

That is the habit the project is really about. Every rule is checked by a test rather than by vibes, including a structural one — each player's owned lots plus their remaining dice must always come to twelve — asserted at every point the state changes. The banked measurement run on disk is a million simulated games and 107 million engine steps with zero failures, across 65 combinations of bot difficulty, producing a win-rate ladder that shows each tier genuinely beating the one below it. Each gate run before a change lands replays a hundred thousand randomised trade scenarios, because multi-party trades are where an adaptation like this breaks.

One more thing, since it is a decision rather than an omission: there is a finished-looking 3D board in the codebase and it is switched off. It could not support one mandatory action — a card can force you to move a die, and the 3D scene had no control for it, so drawing that card left you stuck with no way to end your turn. A renderer that looks better and traps a player is worse than the flat board that works.

So the flat board is the one that got dressed. It is night in 1925 now: an empty lot is a lit building front with a brass deed plaque, a claimed lot is a construction site taped off in its owner's colour, and a finished speakeasy gets a deco sunburst and marquee bulbs that chase. Michigan Avenue has a streetcar and roadsters with their headlights on, and it rains. For anyone whose device asks for reduced motion, the bulbs hold still and the rain and traffic are left out.

The music and the trailer were made the way everything else here was, in code. The noir jazz is synthesised note by note in Python — upright bass, piano, muted trumpet, brushes — with no samples, and the game loops 38 seconds of it. The 60-second trailer is the real game, recorded: the shipping client against a real server, with four scripted seats so every draw and build lands on the beat of that score, and the browser's clock stepped one frame at a time, so the film runs at a clean 30 frames a second on a machine that could not draw it that fast.

What it does

  • Up to four players in a browser, with bots taking any empty seat
  • Every rule resolved on the server, so a client cannot invent a legal move
  • Rooms survive refreshes and dropped connections; spectators can watch
  • Four bot tiers — the top one ranks every available action by simulating the result
  • Measured win ladder proving each tier beats the one below it
  • 48 lots across six blocks, five colours, and Michigan Avenue
  • A night board: lit facades, construction sites, chasing marquees, Avenue traffic and rain
  • Noir jazz synthesised in code, with no samples, and a 60-second trailer recorded from the real game
  • Multi-party trades of dice, lots and cash
  • Seven optional house rules, chat and direct messages, and 25 achievements
  • A scripted tutorial for players new to the original game
  • 71 test suites; one million simulated games and 107 million engine steps banked with zero failures
  • A hundred thousand randomised trade scenarios replayed before a change can land
  • A structural invariant — lots owned plus dice remaining always equals twelve — checked at every change

Built with: TypeScript, Node.js, Socket.IO, PostgreSQL, Python, Playwright, FFmpeg, Railway