← Research

/research/game

Paris Battle Royale: the A to Z roadmap

The A to Z build plan for the Paris battle royale, phase by phase, with deliverables and exit criteria.

From "we have a page of ideas" to "thirty seats, live on alexsssaint.com/game, humans and JEV agents in the same round". Every step says what gets built, what it depends on, and what you can open in a tab when it's done.

The shape of the whole thing, in one line per phase:

PhaseWeeksWhat exists at the end
A. Concept and planning1A locked design doc and a greybox layout on paper
B. Blender: the four landmarks and the Seine2 to 3A stylised Paris you can orbit in Blender
C. Asset pipeline3One command turns Blender files into web-ready assets
D. 3D implementation4 to 5You walk, run, jump and swim through Paris in a browser tab
E. Networking5 to 6Two browsers, same Paris, server in charge
F. Zone system and round loop7A full three-minute round, alone
G. The fight7 to 8Baguettes, hits, gadgets, eliminations
H. JEV-powered agents8 to 1030 seats, all agents, real decisions in real time
I. Human join mode10You take a seat, an agent steps out, and back
J. Spectator camera11Eliminated players and visitors watch the live round
K. Life between rounds11 to 12Memory, grudges, the council in the pyramid
L. Build and deploy12 to 13Game bundle on the site, game server on the VPS
M. Playtest and harden13 to 14Ten friends, a fair round, no crashes
Z. Live14Rounds every three minutes, the 30 keep it full

Fourteen weeks if one person does it full time and nothing goes wrong. Something will go wrong in phases E through H, so call it four months.


A. Concept and planning (week 1)

Goal: stop deciding things while building.

What gets built

  • The design doc. The /game page already is most of it. Lock: four landmarks, the Seine, 30 seats, human-or-agent per seat, baguettes, three hits, three-minute rounds, two zone closes, JEV behind every agent.
  • The map on paper. A top-down sketch with real distances: the Avenue from the Arc to the Louvre, the Seine from the tower to Notre Dame, the three bridges, the quais. Mark the four final-zone circles and their radii.
  • The art bible, one page. The look is Blade Runner 2049 Paris with Playboi Carti energy: smoky volumetric fog, orange smog in the distance, cyan and magenta neon up close, holograms drifting over the avenue, brutalist towers behind the old stone, dark luxury streetwear on the characters. Built with game shapes: chunky proportions, clean bevels, flat colours, strong silhouettes, no photo textures. The reference images come from the prompts in game-art-prompts.md, saved to research/game-refs/. Pick a palette of about twelve colours from them.
  • The tech decisions. three.js with React Three Fiber, Rapier for physics, a Node WebSocket server on the VPS, Supabase for persistence, JEV through one API client. Write it down so nobody reopens it in week 9.
  • Budgets. Triangles per landmark (about 20k), total scene (under 300k), texture memory (under 64 MB), draw calls (under 200), target 60 fps on a three-year-old laptop and 30 fps on a mid phone.

Done when: the doc is on the site, the sketch is in the repo, and the budgets are numbers.


B. Blender: the four landmarks and the Seine (weeks 2 to 3)

Goal: a Paris that reads as Paris at a glance and as Blade Runner 2049 in mood, with game-clean shapes.

What gets built, in order

  1. Terrain and river. One flat ground plane with the Seine cut through it, the two banks raised, the quais as a lower step with stairs every so often. The island for Notre Dame. Smog planes at the east and west ends, and a ring of brutalist megastructure silhouettes beyond the playable edge, flat cards, never reachable.
  2. The three bridges. Pont d'Iéna, Pont des Arts, Pont Neuf. Each a different silhouette so you know where you are from the shape alone. Railings you can vault, arches you can hide under.
  3. The Eiffel Tower. Three walkable levels, stairs between them, the lattice faked with a few big beams and a trim texture, wrapped in scaffolding and holographic ad panels. Chunky, not accurate. The top platform is the spectator perch.
  4. The Louvre. The courtyard, the glass pyramid (climbable, with a cap you can stand on) lit from inside in cyan like a hologram, the facades as big flat panels with window trims. The Tuileries next to it: hedges as blocks, a fountain, statues as cover.
  5. The Arc de Triomphe. The arch itself with a roof you can reach, the roundabout ring, a dozen matte-black low-poly supercars as cover. The Avenue as a wide flat road with plane trees and holograms drifting above it.
  6. Notre Dame. Two towers with stairs, the nave as one big shape with buttresses, half rebuilt in dark steel, the rose window as a magenta emissive plane. The island edge with walls you can drop from.
  7. Set dressing. Lamp posts, benches, Métro entrances with steam vents, kiosks, floating hologram panels, a péniche moored under Pont des Arts, two chrome bateaux-mouches. One kit of about thirty props, reused everywhere.
  8. Materials. One shared palette texture, gradient atlas, a trim sheet for edges and windows. No unique textures per building.
  9. Lighting bake. Night. A dim cold sky, orange smog on the horizon, neon as emissive materials baked into a lightmap per landmark, volumetric fog done at runtime in the renderer, not in the bake. The tower's sparkle and every hologram are emissive, not lights.
  10. Collision meshes. Simplified invisible geometry for every walkable and blocking surface, named so the pipeline can find them.

