二七王:确立「余主公示」「底牌公示」术语,核查「亮牌」冲突

术语决策:
- A 庄家手牌达门槛后公开数量/结构 → 仍叫「亮牌」(保持不变)
- B 有人报无主后展示各家剩余主牌数与对数 → 新术语「余主公示」
- C 70 分坐庄摸底牌前向全场亮 8 张底牌 3 秒 → 新术语「底牌公示」
- 「亮主」确认为选主界面的标题文案、不是规则术语,三份文档均注明不得
  用它指代任何规则

「亮牌」冲突核查结论:无同名不同义,但有三处字面相近而语义方向相反的
读错风险——亮牌 vs 明牌(一个给数量、一个给牌面,方向还相反)、亮牌 vs
亮主(只差一字且同在庄家阶段)、亮牌 vs「亮出底牌」。故在 design 术语表、
协议 §0.0b、前端清单 §0.0 各加一张四类「公开信息」对照表,一句话口诀:
「亮牌」「余主公示」只给数字,「明牌」「底牌公示」才给牌面。

design.md:术语表新增 亮牌 / 余主公示 / 明牌 / 底牌公示 四条定义 +
易混对照表;§4、§9、§12.1 正文启用新术语。
packet_protocol.md:新增 §0.0b 术语小节;seatlist 第 5 位、ancard3s、
baozhu 三处字段说明冠以对应术语。
前端清单:§0.0 补对照表,§2.5 改名为「自己的主牌统计 + 余主公示」。

另据新图 等待庄家选主.png 抽出一个通用部件「状态提示条」(§2.8):
深色半透条 + 居中白字,等待类(等待庄家选主…)与即时反馈类(强甩失败)
共用同一套精灵,只切位置预设与文案。原单列的 BAR_SHUAICUO 并入该部件。

新增 T-32(该图底牌仍摊着与 design §4 的先后顺序对不上,需确认)、
T-33(等待类文案清单待定)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-25 23:04:03 +08:00
co-authored by Claude Opus 5
parent be06d3bf58
commit 6ec6bdbbc2
4 changed files with 93 additions and 25 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

