二七王:修正重连出牌历史 pushlist 的结构与排序

get_deskinfo 的 PushCards.pushlist 排序段有两处错:

1. 内层循环上界误用 pushlist.length(轮次数)当座位数。轮次 >3 时
   会给内层数组写入下标 3..轮次-1,把本应恒为 3 个座位的数组撑成
   轮次长度并填满 undefined;轮次 <3 时又漏排后面的座位。实测 5 轮
   时内层长度变成 5 且含 undefined。
2. 排序传的是上一个 for 循环泄漏出来的 pai.flower。循环结束后 pai
   指向牌表最后一张(大王,flower=5),等于按「无主牌花色」排序,
   主牌不会排到副牌前面。

改为内层固定 3 个座位、按 paiju.flower 排序,并对缺失轮次加守卫。

test_rpc 新增 4 项:轮数、内层恒 3、无 undefined,以及排序判别用例
(seat0 同轮出「主5 + 副♥A」,主5 必须在前——旧代码下 副A 会排前)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 04:18:30 +08:00
co-authored by Claude Opus 5
parent 5832b781c8
commit 84774fa525
2 changed files with 47 additions and 3 deletions
+38
View File
@@ -130,6 +130,44 @@ 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);
// ===================== 重连 PushCards.pushlist:结构恒 3 座位 + 按本局主牌花色排序 =====================
// 造 5 轮已出牌的牌局(每轮每家 1 张),外加 seat0 在第 1 轮同时出「主5 + 副♥A」用于验证排序
function mkPushlist() {
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: { round: 5, start: 0, currseat: 0, cards: [[], [], []] },
cards: make108()
};
for (let i = 0; i < 108; i++) pj.cards[i].dealowner = (i % 3) + 1;
// 每轮每家一张
let next = 0;
for (let r = 1; r <= 5; r++) for (let s = 0; s < 3; s++) {
for (let i = next; i < 108; i++) {
if (pj.cards[i].dealowner === s + 1 && pj.cards[i].playround === -1) { pj.cards[i].playround = r; break; }
}
}
// seat0 第1轮补出:主5(flower1) 与 副♥A(flower3),主牌必须排在副牌前
const zhu5 = id(1, 1, 5), fuA = id(1, 3, 1);
for (const c of [zhu5, fuA]) { pj.cards[c].dealowner = 1; pj.cards[c].playround = 1; }
pj.method = {
get_seat_cards: s => P.get_seat_cards(pj, s),
get_jian_grade: () => P.get_jian_grade(pj),
get_burycard: () => P.get_burycard(pj),
get_liangpai: () => null
};
return { pj, zhu5, fuA };
}
const pl = mkPushlist();
const plRoom = setup("00000", pl.pj).o_room;
const di = E.get_deskinfo(plRoom, 1).PushCards.pushlist;
t.eq('重连 pushlist 轮数=5', di.length, 5);
t.eq('重连 pushlist 每轮恒3个座位', di.map(r => r.length), [3, 3, 3, 3, 3]);
t.eq('重连 pushlist 不含 undefined', di.some(r => r.some(x => x === undefined)), false);
// 第1轮 seat0 的牌:主5 必须排在副♥A 之前(按 paiju.flower=1 排序,而非泄漏的大王花色5)
t.eq('重连 pushlist 按本局主牌花色排序(主5在副A前)',
di[0][0].indexOf(pl.zhu5) < di[0][0].indexOf(pl.fuA), true);
// ===================== §7.3 下发面 multiple 必须随「爬坡」开关取值(与结算 aset.multiple 同源)=====================
// 叫 45 分:常规算子基础子数 6(design §7.1「50 及以下统一 6」),爬坡 7(design §7.3.1)
const A = require('../class.arith.js');