public CombinedMovementAndFiringDistanceCalculation( DistanceCalculation movementDistanceToFiringLine, FiringDistance firingDistance, Direction finalMovementDirectionTowardsTarget) { MovementDistanceToFiringLine = movementDistanceToFiringLine; FiringDistance = firingDistance; FinalMovementDirectionTowardsTarget = finalMovementDirectionTowardsTarget; // Calculate ticks until the target is shot: int ticksTillTargetShot = MovementDistanceToFiringLine.Distance + FiringDistance.TicksTillTargetShot; if (ticksTillTargetShot > Constants.UNREACHABLE_DISTANCE) { ticksTillTargetShot = Constants.UNREACHABLE_DISTANCE; } TicksTillTargetShot = ticksTillTargetShot; // Calculate ticks until the last shot is fired: int ticksTillLastShotFired = MovementDistanceToFiringLine.Distance + FiringDistance.TicksTillLastShotFired; if (ticksTillLastShotFired > Constants.UNREACHABLE_DISTANCE) { ticksTillLastShotFired = Constants.UNREACHABLE_DISTANCE; } TicksTillLastShotFired = ticksTillLastShotFired; }
public static Node[] GetIncomingNodesOnShortestPath( DirectionalMatrix <DistanceCalculation> distances, Direction dir, int fromX, int fromY, int toX, int toY, FiringLineMatrix firingLineMatrix = null, bool keepMovingCloserOnFiringLastBullet = false) { DistanceCalculation distanceCalc = distances[dir, fromX, fromY]; if (distanceCalc.Distance == Constants.UNREACHABLE_DISTANCE) { return(new Node[0]); } int length = distanceCalc.Distance; Node[] nodes = new Node[length]; int nodeIndex; Node node; nodeIndex = 0; node = distanceCalc.AdjacentNode; while (nodeIndex != length) { if (node.ActionType == ActionType.FiringLine) { Line <FiringDistance> firingLine = firingLineMatrix[toX, toY, node.Dir.GetOpposite(), node.EdgeOffset]; FiringDistance firingDistance = firingLine[node.FiringLineIndex]; FiringDistanceCalculator.AddFiringLineNodesToRoute(firingDistance, firingLine.DirectionOfLine.GetOpposite(), nodes, ref nodeIndex, keepMovingCloserOnFiringLastBullet); break; } // Add the node: nodes[nodeIndex] = node; nodeIndex++; if (node.ActionType == ActionType.Firing) { // Add a moving node - the only reason to fire is to move... node = new Node(ActionType.Moving, node.Dir, node.X + node.Dir.GetXOffset(), node.Y + node.Dir.GetYOffset()); nodes[nodeIndex] = node; nodeIndex++; } distanceCalc = distances[node.Dir, node.X, node.Y]; node = distanceCalc.AdjacentNode; } if (nodeIndex < length) { Array.Resize(ref nodes, nodeIndex); } return(nodes); }
public CombinedMovementAndFiringDistanceCalculation GetShortestAttackDistanceGivenTheSourcePointsMovementMatrix( DirectionalMatrix <DistanceCalculation> movementDistanceMatrix, Cell target) { int bestCombinedTicksUntilTargetShot = Constants.UNREACHABLE_DISTANCE; CombinedMovementAndFiringDistanceCalculation bestCombinedDistance = null; foreach (Direction attackDir in MovementDirections) { foreach (EdgeOffset edgeOffset in EdgeOffsets) { Direction outwardDir = attackDir.GetOpposite(); Line <FiringDistance> firingLine = FiringLineMatrix[target.Position, outwardDir, edgeOffset]; for (int i = 0; i < firingLine.Length; i++) { FiringDistance firingDist = firingLine[i]; // Ignore firing line points that start off with a normal movement, // as that path can be found by moving to the closer point in a non-firing line way: if (firingDist.CanMoveOrFire) { continue; } // Ignore invalid starting points on the firing line: if (!(GameStateCalculationCache.GameState.Walls.BoardBoundary.ContainsPoint(firingDist.StartingTankPosition) && TurnCalculationCache.TankLocationMatrix[firingDist.StartingTankPosition].IsValid)) { break; } DistanceCalculation movementDist = movementDistanceMatrix[attackDir, firingDist.StartingTankPosition]; int combinedTicks = movementDist.Distance + firingDist.TicksTillTargetShot; if (combinedTicks < bestCombinedTicksUntilTargetShot) { bestCombinedTicksUntilTargetShot = combinedTicks; bestCombinedDistance = new CombinedMovementAndFiringDistanceCalculation(movementDist, firingDist, attackDir); } } } } return(bestCombinedDistance); }
private void AddNextFiringLineNodesToQueueForMovementDirAndEdgeOffset( TwoValuedCircularBuffer <Node> bfsQueue, Direction movementDir, EdgeOffset edgeOffset, FiringLineSummary firingLineSummary, int distanceToAdd) { Line <FiringDistance> firingLine = firingLineSummary.FiringLine; int nextFiringLineIndex; for (nextFiringLineIndex = firingLineSummary.IndexOfNextFiringLinePoint; nextFiringLineIndex < firingLine.Length; nextFiringLineIndex++) { if (nextFiringLineIndex == -1) { return; } FiringDistance firingDist = firingLine[nextFiringLineIndex]; int nextEdgeWeighting = firingDist.TicksTillTargetShot - 1; // This distance is the edge weight in the graph. // The -1 is because we need to compensate for the weight 1 edge added from // the tank's position + direction on the firing line, to the firing line node. if (nextEdgeWeighting > distanceToAdd) { firingLineSummary.NextEdgeWeighting = nextEdgeWeighting; firingLineSummary.IndexOfNextFiringLinePoint = nextFiringLineIndex; return; } if (!TurnCalculationCache.CellMatrix[firingDist.StartingTankPosition].IsValid) { firingLineSummary.NextEdgeWeighting = Constants.UNREACHABLE_DISTANCE; firingLineSummary.IndexOfNextFiringLinePoint = -1; return; } Node firingLineNode = new Node(ActionType.FiringLine, movementDir, firingDist.StartingTankPosition, (byte)nextFiringLineIndex, edgeOffset); bfsQueue.Add(firingLineNode, nextEdgeWeighting); } if (nextFiringLineIndex == firingLine.Length) { firingLineSummary.NextEdgeWeighting = Constants.UNREACHABLE_DISTANCE; firingLineSummary.IndexOfNextFiringLinePoint = -1; } }