# 问题 6:结算亮牌 —— 开最大人的牌;All-in 必须翻两边牌,不盖自己的牌 ## 现象(用户反馈) “结算的时候开最大人的牌,如果是 All in 必须翻两边的牌,不要盖住自己的牌。” 推断两条诉求: 1. **摊牌时亮出相关玩家的底牌**(特别是赢得最大池 / 参与对决的玩家)。 2. **有人 all-in 时,必须两边都翻牌**(即所有 all-in 相关的玩家都要亮牌,不能让别人替你盖着), 且**不能盖住自己的牌**(自己的底牌在结算后应当可见,而不是被盖回)。 ## 现状(基于 `holdem.ts` + `HoldemBoard.tsx`) - `resolveHand`(showdown)构造 `results.revealedHands`: ```ts revealedHands: Object.fromEntries( unfolded.filter(pid => G.hands[pid]).map(pid => [pid, G.hands[pid]]) ) ``` 即**所有未弃牌玩家**的底牌都会亮(`HoldemBoard` 读 `G.results.revealedHands` 渲染,`HoldemBoard.tsx:122`)。 → 已经“开最大人的牌”(摊牌就全体亮),符合诉求 1。 - **问题在 all-in 提前摊牌**:当多人 all-in 且街道还没发完(例如翻牌后全员 all-in → 直接级联到 showdown), 此时 `G.hands` 里**只有仍 inHand 的玩家**有牌;弃牌者没有。这是对的(弃牌不亮)。 - **“不要盖住自己的牌”**:结算后 `resolveHand` 末尾 `G.hands = {}`(`holdem.ts:647`)清空了秘密数据, 导致结算结果界面里**自己的底牌也消失**(被“盖住”)。用户希望结算后仍能看到自己的牌。 - **“All-in 必须翻两边的牌”**:当前若一方全下、另一方跟注后继续(没到 showdown),中途弃牌不亮——标准规则 是“全下对决时双方都亮”。本项目只在 showdown 才亮全部未弃牌者,基本满足;但**被跟注后对方弃牌(fold-win)时不亮牌** (`HoldemBoard` fold-win `revealedHands = null`),此时全下者其实已经获胜且应亮牌——现有规则“fold-win 不亮”是常见做法, 但用户明确要求“all-in 必须翻两边”,需调整为:**只要有玩家 all-in 且手牌结束,就亮出参与对决者的牌**。 ## 拟采用方案 1. **结算后保留自己的牌可见**: - 不要在 `resolveHand` 里立刻 `G.hands = {}`。改为:把“我自己的底牌”也纳入 `results` 的一个字段 `results.myHandAtShowdown?: Record` 或在 `revealedHands` 中保留自己。 - 简化:在 `playerView` 里,若 `results` 存在,把自己的 `G.hands[playerID]` 也塞进 `myHand` 或 `revealedHands[playerID]`, 供 UI 显示“你这手牌”。 - 真正的秘密清理仍要做(避免下一手泄露),但可延迟到下一手 `preflop.onBegin` 发牌前再清。 当前 `startHandSetup` 开头就重置并覆盖 `G.hands`,所以**不清空也不影响下一手保密**,只需在 `waiting` 阶段展示完即可。 → 折中:保留 `G.hands` 直到下一手 onBegin 覆盖(最简洁),或显式复制进 `results` 后清空。 2. **All-in 对决强制亮牌**: - 在 `resolveHand` 之前/之中判定:若手牌结束是因为有人 all-in 且存在“跟注者/对决者”, 即使最终走 fold-win(对方弃牌),也把**全下者 + 其对手**的底牌亮出。 - 具体:构造 `revealedHands` 时,除了 `unfolded`(未弃牌者),还纳入 `allIn 玩家` 与 `对其下注被跟注的玩家`,保证“all-in 两边都翻”。 - 调整 `results.kind`:fold-win 但含 all-in 对决时,仍填充 `revealedHands`(不完全是“无人跟注”语义, 可保留 kind 但让 UI 显示亮牌)。或新增 `kind: 'allin-showdown'`。 3. **UI(`HoldemBoard`)**: - 结算区(已有 `results` 渲染,`HoldemBoard.tsx:243`)展示 `revealedHands` 里所有亮出的牌(含自己的)。 - 自己的底牌:若 `G.results` 存在且自己在对决中,`myHand` 仍显示,不被盖。 ## 验证 - 单测:`resolveHand` 在 all-in + 对方弃牌场景,断言 `revealedHands` 包含全下者及其对手。 - 单测:showdown 后 `results` 包含自己 pid 的牌(或 `myHand` 在 results 阶段仍非空)。 - 联机手测:全下对决 → 结算界面双方底牌都翻开,自己的牌不盖。