コード例 #1
0
ファイル: DjikstraTests.cs プロジェクト: ptrick/JewelThief
        public void GraphWithoutTeleportRule()
        {
            var cellGraph    = generateTestGraph();
            var startingCell = cellGraph.LookupCell(0, 0);
            var targetCell   = cellGraph.LookupCell(2, 2);

            var graph = DijkstraWeightGraph.BuildDijkstraWeightGraph(cellGraph, startingCell, maxDistance: 0, allowNeighborTeleportation: false);

            var expectedPath = new Vector3Int[]
            {
                new Vector3Int(0, 0, 0),
                new Vector3Int(0, 1, 0),
                new Vector3Int(0, 2, 0),
                new Vector3Int(0, 3, 0),
                new Vector3Int(1, 3, 0),
                new Vector3Int(2, 3, 0),
                new Vector3Int(2, 2, 0),
            };
            var expectedDistance = expectedPath.Length - 1;

            var(accessible, shortestPath) = graph.LookupShortestPath(targetCell);
            Assert.True(accessible);
            Assert.True(PathsMatch(shortestPath.Path, expectedPath));

            var(accessible2, distance) = graph.LookupDistance(targetCell);
            Assert.True(accessible2);
            Assert.True(distance == expectedDistance);
        }
コード例 #2
0
ファイル: DjikstraTests.cs プロジェクト: ptrick/JewelThief
        public void GraphWithTeleportRule()
        {
            var cellGraph    = generateTestGraph();
            var startingCell = cellGraph.LookupCell(0, 0);
            var targetCell   = cellGraph.LookupCell(2, 2);

            var graph = DijkstraWeightGraph.BuildDijkstraWeightGraph(cellGraph, startingCell, maxDistance: 0, allowNeighborTeleportation: true);

            // Either of these is acceptable...
            var expectedPathOne = new Vector3Int[]
            {
                new Vector3Int(0, 0, 0),
                new Vector3Int(0, 1, 0),
                new Vector3Int(0, 2, 0),
                new Vector3Int(2, 2, 0),
            };
            var expectedPathTwo = new Vector3Int[] // Hop the gate allowed, contrary to actual rules in original
            {                                      // I might adjust that later, but for now it's expected
                new Vector3Int(0, 0, 0),
                new Vector3Int(1, 0, 0),
                new Vector3Int(2, 0, 0),
                new Vector3Int(2, 2, 0),
            };
            var expectedDistance = expectedPathOne.Length - 1;

            var(accessible, shortestPath) = graph.LookupShortestPath(targetCell);
            Assert.True(accessible);
            Assert.True(PathsMatch(shortestPath.Path, expectedPathOne) ||
                        PathsMatch(shortestPath.Path, expectedPathTwo));

            var(accessible2, distance) = graph.LookupDistance(targetCell);
            Assert.True(accessible2);
            Assert.True(distance == expectedDistance);
        }
コード例 #3
0
ファイル: PlayerController.cs プロジェクト: ptrick/JewelThief
    /// <summary>
    /// Call this when something changes in the environment
    /// (Gate unlocked, for example)
    /// </summary>
    /// <param name="cellGraph">The current scene cell graph</param>
    public void RebuildGraph(LogicalCellGraph cellGraph)
    {
        if (playerPawn == null)
        {
            return;
        }

        LogicalCell commandPosition;

        if (hasCommitedCell)
        {
            commandPosition = cellGraph.LookupCell(lastCommittedCell.x, lastCommittedCell.y);
        }
        else
        {
            var playerPos  = playerPawn.LogicalLocation;
            var playerCell = cellGraph.LookupCell(playerPos.x, playerPos.y);
            commandPosition = playerCell;
        }
        playerWeightGraph = DijkstraWeightGraph.BuildDijkstraWeightGraph(
            cellGraph,
            commandPosition,
            maxDistance: 6,
            allowNeighborTeleportation: true);
    }
