[verified] Snake 0.8: circular arena and larger 32px tiles

This commit is contained in:
2026-09-12 13:18:15 +01:00
parent 5a7081b933
commit 18a6ef7d72
31 changed files with 272 additions and 70 deletions
+17 -12
View File
@@ -40,13 +40,12 @@ test('retired timer callbacks cannot advance a resumed or restarted run', () =>
})
test('filling the board wins without null food crashes and retry clears the result', () => {
const {p, timers} = page()
// A serpentine Hamilton path, head (14,0), final food (15,0).
const path = []
for (let y=0;y<16;y++) for (let k=0;k<16;k++) path.push({x:y%2 ? k : 15-k,y})
p.model = path.slice(1); p.dir = {x:1,y:0}; p.foodModel = {x:15,y:0}
// Legal occupancy fixture isolates final-cell victory from pathfinding.
p.model = [{x:5,y:0}, ...snake.ARENA.cells.filter(c=>!(c.y===0 && (c.x===5 || c.x===6)))]
p.dir = {x:1,y:0}; p.foodModel = {x:6,y:0}
p.tick(); assert.equal(p.over, true); assert.equal(p.endText, 'YOU WIN')
assert.equal(p.scoreText, 'SCORE 253'); assert.equal(p.bestText, 'BEST 253')
assert.equal(p.hasFood, false); assert.equal(p.snake.length, 256); assert.equal(timers.size, 0)
assert.equal(p.scoreText, 'SCORE 86'); assert.equal(p.bestText, 'BEST 86')
assert.equal(p.hasFood, false); assert.equal(p.snake.length, 89); assert.equal(timers.size, 0)
p.tick(); p.onShow(); assert.equal(timers.size, 0)
p.restart(); assert.equal(p.hasFood, true); assert.equal(p.endText, 'GAME OVER'); assert.equal(p.model.length, 3)
assert.match(ux, /show="\{\{ hasFood \}\}"/)
@@ -58,11 +57,11 @@ test('select modes while paused or over, resetting safely, and retry keeps mode'
p.selectMode('wrap'); assert.equal(p.mode, 'classic', 'no mid-run mode change')
p.onTap(); p.selectMode('garbage'); assert.equal(p.mode, 'classic')
p.selectMode('wrap'); assert.equal(p.mode, 'wrap'); assert.equal(p.paused, true); assert.equal(timers.size, 0)
p.onTap(); p.model = [{x:15,y:7},{x:14,y:7},{x:13,y:7}]; p.tick()
assert.equal(p.model[0].x, 0); assert.match(p.snake[1].src, /body_h/)
p.onTap(); p.model = [{x:9,y:7},{x:8,y:7},{x:7,y:7}]; p.tick()
assert.equal(p.model[0].x, 1); assert.match(p.snake[1].src, /body_h/)
p.restart(); assert.equal(p.mode, 'wrap'); assert.equal(timers.size, 1)
p.onTap(); p.selectMode('classic'); p.onTap()
p.model = [{x:15,y:7},{x:14,y:7},{x:13,y:7}]; p.tick()
p.model = [{x:9,y:7},{x:8,y:7},{x:7,y:7}]; p.tick()
assert.equal(p.over, true); assert.equal(timers.size, 0)
p.onShow(); p.onTap(); assert.equal(p.over, true); assert.equal(timers.size, 0)
p.restart(); assert.equal(p.over, false); assert.equal(timers.size, 1)
@@ -95,7 +94,7 @@ test('Wrap crosses every edge, still collides with body and renders seam connect
assert.deepEqual(snake.renderPieces([{x:0,y:7},{x:15,y:7}], dirs[0], 16), ['head_e','tail_w'])
})
function eatTo(p, score) {
p.model = [{x:6,y:7}, ...Array.from({length:score+1}, (_,i) => ({x:i%16,y:12+Math.floor(i/16)}))]
p.model = [{x:6,y:7}, ...snake.ARENA.cells.filter(c=>c.y!==7).slice(0,score+1)]
p.dir = {x:1,y:0}; p.foodModel = {x:7,y:7}; p.tick()
}
test('late best read cannot lower local record; writes are serialized', () => {
@@ -124,12 +123,18 @@ test('storage throws and corrupt values never crash or poison gameplay', () => {
assert.equal(p.bestText, 'BEST 0'); eatTo(p, 1); assert.equal(p.bestText, 'BEST 1')
}
})
test('legacy 0.7 records above the new arena maximum survive', () => {
const writes=[]
const {p}=page({get(o){o.success('253')},set(o){writes.push(o)}})
eatTo(p,20); p.restart()
assert.equal(p.bestText,'BEST 253'); assert.equal(writes.length,0)
})
test('best score loads raw storage value and persists only new records', () => {
let get; const writes = []
const {p} = page({get(o) { get=o }, set(o) { writes.push(o) }})
assert.ok(get, 'best score requested'); assert.equal(get.default, '0')
get.success('4'); assert.equal(p.bestText, 'BEST 4')
p.model = [{x:6,y:7}, ...Array.from({length:6}, (_,i) => ({x:i,y:12}))]
p.model = [{x:6,y:7}, ...snake.ARENA.cells.filter(c=>c.y!==7).slice(0,6)]
p.foodModel = {x:7,y:7}; p.tick()
assert.equal(p.bestText, 'BEST 5'); assert.equal(writes.length, 1)
assert.equal(writes[0].value, '5'); assert.equal(writes[0].key, get.key)
@@ -141,7 +146,7 @@ test('eating updates live score and accelerates to a capped 120ms', () => {
const {p, timers} = page()
assert.equal([...timers.values()][0].ms, 300)
for (let score = 1; score <= 20; score++) {
p.model = [{x:6,y:7}, ...Array.from({length:score+1}, (_,i) => ({x:i%16,y:12+Math.floor(i/16)}))]
p.model = [{x:6,y:7}, ...snake.ARENA.cells.filter(c=>c.y!==7).slice(0,score+1)]
p.dir = {x:1,y:0}; p.foodModel = {x:7,y:7}; p.tick()
assert.equal(p.scoreText, 'SCORE ' + score)
assert.equal(timers.size, 1); assert.equal([...timers.values()][0].ms, Math.max(120, 300-score*10))