v0.1.0 — M1: Project Setup + Tilemap + Combat + Backend
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
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
# 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)
|
||||
|
||||
```sql
|
||||
-- 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
|
||||
|
||||
```python
|
||||
# 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
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
# 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
|
||||
Reference in New Issue
Block a user