Пример #1
0
        private IclusterIGCWrapper GetStationBuildCluster(StationType stationType)
        {
            var stations         = ClientConnection.GetSide().GetStations();
            var homeStation      = stations.Where(p => p.GetCluster().GetHomeSector() == true).FirstOrDefault();
            var homeCluster      = homeStation.GetCluster();
            var homeRock         = homeCluster.GetAsteroids().Where(p => p.GetName().StartsWith("He") == false && p.GetName().StartsWith("a") == false && String.IsNullOrWhiteSpace(p.GetName()) == false).FirstOrDefault();
            var enemyHomeCluster = ClientConnection.GetCore().GetClusters().Where(p => p.GetHomeSector() == true && p.GetObjectID() != homeCluster.GetObjectID()).FirstOrDefault();

            // Always build a home tele first if we don't have one in our home cluster.
            if (stationType == StationType.Teleport && homeCluster.GetStations().Exists(p => p.GetName().Contains("Teleport") == true) == false &&
                _constuctorsInFlightToClusterObjectIDByShipObjectID.Values.Count(r => r.Cluster.GetObjectID() == homeCluster.GetObjectID()) == 0)
            {
                Log($"There is no home teleporter yet, let's put this tele con at home: {homeCluster.GetName()}");
                return(homeCluster);
            }

            // Try to find empty clusters where we have secured all sides.
            if (stationType == StationType.Refinery)
            {
                // For hihigher, this is the middle cluster.
                Log("Checking for an empty cluster that is bordered by our own stations.");
                var goodRefCluster = ClientConnection.GetCore().GetClusters()
                                     .Where(p => p.GetStations().Count == 0 && // Make sure there are no stations in it already.
                                            _constuctorsInFlightToClusterObjectIDByShipObjectID.Values.Count(r => r.Cluster.GetObjectID() == p.GetObjectID()) == 0 && // Are any other cons heading to this cluster?
                                            GameInfo.GetUnexploredClusters(p.GetMission()).ContainsKey(p.GetObjectID()) == false && // Is this cluster fully explored?
                                            p.GetWarps().All(r =>
                                                             r.GetDestination().GetCluster().GetStations().Count > 0 && // Neighboring clusters have at least one station
                                                             r.GetDestination().GetCluster().GetStations().All(s => s.GetSide().GetObjectID() == ClientConnection.GetSide().GetObjectID()))) // And all the stations belong to our side.
                                     .FirstOrDefault();

                if (goodRefCluster != null)
                {
                    Log($"Found a good cluster for a refinery: {goodRefCluster.GetName()}");
                    return(goodRefCluster);
                }
                else
                {
                    Log($"No good refinery cluster found. Looking for a good spot on available lines.");
                }
            }

            //var availableClusters = GameInfo.Clusters.Where(p => p.GetHomeSector() == true || ClientConnection.

            var routeFinder = new DijkstraPathFinder(GameInfo.Clusters, homeCluster.GetObjectID(), enemyHomeCluster.GetObjectID());
            var singleHopClusterDistances = homeCluster.GetWarps()
                                            .ToDictionary(
                p => p.GetDestination().GetCluster(),
                r => new DijkstraPathFinder(GameInfo.Clusters, r.GetDestination().GetCluster().GetObjectID(), enemyHomeCluster.GetObjectID())
                .GetDistance(r.GetDestination().GetCluster(), enemyHomeCluster));

            List <ClusterInfo> clustersNextToHome = GameInfo.Clusters.Where(p => p.GetWarps().Exists(r => r.GetDestinationCluster().GetObjectID() == homeCluster.GetObjectID()) == true).ToList();

            // Walk each path until a station is found.
            while (clustersNextToHome.Count > 0)
            {
                var currentClusterObjectID = clustersNextToHome[_random.Next(0, clustersNextToHome.Count)];
                clustersNextToHome.Remove(currentClusterObjectID);

                var pathFinder = new DijkstraPathFinder(GameInfo.Clusters, currentClusterObjectID.GetObjectID(), enemyHomeCluster.GetObjectID());

                var currentCluster = ClientConnection.GetCore().GetCluster(currentClusterObjectID.GetObjectID());

                Log($"Considering line for {currentCluster.GetName()}");

                for (var nextClusterObjectID = (short)pathFinder.NextClusterObjectID(currentCluster.GetObjectID(), enemyHomeCluster.GetObjectID());
                     currentCluster.GetObjectID() != enemyHomeCluster.GetObjectID();
                     currentCluster = ClientConnection.GetCore().GetCluster(nextClusterObjectID), nextClusterObjectID = (short)pathFinder.NextClusterObjectID(nextClusterObjectID, enemyHomeCluster.GetObjectID()).GetValueOrDefault(-1))
                {
                    var nextCluster = ClientConnection.GetCore().GetCluster(nextClusterObjectID);

                    Log($"Considering cluster: {currentCluster.GetName()}, nextCluster: {nextCluster.GetName()}");

                    // Don't select this cluster if another constructor is already on the way to it.
                    if (_constuctorsInFlightToClusterObjectIDByShipObjectID.Values.Count(r => r.Cluster.GetObjectID() == currentCluster.GetObjectID()) > 0)
                    //if (_constuctorsInFlightToClusterObjectIDByShipObjectID.ContainsValue(currentCluster.GetObjectID()) == true)
                    {
                        Log($"There is already a constructor heading to {currentCluster.GetName()}, skipping to next sector.");
                        continue;
                    }

                    // If the station is a friendly station, then we can put a ref or tech base next to it.
                    if (ClientConnection.GetCore().GetCluster(nextClusterObjectID).GetStations().Exists(p => p.GetSide().GetObjectID() == ClientConnection.GetSide().GetObjectID()) == true)
                    {
                        Log($"Friendly station found in nextCluster: {nextCluster.GetName()}");

                        // We don't want to put an output behind another friendly station. See if we can get closer!
                        if (stationType == StationType.Outpost)
                        {
                            Log("There is an outpost already in this line, so we don't want to put another one behind it.");
                            continue;
                        }

                        // If this matches to our home tech rock, then let's drop it here.
                        if (stationType == StationType.Teleport)
                        {
                            // If the sector already has a teleport, then see if we can get closer!
                            if (ClusterContainsStation(StationType.Teleport, currentCluster) == true)
                            {
                                Log("There is already a teleport here, seeing if we can get closer.");
                                continue;
                            }

                            // If the sector's tech rock matches the home rock, then put a tele in it.
                            if (currentCluster.GetStations().Count == 0 && GetClusterTechRock(currentCluster).GetName()[0] == homeRock.GetName()[0])
                            {
                                Log("There is a good tech rock here, let's a put a tele here too!");
                                return(currentCluster);
                            }
                        }

                        // We have a covering station in front of this one, so this is a good sector use for mining or tech bases, but we want refs to be as close to home as possible.
                        if (stationType == StationType.Refinery &&
                            ClusterContainsStation(StationType.Refinery, currentCluster) == false)
                        {
                            var homeSectorPath            = new DijkstraPathFinder(ClientConnection.GetCore(), currentCluster, homeCluster);
                            IclusterIGCWrapper refCluster = currentCluster;
                            for (nextCluster = currentCluster; nextCluster != homeCluster && nextCluster != null; nextCluster = homeSectorPath.NextCluster(nextCluster, homeCluster))
                            {
                                if (nextCluster.GetStations().Count(p => p.GetSide().GetObjectID() == ClientConnection.GetSide().GetObjectID()) > 0)
                                {
                                    Log($"Found a refinery cluster that is on a line protected by another station, with a friendly station backing it: {refCluster.GetName()}");
                                    return(refCluster);
                                }

                                refCluster = nextCluster;
                            }

                            //Log($"This is good spot for a refinery! Recommending: {currentCluster.GetName()}");
                            //return currentCluster;
                        }

                        if (stationType == StationType.Garrison &&
                            ClusterContainsStation(StationType.Garrison, currentCluster) == false)
                        {
                            Log($"This is good spot for a garrison! Recommending: {currentCluster.GetName()}");
                            return(currentCluster);
                        }

                        if (stationType == StationType.ShipYard &&
                            ClusterContainsStation(StationType.ShipYard, currentCluster) == false)
                        {
                            Log($"This is good spot for a ship yard! Recommending: {currentCluster.GetName()}");
                            return(currentCluster);
                        }

                        if (stationType == StationType.Supremacy && ClusterContainsStation(StationType.Supremacy, currentCluster) == false)
                        {
                            Log($"This is good spot for a supremacy! Recommending: {currentCluster.GetName()}");
                            return(currentCluster);
                        }

                        if (stationType == StationType.Expansion && ClusterContainsStation(StationType.Expansion, currentCluster) == false)
                        {
                            Log($"This is good spot for an expansion! Recommending: {currentCluster.GetName()}");
                            return(currentCluster);
                        }

                        if (stationType == StationType.Tactical && ClusterContainsStation(StationType.Tactical, currentCluster) == false)
                        {
                            Log($"This is good spot for a tactical! Recommending: {currentCluster.GetName()}");
                            return(currentCluster);
                        }
                    }

                    // If the station is an enemy station, then we want to put a tele or outpost next to it.
                    if (ClientConnection.GetCore().GetCluster(nextClusterObjectID).GetStations().Exists(p => p.GetSide().GetObjectID() != ClientConnection.GetSide().GetObjectID()) == true ||
                        (nextCluster.GetAsteroids().Count == 0 && ClientConnection.GetCore().GetCluster(nextClusterObjectID).GetHomeSector() == true))    // If we haven't actually eyed the enemy home, then we know their garrison is in there.
                    {
                        Log($"Next sector: {nextCluster.GetName()} has an enemy station in it.");

                        // Always put outposts next to enemy stations. That's our favorite!
                        if (stationType == StationType.Outpost && ClusterContainsStation(StationType.Outpost, currentCluster) == false)
                        {
                            Log($"Found a good cluster for this outpost: {currentCluster.GetName()}, next to an enemy sector.");
                            return(currentCluster);
                        }

                        // If the target sector doesn't already have an outpost in it, then put a tele one sector back if possible to allow an outpost to come forward.
                        if (stationType == StationType.Teleport && ClusterContainsStation(StationType.Outpost, currentCluster) == false)
                        {
                            var previousCluster = ClientConnection.GetCore().GetCluster((short)pathFinder.NextClusterObjectID(currentCluster.GetObjectID(), homeCluster.GetObjectID()));

                            if (previousCluster.GetStations().Count == 0)
                            {
                                Log($"There is an open cluster in {previousCluster.GetName()}, let's send the tele to there!");
                                return(previousCluster);
                            }
                        }
                    }
                }
            }

            if (stationType == StationType.Refinery)
            {
                Log($"No good cluster found for this refinery, waiting for a good option to appear.");
                return(null);
            }


            Log($"No targeted clusters were found, placing con in a random open cluster.");

            // No targeted clusters were found, let's go with any random empty cluster that we know about.
            var emptyClusters = ClientConnection.GetCore().GetClusters().Where(p => p.GetAsteroids().Count > 0 &&
                                                                               p.GetStations().Count == 0 &&
                                                                               _constuctorsInFlightToClusterObjectIDByShipObjectID.Values.Count(r => r.Cluster.GetObjectID() == p.GetObjectID()) == 0)
                                .ToArray();

            if (emptyClusters.Count() == 0)
            {
                return(null);
            }

            var targetCluster = emptyClusters[_random.Next(0, emptyClusters.Count())];

            Log($"Selecting random cluster: {targetCluster.GetName()} as target.");

            return(targetCluster);



            //int minHops = singleHopClusterDistances.Select(p => p.Value).OrderBy(p => p).First();
            //var bestClusterRoutesForOutposts = singleHopClusterDistances.Where(p => p.Value == minHops).ToDictionary(p => p.Key, r => r.Value);

            //foreach (var cluster in bestClusterRoutesForOutposts.Keys)
            //{
            //    Log($"Start: {cluster.GetName()}");

            //    routeFinder = new DijkstraPathFinder(GameInfo.Clusters, cluster.GetObjectID(), enemyHomeCluster.GetObjectID());

            //    for (var nextCluster = routeFinder.NextClusterObjectID(cluster.GetObjectID(), enemyHomeCluster.GetObjectID()); nextCluster != null; nextCluster = routeFinder.NextClusterObjectID(nextCluster.GetValueOrDefault(0), enemyHomeCluster.GetObjectID()))
            //    {
            //        Log($"\tNext: {ClientConnection.GetCore().GetCluster((short)nextCluster.GetValueOrDefault(0)).GetName()}");
            //    }
            //}
        }