纠正仓库内容为衍生项目,标明 campaign-200-r2 最新版

This commit is contained in:
toshiocn
2026-10-19 16:56:31 +08:00
parent a492c5b80e
commit fdca4f67ea
1396 changed files with 392768 additions and 19530 deletions
+11
View File
@@ -0,0 +1,11 @@
import {signature} from './fingerprint.mjs';
import fs from 'node:fs';import path from 'node:path';import {fileURLToPath} from 'node:url';import {base,setup,chooseClues,metrics,setSeed} from './generator-core.mjs';import {solve,violations,constraints,assertStructure,units} from '../rules.mjs';
const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..'),plan=JSON.parse(fs.readFileSync(path.join(root,'plan.json'))),old=JSON.parse(fs.readFileSync(path.join(root,'../campaign-50/design.json'))),tutorials=JSON.parse(fs.readFileSync(path.join(root,'tutorials.json')));
const file=path.join(root,'design.json');let notes=fs.existsSync(file)?JSON.parse(fs.readFileSync(file)):[],seen=new Set(notes.filter(n=>!n.level.tutorial).map(n=>signature(n.level)));
function finish(l,s,author,witnesses,source){l.id=s.levelId;l.order=s.displayOrder;l.chapter=s.chapter;l.chapterTitle=plan.chapters[s.chapter-1].title;l.title=s.title||l.title;l.role=s.role;l.targetDifficulty=s.targetDifficulty;l.mode='campaign-200';l.contentRevision=1;l.caption=s.caption||l.caption||'先观察出口,再按当前规则走遍每一格。';if(s.tutorial)l.tutorial=s.tutorial;for(const c of l.cells.filter(c=>c.clue!==undefined&&c.clue!==1)){const number=c.clue;delete c.clue;if(solve(l,{limit:2}).length!==1)c.clue=number;}const m=metrics(l,author);return {level:l,author,witnesses,metrics:m,planningIntent:s.teachingGoal,difficultyStatus:'策划目标,真人难度待试玩校准',source:source||'新制作',designKey:s.designKey};}
for(const s of plan.levels){if(notes.some(n=>n.level.id===s.levelId))continue;let accepted=null;
if(s.tutorial){const l=structuredClone(tutorials[s.tutorial]),author=solve(l,{limit:2});if(author.length!==1)throw Error('教学不唯一 '+s.displayOrder);const ws=constraints(l).map(c=>{const p=solve(l,{omit:c.key,limit:Infinity}).find(p=>violations(l,p).some(v=>v.key===c.key));if(!p)throw Error('教学机制冗余');return {constraint:c.key,path:p};});accepted=finish(l,s,author[0],ws,'极简教学');}
else if(s.reuseId){const n=old.find(n=>n.level.id===s.reuseId);accepted=finish(structuredClone(n.level),s,n.author,n.witnesses,'重编原关卡 '+n.level.order);if(seen.has(signature(accepted.level)))accepted=null;}
if(!accepted){setSeed(20261015+s.displayOrder*1759);for(let attempt=0;attempt<12000;attempt++){const item=base(s,Math.floor(attempt/55));if(!item)continue;const author=item.paths[Math.floor((attempt*37+s.displayOrder*11)%item.paths.length)],l=setup(s,item.cells,author);if(!l)continue;const ws=chooseClues(l,author,item.paths,s);if(!ws)continue;try{assertStructure(l);}catch{continue;}const sig=signature(l);if(seen.has(sig))continue;const m=metrics(l,author);const min=s.role==='回落'?0:s.targetDifficulty>60?2:s.displayOrder>15?1:0;if(m.noImmediateConflictChoices<min)continue;accepted=finish(l,s,author,ws);accepted.candidateAttempts=attempt+1;break;}}
if(!accepted)throw Error('无法制作 '+s.displayOrder+' '+s.title);notes.push(accepted);if(!accepted.level.tutorial)seen.add(signature(accepted.level));fs.writeFileSync(file,JSON.stringify(notes,null,2));console.log('made',s.displayOrder,accepted.level.title,accepted.level.cells.length,'cells',constraints(accepted.level).length,'rules',accepted.candidateAttempts||'reuse/teach');}
notes.sort((a,b)=>a.level.order-b.level.order);const pack={mode:'campaign-200',version:'200-2026-10-15-v1',title:'数字一笔 · 200关版本',chapters:plan.chapters,rule:'每格一次,共边移动;数字为步号,标记按本关规则执行。',levels:notes.map(n=>n.level),playOrder:notes.map(n=>n.level.id)};fs.writeFileSync(file,JSON.stringify(notes,null,2));fs.writeFileSync(path.join(root,'levels.json'),JSON.stringify(pack,null,2));console.log('Generated',pack.levels.length,'levels');