#pragma once #include #include #include #include #include #include "BuildingType.h" #include "Rotation.h" // QPoint has no operator<, so an explicit ordering is needed to key a map or set // by tile. struct QPointCompare { bool operator()(const QPoint& a, const QPoint& b) const { if (a.x() != b.x()) { return a.x() < b.x(); } return a.y() < b.y(); } }; // A tunnel building occupying a single tile: whether it is an entry or an exit and // the direction it faces. Used by the tunnel pairing scan (REQ-BLD-TUNNEL-PAIR) and // the unified tunnel build mode (REQ-BLD-TUNNEL-MODE). struct TunnelTileInfo { BuildingType type; // TunnelEntry or TunnelExit Rotation rotation; // facing direction }; // Given a tile, returns the tunnel building on it (entry or exit) with its facing // direction, or std::nullopt when the tile holds no tunnel building. using TunnelLookup = std::function(QPoint)>; // Tunnel entries/exits indexed by their single-cell tile (REQ-BLD-TUNNEL-MODE). using TunnelTileMap = std::map; // Wraps a tunnel tile index in the lookup functor the helpers below take. The // returned functor references `tunnels`, which must outlive it. TunnelLookup makeTunnelLookup(const TunnelTileMap& tunnels); // Steps from `start` in `stepDir` over the tiles at distance 1..maxDistance and // returns the first tile whose tunnel faces `targetFacing`. Tunnel buildings facing // any other direction are skipped, mirroring the "stop at the first same-direction // tunnel" rule of REQ-BLD-TUNNEL-PAIR. Returns std::nullopt if none is found in range. std::optional firstTunnelFacing(const TunnelLookup& lookup, QPoint start, Rotation stepDir, Rotation targetFacing, int maxDistance); // Result of resolving which tunnel end the ghost should become at a hovered tile // (REQ-BLD-TUNNEL-MODE): the type to place and the existing tunnel it would complete. struct TunnelCompletion { BuildingType resolvedType; // TunnelEntry (default) or TunnelExit std::optional partnerTile; // matched existing tunnel, if any }; // Resolves the tunnel ghost type for a hover at `hoverTile` with the ghost facing // `rotation` (REQ-BLD-TUNNEL-MODE): // - exit-completion: placing an exit here would pair with an existing entry behind // it (the entry's forward search reaches this tile as its first same-direction // tunnel) — the ghost becomes a TunnelExit; // - entry-completion: placing an entry here would pair with an existing exit ahead // of it — the ghost stays a TunnelEntry. // When both apply, the end whose existing partner is closer to `cursorWorldPos` (the // sub-tile cursor position in world tile units) wins, so nudging the cursor within a // single tile can flip the target. With no match the ghost stays a TunnelEntry with // no partner. TunnelCompletion resolveTunnelCompletion(const TunnelLookup& lookup, QPoint hoverTile, Rotation rotation, int maxDistance, QVector2D cursorWorldPos); // Finds the matching end of an existing tunnel building at `tile` of the given `type` // (TunnelEntry or TunnelExit) facing `rotation`, applying the pairing scan of // REQ-BLD-TUNNEL-PAIR over `lookup`: // - for an entry, the first same-direction tunnel along its facing direction, if it // is an exit; // - for an exit, the first same-direction tunnel opposite its facing direction, if it // is an entry. // Returns the partner tile, or std::nullopt when the tunnel is unpaired. std::optional findTunnelPartner(const TunnelLookup& lookup, QPoint tile, BuildingType type, Rotation rotation, int maxDistance);