revert(levels): ship round 2's set — contrast selection measurably made it easier
Round 3 tested one hypothesis from round 2's data: levels the agent rated 3 carried 59% more 反差 than the rest, so select for it. With both rounds now at ~100 runs, the answer is in and it is no. The back band went from 2.39 ± 0.10 to 2.19 ± 0.08, roughly two standard errors apart, and the levels averaging 2.5 or better fell from 11 to 6. Contrast is real and it does correlate with being rated harder; selecting on it does not produce harder levels. The low retest reliability does not rescue the change either — r = 0.55 limits ranking one level against another, not the mean of eighteen levels measured a hundred times. So round 2's levels are the ones handed over, rebuilt from its runs via round-set --emitCampaign. select-50 cannot reproduce them: the pool it drew from has been rebuilt since, so the same flags now return different levels. The runs are the record. Rule bot on the shipped set: 50/50 cleared, dead taps 0.00, blind rotations 0.12, worst blind streak 1. 198 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,10 +34,31 @@ export function roundSet(round, dir = resolve('bench/runs')) {
|
||||
return [...byBoard.values()].sort((a, b) => (a.level.campaign?.index ?? 0) - (b.level.campaign?.index ?? 0));
|
||||
}
|
||||
|
||||
// Ship a round that was already played. Re-running select-50 cannot reproduce
|
||||
// one: the pool it drew from has since been rebuilt, so the same flags now
|
||||
// return different levels. The runs are the only exact record.
|
||||
function emitCampaign(levels) {
|
||||
writeFileSync(resolve('levels/campaign-50.json'),
|
||||
JSON.stringify({ generated: `round-set ${ROUND}`, version: 1, count: levels.length, levels }, null, 1));
|
||||
const chapterSize = 10;
|
||||
const chapters = Array.from({ length: Math.ceil(levels.length / chapterSize) },
|
||||
(_, i) => ['起步', '转起来', '看清路', '深一点', '收束'][i] ?? `第 ${i + 1} 章`);
|
||||
writeFileSync(resolve('src/levels-c50.js'),
|
||||
`// Generated by scripts/round-set.mjs --round=${ROUND} --emitCampaign — do not edit by hand.\n`
|
||||
+ `export const C50_CAMPAIGN = ${JSON.stringify({ id: 'c50', name: '五十关调优版', description: `按演出、反差与旋转深度选出的 50 关,难度递增。`, chapters, chapterSize }, null, 1)};\n`
|
||||
+ `export const C50_LEVELS = ${JSON.stringify(levels)};\n`);
|
||||
console.log('已写入 levels/campaign-50.json 与 src/levels-c50.js');
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
const rows = roundSet(ROUND);
|
||||
const levels = rows.map(r => r.level);
|
||||
console.log(`${ROUND}:${levels.length} 关,共 ${rows.reduce((s, r) => s + r.runs.length, 0)} 局`);
|
||||
console.log(`旋转深度 ${JSON.stringify(levels.reduce((m, l) => (m[l.campaign?.rotations ?? '?'] = (m[l.campaign?.rotations ?? '?'] || 0) + 1, m), {}))}`);
|
||||
console.log(`家族 ${JSON.stringify(levels.reduce((m, l) => (m[l.campaign?.family ?? '?'] = (m[l.campaign?.family ?? '?'] || 0) + 1, m), {}))}`);
|
||||
if (args.out) { writeFileSync(resolve(args.out), JSON.stringify({ generated: `round-set ${ROUND}`, count: levels.length, levels }, null, 1)); console.log(`已写入 ${args.out}`); }
|
||||
if (args.emitCampaign) {
|
||||
if (levels.length !== 50) { console.error(`只反建出 ${levels.length} 关,不足 50,拒绝写入`); process.exit(1); }
|
||||
emitCampaign(levels);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user