Here we are, 24 hours into the competition.
A lot of the last few hours has been spent doing a fair amount of restructing. Before, I had a single ’thread’1 for each of the tiles, along with another thread listening for user input. Unfortunately though, that lead to all sorts of race conditions. Specifically, whenever two tiles overlapped, it was often the case that one was doing the falling step (which copies from one internal buffer to another) while the other was in the swap step (which copies from tile to another). Then after the first finished, it would copy the second buffer over… overwriting anything that had been swapped.
Oops.