Fly vs Jev: Pong

A simulated fruit fly brain against an AI model, at Pong, on the same court.
The full wiring of an adult fly, all 166,700 neurons, watches the ball and moves the left paddle. TypeSafe AI's Jev moves the right one.

The fly and Jev playing Pong, then all 300 games at once, 274 won by the fly

## How it works 1. **Court.** Pong on a court one and a half times as wide as it is tall. The ball bounces off the top and bottom walls and gets 6% faster with every hit. Where it meets the paddle sets the return angle, up to 55 degrees, as in the original game. First to five points. Serves alternate, and a seed fixes every serve. 2. **Looks.** Nobody moves continuously. While the ball comes toward a player, that player looks four times (with 88, 66, 44 and 22% of the court left to cross) and each time picks one of 11 heights for its paddle. The paddle glides there at a fixed top speed, so a late read can come too late. Neither player is ever told where the ball will arrive. 3. **Eyes.** For each of the 11 heights, the fly sees a picture of the court centred on where its paddle would actually be when the ball arrives: the ball now, the ball 0.08 seconds ago, and the other paddle. The picture lands on 3,316 real R1-R6 photoreceptors, laid out by the position of the lamina column each one feeds, in a three-colour mosaic with one colour for each of those three things. 4. **Brain.** The MaleCNS connectome (166,700 neurons, 6.2 million connections) runs as a spiking network for 150 ms per candidate height. Its wiring is never changed. This is the same simulator as [Flytris](https://github.com/EnesYilmazcode/Flytris). 5. **Move.** A readout over 2,048 L1/L2 neurons scores each height and the paddle heads for the best one. The readout is the only part that learned: once, from 8,000 looks scored by a physics teacher that knows where the ball will land. The teacher is never consulted during a game. 6. **Jev.** Jev gets the rules, the ball's position and speed, both paddles, and for each height, how far its paddle would get before the ball arrives, which is the same thing the fly's picture is centred on. It picks one. It gets no practice games. 7. **Laya.** [Laya](https://huggingface.co/convaiinnovations/laya), Convai Innovations' open decision model and a direct Jev competitor, gets the same question trimmed to fit its 512-token input. It runs on the same GPU as the fly. ## System design During a game the teacher is never consulted: every fly move comes from simulated neurons and the readout on top. The teacher only scored examples once, during setup. ```mermaid flowchart TB subgraph look["Every look, for each of 11 paddle heights"] P["Picture of the court, centred on where the paddle would be when the ball arrives"] --> E["3,316 photoreceptors"] E --> C["Simulate all 166,700 neurons for 150 ms on a GPU"] C --> R["Read 2,048 L1/L2 neurons"] R --> S["The readout scores each height and the paddle heads for the best"] end subgraph setup["One-time setup, on Modal GPUs"] T["A physics teacher scores 8,000 looks from practice games"] --> L["The readout learns which neuron activity marks a good height"] end L -. trained once, then frozen .-> S subgraph jev["Jev, the other paddle"] J1["Ball, both paddles, how far each height can be reached"] --> J2["Jev picks a height through the Vercel AI Gateway"] end S --> G["One game, one court"] J2 --> G G --> X["300 games: the fly wins 274, Jev 26"] ``` ## Results A round robin, 300 games per match, seeds 1000 to 1299, first to five points. The first player named has the left paddle; the court is mirror symmetric and serves alternate. | Match | Games won | Points won | Balls returned | |---|---:|---:|---:| | **Fly vs Jev** | **274** to 26 | 1,442 to 634 | 74% to 49% | | **Fly vs Laya** | **291** to 9 | 1,486 to 428 | 73% to 29% | | Jev vs Laya | 252 to 48 | 1,405 to 748 | 53% to 27% | All three are far past chance (sign test p below 10-33 each). To put everyone on one scale, each player also played 100 games against the same simple bot, the classic Pong opponent that just moves to wherever the ball is now. Seeds 3000 to 3099. | Against the ball follower | Games won of 100 | Balls returned | |---|---:|---:| | Physics teacher, knows where the ball will land | 100 | 100% | | Readout on the eye inputs, no brain | 100 | 89% | | **The fly** | **82** | **72%** | | Jev | 60 | 50% | | Random heights | 23 | 24% | | Laya | 22 | 24% | Jev plays about as well as the ball follower (60 of 100 is not clearly better, p = 0.057). Laya plays like random picks. The skill comes from the trained readout, not from the brain being clever on its own: the same kind of readout fitted straight to the eye inputs, with no connectome in between, beats the fly. On held-out looks it lands within one height of the teacher's pick 57.7% of the time against the fly's 52.3%, and it wins all 100 games against the follower. What the brain is required for, the controls show: break one part of the pathway and the fly plays like random picks. | Control, same 100 games | Games won | Balls returned | |---|---:|---:| | Intact fly | **82** | **72%** | | Eye wiring shuffled | 25 | 24% | | Readout silenced | 17 | 20% | | Readout weights shuffled | 13 | 17% | This is also not a like-for-like contest. The fly's readout practised on 8,000 teacher-scored looks. Jev and Laya are general decision models answering a text question, with no practice games. Each got the best of several phrasings, tried against the ball follower before the real games. For Jev, more help made it worse: plain positions and speeds won 22 of 40, while adding the ball's slope and a hint about folding its path off the walls won 8 on the same 40 seeds. Every trial is in [`results/prompt_trials.json`](results/prompt_trials.json). | Prompt tried against the ball follower | Games won | |---|---:| | Jev, plain positions and speeds (used) | **22 of 40** | | Jev, plus a strategy line and where the ball is relative to each option | 19 of 40 | | Jev, plus where the ball is relative to each option | 13 of 40 | | Jev, the ball's slope and a hint on folding off the walls | 8 of 40 | | Laya, the ball's height next to the paddle's (used) | **11 of 40** | | Laya, plus "aim for where the ball will be" | 7 of 40 | | Laya, plain | 5 of 40 | The readout picks the teacher's exact height on 22.8% of held-out looks, against 9.1% for chance. That sounds low, but a paddle that is roughly right early and closer on each later look still meets the ball: the fly gets back 74% of Jev's shots. See [`results/gate.json`](results/gate.json). ## The video One game, seed 1111, chosen by a fixed rule in [`scripts/pick_showcase.py`](scripts/pick_showcase.py): among the fly's 5-2 and 5-3 wins that last at most 40 seconds (124 games), the one with the most paddle hits. It has 19; the median game in the pool has 10. The video opens on the finish, the grid of all 300 games, then dissolves back to the first serve. The first point plays at close to real speed, the middle fast-forwards at up to 4.7 times, and the last point eases down. The outline next to a paddle marks the height it picked on its latest look. After "Fly wins!", the court shrinks into its own square and all 300 games play at once on a shared clock; each court takes the winner's colour as it ends and the boxes count games. Every frame is rebuilt from the saved record in [`results/games`](results/games), and every replay must reach its recorded score. The sound is synthesized: a marimba note per hit that climbs with the rally, a tick off the walls, a chime on each point, a faint pip as each small game ends. **[Watch/download the video with sound](media/fly-vs-jev.mp4)**

