Files
dota_factory/src/test/SurfaceMaskTest.cpp
2026-04-19 20:53:08 +02:00

185 lines
6.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "catch.hpp"
#include <algorithm>
#include <vector>
#include <QPoint>
#include "Port.h"
#include "Rotation.h"
#include "SurfaceMask.h"
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
static bool hasBodyCell(const ParsedSurfaceMask& mask, int x, int y)
{
const QPoint pt(x, y);
return std::find(mask.bodyCells.begin(), mask.bodyCells.end(), pt)
!= mask.bodyCells.end();
}
static bool hasOutputPort(const ParsedSurfaceMask& mask, int x, int y, Rotation dir)
{
for (const Port& port : mask.outputPorts)
{
if (port.tile == QPoint(x, y) && port.direction == dir)
{
return true;
}
}
return false;
}
static bool hasShipDockCell(const ParsedSurfaceMask& mask, int x, int y)
{
const QPoint pt(x, y);
return std::find(mask.shipDockCells.begin(), mask.shipDockCells.end(), pt)
!= mask.shipDockCells.end();
}
// ---------------------------------------------------------------------------
// Belt ["A>"] — 1×1 body, East output
// ---------------------------------------------------------------------------
TEST_CASE("SurfaceMask: belt East — 1 body cell, port at (1,0) East", "[surface_mask]")
{
const ParsedSurfaceMask mask = parseSurfaceMask({"A>"}, Rotation::East);
REQUIRE(mask.footprint.width() == 1);
REQUIRE(mask.footprint.height() == 1);
REQUIRE(mask.bodyCells.size() == 1);
REQUIRE(hasBodyCell(mask, 0, 0));
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(hasOutputPort(mask, 1, 0, Rotation::East));
}
TEST_CASE("SurfaceMask: belt South — body at (0,0), port at (0,1) South", "[surface_mask]")
{
const ParsedSurfaceMask mask = parseSurfaceMask({"A>"}, Rotation::South);
REQUIRE(mask.bodyCells.size() == 1);
REQUIRE(hasBodyCell(mask, 0, 0));
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(hasOutputPort(mask, 0, 1, Rotation::South));
}
TEST_CASE("SurfaceMask: belt West — body at (0,0), port at (-1,0) West", "[surface_mask]")
{
const ParsedSurfaceMask mask = parseSurfaceMask({"A>"}, Rotation::West);
REQUIRE(mask.bodyCells.size() == 1);
REQUIRE(hasBodyCell(mask, 0, 0));
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(hasOutputPort(mask, -1, 0, Rotation::West));
}
TEST_CASE("SurfaceMask: belt North — body at (0,0), port at (0,-1) North", "[surface_mask]")
{
const ParsedSurfaceMask mask = parseSurfaceMask({"A>"}, Rotation::North);
REQUIRE(mask.bodyCells.size() == 1);
REQUIRE(hasBodyCell(mask, 0, 0));
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(hasOutputPort(mask, 0, -1, Rotation::North));
}
// ---------------------------------------------------------------------------
// Miner ["AA", "A>"] — 3 body cells, East output
// ---------------------------------------------------------------------------
TEST_CASE("SurfaceMask: miner East — 3 body cells, port at (1,1) East, footprint 2×2",
"[surface_mask]")
{
const ParsedSurfaceMask mask = parseSurfaceMask({"AA", "A>"}, Rotation::East);
REQUIRE(mask.footprint.width() == 2);
REQUIRE(mask.footprint.height() == 2);
REQUIRE(mask.bodyCells.size() == 3);
REQUIRE(hasBodyCell(mask, 0, 0));
REQUIRE(hasBodyCell(mask, 1, 0));
REQUIRE(hasBodyCell(mask, 0, 1));
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(hasOutputPort(mask, 1, 1, Rotation::East));
}
TEST_CASE("SurfaceMask: miner South — port faces South", "[surface_mask]")
{
const ParsedSurfaceMask mask = parseSurfaceMask({"AA", "A>"}, Rotation::South);
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(mask.outputPorts[0].direction == Rotation::South);
}
TEST_CASE("SurfaceMask: miner West — port faces West", "[surface_mask]")
{
const ParsedSurfaceMask mask = parseSurfaceMask({"AA", "A>"}, Rotation::West);
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(mask.outputPorts[0].direction == Rotation::West);
}
TEST_CASE("SurfaceMask: miner North — port faces North", "[surface_mask]")
{
const ParsedSurfaceMask mask = parseSurfaceMask({"AA", "A>"}, Rotation::North);
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(mask.outputPorts[0].direction == Rotation::North);
}
// ---------------------------------------------------------------------------
// Splitter ["<A>"] — 1 body cell, West + East outputs
// ---------------------------------------------------------------------------
TEST_CASE("SurfaceMask: splitter East — 1 body cell, ports at (-1,0) West and (1,0) East",
"[surface_mask]")
{
const ParsedSurfaceMask mask = parseSurfaceMask({"<A>"}, Rotation::East);
REQUIRE(mask.footprint.width() == 1);
REQUIRE(mask.footprint.height() == 1);
REQUIRE(mask.bodyCells.size() == 1);
REQUIRE(hasBodyCell(mask, 0, 0));
REQUIRE(mask.outputPorts.size() == 2);
REQUIRE(hasOutputPort(mask, -1, 0, Rotation::West));
REQUIRE(hasOutputPort(mask, 1, 0, Rotation::East));
}
// ---------------------------------------------------------------------------
// Shipyard ["AAAS>", "AAAS "] — 6 A + 2 S body cells, 1 port
// ---------------------------------------------------------------------------
TEST_CASE("SurfaceMask: shipyard East — 6 A bodyCells, 2 S shipDockCells, port at (4,0) East",
"[surface_mask]")
{
const std::vector<std::string> rows = {"AAAS>", "AAAS "};
const ParsedSurfaceMask mask = parseSurfaceMask(rows, Rotation::East);
REQUIRE(mask.footprint.width() == 4);
REQUIRE(mask.footprint.height() == 2);
REQUIRE(mask.bodyCells.size() == 8); // 6 A + 2 S
REQUIRE(mask.shipDockCells.size() == 2);
REQUIRE(hasShipDockCell(mask, 3, 0));
REQUIRE(hasShipDockCell(mask, 3, 1));
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(hasOutputPort(mask, 4, 0, Rotation::East));
}
// ---------------------------------------------------------------------------
// Assembler ["AAA ", "AAA>", "AAA "] — 9 body cells, East output
// ---------------------------------------------------------------------------
TEST_CASE("SurfaceMask: assembler East — 9 body cells, port at (3,1) East, footprint 3×3",
"[surface_mask]")
{
const std::vector<std::string> rows = {"AAA ", "AAA>", "AAA "};
const ParsedSurfaceMask mask = parseSurfaceMask(rows, Rotation::East);
REQUIRE(mask.footprint.width() == 3);
REQUIRE(mask.footprint.height() == 3);
REQUIRE(mask.bodyCells.size() == 9);
REQUIRE(mask.outputPorts.size() == 1);
REQUIRE(hasOutputPort(mask, 3, 1, Rotation::East));
}