implement building system

This commit is contained in:
2026-04-19 20:50:42 +02:00
parent c70b5c8f08
commit bf29cc40e3
19 changed files with 1818 additions and 7 deletions

View File

@@ -0,0 +1,172 @@
#include "SurfaceMask.h"
#include <algorithm>
#include <climits>
namespace
{
// Rotate direction character 90° clockwise.
char rotateDirCharCW(char c)
{
switch (c)
{
case '>': return 'v';
case 'v': return '<';
case '<': return '^';
case '^': return '>';
default: return c;
}
}
// Rotate the character grid 90° clockwise.
// Input grid[row][col]. Returns a new grid with swapped dimensions.
std::vector<std::string> rotateCW(const std::vector<std::string>& grid)
{
if (grid.empty())
{
return {};
}
const int srcH = static_cast<int>(grid.size());
// Pad all rows to the same width.
int srcW = 0;
for (const std::string& row : grid)
{
const int w = static_cast<int>(row.size());
if (w > srcW)
{
srcW = w;
}
}
// After 90° CW: new width = srcH, new height = srcW.
const int dstW = srcH;
const int dstH = srcW;
std::vector<std::string> dst(dstH, std::string(dstW, ' '));
for (int row = 0; row < srcH; ++row)
{
for (int col = 0; col < srcW; ++col)
{
const char ch = (col < static_cast<int>(grid[row].size()))
? grid[row][col]
: ' ';
// 90° CW mapping: (col, row) -> (dstCol = srcH-1-row, dstRow = col)
const int dstCol = srcH - 1 - row;
const int dstRow = col;
dst[dstRow][dstCol] = rotateDirCharCW(ch);
}
}
return dst;
}
} // namespace
ParsedSurfaceMask parseSurfaceMask(const std::vector<std::string>& rows,
Rotation rotation)
{
// Number of 90° CW steps to apply.
int cwSteps = 0;
switch (rotation)
{
case Rotation::East: cwSteps = 0; break;
case Rotation::South: cwSteps = 1; break;
case Rotation::West: cwSteps = 2; break;
case Rotation::North: cwSteps = 3; break;
}
// Apply rotations.
std::vector<std::string> grid = rows;
for (int i = 0; i < cwSteps; ++i)
{
grid = rotateCW(grid);
}
// Scan grid: collect body cells, ship dock cells, and output port indicators.
std::vector<QPoint> rawBodyCells;
std::vector<QPoint> rawShipDockCells;
struct RawPort
{
QPoint tile;
Rotation direction;
};
std::vector<RawPort> rawPorts;
for (int row = 0; row < static_cast<int>(grid.size()); ++row)
{
for (int col = 0; col < static_cast<int>(grid[row].size()); ++col)
{
const char ch = grid[row][col];
if (ch == 'A')
{
rawBodyCells.push_back(QPoint(col, row));
}
else if (ch == 'S')
{
rawBodyCells.push_back(QPoint(col, row));
rawShipDockCells.push_back(QPoint(col, row));
}
else if (ch == '>')
{
rawPorts.push_back({QPoint(col, row), Rotation::East});
}
else if (ch == '<')
{
rawPorts.push_back({QPoint(col, row), Rotation::West});
}
else if (ch == '^')
{
rawPorts.push_back({QPoint(col, row), Rotation::North});
}
else if (ch == 'v')
{
rawPorts.push_back({QPoint(col, row), Rotation::South});
}
}
}
// Compute bounding box of body cells and normalize to (0,0).
int minCol = INT_MAX;
int minRow = INT_MAX;
int maxCol = INT_MIN;
int maxRow = INT_MIN;
for (const QPoint& pt : rawBodyCells)
{
if (pt.x() < minCol) { minCol = pt.x(); }
if (pt.x() > maxCol) { maxCol = pt.x(); }
if (pt.y() < minRow) { minRow = pt.y(); }
if (pt.y() > maxRow) { maxRow = pt.y(); }
}
// If there are no body cells, return an empty mask.
if (rawBodyCells.empty())
{
return ParsedSurfaceMask{};
}
const QPoint offset(-minCol, -minRow);
ParsedSurfaceMask result;
result.footprint = QSize(maxCol - minCol + 1, maxRow - minRow + 1);
for (const QPoint& pt : rawBodyCells)
{
result.bodyCells.push_back(pt + offset);
}
for (const QPoint& pt : rawShipDockCells)
{
result.shipDockCells.push_back(pt + offset);
}
for (const RawPort& rp : rawPorts)
{
Port port;
port.tile = rp.tile + offset;
port.direction = rp.direction;
result.outputPorts.push_back(port);
}
return result;
}