二七王:亮牌改为下发庄家全部固定主牌的具体牌面

规则变更(design §8.2):原先「只亮数量/结构,不亮具体是哪几张牌」,现改为
向两个闲家亮出【庄家手中全部固定主牌的具体牌面】。

- 固定主牌 = 双王 + 全部花色的 2 + 全部花色的 7,【不含】主花色普通牌
  A/K/Q/J/10/9/8/6/5。注意这与旧实现收集的「所有主牌」范围不同。
- 门槛不变(固定主牌总数 ≥10 / 王 ≥3 / 7 ≥6 / 2 ≥6,任一满足)。
- 不限叫分;仅可查牌模式下发;亮出的是固定的一份,不随被哪条门槛触发而增减。
- 协议 liangpai 由 {zhu,zhupair,zhutuo,wang,qi,er} 数量结构改为 {cards:[牌id...]},
  数量交由前端从 cards 自行计算。

服务端 get_liangpai() 重写(class.paiju.js);design §8.2 整节重写,术语表、
易混对照表、§9 相应更新;协议 §0.0b 与 maipai / PushCards 两处字段说明同步。

测试:
- test_paiju 亮牌用例按新规则重写(54 checks)。新增两条针对性用例:
  「只含固定主牌·主花色普通牌未混入」与「同时满足多档仍只亮同一份」——
  前者正是这次范围变更最容易写错的地方。
- test_leak 增加亮牌可见性规则。关键点:期望集合【独立于 get_liangpai 重算】,
  而不是复用被测实现——否则实现若误塞非固定主牌,审计会跟着放行、抓不住。
  反向验证证实了这一点:故意让 get_liangpai 混入主花色普通牌后,审计确实报警。

发现并修复一处假绿:原 6 局随机牌序下庄家一次都没达到亮牌门槛,即
「下发面无越权泄露」对亮牌这条路径根本没走到。现追加换牌序的 4 局(保留
原 6 局覆盖不动),并加两条覆盖断言钉住「可查牌达标 ≥1 局」「不查牌达标
≥1 局」,防止以后再退化成碰巧没触发。反向验证:去掉不查牌门控后审计立即
报出 5 张越权牌。

