 joywayerandClaude Opus 5
|
f04bff4e9f
|
二七王:S-8 curmultiple 改为带符号
问题:S-1 实现时取了绝对值,而判定的正负号恰恰是「谁赢」的区分——
3 大光 vs -3 升3级、2 小光 vs -2 升2级、1 过庄 vs -1 升1级,取绝对值后
三对完全撞在一起,D-8 的过程中判定动画无从分辨该播哪个。
改法:get_curmultiple 直接返回 get_upgrade 原值,与结算包 aset.upgrade
完全同口径(3/2/1 庄家大光/小光/过庄,-N 闲家升N级,0 叫分未定)。
顶部「抓分」角标只关心大小,取 Math.abs 即可;判定动画靠符号分辨,
前端一套映射通吃「过程中」与「结算前」两条路径。
协议 4 处 curmultiple 说明同步(shangzhuang / chupai1 / chupai2·3 /
PushCards)。
测试(hint 33 → 46 checks):
- 钉住三对「绝对值相同、判定相反」的组合可区分,以及符号语义
(>0 庄赢 / <0 闲赢 / ==0 叫分未定)。
- 新增一组【直接调 get_curmultiple 本身】覆盖负数分支,含爬坡 Q 分段。
补上一个测试盲点:第一次反向验证(把实现退回取绝对值)竟然全绿——因为
原有断言里算法层的 cm() 走的是 A.get_upgrade、绕过了 get_curmultiple,
而端到端那局恰好是大光(正数),取不取绝对值都一样。补齐直接调用的用例后
再验,4 条断言立刻失败。
至此 §7.5 服务端待补 8 条全部完成,服务端侧无遗留;D-8 只差动画设计稿
与触发细节。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-26 12:42:29 +08:00 |
|
 joywayerandClaude Opus 5
|
76e82405e1
|
二七王:S-6 大局结算按 基础分/冲关分/傍王分 三项分解
问题:大局结算面板要分项显示,而 account 只有「累积得分 + 每局得分数组」。
傍王分尤其拆不出来——N = 冲关奖数 + 傍王王数,两个来源【求和之后】才代入
grade_aw = X×(2Ni−Nj−Nk),事后无法反推各自占比。
解法:在算钱时就拆。把 N 分成 N_冲关(只计庄家)与 N_傍王(勾选后庄闲都算),
分别代入同一公式各算一次。公式对 N 线性,故恒有
grade_cg + grade_bw == grade_aw
这条恒等式正好当回归断言用。
服务端:
- class.paiju.js 抽出 award_pay(n) 复用同一公式,新增 grade_cg / grade_bw;
desk.seatlist 追加三个累计位(基础/冲关/傍王)。
- class.desk.js seatlist 初始化为 5 元素;account 下发改为【对象数组】
{ score, grades, grade_jf_total, grade_cg_total, grade_bw_total }。
原二元数组下标语义不清,且前端未开工,此时改代价最小(同 S-4 的判断)。
协议:aset.seatlist 增补 grade_cg / grade_bw;account 结构与恒等式
grade_jf_total + grade_cg_total + grade_bw_total == score 写明;
并记录这次结构变更的时间与理由。
测试(endgame 26 → 39 checks):
- 核心不变量:两分量之和 == grade_aw;两分量各自零和。
- 未勾傍王局:grade_bw 恒 0、grade_cg == grade_aw。
- 【新增一整局开傍王的端到端】:不开傍王时 grade_bw 恒 0,只验到平凡情形,
必须有傍王局才算真验证了拆分。该局逐项复核两个分量的公式、naward 口径,
并钉住「王数不全相等时 grade_bw 必有非零」防止又退化成平凡。
- 大局累计恒等式:基础+冲关+傍王 == 累积总分。
反向验证:把 _awbw 置零 → 4 条断言失败;把冲关分量误算到闲家头上 →
2 条断言失败。均已还原、全量 17 文件全绿。
另修四处测试桩:_rpc.js / test_paiju / test_rpc / test_success 里手工构造的
o_desk.seatlist 仍是 2 元素,未跟上 class.desk.js 的结构变更(脚本缺陷,
非业务缺陷)。
顺带解决小局结算「冲关分」标签的不严谨:改取 grade_cg 而非 grade_aw,
开傍王时不再把傍王贡献算进来。
遗留 T-31:参考图「基础分」与「总得分」两行数值相同且与右侧大字对不上
(30/30 vs +135),mock 不自洽。当前按 基础分=grade_jf_total、总分=score
提供。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-26 00:34:46 +08:00 |
|
 joywayerandClaude Opus 5
