feat(levels): boards whose interior is packed and whose rim is left empty
The game has never had a board you simply clear out, and the request for one turned out to need a construction of its own rather than a denser deep lock. Filling cells at random can never work: a packed board has nothing that can move — measured over forty random fills of a 37-cell board, zero pieces free in all six orientations, every time, because a piece steps to the next cell before it can leave and on a full board that cell is taken. So packBoard builds backwards. Start empty, add only a piece that could leave right now, and the placement order reversed is a removal order — solvability becomes a property of the construction. Which cell to fill next decides everything: at random it stalls near half, while filling the most constrained cell first takes a 19-cell interior to 96% and fills it outright. The rim is deliberately empty. Those pieces leave first and ask nothing, and clearing from the rim inward gives a packed board its own difficulty curve inside one level — the outer cells read easily, and it tightens as it opens. Two things were tried against the ceiling and failed, and are recorded as such: depth-first backtracking made it worse on both counts (65-78% filled against greedy's 89%, at 2000-3000 seconds a board) because recomputing every cell's legal directions per node spends the budget three levels deep. And the audit's dead-turn gate could not be trusted here at all — on a packed board its breadth search truncates, so it certified levels the rule bot then walked through three blind turns in a row. The pool is filtered by playing it instead: a full pass takes one second and does not lie. The campaign is 32 packed levels to 18 deep locks, alternating, with the closing six at a completely full interior. Same rule bot, both editions: worst blind streak 1 either way, dead taps zero, and half again as much to do per level. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,7 @@ test('every selectable edition retains its own level count, order and chapters',
|
||||
// Historical editions keep their exact shape; new ones are appended, because
|
||||
// other tests address the originals by position.
|
||||
assert.deepEqual(CAMPAIGN_VERSIONS.map(c=>[c.id,c.levels.length,c.chapterSize,c.chapters.length]),[
|
||||
['v0.1',24,8,3],['v0.2',48,6,8],['v0.3',48,6,8],['v0.4',20,5,4],['v0.5',1000,50,20],['c50',50,10,5],
|
||||
['v0.1',24,8,3],['v0.2',48,6,8],['v0.3',48,6,8],['v0.4',20,5,4],['v0.5',1000,50,20],['c50',50,10,5],['c50b',50,10,5],
|
||||
]);
|
||||
assert.equal(campaignVersion('v0.1').levels[0].name,'转一转,路就通了');
|
||||
assert.equal(campaignVersion('v0.1').levels.at(-1).name,'六角大满贯');
|
||||
|
||||
Reference in New Issue
Block a user