Files
huajishe-tts/docs/mahjong/00-rules.md
e2hang 8d5fb3c511 feat(mahjong): 立直麻将(四麻/三麻,半庄战,雀魂规则)
- engine/tiles: 34 种牌、四麻 136/三麻 108(去 2m~8m)、赤 5(3/2 枚)、宝牌指示映射、排序与计数
- engine/yaku: 和牌分解(标准/七对/国士)+ 全役种(含双倍役满、累计役满)+ 符计算 + 番符→点数(满贯封顶、不采用切上满贯、三麻自摸损)+ 听牌/振听/食替
- engine/game: boardgame.io Game(阶段机 + 摸打/立直/鸣牌/和了/流局 moves + 鸣牌窗口“荣>碰/杠>吃/头跳” + playerView 隐藏 + 连庄/进庄/击飞/西入/半庄终局)
- ui: 新增 MahjongBoard(立式麻将桌:手牌/牌河/副露/宝牌/剩余张数/点数/鸣牌倒计时)
- 注册: server 两数组 + App.tsx GAMES/GAME_ORDER/GameKey/本地+联机 View(maxSeats=4, seatChoices=[3,4])
- docs: docs/mahjong/{00-rules,01-implementation-plan}.md + dev-log 15;CODEBUDDY.md 游戏清单更新
- 测试: mahjong-tiles/yaku/game 共 59 条;engine 全量 310 通过;web tsc+vite build、server tsc 通过
2026-10-03 12:43:51 +08:00

