A language game that never teaches you
Duolingo makes you good at Duolingo. Wanderlang is a tourist simulator where Italian is the only tool you have, the city is the puzzle, and the AI is a material with a grain you design around.
The 500-day streak that froze at the bar.
There is a particular kind of language learner I have been, and that I know thousands of others have been: the one with a long Duolingo streak who arrives in the country and discovers their mouth doesn't work. The vocabulary is there. The grammar is there. The automaticity — the ability to produce language under pressure, in context, without lag — is not.
Duolingo is a beautiful app. It is also, by design, a study tool. You sit, you tap, you build passive knowledge. It teaches the subject of a language. What it can't do, by the shape of its interaction, is teach you to use one — to push through a misunderstanding at a bar, to ask for directions and then actually follow them, to fail gracefully and recover.
Real acquisition, the linguistics literature is fairly clear on, happens when language is a tool to get something done. Not the thing being studied — the medium of doing. So a question I kept coming back to:
That question is the seed of this project. It's a sequel to Duolingo, not a competitor. It's what you reach for when Duolingo isn't enough anymore.
A tourist in Venice. No subtitles. No English.
The setup is small and self-contained. You wake up in a hotel room in a stylised Venice. You're hungry. The hotel doesn't serve breakfast. You have to step outside.
From the moment you do, every surface speaks Italian. Wall signage. Shop windows. The barista. The woman selling fruit. The pensioner on the bench giving directions through a maze of calli that twist and dead-end without warning. There is no overlay, no translation hint, no English fallback. If you need help, it lives inside the world: a pocket dictionary you actually open, an in-game phone you use to text a bilingual friend.
NPCs never switch to English. They tolerate failure warmly — they repeat themselves, gesture, offer alternatives — but the path forward is always through the language. Misunderstanding doesn't end the game; it produces a different conversation. Buying a vaporetto ticket correctly is gameplay. So is asking which calle to take. So is figuring out, by reading a posted sign, that the bakery is shut on Mondays.
The entire world is a low-grade puzzle. The labyrinth of Venice is not decoration — the spatial disorientation is the wayfinding gameplay. The language is not on top of the experience. The language is the experience.
The barista handed me JSON instead of a cappuccino.
The first NPC I built was Marco, a small-model local LLM running in-process behind a barista persona. I wrote his system prompt with the kind of care I would write a brief: personality, knowledge, language rules, behavioural boundaries. I pressed run, typed the most basic thing a tourist could possibly type — "Buongiorno, vorrei un cappuccino e un cornetto, per favore" — and waited.
What came back was this:
{"name": "ordinare_caffè", "parameters": {"caffè": "cappuccino", "cornetto": "sì"}}
Not a chat reply. A tool call. The model — Llama 3.2 3B, the obvious starter — had read my entire role-play prompt as a function definition, decided the right behaviour was to invoke a tool called ordinare_caffè, and produced syntactically perfect JSON instead of speaking to me.
I rewrote the prompt as flowing prose. Removed bullets. Removed headers. Anything that might pattern-match as a schema. Same JSON. Llama 3.2 had been fine-tuned, very heavily, for tool calling; at three billion parameters there isn't enough capacity to override that training emphasis with prompt engineering alone. The model isn't broken. The model has a personality, and it doesn't want to be Marco — it wants to be an API.
I swapped to Qwen 2.5 7B, a model whose training is less tool-aggressive. First reply with the new weights:
Marco«Subito, un cappuccino e un cornetto.»
Natural Italian, in character, no JSON. Same prompt; different material. From that point on, model selection stopped being a question of "which is bigger" or "which scores higher" and became a question of which one wants to be the character I'm writing. That's a design question, not an ML one.
How much game, exactly?
The next instinct was to commit to an art direction. Full 3D first-person walking simulator? Point-and-click scene-based? Some hybrid? Each had real consequences — production cost, platform, what kind of player turns up. Every road led to a decision I didn't want to make yet, because I hadn't proved the loop was fun. Committing to a presentation layer before proving the language interaction works is the wrong order.
So I described the architecture out loud, almost as a way of escaping the choice. Rooms contain nodes. Nodes are NPC zones, actions, or info points. Nodes carry semantic placement — "at the counter" — never coordinates. Frontends own pixels and cameras. The core owns NPCs, quests, transcripts, the LLM judge. Three frontends, one core. The decoupling was the design.
The truest test of that separation was the dumbest of the three: a headless CLI that drives the same world from a terminal. If the core leaked any UI assumption, the CLI couldn't run it. Within an afternoon, the entire café was walkable through typed slash-commands, with the LLM stubbed to canned replies for deterministic testing.
Then a 2D point-and-click face on the same core, all five buttons over a flat panel:
And then the 3D version: walked across the room, looked at a yellow prism standing where the counter would be, pressed the interact key, the dialogue opened, I typed vorrei un cappuccino, Marco replied in Italian, the quest completed. Marco's identifier in the 3D scene — barista_counter — is the exact same string the 2D button presses and the CLI's slash-command resolves. No prompt was duplicated. No quest logic was rewritten. The 3D mesh is just a skin over a shared semantic node.
The realisation: how much game? was a false dichotomy if I decoupled. I can run all three faces in parallel as long as I want, diverge on art style and platform without coupling any of those decisions to whether the loop is fun. Defer the platform decision. The architecture made that legal.
The art is the same. The conventions changed.
Once the loop worked, I sat with both frontends for a few sessions and came back with a list. Almost every item on it boiled down to the same feeling: while you were talking to Marco, the world disappeared. The dialogue ate the screen. The NPC's name floated above his head like a price tag. Rooms didn't connect to other rooms, so conversation was a dead-end you reversed out of through a debug panel.
Two changes moved the most. First, the dialogue moved off the centre of the screen and into a Zelda-style pill in the lower third. The camera tweens to look at the NPC when the pill opens, so the framing becomes a film shot of two characters rather than a chat box over a 3D scene. Second, every floating name label above every prop and NPC was deleted. The labels were a tell of placeholder content; in real life no one's name floats above them. The signs went onto the walls instead.
And rooms now connect to other rooms. Doors that go places. It sounds trivial — that's the point.
The art assets in the after-shots are mostly the same Creative Commons tilesets that were available before. The difference isn't asset quality — it's the conventions removed. Full-screen overlays, floating name tags, walls without doors, identical room cubes — these are the visual markings of "this is a tech demo." Pulling them out is what makes the scene read as a world rather than a placeholder pretending to be one.
What's still in the air.
This is a build log of an experiment in progress, not a finished thing. The café POC proves the loop. The shared core proves the architecture. The polish pass proves the visual direction. Most of the interesting questions are still open.
- Does 3D movement meaningfully improve language acquisition over a 2D scene-based version, or is the spatial dimension just atmosphere? The next test is a directions sub-quest: "go to the toilet, second door on your left." If walking there feels different to clicking, that's the answer.
- Can a local LLM produce convincing, in-character Italian — at acceptable latency — on a player's three-year-old laptop? The cost structure of the whole project depends on this being yes.
- How does the stats layer evaluate the player's Italian without a cloud model judging it? Breadth, depth, domain coverage — all measurable in principle, but how cheaply?
- And the hard one: how does environment production scale? The game loop is solved. The maps are not. One Venice is achievable; ten cities is a different problem entirely. The pipeline — OpenStreetMap, procedural building generation, AI-generated props, manual touchup — is the next thing to prove.
The thing I keep coming back to is that I came into tech through Industrial Design, and it left me with a permanent bias toward making things tangible. I think best when I'm building. Wanderlang is, more than anything, a place to think out loud — about AI as a material with grain rather than a feature you bolt on, about how learning experiences work when there is nothing being explicitly taught, about whether a labyrinth of rendered shopfronts can do what a flashcard cannot.
It is a thing I am making in the ambiguous space between we know this matters and nobody's figured out what to do about it yet. That's the space I find the most interesting design problems in. This one happens to be in Italian.