What it does
The board moves the snake one cell per step and owns everything that can happen on the way. Turns are buffered, up to three by default, and each is checked against the last queued heading, so a quick up-then-left inside one move works while a reversal into the neck is refused. Food is placed only on cells that are not body, obstacle or other food, after the move, and a board with no free cell left is a win rather than a misplaced apple. The tail counts as free only when it really moves away that step, so chasing your tail is legal but chasing it while growing is not.
Walls follow one of two policies. Under die, walls, obstacles and unwrapped edges are fatal, as in the classic
game. Under stop, the snake halts in place while the clock runs on; it follows a corner with only one way on by
itself, waits at a junction, and holds a turn pressed into a wall until the next opening. Biting the body is always
fatal.
The session wraps the board in a game: title, READY, playing, paused, dying, wave clear, GAME OVER and won. It keeps
lives and extra lives, authored maze waves that can loop with the wave number still rising, a clock per wave that can
speed up when the player dawdles, a speed curve that rises per wave and per food up to a cap, score multipliers and a
time bonus. Your game calls update(dt) as its only clock and reads the events it returns. Snapshots and restores
support restarts and replays, and rebuilding the session from the same config replays the same game.
Features
- Buffered turns — a queue of turns applied one per step, with reversals into the neck refused.
- Fair food — food only on free cells, several at once if you like, with their own kinds, growth and scores.
- Wall policies — walls that kill, or walls that stop the snake, with automatic cornering and held turns.
- Wrap or walls — wrapping edges, obstacle layouts (box, pillars, bars) or authored mazes.
- Goals — fill the board, clear the food, or reach a target score.
- A session — phases, lives, extra lives by wave or score, and a high score.
- Maze waves — mazes drawn as text, each with its own time and speed, looping or ending in a win.
- A clock — a time limit per wave that shortens with each wave, a time bonus, and a stall rule that speeds the clock up.
- A speed curve — cells per second rising per wave and per food, up to a cap.
- Replays — snapshots, restores and seeded food.
Good for
- Classic snake games on a walled board, in the style of the phone games of the late 1990s.
- Wrap-around snake with several apples at once.
- Timed maze snake games, where the snake must clear every piece of food before the clock runs out, in the style of Nibbler.
- Obstacle boards with boxes, pillars or bars to steer round.
- Your own mixes, such as a walled maze where walls kill, or an open board with lives and a timer.
Make it yours
The pack factory has no options; rules are set per session or board. The board takes columns and rows, a seed, wrap,
a starting body or length and direction, obstacles, foods with their kinds, how many foods at once, growth and score
per food, the goal, the turn queue size, the wall policy and automatic turning. The session takes the base board, the
waves (a text maze, board overrides and their own time and speed), whether waves loop, lives and their cap, extra
lives every so many waves or at score thresholds, the speed curve, the timer, a score multiplier by wave, whether
eaten food stays eaten after a death, banner times, the start wave and the maze legend. parseSnakeMaze turns text
into a board, with # for walls, . for food and an arrow for the head, and snakeObstacles lays obstacles on any
open board.
snakeGamePreset('classic') is a 32 by 24 walled board, one apple at a time, speed rising per apple to a cap and one
life. snakeGamePreset('nibbler') is materially different: six authored maze waves that loop faster, walls that stop
the snake, a clock that shortens each wave and runs faster when the player stalls, points multiplied by the wave, a
time bonus and an extra life every four waves.
A quick look
A maze session with five lives, a buffered turn and the update loop:
const g = game.snake.createSnakeGame(game.snake.snakeGamePreset('nibbler', { lives: 5, board: { foodGrowth: 2 } }));
g.start(); // title / over / won -> READY
g.input('up'); // buffered turn (accepted during READY too)
const events = g.update(dt); // go, move, blocked, ate, died, cleared, wave, extra-life, game-over, won
g.state; // phase, wave, lives, score, highScore, timeLeft, speed, board
Works with
world-screenandtypography— a fixed screen to draw the board on, and the score, clock and banners.scoreboard— a high-score table with initials, beyond the single high score kept here.
Good to know
- The maze preset's six mazes are authored in the original's style, since its maze data is not published; its clock, speeds and growth are approximations, all configurable.
- The pack does not prove an arbitrary maze or food layout solvable, though the shipped mazes are checked to be enclosed, free of dead ends and fully reachable.
autoInput()is a greedy one-step steering aid, not a solver.- Boards are limited to a million cells,
update(dt)clamps a frame to 0.25 seconds and at most 64 moves, and speeds run from 0.01 to 1000 cells a second.






