π 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
dialoguesdictionary - 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:
- System Design: First, write down the functionality, interfaces, and data flow of each module in Chinese
- Prompt Writing: Convert the design into clear "task prompts" (like a requirements document for an intern)
- CodeBuddy Code Generation: Use AI programming assistant to generate initial code based on prompts
- DeepSeek Review: Have the generated code reviewed by DeepSeek, pointing out logical flaws and boundary conditions
- 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
- Clone the repository (if available)
- Create a
.envfile and fill inDEEPSEEK_API_KEY - Install dependencies:
pip install -r requirements.txt - 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
- Gitee Repository: https://gitee.com/hanght/illusory-api-demo.git
- Design Document: https://www.cnblogs.com/hanght/articles/19736167
- Some prompt examples: https://www.cnblogs.com/hanght/category/2497552.html
Thank you for reading, feel free to communicate!β A Java backend still on the path of cultivation