internal static List <PathInfo> GetNeighbors(TileIndex tile, PathInfo cameFrom, Action <TileIndex, string> sign = null) { var oldcost = cameFrom.Cost; var result = new List <PathInfo>(); var isFlat = AITile.GetSlope(tile) == AITile.SLOPE_FLAT; var dirs = new int[][] { new int[] { 0, 1 }, new int[] { 0, -1 }, new int[] { 1, 0 }, new int[] { -1, 0 } }; var oldDir = (cameFrom.Previous != null) ? Helper.GetDirection(cameFrom.Previous.Tile, tile) : Direction.None; foreach (var dir in dirs) { var x = dir[0]; var y = dir[1]; if (cameFrom.Tile == tile + AIMap.GetTileIndex(x, y)) { continue; } var newDir = Helper.GetDirection(tile, tile + AIMap.GetTileIndex(x, y)); var isCoast = AITile.IsCoastTile(tile); var straight = newDir == oldDir; var maxLength = 20; bool lastWasExistingBridge = false; TileIndex neighbor; for (var length = 1; AIMap.IsValidTile(neighbor = tile + AIMap.GetTileIndex(x * length, y * length)) && length <= maxLength; length++) { if (AIBridge.IsBridgeTile(neighbor)) { var otherEnd = AIBridge.GetOtherBridgeEnd(neighbor); var bridgeDir = Helper.GetDirection(neighbor, otherEnd); if (newDir == bridgeDir) { length += AIMap.DistanceManhattan(neighbor, otherEnd); lastWasExistingBridge = true; continue; } } else if (AIRoad.IsRoadTile(neighbor) && (lastWasExistingBridge || (length == 1))) { result.Add(new PathInfo( neighbor, length, oldcost + (length * 0.5), length > 1 ? BuildType.Bridge : BuildType.Basic, cameFrom )); break; } lastWasExistingBridge = false; if (isCoast) { if (!straight) { break; } if (AITile.IsWaterTile(neighbor)) { continue; } } double multiplier = 1; if (AITile.IsFarmTile(neighbor) || AITile.IsRockTile(neighbor) || AITile.IsRoughTile(tile)) { // Make farms, rocks, etc more expensive. multiplier *= 1.1; } if (AITile.IsBuildable(neighbor)) { if (isCoast) { result.Add(new PathInfo( neighbor, length, oldcost + ((length * multiplier * 2)), BuildType.Bridge, cameFrom )); break; } else if ((isFlat && cameFrom.Length == 1) || ((length == 1) && straight)) { result.Add(new PathInfo( neighbor, length, oldcost + ((length * multiplier)), length == 1 ? BuildType.Basic : BuildType.Bridge, cameFrom )); break; } } else if (!( (AIRoad.IsRoadTile(neighbor) || AIRoad.IsRoadTile(neighbor) || AITile.IsWaterTile(neighbor)) && (AITile.GetSlope(neighbor) == AITile.SLOPE_FLAT) && !AIStation.IsValidStation(AIStation.GetStationID(neighbor)))) { // Can't built over break; } } } return(result); }