# pathfinder.cpp

    00001 /* $Id: pathfinder.cpp 11983 2008-01-25 15:47:58Z frosch $ */
    00002
    00003 #include "../../stdafx.h"
    00004 #include "../../openttd.h"
    00005 #include "../../bridge_map.h"
    00006 #include "../../debug.h"
    00007 #include "../../command_func.h"
    00008 #include "trolly.h"
    00009 #include "../../depot.h"
    00010 #include "../../tunnel_map.h"
    00011 #include "../../bridge.h"
    00012 #include "../../tunnelbridge_map.h"
    00013 #include "../ai.h"
    00014 #include "../../variables.h"
    00015 #include "../../player_base.h"
    00016 #include "../../player_func.h"
    00017 #include "../../tunnelbridge.h"
    00018
    00019
    00020 #define TEST_STATION_NO_DIR 0xFF
    00021
    00022 // Tests if a station can be build on the given spot
    00023 // TODO: make it train compatible
    00024 static bool TestCanBuildStationHere(TileIndex tile, byte dir)
    00025 {
    00026   Player *p = GetPlayer(_current_player);
    00027
    00028   if (dir == TEST_STATION_NO_DIR) {
    00029     CommandCost ret;
    00030     // TODO: currently we only allow spots that can be access from al 4 directions...
    00031     //  should be fixed!!!
    00032     for (dir = 0; dir < 4; dir++) {
    00033       ret = AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST);
    00034       if (CmdSucceeded(ret)) return true;
    00035     }
    00036     return false;
    00037   }
    00038
    00039   // return true if command succeeded, so the inverse of CmdFailed()
    00040   return CmdSucceeded(AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST));
    00041 }
    00042
    00043
    00044 static bool IsRoad(TileIndex tile)
    00045 {
    00046   return
    00047     // MP_ROAD, but not a road depot?
    00048     (IsTileType(tile, MP_ROAD) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
    00049     (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD);
    00050 }
    00051
    00052
    00053 // Checks if a tile 'a' is between the tiles 'b' and 'c'
    00054 #define TILES_BETWEEN(a, b, c) (TileX(a) >= TileX(b) && TileX(a) <= TileX(c) && TileY(a) >= TileY(b) && TileY(a) <= TileY(c))
    00055
    00056
    00057 // Check if the current tile is in our end-area
    00058 static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
    00059 {
    00060   const Ai_PathFinderInfo* PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
    00061
    00062   // It is not allowed to have a station on the end of a bridge or tunnel ;)
    00063   if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
    00064   if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
    00065     if (IsTileType(current->path.node.tile, MP_CLEAR) || IsTileType(current->path.node.tile, MP_TREES))
    00066       if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile, AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
    00067         return AYSTAR_FOUND_END_NODE;
    00068
    00069   return AYSTAR_DONE;
    00070 }
    00071
    00072
    00073 // Calculates the hash
    00074 //   Currently it is a 10 bit hash, so the hash array has a max depth of 6 bits (so 64)
    00075 static uint AiPathFinder_Hash(uint key1, uint key2)
    00076 {
    00077   return (TileX(key1) & 0x1F) + ((TileY(key1) & 0x1F) << 5);
    00078 }
    00079
    00080
    00081 // Clear the memory of all the things
    00082 static void AyStar_AiPathFinder_Free(AyStar *aystar)
    00083 {
    00084   AyStarMain_Free(aystar);
    00085   delete aystar;
    00086 }
    00087
    00088
    00089 static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
    00090 static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
    00091 static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current);
    00092 static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
    00093
    00094
    00095 // This creates the AiPathFinder
    00096 AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo)
    00097 {
    00098   PathNode start_node;
    00099   uint x;
    00100   uint y;
    00101   // Create AyStar
    00102   AyStar *result = new AyStar();
    00103   init_AyStar(result, AiPathFinder_Hash, 1 << 10);
    00104   // Set the function pointers
    00105   result->CalculateG = AyStar_AiPathFinder_CalculateG;
    00106   result->CalculateH = AyStar_AiPathFinder_CalculateH;
    00107   result->EndNodeCheck = AyStar_AiPathFinder_EndNodeCheck;
    00108   result->FoundEndNode = AyStar_AiPathFinder_FoundEndNode;
    00109   result->GetNeighbours = AyStar_AiPathFinder_GetNeighbours;
    00110
    00111   result->free = AyStar_AiPathFinder_Free;
    00112
    00113   // Set some information
    00114   result->loops_per_tick = AI_PATHFINDER_LOOPS_PER_TICK;
    00115   result->max_path_cost = 0;
    00116   result->max_search_nodes = AI_PATHFINDER_MAX_SEARCH_NODES;
    00117
    00118   // Set the user_data to the PathFinderInfo
    00119   result->user_target = PathFinderInfo;
    00120
    00121   // Set the start node
    00122   start_node.parent = NULL;
    00123   start_node.node.direction = 0;
    00124   start_node.node.user_data[0] = 0;
    00125
    00126   // Now we add all the starting tiles
    00127   for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
    00128     for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
    00129       start_node.node.tile = TileXY(x, y);
    00130       result->addstart(result, &start_node.node, 0);
    00131     }
    00132   }
    00133
    00134   return result;
    00135 }
    00136
    00137
    00138 // To reuse AyStar we sometimes have to clean all the memory
    00139 void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo)
    00140 {
    00141   PathNode start_node;
    00142   uint x;
    00143   uint y;
    00144
    00145   aystar->clear(aystar);
    00146
    00147   // Set the user_data to the PathFinderInfo
    00148   aystar->user_target = PathFinderInfo;
    00149
    00150   // Set the start node
    00151   start_node.parent = NULL;
    00152   start_node.node.direction = 0;
    00153   start_node.node.user_data[0] = 0;
    00154   start_node.node.tile = PathFinderInfo->start_tile_tl;
    00155
    00156   // Now we add all the starting tiles
    00157   for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
    00158     for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
    00159       TileIndex tile = TileXY(x, y);
    00160
    00161       if (!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES)) continue;
    00162       if (!TestCanBuildStationHere(tile, TEST_STATION_NO_DIR)) continue;
    00163       start_node.node.tile = tile;
    00164       aystar->addstart(aystar, &start_node.node, 0);
    00165     }
    00166   }
    00167 }
    00168
    00169
    00170 // The h-value, simple calculation
    00171 static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
    00172 {
    00173   const Ai_PathFinderInfo* PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
    00174   int r, r2;
    00175
    00176   if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
    00177     // The station is pointing to a direction, add a tile towards that direction, so the H-value is more accurate
    00178     r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDiagDir(PathFinderInfo->end_direction));
    00179     r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDiagDir(PathFinderInfo->end_direction));
    00180   } else {
    00181     // No direction, so just get the fastest route to the station
    00182     r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl);
    00183     r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br);
    00184   }
    00185   // See if the bottomright is faster than the topleft..
    00186   if (r2 < r) r = r2;
    00187   return r * AI_PATHFINDER_H_MULTIPLER;
    00188 }
    00189
    00190
    00191 // We found the end.. let's get the route back and put it in an array
    00192 static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current)
    00193 {
    00194   Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
    00195   uint i = 0;
    00196   PathNode *parent = &current->path;
    00197
    00198   do {
    00199     PathFinderInfo->route_extra[i] = parent->node.user_data[0];
    00200     PathFinderInfo->route[i++] = parent->node.tile;
    00201     if (i > lengthof(PathFinderInfo->route)) {
    00202       // We ran out of space for the PathFinder
    00203       DEBUG(ai, 0, "No more space in pathfinder route[] array");
    00204       PathFinderInfo->route_length = -1; // -1 indicates out of space
    00205       return;
    00206     }
    00207     parent = parent->parent;
    00208   } while (parent != NULL);
    00209   PathFinderInfo->route_length = i;
    00210   DEBUG(ai, 1, "Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
    00211 }
    00212
    00213
    00214 // What tiles are around us.
    00215 static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current)
    00216 {
    00217   CommandCost ret;
    00218   int dir;
    00219
    00220   Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
    00221
    00222   aystar->num_neighbours = 0;
    00223
    00224   // Go through all surrounding tiles and check if they are within the limits
    00225   for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
    00226     TileIndex ctile = current->path.node.tile; // Current tile
    00227     TileIndex atile = ctile + TileOffsByDiagDir(i); // Adjacent tile
    00228
    00229     if (TileX(atile) > 1 && TileX(atile) < MapMaxX() - 1 &&
    00230         TileY(atile) > 1 && TileY(atile) < MapMaxY() - 1) {
    00231       // We also directly test if the current tile can connect to this tile..
    00232       //  We do this simply by just building the tile!
    00233
    00234       // If the next step is a bridge, we have to enter it the right way
    00235       if (!PathFinderInfo->rail_or_road && IsRoad(atile)) {
    00236         if (IsTileType(atile, MP_TUNNELBRIDGE)) {
    00237           if (GetTunnelBridgeDirection(atile) != i) continue;
    00238         }
    00239       }
    00240
    00241       if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
    00242           (AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
    00243         // We are a bridge/tunnel, how cool!!
    00244         //  This means we can only point forward.. get the direction from the user_data
    00245         if ((uint)i != (current->path.node.user_data[0] >> 8)) continue;
    00246       }
    00247       dir = 0;
    00248
    00249       // First, check if we have a parent
    00250       if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
    00251         // If not, this means we are at the starting station
    00252         if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
    00253           // We do need a direction?
    00254           if (AiNew_GetDirection(ctile, atile) != PathFinderInfo->start_direction) {
    00255             // We are not pointing the right way, invalid tile
    00256             continue;
    00257           }
    00258         }
    00259       } else if (current->path.node.user_data[0] == 0) {
    00260         if (PathFinderInfo->rail_or_road) {
    00261           // Rail check
    00262           dir = AiNew_GetRailDirection(current->path.parent->node.tile, ctile, atile);
    00263           ret = AI_DoCommand(ctile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
    00264           if (CmdFailed(ret)) continue;
    00265 #ifdef AI_PATHFINDER_NO_90DEGREES_TURN
    00266           if (current->path.parent->parent != NULL) {
    00267             // Check if we don't make a 90degree curve
    00268             int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, ctile);
    00269             if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
    00270               continue;
    00271             }
    00272           }
    00273 #endif
    00274         } else {
    00275           // Road check
    00276           dir = AiNew_GetRoadDirection(current->path.parent->node.tile, ctile, atile);
    00277           if (IsRoad(ctile)) {
    00278             if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
    00279               // We have a bridge, how nicely! We should mark it...
    00280               dir = 0;
    00281             } else {
    00282               // It already has road.. check if we miss any bits!
    00283               if ((GetAnyRoadBits(ctile, ROADTYPE_ROAD) & dir) != dir) {
    00284                 // We do miss some pieces :(
    00285                 dir &= ~GetAnyRoadBits(ctile, ROADTYPE_ROAD);
    00286               } else {
    00287                 dir = 0;
    00288               }
    00289             }
    00290           }
    00291           // Only destruct things if it is MP_CLEAR of MP_TREES
    00292           if (dir != 0) {
    00293             ret = AI_DoCommand(ctile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
    00294             if (CmdFailed(ret)) continue;
    00295           }
    00296         }
    00297       }
    00298
    00299       // The tile can be connected
    00300       aystar->neighbours[aystar->num_neighbours].tile = atile;
    00301       aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
    00302       aystar->neighbours[aystar->num_neighbours++].direction = 0;
    00303     }
    00304   }
    00305
    00306   // Next step, check for bridges and tunnels
    00307   if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
    00308     // First we get the dir from this tile and his parent
    00309     DiagDirection dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
    00310     // It means we can only walk with the track, so the bridge has to be in the same direction
    00311     TileIndex tile = current->path.node.tile;
    00312     TileIndex new_tile = tile;
    00313     Slope tileh = GetTileSlope(tile, NULL);
    00314
    00315     // Bridges can only be build on land that is not flat
    00316     //  And if there is a road or rail blocking
    00317     if (tileh != SLOPE_FLAT ||
    00318         (PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_ROAD)) ||
    00319         (!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_RAILWAY))) {
    00320       for (;;) {
    00321         new_tile += TileOffsByDiagDir(dir);
    00322
    00323         // Precheck, is the length allowed?
    00324         if (!CheckBridge_Stuff(0, GetTunnelBridgeLength(tile, new_tile))) break;
    00325
    00326         // Check if we hit the station-tile.. we don't like that!
    00327         if (TILES_BETWEEN(new_tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) break;
    00328
    00329         // Try building the bridge..
    00330         ret = AI_DoCommand(tile, new_tile, (0 << 8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
    00331         if (CmdFailed(ret)) continue;
    00332         // We can build a bridge here.. add him to the neighbours
    00333         aystar->neighbours[aystar->num_neighbours].tile = new_tile;
    00334         aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
    00335         aystar->neighbours[aystar->num_neighbours++].direction = 0;
    00336         // We can only have 12 neighbours, and we need 1 left for tunnels
    00337         if (aystar->num_neighbours == 11) break;
    00338       }
    00339     }
    00340
    00341     // Next, check for tunnels!
    00342     // Tunnels can only be built on slopes corresponding to the direction
    00343     //  For now, we check both sides for this tile.. terraforming gives fuzzy result
    00344     if (tileh == InclinedSlope(dir)) {
    00345       // Now simply check if a tunnel can be build
    00346       ret = AI_DoCommand(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
    00347       tileh = GetTileSlope(_build_tunnel_endtile, NULL);
    00348       if (CmdSucceeded(ret) && IsInclinedSlope(tileh)) {
    00349         aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
    00350         aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
    00351         aystar->neighbours[aystar->num_neighbours++].direction = 0;
    00352       }
    00353     }
    00354   }
    00355 }
    00356
    00357
    00358 extern Foundation GetRailFoundation(Slope tileh, TrackBits bits); // XXX function declaration in .c
    00359 extern Foundation GetRoadFoundation(Slope tileh, RoadBits bits); // XXX function declaration in .c
    00360
    00361 // The most important function: it calculates the g-value
    00362 static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
    00363 {
    00364   Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
    00365   int res = 0;
    00366   Slope tileh = GetTileSlope(current->tile, NULL);
    00367   Slope parent_tileh = GetTileSlope(parent->path.node.tile, NULL);
    00368
    00369   // Check if we hit the end-tile
    00370   if (TILES_BETWEEN(current->tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) {
    00371     // We are at the end-tile, check if we had a direction or something...
    00372     if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction) {
    00373       // We are not pointing the right way, invalid tile
    00374       return AYSTAR_INVALID_NODE;
    00375     }
    00376     // If it was valid, drop out.. we don't build on the endtile
    00377     return 0;
    00378   }
    00379
    00380   // Give everything a small penalty
    00381   res += AI_PATHFINDER_PENALTY;
    00382
    00383   if (!PathFinderInfo->rail_or_road) {
    00384     // Road has the lovely advantage it can use other road... check if
    00385     //  the current tile is road, and if so, give a good bonus
    00386     if (IsRoad(current->tile)) {
    00387       res -= AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS;
    00388     }
    00389   }
    00390
    00391   // We should give a penalty when the tile is going up or down.. this is one way to do so!
    00392   //  Too bad we have to count it from the parent.. but that is not so bad.
    00393   // We also dislike long routes on slopes, since they do not look too realistic
    00394   //  when there is a flat land all around, they are more expensive to build, and
    00395   //  especially they essentially block the ability to connect or cross the road
    00396   //  from one side.
    00397   if (parent_tileh != SLOPE_FLAT && parent->path.parent != NULL) {
    00398     // Skip if the tile was from a bridge or tunnel
    00399     if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
    00400       if (PathFinderInfo->rail_or_road) {
    00401         Foundation f = GetRailFoundation(parent_tileh, (TrackBits)(1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile)));
    00402         if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
    00403           res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
    00404         } else {
    00405           res += AI_PATHFINDER_FOUNDATION_PENALTY;
    00406         }
    00407       } else {
    00408         if (!IsRoad(parent->path.node.tile) || !IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE)) {
    00409           Foundation f = GetRoadFoundation(parent_tileh, (RoadBits)AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
    00410           if (IsInclinedFoundation(f) || (!IsFoundation(f) && IsInclinedSlope(parent_tileh))) {
    00411             res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
    00412           } else {
    00413             res += AI_PATHFINDER_FOUNDATION_PENALTY;
    00414           }
    00415         }
    00416       }
    00417     }
    00418   }
    00419
    00420   // Are we part of a tunnel?
    00421   if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
    00422     int r;
    00423     // Tunnels are very expensive when build on long routes..
    00424     // Ironicly, we are using BridgeCode here ;)
    00425     r = AI_PATHFINDER_TUNNEL_PENALTY * GetTunnelBridgeLength(current->tile, parent->path.node.tile);
    00426     res += r + (r >> 8);
    00427   }
    00428
    00429   // Are we part of a bridge?
    00430   if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) {
    00431     // That means for every length a penalty
    00432     res += AI_PATHFINDER_BRIDGE_PENALTY * GetTunnelBridgeLength(current->tile, parent->path.node.tile);
    00433     // Check if we are going up or down, first for the starting point
    00434     // In user_data[0] is at the 8th bit the direction
    00435     if (!HasBridgeFlatRamp(parent_tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
    00436     // Second for the end point
    00437     if (!HasBridgeFlatRamp(tileh, (Axis)((current->user_data[0] >> 8) & 1))) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
    00438   }
    00439
    00440   //  To prevent the AI from taking the fastest way in tiles, but not the fastest way
    00441   //    in speed, we have to give a good penalty to direction changing
    00442   //  This way, we get almost the fastest way in tiles, and a very good speed on the track
    00443   if (!PathFinderInfo->rail_or_road) {
    00444     if (parent->path.parent != NULL &&
    00445         AiNew_GetDirection(current->tile, parent->path.node.tile) != AiNew_GetDirection(parent->path.node.tile, parent->path.parent->node.tile)) {
    00446       // When road exists, we don't like turning, but its free, so don't be to piggy about it
    00447       if (IsRoad(parent->path.node.tile)) {
    00448         res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
    00449       } else {
    00450         res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
    00451       }
    00452     }
    00453   } else {
    00454     // For rail we have 1 exeption: diagonal rail..
    00455     // So we fetch 2 raildirection. That of the current one, and of the one before that
    00456     if (parent->path.parent != NULL && parent->path.parent->parent != NULL) {
    00457       int dir1 = AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile);
    00458       int dir2 = AiNew_GetRailDirection(parent->path.parent->parent->node.tile, parent->path.parent->node.tile, parent->path.node.tile);
    00459       // First, see if we are on diagonal path, that is better than straight path
    00460       if (dir1 > 1) res -= AI_PATHFINDER_DIAGONAL_BONUS;
    00461
    00462       // First see if they are different
    00463       if (dir1 != dir2) {
    00464         // dir 2 and 3 are 1 diagonal track, and 4 and 5.
    00465         if (!(((dir1 == 2 || dir1 == 3) && (dir2 == 2 || dir2 == 3)) || ((dir1 == 4 || dir1 == 5) && (dir2 == 4 || dir2 == 5)))) {
    00466           // It is not, so we changed of direction
    00467           res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
    00468         }
    00469         if (parent->path.parent->parent->parent != NULL) {
    00470           int dir3 = AiNew_GetRailDirection(parent->path.parent->parent->parent->node.tile, parent->path.parent->parent->node.tile, parent->path.parent->node.tile);
    00471           // Check if we changed 3 tiles of direction in 3 tiles.. bad!!!
    00472           if ((dir1 == 0 || dir1 == 1) && dir2 > 1 && (dir3 == 0 || dir3 == 1)) {
    00473             res += AI_PATHFINDER_CURVE_PENALTY;
    00474           }
    00475         }
    00476       }
    00477     }
    00478   }
    00479
    00480   return (res < 0) ? 0 : res;
    00481 }