diff --git a/dsl-examples/shanghai.yaml b/dsl-examples/shanghai.yaml new file mode 100644 index 0000000..2a26e9d --- /dev/null +++ b/dsl-examples/shanghai.yaml @@ -0,0 +1,118 @@ +# 上海麻将 (上海敲麻) DSL 配置 +# +# 规则概要: +# - 144张牌 (万条筒108 + 东南西北中发白28 + 春夏秋冬梅兰竹菊8) +# - 不可吃牌 (敲麻模式核心特征) +# - 花牌计分: 每张花牌+1番, 对应花配对(春梅/夏兰/秋竹/冬菊)+1番 +# - 番型叠加 (all fans add up) +# - 一人胡牌即结束 (非血战) +# +# 引擎已知限制 (合规检查会警告): +# - "敲" 机制 (declare ting) 不支持: 上海敲麻核心规则是必须声明听牌才能胡牌, +# 引擎无此概念, 配置中未表达。模拟运行时所有玩家均可随时胡牌。 +# - 包三家 (discarder pays all): 引擎计分模块不支持此结算模式。 +# - 全花计分 (春夏秋冬齐/梅兰竹菊齐): 引擎 flower_rules 仅支持单张+配对, +# 不支持"集齐四花"额外加分。 +# - 番型: 圈风刻/门风刻/箭刻 不在引擎识别列表中。 +# - 缺一门/无字 为结构性 marker fan (base_fan=0), 仅用于 excludes 互斥。 + +game: + name: 上海麻将 + type: mahjong + engine_type: mahjong + players: { min: 4, max: 4 } + +requires: + - deck.generator_mahjong + - meldsolver.standard_win + - meldsolver.seven_pairs + - deck.flower_cards + - phase.mahjong_turn + - phase.priority_arbitration + - scoring.fan_exclusion + +deck: + generator: mahjong + include_honors: true + include_flowers: true + total: 144 + +deal: + cards_per_player: 13 + dealer_extra: 1 + +flower_rules: + on_draw: replace_and_draw + replace_tiles: BEFORE_GAME_START + scoring: + normal: 1 + matching: + value: 1 + mapping: + 1: [春, 梅] + 2: [夏, 兰] + 3: [秋, 竹] + 4: [冬, 菊] + +fan_types: + # ── 基础番型 ── + - { name: 碰碰胡, base_fan: 2 } + - { name: 混一色, base_fan: 4, excludes: [缺一门] } + - { name: 清一色, base_fan: 8, excludes: [缺一门, 无字] } + - { name: 七对, base_fan: 4, excludes: [门前清, 单钓将] } + - { name: 全求人, base_fan: 4 } + - { name: 字一色, base_fan: 16, excludes: [缺一门, 混一色, 碰碰胡] } + # ── 事件番型 ── + - { name: 杠上开花, base_fan: 1, excludes: [海底捞月] } + - { name: 海底捞月, base_fan: 1 } + - { name: 抢杠胡, base_fan: 1 } + - { name: 天胡, base_fan: 32 } + - { name: 地胡, base_fan: 16 } + # ── 兜底 ── + - { name: 鸡胡, base_fan: 1 } + +fan_stacking: add +max_fan: 999 + +phases: + - name: deal + type: auto + action: deal_cards_with_flowers + next: play + + - name: play + type: mahjong_turn + turn_order: counter_clockwise + sub_phases: + draw: + type: auto + action: draw_card + on_draw_flower: replace + on_empty_deck: exhausted + self_action: + options: + - { action: discard } + - { action: an_kong } + - { action: bu_kong, condition: has_punged_pair } + - { action: win, condition: can_win_tumo } + others_reaction: + options: + # 上海敲麻不可吃 — chi 不在此列表中 + - { action: pung, priority: 2, condition: has_two_same } + - { action: ming_kong, priority: 3, condition: has_three_same } + - { action: win, priority: 4, condition: can_win } + - { action: pass, priority: 0 } + priority_policy: highest_wins + on_win: game_over + end_conditions: + - { type: player_wins, action: settle } + - { type: deck_exhausted, action: draw_game } + + - name: settle + type: auto + action: calculate_scores + next: null + +scoring: + mode: fan_table + max_cap: 999