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)); }
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"]); }
// 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); }
/// <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)); }
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()); }
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); }
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); }
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); }
public bool Contains(Predicate <T> predicate) { return(_queue.Any(predicate.Invoke)); }
//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); }
public override bool Empty() { return(!_queue.Any()); }
//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); }
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); } }