/// <summary> /// Constructor for single object name, or for object path /// </summary> /// <remarks> /// Unity object naming is unrestricted. In particular: /// - Names can be repeated. /// - Names can include the path separator character '/'. /// - Names can be empty. /// Consequently, a PathName is not guaranteed to uniquely identify a GameObject /// Paths are relative to a specified GameObject, so the name /// argument must begin and end with GameObject names. /// - name = "" matches "" which is a root GameObject /// - name = "/" matches "" which is a child of "" /// - name = "/" also matches "/" which is a root GameObject /// </remarks> public PathName(string name, PathStep.Step type = PathStep.Step.Path) { var step = new PathStep(name, type); path = new List <PathStep>(); path.Add(step); }
public PathStep(T data, float gScore = 0, float hScore = 0, PathStep <T> parent = null) { this.data = data; this.gCost = gScore; this.hCost = hScore; this.parent = parent; }
public bool MoveMob( Point3d targetPosition) { bool success = false; if (path == null) { PathComputer pathComputer = new PathComputer(); success = pathComputer.BlockingPathRequest( moveRequest.Room.runtime_nav_mesh, moveRequest.Room.room_key, new Point3d(mob.Position), new Point3d(targetPosition)); if (success) { RoomKey roomKey = moveRequest.Room.room_key; PathStep lastPathStep = pathComputer.FinalPath[pathComputer.FinalPath.Count - 1]; PathStep secondLastPathStep = pathComputer.FinalPath[pathComputer.FinalPath.Count - 2]; Vector3d lastPathHeading = lastPathStep.StepPoint - secondLastPathStep.StepPoint; float targetAngle = MathConstants.GetAngleForVector(lastPathHeading); path = new EntityPath() { entity_id = mob.ID, path = pathComputer.FinalPath }; // Post an event that we moved output_game_events.Add( new GameEvent_MobMoved() { mob_id = mob.ID, room_x = roomKey.x, room_y = roomKey.y, room_z = roomKey.z, from_x = mob.Position.x, from_y = mob.Position.y, from_z = mob.Position.z, from_angle = mob.Angle, to_x = targetPosition.x, to_y = targetPosition.y, to_z = targetPosition.z, to_angle = targetAngle }); // Update the mob position and facing mob.Position = targetPosition; mob.Angle = targetAngle; // TODO: Update the mob energy based on the distance traveled } } return(success); }
public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) { return(false); } PathStep <T> other = (PathStep <T>)obj; return(data.Equals(other.data)); }
/* Inserts step into list at its sorted position. list is sorted by ascending fScore's. */ void InsertPathStep(PathStep <Cell> step, List <PathStep <Cell> > list) { int i = 0; for (; i < list.Count; ++i) { if (step.fCost <= list[i].fCost) { break; } } list.Insert(i, step); }
private void SelectRowForStep(PathStep step) { Invoke(new Action(() => { foreach (DataGridViewRow r in dataGridView1.Rows) { if (r.DataBoundItem == step) { dataGridView1.CurrentCell = r.Cells[0]; } } })); }
/// <summary> /// Constructor for object path /// </summary> /// <param name="rootObject">Path ends when root object is reached</param> public PathName(GameObject gameObject, GameObject rootObject = null) { path = new List <PathStep>(); Transform parent = gameObject.transform; while (parent && parent != rootObject?.transform) { var step = new PathStep(parent.name, PathStep.Step.Name); path.Add(step); parent = parent.parent; } path.Reverse(); }
public List <PathStep> GetPathsGraph(Vector2Int from) { List <PathStep> pathsGraph = new List <PathStep>(); PathStep start = new PathStep { pos = from, reach = new List <PathStep>() }; pathsGraph.Add(start); BuildPathsGraphFrom(ref start, ref pathsGraph, new Vector2Int(-1, -1)); return(pathsGraph); }
/// <summary> /// A* algorithm that traverses the graph to find shortest path between set vertices /// </summary> /// <param name="graph"> <see cref="Graph"/> instance. </param> /// <param name="startVertex"> The start <see cref="Vertex"/> of path to calculate minimum distance for. </param> /// <param name="endVertex"> The end <see cref="Vertex"/> of path to calculate minimum distance for. </param> /// <returns> The shortest (minimum cost) path from starting point to ending point. </returns> public Pathway <T> FindPath(IAdjacencyMatrix <T> graph, Vertex <T> start, Vertex <T> target) { /// System.Collections.Generic.SortedList by default does not allow duplicate items. /// Since items are keyed by TotalCost there can be duplicate entries per key. var priorityComparer = Comparer <int> .Create((x, y) => (x <= y)? -1 : 1); var opened = new PriorityQueue <int, Vertex <T> >(priorityComparer); var visited = new PriorityQueue <int, Vertex <T> >(priorityComparer); var path = new Dictionary <Vertex <T>, PathStep <T> >(); // Resets the AStar algorithm with the newly specified start node and goal node. var current = start; int estimatedDistance = _distanceMesureable.MesureDistance(start, target); path[start] = new PathStep <T>(start, null, 0, estimatedDistance); opened.Enqueue(path[start].TotalCost, start); // Continue searching until either failure or the goal node has been found. AlgorithmState state = AlgorithmState.Searching; while (state == AlgorithmState.Searching) { current = GetNext(opened, visited); if (current == null) { state = AlgorithmState.PathDoesNotExist; break; } // Remove from the open list and place on the closed list // since this node is now being searched. visited.Enqueue(path[current].TotalCost, current); // Found the goal, stop searching. if (current.Equals(target)) { state = AlgorithmState.PathFound; break; } ExtendOpened(opened, visited, current, target, path); } ICollection <Vertex <T> > vertices = ReconstructPath(current, path); int totalDistance = current != null && path.ContainsKey(current) ? path[current].MovementCost : 0; return(new Pathway <T>(vertices, totalDistance, state)); }
//this is main function of pathStep, which spawn inumerable objects around if there are no walls in the vicinity //the spawned objects will go on doing the same thing until one of their location is next to the player //along with each object is a string that show how to get to the starting point to its position IEnumerable SmallStep() { if (this.transform.position == pathManager.Destination()) { pathManager.WayIsFound(theWay); iFindTheWay = true; } wallCheckUp = Physics2D.Linecast(this.transform.position, new Vector3(this.transform.position.x, this.transform.position.y + 1, 0), wall); wallCheckDown = Physics2D.Linecast(this.transform.position, new Vector3(this.transform.position.x, this.transform.position.y - 1, 0), wall); wallCheckLeft = Physics2D.Linecast(this.transform.position, new Vector3(this.transform.position.x - 1, this.transform.position.y, 0), wall); wallCheckRight = Physics2D.Linecast(this.transform.position, new Vector3(this.transform.position.x + 1, this.transform.position.y, 0), wall); if (wallCheckLeft.collider == null) { stepLeft = Instantiate(step, new Vector3(this.transform.position.x - 1, this.transform.position.y, 0), Quaternion.Euler(new Vector3(0, 0, 0)), pathManager.transform) as PathStep; stepLeft.theWay = this.theWay + "a;"; stepLeft.gameObject.SetActive(true); theWay = rememberTheWay; } if (wallCheckUp.collider == null) { //stepUp = new PathStep(); stepUp = Instantiate(step, new Vector3(this.transform.position.x, this.transform.position.y + 1, 0), Quaternion.Euler(new Vector3(0, 0, 0)), pathManager.transform) as PathStep; stepUp.theWay = this.theWay + "w;"; stepUp.gameObject.SetActive(true); theWay = rememberTheWay; } if (wallCheckDown.collider == null) { //stepDown = new PathStep(); stepDown = Instantiate(step, new Vector3(this.transform.position.x, this.transform.position.y - 1, 0), Quaternion.Euler(new Vector3(0, 0, 0)), pathManager.transform) as PathStep; stepDown.theWay = this.theWay + "s;"; stepDown.gameObject.SetActive(true); theWay = rememberTheWay; } if (wallCheckRight.collider == null) { // stepRight = new PathStep(); stepRight = Instantiate(step, new Vector3(this.transform.position.x + 1, this.transform.position.y, 0), Quaternion.Euler(new Vector3(0, 0, 0)), pathManager.transform) as PathStep; stepRight.theWay = this.theWay + "d;"; stepRight.gameObject.SetActive(true); theWay = rememberTheWay; } return(null); }
public List <DijkstraStep> GetSubGraph(Vector2Int from, List <PathStep> graph) { // SubGraph and a copy to keep track of processed elements List <DijkstraStep> subGraph = new List <DijkstraStep>(); List <DijkstraStep> unprocessed = new List <DijkstraStep>(); // Subgraphes initialization foreach (PathStep step in graph) { DijkstraStep ds = new DijkstraStep { pathStep = step, weight = (step.pos == from) ? 0 : int.MaxValue, prev = null }; subGraph.Add(ds); unprocessed.Add(ds); } // Computes subgraph values: shorter distances, previous element while (unprocessed.Count > 0) { DijkstraStep current = new DijkstraStep { pathStep = null, prev = null, weight = int.MaxValue }; foreach (DijkstraStep ds in unprocessed) { if (ds.weight < current.weight) { current = ds; } } foreach (PathStep next in current.pathStep.reach) { DijkstraStep dijkstraNext = subGraph.Find(n => n.pathStep == next); if (dijkstraNext.weight > current.weight + PathStep.Distance(current.pathStep, dijkstraNext.pathStep)) { dijkstraNext.weight = current.weight + PathStep.Distance(current.pathStep, dijkstraNext.pathStep); dijkstraNext.prev = current; } } unprocessed.Remove(current); } return(subGraph); }
private void AddPathSteps(char[][] maze, PathStep currentStep) { // checks for all possible moves of the currentStep foreach (var move in _possibleMoves) { var nextX = currentStep.X + move[0]; var nextY = currentStep.Y + move[1]; if (IsValidPathStep(maze, currentStep.Y, nextX, nextY)) { // adds the next step to _pathQueue while retaining the currentStep as part of the next step and set as visited var nextStep = new PathStep { X = nextX, Y = nextY, PreviousStep = currentStep }; _pathQueue.Enqueue(nextStep); _visitedPaths[nextY, nextX] = true; } } }
private char[][] GetSolvedMaze(char[][] maze, PathStep currentStep) { _totalMazeSteps = 0; // loops through all previous steps totaling all maze steps // and adding @ symbol to designate the completed path through the maze. do { _totalMazeSteps++; currentStep = currentStep.PreviousStep; if (maze[currentStep.Y][currentStep.X] != 'A') { maze[currentStep.Y][currentStep.X] = '@'; } } while (currentStep.PreviousStep != null); return(maze); }
private static object SlowGetMemberValue(PathStep step, object instance) { switch (step.StepType) { case PathStepType.Member: { FieldInfo field = step.Member as FieldInfo; if (field != null) { if (field.IsLiteral) { return(field.GetRawConstantValue()); } return(field.GetValue(instance)); } PropertyInfo prop = step.Member as PropertyInfo; if (prop != null) { return(prop.GetValue(instance, null)); } MethodInfo method = step.Member as MethodInfo; if (method != null) { return(method.Invoke(instance, null)); } throw new NotSupportedException(step.Member.GetType().GetNiceName()); } case PathStepType.WeakListElement: return(WeakListGetItem.Invoke(instance, new object[] { step.ElementIndex })); case PathStepType.ArrayElement: return((instance as Array).GetValue(step.ElementIndex)); case PathStepType.StrongListElement: return(step.StrongListGetItemMethod.Invoke(instance, new object[] { step.ElementIndex })); default: throw new NotImplementedException(step.StepType.ToString()); } }
private void BuildPathsGraphFrom(ref PathStep from, ref List <PathStep> pathsGraph, Vector2Int previousPos) { List <Vector2Int> reachablePositions = FindReachExcluding(from.pos, previousPos); foreach (Vector2Int position in reachablePositions) { PathStep nextStep = pathsGraph.Find(p => p.pos == position); if (nextStep == null) { nextStep = new PathStep { pos = position, reach = new List <PathStep>() }; pathsGraph.Add(nextStep); BuildPathsGraphFrom(ref nextStep, ref pathsGraph, from.pos); } from.reach.Add(nextStep); } }
private void ExtendOpened( PriorityQueue <int, Vertex <T> > opened, PriorityQueue <int, Vertex <T> > visited, Vertex <T> current, Vertex <T> target, Dictionary <Vertex <T>, PathStep <T> > path) { foreach (var neighbor in current.Neighbors) { // If the child has already been visited (closed list) or is on // the open list to be searched then do not modify its movement cost // or estimated cost since they have already been set previously. if (!visited.ContainsValue(neighbor) && !opened.ContainsValue(neighbor)) { // Each child needs to have its movement cost set and estimated cost. int estimatedDistance = _distanceMesureable.MesureDistance(neighbor, target); path[neighbor] = new PathStep <T>(neighbor, current, path[current].MovementCost, estimatedDistance); opened.Enqueue(path[neighbor].TotalCost, neighbor); } } }
private char[][] GetMazeSolution(char[][] maze) { _pathQueue.Enqueue(new PathStep { X = _startingStep[0], Y = _startingStep[1] }); while (_pathQueue.Count > 0) { PathStep currentStep = _pathQueue.Dequeue(); if (currentStep.X == _endStep[0] && currentStep.Y == _endStep[1]) { // returns array that represents the solved maze return(GetSolvedMaze(maze, currentStep)); } AddPathSteps(maze, currentStep); } return(maze); }
private static void SlowSetMemberValue(PathStep step, object instance, object value) { switch (step.StepType) { case PathStepType.Member: { FieldInfo field = step.Member as FieldInfo; if (field != null) { field.SetValue(instance, value); break; } PropertyInfo prop = step.Member as PropertyInfo; if (prop != null) { prop.SetValue(instance, value, null); break; } throw new NotSupportedException(step.Member.GetType().GetNiceName()); } case PathStepType.WeakListElement: WeakListSetItem.Invoke(instance, new object[] { step.ElementIndex, value }); break; case PathStepType.ArrayElement: (instance as Array).SetValue(value, step.ElementIndex); break; case PathStepType.StrongListElement: var setItemMethod = typeof(IList <>).MakeGenericType(step.ElementType).GetMethod("set_Item"); setItemMethod.Invoke(instance, new object[] { step.ElementIndex, value }); break; default: throw new NotImplementedException(step.StepType.ToString()); } }
public List <Vector2Int> FindShorterPathFromTo(Vector2Int from, Vector2Int to, List <PathStep> graph) { // Find from and end postitions in graph PathStep start = null, end = null; if (graph != null) { start = graph.Find(step => step.pos == from); end = graph.Find(step => step.pos == to); } if (graph == null || start == null || end == null) { Debug.Log("No path!"); return(null); } // Output initialization List <Vector2Int> path = new List <Vector2Int>(); // Build Subgraph List <DijkstraStep> subGraph = GetSubGraph(from, graph); // Retrieves shorter path step by step, from end to start DijkstraStep shortestPathStep = subGraph.Find(s => s.pathStep == end); while (shortestPathStep.pathStep != start) { path.Add(shortestPathStep.pathStep.pos); shortestPathStep = shortestPathStep.prev; } path.Add(start.pos); // Revert path so it's from start to end path.Reverse(); return(path); }
public static bool GetPath(Vec2I StartPos, Vec2I EndPos, int maxDistance, out Vec2I[] path) { if (StartPos == EndPos) { path = new Vec2I[1]; path[0] = EndPos; return(true); } path = null; if (Vec2I.Max(StartPos, EndPos) > maxDistance) { return(false); } if (Heatmap.GetNode(EndPos) == null) { return(false); } HeatmapNode startNode = Heatmap.GetNode(StartPos); if (startNode == null) { return(false); } //init arrays int arraySize = maxDistance * 2 + 1; bool[,] closedCheck = new bool[arraySize, arraySize]; bool[,] openCheck = new bool[arraySize, arraySize]; Vec2I[,] parent = new Vec2I[arraySize, arraySize]; PathStep[,] openArray = new PathStep[arraySize, arraySize]; //set start point BinaryHeap <PathStep> openList = new BinaryHeap <PathStep>(arraySize * arraySize); openList.Add(new PathStep(startNode, Heuristic(StartPos, EndPos))); openCheck[maxDistance, maxDistance] = true; parent[maxDistance, maxDistance] = StartPos; bool found = false; while (openList.ItemCount > 0) { //get top of heap PathStep current = openList.RemoveFirst(); int cx = current.node.gridPos.x - StartPos.x + maxDistance; int cy = current.node.gridPos.y - StartPos.y + maxDistance; closedCheck[cx, cy] = true; foreach (HeatmapNode neighbor in current.node.neighbors) { //calculate array position int nx = neighbor.gridPos.x - StartPos.x + maxDistance; int ny = neighbor.gridPos.y - StartPos.y + maxDistance; //cull disallowed if (Vec2I.Max(neighbor.gridPos, StartPos) > maxDistance) { continue; } if (closedCheck[nx, ny]) { continue; } if (!CanTravel(current.node, neighbor)) { continue; } //found target if (neighbor.gridPos == EndPos) { parent[nx, ny] = current.node.gridPos; found = true; goto finalize; } //calculate cost int travelCost = current.travelCost + TravelCostAstar(current.node, neighbor); int heuristic = Heuristic(neighbor.gridPos, EndPos); int fullCost = travelCost + heuristic; //check if we can update parent to better if (openCheck[nx, ny]) { if (openArray[nx, ny].fullCost > fullCost) { openArray[nx, ny].travelCost = travelCost; openArray[nx, ny].heuristic = heuristic; openArray[nx, ny].fullCost = fullCost; parent[nx, ny] = current.node.gridPos; openList.UpdateItem(openArray[nx, ny]); continue; } else { continue; } } //priority sorted by heap PathStep step = new PathStep(neighbor, travelCost, heuristic); openList.Add(step); openArray[nx, ny] = step; openCheck[nx, ny] = true; parent[nx, ny] = current.node.gridPos; } } finalize: if (found) { SingleLinkedList <Vec2I> list = new SingleLinkedList <Vec2I>(); Vec2I current = EndPos; while (current != StartPos) { list.InsertFront(current); current = parent[current.x - StartPos.x + maxDistance, current.y - StartPos.y + maxDistance]; } list.InsertFront(current); //adds the starting point to the path path = list.ToArray(); return(true); } return(false); }
public override void IterateOpenSet() { //Track how many iterations have taken place to find this pathway OpenSetIterations++; //Once the openset has been exhausted its time to complete the pathway if (OpenSet.Count <= 0) { //Get the completed pathway List <Node> Pathway = GridManager.Instance.GetCompletedPathway(PathStart, PathEnd); //If the path is empty, then no pathway was able to be found between the target nodes if (Pathway == null) { //Print a failure message and reset the grid Log.Print("Unable to find a valid pathway using Dijkstras algorithm."); FindingPathway = false; GridManager.Instance.HideAllParentIndicators(); return; } //Announce the pathway has been found Log.Print("Dijkstras pathfinding completed after " + OpenSetIterations + " iterations."); //Hide all the neighbour indicators GridManager.Instance.HideAllParentIndicators(); //Change the type of all nodes in the pathway to display it in the game foreach (Node PathStep in Pathway) { PathStep.SetType(NodeType.Pathway); } //Complete the process FindingPathway = false; return; } //Find the new current node, then iterate through all its neighbours Node Current = GridManager.Instance.FindCheapestNode(OpenSet); OpenSet.Remove(Current); foreach (Node Neighbour in GridManager.Instance.GetTraversableNeighbours(Current)) { //Ignore nodes not listed in the open set if (!OpenSet.Contains(Neighbour)) { continue; } //check if its cheaper to travel over this neighbour float NeighbourCost = Current.FScore + GridManager.FindHeuristic(Current, Neighbour); if (NeighbourCost < Neighbour.FScore) { //update this neighbour as the best way to travel Neighbour.FScore = NeighbourCost; Neighbour.Parent = Current; Neighbour.ToggleParentIndicator(true); Neighbour.PointIndicator(Neighbour.GetDirection(Current)); } } }
private static bool AreEqual(PathStep first, PathStep second) { return(first.Equals(second)); // PathStep is a struct }
//AI Algorithm to create a path between and around impassible objects using OccupiedGrid as a reference //and then converting it to world space thanks to GridDimension //Takes a point (x and y) for start and destination //point is declared in PathStep.cs, along with the constructor for PathStep //Called by GuardBrain.cs //Realistically, you almost never need to do this and you could just use Unity's Navmesh tools to do this in like 2 lines of code. //This is also extremely resource intensive and the game will noticably hitch everytime you call this function. //But because Unity2d is basically incomplete, we have no choice public List <point> GeneratePath(point start, point destination) { //Create a queue of points for GuardBrain to test for navigation Queue <PathStep> unVisited = new Queue <PathStep>(); //When points are processed by unVisited, it gets added to visited List <point> Visited = new List <point>(); //Start by Enqueuing (Putting into the end of the queue) the start position unVisited.Enqueue(new PathStep(start, null)); //When every point on the path has been checked, Unvisited will be equal to 0 and and leave the while loop while (unVisited.Count > 0) { //Start by removing the first item from unVisited and putting into a temp PathStep. //This increments the while and lets us work with its value easier PathStep thisStep = unVisited.Dequeue(); //Check if the point we're testing is our destination. If it is, finalize the path and pass it along to GuardBrain if (thisStep.position.Equals(destination)) { //Create a list of the points used to reach the destination. //Because we used a queue starting from the start, when things get put into this list, they'll start from the destination instead List <point> path = new List <point>(); //Create a holder for our last step PathStep cur = thisStep; //add the first item to our path path.Add(cur.position); //Each PathStep also holds the data for the step it took before that. //This allows us to work our way backwards through where we've been to figure out where we need to go //This while loop keeps checking the previous step until it gets to a PathStep that doesn't have a previous step //This is the first step, and it means our path is built. while (cur.previous != null) { //switch which PathStep we're working with cur = cur.previous; //Add it to the path path.Add(cur.position); } //Once we have all our points, we can reverse the path so the start is now first and the AI can go through them properly. path.Reverse(); //Send the path to the object that caled this function. return(path); } //Until we have our destination, we need to try the squares above, below, to the right, and to the left of this //try-catch lets you do something that may crash the game, and when it would crash, simply doesn't do it and runs whatever is in catch instead //In this case, we're doing it to prevent an ArrayOutOfBounds if we try to check a point that doesn't exist (Like if we're on the top row and try to check the row above us) try { //x-1 would be the step to the left of our current one, for example. if (!OccupiedGrid[thisStep.position.x - 1, thisStep.position.y]) { //If the grid space isn't occupied, it checks to make usre we haven't already checed that space, and if we haven't... if (!Visited.Contains(new point(thisStep.position.x - 1, thisStep.position.y))) { //...it enqueues it for unVisited. unVisited.Enqueue(new PathStep(new point(thisStep.position.x - 1, thisStep.position.y), thisStep)); } } }catch { } try { if (!OccupiedGrid[thisStep.position.x + 1, thisStep.position.y]) { if (!Visited.Contains(new point(thisStep.position.x + 1, thisStep.position.y))) { unVisited.Enqueue(new PathStep(new point(thisStep.position.x + 1, thisStep.position.y), thisStep)); } } } catch { } try { if (!OccupiedGrid[thisStep.position.x, thisStep.position.y - 1]) { if (!Visited.Contains(new point(thisStep.position.x, thisStep.position.y - 1))) { unVisited.Enqueue(new PathStep(new point(thisStep.position.x, thisStep.position.y - 1), thisStep)); } } } catch { } try { if (!OccupiedGrid[thisStep.position.x, thisStep.position.y + 1]) { if (!Visited.Contains(new point(thisStep.position.x, thisStep.position.y + 1))) { unVisited.Enqueue(new PathStep(new point(thisStep.position.x, thisStep.position.y + 1), thisStep)); } } } catch { } } //If no path could be found, return null to avoid crashing anything return(null); }
void CreatePath(Cell origin, Cell destination) { List <PathStep <Cell> > openSteps = new List <PathStep <Cell> >(); HashSet <PathStep <Cell> > closedSteps = new HashSet <PathStep <Cell> >(); openSteps.Add(new PathStep <Cell>(origin)); do { // Pop the next step in openSteps PathStep <Cell> curStep = openSteps.First(); Cell curCell = curStep.data; openSteps.RemoveAt(0); closedSteps.Add(curStep); // Destination reached, carve the path. if (curStep.data.Equals(destination)) { do { if (curStep.parent != null) { curCell = curStep.data; curCell.Empty(); } curStep = curStep.parent; } while (curStep != null); return; } List <Cell> adjacentCells = GetAdjacentCells(curCell); // Perform A* search to find shortest path. foreach (Cell adjCell in adjacentCells) { PathStep <Cell> step = new PathStep <Cell>(adjCell); Cell stepCell = step.data; // Only proceed if the nextStep is not already in the closedSteps. if (!closedSteps.Contains(step)) { float moveCost = GetCostForStep(curCell, stepCell); step.parent = curStep; step.gCost = curStep.gCost + moveCost; // Check if the nextStep is already in the openSteps int stepIndex = openSteps.IndexOf(step); // nextStep is not in openSteps, so add it. if (stepIndex == -1) { step.hCost = GetCostForStep(stepCell, destination); InsertPathStep(step, openSteps); } // nextStep is already in openSteps, so update its score. else { // If the current path gives nextStep a better gScore than its existing // gScore, remove the existing and insert step. if (curStep.gCost + moveCost < openSteps[stepIndex].gCost) { step.hCost = openSteps[stepIndex].hCost; openSteps.RemoveAt(stepIndex); InsertPathStep(step, openSteps); } } } } } while (openSteps.Count > 0); }
private void UpdateAIPropVisibility( MobUpdateContext context) { Mob ownerMob = context.mob; NavMesh navMesh = context.moveRequest.Room.runtime_nav_mesh; foreach (EntityProp prop in ai_props) { Point3d oldPropPosition = prop.GetPosition(); // Find the player associated with the player id MobUpdateContext otherMobContext = context.moveRequest.MobContexts.Find(m => m.mob.ID == prop.target_object_id); Mob otherMob = otherMobContext.mob; // Can the mob see the other mob at their current location bool canSee = CanMobSeePoint(navMesh, ownerMob, otherMob.Position); TypedFlags <EntityProp.ePropVisibilityFlags> oldVisibilityFlags = new TypedFlags <EntityProp.ePropVisibilityFlags>(prop.visibilityFlags); prop.visibilityFlags.Set(EntityProp.ePropVisibilityFlags.canSee, canSee); prop.visibilityFlags.Set(EntityProp.ePropVisibilityFlags.caughtGlimpse, canSee); if (canSee) { // If so, we get to pull the entity properties prop.RefeshEntityProperties(ownerMob, otherMob); prop.visibilityFlags.Set(EntityProp.ePropVisibilityFlags.seenAtLeastOnce, true); } else { EntityPath entityPath = otherMobContext.path; if (entityPath != null) { // Find the last place we saw the player along their path, if at all for (int pathStepIndex = entityPath.path.Count - 1; pathStepIndex >= 0; pathStepIndex--) { PathStep pathStep = entityPath.path[pathStepIndex]; if (CanMobSeePoint(navMesh, ownerMob, pathStep.StepPoint)) { prop.position_x = pathStep.StepPoint.x; prop.position_y = pathStep.StepPoint.y; prop.position_z = pathStep.StepPoint.z; prop.visibilityFlags.Set(EntityProp.ePropVisibilityFlags.caughtGlimpse, true); prop.visibilityFlags.Set(EntityProp.ePropVisibilityFlags.seenAtLeastOnce, true); break; } } } } // Post an event if we just spotted another mob that we've never seen before if (!oldVisibilityFlags.Test(EntityProp.ePropVisibilityFlags.canSee) && !oldVisibilityFlags.Test(EntityProp.ePropVisibilityFlags.seenAtLeastOnce) && (prop.visibilityFlags.Test(EntityProp.ePropVisibilityFlags.canSee) || prop.visibilityFlags.Test(EntityProp.ePropVisibilityFlags.caughtGlimpse))) { context.output_game_events.Add( new GameEvent_MobAIPropSpotted() { mob_id = ownerMob.ID, spotted_mob_id = prop.target_object_id, x = prop.position_x, y = prop.position_y, z = prop.position_z }); } } }
public override void IterateOpenSet() { //Track how many times the open set has been iterated over OpenSetIterations++; //If the open set is empty, then no pathway could be found if (OpenSet.Count <= 0) { //Print a failure message and reset the grid Log.Print("Unable to find a valid pathway using Theta* algorithm, after a total " + OpenSetIterations + " iterations."); FindingPathway = false; GridManager.Instance.HideAllParentIndicators(); return; } //Grab the node from open set with the lowest FScore value, move it from the OpenSet to the ClosedSet Node Current = GridManager.Instance.FindCheapestNode(OpenSet); OpenSet.Remove(Current); ClosedSet.Add(Current); //If the Current node is the EndNode, then the pathway has been found if (Current == PathEnd) { //Announce the pathway has been found Log.Print("Theta* pathfinding complete after " + OpenSetIterations + " iterations."); //Hide all nodes parent indicators GridManager.Instance.HideAllParentIndicators(); //Get the completed pathway List <Node> FinalPathway = GridManager.Instance.GetCompletedPathway(PathStart, PathEnd); //Change all pathway node types so the completed pathway is displayed foreach (Node PathStep in FinalPathway) { PathStep.SetType(NodeType.Pathway); } //Finalize the pathfinding process FindingPathway = false; return; } //Go through all the current nodes neighbours foreach (Node Neighbour in GridManager.Instance.GetTraversableNeighbours(Current)) { //Ignore neighbours in the closed list if (ClosedSet.Contains(Neighbour)) { continue; } if (!OpenSet.Contains(Neighbour)) { Neighbour.GScore = Mathf.Infinity; Neighbour.Parent = null; } UpdateNode(Current, Neighbour); } }
private AssertionContext ProcessPathPartWithWildcardForArId(AssertionContext contextObj, PathStep pathStep) { DesignByContract.Check.Require(pathStep.Attribute == "//*", "anyAttribute value must be //*."); Locatable locatable = contextObj.Data as Locatable; if (locatable != null) { ArchetypedPathProcessor archetypePathProcessor = new ArchetypedPathProcessor(locatable); string archetypePathWithWildcardKey = null; if (!string.IsNullOrEmpty(pathStep.ArchetypeNodeId)) archetypePathWithWildcardKey = pathStep.Attribute + "[" + pathStep.ArchetypeNodeId + "]"; else if (!string.IsNullOrEmpty(pathStep.NodePattern)) archetypePathWithWildcardKey = pathStep.Attribute + "[{/" + pathStep.NodePattern + "/}]"; else throw new NotSupportedException(pathStep.Value+" path not supported"); object obj = null; if (!archetypePathProcessor.PathExists(archetypePathWithWildcardKey)) return null; if (archetypePathProcessor.PathUnique(archetypePathWithWildcardKey)) obj = archetypePathProcessor.ItemAtPath(archetypePathWithWildcardKey); else obj = archetypePathProcessor.ItemsAtPath(archetypePathWithWildcardKey); if (obj == null) throw new ApplicationException("obj must not be null."); return new AssertionContext(obj, contextObj); } AssumedTypes.IList ilist = contextObj.Data as AssumedTypes.IList; if (ilist == null) throw new ApplicationException("only support either locatable or ilist"); AssumedTypes.List<object> results = new OpenEhr.AssumedTypes.List<object>(); foreach (Locatable locatableItem in ilist) { AssertionContext assertionContext = new AssertionContext(locatableItem, contextObj); AssertionContext result = ProcessPathPartWithWildcardForArId(assertionContext, pathStep); if (result != null && result.Data != null) results.Add(result.Data); } if (results.Count > 0) return new AssertionContext(results, contextObj); return null; }
private AssertionContext ProcessPathPartWithAttrObject(AssertionContext attributeObjContext, PathStep pathStep) { DesignByContract.Check.Require(attributeObjContext != null && attributeObjContext.Data != null, "attributeObjContext and attributeObjContext.Data must not be null."); AssertionContext tempContext = attributeObjContext; if (pathStep.Predicates != null) { foreach (PredicateExpr predicate in pathStep.Predicates) { AssertionContext predicateObj = predicate.Evaluate(tempContext); if (predicateObj == null) return null; tempContext = predicateObj; } } return tempContext; }
//optimized A* pathfinding public static bool GetPath(Vec2I StartPoint, Vec2I EndPoint, int maxDistance, out Vec2I[] path) { if (StartPoint == EndPoint) { path = new Vec2I[1]; path[0] = EndPoint; return(true); } path = null; if (AxMath.RogueDistance(StartPoint, EndPoint) > maxDistance) { return(false); } if (GetHeat(StartPoint).x == -1) { return(false); } if (GetHeat(EndPoint).x == -1) { return(false); } //init arrays int arraySize = maxDistance * 2 + 1; bool[,] closedCheck = new bool[arraySize, arraySize]; bool[,] openCheck = new bool[arraySize, arraySize]; Vec2I[,] parents = new Vec2I[arraySize, arraySize]; PathStep[,] openArray = new PathStep[arraySize, arraySize]; //set start point BinaryHeap <PathStep> openList = new BinaryHeap <PathStep>(arraySize * arraySize); openList.Add(new PathStep(StartPoint, AxMath.WeightedDistance(StartPoint, EndPoint))); openCheck[maxDistance, maxDistance] = true; parents[maxDistance, maxDistance] = StartPoint; bool found = false; while (openList.ItemCount > 0) { //get top of heap PathStep current = openList.RemoveFirst(); closedCheck[current.position.x - StartPoint.x + maxDistance, current.position.y - StartPoint.y + maxDistance] = true; foreach (Vec2I neighbor in current.position.neighbors) { //calculate array position int arrayX = neighbor.x - StartPoint.x + maxDistance; int arrayY = neighbor.y - StartPoint.y + maxDistance; //cull disallowed if (AxMath.RogueDistance(neighbor, StartPoint) > maxDistance) { continue; } if (closedCheck[arrayX, arrayY]) { continue; } //found target if (neighbor == EndPoint) { parents[arrayX, arrayY] = current.position; found = true; goto finalize; } if (!CanPath(neighbor)) { continue; } //calculate cost int travelCost = current.travelCost + AxMath.WeightedDistance(current.position, neighbor); int heuristic = AxMath.WeightedDistance(neighbor, EndPoint); int fullCost = travelCost + heuristic; //check if we can update parent to better if (openCheck[arrayX, arrayY]) { if (openArray[arrayX, arrayY].travelCost > travelCost) { openArray[arrayX, arrayY].travelCost = travelCost; openArray[arrayX, arrayY].heuristic = heuristic; openArray[arrayX, arrayY].fullCost = fullCost; parents[arrayX, arrayY] = current.position; openList.UpdateItem(openArray[arrayX, arrayY]); continue; } else { continue; } } //priority sorted by heap PathStep step = new PathStep(neighbor, travelCost, heuristic); openList.Add(step); openCheck[arrayX, arrayY] = true; openArray[arrayX, arrayY] = step; parents[arrayX, arrayY] = current.position; } } finalize: if (found) { SingleLinkedList <Vec2I> list = new SingleLinkedList <Vec2I>(); Vec2I current = EndPoint; while (current != StartPoint) { list.InsertFront(current); current = parents[current.x - StartPoint.x + maxDistance, current.y - StartPoint.y + maxDistance]; } //list.InsertFront(current); //adds the starting point to the path path = list.ToArray(); return(true); } return(false); }
public override void IterateOpenSet() { //Track how many iterations have taken place to find this pathway so far OpenSetIterations++; //If the open set is empty, then no pathway was able to be found if (OpenSet.Count <= 0) { //Print a failure message and reset the grid Log.Print("Unable to find a valid pathway using A* algorithm."); FindingPathway = false; GridManager.Instance.HideAllParentIndicators(); return; } //Get the cheapest node currently being stored in the open set Node Current = GridManager.Instance.FindCheapestNode(OpenSet); OpenSet.Remove(Current); //When Current matches the end node, the pathway is ready to be reconstructed if (Current == PathEnd) { //Announce the pathway has been found and how long it took to find Log.Print("A* pathfinding completed after " + OpenSetIterations + " iterations."); //Hide all parent indicators GridManager.Instance.HideAllParentIndicators(); //Grab and display the final pathway List <Node> Pathway = GridManager.Instance.GetCompletedPathway(PathStart, PathEnd); foreach (Node PathStep in Pathway) { PathStep.SetType(NodeType.Pathway); } //Finalize the process FindingPathway = false; return; } //Remove the current node from the open set, then iterate over its neighbours OpenSet.Remove(Current); foreach (Node Neighbour in GridManager.Instance.GetTraversableNeighbours(Current)) { if (Current.GScore < Neighbour.GScore) { //Update this as the preferred way to travel Neighbour.Parent = Current; Neighbour.ToggleParentIndicator(true); Neighbour.PointIndicator(Neighbour.GetDirection(Current)); //Update neighbours score values Neighbour.GScore = Current.GScore; Neighbour.FScore = Neighbour.GScore + GridManager.FindHeuristic(Neighbour, PathEnd); //Add neighbour to open set if its not there already if (!OpenSet.Contains(Neighbour)) { OpenSet.Add(Neighbour); } } } }
public PathStep previous; //The PathStep that was used before this // Use this for initialization public PathStep(point position, PathStep previous) { this.position = position; this.previous = previous; }
//same as previous, but take into account movement cost of cells public static void FillPlayerBreath(ref BreathArea breath, ref List <ThingController> monstersList, bool cullByTrueDistance = false) { int maxDistance = breath.maxDistance; int arraySize = breath.size; Vec2I StartPoint = breath.position; breath.Invalidate(); monstersList.Clear(); if (GetHeat(StartPoint).x == -1) { return; } //init arrays bool[,] closedCheck = new bool[arraySize, arraySize]; bool[,] openCheck = new bool[arraySize, arraySize]; PathStep[,] openArray = new PathStep[arraySize, arraySize]; //set start point BinaryHeap <PathStep> openList = new BinaryHeap <PathStep>(arraySize * arraySize); openList.Add(new PathStep(StartPoint, 0)); openCheck[maxDistance, maxDistance] = true; breath.exist[maxDistance, maxDistance] = true; breath.steps[maxDistance, maxDistance] = 0; breath.distance[maxDistance, maxDistance] = 0; breath.direction[maxDistance, maxDistance] = 0; List <ThingController> monsters = new List <ThingController>(); int maxStepDistance = maxDistance * 10; while (openList.ItemCount > 0) { //get top of heap PathStep current = openList.RemoveFirst(); int ax = current.position.x - StartPoint.x + maxDistance; int ay = current.position.y - StartPoint.y + maxDistance; int currentDistance = breath.distance[ax, ay]; int currentSteps = breath.steps[ax, ay]; closedCheck[ax, ay] = true; TheGrid.GetNearbyMonsters(current.position, 0).Perform((n) => { monsters.Add(n.Data); }); if (cullByTrueDistance) { if (currentDistance >= maxStepDistance) { continue; } } Vector3 currentHeat = GetHeat(current.position); //no propagation through solids if (currentHeat.x >= 1f) { if (current.position != StartPoint) { continue; } } for (int i = 1; i < 9; i++) { Vec2I neighbor = current.position + Vec2I.directions[i]; //calculate array position int arrayX = neighbor.x - StartPoint.x + maxDistance; int arrayY = neighbor.y - StartPoint.y + maxDistance; //cull disallowed if (AxMath.RogueDistance(neighbor, StartPoint) > maxDistance) { continue; } if (openCheck[arrayX, arrayY]) { continue; } if (closedCheck[arrayX, arrayY]) { continue; } if (!CanPath(neighbor)) { continue; } if (HasLedge(current.position, neighbor, false)) { continue; } //calculate cost int travelCost = current.travelCost + GetTravelCost(neighbor); int heuristic = AxMath.WeightedDistance(neighbor, StartPoint); int fullCost = travelCost + heuristic; //reverse direction to point towards the source of breath int p = i + 4; if (p > 8) { p -= 8; } //check if we can update parent to better if (openCheck[arrayX, arrayY]) { if (openArray[arrayX, arrayY].travelCost > travelCost) { openArray[arrayX, arrayY].travelCost = travelCost; openArray[arrayX, arrayY].heuristic = heuristic; openArray[arrayX, arrayY].fullCost = fullCost; breath.direction[arrayX, arrayY] = p; breath.distance[arrayX, arrayY] = currentDistance + StepDistance(i); breath.steps[arrayX, arrayY] = currentSteps + 1; openList.UpdateItem(openArray[arrayX, arrayY]); continue; } else { continue; } } //priority sorted by heap PathStep step = new PathStep(neighbor, travelCost, heuristic); openList.Add(step); openArray[arrayX, arrayY] = step; openCheck[arrayX, arrayY] = true; breath.exist[arrayX, arrayY] = true; breath.direction[arrayX, arrayY] = p; breath.distance[arrayX, arrayY] = currentDistance + StepDistance(i); breath.steps[arrayX, arrayY] = currentSteps + 1; } } monstersList = monsters; }
private AssertionContext ProcessPathPartWithAllProperties(AssertionContext rootObjContext, PathStep pathStep) { DesignByContract.Check.Require(rootObjContext != null && rootObjContext.Data != null, "attributeObjContext and attributeObjContext.Data must not be null."); object rootObj = rootObjContext.Data; AssumedTypes.List<object> objList = new OpenEhr.AssumedTypes.List<object>(); // go through all properties System.Reflection.PropertyInfo[] allProperties = rootObj.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.Instance); foreach (System.Reflection.PropertyInfo property in allProperties) { object propertyValue = property.GetValue(rootObj, null); if (propertyValue != null) { AssertionContext propertyContext = new AssertionContext(propertyValue, rootObjContext); AssertionContext tempContext = ProcessPathPartWithAttrObject(propertyContext, pathStep); if (tempContext != null && tempContext.Data != null) { objList.Add(tempContext.Data); } } } if (objList.Count == 0) return null; if (objList.Count == 1) return new AssertionContext(objList[0], rootObjContext); return new AssertionContext(objList, rootObjContext); }