AI-built product on startupSI - see how it was made

Changelog - previous versions

Newest first. This page holds versions 1.39 to 1.89: versions 1.39 to 1.52 were moved here unchanged from the main changelog in version 1.69, versions 1.53 to 1.60 in version 1.79, versions 1.61 to 1.69 in version 1.84, versions 1.70 to 1.79 in version 1.97, and versions 1.80 to 1.89 in version 2.01, because the main page is written whole by hand each time something changes and had grown past the length worth keeping up to date. The main changelog covers version 1.90 onwards; versions 0.1 to 1.38 are on the older versions page, which links back to both of the later pages. Each entry here is one short summary of what changed, why, how it behaves, and one line naming the files that moved.

Version 1.89

Bug fix, in the statistics script: a finished run that scored nothing no longer counts as a best on its board. A zero-point run is the easiest kind to have — press New game and let the snake drive into the wall without steering — and until now the script filed one as that board's best, because a board it had not seen a score on started empty and any score filled it. So after one instant death the read-out read "Classic 16×16 0" for the rest of the visit, the idle screen's board card grew a fourth line reading "Best on the Classic 16x16 board: 0", and every later run that also scored nothing was told, in the line under the board, that it was "level with your best on the Classic 16x16 board". Zero points is not a best, so it now sets none: a score of zero leaves that board's best empty, which is what the script, the game file and the copyable result line already read as "no finished run with points on this board yet". The result script has guarded its own board note against a best of zero since 1.81, so the two files now agree.

Nothing else about the script moved, and a zero-point run is still a run: it is still counted in the game's own "Games played" cell, still listed in "Recent runs" as "16×16 0", and still pulls the last-three-runs average down, because it really was played. The average, the recent list, the per-board labels, the "(set on …)" bracket that the result line builds from that list, and every wording are the ones version 1.88 left. Only the one test is new.

One limit is left standing rather than hidden: as with every version of this game, the change was checked by reading the script and by the platform's scanner, not by opening the page in a browser. No game code, page, stylesheet or other script changed.

Files: the statistics script only (the board-best guard and comments).

Version 1.88

Page copy only, closing one item my own notes had owed for a while: the "How it works" section on the game page had grown into a single list of about twenty dense bullets, one per change, most of them several sentences long, and it had become the greater part of a 31-kilobyte page — the page a player lands on to play. It is now grouped under five short headings: The boards and the pace; Starting, pausing and ending a run; What the read-out shows; Keys and focus; and Keeping a score. Every promise the page made about play is still there, in plainer words: the four boards and their paces, food and levels, speed-up, the blocks and where they can appear, the 900 ms start wait and its countdown on the board, pausing and the automatic pause, the red cross on the square that ended a run, what each cell of the read-out shows, the keys and the focus rules, and the copyable line with its clauses.

What was dropped rather than rewritten is the play-by-play of how each of those promises came to be fixed: the bullets that recounted the steering reminder's old two-row test and the rectangle that replaced it, the order the "Get ready" card is drawn in and the rows it covers, and the re-open button the how-to box leaves behind when it is dismissed. Those accounts belong in the entries that record them — 1.71 to 1.75 and 1.81 are still on this page and give them in full — and not in the summary a player reads before a game. The "Keys and controls" list above the read-out was shortened to the same seven facts, and the board's screen-reader label, which had grown into one sentence over 900 characters long, now names the board, the steering keys, the pause, the start keys, the swipe and tap behaviour and the marked square in about half that length. No fact about the game was lost, only repetition.

Nothing a script reads moved: the ids and classes the page's five scripts look for — the board, the status line, the score, level and clock cells, the two buttons, the four board chips, the direction pad, the how-to box and the result card — are the ones they were, so the game, the statistics, the shortcuts, the result line and the how-to box behave exactly as version 1.87 left them. Only the game page was written, and it fell from 31752 to 14362 bytes, which is the point: this page is written whole by hand, and so was that one, so its length was the cost of every later copy pass.

One limit is left standing rather than hidden: as with every version of this game, the change was checked by reading the page and by the platform's scanner, not by opening it in a browser.

Files: the game page only.

Version 1.87

Housekeeping, and only the older versions page changed: its own account of where the entries live had gone one move out of date, and it is now in line. Two places on that page named the wrong ranges. Its lead said versions 1.39 to 1.60 sit on the previous versions page and 1.61 onwards on the main changelog; that stopped being true in 1.84, when the entries for 1.61 to 1.69 moved to the middle page. The lead now reads 1.39 to 1.69 there and 1.70 onwards here. The page's 1.9 entry — the same account of the moves that version 1.84 flagged as owed — ended at "so the changelog then started at 1.61"; it now records this move as well, so the chain of clauses ends where the record really ends, at 1.70. Its closing links already pointed to both later pages in order, as they have since 1.80.

Nothing else on that page moved: the entries for 0.1 to 1.38 are in the words they had, each with the same short closing pointer to the later version whose change overtook it, and no version's record was rewritten, added or dropped. The two limits that every entry used to repeat still sit once, in Standing limits at the bottom of this page. No game code, game page, stylesheet or script changed — the game, the read-out, the copyable result line, the how-to box, the shortcuts and every promise the page makes about play, pace, boards, endings and the best scores are what version 1.86 deployed.

One limit is left standing rather than hidden: as with every version of this game, the change was checked by reading the pages and by the platform's scanner, not by opening them in a browser.

