Inspiration

Descent-World was inspired by a gap between two formats we love: tightly authored narrative games and open-ended roleplay. Scripted games deliver strong pacing and atmosphere, but they eventually run out of paths. Fully open systems offer freedom, but often lose consistency and dramatic weight.

The project started with one core question:

Can we build a story engine where each choice feels meaningful, while the world still behaves like it has rules, history, and consequences?

We were also inspired by tabletop RPG session dynamics, where tension emerges through character conflict and imperfect information—not just combat or branching menus.

That is why the engine emphasizes structured world constraints, faction dynamics, and stateful NPC behavior, instead of treating every turn as a fresh prompt.


What It Does

Descent-World is a cinematic, AI-driven interactive narrative experience where players can:

  • Create a world premise and tone
  • Choose a world mode: realistic or speculative
  • Shape a protagonist identity and attributes
  • Progress through turn-based scenes with dynamic choices
  • Interact with stateful NPCs and evolving relationships
  • Reach endings based on accumulated commitment, tension, and world plasticity

The app combines:

  • Narrative text
  • Scene imagery
  • Adaptive music planning

It also tracks long-running game state, including:

  • Player attributes
  • Faction relationships
  • Hidden consequences
  • Scene history
  • Ending eligibility signals

How We Built It

We built the project using a modular TypeScript + React architecture.

Core Structure

  • components/
    Drives UI and gameplay flow (START → ROLE → PLAYING → ENDING)

  • services/narrativeEngine.ts
    Orchestrates world compilation, progression, dialogue, and endings

  • services/geminiService.ts
    Integrates Gemini for text, image generation, and live music session control

  • prompts/
    Specialized prompt contracts:

    • world_compiler
    • narrative_progression
    • narrative_director
    • dialogue_agent
    • ending_narrator
    • others
  • config/
    Defines pacing, tension thresholds, and gameplay tuning

Key Implementation Details

  • Enforced structured JSON outputs with parsing safeguards
    (cleaning, extraction, retry logic)

  • World generation produces enforceable laws, factions, and NPC knowledge boundaries

  • Turn progression updates:

    • Player attributes
    • Tension
    • Pending consequences
    • Director state
  • Ending logic evaluates metrics like commitment and world plasticity to trigger closure

  • Visual and music systems are context-aware with caching and fallback paths


Challenges We Ran Into

1. LLM Output Reliability

Model creativity is valuable, but game loops need deterministic structure.
We hardened JSON extraction, added sanitization, and implemented retries for malformed outputs.

2. Narrative Continuity Across Turns

Maintaining coherent character behavior over many turns was difficult.
We solved this by persisting:

  • NPC state
  • Active characters
  • Memory snippets
  • Consequence queues

3. Balancing Freedom vs Pacing

Too much freedom kills momentum; too much constraint feels scripted.
We introduced a director layer and configurable decision modes to maintain dramatic tension without removing agency.

4. Multi-Modal Consistency

Text, imagery, and music needed a shared identity.
We added world-level style guidance and context-aware prompt composition to keep assets aligned in tone and era.

5. Deciding When a Story Should End

Forced endings feel abrupt; endless stories lose impact.
We added player-facing round control and clear ending triggers to support both short and extended runs with meaningful closure.


Accomplishments We’re Proud Of

  • Built a complete playable loop from world setup to dynamic ending generation
  • Created a structured narrative engine with NPC stance, memory, and knowledge limits
  • Implemented dual world modes with realism constraints
  • Integrated visuals and audio tied to shared narrative context
  • Designed the codebase with clear module boundaries for scalability

Most importantly, we moved from an “AI text demo” to a systems-driven storytelling product where choices have persistent effects.


What We Learned

  • Generative models require strong constraints to be usable in interactive systems.
    Free-form creativity breaks game loops. Stability requires validation, retries, and fallbacks.

  • Narrative quality emerges from state, not text quality.
    Meaningful stories depend on memory, rules, and consequences—not better prose.

  • Player agency must be shaped to preserve pacing.
    A director layer helps balance freedom with tension.

  • Procedural stories still need intentional endings.
    Closure must be designed using explicit narrative signals.

  • Multimodal systems need shared context to stay coherent.
    Unified world guidance prevents drift across text, visuals, and audio.

  • Building an AI demo is easy; building an AI system is not.
    Real systems demand architecture, failure handling, and discipline.


What’s Next for Descent-World

1. Save / Load & Campaign Continuity

Persist full world and player state across sessions.

2. Content Expansion

Add new archetypes, faction templates, and event packs to increase replayability.

3. Tooling for Creators

Build editor-style controls for prompts and world rules so designers can tune experiences without code changes.

4. Accessibility & Localization

Improve multilingual parity, readability options, and long-session UX clarity.

5. Performance & Observability

Add telemetry for:

  • Turn latency
  • Generation failure rates
  • Player progression funnels

6. More Immersive Gameplay (2D → 3D)

Practical roadmap:

  • Build a stronger 2D interactive version
    (map navigation, character movement, scene interaction, UI overlays)

  • Prototype a 3D world mode
    (spatial environments, exploration, cinematic camera transitions)

  • Keep the same narrative engine as the core “brain” while upgrading the presentation layer

Built With

  • css
  • gemini
  • gemini-2.5-flash-image
  • gemini-3-flash
  • gemini-image
  • gemini-image-generation-models
  • gemini-lyria
  • google
  • google/genai
  • html
  • html-frameworks/libraries:-react
  • javascript
  • lucide-react
  • prompt-engineering
  • react
  • recharts-platform:-web-app-(browser-based)
  • typescript
  • vite
  • webapp
Share this project:

Updates