Beispiel #1
0
        public void Equals_SameReference_True()
        {
            Motility motility  = Motility.Fly;
            Motility motility2 = motility;

            Assert.IsTrue(motility.Equals(motility2));
        }
Beispiel #2
0
        public void Equals_SameType_True()
        {
            Motility motility  = Motility.Fly;
            Motility motility2 = Motility.Fly;

            Assert.IsTrue(motility.Equals(motility2));
        }
Beispiel #3
0
        public void Contains_SameType_True()
        {
            Motility motility  = Motility.Fly;
            Motility motility2 = Motility.Fly;

            Assert.IsTrue(motility.Contains(motility2));
        }
        public void FilteredNeighbors_Unconstrained_EightWayNeighbors()
        {
            Vec2            vec2            = new Vec2(5, 5);
            PathfindingGrid grid            = new PathfindingGrid(vec2);
            Vec2            tileCoordinates = new Vec2(3, 3);

            Motility        agentMotility = Motility.Unconstrained | Motility.EightWayNeighbors;
            List <GridNode> nodes         = new List <GridNode>();

            grid.Fill(position => new GridNode(Tiles.Stone, position, grid));
            nodes.Add(new GridNode(Tiles.Stone, new Vec2(2, 2), grid));
            nodes.Add(new GridNode(Tiles.Stone, new Vec2(3, 2), grid));
            nodes.Add(new GridNode(Tiles.Stone, new Vec2(4, 2), grid));

            nodes.Add(new GridNode(Tiles.Stone, new Vec2(2, 3), grid));
            nodes.Add(new GridNode(Tiles.Stone, new Vec2(4, 3), grid));

            nodes.Add(new GridNode(Tiles.Stone, new Vec2(2, 4), grid));
            nodes.Add(new GridNode(Tiles.Stone, new Vec2(3, 4), grid));
            nodes.Add(new GridNode(Tiles.Stone, new Vec2(4, 4), grid));

            IReadOnlyCollection <GridNode> filteredNeighbors = grid.FilteredNeighbors(grid[tileCoordinates], agentMotility);

            CollectionAssert.AreEquivalent(nodes.AsReadOnly(), filteredNeighbors);
        }
Beispiel #5
0
        public void Bitwise_OR()
        {
            Motility motility    = Motility.Land | Motility.Swim;
            int      landAndSwim = 3;

            Assert.AreEqual(motility.GetHashCode(), landAndSwim.GetHashCode());
        }
Beispiel #6
0
        public void Equals_DifferentType_False()
        {
            Motility motility  = Motility.Fly;
            Motility motility2 = Motility.Climb;

            Assert.IsFalse(motility.Equals(motility2));
        }
Beispiel #7
0
        public void Bitwise_AND()
        {
            Motility motility = Motility.Land | Motility.Swim;
            int      land     = 1;

            motility &= Motility.Land;

            Assert.AreEqual(motility.GetHashCode(), land.GetHashCode());
        }
Beispiel #8
0
        public void Subtract()
        {
            Motility motility = Motility.Land | Motility.Swim;
            int      land     = 1;

            motility -= Motility.Swim;

            Assert.AreEqual(motility.GetHashCode(), land.GetHashCode());
        }
Beispiel #9
0
        public void IsTraversableTo_ContainsTraversable_True()
        {
            Motility traversable = Motility.Land | Motility.Burrow | Motility.Climb;

            //Assert.IsFalse(start.IsTraversableTo(end, Motility.Land));

            //end.SetIncomingTraversableFlag(traversable);

            //Assert.IsTrue(start.IsTraversableTo(end, Motility.Land));
        }
Beispiel #10
0
        public void SetIncomingTravsersableFlag_SetMultipleTraversableFlags_True()
        {
            Motility traversable = Motility.Land | Motility.Fly;

            /*Assert.IsFalse(start.IsTraversableTo(end, traversable));
            *
            *  end.SetIncomingTraversableFlag(traversable);
            *
            *  Assert.IsTrue(start.IsTraversableTo(end, Motility.Land));
            *  Assert.IsTrue(start.IsTraversableTo(end, Motility.Fly));*/
        }
        public void IsTraversible_DoesNotContainTraversability_False()
        {
            Motility traversable = Motility.Fly;

            Assert.IsFalse(edge.IsTraversable(Motility.Land));
            Assert.IsFalse(edge.IsTraversable(Motility.Fly));
            Assert.IsFalse(edge.IsTraversable(Motility.Burrow));

            edge.SetMotilityFlag(Motility.Land);
            edge.SetMotilityFlag(Motility.Burrow);

            Assert.IsFalse(edge.IsTraversable(traversable));
        }
