Пример #1
0
    public Maybe <Path> CalculateDijkstraPath <T>(BaseTile <T> source, BaseTile <T> destination, float z) where T : BaseTile <T>, IHaveMovementCost
    {
        var frontier  = new SimplePriorityQueue <BaseTile <T> >();
        var cameFrom  = new Dictionary <BaseTile <T>, BaseTile <T> >();
        var costSoFar = new Dictionary <BaseTile <T>, int>();

        costSoFar.Add(source, 0);
        frontier.Enqueue(source, 0);

        while (frontier.Any())
        {
            var current = frontier.Dequeue();

            if (current == destination)
            {
                break;
            }

            current.ForEachCardinalNeighbor(next =>
            {
                var newCost = costSoFar[current] + next.MovementCost;

                if ((!cameFrom.ContainsKey(next) || newCost < costSoFar[next]) && next.IsWalkable)
                {
                    costSoFar[next] = newCost;
                    frontier.Enqueue(next, newCost);
                    cameFrom[next] = current;
                }
            });
        }

        return(ConstructPath(cameFrom, source, destination, z));
    }
Пример #2
0
        private static int Reduce(List <Rule> rules, string molecule)
        {
            // Dictionary with number of steps to molecule
            Dictionary <string, int> moleculeToSteps = new Dictionary <string, int>()
            {
                { molecule, 0 }
            };

            // Remember processed molecules
            HashSet <string> seen = new HashSet <string>();

            // Queue with molecules to process
            SimplePriorityQueue <string> toProcess = new SimplePriorityQueue <string>();

            toProcess.Enqueue(molecule, molecule.Length);

            // Randomizator, because otherwise we get stuck
            Random rng = new Random();

            while (toProcess.Any())
            {
                // Get another molecule to process
                string oldMolecule = toProcess.Dequeue();

                //Console.WriteLine(oldMolecule);
                if (oldMolecule == "e")
                {
                    break;
                }

                // Do all possible reductions
                foreach (Rule rule in rules.OrderBy(x => rng.Next()))
                {
                    foreach (int index in oldMolecule.IndiciesOf(rule.To))
                    {
                        // Do reduction
                        string newMolecule = oldMolecule.Substring(0, index) + rule.From + oldMolecule.Substring(index + rule.To.Length);

                        // Calculate steps
                        int steps = moleculeToSteps[oldMolecule] + 1;

                        // Save progress
                        if (!moleculeToSteps.TryGetValue(newMolecule, out int oldSteps) || oldSteps > steps)
                        {
                            moleculeToSteps[newMolecule] = steps;
                        }

                        // Do more reductions
                        if (!seen.Contains(newMolecule))
                        {
                            toProcess.Enqueue(newMolecule, newMolecule.Length);
                            seen.Add(newMolecule);
                        }
                    }
                }
            }

            return(moleculeToSteps["e"]);
        }
Пример #3
0
        // Returns true if goal node is found. Returns false if no goal node is found.
        public bool hSearch()
        {
            worldNode currentNode;

            setup();
            while (fringe.Any())
            {
                currentNode = fringe.Dequeue();
                if (currentNode == worldNodes[endx, endy])
                {
                    sw.Stop();
                    return(true);
                }
                expandNode(currentNode);
            }
            sw.Stop();
            return(false);
        }
Пример #4
0
        /// <summary>
        /// Find the closest objective to go on. Dijkstra Pathfinding
        /// </summary>
        /// <returns>Next to tile to go on and the cost to go on that tile. Postion is null and cost is equal to NO_COST if path find.</returns>
        //http://www.redblobgames.com/pathfinding/a-star/introduction.html Python -> C#
        public Tuple <Coordinates, int> GetDirection()
        {
            // We make sure that we still have a possible target.
            if (!IHaveAGoalRemaning())
            {
                return(Tuple.Create(currentTile.Position, 0));
            }
            SimplePriorityQueue <Tile> frontier = new SimplePriorityQueue <Tile>();

            frontier.Enqueue(currentTile, 0);
            Dictionary <Tile, Tile> cameFrom  = new Dictionary <Tile, Tile>();
            Dictionary <Tile, int>  costSoFar = new Dictionary <Tile, int> {
                { currentTile, 0 }
            };
            Tile current = currentTile, last = currentTile;

            // While we still have tiles to go.
            while (frontier.Any())
            {
                current = frontier.Dequeue();

                // If the tile is an objective, we stop the search.
                if (IsGoal(current))
                {
                    break;
                }

                foreach (Tile next in GetNeighbors(current))
                {
                    int newCost = costSoFar[current] + 1;
                    // We update or add the cost of the tile so far.
                    if (!costSoFar.ContainsKey(next) || newCost < costSoFar[next])
                    {
                        costSoFar[next] = newCost;
                        frontier.Enqueue(next, newCost);
                        cameFrom[next] = current;
                    }
                }
            }

            // We reconstruct the path the find the next tile to go on.
            int cost = costSoFar[cameFrom[current]] + 1;

            while (!current.Equals(currentTile))
            {
                last    = current;
                current = cameFrom[current];
            }

            return(Tuple.Create(last.Position, cost));
        }
