二七王:亮牌改为下发庄家全部固定主牌的具体牌面
规则变更(design §8.2):原先「只亮数量/结构,不亮具体是哪几张牌」,现改为
向两个闲家亮出【庄家手中全部固定主牌的具体牌面】。
- 固定主牌 = 双王 + 全部花色的 2 + 全部花色的 7,【不含】主花色普通牌
A/K/Q/J/10/9/8/6/5。注意这与旧实现收集的「所有主牌」范围不同。
- 门槛不变(固定主牌总数 ≥10 / 王 ≥3 / 7 ≥6 / 2 ≥6,任一满足)。
- 不限叫分;仅可查牌模式下发;亮出的是固定的一份,不随被哪条门槛触发而增减。
- 协议 liangpai 由 {zhu,zhupair,zhutuo,wang,qi,er} 数量结构改为 {cards:[牌id...]},
数量交由前端从 cards 自行计算。
服务端 get_liangpai() 重写(class.paiju.js);design §8.2 整节重写,术语表、
易混对照表、§9 相应更新;协议 §0.0b 与 maipai / PushCards 两处字段说明同步。
测试:
- test_paiju 亮牌用例按新规则重写(54 checks)。新增两条针对性用例:
「只含固定主牌·主花色普通牌未混入」与「同时满足多档仍只亮同一份」——
前者正是这次范围变更最容易写错的地方。
- test_leak 增加亮牌可见性规则。关键点:期望集合【独立于 get_liangpai 重算】,
而不是复用被测实现——否则实现若误塞非固定主牌,审计会跟着放行、抓不住。
反向验证证实了这一点:故意让 get_liangpai 混入主花色普通牌后,审计确实报警。
发现并修复一处假绿:原 6 局随机牌序下庄家一次都没达到亮牌门槛,即
「下发面无越权泄露」对亮牌这条路径根本没走到。现追加换牌序的 4 局(保留
原 6 局覆盖不动),并加两条覆盖断言钉住「可查牌达标 ≥1 局」「不查牌达标
≥1 局」,防止以后再退化成碰巧没触发。反向验证:去掉不查牌门控后审计立即
报出 5 张越权牌。
待定:T-34 亮牌的展示时机(出牌前一次性弹出 / 随时可查)。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -762,49 +762,42 @@ var cls_youle_erqiwang_paiju = cls_youle_erqiwang_paiju || {
|
||||
//手牌来源必须是 get_seat_cards_award 的【静态快照】(埋牌后 28 张,含之后已打出的),
|
||||
//不能用 get_seat_cards(只取未出的牌):出牌开始亮出的这份统计全局固定、不随出牌缩水,
|
||||
//否则闲家断线重连后 get_deskinfo 会按庄家当前剩余手牌重算,亮牌信息缩水甚至变成 null
|
||||
//亮牌(design §8.2):庄家埋牌后、出牌前,若手中【固定主牌】达到门槛,
|
||||
//就向两个闲家亮出【自己全部固定主牌的具体牌面】。
|
||||
// 固定主牌 = 双王 + 全部花色的 2 + 全部花色的 7,【不含】主花色的普通牌 A/K/Q/J/10/9/8/6/5
|
||||
// 门槛(任一满足即亮):固定主牌总数 ≥10 / 王 ≥3 / 7 ≥6 / 2 ≥6
|
||||
// 不限叫分;是否真的发给闲家由调用方按查牌模式门控(design §9)
|
||||
//返回 { cards: [牌id...] }(按本局主牌序从大到小),不达标返回 null。
|
||||
//注意:亮出的内容是固定的一份,不随"被哪一条门槛触发"而增减。
|
||||
get_liangpai: function(o_paiju){
|
||||
if (o_paiju.banker < 0){
|
||||
return null;
|
||||
}
|
||||
//静态初始手牌快照(与 8.1 算奖同源):庄家埋牌后的 28 张
|
||||
var cards = cls_youle_erqiwang_paiju.get_seat_cards_award(o_paiju, o_paiju.banker);
|
||||
var wang = 0, qi = 0, er = 0;
|
||||
var zhucards = [];
|
||||
var gudingcards = []; //固定主牌
|
||||
for (var i = 0; i < cards.length; i++){
|
||||
var num = cls_youle_erqiwang_arith.id_to_number(cards[i]);
|
||||
var flw = cls_youle_erqiwang_arith.id_to_flower(cards[i]);
|
||||
if (num >= 53){ wang = wang + 1; }
|
||||
if (num == 7){ qi = qi + 1; }
|
||||
if (num == 2){ er = er + 1; }
|
||||
//主牌 = 主花色普通牌 或 王 或 任意 2/7
|
||||
if (flw == o_paiju.flower || flw == 5 || num == 2 || num == 7){
|
||||
zhucards.push(cards[i]);
|
||||
if (num >= 53){ //大王 54 / 小王 53
|
||||
wang = wang + 1;
|
||||
gudingcards.push(cards[i]);
|
||||
} else if (num == 7){ //任意花色的 7
|
||||
qi = qi + 1;
|
||||
gudingcards.push(cards[i]);
|
||||
} else if (num == 2){ //任意花色的 2
|
||||
er = er + 1;
|
||||
gudingcards.push(cards[i]);
|
||||
}
|
||||
}
|
||||
var guding = wang + qi + er; //固定主牌(王 + 全部 2 + 全部 7)
|
||||
var re = {};
|
||||
var has = false;
|
||||
if (guding >= 10){
|
||||
zhucards = cls_youle_erqiwang_arith.order_cards(o_paiju.flower, zhucards);
|
||||
var pairs = cls_youle_erqiwang_arith.get_pairlist(o_paiju.flower, zhucards);
|
||||
var comps = cls_youle_erqiwang_arith.decompose_trump(o_paiju.flower, zhucards);
|
||||
var tuo = 0;
|
||||
for (var c = 0; c < comps.length; c++){
|
||||
if (comps[c].type == "tractor"){ tuo = tuo + 1; }
|
||||
}
|
||||
re.zhu = zhucards.length; //主牌总数
|
||||
re.zhupair = pairs.length; //主对子数
|
||||
re.zhutuo = tuo; //主拖拉机组数
|
||||
has = true;
|
||||
}
|
||||
if (wang >= 3){ re.wang = wang; has = true; }
|
||||
if (qi >= 6){ re.qi = qi; has = true; }
|
||||
if (er >= 6){ re.er = er; has = true; }
|
||||
if (!has){
|
||||
//门槛判定(design §8.2)
|
||||
if (gudingcards.length < 10 && wang < 3 && qi < 6 && er < 6){
|
||||
return null;
|
||||
}
|
||||
var re = {};
|
||||
re.cards = cls_youle_erqiwang_arith.order_cards(o_paiju.flower, gudingcards);
|
||||
return re;
|
||||
},
|
||||
|
||||
//获取抠底包
|
||||
get_bottom_account: function(o_paiju, msg){
|
||||
msg.data.bottom = {};
|
||||
|
||||
Reference in New Issue
Block a user