// Update And Re-Issue PathQuery From Start public PathQuery ReissuePathQuery(PathQuery query, Vector2 start, Vector2 goal, int teamIndex) { if (query != null) { query.IsOld = true; } query = new PathQuery(start, goal, teamIndex); Add(query); return(query); }
public SquadQuery(RTSSquad s, PathQuery q) { Squad = s; Query = q; }
public void Add(PathQuery q) { queries.Enqueue(q); }
// Run A* Search, Given This Pathfinder's World And A Query private void Pathfind(PathQuery q) { // Initialization isThoughtCollidable = new bool[World.numCells.X, World.numCells.Y]; start = HashHelper.Hash(q.Start, World.numCells, World.size); end = HashHelper.Hash(q.End, World.numCells, World.size); ; for(int y = 0; y < World.numCells.Y; y++) { for(int x = 0; x < World.numCells.X; x++) { fScore[x, y] = int.MaxValue; gScore[x, y] = int.MaxValue; } } // Precondition: Any Buildings In World Have Valid Centers var viewedBuildings = gameState.teams[q.FOWIndex].ViewedEnemyBuildings; foreach(var vb in viewedBuildings) { var vbData = gameState.teams[vb.Team].Race.Buildings[vb.Type]; Point p = vb.CellPoint; for(int y = 0; y < vbData.GridSize.Y; y++) { for(int x = 0; x < vbData.GridSize.X; x++) { isThoughtCollidable[p.X + x, p.Y + y] = true; } } } gScore[start.X, start.Y] = 0; fScore[start.X, start.Y] = Estimate(start.X, start.Y); var openSet = new MinHeap<Point>(Comparison, 30); openSet.Insert(start); // A* Loop List<Point> path = null; while(openSet.Count > 0) { Point p = openSet.Pop(); if(p.X == end.X && p.Y == end.Y) { path = new List<Point>(); BuildPath(path, end); break; } bool canMove = false; foreach(Point n in NeighborhoodAlign(p).Where(InGrid)) { int tgs = gScore[p.X, p.Y] + 10; canMove = CanMoveFrom(p, n, q.FOWIndex); if(canMove && tgs < gScore[n.X, n.Y]) { prev[n.X, n.Y] = p; gScore[n.X, n.Y] = tgs; fScore[n.X, n.Y] = gScore[n.X, n.Y] + Estimate(n.X, n.Y); if(!openSet.Contains(n)) { openSet.Insert(n); } } } foreach(Point n in NeighborhoodDiag(p).Where(InGrid)) { int tgs = gScore[p.X, p.Y] + 14; // To Move Diagonally, Destination Must Be Reachable By Horizontal & Vertical Moves As Well canMove = CanMoveFrom(p, n, q.FOWIndex); foreach(Point d in DiagDecomp(p, n)) { canMove &= CanMoveFrom(p, d, q.FOWIndex); } if(canMove && tgs < gScore[n.X, n.Y]) { prev[n.X, n.Y] = p; gScore[n.X, n.Y] = tgs; fScore[n.X, n.Y] = gScore[n.X, n.Y] + Estimate(n.X, n.Y); if(!openSet.Contains(n)) { openSet.Insert(n); } } } } // Check If We Need To Find The Nearest Point if(path == null) { int s; bool[,] ch = new bool[World.numCells.X, World.numCells.Y]; Array.Clear(ch, 0, ch.Length); Point cg = FindClosestGoal(end, fScore, ch, out s, 0); if(s == int.MaxValue) { // Impossible } else { path = new List<Point>(); BuildPath(path, cg); } } // A* Conclusion if(path != null) { foreach(Point wp in path) { q.waypoints.Add(new Vector2(((float)wp.X + 0.5f) * World.cellSize, ((float)wp.Y + 0.5f) * World.cellSize)); } } q.IsComplete = true; }
// Update And Re-Issue PathQuery From Start public PathQuery ReissuePathQuery(PathQuery query, Vector2 start, Vector2 goal, int teamIndex) { if(query != null) query.IsOld = true; query = new PathQuery(start, goal, teamIndex); Add(query); return query; }
// Run A* Search, Given This Pathfinder's World And A Query private void Pathfind(PathQuery q) { // Initialization isThoughtCollidable = new bool[World.numCells.X, World.numCells.Y]; start = HashHelper.Hash(q.Start, World.numCells, World.size); end = HashHelper.Hash(q.End, World.numCells, World.size);; for (int y = 0; y < World.numCells.Y; y++) { for (int x = 0; x < World.numCells.X; x++) { fScore[x, y] = int.MaxValue; gScore[x, y] = int.MaxValue; } } // Precondition: Any Buildings In World Have Valid Centers var viewedBuildings = gameState.teams[q.FOWIndex].ViewedEnemyBuildings; foreach (var vb in viewedBuildings) { var vbData = gameState.teams[vb.Team].Race.Buildings[vb.Type]; Point p = vb.CellPoint; for (int y = 0; y < vbData.GridSize.Y; y++) { for (int x = 0; x < vbData.GridSize.X; x++) { isThoughtCollidable[p.X + x, p.Y + y] = true; } } } gScore[start.X, start.Y] = 0; fScore[start.X, start.Y] = Estimate(start.X, start.Y); var openSet = new MinHeap <Point>(Comparison, 30); openSet.Insert(start); // A* Loop List <Point> path = null; while (openSet.Count > 0) { Point p = openSet.Pop(); if (p.X == end.X && p.Y == end.Y) { path = new List <Point>(); BuildPath(path, end); break; } bool canMove = false; foreach (Point n in NeighborhoodAlign(p).Where(InGrid)) { int tgs = gScore[p.X, p.Y] + 10; canMove = CanMoveFrom(p, n, q.FOWIndex); if (canMove && tgs < gScore[n.X, n.Y]) { prev[n.X, n.Y] = p; gScore[n.X, n.Y] = tgs; fScore[n.X, n.Y] = gScore[n.X, n.Y] + Estimate(n.X, n.Y); if (!openSet.Contains(n)) { openSet.Insert(n); } } } foreach (Point n in NeighborhoodDiag(p).Where(InGrid)) { int tgs = gScore[p.X, p.Y] + 14; // To Move Diagonally, Destination Must Be Reachable By Horizontal & Vertical Moves As Well canMove = CanMoveFrom(p, n, q.FOWIndex); foreach (Point d in DiagDecomp(p, n)) { canMove &= CanMoveFrom(p, d, q.FOWIndex); } if (canMove && tgs < gScore[n.X, n.Y]) { prev[n.X, n.Y] = p; gScore[n.X, n.Y] = tgs; fScore[n.X, n.Y] = gScore[n.X, n.Y] + Estimate(n.X, n.Y); if (!openSet.Contains(n)) { openSet.Insert(n); } } } } // Check If We Need To Find The Nearest Point if (path == null) { int s; bool[,] ch = new bool[World.numCells.X, World.numCells.Y]; Array.Clear(ch, 0, ch.Length); Point cg = FindClosestGoal(end, fScore, ch, out s, 0); if (s == int.MaxValue) { // Impossible } else { path = new List <Point>(); BuildPath(path, cg); } } // A* Conclusion if (path != null) { foreach (Point wp in path) { q.waypoints.Add(new Vector2(((float)wp.X + 0.5f) * World.cellSize, ((float)wp.Y + 0.5f) * World.cellSize)); } } q.IsComplete = true; }