/// <summary></summary> /// <remarks> /// Takes a circle in the form of a center point and radius, and a function /// that can tell whether a given cell is opaque. Calls the setFoV action on /// every cell that is both within the radius and visible from the center. /// </remarks> /// <param name="observerCoords">Cordinates of observer;s hex.</param> /// <param name="radius">Maximum radius for Field-of-View.</param> /// <param name="observerHeight">Height (ASL) of the observer's eyes.</param> /// <param name="isOnBoard">Is this hex on the baoard.</param> /// <param name="targetHeight">Returns ground level (ASL) of supplied hex.</param> /// <param name="terrainHeight">Returns height (ASL) of terrain in supplied hex.</param> /// <param name="setFoV">Sets a hex as visible in the Field-of-View.</param> public static void ComputeFieldOfView( ICoordsCanon observerCoords, int radius, int observerHeight, Func<ICoordsCanon,bool> isOnBoard, Func<ICoordsCanon,int> targetHeight, Func<ICoordsCanon,int> terrainHeight, Action<ICoordsCanon> setFoV ) { #if TraceFOV TraceFlag.FieldOfView.Trace(true, " - Coords = " + observerCoords.User.ToString()); #endif var matrixOrigin = new IntMatrix2D(observerCoords.Vector); setFoV(observerCoords); // Always visible to self! #if TraceFoV for (int dodecant = 3; dodecant < 4; dodecant++) { TraceFlag.FieldOfView.Trace(true," - Dodecant: {0}", dodecant); #else Parallel.For (0, matrices.Count, dodecant => { #endif var matrix = matrices[dodecant] * matrixOrigin; ComputeFieldOfViewInDodecantZero( radius, observerHeight, TranslateDodecant(matrix, isOnBoard), TranslateDodecant(matrix, targetHeight), TranslateDodecant(matrix, terrainHeight), TranslateDodecant(matrix, setFoV)); } #if !TraceFoV ); #endif }
protected override int Range(ICoordsCanon coords) { var deltaX = coords.X - VectorCanon.X; var deltaY = coords.Y - VectorCanon.Y; return((Math.Abs(deltaX) + Math.Abs(deltaY) + Math.Abs(deltaX - deltaY)) / 2); }
protected override IEnumerable <NeighbourCoords> GetNeighbours(Hexside hexsides) { ICoordsCanon coords = this; foreach (Hexside hexside in Enum.GetValues(typeof(Hexside))) { if (hexside != Hexside.None && hexsides.HasFlag(hexside)) { yield return(new NeighbourCoords(hexside, coords.StepOut(hexside))); } } }
public override IMapGridHex this[ICoordsCanon coords] { get { return(this[coords.User]); } }
int ICoordsCanon.Range(ICoordsCanon coords) { return(Range(coords)); }
public NeighbourCoords(Hexside direction, ICoordsCanon coords) : this() { Direction = direction; Coords = coords; }
protected abstract int Range(ICoordsCanon coords);
static IntVector2D VectorHexTop(ICoordsCanon hex) { return(hex.Vector * matrixHexTop); }
static IntVector2D VectorHexBottom(ICoordsCanon hex) { return(hex.Vector * matrixHexBottom); }
public static IPath <ICoordsCanon> FindPath( ICoordsCanon start, ICoordsCanon goal, Func <ICoordsCanon, Hexside, int> stepCost, Func <ICoordsCanon, int> range, Func <ICoordsCanon, bool> isOnBoard ) { var vectorGoal = goal.Vector - start.Vector; var closed = new HashSet <ICoordsUser>(); var queue = goal.Range(start) > RangeCutoff ? (IPriorityQueue <uint, Path <ICoordsCanon> >) new HeapPriorityQueue <uint, Path <ICoordsCanon> >() : (IPriorityQueue <uint, Path <ICoordsCanon> >) new DictPriorityQueue <uint, Path <ICoordsCanon> >(); #if DEBUG TraceFlag.FindPath.Trace(true, "Find path from {0} to {1}; vectorGoal = {0}", start.User, goal.User, vectorGoal); #endif queue.Enqueue(0, new Path <ICoordsCanon>(start)); while (!queue.IsEmpty) { var oldPref = queue.Peek().Key & 0xFFFF; var path = queue.Dequeue(); if (closed.Contains(path.LastStep.User)) { continue; } #if DEBUG var previous = (path.PreviousSteps) == null ? HexCoords.EmptyCanon : path.PreviousSteps.LastStep; TraceFlag.FindPath.Trace("Dequeue Path at {0} from {3} w/ cost={1,4}:{2,3}.", path.LastStep, path.TotalCost, oldPref, previous); #endif if (path.LastStep != null && path.LastStep.Equals(goal)) { return(path); } closed.Add(path.LastStep.User); foreach (var neighbour in path.LastStep.GetNeighbours(~Hexside.None)) { if (isOnBoard(neighbour.Coords)) { var cost = stepCost(path.LastStep, neighbour.Direction); if (cost > 0) { var preference = (ushort)Math.Abs(vectorGoal ^ (goal.Vector - neighbour.Coords.Vector)); var newPath = path.AddStep(neighbour.Coords.User.Canon, (ushort)cost, neighbour.Direction); var estimate = ((uint)range(neighbour.Coords.User.Canon) + (uint)newPath.TotalCost) << 16; queue.Enqueue(estimate + preference, newPath); #if DEBUG TraceFlag.FindPath.Trace(" Enqueue {0}: {1,4}:{2,3}", neighbour.Coords, estimate >> 16, preference); #endif } } } } return(null); }
private static int GetRange(ICoordsCanon coords) { return(HexCoords.EmptyCanon.Range(coords)); }
public abstract int StepCost(ICoordsCanon coords, Hexside hexSide);
public abstract IMapGridHex this[ICoordsCanon coords] { get; }
IGridHex IBoard <IGridHex> .this[ICoordsCanon coords] { get { return(this[coords]); } }
public override int StepCost(ICoordsCanon coords, Hexside hexSide) { return(IsOnBoard(coords.User) && this[coords.StepOut(hexSide)].Value == '.' ? 1 : -1); }
public override int StepCost(ICoordsCanon coords, Hexside hexSide) { return(this[coords].StepCost); }