Original Post
We're working on a tile-based tactical RPG, and we're stumped with this problem. I developed this function that returns a list of directions to follow on the map. However, on really hilly maps, it enters an infinite loop. Narrowing it down, we discovered it to be within the first while loop, so I'll just post that code here. This is my first time I've attempted to implement A* algorithm. One thing that seemed to help is implementing "Travelled" map that checks if the tile is already traversed, to prevent flipping back and forth between two tiles with lowest gValue. Then I realized that I forgot to carry over gValue from previous tile to current tile, so I added that. If someone can help me, I'd really appreciate it! Thanks. [Edited by - Zeraan on June 12, 2009 5:06:53 PM]
int X = StartX % SuperMapSize;
int Y = StartY % SuperMapSize;
int TargetX = EndX % SuperMapSize;
int TargetY = EndY % SuperMapSize;
int StartingX = StartX % SuperMapSize;
int StartingY = StartY % SuperMapSize;
int length = 0; //How long is the path?
int[,] PathMap = new int[SuperMapSize, SuperMapSize]; //Track which movements are taken while walking
int[,] GMap = new int[SuperMapSize, SuperMapSize]; //Cost of path
bool[,] Travelled = new bool[SuperMapSize, SuperMapSize]; //See if path is already touched
int NextX = 0;
int NextY = 0;
int gValue;
int absX, absY;
int height;
int MaxValue;
while (!(X == TargetX && Y == TargetY))
{
for (int i = -1; i < 2; i++)
for (int j = -1; j < 2; j++) //Fill in GMap, and determine the next best action
{
if (i + X >= 0 && i + X < SuperMapSize && //Make sure it's safely inside the area
j + Y >= 0 && j + Y < SuperMapSize)
{
absX = TargetX - (i + X); //Factor in distance to the target spot
if (absX < 0)
absX *= -1;
else
absX *= 1;
absY = TargetY - (j + Y);
if (absY < 0)
absY *= -1;
else
absY *= 1;
height = (TileMap[i + X][j + Y].height - TileMap[X][Y].height); //Factor in the tile's height
if (height < 0 && height > -3)
height *= -3;
else if (height <= 2)
height *= 3;
else
height *= 6; //climbing a cliff tile requires some time
//if (i == j || i == (j * -1)) //it's a diagonal
// height += 2;
gValue = absX + absY + height + GMap[X, Y];
if (GMap[X + i, Y + j] == 0 || GMap[X + i, Y + j] > gValue) //This tile is better accessed from current tile
{
GMap[X + i, Y + j] = gValue;
if (i == 0 && j == 1) //Moved down
PathMap[X + i, Y + j] = 2;
else if (i == 0 && j == -1) //Moved up
PathMap[X + i, Y + j] = 7;
else if (i == 1 && j == 0) //Moved right
PathMap[X + i, Y + j] = 4;
else if (i == -1 && j == 0) //Moved left
PathMap[X + i, Y + j] = 5;
else if (i == -1 && j == -1) //Moved up left
PathMap[X + i, Y + j] = 8;
else if (i == -1 && j == 1) //Moved down left
PathMap[X + i, Y + j] = 3;
else if (i == 1 && j == -1) //Moved up right
PathMap[X + i, Y + j] = 6;
else if (i == 1 && j == 1) //Moved down right
PathMap[X + i, Y + j] = 1;
Travelled[X + i, Y + j] = false;
}
}
}
MaxValue = SuperMapSize * SuperMapSize * 100; //So it's impossible to have this accidentally lower than gValue
for (int i = -1; i < 2; i++) //Find the next lowest gValue
for (int j = -1; j < 2; j++)
{
if (GMap[X + i, Y + j] < MaxValue && Travelled[X + i, Y + j] == false)
{
MaxValue = GMap[X + i, Y + j];
NextX = X + i;
NextY = Y + j;
}
}
X = NextX;
Y = NextY;
Travelled[X, Y] = true;
}