For a long time the JoyLite maze had been sitting in a box in my basement. After a great experience using AI (ChatGPT specifically) to help program an e-Ink display (writeup coming soon), I thought it might be nice to resurrect the JoyLite project and tackle a few things that had always nagged at me.
The first limitation that bothered me was that i could only support a 3x3 set of tiles. The maze was hardcoded to 21x21, and while this didn't constitute a completely trivial solve, it didn't hold peoples attention for very long. Memory constraints (at least the way I developed it) got in the way.
Secondly, getting to the end of the maze was kind of anti-climactic. you just... get there. Then you hit the atari button, wired to RESET, and start again.
So, I worked with an AI to help optimize some things.
New code: https://github.com/joetcochran/JoyLiteMaze/blob/master/SeeedMaster_maze2/SeedMaster_maze3.pde
It had always nagged at me that I was using a bool array for the 2D maze pattern. we were using 1 byte per cell, and we could get away with using 1 bit per cell, packing a lot more information into a tighter memory space. This was the biggest improvement made.
Another improvement was to not send the full frame buffer [3][8][8], to send one row at a a time. the full [3][8][8] is certainly easy to visualize, but not optimal from a memory management perspective.
Finally I replaced some unused globals and replacing some larger types with smaller ones like uint8_t and int8_t.
Testing
To test, I ran a hardcoded 5x5 maze, and it worked. With the old code, the lights would not even turn on because of the memory issues. I pushed it to 8x8 and that worked as well.
Maze Complexity Selection
I added an interactive complexity selection screen that highlights for a simple 1x1 tiles maze, 2x2 tiled maze, etc all the way up to 8x8. You use the joystick to grow/shrink the complexity selection. To actually "select" you just leave the joystick alone for a few moments. I can't use the joystick button because I still want to have it for RESET purposes. The arudino waits for a few moments and begins the maze with the chosen complexity.
A new bug appears
For even tiled mazes (2x2,4x4,6x6,8x8) the "goal" green dot would appear in a wall because it was hardcoded to the (6x6) coordinate.
Using 0-based indexing for rows and columns:
In this maze generator, the primary carved maze cells lie on odd global row / odd global column coordinates. The generator moves in steps of 2, so those odd/odd positions are the main “maze nodes,” and the cells between them are opened as connectors. The whole maze is also bound by a global outside border.
For the first tile, tile A, the tile offset is 0, so local coordinates map directly to global coordinates. That means the odd global columns in tile A are local columns 1, 3, 5, and the odd global rows are local rows 1, 3, 5. So in tile A, the generator’s natural carved-cell lattice lines up with local odd coordinates.
Now consider moving one tile to the right, from tile A to tile B. The tile stride is 7, so tile B starts at a global column offset of 7 (not 8!). The two tiles share that boundary column. Column 7 of tile A is the same physical maze column as column 0 of tile B. Because tile B has an ODD offset from the global maze coordinate (7) tile B, the odd global columns now line up with local columns 0, 2, 4, 6, while local columns 1, 3, 5, 7 line up with even global columns.
The same parity flip happens for rows when moving vertically by one tile, since the row stride is also 7.
That is why a goal position like (5,5) works for some tile counts but not others. In the final tile of an odd-sized tile grid, (5,5) maps to an odd/odd global coordinate, which matches the generator’s carved-cell lattice. In the final tile of an even-sized tile grid, (5,5) maps to an even/even global coordinate instead, so it can land on a wall. In those even-sized grids, (6,6) is the correct local goal position because it maps back to an odd/odd global coordinate.
The fix on this was: for odd tiled mazes, show the goal in coordinate (5,5) of the lower-righthand tile and for even tiled mazes show it in (6,6)
A Better Ecnclosure
Rainbowduino diffuser: https://www.thingiverse.com/thing:1638743
Diffuser Panel: https://www.thingiverse.com/thing:7347142
Wiring details
Arduino Inputs
D3 = Down
D4 = Right
D5 = Up
D6 = Left
RESET = Button Press
Joystick wire colors:
Black = GND
Green = RESET
Red = Left
White = Right
Orange = Up
Yellow = Down
Rainbowduino to Arduino mappings
PWR - Arduino 5V
GND - Arduino GND
SDA - Analog 4
SCL - Analog 5