Skip to content

Commit 11a7971

Browse files
committed
docs: add api-protocol page to the docs
1 parent c559ca2 commit 11a7971

File tree

2 files changed

+179
-1
lines changed

2 files changed

+179
-1
lines changed

docs/api-protocol.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# Balatro Bot API Protocol
2+
3+
This document provides the UDP protocol reference for developing bots that interface with Balatro via raw UDP sockets.
4+
5+
## UDP Communication
6+
7+
The Balatro Bot API uses UDP sockets for real-time communication between the game and external bot clients.
8+
9+
**Connection Details:**
10+
- **Host:** `127.0.0.1` (localhost)
11+
- **Port:** `12346` (default)
12+
- **Protocol:** UDP
13+
14+
## Communication Sequence
15+
16+
```mermaid
17+
sequenceDiagram
18+
participant Bot
19+
participant Game
20+
21+
Bot->>Game: "HELLO" (UDP)
22+
Game->>Bot: JSON Game State
23+
24+
loop Game Loop
25+
Game->>Bot: Updated JSON Game State (when waitingForAction changes)
26+
27+
Note over Bot: Bot analyzes game state and decides action
28+
29+
Bot->>Game: "ACTION_NAME|param1,param2|param3"
30+
31+
alt Valid Action
32+
Game->>Bot: {"response": "Action executed successfully"}
33+
else Invalid Action
34+
Game->>Bot: {"response": "Error: [description]"}
35+
end
36+
end
37+
```
38+
39+
## Message Formats
40+
41+
**Handshake**
42+
```
43+
Bot -> Game: "HELLO"
44+
Game -> Bot: {JSON game state with waitingFor field}
45+
```
46+
47+
**Action Request**
48+
```
49+
Bot -> Game: "ACTION_NAME|param1,param2|param3,param4"
50+
```
51+
52+
**Responses**
53+
```
54+
Success: {"response": "Action executed successfully"}
55+
Error: {"response": "Error: [description]"}
56+
```
57+
58+
## Game State JSON
59+
60+
The game sends JSON containing:
61+
62+
- **waitingFor**: What action type the game expects
63+
- **waitingForAction**: Boolean indicating if bot input is needed
64+
- **gamestate**: Current game phase and data
65+
- **hand**: Player's current hand cards
66+
- **jokers**: Active joker cards
67+
- **consumables**: Available consumable cards
68+
- **shop**: Shop items and costs
69+
- **blinds**: Current blind information
70+
- **round**: Round data (hands/discards remaining, etc.)
71+
72+
Key field for bots: **waitingForAction** - only send actions when this is `true`.
73+
74+
## Available Actions
75+
76+
Actions use pipe-separated format: `ACTION_NAME|param1,param2|param3,param4`
77+
78+
79+
| Action | Parameters | Description | Valid When waitingFor |
80+
|--------|------------|-------------|------------|
81+
| `SELECT_BLIND` | `1` | Select the current blind | `skip_or_select_blind` |
82+
| `SKIP_BLIND` | `2` | Skip the current blind | `skip_or_select_blind` |
83+
| `PLAY_HAND` | `3|card_indices` | Play selected cards | `select_cards_from_hand` |
84+
| `DISCARD_HAND` | `4|card_indices` | Discard selected cards | `select_cards_from_hand` |
85+
| `END_SHOP` | `5` | Leave the shop | `select_shop_action` |
86+
| `REROLL_SHOP` | `6` | Reroll shop items | `select_shop_action` |
87+
| `BUY_CARD` | `7|shop_index` | Buy joker from shop | `select_shop_action` |
88+
| `BUY_VOUCHER` | `8|voucher_index` | Buy voucher from shop | `select_shop_action` |
89+
| `BUY_BOOSTER` | `9|booster_index` | Buy booster pack | `select_shop_action` |
90+
| `SELECT_BOOSTER_CARD` | `10|pack_index|hand_indices` | Use consumable on cards | `select_booster_action` |
91+
| `SKIP_BOOSTER_PACK` | `11` | Skip booster pack | `select_booster_action` |
92+
| `SELL_JOKER` | `12|joker_indices` | Sell joker cards | `sell_jokers` |
93+
| `USE_CONSUMABLE` | `13|consumable_indices` | Use consumable cards | `use_or_sell_consumables` |
94+
| `SELL_CONSUMABLE` | `14|consumable_indices` | Sell consumable cards | `use_or_sell_consumables` |
95+
| `REARRANGE_JOKERS` | `15|new_order` | Reorder joker positions | `rearrange_jokers` |
96+
| `REARRANGE_CONSUMABLES` | `16|new_order` | Reorder consumable positions | `rearrange_consumables` |
97+
| `REARRANGE_HAND` | `17|new_order` | Reorder hand cards | `rearrange_hand` |
98+
| `PASS` | `18` | Do nothing (always valid) | Any state |
99+
| `START_RUN` | `19|stake|deck|seed|challenge` | Start new run | `start_run` |
100+
101+
102+
**Card Indices:** 1-based array of card positions
103+
104+
- Example: `PLAY_HAND|3|1,3,5` (play cards at positions 1, 3, and 5)
105+
106+
**Shop Indices:** 1-based position in shop
107+
108+
- Example: `BUY_CARD|7|2` (buy second joker in shop)
109+
110+
**Reorder Arrays:** Complete new ordering (all positions)
111+
112+
- Example: `REARRANGE_JOKERS|15|3,1,2,4` (move 3rd joker to 1st position, etc.)
113+
114+
**Run Parameters:**
115+
116+
- stake: 1-8 (difficulty)
117+
- deck: deck name string
118+
- seed: seed string or empty
119+
- challenge: challenge name or empty
120+
121+
## Game States
122+
123+
124+
| waitingFor State | Description | Valid Actions |
125+
|------------------|-------------|---------------|
126+
| `start_run` | Main menu | `START_RUN` |
127+
| `skip_or_select_blind` | Blind selection screen | `SELECT_BLIND`, `SKIP_BLIND` |
128+
| `select_cards_from_hand` | Playing/discarding phase | `PLAY_HAND`, `DISCARD_HAND` |
129+
| `select_shop_action` | In shop | `END_SHOP`, `REROLL_SHOP`, `BUY_CARD`, `BUY_VOUCHER`, `BUY_BOOSTER` |
130+
| `select_booster_action` | Opening booster packs | `SELECT_BOOSTER_CARD`, `SKIP_BOOSTER_PACK` |
131+
| `sell_jokers` | Joker management | `SELL_JOKER` |
132+
| `use_or_sell_consumables` | Consumable management | `USE_CONSUMABLE`, `SELL_CONSUMABLE` |
133+
| `rearrange_jokers` | Joker positioning | `REARRANGE_JOKERS` |
134+
| `rearrange_consumables` | Consumable positioning | `REARRANGE_CONSUMABLES` |
135+
| `rearrange_hand` | Hand card positioning | `REARRANGE_HAND` |
136+
137+
138+
## Error Handling
139+
140+
The game validates all actions and returns errors for:
141+
142+
- **Invalid format:** Incorrect action syntax
143+
- **Invalid parameters:** Wrong number or type of parameters
144+
- **Invalid state:** Action not allowed in current game state
145+
- **Invalid indices:** References to non-existent cards/items
146+
- **Insufficient resources:** Not enough money, hands, discards, etc.
147+
148+
## Example Bot Communication
149+
150+
```
151+
1. Bot connects and sends handshake:
152+
Bot -> Game: "HELLO"
153+
154+
2. Game responds with initial state:
155+
Game -> Bot: {"waitingFor": "start_run", "waitingForAction": true, ...}
156+
157+
3. Bot starts a run:
158+
Bot -> Game: "START_RUN|19|1|Red Deck||"
159+
Game -> Bot: {"response": "Action executed successfully"}
160+
161+
4. Game state updates automatically:
162+
Game -> Bot: {"waitingFor": "skip_or_select_blind", "waitingForAction": true, ...}
163+
164+
5. Bot selects blind:
165+
Bot -> Game: "SELECT_BLIND|1"
166+
Game -> Bot: {"response": "Action executed successfully"}
167+
168+
6. Continue until run ends...
169+
```
170+
171+
## Implementation Notes
172+
173+
- **Wait for waitingForAction:** Only send actions when `waitingForAction` is `true`
174+
- **One action per request:** Send one action string per UDP message
175+
- **Monitor responses:** Check for error messages and handle appropriately
176+
- **State changes:** Game automatically sends updated state when ready for next action
177+
- **Index validation:** All card/item indices are 1-based and must refer to existing items

mkdocs.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ plugins:
3232
nav:
3333
- Home: README.md
3434
- Installation: installation.md
35-
- Bot Development: bot-development.md
35+
- API Protocol: api-protocol.md
36+
# - Bot Development: bot-development.md # WIP
3637
- Troubleshooting: troubleshooting.md
3738
markdown_extensions:
3839
- admonition

0 commit comments

Comments
 (0)