Пример #1
0
        internal static bool BuildRail(TileIndex previous, TileIndex from, TileIndex to, TileIndex next, HashSet <TileIndex> forbidden, int railCount = 1, Action <TileIndex, string> sign = null)
        {
            var path = RailBuilder.FindPath(from, to, previous, forbidden, sign);

            if (path == null)
            {
                return(false);
            }

            for (var i = 0; i < path.Count - 1; i++)
            {
                var p  = i == 0 ? next : path[i - 1].Tile;
                var c  = path[i].Tile;
                var n  = i == path.Count - 1 ? previous : path[i + 1].Tile;
                var nt = i == 0 ? BuildType.Basic : path[i - 1].Type;
                //sign(c, "[" + AIMap.GetTileX(c) + ", " + AIMap.GetTileY(c) + "] " + path[i].type);
                bool good = false;
                switch (path[i].Type)
                {
                case BuildType.Basic:
                    if (path[i].Length > 1)
                    {
                        throw new Exception("Should not be rail");
                    }

                    if (nt != BuildType.Basic)
                    {
                        continue;
                    }

                    //AILog.Info("Build a rail  from [" + AIMap.GetTileX(p) + ", " + AIMap.GetTileY(p) + "] via [" + AIMap.GetTileX(c) + ", " + AIMap.GetTileY(c) + "] to [" + AIMap.GetTileX(n) + ", " + AIMap.GetTileY(n) + "].");
                    good = AIRail.BuildRail(p, c, n);
                    break;

                case BuildType.Bridge:
                    var bridgeTypes = new AIBridgeList_Length(path[i].Length);
                    //AILog.Info("Build a bridge " + bridgeTypes.Begin() + " from [" + AIMap.GetTileX(c) + ", " + AIMap.GetTileY(c) + "] to [" + AIMap.GetTileX(n) + ", " + AIMap.GetTileY(n) + "].");
                    good = AIBridge.BuildBridge(AIVehicle.VT_RAIL, bridgeTypes.Begin(), c, n);
                    if (!good)
                    {
                        sign(p, "s");
                        sign(c, "e");
                    }

                    break;

                case BuildType.Tunnel:
                    throw new Exception("Tunnels not supported");
                }

                if (!good)
                {
                    AILog.Error("Failed to build on [" + AIMap.GetTileX(c) + ", " + AIMap.GetTileY(c) + "]. Reason: " + AIError.GetLastErrorString());
                }
            }

            return(true);
        }
Пример #2
0
        /// <summary>
        /// Uses A*-algorithm to find the best route between two tiles.
        /// </summary>
        /// <param name="start">First tile to search from.</param>
        /// <param name="goal">Goal to find.</param>
        /// <param name="previous">Tile just before the first tile.</param>
        /// <param name="forbidden">List of tiles that should be never used on route.</param>
        /// <param name="sign">Optional function for building signs.</param>
        /// <returns></returns>
        internal static List <PathInfo> FindPath(TileIndex start, TileIndex goal, TileIndex previous, HashSet <TileIndex> forbidden = null, Action <TileIndex, string> sign = null)
        {
            // Nodes to evaluate
            var tilesToProcess = new FibonacciHeap <TileIndex>();

            tilesToProcess.Insert(start, 0);

            // Nodes evaluated
            var cameFrom = new Dictionary <TileIndex, PathInfo>();

            cameFrom[start] = new PathInfo(start, 1, 0, BuildType.Basic, new PathInfo(previous, 1, 0, BuildType.Basic, null));

            while (tilesToProcess.Count() > 0)
            {
                var current = tilesToProcess.Pop();
                if (current == goal)
                {
                    // We found the target.
                    return(RailBuilder.BuildFinalPath(cameFrom[current]));
                }

                var neighbors = RailBuilder.GetNeighbors(current, cameFrom[current]);
                foreach (var neighborItem in neighbors)
                {
                    var neighbor = neighborItem.Tile;
                    if ((neighbor == previous) || ((forbidden != null) && forbidden.Contains(neighbor)))
                    {
                        // We can't go here.
                        continue;
                    }

                    var neighborDist = neighborItem.Length;
                    if (!cameFrom.ContainsKey(neighbor))
                    {
                        tilesToProcess.Insert(neighbor, neighborItem.Cost);
                    }
                    else
                    {
                        if (neighborItem.Cost >= cameFrom[neighbor].Cost)
                        {
                            continue;
                        }
                    }

                    sign?.Invoke(neighbor, neighborItem.Cost.ToString());
                    cameFrom[neighbor] = neighborItem;
                }
            }

            return(null);
        }
