Case study: Delve roguelike

Building a browser-based roguelike with procedural dungeons, turn-based combat, and enough replayability to keep you coming back.

Context

I wanted to see if Claude could design and balance a roguelike from scratch, figuring out features and systems iteratively without following a design doc. Also wanted a quick-run roguelike that respected my time—10 floors, 30–60 minute runs, replayability from modifiers and class variety rather than grinding for unlocks.

Roguelikes are a great test bed for systems design: procedural generation, combat balancing, progression curves, item variety, risk/reward decisions. Every run needs to feel different, but fair. Too easy and it’s boring. Too hard and it’s frustrating. Getting that balance right requires playtesting and iteration.

Problem

Build a roguelike that:

  • Feels classic: ASCII rendering, turn-based combat, permadeath, procedural dungeons
  • Runs quick: 30–60 minutes to completion, not 40-hour epics
  • Has variety: different classes, run modifiers, item builds, enemy types
  • Stays fair: RNG can be cruel, but never unfair. Deaths should feel deserved (even when you blame the game)
  • Works in a browser: no install, keyboard-driven, mobile-friendly

Constraints

  • Balancing without a design doc: I didn’t spec out the entire game upfront—Claude proposed systems, I playtested them, we iterated
  • Browser performance: pathfinding for 20+ enemies per turn, FOV calculations, dungeon generation—all need to feel instant
  • Mobile support: touch controls for movement, inventory, abilities (but keyboard remains primary)
  • Fair RNG: random generation can’t create unwinnable situations (no unavoidable damage, no mandatory items locked behind RNG)

Approach

1) Start with the core loop

Standard roguelike flow:

  1. Create character (class + background + run modifier)
  2. Descend through procedural dungeons
  3. Fight enemies, collect loot, level up
  4. Die or win
  5. Start over with knowledge gained

The key design question: what makes each run feel different?

Answer: class abilities + run modifiers + procedural dungeons + item variety.

2) Build systems incrementally

Rather than building everything up front, we added systems one at a time and playtested:

Iteration 1: MVP (1 week)

  • Single class (Warrior)
  • Basic combat (bump-to-attack)
  • 5 floors, simple procedural generation (rectangular rooms + corridors)
  • 5 enemy types (rat, bat, goblin, orc, skeleton)
  • 3 item types (health potion, weapon, armor)

Iteration 2: Class variety (1 week)

  • Added Rogue, Mage, Ranger, Necromancer
  • Unique abilities per class (Cleave, Smoke Bomb, Arcane Bolt, Volley, Animate Dead)
  • Passive class traits (Warrior regen, Rogue backstab, Mage potion mastery, Ranger eagle eye, Necromancer corpse pact)
  • Level-up perk trees

Iteration 3: Run modifiers (1 week)

  • 19 modifiers system (curses, blessings, mixed)
  • Rerollable at character creation
  • Each modifier changes the run significantly (Forsaken = no shop, Haunted = +3 enemies per floor, Glass Cannon = half HP + double ATK)

Iteration 4: Enemy variety (2 weeks)

  • Expanded to 30+ enemy types across 3 biomes
  • Special enemies: mimics (item/chest/door variants), pack leaders, named uniques
  • Boss fights for floors 3, 6, 9, 10
  • Enemy behaviors: fleeing, pack alerting, ranged attacks, regeneration, draining

Iteration 5: Item depth (1 week)

  • 12 potion types (unidentified each run)
  • Special weapons (Thornwhip, Soulstealer, Void Edge)
  • Special armors (Thornplate, Shadowweave, Wraithskin)
  • Rings, amulets, scrolls, wands, throwables

Iteration 6: Dungeon features (1 week)

  • Special rooms (shrines, libraries, vaults, challenge rooms, NPC encounters, mirror rooms, transmutation altars)
  • Floor events (65% chance: Hunting Pack, Blood Bounty, Silent Floor, Gold Rush, Undying, etc.)
  • Traps (spike, poison dart, confusion gas, teleport, alarm bell)
  • Gravestones from past runs

Iteration 7: Polish (ongoing)

  • Daily Challenge mode (shared seed, same dungeon for all players)
  • Kill streak system (×3 = XP bonus, ×5 = ATK buff, ×7+ = massive XP)
  • Status effects (poison, confusion, slow, strengthen, invisible, berserk)
  • Mobile touch controls
  • Balance tuning (this never ends)

3) Balance through playtesting

The hardest part: making the game challenging but fair.

Early problems:

  • Floor 1 was too deadly: Cave rats killed you before you found a weapon. Fixed by giving starting weapons.
  • Mage was overpowered: Infinite Arcane Bolts trivialize combat. Added mana system, then removed it (too fiddly). Final solution: cooldown + limited casts per floor.
  • Boss fights were trivial: Just stack health potions and tank. Fixed by adding boss abilities (Brood Mother spawns minions, Warlord has cleave, Pale King has phases).
  • Run modifiers unbalanced: Blessed gave too much free stuff, Haunted was unplayable. Tuned values through 20+ test runs.
  • Lategame scaling broken: Enemies hit too hard, armor didn’t matter. Fixed by adjusting DEF scaling and adding armor-bypassing enemies (so stacking DEF isn’t always optimal).

