Hidden link you should not click

Puzzle Game: Snek!

This is a puzzle where you have to remove all the arrows from the game board, one by one. Click arrows that have a clear straight path to the edge and are not blocked by other arrows. The puzzle is guaranteed to be solvable, there is always at least one arrow that can be removed. You can make as many errors as you like, there is no time limit or lose condition.

Settings


Why?

I really like this puzzle game on mobile and started wondering how level generation might work. Generating solvable and interesting puzzles is actually quite a challenge. I wanted to test my theory and just started coding, one thing led to another, and there it is: a pure vanilla JavaScript puzzle game written entirely by hand (no AI) and from scratch (no framework).

The goal here was not to write the perfect game, but to experiment and learn something. It's nice to work on small and useless projects once in a while. Enjoy :)

How are levels generated?

The level generator builds the puzzle in the same order in which a player would later be able to solve it. For each new arrow, the generator chooses a random free cell and direction, and then checks the escape route. Since all existing arrows are guaranteed to be removable before the current one, we can safely escape through occupied cells. The minimum arrow length is 2, so isolated free cells surrounded by arrows are also safe to travel through. If we hit a free cell that also has a free neighbor, then a later arrow may be placed there and block our current arrow, creating a deadlock. We could mark this cell as reserved to prevent the deadlock, but that would result in a sparse game board with lots of holes. Instead, we just scrap the current arrow and find a new spot.

Once we found a valid position and direction for a new arrow, we extend it backwards into neighboring free cells using a random walk. We can tweak the probability for bends or endings to control the visual appearance and difficulty of the game. Short arrows and lots of bends make the game harder, and sometimes more annoying.

This will give us a solvable game, but not necessarily an interesting game. Let's add a heuristic for how fun an arrow is, and for each step, generate a bunch of random valid arrows and choose the one that is the most fun.

The current heuristic favours longer arrows with bends (both tunable), but also rewards challenging arrows. Here is the idea: If you are stuck as a player, it's a common tactic to choose a random arrow that annoys you, check which arrow blocks it, and track those arrows until you find one that can be removed. You then backtrack and remove the previous arrow, if possible, or continue your search. This is what makes the game challenging in a good way. An interesting game requires lots of tracking and backtracking.

To calculate the fun score for a possible new arrow, we analyse its escape path. All arrows that block our candidate are tracked and counted as direct dependencies. Those blocking arrows may also have dependencies themselves, so we can think of this as a dependency tree. All arrows in this tree have to be removed before the current arrow can be removed.

A large dependency tree prevents the player from removing the arrow too early. A deep tree means that they have to follow more arrows before they find an exit, making solutions less obvious and the chase more fun. A wide tree means that they cannot immediately remove the previous arrow and have to backtrack more often, as there are more arrows in the way. A balance of those three metrics makes the game more challenging, especially with large game boards.

Want to know all the details? Here is the code :)