Beispiel #12
0
        public void IsTraversibleTo_DoesNotContainTraversability_False()
        {
            Motility traversable = Motility.Fly;

            /*Assert.IsFalse(start.IsTraversableTo(end, Motility.Land));
             * Assert.IsFalse(start.IsTraversableTo(end, Motility.Fly));
             * Assert.IsFalse(start.IsTraversableTo(end, Motility.Burrow));
             *
             * end.SetIncomingTraversableFlag(Motility.Land);
             * end.SetIncomingTraversableFlag(Motility.Burrow);
             *
             * Assert.IsFalse(start.IsTraversableTo(end, traversable));*/
        }
        public void FilteredNeighbors_LandMotility_FourWayNeighbors()
        {
            Vec2            vec2            = new Vec2(5, 5);
            PathfindingGrid grid            = new PathfindingGrid(vec2);
            Vec2            tileCoordinates = new Vec2(3, 3);

            Motility        agentMotility = Motility.Land | Motility.FourWayNeighbors;
            List <GridNode> nodes         = new List <GridNode>();

            grid.Fill(position => new GridNode(Tiles.Stone, position, grid));
            grid[2, 3] = new GridNode(Tiles.Floor, new Vec2(2, 3), grid);
            grid[3, 4] = new GridNode(Tiles.Floor, new Vec2(3, 4), grid);

            nodes.Add(new GridNode(Tiles.Floor, new Vec2(2, 3), grid));
            nodes.Add(new GridNode(Tiles.Floor, new Vec2(3, 4), grid));

            CollectionAssert.AreEquivalent(nodes.AsReadOnly(), grid.FilteredNeighbors(grid[tileCoordinates], agentMotility));
        }
Beispiel #14
0
        public override IList <GridNode> Search(GridNode start, GridNode goal, Motility motility,
                                                Func <GridNode, GridNode, float> heuristic)
        {
            Dictionary <GridNode, GridNode> parentMap = new Dictionary <GridNode, GridNode>();
            SimplePriorityQueue <GridNode>  frontier  = new SimplePriorityQueue <GridNode>();

            frontier.Enqueue(start, start.PathCost);

            while (frontier.Count > 0)
            {
                GridNode current = frontier.Dequeue();

                if (current == goal)
                {
                    break;
                }

                foreach (GridNode neighbor in current.Neighbors)
                {
                    IPathfindingEdge edge = current.JoiningEdge(neighbor);

                    //if (!IsTraversable(edge, motility)) continue; // TODO: This line should be made irrelevant

                    float newCost      = current.PathCost + edge.Weight;
                    float neighborCost = neighbor.PathCost;
                    bool  containsKey  = parentMap.ContainsKey(neighbor);

                    if (containsKey && (newCost >= neighborCost))
                    {
                        continue;
                    }

                    neighbor.PathCost   = newCost;
                    parentMap[neighbor] = current; // UPSERT dictionary function
                    float priority = newCost + heuristic(goal, neighbor);
                    frontier.Enqueue(neighbor, priority);
                }
            }

            IList <GridNode> path = ReconstructPath(parentMap, start, goal);

            return(path);
        }
