AI-Driven Text Adventure Game Development

🌟 AI-Driven Text Adventure Game Development

A Two-Week Journey of Building an AI-Native Game with Java Backend

When ancient cultivation realms meet large language models, and moral choices collide with card battlesβ€” I built an AI-native text game from scratch in two weeks. This is not just about coding, but a test of "design" and "harnessing AI".

🧠 Project Overview | What is the AI-Driven Text Adventure?

The AI-Driven Text Adventure is a LLM-driven narrative game. Players take on the role of a cultivator named Li Feiyu, who accidentally enters an ancient trial realm. In 10 layers and 200 decisions, each choice affects the good/neutral/evil balance of the character's heart, accumulating cards, and finally facing a personalized inner demon, leading to 7 different endings.

Key Innovations:

  • 🎭 Three-Value Morality + Threshold Elimination: If any value exceeds 90%, it triggers an extreme ending (saint dies, villain reaps what they sowed, or nothing is achieved)
  • πŸ”₯ Forced Choice Mechanism: Continuous selections increase weight, preventing mindless clicking
  • πŸƒ Card-Based Boss Battle: Psychological strategy + wildcard interference, rule-based AI + LLM-generated dialogue
  • πŸ‘» Inner Demon Concept: Companions are inner demons, following and reversing throughout the game

πŸ—“οΈ Two-Week Development Timeline | Timeline

