Module number two for the screaming.computer is a Maze Generator!
After much research into maze generation algorithms, I realized it was fascinating, but a deeper rabbit-hole than I wanted to explore at the moment. Thankfully there are plenty of pre-written maze generators available online, ready to use with some minor tweaks.
I grabbed Bill Parrott's PHP maze class since it seemed pretty straightforward. It generates random mazes of arbitrary size, but unfortunately only renders them to an HTML-based text format.
I modified the display algorithm to instead generate a PNG image via ImageMagick (as in the example image here), and expanded the code to allow for arbitrary cell size.
Once the image generation was in place, I needed to adapt it to the constraints of my thermal receipt printer. Finished off a roll of paper during the dev process; thankfully I bought a big multipack of supplies.
The major issue that immediately presented itself was the printer failed to print the top and bottom borders of the maze image. As far as I can tell, the printer just can't handle a solid horizontal line. I tried increasing the line thickness, but to no avail. Something about the thermal printing process responds poorly to large streaks of pure black (I saw this with the dithered Magic 8-Ball image as well).
The solution I came up with was to rotate the image, thereby causing perfectly-horizontal lines to break up over multiple rows. I experimented with various degrees of rotation; 30° and 45° rotations looked most visually pleasing, but the necessary reduction in size was too much for my taste. I settled on a counterclockwise 1° rotation. It looks a little crooked, but serves the purpose of fixing the horizontal line printing issue.
Various stages of development and testing can be seen here:
The code was then integrated into my standardized module interface. This means when the screaming.computer is run, a module is randomly selected and executed. So far I have just two: the 8-Ball and this Maze.
In the spirit of variety, I randomly select a cell size and maze height (within sensible constraints given the printer resolution). The smaller the cell the more “difficult” the maze is considered to be. Mix in some fun strings to describe the difficulties, and boom, we're done:
$randDifficulty = random_int (0, 1000) / 1000.0;
$cellSize = (int) round (($maxCellSize - $minCellSize) * (1.0 - $randDifficulty)) + $minCellSize;
$difficulties = array ('Trivial', 'No sweat', 'Easy-peasy', 'Pretty easy', 'Not so hard', 'Make you think', 'Extra medium', 'Time consuming', 'Challenging', 'Expert', 'Painful', 'Hurt me');
$difficultyStr = mb_strtoupper ($difficulties[(int) round ($randDifficulty * (count ($difficulties) - 1))]);