All 300 games as a grid of small courts, blue where the fly won and pink where Jev won

## Run it ```bash pip install numpy pandas pyarrow torch pillow modal laya python tests/test_game.py # walls, paddle angles, serves, exact replays modal run scripts/modal_pong.py::build_readout # 8,000 teacher looks through the connectome modal run scripts/modal_pong.py::play --left fly --right jev --first 1000 --last 1300 modal run scripts/modal_pong.py::play --left fly --right laya --first 1000 --last 1300 modal run scripts/modal_pong.py::play --left jev --right laya --first 1000 --last 1300 modal run scripts/modal_pong.py::play --left fly-silenced --right follower --first 3000 --last 3100 modal volume get pong-runs games runs/ AI_GATEWAY_API_KEY=... python scripts/play.py jev follower 3000 3100 python scripts/play.py no-brain follower 3000 3100 python scripts/export_results.py # results/games and the scoreboards python scripts/pick_showcase.py fly-vs-jev 40 python video/publish.py # needs ffmpeg ``` The connectome comes from the Flytris repo's `data/malecns`, and the Modal jobs mount the same data as a volume. Building the readout simulated 88,000 candidate pictures on one Modal L4 in about 24 minutes; the 300 games against Jev took another 29. All the GPU work, controls included, came to about two hours of L4 time. Jev read 10.3 million input tokens in its 300 games against the fly, about 43 cents at list price. | Folder | What's in it | |---|---| | [`pong/`](pong/) | the game, the physics teacher and simple bots, the eyes, the connectome simulator, the fly, Jev and Laya players, the lockstep match runner | | [`scripts/`](scripts/) | building the readout, the Modal jobs, playing matches, exporting results, the scoreboard, picking the video's game | | [`video/`](video/) | the replay renderer, the 300-game grid, the sound, the media publish step | | [`results/`](results/) | every game from every match, the prompt trials, the frozen readout and its gate report | | [`tests/`](tests/) | walls, paddle angles, serves, exact replays | ## Credits MaleCNS v1.0 connectome by FlyEM (HHMI Janelia), Cambridge, MRC LMB and Google Research, CC BY 4.0 ([Berg et al. 2026](https://doi.org/10.1016/j.cell.2026.08.015)). Neuron model constants from [Shiu et al. 2024](https://github.com/philshiu/Drosophila_brain_model). Pong by Allan Alcorn at Atari, 1972. Jev by [TypeSafe AI](https://www.typesafe.ai) through the [Vercel AI Gateway](https://vercel.com/ai-gateway/models/jev). [Laya](https://huggingface.co/convaiinnovations/laya) by Convai Innovations, Apache 2.0. Compute by [Modal](https://modal.com).