- 新增桥牌(Contract Bridge)完整实现:固定 4 人分南北/东西两队
- 引擎 packages/engine/src/games/bridge.ts:
- 52 张牌均分,每人 13 张,共 13 墩
- 阶段机 waiting → bidding → play → score
- 叫牌:Pass / Bid(1♣..7NT 35 个叫品)/ Double / Redouble
* Bid 必须高于上一叫品(阶数优先,同阶则花色等级 ♣<♦<♥<♠<NT)
* Double 只能针对敌方叫品;Redouble 只能针对己方被加倍的叫品
* 连续 3 家 Pass 结束叫牌;4 家全 Pass 作废重发
- 打牌:强制跟花色 / 将牌赢墩 / NT 不可将吃;明手 13 张牌摊开由庄家控制
- 计分:完整实现成局 ≥100、超墩、满贯(小/大)、加倍/再加倍、罚分表(含易局/非易局)
- 橡胶局(Rubber Bridge):完成且成局记 1 局;赢 2 局胜一盘,重置易局
- playerView 隐藏他人手牌,明手牌公开对所有人可见
- UI apps/web/src/BridgeBoard.tsx:
- 椭圆牌桌 + 4 家固定 N/E/S/W 方位(参照双升 / 拱猪 UI 风格)
- 真实姓名显示:G.playerNames(引擎 setName 写入)+ prop(ctx.players)+ setName 兜底
- 常驻计分板:NS / EW 队员姓名 + 本副赢墩数 + 累计分 + 队总分 + 易局 + 盘数
- 顶部状态条:当前副数 / 局数 / 易局 / 契约 / 庄家明手 / 大字号 NS vs EW 墩数对比
- 座位卡:每玩家本副赢墩数 + 手牌张数 + 角色(庄/明/防)
- 叫牌:35 个 bid 按钮 + Pass / X / XX;叫牌历史 hover 显示真实姓名
- 牌桌内显示:上一墩(3 秒高亮后由 collectTrick 收牌)+ 当前墩 + 领出花色
- 明手手牌区:庄家控制时高亮可点;明手本人不可自己出牌
- 文档 docs/bridge/00-rules.md:桥牌规则调研 + 10 条实现选型 + 与标准桥牌的差异说明
- 测试 packages/engine/src/games/bridge.test.ts:49 个用例覆盖牌组 / 叫品合法性 / 跟牌 / 赢墩 / 计分 / 成局
- App.tsx:GAMES 表新增 bridge(fixedSeats=4),GAME_ORDER 插入;BridgeLocalView / BridgeOnlineView
- server/src/index.ts:games 数组与 GAMES_ENTRIES 注册 Bridge,启动日志同步
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
16 KiB
桥牌(Contract Bridge)玩法规则与实现选型汇总
本文档是给 CodeBuddy 实现桥牌游戏
packages/engine/src/games/bridge.ts的玩法依据。 来源:WBF《Laws of Duplicate Bridge 2017》、ACBL《Rubber Bridge》官方规则、维基百科 Contract Bridge 词条、Bridge Base Online(在线桥牌平台)规则页。 所有 【已拍板】 标记的规则为实现选型(按本地 4 人联机场景做了合理化裁剪),引擎实现以此为准;与真实桥牌有出入的条目在第十节「与标准桥牌的差异」中单独说明。
0. 一句话定义
四人两两结对(南北 NS vs 东西 EW),用一副 52 张标准牌(每人 13 张,共 13 墩),按「发牌 → 叫牌(确定定约方/将牌/阶数/加倍状态)→ 打牌(庄家指挥明手赢墩)→ 计分」的流程决出胜负。计分采用橡胶桥(Rubber Bridge)模式:完成 ≥100 墩分即成一局,赢两局胜一盘。
1. 牌具与座位
- 牌:52 张标准牌,4 花色 × 13 点(A K Q J 10 9 8 7 6 5 4 3 2),无大小王。
- 人数:固定 4 人,不支持 2/3 人。
- 座位:4 人围坐一圈,按顺时针编号为 N(北)→ E(东)→ S(南)→ W(西)。
- 搭档固定:N + S(南北队,NS)、E + W(东西队,EW)。
- 相对而坐,互为对手。
- 手牌:每人 13 张,共 13 墩(每墩 4 张)。
2. 发牌阶段
- 房主点「开始游戏」时系统洗一副 52 张牌,按座位顺序一张一张均分,每人 13 张。
- 发牌后立即进入叫牌阶段,发牌人(首局的 N)先叫。
- 发牌阶段(deal)只是一次性原子动作,不需要一张一张动画(与双升不同,桥牌发牌后所有 13 张一次摊给玩家,立即开始叫牌)。
3. 叫牌阶段(Auction)
叫牌是顺时针轮流进行的公开过程,每位玩家依次说出一个叫品(pass / bid / double / redouble),直到连续三人 pass(Pass Out Pass)后叫牌结束。
3.1 叫品结构
- Pass(P / 不叫):放弃本次叫牌机会,不构成定约。
- Bid(叫品) = 阶数(1~7)+ 花色(♣/♦/♥/♠/NT),承诺该方能在该阶数 + 6 墩的基础上完成定约(如
1♥= 承诺至少赢 7 墩,且 ♥ 为将牌)。- 阶数:1、2、3、4、5、6、7(共 7 档,对应 7~13 墩)。
- 花色等级(从低到高):♣ < ♦ < ♥ < ♠ < NT。
- Double(X / 加倍):对敌方最后一个叫品加倍。
- Redouble(XX / 再加倍):本方叫品被敌方加倍后,对该加倍再翻倍。
3.2 叫品合法性规则
- 必须高于之前的叫品——阶数优先;同阶数则花色等级必须更高。
- 例:
1♣ → 1♦ → 1♥ → 1♠ → 1NT → 2♣ → 2♦ → ... → 7NT。
- 例:
- Double:必须针对敌方的最后一个叫品;不能加倍己方叫品;不能加倍 Pass 后的「叫品」(Pass 不构成叫品)。
- Redouble:必须针对敌方对自己叫品的 Double;其它情况不允许。
- Pass:随时可叫,总是合法。
- 一家叫出非 Pass 后,后续各家在没新叫品出现前,不能再次叫同等或更低的叫品(包括花色等级)。
3.3 叫牌结束条件
| 情况 | 结果 |
|---|---|
| 连续 3 家 Pass | 叫牌结束 |
| 4 家全部 Pass | Pass Out(PO)——本局作废,分数清零,开始新一手 |
| 最后叫品后被连续 Pass | 进入打牌阶段 |
3.4 定约方与术语
- 庄家(Declarer) = 首先叫出最终定约花色的一方玩家(若最终叫品为 NT,则为首先叫 NT 的玩家)。
- 例:叫牌过程
P-1♣-P-1♥-P-1♠-P-P-P,最终定约1♠,则庄家 = 首先叫 ♠ 的那位玩家(不是必然最后叫的人)。
- 例:叫牌过程
- 明手(Dummy) = 庄家的搭档。
- 定约方(Declaring Side) = 庄家 + 明手(搭档二人);他们需要完成定约。
- 防守方(Defending Side) = 敌方二人(对手)。
- 首攻方(Opening Leader) = 庄家左侧的那位玩家(属于防守方之一)。
4. 将牌(Trump)
- 叫牌确定的花色为将牌花色(trump);叫
X NT则无将(No Trump)。 - 将牌永远大于其他花色——任何将牌都比非将牌花色的最大牌更大。
- 无将(NT):没有将牌花色,只能用领出花色中的最大牌赢墩;领出花色外的牌是废牌(无法赢墩,除非用将吃——但 NT 不可将吃)。
- 实际出牌时,将牌赢墩优先级最高:若领出方出非将牌花色,下家可以将吃(ruff)——出一张将牌盖掉(无论点数高低),赢得本墩。
5. 打牌阶段(Play)
5.1 流程
- 打牌共 13 墩。第一墩由首攻方(庄家左手玩家)领出一张牌(面朝上)。
- 之后按顺时针各家各出一张,构成一墩。
- 4 人出完一墩后,比较大小,赢墩者收走该墩并领出下一墩。
- 13 墩打完,本副牌结束,进入计分。
5.2 跟牌规则(强制)
- 若手中有**领出花色(lead suit)**的牌,必须出该花色(包括领出方出牌后续的所有人)。
- 若手中没有领出花色:
- 若有将牌:可以将吃(ruff)——出一张将牌(无论点数),赢得本墩。
- 若既无领出花色又无将牌:可以垫牌(discard)——任意其他花色牌(永远不能赢墩,除非被将吃,但此处已将牌没有)。
- 无将(NT):不能将吃——若没有领出花色,只能垫牌,永远不能赢此墩。
5.3 赢墩规则
按出牌顺序,第 4 张牌出完后比较本墩:
| 情况 | 赢墩者 |
|---|---|
| 有人将吃 | 最大将牌赢墩(无论点数) |
| 无人将吃,有将牌花色在内 | 最大将牌赢墩 |
| 无人将吃,纯领出花色 | 最大领出花色赢墩 |
| NT 局且都是垫牌 | 第一张牌(领出者)赢墩(其领出花色牌最大) |
注:首攻方出的领出花色牌永远是该花色最大或唯一存在该花色的牌(否则首攻方不出该花色)。
5.4 明手(Dummy)
- 打牌阶段,明手的 13 张牌明牌摊开在桌上,所有人可见。
- 明手牌由庄家指挥出牌(庄家对明手和自己的牌共 26 张都有控制权)。
- 明手玩家不能自主出牌——UI 上把明手的牌视为「庄家控制的牌堆」,庄家每轮选明手该出哪张。
- 防守方(敌方二人)各自出自己手中的牌。
6. 计分(Scoring)
桥牌计分比较复杂,分为 完成定约奖励(Contract Points) 和 罚分(Penalty Points)。本文档采用橡胶桥计分法。
6.1 墩分(Trick Points)
完成定约所要求的 6 + 阶数 墩叫「合约墩」,每超过 6 墩的部分叫「奇墩(odd tricks)」。每奇墩的得分:
| 定约花色 | 每奇墩得分 |
|---|---|
| ♣ 或 ♦ | 20 |
| ♥ 或 ♠ | 30 |
| NT(无将) | 首墩 40,之后每墩 30 |
加倍/再加倍 时奇墩分翻倍:
| 状态 | 墩分 |
|---|---|
| 未加倍 | 上述原值 |
| 加倍(X) | 墩分 ×2 |
| 再加倍(XX) | 墩分 ×4 |
6.2 成局与未成局
- 合约墩分 ≥ 100:成局(Game)。
- 合约墩分 < 100:未成局(Part-Score / Partial)。
| 定约 | 合约墩分 | 是否成局 |
|---|---|---|
| 3NT | 70 + 30×2 = 100 | ✅ 成局 |
| 4♥ / 4♠ | 30×4 = 120 | ✅ 成局 |
| 5♣ / 5♦ | 20×5 = 100 | ✅ 成局 |
| 4♣ / 4♦ | 20×4 = 80 | ❌ 未成局 |
| 1NT / 2NT | 40 + 30×(n-1) | 1NT=70 未成局;2NT=90 未成局;3NT=100 成局 |
6.3 完成定约奖励
定约方完成(或超过)合约墩数时的奖励分:
| 类型 | 未成局(Part-Score) | 成局(Game) |
|---|---|---|
| 完成定约基本分(未加倍) | 50 | 300(小满贯/大满贯另算) |
| 完成定约基本分(加倍 X) | 50 | 500 |
| 完成定约基本分(再加倍 XX) | 100 | 1000 |
注:完成定约基本分与奇墩分分开记——基本分是奖励,奇墩分计入成局线(≥100 即成局)。
6.4 超墩奖励(Overtricks)
多得墩数(合约外的赢墩)的奖励:
| 状态 | 每超墩得分 |
|---|---|
| 未加倍 | 与原墩分相同(♣♦20,♥♠30,NT30) |
| 加倍(X) | 易局 200;非易局 100 |
| 再加倍(XX) | 易局 400;非易局 200 |
6.5 满贯奖励(Slam Bonus)
完成 12 墩 = 小满贯(Small Slam);完成 13 墩 = 大满贯(Grand Slam)。
| 类型 | 未成局/非易局 | 易局 |
|---|---|---|
| 小满贯(12 墩) | 500 | 750 |
| 大满贯(13 墩) | 1000 | 1500 |
满贯奖励与加倍状态无关——只跟是否达成 12/13 墩以及是否易局相关。
6.6 失败罚分(Undertricks)
定约方未达到合约墩数时(即输 N 墩),敌方获得罚分(按"输墩的次数"算):
| 输墩数 | 非易局未加 | 非易局加倍 | 非易局再加倍 | 易局未加 | 易局加倍 | 易局再加倍 |
|---|---|---|---|---|---|---|
| 第 1 墩 | 50 | 100 | 200 | 100 | 200 | 400 |
| 第 2 墩 | 50 | 200 | 400 | 100 | 300 | 600 |
| 第 3 墩 | 50 | 200 | 400 | 100 | 300 | 600 |
| 第 4+ 墩(每) | 50 | 200 | 400 | 100 | 300 | 600 |
易局(Vulnerable):当一方已经赢了一局(成局)后,下一局该方自动为易局,直到该盘结束。 详细规则见 §6.8 橡胶桥规则。
6.7 简化计分(本文档采用)
为了本地 4 人联机的简单性,本实现对标准桥牌的计分做了适度简化(详见 §10)。核心规则:
- 完成定约奖励、超墩奖励、满贯奖励、罚分均按上述标准表。
- 墩分和奖励分合并计入完成方的总分——便于 UI 一目了然。
- 罚分单独计入敌方总分(负数表示被扣分)。
6.8 橡胶桥规则(一盘制胜)
- 一盘(Rubber)= 一局 + 双方完成各自的局数。
- 橡胶桥采用累计分制:
- 任一方先赢 2 局(Game)即赢一盘。
- 一盘结束,双方易局状态重置,新一盘重新开始。
- 简单起见,本实现把"局"理解为:只要有一方成局(≥100 合约墩分)即记录「1 局胜利」;第一个赢 2 局的队伍胜一盘。
- 本地游戏可以无限进行(无终局条件),玩家自行决定结束。
7. 玩法变体
- 橡胶桥(Rubber Bridge) ✅ 本实现采用:累计局数决胜。
- 复式桥(Duplicate Bridge):俱乐部/比赛用,同手牌多桌对比,不在本地联机场景使用。
- 芝加哥桥(Chicago Bridge):4 局一盘,不在本实现范围。
8. 策略基础
8.1 4 种赢墩方式
- 建立长套(Establishment):打一花色树立长套,后期必赢。
- 打大牌(Top of the Line):持有对方无法超越的大牌直接赢墩。
- 飞牌(Finesse):利用大牌位置优势(明手/自己持有大牌,争取让对方在大牌之间出小牌)。
- 将吃(Ruff):用将牌赢对方领出的非将牌花色。
8.2 牌力估算(Milton Work Count)
| 牌 | 点数 |
|---|---|
| A | 4 |
| K | 3 |
| Q | 2 |
| J | 1 |
- 全副牌共 40 点(4×4+3×4+2×4+1×4=40)。
- 通常 12+ 点开叫,搭档合计 25+ 点可成局。
本实现不实现任何叫牌体系(SA / Acol / 2/1 / Precision),完全由玩家自由叫牌。AI 队友(如果有)也只做基本决策。
9. 已拍板的规则选型
| # | 项目 | 选型 |
|---|---|---|
| V1 | 人数 | 固定 4 人,不支持 2/3 |
| V2 | 牌组 | 52 张标准牌(无大小王) |
| V3 | 叫牌体系 | 自由叫牌——不实现任何体系(玩家自决);AI(若加)只做基本开叫决策 |
| V4 | 叫牌结束 | 连续 3 家 Pass 或 4 家全 Pass(PO 重新开始) |
| V5 | 定约方/庄家 | 首先叫出最终定约花色的玩家(标准规则) |
| V6 | 打牌 | 13 墩,首攻方 = 庄家左手;明手牌公开由庄家控制 |
| V7 | 跟牌规则 | 标准强制跟牌 / 将吃 / 垫牌;NT 不可将吃 |
| V8 | 计分 | 橡胶桥制:完成 ≥100 合约墩分成局;赢 2 局胜一盘 |
| V9 | 易局 | 一方赢一局后该方在剩余该盘易局,直到新盘 |
| V10 | 终局条件 | 无终局——连续多盘进行,累计分数显示在 UI,玩家自决 |
未拍板项(实现时采用主流默认):
- 叫牌超时机制:本地联机玩家每叫有思考时间,无强制超时。
- 非法叫品拦截:UI 显示可叫品(基于当前叫牌历史),点击非法叫品直接拒绝。
10. 与标准桥牌的差异
为了在 4 人联机的浏览器环境下顺利实施,本实现做了适度简化,不影响核心玩法:
- 无规则违规惩罚:标准桥牌中有「违规/修正」机制(lead out of turn 等),本实现不实现,只校验叫品合法性、出牌合法性、跟牌合法性。违反顺序的 move 在 server 端被忽略。
- 无 Claim(声称已胜)机制:标准桥牌允许玩家在中途声称已胜局并摊牌,本实现要求打满 13 墩。
- 无慢速打牌/喊单超时:本地玩家无思考时间限制;超时则自动 Pass。
- 无慢速叫牌叫品(Slow Bid)限制:标准桥牌禁止某些拖延叫品,本实现不限制。
- 易局按「本盘」累计:标准橡胶桥是「一盘(Rubber)」重置易局;本实现用相同规则。
- 复式桥牌模式不支持:只有橡胶桥。
11. 与现有代码库的对接要点
- 新游戏文件:
packages/engine/src/games/bridge.ts,导出TTSGame,name: 'Bridge',engineName: 'Bridge',minPlayers/maxPlayers: 4。 setup:建 4 个空 hands 桶、初始化 callHistory / finalContract / declarer / leadPlayer / vulnerability / rubber 状态。- 阶段机:
waiting(进房)→bidding(叫牌)→play(打牌)→score(结算)。bidding阶段维护callHistory,结束时定庄家/定约方。 playerView:- 隐藏:他人 hands(除明手外,明手一旦摊开就对所有人可见)。
- 公开:
currentTrick、callHistory、finalContract、declarer、dummy、vulnerability、scores。
- 必实现的核心校验:
- 叫品合法性(必须高于上一叫品;Double/Redouble 仅对敌方/己方被加倍叫品)。
- 跟牌规则(有领出花色必须跟;NT 局不可将吃;将吃用最大将牌赢墩)。
- 明手控制(庄家指挥明手出牌)。
- 计分(按 §6.1~§6.6 表格;橡胶局制胜按 §6.8)。
- 需注册到
packages/server/src/index.ts的games数组与GAMES_ENTRIES数组,及apps/web/src/App.tsx的GAMES表(maxSeats=4,fixedSeats=4)。 - 配套单元测试
packages/engine/src/games/bridge.test.ts:发牌、叫牌合法性、跟牌规则、赢墩判定、计分表(成局/满贯/加倍/超墩/罚分)、橡胶局胜。
12. 参考来源
- 维基百科:Contract Bridge(en.wikipedia.org/wiki/Contract_bridge)
- WBF《Laws of Duplicate Bridge 2017》(worldbridge.org)
- ACBL《Rubber Bridge》规则页(acbl.org)
- Bridge Base Online 规则页(bridgebase.com)
- 百度百科「桥牌」词条
- 知乎「桥牌玩法」专栏