Пример #5
0
        public static ISearchResult FindShortestPath(Point startingPoint, Point destinationPoint, Predicate <Point> isWalkable, Func <Point, Point, int> estimateH)
        {
            GuardAgainstUnwakableStartingPoint(startingPoint, isWalkable);

            // Bootstrap
            var startingNode = Node.CreateTheStartingNodeWith(startingPoint);
            var openList     = new SimplePriorityQueue <Point>();

            openList.Enqueue(startingPoint, 0);
            var nodesByPoint = new Dictionary <Point, Node> {
                { startingPoint, startingNode }
            };
            var closedSet = new HashSet <Point>();

            int EstimateHFromFor(Point point) => estimateH(point, destinationPoint);

            while (openList.Any())
            {
                var currentPoint = openList.Dequeue();
                var currentNode  = nodesByPoint[currentPoint];
                if (currentPoint.Equals(destinationPoint))
                {
                    return(FoundSolution.CreateSolutionFor(currentNode));
                }

                nodesByPoint.Remove(currentPoint);

                var availableAdjacentPoints = GetAvailableAdjacentPointsTo(currentPoint, isWalkable, closedSet);
                foreach (var adjacentPoint in availableAdjacentPoints)
                {
                    Node availableNode;
                    if (nodesByPoint.TryGetValue(adjacentPoint.Point, out availableNode))
                    {
                        availableNode.UpdateGiven(currentNode, adjacentPoint.FromParentMoveCost);
                        openList.UpdatePriority(adjacentPoint.Point, availableNode.F);
                    }
                    else
                    {
                        var h = EstimateHFromFor(adjacentPoint.Point);
                        availableNode = Node.CreateNodeWith(currentNode, adjacentPoint, h);
                        nodesByPoint.Add(adjacentPoint.Point, availableNode);
                        openList.Enqueue(adjacentPoint.Point, availableNode.F);
                    }
                }
                closedSet.Add(currentPoint);
            }
            return(new NotFoundSolution());
        }
Пример #6
0
        public static Stack <TileNode> Astar(TileGraph tg, TileNode start, TileNode end)
        {
            frontier = new SimplePriorityQueue <TileNode, float>();
            frontier.Enqueue(start, 0f);
            //node_dict = new Dictionary<TileNode, NodeInfo>();
            node_dict = DijkstraInitialDictLoad(start, tg);
            List <TileNode> Expanded = new List <TileNode>();

            TileNode v;
            TileNode other;
            float    cost_so_far;
            float    edge_weight;
            float    dist_to_node;
            float    manhattanDistance;

            while (frontier.Count > 0)
            {
                v           = frontier.Dequeue();
                cost_so_far = node_dict[v].dist;
                Expanded.Add(v);

                List <Edge> experiment = tg.getAdjacentEdges(v) as List <Edge>;
                foreach (Edge adj_edge in tg.getAdjacentEdges(v))
                {
                    other             = adj_edge.getNeighbor(v);
                    edge_weight       = adj_edge.weight;
                    dist_to_node      = node_dict[other].dist;
                    manhattanDistance = Mathf.Abs(end.transform.position.z - other.transform.position.z) + Mathf.Abs(end.transform.position.x - other.transform.position.x);

                    if (cost_so_far + edge_weight < dist_to_node)
                    {
                        node_dict[other].dist      = cost_so_far + edge_weight;
                        node_dict[other].heuristic = node_dict[other].dist + manhattanDistance;
                        node_dict[other].parent    = v;
                    }

                    if (!Expanded.Any(node => node.isEqual(other)) && !frontier.Any(node => node.isEqual(other)))
                    {
                        frontier.Enqueue(other, node_dict[other].heuristic);
                    }
                }
            }

            Path = NodeDictToPath(node_dict, start, end);

            return(Path);
        }
