#pragma once #include #include #include #include "BuildingId.h" #include "BuildingType.h" #include "FactoryState.h" #include "GameConfig.h" #include "Rotation.h" // Where a building may be placed, and what is already sitting on those tiles. // Free functions over the factory state and the config — they read no other // system state, so they do not belong to BuildingSystem. // True if every body cell lies inside the world: 0 <= y < world.height_tiles and // x >= the current asteroid left edge (REQ-BLD-PLACE-VALID). Terrain type is not // checked — see isPlacementValid for the full rule. bool bodyCellsWithinWorldBounds(const FactoryState& state, const GameConfig& config, const std::vector& bodyCells, QPoint anchor); // True if the placement satisfies REQ-BLD-PLACE-VALID terrain and world-bounds // rules: every ship-dock (S) cell sits in space (x >= 0), every other body (A) // cell sits on the asteroid (x < 0 and x >= the left edge), and every cell has // 0 <= y < world.height_tiles. There is no right-side bound — space extends // rightward. Tile occupancy is NOT checked here. bool isPlacementValid(const FactoryState& state, const GameConfig& config, BuildingType type, QPoint anchor, Rotation rotation); // The building or site that a ghost of the given type/anchor/rotation would // rotate in place rather than replace: same type, same body cells, one owner // (REQ-BLD-ROTATE-IN-PLACE). Tunnels never qualify. std::optional findRotateInPlaceTarget(const FactoryState& state, const GameConfig& config, BuildingType type, QPoint anchor, Rotation rot);