斗地主插件总览
DoudizhuPlugin 是 CardGameEngine 的内置斗地主(Doudizhu / Fight-the-Landlord)游戏插件,实现了完整的 3 人斗地主流程:发牌、叫地主、出牌、胜负判定与倍率计算。
概述
斗地主是中国流行的 3 人扑克游戏。一副 54 张牌(52 张花色牌 + 大小王)平均发给 3 位玩家各 17 张,剩余 3 张作为底牌。其中一位玩家成为"地主"(landlord),独自对抗另两位组成的"农民"(farmers)队。地主额外获得 3 张底牌(共 20 张),并由地主先手出牌。地主或任一农民首先清空手牌即获胜。
关键特性
| 特性 | 说明 |
|---|---|
| 玩家数 | 3(地主 1 + 农民 2) |
| 牌堆 | 54 张(4 花色 × 13 点 + 大小王) |
| 每人手牌 | 17 张;地主额外持 3 张底牌(共 20 张) |
| 牌型 | 13 种(含 SINGLE / PAIR / TRIPLE / 顺子 / 连对 / 飞机变体 / 炸弹 / 火箭 等) |
| 倍率机制 | 出炸弹 / 火箭倍率 ×2;抢地主 ×2(默认流程未启用) |
| 阶段 | DEALING → BIDDING → PLAYING → FINISHED |
游戏流程
┌────────────────────────────────────────────────────────────────┐
│ GameEngine.createGame(DoudizhuPlugin.setup) │
│ - 创建 ddz-deck / ddz-bottom / ddz-discard 三个 zone │
│ - 通过 ctx.random 生成并洗牌 54 张牌 │
│ - 初始化所有 DDZ_VAR_* 变量;phase = DEALING │
│ - 将 doudizhuStateCheck 注册到核心 StateValidator │
└──────────────────────────────────┬─────────────────────────────┘
▼
engine.start()
│
派发 GAME_STARTED 事件
│
▼
┌────────────────────────────────────────────────────────────────┐
│ 阶段 1:DEALING │
│ handleGameStarted: │
│ - 按座位顺序为每位玩家发 17 张手牌 │
│ - 3 张底牌 → DDZ_BOTTOM_ZONE_ID │
│ - 记录 DDZ_VAR_BOTTOM_CARD_IDS │
│ - phase = BIDDING;首位叫分人 = 最低座位号玩家 │
│ - 发出 DDZ_CARDS_DEALT / DDZ_GAME_STARTED │
└──────────────────────────────────┬─────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────────┐
│ 阶段 2:BIDDING(叫地主) │
│ 按座位顺序轮流:CALL_LANDLORD │
│ - call=true → 成为 landlord 候选人 → REVEAL_BOTTOM_CARDS │
│ - call=false → 加入 bidderPassed;推进 bidderIndex │
│ 所有人不叫 → redeal()(重新洗牌、发牌、再次叫分) │
│ ROB_LANDLORD(前向兼容,Phase 5 默认流程不使用) │
└──────────────────────────────────┬─────────────────────────────┘
▼
REVEAL_BOTTOM_CARDS(系统派发,无 playerId)
│
- 候选人 → 最终 landlordId │
- 按座位顺序推导另两位 → farmerIds │
- 3 张底牌移入地主手牌(地主共 20 张) │
- phase = PLAYING;currentPlayerId = landlordId │
- 发出 DDZ_LANDLORD_ASSIGNED / DDZ_BOTTOM_CARDS_REVEALED │
▼
┌────────────────────────────────────────────────────────────────┐
│ 阶段 3:PLAYING(出牌) │
│ 地主先手 → 轮流 PLAY_CARDS / PASS │
│ PLAY_CARDS: │
│ - 校验牌型并比较 mainRank / BOMB / ROCKET │
│ - 出牌 → DDZ_DISCARD_ZONE_ID;更新 lastCombination │
│ - BOMB / ROCKET → 倍率 ×2;发出 DDZ_BOMB_PLAYED / │
│ DDZ_ROCKET_PLAYED │
│ - 手牌空 → declareWin │
│ PASS: │
│ - 累加 DDZ_VAR_PASS_COUNT │
│ - 达到 N-1 → resetRoundState;发出 DDZ_ROUND_RESET │
└──────────────────────────────────┬─────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────────┐
│ 阶段 4:FINISHED │
│ - state.status = 'finished' │
│ - winnerIds 写入获胜队伍全部玩家 │
│ - 发出 GAME_WON / GAME_FINISHED / DDZ_PLAYER_WON / │
│ DDZ_GAME_FINISHED │
└────────────────────────────────────────────────────────────────┘阶段(DoudizhuPhase)
| 阶段 | 枚举值 | 说明 |
|---|---|---|
| 发牌 | DoudizhuPhase.DEALING | 已洗牌但尚未发牌;setup 完成后的初始阶段 |
| 叫地主 | DoudizhuPhase.BIDDING | 已发牌;玩家按座位顺序轮流叫 / 不叫地主 |
| 出牌 | DoudizhuPhase.PLAYING | 地主已确定,底牌已亮给地主;轮流出牌 |
| 结束 | DoudizhuPhase.FINISHED | 有玩家清空手牌;已记录胜者 |
队伍与倍率
- 地主(LANDLORD):单独一队,持有 20 张牌(17 + 3 底牌)。
- 农民(FARMERS):两位玩家共同一队,任一农民清空手牌即视为 FARMERS 队获胜。
- 倍率(multiplier):初始为 1。出炸弹 / 火箭时倍率 ×2;抢地主成功时倍率 ×2(Phase 5 默认叫分流程不触发)。
装配内容
DoudizhuPlugin 通过 GamePlugin 接口装配以下内容:
- setup:创建
ddz-deck/ddz-bottom/ddz-discard三个 zone,洗牌生成 54 张牌并放入 deck zone,初始化所有斗地主变量;将doudizhuStateCheck注册到核心StateValidator。 - rules:阶段、轮次、牌权、所属权、牌型、PASS、叫 / 抢地主等校验(共 9 条)。
- actions:
PLAY_CARDS/PASS/CALL_LANDLORD/ROB_LANDLORD/REVEAL_BOTTOM_CARDS共 5 个处理器。 - events:监听
GAME_STARTED/CARD_PLAYED/DDZ_LANDLORD_CALLED/DDZ_LANDLORD_ROBBED/DDZ_PLAYER_PASSED共 5 个事件,将副作用委托给effects/*中的纯函数。
最小示例
ts
import {
GameEngine,
TurnPlugin,
DrawPlugin,
DoudizhuPlugin,
createCallLandlordAction
} from 'decklet/doudizhu'
const engine = new GameEngine({ seed: 2024 })
engine.use(TurnPlugin).use(DrawPlugin).use(DoudizhuPlugin)
engine.createGame({
players: [
{ id: 'p1', name: 'Alice', seat: 1 },
{ id: 'p2', name: 'Bob', seat: 2 },
{ id: 'p3', name: 'Carol', seat: 3 }
]
})
engine.start()
// 首位叫分人叫地主 → REVEAL_BOTTOM_CARDS 自动派发 → 进入 PLAYING
engine.dispatch(createCallLandlordAction('p1', true))文档导航
| 文档 | 内容 |
|---|---|
| doudizhu-plugin.md | DoudizhuPlugin 入口与导出符号 |
| state.md | 状态变量、阶段、队伍、访问器函数 |
| actions.md | Action 类型与工厂函数 |
| effects.md | 副作用处理函数 |
| rules.md | 校验规则 |
| combinations.md | 牌型检测与比较 |
| cards.md | 卡牌、牌堆与花色 |
| events.md | 事件常量与 Payload |