コード例 #1
0
 private void BuildQueen(GameState gameState, ZergBuilding hatchery, List <Command> commands)
 {
     if (gameState.Observation.PlayerCommon.Minerals < 150 ||
         gameState.Observation.PlayerCommon.FoodUsed > gameState.Observation.PlayerCommon.FoodCap - 2)
     {
         return;
     }
     commands.Add(hatchery.Train(ZergUnitType.Queen));
 }
コード例 #2
0
        private void Attack(GameState gameState, ZergBuilding hatchery, List <ZergUnit> soldiers, List <Command> commands)
        {
            // Initially, await X idle soldiers and send them toward the enemy's starting location.
            // Once they're there and have no further orders, send them to attack any sighted enemy unit/structure.
            // Once we run out of those, send them to scout every resource deposit until we find more.
            var enemyStartLocation = gameState.MapData.Raw.StartLocations.OrderByDescending(point => hatchery.GetDistance(point)).First();

            var idleSoldiers = soldiers.Where(s => s.Raw.Orders.Count == 0).ToList();

            if (!soldiers.Any(s => s.GetDistance(enemyStartLocation) < 5f) ||
                gameState.EnemyUnits.Any(e => e.GetDistance(enemyStartLocation) < 10f))
            {
                if (idleSoldiers.Count >= AttackThreshold)
                {
                    foreach (var soldier in idleSoldiers)
                    {
                        commands.Add(soldier.AttackMove(enemyStartLocation.X, enemyStartLocation.Y));
                    }
                }

                return;
            }

            if (gameState.EnemyUnits.Count > 0)
            {
                foreach (var soldier in idleSoldiers)
                {
                    commands.Add(soldier.AttackMove(gameState.EnemyUnits[0].X, gameState.EnemyUnits[0].Y));
                }

                return;
            }

            var unscoutedLocations = gameState.MapData.Deposits.Select(d => d.Center).ToList();

            foreach (var location in unscoutedLocations)
            {
                if (soldiers.Any(s => s.GetDistance(location) < 5f ||
                                 s.Raw.Orders.Any(o => o.TargetWorldSpacePos.GetDistance(location) < 5f)))
                {
                    continue;
                }

                if (idleSoldiers.Count == 0)
                {
                    break;
                }

                commands.Add(idleSoldiers[0].AttackMove(location));
                idleSoldiers.RemoveAt(0);
            }
        }
コード例 #3
0
        public IReadOnlyList <Command> Act(GameState gameState)
        {
            var commands = new List <Command>();

            if (sleep > 0)
            {
                sleep--;
                return(commands);
            }
            ZergBuilding hatchery  = null;
            ZergBuilding pool      = null;
            var          workers   = new List <ZergUnit>();
            var          lings     = new List <ZergUnit>();
            var          idleLarva = new List <ZergUnit>();


            foreach (var unit in gameState.Units)
            {
                if (unit is ZergBuilding zergBuilding)
                {
                    if (zergBuilding.ZergBuildingType == ZergBuildingType.Hatchery ||
                        zergBuilding.ZergBuildingType == ZergBuildingType.Lair ||
                        zergBuilding.ZergBuildingType == ZergBuildingType.Hive)
                    {
                        if (zergBuilding.X == primaryHatcheryX || zergBuilding.Y == primaryHatcheryY)
                        {
                            hatchery = zergBuilding;
                        }
                        else
                        {
                            if (first)
                            {
                                hatchery         = zergBuilding;
                                primaryHatcheryX = hatchery.X;
                                primaryHatcheryY = hatchery.Y;
                            }
                            // we proooobably don't care about secondary hatcheries, but if we did they'd go here.
                        }
                    }
                    if (zergBuilding.ZergBuildingType == ZergBuildingType.SpawningPool)
                    {
                        pool = zergBuilding;
                    }
                }
                else if (unit is ZergUnit zUnit)
                {
                    if (zUnit.ZergUnitType == ZergUnitType.Drone)
                    {
                        workers.Add(zUnit);
                    }
                    else if (zUnit.ZergUnitType == ZergUnitType.Zergling)
                    {
                        lings.Add(zUnit);
                    }
                    if (zUnit.ZergUnitType == ZergUnitType.Larva)
                    {
                        idleLarva.Add(zUnit);
                    }
                }
            }
            if (hatchery == null)
            {
                // Accept death as inevitable.
                return(new List <Command>());

                // TODO: Surrender?
            }
            Deposit closestDeposit = gameState.MapData.Deposits.OrderBy(d => hatchery.GetDistance(d.Center)).First();

            var mineralDeposits = closestDeposit.Resources.Where(u => u.IsMineralDeposit).ToList();

            // First update, ignore the default worker orders, which are to mass on the center mineral deposit
            // (this ends up causing problems since we have to keep track of who is harvesting what ourselves)
            if (first)
            {
                foreach (var worker in workers)
                {
                    worker.Raw.Orders.Clear();
                }

                workersByMineralDeposit = mineralDeposits.ToDictionary(m => m.Raw.Tag, m => new List <ulong>());
            }

            if (pool == null)
            {
                TryBuildPool(gameState, workers, commands);
            }

            if (idleLarva.Any())
            {
                if (pool?.IsBuilt == true)
                {
                    BuildAllLings(gameState, idleLarva, commands);
                }

                if (gameState.Observation.PlayerCommon.FoodCap - gameState.Observation.PlayerCommon.FoodUsed <= 2 &&
                    !gameState.Units.Any(u => u is ZergUnit zU && zU.ZergUnitType == ZergUnitType.Cocoon && zU.RawType.Armor >= 10))
                // HACK: Cocoons *also* signify Baneling, Ravager, Lurker, Overseer, and Broodlord, so we check for high-armor Cocoons, because Larva create the highest armor Cocoons.
                // if it's stupid, but it works... still stupid and a little shameful.
                {
                    BuildOverlord(gameState, idleLarva, commands);
                }
                // Could not find a larva timer in the SC2 API.
                if (idleLarva.Count >= 3)
                {
                    BuildWorker(gameState, idleLarva, commands);
                }
            }

            // This bot isn't exactly aiming for the stars in terms of the tech tree, so we can get away with this. Revisit if you're shamelessly bastardizing this code.
            BuildHatchery(gameState, workers, closestDeposit, commands);

            // TODO: Vespene is important for Zerg.

            commands = commands.Take(1).ToList();

            // If we tell a worker to build something, make sure we don't think he's harvesting
            if (commands.Count == 1)
            {
                sleep = 1;
                RemoveWorkerFromHarvestAssignments(commands[0].Unit);
            }

            // No matter what else happens, we can always attack, and we should always set idle workers to harvest minerals
            Attack(gameState, hatchery, lings, commands);
            SetIdleWorkerToHarvest(gameState, workers, mineralDeposits, commands);

            if (first)
            {
                first = false;

                // Make sure workers don't automatically harvest minerals, since we're managing assignments ourselves
                commands.Add(hatchery.RallyWorkers(hatchery.Raw.Pos.X, hatchery.Raw.Pos.Y));
            }

            return(commands);
        }
