61 {
62
63 gravity_deg += 225.0f;
64 if (gravity_deg >= 360.0f) gravity_deg -= 360.0f;
65
66
67 float angle_rad = gravity_deg * PI / 180.0f;
68 float gx = std::cos(angle_rad);
69 float gy = std::sin(angle_rad);
70
71
72 static const std::vector<std::pair<int, int>> directions = {
73 {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1},
74 };
75
76
77 std::uniform_real_distribution<float> noise_dist(-30.0f, 30.0f);
78
79
80
81 std::vector<std::tuple<int, int, int, int>> moves;
82
83
84 std::array<std::array<bool, SIZE>, SIZE> occupied_next = {};
85
86
87 std::vector<std::pair<int, int>> traversal_order;
88 for (int r = SIZE - 1; r >= 0; --r) {
89 int center = SIZE / 2;
90 traversal_order.emplace_back(r, center);
91 for (int offset = 1; offset < SIZE; ++offset) {
92 int left = center - offset;
93 int right = center + offset;
94 if (left >= 0) traversal_order.emplace_back(r, left);
95 if (right < SIZE) traversal_order.emplace_back(r, right);
96 }
97 }
98
99
100 for (auto [r, c] : traversal_order) {
101 if (!grid_[r][c]) continue;
102
103 float noise_deg = noise_dist(rng_);
104 float cos_threshold = std::cos((55.0f + noise_deg) * PI / 180.0f);
105
106 std::pair<int, int> best_move = {0, 0};
107 float best_dot = -2.0f;
108
109
110 for (auto [dr, dc] : directions) {
111 int nr = r + dr;
112 int nc = c + dc;
113 if (!InBounds(nr, nc) || grid_[nr][nc])
114 continue;
115
116 float vx = static_cast<float>(dc);
117 float vy = static_cast<float>(dr);
118 float len = std::sqrt(vx * vx + vy * vy);
119 if (len == 0.0f) continue;
120
121 vx /= len;
122 vy /= len;
123
124
125 float dot = vx * gx + vy * gy;
126
127
128 if (dot > cos_threshold && dot > best_dot) {
129 best_dot = dot;
130 best_move = {dr, dc};
131 }
132 }
133
134
135 if (best_dot > -1.0f) {
136 int nr = r + best_move.first;
137 int nc = c + best_move.second;
138
139 if (!occupied_next[nr][nc]) {
140 occupied_next[nr][nc] = true;
141 moves.emplace_back(r, c, nr, nc);
142 }
143 }
144 }
145
146
147 for (auto [r, c, nr, nc] : moves) {
148 grid_[r][c] = false;
149 grid_[nr][nc] = true;
150 }
151
152
153
154 }