Skip to main content
added 3 characters in body
Source Link
bandrewk
  • 335
  • 1
  • 2
  • 13

I’m having some trouble implementing the A* algorithm in a 2D tile based game.

The problem is basically that the algorithm gets stuck when something gets in its direct way (e.g. walls) Note that it only allows Horizontal and Vertical movement.

Here's a picture as it works fine across the map without something in its direct way: (Green tile = destination, Blue = In closed list, Green = in open list)

enter image description here

This is what happens if I try to walk 'around' a wall:

enter image description here


EDIT

Thanks DeadMG, I rewrote the algorithm last week and got it somewhat working.

But the heuristics are still aren't working probersome faulty.

As you can see here it prefers a uneven path on an straight way:

enter image description here

The heuristics function:

float c_astar::GetH(cTILEext TILEX)
{
    short a = 0; short b = 0;
    if(TILEX.Tile.Position.x > Destination.x) a = TILEX.Tile.Position.x - Destination.x;
    else a = Destination.x - TILEX.Tile.Position.x;
    if(TILEX.Tile.Position.y > Destination.y) b = TILEX.Tile.Position.y - Destination.y;
    else b = Destination.y - TILEX.Tile.Position.y;

    float h = a+b;

    //Tie-Breaker
    float dx1,dy1,dx2,dy2;
    dx1=dy1=dx2=dy2 = 0;

    if(TILEX.Tile.Position.x > Destination.x) dx1 = TILEX.Tile.Position.x - Destination.x;
    else dx1 = Destination.x - TILEX.Tile.Position.x;

    if(TILEX.Tile.Position.y > Destination.y) dy1 = TILEX.Tile.Position.y - Destination.y;
    else dy1 = Destination.y - TILEX.Tile.Position.y;

    if(Start.x > Destination.x) dx2 = Start.x - Destination.x;
    else dx2 = Destination.x - Start.x;

    if(Start.y > Destination.y) dy2 = Start.y - Destination.y;
    else dy2 = Destination.y - Start.y;
    float cross = abs(dx1*dy2 - dx2*dy1);

    h += cross*0.001;

    return h;
}

I used the Tie-Breaker as described here. What am I doing wrong?

Regards, bryan226

I’m having some trouble implementing the A* algorithm in a 2D tile based game.

The problem is basically that the algorithm gets stuck when something gets in its direct way (e.g. walls) Note that it only allows Horizontal and Vertical movement.

Here's a picture as it works fine across the map without something in its direct way: (Green tile = destination, Blue = In closed list, Green = in open list)

enter image description here

This is what happens if I try to walk 'around' a wall:

enter image description here


EDIT

Thanks DeadMG, I rewrote the algorithm last week and got it working.

But the heuristics still aren't working prober.

As you can see here it prefers a uneven path on an straight way:

enter image description here

The heuristics function:

float c_astar::GetH(cTILEext TILEX)
{
    short a = 0; short b = 0;
    if(TILEX.Tile.Position.x > Destination.x) a = TILEX.Tile.Position.x - Destination.x;
    else a = Destination.x - TILEX.Tile.Position.x;
    if(TILEX.Tile.Position.y > Destination.y) b = TILEX.Tile.Position.y - Destination.y;
    else b = Destination.y - TILEX.Tile.Position.y;

    float h = a+b;

    //Tie-Breaker
    float dx1,dy1,dx2,dy2;
    dx1=dy1=dx2=dy2 = 0;

    if(TILEX.Tile.Position.x > Destination.x) dx1 = TILEX.Tile.Position.x - Destination.x;
    else dx1 = Destination.x - TILEX.Tile.Position.x;

    if(TILEX.Tile.Position.y > Destination.y) dy1 = TILEX.Tile.Position.y - Destination.y;
    else dy1 = Destination.y - TILEX.Tile.Position.y;

    if(Start.x > Destination.x) dx2 = Start.x - Destination.x;
    else dx2 = Destination.x - Start.x;

    if(Start.y > Destination.y) dy2 = Start.y - Destination.y;
    else dy2 = Destination.y - Start.y;
    float cross = abs(dx1*dy2 - dx2*dy1);

    h += cross*0.001;

    return h;
}