+53 -13
View File
@@ -6,7 +6,7 @@
>
> **权威源**:玩法规则以 `server/games/erqiwang/docs/design/design.md` 为准;下发字段以 `server/games/erqiwang/docs/protocol/packet_protocol.md` 为准;前端规范以 `docs/client/development-guide/` 为准。本文只做「规则/协议 → 界面资源」的映射,**不重新定义规则**。
>
> **参考图**:`./uiref/*.png`,共 15 张,设计分辨率 1280×720。
> **参考图**:`./uiref/*.png`,共 16 张,设计分辨率 1280×720。
---
@@ -52,6 +52,21 @@
> ✅ `design.md` 与 `packet_protocol.md` **已同步此变更**(S-5 完成),协议字段名也已拆分为 `bottomcards` / `burycards`(S-4 完成)。
#### 四类「公开信息」——名字像、含义差很远
| 术语 | 谁公开给谁 | 给的是什么 | 触发 | 界面位置 | 字段 |
| --- | --- | --- | --- | --- | --- |
| **亮牌** | 庄家 → 两个闲家 | **只有数量/结构** | 庄家埋牌后手牌达门槛(design §8.2) | **暂无**(T-30) | `liangpai` |
| **余主公示** | 全体 → 全体 | **只有数量**(剩余主牌数、主对数) | 任一玩家报无主(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` |
一句话记:**「亮牌」「余主公示」只给数字,「明牌」「底牌公示」才给牌面**。
> **「亮主」不是术语**——它是**选主界面的标题文案**(庄家选主牌花色那一步,见 `亮主.png`),与上表四项都无关。文档与代码里不要拿它指代任何规则。
>
> 另:**自己**的主牌统计条(手牌上方 `x对 x主`,§2.5)**不属于上表任何一项**——那是本地统计、始终显示,不涉及"公开"。
---
### 0.1 设计基准与座位映射
@@ -514,6 +529,10 @@ EQW_RoomOptions = {
| **70 分坐庄** | **全场三人都能看到** |
因此**不需要单独的「公示」面板**,只是同一套翻牌表现的可见范围不同——精灵复用 §5.3 群组 211(底牌区),无需新增。
【图:等待庄家选主.png】即闲家视角下的底牌公示:中央 8 张底牌翻正面摊开,下方一条 `等待庄家选主` 状态提示条(见 §2.8)。
> ⚠️ **T-32**:该图里底牌**仍摊着**、同时提示「等待庄家选主」。但 design §4 的顺序是「公示 3 秒 → 庄家摸入手牌 → 选主」——按此,选主阶段底牌应已被庄家摸走、不该还摊在桌面。是 mock 把两个状态画在一起,还是 70 分局的底牌要一直摊到庄家选完主?需确认。
- 上庄后统一更新:顶部信息条 `叫分` 列 = `grade`、角标 = `multiple`;`banker` 对应玩家位显示 **`庄` 印章**(含底栏自己位)。
- 三处 `庄` 印章是三个独立精灵(左上 / 右上 / 底栏),按 `banker` 显隐其一。
- **重连不重放**:协议明确 70 分的 3 秒亮牌是上庄时的一次性事件,`deskinfo` 重连**不重放**——前端不得在重连时补播。
@@ -646,14 +665,14 @@ EQW_RoomOptions = {
**甩错提示(D-3 已定)** 【图:强甩失败.png】:
- 收到 `shuaicuo === 1` 时,在桌面中央弹一条**深色半透条**:**`强甩失败`**(白字,x≈462 y≈172 w≈363 h≈50)。
- 收到 `shuaicuo === 1` 时,用**通用状态提示条**(§2.8)显示 **`强甩失败`**,取「即时反馈类」位置预设。
- **不做收回动画**——甩出的牌不演"飞回手里",直接按服务端下发的 `cards`(那张被强制打出的最小主牌单张)落牌即可。
- 提示条自动淡出,时长进配置。
**报无主(D-4 已定)**:
**报无主 → 余主公示(D-4 已定)**:
- **不做全场提示**。报无主本身没有独立的提示表现。
- 唯一的界面变化是:**他家的 `主N` / `对N` 角标出现**(服务端 `baozhu=1` 并整表刷新 `seatlist`,仅可查牌模式)。详见 §2.5。
- 唯一的界面变化是**余主公示**生效:他家的 `主N` / `对N` 角标出现(服务端 `baozhu=1` 并整表刷新 `seatlist`,仅可查牌模式)。详见 §2.5。
- 自己的主牌统计条**本来就一直显示**,不因报无主而变化。
**明牌**(design §9.3):
@@ -888,14 +907,14 @@ EQW_RoomOptions = {
- **归零后停在 `0` 继续显示,不隐藏**:协议 §0.3 明确归零不触发任何动作、牌局原地等待该玩家;隐藏会被误读为「已超时/已跳过」。
- 精灵:群组 224,号段 1150–1159。
### 2.5 主牌统计(自己)+ 报无主标签(他家)【图:多张】
### 2.5 自己的主牌统计 + 余主公示(他家)【图:多张】
**这是两套不同的东西,别混为一谈**:
| 谁的 | 显示在 | 何时显示 | 数据来源 |
| --- | --- | --- | --- |
| **自己的主牌统计** | 手牌**上方偏左**(x≈35 y≈400 那条) | **有手牌时始终显示**,与报无主无关 | 前端据 `flower` 本地统计自己手牌 |
| **他家的主牌数 / 对数** | 左上、右上家**头像下方**的 `主N` `对N` 角标 | **仅可查牌模式 + 已报无主**(design §9) | `seatlist[seat][4]` = `[剩余主牌数, 剩余主对数]` |
| **他家的主牌数 / 对数**(**余主公示**) | 左上、右上家**头像下方**的 `主N` `对N` 角标 | **仅可查牌模式 + 已报无主**(design §9) | `seatlist[seat][4]` = `[剩余主牌数, 剩余主对数]` |
**自己的主牌统计条**(群组 206):
@@ -903,13 +922,13 @@ EQW_RoomOptions = {
- **始终显示、本地计算**——自己的手牌自己完全可见,不需要服务端下发,也不受查牌模式与报无主影响。
- 参考图里的 `主牌对子: 1对` 即此条。
**他家的 `主N` / `对N` 角标**(群组 202 / 203,结构见 §2.2):
**余主公示:他家的 `主N` / `对N` 角标**(群组 202 / 203,结构见 §2.2):
- 一个**图片底 + 一个文字精灵**,两家各一组。
- 初始 `[-1,-1]` 时隐藏;一旦全场有人报无主,服务端整表刷新 `seatlist` 并下发,两家的角标同时出现。
- 不可查牌模式下**永不出现**。
> ⚠️ **协议里的 `liangpai` 字段目前没有对应的界面位置**。它是 design §8.2 的「庄家亮牌」——庄家埋牌后手牌达标时向**闲家**亮出的统计(主牌总数/对子数/拖拉机数、王数、7 数、2 数),与上面两者都不是一回事。服务端照常下发,前端**当前不渲染**。展示位置待定,见 §7.2 **T-30**。
> ⚠️ **「亮牌」(`liangpai`)目前没有界面位置**。它是 design §8.2 的规则——庄家埋牌后手牌达门槛时向**闲家**公开的统计(主牌总数/对子数/拖拉机数、王数、7 数、2 数),与上面两者都不是一回事。服务端照常下发,前端**当前不渲染**。展示位置待定,见 §7.2 **T-30**。
### 2.6 底栏 【图:全部】
@@ -966,6 +985,22 @@ y≈648–720 深色条。左侧头像/昵称/分数由平台渲染(§0.2)
- 牌上标记(`拖` 圆标、⭐、🔵)见 T-8。
- 精灵:群组 210,号段 1200–1249。
### 2.8 状态提示条(通用)【图:等待庄家选主.png / 强甩失败提示.png】
一条**深色半透圆角条 + 居中白字**,用于显示当前在等谁、或一次性的即时反馈。整个牌局复用**同一个**精灵,只换文字与位置。
| 用途 | 文案示例 | 位置(实测估值) |
| --- | --- | --- |
| **等待类**(常驻到状态结束) | `等待庄家选主`、`等待庄家埋牌`、`等待XX叫分` | 桌面中央 x≈500 y≈373 w≈320 h≈47 |
| **即时反馈类**(自动淡出) | `强甩失败` | 桌面中央偏上 x≈462 y≈172 w≈363 h≈50 |
- 两类**共用一套精灵**(`BAR_TOAST` + 文字精灵),位置由布局配置的两个预设切换。
- 文案表进配置,不在代码里写死字符串。
- 精灵:图层 105 群组 230,`1760` 条底 + `1761` 文字。
- 【T-33】等待类提示条的完整文案清单(各阶段分别显示什么)待定;即时反馈类目前只有 `强甩失败` 一条。
> 原 §5.5 的 `BAR_SHUAICUO`(1754/1759)并入本部件——甩错只是这条通用提示条的一种文案,不必单独出图。
---
## 3. 图片资源总表
@@ -1063,7 +1098,7 @@ y≈648–720 深色条。左侧头像/昵称/分数由平台渲染(§0.2)
| --- | --- | --- | --- | --- | --- |
| 651 | `BUBBLE_TISHI` | 踩 / 没分 / 有分 提示气泡 | **6**(3×2) | **帧1=踩·箭头向左 帧2=没分·箭头向左 帧3=有分·箭头向左 帧4=踩·箭头向右 帧5=没分·箭头向右 帧6=有分·箭头向右**。帧序内层是 `tip`(1踩/2没分/3有分)、外层是箭头朝向 → `frame = (arrowRight ? 3 : 0) + tip`。**箭头向左 = 头像在气泡左侧**、箭头向右 = 头像在气泡右侧 | 待定 |
| ~~652~~ | ~~`TXT_BAOZHU`~~ | **不需要**:报无主不做全场提示(D-4),只让他家 `主N`/`对N` 角标出现 | —— | —— | —— |
| 653 | `BAR_SHUAICUO` | **`强甩失败`** 提示条底(深色半透,白字居中) | 1 | 深色半透圆角条,文字用文字精灵 | 363 × 50 |
| 653 | `BAR_TOAST` | **通用状态提示条**底(深色半透圆角,白字居中)——`等待庄家选主` / `强甩失败` 等共用(§2.8) | 1 | 可九宫拉伸,按文案长度变宽 | 363 × 50 |
| 654 | `TXT_GRADE_FLOAT` | 捡分飘字底(`20分` 金色) | 1 | 待定 | 待定 |
| ~~655~~ | ~~`PANEL_BOTTOM_3S`~~ | **不需要**:底牌 3 秒展示复用庄家翻底牌那套 UI(D-2),仅可见范围不同 | —— | —— | —— |
@@ -1211,8 +1246,9 @@ design 与协议均**未定义任何音效**。以下是按牌类游戏常规推
| --- | --- | --- | --- | --- |
| 1750–1752 | `BUBBLE_TISHI_LEFT/RIGHT/SELF` | 图片 ×3 | 踩/没分/有分 气泡(按发送者位置) | `BUBBLE_TISHI` 帧 = tip |
| ~~1753~~ | ~~`TXT_BAOZHU`~~ | —— | **不需要**(D-4) | —— |
| 1754 | `BAR_SHUAICUO` | 图片 | `强甩失败` 提示条底 | `BAR_SHUAICUO` |
| 1759 | `TXT_SHUAICUO` | 文字 | `强甩失败` 文案 | —— |
| ~~1754 / 1759~~ | ~~`BAR_SHUAICUO`~~ | —— | 并入下方通用状态提示条 | —— |
| 1760 | `BAR_TOAST` | 图片 | 通用状态提示条底(§2.8) | `BAR_TOAST` |
| 1761 | `TXT_TOAST` | 文字 | 提示文案(等待类 / 即时反馈类共用) | —— |
| 1755 | `GRADE_FLOAT_BG` | 图片 | 捡分飘字底 | `TXT_GRADE_FLOAT` |
| 1756 | `GRADE_FLOAT_TEXT` | 文字 | `20分` | —— |
| ~~1757 / 1758~~ | ~~`BOTTOM_3S_*`~~ | —— | **不需要**(D-2:底牌 3 秒展示复用底牌区翻牌,仅可见范围不同) | —— |
@@ -1590,6 +1626,8 @@ CARD_SIZE: {
| 埋牌 · 操作条 | `line` + `items` | `direction:horizontal anchorX:640 anchorY:165 itemHeight:63 spacing:45 anchor:center`,`items:[180,60,180]`(提示 / 倒计时 / 埋牌) |
| 出牌 · 操作条 | `line` + `items` | `direction:horizontal anchorX:640 anchorY:345 itemHeight:55 spacing:35 anchor:center`,`items:[75,157]`(倒计时 / 出牌) |
| 捡分飘字 | `point` | `x:570 y:180 w:170 h:55`;另配 `floatRise:-60`、`floatDuration:800`(动画参数也进配置) |
| 状态提示条 · 等待类 | `point` | `x:500 y:373 w:320 h:47`(§2.8) |
| 状态提示条 · 即时反馈类 | `point` | `x:462 y:172 w:363 h:50`;另配 `toastDuration:1500` |
### 6.9 结算区配置
@@ -1736,8 +1774,10 @@ codes/config/
| 编号 | 问题 | 影响 |
| --- | --- | --- |
| **T-30** | 协议 `liangpai`(design §8.2 庄家亮牌:主牌总数/对子数/拖拉机数、王数、7 数、2 数)**当前没有界面位置**。要不要显示?显示在哪(庄家头像旁?闲家侧的独立条?)? | 服务端照常下发,前端暂不渲染;确定后可能需新增一处 UI |
| **T-30** | **亮牌**(`liangpai`,design §8.2)**当前没有界面位置**。要不要显示?显示在哪(庄家头像旁?闲家侧独立条?)? | 服务端照常下发,前端暂不渲染;确定后可能需新增一处 UI |
| **T-31** | 大局结算面板的「基础分」与「总得分」两行分别对应什么?参考图两者数值相同(`基础分30`/`总得分30`),是 mock 巧合还是确有区别? | S-6 的字段定义 |
| **T-32** | `等待庄家选主.png` 里底牌仍摊着、同时提示「等待庄家选主」,但 design §4 的顺序是「公示 3 秒 → 庄家摸入手牌 → 选主」。是 mock 叠画,还是 70 分局底牌要摊到选主结束? | §1.4 底牌区的收起时机 |
| **T-33** | 「等待类」状态提示条的完整文案清单(各阶段分别显示什么) | §2.8 文案配置表 |
#### T-5 手牌排序(已定)
@@ -1940,7 +1980,7 @@ data.bottom.cards // 结算包
| `server/games/erqiwang/docs/design/design.md` | **玩法规则权威源**。本文引用其条款,不重新定义规则;术语「底牌 / 埋牌底牌」已同步(见 §0.0) |
| `server/games/erqiwang/docs/protocol/packet_protocol.md` | **协议字段权威源**。本文的「渲染什么」全部溯源到具体字段 |
| `docs/client/development-guide/` | **前端规范权威源**。ID 范围、组件范式、红线均以其为准 |
| `docs_dev/uiref/*.png` | 参考图,15 张(牌桌态 + 叫分按钮面板 + 大局结算 + 强甩失败 + 1 张建房**样式范式**,末者内容属他游戏、不可照抄) |
| `docs_dev/uiref/*.png` | 参考图,16 张(牌桌态 + 叫分按钮面板 + 大局结算 + 强甩失败 + 等待庄家选主 + 1 张建房**样式范式**,末者内容属他游戏、不可照抄) |
| `client/js/gameabc-framework/ui/AlignmentUtils.js` | **布局求解的框架能力**。§6 的配置参数名与其入参一一对应,配置可原样喂入 |
| `client/js/gameabc-framework/ui/SpriteCopyUtils.js` | 精灵复制。用于算奖牌型、大局结算玩家栏、出牌历史 / 明牌(§5.6a 判据表) |
| `client/js/gameabc-framework/templates/*.template.js` | 常量文件写法蓝本。本清单落地为常量文件时按其格式 |
+21 -5
View File
@@ -47,6 +47,10 @@
| 埋牌 | 庄家看到底牌、摸起查看后,从手牌中选出 8 张重新扣下,作为"埋牌底牌" |
| 捡分 | 出牌中赢下的分牌(5、10、K)计入闲家总得分的过程 |
| 扣底 | 出完所有手牌后的最后一轮,若被闲家用主牌牌型压过庄家,则埋下的 8 张埋牌底牌也计入闲家捡分,并按牌型翻倍 |
| 亮牌 | 庄家埋牌后手牌达到门槛(固定主牌 ≥10 / 王 ≥3 / 7 ≥6 / 2 ≥6)时,向两个闲家公开对应的**数量与结构**统计——**只亮数量 / 结构,不亮具体是哪几张牌**(见第 8.2 节)|
| 余主公示 | 任一玩家主牌出空(报无主)后,为**全体三人**展示另外两家各自的**剩余主牌数与剩余主对数**(见第 9 节)。只给数量,不给具体牌面 |
| 明牌 | 可查牌模式下,查看另外两家手中**全部未出主牌的具体牌面**(见第 9 节)。与"亮牌""余主公示"只给数量不同,明牌给的是具体牌 |
| 底牌公示 | 70 分坐庄时,在庄家摸底牌之前,把那 8 张底牌向**所有玩家**亮出 3 秒(见第 4 节)。给的是具体牌面 |
| 拖拉机 | 同一花色(含主牌)里点数相邻的连续对子,如 K K Q Q 为"两托"(两连对) |
| 甩牌 | 首家出牌时,一次性打出多组主牌组合(单张 / 对子 / 拖拉机自由搭配);仅主牌可以甩牌,副牌禁止甩牌,只能分单张 / 对子 / 拖拉机依次打出(见第 5.4 节) |
| 毙牌 | 跟牌时手中没有本轮花色(缺门),改用主牌打出、且牌面大过本轮目前所有人的牌(见第 5.1 / 5.2 节) |
@@ -63,6 +67,18 @@
>
> **本文已全文改用新术语。** 但 `docs/protocol/packet_protocol.md` 与服务端代码里的 `bottomcards` 字段名**尚未拆分**——两批牌目前仍共用这一个字段名,只靠「出现在哪个包」区分语义:`shangzhuang` / `ChooseMain` / `BuryCards` 里的是**底牌**,`maipai` / `PushCards` / 结算 `bottom` 分组里的是**埋牌底牌**。拆分计划见 `docs_dev/二七王-UI资源与精灵清单.md` §7.5 的 S-4。
> **易混术语对照(都带"亮/明"字,但方向与粒度各不相同,务必分清)**:
>
> | 术语 | 谁公开给谁 | 给的是什么 | 触发条件 | 协议字段 |
> | --- | --- | --- | --- | --- |
> | **亮牌** | 庄家 → 两个闲家 | **只有数量/结构** | 庄家埋牌后手牌达门槛(§8.2) | `liangpai` |
> | **余主公示** | 全体 → 全体 | **只有数量**(剩余主牌数、主对数) | 任一玩家报无主(§9) | `seatlist[seat][4]` + `baozhu` |
> | **明牌** | 他家 → 请求者 | **具体牌面**(他家全部未出主牌) | 可查牌 + 报无主,主动点击(§9) | `mingpai.others[].zhucards` |
> | **底牌公示** | 桌面 → 所有玩家 | **具体牌面**(8 张底牌) | 70 分坐庄,摸底牌前 3 秒(§4) | `ancard3s` + `bottomcards` |
>
> 一句话记:**「亮牌」「余主公示」只给数字,「明牌」「底牌公示」才给牌面**。
> 另注:**「亮主」不是本文档的术语**——它是前端选主界面的标题文案(庄家选主牌花色那一步),与上表四项无关。
---
## 2. 牌局构成
@@ -111,7 +127,7 @@
- 若一家叫分后,另外两家都选择"不叫",则该叫分玩家成为本局庄家。
3. 庄家确定后摸底牌(摸完后庄家共 36 张):
- **非 70 分坐庄**:桌面 8 张底牌**只有庄家可见**,庄家查看后摸入手牌。
- **70 分坐庄**:在庄家摸底牌**之前**,先把这 8 张底牌**向所有玩家(含两个闲家)亮出 3 秒**,然后才由庄家把它们摸入手牌。
- **70 分坐庄**(触发**底牌公示**):在庄家摸底牌**之前**,先把这 8 张底牌**向所有玩家(含两个闲家)亮出 3 秒**,然后才由庄家把它们摸入手牌。
4. **选主 / 投降(同一决策点,二选一,互斥)**:
- **选主**:庄家在 4 个花色中选定一个作为本局主牌(见第 3 节)→ 进入下一步埋牌、随后出牌。
- **投降**:仅当**叫分为 70 分**时,此决策点才额外提供"投降"选项;选择投降表示放弃本局,**直接结束、不再选主、不埋牌、不出牌**,按 7.1 节"70 分坐庄 · 投降"的固定结果结算(基础子数 1 个,庄家直接输;算奖仍照常,见 8.4 节)。选主与投降互斥——**选了花色就等于放弃投降、正常打牌;选了投降就不再选主**。
@@ -645,13 +661,13 @@ A - K - Q - J - 10 - 9 - 8 - 6 - 5
- **可查牌模式**(四项功能全部提供):
1. **出牌历史**:当前牌局中,所有玩家已经打出的牌(含之前每一轮打出、已被收走的牌),任何时候都可以回看。
2. 一旦有玩家的主牌全部打空(即 5.4.2 节所说的"报无主"状态;"主牌"指大王、小王、所有花色的 2、所有花色的 7,以及主花色的其余普通牌,见第 3 节),系统就为**全体三人**(含刚刚报无主的这位玩家自己)显示另外两家各自的主牌数量、以及这些主牌里有多少对子。
2. **余主公示**:一旦有玩家的主牌全部打空(即 5.4.2 节所说的"报无主"状态;"主牌"指大王、小王、所有花色的 2、所有花色的 7,以及主花色的其余普通牌,见第 3 节),系统就为**全体三人**(含刚刚报无主的这位玩家自己)显示另外两家各自的主牌数量、以及这些主牌里有多少对子。**只给数量、不给具体牌面**——要看具体牌面是下一条的"明牌"。
3. 同时界面上会出现一个"明牌"按钮:点击后可以查看另外两家手中全部主牌的**具体牌面**(不只是数量 / 对子结构),再点一次取消查看、恢复隐藏。
4. 庄家若触发了 8.2 节的"亮牌要求",两个闲家可以看到对应的统计信息(只亮数量 / 结构,不亮具体牌面,见 8.2 节)。
- **不可查牌模式**:以上四项**一项都不提供**——
- **不提供出牌历史**:之前各轮打出过什么牌一律不能回看,只能靠玩家自己记牌;
- 即使有玩家报无主,也不会显示任何人的主牌数量、对子结构,也没有"明牌"按钮;
- **不提供余主公示**:即使有玩家报无主,也不会显示任何人的主牌数量、对子结构,也没有"明牌"按钮;
- 庄家即使触发了 8.2 节的亮牌条件,闲家也看不到相应的统计信息(见 8.2 节)。
> **"查牌"与"当前这一轮桌面上的牌"是两回事**:本轮已经出过牌的玩家、打在桌面上的这几张牌,**两种模式下都必须对全体可见**——否则后出的人无从跟牌、也无从判断本轮谁最大。查牌模式管的是**已经收走的往轮牌**与**他家手牌信息**能不能回看,不影响当前这一轮的正常出牌展示(断线重连回到牌桌时同理:当前轮桌面上的牌照常恢复,往轮历史则按本节的模式开关决定给不给)。
@@ -704,7 +720,7 @@ A - K - Q - J - 10 - 9 - 8 - 6 - 5
3. **叫分坐庄**(4.2):由暂定庄家起、按逆时针依次叫分。暂定庄家必叫(5~70 分、步进 5,不能"不叫");其后每家只能叫比当前更低的分,或选择"不叫";有人叫出 5 分即立即坐庄,或一家叫分后另外两家都"不叫"也即坐庄。叫分越低表示庄家对"压住闲家捡分"越有信心,对应的基础子数越高(第 7 节)。
4. **看底牌**:庄家坐定后摸底牌(摸完共 36 张)。非 70 分:8 张底牌仅庄家可见。**70 分坐庄:庄家摸底牌之前,先把这 8 张底牌向所有玩家亮 3 秒,再由庄家摸入手牌**(4.4 / 第 4 节)。
4. **看底牌**:庄家坐定后摸底牌(摸完共 36 张)。非 70 分:8 张底牌仅庄家可见。**70 分坐庄触发「底牌公示」:庄家摸底牌之前,先把这 8 张底牌向所有玩家亮 3 秒,再由庄家摸入手牌**(4.4 / 第 4 节)。
5. **选主 / 投降(同一决策点,二选一,互斥)**(第 4 节):
- **选主**:庄家选定一门花色为本局主牌(大王、小王、所有花色的 2、7 恒为主牌)→ 进入下一步埋牌。前端此阶段每个花色按钮上要显示该花色在庄家手中的对子数;70 分坐庄时并列显示投降按钮。
@@ -718,7 +734,7 @@ A - K - Q - J - 10 - 9 - 8 - 6 - 5
- 首家出什么花色 / 牌型,其余两家按 5.1~5.3 跟牌(同花色不够时可用主牌"毙牌"抢权,或"垫牌"不争)。
- 首家出主牌时可"甩牌"(5.4):一次性打出多组主牌组合;服务端按全场手牌判定"最大性",甩错则按 5.4.5 收回、只强制打出最小一张。副牌一律不能甩。
- 每轮比大小定出胜者:闲家赢下的那一轮,牌面上的分牌(5→5 分、10→10 分、K→10 分)计入闲家捡分;庄家赢的轮分牌作废(6.1~6.2)。
- 过程中:有玩家主牌出空需"报无主",可查牌模式下为全体展示他家主牌数量 / 对子结构(第 9 节);庄家手牌达到 8.2 的门槛时触发"亮牌"。
- 过程中:有玩家主牌出空需"报无主",可查牌模式下触发**余主公示**(为全体展示他家主牌数量 / 对子结构,第 9 节);庄家手牌达到 8.2 的门槛时触发**亮牌**。
8. **末轮扣底**(6.3):所有手牌出完后,若最后一轮由闲家**用主牌**赢下,则庄家埋的 8 张埋牌底牌翻开,其中的分按闲家赢牌的牌型翻倍(单张 ×1、主对 ×2、N 连对 ×2N)后计入闲家捡分。
@@ -25,6 +25,18 @@
同一个包里不会同时出现这两个字段。**下发面**:`burycards` 与 `bottomcards`(非 70 分时)都**只发给庄家**,闲家两者皆无——已由 `test/test_leak.js` 的泄露审计覆盖。
### 0.0b 四类「公开信息」术语(都带亮/明字,别读混)
| 术语 | 谁公开给谁 | 给的是什么 | 触发 | 本文相关字段 |
| --- | --- | --- | --- | --- |
| **亮牌** | 庄家 → 两个闲家 | **只有数量/结构** | 庄家埋牌后手牌达门槛(design §8.2) | `liangpai` |
| **余主公示** | 全体 → 全体 | **只有数量**(剩余主牌数、主对数) | 任一玩家报无主(design §9) | `seatlist[seat][4]`、`baozhu` |
| **明牌** | 他家 → 请求者 | **具体牌面**(他家全部未出主牌) | 可查牌 + 报无主,主动点击(design §9) | `mingpai.others[].zhucards` |
| **底牌公示** | 桌面 → 所有玩家 | **具体牌面**(8 张底牌) | 70 分坐庄,摸底牌前 3 秒(design §4) | `ancard3s` + `bottomcards` |
一句话记:**「亮牌」「余主公示」只给数字,「明牌」「底牌公示」才给牌面**。
(「亮主」不是术语,是前端选主界面的标题文案,与上表无关。)
### 0.1 成败标志 `data.success`
**每一个「服务器 → 客户端」的包,`data` 都必带 `success`**(布尔):
@@ -157,7 +169,7 @@
| grade | 整数 | 庄家的叫分 |
| multiple | 整数 | 叫分对应的基础子数 `get_base_bycall(call, climb)`,**随房间「爬坡」开关取值**(roomtype 位3):常规算子 65→2 60→3 55→4 50及以下→6;爬坡 65→2 60→3 55→4 50→6 45→7 40→8 35→9 30→10 25→11 20→12 15→13 10→14 5→15;两种模式下 70→2;无叫分→0。与结算包 `aset.multiple` 同源同值(design §7.1/§7.3.1)|
| bottomcards | 数组 | 8 张**底牌**(发牌时没发给玩家、扣在桌面的 8 张)。**庄家恒有**;**闲家仅当 70 分坐庄时才有**(供 3 秒亮牌用),非 70 分时闲家没有该属性(底牌只有庄家可见,design §4)|
| ancard3s | 整数 | 仅 70 分坐庄时出现且为 `1`:表示庄家把底牌摸入手前,需将 `bottomcards` 这 8 张**底牌**向所有玩家亮出 3 秒(design §4/§7.1);非 70 分无此属性 |
| ancard3s | 整数 | **底牌公示**标志。仅 70 分坐庄时出现且为 `1`:表示庄家把底牌摸入手前,需将 `bottomcards` 这 8 张**底牌**向所有玩家亮出 3 秒(design §4/§7.1);非 70 分无此属性 |
| cards | 数组 | 拿了底牌后手上的牌(36 张,含底牌),庄家才有此属性,闲家没有该属性 |
| countdown | 整数 | 选主倒计时 |
| touxiang | 整数 | 是否允许投降 0:不允许 1:允许(仅 70 分坐庄为 1)。投降与选主互斥、同为选主阶段(step2)的决策,见 touxiang 包与 design §4 |
@@ -260,14 +272,14 @@
| seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 实际打出的牌id列表;**甩错时**(见 `shuaicuo`)为被强制打出的那一张最小主牌单张 |
| shuaicuo | 整数 | 甩错标志,仅甩错时出现且为 `1`(design §5.4.5:甩牌未通过最大性判定,整套甩牌收回,本轮只强制打出最小一张、失去本轮甩牌资格);正常出牌无此属性 |
| seatlist | 数组 | 三家座位牌况 `o_paiju.seatlist`(长度 3,下标 = 座位序号),**仅可查牌模式下发**(不查牌无此属性,design §9)。每个座位为 5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为报副情况 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`)。**一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位并整表下发**(design §9「为全体三人显示另外两家」),无需等另两家各自出牌才补。字段名与结构同重连包 `PushCards.seatlist` |
| seatlist | 数组 | 三家座位牌况 `o_paiju.seatlist`(长度 3,下标 = 座位序号),**仅可查牌模式下发**(不查牌无此属性,design §9)。每个座位为 5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为**余主公示**数据 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`,代码内旧称「报副」)。**一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位并整表下发**(design §9「为全体三人显示另外两家」),无需等另两家各自出牌才补。字段名与结构同重连包 `PushCards.seatlist` |
| count | 整数 | 出牌数量(甩错时为 1) |
| flower | 整数 | 出牌花色 |
| cardtype | 整数 | 出牌牌型:`>100` 单张(101 一张、102 两张…)、`>200` 对子(201 一对、202 两对…)、`>300` 拖拉机(302 两连对、303 三连对…),见 `class.pai.js` 顶部注释。**注意:cardtype 只能表达单一牌型**,而甩牌是单张/对子/拖拉机自由混搭(design §5.4.3),会被牌型推导压平成 1xx 或 2xx(例如「主K对 + 主5」得 103、「两连对 + 一散对」得 203)。**甩牌的真实结构请读 `shuai`,不要据 cardtype 反推** |
| shuai | json | 甩牌分量构成,**仅本次出牌是合法甩牌时才有**(非甩牌、以及甩错退化为单张时都没有该属性)。结构 `{ tractors: [连对数...], pairs: 独立对子数, singles: 单张数 }`,例如「主K对 + 主5」为 `{tractors:[],pairs:1,singles:1}`。与服务端跟牌时逐分量强制匹配用的 `shuai_demand` 同源(design §5.4.3/§5.4.4)|
| nextseat | 整数 | 下一个出牌者的位置序号 |
| countdown | 整数 | 下一个出牌者的出牌倒计时 |
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,供客户端展示他家主牌数量/对子结构并出现"明牌"按钮;**不查牌模式恒为 0**(design §9)|
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,是**余主公示**与"明牌"按钮的开关;**不查牌模式恒为 0**(design §9)|
| cardsinhand | 数组 | 出牌者出牌后手上剩下的牌id列表,只有出牌者才有此属性 |
| curmultiple | 整数 | **当前抓分倍数**(design §7.2.0):按当前累计捡分实时算出的判定倍率**绝对值**(3 大光 / 2 小光 / 1 过庄 / N 升 N 级)。与结算包 `aset.upgrade` 同源同算法,差别仅在此处**不含扣底**。三家同值,随本包下发、不另开推送 |
| mustcard | 数组 | **下一个出牌者本轮跟牌的必出牌**(design §5.2),供其客户端自动选中。**只发给 `nextseat` 那一家**,其余两家无此属性——它是该玩家自己手牌的子集,整表下发会泄露他家手牌结构。以下情形不下发:`nextseat` 是本轮首家、首家为**甩牌**(甩牌跟牌走逐分量匹配,见 design §5.4.4)、或算出的必出牌为空 |
@@ -282,10 +294,10 @@
| --- | --- | --- |
| seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 出的牌id列表 |
| seatlist | 数组 | 三家座位牌况 `o_paiju.seatlist`(长度 3,下标 = 座位序号),**仅可查牌模式下发**(不查牌无此属性,design §9)。每个座位为 5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为报副情况 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`)。**一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位并整表下发**(design §9「为全体三人显示另外两家」),无需等另两家各自出牌才补。字段名与结构同重连包 `PushCards.seatlist` |
| seatlist | 数组 | 三家座位牌况 `o_paiju.seatlist`(长度 3,下标 = 座位序号),**仅可查牌模式下发**(不查牌无此属性,design §9)。每个座位为 5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为**余主公示**数据 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`,代码内旧称「报副」)。**一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位并整表下发**(design §9「为全体三人显示另外两家」),无需等另两家各自出牌才补。字段名与结构同重连包 `PushCards.seatlist` |
| nextseat | 整数 | 下一个出牌者的位置序号 |
| countdown | 整数 | 出牌倒计时 |
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,供客户端展示他家主牌数量/对子结构并出现"明牌"按钮;**不查牌模式恒为 0**(design §9)|
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,是**余主公示**与"明牌"按钮的开关;**不查牌模式恒为 0**(design §9)|
| cardsinhand | 数组 | 出牌后出牌者手上剩下的牌id列表,只有出牌者才有此属性 |
| mustcard | 数组 | **下一个出牌者本轮跟牌的必出牌**(design §5.2),供其客户端自动选中。**只发给 `nextseat` 那一家**,其余两家无此属性——它是该玩家自己手牌的子集,整表下发会泄露他家手牌结构。以下情形不下发:`nextseat` 是本轮首家、首家为**甩牌**、或算出的必出牌为空 |
@@ -299,10 +311,10 @@
| --- | --- | --- |
| seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 出的牌id列表 |
| seatlist | 数组 | 三家座位牌况 `o_paiju.seatlist`(长度 3,下标 = 座位序号),**仅可查牌模式下发**(不查牌无此属性,design §9)。每个座位为 5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为报副情况 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`)。**一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位并整表下发**(design §9「为全体三人显示另外两家」),无需等另两家各自出牌才补。字段名与结构同重连包 `PushCards.seatlist` |
| seatlist | 数组 | 三家座位牌况 `o_paiju.seatlist`(长度 3,下标 = 座位序号),**仅可查牌模式下发**(不查牌无此属性,design §9)。每个座位为 5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为**余主公示**数据 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`,代码内旧称「报副」)。**一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位并整表下发**(design §9「为全体三人显示另外两家」),无需等另两家各自出牌才补。字段名与结构同重连包 `PushCards.seatlist` |
| nextseat | 整数 | 下一个出牌者的位置序号 |
| countdown | 整数 | 出牌倒计时 |
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,供客户端展示他家主牌数量/对子结构并出现"明牌"按钮;**不查牌模式恒为 0**(design §9)|
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,是**余主公示**与"明牌"按钮的开关;**不查牌模式恒为 0**(design §9)|
| cardsinhand | 数组 | 出牌后出牌者手上剩下的牌id列表,只有出牌者才有此属性 |
| maxseat | 整数 | 本轮出牌谁最大,只有本轮最后一个玩家出牌后才有此属性 |
| grade | 整数 | 本轮闲家得分,只有本轮最后一个玩家出牌后且闲家有得分才有此属性 |