495 lines
28 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.
# 日本立直麻将(雀魂规则)玩法规则与实现选型汇总
> 本文档是给 CodeBuddy 实现日麻游戏 `packages/engine/src/games/mahjong.ts` 的玩法依据。
> 目标:**规则完全符合日本立直麻将,采用雀魂(Majsoul)标准规则**,覆盖**四人麻将(四麻)与三人麻将(三麻)**、**半庄战**。
> 来源:雀魂官方规则说明、OurPlay《雀魂麻将规则和打法》、萌娘百科/维基百科立直麻将词条、MemoJong《三麻规则一览》、天鳳/万年東風等日麻规则站。
> 所有 **【已拍板】** 标记的实现选型以本文为准;与真实日麻存在差异的条目在 §15「与标准日麻的差异/实现裁剪」中单独说明。
>
> **用户已拍板(2026-10-03)**:
> 1. **纯真人**开局(AI 补位作为后续独立阶段,本期不做)。
> 2. **半庄战**(东南战,东风+南风;不足则西入)。
> 3. **完整雀魂规则**(全部役种+役满+振听+鸣牌+赤宝+流局+连庄+立直/一发/里宝/杠宝等)。
> 4. **四麻 + 三麻** 两种人数模式。
---
## 0. 一句话定义
四(三)人围坐,用含有赤宝牌的 136(108)张牌,通过「**配牌 → 摸打(可吃碰杠)→ 立直 → 和了/流局 → 结算 → 连庄/进庄**」的循环,先做出「**役**」并满足「**番+符**」的和牌型者得分;以**半庄战**(东风战+南风战)累计点数决出顺位,点数低于 0 立即**击飞**终局。
---
## 1. 牌具与座位
### 1.1 四麻(4 人)
- **牌**:34 种 × 4 张 = **136 张**。
- 数牌:万子 `1m~9m`、筒子 `1p~9p`、索子 `1s~9s`,各 4 张。
- 字牌:风牌 `東 南 西 北`、三元牌 `白 發 中`,各 4 张。
- **赤宝牌(赤ドラ)**:**红 5 万、红 5 筒、红 5 索 各 1 张**(共 3 枚),占用对应 5 的一张位置。
- **座位**:4 人围坐,起家为 **东**,按**逆时针**(麻将的「下家」方向,即东→南→西→北)编号 P0/P1/P2/P3。
- 起家(最初亲家)= 东家;每局结束后亲家按东→南→西→北轮转。
- **自风**:每家的当前门风(东/南/西/北)。
- **场风**:当前是东风战还是南风战(场风 = 东 或 南)。
- **手牌**:每家 **13 张**(摸打时 14 张);和牌型 = 4 面子 + 1 雀头(+ 可能的杠)或七对子/国士无双。
### 1.2 三麻(3 人,雀魂友人场/段位三麻)
- **牌**:**去掉 2m~8m 共 28 张**,保留 `1m 9m` + 全筒 + 全索 + 全字牌,共 **108 张**(27 种 × 4)。
- **赤宝牌**:**红 5 筒、红 5 索 各 1 张**(共 2 枚;万子无 5,故无红 5 万)。
- **座位**:只有 **东、南、西** 三家(**无北家**)。
- **吃牌**:**不可吃**(碰、杠、拔北允许)。
- 其余流程与四麻一致,差异见 §12。
> 一张牌用字符串表示:`{ id, kind }`,如 `5m`(普通五万)、`0m`(红五万)、`1p`、`東`、`白`。红 5 用 `0m/0p/0s` 或 `r5m/r5p/r5s` 表示(实现自定,需全局一致)。
---
## 2. 场次与对局长度
### 2.1 半庄战(本实现采用)
- 打 **东风战(东 1~4 局)+ 南风战(南 1~4 局)**;庄家按东→南→西→北循环(例如东 4 局庄家为北家,之后南 1 局庄家回到东家)。
- **起始点数 25000**;**返点 30000**。
- **连庄**:亲家和了、或荒牌流局时亲家听牌 → 连庄(本场 +1,亲家不变);否则亲家下庄(本场 +1,下家做亲)。
- **顺位马(ウマ)**:1 位 +15 / 2 位 +5 / 3 位 −5 / 4 位 −15(用于段位分/最终顺位,非对局内点数);**头名赏** = 返点 − 起点 = 30000 − 25000 = 5000/人,共 20000 全部给一位(仅结算时计算)。
- **本场(積み棒)**:每本场 **300 点**(四麻),计入和了点数。
- **供托(立直棒)**:每根 **1000 点**,立直时置于桌上;和了者收走全部供托。
### 2.2 终局条件(半庄)
- **击飞(トビ)**:任一玩家点数 **< 0** 时立即终局(负分部分照算;恰好 = 0 继续)。
- **和了终局(アガリやめ)**:南 4 局(All Last)**亲家为一位**、点数 **> 30000**、且满足连庄条件时,**不再连庄**,直接终局。
- **西入(シャンボ)**:南 4 局结束(含流局)时,**若无人点数 ≥ 30000**,进入 **西风战**(西 1~4 局)加时;**加时赛一旦有人 ≥ 30000 立即终局**;最长打到西 4 局结束强制结算。
- (东风战模式——非本期默认——则为「南入」,规则同上,切到南风战加时。)
---
## 3. 配牌与摸打
1. **洗牌砌墙**:136(108)张洗匀,砌成牌墙,开牌确定「**王牌**」(最后 14 张,其中 4 张岭上牌 + 若干宝牌指示牌)。
2. **掷骰定亲开牌**:确定起家与开牌位置(实现可简化为随机亲家 + 随机墙位置)。
3. **配牌**:各家依次摸 13 张(亲家先摸第 14 张作为开局手牌)。
4. **摸打循环**:
- 当前行动者**摸一张**(自摸牌)→ 打出一张(**打牌**)。
- 打出的牌进入该家**牌河(河)**,按顺序排列。
- 下一行动者 = 下家(逆时针)。若有鸣牌,行动者改变(见 §4)。
- **摸牌顺序**:从牌墙顺序摸;杠后从**岭上牌**摸(见 §4.3)。
5. **自摸牌处理**:摸到的牌可**插入手牌**(立直后仅能摸切/暗杠,见 §5)。
6. **本场/供托**:每局开始时把上一局累积的立直棒仍留在桌上,本场数显示在中央。
---
## 4. 鸣牌(副露)
鸣牌后手牌**不再门清**(影响立直、门前清自摸和、平和、一杯口、二杯口等)。
### 4.1 吃(チー)
- **仅能吃上家**(左手,逆时针上一位)打出的牌。
- 用手中两张牌 + 上家弃牌组成顺子;**顺子不得重复吃**导致食替(见 4.5)。
- **三麻不可吃**。
- 吃后由**吃牌者**打出下一张。
### 4.2 碰(ポン)
- 任意玩家可碰**任意出牌者**打出的牌,用手中两张同种牌组成刻子。
- **碰优先于吃**;同一张牌多人可鸣时**碰/杠优先于吃**。
- 碰后由碰牌者打出下一张。
- **三麻**:碰后**不可立即拔北**(拔北近似鸣牌,需先打牌)。
### 4.3 杠(カン)
| 类型 | 说明 | 新宝牌 | 岭上 |
| --- | --- | --- | --- |
| **大明杠** | 手中 3 张 + 他家弃牌 | ✅ 翻开新宝牌指示牌 | 从岭上摸 1 张 |
| **加杠** | 已碰的刻子 + 摸到的第 4 张 | ✅ | 从岭上摸 1 张(可被**抢杠**) |
| **暗杠** | 手中 4 张(门清) | ✅(一般规则) | 从岭上摸 1 张(可被国士**抢杠**) |
- 杠后从**岭上牌**补摸;若和了 → **岭上开花**(1 番)。
- **四杠散了**:若 4 个杠分属不同玩家(或含 1 暗杠共 4 杠)→ 途中流局(见 §10)。
- **加杠**的牌可被**抢杠(チャンカン)**:同一张牌他家和了则加杠不成立,和了者算抢杠(1 番);他人枪杠失败则加杠继续。
### 4.4 拔北(三麻专有)
- 摸到 **北** 时可**拔北**:把北亮出置于自留区,**从岭上补摸一张**。
- 每张拔出的北计为 **1 张宝牌(抜きドラ)**。
- **拔北后自摸和了视为岭上开花**(因补牌来自岭上)。
- 拔北近似鸣牌;**碰后不可立即拔北**。
- **抢北**:他家可对「拔北」宣言**荣和**(相当于抢杠,**非役满牌型也可抢**);北牌被拔时若他家能和 → 拔北不成立。
- 北若**作为面子**使用 → 按**客风**计算(不构成役牌役)。
- 三麻**无北家**,故**无四风连打、无四家立直**流局。
### 4.5 禁止食替(食い替え禁止)
- **现物食替禁止**:吃/碰后,**不能立即打出**与所鸣牌同种的牌(例如吃 `3m4m` 鸣 `2m` 后不能马上打 `2m`)。
- **筋食替禁止**:吃两面/嵌张后有对应的禁止打牌(如吃 `2m3m` 鸣 `1m`/`4m` 后不能打 `4m`/`1m` 等)。
- **雀魂采用食替禁止(无食替)**。实现时在鸣牌 move 中校验。
- 碰、杠无食替限制。
---
## 5. 立直(リーチ)
- **条件**:**门清**(未吃/碰/明杠)且**听牌**,且**点数 ≥ 1000**(付出一根立直棒)。
- **宣言**:在自摸后打牌前宣言立直,并**横置一张立直宣言牌**(若该牌被鸣,则立直仍成立,宣言牌被鸣走;若因此**破坏听牌**——雀魂允许「振听立直」情形见下)。
- 雀魂:宣言牌被吃/碰/杠时,**立直照常成立**(立直棒已支付)。若宣言牌被鸣后手牌仍听牌则正常;若变成不听,一般规则不允许(实现需校验仍听牌,否则拒绝立直)。
- **费用**:支付 **1000 点**作为供托。
- **限制**:立直后**只能摸切或暗杠**(暗杠不得改变听牌型,且所暗杠牌不破坏听牌结构);**不能吃碰明杠**。
- **一発(イッパツ)**:立直后**一巡内**和了,且期间**无任何鸣牌(含拔北)** → +1 番。
- **里宝牌(裏ドラ)**:立直和了时,翻开宝牌指示牌**下方**的里宝牌指示牌,对应牌每张 +1 番。
- **双立直(ダブルリーチ)**:**第一巡(无人鸣牌前)**立直 → 2 番。
- **四家立直**:四家全部立直(宣言牌无人和)→ **途中流局**(三麻无此,因只有三家)。
---
## 6. 和了与特殊和了
### 6.1 和了方式
- **自摸(ツモ)**:自己摸到和了牌,其余各家付点(亲家自摸由三家平摊;子家自摸由亲家付 2 倍、其余闲家各付 1 倍)。
- **荣和(ロン)**:他家打出的牌(或加杠牌、拔北牌)使自己成和牌型,由**放铳者**付全部点数(含本场)。
- **和了条件**:必须**至少有一个役**(无役不能和,宝牌不算役)。门前清自摸和有役。
### 6.2 振听(フリテン)
以下情况**不能荣和**(只能自摸):
1. **舍张振听**:自己的牌河中(含被鸣走前的鸣牌)有**自己听牌所需的牌**(任意一张听牌即振听全部)。
2. **同巡振听**:**本轮内**他家打出的和了牌被自己放过(未荣和),则本轮内不能再荣和(下一巡解除)。
3. **立直后振听**:**立直后**他家打出的和了牌被放过 → 立直期间持续振听(转听也保持),只能自摸。
- 振听仅限制**荣和**;**自摸不受影响**。
- **振听立直**:听牌但处于舍张振听时仍可立直(雀魂允许),立直后依然只能自摸。
### 6.3 一炮多响与头跳
- 一张牌可被多人同时荣和(**一炮多响/双响**)。
- **雀魂采用头跳(アタマハネ/截和)**:只承认**按出牌者逆时针顺序最近的一家**荣和;其和了成立,其余不成立。
- **供托与本场**全部归头跳和了者。
### 6.4 抢杠与抢北
- **抢杠**:他家对**加杠**的牌荣和 → 加杠不成立,和了者 +1 番(抢杠)。
- **抢北(三麻)**:对他家**拔北**的北荣和(非役满牌型也可)。
### 6.5 特殊和了
- **岭上开花(リンシャン)**:杠/拔北后从岭上补摸的牌自摸 → +1 番。
- **海底摸月(ハイテイ)**:牌墙**最后一张**自摸和了 → +1 番。
- **河底捞鱼(ホウテイ)**:牌墙**最后一张**被打出后荣和 → +1 番。
- **天和(テンホウ)**:亲家配牌后**立即**自摸和了 → 役满。
- **地和(チーホウ)**:子家第一巡自摸和了,且期间无人鸣牌 → 役满。
---
## 7. 役种完整表(雀魂)
> 「食下」= 副露时降番。宝牌(含赤、里、拔北)**不计入役**,仅在和了后加算番数。
### 7.1 一番役
| 役种 | 门清 | 食下 | 说明 |
| --- | --- | --- | --- |
| 立直 | ✅必 | — | 门清听牌宣言,付 1000 点 |
| 一发 | ✅必 | — | 立直后一巡内和了且无鸣牌 |
| 门前清自摸和 | ✅必 | — | 门清状态下自摸和了 |
| 平和(ピンフ) | ✅必 | — | 4 顺子+非役牌雀头+两面听;**固定 20 符** |
| 断幺九(タンヤオ) | ✅ | ✅ | 全手无幺九牌与字牌(雀魂**有食断**) |
| 一杯口(イーペーコー) | ✅必 | — | 两组完全相同的顺子 |
| 役牌·场风 | ✅ | ✅ | 场风刻子 |
| 役牌·自风 | ✅ | ✅ | 自风刻子(与场风重合=**连风**,计 2 番) |
| 役牌·三元牌 | ✅ | ✅ | 白/發/中刻子(各 1 番) |
| 岭上开花 | ✅ | ✅ | 杠/拔北后岭上自摸 |
| 抢杠 | ✅ | ✅ | 抢他家加杠 |
| 海底摸月 | ✅ | ✅ | 牌墙最后一张自摸 |
| 河底捞鱼 | ✅ | ✅ | 牌墙最后一张荣和 |
### 7.2 二番役
| 役种 | 门清 | 食下 | 说明 |
| --- | --- | --- | --- |
| 双立直 | ✅必 | — | 第一巡立直 |
| 三色同顺(三色同順) | ✅ | 1 番 | 三种花色同一顺子 |
| 一气通贯(一気通貫) | ✅ | 1 番 | 同花色 `123+456+789` |
| 混全带幺九(チャンタ) | ✅ | 1 番 | 全部面子/雀头含幺九或字牌(且含字牌) |
| 七对子(チートイツ) | ✅必 | — | 7 个对子;**固定 25 符** |
| 对对和(トイトイ) | ✅ | ✅ | 4 刻子+雀头 |
| 三暗刻 | ✅ | ✅ | 3 个暗刻(荣和的三暗刻型仍成立) |
| 三色同刻 | ✅ | ✅ | 三种花色同一数字刻子 |
| 三杠子 | ✅ | ✅ | 3 个杠 |
| 混老头(ホンロウトウ) | ✅ | ✅ | 仅由幺九牌与字牌组成(对对型或七对型) |
| 小三元 | ✅ | ✅ | 两种三元刻子 + 第三种三元对子 |
### 7.3 三番役
| 役种 | 门清 | 食下 | 说明 |
| --- | --- | --- | --- |
| 二杯口(リャンペーコー) | ✅必 | — | 两组一杯口(含七对型时按二杯口) |
| 纯全带幺九(ジュンチャン) | ✅ | 2 番 | 全部面子/雀头含幺九,**不含字牌** |
| 混一色(ホンイツ) | ✅ | 2 番 | 一种花色 + 字牌 |
### 7.4 六番役
| 役种 | 门清 | 食下 | 说明 |
| --- | --- | --- | --- |
| 清一色(チンイツ) | ✅ | 5 番 | 仅一种花色 |
### 7.5 役满(ヤクマン)
| 役种 | 倍数 | 说明 |
| --- | --- | --- |
| 国士无双 | 1 | 13 种幺九/字牌各 1 + 其中一种成对 |
| 四暗刻 | 1 | 4 个暗刻;**自摸**成立(荣和一般算三暗刻) |
| 大三元 | 1 | 白發中三刻子 |
| 小四喜 | 1 | 三风刻子 + 第四风对子(雀魂计役满) |
| 大四喜 | **2(双倍)** | 四风刻子 |
| 字一色 | 1 | 全字牌 |
| 绿一色 | 1 | 仅 `2s3s4s6s8s` + `發` |
| 清老头(チンロウトウ) | 1 | 仅幺九牌,无字牌 |
| 九莲宝灯 | 1 | 同花色 `1112345678999` + 任意同花一张 |
| 纯正九莲宝灯 | **2(双倍)** | 九莲**只听 9 面**(`1112345678999` 和该花任意张) |
| 四杠子 | 1 | 4 个杠 |
| 天和 | 1 | 亲家配牌即和 |
| 地和 | 1 | 子家第一巡自摸且无鸣牌 |
| 国士无双十三面 | **2(双倍)** | 国士只听 13 面 |
| 四暗刻单骑 | **2(双倍)** | 四暗刻+单骑听 |
| 累计役满 | 1 | 非役满牌型番数 ≥ 13(**不叠加双倍**) |
> **双倍役满**:雀魂采用(四暗刻单骑、国士十三面、纯正九莲、大四喜)。**复合役满**可叠加(如字一色+四暗刻)。**累计役满**封顶 1 倍。
### 7.6 不采用的役/古役
- **人和(レンホウ)**:非标准役,雀魂段位**不采用**(实现不判定)。
- **其他古役**(十二落抬、十五本場、三連刻等):不采用。
---
## 8. 宝牌(ドラ)
| 类型 | 触发 | 说明 |
| --- | --- | --- |
| 表宝牌(ドラ) | 开局 | 翻开宝牌指示牌的「下一张」为宝牌(`9→1` 循环,风 `北→東`,三元 `中→白`) |
| 里宝牌(裏ドラ) | 立直和了 | 看指示牌下方一层 |
| 赤宝牌(赤ドラ) | 固定 | 红 5:四麻 3 枚、三麻 2 枚,各计 1 番 |
| 杠宝牌(カンドラ) | 每次杠 | 翻开新的宝牌指示牌 |
| 杠里宝牌(カン裏) | 杠 + 立直和了 | 对应里指示牌 |
| 拔北宝牌(三麻) | 每次拔北 | 每张拔出的北 +1 番 |
- **指示牌 → 宝牌**:数牌按 `1→2→…→9→1` 循环;风牌 `東→南→西→北→東`;三元牌 `白→發→中→白`。
- 宝牌**不是役**:没有役时即便有宝牌也不能和。
- **赤宝牌可作普通 5 使用**(兼具宝牌与顺子/刻子功能)。
---
## 9. 符计算与点数
### 9.1 符(符計算)
| 项目 | 符 |
| --- | --- |
| 副底(基础) | 20 |
| 门前清荣和 | +10 |
| 自摸 | +2 |
| 雀头·三元牌 | +2 |
| 雀头·自风/场风 | +2(连风=+4) |
| 中张明刻 | +2 |
| 幺九明刻 | +4 |
| 中张暗刻 | +4 |
| 幺九暗刻 | +8 |
| 中张明杠 | +8 |
| 幺九明杠 | +16 |
| 中张暗杠 | +16 |
| 幺九暗杠 | +32 |
| 听牌·单骑/嵌张/边张 | +2 |
| 听牌·两面/双碰 | +0 |
- **特殊**:平和自摸 = **20 符**;七对子 = **25 符**(不加算其它符)。
- **最低符**:食和最低 **30 符**(20 副底不满 30 进位);自摸(非平和)最低 **30 符**(20+2→进位)。
- 符数**向上取整到 10 位**(如 32 → 40)。
### 9.2 番符 → 基本点
```
基本点 = 符 × 2^(2 + 番)
```
**满贯封顶规则**:
| 番数/条件 | 级别 | 基本点 |
| --- | --- | --- |
| 5 番;或 4 番 40 符+;或 3 番 70 符+ | 满贯 | 2000 |
| 6–7 番 | 跳满(跳满) | 3000 |
| 8–10 番 | 倍满 | 4000 |
| 11–12 番 | 三倍满 | 6000 |
| 13 番+ | 累计役满 | 8000 |
| 役满 | 役满 | 8000 × 倍数 |
> **切上满贯(切り上げ満貫)不采用**(雀魂默认):4 番 30 符 / 3 番 60 符等按原值计算,不提前进位满贯。
### 9.3 支付
- **亲家荣和** = 基本点 × 6;**子家荣和** = 基本点 × 4。
- **亲家自摸** = 每家付 基本点 × 2(三家各付);**子家自摸** = 亲家付 基本点 × 2、其余闲家各付 基本点 × 1。
- 所有点数**向上取整到 100 位**。
- **本场**:每本场 **300 点**(四麻)/**200 点**(三麻),荣和由放铳者全额支付 `300×本场`,自摸由各家分摊 `100×本场`(三麻 200 本场对应分摊)。
- **供托**:和了者收走桌上全部立直棒(每根 1000)。
**点数速查(节选,子家/亲家荣和)**:
| 番符 | 子家荣和 | 亲家荣和 |
| --- | --- | --- |
| 1 番 30 符 | 1000 | 1500 |
| 1 番 40 符 | 1300 | 2000 |
| 2 番 25 符(七对) | 1600 | 2400 |
| 2 番 30 符 | 2000 | 2900 |
| 3 番 30 符 | 3900 | 5800 |
| 4 番 30 符 | 7700 | 11600 |
| 满贯 | 8000 | 12000 |
| 跳满 | 12000 | 18000 |
| 倍满 | 16000 | 24000 |
| 三倍满 | 24000 | 36000 |
| 役满 | 32000 | 48000 |
---
## 10. 流局(リュウキョク)
### 10.1 荒牌流局(牌墙摸完无人和了)
- **听牌罚符(ノーテン罰符)**,四麻合计 **3000 点**,三麻合计 **2000 点**:
- 1 家听牌:3 家不听各付 1000(三麻:2 家各付 1000)。
- 2 家听牌:2 家不听各付 1500(三麻:1 家不听付 2000?——三麻 1 听 2 不听按 1000/家、2 听 1 不听按 2000 全额)。
- 3 家听牌:1 家不听付 3000(三麻无第 3 家情形)。
- 全听或全不听:无罚符。
- **连庄**:亲家听牌 → 连庄(本场 +1);亲家不听 → 下庄(本场 +1)。
- **立直棒**:荒牌流局时不收回,留到下一局;和了者继续收。
### 10.2 途中流局(途中流局)
| 类型 | 条件 | 处理 |
| --- | --- | --- |
| **九种九牌** | 门清且第一巡打牌前,手牌含 ≥9 种幺九/字牌 | 可宣言流局;亲下庄,本场 +1(三麻适用) |
| **四风连打** | 第一巡 4 家打出**同一风牌**(无鸣牌) | 流局;亲下庄,本场 +1(**三麻无**) |
| **四家立直** | 4 家全部立直(宣言牌无人和) | 流局;亲下庄,本场 +1(**三麻无**) |
| **三家和了** | 同一张牌 3 家同时荣和 | 流局;亲下庄,本场 +1(**三麻无**) |
| **四杠散了** | 4 个杠分散于不同玩家(或含 1 暗杠) | 流局;亲下庄,本场 +1(三麻:北抜き是否计杠按实现定,默认计) |
> 途中流局**不进行听牌罚符**;立直棒保留。
### 10.3 流局满贯(流し満貫)
- **条件**:荒牌流局时,某玩家**打出的牌全部为幺九牌或字牌**,且**未被任何人鸣走**。
- **处理**:该玩家按**满贯自摸**计算点数(不进和了结算,属流局结算);**不收立直棒与本场**。
- **连庄**:按荒牌流局规则判定(亲听牌则连庄)。
- 多家达成时并列按满贯结算(实现需定义顺序,按头跳思路或全部结算,默认**全部结算**)。
---
## 11. 连庄 / 进庄 / 终局 / 击飞
- **和了连庄**:亲家和了 → 连庄。
- **听牌连庄**:荒牌流局亲家听牌 → 连庄。
- **下庄**:其余情况 → 亲家移至下家(东→南→西→北循环),本场 +1。
- **本场数**:每次连庄或下庄本场 +1;和了时按本场加算点数;有人和了则本场清零(下一局本场从 0 开始——注:和了连庄时本场 +1 继续累计,标准为和了后本场重置?-> 雀魂:和了即本场清零并进入下一局;连庄时本场数保留并 +1。**实现按「和了后本场重置为 0;连庄时保留」的雀魂行为处理**)。
> 精确语义:本场棒是「连续流局或连庄累积的加算棒」;**有人和了后本场归零**(和了者已收下所有本场点)。
- **终局**:见 §2.2(击飞、和了终局、西入)。
- **顺位**:终局按最终点数排序;同点按「起家顺序」或「上家优先」判定,雀魂按座次(东起逆时针)排名。
---
## 12. 三麻特有规则(雀魂)
| 项目 | 三麻 | 四麻 |
| --- | --- | --- |
| 用牌 | 108 张(去 2m~8m) | 136 张 |
| 座位 | 东、南、西(无北家) | 东南西北 |
| 吃 | ❌ 不可 | ✅ |
| 赤宝牌 | 2 枚(红 5p、红 5s) | 3 枚(红 5m/5p/5s) |
| 北 | **拔北宝牌**;作面子按**客风**;可被**抢北** | 普通风牌 |
| 起始/返点 | **35000 / 40000** | 25000 / 30000 |
| 本场 | **200 点** | 300 点 |
| 不听罚符 | 合计 **2000 点** | 3000 点 |
| 自摸损 | **有**:子家自摸少收一名闲家应付款(无北家补位) | 无 |
| 四风连打 / 四家立直 / 三家和了 | ❌ 不适用 | ✅ |
| 九种九牌 / 四杠散了 | ✅ | ✅ |
| 双响 | 头跳 | 头跳/三家和了流局 |
| 顺位马 | 1 位 +15 / 2 位 0 / 3 位 −15(以雀魂实际为准) | +15/+5/−5/−15 |
> **自摸损细节**:子家自摸时,理论上应收「亲家 2 倍 + 闲家 1 倍 + 闲家 1 倍」;三麻少一名闲家,缺失的 1 倍不收(有自摸损)。例如子家满贯自摸:亲付 4000 + 闲付 2000 = 6000(四麻为 8000)。
> **拔北是否计杠**:四杠散了判定中,拔北**计入**杠数(雀魂默认,实现按此);即 3 拔北 + 1 杠也可能触发四杠散了(罕见)。
---
## 13. 已拍板规则选型汇总
| # | 项目 | 选型 |
| --- | --- | --- |
| V1 | 人数 | **四麻 + 三麻**(房间创建时选择) |
| V2 | 场次 | **半庄战**(东南战,含西入);终局条件含击飞/和了终局 |
| V3 | 起始/返点 | 四麻 25000/30000;三麻 35000/40000 |
| V4 | 赤宝牌 | 四麻 3 枚、三麻 2 枚 |
| V5 | 吃碰杠 | 三麻不可吃;四麻可吃;杠含明杠/暗杠/加杠;三麻含拔北 |
| V6 | 食替 | **禁止**(现物食替 + 筋食替) |
| V7 | 一炮多响 | **头跳**(头家荣和);三家和了 → 途中流局 |
| V8 | 振听 | 舍张振听/同巡振听/立直后振听,**均实现** |
| V9 | 流局 | 荒牌流局(听牌罚符)+ 途中流局(九种九牌/四风连打/四家立直/三家和了/四杠散了)+ 流局满贯 |
| V10 | 连庄 | 和了连庄 + 亲听牌流局连庄;本场 300/200 |
| V11 | 役满 | 含双倍役满;累计役满封顶 1 倍;人和不采用 |
| V12 | 切上满贯 | 不采用 |
| V13 | 击飞 | 点数 < 0 立即终局(=0 继续) |
| V14 | AI | 本期不做(纯真人);后续独立阶段 |
| V15 | 终局结算 | 顺位马 + 头名赏按雀魂段位场计算(对局内点数照常显示) |
未拍板项(实现采用雀魂主流默认):
- 途中流局后亲家处理:统一「亲下庄 + 本场 +1」(雀魂主流)。
- 流局满贯多家达成:全部结算。
- 三麻顺位马:+15/0/−15,以雀魂实际为准,可配置。
---
## 14. 与现有代码库的对接要点(实现提示,非规则)
- **引擎文件**:`packages/engine/src/games/mahjong.ts`,导出 `TTSGame<MahjongState>`,`name: 'Mahjong'`,`minPlayers: 3`,`maxPlayers: 4`。
- 建议拆分子模块(纯函数,便于单测):
- `mahjong-tiles.ts`:牌定义、牌组生成(四麻/三麻)、赤宝牌、排序、宝牌指示映射。
- `mahjong-yaku.ts`:和牌型分解(面子分解 / 七对 / 国士)、役种判定、符计算、点数计算。
- `mahjong.ts`:Game 定义、阶段机、moves、playerView、结算。
- **阶段机(phases)建议**:`waiting`(进房)→ `playing`(摸打主循环,含鸣牌子状态)→ `roundEnd`(本局结算/流局展示)→ `gameEnd`(半庄终局)。
- 主循环内部用状态标记区分「等待摸牌 / 等待打牌 / 等待鸣牌响应」;因为 boardgame.io 无法真正并发,鸣牌响应建议用「思考窗口」+ 超时兜底(见踩坑记忆:**发牌必须原子完成,避免多客户端 flood move 导致同步错乱**)。
- **moves 规划**:`startGame`、`draw`(摸牌,可在 move 内自动推进)、`discard`、`riichi`、`chi/pon/kan/ankkan/kakan`、`north`(三麻拔北)、`ron/tsumo`、`pass`(鸣牌放弃)、`kyuushu9`(九种九牌)、`nextRound`、`setName`。
- **playerView**:隐藏他家手牌(含摸到的牌);公开牌河、副露、宝牌指示牌、点数、立直状态;本人手牌通过 `myHand` 注入(与 Bridge 一致)。**不可在 UI 重新实现隐藏逻辑**(沿用 boardgame.io `playerView`)。
- **注册三处**:
1. `packages/server/src/index.ts` 的 `Server({ games: [...] })` 数组;
2. 同文件的 `GAMES_ENTRIES` 数组(`{ name: 'Mahjong', game: Mahjong }`);
3. `apps/web/src/App.tsx` 的 `GAMES` 表(`engineName: 'Mahjong'`,`maxSeats: 4`,`seatChoices: [3, 4]`),并加入 `GAME_ORDER`、`GameKey` 联合类型、`LocalGameView`/`OnlineGameView` 分派。
- **UI**:新增 `apps/web/src/MahjongBoard.tsx`(参照 `BridgeBoard.tsx` 的椭圆桌 + 座位卡思路,重设计为**立式牌山视角**:自己手牌在底部、他家显示背面、四家牌河环形排布、中央显示场风/本场/供托/宝牌指示/剩余牌数)。因隐藏信息多,联机模式每 client 只见自己手牌。
- **单元测试**:`packages/engine/src/games/mahjong.test.ts`(+ `mahjong-yaku.test.ts`):牌组构成、和牌分解、全部役种判定、符与点数表、振听、食替、头跳、流局罚符、连庄/进庄、三麻自摸损。
- **玩家名**:沿用 `setName` move + `G.playerNames`(与 Bridge/DoubleUp 一致)。
- **注意**:Game 的 `moves` 直接 mutate `G`(无 Immer),移动牌时必须**新建数组**,避免别名 bug(见 `drag-test.ts` 注释与踩坑记录)。
---
## 15. 与标准日麻的差异 / 实现裁剪
用于 4 人(及 3 人)浏览器联机场景的合理裁剪,不影响核心玩法:
1. **无「中途流局宣言」之外的罚则**(如错荣、错鸣的纠正),仅**静默拒绝非法 move**。
2. **鸣牌响应窗口**:真实日麻允许并发申请鸣牌并比较优先级;实现采用「按逆时针顺序依次询问 + 超时」,与雀魂的即时响应体验有差异。
3. **无掷骰动画/点棒物理**,开牌位置随机或由引擎决定。
4. **无「观战」**(本期不做)、**无 AI 补位**(本期纯真人)。
5. **人和不实现**(非雀魂标准)。
6. **本场语义**按雀魂「和了后重置」实现,细节见 §11。
7. **顺位马/头名赏**仅用于终局顺位展示,对局内不改变点数。
---
## 16. 参考来源
- 雀魂(Majsoul)官方规则说明与段位场规则页
- OurPlay《雀魂麻将规则和打法》(四麻段位场/友人场/三麻)https://m.ourplay.net/find/detail/150493
- MemoJong《三麻规则一览|四麻差异、拔北、自摸损、点数与马点详解》https://memojong.com/zh-cn/guides/sanma-rule-list/
- 维基百科/萌娘百科「日本麻将」「立直麻将」「役种列表」「符計算」「振听」「流局满贯」
- 百度百科「役满」「双倍役满」「流局满贯」「人和」
- 天鳳/万年東風等日麻规则站(役种、符、点数表校验)