AI PRODUCT DESIGN · GAME CASE STUDY

DEMON RISING

A dark-fantasy roguelike auto-battler where you don't play the hero — you play the Demon Lord. Raise an army, rule a treacherous court, and watch your battles erupt in synergies.

ROGUELIKE AUTO-BATTLER DARK FANTASY GODOT 4 SOLO DEV
Demon Rising trailer ▶ WATCH THE TRAILER Opens the trailer on YouTube in a new tab.
▼  SCROLL
THE PROJECT

Rule The Castle

An overview of the game, my role, and the tech behind it.

Demon Rising is a dark-fantasy roguelike auto-battler. You command the Demon Lord's castle: recruit fallen champions, convert captured heroes, and lead an inner circle of officers whose loyalty, ambition, and grudges you have to manage as carefully as the battlefield itself.

Every run sends you down a branching world map of battles, elites, markets, treasures and eerie encounters. Between fights you craft your army through talents, class fusion, relics and gear — then watch deterministic auto-battles play out, full of procs, spell chains and brutal combos.

I designed and built the whole game solo. But the part this case study focuses on is the AI-product-design work: the castle's court is driven by a local language model, and making a non-deterministic model feel like a reliable, readable product is the real story. The sections below break down how it was made.

QUICK FACTS

ROLEAI Product Designer — Interaction Design, AI Integration, Systems & UX
SCOPESolo — design & build, end to end
ENGINEGodot 4 · GDScript
AILocal LLM in the game loop
GENRERoguelike Auto-Battler
STATUSPlayable demo · in development
CORE SYSTEMS

What Makes It Tick

Six interlocking systems define the game loop.

⚔️

Positional Auto-Battler

Battles run as a deterministic simulation — units take positions, move, and unleash class skills, spell chains and combo procs. You set the army, then watch synergies collide.

🎣

9 Classes & Talent Trees

Charging heavies, blinking assassins, war-priests, lifesteal vampires — each class plays differently. Three-path talent trees and dual-class fusion drive deep build craft.

👑

The Round Table Council

Your top officers debate proposals at a round table — driven by a local LLM. Persuade them, settle disputes through sparring, and rule through politics.

💬

Living Minions

Every follower has a personality and a voice. Talk to them between battles, read the room, and manage loyalty before ambition turns to mutiny.

🗺️

Roguelike Runs

A branching world map, starting relics, a refreshing black market and dark random encounters. Build-defining choices stack up — no two runs play the same.

Fuse Your Army

Merge followers into stronger forms, combine two classes into one demon, and reshape your roster mid-run into something far deadlier than its parts.

MY ROLE

Case Study — Building Demon Rising

Design goals, the systems I engineered, and what the hard parts taught me.

The Concept

I wanted to build a roguelike that put the player on the other side of the fantasy. Instead of a band of heroes storming a dungeon, you are the Demon Lord at the top of it — recruiting, scheming, and sending your own monsters out to die. That single inversion drives everything: you don't just build a party, you run a court.

The goal was a game with the build-craft depth of a deck-builder, the spectacle of an auto-battler, and a layer of character and politics that most auto-battlers skip entirely.

Design Pillars

01

Be The Villain

You manage a castle and a court, not just a squad — loyalty and ambition matter as much as stats.

02

Deep, Legible Builds

Many systems, one clear loop. Power comes from synergy and choices within a run — not permanent grind.

03

A World That Talks Back

Minions have voices, officers have agendas — the castle should feel alive between every battle.

What I Built

Solo, in Godot 4 / GDScript: a deterministic combat simulator with a separate visual replay layer; 9 classes with branching talent trees, fusion, relics and traits; a full roguelike run structure; a complete pixel-art interface; and the system this case study is about — an LLM-driven council and a cast of living minions. Everything below is about that last part: the AI-product-design work.

The Hard Problem — Designing On Top Of An Unreliable Co-Author

The castle's standout system is the Round Table Council. Your officers debate a proposal, and you answer them by typing whatever you want. It runs on a local language model. Talking to a model is easy; shipping a product on one is not.

A language model is a co-author you can't fully trust. It is non-deterministic, sometimes slow, occasionally wrong, and every so often returns output in the wrong format entirely. A game cannot answer that with a spinner that never ends or an error on screen. So the core question was never "what prompt?" — it was: how do you build a reliable, legible experience on top of an unreliable component? That question shaped every decision below.

Fallback-First — Design The Failure Path Before The Happy Path

