feat: add production campaigns, gameplay labs, and review documentation

This commit is contained in:
cabinw
2026-09-13 12:27:10 +08:00
parent d1dffa9338
commit 4644e975b0
214 changed files with 98994 additions and 134 deletions
+23
View File
@@ -0,0 +1,23 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { generate, rotate, trace } from '../labs/car-loop/model.js';
import { drainOrientation, rotationPlan, batchSeeds } from '../labs/car-loop/batch.js';
for (const kind of ['hex', 'square']) test(`${kind}: batch levels require meaningful rotation choices`, () => {
for (const [index,seed] of batchSeeds[kind].entries()) {
const board = generate(kind,seed,16), plan = rotationPlan(board);
const first = drainOrientation(board);
assert.ok(first.departed.length >= 2);
assert.ok(first.remaining.length > 0);
assert.ok(first.remaining.every(c=>trace(board,c,first.remaining).status !== 'exit'));
assert.ok(plan.turns.length >= 2 && plan.turns.length <= 4);
const left = 1 + rotationPlan(rotate(board,-1),first.remaining).turns.length;
const right = 1 + rotationPlan(rotate(board,1),first.remaining).turns.length;
assert.notEqual(left,right,`level ${index}: first direction must affect turn cost`);
if (index === 1) assert.ok(plan.turns.includes(-1) && plan.turns.includes(1),'second challenge rewards reversing direction');
let current=board, remaining=first.remaining;
for (const turn of plan.turns) {current=rotate(current,turn);remaining=drainOrientation(current,remaining).remaining;}
assert.equal(remaining.length,0);
assert.equal(plan.waves.reduce((sum,n)=>sum+n,0),16);
}
});