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