Done when: you can orbit the whole map in Blender, screenshot each landmark, and someone who has never seen the project says "oh, Blade Runner Paris".


C. Asset pipeline (week 3, alongside B)

Goal: one command from Blender to the browser, repeatable forever.

What gets built

  • Naming rules. LM_Tower_L0, COL_Tower_L0, PROP_Bench, SPAWN_Loot_01, ZONE_Louvre. The name tells the pipeline what the object is for.
  • Export script. A Blender Python script that exports each landmark, the terrain, the props kit and the collision set as separate glTF files, applies transforms, strips unused data.
  • Compression. Draco or meshopt on every mesh. KTX2 texture compression. Target under 15 MB for the whole map on first load.
  • LODs. Two levels per landmark, generated in Blender, tagged by name. The far LOD is what you see from the tower.
  • Lightmap packing. Baked lightmaps exported alongside, referenced by material name.
  • Manifest. A JSON the game reads: which files, where they sit in the world, which are collision, where loot spawns, where the four zone centres are.
  • Validation. A script that fails if any budget from phase A is exceeded, run on every export.

Done when: npm run assets rebuilds everything from the .blend files and the game loads the manifest without a code change.


D. 3D implementation (weeks 4 to 5)

Goal: Paris in a tab, and moving through it feels good.

What gets built

  1. Scene loader. Reads the manifest, streams the glTFs, places everything, swaps LODs by distance, applies lightmaps. Loading screen with a pigeon.
  2. Physics world. Rapier, with the collision meshes from the pipeline. Static Paris, dynamic players and baguettes.
  3. Character controller. The gym model (public/coach.glb, rigged, with Idle, Walk, Run and Jump clips already baked in) on a capsule collider. Walk, sprint, jump, vault low railings, climb stairs, swim (slow, drops your loot), drop from ledges with a small stun.
  4. Third-person camera. Over the shoulder, collision-aware so it never clips through the Louvre. Mouse look on desktop, drag on touch.
  5. Input. Keyboard and mouse. A touch layer with a left joystick and a right aim-and-throw area, designed, not ported.
  6. Boats. The two bateaux-mouches loop the river on a spline and carry whoever stands on them.
  7. Performance pass. Instancing for props, frustum and distance culling, the frame budget from phase A hit on the reference laptop and phone.

Done when: you sprint from the Arc, down the Avenue, over Pont des Arts, along the quais and up the tower without a hitch, on a laptop and on a phone.


E. Networking (weeks 5 to 6)

Goal: the server owns the world; browsers just look at it.

What gets built

  1. Game server. Node, WebSockets, one process per room, 30 seats. Runs on the VPS. Authoritative simulation at 20 ticks per second using the same Rapier world as the client.
  2. Protocol. Small binary messages: inputs up, state snapshots down. A join handshake with a nickname and a seat assignment.
  3. Client prediction and reconciliation. Your own capsule moves instantly on input, then corrects to the server's answer. Others are interpolated 100 ms behind.
  4. Rooms and matchmaking. One public room to start. Join by URL. A second room opens when the first is full.
  5. Presence. Who's on the page, who's in the round, who's watching. Feeds the lobby and the spectator count.
  6. Resilience. Reconnect with the same seat within 30 seconds. Rate limits on inputs. Server rejects impossible moves.

Done when: two browsers on two networks see the same Paris, run past each other smoothly, and a pulled cable reconnects cleanly. If this feels bad, nothing after it matters. Fix it here.


F. Zone system and round loop (week 7)

Goal: a full round, alone, start to finish.

