public AStar(VG.Map.Tissue t) { this.map = t; nodeGrid = new AStarNode[200][]; openSet = new bool[200][]; closedSet= new bool[200][]; cacheable = new bool[200][]; for (int i = 0; i < 200; i++) { nodeGrid[i] = new AStarNode[200]; openSet[i] = new bool[200]; closedSet[i] = new bool[200]; cacheable[i] = new bool[200]; } // prepare cacheable set EntityCollection aznCol = map.get_EntitiesByType(EntityEnum.AZN); for (int i = 0; i < aznCol.Count; i++) cacheable[aznCol[i].X][aznCol[i].Y] = true; EntityCollection hpCol = map.get_EntitiesByType(EntityEnum.HoshimiPoint); for (int i = 0; i < hpCol.Count; i++) cacheable[hpCol[i].X][hpCol[i].Y] = true; //cache PierreIP cacheable[Global.MYAI.PierreTeamInjectionPoint.X][Global.MYAI.PierreTeamInjectionPoint.Y] = true; cache = new System.Collections.Hashtable( (hpCol.Count * hpCol.Count) + (aznCol.Count * aznCol.Count) ); aznCol = null; // garbage-collected hpCol = null; }
// put element to heap public void Put(AStarNode n) { // find the appropriate place for element // start as new leaf and moves up accordingly int currentNode = ++this.size; while (currentNode != 1 // not at root && heap[currentNode/2].F > n.F // current node is > new node ) { heap[currentNode] = heap[currentNode/2]; // move current node down (cos its greater) currentNode /= 2; // move to the parent of current } // we found a place heap[currentNode] = n; }
public AStarNode(AStarNode parent, Point p, int length) { this.Parent = parent; this.PointData = p; this.PathLength = length; }
public virtual Path FindWay(Point from, Point goal) { if (from.X == goal.X && from.Y == goal.Y) { return(new Path(null, 0)); } #region Check if in Cache string fromTo = GetCacheKey(from, goal); if (cache[fromTo] != null) { return((Path)cache[fromTo]); } #endregion if (!firstTime) { // reset for (int i = 0; i < 200; i++) { for (int j = 0; j < 200; j++) { openSet[i][j] = closedSet[i][j] = false; } } if (!openList.IsEmpty) { openList.Clear(); } } firstTime = false; // Prepare starting node int g; nodeGrid[from.X][from.Y] = new AStarNode(null, from, 0); // put start node to openList openList.Put(nodeGrid[from.X][from.Y]); openSet[from.X][from.Y] = true; AStarNode popped = null; Point successor = new Point(0, 0); do { if (openList.IsEmpty) // no path found { Path noPath = new Path(null, int.MaxValue); // put path to cache to prevent future long search cache[fromTo] = noPath; return(noPath); } // Pop the best node so far popped = openList.RemoveMin(); if (popped.PointData.Equals(goal)) // path found { break; } if (closedSet[popped.PointData.X][popped.PointData.Y] == true) { // successors already generated continue; } // Generate successors for (int i = 0; i < offset.Length; i++) { successor.X = popped.PointData.X + offset[i].X; successor.Y = popped.PointData.Y + offset[i].Y; // ignore some successors if (closedSet[successor.X][successor.Y] == true || // already expanded map[successor.X, successor.Y].AreaType == AreaEnum.Bone || // impassable map[successor.X, successor.Y].AreaType == AreaEnum.Vessel || // impassable map[successor.X, successor.Y].AreaType == AreaEnum.Special || // impassable map.IsInMap(successor.X, successor.Y) == false || // not in map (successor.X == from.X && successor.Y == from.Y) // same as from loc ) { continue; } /*if ((!Global.PierreIP.IsEmpty) && (!Global.isPierreAIDead)) * { // avoid Pierre * if (Global.CanShoot(successor, Global.PierreIP, 10)) * continue; * }*/ // valid successor // not at goal yet g = popped.G + GetTurnCost(successor, offset[i]); // if node with successor position is already in open... if (openSet[successor.X][successor.Y] == true) { // is it lower? if (nodeGrid[successor.X][successor.Y].G < g) { continue; // skip this successor } } // set successor to parent nodeGrid[successor.X][successor.Y] = new AStarNode(popped, successor, popped.PathLength + 1); // add sucessor to open list nodeGrid[successor.X][successor.Y].H = GetHCost(successor, goal); nodeGrid[successor.X][successor.Y].G = g; nodeGrid[successor.X][successor.Y].F = nodeGrid[successor.X][successor.Y].G + nodeGrid[successor.X][successor.Y].H; openSet[successor.X][successor.Y] = true; openList.Put(nodeGrid[successor.X][successor.Y]); } // put popped on closed list (already expanded) closedSet[popped.PointData.X][popped.PointData.Y] = true; } while(true); Point[] path = new Point[popped.PathLength]; AStarNode current = popped; AStarNode temp = null; int pathElem = path.Length - 1; while (current.Parent != null) // until original loc is met { path[pathElem--] = current.PointData; temp = current; current = current.Parent; temp = null; // enable Garbage-Collection } Path foundPath = new Path(path, path.Length); // hide destination Point Point[] pt = new Point[foundPath.Points.Length + 2]; for (int idx = 0; idx < pt.Length - 2; idx++) { pt[idx] = foundPath.Points[idx]; } pt[pt.Length - 1] = new Point(0, 0); foundPath = new Path(pt, pt.Length + 1); #region Put in Cache Only if Dest is AZN or HP if (cacheable[goal.X][goal.Y] == true) { // from->to cache[fromTo] = foundPath; } #endregion return(foundPath); }