feat: version campaigns and document original puzzle design

Restore v0.1 and v0.2 archives with separate progress, publish the curved v0.3 campaign, and document the original 24-level design with reproducible evidence. Refine board presentation and movement, and keep video lab tooling within its own directory.
This commit is contained in:
cabinw
2026-09-09 13:17:30 +08:00
parent 70b021d4cc
commit e92cccba82
52 changed files with 76449 additions and 15076 deletions
+6
View File
@@ -16,6 +16,12 @@ test('bends follow the paired exit, never a crossing branch',()=>{
const l=level([{q:0,r:0},{q:0,r:-1,tracks:[2,3,0,1,5,4]},{q:1,r:-2}],[tile('a',0,0)]);
const path=trace(l,l.tiles[0]);assert.equal(path.status,'exit');assert.equal(path.steps[1].enter,3);assert.equal(path.steps[1].exit,1);assert.deepEqual(path.steps[2],{q:1,r:-2,enter:4,exit:1});
});
test('path usage counts successful bends and ignores decorative tracks outside the traveled route',()=>{
const bent=level([{q:0,r:0},{q:0,r:-1,tracks:[2,3,0,1,5,4]},{q:1,r:-2}],[tile('a',0,0)]);
const p=analyze(bent).pathUsage;assert.equal(p.curvedRemovals,1);assert.equal(p.singleBendRemovals,1);assert.equal(p.totalBends,1);assert.equal(p.curvedRatio,1);
const decoration=level([{q:0,r:0},{q:1,r:0,tracks:[1,0,3,2,5,4]}],[tile('a',0,0)]);
const unused=analyze(decoration).pathUsage;assert.equal(unused.curvedRemovals,0);assert.equal(unused.straightRemovals,1);assert.equal(unused.curvedRatio,0);
});
test('occupied cell blocks even when its own arrow points elsewhere',()=>{
const l=level([{q:0,r:0},{q:0,r:-1}],[tile('a',0,0),tile('b',0,-1,1)]);
assert.equal(trace(l,l.tiles[0]).blocker,'b');assert.deepEqual(available(l).map(t=>t.id),['b']);