mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
Files

This is the most efficient way to apply the combinatorial coordinate system. As described in my original article (and mentioned again in the followup one), you can walk along a horizontal or vertical line of the tiling, identifying which edge of each tile the line will leave it by, and computing the location and coordinates of the next tile beyond that edge, so that you visit every tile intersected by the edge. By doing one iteration, say vertically up the left of your target area, and using the tiles you find as starting points for a series of perpendicular sub-iterations spaced closely enough not to miss any tiles, you can arrange to visit every tile intersecting your target region, without having ever had to store a large BFS queue of tiles left to visit. You only have to keep a small bounded number of coordinate variables for the whole run, so you can generate a very large patch of tiling with minimal memory and CPU time. You can even arrange not to emit any duplicates, without having to actually store the tiles you've already visited, by checking whether the y-coordinate of the previous horizontal iteration will have visited the same tile already. For Spectres, an extra wrinkle (almost literally) is that they're not convex, so a horizontal line can visit the same one twice, with another tile in between. So another part of de-duplication is noticing _that_: is the edge through which we've just entered this tile the first one we would have seen while traversing our line? If not, then trust that it's been emitted already. As a proof of concept (since I claimed it would work in my writeup article), and in case anyone wants larger tilings than actual Loopy will conveniently give you, I've implemented that algorithm in spectre-test. However, the actual grid generation for Loopy still uses the more memory-intensive breadth-first search: because that's what I implemented first (it's more likely to detect its own errors); because if I changed it now it would invalidate game descriptions (from all of two days' worth of live play, but even so); and because the linear space requirement isn't an important cost for Loopy, which is actually going to _store_ the whole grid after it's generated, so it needed linear space _anyway_.