I designed the degraded experience first, then built the ideal one on top of it. Four rules:

  • Bound the latency. The game waits a fixed budget (~8 seconds) for the model. Past that, it stops waiting — no interaction is ever held hostage to the model's mood.
  • Always keep a deterministic fallback. A keyword-based intent classifier sits underneath the LLM at all times. If the model is slow, offline, or returns garbage, the keyword layer resolves the player's decision and the council still concludes — correctly.
  • Skip the model when you don't need it. If the player's words clearly contain "approved" or "denied", I classify locally and never call the LLM at all — faster, and it sidesteps a real failure mode where a small local model misreads a plain "Approved" as a question.
  • Never block the loop. The model runs asynchronously; the UI polls for a result. The player sees an honest, in-fiction "the officers are composing…" state — never a frozen screen.

The governing principle: the AI is an enhancement layer, not a dependency. Strip the model out entirely and the game is still fully playable. Designing to that bar is what made an AI-native feature genuinely shippable.

Designing For Open-Ended Input

Letting players type free text into a council is a UX trap — people don't know what's allowed, and an open box invites inputs the system can't honour. I designed around that instead of restricting it:

  • One intent model, five outcomes. Any input — eloquent or a single word — is mapped onto five intents: agree, refuse, modify, counter, or stay silent. The player keeps full expressive freedom; the system gets a bounded space it can actually act in.
  • Teach the space with affordances. The input field always shows live examples ("Try: Approved, Denied, Too rash—table it…"). Players learn what's possible by reading the UI, never a manual.
  • Make the AI's decision legible. A "herald" character translates the model's classification back to the player, in fiction — "The Lord's 'why' suggests he wants the proposal clarified." A hidden ML decision becomes readable, diegetic feedback; the player always knows what the system heard and why it responded the way it did.
  • Treat "no decision" as a designed state. Asking a question — the "counter" path — doesn't break the flow or read as an error. It loops back: the officer answers, and the player speaks again. Hesitation is a valid move, not a dead end.

The Trade-offs

  • Local model vs. cloud API. I chose a local LLM: zero per-player cost, works offline, no player data leaves the machine. The price is lower quality, higher and less predictable latency, and no guarantee the player has a strong GPU. Every fallback above exists because of this trade.
  • Determinism vs. emergence. Combat is fully deterministic — reproducible and balance-safe. The council is deliberately the opposite. I quarantined the non-determinism to the one system where surprise is the point, and kept it out of everything where fairness matters.
  • Freedom vs. legibility. Free text is expressive but opaque; menus are legible but flat. I kept the free text and bought the legibility back with the herald and the on-screen examples — so freedom didn't cost comprehension.
  • Depth vs. scope. Solo, finite time. When a whole subsystem (an entire shop economy) was costing the core loop more than it gave back, I cut it. Scoping by subtraction kept the game coherent.

Before & After — How It Evolved

None of this was right the first time. The shippable version is the iterated one:

  • The freeze. First: the council awaited the model with no timeout — on a slow machine the game locked up for 45+ seconds. Now: a bounded wait plus the keyword fallback; worst case is a few seconds, and it always resolves.
  • The dead end. First: the council only understood a literal "yes" or "no"; anything else stalled the screen. Now: the full five-intent model plus herald feedback — the player can argue, hedge, or ask a question, and the scene always moves forward.
  • The invisible deadlock. First: a follow-up dialog rendered behind the council panel — invisible, yet it still captured every click, so the whole screen silently stopped responding. Now: fixed layering. The lesson stuck: around AI interactions, the interaction plumbing fails just as hard as the model — and far more quietly.
  • The economy. First: early numbers made the AI-driven events trivial to spam. Now: retuned costs and gated low-value events, so each one stays a real decision.

Working Under Real Constraints

One developer, limited time, and a hard ceiling: the AI has to run on a normal player's PC — not a server I control. That ruled out "just call a big cloud model" and forced the discipline above — design the fallback first, treat the model as optional, quarantine the non-determinism, and turn every failure mode into a designed experience instead of a bug.

What made an AI-native feature shippable wasn't a better model — it was product design around an imperfect one. That approach generalises to any product with an LLM in the loop: assume it will sometimes be slow, wrong, or offline, and design so the user never pays for it.

What I Took Away

AI product design isn't prompt-writing. It's designing the system around a probabilistic component so the end user still gets something reliable and legible: bounded latency, an honest fallback, in-product feedback that explains what the AI did, and clear, deliberate trade-offs between the AI path and the deterministic one. Demon Rising is where I learned to actually build that — and it is the lens I bring to every AI product after it.