- 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 通过
28 KiB
日本立直麻将(雀魂规则)玩法规则与实现选型汇总
本文档是给 CodeBuddy 实现日麻游戏
packages/engine/src/games/mahjong.ts的玩法依据。 目标:规则完全符合日本立直麻将,采用雀魂(Majsoul)标准规则,覆盖四人麻将(四麻)与三人麻将(三麻)、半庄战。 来源:雀魂官方规则说明、OurPlay《雀魂麻将规则和打法》、萌娘百科/维基百科立直麻将词条、MemoJong《三麻规则一览》、天鳳/万年東風等日麻规则站。 所有 【已拍板】 标记的实现选型以本文为准;与真实日麻存在差异的条目在 §15「与标准日麻的差异/实现裁剪」中单独说明。用户已拍板(2026-10-03):
- 纯真人开局(AI 补位作为后续独立阶段,本期不做)。
- 半庄战(东南战,东风+南风;不足则西入)。
- 完整雀魂规则(全部役种+役满+振听+鸣牌+赤宝+流局+连庄+立直/一发/里宝/杠宝等)。
- 四麻 + 三麻 两种人数模式。
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 局)+ 南风战(南 14 局);庄家按东→南→西→北循环(例如东 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. 配牌与摸打
- 洗牌砌墙:136(108)张洗匀,砌成牌墙,开牌确定「王牌」(最后 14 张,其中 4 张岭上牌 + 若干宝牌指示牌)。
- 掷骰定亲开牌:确定起家与开牌位置(实现可简化为随机亲家 + 随机墙位置)。
- 配牌:各家依次摸 13 张(亲家先摸第 14 张作为开局手牌)。
- 摸打循环:
- 当前行动者摸一张(自摸牌)→ 打出一张(打牌)。
- 打出的牌进入该家牌河(河),按顺序排列。
- 下一行动者 = 下家(逆时针)。若有鸣牌,行动者改变(见 §4)。
- 摸牌顺序:从牌墙顺序摸;杠后从岭上牌摸(见 §4.3)。
- 自摸牌处理:摸到的牌可插入手牌(立直后仅能摸切/暗杠,见 §5)。
- 本场/供托:每局开始时把上一局累积的立直棒仍留在桌上,本场数显示在中央。
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 振听(フリテン)
以下情况不能荣和(只能自摸):
- 舍张振听:自己的牌河中(含被鸣走前的鸣牌)有自己听牌所需的牌(任意一张听牌即振听全部)。
- 同巡振听:本轮内他家打出的和了牌被自己放过(未荣和),则本轮内不能再荣和(下一巡解除)。
- 立直后振听:立直后他家打出的和了牌被放过 → 立直期间持续振听(转听也保持),只能自摸。
- 振听仅限制荣和;自摸不受影响。
- 振听立直:听牌但处于舍张振听时仍可立直(雀魂允许),立直后依然只能自摸。
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.ioplayerView)。 - 注册三处:
packages/server/src/index.ts的Server({ games: [...] })数组;- 同文件的
GAMES_ENTRIES数组({ name: 'Mahjong', game: Mahjong }); 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):牌组构成、和牌分解、全部役种判定、符与点数表、振听、食替、头跳、流局罚符、连庄/进庄、三麻自摸损。 - 玩家名:沿用
setNamemove +G.playerNames(与 Bridge/DoubleUp 一致)。 - 注意:Game 的
moves直接 mutateG(无 Immer),移动牌时必须新建数组,避免别名 bug(见drag-test.ts注释与踩坑记录)。
15. 与标准日麻的差异 / 实现裁剪
用于 4 人(及 3 人)浏览器联机场景的合理裁剪,不影响核心玩法:
- 无「中途流局宣言」之外的罚则(如错荣、错鸣的纠正),仅静默拒绝非法 move。
- 鸣牌响应窗口:真实日麻允许并发申请鸣牌并比较优先级;实现采用「按逆时针顺序依次询问 + 超时」,与雀魂的即时响应体验有差异。
- 无掷骰动画/点棒物理,开牌位置随机或由引擎决定。
- 无「观战」(本期不做)、无 AI 补位(本期纯真人)。
- 人和不实现(非雀魂标准)。
- 本场语义按雀魂「和了后重置」实现,细节见 §11。
- 顺位马/头名赏仅用于终局顺位展示,对局内不改变点数。
16. 参考来源
- 雀魂(Majsoul)官方规则说明与段位场规则页
- OurPlay《雀魂麻将规则和打法》(四麻段位场/友人场/三麻)https://m.ourplay.net/find/detail/150493
- MemoJong《三麻规则一览|四麻差异、拔北、自摸损、点数与马点详解》https://memojong.com/zh-cn/guides/sanma-rule-list/
- 维基百科/萌娘百科「日本麻将」「立直麻将」「役种列表」「符計算」「振听」「流局满贯」
- 百度百科「役满」「双倍役满」「流局满贯」「人和」
- 天鳳/万年東風等日麻规则站(役种、符、点数表校验)