I used the Tie-Breaker as described here. What am I doing wrong?

Regards, bryan226

I’m having some trouble implementing the A* algorithm in a 2D tile based game.

The problem is basically that the algorithm gets stuck when something gets in its direct way (e.g. walls) Note that it only allows Horizontal and Vertical movement.

Here's a picture as it works fine across the map without something in its direct way: (Green tile = destination, Blue = In closed list, Green = in open list)

enter image description here

This is what happens if I try to walk 'around' a wall:

enter image description here


EDIT

Thanks DeadMG, I rewrote the algorithm last week and got it somewhat working.

But the heuristics are still some faulty.

As you can see here it prefers a uneven path on an straight way:

enter image description here

The heuristics function:

float c_astar::GetH(cTILEext TILEX)
{
    short a = 0; short b = 0;
    if(TILEX.Tile.Position.x > Destination.x) a = TILEX.Tile.Position.x - Destination.x;
    else a = Destination.x - TILEX.Tile.Position.x;
    if(TILEX.Tile.Position.y > Destination.y) b = TILEX.Tile.Position.y - Destination.y;
    else b = Destination.y - TILEX.Tile.Position.y;

    float h = a+b;

    //Tie-Breaker
    float dx1,dy1,dx2,dy2;
    dx1=dy1=dx2=dy2 = 0;

    if(TILEX.Tile.Position.x > Destination.x) dx1 = TILEX.Tile.Position.x - Destination.x;
    else dx1 = Destination.x - TILEX.Tile.Position.x;

    if(TILEX.Tile.Position.y > Destination.y) dy1 = TILEX.Tile.Position.y - Destination.y;
    else dy1 = Destination.y - TILEX.Tile.Position.y;

    if(Start.x > Destination.x) dx2 = Start.x - Destination.x;
    else dx2 = Destination.x - Start.x;

    if(Start.y > Destination.y) dy2 = Start.y - Destination.y;
    else dy2 = Destination.y - Start.y;
    float cross = abs(dx1*dy2 - dx2*dy1);

    h += cross*0.001;

    return h;
}

I used the Tie-Breaker as described here. What am I doing wrong?

Regards, bryan226

Updated Post
Source Link
bandrewk
  • 335
  • 1
  • 2
  • 13

I calculate costs with the F = G + H formula:

G = 1 Cost per Step

H = 10 Cost per Step //Count how many tiles are between current-tile & destination-tile

The functions:

short c_astar::GuessH(short Startx,short Starty,short Destinationx,short Destinationy)
{
                hgeVector Start, Destination;
                Start.x = Startx;
                Start.y = Starty;
                Destination.x = Destinationx;
                Destination.y = Destinationy;

                short a = 0; short b = 0;
                if(Start.x > Destination.x) a = Start.x - Destination.x;
                else a = Destination.x - Start.x;
                if(Start.y > Destination.y) b = Start.y - Destination.y;
                else b = Destination.y - Start.y;

                return (a+b)*10;
}

short c_astar::GuessG(short Startx,short Starty,short Currentx,short Currenty)
{
                hgeVector Start, Destination;
                Start.x = Startx;
                Start.y = Starty;
                Destination.x = Currentx;
                Destination.y = Currenty;

                short a = 0; short b = 0;
                if(Start.x > Destination.x) a = Start.x - Destination.x;
                else a = Destination.x - Start.x;
                if(Start.y > Destination.y) b = Start.y - Destination.y;
                else b = Destination.y - Start.y;

                return (a+b);
}

At the end of the loop I check which tile is the cheapest to go according to its F value:

 

Then some quick checks are done for each tile (UP,DOWN,LEFT,RIGHT):EDIT

                           //...CX are holding the F value of the TILE specified
                           //            Info:                                        C0 = Center (Current)
                           //                                                           C1 = UP
                           //                                                           C2 = DOWN
                           //                                                           C3 = LEFT
                           //                                                           C4 = RIGHT
                           //Quick checks
                           if(((C1 < C2) && (C1 < C3) && (C1 < C4)))
                           {
                                           Current.y  -= 1;
                                           bSimilar  = false;
                                           if(DEBUG) hge->System_Log("C1 < ALL");
                           }
                           //.. same for C2,C3 & C4

