绘制修复(mini-desktop CDP 复验揪出:战斗屏除回合横幅外 lumStd=0 全空,逻辑与指针全通):根因=run-scene.js
const txt 声明位于工厂 return 之后永不执行,txt 永陷 TDZ,全部整屏绘制函数每帧 ReferenceError 无声失败,
唯 floatText(function 声明提升)独活=只剩横幅;M1 并入 run-scene 时引入,headless 门不建场景故只有真浏览器
暴露。修=txt 改 function 声明(提升语义)+事故注释钉原地+自证钩子(场景 rebuild 后回写
readState().debug={displayCount,rebuilds,screen} 供 CDP 机断)+防回潮门 scene-smoke.mjs(mock 场景重放十屏/
异常零容忍/每屏绘制对象≥5;修复后 map=33/battle=32/reward=14)。
M3:S13 职业乙 66+中立 22=154 卡定容(static-screen 3,676,134 序列零经济环)+S14 进阶 ASCENSIONS 16 级入
矩阵轴+多样性 driver(chain/defensive 档,死卡候选 42 张如实挂账 README)+S15 meta 三件(图鉴/成就 40/每日,
meta-core.js+meta.test)+S16 事件 45;存档 v2 双域+v1 迁移链(19 断言);home 局外模式机+终局结算。
门证据:八门全绿(battle-core/logic-smoke/run-core+R15 职业进阶 7 断言/run-smoke/save v2 19 断言/meta/
static-screen/scene-smoke);六带全绿 nightly n=1000/格(甲 A0 58.2%/A5 32.2%/A15 6.9%,乙 55.1%/28.3%/5.7%,
带 45–60/25–40/5–15);构筑指纹去重 A0 六格全 100%(门>85% 草案);金标 26 套(甲 20 漂移≤3.6pp 全 PASS+乙 6 首锁);
**全矩阵 96,000 局书面口径首次真跑=158.6s、nightly 总 223.2s**;平衡轮主杠杆=职业起始遗物 +36.6pp;
主会话真跑复验八门+PR 层。浏览器像素复验随本笔 push 后触发。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
131 lines
6.2 KiB
JavaScript
131 lines
6.2 KiB
JavaScript
/**
|
||
* scripts/static-screen.mjs —— 《山海巡异录》静态快筛(M2 S9;链护栏第①层 + 估值黄牌)
|
||
* owner:北极星顶级线③(M2)
|
||
*
|
||
* 【验什么】设计书 §6.3 无限连护栏·静态快筛层:对卡池做深度 ≤3 的有序组合遍历,
|
||
* 标红「净能量增益 + 净抽卡增益」同时为正的闭环(exit 1=命中,须同池禁入或加疲劳规则)。
|
||
* 本层只覆盖 ≤3 卡短闭环,是快筛不是证明;≥4 卡长循环靠运行时动作护栏+指纹观测兜(②③层)。
|
||
* 附带:估值黄牌普查(valuation.js 单源,advisory 只打印不拦——平衡门裁定二)。
|
||
*
|
||
* 【词汇封闭假设】经济环只由 energy/draw/chainBonus{energy,draw}/costChainDiscount 四词构成,
|
||
* 本筛用表级折算器(链态是唯一动态,精确可算)。E0 断言钉死封闭性:表中出现的经济词
|
||
* 若超出折算器词汇集,立即 FAIL——新经济词入表必须先扩本筛,防绕过。
|
||
*
|
||
* 用法:node scripts/static-screen.mjs(退出码 0=无命中;S9/S10 每批入表即跑)
|
||
*/
|
||
|
||
'use strict';
|
||
|
||
import { CARDS, ELEMENT_CYCLE } from '../src/data/tables.js';
|
||
import { valueOf } from '../src/sim/valuation.js';
|
||
import { isShengNext } from '../src/battle-core.js';
|
||
|
||
let failures = 0;
|
||
const fail = (msg) => { console.error(` FAIL ${msg}`); failures++; };
|
||
|
||
console.log(`[static-screen] 卡池 ${CARDS.length} 张;深度 ≤3 经济环快筛 + 估值黄牌`);
|
||
|
||
// ── E0 经济词汇封闭性(折算器认知集 = 表中实际经济词集;漂移即红)──
|
||
const ECON_WORDS = new Set(['energy', 'draw', 'chainBonus', 'costChainDiscount', 'ifZhoutian']);
|
||
{
|
||
const seen = new Set();
|
||
for (const c of CARDS) {
|
||
for (const k of Object.keys(c.effects)) {
|
||
// 产能量/产抽卡的词才是经济词;伤害/护甲/词缀/血价不构成经济环。
|
||
if (k === 'energy' || k === 'draw' || k === 'costChainDiscount') seen.add(k);
|
||
if (k === 'chainBonus' && (c.effects.chainBonus.energy || c.effects.chainBonus.draw)) seen.add('chainBonus');
|
||
if (k === 'ifZhoutian' && (c.effects.ifZhoutian.energy || c.effects.ifZhoutian.draw)) seen.add('ifZhoutian');
|
||
}
|
||
}
|
||
const unknown = [...seen].filter((w) => !ECON_WORDS.has(w));
|
||
if (unknown.length) fail(`E0 经济词超出折算器词汇集:${unknown.join(',')}(先扩本筛再入表)`);
|
||
else console.log(` PASS E0 经济词汇封闭(${[...seen].join(',') || '无'})`);
|
||
}
|
||
|
||
// ── E1 深度 ≤3 有序序列遍历(同名可重复=卡组多份合法)──
|
||
{
|
||
/**
|
||
* 表级折算一个序列:按打出序推链态,算净能量(得-费)与净抽(抽-打出数)。
|
||
* 费用折扣(costChainDiscount)与成链加成(chainBonus)按相生序精确判定。
|
||
*/
|
||
function evalSeq(seq) {
|
||
let prevEl = null;
|
||
let netEnergy = 0;
|
||
let netDraw = 0;
|
||
for (const c of seq) {
|
||
const extendsChain = prevEl != null && isShengNext(prevEl, c.element);
|
||
let cost = c.cost;
|
||
if (c.effects.costChainDiscount && extendsChain) cost = Math.max(0, cost - c.effects.costChainDiscount.n);
|
||
netEnergy -= cost;
|
||
if (c.effects.energy) netEnergy += c.effects.energy.n;
|
||
if (c.effects.draw) netDraw += c.effects.draw.n;
|
||
if (c.effects.chainBonus && extendsChain) {
|
||
if (c.effects.chainBonus.energy) netEnergy += c.effects.chainBonus.energy;
|
||
if (c.effects.chainBonus.draw) netDraw += c.effects.chainBonus.draw;
|
||
}
|
||
// ifZhoutian(M3):周天须五行全环,深度 ≤3 序列数学上不可能触发——本筛零入账即精确;
|
||
// ≥4 卡的周天经济环归运行时兜底层+指纹观测(§6.3 分层设防,快筛不越界宣称)。
|
||
netDraw -= 1; // 打出即消耗一张手牌
|
||
prevEl = c.element; // 延续与破序殊途同归:链尾都是本卡元素(破序=重开链,链首=本卡)
|
||
}
|
||
return { netEnergy, netDraw };
|
||
}
|
||
|
||
const hits = [];
|
||
const n = CARDS.length;
|
||
let checked = 0;
|
||
// 深度 1–3 全遍历(66³≈28.7 万序列,表级毫秒批)。
|
||
for (let a = 0; a < n; a++) {
|
||
const r1 = evalSeq([CARDS[a]]);
|
||
checked++;
|
||
if (r1.netEnergy > 0 && r1.netDraw > 0) hits.push([CARDS[a].id]);
|
||
for (let b = 0; b < n; b++) {
|
||
const r2 = evalSeq([CARDS[a], CARDS[b]]);
|
||
checked++;
|
||
if (r2.netEnergy > 0 && r2.netDraw > 0) hits.push([CARDS[a].id, CARDS[b].id]);
|
||
for (let c = 0; c < n; c++) {
|
||
const r3 = evalSeq([CARDS[a], CARDS[b], CARDS[c]]);
|
||
checked++;
|
||
if (r3.netEnergy > 0 && r3.netDraw > 0) hits.push([CARDS[a].id, CARDS[b].id, CARDS[c].id]);
|
||
}
|
||
}
|
||
}
|
||
if (hits.length) {
|
||
fail(`E1 经济环命中 ${hits.length} 条(样本:${hits.slice(0, 5).map((h) => h.join('→')).join(' | ')})`);
|
||
} else {
|
||
console.log(` PASS E1 深度 ≤3 无「净能量+净抽卡同正」闭环(遍历 ${checked} 序列)`);
|
||
}
|
||
}
|
||
|
||
// ── E2 估值黄牌普查(advisory:超稀有度帽打印;超 hardCap 才 FAIL,与 T1e 同线)──
|
||
{
|
||
const overCaps = [];
|
||
let overHard = null;
|
||
for (const c of CARDS) {
|
||
const v = valueOf(c);
|
||
if (v.overCap) overCaps.push(`${c.name}(${c.rarity})=${v.value}>帽${v.cap}`);
|
||
if (v.overHard) overHard = `${c.name}=${v.value}`;
|
||
}
|
||
if (overCaps.length) console.log(` WARN 估值黄牌 ×${overCaps.length}(advisory):${overCaps.join(' / ')}`);
|
||
else console.log(' PASS E2 全池估值均在稀有度帽内');
|
||
if (overHard) fail(`E2 估值超 hardCap:${overHard}(表失误量级)`);
|
||
}
|
||
|
||
// ── E3 表卫生(id 唯一/五行合法/稀有度合法/费用域)──
|
||
{
|
||
const ids = new Set();
|
||
let ok = true;
|
||
for (const c of CARDS) {
|
||
if (ids.has(c.id)) { fail(`E3 id 重复:${c.id}`); ok = false; }
|
||
ids.add(c.id);
|
||
if (!ELEMENT_CYCLE.includes(c.element)) { fail(`E3 非法五行:${c.id}=${c.element}`); ok = false; }
|
||
if (!['普通', '罕见', '稀有'].includes(c.rarity)) { fail(`E3 非法稀有度:${c.id}`); ok = false; }
|
||
if (!(Number.isInteger(c.cost) && c.cost >= 0 && c.cost <= 3)) { fail(`E3 费用出域:${c.id}=${c.cost}`); ok = false; }
|
||
if (!c.text || !c.name) { fail(`E3 缺文案:${c.id}`); ok = false; }
|
||
}
|
||
if (ok) console.log(` PASS E3 表卫生(id/五行/稀有度/费用/文案)`);
|
||
}
|
||
|
||
console.log(failures === 0 ? '[static-screen] 全绿' : `[static-screen] ${failures} 条失败`);
|
||
process.exit(failures === 0 ? 0 : 1);
|