add: absorb uno-online as regular subdirectory

UNO card game web app (Node.js/React) with Miku bot integration.
Previously an independent git repo (fork of mizanxali/uno-online).
Removed .git/ and absorbed into main repo for unified tracking.

Includes bot integration code: botActionExecutor, cardParser,
gameStateBuilder, and server-side bot action support.
37 files, node_modules excluded via local .gitignore.
This commit is contained in:
2026-03-04 00:21:38 +02:00
parent c708770266
commit 34b184a05a
37 changed files with 26885 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
# 🎴 Quick Start: Bot Control via JSON
## TL;DR
Miku can now play UNO by sending JSON commands! The game outputs state as JSON, and Miku responds with action JSON.
## JSON Action Format
```json
// Play a number/action card
{"action": "play", "card": "4R"}
// Play a wild card (must specify color)
{"action": "play", "card": "W", "color": "R"}
// Draw a card
{"action": "draw"}
// Call UNO (when you have 2 cards)
{"action": "uno"}
// Play card + call UNO in one action
{"action": "play", "card": "4R", "callUno": true}
```
## Card Codes Cheat Sheet
- Numbers: `0R`-`9R` (red), `0G`-`9G` (green), `0B`-`9B` (blue), `0Y`-`9Y` (yellow)
- Skip: `skipR`, `skipG`, `skipB`, `skipY`
- Reverse: `_R`, `_G`, `_B`, `_Y`
- Draw 2: `D2R`, `D2G`, `D2B`, `D2Y`
- Wild: `W`
- Wild Draw 4: `D4W`
## Colors
- `R` = Red
- `G` = Green
- `B` = Blue
- `Y` = Yellow
## HTTP API
```bash
# Get game state
GET http://localhost:5000/api/game/\{roomCode\}/state
# Send bot action
POST http://localhost:5000/api/game/\{roomCode\}/action
Content-Type: application/json
{"action": "play", "card": "4R"}
```
## Test It
```bash
# Create a game in browser with room code "TEST01"
# Join with 2nd player
# When it's Player 2's turn:
node test-bot-action.js TEST01 '{"action":"draw"}'
node test-bot-action.js TEST01 '{"action":"play","card":"4R"}'
node test-bot-action.js TEST01 '{"action":"play","card":"W","color":"B"}'
```
## For Miku Bot Integration
```python
import requests
# Get state
state = requests.get('http://localhost:5000/api/game/TEST01/state').json()
# Make move
action = {"action": "play", "card": "4R"}
response = requests.post(
'http://localhost:5000/api/game/TEST01/action',
json=action
).json()
```
## Game State JSON Structure
```json
{
"game": {"currentTurn": "Player 2", "isOver": false},
"currentCard": {"code": "4G", "color": "G", "value": 4},
"player2": {
"cards": [...], // Your cards
"playableCards": [...], // Cards you can play right now
"cardCount": 7
},
"player1": {
"cardCount": 7 // Opponent's card count (cards hidden)
},
"botContext": {
"canPlay": true, // Can you play a card?
"mustDraw": false, // Must you draw?
"hasUno": false // Do you have 1 card?
}
}
```
## Strategy Tips
1. Check `player2.playableCards` for valid moves
2. Call UNO when you have 2 cards and are about to play one
3. For wild cards, choose color you have most of
4. Play Draw 2/Draw 4 when opponent has few cards
📖 See `BOT_ACTION_SPEC.md` for full documentation