Files
huajishe-tts/docs/texas/06-showdown-reveal-cards.md
e2hang 04d0af515c feat: 登录系统落地 + 踢人修正 + 单房间约束 + 权限收口
问题8 登录系统:
- node:sqlite 账号存储(scrypt 哈希 + HMAC 签名 token),preset admin 改为 e2hang/evan1115
- /api/auth/register|login|me,me 返回 room 供重联
- 网关拦截 create/join 需登录(401),列表保持开放

踢人逻辑修正(问题2 延伸):
- kickMove 真正释放座位(folded=false, name=null)而非锁死
- war/mill 去掉永久封禁语义

管理员越权:管理员 token 可删任意房间、踢任意房间内的人

单房间约束(用户新需求):
- 同一用户同时只能在一个房间,create/join 他房返回 409
- 踢人后若房间仅剩踢人者则自动解散并释放其记录(修复 2 人局踢光对手后被困 409)
- 陈旧房间记录兜底清理

UI 清理:移除"改名"按钮与"你的名字"输入框;删除房间按钮仅房主/管理员可见

docs: 新增 12-auth-kick-single-room.md 汇总本会话全部需求/根因/修复/边界测试

Co-Authored-By: Claude (CodeBuddy) <noreply@codebuddy.ai>
2026-08-25 14:13:59 +08:00

4.2 KiB
Raw Permalink Blame History

问题 6结算亮牌 —— 开最大人的牌All-in 必须翻两边牌,不盖自己的牌

现象(用户反馈)

“结算的时候开最大人的牌,如果是 All in 必须翻两边的牌,不要盖住自己的牌。”

推断两条诉求:

  1. 摊牌时亮出相关玩家的底牌(特别是赢得最大池 / 参与对决的玩家)。
  2. 有人 all-in 时,必须两边都翻牌(即所有 all-in 相关的玩家都要亮牌,不能让别人替你盖着), 且不能盖住自己的牌(自己的底牌在结算后应当可见,而不是被盖回)。

现状(基于 holdem.ts + HoldemBoard.tsx

  • resolveHandshowdown构造 results.revealedHands
    revealedHands: Object.fromEntries(
      unfolded.filter(pid => G.hands[pid]).map(pid => [pid, G.hands[pid]])
    )
    
    所有未弃牌玩家的底牌都会亮(HoldemBoardG.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<pid, [Card,Card]> 或在 revealedHands 中保留自己。
    • 简化:在 playerView 里,若 results 存在,把自己的 G.hands[playerID] 也塞进 myHandrevealedHands[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.kindfold-win 但含 all-in 对决时,仍填充 revealedHands(不完全是“无人跟注”语义, 可保留 kind 但让 UI 显示亮牌)。或新增 kind: 'allin-showdown'
  3. UIHoldemBoard

    • 结算区(已有 results 渲染,HoldemBoard.tsx:243)展示 revealedHands 里所有亮出的牌(含自己的)。
    • 自己的底牌:若 G.results 存在且自己在对决中,myHand 仍显示,不被盖。

验证

  • 单测:resolveHand 在 all-in + 对方弃牌场景,断言 revealedHands 包含全下者及其对手。
  • 单测showdown 后 results 包含自己 pid 的牌(或 myHand 在 results 阶段仍非空)。
  • 联机手测:全下对决 → 结算界面双方底牌都翻开,自己的牌不盖。