Thanks DeadMG, I rewrote the algorithm last week and got it working.

If there are multiple tiles withBut the same F value:heuristics still aren't working prober.

It’s actually a switch for DOWNLEFT,UPRIGHT.. etc. Here’s one ofAs you can see here it prefers a uneven path on an straight way:

   case UPRIGHT:
         {
                //UP
                Temporary = Current;
                Temporary.y -= 1;

                bTileStatus[0] = IsTileWalkable(Temporary.x,Temporary.y);

                if(bTileStatus[0])
                {
                       //Proceed normal we are OK & walkable
                       Tilex.Tile                 = map.at(Temporary.y).at(Temporary.x);

                       //Search in lists
                       if(SearchInClosedList(Tilex.Tile.ID,C0)) bFoundInClosedList[0] = true;
                       if(SearchInOpenList(Tilex.Tile.ID,C0)) bFoundInOpenList[0]  = true;


                       //RIGHT
                       Temporary = Current;
                       Temporary.x += 1;

                       bTileStatus[1] = IsTileWalkable(Temporary.x,Temporary.y);
                              
                       if(bTileStatus[1])
                       {
                              //Proceed normal we are OK & walkable
                              Tilex.Tile                 = map.at(Temporary.y).at(Temporary.x);

                              //Search in lists
                              if(SearchInClosedList(Tilex.Tile.ID,C0)) bFoundInClosedList[1] = true;
                              if(SearchInOpenList(Tilex.Tile.ID,C0)) bFoundInOpenList[1]  = true;

                              //*************************************************
                              //     Purpose: ClosedList behavior
                              //*************************************************
                              if(bFoundInClosedList[0] && !bFoundInClosedList[1])
                              {
                                    //UP found in ClosedList. Go RIGHT
                                    return RIGHT;
                              }
                              if(!bFoundInClosedList[0] && bFoundInClosedList[1])
                              {
                                    //RIGHT found in ClosedList. Go UP
                                    return UP;
                              }
                              if(bFoundInClosedList[0] && bFoundInClosedList[1])
                              {
                                    //Both found in ClosedList. Random value
                                    switch(hge->Random_Int(8,9))
                                    {
                                    case 8:
                                           return UP;
                                           break;
                                    case 9:
                                           return RIGHT;
                                           break;
                                    }
                              }

                              //*************************************************
                              //     Purpose: OpenList behavior
                              //*************************************************
                              if(bFoundInOpenList[0] && !bFoundInOpenList[1])
                              {
                                    //UP found in OpenList. Go RIGHT
                                    return RIGHT;
                              }
                              if(!bFoundInOpenList[0] && bFoundInOpenList[1])
                              {
                                    //RIGHT found in OpenList. Go UP
                                    return UP;
                              }
                              if(bFoundInOpenList[0] && bFoundInOpenList[1])
                              {
                                    //Both found in OpenList. Random value
                                    switch(hge->Random_Int(8,9))
                                    {
                                    case 8:
                                           return UP;
                                           break;
                                    case 9:
                                           return RIGHT;
                                           break;
                                    }
                              }
                       }
                       else if(!bTileStatus[1])
                       {
                              //RIGHT is not walkable OR out of range
                              //Choose UP
                              return UP;
                       }
                }
                else if(!bTileStatus[0])
                {
                       //UP is not walkable OR out of range
                       //Fast check RIGHT
                       Temporary = Current;
                       Temporary.x += 1;

                       bTileStatus[1] = IsTileWalkable(Temporary.x,Temporary.y);
                              
                       if(bTileStatus[1])
                       {
                              return RIGHT;
                       }
                       else return FAILED; //Failed, no valid path found!
                }
         }
         break;

enter image description here