What gets built

  • Round state machine on the server: lobby (30 s), drop, loot (45 s), zone one, zone two, results (20 s), repeat.
  • The drop. Everyone spawns as a pigeon above the tower, glides, picks a landing spot. Landing turns you into your character.
  • Zone one. The fog closes from the map edge to the two banks over 40 seconds. A wall of stylised fog, not a circle line.
  • Zone two. The server picks one of the four landmark centres at random and closes to its radius over 40 seconds. The pick is announced with a landmark icon.
  • Zone damage. One hit lost every ten seconds outside the fog.
  • Loot spawns. From the manifest markers, seeded per round.
  • Results. Winner, placement, a replay of the final elimination from the server's recorded snapshots, next-round countdown.
  • Round HUD. Timer, zone phase, players left, hits left, minimap with the fog.

Done when: you can play a complete round by yourself against nobody and it ends correctly at the right landmark.


G. The fight (weeks 7 to 8)

Goal: eliminations that feel fair and look funny.

What gets built

  • Baguettes. Pick up, carry up to five, throw with a visible arc. Server simulates the projectile and decides the hit. Client shows the throw immediately and reconciles.
  • Hits. Three per player. Hit flash, a puff of crumbs, a short knockback.
  • Gadgets. One slot. Pigeon decoy, Vélib speed burst, umbrella that blocks one hit. Each is one server-side rule and one client effect.
  • Elimination. You drop your loot, become a pigeon, fly to the tower, become a spectator (phase J).
  • Elimination feed. Who got whom, with what, at which landmark.
  • Anti-cheat basics. Server-side throw rate, throw range, movement speed. No trust in the client for anything that affects another player.

Done when: two humans can play a fair round to the end. This is version one of the game.


H. JEV-powered agents (weeks 8 to 10)

Goal: 30 seats, every one an agent making real decisions in real time, all on JEV.

What gets built

  1. The agent runtime. A service next to the game server. One agent per seat, each with a personality file, a memory store and a grudge list in Supabase.
  2. The snapshot. Every two seconds per agent, a compact text view: position, landmark, hits left, loot, the zone phase and target, the five nearest players with distance and last seen action, the agent's own memory of each. Under 400 tokens.
  3. The decision. JEV answers with one structured intent: move_to, chase, throw, hide, swim, board_boat, hold, plus a target and a one-line reason kept for the feed. Strict schema, rejected if malformed.
  4. The local controller. Between decisions, code executes the intent: pathfinding over a navmesh baked from the collision set, aiming with a small error tuned per personality, dodging incoming throws. A slow JEV answer never freezes an agent; the controller keeps running the last intent.
  5. Personalities. Thirty short bios: home landmark, style (camper, rusher, boat person, bridge troll), a catchphrase, a fear. Same model, different people.
  6. Memory. After each round, JEV writes a two-line memory per agent: who eliminated them, who they eliminated, what they'll do differently. Read back into the next snapshot.
  7. Budget control. Decisions only during rounds. Hard monthly token cap with a graceful fallback where agents keep their last intent and the controller improvises. The whole sim sleeps ten minutes after the last visitor leaves.
  8. Observability. A hidden /game/agents view showing each agent's last snapshot, decision and reason. This is how you tune them.

Done when: you join a round alone, 29 JEV agents play it against you, and at least one of them does something you didn't expect and can explain when you check the log.


I. Human join mode (week 10)

Goal: a human takes a seat and gives it back, and nobody in the round can tell.

What gets built

  • Seat swap. On join, the server picks an agent seat (lowest current stake: not mid-fight, not the champion), benches it, and hands the seat to the human at the next lobby. On leave, the agent returns at the next lobby.
  • Benched agents walk to the quais and watch. They keep their memory. They notice they were benched.
  • Identity hiding. Nicknames for humans, names for agents, same style. No badges. Reading who's human is part of the game.
  • Mixed rounds. Any ratio from 1 human and 29 agents to 30 humans and 0 agents. The server doesn't care.
  • Fairness pass. Agent aim error and reaction time tuned so a decent human wins about as often as a decent agent.

Done when: three friends join at different times during a session, the seat count stays at 30 throughout, and afterwards none of them can list which players were agents.


J. Spectator camera (week 11)

Goal: watching is a first-class way to be on the page.

