#region Copyright & License Information /* * Copyright (c) The OpenRA Developers and Contributors * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System; using System.Collections.Generic; namespace OpenRA.Mods.Common.Pathfinder { /// /// Represents a pathfinding graph with nodes and edges. /// Nodes are represented as cells, and pathfinding information /// in the form of is attached to each one. /// public interface IPathGraph : IDisposable { /// /// Given a source node, returns connections to all reachable destination nodes with their cost. /// /// PERF: Returns a rather than an as enumerating /// this efficiently is important for pathfinding performance. Callers should interact with this as an /// and not mutate the result. List GetConnections(CPos source, Func targetPredicate); /// /// Gets or sets the pathfinding information for a given node. /// CellInfo this[CPos node] { get; set; } } public static class PathGraph { public const int PathCostForInvalidPath = int.MaxValue; public const short MovementCostForUnreachableCell = short.MaxValue; } /// /// Represents a full edge in a graph, giving the cost to traverse between two nodes. /// public readonly struct GraphEdge { public readonly CPos Source; public readonly CPos Destination; public readonly int Cost; public GraphEdge(CPos source, CPos destination, int cost) { if (source == destination) throw new ArgumentException($"{nameof(source)} and {nameof(destination)} must refer to different cells"); if (cost < 0) throw new ArgumentOutOfRangeException(nameof(cost), $"{nameof(cost)} cannot be negative"); if (cost == PathGraph.PathCostForInvalidPath) throw new ArgumentOutOfRangeException(nameof(cost), $"{nameof(cost)} cannot be used for an unreachable path"); Source = source; Destination = destination; Cost = cost; } public GraphConnection ToConnection() { return new GraphConnection(Destination, Cost); } public override string ToString() => $"{Source} -> {Destination} = {Cost}"; } /// /// Represents part of an edge in a graph, giving the cost to traverse to a node. /// public readonly struct GraphConnection { public readonly struct CostComparer : IComparer { public int Compare(GraphConnection x, GraphConnection y) { return x.Cost.CompareTo(y.Cost); } } public readonly CPos Destination; public readonly int Cost; public GraphConnection(CPos destination, int cost) { if (cost < 0) throw new ArgumentOutOfRangeException(nameof(cost), $"{nameof(cost)} cannot be negative"); if (cost == PathGraph.PathCostForInvalidPath) throw new ArgumentOutOfRangeException(nameof(cost), $"{nameof(cost)} cannot be used for an unreachable path"); Destination = destination; Cost = cost; } public GraphEdge ToEdge(CPos source) { return new GraphEdge(source, Destination, Cost); } public override string ToString() => $"-> {Destination} = {Cost}"; } }