Files
huajishe-tts/docs/heart/00-research.md
e2hang a4fd9ea8fa feat(pig): 拱猪完整实现(3/4 人)+ 修复联机手牌渲染
- engine: Pig 游戏(发牌/跟牌/赢墩/结算:猪羊变压器全红大满贯),每人均分独立 13 张手牌
- engine: playerView 为每个请求者注入各自 myHand,他家手牌剥除
- web: PigBoard UI(椭圆桌+环形座位+计分板),修复 realG 提取——myHand 在 board 回调顶层而非 .G 内,此前只房主看到牌
- web/test: 15 个单测;Playwright 4 人验证每人 13 张、共 52 张、互不重叠
- app/lobby/server: 拱猪进房间列表、座位选择 [3,4]、engineName GongZhu
2026-08-25 16:57:52 +08:00

193 lines
13 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.
# 拱猪Gong Zhu / Pig游戏调研报告
> 本文档为「在 tts-like 模拟器中实现拱猪」前的规则调研。
> 拱猪是中国流行的扑克游戏,由国外 "Black Lady / 黑桃皇后"(即 Windows 自带「红心大战」Hearts 的玩法)传入后本土化发展而来。
> 用户要求:**可 3 人玩,也可 4 人玩**,规则与红心大战很像。
> 以下内容综合百度百科、各游戏平台规则页、玩家社区资料整理,并标注了 3 人局的可行变体方案。
---
## 一、游戏定位与关系
- **拱猪 ≈ 红心大战Hearts的中国变体**。共同内核:
- 4 人、一副 52 张(无大小王)、每人 13 张。
- 目标都是**躲分**(红心为负分), tricks 中吃到的分牌累计。
- 跟牌必须跟同花色(无该花色可垫任意牌)。
- **与红心大战的关键差异**
| 维度 | 红心大战 (Hearts) | 拱猪 (Gong Zhu) |
|------|-------------------|------------------|
| 换牌pass 3 | 每局开局互相传 3 张 | **无换牌**,改为**亮牌(卖牌)**环节 |
| 负分牌 | 仅 13 张红心 | 红心 + **黑桃 Q-100** |
| 正分牌 | 无 | **方块 J+100** |
| 特殊牌 | 无 | **梅花 10变压器加倍** |
| 亮牌加倍 | 无 | 有(见下) |
| 首出限制 | 不能吃第一墩红心(除非手中只有红心) | 多数变体**无首出花色限制**,领出可任意花色 |
| 全收红心 | 全红 = 所有红心变正分(倒扣) | 全红 = +200亮牌则 +400 |
---
## 二、标准规则4 人,一副牌)
### 2.1 牌组与发牌
- 用去掉大小王后的 **52 张牌**4 人平分,**每人 13 张**。
- 点数大小递减A > K > Q > J > 10 > 9 > 8 > 7 > 6 > 5 > 4 > 3 > 2。
- 首局庄家随机;之后一般由**上一局吃到黑桃 Q的玩家**坐庄。
### 2.2 分牌与分值(亮牌前的基础分)
**16 张特殊牌**15 张计分页 + 1 张功能牌(变压器)。
| 牌 | 别称 | 基础分 |
|----|------|--------|
| ♥A | | **-50** |
| ♥K | | **-40** |
| ♥Q | | **-30** |
| ♥J | | **-20** |
| ♥10 / ♥9 / ♥8 / ♥7 / ♥6 / ♥5 | | 各 **-10** |
| ♥4 / ♥3 / ♥2 | | **0**(不计入负分,但属于"红心",影响全红判定) |
| ♠Q | **猪** | **-100**(游戏名"拱猪"的由来) |
| ♦J | **羊** | **+100** |
| ♣10 | **变压器 / 导板(double)** | 见 2.4 |
> 红心合计基础分 = -(50+40+30+20+6×10) = **-200 分**。
> 变体:部分规则把 ♥4 也记 -10、♥3/♥2 记 -3/-2使所有红心相加恰好 -200也有把 ♥2/3/4 都记 0 的简化版(如上表,推荐采用此简化版以贴合主流线上平台)。
### 2.3 亮牌(卖牌)机制
开局由庄家开始,每人可**自愿亮出**手中持有的以下牌之一或多张:
- **♥A 亮出**:所有红心牌分值 **×2**(亮牌后红心合计 -400
- **♠Q 亮出(卖猪)**:猪变为 **-200**。
- **♦J 亮出(卖羊)**:羊变为 **+200**。
- **♣10 亮出**:变压器由"×2"变为"×4"(见 2.4)。
亮牌限制(主流规则):**亮过的牌,在该花色第一次被领出时不能出**,除非手中该花色只剩这一张。
**首抓加倍(天亮/地亮)**:若发牌时抓到的**第一张**即可亮且当场亮出,效果再 ×2即 ♣10 亮牌=×4再首抓=×8其余亮牌×2 再首抓=×4。这是高阶变体初版实现可先不做。
### 2.4 变压器♣10的特殊作用
- 若玩家**只**吃到 ♣10、没吃到任何其他分牌 → 变压器单独计 **+50 分**。
- 若同时吃到其他分牌 → 变压器发生**加倍**作用:该玩家本副牌所有分(含正负、含亮牌翻倍后的结果)**整体 ×2**。
- 配合亮牌♣10 亮出后加倍倍数从 ×2 提升到 **×4**(若再首抓则 ×8
### 2.5 出牌流程
1. **亮牌阶段**:庄家起,每人决定是否亮牌(可亮多张)。
2. **首出**:由特定牌的持有者首出(见 2.6)。之后每轮由上一轮赢得 tricks 最大牌者领出。
3. **跟牌**:轮到出牌时,若手中有领出花色的牌,**必须跟该花色**;若无,可垫任意其他花色(垫牌不赢墩)。
4. **赢墩**:一轮中打出领出花色里点数最大者,赢得该轮所有分牌。
5. 直到 52 张全部出完,该局结束,进入结算。
### 2.6 首出牌规则(变体较多)
- **主流线上平台**:庄家首出,可出任意花色任意牌(无"红心未破不能领红心"限制)。
- 常见指定首牌:持有 **♣2** 者首出 ♣2JJ 比赛变体:由分数最低者首出且不必 ♣2。也有用 ♠2 / ♠3 作首牌的变体。
- **亮牌约束**:亮过的牌在对应花色第一次被领出时不可出(除非该花色仅此一张)。
### 2.7 结算(单副牌得分)
计算顺序(重要,避免歧义):
1. 先按各分牌基础分累加得 `S`(亮牌已使相应牌的基础分翻倍)。
2. 若吃到 ♣10 且还有其他分牌 → `S = S × 2`(亮 ♣10 则 ×4 / 首抓 ×8
3. 若**只**吃到 ♣10 → 该玩家得 **+50**。
**全红(收齐全部 13 张红心)**:所有红心由同一家吃齐 → 红心全部变正分,合计 **+200**(亮 ♥A 则 +400。注意全红只翻转红心不影响猪/羊/变压器本来的正负。
**大满贯(猪羊满圈)**:一家吃齐**全部 16 张分牌**(所有红心 + 猪 + 羊 + 变压器)→ 猪也变正分,总分 = (200 红心正分 + 100 羊 + 100 变压器翻倍基数) ×2 = **+800**;若所有可亮牌均被亮过则 ×4 = **+3200**。
### 2.8 多局累计与胜负
- 各局得分累加为累计分。拱猪是**负分越少越好**(红心大战同)。
- 常见结束条件:某人累计达到 **+1000 或 -1000** 判胜负;或约定固定局数后比低分。
- 奖励/惩罚(娱乐向,非规则必需):用鼻子拱出黑桃 Q、贴纸条、刮鼻子等。
---
## 三、3 人变体方案(用户明确要求支持)
标准 52 张牌 / 4 人 / 13 张是铁律;**3 人时如何分配牌没有统一标准规则**,需自行约定。调研到的可行方案如下,供实现时选定(建议初版采用方案 A
### 方案 A去牌法推荐最贴近 4 人逻辑)
- 去掉 **1 张**非分牌(通常为 ♦2 或任意一张低价值非分牌),剩 **51 张**3 人每人 **17 张**
- 所有分牌(猪/羊/变压器/红心)**原样保留**,分值不变。
- 首出规则同 4 人(庄家或指定牌首出)。
- **优点**:规则 100% 复用 4 人逻辑,仅发牌数变化;分牌体系不变,玩家认知成本低。
- **缺点**:每人 17 张略多于 13但 tricks 数自然为 17 墩,无影响。
### 方案 B完整 52 张 / 轮空(发牌留底)
- 仍用 52 张,每家 17 张 + 留 1 张底牌(或不发,每轮某人轮空)。
- 复杂度高,**不推荐**。
### 方案 C去多张法某些民间 3 人玩法)
- 去掉 ♠2、♣2 等若干低牌,使 52 - k 能被 3 整除(如去 4 张 → 48 张 / 16 每人为常见)。
- 需确保**关键分牌♠Q/♦J/♣10/♥A不被误删**。
### 3 人局的额外设计决策(需与用户确认或默认)
1. **首出指定牌**3 人时仍可用 ♣2 持有者首出;若 ♣2 被去掉(方案 C改由**庄家首出**或**上局猪主首出**。
2. **全红判定**:红心共 13 张3 人时仍可能由一人吃齐,规则同 4 人(+200 / 亮 +400
3. **大满贯判定**16 张分牌由一人吃齐,规则同 4 人。
> 结论3 人支持的最佳实现路径是**参数化发牌张数 + 可选去牌列表**,分牌分值表与亮牌/变压器/全红/满贯逻辑完全共用 4 人代码。
---
## 四、与本项目已有 Holdem 实现的对照(架构提示)
- Holdem 用 boardgame.io 的 `Game({ setup, moves, phases, playerView })`,拱猪可同样建模:
- `setup`: 洗牌发牌(按人数 3/4 决定去牌与每人张数)。
- **阶段**`expose`(亮牌)→ `play`(出牌 13/17 墩)→ `score`(结算)。
- **moves**: `expose(card)`(亮牌)、`playCard(card)`(跟/领牌,带跟牌校验)、`pass`(无合法牌时无需,拱猪无 pass
- **状态**: `G.hands[pid]``G.currentTrick``G.leadSuit``G.taken[pid]`(各家吃到的牌,用于结算)、`G.exposed`(已亮牌集合)、`G.scores[pid]`(累计)。
- **结算**: 一局结束 `onEnd``play` 末墩后计算单局分写入 `G.scores`,并提供"下一局"。
- 与 Holdem 不同:**拱猪是合作躲分 + 个人计分**,无公共筹码池、无下注阶段;`playerView` 仍可隐藏他家手牌,但 tricks 公开可见符合真实玩法。
---
## 五、已确认的设计决策用户拍板2026-08-25
1. **3 人去牌方案(已澄清)**3 人局**去掉 ♣2**1 张非分牌),**保留 ♣3**,剩 **51 张**3 人每人 **17 张**51 ÷ 3 = 17整除无矛盾
- 即 4 人 = 52 张 / 13 每人3 人 = 51 张 / 17 每人(去 ♣2
2. **首出牌规则(已澄清)**
- **第一局**4 人局 = 持有 **♣2** 者首出 ♣2**3 人局 = 持有 ♣3 者首出 ♣3**(因 ♣2 已去掉,改用保留的 ♣3 作首牌)。
- **第二局起**:按出牌顺序(逆时针),由**上一局首出者的下一位玩家**首出,且**不再强制特定牌**(可出任意牌)。首出权随局轮转。
3. **亮牌功能****不做**。所有分牌按基础分计算,无翻倍/卖牌机制。变压器 ♣10 仅保留"单独 +50 / 同吃其他分牌则 ×2"的基础规则(不含亮牌加成)。
4. **红心 2/3/4 分值**:确认均为 **0 分**(主流简化版),全红仍须集齐全部 13 张红心。
5. **结束条件****无结束条件**。对局连续进行,每局结束自动进入下一局,累计分持续累加,玩家自行决定是否继续。
6. **单房间人数**:创建房间时由房主选择 **3 人或 4 人**(类似 Holdem 的 numPlayers 选项)。
**新增需求 — 计分板(榜)**
- 需要一个**计分板 UI**类似排行榜Leaderboard
- **4 人局**:对家为队友(南-北一组、东-西一组),计分板需体现**组队关系**——既显示每人单局分/总分,也显示两队总分(两组各自成员分数相加)。
- **3 人局**:各自为战,计分板显示每人单局分 + 累计总分,无组队。
- 计分板内容:
- 每位玩家:**本局得分**、**累计总分**、4 人时)**所属队伍**。
- 每局结束后刷新本局分;总分跨局累加。
- 视觉上做成"榜"——按总分排序(低分在前,因拱猪分越低越好),高亮当前玩家。
---
## 六、实现规划提示(供 EnterPlanMode 参考)
### 6.1 引擎 `packages/engine/src/games/pig.ts`
- `setup({ numPlayers })`:洗 52 张牌4 人每人 13 张;**3 人去掉 ♣2 后 51 张,每人 17 张**。
- 阶段:`lead`(首出权决定)→ `play`出牌N 墩)→ `score`(结算单局)。
- moves`playCard(card)`(校验跟牌/领出)、`nextRound()`(进入下一局,重洗重发)。
- 状态:`G.hands[pid]``G.currentTrick``G.leadSuit``G.leadPlayer``G.taken[pid]: Card[]``G.scores[pid]`(累计)、`G.lastRoundScores[pid]`(本局)、`G.round`(局数)、`G.teams`4 人时固定对家分组)。
- 结算函数 `scoreRound(G)`:按第五节分值表算每家单局分 → 写入 `lastRoundScores` 并累加 `scores`
- 首出权:`G.firstLeader` 首局 = ♣2 持有者4 人)/ 庄家3 人);之后 = 上局首出者下家。
- `playerView`隐藏他家手牌tricks 公开。
### 6.2 UI `apps/web/src/PigBoard.tsx` + 计分板
- 椭圆桌 + N 座位环形分布(复用 HoldemBoard 的 `seatPos` 思路)。
- 中央显示当前 trick 与领出花色;手牌区可点击出牌。
- **`<Scoreboard>` 组件**表格式榜4 人显示队伍列 + 每人行按总分升序3 人仅个人列。每局结束弹出/常驻展示本局分与总分。
### 6.3 接入
- `App.tsx``GAMES` 增加 `pig`(名"拱猪"),加入 `GAME_ORDER`(位置待定,建议放在 mill 之后)。
- 创建房间时 `numPlayers` 仅允许 3 或 4`maxSeats=4`setupOptions 提供人数选择,或复用 Holdem 的座位选择 UI 改为 3/4
---
## 七、资料来源
- 百度百科「拱猪」词条
- 维基百科wikidpedia「拱猪」条目含完整分值、亮牌、全红、大满贯、规则差异
- 腾讯游戏 / QQ 游戏 拱猪规则帮助页
- 远航游戏中心、边锋、联众等平台拱猪规则说明
- 萌娘百科「红心大战(拱猪变体)」条目
- 百度贴吧 / 百度文库 玩家经验贴
> 注:拱猪民间变体极多,本报告以"主流线上平台 + 维基百科标准规则"为准3 人局采用上文方案 A 作为推荐默认。