Files
dota_factory/src/lib/core/TunnelCompletion.h

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);