5cf42a5e5d
Frontend: - HTML5 Canvas isometric tilemap renderer - Eichenhafen starting city (procedural) - Click-to-move A* pathfinding - Player stats, HP/SP/EXP bars, skill bar, minimap - 3 NPCs (merchant, class master, innkeeper) - 6 monster spawns with aggro AI - Combat: auto-attack, damage numbers, EXP/gold - Player death + respawn Backend: - FastAPI server with SQLite - Ollama LLM bridge for events + dialogue - Event validation (no soft-lock) - NPC dialogue generation Design: - Full DESIGN.md with architecture, formulas, milestones - 6 base classes + 6 advanced classes - 3 fixed cities, dynamic events
7.5 KiB
7.5 KiB
Aether Chronicles — Design Document
1. Architecture
┌─────────────────────────────────────────────────┐
│ Browser (JS) │
│ ┌─────────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Renderer │ │ Input │ │ UI Manager │ │
│ │ (Canvas) │ │ Handler │ │ (DOM) │ │
│ └──────┬──────┘ └────┬─────┘ └──────┬──────┘ │
│ └───────────────┴───────────────┘ │
│ │ │
│ Game Client (JS) │
└────────────────────────┬─────────────────────────┘
│ REST + WebSocket
┌────────────────────────┴─────────────────────────┐
│ Python Backend (FastAPI) │
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ Game │ │ LLM │ │ World State │ │
│ │ Engine │ │ Bridge │ │ (SQLite) │ │
│ └────┬─────┘ └────┬─────┘ └───────┬───────┘ │
│ │ │ │ │
│ └─────────────┴─────────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ Ollama │ │
│ │ (gemma4) │ │
│ └─────────────┘ │
└──────────────────────────────────────────────────┘
2. Game State (SQLite Schema)
-- Player
CREATE TABLE player (
id INTEGER PRIMARY KEY,
name TEXT,
class TEXT DEFAULT 'wanderer',
level INTEGER DEFAULT 1,
exp INTEGER DEFAULT 0,
hp INTEGER DEFAULT 100,
max_hp INTEGER DEFAULT 100,
sp INTEGER DEFAULT 50,
max_sp INTEGER DEFAULT 50,
str INTEGER DEFAULT 10,
agi INTEGER DEFAULT 10,
int INTEGER DEFAULT 10,
vit INTEGER DEFAULT 10,
dex INTEGER DEFAULT 10,
luk INTEGER DEFAULT 5,
x REAL DEFAULT 400,
y REAL DEFAULT 300,
map_id TEXT DEFAULT 'eichenhafen',
gold INTEGER DEFAULT 100
);
-- Inventory
CREATE TABLE inventory (
id INTEGER PRIMARY KEY,
player_id INTEGER,
item_id TEXT,
quantity INTEGER DEFAULT 1,
equipped INTEGER DEFAULT 0
);
-- World Events (LLM-generated)
CREATE TABLE world_events (
id INTEGER PRIMARY KEY,
map_id TEXT,
event_type TEXT,
description TEXT,
data_json TEXT,
active INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- NPC Dialogues (LLM-generated, cached)
CREATE TABLE npc_dialogues (
id INTEGER PRIMARY KEY,
npc_id TEXT,
mood TEXT,
dialogue TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Quests
CREATE TABLE quests (
id INTEGER PRIMARY KEY,
quest_type TEXT,
name TEXT,
description TEXT,
npc_id TEXT,
map_id TEXT,
min_level INTEGER,
reward_gold INTEGER,
reward_exp INTEGER,
status TEXT DEFAULT 'available'
);
3. LLM Integration
Prompt Templates
# Event Generation
EVENT_PROMPT = """You are the Dungeon Master for Aether Chronicles.
Current map: {map_name}
Current time: {time_of_day}
Player level: {player_level}
Recent events: {recent_events}
Generate ONE optional event for this map. Rules:
- Must be optional (player can ignore it)
- Must not block any paths
- Must not move any NPCs
- Must not be required for progression
- Keep it short (2-3 sentences)
Respond in JSON:
{
"type": "weather|encounter|discovery|npc_mood",
"description": "...",
"effect": "buff|debuff|spawn|dialogue",
"data": { ... }
}
"""
# NPC Dialogue
DIALOGUE_PROMPT = """You are {npc_name}, a {npc_role} in {city_name}.
Your personality: {personality}
Current mood: {mood}
The player ({player_class}, level {player_level}) approaches you.
Say something in character (2-3 sentences). Be brief.
"""
Validation Rules
def validate_event(event: dict, map_id: str) -> bool:
# Never block paths
if event.get("effect") == "block_path": return False
# Never move NPCs
if event.get("effect") == "move_npc": return False
# Never required for main quest
if event.get("required") == True: return False
# Must be optional
if event.get("optional") == False: return False
return True
4. Map System
Fixed Maps
eichenhafen — Starting city (harbor)
eichenhafen_field — Field outside starting city (main road)
sonnenfeld — Central trade city
sonnenfeld_field — Field outside trade city
nebelgipfel — Mountain fortress city
nebelgipfel_path — Mountain path (dangerous)
Dynamic Maps (LLM-generated layouts)
side_dungeon_1 — Generated dungeon layout
side_dungeon_2 — Generated dungeon layout
cave_random — Generated cave layout
5. Combat Formulas
# Physical damage
damage = (atk * (1 + str/100)) - (target_def * 0.5)
damage = max(1, damage) # minimum 1 damage
# Magic damage
magic_damage = (matk * (1 + int/100)) * element_multiplier
# Hit rate
hit_rate = min(95, 80 + (dex - target_agi) * 2)
# Critical rate
crit_rate = min(50, 5 + luk * 2)
# EXP needed for next level
exp_needed = int(100 * (level ** 1.5))
6. Milestone Details
M1: Project Setup + Tilemap (1-2 hours)
- HTML5 Canvas setup
- Isometric tilemap renderer
- Tile loading from JSON
- Camera with mouse pan/zoom
- Basic tileset (grass, water, path, building)
M2: Click-to-Move (1-2 hours)
- A* pathfinding implementation
- Click destination → character walks path
- Collision detection (walls, water)
- Smooth movement animation
M3: Player Stats + UI (1-2 hours)
- HP/SP bars (DOM overlay)
- Skill bar (1-0 keys)
- Character info panel
- EXP bar
M4: Combat (2-3 hours)
- Click enemy → auto-attack
- Damage numbers floating
- Death animation
- EXP gain on kill
- Aggro range for monsters
M5: Monster AI (2-3 hours)
- Spawn system
- Patrol behavior
- Aggro + chase
- Respawn timer
- Drop table
M6: City + NPCs (3-4 hours)
- Eichenhafen map layout
- NPC sprites + interaction
- Shop interface
- Storage interface
- Class master NPC
M7: LLM Integration (3-4 hours)
- Ollama API bridge
- Event generation (periodic)
- NPC dialogue generation
- Event validation
- Caching to reduce LLM calls
M8: Quest System (2-3 hours)
- Fixed main quests
- LLM side quests (validated)
- Quest log UI
- Turn-in mechanics
M9: Inventory + Equipment (2-3 hours)
- Item system
- Equipment slots
- Stats from equipment
- Drop/pickup
M10: Class System (3-4 hours)
- Class change at level 10
- Skill trees
- Skill effects in combat
- 2nd class at level 40