Testing approach:

  • Play 5–10 runs after each major change
  • Track win rate per class (should be 20–40% for skilled players)
  • Watch for “feels bad” moments (unavoidable deaths, impossible situations)
  • Ask: “Did I deserve that death?” If no, investigate.

4) Procedural generation that stays fair

Dungeon generation algorithm:

  1. Place rooms (rectangles of varying sizes)
  2. Connect rooms with corridors (A* pathfinding)
  3. Add special rooms (shrines, libraries, vaults) based on floor depth
  4. Spawn enemies (density increases with depth, biome-specific types)
  5. Place items (weapons, armor, potions, scrolls)
  6. Add stairs to next floor

Fairness constraints:

  • Every floor must have a valid path from entrance to exit
  • Starting room never has enemies
  • No enemy spawns within 3 tiles of player start position
  • At least 1 health potion guaranteed per floor
  • Shop always accessible (unless Forsaken modifier)

Biome variety:

  • The Warren (floors 1–3): Cave rats, bats, goblins, spiders. Tight corridors, small rooms.
  • The Ruins (floors 4–6): Orcs, skeletons, archers, cultists. Larger rooms, more loot.
  • The Crypt (floors 7–10): Trolls, vampires, wraiths, shades. Dark, dangerous, lots of traps.

5) Performance optimizations

Browser games need to feel instant. ROT.js (the ASCII rendering library) does most of the heavy lifting, but some things needed optimization:

Pathfinding:

  • A* for enemy movement (20+ enemies per turn)
  • Cached paths for static enemies (recalculate only when player moves)
  • Early exit if player unreachable

FOV calculations:

  • Computed once per player move (not per frame)
  • Cached explored tiles (don’t recalculate what player has already seen)

Rendering:

  • Only redraw visible tiles (not the entire map)
  • Batch DOM updates (one paint per turn, not per enemy move)

Result: 60fps even with 30+ enemies on screen.

6) Daily Challenge mode

Shared-seed runs for competitive play:

  • Seed based on UTC date (same dungeon layout for all players worldwide)
  • Fixed run modifier (no rerolls)
  • Same item spawns, same enemy positions
  • Leaderboard for each day’s challenge

Implementation: seed = hash of YYYY-MM-DD string → deterministic RNG → reproducible dungeons.

Tradeoffs

Chose simplicity over complexity:

  • No hunger system (adds tedium without depth)
  • No equipment durability (except Brittle modifier)
  • No item identification minigame (potions are unidentified, but drinking is the only way to learn)
  • No multi-floor backtracking (descent is one-way)

Chose browser delivery over native:

  • Easier to iterate (no app store reviews)
  • Instant access (no install friction)
  • Cross-platform by default
  • Tradeoff: can’t use native features (gamepad rumble, notifications, file system)

Chose turn-based over real-time:

  • More tactical, less stressful
  • Works better on mobile (no twitch reflexes required)
  • Easier to balance (no framerate-dependent behavior)

What I learned

Balancing is 90% of game development. The code was done in 2 weeks. The next 2 months were tuning numbers and fixing edge cases.

Roguelikes are unforgiving teachers. Every unfair death reveals a design flaw. Players will find every edge case you didn’t plan for.

Procedural generation is hard to get right. It’s easy to generate random dungeons. It’s hard to generate interesting random dungeons that feel hand-crafted.

Claude is surprisingly good at game design. It proposed smart systems (kill streaks, pack leaders, run modifiers) that I hadn’t thought of. The iterative process worked well.

Players remember unfair deaths forever. A single “bullshit” death will overshadow 10 great runs. Fairness is more important than difficulty.

Results

Current state (v2.41.0):

  • 5 classes with full progression trees (3 milestones each, ~8 perks per class)
  • 19 run modifiers (6 curses, 4 blessings, 9 mixed)
  • 30+ enemy types across 3 biomes
  • 10 floors with 3 distinct biomes
  • 4 boss fights (floors 3, 6, 9, 10)
  • 50+ item types (potions, weapons, armor, rings, amulets, scrolls, wands, throwables)
  • 65% floor event rate (16 different event types)
  • Daily Challenge mode with shared seed and leaderboard
  • Persistent gravestones from past runs
  • Mobile-friendly touch controls

Player outcomes (from my own playtesting):

  • Average run time: 45 minutes
  • Win rate (skilled): ~35%
  • Win rate (first-time): ~5%
  • Most common cause of death: “got surrounded by orcs” (classic)

What I’d do next

  • More classes: Bard (buffs), Paladin (healing + tank), Druid (shapeshifting)
  • Meta-progression: unlock new starting items, perks, or modifiers after completing runs
  • Achievements: track silly stats (“die to a cave rat 10 times”, “win with every class”)
  • More biomes: add 5 floors (The Depths, The Void) for extended runs
  • Multiplayer Daily Challenge leaderboard: show rankings, replay other players’ runs
  • Better mobile UX: larger touch targets, swipe gestures for movement
  • Mod support: let players create custom classes, enemies, items