清单 §0.4 的唯一权威转换:服务端花色段序与美术帧顺序相反, 转换把花色段反过来数。用清单给的 10 条样例逐条锁死, 另加两副牌同帧、值域、单射三组断言。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
58 lines
1.9 KiB
JavaScript
58 lines
1.9 KiB
JavaScript
// cardId → 牌面帧号(清单 §0.4 唯一权威转换)
|
||
const { load } = require('./_load');
|
||
const t = require('./_assert')();
|
||
|
||
load('client/js/01_SubGame/codes/core/CardCodec.js');
|
||
|
||
// ---- 清单 §0.4 的 10 条校验样例,逐条锁死 ----
|
||
const cases = [
|
||
[0, 40, '方块A'],
|
||
[4, 44, '方块5'],
|
||
[12, 52, '方块K'],
|
||
[13, 27, '梅花A'],
|
||
[26, 14, '红桃A'],
|
||
[39, 1, '黑桃A'],
|
||
[51, 13, '黑桃K'],
|
||
[52, 53, '小王'],
|
||
[53, 54, '大王'],
|
||
[106, 53, '小王(deck2)']
|
||
];
|
||
cases.forEach(c => t.eq('帧号 ' + c[2] + ' id=' + c[0], EQW_CardCodec.cardIdToFrame(c[0]), c[1]));
|
||
|
||
// ---- 两副牌同一张牌共用同一帧 ----
|
||
for (let id = 0; id < 54; id++) {
|
||
if (EQW_CardCodec.cardIdToFrame(id) !== EQW_CardCodec.cardIdToFrame(id + 54)) {
|
||
t.eq('deck1/deck2 同帧 id=' + id, false, true);
|
||
}
|
||
}
|
||
t.eq('deck1/deck2 全部同帧', true, true);
|
||
|
||
// ---- 帧号值域:54 张牌只落在 1–54 ----
|
||
let inRange = true;
|
||
for (let id = 0; id < 108; id++) {
|
||
const f = EQW_CardCodec.cardIdToFrame(id);
|
||
if (!(f >= 1 && f <= 54)) { inRange = false; }
|
||
}
|
||
t.eq('帧号值域 1-54', inRange, true);
|
||
|
||
// ---- 单射:deck1 的 54 张牌映射出 54 个互不相同的帧 ----
|
||
const seen = {};
|
||
let dup = false;
|
||
for (let id = 0; id < 54; id++) {
|
||
const f = EQW_CardCodec.cardIdToFrame(id);
|
||
if (seen[f]) { dup = true; }
|
||
seen[f] = true;
|
||
}
|
||
t.eq('54 张牌帧号互不重复', dup, false);
|
||
t.eq('恰好覆盖 54 个帧', Object.keys(seen).length, 54);
|
||
|
||
// ---- 二七王不使用 3、4 的帧(design §2 去掉 3 和 4)----
|
||
// 方块3 id=2 → 帧42,方块4 id=3 → 帧43;资源仍按 60 帧通用排版出图,只是不引用
|
||
t.eq('方块3 帧号', EQW_CardCodec.cardIdToFrame(2), 42);
|
||
t.eq('方块4 帧号', EQW_CardCodec.cardIdToFrame(3), 43);
|
||
|
||
// ---- 牌背常量 ----
|
||
t.eq('牌背帧', EQW_CardCodec.CARD_BACK_FRAME, 55);
|
||
|
||
process.exit(t.done('cardcodec') ? 0 : 1);
|