コード例 #4
0
        public IReadOnlyList <Command> Act(GameState gameState)
        {
            var commands = new List <Command>();

            if (sleep > 0)
            {
                sleep--;
                return(commands);
            }
            ZergBuilding hatchery            = null;
            ZergBuilding pool                = null;
            var          workers             = new List <ZergUnit>();
            var          lings               = new List <ZergUnit>();
            var          idleLarva           = new List <ZergUnit>();
            var          queens              = new List <ZergUnit>();
            var          secondaryHatcheries = new List <ZergBuilding>();

            foreach (var unit in gameState.Units)
            {
                if (unit is ZergBuilding zergBuilding)
                {
                    if (zergBuilding.ZergBuildingType == ZergBuildingType.Hatchery ||
                        zergBuilding.ZergBuildingType == ZergBuildingType.Lair ||
                        zergBuilding.ZergBuildingType == ZergBuildingType.Hive)
                    {
                        if (zergBuilding.X == primaryHatcheryX || zergBuilding.Y == primaryHatcheryY)
                        {
                            hatchery = zergBuilding;
                        }
                        else
                        {
                            if (primaryHatcheryX == -1.0f && primaryHatcheryY == -1.0f)
                            {
                                hatchery         = zergBuilding;
                                primaryHatcheryX = hatchery.X;
                                primaryHatcheryY = hatchery.Y;
                            }
                            secondaryHatcheries.Add(zergBuilding);
                        }
                    }
                    if (zergBuilding.ZergBuildingType == ZergBuildingType.SpawningPool)
                    {
                        pool = zergBuilding;
                    }
                }
                else if (unit is ZergUnit zUnit)
                {
                    if (zUnit.ZergUnitType == ZergUnitType.Drone)
                    {
                        workers.Add(zUnit);
                    }
                    else if (zUnit.ZergUnitType == ZergUnitType.Zergling)
                    {
                        lings.Add(zUnit);
                    }
                    else if (zUnit.ZergUnitType == ZergUnitType.Larva)
                    {
                        idleLarva.Add(zUnit);
                    }
                    else if (zUnit.ZergUnitType == ZergUnitType.Queen)
                    {
                        queens.Add(zUnit);
                    }
                }
            }
            if (hatchery == null)
            {
                // Accept death as inevitable.
                return(new List <Command>());

                // TODO: Surrender?
            }
            var hatcheries = secondaryHatcheries.ToList();

            hatcheries.Add(hatchery);

            if (idleLarva.Any())
            {
                BuildOverlord(gameState, idleLarva, commands);
            }
            if (pool == null)
            {
                TryBuildPool(gameState, workers, commands);
            }
            if (pool?.IsBuilt == true)
            {
                if (idleLarva.Any())
                {
                    if (pool?.IsBuilt == true)
                    {
                        BuildAllLings(gameState, idleLarva, commands);
                    }
                }
                if (hatcheries.Count() > queens.Count() && !gameState.Units.Any(u => u.IsBuilding(ZergUnitType.Queen)))
                {
                    BuildQueen(gameState, hatchery, commands);
                }
            }

            // This bot isn't exactly aiming for the stars in terms of the tech tree, so we can get away with this. Revisit if you're shamelessly bastardizing this code.
            // only expand hatcheries if mineral production >> zergling production. Also only build one because we don't expand.
            if (gameState.Observation.PlayerCommon.Minerals >= 1500)
            {
                BuildHatchery(gameState, workers, commands);
            }

            // TODO: Vespene is important for Zerg.

            commands = commands.Take(1).ToList();

            // If we tell a worker to build something, make sure we don't think he's harvesting
            if (commands.Count == 1)
            {
                sleep = 1;
                economyBot.RemoveWorkerFromHarvestAssignments(commands[0].Unit);
            }

            economyBot.AutoBuildWorkers = !(gameState.Observation.PlayerCommon.FoodCap - gameState.Observation.PlayerCommon.FoodUsed < 3);

            commands.AddRange(economyBot.Act(gameState));

            return(commands);
        }
コード例 #5
0
 public static bool IsSpawningLarva(this ZergBuilding hatchery)
 {
     return(hatchery.HasBuff(BuffType.SpawnLarva));
 }