What gets built

  • Tower perch. Eliminated players and page visitors start on the top platform of the tower with the whole map in view.
  • Follow cam. Click any player or agent to follow them over the shoulder. Cycle with arrow keys or swipe.
  • Director cam. An automatic mode that cuts to the action: nearest fight, the zone close, the last three players. This is what the /game page shows before you join.
  • Spectator chat. Text chat among watchers. "Bread" throws bread that pigeons chase. Rate-limited, filtered.
  • Replay. The results screen replay uses the same camera system over the server's recorded snapshots.

Done when: the /game page opens on a live round that is watchable without touching anything.


K. Life between rounds (weeks 11 to 12)

Goal: the agents have lives, and the map changes because of them.

What gets built

  • Schedules. Between rounds agents commute, sit on the quais, ride the boat, argue at the Arc. Driven by the same controller with cheap idle intents, no JEV calls.
  • The council. Once per sim-day, six agents meet in the Louvre pyramid. JEV runs a short deliberation on one proposal from a fixed menu: close a bridge for a day, extra loot at one landmark, rain, a festival on the quais. The result changes the next rounds.
  • Visitor levers. One whisper a day to an agent, one vote a day on the council's proposal. Both filtered and rate-limited.
  • Grudges paying off. Agents with a grudge against a player bias their landing and chase intents toward them. Visible in the feed: "Colette is looking for you."
  • The plaque. Each landmark lists the names that won a final there.

Done when: you leave for a day, come back, and something on the map is different because the agents decided it.


L. Build and deploy (weeks 12 to 13)

Goal: the game lives on the site, the server lives on the VPS, and a push ships both.

What gets built

  • The game bundle. A separate client-only bundle loaded by the /game page, so the rest of the site never pays for three.js. Code-split: lobby first, map assets streamed after.
  • The /game page. The current markdown page becomes the lobby: live director cam, nickname box, one join button, spectator count, the design doc moved to /game/about.
  • Assets on the CDN. The pipeline output uploaded to Vercel Blob or the site's public folder with long cache headers and versioned filenames.
  • Game server deploy. Docker image for the Node server and the agent runtime, systemd on the VPS, TLS via the existing reverse proxy, a health endpoint.
  • Supabase. Tables for agents, memories, grudges, plaques, council votes, optional accounts and stats. Row-level security so the client can only read.
  • Secrets. JEV key and Supabase service key on the VPS only. Nothing in the client bundle.
  • CI. Push to main: build the site on Vercel, build the server image, run the asset validation, deploy the server, smoke-test a round with agents only.
  • Monitoring. Server tick time, room count, JEV latency and spend per hour, error rate. One dashboard, one alert on spend.

Done when: a commit to main updates the site and the server, and a round with 30 agents runs on production before anyone is told.


M. Playtest and harden (weeks 13 to 14)

Goal: a fair round with strangers on real networks.

What gets built

  • Playtest one, ten friends. Record every round. Fix desync, rubber-banding, unfair hits. Tune baguette speed and zone timing.
  • Playtest two, phones. Touch controls, performance, heat. Cut whatever it takes to hold 30 fps.
  • Abuse pass. Nickname filter, chat filter, join rate limits, per-IP room caps, a kick command.
  • Cost pass. A full day of rounds, measured JEV spend, cap set with margin.
  • Content pass. Sounds, hit feedback, the tower sparkle on the hour, the results share card, an OG image for the page.

Done when: a round with ten humans and twenty agents on mixed networks ends without anyone calling it unfair.


Z. Live (week 14)

Goal: it's on the site, it's always running, and people can join.

  • Soft launch: the /game link goes on the homepage. Rounds every three minutes, the 30 keep it full.
  • Stream the first evening. Chat throws bread.
  • Watch the dashboard for a week. Spend, tick time, how often humans win.
  • Then decide what's next: the fifth landmark, skate on the quais, the council for real, or nothing, if it's fun as is.

Dependencies, so you don't build things in the wrong order

  • B and C run together. Don't finish modelling before the pipeline exists, or you'll re-export everything.
  • D needs C. No hand-placed assets in code.
  • E needs D. Movement has to feel right locally before it's networked.
  • F and G need E. No round logic on the client.
  • H needs F and G. Agents need a real round to play.
  • I needs H. Nothing to swap with until agents exist.
  • J can start any time after F, it only needs snapshots.
  • K needs H and I.
  • L can start early for the site page and server skeleton, but the full deploy needs everything before it.

What can slip without hurting version one

Gadgets, the boats, the council, grudges, phone controls, the plaque. Version one is: the map, movement, networking, the zone, baguettes, 30 seats on JEV, seat swap, spectator cam. Everything else is week 15.