public void Test_IsEmpty_FilledQ() { PriorityQueue <double> q = null; q = new MinPriorityQueue <double>(); q.Enqueue(1); q.Enqueue(2); Assert.IsFalse(q.IsEmpty); }
public void Test_Count() { PriorityQueue <double> q = null; q = new MinPriorityQueue <double>(); q.Enqueue(1); q.Enqueue(2); Assert.AreEqual(2, q.Count); }
public void Test_Contains_Not() { PriorityQueue <double> q = null; q = new MinPriorityQueue <double>(); q.Enqueue(3); q.Enqueue(2); q.Enqueue(1); Assert.IsFalse(q.Contains(4)); }
public void Test_Enqueue() { PriorityQueue <double> q = null; q = new MinPriorityQueue <double>(); q.Enqueue(3); q.Enqueue(2); q.Enqueue(1); Assert.AreEqual(1, q.Peek()); }
public void Test_Capacity_AutoResize() { PriorityQueue <double> q = null; q = new MinPriorityQueue <double>(3); q.Enqueue(1); q.Enqueue(2); q.Enqueue(3); q.Enqueue(4); Assert.AreEqual(6, q.Capacity); }
public IEnumerable <Node> GetPath(Node start, Node goal) { var cost = new Dictionary <Node, int>(); var parents = new Dictionary <Node, Node>(); var visited = new HashSet <Node>(); var queue = new MinPriorityQueue <Node>(); cost[start] = 0; parents[start] = null; queue.Enqueue(start); bool foundPath = false; while (queue.Count > 0) { var current = queue.Dequeue(); visited.Add(current); if (current.Equals(goal)) { foundPath = true; break; } var neighbours = this.GetNeighbours(current); foreach (var neighbour in neighbours) { if (visited.Contains(neighbour) || this.IsWall(neighbour)) { continue; } var newCost = cost[current] + 1; if (!cost.ContainsKey(neighbour) || newCost < cost[neighbour]) { cost[neighbour] = newCost; neighbour.F = newCost + this.GetH(neighbour, goal); queue.Enqueue(neighbour); parents[neighbour] = current; } } } if (!foundPath) { throw new InvalidOperationException("No path found."); } return(this.GetPath(parents, goal)); }
public void Test_PriorityUpgrade() { PriorityQueue <double> q = null; q = new MinPriorityQueue <double>(); q.Enqueue(30); q.Enqueue(20); q.Enqueue(10); q.Remove(20); q.Enqueue(5); Assert.AreEqual(5, q.Peek()); }
public void PriorityQueue_Test() { var queue = new MinPriorityQueue <int>(); queue.Enqueue(10); queue.Enqueue(9); queue.Enqueue(1); queue.Enqueue(21); Assert.AreEqual(queue.Dequeue(), 1); Assert.AreEqual(queue.Dequeue(), 9); Assert.AreEqual(queue.Dequeue(), 10); Assert.AreEqual(queue.Dequeue(), 21); }
/************************************************************************************************************/ /// <summary> /// The Dijkstra's algorithm. /// </summary> private void _dijkstra(TGraph graph, TVertex source) { var minPQ = new MinPriorityQueue <TVertex, decimal>((uint)_verticesCount); var srcIndex = _nodesToIndices[source]; _srcIndex = srcIndex; _distances[srcIndex] = 0; minPQ.Enqueue(source, _distances[srcIndex]); // Main loop while (!minPQ.IsEmpty) { var current = minPQ.DequeueMin(); // get vertex with min weight var currentIndex = _nodesToIndices[current]; // get its index var edges = graph.OutgoingEdges(current) as IEnumerable <WeightedEdge <TVertex> >; // get its outgoing weighted edges foreach (var edge in edges) { var adjacentIndex = _nodesToIndices[edge.Destination]; // calculate a new possible weighted path if the edge weight is less than infinity var delta = Infinity; if (edge.Weight < Infinity && _distances[currentIndex] + edge.Weight < Infinity) // Handles overflow { delta = _distances[currentIndex] + edge.Weight; } // Relax the edge // if check is true, a shorter path is found from current to adjacent if (delta < _distances[adjacentIndex]) { _edgeTo[adjacentIndex] = edge; _distances[adjacentIndex] = delta; _predecessors[adjacentIndex] = currentIndex; // decrease priority with a new distance if it exists; otherwise enqueque it if (minPQ.Contains(edge.Destination)) { minPQ.UpdatePriority(edge.Destination, delta); } else { minPQ.Enqueue(edge.Destination, delta); } } } //end-foreach } //end-while }
public void Peek_Should_Return_The_Min_Value_Without_Removing() { var pq = new MinPriorityQueue <int>(); pq.Enqueue(5); pq.Enqueue(3); pq.Enqueue(8); pq.Enqueue(1); var result = pq.Peek(); result.Should().Be(1); pq.Count.Should().Be(4); }
public void TryDequeue_Should_Return_True_And_Outs_The_Min_Value_When_Queue_Is_Not_Empty() { var pq = new MinPriorityQueue <int>(); pq.Enqueue(5); pq.Enqueue(3); pq.Enqueue(8); pq.Enqueue(1); var result = pq.TryDequeue(out var value); result.Should().BeTrue(); value.Should().Be(1); pq.Count.Should().Be(3); }
/// <summary> /// Nearest neighbor search method to find the single nearest neighbor at a given point. /// Translated from https://github.com/gvd/kdtree/blob/master/kdtree.h /// </summary> /// <param name="query">The nearest neighbor search query point.</param> /// <returns>The closest node to the parameter query is returned.</returns> //public KDNode NNSearch(Point query) //{ // MinPriorityQueue<Tuple<double, KDNode>> pq = new MinPriorityQueue<Tuple<double, KDNode>>(); // //Tuple<double, KDNode> best = new Tuple<double, KDNode>(1.79769e+308, root); // pq.Enqueue(new Tuple<double, KDNode>(0.0, root)); // do // { // var current = pq.Dequeue(); // //if (current.Item1 >= best.Item1) // //{ // // if (EuclideanDistance(query, current.Item2.Data) > EuclideanDistance(query, best.Item2.Data)) // // return best.Item2; // // else // // return current.Item2; // //} // List<KDNode> a = new List<KDNode> // { // }; // var currentNode = current.Item2; // //double d = EuclideanDistance(query, currentNode.Data); // //double dx = Subtract(query, currentNode.Data, currentNode.Depth); // if () // { // best = new Tuple<double, KDNode>(d, currentNode); // } // KDNode near, far; // near = currentNode.Left; // else // near = currentNode.Right; // far = currentNode.Right; // else // far = currentNode.Left; // if (near != null) // pq.Enqueue(new Tuple<double, KDNode>(0, near)); // if (far != null) // pq.Enqueue(new Tuple<double, KDNode>(0, far)); // } while (pq.Count() != 0); // return best.Item2; //} public List <KDNode> LocSearch(Point query) { MinPriorityQueue <Tuple <double, KDNode> > pq = new MinPriorityQueue <Tuple <double, KDNode> >(); Point p = new Point(0, 0); List <KDNode> a = new List <KDNode> { }; pq.Enqueue(new Tuple <double, KDNode>(0.0, root)); do { var current = pq.Dequeue(); // current.Item2.Data; var currentNode = current.Item2; if (query.x < currentNode.Data.x && currentNode.Data.x < query.x && query.y < currentNode.Data.y) { a.Add(currentNode); } double d = EuclideanDistance(query, currentNode.Data); double dx = Subtract(query, currentNode.Data, currentNode.Depth); KDNode near; if (dx <= 0) { near = currentNode.Left; } else { near = currentNode.Right; } //if (dx <= 0) // far = currentNode.Right; //else // far = currentNode.Left; if (near != null) { pq.Enqueue(new Tuple <double, KDNode>(0, near)); } } while (pq.Count() != 0); return(a); }
public void MinPriorityQueueDoesNotInsertItemToHeadIfItemIsHigherPriorityThanHead() { var priorityQueue = new MinPriorityQueue <string, int>(50); List <Tuple <string, int> > items = new List <Tuple <string, int> > { new Tuple <string, int>("A_50", 50), new Tuple <string, int>("A_41", 41), new Tuple <string, int>("A_38", 38), new Tuple <string, int>("A_37", 37), new Tuple <string, int>("A_23", 23), new Tuple <string, int>("A_11", 11), new Tuple <string, int>("A_5", 5), new Tuple <string, int>("A_3", 3), }.Randomize() .ToList(); priorityQueue.EnqueueRange(items); string originalHead = priorityQueue.Peek(); priorityQueue.Enqueue("A_4", 4); string newHead = priorityQueue.Peek(); Assert.AreEqual("A_3", originalHead); Assert.AreEqual("A_3", newHead); }
public void MinPriorityQueue_FullTest_Successful() { var source = new List <int>(); var sourceCount = Faker.RandomNumber.Next(20, 100); for (int i = 0; i < sourceCount; i++) { source.Add(Faker.RandomNumber.Next()); } var additionalDataCount = Faker.RandomNumber.Next(10, 50); // Act 1. Build priority queue with some initial data. var queue = new MinPriorityQueue <int>(source); // Act 2. Add some additional data using Enqueue for (int i = 0; i < additionalDataCount; i++) { queue.Enqueue(Faker.RandomNumber.Next()); } // Act 3 & Assert - Check results from the queue var prev = -1; // Set a negative number as previous; all data in the queue is assumed to be positive. while (!queue.IsEmpty()) { var curr = queue.Dequeue(); Assert.IsTrue(curr >= prev); prev = curr; } }
public void Test_Remove() { PriorityQueue <double> q = null; double[] items = { 5, 85, 43, 2, 28, 99, 67, 1.98, 33, 19, 17, 44 }; SortedList <double, double> monitor = new SortedList <double, double>(); q = new MinPriorityQueue <double>(7); for (int i = 0; i < items.Length; i++) { q.Enqueue(items[i]); monitor.Add(items[i], items[i]); } q.Remove(43); monitor.Remove(43); q.Remove(17); monitor.Remove(17); foreach (double monitorItem in monitor.Values) { Assert.AreEqual(monitorItem, q.Dequeue()); } }
public void Test_Integration_2() { PriorityQueue <double> q = null; double[] items = { 82, 100, 9.3, 1.19, 10, 29, 12, 9.0006, 22, 20.9, 207, 13.56, 30, 2, 66 }; SortedList <double, double> monitor = new SortedList <double, double>(); q = new MinPriorityQueue <double>(); for (int i = 0; i < items.Length; i++) { q.Enqueue(items[i]); monitor.Add(items[i], items[i]); if (i == 3) { q.Dequeue(); monitor.Remove(1.19); } else if (i == 8) { q.Dequeue(); monitor.Remove(9.0006); } } foreach (double monitorItem in monitor.Values) { Assert.AreEqual(monitorItem, q.Dequeue()); } }
/// <summary> /// The Dijkstra's algorithm. /// </summary> private void _dijkstra() { while (!_minPriorityQueue.IsEmpty) { var currentVertex = _minPriorityQueue.DequeueMin(); var currentVertexIndex = _nodesToIndices[currentVertex]; var outgoingEdges = _graph.OutgoingEdges(currentVertex); foreach (var outgoingEdge in outgoingEdges) { var adjacentIndex = _nodesToIndices[outgoingEdge.Destination]; var delta = _distances[currentVertexIndex] != Infinity ? _distances[currentVertexIndex] + outgoingEdge.Weight : Infinity; if (delta < _distances[adjacentIndex]) { _distances[adjacentIndex] = delta; _predecessors[adjacentIndex] = currentVertexIndex; if (_minPriorityQueue.Contains(outgoingEdge.Destination)) { _minPriorityQueue.UpdatePriority(outgoingEdge.Destination, delta); } else { _minPriorityQueue.Enqueue(outgoingEdge.Destination, delta); } } } } }
private void _initialize() { var verticesCount = _graph.VerticesCount; _distances = new long[verticesCount]; _predecessors = new int[verticesCount]; _nodesToIndices = new Dictionary <TVertex, int>(); _indicesToNodes = new Dictionary <int, TVertex>(); _minPriorityQueue = new MinPriorityQueue <TVertex, long>((uint)verticesCount); var vertices = _graph.Vertices.ToList(); for (int i = 0; i < verticesCount; i++) { if (_source.Equals(vertices[i])) { _distances[i] = 0; _predecessors[i] = 0; } else { _distances[i] = Infinity; _predecessors[i] = NilPredecessor; } _minPriorityQueue.Enqueue(vertices[i], _distances[i]); _nodesToIndices.Add(vertices[i], i); _indicesToNodes.Add(i, vertices[i]); } }
public void Dequeue_Should_Always_Return_The_Min_Value() { var pq = new MinPriorityQueue <int>(); pq.Enqueue(6); pq.Enqueue(9); pq.Enqueue(8); pq.Enqueue(3); pq.Enqueue(5); pq.Enqueue(1); pq.Enqueue(3); pq.Count.Should().Be(7); pq.Dequeue().Should().Be(1); pq.Count.Should().Be(6); pq.Dequeue().Should().Be(3); pq.Count.Should().Be(5); pq.Dequeue().Should().Be(3); pq.Count.Should().Be(4); pq.Dequeue().Should().Be(5); pq.Count.Should().Be(3); pq.Dequeue().Should().Be(6); pq.Count.Should().Be(2); pq.Dequeue().Should().Be(8); pq.Count.Should().Be(1); pq.Dequeue().Should().Be(9); pq.Count.Should().Be(0); }
public void Enqueue_Should_Add_Item_To_An_Empty_Queue() { var pq = new MinPriorityQueue <int>(); pq.Enqueue(10); pq.IsEmpty.Should().BeFalse(); pq.Count.Should().Be(1); }
private static MinPriorityQueue <int> CreateQueue(int[] priorities) { var queue = new MinPriorityQueue <int>(priorities.Length, int.MaxValue); for (var i = 0; i < priorities.Length; i++) { queue.Enqueue(i, priorities[i]); } return(queue); }
public static IEnumerable <Edge <T> > DijkstraShortestPath <T>(this IGraph <T> graph, T startVertex, T finishVertex) where T : IEquatable <T> { var currentVertex = startVertex; var weigths = new MinPriorityQueue <Weight <T> >(); var paths = new Dictionary <T, Path <T> > { { startVertex, new Path <T> { Weight = 0.0, Edges = new List <Edge <T> >() } } }; while (paths.Count < graph.VertexCount) { foreach (var edge in graph.EdgesOf(currentVertex)) { if (edge.Weight < 0) { throw new ArgumentOutOfRangeException( "Edge.Weight", edge.Weight, "Dijkstra's algorithm for shortest paths does not support negative weights."); } if (!paths.ContainsKey(edge.Target)) { weigths.Enqueue(new Weight <T> { Edge = edge, PathWeight = paths[edge.Source].Weight + edge.Weight }); } } Weight <T> smallest; do { // skip obsolete edges smallest = weigths.DequeueMin(); } while (paths.ContainsKey(smallest.Edge.Target)); var pathToSource = paths[smallest.Edge.Source]; var path = new List <Edge <T> >(pathToSource.Edges); path.Add(smallest.Edge); if (smallest.Edge.Target.Equals(finishVertex)) { return(path); } currentVertex = smallest.Edge.Target; paths.Add(smallest.Edge.Target, new Path <T> { Weight = smallest.PathWeight, Edges = path }); } return(new Edge <T> [0]); }
public void MinQueueAddItemWithSize() { var queue = new MinPriorityQueue <string, int>(Number); for (int i = 0; i < _array.Length; i++) { queue.Enqueue(_array[i].Item1, _array[i].Item2); } Assert.AreEqual(Number, queue.Count); }
//Placeholder, full game would have units stored elsewhere public void UnitInit() { PlayerUnit adam = new PlayerUnit( 84, "Adam", "The Bearded Buddy", 422, 2, 69, 7, 0, 4, 98, 20, 0, 87, 0); playerUnits.Add(adam); turnQueue.Enqueue(adam, defaultTurnSpeed); PlayerUnit dylan = new PlayerUnit( 2, "Dylan", "Probably an Alien", 999, 2, 80, 70, 10, 0, 1, 47, 10, 77, 0); playerUnits.Add(adam); turnQueue.Enqueue(adam, defaultTurnSpeed); }
public void Dequeue_ShouldRemoveTheSmallestItem() { var items = new List <char> { 'T', 'Z', 'B' }; var target = new MinPriorityQueue <char>(); items.ForEach(anItem => target.Enqueue(anItem)); items.Sort(); Assert.That(target.Dequeue(), Is.EqualTo(items[0])); }
public void ReplacingMinElementAndCheckingIfExtractedInSortedOrder() { var pq = new MinPriorityQueue <int, int>(); int maxHeapElement = 50000; int minHeapElement = -50000; int addedElements = 0; //Adding every seventh number, then every fifth number, //every third and at last all numbers //NOTE: some items are added more than once for (int i = 7; i > 0; i -= 2) { int el = minHeapElement; while (el <= maxHeapElement) { pq.Enqueue(el, -el); addedElements++; el += i; } } if (pq.Count != addedElements) { Assert.Fail(); } pq.ReplaceFirst(int.MaxValue, -int.MaxValue); pq.ReplaceFirst(int.MaxValue, -int.MaxValue); pq.ReplaceFirst(int.MaxValue, -int.MaxValue); int removedElements = 0; var min = pq.Peek(); while (!pq.IsEmpty) { var kvp = pq.Peek(); if (min.Key > kvp.Key) { Assert.Fail(); } min = pq.Dequeue(); removedElements++; } Assert.IsTrue(pq.IsEmpty && pq.Count == 0 && addedElements == removedElements); }
public void DequeueMinValue() { var sut = new MinPriorityQueue <int, int>(); for (var i = 0; i < 50000; i++) { sut.Enqueue(i, i); } for (var i = 0; i < 50000; i++) { Assert.AreEqual(i, sut.Dequeue()); } }
public void AddingElementsWithCustomComparerAndCheckingIfExtractedInSortedOrder() { //Creating heap with reversed comparer var pq = new MinPriorityQueue <int, int>(Comparer <int> .Create( (x, y) => y.CompareTo(x))); int maxHeapElement = 50000; int minHeapElement = -50000; int addedElements = 0; //Adding every seventh number, then every fifth number, //every third and at last all numbers //NOTE: some items are added more than once for (int i = 7; i > 0; i -= 2) { int el = minHeapElement; while (el <= maxHeapElement) { pq.Enqueue(el, -el); addedElements++; el += i; } } if (pq.Count != addedElements) { Assert.Fail(); } int removedElements = 0; // because of the reversed comparer var max = pq.Peek(); while (!pq.IsEmpty) { var kvp = pq.Peek(); if (max.Key < kvp.Key) { Assert.Fail(); } max = pq.Dequeue(); removedElements++; } Assert.IsTrue(pq.IsEmpty && pq.Count == 0 && addedElements == removedElements); }
private static void Main() { var maxPriorityQueue = new MaxPriorityQueue <string>(); maxPriorityQueue.Enqueue("Buy bread", 15); maxPriorityQueue.Enqueue("Buy milk", 10); maxPriorityQueue.Enqueue("Buy chocolate", 17); maxPriorityQueue.Enqueue("Go to shop", 30); maxPriorityQueue.Enqueue("Go home", 9); Console.WriteLine("Max priority queue: "); maxPriorityQueue.PrintQueue(); var minPriorityQueue = new MinPriorityQueue <string>(); minPriorityQueue.Enqueue("Buy bread", 15); minPriorityQueue.Enqueue("Buy milk", 10); minPriorityQueue.Enqueue("Buy chocolate", 17); minPriorityQueue.Enqueue("Go to shop", 30); minPriorityQueue.Enqueue("Go home", 9); Console.WriteLine("Min priority queue: "); minPriorityQueue.PrintQueue(); }
public void MinPriorityQueue_SingleEnqueueDequeueTest() { string test = "test"; var queue = new MinPriorityQueue <string>(); queue.Enqueue(test); Assert.IsFalse(queue.IsEmpty); Assert.AreEqual(1, queue.Size); var dequeued = queue.DequeueMin(); Assert.IsTrue(queue.IsEmpty); Assert.AreEqual(0, queue.Size); Assert.AreEqual(test, dequeued); }
public void MinPriorityQueue_Enqueue() { int capacity = 5; var q = new MinPriorityQueue<Element>(capacity); for (int i = capacity; i > 0; i--) { q.Enqueue(new Element { Number = i, Data = new byte[i]}); } Assert.IsTrue(q.Size == capacity); for (int i = 1; i <= capacity; i++) { var e = q.Dequeue(); Assert.IsTrue(i == e.Number); } }
/// <summary> /// Runs MinMax on a unit. /// </summary> /// <returns>A result-UnitAction pair.</returns> private KeyValuePair<Result, UnitAction> MinMax() { List<Node.NodePointer> targets = pathManager.getCurrentTargets(subjectRef); MinPriorityQueue<UnitAction> bestMoves = new MinPriorityQueue<UnitAction>(); int realclay = subjectRef.getClay(); // The "max-y" part: maximize (damage/counter-damage) foreach (Node.NodePointer candidateAttackTarget in targets) { int moveCost = candidateAttackTarget.getDist(); Unit curEnemy = candidateAttackTarget.getTarget().Occupier; AttackRound util = new AttackRound(subjectRef, moveCost, curEnemy); UnitAction roundMove = new UnitAction(subjectRef, curEnemy, candidateAttackTarget.getStart()); int totDmg = 0; // Will very likely die, enqueue this move as bad, and don't move to next step. //TODO: utility = 0 if (util.attackerDies() || util.getUtility() == 0) { bestMoves.Enqueue(roundMove, double.PositiveInfinity); util.resetBack(); subjectRef.setClay(realclay); continue; } totDmg += util.getExpectedDamage(); // Loop through all things that could attack this position, and continue testing attacks. // The "min-y" part. Enemy tries to maximize their (damage/counter-damage) // Technically could just do damage maximization, since counter-damage is fixed. foreach (Unit enemy in subjectsEnemiesRef) { if (enemy.getClay() > 0 && pathManager.canAttack(enemy, candidateAttackTarget.getStart())) { //gets the closest move. This will be the move that maxes damage. int enemyMoveCost = pathManager.maxDamageMoveCost(enemy, candidateAttackTarget.getStart()); AttackRound subRound = new AttackRound(enemy, enemyMoveCost, subjectRef); int roundClay = subjectRef.getClay(); subRound.resetBack(); subjectRef.setClay(roundClay); // If we die, break early, as usual. if (util.defenderDies()) { break; } totDmg += subRound.getExpectedCounterDamage(); } } // Died. Enqueue with +inf again. if (subjectRef.getClay() == 0) bestMoves.Enqueue(roundMove, double.PositiveInfinity); // enqueue move! min pri queue, so invert answer. else bestMoves.Enqueue(roundMove, -((double)totDmg / subjectRef.getClay())); util.resetBack(); subjectRef.setClay(realclay); } subjectRef.setClay(realclay); // no local targets... if (bestMoves.Count == 0) return new KeyValuePair<Result, UnitAction>(Result.NothingFound, null); // all moves die. only move is not to play. else if (bestMoves.currentInversePriority(bestMoves.Peek()) == double.PositiveInfinity) return new KeyValuePair<Result, UnitAction>(Result.WillDie, bestMoves.Peek()); // found good target. return new KeyValuePair<Result, UnitAction>(Result.Success, bestMoves.Peek()); }
/// <summary> /// Returns a sorted list of nodes within a given endurance value. /// Performs a Dijkstra-like algorithm. /// </summary> /// <param name="satifies">The predicate each node must follow.</param> /// <param name="endurance">The maximum endurance to follow out.</param> /// <returns>A sorted list of nodes within a given endurance value.</returns> public List<Node> nodesThatSatisfyPred(Node startNode, System.Predicate<Node> satifies, float endurance = 16.0f, bool stopOnFirst = false, bool isPathfinding = true) { List<Node> foundNodes = new List<Node>(); MinPriorityQueue<Node> nodeList = new MinPriorityQueue<Node>(); initializePathfinding(isPathfinding); startNode.realCost = 0; nodeList.Enqueue(startNode, startNode.realCost); #if DEBUG_PATHFINDER_LOGDEBUG StringBuilder encountered = new StringBuilder(); StringBuilder nodes = new StringBuilder(); nodes.Append("Start node ").Append(startNode.Number).AppendLine(); encountered.Append("Start node ").Append(startNode.Number).AppendLine(); encountered.Append("endurance = ").Append(endurance).AppendLine(); #endif while (nodeList.Count > 0) { //Pick the best looking node, by f-value. Node best = nodeList.Dequeue(); double bestDist = best.realCost; #if DEBUG_PATHFINDER_LOGDEBUG encountered.Append("Node ").Append(best.Number).Append(" ").Append(best).AppendLine(); nodes.Append("Node ").Append(best.Number).AppendLine(); #endif best.Visited = true; if (satifies(best)) { foundNodes.Add(best); if (stopOnFirst) return foundNodes; } //string updateString = "updating: "; foreach (Edge e in best.getEdges()) { Node other = e.getNode(); //We already visited this node, move along, if (other.Visited) continue; //Tentative distance. double testDist = e.getWeight() + bestDist; if (testDist > endurance) continue; //If the other node isn't in the priority queue, add it. if (!nodeList.Contains(other)) { other.CameFrom = best; other.realCost = testDist; nodeList.Enqueue(other, other.realCost); #if DEBUG_PATHFINDER_LOGDEBUG encountered.Append(" added ").Append(other.Number) .Append(", total estimated cost ") .Append(other.realCost).AppendLine(); #endif continue; } //If the other node was a bad path, and this one's better, replace it. else if (other.realCost > testDist) { other.CameFrom = best; other.realCost = testDist; nodeList.Update(other, other.realCost); #if DEBUG_PATHFINDER_LOGDEBUG encountered.Append(" updated ").Append(other.Number) .Append(", total new estimated cost ") .Append(other.realCost).AppendLine(); #endif } } } #if DEBUG_PATHFINDER_LOGDEBUG Debug.Log(encountered); Debug.Log(nodes); #endif return foundNodes; }
protected virtual Stack<PathNode> AStar(Tile source, Tile destination) { List<Tile> closed = new List<Tile>(); List<Tile> toDetermine; List<Tile> toAdd = new List<Tile>(); Stack<PathNode> finalPath = null; MinPriorityQueue<PathNode> open = new MinPriorityQueue<PathNode>(); List<PathNode> openList = new List<PathNode>(); open.Enqueue(new PathNode(source, destination)); openList.Add(open.Peek()); PathNode currentNode = null; bool endReached = false; do { currentNode = open.Dequeue(); openList.Remove(currentNode); if (currentNode.HCost == 0) { endReached = true; finalPath = currentNode.GetPath(); } else { closed.Add(tiles[currentNode.Current.X, currentNode.Current.Y]); toDetermine = getAdjacent(currentNode); foreach (Tile t in toDetermine) { bool remove = false; if (t.Collision > source.Unit.Collision) remove = true; if (t.HasUnit()) if (t.Unit.Army != source.Unit.Army) //added so that AI works remove = true; if (closed.Contains(t)) remove = true; //Add this if I want to have no duplicate pathnodes (currently, //multiple exist with different source nodes /* PathNode temp = new PathNode(t.GridwiseLocation, currentNode, destination.GridwiseLocation); foreach (PathNode p in openList) { if (p.Current == temp.Current) { if (p.GCost > temp.GCost) { p.Source = temp.Source; remove = true; } } }'*/ if (!remove) toAdd.Add(t); } foreach (Tile t in toAdd) { PathNode temp = new PathNode(t.GridwiseLocation, currentNode, destination.GridwiseLocation); open.Enqueue(temp); } toAdd.Clear(); } } while (!endReached); return finalPath; }
// run away to the node that's farthest away from all enemies. private KeyValuePair<Result, UnitAction> RunAway() { MinPriorityQueue<UnitAction> farthestActions = new MinPriorityQueue<UnitAction>(); foreach (Node n in pathManager.getAccessibleNodes(subjectRef)) { int curCount = 0; foreach (Unit en in subjectsEnemiesRef) curCount += Node.range(n, en.getNode()); // min priority queue: negate results. UnitAction runAwayTo = new UnitAction(subjectRef, null, n); farthestActions.Enqueue(runAwayTo, -curCount); } if (farthestActions.Count == 0) return new KeyValuePair<Result, UnitAction>(Result.NothingFound, UnitAction.DoNothing(subjectRef)); else return new KeyValuePair<Result, UnitAction>(Result.Success, farthestActions.Dequeue()); }
/// <summary> /// A* on the graph. /// </summary> /// <param name="pathStoreLoc">The Queue to store the path in.</param> /// <param name="start">The starting node.</param> /// <param name="end">The ending node.</param> public double AStar(Queue<Node> pathStoreLoc, Node start, Node end, Node toIgnore = null) { MinPriorityQueue<Node> nodeList = new MinPriorityQueue<Node>(); initializePathfinding(true); if (toIgnore != null) toIgnore.Visited = false; System.Func<Node, Node, float> Heuristic; if (allowedPaths == Paths.quadDir) Heuristic = ManhattenHeuristic; else if (allowedPaths == Paths.octDir) Heuristic = DiagonalHeuristic; else Heuristic = DiagonalHeuristic; start.CameFrom = null; start.heuristicCost = Heuristic(start, end); start.realCost = 0; nodeList.Enqueue(start, start.heuristicCost); #if DEBUG_PATHFINDER_LOGDEBUG StringBuilder encountered = new StringBuilder(); StringBuilder nodes = new StringBuilder(); nodes.Append("Start node ").Append(start.Number).AppendLine(); encountered.Append("Start node ").Append(start.Number).AppendLine(); nodes.Append("End node ").Append(end.Number).AppendLine(); encountered.Append("End node ").Append(end.Number).AppendLine(); #endif while (nodeList.Count > 0) { //Pick the best looking node, by f-value. Node best = nodeList.Dequeue(); double bestDist = best.realCost; #if DEBUG_PATHFINDER_LOGDEBUG encountered.Append("Node ").Append(best.Number).Append(" ").Append(best).AppendLine(); nodes.Append("Node ").Append(best.Number).AppendLine(); #endif //If this is the end, stop, show the path, and return it. if (best.Equals(end)) { ReconstructPath(pathStoreLoc, end); ShowPath(pathStoreLoc); #if DEBUG_PATHFINDER_LOGDEBUG encountered.Append("Finished!\n\nFinal dist: ") .Append(best.realCost).AppendLine(); Debug.Log(encountered); Debug.Log(nodes); #endif return best.realCost; } best.Visited = true; //string updateString = "updating: "; foreach (Edge e in best.getEdges()) { Node other = e.getNode(); //We already visited this node, move along, if (other.Visited) continue; //Tentative distance. double testDist = e.getWeight() + bestDist; //If the other node isn't in the priority queue, add it. if (!nodeList.Contains(other)) { other.CameFrom = best; other.realCost = testDist; other.heuristicCost = Heuristic(other, end); nodeList.Enqueue(other, other.realCost + other.heuristicCost); #if DEBUG_PATHFINDER_LOGDEBUG encountered.Append(" added ").Append(other.Number) .Append(", total estimated cost ") .Append(other.realCost + other.heuristicCost) .AppendLine(); #endif continue; } //If the other node was a bad path, and this one's better, replace it. else if (other.realCost > testDist) { other.CameFrom = best; other.realCost = testDist; nodeList.Update(other, other.realCost + other.heuristicCost); #if DEBUG_PATHFINDER_LOGDEBUG encountered.Append(" updated ").Append(other.Number) .Append(", total new estimated cost ") .Append(other.realCost + other.heuristicCost) .AppendLine(); #endif } } } #if DEBUG_PATHFINDER_LOGDEBUG encountered.Append("Failed!\n"); Debug.Log(encountered); Debug.Log(nodes); #endif return double.PositiveInfinity; }