public void CompletePathTest() { var graph = new Algorithms.AStar <TestGraphElement> .LazyGraph(); Func <TestGraphElement, TestGraphElement, float> costFunc = (TestGraphElement lhs, TestGraphElement rhs) => { return(TestGraphElement.DistanceBetween(lhs, rhs)); }; IDictionary <Vector2, TestGraphElement> graphElements = new Dictionary <Vector2, TestGraphElement> (); Func <Vector2, TestGraphElement> getGraphElementFunc = (Vector2 position) => { if (!graphElements.ContainsKey(position)) { graphElements[position] = TestGraphElement.At(position); } Assert.IsTrue(graphElements[position] != null && graphElements[position].position == position); return(graphElements[position]); }; graph.getElementsConnectedToElementFunc = (TestGraphElement testPos) => { IList <TestGraphElement> connectedElems = new List <TestGraphElement> (); connectedElems.Add(getGraphElementFunc(OffsetPos(testPos.position, Vector2.right))); connectedElems.Add(getGraphElementFunc(OffsetPos(testPos.position, -Vector2.right))); connectedElems.Add(getGraphElementFunc(OffsetPos(testPos.position, Vector2.up))); connectedElems.Add(getGraphElementFunc(OffsetPos(testPos.position, -Vector2.up))); return(connectedElems); }; graph.getActualCostForMovementBetweenElementsFunc = costFunc; graph.getLowestCostEstimateForMovementBetweenElementsFunc = costFunc; Assert.IsTrue(graph.GetIsValid()); var aStarSearch = new Algorithms.AStar <TestGraphElement>(graph); // Calculate a route... Vector2 startPos = Vector2.zero; Vector2 endPos = new Vector2(5, 0); int xOffset = Mathf.RoundToInt(Mathf.Abs(startPos.x - endPos.x)); int yOffset = Mathf.RoundToInt(Mathf.Abs(startPos.y - endPos.y)); int shortestRouteNumElements = xOffset + yOffset + 1; IList <TestGraphElement> route = aStarSearch.Calculate(getGraphElementFunc(startPos), getGraphElementFunc(endPos)); Assert.IsNotNull(route); Assert.AreEqual(route.Count, shortestRouteNumElements); Assert.AreEqual(route.First().position, startPos); Assert.AreEqual(route.Last().position, endPos); for (int currTestIndex = 1; currTestIndex < route.Count; ++currTestIndex) { TestGraphElement prevElem = route[currTestIndex - 1]; TestGraphElement currElem = route[currTestIndex]; Assert.IsTrue(TestGraphElement.AreAdjacent(prevElem, currElem)); } }
public void TestStructGraphElement() { var graph = new Algorithms.AStar <Vector2> .LazyGraph(); Func <Vector2, Vector2, float> costFunc = (Vector2 lhs, Vector2 rhs) => { return((rhs - lhs).magnitude); }; graph.getActualCostForMovementBetweenElementsFunc = costFunc; graph.getLowestCostEstimateForMovementBetweenElementsFunc = costFunc; IList <Vector2> connectedOffsets = (new List <Vector2> { Vector2.right, Vector2.left, Vector2.up, Vector2.down }).AsReadOnly(); // Connect a grid of all integer positions in both axes up to 100.0f away from the origin. graph.getElementsConnectedToElementFunc = (Vector2 startPos) => { IList <Vector2> connectedPositions = new List <Vector2> (); foreach (Vector2 currConnectedOffset in connectedOffsets) { Vector2 currConnectedPos = OffsetPos(startPos, currConnectedOffset); if (currConnectedPos.magnitude < 10.0f) { connectedPositions.Add(currConnectedPos); } } return(connectedPositions); }; Assert.IsTrue(graph.GetIsValid()); var aStarSearch = new Algorithms.AStar <Vector2>(graph); IList <Vector2> resultPath = aStarSearch.Calculate(new Vector2(-5.0f, 0.0f), new Vector2(5.0f, 0.0f)); // The expected path is a straight path along the y-axis from x = -5.0f to x = 5.0f. IList <Vector2> expectedResultPath = new List <Vector2> (); for (int i = -5; i <= 5; ++i) { expectedResultPath.Add(new Vector2((float)i, 0.0f)); } Assert.IsTrue(resultPath.SequenceEqual(expectedResultPath)); }
public void GraphReuseTest() { var graph = new Algorithms.AStar <Vector2> .LazyGraph(); graph.getElementsConnectedToElementFunc = (Vector2 testPos) => { return(new List <Vector2> { testPos + Vector2.right, testPos + Vector2.up, testPos + Vector2.left, testPos + Vector2.down }); }; Func <Vector2, Vector2, float> costFunc = (Vector2 lhs, Vector2 rhs) => { return((rhs - lhs).magnitude); }; graph.getActualCostForMovementBetweenElementsFunc = costFunc; graph.getLowestCostEstimateForMovementBetweenElementsFunc = costFunc; Assert.IsTrue(graph.GetIsValid()); var aStarSearch = new Algorithms.AStar <Vector2>(graph); // Try a search... { IList <Vector2> result = aStarSearch.Calculate(new Vector2(0, 0), new Vector2(2, 0)); Assert.IsTrue(Enumerable.SequenceEqual(result, new List <Vector2> { new Vector2(0, 0), new Vector2(1, 0), new Vector2(2, 0) })); } // Try a search with a different target... { IList <Vector2> result = aStarSearch.Calculate(new Vector2(-2, 0), new Vector2(2, 0)); Assert.IsTrue(Enumerable.SequenceEqual(result, new List <Vector2> { new Vector2(-2, 0), new Vector2(-1, 0), new Vector2(0, 0), new Vector2(1, 0), new Vector2(2, 0) })); } // Try a search with a different start point... { IList <Vector2> result = aStarSearch.Calculate(new Vector2(-2, 0), new Vector2(3, 0)); Assert.IsTrue(Enumerable.SequenceEqual(result, new List <Vector2> { new Vector2(-2, 0), new Vector2(-1, 0), new Vector2(0, 0), new Vector2(1, 0), new Vector2(2, 0), new Vector2(3, 0) })); } }
public void PartialPathTest() { var graph = new Algorithms.AStar <TestGraphElement> .LazyGraph(); Func <TestGraphElement, TestGraphElement, float> costFunc = (TestGraphElement lhs, TestGraphElement rhs) => { return(TestGraphElement.DistanceBetween(lhs, rhs)); }; IDictionary <Vector2, TestGraphElement> graphElements = new Dictionary <Vector2, TestGraphElement> (); Func <Vector2, TestGraphElement> getGraphElementFunc = (Vector2 position) => { if (!graphElements.ContainsKey(position)) { graphElements[position] = TestGraphElement.At(position); } Assert.IsTrue(graphElements[position] != null && graphElements[position].position == position); return(graphElements[position]); }; graph.getElementsConnectedToElementFunc = (TestGraphElement testPos) => { // Add a gap in the graph between x=2 and x=3 so we cannot do a complete path. float graphBreakXPos = 2.0f; IList <TestGraphElement> connectedElems = new List <TestGraphElement> (); if (testPos.position.x != graphBreakXPos) { connectedElems.Add(getGraphElementFunc(OffsetPos(testPos.position, Vector2.right))); } if (testPos.position.x != graphBreakXPos + 1.0f) { connectedElems.Add(getGraphElementFunc(OffsetPos(testPos.position, -Vector2.right))); } connectedElems.Add(getGraphElementFunc(OffsetPos(testPos.position, Vector2.up))); connectedElems.Add(getGraphElementFunc(OffsetPos(testPos.position, -Vector2.up))); return(connectedElems); }; graph.getActualCostForMovementBetweenElementsFunc = costFunc; graph.getLowestCostEstimateForMovementBetweenElementsFunc = costFunc; Assert.IsTrue(graph.GetIsValid()); var aStarSearch = new Algorithms.AStar <TestGraphElement>(graph); // Calculate a route... Vector2 startPos = Vector2.zero; Vector2 endPos = new Vector2(5, 0); // Check that we can't find a complete route between the two points (as there is a break in the graph). // Note: As we have an non-finite graph and there is no complete path, we MUST give a worst acceptable route cost as otherwise the // calculation will never terminate (as it can never be sure there isn't a viable solution in the parts of the graph it hasn't reached yet). IList <TestGraphElement> completeRoute = aStarSearch.Calculate(getGraphElementFunc(startPos), getGraphElementFunc(endPos), false, 100.0f); Assert.IsNull(completeRoute); IList <TestGraphElement> partialRoute = aStarSearch.Calculate(getGraphElementFunc(startPos), getGraphElementFunc(endPos), true, 100.0f); Assert.IsNotNull(partialRoute); // Check the best partial route we found is what we would expect... Assert.AreEqual(partialRoute.Count, 3); Assert.AreEqual(partialRoute[0].position, startPos); Assert.AreEqual(partialRoute[1].position, new Vector2(1, 0)); Assert.AreEqual(partialRoute[2].position, new Vector2(2, 0)); }