Beispiel #15
0
        /// <summary>
        /// Checks if a given edge is traversable given the motility flags passed in. Will check both movement
        /// motility as well as filter out edges based on the most permissive n-WayNeighbor's flag set. If no
        /// neighbor flag is set, it defaults to Motility.AllNeighbors.
        /// </summary>
        /// <param name="edge">The edge attempting traversal.</param>
        /// <param name="agentMotility">The agent's ability to traverse edges.</param>
        public static bool IsTraversable(GridNode edge, Motility agentMotility)
        {
            // Identify the graph structure for this agent and reject extraneous neighbors.
            if (agentMotility.Contains(Motility.AllNeighbors))
            {
                // Most permissive option is true, so continue to next step, skipping the other checks.
            }
            else if (agentMotility.Contains(Motility.EightWayNeighbors))
            {
                // Reject only special nodes (such as portals)
                //if (!Direction.Clockwise.Contains(edge.Direction))
                {
                    return(false);
                }
            }
            else if (agentMotility.Contains(Motility.FourWayNeighbors))
            {
                // Reject the intercardinal directions (diagonals) as well as any special nodes (such as portals)
                //if (!Direction.CardinalDirections.Contains(edge.Direction))
                {
                    return(false);
                }
            }
            else
            {
                // This is an implicit "has no neighbors flag" flag, which is just a lack of any neighbor flag at all.
                // In this case we default to Motility.AllNeighbors and continue.
            }

            // If the agent has Motility.Unconstrained, then we return, no need to compare to edge Motility.
            if (agentMotility.Contains(Motility.Unconstrained))
            {
                return(true);
            }

            // Check the agent's movement Motility compared to the edge Motility
            throw new NotImplementedException();
            //return edge.IsTraversable(agentMotility);
        }
        public override IList <GridNode> Search(GridNode start, GridNode goal, Motility motility)
        {
            Dictionary <GridNode, GridNode> parentMap = new Dictionary <GridNode, GridNode>();
            Queue <GridNode> frontier = new Queue <GridNode>();

            frontier.Enqueue(start);

            while (frontier.Count > 0)
            {
                GridNode current = frontier.Dequeue();

                if (current == goal)
                {
                    break;
                }

                foreach (GridNode neighbor in current.Neighbors)
                {
                    IPathfindingEdge edge = current.JoiningEdge(neighbor);

                    //if (!edge.IsTraversable(edge, motility)) continue;

                    if (parentMap.ContainsKey(neighbor))
                    {
                        continue;
                    }

                    frontier.Enqueue(neighbor);
                    parentMap.Add(neighbor, current);
                }
            }

            IList <GridNode> path = ReconstructPath(parentMap, start, goal);

            return(path);
        }
Beispiel #17
0
 public TileType _Motility(Motility motility)
 {
     return(new TileType(_name, motility, _spriteIndex));
 }
Beispiel #18
0
 public virtual IList <GridNode> Search(GridNode start, GridNode goal,
                                        Motility motility, Func <GridNode, GridNode, float> heuristic)
 {
     throw new NotImplementedException(
               "\"This algorithm does not use a heuristic. Use \"Search(IPathfindingNode start, IPathfindingNode end, Traversable traversability)\" instead.");
 }
Beispiel #19
0
        public void Contains_SameReference_True()
        {
            Motility motility = Motility.Fly;

            Assert.IsTrue(motility.Contains(motility));
        }
