Case study · In development · Software · Simulation · Games
Raid Manager: a guild management game for Android
Football Manager for a classic MMO raiding guild. You never control a fight, but every decision about who runs, who gets the loot and who raids at 20:00 is yours.
- automated tests, including the balance suite
- 124
- raid bosses across six raids
- 65
- AI guilds on a simulated server
- 20–28
- network or AI calls while you play
- 0



Summary
A single-player, offline Android game. You start with fifteen level-15 characters and build them into a 25-player raiding guild: sending groups on real-time dungeon runs, handing out every piece of loot yourself, recruiting, and leading the nightly raid. The characters remember what happens to them, and that shapes how they feel about you, the loot council and each other.
The problem
Most MMO management games are about combat. The interesting part of running a guild is the people: who you take, who gets the gear, who's fed up with sitting on the bench, and whether you're ready for tonight's raid. I wanted a game about those decisions that runs offline on a phone.
The idea
Make the player the Guild Master and nothing else. No combat to control and no hidden success percentage, but every decision that matters (groups, loot, recruits, the raid roster) is theirs. Write the rules as maths first, prove them by simulation, and only then build the screens.
The architecture
- 01
Design specification
Sections on characters, time, dungeons, items, recruitment, raids, progression, saves and interface, critically reviewed before any code was written.
- 02
Simulation core
Pure Kotlin. A lazy event engine resolves runs, resets and raid nights from a seed and the player's actions.
- 03
Balance suite
Tests that play the game (fifteen starters, groups, dungeons, loot) and check its pacing against targets, writing a balance report.
- 04
Android app
Jetpack Compose screens over the core: roster, dungeons, recap, loot, raids, the server and the guild's chronicle.
- 05
Art pipeline
Gemini sheets via n8n, sliced and catalogued in the repo. A tag-based resolver picks art by type, tier, theme and role.
- 06
Release
GitHub Actions runs the tests and publishes an installable APK on every push.
The build
Kotlin throughout: a core module with no Android dependencies and an app module in Jetpack Compose. The save is a seed plus the player's actions, so the whole world, AI server included, is rebuilt identically on load. 124 tests, including balance tests and full acceptance runs, run on every push before the APK is built.
- KotlinA pure simulation core with no Android dependencies
- Jetpack ComposeThe Android interface: roster, dungeons, recap, loot, raids and the server
- Seed + action logThe save is the seed and the player's actions, and the whole world is rebuilt from them on load
- JUnit124 tests, including a balance suite that plays the game to check its pacing
- GitHub ActionsRuns the tests and builds an installable APK on every push
- Gemini + n8nThe Game Asset Factory: contact sheets of art, sliced, keyed and catalogued by a tool in the repo
- Cinzel + AlegreyaOpen-licence display and body type
The AI
No AI runs in the game: it's offline and fully deterministic. Gemini paints the art when the game is built, through an n8n workflow, and code checks and catalogues every cell. Claude Code was my pair engineer for the specification and the implementation, with the balance tests deciding whether a change was right.
- No AI while you play. Every outcome is seeded and deterministic, and the game makes no network or model calls.
- Gemini paints portraits, bosses, items and backgrounds as 8×8 contact sheets through an n8n workflow. A slicer in the repo keys, trims and names each cell and generates a Kotlin catalogue.
- Built with Claude Code from a written design specification, section by section, with the balance tests as the referee.
The automation
CI is the release process. Each push tests the core, builds the APK and updates the Latest APK release, so my phone always has the newest build. New art sheets are fetched and processed by a second workflow.
- Every push runs the core tests and builds the APK, published as the Latest APK release.
- A second workflow fetches and processes new art sheets from the asset factory.
- Balance reports are regenerated from simulated play, so a rule change shows its effect on pacing straight away.
The data
Everything comes from a seed and an action log: characters with hidden skill, morale and memories, items with stat budgets, runs with per-boss kill times, raid nights with wipe reports, and a server of AI guilds with its own history. Balance reports are generated from simulated play.
The result
So far: a playable beta on my phone, from the first design document to raids and a simulated server in days, with the balance checked by tests rather than by feel. Groups keep running while the phone is in my pocket, and the 20:00 raid is a real decision every evening.
- Dungeon runs take 15 to 60 minutes of real time and carry on while the app is closed. When a group returns, the recap reveals each boss and each drop one tap at a time.
- Loot is always handed out by hand. The allocation screen shows upgrades and set progress, and never marks a 'best' recipient.
- Six raids and 65 raid bosses, from 10-player Thornmantle Hold to the 15-boss Sundered Sanctum, resolved at 20:00 with lockouts, wipe reports and first kills.
- Characters keep memories, relationships and loyalty, which feed the guild chat, a chronicle and how they react to loot decisions and the bench.
- A guild economy: gold, a bank, professions, consumables and repairs.
- The guild lives on a simulated server of 20 to 28 AI guilds with their own progress, rivalries and recruitment, all offline.
- Eleven dungeons in five environments, and an interface that changes with the guild's level, from caves and jungle to iron, volcanic and undead.
Hard parts
- Time. Runs, the 05:00 reset, 20:00 raid nights and catching up after the app has been closed all have to agree, and the game clock must never go backwards when someone changes the phone's clock.
- Determinism. Every random choice draws from its own seeded stream, so adding a system doesn't reshuffle the results of an older one, and reloading never rerolls the AI server.
- Balance. The gear, experience and boss maths was written as models and checked by simulation before any screens were built, and the balance report regenerates from the tests.
- Never deciding for the player. The game shows consequences (upgrades, set progress, who will be unhappy) but never recommends a recipient or names an MVP.
What I learned
Write the maths down before the game. Specifying every model up front and checking it by simulation caught balance problems that would otherwise have taken weeks of play to find. And determinism is worth paying for early: a separate random stream for each decision means a new feature never quietly changes old results.