Thu 24 February 2022
Emma and I are now selling themed puzzle sets for use as entertaining party favours for events like weddings, and stag and hen parties. The idea is that you'd buy enough to give one to every attendee, and people who want to can try to solve it, and regardless they can take it home afterwards. There's also a competitive element: each puzzle has a QR code inside which the successful player can scan to add their name, and solve time, to the event's private online leaderboard.
It's called "Party Puzzling" and we have a website at partypuzzling.co.uk and an Etsy shop at https://www.etsy.com/uk/shop/PartyPuzzling. Right now we're charging £7.50 per puzzle. They cost about £2 in materials and I can only produce 8 per day, so we're not going to get rich off this any time soon. But I still think it's a fun idea.
We first did this for our own wedding, with chess-themed puzzles, and people liked it, which is why we're making them available for sale. We're offering Easy, Medium, and Hard difficulty options, although I still haven't completely finalised the difficulty calibration. Every puzzle in the same order will get the same maze.
The puzzles consist of a maze on the inside of a cylinder, and a peg on the inner piece which follows the track of the maze. To get the inner piece out you need to solve the maze, which is tricky because you can't see it.
So far we only have the beer bottle theme up for sale, but the chess piece theme is mostly finished and will probably go up on Etsy soon. If you have any good ideas for puzzle themes please let me know! A good theme would be a well-known object with a roughly cylindrical shape, with a sensible "parting line" to allow the 2 halves to rotate.
The thing that makes hidden mazes hard for most people is that they don't know the general technique for solving them. Most mazes can be trivially solved by simply holding your left (or right) hand against the left (or right) wall, and following the left (or right) wall until you reach the exit. This works even if you have no way to find out whether you've already visited a given point in the maze. You don't need to remember anything, it just automatically follows the walls all the way to the exit.
If you didn't already know this algorithm, perhaps you want to convince yourself of its correctness. Here's an easy example you can try it out on:
You should be able to see that by following one of the walls you expect to explore 50% of the maze before you find the exit. If you can't see any more than your immediate surroundings (which you can't if the maze is invisible) then no algorithm can do better than this in the general case (I claim but do not prove).
You might think (as I did, before I thought about it enough) that this only works because there are no cycles in the maze. You might think that if we add a cycle, then it is possible to get trapped on the cycle:
Not so. Far from trapping the player on the cycle, you actually isolate the player from the cycle! There is no way to add a cycle whose walls are connected to the outside walls of the maze (otherwise it's not a cycle), which means there is no way for a player who is following the walls of the maze to reach the cycle in the first place. (Although it is true that a player who reaches the cycle by some other method, and then begins to follow the left-hand-wall algorithm, will indeed remain trapped.)
However, putting the maze on the inside of a cylinder gives us a distinct advantage! Represented on a 2D drawing, the left-hand edge of the maze wraps around to the right-hand edge. If we make a cycle that wraps all the way around the circumference of the cylinder, then we can trap the player in the cycle, and isolate them from the rest of the maze:
So we can use this trick to make the mazes challenging even for people who know the left-hand-wall algorithm :).
Manually designing cylindrical mazes in FreeCAD is really annoying, so I have quite a fun build pipeline.
I first draw an ASCII art maze in vim, a simple example would look something like:
- ---------- | | - --- - --- | | | ------- --- | | | - ----- --- | - --- - ---- | | - ---------- ------------
I then have a Perl script which reads in the ASCII art maze and produces an OpenSCAD source file that produces a 3D model of a flat maze:
To save time, I also have a Perl script which can generate the ASCII art mazes, and another script that can take in a maze and give a number for how complicated it is. I run these 2 together in a loop to search for mazes of the appropriate difficulty. Finding a metric for how difficult it is to solve a maze is quite hard, so there's still a lot of manual "curation" here. A key part of the measure is the question:
Having got an ASCII art maze ready, I have a rust program that reads in an STL file and wraps it up into a cylinder. This works by splitting large triangles up into tiny ones, and then rewriting the coordinates by interpreting them as Polar coordinates and rewriting them as the Cartesian equivalents:
And I can run a command like mkpuzzle beer easy-maze which will use the above steps to generate an STL file from the ASCII art in easy-maze, and merge it with the manually-modelled outer part of the beer theme, ready for 3D printing.
For our wedding I generated a load of random hex strings to use for the leaderboard codes. I thought it would be funny if there was an extra layer to this, so instead of just choosing random hex strings and putting a list of them in a database, I made the rule that all strings with a SHA256 sum beginning beef42... were accepted as valid codes. With the idea that if anyone went to the trouble of finding out the SHA256 sum of more than 1 code, then they might get some joy out of making a "keygen" and submitting hundreds of falsified entries to the leaderboard.
Unfortunately, restricting the search so tightly led to me creating a handful of duplicate codes without realising it, so a couple of the guests found that when they solved the puzzle and tried to scan the code, it was rejected. Egg and my face were in alignment!
So for Party Puzzling I am just generating a bunch of random strings and putting them in the database.If you like my blog, please consider subscribing to the RSS feed or the mailing list: