Skip to content

Commit fdf457e

Browse files
committed
feat: add NormalizeCenterMarkers function to adjust grid center markers
1 parent cb9957a commit fdf457e

2 files changed

Lines changed: 107 additions & 2 deletions

File tree

src/RUL0.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,107 @@ namespace RUL0 {
158158
return translated;
159159
}
160160

161+
// Keep '<' (center row) on the right edge and '^' (center column) on the bottom edge
162+
void NormalizeCenterMarkers(Grid& grid, const char fillChar = kEmptyLayoutCell) {
163+
if (grid.empty()) {
164+
return;
165+
}
166+
167+
grid = NormalizeGrid(grid, fillChar);
168+
const size_t originalWidth = grid.front().size();
169+
size_t height = grid.size();
170+
size_t width = grid.front().size();
171+
172+
auto hasCenterRow = false;
173+
size_t centerRow = 0;
174+
auto hasCenterCol = false;
175+
size_t centerCol = 0;
176+
177+
for (size_t y = 0; y < height; ++y) {
178+
for (size_t x = 0; x < width; ++x) {
179+
const char cell = grid[y][x];
180+
if (cell == '<') {
181+
hasCenterRow = true;
182+
centerRow = y;
183+
grid[y][x] = fillChar;
184+
}
185+
else if (cell == '^') {
186+
hasCenterCol = true;
187+
centerCol = x;
188+
grid[y][x] = fillChar;
189+
}
190+
}
191+
}
192+
193+
if (!hasCenterRow && !hasCenterCol) {
194+
return;
195+
}
196+
197+
const auto isRowEmpty = [&](const size_t rowIndex) -> bool {
198+
return std::ranges::all_of(grid[rowIndex], [&](const char c) {
199+
return c == fillChar;
200+
});
201+
};
202+
203+
const auto isColEmpty = [&](size_t colIndex) -> bool {
204+
return std::ranges::all_of(grid, [&](const auto& row) {
205+
return colIndex < row.size() && row[colIndex] == fillChar;
206+
});
207+
};
208+
209+
if (hasCenterRow && centerRow < grid.size() && isRowEmpty(centerRow)) {
210+
grid.erase(grid.begin() + centerRow);
211+
}
212+
213+
if (grid.empty()) {
214+
grid.emplace_back(std::max<size_t>(1, originalWidth), fillChar);
215+
}
216+
217+
if (hasCenterCol && centerCol < grid.front().size() && isColEmpty(centerCol)) {
218+
for (auto& row : grid) {
219+
if (row.empty()) {
220+
row.assign(std::max<size_t>(1, originalWidth), fillChar);
221+
}
222+
if (centerCol < row.size()) {
223+
row.erase(row.begin() + centerCol);
224+
}
225+
}
226+
}
227+
228+
if (grid.empty()) {
229+
grid.emplace_back(std::max<size_t>(1, originalWidth), fillChar);
230+
}
231+
232+
if (!grid.empty() && grid.front().empty()) {
233+
for (auto& row : grid) {
234+
row.assign(std::max<size_t>(1, originalWidth), fillChar);
235+
}
236+
}
237+
238+
height = grid.size();
239+
width = grid.front().size();
240+
241+
const size_t placementRow = std::min(centerRow, height - 1);
242+
const size_t placementCol = std::min(centerCol, width - 1);
243+
244+
for (auto& row : grid) {
245+
row.push_back(fillChar);
246+
}
247+
++width;
248+
249+
grid.push_back(std::string(width, fillChar));
250+
const size_t bottomRow = grid.size() - 1;
251+
const size_t rightmostCol = width - 1;
252+
253+
if (hasCenterRow) {
254+
grid[placementRow][rightmostCol] = '<';
255+
}
256+
257+
if (hasCenterCol) {
258+
grid[bottomRow][placementCol] = '^';
259+
}
260+
}
261+
161262
uint32_t TransposeEdgeFlags(const uint32_t flags) {
162263
const uint32_t south = (flags >> 24) & 0xFF;
163264
const uint32_t east = (flags >> 16) & 0xFF;
@@ -701,9 +802,11 @@ namespace RUL0 {
701802
// Rotate layouts
702803
if (!piece.cellLayout.empty()) {
703804
piece.cellLayout = RotateGrid(piece.cellLayout, times);
805+
NormalizeCenterMarkers(piece.cellLayout);
704806
}
705807
if (!piece.consLayout.empty()) {
706808
piece.consLayout = RotateGrid(piece.consLayout, times);
809+
NormalizeCenterMarkers(piece.consLayout);
707810
}
708811

709812
// Rotate preview effect position and rotation
@@ -747,10 +850,12 @@ namespace RUL0 {
747850

748851
if (!piece.cellLayout.empty()) {
749852
piece.cellLayout = TransposeGrid(piece.cellLayout);
853+
NormalizeCenterMarkers(piece.cellLayout);
750854
}
751855

752856
if (!piece.consLayout.empty()) {
753857
piece.consLayout = TransposeGrid(piece.consLayout);
858+
NormalizeCenterMarkers(piece.consLayout);
754859
}
755860

756861
// Update effect flip state

tests/tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,13 +701,13 @@ TEST_CASE("RUL0 parser applies CopyFrom/Rotate/Transpose/Translate to layouts an
701701
CHECK(base.requestedTransform.rotate == RUL0::Rotation::NONE);
702702

703703
const auto rotated = data.puzzlePieces.at(0x1100);
704-
expectGrid(rotated.NormalizedCellLayout(), {"^a", "<."});
704+
expectGrid(rotated.NormalizedCellLayout(), {"a<", "^."});
705705
expectGrid(rotated.NormalizedConsLayout(), {".x", "|."});
706706
CHECK(rotated.appliedTransform.rotate == RUL0::Rotation::ROT_90);
707707
CHECK(rotated.requestedTransform.rotate == RUL0::Rotation::ROT_90);
708708

709709
const auto transposed = data.puzzlePieces.at(0x1200);
710-
expectGrid(transposed.NormalizedCellLayout(), {"a^", ".<"});
710+
expectGrid(transposed.NormalizedCellLayout(), {"a<", "^."});
711711
expectGrid(transposed.NormalizedConsLayout(), {"x.", ".|"});
712712
CHECK(transposed.appliedTransform.transpose);
713713
CHECK(transposed.requestedTransform.transpose);

0 commit comments

Comments
 (0)