예제 #1
0
        public void Test_IsEmpty_FilledQ()
        {
            PriorityQueue <double> q = null;

            q = new MinPriorityQueue <double>();
            q.Enqueue(1);
            q.Enqueue(2);

            Assert.IsFalse(q.IsEmpty);
        }
예제 #2
0
        public void Test_Count()
        {
            PriorityQueue <double> q = null;

            q = new MinPriorityQueue <double>();
            q.Enqueue(1);
            q.Enqueue(2);

            Assert.AreEqual(2, q.Count);
        }
예제 #3
0
        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));
        }
예제 #4
0
        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());
        }
예제 #5
0
        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);
        }
예제 #6
0
        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));
        }
예제 #7
0
        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
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        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;
            }
        }
예제 #15
0
        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());
            }
        }
예제 #16
0
        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]);
            }
        }
예제 #19
0
        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);
        }
예제 #20
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);
        }
예제 #22
0
        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]);
        }
예제 #23
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);
        }
예제 #24
0
        //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]));
        }
예제 #26
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);
        }
예제 #27
0
        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());
            }
        }
예제 #28
0
        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);
        }
예제 #29
0
        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();
        }
예제 #30
0
        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);
            }
        }
예제 #32
0
    /// <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());
    }
예제 #33
0
        /// <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;
        }
예제 #34
0
        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;
        }
예제 #35
0
    // 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());
    }
예제 #36
0
        /// <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;
        }