diff --git a/README.md b/README.md index fe557ab..419f520 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,179 @@ # Commander AI Lab -A full-stack MTG Commander AI research platform. Simulate hundreds of games overnight, train ML models on the results, and let simulation data automatically shape the AI deck builder — all from a web UI or CLI. +A full-stack Magic: The Gathering Commander research platform. Run thousands of simulated games, train neural networks on the outcomes, build decks with AI that learns from simulation data, get LLM-powered coaching, and play live 4-player battles — all from a single unified system. -## What It Does +--- -| Layer | What it is | -|---|---| -| **Monte Carlo Engine** | Pure-Python headless sim — runs thousands of games in minutes, no JVM needed | -| **Forge Engine** | Java/Forge rules-complete sim for ground-truth validation | -| **Overnight Runner** | Unattended batch runner — runs sims, updates sim weights, trains neural net | -| **ML Pipeline** | Outcome-weighted RL nudges card scoring weights; neural net trains on decision logs | -| **Deck Builder** | 7-step LLM pipeline (EDHrec → Scryfall → Ollama) now injected with sim-learned insights | -| **AI Coach** | LLM-powered coaching sessions (Anthropic/Ollama) with streaming support | -| **Web UI** | React + FastAPI dashboard for decks, sims, training, and deck building | +## Overview + +Commander AI Lab connects a rules-complete Forge engine, a fast Monte Carlo simulator, an LLM deck builder, an ML training pipeline, and multiple game clients (web, LAN, Unity) into one closed-loop platform. Simulation results feed back into deck building and AI decision-making, so the system improves the more it plays. + +### Key Capabilities + +- **Batch Simulation** — Run hundreds or thousands of Commander games unattended using Forge (rules-complete) or a headless Python Monte Carlo engine +- **ML Training Pipeline** — Reinforcement learning (PPO) trains a neural net on game decision logs; outcome-weighted scoring nudges card weights automatically +- **AI Deck Builder** — 7-step LLM pipeline (EDHrec → Scryfall → Ollama) with simulation-learned insights injected into prompts +- **LLM Coach** — Streaming coaching sessions powered by Anthropic Claude or local Ollama models, enriched with RAG-retrieved card knowledge +- **RAG Card Knowledge** — ChromaDB vector store over 30,000+ Scryfall cards with semantic search and auto-staleness monitoring +- **LAN Battlefield** — Browser-based 4-player Commander game client with ML-powered AI opponents and precon deck support +- **Unity Client** — Full Unity application with battleground scene, lobby system, WebSocket game state sync, and cross-platform builds +- **Card Scanner** — OCR pipeline for physical card recognition via Ximilar API +- **163 Precon Decks** — Complete preconstructed deck library in `.dck` format + +--- ## Architecture ``` -┌─────────────────────────────────────────────────────────────────┐ -│ Web UI (React/TypeScript — frontend/) │ -│ Deck Builder · Sim Dashboard · Training · Coach │ -└────────────────────────┬────────────────────────────────────────┘ - │ HTTP/REST + WebSocket -┌────────────────────────┴────────────────────────────────────────┐ -│ FastAPI Server (lab_api.py / routes/ — port 8080) │ -│ /api/lab/* /api/ml/* /api/coach/* /api/deck-builder/* │ -└────────┬──────────────────┬──────────────────┬──────────────────┘ - │ │ │ - Java subprocess Python sim engine Ollama (local LLM) - (Forge rules) (Monte Carlo) qwen2.5:7b + others - │ │ -┌────────┴───────┐ ┌───────┴────────────────────────────────────┐ -│ Forge Engine │ │ src/commander_ai_lab/ │ -│ (rules- │ │ sim/ — engine, models, rules │ -│ complete) │ │ deck_builder/ — 7-step LLM pipeline │ -└────────────────┘ │ coach/ — streaming LLM coach │ - └────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────┐ +│ Clients │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────────┐ │ +│ │ Web UI │ │ LAN Client │ │ Unity Client │ │ +│ │ (React/TS) │ │ (HTML/JS) │ │ (C# / URP) │ │ +│ │ /ui │ │ /lan │ │ /unity-client │ │ +│ └──────┬───────┘ └──────┬───────┘ └──────┬───────────────────────┘ │ +│ └────────────────┼────────────────┘ │ +│ │ HTTP/REST + WebSocket │ +│ ┌───────────────────────┴─────────────────────────────────────────┐│ +│ │ FastAPI Backend (lab_api.py — port 8080) ││ +│ │ ││ +│ │ /api/lab/* Batch simulation (Forge + Monte Carlo) ││ +│ │ /api/deck-builder/* 7-step LLM deck construction ││ +│ │ /api/coach/* Streaming LLM coaching sessions ││ +│ │ /api/ml/* Neural net training + policy server ││ +│ │ /api/rag/* ChromaDB vector search ││ +│ │ /api/game/* Live game sessions (Forge IPC) ││ +│ │ /api/policy/* ML policy decisions for AI players ││ +│ │ /ws/game/{id} WebSocket game state streaming ││ +│ └───────┬──────────────┬──────────────┬──────────────┬────────────┘│ +│ │ │ │ │ │ +│ ┌──────┴──────┐ ┌────┴─────┐ ┌──────┴──────┐ ┌────┴──────┐ │ +│ │ Forge │ │ Monte │ │ Ollama │ │ ChromaDB │ │ +│ │ Engine │ │ Carlo │ │ (local LLM) │ │ (vector │ │ +│ │ (Java/JVM) │ │ Engine │ │ qwen2.5:7b │ │ store) │ │ +│ └─────────────┘ │ (Python) │ └─────────────┘ └───────────┘ │ +│ └──────────┘ │ +│ ┌──────────────────────────────────────────────────────────────────┐│ +│ │ ML Pipeline ││ +│ │ decisions_*.jsonl → update_weights.py → learned_weights.json ││ +│ │ → /api/ml/train → neural net checkpoints ││ +│ └──────────────────────────────────────────────────────────────────┘│ +└─────────────────────────────────────────────────────────────────────┘ ``` -## Quick Start (Windows) +--- -**Prerequisites:** Java 17+, Python 3.10+, Maven 3.8+, [Forge](https://github.com/Card-Forge/forge) built at `D:\ForgeCommander\forge-repo` +## Features + +### Simulation Engines + +| Engine | Description | Speed | +|---|---|---| +| **Forge** | Rules-complete Java engine — handles the stack, instants, triggered abilities, and all Commander rules. Each game spawns a JVM subprocess. | ~0.04 sims/sec (single-threaded) | +| **Monte Carlo** | Headless Python engine — models combat keywords (flying, trample, deathtouch, lifelink, menace, reach, haste), summoning sickness, tapped state, commander zone, multiplayer targeting, and board wipes. No JVM required. | Thousands of games in minutes | + +Both engines feed structured results into the same ML pipeline. + +### Deck Builder + +The `POST /api/deck-builder/build` endpoint runs a 7-step pipeline: + +1. Resolve commander via Scryfall +2. Fetch EDHrec recommendations +3. Fetch Scryfall candidates by category (ramp, removal, draw, lands) +4. Ollama suggests synergy/protection/wincon cards — **simulation insights injected here** +5. Filter by color identity, collection, and ban list +6. Ollama enforces ratios (trim/expand to 99) — **simulation insights injected here** +7. Assemble final deck with smart substitution (guarantees 99-card output) + +### AI Coach + +LLM-powered coaching with two modes: + +- **Full Session** — Deep analysis including removal coverage, ramp quality, draw engine profiling, win conditions, anti-synergy detection, pod meta evaluation, and tempo assessment +- **Quick Digest** — Fast ~5-second summary for rapid feedback + +Coaching prompts are enriched with semantically relevant cards from the ChromaDB RAG store (15 cards for full sessions, 8 for quick digests). Supports both Anthropic Claude and local Ollama models with streaming responses. + +### RAG Card Knowledge + +- **SQLite FTS5** bulk card database from Scryfall data +- **ChromaDB** vector index with natural-language card embeddings +- Automatic staleness monitoring (checks every 6 hours, auto-rebuilds if >14 days old) +- Graceful fallback — RAG failures never block coaching or deck building + +### ML Training Pipeline + +``` +Overnight sims → decisions_*.jsonl + ↓ +update_weights.py → learned_weights.json (feeds deck builder) + ↓ +/api/ml/train → neural net training on decision dataset + ↓ +/api/policy/decide → ML policy serves AI decisions in live games +``` + +- **Outcome-weighted RL** nudges card scoring weights from game results +- **Neural net** trains on the full decision log dataset +- **Distillation loop** — self-play → collect data → retrain → repeat +- **ELO tracking** and model tournaments for comparing AI versions +- Weights clamped to `[-20.0, 20.0]`, stored in `learned_weights.json` + +### Win Condition Tracking + +Games are classified by win type — not just "Combat" vs "Other": + +- **Combat** — standard creature damage wins +- **Combo** — Approach of the Second Sun, Felidar Sovereign, Happily Ever After, and 30+ known alternate-win cards +- **Drain** — life drain effects +- **Mill** — library depletion +- **Poison** — infect/poison counter wins + +Draw games (timeout) are analyzed separately with per-player life-at-timeout snapshots and likely cause identification. + +### LAN Battlefield Client + +Browser-based 4-player Commander game at `/lan`: + +- **AI Bridge** — REST + WebSocket connectivity with ML policy decisions as Priority 1 (falls back to local heuristic AI) +- **Deck System** — 3-tab selector: Precons (163 decks, grouped by set), EDHREC search, and custom deck import +- **Player Panels** — Life counters, commander damage bars, poison/energy/experience/rad counters, emblem management +- **Backend Detection** — Auto-detects the Commander AI Lab backend; works offline with local precon data + +### Unity Client + +Full Unity application (URP, .NET Standard 2.1) with: + +- **Battleground Scene** — 4-seat layout with rotated perspectives, life/poison/commander damage widgets, phase tracker, turn order bar +- **Card System** — Hand, battlefield, graveyard, exile zones with card art, tapped rotation, face-down state, summoning sickness indicators +- **Stack & Mana** — LIFO stack display and 6-pip mana pool +- **Lobby System** — Configure 4 seats (human/AI), POST to backend, WebSocket game state sync +- **Elimination** — Grayscale shader overlay on eliminated players +- **Token System** — Create, tap, add counters, delete tokens +- **Cross-Platform** — Windows, WebGL, Android, iOS build targets +- **Scenes** — MainMenu, Collection, DeckBuilder, DeckGenerator, Simulator, Coach, Scanner, Training, Precon, Battleground + +### Card Scanner + +OCR pipeline for physical Magic cards using the Ximilar API. Scan cards from photos and match them to the Scryfall database. + +--- + +## Quick Start + +### Prerequisites + +| Tool | Version | +|---|---| +| Python | 3.10+ | +| Java | 17+ | +| Maven | 3.8+ | +| Node.js | 18+ (for LAN client scripts) | +| Ollama | Latest (for local LLM inference) | +| [Forge](https://github.com/Card-Forge/forge) | Built at `D:\ForgeCommander\forge-repo` | + +### Setup (Windows) ```powershell # 1. Build Forge (one-time) @@ -51,17 +184,29 @@ mvn package -pl forge-gui-desktop "-DskipTests" "-Drevision=2.0.12-SNAPSHOT" -am cd D:\ForgeCommander\commander-ai-lab mvn package "-DskipTests" -# 3. Install Python deps -pip install -e . +# 3. Install Python dependencies +pip install -e ".[rag,dev]" -# 4. Launch +# 4. Pull an Ollama model for the deck builder +ollama pull qwen2.5:7b + +# 5. Launch .\start-lab.bat -# → open http://localhost:8080 +# → Web UI: http://localhost:8080 +# → LAN Client: http://localhost:8080/lan/ ``` +Or use the automated installer: + +```powershell +.\install-commander-ai-lab.ps1 +``` + +--- + ## Overnight AFK Runner -Runs batch sims unattended, then updates card weights and trains the neural net: +Run batch simulations unattended, then automatically update card weights and train the neural net: ```powershell python overnight-run.py # default: 11.5h DeepSeek sims @@ -74,9 +219,9 @@ python overnight-run.py --no-train # skip neural net training 1. `update_weights.py` — nudges `learned_weights.json` from decision logs (feeds deck builder) 2. `/api/ml/train` — trains the neural net on the full decision dataset -## Sim → Deck Builder Feedback Loop +--- -Simulation outcomes automatically improve deck recommendations: +## Simulation → Deck Builder Feedback Loop ``` Overnight sims → decisions_*.jsonl @@ -90,24 +235,63 @@ Ollama prompts (suggest_cards + enforce_deck_ratios) Better card recommendations ``` -When active, `BuildResult.sources_consulted` includes `"sim_weights"`. No-op until real sim data exists. +When active, `BuildResult.sources_consulted` includes `"sim_weights"`. The loop is a no-op until real sim data exists. -## Deck Builder Pipeline +--- -The `POST /api/deck-builder/build` endpoint runs 7 steps: +## API Reference -1. Resolve commander via Scryfall -2. Fetch EDHrec recommendations -3. Fetch Scryfall candidates by category (ramp, removal, draw, lands) -4. Ollama suggests synergy/protection/wincon cards ← **sim insights injected here** -5. Filter by color identity, collection, ban list -6. Ollama enforces ratios (trim/expand to 99) ← **sim insights injected here** -7. Assemble final deck +### Simulation -## ML Pipeline +| Endpoint | Method | Description | +|---|---|---| +| `/api/lab/decks` | GET | List available Commander decks | +| `/api/lab/start` | POST | Start Forge batch (returns batchId) | +| `/api/lab/start-deepseek` | POST | Start Python/DeepSeek batch | +| `/api/lab/status?batchId=X` | GET | Poll batch progress | +| `/api/lab/result?batchId=X` | GET | Get completed batch JSON | +| `/api/lab/history` | GET | List past batch runs | +| `/api/lab/precons/deck` | GET | Fetch precon `.dck` file content | + +### Deck Builder & Coach + +| Endpoint | Method | Description | +|---|---|---| +| `/api/deck-builder/build` | POST | Build a 99-card Commander deck | +| `/api/coach/chat` | POST | Full coaching session (streaming) | +| `/api/coach/quick-digest` | POST | Fast ~5s coaching summary | + +### ML & Policy + +| Endpoint | Method | Description | +|---|---|---| +| `/api/ml/train` | POST | Start neural net training | +| `/api/ml/train/status` | GET | Poll training progress | +| `/api/policy/decide` | POST | Get ML policy decision for game state | + +### RAG + +| Endpoint | Method | Description | +|---|---|---| +| `/api/rag/build` | POST | Build/rebuild ChromaDB index | +| `/api/rag/search` | POST | Semantic card search | +| `/api/rag/status` | GET | Index health and staleness | + +### Live Game + +| Endpoint | Method | Description | +|---|---|---| +| `/api/game/start` | POST | Create a live game session | +| `/api/game/action` | POST | Submit a player action | +| `/api/game/{id}/actions` | GET | Poll Forge IPC actions | +| `/ws/game/{game_id}` | WS | Real-time game state streaming | + +--- + +## ML Scripts ```powershell -# Update sim card weights from decision logs (runs automatically in overnight-run.py) +# Update card weights from decision logs python -m ml.scripts.update_weights --min-games 10 --lr 0.05 --dry-run # Reset weights to defaults @@ -117,7 +301,7 @@ python -m ml.scripts.update_weights --reset python ml/scripts/generate_synthetic_data.py ``` -Learned weights are clamped to `[-20.0, 20.0]` and stored in `src/commander_ai_lab/sim/learned_weights.json`. +--- ## Python Simulator API @@ -129,52 +313,122 @@ stats = run_simulation(deck, num_games=100, name_a="My Deck") print(f"Win rate: {stats['win_rate']:.1%}, Avg turns: {stats['avg_turns']:.1f}") ``` -The Monte Carlo engine models: combat keywords (flying, trample, deathtouch, lifelink, menace, reach, haste), summoning sickness, tapped/untap state, commander zone, multiplayer attack targeting, and board wipes. It does **not** model the stack, instants, or continuous type-changing effects. - -## API Reference - -| Endpoint | Method | Description | -|---|---|---| -| `/api/lab/decks` | GET | List available Commander decks | -| `/api/lab/start` | POST | Start Forge batch (returns batchId) | -| `/api/lab/start-deepseek` | POST | Start Python/DeepSeek batch | -| `/api/lab/status?batchId=X` | GET | Poll batch progress | -| `/api/lab/result?batchId=X` | GET | Get completed batch JSON | -| `/api/lab/history` | GET | List past batch runs | -| `/api/ml/train` | POST | Start neural net training | -| `/api/ml/train/status` | GET | Poll training progress | -| `/api/coach/chat` | POST | LLM coaching session (streaming) | -| `/api/deck-builder/build` | POST | Build a 99-card Commander deck | +--- ## Project Structure ``` commander-ai-lab/ +├── lab_api.py # FastAPI server entry point ├── overnight-run.py # AFK batch runner ├── start-lab.bat # Windows one-click launcher -├── lab_api.py # FastAPI server entry point -├── frontend/ # React + TypeScript web UI -├── ui/ # Legacy static HTML UI +├── install-commander-ai-lab.ps1 # Automated setup script +├── pom.xml # Maven build (Java/Forge components) +├── pyproject.toml # Python package config +│ +├── routes/ # FastAPI route modules +│ ├── lab.py # Batch simulation +│ ├── deckbuilder.py # Deck builder pipeline +│ ├── coach.py # LLM coaching +│ ├── ml.py # ML training +│ ├── rag.py # ChromaDB vector search +│ ├── game.py # Live game sessions +│ ├── policy.py # ML policy server +│ ├── precon.py # Precon deck serving +│ ├── scanner.py # Card OCR +│ └── ws_game.py # WebSocket game state +│ +├── services/ # Core service layer +│ ├── forge_runner.py # Forge subprocess management +│ ├── draw_game_analyzer.py # Draw/timeout analysis +│ ├── rag_store.py # ChromaDB vector store +│ └── card_text.py # Shared card text builder +│ ├── src/commander_ai_lab/ -│ ├── sim/ # Monte Carlo engine (engine, models, rules) -│ ├── deck_builder/ # LLM deck builder pipeline -│ │ ├── api/ # Scryfall, EDHrec, Ollama, sim_insights -│ │ ├── core/ # Models, rules engine, assembler -│ │ └── pipeline/ # build_deck.py (7-step orchestrator) -│ └── coach/ # LLM coaching (Anthropic + Ollama) -├── ml/ -│ ├── scripts/ # update_weights.py, ml_cli.py -│ ├── training/ # Neural net trainer -│ ├── encoder/ # Feature encoding -│ └── models/ # Saved model checkpoints -├── scanner/ # Card OCR pipeline -├── logs/decisions/ # ML decision logs (gitignored) -└── src/main/java/commanderailab/ # Java/Forge batch runner +│ ├── sim/ # Monte Carlo engine +│ │ ├── engine.py # Game loop +│ │ ├── models.py # GameResult, Card, Player +│ │ ├── rules.py # Combat, keywords, commander rules +│ │ ├── win_condition_parser.py # Alternate win detection +│ │ └── learned_weights.json # ML-learned card weights +│ ├── deck_builder/ # 7-step LLM pipeline +│ │ ├── api/ # Scryfall, EDHrec, Ollama, sim_insights +│ │ ├── core/ # Models, rules engine, assembler +│ │ └── pipeline/ # build_deck.py orchestrator +│ └── coach/ # LLM coaching +│ ├── coach_service.py # Session + quick digest +│ ├── prompt_template.py # System/user prompts +│ └── embeddings.py # Card embedding utilities +│ +├── ml/ # ML training pipeline +│ ├── scripts/ # update_weights.py, ml_cli.py +│ ├── training/ # Neural net trainer +│ ├── encoder/ # Feature encoding +│ └── models/ # Saved checkpoints +│ +├── lan-client/ # Browser-based LAN battlefield +│ ├── index.html # Entry point +│ ├── engine.js # Game engine + ML AI turns +│ ├── ai-bridge.js # Backend connector + policy bridge +│ ├── player-panels.js # Enhanced player panels +│ ├── ui.js # 3-tab deck selector + setup +│ └── precons.js # 163 precon deck data +│ +├── unity-client/ # Unity game client +│ └── Assets/ +│ ├── Scenes/ # 11 scenes (MainMenu → Battleground) +│ ├── Scripts/ # C# controllers, models, services +│ ├── Prefabs/ # Card, deck slot, chat bubble +│ └── Materials/ # URP materials + grayscale shader +│ +├── scanner/ # Card OCR pipeline (Ximilar) +├── precon-decks/ # 163 preconstructed decks (.dck) +├── sample-decks/ # Sample deck files +├── data/ # Runtime data (ChromaDB, bulk DB) +├── logs/ # Simulation + decision logs +├── docs/ # Architecture docs + schemas +├── tests/ # Test suite +├── scripts/ # Utility scripts +├── .github/workflows/ # CI + Unity build automation +└── src/main/java/ # Java/Forge batch runner + └── commanderailab/ ``` +--- + +## Tech Stack + +| Layer | Technology | +|---|---| +| Backend | Python 3.10+, FastAPI, Uvicorn | +| Simulation (rules-complete) | Java 17, Maven, Forge | +| Simulation (fast) | Python Monte Carlo engine | +| LLM Inference | Ollama (qwen2.5:7b), Anthropic Claude | +| Vector Store | ChromaDB with all-MiniLM-L6-v2 embeddings | +| Card Database | SQLite FTS5 (Scryfall bulk data) | +| ML Training | PyTorch, PPO reinforcement learning | +| Web Client | HTML/CSS/JS | +| Unity Client | Unity 2022 LTS, URP, C# | +| CI/CD | GitHub Actions | + +--- + ## Known Limitations -- **Monte Carlo engine** — no stack, no instants, no continuous type changes (animated lands don't attack) -- **Forge engine** — each game spawns a new JVM (~2-3s overhead), ~0.04 sims/sec single-threaded -- **Forge winner life total** not captured (quiet mode only reports losers) -- **Deck builder** — Ollama suggestions are only as good as the local model; `qwen2.5:7b` works well +- **Monte Carlo engine** — no stack, no instants, no continuous type-changing effects (animated lands don't attack) +- **Forge engine** — each game spawns a new JVM (~2–3s overhead); ~0.04 sims/sec single-threaded +- **Forge** — winner life total not captured in quiet mode (only reports losers) +- **Deck builder** — Ollama suggestions depend on the local model quality; `qwen2.5:7b` works well +- **LAN client** — EDHREC commander search is a stub (backend-powered, not yet fully wired) + +--- + +## Contributing + +Commander AI Lab is an active research project. Check the [open issues](https://github.com/KoalaTrapLord/commander-ai-lab/issues) for areas where contributions are welcome. + +--- + +## License + +See repository for license details.