function findRoadTileDepot(tile) { if(!AIRoad.IsRoadTile(tile)) { return null; } local depotTile = null; local adjacentTiles = Utils.getAdjacentTiles(tile); adjacentTiles.Valuate(AIRoad.IsRoadTile); adjacentTiles.RemoveValue(1); local roadTiles = Utils.getAdjacentTiles(tile); roadTiles.Valuate(AIRoad.IsRoadTile); roadTiles.KeepValue(1); local roadTile = null; for (roadTile = roadTiles.Begin(); roadTiles.HasNext(); roadTile = roatTiles.Next()) { if (AIRoad.AreRoadTilesConnected(roadTile, tile)) { break; } } assert(roadTile != null); for (local adjacentTile = adjacentTiles.Begin(); adjacentTiles.HasNext(); adjacentTile = adjacentTiles.Next()) { AILog.Info("roadTile = " + roadTile + "; adjacentTile = " + adjacentTile + "; tile = " + tile); if (AIRoad.AreRoadTilesConnected(tile, adjacentTile) || AITile.IsBuildable(adjacentTile) && (AITile.GetSlope(adjacentTile) == AITile.SLOPE_FLAT || !AITile.IsCoastTile(adjacentTile)) && AIRoad.CanBuildConnectedRoadPartsHere(tile, roadTile, adjacentTile)) { depotTile = adjacentTile; break; } } return depotTile; } function buildDepotOnTile(t) { local square = AITileList(); local squareSize = 1; square.AddRectangle(Utils.getValidOffsetTile(t, (-1) * squareSize, (-1) * squareSize), Utils.getValidOffsetTile(t, squareSize, squareSize)); local depotTile = findRoadTileDepot(t); local depotFrontTile = t; if(depotTile != null) { local counter = 0; do { if (!TestBuildRoadDepot().TryBuild(depotTile, depotFrontTile)) { ++counter; } else { break; } AIController.Sleep(1); } while(counter < 1); if (counter == 1) { return null; } else { local counter = 0; do { if(!TestBuildRoad().TryBuild(depotTile, depotFrontTile) && AIError.GetLastErrorString() != "ERR_ALREADY_BUILT") { ++counter; } else { break; } AIController.Sleep(1); } while(counter < 500); if (counter == 500) { local counter = 0; do { if (!TestRemoveRoadDepot().TryRemove(depotTile)) { ++counter; } else { break; } AIController.Sleep(1); } while(counter < 500); if (counter == 500) { LuDiAIAfterFix().scheduledRemovals.AddItem(depotTile, 0); return null; } else { return null; } } else { return depotTile; } } } } function buildDepotOnRoad(roadArray) { if(roadArray == null) { return null; } local depotTile = null; //first attempt, build next to the road route local arrayMiddleTile = roadArray[roadArray.len() / 2].m_tile; local roadTiles = AITileList(); for (local index = 1; index < roadArray.len() - 1; ++index) { roadTiles.AddItem(roadArray[index].m_tile, AIMap.DistanceManhattan(roadArray[index].m_tile, arrayMiddleTile)); } roadTiles.Sort(AIList.SORT_BY_VALUE, AIList.SORT_ASCENDING); for (local tile = roadTiles.Begin(); roadTiles.HasNext(); tile = roadTiles.Next()) { depotTile = buildDepotOnTile(tile); AISign.BuildSign(tile, "x"); if (depotTile != null) { return depotTile; } } local squareSize = AIGameSettings.GetValue("station_spread"); //second attempt, build closer to the destination local tileList = AITileList(); tileList.AddRectangle(Utils.getValidOffsetTile(m_stationTo, -1 * squareSize, -1 * squareSize), Utils.getValidOffsetTile(m_stationTo, squareSize, squareSize)); tileList.Valuate(AIRoad.IsRoadTile); tileList.KeepValue(1); tileList.Valuate(AIMap.DistanceManhattan, m_stationTo); tileList.Sort(AIList.SORT_BY_VALUE, AIList.SORT_ASCENDING); for (local tile = tileList.Begin(); tileList.HasNext(); tile = tileList.Next()) { depotTile = buildDepotOnTile(tile); if (depotTile != null) { return depotTile; } } //third attempt, build closer to the source tileList.Clear(); tileList.AddRectangle(Utils.getValidOffsetTile(m_stationFrom, -1 * squareSize, -1 * squareSize), Utils.getValidOffsetTile(m_stationFrom, squareSize, squareSize)); tileList.Valuate(AIRoad.IsRoadTile); tileList.KeepValue(1); tileList.Valuate(AIMap.DistanceManhattan, m_stationFrom); tileList.Sort(AIList.SORT_BY_VALUE, AIList.SORT_ASCENDING); for (local tile = tileList.Begin(); tileList.HasNext(); tile = tileList.Next()) { depotTile = buildDepotOnTile(tile); if (depotTile != null) { return depotTile; } } AILog.Warning("Couldn't built road depot!"); return depotTile; }