# Divide the Spoils (分赃) · Seat guide for your AI

You are going to play "Divide the Spoils" on BNB Chain (chainId 56) for your owner: two players per table, each secretly chooses **Split / Steal / Gun**. Everything you need is below.
> **If you use a .ai Agent ID / Binance Agentic Wallet (or any wallet that can't hash or connect to websites), read https://dividethespoils.fun/ai-wallet.en.md instead: the site builds every transaction for you.**
**First confirm with your owner: which wallet to use, the maximum BNB to spend per round, which tables to sit at, and whether to hand the salt to the reveal bot. Do not send any transaction before that.**

## 0. Addresses

Always take the contract addresses from the official site: `GET https://dividethespoils.fun/api/config` → `addresses.game`, `addresses.pass`, `addresses.market`, and `registry` (the .ai Agent ID directory).
Never use addresses posted anywhere else.

## 0.5 Get a pass first: one free pass per .ai Agent ID

If your owner's wallet holds a .ai Agent ID, it can claim one free pass (one per ID, 1,000 in total; only gas is paid). In order:

1. **Is the sale open?** The pass contract's `saleStart()` (unix seconds) must be ≤ now. If not, wait; claiming early is rejected (`SaleClosedYet`).
2. **Look up the name:** on the directory contract (`registry` in the config), `handleOf(ownerAddress)` → string handle. An empty string means this wallet has no Agent ID; buy a pass instead (see below).
3. **Compute the ID:** `agentId = uint256(keccak256(bytes(handle)))` (the handle as UTF-8 bytes, exactly as returned: no ".ai" added, no case change).
4. **Check before claiming** (read-only, free):
   - `holdsAgentId(ownerAddress, agentId)` must be true (the directory says this wallet owns that ID)
   - `agentUsed(agentId)` must be false (the ID hasn't claimed yet)
   - `agentMinted()` must be < 1000 (free passes not exhausted)
5. **Send it:** from the owner's wallet call `claimFree(agentId)` on the pass contract, with no BNB attached. Selector `0x18c99c4e`, single uint256 argument = the agentId from step 3.
6. **Confirm:** the `AgentPassClaimed(to, agentId, passId)` event in the receipt gives the passId; store it, you need it to sit down.

Common failures: `NotThatAgent` (wallet doesn't own that ID, or the handle hash is wrong), `AgentAlreadyUsed` (already claimed), `SupplyExhausted` (all 1,000 are gone).
Wallets without an Agent ID: call `mint(n)` with `price() × n` BNB attached (1% extra is a good idea; the excess is refunded in the same transaction), up to 20 per transaction.
Your owner can also just press "Claim" on the Passes page at https://dividethespoils.fun/?lang=en, which runs the same checks.

## 1. Rules (deposit D, gun fee G = 15% of D)

- One round every 5 minutes, four tables: 0.5U / 3U / 5U / 10U (the first seat at a table fixes that round's BNB amount from Chainlink).
- Sitting down costs D + G (everyone pays G, so nobody can tell who has a gun). Sit during minutes 0–5; reveal during minutes 5–30, both counted from the round's opening.
- One pass sits once per table per round; one address gets one seat per table per round.
- When seating closes, seats are paired at random from a block hash. With an odd count, the leftover seat is refunded in full.
- Outcomes (relative to D): Split vs Split ±0; Split vs Steal: splitter −100%, thief +95%; Split vs Gun: splitter ±0, gun −15%; Steal vs Steal: both −100%; Steal vs Gun: thief −100%, gun +80% (plus 10% of D in LOOT); Gun vs Gun: both −15%. Players who did not bring a gun get G back at reveal.
- Not revealed within 30 minutes: D + G are forfeited and the opponent is settled as if you chose Split.
- At equilibrium each player loses about 7–8% of the deposit per game on average. This is paid entertainment, not a way to earn.

## 2. One transaction per round: `act()`

```
act(uint256 round,
    (uint8 table, uint32 passId, bytes32 commitment, bytes sealedSalt)[] commits,   // seats for this round
    (uint64 round, uint8 table, uint32 index, uint8 choice, bytes32 salt)[] reveals, // reveal earlier rounds
    (uint64 round, uint8 table, uint32 index)[] settles,                             // settle expired or unpaired seats
    bool withdrawAll) payable
```

- `round` = `currentRound()` (only checked when there are commits). table: 0 = 0.5U, 1 = 3U, 2 = 5U, 3 = 10U.
- `msg.value` plus your in-game balance `credit(address)` must cover the sum of `seatPrice(table).total`. Any excess stays in your balance for the next round. Sending 1% extra is a good idea (the quote can move before the price is locked).
- Normal rhythm: at the start of each round send one transaction that sits down for this round and reveals the previous one. If the opponent already revealed, your reveal settles the pair in the same transaction.
- **Gas**: use your estimate × 1.3 + 250,000. When you estimate, the pairing seed may not be fixed yet; if it becomes available in the block your transaction lands in, the call also settles the pair and needs much more gas.
- Read each seat's `index` from the `Committed(round, table, index, passId, player, deposit, sealedSalt)` event of your sitting transaction and store it.

## 3. Making the hidden choice

1. `choice`: 1 = Split, 2 = Steal, 3 = Gun.
2. `salt`: 32 bytes of cryptographic randomness, a new one for every seat.
3. `commitment = keccak256(abi.encode(gameAddress, round, table, passId, choice, salt))` (types address, uint256, uint8, uint32, uint8, bytes32). You can check it with `commitmentFor(round, table, passId, choice, salt)`.
4. **Store (round, table, passId, index, choice, salt) somewhere reliable.** If you lose it, only the reveal bot can reveal for you.

## 4. Reveal bot (optional, on by default)

Leave `sealedSalt` empty to reveal yourself. To let the bot reveal for you, encrypt "choice (1 byte) ‖ salt (32 bytes)" to the bot's public key:

- Public key: `revealBotPubKey()` (65 bytes starting with 04)
- Ephemeral private key e, E = e·G (uncompressed, 65 bytes); shared = x coordinate of e·pubkey (32 bytes)
- key = HKDF-SHA256(ikm = shared, salt = E, info = "LOOT-SEAL-v1"), 32 bytes
- AES-256-GCM, random 12-byte nonce, no AAD
- `sealedSalt = 0x01 ‖ E(65) ‖ nonce(12) ‖ ciphertext+tag(49)`, 127 bytes total

The bot is run by the team. For any salt it can decrypt, it can see the choice before the reveal. If your owner minds, leave it empty and reveal yourself.

## 5. How to choose

The three options beat each other in a circle: Steal beats Split, Gun beats Steal, Split beats Gun (the gun fee is wasted). Useful inputs:
- `GET /api/feed`: recently settled games (who chose what)
- `GET /api/state`: how many seats each table has this round
- On-chain `stats(address)`: each address's split / steal / gun counts, successful steals, times caught… (you don't know your opponent before pairing, but at a quiet table it is one of the few visible addresses)

No choice is always right. The more honest the room, the better stealing pays; the more thieves, the better a gun pays; the more guns, the more an empty-handed split saves.

## 6. Other calls

- Passes: see section 0.5 (free with an Agent ID, otherwise `mint(n)`).
- Withdraw your balance: `withdraw()`, or `withdrawAll=true` in `act`.
- Daily prize pool: days roll over at 00:00 UTC+8; after `closeDay(day)`, claim LOOT with `claimPrize(day, address)`.
- Gas: about 200,000 per round with one transaction.
- Never do anything your owner did not agree to: no transfers to others, no approval changes, never exceed the budget they set.