待定:T-34 亮牌的展示时机(出牌前一次性弹出 / 随时可查)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-25 23:46:06 +08:00
co-authored by Claude Opus 5
parent dc9123da92
commit b98f58effc
6 changed files with 171 additions and 79 deletions
+21 -17
View File
@@ -56,12 +56,12 @@
| 术语 | 谁公开给谁 | 给的是什么 | 触发 | 界面位置 | 字段 |
| --- | --- | --- | --- | --- | --- |
| **亮牌** | 庄家 → 两个闲家 | **只有数量/结构** | 庄家埋牌后手牌达门槛(design §8.2) | **暂无**(T-30) | `liangpai` |
| **亮牌** | 庄家 → 两个闲家 | **具体牌面**(庄家全部固定主牌) | 庄家埋牌后固定主牌达门槛(design §8.2) | 遮罩面板,同明牌版式(§1.6) | `liangpai.cards` |
| **余主公示** | 全体 → 全体 | **只有数量**(剩余主牌数、主对数) | 任一玩家报无主(design §9) | 他家头像下 `主N` `对N` 角标(§2.5) | `seatlist[seat][4]`、`baozhu` |
| **明牌** | 他家 → 请求者 | **具体牌面** | 可查牌 + 无主,点按钮(design §9) | 遮罩面板(§1.7 D-6) | `mingpai.others[].zhucards` |
| **开底** | 桌面 → 所有玩家 | **具体牌面**(8 张底牌) | 70 分坐庄,**摸底之前** 3 秒(design §4) | 复用底牌区翻牌(§1.4 D-2) | `ancard3s` + `bottomcards` |
一句话记:**「亮牌」「余主公示」是统计类,「明牌」「开底」是牌面类**。
一句话记:**只有「余主公示」是统计类(给数字),「亮牌」「明牌」「开底」都给具体牌面**——区别在给谁的牌:亮牌给庄家自己的、明牌给他家的、开底给桌上那 8 张。
另有一组「底」字族专管发牌留桌的那 8 张牌:
@@ -586,22 +586,24 @@ EQW_RoomOptions = {
- **闲家**若收到 `liangpai`(仅可查牌模式 + 庄家达标),渲染 §2.5 亮牌信息条;
- 进入出牌,`seat` = 首出者(必为庄家)。
**亮牌信息条内容**(design §8.2,协议 `liangpai`):
**亮牌**(design §8.2,协议 `liangpai`):
| 字段 | 触发条件 | 展示 |
| --- | --- | --- |
| `zhu` / `zhupair` / `zhutuo` | 固定主牌(王+2+7)总数 ≥ 10 | 如 `12 张主,3 对主带 1 拖` |
| `wang` | 王 ≥ 3 | 如 `3 张王` |
| `qi` | 7 ≥ 6 | 如 `6 张 7` |
| `er` | 2 ≥ 6 | 如 `6 张 2` |
庄家埋牌后、出牌开始前,若手中**固定主牌**达门槛,就向两个闲家亮出**自己全部固定主牌的具体牌面**。
**文案(暂定)**:显示 **`x对 x主`** —— 即「对子数 + 主牌总数」,例如 `3对 12主`。
| 项 | 说明 |
| --- | --- |
| 触发门槛(任一) | 固定主牌总数 ≥10 / 王 ≥3 / 7 ≥6 / 2 ≥6 |
| 固定主牌 | 双王 + 全部花色的 2 + 全部花色的 7;**不含**主花色普通牌 A/K/Q/J/10/9/8/6/5 |
| 亮出内容 | `liangpai.cards`,已按主牌序排好。**固定的一份**,不随被哪条门槛触发而增减 |
| 叫分限制 | **无**,任何叫分档位都适用 |
| 查牌模式 | 仅可查牌模式下发;不查牌时闲家收不到该字段 |
| 谁能看 | 只有两个闲家收到(庄家自己的牌自己本来就看得见) |
- 取 `liangpai.zhupair`(对子数)与 `liangpai.zhu`(主牌总数)。这两项同属「固定主牌 ≥10 张」那一档,要么都有、要么都没有。
- 其余三档(`wang` / `qi` / `er`)与 `zhutuo`(拖拉机数)当前**不进文案**;服务端仍照常下发,前端先不渲染,后续要加时不必改协议。
- 若 `liangpai` 里没有 `zhu` / `zhupair`(庄家未达到「固定主牌 ≥10 张」这一档),**整条亮牌条不显示**。
**展示形式**:与**明牌**同一套版式(半透黑遮罩 + 一排牌,照 `算奖牌型显示.png`),只是这里只有一排(庄家的)。可与 §5.7b 的明牌面板复用同一套精灵与渲染,仅数据源不同。
> 暂定文案,正式稿到位后只改这一处模板。
**数量前端自己数**——协议不再下发 `zhu`/`zhupair`/`wang`/`qi`/`er` 等统计,需要显示「x 张王」之类就从 `cards` 里算。
> 【T-34】**展示时机待定**:出牌开始时一次性弹出、还是给个入口让闲家随时查看?前者需定自动关闭时长。
### 1.7 出牌对局 `chupai1` / `chupai2` / `chupai3` 【图:出牌.png / 出牌2.png】
@@ -937,7 +939,7 @@ EQW_RoomOptions = {
- 初始 `[-1,-1]` 时隐藏;一旦全场有人报无主,服务端整表刷新 `seatlist` 并下发,两家的角标同时出现。
- 不可查牌模式下**永不出现**。
> ⚠️ **「亮牌」(`liangpai`)目前没有界面位置**。它是 design §8.2 的规则——庄家埋牌后手牌达门槛时向**闲家**公开的统计(主牌总数/对子数/拖拉机数、王数、7 数、2 数),与上面两者都不是一回事。服务端照常下发,前端**当前不渲染**。展示位置待定,见 §7.2 **T-30**。
> **「亮牌」(`liangpai`)与上面两者都不是一回事**:它是 design §8.2 的规则——庄家达门槛时向**闲家**亮出自己**全部固定主牌的具体牌面**,用遮罩面板展示(§1.6),不是这里的统计条。
### 2.6 底栏 【图:全部】
@@ -1374,6 +1376,7 @@ for (var i = 0; i < cards.length; i++) {
- **出牌历史**:三家都显示,数据 = `pushlist` 摊平聚合到各家、按主牌序排序(§1.7 D-7)。
- **上一轮**:同一套精灵,数据只取 `pushlist` 末尾一项。
- **明牌**:只显示另两家,数据 = `mingpai.others[].zhucards`(§1.7 D-6)。
- **亮牌**:只显示一排(庄家的固定主牌),数据 = `liangpai.cards`(§1.6)。复用同一套遮罩 + 容器 + 牌模板,仅数据源与排数不同。
> 解散投票由平台提供(Layer 420),子游戏无需精灵。
@@ -1744,7 +1747,7 @@ codes/config/
| 编号 | 问题 | 影响 |
| --- | --- | --- |
| ~~T-9~~ | ~~亮牌条文案~~ | **已暂定**:自己的主牌统计条显示 `x对 x主`、有手牌时常显(见 §2.5)。注意这条**不是** design §8.2 的 `liangpai`,后者展示位置另见 **T-30** |
| ~~T-9~~ | ~~亮牌条文案~~ | **已定**:自己的主牌统计条显示 `x对 x主`、有手牌时常显(§2.5)。注意这条**不是** design §8.2 的亮牌 |
| **T-20** | **整套音效**:清单、是否需要语音包、是否分男女声、倒计时提示音从第几秒起 | §4 全节;**已明确「等待后续补充」** |
**已定论(27 项)**
@@ -1783,10 +1786,11 @@ codes/config/
| 编号 | 问题 | 影响 |
| --- | --- | --- |
| **T-30** | **亮牌**(`liangpai`,design §8.2)**当前没有界面位置**。要不要显示?显示在哪(庄家头像旁?闲家侧独立条?)? | 服务端照常下发,前端暂不渲染;确定后可能需新增一处 UI |
| ~~T-30~~ | ~~亮牌没有界面位置~~ | **已定**:亮牌改为下发庄家全部固定主牌的**具体牌面**,用与明牌相同的遮罩版式展示(§1.6)。**展示时机**(出牌前一次性弹出 / 可反复查看)仍待定 → 见 **T-34** |
| **T-31** | 大局结算面板的「基础分」与「总得分」两行分别对应什么?参考图两者数值相同(`基础分30`/`总得分30`),是 mock 巧合还是确有区别? | S-6 的字段定义 |
| **T-32** | `等待庄家选主.png` 里底牌仍摊着、同时提示「等待庄家选主」,但 design §4 的顺序是「公示 3 秒 → 庄家摸入手牌 → 选主」。是 mock 叠画,还是 70 分局底牌要摊到选主结束? | §1.4 底牌区的收起时机 |
| **T-33** | 「等待类」状态提示条的完整文案清单(各阶段分别显示什么) | §2.8 文案配置表 |
| **T-34** | **亮牌的展示时机**:出牌开始时一次性弹出(需定自动关闭时长),还是给闲家一个入口随时查看? | §1.6;影响是否要加一个入口按钮 |
#### T-5 手牌排序(已定)