Beispiel #20
0
 /* TODO: When multiple movement types are added, the pathfinding algorithms will have to account for the fact
  * that there are "preferences" for movement - i.e. if you have a land speed of 6 and a climb speed
  * of 3 the costs of climbing are twice as high as the cost of walking. This will probably need to have the
  * traversabilities given in a Dictionary format with the traversability as the key and the cost as the value.
  * This would also add another bonus: implicitly giving whether or not an agent has a particular movement
  * type by way of if they have a movement speed listed, instead of needing to explicitly define their movement
  * types! -- Cost = BaseMovementCost + FastestMovementSpeed / FastestMovementSpeedOnEdgeThatTheAgentCanUse
  * NOTE: A possible solution for the "cant end movement in a particular tile" problem would be to have a
  * traversability flag Traversable.CantEndMovementHere and if the (pathCost % (mod) moveSpeed == 0) then reject
  * that edge in the IsTraversable function, or alternatively in a separate check.
  */
 public virtual IList <GridNode> Search(GridNode start, GridNode goal,
                                        Motility motility)
 {
     throw new NotImplementedException(
               "\"A heuristic is required for this algorithm. Use \"Search(IPathfindingNode start, IPathfindingNode end, Traversable traversability, Func<IPathfindingNode, IPathfindingNode, float> heuristic)\" instead.");
 }
        public bool MakeHalls()
        {
            List <Vertex> vertices = new List <Vertex>();

            // add a vertex at the center of each room
            foreach (Rect room in _rooms)
            {
                vertices.Add(new Vertex <Rect>(new Vector2(room.Center.x, room.Center.y), room));
            }

            // Create a Delaunay triangulation of the rooms
            _delaunay = Delaunay2D.Triangulate(vertices);

            // Convert the Delaunay edges to Prim edges
            List <Prim.Edge> edges = new List <Prim.Edge>();

            foreach (Delaunay2D.Edge edge in _delaunay.Edges)
            {
                edges.Add(new Prim.Edge(edge.U, edge.V));
            }

            // Create a minimum spanning tree of the triangulation
            List <Prim.Edge> mst = Prim.MinimumSpanningTree(edges, edges[0].U);

            // Get the edges not part of the MST
            HashSet <Prim.Edge> selectedEdges  = new HashSet <Prim.Edge>(mst);
            HashSet <Prim.Edge> remainingEdges = new HashSet <Prim.Edge>(edges);

            remainingEdges.ExceptWith(selectedEdges);

            // Create some loops, since MSTs make for boring maps
            foreach (Prim.Edge edge in remainingEdges)
            {
                if (Rng.Int(100) < _writer.Options.ChanceOfExtraHallway)
                {
                    selectedEdges.Add(edge);
                }
            }

            // Drive a pathfinder to carve out the halls
            Motility motility = Motility.FourWayNeighbors | Motility.Unconstrained;

            foreach (Prim.Edge edge in selectedEdges)
            {
                Rect startRoom = (edge.U as Vertex <Rect>).Item;
                Rect endRoom   = (edge.V as Vertex <Rect>).Item;

                GridNode start = _writer.GetTile(new Vec2(startRoom.Center.x, startRoom.Center.y));
                GridNode goal  = _writer.GetTile(new Vec2(endRoom.Center.x, endRoom.Center.y));

                // Heuristic is Manhattan distance on a square grid
                IList <GridNode> path = _writer.Graph.FindPath <AStarSearchAlgorithm>(start, goal,
                                                                                      motility, (a, b) =>
                                                                                      Math.Abs((float)(a.Position.x - b.Position.x)) + Math.Abs((float)(a.Position.y - b.Position.y)));

                // Bail if the pathfinder failed to find a path (NOTE: if it does, it seems like it should be a problem)
                if (path == null)
                {
                    continue;
                }
                foreach (GridNode step in path)
                {
                    _writer.SetTile(step.Position, Tiles.Floor);
                    foreach (GridNode neighbor in step.Neighbors)
                    {
                        if ((_writer.GetTile(neighbor.Position)).Type == Tiles.Stone)
                        {
                            _writer.SetTile(neighbor.Position, Tiles.Wall);
                        }
                    }
                }
            }

            return(true);
        }
        public IDictionary <GridNode, GridNode> Fill(GridNode start, float searchDepth, Motility motility)
        {
            Dictionary <GridNode, GridNode> parentMap = new Dictionary <GridNode, GridNode>();
            SimplePriorityQueue <GridNode>  frontier  = new SimplePriorityQueue <GridNode>();

            frontier.Enqueue(start, 0);

            while (frontier.Count > 0)
            {
                GridNode current = frontier.Dequeue();

                foreach (GridNode neighbor in current.Neighbors)
                {
                    IPathfindingEdge edge = current.JoiningEdge(neighbor);

                    //if (!edge.IsTraversable(edge, motility)) continue;

                    float newCost      = current.PathCost + edge.Weight;
                    float neighborCost = neighbor.PathCost;
                    bool  containsKey  = parentMap.ContainsKey(neighbor);

                    if (containsKey && (newCost >= neighborCost) || newCost > searchDepth)
                    {
                        continue;
                    }

                    neighbor.PathCost   = newCost;
                    parentMap[neighbor] = current; // UPSERT dictionary function
                    float priority = newCost;
                    frontier.Enqueue(neighbor, priority);
                }
            }

            return(parentMap);
        }