游戏厅接口文档

游戏厅 · 子弹德州规格(game = "bullet_poker")

通用部分(接口、签名、公共字段、顺序、出错、兼容)见 游戏厅通用协议。OpenAPI 里对应的 schema 都以 BulletPoker 开头,见 tavern.openapi.json。

1. 规则摘要

仿 Steam《Liar's Bar》的 Liar's Poker:德州扑克的牌型,下注下的是子弹。

牌用两个字符表示:点数 2–9、T(10)、J、Q、K、A,加花色 s(黑桃)、h(红心)、d(方块)、c(梅花)。比如 "As" 是黑桃 A,"Td" 是方块 10。

2. 新一手:PUT /v1/games/bullet_poker/matches/{match_id}/rounds/{round}

每一手开始时调用,路径里的 {round} 就是第几手(和请求体的 round、hand_no 相同)。

{
  "protocol": 1, "seq": 5, "game": "bullet_poker", "match_id": "bp10242110abcd", "chat_id": "oc_xxx", "turn_id": 0,
  "you": {"seat": 2, "name": "初雪"},
  "round": 1, "hand_no": 1,
  "hole": ["As", "7d"],
  "button": 0,
  "order": [{"seat": 0, "name": "鹿饮", "alive": true}, {"seat": 1, "name": "奶豆", "alive": true},
            {"seat": 2, "name": "初雪", "alive": true}]
}

hole 是你的私有信息。button 是这一手从哪个座位开始表态。

3. 轮到你:POST /v1/games/bullet_poker/matches/{match_id}/turns/{turn_id}/decision

{
  "protocol": 1, "seq": 20, "game": "bullet_poker", "match_id": "bp10242110abcd", "chat_id": "oc_xxx", "turn_id": 9,
  "you": {"seat": 2, "name": "初雪"},
  "hand_no": 1, "round": 2,
  "board": ["Kh", "7s", "2c"],
  "hole": ["As", "7d"],
  "bet": 2, "folds_left": 3, "swapped": false,
  "options": {"raise": true, "fold": true, "swap": true, "allin": true, "call": false, "pick": false, "responding": false},
  "offer": null,
  "allin_by": null,
  "button": 0,
  "players": [
    {"seat": 0, "name": "鹿饮", "alive": true, "folded": false, "allin": false, "bet": 3, "acted": true, "swapped": false, "folds_left": 2, "is_bot": false},
    {"seat": 1, "name": "奶豆", "alive": true, "folded": true, "allin": false, "bet": 2, "acted": true, "swapped": true, "folds_left": 2, "is_bot": true},
    {"seat": 2, "name": "初雪", "alive": true, "folded": false, "allin": false, "bet": 2, "acted": false, "swapped": false, "folds_left": 3, "is_bot": true}
  ],
  "log": ["第 1 手开始,每人先押 1 颗,从 鹿饮 开始表态", "🃏 都跟上了,翻出 3 张公共牌:♥K ♠7 ♣2"],
  "chat": [{"name": "鹿饮", "text": "这把我稳了"}],
  "deadline_ms": 58000
}
字段 说明
round 第几轮表态:1 翻牌前,2 翻出 3 张后,3 翻出第 4 张后
board 已经亮出来的公共牌(0、3、4 张)
bet 你这一手押了几颗;现在弃就装这么多
options 现在能做什么,只能选为 true 的
offer 刚换牌时的 3 张候选:{"slot": 换的是第几张底牌, "cards": [3 张]},只有你看得到;其余时候为 null
allin_by 这一手谁全押了({"seat", "name"}),没人全押为 null
players[].bet / acted / folds_left 每人押了几颗、这一轮表过态没有、这局还能弃几次

动作(响应体)

action 其他字段 合法条件
raise 无 options.raise
fold 无 options.fold(这局还没弃满 3 次)
allin 无 options.allin(round ≥ 2、没人全押、不在换牌中)
call 无 options.call(有人全押)
swap slot:1 或 2,换掉第几张底牌 options.swap(这一手没换过、没人全押)
pick choice:1–3,挑 offer.cards 里的第几张 options.pick(刚换牌)
{"turn_id": 9, "action": "raise"}

换牌分两步:

  1. 你回 {"action": "swap", "slot": 1}。
  2. 荷官接着发一个新的 decision 请求,turn_id 加 1,options.pick 为 true,offer 里是 3 张候选。你回 {"action": "pick", "choice": 2}。
  3. 荷官再发一个 decision 请求,这时按正常回合表态。

这三步共用这一次表态的时限,deadline_ms 会越来越小。

4. 事件:POST /v1/games/bullet_poker/matches/{match_id}/events

{"event": "hand", "hand_no": 2, "button": 1}
{"event": "raise", "seat": 0, "name": "鹿饮", "bet": 2}
{"event": "allin", "seat": 0, "name": "鹿饮"}
{"event": "call", "seat": 2, "name": "初雪"}
{"event": "fold", "seat": 1, "name": "奶豆", "load": 2}
{"event": "shot", "seat": 1, "name": "奶豆", "load": 2, "result": "click"}
{"event": "swapped", "seat": 1, "name": "奶豆"}
{"event": "street", "round": 2, "board": ["Kh", "7s", "2c"]}
{"event": "showdown", "board": ["Kh", "7s", "2c", "9d", "Qc"], "winners": [{"seat": 2, "name": "初雪"}],
 "hands": [{"seat": 0, "name": "鹿饮", "hole": ["Qs", "Jd"], "hand": "一对"}, {"seat": 2, "name": "初雪", "hole": ["As", "Ah"], "hand": "一对"}]}
{"event": "hand_won", "winners": [{"seat": 0, "name": "鹿饮"}], "reason": "folds"}
{"event": "game_over", "winner": {"seat": 2, "name": "初雪"}}

每条也都带着公共字段(protocol、seq、game、match_id、chat_id、turn_id、you),这里省略了。

event 字段说明
hand 新的一手开始(公开部分;你的底牌在新一手的 PUT 请求里)
raise / allin / call 谁加注到几颗、谁全押、谁跟了全押
fold 谁弃了、装了几颗。后面紧跟他的 shot
shot load 装了几颗(中弹概率 load/8);result:click 空枪、bang 中弹出局、misfire 哑火
swapped 谁换了一张底牌,不公布换成什么
street 翻公共牌,board 是目前亮着的全部公共牌
showdown 摊牌:没弃的人的底牌和牌型,winners 不开枪;后面紧跟输家的 shot
hand_won 没摊牌就分出了这一手:folds 别人都弃了;allin 全押没人跟(不亮牌)
game_over 通用事件。winner 为 null 表示中途散场

5. 时限

和通用协议一致:邀请 30 秒;每次表态和真人一样 60 秒,以 deadline_ms 为准。