public static void BuildTrain(TileIndex depot, StationID[] stations, Action <TileIndex, string> sign = null) { var list = new AIEngineList(AIVehicle.VT_RAIL); list.Valuate(AIEngine.GetMaxSpeed); EngineID passangerWagon = null; EngineID mailWagon = null; foreach (var(a, b) in list) { if (AIEngine.IsBuildable(a) && !AIEngine.IsWagon(a)) { //AILog.Info(a + ": " + AIEngine.GetName(a) + " | " + AIEngine.GetMaxSpeed(a) + " | " + AIEngine.GetReliability(a) + " | " + AIEngine.GetMaxTractiveEffort(a)); } else if (AIEngine.IsBuildable(a) && AIEngine.IsWagon(a)) { //AILog.Info(a + ": " + AIEngine.GetName(a) + " | " + AIEngine.GetCargoType(a)); if (AICargo.HasCargoClass(AIEngine.GetCargoType(a), AICargo.CC_PASSENGERS)) { passangerWagon = a; //AILog.Info("passanger"); } else if (AICargo.HasCargoClass(AIEngine.GetCargoType(a), AICargo.CC_MAIL)) { mailWagon = a; //AILog.Info("mail"); } } } var engineType = list.Begin(); //AILog.Info("Engine id: " + engineType); //AILog.Info("Building: " + AIEngine.GetName(engineType)); var train = AIVehicle.BuildVehicle(depot, engineType); var firstPassanger = AIVehicle.BuildVehicle(depot, passangerWagon); AIVehicle.BuildVehicle(depot, passangerWagon); AIVehicle.BuildVehicle(depot, passangerWagon); var firstMail = AIVehicle.BuildVehicle(depot, mailWagon); AIVehicle.MoveWagonChain(firstMail, 0, train, 0); AIVehicle.MoveWagonChain(firstPassanger, 0, train, 0); for (var i = 0; i < stations.Length; i++) { AIOrder.AppendOrder(train, AIStation.GetLocation(stations[i]), AIOrder.OF_NONE); } AIVehicle.StartStopVehicle(train); }
public static RailStationBuildResult BuildStationNear(TileIndex tile, int platformLength, int platformCount = 2) { var stationTile = RailStationBuilder.FindPlaceForStation(tile, platformLength, platformCount); if (stationTile != null) { AILog.Info("Build " + stationTile.tile + ", " + stationTile.direction); var good = AIRail.BuildRailStation(stationTile.tile, stationTile.direction, platformCount, platformLength, AIStation.STATION_NEW); if (good) { TileIndex entryTile; int[] matrix; if (stationTile.direction == AIRail.RAILTRACK_NW_SE) { if (stationTile.entryNearTopCorner) { /* \ \/\ \/ */ entryTile = stationTile.tile + AIMap.GetTileIndex(0, 0); matrix = new int[] { -1, 0, 0, -1 }; } else { /* /\ \/\ \ */ entryTile = stationTile.tile + AIMap.GetTileIndex(1, platformLength - 1); matrix = new int[] { 1, 0, 0, 1 }; } } else if (stationTile.direction == AIRail.RAILTRACK_NE_SW) { if (stationTile.entryNearTopCorner) { /* / * /\/ \/ */ entryTile = stationTile.tile + AIMap.GetTileIndex(0, 1); matrix = new int[] { 0, -1, 1, 0 }; } else { /* /\ * /\/ * / */ entryTile = stationTile.tile + AIMap.GetTileIndex(platformLength - 1, 0); matrix = new int[] { 0, 1, -1, 0 }; } } else { return(null); } /* | | +00-01-+ * 02 03 * 04 05 06 07 * 08 09 * 10 11 * */ var tiles = new TileIndex[] { entryTile + RailStationBuilder.GetTransformedTileIndex(0, 0, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(-1, 0, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(0, 1, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(-1, 1, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(1, 2, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(0, 2, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(-1, 2, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(-2, 2, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(0, 3, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(-1, 3, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(0, 4, matrix), entryTile + RailStationBuilder.GetTransformedTileIndex(-1, 4, matrix), }; // Exit rail AIRail.BuildRail( tiles[0], tiles[2], tiles[10]); // Entry rail AIRail.BuildRail( tiles[1], tiles[3], tiles[11]); // Signals AIRail.BuildSignal(tiles[2], tiles[0], AIRail.SIGNALTYPE_PBS); AIRail.BuildSignal(tiles[3], tiles[1], AIRail.SIGNALTYPE_PBS); AIRail.BuildSignal(tiles[9], tiles[11], AIRail.SIGNALTYPE_PBS_ONEWAY); //Depot TileIndex depotTile = AIMap.TILE_INVALID; if (AIRail.BuildRailDepot(tiles[4], tiles[5])) { depotTile = tiles[4]; RailStationBuilder.BuildIntersection(tiles[2], tiles[4], tiles[6], tiles[8]); RailStationBuilder.BuildIntersection(tiles[3], tiles[5], tiles[9]); } else { if (AIRail.BuildRailDepot(tiles[7], tiles[6])) { depotTile = tiles[7]; RailStationBuilder.BuildIntersection(tiles[3], tiles[5], tiles[7], tiles[9]); RailStationBuilder.BuildIntersection(tiles[2], tiles[6], tiles[8]); } } return(new RailStationBuildResult() { StationID = AIStation.GetStationID(stationTile.tile), ExitCloser = tiles[8], ExitFarther = tiles[10], EntryCloser = tiles[9], EntryFarther = tiles[11], DepotTile = depotTile }); } } return(null); }
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); }
internal void UpdateRoutes() { AILog.Error(" -- UpdateRoutes --"); CargoID passangerCargo = null; var cargoList = new AICargoList(); foreach (var(cargo, _) in cargoList) { if (AICargo.HasCargoClass(cargo, AICargo.CC_PASSENGERS)) { passangerCargo = cargo; } } if (passangerCargo == null) { AILog.Error("No passanger cargo found."); return; } foreach (var edge in this.Graph.Edges) { if (!this.vehicles.ContainsKey(edge)) { continue; } var list = this.vehicles[edge]; var s1 = AIStation.GetStationID(stations[edge.Node1.TownId].tile); var s2 = AIStation.GetStationID(stations[edge.Node2.TownId].tile); var waiting1 = AIStation.GetCargoWaitingVia(s1, s2, passangerCargo); var waiting2 = AIStation.GetCargoWaitingVia(s2, s1, passangerCargo); var waiting = waiting1 + waiting2; AILog.Info($"Route from {edge.Node1.Name} to {edge.Node2.Name} has {waiting} passangers waiting."); var target = (waiting / 31) - 1; // TODO: Capacity AILog.Info($"{list.Count} vehicles operating. Target: {target}"); if (list.Count < target) { if (waiting1 > waiting2) { MakeRoute(edge.Node1, edge.Node2); } else { MakeRoute(edge.Node2, edge.Node1); } } } //var stations = new AIStationList(AIStation.STATION_BUS_STOP); //foreach (var (s1, _) in stations) //{ // AILog.Info(AIStation.GetName(s1) + ":"); // var stations2 = new AIStationList(AIStation.STATION_BUS_STOP); // var totalWaiting = AIStation.GetCargoWaiting(s1, passangerCargo); // foreach (var (s2, _) in stations2) // { // if (s1 != s2) // { // var waiting = AIStation.GetCargoWaitingVia(s1, s2, passangerCargo); // AILog.Info($"- {AIStation.GetName(s2)}: {waiting}"); // totalWaiting -= waiting; // } // } // AILog.Info($"- any: {totalWaiting}"); //} }
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 = Helper.GetDirection(tile, cameFrom.Previous.Tile); 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 + AIMap.GetTileIndex(x, y), tile); var isCoast = AITile.IsCoastTile(tile); var straight = newDir == oldDir; var maxLength = isCoast ? 20 : (straight ? 5 : 1); TileIndex neighbor; for (var length = 1; AIMap.IsValidTile(neighbor = tile + AIMap.GetTileIndex(x * length, y * length)) && length <= maxLength; length++) { 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)) { double angleFactor = RailBuilder.CalculateAngle(neighbor, tile, cameFrom.Previous); if (isCoast) { result.Add(new PathInfo( neighbor, length, oldcost + ((length * multiplier * 2) + angleFactor), BuildType.Bridge, cameFrom )); break; } else if ((isFlat && cameFrom.Length == 1) || ((length == 1) && straight)) { result.Add(new PathInfo( neighbor, length, oldcost + ((length * multiplier) + angleFactor), length == 1 ? BuildType.Basic : BuildType.Bridge, cameFrom )); break; } } else if (!( (AIRail.IsRailTile(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); }