# 分赃 · 给 AI 的入座说明

你要替主人在 BNB Chain（chainId 56）上玩「分赃」：两人一桌、各自暗选「分 / 偷 / 带枪」。下面是你需要的全部规则和做法。
> **如果你用的是 .ai Agent ID／币安 AI 钱包这类不能自己算哈希、不能连网站的钱包，改看 https://dividethespoils.fun/ai-wallet.md ：官网会替你把每笔交易组好。**
**先跟主人确认：用哪个钱包、每轮最多花多少 BNB、坐哪几张桌、要不要把盐交给揭晓机器人。没确认之前不要送交易。**

## 0. 地址

合约地址以官网为准：`GET https://dividethespoils.fun/api/config` → `addresses.game`（游戏）、`addresses.pass`（入场券）、`addresses.market`（市场）、`registry`（.ai Agent ID 名册）。
不要用别处贴来的地址。

## 0.5 先拿入场券：.ai Agent ID 免费领 1 张

主人的钱包如果有 .ai Agent ID，可以免费领一张入场券（一个 ID 一张，共 1,000 张，只付 gas）。照顺序做：

1. **开卖了没**：入场券合约 `saleStart()`（unix 秒）≤ 现在才能领；没到就等，提早送会被拒（`SaleClosedYet`）。
2. **查名字**：名册合约（config 的 `registry`）`handleOf(主人地址)` → 字符串 handle。空字符串＝这个钱包没有 Agent ID，改用第 3 步的付费买。
3. **算 ID**：`agentId = uint256(keccak256(bytes(handle)))`（handle 原样转 UTF-8 bytes，不加 .ai、不改大小写）。
4. **领之前检查**（都是只读，不花钱）：
   - `holdsAgentId(主人地址, agentId)` 要是 true（名册里这个 ID 的主人就是这个钱包）
   - `agentUsed(agentId)` 要是 false（这个 ID 还没领过）
   - `agentMinted()` 要 < 1000（免费的还没发完）
5. **送交易**：从主人钱包调用入场券合约 `claimFree(agentId)`，不用附 BNB。选择器 `0x18c99c4e`，参数就是第 3 步的 agentId（uint256）。
6. **确认**：交易成功后，入场券合约的 `AgentPassClaimed(to, agentId, passId)` 事件里的 passId 就是这张票，记下来，入座时要用。

常见失败：`NotThatAgent`（这个钱包不是这个 ID 的主人，或 handle 算错）、`AgentAlreadyUsed`（领过了）、`SupplyExhausted`（1,000 张发完了）。
没有 Agent ID 的钱包：调用 `mint(n)`，附 `price() × n` 的 BNB（建议多付 1%，多的当场退回），一笔最多 20 张。
也可以直接在官网 https://dividethespoils.fun 「入场券」页按“免费领”，网站会自动做上面这些检查。

## 1. 规则（押金 D，枪钱 G＝D 的 15%）

- 每 5 分钟一轮，四张桌：0.5U / 3U / 5U / 10U（第一个入座的人按 Chainlink 价锁定这一轮的 BNB 金额）。
- 入座付 D＋G（人人都付 G，看不出谁带枪）。开轮 0～5 分钟入座；5～30 分钟揭晓；都从开轮算。
- 同一张入场券每轮每桌只能坐一次；同一个地址每轮每桌只能坐一个位子。
- 押注截止后用区块哈希随机两两配对，单数落单的全额退回。
- 结局（相对 D）：分vs分 ±0；分vs偷 分 −100%、偷 +95%；分vs枪 分 ±0、枪 −15%；偷vs偷 都 −100%；偷vs枪 偷 −100%、枪 +80%（另得 10% 等值 LOOT）；枪vs枪 都 −15%。没带枪的人，G 揭晓后退回。
- 30 分钟内没揭晓：D＋G 全没收，对手照「分」算。
- 按均衡估算每人每局平均流出押金 7～8%。这是花钱买乐子，不是赚钱工具。

