67 lines
3.3 KiB
C++
67 lines
3.3 KiB
C++
#pragma once
|
|
|
|
#include <functional>
|
|
#include <optional>
|
|
|
|
#include <QPoint>
|
|
#include <QVector2D>
|
|
|
|
#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<std::optional<TunnelTileInfo>(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<QPoint> 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<QPoint> 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<QPoint> findTunnelPartner(const TunnelLookup& lookup, QPoint tile,
|
|
BuildingType type, Rotation rotation,
|
|
int maxDistance);
|