Пример #3
0
        protected /*override*/ void Start2()
        {
            SignManager signManager = new SignManager();

            this.signs = new AISignList();
            var list = new AIRailTypeList();

            AIRail.SetCurrentRailType(list.Begin());

            AICompany.SetLoanAmount(AICompany.GetMaxLoanAmount());

            ////*
            //RailBuilder.BuildRail(
            //    AIMap.GetTileIndex(42, 121),
            //    AIMap.GetTileIndex(41, 121),
            //    AIMap.GetTileIndex(31, 121),
            //    AIMap.GetTileIndex(30, 121),
            //    new HashSet<TileIndex>(),
            //    1,
            //    this.BuildSign);
            ///*/

            //var i = 39;
            //var ns = RailBuilder.GetNeighbors(
            //    AIMap.GetTileIndex(i, 121),
            //    new RailBuilder.PathInfo(
            //        AIMap.GetTileIndex(i + 1, 121),
            //        1,
            //        1,
            //        RailBuilder.BuildType.Rail,
            //        new RailBuilder.PathInfo(
            //            AIMap.GetTileIndex(i + 2, 121),
            //            1,
            //            1,
            //            RailBuilder.BuildType.Rail,
            //            null)),
            //    this.BuildSign);

            //foreach (var n in ns)
            //{
            //    this.BuildSign(n.Tile, n.Cost.ToString());
            //}
            ///* */

            ///*
            try
            {
                if (this.workStatus == 0)
                {
                    var towns = new AITownList();
                    towns.Valuate(AITown.GetPopulation);
                    RailStationBuildResult s1 = null;
                    foreach (var(town, _) in towns)
                    {
                        if (s1 == null)
                        {
                            s1 = RailStationBuilder.BuildStationNear(AITown.GetLocation(town), this.platformSize, 2);
                        }
                        else
                        {
                            RailStationBuildResult s2        = RailStationBuilder.BuildStationNear(AITown.GetLocation(town), this.platformSize, 2);
                            HashSet <TileIndex>    forbidden = new HashSet <TileIndex>();
                            forbidden.Add(s1.ExitFarther);
                            forbidden.Add(s2.EntryFarther);
                            var good = RailBuilder.BuildRail(s1.EntryCloser, s1.EntryFarther, s2.ExitFarther, s2.ExitCloser, forbidden);
                            signManager.ClearSigns();
                            if (good)
                            {
                                forbidden = new HashSet <TileIndex>();
                                good      = RailBuilder.BuildRail(s1.ExitCloser, s1.ExitFarther, s2.EntryFarther, s2.EntryCloser, forbidden, 1);
                            }

                            if (good)
                            {
                                if (s1.DepotTile != AIMap.TILE_INVALID)
                                {
                                    TrainManager.BuildTrain(s1.DepotTile, new StationID[] { s1.StationID, s2.StationID }, this.BuildSign);
                                }
                                else
                                {
                                    TrainManager.BuildTrain(s2.DepotTile, new StationID[] { s2.StationID, s1.StationID }, this.BuildSign);
                                }
                            }
                            else
                            {
                                AILog.Info("No route found.");
                            }

                            s1 = null;

                            //if (AICompany.GetBankBalance(AICompany.COMPANY_SELF) < 50000)
                            {
                                // Better to stop before bankrupcy.
                                AILog.Info("Better to stop before bankrupcy.");
                                break;
                            }
                        }
                    }
                }

                this.workStatus = 1;
            }
            catch
            {
                AILog.Error("An error happened");
            }
            /* */

            signManager.ClearSigns();
            AILog.Info("Sign count: " + this.signs.Count());
            AIController.Sleep(150);

            AILog.Info("Remove all signs");
            foreach (var(signId, _) in this.signs)
            {
                AISign.RemoveSign(signId);
            }

            while (true)
            {
                // Main loop
                //this.setMinLoan();
                CsTestAi.SetMinimumLoanAmount();
                Sleep(100);
            }
        }
Пример #4
0
        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);
        }