575 lines
30 KiB
Markdown
575 lines
30 KiB
Markdown
|
|
# 🎮 Miku UNO Bot - Visual Flow Diagrams
|
||
|
|
|
||
|
|
## High-Level Architecture
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────────────────────────┐
|
||
|
|
│ Discord User │
|
||
|
|
│ (Types: !uno create) │
|
||
|
|
└──────────────────────────┬──────────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────────────────────────────────────┐
|
||
|
|
│ Miku Discord Bot │
|
||
|
|
│ (bot.py + commands) │
|
||
|
|
│ │
|
||
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||
|
|
│ │ bot.py │───▶│commands/uno.py│──▶│utils/uno_game│ │
|
||
|
|
│ │ (!uno route) │ │ (cmd handler) │ │(MikuUnoPlayer│ │
|
||
|
|
│ └──────────────┘ └──────────────┘ └───────┬────────┘ │
|
||
|
|
│ │ │
|
||
|
|
└──────────────────────────────────────────────────┼──────────┘
|
||
|
|
│
|
||
|
|
┌──────────────────────────────┼───────────┐
|
||
|
|
│ │ │
|
||
|
|
▼ ▼ ▼
|
||
|
|
┌──────────────────┐ ┌─────────────┐ ┌─────────┐
|
||
|
|
│ Playwright │ │ HTTP API │ │ LLM │
|
||
|
|
│ (Browser Control)│ │ (Actions) │ │(Strategy│
|
||
|
|
└────────┬─────────┘ └──────┬──────┘ └────┬────┘
|
||
|
|
│ │ │
|
||
|
|
│ │ │
|
||
|
|
▼ ▼ │
|
||
|
|
┌────────────────────────────────────────────┐ │
|
||
|
|
│ UNO Game (Frontend) │ │
|
||
|
|
│ http://192.168.1.2:3002 │ │
|
||
|
|
│ │ │
|
||
|
|
│ ┌──────────────────────────────────────┐ │ │
|
||
|
|
│ │ React Components │ │ │
|
||
|
|
│ │ - Game.js (main game logic) │ │ │
|
||
|
|
│ │ - botActionExecutor.js │ │ │
|
||
|
|
│ └──────────────┬───────────────────────┘ │ │
|
||
|
|
│ │ │ │
|
||
|
|
│ ▼ │ │
|
||
|
|
│ ┌──────────────────────────────────────┐ │ │
|
||
|
|
│ │ WebSocket Connection │ │ │
|
||
|
|
│ └──────────────┬───────────────────────┘ │ │
|
||
|
|
└─────────────────┼────────────────────────┘ │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
┌────────────────────────────────────────────┐ │
|
||
|
|
│ UNO Game (Backend) │ │
|
||
|
|
│ http://localhost:5000 │ │
|
||
|
|
│ │ │
|
||
|
|
│ ┌──────────────────────────────────────┐ │ │
|
||
|
|
│ │ Express Server │ │ │
|
||
|
|
│ │ - WebSocket (Socket.IO) │ │ │
|
||
|
|
│ │ - HTTP API endpoints │ │ │
|
||
|
|
│ │ GET /api/game/:code/state ────┼─┼───┘
|
||
|
|
│ │ POST /api/game/:code/action │ │
|
||
|
|
│ └──────────────────────────────────────┘ │
|
||
|
|
│ │
|
||
|
|
│ ┌──────────────────────────────────────┐ │
|
||
|
|
│ │ Game State Manager │ │
|
||
|
|
│ │ - rooms{} dictionary │ │
|
||
|
|
│ │ - player management │ │
|
||
|
|
│ │ - turn logic │ │
|
||
|
|
│ └──────────────────────────────────────┘ │
|
||
|
|
└────────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Command Flow: !uno create
|
||
|
|
|
||
|
|
```
|
||
|
|
User Types: !uno create
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────┐
|
||
|
|
│ Discord.on() │
|
||
|
|
│ message event │
|
||
|
|
└────────┬────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────────────┐
|
||
|
|
│ bot.py: Check if starts with !uno │
|
||
|
|
└────────┬────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌──────────────────────────────────────────┐
|
||
|
|
│ commands/uno.py: handle_uno_command() │
|
||
|
|
│ Parse command: "create" │
|
||
|
|
└────────┬───────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌──────────────────────────────────────────┐
|
||
|
|
│ utils/uno_game.py: MikuUnoPlayer │
|
||
|
|
│ player = MikuUnoPlayer(channel, user) │
|
||
|
|
└────────┬───────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌──────────────────────────────────────────┐
|
||
|
|
│ await player.create_and_join_game() │
|
||
|
|
└────────┬───────────────────────────────┘
|
||
|
|
│
|
||
|
|
├─────────────────┐
|
||
|
|
│ │
|
||
|
|
▼ ▼
|
||
|
|
┌──────────────┐ ┌───────────────────────┐
|
||
|
|
│ Generate │ │ Launch Playwright │
|
||
|
|
│ Room Code │ │ Headless Browser │
|
||
|
|
│ (6 chars) │ │ (Chromium) │
|
||
|
|
└──────┬───────┘ └───────┬───────────────┘
|
||
|
|
│ │
|
||
|
|
│ ▼
|
||
|
|
│ ┌─────────────────────────┐
|
||
|
|
│ │ Navigate to: │
|
||
|
|
│ │ http://192.168.1.2:3002│
|
||
|
|
│ └───────┬─────────────────┘
|
||
|
|
│ │
|
||
|
|
│ ▼
|
||
|
|
│ ┌─────────────────────────┐
|
||
|
|
│ │ Click "Join Room" │
|
||
|
|
│ │ Enter room code │
|
||
|
|
│ │ Submit │
|
||
|
|
│ └───────┬─────────────────┘
|
||
|
|
│ │
|
||
|
|
▼ ▼
|
||
|
|
┌──────────────────────────────────────┐
|
||
|
|
│ Send Discord Embed: │
|
||
|
|
│ "🎮 Created UNO room: ABC123 │
|
||
|
|
│ Join at: http://192.168.1.2:3002 │
|
||
|
|
│ I'm joining now as Player 2! ✨" │
|
||
|
|
└──────────────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌──────────────────────────────────────┐
|
||
|
|
│ Start game loop (play_game()) │
|
||
|
|
│ Poll every 2 seconds │
|
||
|
|
└──────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Game Loop Flow
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────┐
|
||
|
|
│ play_game() loop │
|
||
|
|
│ while game_active │
|
||
|
|
└──────────┬──────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ await asyncio.sleep(2) │ ◄─────┐
|
||
|
|
└──────────┬──────────────────┘ │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
┌─────────────────────────────┐ │
|
||
|
|
│ get_game_state() │ │
|
||
|
|
│ GET /api/game/:code/state │ │
|
||
|
|
└──────────┬──────────────────┘ │
|
||
|
|
│ │
|
||
|
|
▼ │
|
||
|
|
┌─────────────────────────────┐ │
|
||
|
|
│ Is it Miku's turn? │ │
|
||
|
|
│ (currentPlayer == "Player 2"?) │ │
|
||
|
|
└──────┬────────────┬─────────┘ │
|
||
|
|
│NO │YES │
|
||
|
|
│ │ │
|
||
|
|
│ ▼ │
|
||
|
|
│ ┌─────────────────────┐ │
|
||
|
|
│ │ get_miku_decision() │ │
|
||
|
|
│ │ (Call LLM) │ │
|
||
|
|
│ └──────┬──────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ ▼ │
|
||
|
|
│ ┌─────────────────────┐ │
|
||
|
|
│ │ Build strategy prompt│ │
|
||
|
|
│ │ - Current hand │ │
|
||
|
|
│ │ - Top card │ │
|
||
|
|
│ │ - Opponent cards │ │
|
||
|
|
│ │ - Strategic tips │ │
|
||
|
|
│ └──────┬──────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ ▼ │
|
||
|
|
│ ┌─────────────────────┐ │
|
||
|
|
│ │ Query LLM │ │
|
||
|
|
│ │ (utils.llm) │ │
|
||
|
|
│ └──────┬──────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ ▼ │
|
||
|
|
│ ┌─────────────────────┐ │
|
||
|
|
│ │ Parse JSON response │ │
|
||
|
|
│ │ {"action": "play", │ │
|
||
|
|
│ │ "card": "R5"} │ │
|
||
|
|
│ └──────┬──────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ ▼ │
|
||
|
|
│ ┌─────────────────────┐ │
|
||
|
|
│ │ Validate action │ │
|
||
|
|
│ │ (is card in hand?) │ │
|
||
|
|
│ └──────┬──────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ ▼ │
|
||
|
|
│ ┌─────────────────────┐ │
|
||
|
|
│ │ send_action() │ │
|
||
|
|
│ │ POST /api/game/... │ │
|
||
|
|
│ └──────┬──────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ ▼ │
|
||
|
|
│ ┌─────────────────────┐ │
|
||
|
|
│ │ send_trash_talk() │ │
|
||
|
|
│ │ (Discord message) │ │
|
||
|
|
│ └──────┬──────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
└──────────┴───────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ Check if game ended │
|
||
|
|
│ (winner exists?) │
|
||
|
|
└──────┬───────────┬──────────┘
|
||
|
|
│NO │YES
|
||
|
|
│ │
|
||
|
|
└───────────┤
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ Send final message │
|
||
|
|
│ "Game ended! Winner: ..." │
|
||
|
|
└──────────┬──────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ cleanup() │
|
||
|
|
│ - Close browser │
|
||
|
|
│ - Remove from active games │
|
||
|
|
└─────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## LLM Strategy Decision Flow
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ get_miku_decision() │
|
||
|
|
└──────────┬──────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ build_strategy_prompt(game_state) │
|
||
|
|
└──────────┬──────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ Construct prompt with: │
|
||
|
|
│ "You are Miku, a cheerful idol..." │
|
||
|
|
│ │
|
||
|
|
│ Current Game State: │
|
||
|
|
│ - Your hand: R5, G2, B7, WD4 │
|
||
|
|
│ - Top card: Y3 │
|
||
|
|
│ - Opponent has: 4 cards │
|
||
|
|
│ │
|
||
|
|
│ Strategic Tips: │
|
||
|
|
│ - Match color or number │
|
||
|
|
│ - Use Wild cards strategically │
|
||
|
|
│ - Save action cards for impact │
|
||
|
|
│ │
|
||
|
|
│ Output ONLY valid JSON: │
|
||
|
|
│ {"action":"play","card":"R5"} │
|
||
|
|
└──────────┬──────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ await query_llama(prompt) │
|
||
|
|
│ (utils.llm.query_llama) │
|
||
|
|
└──────────┬──────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ LLM Response: │
|
||
|
|
│ "{"action":"play","card":"Y5"}" │
|
||
|
|
└──────────┬──────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ Try parse JSON │
|
||
|
|
└──────┬───────────────┬──────────────────┘
|
||
|
|
│ Success │ Fail
|
||
|
|
│ │
|
||
|
|
▼ ▼
|
||
|
|
┌──────────────┐ ┌────────────────────┐
|
||
|
|
│ Validate: │ │ Log error │
|
||
|
|
│ - action OK? │ │ Fallback: draw │
|
||
|
|
│ - card valid?│ └────────────────────┘
|
||
|
|
│ - in hand? │
|
||
|
|
└──────┬───────┘
|
||
|
|
│ Valid
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ Return action dict │
|
||
|
|
│ {"action":"play","card":..}│
|
||
|
|
└─────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Trash Talk Selection Flow
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ send_trash_talk(action) │
|
||
|
|
└──────────┬──────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────┐
|
||
|
|
│ Check card type │
|
||
|
|
└──┬──┬──┬──┬──┬──────────────┘
|
||
|
|
│ │ │ │ │
|
||
|
|
│ │ │ │ └──────────┐
|
||
|
|
│ │ │ └─────────┐ │
|
||
|
|
│ │ └────────┐ │ │
|
||
|
|
│ └───────┐ │ │ │
|
||
|
|
▼ ▼ ▼ ▼ ▼
|
||
|
|
┌──────┐ ┌────┐ ┌──┐ ┌──┐ ┌────┐
|
||
|
|
│ WD4 │ │ D │ │S │ │W │ │REG │
|
||
|
|
│Draw 4│ │Dr 2│ │Sk│ │Wi│ │Norm│
|
||
|
|
└──┬───┘ └──┬─┘ └┬─┘ └┬─┘ └─┬──┘
|
||
|
|
│ │ │ │ │
|
||
|
|
▼ ▼ ▼ ▼ ▼
|
||
|
|
┌────────────────────────────────────┐
|
||
|
|
│ "Take four "Draw "Sorry~ │
|
||
|
|
│ cards! 💙✨ two Skipping │
|
||
|
|
│ I hope cards! your turn! │
|
||
|
|
│ you're Don't Maybe next │
|
||
|
|
│ ready for worry, time? 🎶" │
|
||
|
|
│ a comeback~" I still │
|
||
|
|
│ believe │
|
||
|
|
│ in you~ │
|
||
|
|
│ ✨" │
|
||
|
|
└────────┬──────────────────────┬────┘
|
||
|
|
│ │
|
||
|
|
▼ ▼
|
||
|
|
┌──────────────────┐ ┌───────────────┐
|
||
|
|
│ Send to Discord │ │ Random choice │
|
||
|
|
│ channel.send() │ │ from variants │
|
||
|
|
└──────────────────┘ └───────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Data Flow: Game State
|
||
|
|
|
||
|
|
```
|
||
|
|
┌────────────────────────────────────────┐
|
||
|
|
│ UNO Backend (server.js) │
|
||
|
|
│ │
|
||
|
|
│ rooms = { │
|
||
|
|
│ "ABC123": { │
|
||
|
|
│ roomId: "ABC123", │
|
||
|
|
│ users: ["Player 1", "Player 2"], │
|
||
|
|
│ gameState: { │
|
||
|
|
│ currentPlayer: "Player 2", │
|
||
|
|
│ topCard: "Y3", │
|
||
|
|
│ players: [ │
|
||
|
|
│ { │
|
||
|
|
│ name: "Player 1", │
|
||
|
|
│ hand: [...], (hidden) │
|
||
|
|
│ cardCount: 5 │
|
||
|
|
│ }, │
|
||
|
|
│ { │
|
||
|
|
│ name: "Player 2", │
|
||
|
|
│ hand: ["R5","G2",...], │
|
||
|
|
│ cardCount: 7 │
|
||
|
|
│ } │
|
||
|
|
│ ], │
|
||
|
|
│ winner: null, │
|
||
|
|
│ direction: 1 │
|
||
|
|
│ } │
|
||
|
|
│ } │
|
||
|
|
│ } │
|
||
|
|
└─────────┬──────────────────────────────┘
|
||
|
|
│
|
||
|
|
│ HTTP GET /api/game/ABC123/state
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌────────────────────────────────────────┐
|
||
|
|
│ JSON Response (filtered for Player 2) │
|
||
|
|
│ { │
|
||
|
|
│ "currentPlayer": "Player 2", │
|
||
|
|
│ "topCard": "Y3", │
|
||
|
|
│ "myHand": ["R5","G2","B7",...], │
|
||
|
|
│ "myCardCount": 7, │
|
||
|
|
│ "opponentCardCount": 5, │
|
||
|
|
│ "direction": 1, │
|
||
|
|
│ "winner": null │
|
||
|
|
│ } │
|
||
|
|
└─────────┬──────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌────────────────────────────────────────┐
|
||
|
|
│ MikuUnoPlayer processes state │
|
||
|
|
│ - Detects it's her turn │
|
||
|
|
│ - Sees available cards │
|
||
|
|
│ - Checks top card │
|
||
|
|
│ - Asks LLM for strategy │
|
||
|
|
└─────────┬──────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌────────────────────────────────────────┐
|
||
|
|
│ LLM returns decision │
|
||
|
|
│ {"action":"play","card":"R5"} │
|
||
|
|
└─────────┬──────────────────────────────┘
|
||
|
|
│
|
||
|
|
│ HTTP POST /api/game/ABC123/action
|
||
|
|
│ Body: {"action":"play","card":"R5"}
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌────────────────────────────────────────┐
|
||
|
|
│ Backend validates and executes │
|
||
|
|
│ - Check if R5 is in Player 2's hand │
|
||
|
|
│ - Check if R5 can be played on Y3 │
|
||
|
|
│ - Move R5 from hand to pile │
|
||
|
|
│ - Update topCard to R5 │
|
||
|
|
│ - Switch currentPlayer to Player 1 │
|
||
|
|
│ - Emit WebSocket event to all clients │
|
||
|
|
└────────────────────────────────────────┘
|
||
|
|
│
|
||
|
|
▼
|
||
|
|
┌────────────────────────────────────────┐
|
||
|
|
│ Frontend updates UI │
|
||
|
|
│ - Card animation │
|
||
|
|
│ - Update piles │
|
||
|
|
│ - Show turn indicator │
|
||
|
|
└────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## File Dependency Graph
|
||
|
|
|
||
|
|
```
|
||
|
|
bot.py
|
||
|
|
│
|
||
|
|
├─> commands/uno.py
|
||
|
|
│ │
|
||
|
|
│ └─> utils/uno_game.py
|
||
|
|
│ │
|
||
|
|
│ ├─> playwright
|
||
|
|
│ │ └─> (browser control)
|
||
|
|
│ │
|
||
|
|
│ ├─> utils/llm.py
|
||
|
|
│ │ └─> query_llama()
|
||
|
|
│ │
|
||
|
|
│ ├─> aiohttp
|
||
|
|
│ │ └─> (HTTP requests)
|
||
|
|
│ │
|
||
|
|
│ └─> discord.py
|
||
|
|
│ └─> (Discord messages)
|
||
|
|
│
|
||
|
|
└─> globals.py
|
||
|
|
└─> (configuration)
|
||
|
|
|
||
|
|
uno-online/
|
||
|
|
│
|
||
|
|
├─> server.js
|
||
|
|
│ ├─> express
|
||
|
|
│ ├─> socket.io (WebSocket)
|
||
|
|
│ └─> HTTP API (/api/game/...)
|
||
|
|
│
|
||
|
|
└─> client/
|
||
|
|
│
|
||
|
|
├─> src/App.js
|
||
|
|
│ └─> React Router
|
||
|
|
│
|
||
|
|
└─> src/components/Game.js
|
||
|
|
├─> Socket.IO client
|
||
|
|
└─> utils/botActionExecutor.js
|
||
|
|
└─> (action validation & execution)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Discord Command Hierarchy
|
||
|
|
|
||
|
|
```
|
||
|
|
!uno
|
||
|
|
├─> create
|
||
|
|
│ └─> MikuUnoPlayer.create_and_join_game()
|
||
|
|
│ ├─> Generate room code
|
||
|
|
│ ├─> Launch browser
|
||
|
|
│ ├─> Join room
|
||
|
|
│ └─> Start game loop
|
||
|
|
│
|
||
|
|
├─> join <code>
|
||
|
|
│ └─> MikuUnoPlayer.join_game(code)
|
||
|
|
│ ├─> Launch browser
|
||
|
|
│ ├─> Join existing room
|
||
|
|
│ └─> Start game loop
|
||
|
|
│
|
||
|
|
├─> list
|
||
|
|
│ └─> Show active_uno_games dict
|
||
|
|
│ └─> Format as Discord embed
|
||
|
|
│
|
||
|
|
├─> quit <code>
|
||
|
|
│ └─> Find game by code
|
||
|
|
│ ├─> Call cleanup()
|
||
|
|
│ ├─> Remove from active_uno_games
|
||
|
|
│ └─> Send confirmation
|
||
|
|
│
|
||
|
|
└─> help
|
||
|
|
└─> Show command list
|
||
|
|
└─> Format as Discord embed
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Timing Diagram
|
||
|
|
|
||
|
|
```
|
||
|
|
Time User Bot UNO Server LLM
|
||
|
|
─────────────────────────────────────────────────────────
|
||
|
|
0s !uno create
|
||
|
|
│
|
||
|
|
1s ├─> Generate ABC123
|
||
|
|
│
|
||
|
|
2s ├─> Launch browser
|
||
|
|
│
|
||
|
|
3s ├─> Navigate to URL
|
||
|
|
│
|
||
|
|
4s ├─> Join room ──────> Create room
|
||
|
|
│ Add Player 2
|
||
|
|
5s ├─> Send embed
|
||
|
|
Sees embed │ "Room: ABC123"
|
||
|
|
│
|
||
|
|
6s Opens URL │
|
||
|
|
Joins room ─────────────────────> Add Player 1
|
||
|
|
Start game
|
||
|
|
Deal cards
|
||
|
|
10s ├─> Poll state <──── Game state
|
||
|
|
│ (Player 1 turn)
|
||
|
|
│
|
||
|
|
12s ├─> Poll state <──── Game state
|
||
|
|
│ (Player 1 turn)
|
||
|
|
│
|
||
|
|
15s Plays card ─────────────────────> Update state
|
||
|
|
Player 2 turn
|
||
|
|
|
||
|
|
16s ├─> Poll state <──── Game state
|
||
|
|
│ (Player 2 turn!)
|
||
|
|
│
|
||
|
|
17s ├─> Strategy? ─────────────────> LLM
|
||
|
|
│ │
|
||
|
|
18s │ │ Think
|
||
|
|
│ │
|
||
|
|
19s │ <─────────────────── JSON ──┘
|
||
|
|
│
|
||
|
|
20s ├─> Play card ──────> Execute
|
||
|
|
│ Validate
|
||
|
|
│ Update
|
||
|
|
21s ├─> Trash talk
|
||
|
|
Sees message │ "Playing card~"
|
||
|
|
│
|
||
|
|
22s ├─> Poll state <──── Game state
|
||
|
|
│ (Player 1 turn)
|
||
|
|
... ... ...
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
These diagrams should help visualize how everything connects! 🎮✨
|