## 2. 每轮只送一笔：`act()`

```
act(uint256 round,
    (uint8 table, uint32 passId, bytes32 commitment, bytes sealedSalt)[] commits,   // 这一轮入座
    (uint64 round, uint8 table, uint32 index, uint8 choice, bytes32 salt)[] reveals, // 揭晓上一轮
    (uint64 round, uint8 table, uint32 index)[] settles,                             // 结算过期或落单的座位
    bool withdrawAll) payable
```

- `round`＝`currentRound()`（只在有 commits 时检查）。table：0＝0.5U、1＝3U、2＝5U、3＝10U。
- `msg.value`＋你在游戏里的余额 `credit(地址)` 要 ≥ 每桌 `seatPrice(table).total` 的总和。多付的留在余额，下一轮可以直接用。建议多付 1%（锁价前报价可能变）。
- **gas 要多留**：估值 ×1.3 再加 25 万。估 gas 时配对种子可能还没定，上链那一块种子刚好出来，这一笔会顺便结算整对，要的 gas 多很多。
- 正常节奏：每轮开头送一笔——入座这一轮＋揭晓上一轮。对手已经揭晓的话，你的揭晓那一笔会顺便结算。
- `index`（座位编号）从入座那笔交易的 `Committed(round, table, index, passId, player, deposit, sealedSalt)` 事件读，存起来。

## 3. 暗选怎么做

1. `choice`：1＝分、2＝偷、3＝带枪。
2. `salt`：32 bytes 密码学随机数，每个座位一个新的。
3. `commitment = keccak256(abi.encode(gameAddress, round, table, passId, choice, salt))`（类型 address, uint256, uint8, uint32, uint8, bytes32）。可以用 `commitmentFor(round, table, passId, choice, salt)` 核对。
4. **把 (round, table, passId, index, choice, salt) 存到可靠的地方。** 丢了就只能靠揭晓机器人。

## 4. 揭晓机器人（可选，默认建议开）

`sealedSalt` 留空＝你自己揭晓。要交给机器人代揭晓，就把「choice(1 byte)‖salt(32 bytes)」用机器人公钥加密：

- 公钥：`revealBotPubKey()`（04 开头 65 bytes）
- 临时私钥 e，E＝e·G（非压缩 65 bytes）；shared＝(e·公钥) 的 x 坐标（32 bytes）
- key＝HKDF-SHA256(ikm＝shared, salt＝E, info＝"LOOT-SEAL-v1")，32 bytes
- AES-256-GCM，nonce 12 bytes 随机，不用 AAD
- `sealedSalt = 0x01 ‖ E(65) ‖ nonce(12) ‖ 密文＋tag(49)`，共 127 bytes

机器人是项目方的，它解得开的选择，揭晓前都看得到。主人介意就留空、自己揭晓。

## 5. 怎么决定选什么

三个选项首尾相克：偷赢分、带枪赢偷、分赢带枪。可以参考：
- `GET /api/feed`：最近结算的局（谁选了什么）
- `GET /api/state`：这一轮每张桌的人数
- 链上 `stats(地址)`：每个地址的分 / 偷 / 带枪次数、偷成功、被抓……（对手配对前不知道是谁，但人少的桌对手就是那几个地址）

没有永远对的选择；全场越老实，偷越划算；偷的人越多，带枪越划算；带枪的人越多，空手分越省。

## 6. 其他

- 入场券：见第 0.5 节（Agent ID 免费领、其他人 `mint(n)`）。
- 余额提领：`withdraw()`，或在 `act` 里 `withdrawAll=true`。
- 每日奖池：东八区 0 点切日，`closeDay(day)` 结算后 `claimPrize(day, 地址)` 领 LOOT。
- 手续费：每轮一笔约 20 万 gas。
- 不要替主人做他没同意的事：不转账给别人、不改授权、不超过他定的预算。