コード例 #4
0
ファイル: DjikstraTests.cs プロジェクト: ptrick/JewelThief
        public void GraphWithLimitedDistance()
        {
            var cellGraph    = generateTestGraph();
            var startingCell = cellGraph.LookupCell(0, 0);
            var targetCell   = cellGraph.LookupCell(2, 2);

            var graph = DijkstraWeightGraph.BuildDijkstraWeightGraph(cellGraph, startingCell, maxDistance: 2, allowNeighborTeleportation: true);

            var(accessible, _) = graph.LookupShortestPath(targetCell);
            Assert.False(accessible);

            var(accessible2, _) = graph.LookupDistance(targetCell);
            Assert.False(accessible2);
        }
コード例 #5
0
    /// <summary>
    /// Should be called when the scene's graph changes
    /// (Ie. a locked gate has been lifted)
    /// </summary>
    /// <param name="cellGraph">The scene graph</param>
    public void RebuildGraph(LogicalCellGraph cellGraph)
    {
        if (enemyPawn == null)
        {
            return;
        }

        var enemyPos  = enemyPawn.LogicalLocation;
        var enemyCell = cellGraph.LookupCell(enemyPos.x, enemyPos.y);

        enemyWeightGraph = DijkstraWeightGraph.BuildDijkstraWeightGraph(
            cellGraph,
            enemyCell,
            maxDistance: 0,
            allowNeighborTeleportation: true);
    }
コード例 #6
0
    /// <summary>
    /// Builds a new precalculated Dijkstra graph based on the starting location.
    /// </summary>
    /// <param name="graph">The cell graph we are working from</param>
    /// <param name="startingLocation">The location common to all futher distance calculations</param>
    /// <param name="maxDistance">The maximum distance away from the starting location the graph will store. If left as 0, it counts as infinite.</param>
    /// <param name="allowNeighborTeleportation">This game has special rules to allow traversal on non-adjacent cells. Passing false will disable this rule making it more like the assignment likely intended (but that would be less fun!)</param>
    /// <returns>The baked/calculated Dijkstra graph</returns>
    public static DijkstraWeightGraph BuildDijkstraWeightGraph(LogicalCellGraph graph, LogicalCell startingLocation, int maxDistance = 0, bool allowNeighborTeleportation = false)
    {
        DijkstraWeightGraph g = new DijkstraWeightGraph();

        g.startingLocation = startingLocation;

        var distances      = new Dictionary <LogicalCell, int>();
        var path           = new Dictionary <LogicalCell, LogicalCell>();
        var remainingCells = new HashSet <LogicalCell>();

        foreach (LogicalCell cell in graph.Cells)
        {
            distances[cell] = int.MaxValue;
            path[cell]      = null;
            remainingCells.Add(cell);
        }
        distances[startingLocation] = 0;

        while (remainingCells.Any())
        {
            LogicalCell currentCell         = remainingCells.First();
            int         currentCellDistance = int.MaxValue;
            foreach (LogicalCell cell in remainingCells)
            {
                var d = distances[cell];
                if (d < currentCellDistance)
                {
                    currentCellDistance = d;
                    currentCell         = cell;
                }
            }
            remainingCells.Remove(currentCell);

            if (currentCellDistance != int.MaxValue && (maxDistance == 0 || currentCellDistance + 1 <= maxDistance))
            {
                foreach (var neighbor in currentCell.Neighbors)
                {
                    if (neighbor == null)
                    {
                        continue;
                    }

                    // The special rule for this game allows non-adjacent traversal on matching colors.
                    if (!allowNeighborTeleportation)
                    {
                        bool adjacent = (Math.Abs(neighbor.X - currentCell.X) <= 1 && neighbor.Y == currentCell.Y) ||
                                        (Math.Abs(neighbor.Y - currentCell.Y) <= 1 && neighbor.X == currentCell.X);
                        if (!adjacent)
                        {
                            continue; // Skip
                        }
                    }

                    if (!remainingCells.Contains(neighbor))
                    {
                        continue; // Skip
                    }

                    int newDistance = currentCellDistance + 1;

                    if (newDistance < distances[neighbor])
                    {
                        distances[neighbor] = newDistance;
                        path[neighbor]      = currentCell;
                    }
                }
            }
        }

        g.distancesByCell = distances;
        g.paths           = path;

        return(g);
    }