#pragma once #include #include #include #include #include "BuildingType.h" #include "Rotation.h" // 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)>; // 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);