I spent the last week learning Clojure and generating jigsaw puzzles as part of my one-week programming retreat at the Recurse Center.
Why jigsaw puzzles? I was motivated by two things: first, I wanted a good-sized language-learning project. Secondly, I was heavily inspired by the amazing, beautiful, intricate jigsaw puzzles produced by Nervous Systems and wanted to experiment with similar-ish generative methods. (I’m a sucker for generative things and hadn’t played with generative algorithms too much before.) If you want a crazy cool puzzle, seriously, go buy one from Nervous.
I think they turned out well!
![A hand holding the cat-shaped puzzle piece.](https://blog.bonnieeisenman.com/images/svg-puzzles/puzzle-cat-piece.JPG)
Because I have access to NYC Resistor’s laser cutter, the obvious thing to do was generate SVGs which I could then laser cut. If you haven’t worked with SVG before, it’s an XML-based format for describing vector graphics. It’s pretty easy to generate “by hand”.
Here is what an SVG looks like, if you open it up with a text editor:
<svg width="100" height="100">
<circle
cx="50"
cy="50"
r="40"
stroke="green"
stroke-width="4"
fill="yellow"
/>
</svg>
This produces a yellow circle, centered at (50, 50), with a radius of 40, and a four-pixel green outline. You can view an SVG file in any web browser, or edit it in an editor like Inkscape.
![A yellow circle](https://blog.bonnieeisenman.com/images/svg-puzzles/00-basic-circle.png)
See? Easy-peasy.
I started by generating a “classic” jigsaw puzzle shape, and figuring out how to tile it.
![A grid of mostly-identical jigsaw puzzles](https://blog.bonnieeisenman.com/images/svg-puzzles/02-grid.jpg)
But I wanted something more interesting than just a grid of similar puzzle pieces! My next step was to use a Voronoi diagram to draw more irregularly-sized polygons around “seed” points. At first this created some amusing failures:
![A grid of orange dots and some black lines between them. Something looks weird - the lines skew off in random directions!](https://blog.bonnieeisenman.com/images/svg-puzzles/03-blooper-voronoi.jpg)
Oops. This is what happens when you draw points at (x, x) instead of (x, y). Let’s fix those coordinates.
![A grid of orange dots, surrounded by black lines representing voronoi edges. Now they actually are enclosed cells, like they're supposed to be.](https://blog.bonnieeisenman.com/images/svg-puzzles/04-voronoi.jpg)
If we replace those straight lines with puzzle-piece edges, we get something that starts to look like a more interesting puzzle. There are still obviously flaws to be ironed out here (e.g. edge overlap).
![Similar to the previous image, polygons constructed by voronoi tiling then have their edges deformed using puzzle-piece-like squiggles. There is some overlap between lines so this would not make a good puzzle.](https://blog.bonnieeisenman.com/images/svg-puzzles/05-simple-voronoi-tiling.jpg)
I wanted to make more novel puzzle piece shapes, though, so I turned to the SVG path
type. You can draw Bézier curves in SVG pretty easily:
<path d="M 0 0 C 0 -100 50 -100 50 0 S 100 100 100 0"
stroke="blue"
fill="transparent"
transform="translate(0 400)"/>
![A blue curve that dips up then down.](https://blog.bonnieeisenman.com/images/svg-puzzles/06-01-bezier-blue.png)
OK, here’s what it looks like when we replace our puzzle piece shape with some random-ish curves:
![More puzzle pieces, now with squiggles.](https://blog.bonnieeisenman.com/images/svg-puzzles/07-simple-bezier-tiling.jpg)
Add more curves and it gets even better!
![Very squiggly pieces.](https://blog.bonnieeisenman.com/images/svg-puzzles/08-many-squiggles-tiling.jpg)
I also experimented with variations on how to place the seed points for my puzzle generation. Here’s one that’s based on a circular point distribution.
![A puzzle arranged by concentric circles of squiggles.](https://blog.bonnieeisenman.com/images/svg-puzzles/12-circular.png)
Now I had some monstrously-irregular puzzle pieces to play with. Cool! I wanted to take it one step further by implementing whimsy pieces. In jigsaw jargon, a whimsy piece is a themed, recognizably-shaped puzzle piece. They might be butterflies or people or letters or…you name it!
I modified my puzzle-generator to clear space for a whimsy piece, first testing it with circular whimsy pieces.
![A puzzle with two circular pieces placed inside it.](https://blog.bonnieeisenman.com/images/svg-puzzles/09-01-whimsy-clearing.png)
Then, using a kd-tree, I identified the whimsy piece’s nearest-neighbors and connected it back to the rest of the puzzle. Here’s a cat!
![Same image as earlier - a puzzle with a cat-shaped piece in it.](https://blog.bonnieeisenman.com/images/svg-puzzles/11-cat-whimsy.png)
And, finally, I took these files over to NYC Resistor and lasered them.
![Laser cutting cutting puzzle pieces into white acrylic](https://blog.bonnieeisenman.com/images/svg-puzzles/lasering.gif)
![The completed puzzle, with the cat whimsy removed.](https://blog.bonnieeisenman.com/images/svg-puzzles/puzzle-cat.jpg)
It took a group of us about ninety minutes to solve the cat puzzle. Not bad for four days’ work!
![Several people gathered around the puzzle, working on solving it.](https://blog.bonnieeisenman.com/images/svg-puzzles/puzzle-cat-playtesting.jpg)
All of the code is available on Github at bonniee/svg-puzzle-gen. (It’s my first Clojure program, so I’m sure there are plenty of non-idiomatic things happening there.)
Dependencies / thank-yous:
Testimonials from playtesters:
- “This is awesome!”
- “This is horrible!”
- “This is amazing! And by amazing I mean terrible!”
- “Why are all the puzzle pieces the same ???”
- “Is this supposed to be evil?”
- “How can I get one?”