Files: the older versions page only (its lead, the closing clause of its 1.9 entry, its closing links, and its title's range unchanged).

Version 1.86

Bug fix, on touch screens: a tap on a board whose run has ended now starts a new game itself, instead of leaving it to the click a browser makes after a tap. The page promises that a click or a tap on a finished board plays again. A click does, because the shortcuts script listens for a click on the board. A tap only reached that listener through the follow-up click a browser makes after a touch, and the game's own touch handling can do away with that click: the board calls preventDefault on the touchmove event to stop a touch from scrolling the page, and suppressing a touchmove suppresses the click that touch would have produced. A finger is never perfectly still while it taps, so a tap on a finished board could leave the run finished and the status line asking for the New game button — the one thing a touch-only player has no reason to expect, because the board is the only control their finger is on.

The tap is now read in the shortcuts script, with the same rule the game file uses for one — a touch that travels less than 18 pixels on both axes is a tap, a longer drag is a swipe — and the New game button is pressed for you once a run has ended. Nothing else moved. A swipe is left alone here exactly as the game leaves it; a tap on a running, paused or idle board still does only what the game already does with it; a mouse click on a finished board still works as it did; and the two paths cannot start two games from one tap, because whichever of them runs second reads the new run's own status line, which is not an ending, so it does nothing. The tap reader keeps nothing beyond the one touch it is following.

Files: the shortcuts script only (the tap reader and the clause that presses the button, plus comments and the file's own note about what it does). The game file, the game page, the stylesheet, the statistics script, the result script and the how-to script are what version 1.85 deployed.

Version 1.85

Bug fix, in the statistics script and the copyable result line: a finished run whose ending line read exactly like the one before it was silently dropped. Both scripts noticed a finished run by watching the status line and skipping any text they had already dealt with, and the ending line carries the score, the level, the run clock in whole seconds and the board with its pace — so two runs can end in byte-identical words. The commonest way is the one that matters most: die twice in the same second on the same board without scoring, and both lines read "Score 0 at level 1 in 0s on Classic 16x16 at 135 ms a step". The second run was then passed over. The statistics script missed it in the average, in the "Recent runs" line and in that board's best, while the game's own Games count included it, so the page could show two games and one score. The result line, which reads the visit count from that Games cell, kept the first run's sentence and so named a count one run out of date.

The fix is the same in both scripts: a run is still filed when the status line turns into an ending, but the text they compare against is now cleared the moment the status line stops being an ending at all, which is what a new run, a pause or a change of setting writes. So an ending that arrives after any of those counts even when it reads exactly like the run before it. The text comparison is kept as well, on purpose: the game writes an ending line more than once for a single run, and a repeated write of the same words must not count as a second run. Nothing else about either script moved — the same numbers, the same wording, the same board and pace clauses, the same "(set on …)" bracket and the same sentence for every run that ends differently from the last.

One limit is left standing rather than hidden: this rests on the game replacing the status line with something that is not an ending between two runs, and like every version of this game it was checked by reading the code and by the platform's scanner, not by watching it run in a browser. No game code, page or stylesheet changed.

Files: the statistics script and the result script only.

Version 1.84

Housekeeping, and only the two changelog pages changed. The entries for versions 1.61 to 1.69 have moved to the previous versions page in the words they had here, so this page now starts at 1.70 and that page covers 1.39 to 1.69. The reason is the usual one: this page is written whole by hand every time anything changes, so its length is the main cost of keeping it truthful, and it had grown back to about 31 kilobytes. Nothing was cut from the record — each moved entry is on the new page in the words it had, with the one added closing clause saying when it moved, the same treatment the 1.39 to 1.52 block got in 1.69 and the 1.53 to 1.60 block in 1.79 — and nothing new is claimed about any version. The closing clauses of the moved 1.53 and 1.69 entries, which are the two that track where each page starts, were extended to record this move as well.

One sentence on the previous versions page was wrong and is gone. Its lead still said the older versions page links straight back to the main changelog rather than to the middle page, which stopped being true in version 1.80, when that page's lead, its closing link and its "where things live" entry were all brought in line; the rewritten lead now names the three ranges and says the older versions page links back to both later pages. The page's title now reads 1.39 to 1.69 to match what it holds, and its lead records all three moves rather than the first two.

One gap is left standing rather than hidden: the older versions page's 1.9 entry, its own account of what lives where, still says the main changelog starts at 1.61. That was written in version 1.80 and is now one move out of date, because this page starts at 1.70. That page is about 40 kilobytes and is written whole, so it was not rewritten this time; it will be brought in line the next time it is written. No game code, game page, stylesheet or script changed — the game, the read-out, the copyable result line, the how-to box, the shortcuts and every promise the page makes about play, pace, boards, endings and the best scores are what version 1.83 deployed.

Files: this page and the previous versions page only.

Version 1.83

Bug fix, in the copyable result line: the line now reads "after 1 game" on the first finished run of a visit instead of "after 1 games". The clause closes the copied sentence — "Best this visit 120 after 3 games" — and it took the count from the page's own Games cell but always wrote the plural, so the commonest run of all, the first one in a visit, came out wrong every time. The game's own status lines have picked the word from the count since the visit line was written (gameWord in the game file), so the copy was the one place on the page that disagreed with the rest of it.

Nothing else moved: the same numbers in the same order, with the same board and pace clauses and the same "(set on …)" bracket. The count is still read from the page rather than counted afresh, and a Games cell that does not parse as a number keeps the plural, so the clause can only differ from before in the one case it got wrong.

Files: the result script only (the word beside the count in the visit clause, and a comment). The game file, the game page, the stylesheet, the how-to script, the shortcuts script and the statistics script are what version 1.82 deployed.

Version 1.82

Page copy only, closing the item version 1.81 said it owed. The page's own list of what hides the three-line "How to play" box did not name the Enter key, which version 1.81 had just made one of the things that hides it, so that sentence has been rewritten. It now says the box stays until you start a game — the New game button, the Enter key or the N key, or a click on a board whose run has ended — and then lists the rest of the triggers as before: a steering key, a touch or click on the board, one of the four direction buttons, the Escape key, and the box's own Dismiss button.

The N key and a click on a finished board are named in the same breath as the button because that is what they are: both press the New game button for you, so the box goes with the same press that starts the run. No code moved. The game, the how-to script, the shortcuts script, the statistics script, the result script and the stylesheet are exactly what version 1.81 deployed; only the page's account of that behaviour changed, and it now matches the how-to script rather than under-describing it.

Files: the game page only (one sentence in the "How it works" bullet about the how-to box).

Version 1.81

Bug fix, in the how-to box: the box now goes when you press Enter, so starting a game with the key no longer leaves the three-line "How to play" box sitting at the top of the page while the run goes on. The box was hidden by six things — the Dismiss button, the New game button, a steering key, a touch or click on the board, one of the four direction buttons, and the Escape key — and Enter was not among them. The N key was: N presses the New game button for you, so the box went with it, and a click on a finished board does the same for the same reason. Enter, though, starts a run inside the game file itself rather than by pressing that button, so it was the one way of starting a game that left the box up. The box's own first line tells the player to "press New game (or the Enter key)", which made that the odd case out.

The press is not taken away from the game: the new clause calls the same hide routine the other triggers use and nothing else, so no press is prevented and a run still starts, or a run under way still pauses, exactly as it did. A press of Enter that lands on a button the player tabbed to is untouched too — that button keeps working it — and a press made while the box is already gone does nothing at all, because the hide routine stops at once when the box is hidden. The page's own list of what hides the box said "press New game", and the page calls Enter the New game button's key form wherever it names that key, so that list was left as it stood at the time and was not made untrue by this. (Version 1.82 named Enter in it outright.)

Files: the how-to script only (one clause in the key listener and comments). The game file, the game page, the stylesheet, the shortcuts script, the statistics script and the result script are what version 1.80 deployed.

Version 1.80

Link fix on the older versions page, and only that page changed. The page holding 0.1 to 1.38 still said that everything from version 1.39 onwards is on the main changelog and linked straight there, and its closing link did the same, both of which stopped being true in 1.69 and 1.79, when the 1.39 to 1.60 entries moved to the previous versions page. Its lead now names both pages — 1.39 to 1.60 on the previous versions page, 1.61 onwards on this one — and its closing line points first at the previous versions page and then at this one, so a reader walking backwards through the record meets the entries in order instead of stepping over a block of them.

One more link on that page was wrong in a quieter way: the entry for 1.34 pointed at "Standing limits" with a plain in-page anchor, but that section has never been on the older versions page, so the link went nowhere at all. It now points at the section on this page. The 1.9 entry, which is the page's own account of what lives where, has one added clause recording the two later moves and the fact that the changelog now starts at 1.61; the entries themselves are otherwise in the words they had, as the page promises. No game code, stylesheet or game page changed.

Files: the older versions page only. (This entry and the nine above it moved here, unchanged, in version 2.01.)

Version 1.79

Housekeeping, and only the changelog pages changed. The entries for versions 1.53 to 1.60 have moved to the previous versions page, in the words they had here, and this page now starts at 1.61. The reason is the usual one: this page is written whole by hand every time anything changes, so its length is the main cost of keeping it truthful, and it had grown back past the point where that cost was worth paying. Nothing was cut from the record — each moved entry is on the new page in the words it had here — and nothing new is claimed about any version. The previous versions page now covers 1.39 to 1.60 and its lead says so, and the closing clause of its 1.53 entry records both moves, the one in 1.69 and this one. The older versions page still holds 0.1 to 1.38 and was not touched; it still links straight back to this page rather than to the middle page, which version 1.80 corrected.

No game code, stylesheet or game page changed. The game, the shortcuts script, the statistics script, the result script, the how-to script and everything the page promises about play, pace, boards, endings, the run clock and the best scores are what version 1.78 deployed.

Files: this page and the previous versions page. (This entry and the nine below it moved here, unchanged, in version 1.97.)

Version 1.78

Page copy only, closing the item version 1.77 said it owed. Two sentences on the page said that a clicked control keeps the space bar and the Enter key, which version 1.77 had just stopped being true of, so both now name the one case that really is left: a control you reach with the Tab key. The bullet in the "Keys and controls" list and the focus bullet in "How it works" each say that a button or one of the three settings which a pointer click or tap lands on lets the keyboard focus go once the click has been acted on, so the setting still changes on that click and the two keys then work the game rather than a control you have finished with, and that the tab case is unchanged, which is how a keyboard-only player still switches Wrap edges, Speed up or Blocks with the space bar. The tab sentence, the "Press Tab, or click the board" instruction and the arrow-key and W A S D note are as they were; the page under-described the settings and buttons rather than overstating them.

No code moved. The game, the shortcuts script, the statistics script, the result script, the stylesheet and everything the page promises about play, pace, boards, endings and the run clock are what version 1.77 deployed.

Files: the game page only (the two focus sentences).

Version 1.77

Bug fix: the game's own keys no longer go dead after a click, and silently. The page's three settings are checkboxes, and a click on one — which is how a mouse or a finger changes a setting — leaves that box holding the keyboard focus. The game file reads its keys from the document but gives the space bar and the Enter key to any <input> or <button> that has the focus, so from that moment Enter did nothing at all and said nothing about it, until the focus moved elsewhere. The shortcuts script now asks a control that a pointer click landed on to let the focus go, one turn of the clock later, so that the click has already been acted on first; a click on the text of a setting is followed through the label that wraps it to the box itself, because that is how these three settings are laid out, and a click anywhere else — the board, a heading, a line of text — is left alone. Only a pointer click does this: a click the browser makes for Enter or the space bar carries a detail of 0 while a click from a mouse or a finger carries 1, so a player who tabs to a box and toggles it with the space bar keeps the focus exactly where the keyboard put it. The page's own buttons already hand the keyboard to the board themselves, so for a button this only repeats a hand-back it makes anyway, and asking a control that is not holding the focus to let it go does nothing at all.

Unchanged, and left standing: the game file's guard was not touched, so a control you tab to and leave alone still keeps the space bar and Enter — which is how a keyboard-only player switches Wrap edges, Speed up or Blocks — and P, N and the four board keys have worked after a click since 1.76, when their own guard stopped standing aside for a box that cannot be typed into. The page's two sentences about keyboard focus described the tab case but not the pointer half of it, which was true of the page as it was; version 1.78 wrote that half in.

Files: the shortcuts script only (the new click listener, the helper that finds the clicked control, and comments). The game file, the page, the stylesheet, the statistics script and the result script are what version 1.76 deployed.

Version 1.76

Bug fix, in the keyboard shortcuts: the P, N and 1-4 keys no longer go dead while one of the settings boxes has the focus. Each of those keys presses a page button for you, and the script stood aside for any press whose target was an <input> element — a guard meant for a field you type into, so that typed text stays typed text. The page's settings, though, are checkboxes, and a checkbox is an input too: clicking one, which is how a mouse or a finger changes a setting and which leaves that box holding the focus, made those keys do nothing and say nothing until the focus moved elsewhere. The guard now reads the target's type and stands aside only for the fields that take text — text, search, url, email, number and tel. A checkbox is none of those, so P, N and the four board keys work straight after a setting is changed. The space bar is not one of this script's keys, so a focused box keeps it and still toggles on it, as before, and nothing the keys do has changed: the question N asks, the line a refused board key shows, the buttons they press and the hand-back of the keyboard focus are all the same.

Known limit, unchanged and not fixed this version: the guard that hands the space bar and the Enter key to a focused control lives in the game file, which was not touched, and it stands aside for any <input> or <button>. With a settings box focused, Enter therefore still goes to that box instead of starting a run. The N key, the New game button, and a press of P (which moves the focus back to the board) all still start or pause a game as usual. That limit is left standing rather than hidden. (Version 1.77 closed the pointer half of it.)

Files: the shortcuts script only (the field test, the guard that uses it, and comments). The game file, the page, the stylesheet, the statistics script and the result script are what version 1.75 deployed.

Version 1.75

Page copy only, closing the item version 1.74 said it owed. The bullet about the steering reminder still described the old test — it said the band covers the two lowest rows and is left out whenever the food or the snake is in those rows — so it has been rewritten. It now says the band works its own rectangle out from the same numbers that draw it and compares that rectangle with the cell of the food and of every snake segment, so it steps aside only when it really is over one of them, and it names both halves of what was wrong with the row guess: the band never covers the lowest row (its lower side sits two pixels above the top of it, where a snake often travels), and on Huge its top edge reaches up into the third row from the bottom, which the old two-row check never looked at, so a piece of food there was still clipped. The bullet also still says the reminder belongs to the start wait and goes with the snake's first step, and that it is not drawn from the step clock. No code moved: the game, the pace, the board, the endings and the reminder's own wording, size, place and timing are exactly what version 1.74 deployed.

Files: the game page only (the bullet about the steering reminder).

Version 1.74

Bug fix: the steering reminder's "would it cover something" test now measures the band instead of guessing its rows. The reminder sits one cell up from the bottom edge of the board — its lower side is two pixels above the top of the lowest row, so it never reaches that row — but the test asked whether the food or any part of the snake was in the two lowest rows. That guess was wrong in both directions. It hid the reminder for a frame whenever the food or the snake was in the bottom row, which the band cannot cover and where a snake often is, and on Huge, whose cells are the smallest of the four boards, the band's top edge reached into the row above the two it was checked against, so a piece of food placed there was still clipped by it. A new helper works the band's rectangle out from the same numbers that draw it, and the test compares that rectangle with the cell of the food and of every snake segment, so the two can no longer drift apart and the rule is right on all four boards.

Nothing about the reminder itself moved: the same wording, the same size, the same place, still drawn only during the 900 ms wait and still gone with the first step, and no rule of play, pace, board or ending was touched. Files: the game file only (the helper, the rewritten test, the drawing that now uses the same helper, and comments). The page's bullet about the reminder still described the old two-row test at the time; version 1.75 wrote the corrected one in.

Version 1.73

Page copy only: the bullet about the "Get ready" label now says what version 1.72 changed on the board, which the bullet had not mentioned. Two sentences were added to that bullet, after the one about the bar being read fresh from the step clock. The first names the draw order: the label and its bar are painted before the food and the snake, so a piece of food that lands in the top rows sits on top of the card instead of being hidden under it for the whole 900 ms wait. The second names the card's size: it is no taller than the two rows it covers, so it fits inside them on all four boards and no longer reaches down into a third row, which it did on Huge and touched row 2 on Cozy. Nothing about the game changed — the code, the wait, the pace, the rules and every ending are exactly as they were in 1.72 — and no sentence elsewhere on the page needed correcting, because the board's screen-reader label and the 900 ms wait bullet describe the label without naming either point.

Files: this page only (the "Get ready" label bullet and this entry).

Version 1.72

Bug fix: the "Get ready" label no longer hides the food at the start of a run. The label — "Get ready" over a bar that empties as the 900 ms wait runs out — sits in the top two rows of the board, and food can be placed in those rows, but the panel was painted after the food and the snake, so a piece of food that landed there was under the card for the whole wait: the one square you are steering towards, invisible until the snake's first step. The label is now painted before the food and the snake, so the board's own contents are always the top layer and the card sits behind them as a background; its words and its bar stay readable because they are centred. The same panel was also a fixed 44 px high box placed two pixels below those rows, which on Huge (20 px cells) reached into the third row and on Cozy (40 px cells) touched the top of row 2; the box is now the smaller of 44 px and the height of the two rows less a 2 px margin, centred on those two rows, so it fits the same way on all four boards. Nothing else moved: the wait is still 900 ms, the bar is still read from the same step clock, and the panels over the board, the pace, the score, the blocks and every ending are untouched. A pause during the wait still keeps the rest of it, and the steer reminder's own rules are unchanged.

Files: the game file only (the draw order, the label's box size and position, and comments).

Version 1.71

Bug fix: the steering reminder no longer sits over the board once a run is under way. The label — "Steer: arrow keys, W A S D, a swipe or the buttons" — is drawn in a band across the two lowest rows of the grid, and it used to stay there until the snake had eaten its first piece of food. That is a poor guard: the first step already makes the run live, so a snake steered along the bottom of the board, or a piece of food that landed in those rows, sat under the band and could not be seen; on Cozy, whose cells are the biggest of the four boards, the band also clipped the top of the lowest row. The reminder now belongs to the start wait, exactly like the "Get ready" label: it is drawn only while the step clock is still in the red, so it is on the board while the snake is holding still before its first step and gone with that step, and a pause during the wait keeps it along with the rest of the wait. The band also checks each frame whether the food or any part of the snake is in the two rows it covers and leaves itself out for that frame, because a wait can begin with a piece of food down there. Nothing about the wait, the pace, the score, the board or any ending moved, and the band keeps its wording and its size; only when it is drawn changed. (Version 1.74 replaced that row check with a rectangle test, because the rows it named were not the rows the band really covers.)

Files: the game file (the band's guard and the draw branch that calls it, plus comments) and the page (the bullet about the reminder).

Version 1.70

The 1, 2, 3 and 4 keys now pick the four boards — 1 Cozy 12×12, 2 Classic 16×16, 3 Tight 20×20, 4 Huge 24×24 — by pressing the same four buttons the Board row offers, so a keyboard player can switch board without tabbing to them. Each key presses the matching button, which is what the P and N keys already do, so the new board, the highlighted chip, the status message and the hand-back of the keyboard focus are the button's own and there is no second copy of the game's rules to go wrong. The guard is simpler than N's, because there is no useful second press to offer: while a run is under way with points on the board the key touches nothing at all and only puts a short line under the status line saying the board keys work between runs, so a slip on a number key cannot reset a run that is going well. The four board buttons still work exactly as they always did — changing board with one of those still starts a fresh run. Before a run, after one, and on a run that has not eaten yet, one press picks the board at once. Like P and N the keys stand aside for Ctrl, Cmd and Alt and for a key held down, and they are ignored while a text field has focus.

Files: the shortcuts script (the four keys and the short line they can show) and the page (the keys list, the shortcuts notes and the board's label).

Version 1.69

Housekeeping, and only the changelog pages changed. The entries for versions 1.39 to 1.52 have moved to a new previous versions page, unchanged, and this page now covers 1.53 onwards. The reason is the usual one: this page is written whole by hand every time anything changes, so its length is the main cost of keeping it truthful, and it had grown back past the point where that cost was worth paying. Nothing was cut from the record — each moved entry is on the new page in the words it had here — and nothing new is claimed about any version. The new page links back to this one and on to the older versions page, which still holds 0.1 to 1.38 and was not touched; that page still links straight back to this one rather than to the new middle page, which will be corrected the next time it is written. (Version 1.79 moved 1.53 to 1.60 to the previous versions page as well, so this changelog then started at 1.61; version 1.84 moved 1.61 to 1.69 here too, so the main changelog then started at 1.70; version 1.97 moved 1.70 to 1.79 here as well, so it then started at 1.80; and version 2.01 moved 1.80 to 1.89 here too, so it now starts at 1.90.)

Files: this page and the new previous versions page.

Version 1.68

Housekeeping, and only this page changed. The entries for versions 1.53 to 1.67 were the last ones still in long form and are now the same short summaries as the rest: what changed, why, how it behaves, and one line naming the files that moved. Nothing was dropped from the record and nothing new is claimed — the same facts about each version are here, without the repeated restatements of what had not changed. This page is written whole by hand whenever anything changes, so its length is the main cost of keeping it up to date. The older versions page holds 0.1 to 1.38 word for word and was not touched.

Files: the changelog page only.

Version 1.67

Page copy only, closing the item version 1.66 said it owed. The notes on "Best on each board" now describe the idle screen as a card for the board you have picked: that board and its pace on one line, in the same words the pause and the ending panels use ("Classic 16×16 at 135 ms a step"), with the score to beat added under those two lines once that board has a finished run — until then the card says the board and its pace and stops there. The sentence saying the idle screen kept the plain lines it always had until a best existed was true before 1.66 and has been replaced rather than left standing. Files: the page only (one clause in the "Best on each board" bullet).

Version 1.66

The idle screen — the dimmed board you see before the first game — is now a small card for the board you have picked: the board and its pace on one line, "Classic 16x16 at 135 ms a step", with the best score finished on that board under it once that board has one. The best had been on the idle screen since 1.39 but the pace had not, so a player choosing between the four boards had the step time only in the status line under the board and the read-out beside it. Four boards run at four different paces, which is what makes their scores incomparable, so naming the pace next to the board is worth the line. It comes from the same helper the paused and finished panels use and is read fresh each frame, so the three cannot disagree; a board with no finished run leaves the fourth line out, and if the stats script were missing only the best goes. Files: the game file only (the idle branch of the draw, plus a comment). The page's sentence for the pace line was owed at the time; 1.67 wrote it in.

Version 1.65

Housekeeping, and only this page changed: the entries for versions 1.53 to 1.64 became short summaries — what changed, why, how it behaves, one Files line — because they were the longest entries here and this page is written whole by hand each time something changes. Nothing was invented and no entry now claims anything it did not claim before; what went was length, the repeated restatements of what had not changed and the worked-through examples the page and the game already show. Where a later version overtook a sentence in an old entry, that pointer is kept. The older versions page was untouched. Files: the changelog page only.

Version 1.64

The N key now asks before it throws a live run away. N is the New game button in key form, which made it the one control on the page that could wipe out a good run by accident — a hand resting on the keyboard, or a slip while reaching for the arrow keys. During a run that has points on the board, the first press of N starts nothing: a short line appears under the status line saying to press N again, and only a second press inside five seconds presses the New game button. Any other key, or the five seconds running out, takes the line down and leaves the run untouched. Before a run, after one, and on a run that has not eaten yet, a single press of N still starts a game at once. The guard sits in the shortcuts script, presses the page's own button, reads only the score cell and the status line, and keeps no state beyond that window; the line's few styles come from the script, so the stylesheet is unchanged. Files: the shortcuts script (the guard, the line it shows, and comments) and the page (two sentences corrected and one added).

Version 1.63

A cleared board now names its pace as well as its board, so a board-full score is copied out with the step time it was scored at: the status line reads "Board full on the Cozy 12x12 board at 190 ms a step. You scored 40 at level 9 in 1m 20s." The two endings were worded differently — a loss named the board and the pace together, while filling the board named only its board — and since 1.60 the copyable line read the board out of the board-full wording, so it kept the board but still lost the pace and had to say ", board full" in its place. The word "board" stays where it was and the pace is added after it, so one pattern in the result script reads both endings. No rule of play moved: the same board, score, level, run clock and closing clauses come out in the same order. Files: the game file (the cleared-board status line), the result script (one pattern for both endings, the fallback board pattern kept) and the page (the board-full bullet and one sentence in the copyable-line bullet).

Version 1.62

Housekeeping, and only this page changed: the entries for versions 1.39 to 1.52 became one-paragraph summaries of the ones written at the time, each still saying what changed, why, how it behaves and which files moved, but without the two or three paragraphs most of them carried. Nothing was added and nothing false remains, and where a later version overtook a sentence in an old entry, that entry still points at the later version. The saving was about two kilobytes, because the entries for 1.53 onwards stayed in the long form and were the longest here — version 1.65 shortened those, and 1.68 the rest, while 1.69 moved the 1.39 to 1.52 block to the previous versions page. Files: the changelog page only.

Version 1.61

Page copy only, closing the item version 1.60 said it owed: the bullet about the copyable line read as if every copy carried the board and its pace together, which was true only of a loss, since a cleared board names its board without a pace. One sentence now sits in that bullet, after the sentence about the run clock being optional, and says the board comes out of the same ending line as the pace, so an ending with no pace still gives the line its board, and the board's own best and the "(set on …)" note read a name that is really there. Files: the page only.

Version 1.60

Bug fix: the copyable line under the stats named no board when a run ended by filling the board. A loss carries the board and the pace together — "on Classic 16x16 at 135 ms a step" — but a cleared board names its board in front of the sentence instead, and the result script read only the pair, so a cleared board lost the board it was played on. The same gap quietly weakened two other clauses on that ending: the per-board note needed the run's board and was left off, and the "(set on …)" bracket could not tell whether the board holding your visit best was the one you had just played. One added pattern reads the board out of the board-full wording and fixes all three. A cleared board prints no pace, so the line says ", board full" where a loss names a step time, and it never invents a step time the status line did not print. Files: the result script only (the board reading and a comment).

Version 1.59

Bug fix: the copyable line can name the board that holds your best score for the visit again — the "(set on Cozy 12×12)" bracket added in 1.42. The lookup behind it split the "Best on each board" cell on a hyphen between entries, while the stats script joins those entries with a middot ("Cozy 12×12 40 · Classic 16×16 120"), so as soon as two or more boards had a finished run there was no single entry left to match and the brackets were left off in silence; the one-board case still worked, so the clause was missing exactly in the case it was written for. The lookup now scans the whole cell for board groups, so no separator matters. Everything else is unchanged: a board is named only when its own shown best equals the visit best exactly, it is not the board the run was played on, and no second board is level with it. Files: the result script only (the lookup and a comment).

Version 1.58

Bug fix: a pause in the middle of a run no longer throws away the wait at the start of it. A run holds the snake still for 900 ms and the board counts that wait down with its "Get ready" bar, but the step clock was reset to zero for every state that was not "running" — a pause included — so a pause inside that first 900 ms, from the space bar or the P key, a tap on the board, or the automatic pause when the window loses focus, quietly cancelled the rest of the wait: no bar left, and the snake setting off the instant you carried on. Only the game file changed, and by one line: the step clock is now kept while a game is paused, the same way the run clock already was. A fresh board, a board change mid-run and a finished run still start it from zero, and the wait in full is still exactly 900 ms. Files: the game file (one line and the comments around it) and the page (one sentence each in the keys list, the start-wait bullet, the label bullet and the automatic-pause bullet).

Version 1.57

Housekeeping, and only the page changed: every entry used to end with a paragraph of its own listing all the files that had not changed — the same list, with the same sentence about the browser, written out under each version, and most of this page's length. Each entry now ends with one short line, "Files: …", naming what did change; nothing was added and nothing false remains, and the older versions page was not touched. Files: the changelog page only.

Version 1.56

Bug fix: the P and N shortcuts no longer swallow presses that belong to the browser. The script acted on any press of P or N, whatever else was held down, so Ctrl + P paused the game instead of printing the page and Ctrl + N started a new game instead of opening a window (Cmd on a Mac the same); those chords, and any press with Alt held, now reach the browser, while the two keys still press the page's own Pause and New game buttons. A key held down no longer repeats itself either: a leaning finger on P used to flap the pause on and off and one on N started game after game. The script also checks up front that the four controls it drives are on the page and does nothing at all if one is missing, rather than throwing on a null. Files: the shortcuts script (the two guards and a comment) and the page (the keys list and the shortcuts bullet).

Version 1.55

Page copy only: the notes now describe the "Get ready" label the board draws at the start of a run, which version 1.54 added and said the notes had not yet mentioned. The new bullet sits right after the one about the 900 ms start wait and says what the label is and when it goes, that it is drawn from the same step clock that already held the wait so it cannot drift out of step with the snake, and that it is drawn only while a run is under way, so the idle screen, the paused panel and the finished panels are left as they were. The board's screen-reader label names it too. Files: the page only.

Version 1.54

The board now counts the wait at the start of a run: a small label sits in the top rows — "Get ready" over a bar that empties as the wait runs out — and disappears on the first step the snake takes. The status line has said since 1.31 that the snake holds still for 900 ms before its first move, but the board itself said nothing, so a player who had just pressed New game saw a still board with food on it and no way to tell whether the game had started or something had gone wrong. Only the game file changed, and this one is drawn, not computed: no rule of play, pace, score, board, block or ending moved, and the wait is still exactly 900 ms. The bar is driven by the step clock that already held the wait, so it needs no new state and cannot drift out of step with the snake; it is drawn only while a run is under way and under the panels, so it can never cover them. Files: the game file only. The page's notes were owed at the time and 1.55 wrote them in.

Version 1.53

Housekeeping: the entries for versions 1.32 to 1.38 moved to the older versions page, which now covers 0.1 to 1.38, and this page started at 1.39. Nothing was cut — each moved entry is there word for word, with one line added to say when it moved — and the older versions page records in its 1.9 entry that the range it holds grew. Both pages still link to each other in both directions. The reason is the usual one: this page is written whole by hand each time something changes, and it had grown past the length worth keeping up to date. Files: the changelog page and the older versions page only. (Version 1.69 later moved 1.39 to 1.52 to the previous versions page, so the main changelog then started at 1.53; version 1.79 moved 1.53 to 1.60 as well, so it then started at 1.61; version 1.84 moved 1.61 to 1.69 too, so it started at 1.70; version 1.97 moved 1.70 to 1.79 as well, so it then started at 1.80; and version 2.01 moved 1.80 to 1.89 too, so the main changelog now starts at 1.90.)

Version 1.52

The "Recent runs" line in the read-out now names the board each score was played on: "16×16 90 · 12×12 40" where it used to read "90 · 40". The four boards run at four different paces, so their scores are not comparable — 40 on Cozy 12×12 is a longer run than 40 on Classic 16×16 — and the flat list of numbers made a step forwards on a harder board look like a step backwards. Only the stats script changed: it already read the board out of every ending line for the per-board bests, and it now keeps that board beside the score and prints it shortened to the board's size; a run whose board cannot be read keeps the plain number it had before. Nothing else in the script moved — the same average, the same per-board bests, the same memory of the last 30 runs. Files: the stats script and the page (the list's row, the bullet about it, and a sentence in the average bullet saying the average mixes boards, so it is a rough figure on a mixed visit).

Version 1.51

The "Run clock" cell in the read-out is now written on every frame the page draws, so it counts through the 900 ms wait before the snake's first move — where it used to sit at "0s" and then jump — and on the slowest board, Cozy 12x12 at 190 ms a step, it no longer trails the real time by up to a step. Nothing about the clock itself changed: the same number, the same words ("47s", "1m 04s"), the same start, the same standstill while paused, and the same final time held after a run ends. Only the moment the cell is written moved, and 1.49's note that it could lag by up to one step no longer holds. Files: the game file (one line in the frame, the write at each step kept) and the page (the bullet about the cell, the start-wait bullet, and the board's screen-reader label).

Version 1.50

A run that ends on a grey block or on the snake's own tail now leaves a red cross on the square that ended it, drawn on the board over the snake. The ending panel already said why in words — "you hit a block", "you bit your own tail" — and the shape the snake died in only implied where. It is the only warm red on the board, so it cannot be taken for the food, the snake or a grey block, and a run that ended on the wall leaves none at all: the wall is the edge of the board, so there is no square to point at. The cross belongs to the board it was made on, so the next run — a new game, or a board change mid-run — takes it away, and the status line names it: "The square that ended the run is marked on the board." Files: the game file (the square is set in the two collision branches it already had and drawn in the same frame that draws the snake; no rule of play, pace, score or message about play changed, and no new state beyond the one square) and the page (one bullet, and the board's screen-reader label).

Version 1.49

The read-out under the board gained a "Run clock" cell, between Level and Best this visit: it shows the current run's time in the same words the endings use — "47s", "1m 04s". The clock has been carried by the panel over the board, the status line and the pause messages since 1.47, but only after a run had ended or been paused; while a game was actually being played there was no way to see how long this break had lasted without stopping it. It is the same clock, read from the same number, so the four cannot disagree: it counts from the moment a run starts, so the 900 ms start wait is part of it, and it adds nothing while the game is paused. Paused, it stands still; after a run it holds that run's final time until the next run starts; before your first run of the visit it reads "0s". It was refreshed as the snake took its steps, so between steps it could lag the real time by up to one step. Files: the game file (it writes the cell beside the counters it already wrote) and the page (the cell and one bullet).

Version 1.48

The copyable line under the stats now carries the run clock as well, in the same words the panel over the board and the status line use: "Snakeyard: score 80 at level 3 in 47s on Classic 16×16 at 135 ms a step. …". The script's reading of the ending line takes an optional clock clause — "in 47s" or "in 1m 04s" — and writes it after the level, before the board and the pace; an ending line with no clock in it still parses and prints exactly as it did in 1.47. The copy is the one part of the page meant to be taken away, and how long a run lasted is half of what makes two scores comparable, since the four boards run at four different paces. Files: the result script and the page (two claims that the copyable line had no time in it were corrected, and the example in the card's bullet now shows the clock).

Version 1.47

A finished run now says how long it lasted. The panel over the board reads "Score 120 at level 3 in 1m 04s" where it used to read "Score 120 at level 3", and the status line under the board carries the same words just before the board and the pace. The clause sits between the level and the board-and-pace sentence, so every clause that was there before is still there in the same order, and the stats and result scripts keep the patterns they already used. The clock counts real time from the moment a run starts, so the 900 ms start wait is part of it; it adds nothing while paused or after a run has ended, and a new run — a board change mid-run included — puts it back to zero. The three pause messages report the time so far ("Run clock so far 12s"). Time reads in whole seconds under a minute ("47s") and in minutes above it ("1m 04s"). Files: the game file and the page (one bullet for the clock; the sentence saying the copyable line still had no time in it was corrected by 1.48).

Version 1.46

Page copy only: the page's description of the end of a run now mentions the sentence version 1.45 added to the status line under the board. The notes said the ending panel named the board and the pace and the read-out repeated it, but nothing on the page said the read-out also tells you where the run stands against the best score finished on that same board — a new best there, level with it, or the number still to beat. The new bullet sits right after the one about the panel naming the board and the pace, and says the three wordings, that the sentence comes after the board-and-pace sentence and before the "New best for this visit!" clause, that both endings get it, and that the endings read exactly as they did before until that board has a finished run. This closes the one item 1.45 said it owed. Files: the page only.

Version 1.45

When a run ends, the status line under the board now says where that run stands against the best score finished on the board it was played on: "That is a new best on the Classic 16x16 board.", "That is level with your best on the Cozy 12x12 board." or "Your best on the Tight 20x20 board is 120." It sits in the read-out rather than on the panel over the board, because the panel's four lines are full, and it is the same number the pause messages have named since 1.40 and the idle screen since 1.39. Both endings get it, in the same place: after the board-and-pace sentence, before the "New best for this visit!" clause. The comparison is against the best from before the run, since the stats script files a finished run only after that line is built, so the number read is genuinely the score to beat; until that board has a finished run the endings read as they did in 1.44. Files: the game file only; the page's description was owed at the time and 1.46 wrote it in.

Version 1.44

Housekeeping: the entries for versions 1.23 to 1.31 moved to the older versions page, which then covered 0.1 to 1.31, and the main page started at 1.32. The reason is the usual one — the main changelog is written whole by hand each time something changes, and at about 21 kilobytes it had grown past the length worth keeping up to date. Nothing was cut: each moved entry is there word for word, with one line saying when it moved, and the older versions page records in its 1.9 entry that the range it holds grew. Both pages still link to each other. Files: the two changelog pages only. (Version 1.53 later moved 1.32 to 1.38 as well, so the main page then started at 1.39, and version 1.69 moved 1.39 to 1.52 to this page.)

Version 1.43

Page copy only: two things the game does are now written down. The notes on "Best on each board" say the board you have picked is named again on the idle screen — the dimmed board you see before a run starts — once that board has a finished run, so the score to beat can be read before pressing New game; that idle line shipped in 1.39 and the page had never described it. The second is the paused panel: since 1.36 a pause names the board and the pace on the panel and in the status line — "Classic 16×16 at 135 ms a step" — so a break mid-run tells you which run you are in. Files: the page only (two sentences added to two bullets).

Version 1.42

The copyable line now names, in brackets, the board that holds your best score for the visit whenever that board is not the one you just played: "Best this visit 140 after 4 games (set on Cozy 12×12), 60 more than this run." "Best this visit" counts all four boards together, so a player who had played Classic and read a visit best of 140 beside their Classic best of 120 could not tell whether the 140 had been set somewhere else or whether the two numbers simply disagreed. The board is named only when the page already shows it: the names come from the "Best on each board" cell, and a board is named only when its own shown best equals the visit best exactly, it is a different board from the run's, and no second board is level with it; otherwise the brackets are left off rather than a guess being made. Boards are compared with the multiplication sign and a plain x treated as the same character. Files: the result script (the lookup beside the reading of the counters it already did) and the page (its example of the line).

Version 1.41

The copyable line now says how far your best score for the whole visit is ahead of the run you just finished: "Best this visit 140 after 4 games, 60 more than this run." It already named the gap to your best on that one board, but "Best this visit" counts all four boards together, so a player who had done better on a smaller board got the number with no sense of how far off it was. When the run itself set the visit best there is no gap clause at all: the number is then the run's own score, and the line already calls it a new best. The clause appears only when the visit best is strictly above the run's own score, so the line still cannot claim anything the page does not show; one detail rests on how browsers are specified rather than on a recording — the stats script is loaded before the result script, and observers run in the order they were made, so each finished run is filed in the counters before the sentence is written from them. Files: the result script and the page (its example of the line, which had numbers that could not all have come from one run, now uses one set that can).

Version 1.40

The pause messages now name the best score finished on the board you are paused on — "Best on the Classic 16x16 board: 240" — alongside the visit summary they already gave. That number has been on the idle screen since 1.39 and in the read-out beside the board even longer, but the moment a run began it was out of sight, so a player stopped mid-run could not see what they were chasing on that board. The panel over the board was not the place for it: its four lines are already full. All three ways into a pause gained it, and gained it the same way, through one small helper beside the idle screen's own lookup: the space bar or the Resume button, a tap on the board, and the automatic pause when the window loses focus. Until the board you are playing on has a finished run, all three messages read exactly as they did in 1.39, and if the stats script were missing they would read that way too; the number comes from the same per-board bests the read-out shows, so the two cannot disagree. Files: the game file, plus one sentence in the page's notes.

Version 1.39

The idle screen — the dimmed board you see before the first game — now names the best score finished on the board you have picked, once that board has one: "Best on the Classic 16x16 board: 240". The per-board bests were already kept and already shown in the read-out beside the board, but a player who had just chosen a board could not see what they had to beat on it without finishing a run first. Until a board has a finished run, the idle screen keeps the two plain lines it has always had. The stats script gained a small lookup that finds a board's best by name, and it hands that one line to the game through the same optional door the run average already uses, so if that script were missing the idle screen would simply read as it always did; the game reads it fresh each frame, next to the code that draws the panel, so no new state is kept. Files: the stats script and the game file.

Version 1.38 and earlier

Entries for versions 0.1 to 1.38 are on the older versions page: the first version of the game, the speed-up and blocks toggles and the per-board block counts, the level counter, the pause summary, the Huge board, the run average in the panels, the "How to play" box, the "Recent runs" list, the board-and-pace line on the end panels, the copyable end line, the best score kept separately for each board, the keyboard and focus fixes, the tap and window-focus pauses, the 900 ms start wait, and the housekeeping trims up to 1.53.

Back to the main changelog · Back to the game