Files
huajishe-tts/docs/double-up/00-rules.md
e2hang ddcb28472c feat(double-up): 双升游戏 + 单端口 start.sh 部署 + 文档统一更新
- 新增双升(DoubleUp)完整实现:引擎 double-up-core.ts / double-up.ts、牌桌 UI DoubleUpBoard.tsx、单测与 E2E
- 甩牌跟牌修复:validateFollow 新增 mixed 分支,甩牌后其他家可正常跟单张同花色牌
- start.sh:PORT=5173 单端口一键启动(Koa 同时 serve 页面+/api+/socket.io),浏览器直连无需 Vite 代理
- 玩家名 server 权威化(join 时写入 G.playerNames);LobbyRoomList 支持 fixedSeats(双升固定 4 人)
- 文档:新增 dev-log/14、更新 dev-log README 索引与进度、更新根 README 启动/部署说明
- .gitignore 忽略根目录 data/*.db 运行时 SQLite
2026-08-30 02:11:04 +08:00

14 KiB
Raw Permalink Blame History

双升(两副牌升级 / 拖拉机 / 80分玩法规则汇总

本文是给 CodeBuddy及后续实现双升游戏 packages/engine/src/games/double-up.ts)的玩法依据。 来源QQ游戏"升级"规则说明、百度百科"升级/拖拉机"词条、知乎升级(拖拉机)规则说明。 所有 【已拍板】 标记的规则为用户在 2026-08-27 确认的选型,实现时以此为准。


0. 一句话定义

四人两两结对,用两副含大小王的扑克牌108张,通过"亮主定花色(无人亮则翻牌兜底)→ 庄家扣底 → 轮流出牌捡分5/10/K→ 抠底翻番"的流程,按闲家得分决定庄家队伍是否升级,先打到 A 的一方获胜。


1. 牌具与发牌

  • 牌数:108 张(两副 × 54 张,含大小王)。【已拍板 V1含大小王】
  • 人数4 人,固定 4 人(双升不支持其他人数),对家为一队(南北 vs 东西)。
  • 分牌分值:5 = 5 分10 = 10 分K = 10 分。两副牌总分 = 200 分。

1.1 发牌流程(逐张发 + 实时排序 + 可亮主)

发牌是一个独立阶段deal,与出牌严格分离。流程:

  1. 洗牌后,一张一张发给 4 家(按座位顺序轮转)。每发出一张,收到牌的玩家手牌立即按「花色分组(主牌在前、副牌按 ♠>♥>♦>♣)、同花色点数从大到小」重排(由 sortHand 保证,玩家无需手动整理)。
  2. 发到 100 张时停止(每人 25 张),剩余 8 张作为底牌,不再发给任何人
  3. 发牌过程中deal 阶段内任意时刻)任何玩家可亮主(见 §3。亮出的牌从手牌移到该玩家座位前的「亮主公开区」(桌上所有人可见),被更高优先级反主时自动归还其手牌
  4. 发牌结束(满 100 张、剩 8 张底牌)自动定主:按亮主公开区里「当前最大优先级」的亮主记录定主花色+庄家(无人亮则翻底牌第一张兜底,见 §3 V3亮主区牌归还各自主人庄家收底直接进入 bottom 阶段不再有独立的「确认主花色」按钮/阶段Request B
  5. 主花色确认后进入 bottom 阶段庄家把 8 张底牌全部收入自己手牌(临时 33 张),按主花色在前、副花色在后重新排序,再挑 8 张扣出作为新底牌。这 8 张扣底牌只有庄家可见,其他人不可见(结算抠底时才公开)。
  6. 扣底完成后进入 play 阶段开始出牌。

工程实现注v2026-08-27 重构):发牌改为真正的一张一张发——房主端 UI 通过 dealOne move 以 ~150ms 间隔自动驱动(DoubleUpBoarduseEffect 监听 phase==='deal' && me==='0'),发满 100 张(dealIndex>=100)自动调用 resolveTrump 定主并转 bottom。亮主为公开亮主区revealed[pid]declareTrump 把牌从手牌移入该区(所有人可见),更高优先级反主时先把被反者亮主区的牌归还其手牌再落新亮主;resolveTrump(发满 100 张自动触发,或旧 confirmTrump move 兜底)把所有亮主区牌归还各自主人、确定主花色/庄家、庄家收底。playerView 对所有人隐藏 deck(未发的整副牌)与 bottom(非庄家),但 revealed 公开。

阶段机:waiting(进房)→ deal(一张一张发+可亮主,发满自动定主)→ bottom(庄家收底+扣 8 张隐藏)→ play(出牌)→ score(结算)。trump 阶段已合并进 deal 末尾自动处理。


2. 级牌 / 主牌 / 副牌

  • 级数:双方从 2 级起步;庄家队伍的当前级别 = 本局级牌点数。序列2,3,4,5,6,7,8,9,10,J,Q,K,A。打到 A 且获胜即整场获胜。
  • 级牌:点数等于当前级数的一切牌(四种花色都有),无论是否主花色皆为主牌。
  • 主牌:大小王(无花色,恒为主)+ 级牌(四花色皆主)+ 主花色所有牌(亮主决定)。
  • 副牌:除主牌之外其余三花色的牌。
  • 2 是否常主:【已拍板 V22 为常主】所有花色的 2 均为主牌,分"主2"主花色里的2与"副2"其他花色的2

主牌大小顺序2为常主从大→小

大王 > 小王 > 主级牌 > 副级牌 > 主2 > 副2 > A > K > Q > J > 9 > 8 > 7 > 6 > 5 > 4 > 3

副牌大小顺序(从大→小,花色间无大小):

A > K > Q > J > 9 > 8 > 7 > 6 > 5 > 4 > 3 > 2

同级牌"先出者大"(出牌时同点同花色以先落者为大)。


3. 亮主 / 反主(确定主花色)

时机:在 deal 阶段(发牌过程中) 即可亮主;亮出的牌从手牌移到该玩家座位前的「亮主公开区」(桌面可见,所有人都能看到),被反主时立即归还其手牌——不在手中、也不在暗处。发牌满 100 张时自动定主(亮主区最大优先级胜出,否则翻底牌第一张兜底),无需手动确认。

抢亮优先级由低到高V5 四级抢亮,"2 张反 1 张"

等级 亮出的牌 效果
1 单张级牌 定该花色为主
2 一对级牌 反主(覆盖单张)
3 一对小王 反主(覆盖级牌对,等同"反无主"方向)
4 一对大王 反主(最高,打无主)
  • 后亮者用更高优先级的牌可反主改花色;同优先级不能再反(以先出现者为准)。
  • "自保":直接亮对级牌同花色,除反无主外不能被反;"自反":本队再次用更高牌反。
  • 一对小王/大王亮出 = 打无主(无主花色,仅大小王+级牌+2 为主)。
  • 庄家认定:本局庄家 = 最后成功亮主(优先级最高)的玩家。第一局若无人亮主,庄家按轮庄默认值(初始 P0之后每局按轮庄顺序§8依次更替。
  • 【已拍板 V3翻第四张兜底】 仅当全程无人亮主时,发牌满 100 张后从底牌翻一张牌兜底定主:
    • 翻到普通花色牌 → 该花色为主花色。
    • 翻到大小王 → 打无主。
    • 翻到级牌 → 该级牌的花色为主花色。
    • 有人亮过主(含无主)则翻牌,直接采用已亮主结果。
  • 定主由 resolveTrump 在发满 100 张时自动完成(旧 confirmTrump move 作为手动兜底保留但未在 UI 暴露。定案后庄家收底牌§4

4. 扣底(庄家收底 + 扣 8 张隐藏)

  • 主花色确认后,进入 bottom 阶段:庄家先将 8 张底牌全部收入自己手牌(手牌临时变为 25+8 = 33 张),按主花色在前、副花色在后重新排序。
  • 庄家从这 33 张中挑 8 张扣出,作为新底牌(unshownBottom)。这 8 张只有庄家可见其他人不可见不放在明面直到结算抠底§6才公开。
  • 庄家扣底后手牌回到 25 张,进入 play 阶段。
  • 扣底策略:藏分牌或藏大牌防被抠。
  • 底牌分数归属在 §6 抠底时结算。

工程实现注:底牌 8 张在 playerView 中对非庄家返回空数组,确保 secrecy仅庄家 myHand 含其完整 33→25 牌。


5. 出牌规则

  • 首家(首引):每局第一轮由庄家先出;之后每轮由上一轮赢家先出。
    • 首家可出任意牌型:单张、对子、拖拉机(连对)、或"甩牌"。
  • 跟牌义务
    • 首家出单张:有该花色必须跟单张(无该花色可毙/垫)。
    • 首家出对子:有对子必须出对子(含拖拉机中的对)。
    • 首家出拖拉机:有拖拉机必须出拖拉机;无拖拉机则必须出对子;无对子才能出别的。
    • 首家出副牌花色而某家无此门花色:可出主牌毙(牌型须匹配:对子用主对、拖拉机用主拖拉机),或出别的副牌垫(垫牌永远最小)。
    • ⚠️ 若手上有首出花色牌,不能直接用主牌毙,必须先跟该花色。
  • 毙牌(主牌压副牌)
    • 仅当无首出花色时可出主牌;主牌天然大于副牌。
    • 毙牌牌型须 ≥ 首出牌型(拖拉机数、对子数都不能少于首家),否则算垫牌。
    • 多家毙牌时比毙牌中拖拉机/对子大小,大者"盖毙"。
  • 甩牌规则
    • 甩出的所有牌必须全大(同花色无人能压)。
    • 甩牌失败(他人有更大的)→ 强制出被压制牌型中的最小牌
    • 【已拍板 V4甩牌失败罚分】 额外按被压制的牌型张数罚分:
      • 单张被压:罚 10 分
      • 对子被压:罚 20 分
      • 拖拉机被压(长度 n罚 20 × n 分
      • 结算方向:庄家甩牌失败 → 闲家得分(罚分加给闲家);闲家甩牌失败 → 闲家扣分(从闲家总分中扣除)。
      • 甩牌失败的具体最小牌型仍须按规则打出(软惩罚 + 罚分并存)。
  • 一轮 4 家出齐(或对应牌型张数),最大者赢墩并收走本圈所有分牌。

UI 出牌交互v2026-08-27:本人手牌可自由多选DoubleUpBoard 实时调用 parsePlay + validateFollow 解析当前选择并提示牌型(单张/对子/拖拉机/甩牌)与合法性(如"必须跟领出花色")。「出牌」按钮仅当选择合法时才点亮。首出可任意牌型;跟牌若持有领出花色/对子/拖拉机则必须匹配,断门才可毙/垫。这样对子、拖拉机、甩牌均可在 UI 正常打出(之前缺实时提示导致只能出单张)。


6. 拖拉机(连对)定义

  • 定义:同花色、点数连续、每点两张(对子)的联牌。必须全主或全副,主副不可混。
    • 副牌例:KKQQJJ99554433
    • 主牌例:一对小王+一对主级牌主级牌对+副级牌对主级牌对+主A对
  • 级牌相邻可连:主花色级牌 7 可与红桃 66、红桃 88 连成拖拉机;副级牌 7 与副花色 7 可连(同为主)。
  • 王的特殊:大王+小王 可成对/连(在主牌序相邻)。
  • 不算拖拉机5545445533JJQ两对副10(不相邻)、JJ1010AA22(常主时 AA 与 22 间隔 KQJ9…8不相邻

连续长度 n两连对 n=2三连对 n=3以此类推。


7. 抠底(底牌翻番)

  • 最后一圈若闲家方赢,触发抠底:底牌中的分牌按倍数计入闲家得分。
  • 倍数 = 2 的(最后一圈最大牌型张数)次方。【已拍板 V6封顶 64 倍】(即 6 张 / 三连对封顶)。
    • 单张抠底2¹ = 2 倍。
    • 对子抠底(如 442² = 4 倍。
    • 两连对(如 44552⁴ = 16 倍。
    • 三连对(如 4445552⁶ = 64 倍(封顶)。
  • 甩牌抠底:只按甩牌中的最大牌型算倍数(如甩 AKQJ109877按对子 77 算 4 倍;甩 AKQJ 按单张算 2 倍)。
  • 最后一圈庄家方大 → 不抠底(底牌分归庄家,闲家不得分)。

底牌分 = 底牌中 5/10/K 的面值之和 × 倍数,加入闲家总分后参与 §8 升级判定。


8. 得分与升级判定

闲家(抓分方)本局总得分计(含捡到的分牌 + 抠底翻番分 + 甩牌罚分加减),总分 200

闲家得分 结果
0 庄家方连升 3 级
1 39不满40 庄家方升 2 级
40 79 庄家方升 1 级
80 119 轮换庄家(闲家上台,不升级)
120 159 闲家方升 1 级
160 199 闲家方连升 2 级
≥200每多40 闲家方再加升相应级数

台阶累计逻辑0/40/80/120/160/200… 各对应 庄+3/庄+2/庄+1/闲+1/闲+2/闲+3…之后每 40 分再 +1 级。

轮庄

  • 庄家升级(保庄):下一副由对家当庄家。
  • 闲家上台:下一副由本副庄家的下家当庄家。

胜负:某队打到 A 且本局获胜(升级过 A 或闲家上台时已达 A→ 该队整场胜。

A 级特殊回流(如被用 A 抠底则下局级牌回退到 J属进阶变体【待确认默认不实现】。


9. 已拍板的规则选型汇总

# 项目 选型
V1 是否含大小王 108张
V2 2 是否常主 主2/副2
V3 无人亮牌兜底 翻第四张兜底(有人亮则不打翻牌);翻到王=无主,翻到花色/级牌=该花色主
V4 甩牌失败惩罚 罚分单张10/对子20/拖拉机20×n庄家失败闲家得、闲家失败闲家扣
V6 抠底倍数上限 64 倍封顶

未拍板项(实现时采用主流默认,后续可调整):

  • V5 亮主机制:四级抢亮(单级牌<对级牌<对小王<对大王)+ 自保/自反。
  • V7 级牌起始:从 2 级起步。
  • A 级回流变体:默认不实现。
  • 翻牌兜底翻到"级牌"时是否允许再反主:默认不允许(翻牌为最终兜底,等同于定主)。

10. 与现有代码库的对接要点(实现提示,非规则)

  • 新游戏文件:packages/engine/src/games/double-up.ts,导出 TTSGamename: 'DoubleUp'engineName: 'DoubleUp'minPlayers/maxPlayers: 4setup 发 108 张牌(含大小王),留 8 张底。
  • game.ui:需声明主/副牌区、4 家手牌区、底牌区、已出牌区、当前级牌/主花色指示。因 4 人 + 拖拉机复杂度高,建议先实现逻辑引擎moves亮主/翻牌兜底/扣底/出牌/跟牌校验/收分/甩牌罚分/抠底/升级判定UI 可先用 game.ui.actions + 简化 Board或仿 HoldemBoard 写专用 DoubleUpBoard
  • 必实现的核心校验(出牌合法性):跟牌花色义务、对子/拖拉机跟牌、毙牌牌型匹配、甩牌全大判定 + 罚分、主副大小比较、抠底倍数封顶64
  • 需注册到 packages/server/src/index.ts 的两个数组(Server({games})GAMES_ENTRIES),及 apps/web/src/App.tsxGAMESmaxSeats=4
  • 建议配套:在 packages/engine/src/games/double-up.test.ts 写单元测试覆盖亮主/反主、跟牌校验、拖拉机判定、抠底倍数、升级判定表、甩牌罚分。

11. 参考来源

  • QQ游戏"升级"规则说明minigameimg.qq.com/help/rule36.html
  • 百度百科:升级/拖拉机baike.baidu.com/item/升级/3563150
  • 知乎升级拖拉机规则zhuanlan.zhihu.com/p/2035707530240844260甩牌罚分精确算法来源
  • 知乎:升级(拖拉机)游戏基本游戏规则zhuanlan.zhihu.com/p/101357920
  • 知乎四人升级80分/拖拉机/双升游戏规则说明zhuanlan.zhihu.com/p/1900479633754948317