A log for the second pictureThe heuristics function: (Cut down to ten passes, because it’s just repeating itself)

-----------------------------------------------------
PASS: 1 | C1: 211 |float C2c_astar: 191 | C3: 211 | C4:GetH(cTILEext 191TILEX)
DOWN{
 + RIGHT SIMILAR
Going DOWN
-----------------------------------------------------
PASS:short 2a |= C1:0; 200short |b C2:= 1820;
 | C3: 202 |if(TILEX.Tile.Position.x C4:> 182
DOWNDestination.x) +a RIGHT= SIMILAR
GoingTILEX.Tile.Position.x DOWN
-----------------------------------------------------
PASS: 3Destination.x;
 | C1: 191 | C2:else 193a |= C3:Destination.x 193- |TILEX.Tile.Position.x;
 C4: 173
C4 < ALL
Tileif(12TILEX.000000,6Tile.000000)Position.y not> walkableDestination.y) MAX_F_VALUEb set= TILEX.
----------------------------------------------------Tile.Position.y - Destination.y;
PASS: 4 | C1: 182else |b C2:= 184Destination.y |- C3:TILEX.Tile.Position.y;

 182 | C4: 999
UPfloat +h LEFT= SIMILARa+b;
Going UP
Tile(12.000000,5.000000) not walkable. MAX_F_VALUE set.
----------------------------------------------------//Tie-Breaker
PASS: 5 | C1: 191float |dx1,dy1,dx2,dy2;
 C2: 173 | C3:dx1=dy1=dx2=dy2 191= |0;

 C4: 999
C2 < ALL
Tileif(12TILEX.000000,6Tile.000000) not walkablePosition.x MAX_F_VALUE> setDestination.
-----------------------------------------------------
PASS:x) 6dx1 |= C1:TILEX.Tile.Position.x 182- |Destination.x;
 C2: 184 | C3:else 182dx1 |= C4:Destination.x 999- TILEX.Tile.Position.x;
UP 
 + LEFT SIMILAR
Going UP
Tileif(12TILEX.000000,5Tile.000000) not walkablePosition.y MAX_F_VALUE> setDestination.
-----------------------------------------------------
PASS: 7y) |dy1 C1:= 191TILEX.Tile.Position.y |- C2:Destination.y;
 173 | C3: 191else |dy1 C4:= 999
C2Destination.y <- ALL
TILEX.Tile(12.000000,6Position.000000)y;

 not walkable. MAX_F_VALUE setif(Start.
-----------------------------------------------------
PASS: 8x |> C1:Destination.x) 182dx2 |= C2:Start.x 184- |Destination.x;
 C3: 182 | C4:else 999
UPdx2 += LEFTDestination.x SIMILAR
Going- LEFTStart.x;
-----------------------------------------------------
PASS: 9 | C1: 191if(Start.y |> C2:Destination.y) 193dy2 |= C3:Start.y 193- |Destination.y;
 C4: 173
C4 < ALL
Tile(12.000000,6.000000)else notdy2 walkable= Destination.y MAX_F_VALUE- setStart.
-----------------------------------------------------y;
PASS: 10 | C1: 182float |cross C2:= 184abs(dx1*dy2 |- C3:dx2*dy1);

 182 | C4: 999h += cross*0.001;
UP 
 + LEFT SIMILAR
Going LEFTreturn h;
-----------------------------------------------------}

Its always going after the cheapest F value, which seems to be wrong.

If someone could point me toI used the right direction I'd be thankfulTie-Breaker as described here. What am I doing wrong?

I calculate costs with the F = G + H formula:

G = 1 Cost per Step

H = 10 Cost per Step //Count how many tiles are between current-tile & destination-tile

The functions:

short c_astar::GuessH(short Startx,short Starty,short Destinationx,short Destinationy)
{
                hgeVector Start, Destination;
                Start.x = Startx;
                Start.y = Starty;
                Destination.x = Destinationx;
                Destination.y = Destinationy;

                short a = 0; short b = 0;
                if(Start.x > Destination.x) a = Start.x - Destination.x;
                else a = Destination.x - Start.x;
                if(Start.y > Destination.y) b = Start.y - Destination.y;
                else b = Destination.y - Start.y;

                return (a+b)*10;
}

