Browse code

Use less redundant and branchy neighbor iteration

Robert Cranston authored on 21/05/2025 20:13:27
Showing 1 changed files

  • maze.cpp index 40ab8ca..d66838f 100644
... ...
@@ -61,28 +61,34 @@ Maze hunt_and_kill(int w, int h, unsigned seed, C callback = [](Maze &){})
61 61
     auto done = false;
62 62
     while (!done)
63 63
     {
64
+        #define FOR_NEIGHBOR(...) \
65
+            for (auto i = 0; i < 4; ++i) \
66
+            { \
67
+                auto ni = i%2*4-2;   /* -2, +2, -2, +2 */ \
68
+                auto nx = ni* (i/2); /*  0,  0, -2, +2 */ \
69
+                auto ny = ni*!(i/2); /* -2, +2,  0,  0 */ \
70
+                __VA_ARGS__ \
71
+            }
64 72
         // Call callback.
65 73
         callback(maze);
66 74
         // Find number of neighbors.
67 75
         auto n = 0;
68
-        for (auto ny = -2; ny <= 2; ny += 2)
69
-        for (auto nx = -2; nx <= 2; nx += 2)
70
-            if (!nx != !ny)
76
+        FOR_NEIGHBOR(
71 77
             if (maze(cx+nx, cy+ny) == Maze::WALL)
72 78
                 ++n;
79
+        )
73 80
         // If we have neighbors, carve path to random one.
74 81
         if (n != 0)
75 82
         {
76 83
             n = std::rand() % n;
77
-            for (auto ny = -2; ny <= 2; ny += 2)
78
-            for (auto nx = -2; nx <= 2; nx += 2)
79
-                if (!nx != !ny)
84
+            FOR_NEIGHBOR(
80 85
                 if (maze(cx+nx, cy+ny) == Maze::WALL && n-- == 0)
81 86
                 {
82 87
                     maze(cx+nx/2, cy+ny/2) = maze(cx+nx, cy+ny) = Maze::PATH;
83 88
                     cx = cx+nx;
84 89
                     cy = cy+ny;
85 90
                 }
91
+            )
86 92
             continue;
87 93
         }
88 94
         // No neighbors, done unless there's an uncarved cell to restart at.
... ...
@@ -90,17 +96,17 @@ Maze hunt_and_kill(int w, int h, unsigned seed, C callback = [](Maze &){})
90 96
             for (; ry < h; ry += 2, rx = 1)
91 97
             for (; rx < w; rx += 2)
92 98
                 if (maze(rx, ry) == Maze::WALL)
93
-                    for (auto ny = -2; ny <= 2; ny += 2)
94
-                    for (auto nx = -2; nx <= 2; nx += 2)
95
-                        if (!nx != !ny)
99
+                    FOR_NEIGHBOR(
96 100
                         if (maze(rx+nx, ry+ny) == Maze::PATH)
97 101
                         {
98 102
                             cx = rx+nx;
99 103
                             cy = ry+ny;
100 104
                             return false;
101 105
                         }
106
+                    )
102 107
             return true;
103 108
         }();
109
+        #undef FOR_NEIGHBOR
104 110
     }
105 111
     // Exit.
106 112
     w -= (w + 1) % 2;