timeline title AI-Driven Text Adventure Β· Two-Week Sprint Week1-1 : Core Algorithm Design (Morality Values / Card Control) : Boss Fight Rules Week1-2 : Writing Prompt Templates (Scenes / Layer Events / Inner Demon Dialogue) : Configuration Management Module Week2-1 : LLM Companion Prompts / Card Name Generation : Boss Fight Main Logic Implementation Week2-2 : Layer Events / Option Subsequent Generation : System Commands + Main Loop Integration : Testing and Documentation (Note: If the blog does not support mermaid, replace with a text listοΌ‰

βš™οΈ Technical Stack | Tech Stack

Domain Tools/Technologies Purpose
**Backend Language** Python 3.12 Main logic implementation
**AI Framework** LangChain Prompt templates, LLM calls
**Large Model** Deepseek API Scene generation, dialogue generation, card name generation
**Assistive Development** CodeBuddy Code generation based on prompts
**Code Review** DeepSeek Chat Review CodeBuddy code
**Configuration Management** python-dotenv API key management
**Testing Framework** unittest Unit testing

🧩 Modular Architecture | Modular Design

src/game_logic/
β”œβ”€β”€ config.py                # 200+ adjustable parameters (layers/rounds/thresholds/consecutive weight...)
β”œβ”€β”€ morality.py              # Morality algorithm (three-value ratio/consecutive weight/ending check)
β”œβ”€β”€ card_acquisition.py      # Card control (pure function probability algorithm)
β”œβ”€β”€ boss_ai.py               # Rule-based AI (boss card strategy)
β”œβ”€β”€ boss_dialogues.py        # Pre-generated dialogue (4 types Γ— 5 dialogue categories)
β”œβ”€β”€ boss_fight.py            # Boss fight state machine (challenge/ follow/ not follow)
β”œβ”€β”€ boss_fight_loop.py       # Human-computer interaction loop (including Chinese/English command parsing)
β”œβ”€β”€ scene_generator.py       # Full layer scene generation (LLM-driven)
β”œβ”€β”€ layer_event_generator.py # Layer event generation (including trap options)
β”œβ”€β”€ option_outcome_generator.py # Option subsequent + card naming
β”œβ”€β”€ commands.py              # System commands (HELP/PACK/STATUS/HINT/QUIT)
└── llm_hint.py              # AI companion hints (limited calls during boss fight)


🎨 Design Highlights | Highlights

πŸ§ͺ 1. Morality Algorithm: Forced Choice + Threshold Elimination

def update_morality(current_round, last_choice, current_choice, good, neutral, evil, consecutive):
    # Base score + consecutive weight ([0,3,5,7,8])
    if current_choice == 'A': good += 10 + bonus
    elif current_choice == 'B': 
        neutral += 8 + bonus
        random.choice([good, evil]) += 4   # Random offset
    elif current_choice == 'C': evil += 10 + bonus
    else:  # D
        target = random.choice(['good','evil'])
        target += 8 + bonus
    
    # Consecutive count update
    new_consecutive = consecutive+1 if current_choice==last_choice else 0
    
    # Extreme ending check
    if current_round>=10 and total>=80 and any(ratio>=0.9):
        return (..., ending=dominant)


Design Intent:

  • Three-value ratio instead of binary good/evil, more aligned with the complexity of cultivation "heart"
  • B option random offset simulates "cautious neutrality can occasionally act benevolently or maliciously"
  • Continuous selection weight makes "firm heart" accelerate, but exceeding threshold leads to extremes

πŸ‘Ή 2. Personalized Inner Demons: Your Heart, My Mirror

Before the boss battle, the inner demon form is dynamically generated based on the player's morality ratio:

Morality Tendency Inner Demon Form Entry Dialogue Example
**Good β‰₯ 50%** Anger of the Sacrificed "You saved Zhang San, but did you remember Li Si?"
**Evil β‰₯ 50%** Revenge of the Betrayed "The people you killed have come for you."
**Neutral β‰₯ 50%** Missed Possibilities "You chose nothing, so you missed everything."
**Balanced** Your own mirror "Who are you really?"

Technical Implementation:

  • Pre-generated 5 types of dialogues (entry/advantage taunt/disadvantage thought/victory/loss), stored in dialogues dictionary
  • Randomly triggered during battle, 30% chance to activate

πŸƒ 3. Boss Battle: Card Variant + Wildcard Psychological Strategy

# Player input parsing (supports Chinese/English three formats)
Example commands:
- Follow 2 Good   | follow 2 good   | Follow 3 Neutral
- Challenge       | challenge       | Doubt
- Fold            | fold            | Discard


Rule Design:

  • The player plays 1-3 cards, claiming their type (wildcards can be used as deception)
  • The response can choose Challenge/Follow/Fold
  • Successful challenge results in the opponent discarding their pile + additional discard, unsuccessful challenge results in the challenger discarding their pile + additional discard
  • The first to discard all cards wins

Wildcard Function:

  • Can act as any regular card, disrupting the opponent's reasoning
  • Limited quantity (up to 1 per layer), players must use them at critical moments

πŸ“œ 4. Layer Events: Trap Option Design

After each layer (non-boss layer), a special event is triggered, with four options where only one is a trap (selecting the trap does not grant a wildcard).

{
  "description": "A distant flute melody echoes through the illusion...",
  "options": {
    "A": { "text": "Follow the sound", "is_trap": false, "card_name": "Flute Card" },
    "B": { "text": "Listen quietly", "is_trap": false, "card_name": "Hear Sound Card" },
    "C": { "text": "Shout loudly", "is_trap": true, "card_name": null },
    "D": { "text": "Turn back", "is_trap": false, "card_name": "Pursue Flute Card" }
  }
}


Design Intent:

  • Enhance the unpredictability of the illusion
  • Encourage players to find "opportunity" in seemingly identical options

πŸ€– AI-Assisted Development Approach | My AI-First Workflow

As a Java backend developer, my Python knowledge was learned on the fly, but this didn't stop me from completing the project. My secret weapon was:

  1. System Design: First, write down the functionality, interfaces, and data flow of each module in Chinese
  2. Prompt Writing: Convert the design into clear "task prompts" (like a requirements document for an intern)
  3. CodeBuddy Code Generation: Use AI programming assistant to generate initial code based on prompts
  4. DeepSeek Review: Have the generated code reviewed by DeepSeek, pointing out logical flaws and boundary conditions
  5. Manual Integration and Debugging: Fix AI omissions, assemble all modules into a complete game

This approach allowed me to achieve:

  • 2-3x efficiency gain: A module that would have taken 2 days to write manually could be completed in half a day
  • Quality double assurance: AI-generated + AI-reviewed, significantly reducing low-level bugs
  • Cross-domain learning: By reviewing AI code, I reverse-engineered Python best practices

πŸ“Š Project Metrics | Metrics

Dimension Data
**Total Code Lines** ~3000 lines (excluding tests)
**Number of Modules** 12 core modules + 7 static text files
**Adjustable Parameters** 37 configurations (layers/rounds/thresholds/consecutive weight/probability distribution...)
**Ending Count** 7 endings (3 extreme + 3 normal + 1 special)
**LLM Call Count** Once per layer (scene generation) + once per boss fight (dialogue pre-generation) + limited HINT calls
**API Cost Estimate** Approximately $0.5-$1.0 per game (depending on model)

🌈 Fun ASCII Art | Just for Fun

    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
    β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β•β•β•β•β•
    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  
    β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β•β•β•  
    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
    β•šβ•β•β•β•β•β•   β•šβ•β•β•β•β•β•  β•šβ•β•  β•šβ•β•β•β• β•šβ•β•β•β•β•β•β•

         πŸŒ€ Realm Entrance | Heart Trial | Inner Demon Appears πŸŒ€


🧠 Core Algorithm Pseudocode (for demonstration only)

Morality Update Function

def update_morality(round, last, cur, g, n, e, consec):
    bonus = [0,3,5,7,8][min(consec,4)]
    if cur == 'A': g += 10 + bonus
    elif cur == 'B': 
        n += 8 + bonus
        (g if random<0.5 else e) += 4
    elif cur == 'C': e += 10 + bonus
    else:  # D
        (g if random<0.5 else e) += 8 + bonus
    
    new_consec = consec+1 if cur==last else 0
    # Ending check
    if round>=10 and (g+n+e)>=80:
        if max(g,n,e)/(g+n+e) >= 0.9:
            return (..., ending=dominant)
    return (g,n,e,new_consec,None)


Boss Battle Challenge Determination Core

def _apply_challenge(self, challenger):
    # Validate each card on the table
    for entry in self.table_pile:
        actual = entry['card']['type']
        claimed = entry['claimed']
        if actual != CardType.WILD and actual != claimed:
            # Found a fake
            # The challenged party recovers their pile + additional discard
            # Next round starts with the challenger
            return (..., new_turn=claimer)
    # All are real
    # The challenger recovers their pile + additional discard
    # Next round starts with the challenger
    return (..., new_turn=challenger)


πŸ“š Static Text Structure | Separate Content from Code

texts/
β”œβ”€β”€ welcome.txt               # Game opening
β”œβ”€β”€ rules.txt                 # Detailed rules
└── endings/                  # 7 ending texts
    β”œβ”€β”€ ending_extreme_good.txt
    β”œβ”€β”€ ending_extreme_evil.txt
    β”œβ”€β”€ ending_extreme_neutral.txt
    β”œβ”€β”€ ending_trick.txt
    β”œβ”€β”€ ending_good.txt
    β”œβ”€β”€ ending_evil.txt
    └── ending_neutral.txt


Design Intent:

  • Non-technical users (even myself) can modify the text without changing the code
  • Supports adding more ending variations later

πŸš€ How to Run? | How to Run

  1. Clone the repository (if available)
  2. Create a .env file and fill in DEEPSEEK_API_KEY
  3. Install dependencies: pip install -r requirements.txt
  4. Run: python src/main.py

πŸ’‘ Final Thoughts | Reflection

The biggest takeaway from these two weeks wasn't the code itself, but a new development paradigm:

  • Design > Coding: Focus on system decomposition and logic design, with AI handling execution
  • Review > Writing: Learn by reviewing AI code, quickly compensating for language gaps
  • Prompts = New Programming Language: Writing prompts is like writing a requirements document, but more precise and structured

If you also want to transition from backend to AI Agent, start by building your own small project with AIβ€”no need to wait until you learn all the syntax, just start building and learning along the way. Dedicated to my 37-year-old self, "Even if life is wasted, I will strive for that sliver of sky," "Uncle Han, is age really a barrier for programmers?" I asked myself again and again, and the answer was always, "No!" With the arrival of the AI era, it's completely possible to be a solo soldier, I am the army, and the next chapter we will use opencode to walk through a development process directly.

πŸ”— Links

Thank you for reading, feel free to communicate!β€” A Java backend still on the path of cultivation

Tags: LLM python GameDevelopment AIIntegration TextAdventure

Posted on Sat, 30 May 2026 19:42:24 +0000 by riddhi