public int AStarBinarySearch(List<AStarTile> openList, AStarTile tileToInsert) { // List<AStarTile> list = openList; //The AStarTile list to consider // AStarTile tile = tileToInsert; //The tile to insert // bool done = false; //Loop condition // int min = 0; //The minimum index number to look at // int max = list.Count - 1; //The maximum index number to look at // int range = max - min; //The range between max and min // // int f = tile.f; //The f cost to insert and compare with // //bool totalIsEven; //Whether the number of insert points is even or odd // //if ((range + 1) % 2 == 0) //If insert points is even // //{ // // totalIsEven = true; // //} // //else //If odd // //{ // // totalIsEven = false; // //} // // while (!done) //Loop until done with the search // { // if (list.Count == 0) //If nothing's there, then obviously the new Tile will have the lowest f cost // { // done = true; //Nothing's there already, so we're done // } // // if (list.Count == 1) // { // if (f < list[0].f) // { // indexToInsertAt = 0; // } // else if (f > list[0].f) // { // indexToInsertAt = 1; // } // else // { // indexToInsertAt = random.Next(0, 1); // } // } // // if (list.Count == 2) // { // // } // } return -1; //Error if it gets here }
public Stack<byte> AStarPathfind(Creature creature, Vector2 pointA, Vector2 pointB) { Stack<byte> path = new Stack<byte>(); if (ConvertAbsolutePosToRelative(pointA, pointB) > 0) { path.Push((byte)ConvertAbsolutePosToRelative(pointA, pointB)); return path; } if (pointA.X == pointB.X && pointA.Y == pointB.Y) { path.Push(5); return path; } #region Variables //int g = 0; //int h = (int)(Math.Abs(pointB.X - pointA.X) + (int)Math.Abs(pointB.Y - pointA.Y)); bool done = false; AStarTile currentTile = new AStarTile(pointA, new Vector2(-1, -1), 0, 100 * ((int)(Math.Abs(pointB.X - pointA.X) + (int)Math.Abs(pointB.Y - pointA.Y)))); List<AStarTile> openList = new List<AStarTile>(); List<AStarTile> closedList = new List<AStarTile>(); #endregion openList.Add(currentTile); //Add the current tile while (!done) { #region Find new current tile currentTile = openList[0]; //The lowest F cost tile is the current tile openList.RemoveAt(0); //Removed from the open list closedList.Add(currentTile); //And placed in the closed list #endregion if (currentTile.pos == pointB) //If target has been just added to closed list { done = true; } #region Define adjacent vectors Vector2[] adjacent = new Vector2[8]; adjacent[0] = new Vector2(currentTile.pos.X - 1, currentTile.pos.Y + 1); //Adjacent tile at position 1 adjacent[1] = new Vector2(currentTile.pos.X, currentTile.pos.Y + 1); //Adjacent tile at position 2 adjacent[2] = new Vector2(currentTile.pos.X + 1, currentTile.pos.Y + 1); //Adjacent tile at position 3 adjacent[3] = new Vector2(currentTile.pos.X - 1, currentTile.pos.Y); //Adjacent tile at position 4 adjacent[4] = new Vector2(currentTile.pos.X + 1, currentTile.pos.Y); //Adjacent tile at position 6 adjacent[5] = new Vector2(currentTile.pos.X - 1, currentTile.pos.Y - 1); //Adjacent tile at position 7 adjacent[6] = new Vector2(currentTile.pos.X, currentTile.pos.Y - 1); //Adjacent tile at position 8 adjacent[7] = new Vector2(currentTile.pos.X + 1, currentTile.pos.Y - 1); //Adjacent tile at position 9 #endregion #region Process adjacent tiles to Current Tile for (int i = 0; i <= 7; i++) // the adjacent tiles 0-7, all 8 { if (adjacent[i].X < 0 || adjacent[i].X > GRIDW-1 || adjacent[i].Y < 0 || adjacent[i].Y > GRIDH-1) { i++; break; } bool shouldBeOpen = true; bool isAlreadyOpen = false; bool closedDoor = false; //Whether this tile has a door in it. int indexOnOpen = -1; //if (tileArray[(int)adjacent[i].X, (int)adjacent[i].Y].fixtureLibrary.Count > 0) //{ // foreach (Fixture fixture in tileArray[(int)adjacent[i].X, (int)adjacent[i].Y].fixtureLibrary) // { // if (fixture is Door) //If it's a door // { // Door door = (Door)fixture; // if (!door.isOpen) //If the door is closed // closedDoor = true; // } // } //} if (tileArray[(int)adjacent[i].X, (int)adjacent[i].Y] == null) { shouldBeOpen = false; } else if (this.tileArray[(int)adjacent[i].X, (int)adjacent[i].Y].isPassable == false && !(closedDoor && creature.isDextrous)) //If not passable { shouldBeOpen = false; //It's not a candidate if not blocked by door } else //If passable { foreach (AStarTile j in closedList) //For each closedList item { if (j.pos == adjacent[i]) //If a closedList item is the same as the potential tile { shouldBeOpen = false; //Not a candidate } } foreach (Creature c in creatures) if (c.pos == adjacent[i] && adjacent[i] != pointB) //If a creature is in the way shouldBeOpen = false; int openListCount = openList.Count; for (int j = 0; j < openListCount; j++) { if (openList[j].pos == adjacent[i]) //If an openList item is the same as the potential tile { isAlreadyOpen = true; //Mark it as already on the open list indexOnOpen = j; } } } if (shouldBeOpen) //If it should go on the open list { int g = 100; //Weight of tile ***IMPROVE THIS LATER*** int h = 100 * ((int)(Math.Abs(pointB.X - adjacent[i].X) + (int)Math.Abs(pointB.Y - adjacent[i].Y))); //Heuristic guess //int f = g + h; //Definition of f cost AStarTile newTile = new AStarTile(adjacent[i], currentTile.pos, currentTile.g + g, h, g); //Make an official tile for it if (isAlreadyOpen) //If already on the open list { if (newTile.g < openList[indexOnOpen].g) //If this path to the tile is cheaper than its previous g { openList[indexOnOpen] = newTile; //Overwrite its old info with this cheaper info } } else { openList.Insert(AStarSequentialSearch(openList, newTile), newTile); //Insert in openList a sequential search according to f cost //Calculate where this new tile should go with a binary search. ***UNFINISHED*** //AStarBinarySearch(openList, newTile); } } } if (openList.Count == 0) //If no more tiles to look at, there's no path { path.Push(0); return path; } #endregion } #region Trace back to starting tile int oldIndex = -1; int index = 0; while (currentTile.parentpos != new Vector2(-1, -1)) //Until parent is starting tile { int closedListCount = closedList.Count; for (int j = 0; j < closedListCount; j++) { if (closedList[j].pos == currentTile.parentpos) { oldIndex = index; index = j; path.Push((byte)ConvertAbsolutePosToRelative(closedList[index].pos, currentTile.pos)); break; } } currentTile = closedList[index]; } #endregion currentTile = closedList[oldIndex]; openList.Clear(); closedList.Clear(); return path; }
public static int AStarSequentialSearch(List<AStarTile> openList, AStarTile tileToInsert) { int max = openList.Count - 1; if (openList.Count == 0) //If the list is empty { return 0; //Insert at zero, since nothing's there to mess up } if (openList.Count == 1) { if (tileToInsert.f < openList[0].f) { return 0; } else { return 1; } } for (int i = 0; i <= max; i++) { if (i == max) //If at the far right of the list { if (tileToInsert.f >= openList[i].f) //newtile.f > farrightnumber.f { return i + 1; //Insert it just to the right of the max number, bumping nothing } else { return i; } } else if (i == 0) //If at the far left of the list { if (tileToInsert.f <= openList[i].f) //newtile.f < farleftnumber.f { return 0; //Insert it at index zero, bumping everything to the right one } else { return 1; } } else { if (openList[i - 1].f < tileToInsert.f && tileToInsert.f <= openList[i].f) //If between two { return i; //Bump everything it's less than to the right. } } } return -1; //Error if it makes it here }