Пример #7
0
        public static Stack <TileNode> Dijkstra(TileGraph tg, TileNode start, TileNode end)
        {
            frontier = new SimplePriorityQueue <TileNode, float>();
            frontier.Enqueue(start, 0f);
            node_dict = DijkstraInitialDictLoad(start, tg);
            List <TileNode> Expanded = new List <TileNode>();

            TileNode v;
            TileNode other;
            float    edge_weight;
            float    dist_to_node;
            float    cost_so_far;

            while (frontier.Count > 0)
            {
                v           = frontier.Dequeue();
                cost_so_far = node_dict[v].dist;
                Expanded.Add(v);

                //List<Edge> experiment = tg.getAdjacentEdges(v) as List<Edge>;
                foreach (Edge adj_edge in tg.getAdjacentEdges(v))
                {
                    other        = adj_edge.getNeighbor(v);
                    edge_weight  = adj_edge.weight;
                    dist_to_node = node_dict[other].dist;
                    if (cost_so_far + edge_weight < dist_to_node)
                    {
                        node_dict[other].dist   = cost_so_far + edge_weight;
                        node_dict[other].parent = v;
                    }

                    if (!Expanded.Any(node => node.isEqual(other)) && !frontier.Any(node => node.isEqual(other)))
                    {
                        frontier.Enqueue(other, node_dict[other].dist);
                    }
                }
            }

            Path = NodeDictToPath(node_dict, start, end);

            return(Path);
        }
Пример #8
0
        public Dictionary <int, int> MainAlgorithm(int source)
        {
            SimplePriorityQueue <int> priorityQueue = new SimplePriorityQueue <int>();

            InitiateLenghts(source);
            priorityQueue.Enqueue(source, 0);
            while (priorityQueue.Any())
            {
                int operatedVertex = priorityQueue.First();
                priorityQueue.Dequeue();
                foreach (var item in calculatedGraph.vertices[operatedVertex].outgoingEdges)
                {
                    int newLenght = lenghts[operatedVertex] + item.Value;
                    if (lenghts[item.Key] > newLenght)
                    {
                        lenghts[item.Key] = newLenght;
                        priorityQueue.Enqueue(item.Key, newLenght);
                    }
                }
            }
            return(lenghts);
        }
Пример #9
0
 public bool Contains(Predicate <T> predicate)
 {
     return(_queue.Any(predicate.Invoke));
 }
Пример #10
0
        //for more info check video 92, 93, 94 in Mosh data-structure course part II
        public WeightedGraph GetMinSpanningTree()
        {
            // tree basically is a graph but without cycle (cycle links)
            var tree = new WeightedGraph();
            SimplePriorityQueue <Edge> edges = new SimplePriorityQueue <Edge>();

            if (Count == 0)
            {
                // if graph has zero nodes then return empty tree
                return(tree);
            }

            using (var nodesEnumerator = _nodes.Values.GetEnumerator())
            {
                if (!nodesEnumerator.MoveNext())
                {
                    return(tree);
                }

                var startNode = nodesEnumerator.Current;
                foreach (var edge in startNode.Edges)
                {
                    edges.Enqueue(edge, edge.Weight);
                }
                tree.AddNode(startNode.Label);

                if (!edges.Any())
                {
                    // if graph has no edges then return empty tree
                    return(tree);
                }

                while (tree.Count < Count)
                {
                    // we will get edge with min-weight
                    var minEdge  = edges.Dequeue();
                    var nextNode = minEdge.To;

                    if (tree.ContainsNode(nextNode.Label))
                    {
                        // if the edge is connected to existing node in min-spanning-tree
                        // then we skip it & pick the next minEdge
                        continue;
                    }

                    //we will add nextNode to tree
                    tree.AddNode(nextNode.Label);
                    tree.AddEdge(minEdge.From.Label, nextNode.Label, minEdge.Weight);

                    // add only connected Edges to "Edges" queue
                    foreach (var edge in nextNode.Edges)
                    {
                        // we only add connected-node if it is not added to min-spanning-tree before
                        if (!tree.ContainsNode(edge.To.Label))
                        {
                            edges.Enqueue(edge, edge.Weight);
                        }
                    }
                }
            }

            return(tree);
        }
