二七王:chupai1 下发甩牌分量构成 shuai
cardtype 只能表达单一牌型(1xx 单张 / 2xx 对子 / 3xx 拖拉机),而
甩牌是单张、对子、拖拉机自由混搭(design §5.4.3),会被 can_playcard
的牌型推导压平——例如「主K对 + 主5」得到 103、「两连对 + 散对」得到
203,客户端拿到 cardtype 无从还原分组,甚至看不出这是一次甩牌。
服务端本就已经算出了分量需求 shuai_demand(供跟牌逐分量强制匹配,
design §5.4.4),按「每个下发包必须携带前端界面所需的全部核心数据」
一并下发:chupai1 在合法甩牌时带 shuai = {tractors,pairs,singles},
非甩牌与甩错退化为单张时不带此属性。
test_rpc 新增 8 项:合法甩牌带 shuai、非甩牌不带、甩错只打最小一张
且不带 shuai。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -638,6 +638,11 @@ var cls_youle_erqiwang_paiju = cls_youle_erqiwang_paiju || {
|
||||
re1.cardtype = can.cardtype;
|
||||
re1.cards = cards; //实际打出的牌(甩错时为单张)
|
||||
re1.shuaicuo = _shuaicuo;
|
||||
//合法甩牌的分量构成:cardtype 只能表达单一牌型,甩牌(单张/对子/拖拉机自由混搭,
|
||||
//design §5.4.3)会被压平成 1xx/2xx,客户端无从据此还原分组,故另行下发分量需求
|
||||
if (o_paiju.playproc.shuai_demand){
|
||||
re1.shuai = o_paiju.playproc.shuai_demand;
|
||||
}
|
||||
return re1;
|
||||
}
|
||||
|
||||
|
||||
@@ -477,6 +477,11 @@ youle_erqiwang.chupai = function(pack){
|
||||
msg.data.count = re.count;
|
||||
msg.data.flower = re.flower;
|
||||
msg.data.cardtype = re.cardtype;
|
||||
//合法甩牌的分量构成(design §5.4.3),供前端按 拖拉机/对子/单张 分组展示;
|
||||
//非甩牌(含甩错退化为单张)无此属性
|
||||
if (re.shuai){
|
||||
msg.data.shuai = re.shuai;
|
||||
}
|
||||
break;
|
||||
case 2: //第二个出牌
|
||||
msg.rpc = "chupai2";
|
||||
|
||||
@@ -133,6 +133,51 @@ t.eq('埋牌 不查牌 闲家无liangpai', mpXian && mpXian.data.liangpai, undef
|
||||
t.eq('重连 可查牌 PushCards有seatlist', E.get_deskinfo(e.o_room, 1).PushCards.seatlist !== undefined, true);
|
||||
t.eq('重连 不查牌 PushCards无seatlist', E.get_deskinfo(en.o_room, 1).PushCards.seatlist, undefined);
|
||||
|
||||
// ===================== §5.4 甩牌:chupai1 需下发分量构成 shuai(cardtype 表达不了甩牌)=====================
|
||||
// 主花色=♦(1)。庄家(0) 甩「主♦K对 + 主♦5单张」;两闲家手上一张主牌都没有 → 甩牌合法
|
||||
function mkShuai(extraToSeat1) {
|
||||
const pj = {
|
||||
idx: 1, step: 5, banker: 0, call: 65, flower: 1, callproc: [],
|
||||
seatlist: [[[0, 0], [0, 0], [0, 0], [0, 0], [-1, -1]], [[0, 0], [0, 0], [0, 0], [0, 0], [-1, -1]], [[0, 0], [0, 0], [0, 0], [0, 0], [-1, -1]]],
|
||||
playproc: {}, cards: make108()
|
||||
};
|
||||
for (let i = 0; i < 108; i++) pj.cards[i].dealowner = -1; // 先全部清空
|
||||
const give = (cid, s) => { pj.cards[cid].dealowner = s + 1; pj.cards[cid].playround = -1; };
|
||||
give(id(1, 1, 13), 0); give(id(2, 1, 13), 0); give(id(1, 1, 5), 0); // 庄家:主♦K对 + 主♦5
|
||||
give(id(1, 3, 9), 1); give(id(1, 3, 8), 1); give(id(2, 3, 9), 1); // 闲1:全副♥,无主牌
|
||||
give(id(1, 2, 9), 2); give(id(1, 2, 8), 2); give(id(2, 2, 9), 2); // 闲2:全副♣,无主牌
|
||||
if (extraToSeat1) give(extraToSeat1, 1); // 需要造甩错时给闲1一张大主牌
|
||||
pj.method = {
|
||||
check_cards_valid: c => P.check_cards_valid(pj, c),
|
||||
check_cards_inhand: (c, s) => P.check_cards_inhand(pj, c, s),
|
||||
do_playcard: c => P.do_playcard(pj, c),
|
||||
get_seat_cards: s => P.get_seat_cards(pj, s),
|
||||
have_baofu: () => (pj.seatlist[0][4][0] == 0 || pj.seatlist[1][4][0] == 0 || pj.seatlist[2][4][0] == 0)
|
||||
};
|
||||
P.new_playround(pj, 1, 0);
|
||||
return pj;
|
||||
}
|
||||
// 合法甩牌 → 带 shuai 分量
|
||||
let sh = mkShuai(null); let shc = setup("00000", sh);
|
||||
mod.chupai(pack(0, { cards: [id(1, 1, 13), id(2, 1, 13), id(1, 1, 5)] }));
|
||||
let shPk = shc.sent.filter(m => m.rpc === 'chupai1')[0];
|
||||
t.eq('甩牌 合法 下发 chupai1', !!shPk, true);
|
||||
t.eq('甩牌 打出3张', shPk && shPk.data.cards.length, 3);
|
||||
t.eq('甩牌 shuai=1对+1单张', shPk && shPk.data.shuai, { tractors: [], pairs: 1, singles: 1 });
|
||||
t.eq('甩牌 无 shuaicuo', shPk && shPk.data.shuaicuo, undefined);
|
||||
// 非甩牌(单一对子)→ 无 shuai
|
||||
sh = mkShuai(null); shc = setup("00000", sh);
|
||||
mod.chupai(pack(0, { cards: [id(1, 1, 13), id(2, 1, 13)] }));
|
||||
shPk = shc.sent.filter(m => m.rpc === 'chupai1')[0];
|
||||
t.eq('非甩牌(单一对子) 无 shuai', shPk && shPk.data.shuai, undefined);
|
||||
// 甩错(闲1 持大王,能压过主K对里的单张分量)→ 收回、只打最小一张、无 shuai
|
||||
sh = mkShuai((2 - 1) * 54 + 53); shc = setup("00000", sh); // 第二副大王给闲1
|
||||
mod.chupai(pack(0, { cards: [id(1, 1, 13), id(2, 1, 13), id(1, 1, 5)] }));
|
||||
shPk = shc.sent.filter(m => m.rpc === 'chupai1')[0];
|
||||
t.eq('甩错 shuaicuo=1', shPk && shPk.data.shuaicuo, 1);
|
||||
t.eq('甩错 只打出最小一张(主♦5)', shPk && shPk.data.cards, [id(1, 1, 5)]);
|
||||
t.eq('甩错 无 shuai 分量', shPk && shPk.data.shuai, undefined);
|
||||
|
||||
// ===================== 重连 PushCards.pushlist:结构恒 3 座位 + 按本局主牌花色排序 =====================
|
||||
// 造 5 轮已出牌的牌局(每轮每家 1 张),外加 seat0 在第 1 轮同时出「主5 + 副♥A」用于验证排序
|
||||
function mkPushlist() {
|
||||
|
||||
Reference in New Issue
Block a user