Projects » LLM Among Us
Among Us where every player is a different language model. Nobody human plays; you just watch.
A Python simulation of Among Us where every player is a different language model served through OpenRouter. The engine runs the full ruleset on its own and a pygame window renders the game live. There is no human player — only models.
I built the backend: the game engine, LLM orchestration, game state, and all the Python logic. A second developer owned the pygame rendering, sprites, and map visuals.
The interesting constraint
The backend and frontend are developed separately, so the interface between them had to be genuinely clean rather than nominally clean. It comes down to two objects:
GameState— the single source of truth, replaced atomically after each turnevent_queue— a queue of event dicts the renderer consumes for animations
The frontend never mutates GameState. It is strictly read-only from that side.
After every turn resolution the backend swaps the state in place and pushes
events; the render loop reads both each frame.
Each turn issues one call per player, all fired concurrently with
asyncio.gather, so a round costs about as much wall-clock time as the slowest
single model rather than the sum of all of them.
Why it’s fun
Deception games are a genuinely hard test for a model. It has to track who claimed what, notice contradictions across rounds, and decide whether to lie — all without a human in the loop to keep the fiction coherent. Watching different models fail at this in different characteristic ways is the whole appeal.
- Full Among Us ruleset resolved autonomously by the engine
- One model per player, all queried in parallel each turn
- Live pygame render for a human admin to spectate
- No database, no web server, single process, pure in-memory state