From cab66bea01c932eafdb0d22721eac56d61da79b6 Mon Sep 17 00:00:00 2001 From: Joywayer Date: Sun, 5 Jul 2026 07:02:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=8C=E4=B8=83=E7=8E=8B=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=EF=BC=9A=E5=9B=BA=E5=8C=96=20=E5=9E=AB=E7=89=8C/=E6=B7=B7?= =?UTF-8?q?=E5=90=88=E5=87=BA=E7=89=8C=20=E5=9B=9E=E5=BD=92=E7=94=A8?= =?UTF-8?q?=E4=BE=8B=EF=BC=88=E4=BB=A3=E7=A0=81=E6=9C=AC=E5=B7=B2=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对应 design.md 新成文的 垫牌(对子/拖拉机首家)与混合出牌概念。经探针 核对,can_followcard 早已让混合牌/垫牌 cardvalue=0、不争夺出牌权, 正式代码无需改。此前仅单张垫牌有覆盖、混合出牌零覆盖,现补 10 条: - 垫:对子/拖拉机缺门出副牌散张,合法且 beat=false - 混:有该副花色但不够、只能补主牌 → 合法、beat=false(等效垫牌), 丢下必出的副牌只出主牌→拒;含"有对也压不过"边界 期望值取自 design 规则(不争权/须先出该花色),全套 254 项通过。 Co-Authored-By: Claude Opus 4.8 (1M context) --- server/games/erqiwang/test/test_follow.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/server/games/erqiwang/test/test_follow.js b/server/games/erqiwang/test/test_follow.js index 77147b9..1a44d06 100644 --- a/server/games/erqiwang/test/test_follow.js +++ b/server/games/erqiwang/test/test_follow.js @@ -74,4 +74,22 @@ t.eq('拖 3连对·拆散3连拖(改出99)→拒', res(f([K(1), K(2), Q(1), Q(2) t.eq('全出 手牌恰1张(单张首出)', res(f([oth(9)], [oth(9)], 1, 2, 101)), true); t.eq('全出 手牌恰2张(对子首出)', res(f([oth(9), oth(8)], [oth(9), oth(8)], 2, 2, 201)), true); +// ===================== 垫牌:缺门首家副花色,用其他副牌补,不争夺出牌权 ===================== +// (单张垫牌上文已覆盖;此处补对子/拖拉机首家时的副牌垫) +t.eq('垫 对子缺门出两副散(合法)', res(f([oth(9), oth(8), zK(1)], [oth(9), oth(8)], 2, 2, 201)), true); +t.eq('垫 对子缺门出两副散 不压', beat(f([oth(9), oth(8), zK(1)], [oth(9), oth(8)], 2, 2, 201)), false); +t.eq('垫 拖缺门出四副散(合法)', res(f([oth(9), oth(8), oth(6), oth(5), zK(1)], [oth(9), oth(8), oth(6), oth(5)], 4, 2, 302)), true); +t.eq('垫 拖缺门出四副散 不压', beat(f([oth(9), oth(8), oth(6), oth(5), zK(1)], [oth(9), oth(8), oth(6), oth(5)], 4, 2, 302)), false); + +// ===================== 混合出牌:有该花色但不够,只能补主牌,等效垫牌不争权 ===================== +// 首家副对子:手中仅1张该副花色 + 主牌(无其他副牌)→ 必出该副 + 补主,混合牌压不过 +t.eq('混 对子·1副+补主(合法)', res(f([N9(1), zK(1), zQ(1)], [N9(1), zK(1)], 2, 2, 201)), true); +t.eq('混 对子·1副+补主 不压(等效垫)', beat(f([N9(1), zK(1), zQ(1)], [N9(1), zK(1)], 2, 2, 201)), false); +t.eq('混 对子·丢下必出的副牌只出两主→拒', res(f([N9(1), zK(1), zQ(1)], [zK(1), zQ(1)], 2, 2, 201)), false); +// 首家副拖拉机:手中2张该副花色散张 + 主牌 → 必出2副 + 补2主,混合压不过 +t.eq('混 拖·2副散+补2主(合法)', res(f([N9(1), N8(1), zK(1), zQ(1), zJ(1)], [N9(1), N8(1), zK(1), zQ(1)], 4, 2, 302)), true); +t.eq('混 拖·2副散+补2主 不压', beat(f([N9(1), N8(1), zK(1), zQ(1), zJ(1)], [N9(1), N8(1), zK(1), zQ(1)], 4, 2, 302)), false); +// 首家副拖拉机:手中1对该副花色(数量仍不足) + 主牌 → 有对也压不过(混合非纯主拖) +t.eq('混 拖·副对(不足)+补2主 不压', beat(f([N9(1), N9(2), zK(1), zQ(1), zJ(1)], [N9(1), N9(2), zK(1), zQ(1)], 4, 2, 302)), false); + process.exit(t.done('follow') ? 0 : 1);