short c_astar::GuessG(short Startx,short Starty,short Currentx,short Currenty)
{
                hgeVector Start, Destination;
                Start.x = Startx;
                Start.y = Starty;
                Destination.x = Currentx;
                Destination.y = Currenty;

                short a = 0; short b = 0;
                if(Start.x > Destination.x) a = Start.x - Destination.x;
                else a = Destination.x - Start.x;
                if(Start.y > Destination.y) b = Start.y - Destination.y;
                else b = Destination.y - Start.y;

                return (a+b);
}

At the end of the loop I check which tile is the cheapest to go according to its F value:

Then some quick checks are done for each tile (UP,DOWN,LEFT,RIGHT):

                           //...CX are holding the F value of the TILE specified
                           //            Info:                                        C0 = Center (Current)
                           //                                                           C1 = UP
                           //                                                           C2 = DOWN
                           //                                                           C3 = LEFT
                           //                                                           C4 = RIGHT
                           //Quick checks
                           if(((C1 < C2) && (C1 < C3) && (C1 < C4)))
                           {
                                           Current.y  -= 1;
                                           bSimilar  = false;
                                           if(DEBUG) hge->System_Log("C1 < ALL");
                           }
                           //.. same for C2,C3 & C4

If there are multiple tiles with the same F value:

It’s actually a switch for DOWNLEFT,UPRIGHT.. etc. Here’s one of it:

   case UPRIGHT:
         {
                //UP
                Temporary = Current;
                Temporary.y -= 1;

                bTileStatus[0] = IsTileWalkable(Temporary.x,Temporary.y);

                if(bTileStatus[0])
                {
                       //Proceed normal we are OK & walkable
                       Tilex.Tile                 = map.at(Temporary.y).at(Temporary.x);

                       //Search in lists
                       if(SearchInClosedList(Tilex.Tile.ID,C0)) bFoundInClosedList[0] = true;
                       if(SearchInOpenList(Tilex.Tile.ID,C0)) bFoundInOpenList[0]  = true;


                       //RIGHT
                       Temporary = Current;
                       Temporary.x += 1;

                       bTileStatus[1] = IsTileWalkable(Temporary.x,Temporary.y);
                              
                       if(bTileStatus[1])
                       {
                              //Proceed normal we are OK & walkable
                              Tilex.Tile                 = map.at(Temporary.y).at(Temporary.x);

                              //Search in lists
                              if(SearchInClosedList(Tilex.Tile.ID,C0)) bFoundInClosedList[1] = true;
                              if(SearchInOpenList(Tilex.Tile.ID,C0)) bFoundInOpenList[1]  = true;

                              //*************************************************
                              //     Purpose: ClosedList behavior
                              //*************************************************
                              if(bFoundInClosedList[0] && !bFoundInClosedList[1])
                              {
                                    //UP found in ClosedList. Go RIGHT
                                    return RIGHT;
                              }
                              if(!bFoundInClosedList[0] && bFoundInClosedList[1])
                              {
                                    //RIGHT found in ClosedList. Go UP
                                    return UP;
                              }
                              if(bFoundInClosedList[0] && bFoundInClosedList[1])
                              {
                                    //Both found in ClosedList. Random value
                                    switch(hge->Random_Int(8,9))
                                    {
                                    case 8:
                                           return UP;
                                           break;
                                    case 9:
                                           return RIGHT;
                                           break;
                                    }
                              }

                              //*************************************************
                              //     Purpose: OpenList behavior
                              //*************************************************
                              if(bFoundInOpenList[0] && !bFoundInOpenList[1])
                              {
                                    //UP found in OpenList. Go RIGHT
                                    return RIGHT;
                              }
                              if(!bFoundInOpenList[0] && bFoundInOpenList[1])
                              {
                                    //RIGHT found in OpenList. Go UP
                                    return UP;
                              }
                              if(bFoundInOpenList[0] && bFoundInOpenList[1])
                              {
                                    //Both found in OpenList. Random value
                                    switch(hge->Random_Int(8,9))
                                    {
                                    case 8:
                                           return UP;
                                           break;
                                    case 9:
                                           return RIGHT;
                                           break;
                                    }
                              }
                       }
                       else if(!bTileStatus[1])
                       {
                              //RIGHT is not walkable OR out of range
                              //Choose UP
                              return UP;
                       }
                }
                else if(!bTileStatus[0])
                {
                       //UP is not walkable OR out of range
                       //Fast check RIGHT
                       Temporary = Current;
                       Temporary.x += 1;

                       bTileStatus[1] = IsTileWalkable(Temporary.x,Temporary.y);
                              
                       if(bTileStatus[1])
                       {
                              return RIGHT;
                       }
                       else return FAILED; //Failed, no valid path found!
                }
         }
         break;