Пример #11
0
 public override bool Empty()
 {
     return(!_queue.Any());
 }
Пример #12
0
        //There is no need to aggressively early exit for now, we are in no need for such optimization
        public static bool TryFindPath(Coordinate start,
                                       Coordinate goal,
                                       Map map,
                                       out IList <Coordinate> path,
                                       int maxCost = int.MaxValue,
                                       bool includeStartingTile = false)
        {
            var tileToDiscover = new SimplePriorityQueue <Coordinate, float>();
            var cameFrom       = new Dictionary <Coordinate, Coordinate>();
            var distanceToTile = new Dictionary <Coordinate, float> {
                [start] = 0f
            };

            tileToDiscover.Enqueue(start, Heuristic(start, goal));
            path = null;

            while (tileToDiscover.Any())
            {
                var current = tileToDiscover.Dequeue();
                if (current == goal)
                {
                    path = new List <Coordinate>();
                    while (current != start)
                    {
                        path.Add(current);
                        current = cameFrom[current];
                    }

                    //we ignore the starting tile when calculating the cost
                    var pathCost = path.Select(map.Get <Tile>).Sum(t => t.Data.Weight);
                    if (includeStartingTile)
                    {
                        path.Add(start);
                    }

                    path = path.Reverse().ToList();

                    return(pathCost <= maxCost);
                }

                foreach (var neighbour in map.GetNeighbours <Tile>(current).Values)
                {
                    if (neighbour == null)
                    {
                        //ignore tiles that does not exist(e.g. when current is at the top/bottom edge of the map)
                        continue;
                    }

                    var currentDistanceToNeighbour = distanceToTile[current] + neighbour.Data.Weight;
                    var neighbourCoordinate        = neighbour.Coordinate;
                    if (!distanceToTile.TryGetValue(neighbourCoordinate, out var previousDistanceToNeighbour))
                    {
                        previousDistanceToNeighbour = float.PositiveInfinity;
                    }

                    if (currentDistanceToNeighbour > previousDistanceToNeighbour)
                    {
                        continue;
                    }

                    var newScoreForNeighbour = currentDistanceToNeighbour + Heuristic(neighbourCoordinate, goal);
                    cameFrom[neighbourCoordinate]       = current;
                    distanceToTile[neighbourCoordinate] = currentDistanceToNeighbour;
                    if (!tileToDiscover.TryUpdatePriority(neighbourCoordinate, newScoreForNeighbour))
                    {
                        tileToDiscover.Enqueue(neighbourCoordinate, newScoreForNeighbour);
                    }
                }
            }

            return(false);
        }
