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

55 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 问题 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<pid, [Card,Card]>` 或在 `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 阶段仍非空)。
- 联机手测:全下对决 → 结算界面双方底牌都翻开,自己的牌不盖。