|
b98f58effc
|
二七王:亮牌改为下发庄家全部固定主牌的具体牌面
规则变更(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>
|
2026-08-25 23:46:06 +08:00 |
|
 joywayerandClaude Opus 5
|
4aab71e6a3
|
二七王:实现 S-1 curmultiple 与 S-2 mustcard
S-1 当前抓分倍数(design §7.2.0):
- class.paiju.js 新增 get_curmultiple(),复用 get_qvalue + get_upgrade,
与结算 aset.upgrade 同源同算法,差别仅在不含扣底(末轮才产生)。
- 随现有包下发、不另开推送:shangzhuang / chupai1-3 / deskinfo.PushCards。
- 三家同值,整表下发不涉及泄露(捡分本就公开);叫分未定时为 0。
S-2 跟牌必出牌(design §5.2):
- class.paiju.js 新增 get_mustcard(seat),内部复用与出牌校验完全相同的
get_followcard,故建议与校验天然一致。
- 【只发给 nextseat 一家】:它是该玩家自己手牌的子集,整表下发会泄露
他家手牌结构(server 红线:发全 ≠ 发多)。
- 四种情形不下发:非出牌阶段、该座位是本轮首家、首家甩牌、必出牌为空。
甩牌一条尤其重要——甩牌跟牌走 flush_follow_ok 的逐分量匹配,与
get_followcard 不是同一条路径,给建议会给错。
测试(新增 test/test_hint.js,33 checks):
- curmultiple:算法层逐档对齐 design §7.2.0 判定表(含爬坡 Q 分段)、
三家同值、重连与出牌包一致、叫分未定为 0、与 get_upgrade 绝对值一致。
- mustcard:只有 nextseat 收到、另两家没有、内容确属收包者自己的牌、
首家无、缺门有富余时无、手牌数恰等于首家张数时整手必出、甩牌不发、
非出牌阶段不发、重连按 currseat 门控。
过程中修正的两个测试自身问题(均为脚本缺陷,非业务缺陷,业务判定经证据核实正确):
- 「缺门方无必出」原用例给闲2 只发 2 张牌,恰等于首家张数,get_followcard
正确判定为「整手必出」;改为发 4 张才留出选择余地,并补一条对照用例
锁住「恰等于张数则整手必出」这个正确行为。
- 「甩牌不发」「非出牌阶段不发」两条原本是假通过——桩的 startcount 仍是 -1,
前置守卫先返回了 null,根本没测到被测因素。改为先把桩推进到跟牌态、
每个用例只变动一个因素,并加一条「自证」用例确认推进后确实能算出必出牌。
另:mustcard 补进 test_leak.js 的 CARD_FIELDS 审计白名单(与 burycards 同理,
不加则误发不会被泄露审计发现)。反向验证:改成整表下发后,审计立刻报出
5 张越权牌;把 curmultiple 写死为 1 后,两条断言失败。均已还原、全绿。
协议文档同步 shangzhuang / chupai1-3 / PushCards 的字段说明。
至此 §7.5 服务端待补 5 条全部完成,服务端侧无遗留。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-25 20:25:32 +08:00 |
|
 joywayerandClaude Opus 5
|
916066ba96
|
二七王:修正 design 全量重核发现的 3 项不一致(亮牌快照/报无主下发面/甩牌张数上限)
- §8.2 亮牌改用埋牌后 28 张静态快照 get_seat_cards_award,不再用
get_seat_cards(只含未出的牌)——否则闲家重连时 get_deskinfo 按庄家
当前剩余手牌重算,亮牌统计缩水甚至变 null。
- §9 出牌包由只带出牌者一家的 info 改为整表下发三家 seatlist,与重连包
PushCards.seatlist 同名同构;报无主后另两家的主牌数/对子数不再滞后两次出牌。
- §5.4.3 甩牌"无组合数量限制":can_playcard 去掉规则外的 14 张硬上限,
改为结构性上界 28(单人手牌上限,牌型编码在此范围内不溢出)。
协议文档同步改写 chupai 三处 info 条目与 liangpai 口径;合规文档补记第四轮
核对(流程层无缺环,规则层 3 项已收口)。全套单测 368 项通过。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-16 19:33:06 +08:00 |
|
 joywayerandClaude Opus 5
|
8948a2950f
|
二七王: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>
|
2026-08-12 04:21:11 +08:00 |
|
 joywayerandClaude Opus 5
|
4276d38267
|
二七王:报无主后立即为全体三人刷新主牌统计
design §9:「一旦有玩家的主牌全部打空,系统就为全体三人显示另外
两家各自的主牌数量、以及这些主牌里有多少对子」。
原实现只在出牌者自己出牌时更新自己那一格 seatlist[seat][4],所以
A 打空主牌报无主的那一刻,B、C 的主牌数/对子数仍是初始 [-1,-1],
要等各自轮到出牌才补上,界面最多滞后两次出牌才完整。
改为:出牌后先判定出牌者主牌是否出空,一旦 have_baofu() 成立,就
按各家实际手牌为三个座位统一重算 [剩余主牌数, 剩余主对数] 及主花
色标志。重算幂等——主牌一旦出空不会再有,[4][0] 恒为 0。
test_rpc 的 mkChupai 原先只把 seatlist[1][4][0] 置 0 伪造报无主,
而不真的清空 seat1 的主牌;新逻辑按实际手牌重算会把这个假状态纠
正回去,导致 baozhu 断言失败。这是新实现更严格的正确表现,故改测
试造真状态(把 seat1 的主牌标为已出),不是放宽断言。
test_input 新增 6 项:报无主前三家均为 [-1,-1];打空瞬间三家统计
与主花色标志同时刷新到实际值。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-12 04:20:03 +08:00 |
|
 joywayerandClaude Opus 5
|
c2a375eef5
|
二七王:补齐 data.success 成败标志与失败回包
此前全仓(除协议文档开头一句说明外)没有任何下发包携带
data.success,且所有失败路径一律裸 return、不回任何包:前端点了
没反应,只能干等倒计时,同时违反 server dev-guide「成败标志唯一
是 data.success,主动推送的 data 必须自带 success」与 client
dev-guide「发包只请求、收包才表现」两条硬红线。
本次:
- 成功包一律补 data.success=true:fapai、zhunbei(class.desk.js)、
jiaofen、shangzhuang、xuanzhu、maipai、chupai1/2/3、mingpai、
tishi(mod.js),jiesuan 在 get_paiju_account 统一注入(覆盖
正常/投降/解散三种结算来源)。
- 新增 youle_erqiwang.ERR 失败码表与 do_sendfail 统一回包封装:
PLAYER/NODESK/STEP/SEAT/PARAM/RULE,失败只回发给请求者
(conmode/fromid 取自请求包),data.success=false + errcode。
- 每个 handler 的每条失败分支都改为「回失败包 + return」,含
check_player 不通过(平台侧只返回 null、不回包,前端会干等)。
tishi 成功时仍按 design §11 只转发给对家、不给发送者回执(该包不
含对局状态,属 fire-and-forget 提示),失败才回给发送者。
test_rpc 中原先以「不发包」表示被拒的断言,同步改为断言「恰好回
1 个 success=false 且 errcode 正确的包」——是随行为修正而加强,
不是软化。新增 test_success.js 29 项覆盖成功包 success 字段与各
handler 失败回包。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-12 04:15:31 +08:00 |
|
 joywayerandClaude Opus 5
|
a4a8eb8408
|
二七王:补齐客户端牌id入参校验(重复/越界/非数组)
check_cards_inhand 此前只逐个校验牌id是否在手上,不查重复、不查
类型与范围,且在牌已出/已埋时 return 空值而非 false,造成两个可
被利用的缺陷:
1. 重复牌id 可伪造牌型:do_playcard([方块K,方块K]) 实测返回
result=true、cardtype=201(同一张牌被判成一对),可进而伪造
拖拉机与甩牌分量,本轮结算时该分牌的 score 还会被重复累加。
2. 埋牌传 8 个相同 id 实测只埋下 1 张,庄家带 35 张进入出牌阶段,
整局牌数错乱。
3. 越界 id 或非数组入参会在解引用处抛异常,中断 DoPack。
新增 check_cards_valid 作为唯一入参校验入口(非空数组、元素为本
局牌表内的整数牌id、互不重复),由 check_cards_inhand 先行调用;
mod.maipai/mod.chupai 在读取 cards.length 之前先过该校验。按
engineering §03「显式失败优于隐式兜底」直接拒绝,不做类型兜底。
新增 test_input.js 28 项正/反/边界用例回归上述三点。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-12 04:10:15 +08:00 |
|
 joywayerandClaude Opus 4.8
|
60271175d6
|
二七王:逻辑文件补双运行时守卫,解锁 Node 单测
按 dev-guide 01 §1「一套代码,两个运行时」补齐 erqiwang 缺失的守卫(此前只支持友乐全局加载模型):
- 顶部:跨模块依赖走 `if (typeof require!=='undefined') var X=require('./class.X.js')`
(config/pai/arith 无跨模块依赖;paiju 依赖 arith/config/pai;desk 依赖 paiju;export 依赖 arith/config/desk)
- 底部:`if (typeof module!=='undefined') module.exports = cls_X`
- export/import 的平台接线 `youle_erqiwang.X=...` 加 `typeof youle_erqiwang` 守卫,Node 无此全局时跳过
纯增量:友乐无 require(浏览器模型),守卫全部跳过、全局名仍无条件暴露,线上行为不变;
仅在 Node 下额外启用 require/module.exports,从而可用 node 直接单测。min_*/youle_erqiwang 等平台全局仍按全局名引用(Node 侧由测试 shim 提供)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-04 23:51:12 +08:00 |
|
 joywayerandClaude Opus 4.8
|
257615aed9
|
二七王:实现 §5.4.4 强制跟牌分量拆解
原缺陷:混合甩牌在 can_playcard 牌型计算中被塌缩为扁平"多单张/多对",
跟牌只强制"同花色凑张数",未强制"拖拉机→对子→单张"的分量优先级。
修复:
- 合法甩牌时 can_playcard 记录分量需求 shuai_demand{tractors,pairs,singles},
do_playcard 存入 playproc、new_playround 复位
- 新增 arith.flush_follow_ok:在"同花色凑张数、主牌最大化"之上追加逐分量强制匹配
——能凑同长主拖必凑、能凑主对必凑(不足则退化为对子/单张),不得拆散去垫
- 新增 arith.remove_pairs 辅助
- 跟牌时 do_playcard 在 can_followcard 通过后再过 flush_follow_ok
不影响捡分/输赢(合法甩牌仍恒不可反超),仅补齐闲家被迫垫牌的结构约束。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-04 23:20:09 +08:00 |
|
 joywayerandClaude Opus 4.8
|
6120580505
|
二七王服务端:按 design.md 整改结算/算奖/甩牌,roomtype 改位串
结算与算奖(§6.3/§7/§8)
- 扣底倍数改线性:单张×1、主对×2、N连对×2N
- 算子实现常规算子 + 爬坡两套(大光×3、Q=40 / 爬坡分段),X=基础子数×判定倍率
- 常规算奖只计庄家;连对链修复(传实际主花色);移除 ≥10 老主误加奖与设计外的
「冲关必叫/四王必踢」作废;算奖快照取庄家埋牌后28张(新增 get_seat_cards_award)
- 算奖并入结算改为 X×(2Ni−Nj−Nk);傍王按房间开关、庄闲每王1奖
出牌与甩牌(§5.4)
- 副牌绝对禁甩;甩牌最大性按对手全部手牌逐分量判定(新增 trump_rank/
decompose_trump/opp_can_beat_flush);甩错惩罚(收回、只打最小一张、下发 shuaicuo)
- 修复 can_followcard 引用未定义 tuolaji_list 的崩溃、can_playcard 14张上限失效
开局/投降/暗牌(§4)
- 投降改为选主阶段(step2)与选主互斥、不埋牌、算奖用庄家36张;埋牌后直进出牌(删废弃step4)
- 70分暗牌摸牌前向所有玩家亮3秒(+ancard3s),非70分不再泄露暗牌给闲家;叫分上限≤70
查牌/亮牌(§8.2/§9)
- 新增亮牌 get_liangpai(庄家埋牌后28张按阈值统计);报无主统计与亮牌按查牌位门控
- 新增 mingpai 明牌 RPC(可查牌+已报无主时查看他家全部主牌)
房间与配置(§10)
- 局数6/12、房主扣卡2/4;新增 class.config.js 以位串解析 roomtype(唯一入口 SSOT)
- 清理 do_choiceflower 死代码
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-04 22:32:53 +08:00 |
|
joywayer
|
96372d713c
|
规则文档理清楚,开始代码层面对比和校对
|
2026-07-04 09:52:49 +08:00 |
|