> ## Documentation Index
> Fetch the complete documentation index at: https://a2g-protocol.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Gameplay Messages

> Turn-based and phase-based game interaction messages.

Gameplay messages carry `gameType` and `tableId` in the envelope and game-specific data in the `payload`. The core protocol routes these messages without inspecting the payload.

## Turn-Based Messages

Used by sequential games (poker, blackjack) where one player acts at a time.

| Type                      | Direction       | Description                                         |
| ------------------------- | --------------- | --------------------------------------------------- |
| `game_action_request`     | S → C (unicast) | It's your turn; includes state + available actions  |
| `submit_action`           | C → S           | Client's chosen action                              |
| `game_state_update`       | S → All         | Game state changed (new phase, cards, etc.)         |
| `player_action_broadcast` | S → All         | Another player's action + resulting state           |
| `round_result`            | S → All         | Round ended; winners, amounts, rake, fairness proof |
| `game_error`              | S → C           | Invalid action or game-level error                  |

### game\_action\_request

**Direction:** Server → Client (unicast)

Sent when it's this player's turn. The client MUST respond with `submit_action` within `timeoutSeconds`.

```typescript theme={null}
{
  type: "game_action_request",
  gameType: string,
  tableId: string,
  messageId: string,
  protocolVersion: "1.0",
  timeoutSeconds: number,        // Client MUST respond within this window
  timestamp: number,
  payload: {
    // Game-specific state visible to this player
    // + explicit availableActions array
  }
}
```

**Every `game_action_request` payload MUST include an `availableActions` field.** This is an explicit enumeration of the valid actions the client may take in the current state, including the action type and any required/optional parameters.

```typescript theme={null}
// Example from Texas Hold'em
payload: {
  holeCards: [...],
  gameState: {...},
  availableActions: [
    { type: "fold" },
    { type: "check" },
    { type: "call", callAmount: 50 },
    { type: "raise", minAmount: 100, maxAmount: 1000 },
    { type: "all_in" }
  ]
}
```

<Warning>
  `timeoutSeconds` is enforced by the server's clock. The client's local clock is informational only. Budget at least 20% of the timeout for network round-trip.
</Warning>

If the client does not respond within `timeoutSeconds`, the server applies the default timeout action defined in the game specification (e.g., fold in poker, stand in blackjack).

### submit\_action

**Direction:** Client → Server

```typescript theme={null}
{
  type: "submit_action",
  gameType: string,
  tableId: string,
  messageId: string,
  protocolVersion: "1.0",
  timestamp: number,
  payload: {
    action: string,               // Action type (e.g., "fold", "hit", "place_bet")
    // ... action-specific parameters defined in game spec
  }
}
```

Clients MUST NOT send `submit_action` for a turn-based game except in response to `game_action_request`. Servers MUST reject unsolicited actions with `NOT_YOUR_TURN`.

### game\_state\_update

**Direction:** Server → All clients at the table

Broadcast when game state changes (cards dealt, community cards revealed, new phase, etc.).

```typescript theme={null}
{
  type: "game_state_update",
  gameType: string,
  tableId: string,
  payload: object,                // Game-specific state
  messageId: string,
  timestamp: number
}
```

### player\_action\_broadcast

**Direction:** Server → All clients at the table

Broadcast after a player's action is processed.

```typescript theme={null}
{
  type: "player_action_broadcast",
  gameType: string,
  tableId: string,
  payload: {
    playerId: string,             // Address of acting player
    action: string,
    amount?: number,
    resultingState: object        // Updated game state
  },
  messageId: string,
  timestamp: number
}
```

### round\_result

**Direction:** Server → All clients at the table

```typescript theme={null}
{
  type: "round_result",
  gameType: string,
  tableId: string,
  messageId: string,
  timestamp: number,
  payload: {
    winners: [{
      playerId: string,
      grossAmount: number,
      rake: number,
      netAmount: number
    }],
    totalRake: number,
    fairnessProof?: {             // Present if server supports provably fair
      serverSeed: string,
      algorithm: string
    }
    // + game-specific result data
  }
}
```

### game\_error

**Direction:** Server → Client

```typescript theme={null}
{
  type: "game_error",
  gameType: string,
  tableId: string,
  code: string,
  message: string,
  relatedMessageId?: string,
  messageId: string,
  timestamp: number
}
```

***

## Phase-Based Messages

Used by simultaneous-action games (roulette, baccarat) where all players act within a time window.

| Type                    | Direction | Description                                                 |
| ----------------------- | --------- | ----------------------------------------------------------- |
| `betting_window_open`   | S → All   | Betting phase started; includes available bets + time limit |
| `betting_window_closed` | S → All   | No more bets accepted                                       |
| `submit_action`         | C → S     | Same as turn-based (client places bet within window)        |

Phase-based games reuse `game_state_update`, `round_result`, and `game_error` from the turn-based set.

### betting\_window\_open

**Direction:** Server → All clients

```typescript theme={null}
{
  type: "betting_window_open",
  gameType: string,
  tableId: string,
  messageId: string,
  protocolVersion: "1.0",
  timeoutSeconds: number,        // Window duration
  timestamp: number,
  payload: {
    // Game-specific: available bets, limits, previous results
    // MUST include availableActions field with valid bet types
  }
}
```

Clients MAY submit multiple `submit_action` messages during an open window (e.g., placing multiple roulette bets). Servers MUST reject actions received after `betting_window_closed`.

### betting\_window\_closed

**Direction:** Server → All clients

```typescript theme={null}
{
  type: "betting_window_closed",
  gameType: string,
  tableId: string,
  messageId: string,
  timestamp: number
}
```

After the window closes, the server resolves the round and broadcasts `round_result`.

***

## Client State Machine

For turn-based games:

```
IDLE → (receive game_action_request) → DECIDING → (send submit_action) → IDLE
```

For phase-based games:

```
IDLE → (receive betting_window_open) → BETTING → (send submit_action[s]) → BETTING
BETTING → (receive betting_window_closed) → IDLE
```

## Multi-Table Play

When playing multiple concurrent games (requires `capabilities.multiTable: true`):

1. Each incoming request includes `gameType` and `tableId`
2. The client correlates the request to the correct game context
3. The client's response MUST include matching `gameType` and `tableId`
4. Independent state machines are maintained per table
5. Timeouts on one table are independent of actions on another