A log for the second picture: (Cut down to ten passes, because it’s just repeating itself)

-----------------------------------------------------
PASS: 1 | C1: 211 | C2: 191 | C3: 211 | C4: 191
DOWN + RIGHT SIMILAR
Going DOWN
-----------------------------------------------------
PASS: 2 | C1: 200 | C2: 182 | C3: 202 | C4: 182
DOWN + RIGHT SIMILAR
Going DOWN
-----------------------------------------------------
PASS: 3 | C1: 191 | C2: 193 | C3: 193 | C4: 173
C4 < ALL
Tile(12.000000,6.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 4 | C1: 182 | C2: 184 | C3: 182 | C4: 999
UP + LEFT SIMILAR
Going UP
Tile(12.000000,5.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 5 | C1: 191 | C2: 173 | C3: 191 | C4: 999
C2 < ALL
Tile(12.000000,6.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 6 | C1: 182 | C2: 184 | C3: 182 | C4: 999
UP + LEFT SIMILAR
Going UP
Tile(12.000000,5.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 7 | C1: 191 | C2: 173 | C3: 191 | C4: 999
C2 < ALL
Tile(12.000000,6.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 8 | C1: 182 | C2: 184 | C3: 182 | C4: 999
UP + LEFT SIMILAR
Going LEFT
-----------------------------------------------------
PASS: 9 | C1: 191 | C2: 193 | C3: 193 | C4: 173
C4 < ALL
Tile(12.000000,6.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 10 | C1: 182 | C2: 184 | C3: 182 | C4: 999
UP + LEFT SIMILAR
Going LEFT
-----------------------------------------------------

Its always going after the cheapest F value, which seems to be wrong.

If someone could point me to the right direction I'd be thankful.

 

EDIT

Thanks DeadMG, I rewrote the algorithm last week and got it working.

But the heuristics still aren't working prober.

As you can see here it prefers a uneven path on an straight way:

enter image description here

The heuristics function:

float c_astar::GetH(cTILEext TILEX)
{
    short a = 0; short b = 0;
    if(TILEX.Tile.Position.x > Destination.x) a = TILEX.Tile.Position.x - Destination.x;
    else a = Destination.x - TILEX.Tile.Position.x;
    if(TILEX.Tile.Position.y > Destination.y) b = TILEX.Tile.Position.y - Destination.y;
    else b = Destination.y - TILEX.Tile.Position.y;

    float h = a+b;

    //Tie-Breaker
    float dx1,dy1,dx2,dy2;
    dx1=dy1=dx2=dy2 = 0;

    if(TILEX.Tile.Position.x > Destination.x) dx1 = TILEX.Tile.Position.x - Destination.x;
    else dx1 = Destination.x - TILEX.Tile.Position.x;
 
    if(TILEX.Tile.Position.y > Destination.y) dy1 = TILEX.Tile.Position.y - Destination.y;
    else dy1 = Destination.y - TILEX.Tile.Position.y;

    if(Start.x > Destination.x) dx2 = Start.x - Destination.x;
    else dx2 = Destination.x - Start.x;

    if(Start.y > Destination.y) dy2 = Start.y - Destination.y;
    else dy2 = Destination.y - Start.y;
    float cross = abs(dx1*dy2 - dx2*dy1);

    h += cross*0.001;
 
    return h;
}

I used the Tie-Breaker as described here. What am I doing wrong?

Source Link
bandrewk
  • 335
  • 1
  • 2
  • 13

A star algorithm implementation problems

I’m having some trouble implementing the A* algorithm in a 2D tile based game.

The problem is basically that the algorithm gets stuck when something gets in its direct way (e.g. walls) Note that it only allows Horizontal and Vertical movement.

Here's a picture as it works fine across the map without something in its direct way: (Green tile = destination, Blue = In closed list, Green = in open list)

enter image description here

This is what happens if I try to walk 'around' a wall:

enter image description here

I calculate costs with the F = G + H formula:

G = 1 Cost per Step

H = 10 Cost per Step //Count how many tiles are between current-tile & destination-tile

The functions:

short c_astar::GuessH(short Startx,short Starty,short Destinationx,short Destinationy)
{
                hgeVector Start, Destination;
                Start.x = Startx;
                Start.y = Starty;
                Destination.x = Destinationx;
                Destination.y = Destinationy;

                short a = 0; short b = 0;
                if(Start.x > Destination.x) a = Start.x - Destination.x;
                else a = Destination.x - Start.x;
                if(Start.y > Destination.y) b = Start.y - Destination.y;
                else b = Destination.y - Start.y;

                return (a+b)*10;
}

short c_astar::GuessG(short Startx,short Starty,short Currentx,short Currenty)
{
                hgeVector Start, Destination;
                Start.x = Startx;
                Start.y = Starty;
                Destination.x = Currentx;
                Destination.y = Currenty;

                short a = 0; short b = 0;
                if(Start.x > Destination.x) a = Start.x - Destination.x;
                else a = Destination.x - Start.x;
                if(Start.y > Destination.y) b = Start.y - Destination.y;
                else b = Destination.y - Start.y;

                return (a+b);
}

At the end of the loop I check which tile is the cheapest to go according to its F value:

Then some quick checks are done for each tile (UP,DOWN,LEFT,RIGHT):

                           //...CX are holding the F value of the TILE specified
                           //            Info:                                        C0 = Center (Current)
                           //                                                           C1 = UP
                           //                                                           C2 = DOWN
                           //                                                           C3 = LEFT
                           //                                                           C4 = RIGHT
                           //Quick checks
                           if(((C1 < C2) && (C1 < C3) && (C1 < C4)))
                           {
                                           Current.y  -= 1;
                                           bSimilar  = false;
                                           if(DEBUG) hge->System_Log("C1 < ALL");
                           }
                           //.. same for C2,C3 & C4

If there are multiple tiles with the same F value:

It’s actually a switch for DOWNLEFT,UPRIGHT.. etc. Here’s one of it:

   case UPRIGHT:
         {
                //UP
                Temporary = Current;
                Temporary.y -= 1;

                bTileStatus[0] = IsTileWalkable(Temporary.x,Temporary.y);

                if(bTileStatus[0])
                {
                       //Proceed normal we are OK & walkable
                       Tilex.Tile                 = map.at(Temporary.y).at(Temporary.x);

                       //Search in lists
                       if(SearchInClosedList(Tilex.Tile.ID,C0)) bFoundInClosedList[0] = true;
                       if(SearchInOpenList(Tilex.Tile.ID,C0)) bFoundInOpenList[0]  = true;


                       //RIGHT
                       Temporary = Current;
                       Temporary.x += 1;

                       bTileStatus[1] = IsTileWalkable(Temporary.x,Temporary.y);
                              
                       if(bTileStatus[1])
                       {
                              //Proceed normal we are OK & walkable
                              Tilex.Tile                 = map.at(Temporary.y).at(Temporary.x);

                              //Search in lists
                              if(SearchInClosedList(Tilex.Tile.ID,C0)) bFoundInClosedList[1] = true;
                              if(SearchInOpenList(Tilex.Tile.ID,C0)) bFoundInOpenList[1]  = true;

                              //*************************************************
                              //     Purpose: ClosedList behavior
                              //*************************************************
                              if(bFoundInClosedList[0] && !bFoundInClosedList[1])
                              {
                                    //UP found in ClosedList. Go RIGHT
                                    return RIGHT;
                              }
                              if(!bFoundInClosedList[0] && bFoundInClosedList[1])
                              {
                                    //RIGHT found in ClosedList. Go UP
                                    return UP;
                              }
                              if(bFoundInClosedList[0] && bFoundInClosedList[1])
                              {
                                    //Both found in ClosedList. Random value
                                    switch(hge->Random_Int(8,9))
                                    {
                                    case 8:
                                           return UP;
                                           break;
                                    case 9:
                                           return RIGHT;
                                           break;
                                    }
                              }

                              //*************************************************
                              //     Purpose: OpenList behavior
                              //*************************************************
                              if(bFoundInOpenList[0] && !bFoundInOpenList[1])
                              {
                                    //UP found in OpenList. Go RIGHT
                                    return RIGHT;
                              }
                              if(!bFoundInOpenList[0] && bFoundInOpenList[1])
                              {
                                    //RIGHT found in OpenList. Go UP
                                    return UP;
                              }
                              if(bFoundInOpenList[0] && bFoundInOpenList[1])
                              {
                                    //Both found in OpenList. Random value
                                    switch(hge->Random_Int(8,9))
                                    {
                                    case 8:
                                           return UP;
                                           break;
                                    case 9:
                                           return RIGHT;
                                           break;
                                    }
                              }
                       }
                       else if(!bTileStatus[1])
                       {
                              //RIGHT is not walkable OR out of range
                              //Choose UP
                              return UP;
                       }
                }
                else if(!bTileStatus[0])
                {
                       //UP is not walkable OR out of range
                       //Fast check RIGHT
                       Temporary = Current;
                       Temporary.x += 1;

                       bTileStatus[1] = IsTileWalkable(Temporary.x,Temporary.y);
                              
                       if(bTileStatus[1])
                       {
                              return RIGHT;
                       }
                       else return FAILED; //Failed, no valid path found!
                }
         }
         break;

A log for the second picture: (Cut down to ten passes, because it’s just repeating itself)

-----------------------------------------------------
PASS: 1 | C1: 211 | C2: 191 | C3: 211 | C4: 191
DOWN + RIGHT SIMILAR
Going DOWN
-----------------------------------------------------
PASS: 2 | C1: 200 | C2: 182 | C3: 202 | C4: 182
DOWN + RIGHT SIMILAR
Going DOWN
-----------------------------------------------------
PASS: 3 | C1: 191 | C2: 193 | C3: 193 | C4: 173
C4 < ALL
Tile(12.000000,6.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 4 | C1: 182 | C2: 184 | C3: 182 | C4: 999
UP + LEFT SIMILAR
Going UP
Tile(12.000000,5.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 5 | C1: 191 | C2: 173 | C3: 191 | C4: 999
C2 < ALL
Tile(12.000000,6.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 6 | C1: 182 | C2: 184 | C3: 182 | C4: 999
UP + LEFT SIMILAR
Going UP
Tile(12.000000,5.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 7 | C1: 191 | C2: 173 | C3: 191 | C4: 999
C2 < ALL
Tile(12.000000,6.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 8 | C1: 182 | C2: 184 | C3: 182 | C4: 999
UP + LEFT SIMILAR
Going LEFT
-----------------------------------------------------
PASS: 9 | C1: 191 | C2: 193 | C3: 193 | C4: 173
C4 < ALL
Tile(12.000000,6.000000) not walkable. MAX_F_VALUE set.
-----------------------------------------------------
PASS: 10 | C1: 182 | C2: 184 | C3: 182 | C4: 999
UP + LEFT SIMILAR
Going LEFT
-----------------------------------------------------

Its always going after the cheapest F value, which seems to be wrong.

If someone could point me to the right direction I'd be thankful.

Regards, bryan226