Пример #13
0
    public void Update()
    {
        UpdateAttack();
        UpdateMovement();

        void UpdateWeapon()
        {
            if (weapon == null || !actor.Inventory.Contains(weapon) || weapon.Gun.AmmoLeft + weapon.Gun.ClipLeft == 0)
            {
                weapon = actor.Inventory.FirstOrDefault(i => i.Gun != null && i.Gun.AmmoLeft + i.Gun.ClipLeft > 0);
            }
        }

        void UpdateAttack()
        {
            if (attack == null || attack.Done())
            {
                UpdateWeapon();
                if (weapon == null)
                {
                    return;
                }
                var enemies = new HashSet <Entity>();
                foreach (var point in actor.World.entities.space.Keys)
                {
                    if (((XYZ)point - actor.Position).Magnitude < 100)
                    {
                        enemies.UnionWith(actor.World.entities[point].OfType <ICharacter>());
                    }
                }
                enemies.Remove(actor);
                enemies = enemies.Where(e => (e.Position - actor.Position).Magnitude < weapon.Gun.range).ToHashSet();
                if (enemies.Any())
                {
                    var target = enemies.First();
                    attack = new ShootAction(actor, weapon, new TargetEntity(target));
                    actor.Actions.Add(attack);
                }
            }
        }

        void UpdateMovement()
        {
            if (movement == null || movement.Done())
            {
                UpdateWeapon();
                if (weapon == null)
                {
                    var weapons = new HashSet <IItem>();
                    foreach (var point in actor.World.entities.space.Keys)
                    {
                        if (((XYZ)point - actor.Position).Magnitude < 100)
                        {
                            weapons.UnionWith(actor.World.entities[point].OfType <IItem>());
                        }
                    }
                    if (!weapons.Any())
                    {
                        UpdateWander();
                        return;
                    }
                    var target = weapons.OrderBy(w => (w.Position - actor.Position).Magnitude2).First();

                    Dictionary <(int, int, int), (int, int, int)> prev = new Dictionary <(int, int, int), (int, int, int)>();
                    var points = new SimplePriorityQueue <XYZ, double>();
                    //Truncate to integer coordinates so we don't get confused by floats
                    (int, int, int)start    = target.Position.i;
                    (int, int, int)actorPos = actor.Position.i;
                    prev[start]             = start;
                    points.Enqueue(start, 0);
                    int  seen    = 0;
                    bool success = false;
                    while (points.Any() && seen < 500 && !success)
                    {
                        var point = points.Dequeue();

                        foreach (var offset in new XYZ[] { new XYZ(0, 1), new XYZ(1, 0), new XYZ(0, -1), new XYZ(-1, 0) })
                        {
                            var next = point + offset;
                            if (prev.ContainsKey(next))
                            {
                                continue;
                            }
                            else if (CanOccupy(next))
                            {
                                prev[next] = point;
                                //Truncate to integer coordinates so we don't get confused by floats
                                if (next.Equals(actorPos))
                                {
                                    success = true;
                                    break;
                                }
                                else
                                {
                                    points.Enqueue(next, (next - actorPos).Magnitude);
                                }
                            }
                        }
                    }

                    if (success)
                    {
                        LinkedList <XYZ> path = new LinkedList <XYZ>();

                        XYZ p = prev[actor.Position];
                        path.AddLast(p);
                        while (!p.Equals(start))
                        {
                            p = prev[p];
                            path.AddLast(p);
                        }

                        movement = new CompoundAction(new FollowPath(actor, path), new TakeItem(actor, target));
                        actor.Actions.Add(movement);
                    }
                    else
                    {
                        UpdateWander();
                    }
                }
                else
                {
                    UpdateWander();
                }
            }
        }

        void UpdateWander()
        {
            HashSet <(int, int, int)> known               = new HashSet <(int, int, int)>();
            HashSet <XYZ>             accessible          = new HashSet <XYZ>();
            Dictionary <(int, int, int), (XYZ, int)> prev = new Dictionary <(int, int, int), (XYZ, int)>();
            Queue <XYZ> points = new Queue <XYZ>();

            var start = actor.Position.i;

            points.Enqueue(start);
            prev[start] = (null, 0);
            int seen = 0;

            while (points.Count > 0 && seen < 500)
            {
                var point = points.Dequeue().i;
                known.Add(point);
                seen++;
                if (CanOccupy(point))
                {
                    accessible.Add(point);
                    foreach (var offset in new XYZ[] { new XYZ(0, 1), new XYZ(1, 0), new XYZ(0, -1), new XYZ(-1, 0) })
                    {
                        var next = point + offset;
                        var dist = prev[point].Item2 + 1;
                        if (known.Add(next))
                        {
                            prev[next] = (point, dist);
                            points.Enqueue(next);
                        }
                        else if (prev.TryGetValue(next, out (XYZ, int)v) && v.Item2 > dist)
                        {
                            prev[next] = (point, dist);
                        }
                    }
                }
            }

            var dest = accessible.OrderByDescending(xyz => (actor.Position - xyz).Magnitude2).ElementAt(new Random().Next(0, 4));
            var path = new LinkedList <XYZ>();

            while (dest != null)
            {
                path.AddFirst(dest);
                XYZ next;
                (next, _) = prev[dest];
                dest      = next;
            }
            movement = new FollowPath(actor, path);
            actor.Actions.Add(movement);
        }

        bool CanOccupy(XYZ position)
        {
            var v     = actor.World.voxels.Try(position);
            var below = actor.World.voxels.Try(position.PlusZ(-1));

            return(v is Air || v is Floor || below?.Collision == VoxelType.Solid);
        }
    }