Files
erqiwang_youle/server/games/erqiwang/test
joywayerandClaude Opus 4.8 21e76b976a 二七王修复:拖拉机跟牌降级递归 else 分支欠约束(放行非法跟牌)
get_followcard 降规格递归中,当某级"等长短拖拉机候选总对数 > 剩余需求"
时(class.arith.js else 分支),因 cantype 单一结构模型无法表达"任选其一
成拖拉机、其余自由",直接返回宽松的"任意 N 对",导致跟牌方明明有 2 连对
却被允许只出三个孤立对子(如首家 3 连对、跟牌方 AA KK JJ TT 88 66 时打
AA JJ 88),违反 design §5.2"能凑多长拖拉机就必须先凑多长"。

方案 2(根治,不引入过约束):在 can_followcard 结构校验后新增"最大拖拉机
覆盖度"闸门 follow_tractor_cover_ok——
- tractor_run_lengths:把同花色对子按相邻拆成连对 run 长度表;
- max_tractor_profile:贪心最长优先取 K 对,得字典序最大规格档案 best;
- profile_less:跟牌自身档案 got 不得字典序劣于 best,否则拒。
仅在"跟牌整手=首家花色对子且该花色牌≥首家张数"时生效,垫/混合/对子不够
等一律放行。can_followcard 是唯一出牌闸门(paiju.js:605),覆盖人工+托管。
get_followcard else 分支加注释指明由该闸门兜底。

回归测试:test_follow.js +5 条(303/304 三组 2 连对场景,含 else 欠约束
回归:出孤立对→拒、出尽量长拖→合法)。全套 259 项断言通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 07:18:42 +08:00
..

二七王服务端单元测试

运行

node server/games/erqiwang/test/run.js      # 跑全部单测
node server/games/erqiwang/test/test_arith.js   # 单独跑某一组

退出码 0 表示全过,非 0 表示有失败;run.js 逐个以独立进程 spawn 各 test_*.js 并汇总。

原理:一套代码,两个运行时(dev-guide 01 §1)

正式代码(class.*.js)遵循平台的双运行时规范:

  • 友乐 / 浏览器:无 require,由 mod.js 用 min_loadJsFile 加载为全局对象;文件顶部的 if (typeof require !== 'undefined') 守卫被跳过,跨模块按同名全局引用。
  • Node(本地 / 单元测试):有 require,守卫块 var X = require('./class.X.js') 取到依赖;文件底部 if (typeof module !== 'undefined') module.exports = ... 导出。

因此这两处守卫是纯增量:友乐运行时行为完全不变,只在 Node 下额外启用 require/exports。

_shim.js:平台全局垫片(仅测试用,不进正式代码)

正式代码按全局名引用少量平台工具(min_ary_include/min_ary_deduct/min_random/min_now/min_ontimeout)与模块入口 youle_erqiwang.import。友乐由平台提供,Node 单测由 test/_shim.js 提供等价实现(数组/随机工具忠实复刻 server/minhttp.js,youle_erqiwang.import 用 mock)。测试文件顶部先 require('./_shim') 再 require('../class.*.js')。

测试计划

完整的"规则 → 用例"覆盖矩阵、缺口清单与优先级见 ../docs/compliance/02-测试计划.md。

覆盖

  • test_arith.js:主牌排序/相邻链(§3)、扣底倍数(§6.3)、算子常规+爬坡逐档+分界+升3级(§7)、算奖 get_chongguan(§8.1)、甩牌分解/最大性/合法性(§5.4)、跟甩牌强制分量拆解(§5.4.4)。
  • test_follow.js:正常跟牌/毙牌/垫牌,单张/对子/拖拉机的必出与缺门毙牌数量对应(§5.1/5.2)。
  • test_callgrade.js:叫分坐庄 do_callgrade(叫5立即/两家不叫/后叫更低)(§4.2)。
  • test_config.js:roomtype 位串解析、局数/扣卡映射(§10.1)。
  • test_paiju.js:亮牌 get_liangpai(§8.2)、结算 get_paiju_account 集成(§7/§8,大光/过庄/升级/爬坡/傍王/投降)、扣底触发 get_bottom_account(§6.3)。
  • test_deal.js:发牌构成——92张/去3-4/三家28+底8/分值(§2/§6.1)。
  • test_desk.js:坐庄轮换 do_prepare(庄赢连庄/闲赢·投降下家)(§4.6)。
  • test_rpc.js(L3,用 _rpc.js 装配 mod.js + 捕获下发包):明牌 mingpai、出牌 chupai 的 info/baozhu 查牌门控(§9)、投降 touxiang 条件、jiaofen 入参校验、70分上庄暗牌亮牌下发(§4)。

约定(dev-guide §10 测试纪律)

  • 测试代码可用现代 JS(不受严格 ES5 限制);正式代码不得为测试放宽/加后门。
  • 正反面 + 边界都要覆盖;失败先裁根因(业务缺陷改业务、脚本缺陷改脚本),不软化断言。