I was flying back from a work conference in Berlin on a budget airline. No entertainment, no Wi-Fi. Usually I’d use a flight to catch up on a film, or plug the laptop in and work. On this one I could do neither.
The colleague sitting next to me had an offline game. I had nothing. Try as I might, I couldn’t help noticing them busy playing away on an arcade puzzle the whole way home.
So, out of frustration, the first thing I did when I got home was build a game. Free to play. No ads. Works offline.
It was inspired by a top-down shooter I played years ago. I can’t remember its name, it must have been pulled from the App Store, and I can’t play it any more. But I remember the bits I liked. I wanted those, plus the best bits of all the best games I remember from the last 20 years, to make something new.
That Saturday I asked Claude to build it.
By Sunday night it had four maps, night and rain, a training mode, sound and music, unlockable skins, an offline mode, and my family playing it on their phones and a tablet. There’s a link to play it at the end.
That isn’t the interesting part. Anyone can get an AI to write a game now.
I’ve built an agentic developer harness, FADE, for exactly this kind of work. I wrote about it here. This time I deliberately didn’t use it. I wanted to vibe code it, to see what difference that makes.
What I found is that almost none of what made the game good was the code. It was the engineering discipline, and it crept in even without the framework.
Writing code took minutes. Knowing it was wrong took telemetry.
The first version worked, and it played well enough. If I’d stopped there I’d have told you AI can build a game in an afternoon, and I’d have been wrong about what I had.
On the first evening the game started sending one small record per match back to my server: how long you lasted, how you died, what gun you had, how accurate you were. A random ID per phone, no names, no location. The start screen says so.
Before anyone played, Claude ran a test match with a player who never moved and never fired. It came 5th out of 20. The bots were so busy killing each other that doing nothing was a strong tactic. No amount of reading the code would have told me that. One test did.
Then my family played 37 matches. The numbers were brutal. On one phone, 18 of 28 finished matches ended in 20th place, most of them between 4 and 16 seconds in, usually with a nearly full gun. Nobody told me that. They just kept pressing Play again. The data said it.
The cause turned out to be a bug. The bots hold fire for the first 12 seconds of a match. The player’s auto-fire didn’t. So every new player started a gunfight they couldn’t win, against a bot that had looted something better. You’d never spot that by playing.
The same thing happened again and again over the weekend:
- My son Luca kept coming last and said he couldn’t aim. “I know I have to face straight, I don’t know exactly what angle.” I suggested a laser pointer from the gun. Later, when the data showed new players dying in the first few seconds, we added a short training level that runs the first time you press Play.
- On the Fire tablet at home the game felt sluggish. The telemetry put a number on it: about 12 to 15 frames a second, slow enough that the whole game ran in slow motion. Now the game notices and lowers its own resolution.
- On the Monday I complained that the forest map, meant to be the easy one, felt like the hardest. The data agreed it had the worst results. A simulation said the map wasn’t the problem: most of those matches came from our weakest player on that slow tablet.
My family tell me how it feels. The data tells me why. You need both, and the second one you have to build on purpose.
No single AI was in charge
I didn’t use one AI. I used tools from two companies, and the most useful thing any of them did was catch another one’s mistake.
It helps to keep three layers apart. There’s the company: Anthropic or OpenAI. There’s the harness, the tool you actually work in, which reads your files, runs commands and calls the model: Claude Code is Anthropic’s, Codex is OpenAI’s. And there’s the model, the brain inside, which comes in tiers. Anthropic’s Claude models run from Haiku through Sonnet and Opus up to Fable. OpenAI’s GPT-6 models run from Luna through Sol up to Astra.
Here’s who did what:
- Claude Code with Opus 5.5, my daily driver, did the building: the engine, the bots, the maps, the deploys.
- Claude Code with Fable 5.1, Anthropic’s top model, did the adversarial reviews. I asked it to find the bugs, the logic flaws and the design problems, and to change nothing.
- Codex with GPT-6 Astra, OpenAI’s top model, did the artwork for the desert, city and neon menus and wired it into the game, and gave me the brutal second opinions, including a release review.
One habit I always keep. When a top model breaks work down, I have it write the brief as if a smaller model will do the work. A bigger model can infer things and figure stuff out. A smaller one won’t, and it will make mistakes, so it needs explicit paths and explicit instructions. Fable’s review came with a fix brief written for Sonnet, the middle tier. If I’m honest, I should have aimed it at Haiku. Then I gave it to Opus to build anyway. I’d been away for a week and hadn’t spent my token budget, so I used it.
The reviews earned their keep. Astra’s first review found that a win could turn into a defeat, because damage kept landing after the match had ended and two end-screen timers raced each other. Opus checked every line reference before fixing anything. All of them were right. Then, while fixing them, Opus introduced a crash of its own on loading. The test run caught it before it reached a phone.
Fable’s review found that one error anywhere would freeze the game for good, and that on older iPhones the City map threw one on its very first frame. It found that about 2 in 100 forest and desert matches ended with the final safe circle somewhere nobody could stand.
Astra later did a release review and refused to sign it off for the App Store. Fair enough. It listed the reasons, Opus checked each one against the code, and the real ones got fixed.
Then I asked Fable the question I actually cared about: would a human developer look at this and see good engineering, or vibe coded slop?
Its answer was more useful than flattery. As a two day prototype, it said, a developer would call it good work: decisions written down with dates and names, commit messages that say what changed, a deploy that checks the live copy byte for byte, telemetry with a report. “None of that is typical of slop.” As the codebase for an App Store product, it isn’t there yet: one 1,300 line file where everything shares the same 62 variables, 37 empty error handlers, and no committed tests until the end of the first day.
Both halves are fair, and I’d rather hear it now than from a developer later.
What I took from it: an AI checking its own work is weak. A different AI checking it, with instructions to find problems and change nothing, is strong. And whoever fixes the findings still has to verify them, because reviewers are wrong too. Fable criticised one bot behaviour that had already been removed.
The bit the AI can’t do for you
So what did I actually do all weekend? Mostly, I made decisions.
It had to be offline, with no servers and no ads. Both control schemes stayed, because I couldn’t tell which was better and neither could my family. The reviews happened before strangers saw it, not after. And before I spend anything on the App Store, I set a pass mark: at least 1 in 5 new players must come back the next day, measured over at least 20 phones that don’t belong to my family. If it fails, I fix the game instead of paying Apple.
Even the safety net had a hole in it. The deploy script was supposed to refuse to say “deployed” when the live copy didn’t match. A review found it printed “deployed” anyway. That’s the kind of mistake that hides for months, and it was in the very thing meant to catch mistakes.
I didn’t plan any of this. I set out to vibe code. But I couldn’t help going back to clear requirements, clear evidence from the telemetry, engineering standards and adversarial review. All of it crept in.
I’ve always thought of vibe coding as a dirty word. Asking for code and shipping whatever comes back is still dangerous. But maybe, if you bring the engineering discipline of what good looks like, vibe coding gets you somewhere real. The tools that make it safe are old and boring: measure what users actually do, get a second pair of eyes from someone who didn’t write it, write down why you decided things, and don’t believe “it works” until you’ve seen it work.
The AI wrote the code in minutes. The engineering was everything else.
Then I tried to teach an AI to play it
Once the game worked, I wondered whether an AI could play it instead of my hand-written bots.
Not a chatbot. The AI most people use writes text, and that’s far too slow for a bot that has to decide what to do several times a second. There’s a newer kind called a decision model. You describe a situation in plain English, give it a list of options, and it picks one and tells you how sure it is. That’s all it does. The best known is Jev, from TypeSafe AI, which runs in their cloud. I used Laya, a free rival you can download and run on your own laptop. It answers in a fraction of a second.
Out of the box it was hopeless. Given a bot’s choices (fight, run, heal, grab a better gun, head for the safe zone), it kept choosing to heal at full health. So I trained it on my laptop, using thousands of matches the bots played against each other.
That’s the next post. If you want to see where it has got to, you can watch it play at watch.offlinearena.com. One bot in each match takes its decisions from Laya, and you can see every choice it makes, what it could see at the time, and how sure it was. It isn’t good yet. It usually finishes near the bottom.
Play it, and tell me what’s wrong
The game is free, with no ads and no sign up: offlinearena.com. It runs in your phone’s browser, and once you’ve opened it, it works with no signal. The other players are bots, and the game tells you so.
If you’ve got advice, or something annoys you, or you find a bug, put it in the comments on this post. I read them all, and they go straight into the next build.
The first person outside my family to play it was someone I only know from another phone game. They did the training, then won their first match. Since then eight phones I don’t know have played it, most of them from a Facebook post. Of the six that have had a day to come back, none has. Six is far too few to mean anything. The pass mark needs twenty, and I’ll tell you how it goes.