private void expandQueue(Queue <Point2D> queue, Point2D point, ImageData map, int[,] distances, int newVal) { int x = (int)point.X; int y = (int)point.Y; List <Point2D> nearbyPoints = new List <Point2D>(); nearbyPoints.Add(new Point2D { X = x + 1, Y = y }); nearbyPoints.Add(new Point2D { X = x - 1, Y = y }); nearbyPoints.Add(new Point2D { X = x, Y = y + 1 }); nearbyPoints.Add(new Point2D { X = x, Y = y - 1 }); foreach (Point2D p in nearbyPoints) { if (p.X < 0 || p.X > map.Size.X - 1 || p.Y < 0 || p.Y > map.Size.Y - 1) { continue; } if (Sc2Util.ReadTile(map, (int)p.X, map.Size.Y - (int)p.Y - 1) && distances[(int)p.X, (int)p.Y] == 100000000) { queue.Enqueue(p); distances[(int)p.X, (int)p.Y] = newVal; } } }
public override void OnFrame() { KnownBuildings = new List <Unit>(); KnownArmy = new List <Unit>(); var enemyUnits = Controller.GetEnemyUnits(); foreach (Unit u in enemyUnits) { if (Units.Structures.Contains(u.UnitType)) { KnownBuildings.Add(u); } else { KnownArmy.Add(u); } } if (KnownBuildings.Count > 0) { VBot.Bot.Map.TargetAttackLocation = Sc2Util.To2D(KnownBuildings[0].Pos); } else if (KnownArmy.Count > 2) // set to 2 to avoid chasing single workers that are scouting { VBot.Bot.Map.TargetAttackLocation = Sc2Util.To2D(KnownArmy[0].Pos); } else { if (VBot.Bot.Map.TargetAttackLocation != VBot.Bot.Map.EnemyStartLocations[0]) { VBot.Bot.Map.TargetAttackLocation = VBot.Bot.Map.EnemyStartLocations[0]; } } }
public List <Point2D> GetScoutLocations() { List <Point2D> baseLocations = BaseLocations .Select(b => Sc2Util.To2D(b.Location)) .OrderBy(b => WalkingDistanceFromEnemy(b)) .ToList(); return(baseLocations); }
/// <summary> /// Get the agent from a collection of units that is nearest to the agent with the given tag /// </summary> /// <param name="units">a collection of agents to check</param> /// <param name="tag">the unit tag of the desired unit. MUST BE AN AGENT</param> /// <returns>the agent that is nearest to the unit with the matching tag, or null if the tag is invalid, or the unit collection is empty</returns> public static Agent GetAgentNear(IEnumerable <Unit> units, ulong tag) { Agent a = GetAgentByTag(tag); if (a == null) { return(null); } return(GetAgentNear(units, Sc2Util.To2D(a.Unit.Pos))); }
/// <summary> /// A function that gets a valid location for a structure of the type specified in the main base /// </summary> /// <param name="unitType">the type for a gas geyser</param> /// <returns>the tag of the unbuild geyser to build a gas on, 0 if none are found</returns> public static ulong FindGasPlacement() { List <Point> gasLocations = GetGasLocations(); ulong constructionTag = 0; foreach (var rc in GetAgents(Units.ResourceCenters)) { foreach (var gas in GetUnits(Units.GasGeysers)) { if (!IsInRange(Sc2Util.To2D(gas.Pos), gasLocations, 4) && DistanceBetweenSq(rc.Unit.Pos, gas.Pos) < 81) { constructionTag = gas.Tag; return(constructionTag); } } } return(constructionTag); }
/// <summary> /// Get a location to place a creep tumor /// </summary> /// <param name="startPoint">the location of the queen or tumor that spreads the creep. MUST BE A PATHABLE TILE</param> /// <param name="towards">the direction of the desired creepspread</param> /// <param name="range">how far from the startpoint it can spread to.</param> /// <returns>a location that is valid for a tumor to be placed. Null if none can be found</returns> public static Point2D GetTumorLocation(Point2D startPoint, Point2D towards, int range) { int[,] distances; if (towards == VBot.Bot.Map.EnemyStartLocations[0]) { distances = VBot.Bot.Map.DistancesToEnemy; } else { distances = VBot.Bot.Map.GenerateDistances(towards); } Point2D closestPoint = null; int minDist = 100000000; List <Point> tumorLocations = GetAgents(Units.AllCreep).Select(a => a.Unit.Pos).ToList(); for (int i = -range; i <= range; i++) { for (int j = -range; j < range + 1; j++) { // check if it is creep var creepMap = VBot.Bot.Observation.Observation.RawData.MapState.Creep; Point2D testLoc = new Point2D { X = startPoint.X + i, Y = startPoint.Y + j }; if (!Sc2Util.ReadTile(creepMap, testLoc)) { continue; } if (distances[(int)testLoc.X, (int)testLoc.Y] < minDist && !IsInRange(testLoc, tumorLocations, 5)) { minDist = distances[(int)testLoc.X, (int)testLoc.Y]; closestPoint = testLoc; } } } if (closestPoint == null) { return(null); } return(closestPoint); }
public override void OnFrame() { // queen logic if (Queen.Unit.Energy >= 25) { Queen.Order(Abilities.SPREAD_CREEP_QUEEN, Controller.GetTumorLocation(Sc2Util.To2D(Queen.Unit.Pos), 12)); // Acts as EXECUTE statement } // add active tumors to tumor list foreach (Agent t in Controller.GetAgents(Units.CREEP_TUMOR_BURROWED)) { if (t.Command == null) { if (!ActiveTumors.ContainsKey(t)) { ActiveTumors.Add(t, VBot.Bot.Observation.Observation.GameLoop); } } } List <Agent> removeTumors = new List <Agent>(); // tumor logic foreach (var tumor in ActiveTumors) { if ((VBot.Bot.Observation.Observation.GameLoop - tumor.Value) < 400) { continue; } else { tumor.Key.Order(Abilities.SPREAD_CREEP_TUMOR, Controller.GetTumorLocation(Sc2Util.To2D(tumor.Key.Unit.Pos), 7)); // acts as EXECUTE statement removeTumors.Add(tumor.Key); } } foreach (var tumor in removeTumors) { ActiveTumors.Remove(tumor); } }
/// <summary> /// checks if the bot has vision of a tile on the map. /// </summary> /// <param name="loc">A Point2D that you want to check the vision of</param> /// <returns>true if the bot actively has vision of the location, false otherwise</returns> public static bool HasVision(Point2D loc) { return(Sc2Util.ReadTile(VBot.Bot.Observation.Observation.RawData.MapState.Visibility, loc)); }
/// <summary> /// This function ensures drones are harvesting optimally across different bases /// </summary> public static void DistributeWorkers() { List <Agent> resourceCenters = GetAgents(Units.ResourceCenters); List <Agent> Geysers = GetAgents(Units.GasGeysers); List <Agent> Workers = GetAgents(Units.Workers).ToList(); List <Unit> mineralPatches = GetUnits(Units.MineralFields); bool oversaturatedGases = false; // step 1 - add drones to gas int workersOnGas = 0; int maxGasPotential = 0; foreach (var gas in Geysers) { if (gas.Unit.AssignedHarvesters > gas.Unit.IdealHarvesters) { oversaturatedGases = true; } workersOnGas += gas.Unit.AssignedHarvesters; maxGasPotential += gas.Unit.IdealHarvesters; } if (workersOnGas < VBot.Bot.Build.IdealGasWorkers && workersOnGas < maxGasPotential) { int idealWorkerCount = maxGasPotential < VBot.Bot.Build.IdealGasWorkers ? maxGasPotential : VBot.Bot.Build.IdealGasWorkers; int workersToTransfer = idealWorkerCount - workersOnGas; Queue <Agent> agentsForGas = new Queue <Agent>(); for (int i = 0; i < workersToTransfer; i++) { var newWorker = GetWorker(); if (newWorker == null) { continue; } agentsForGas.Enqueue(newWorker); newWorker.Busy = true; } foreach (Agent gas in Geysers) { int transfers = gas.Unit.IdealHarvesters - gas.Unit.AssignedHarvesters; for (int i = 0; i < transfers; i++) { if (agentsForGas.Count > 0) { agentsForGas.Dequeue().Order(Abilities.SMART, gas.Unit.Tag); } } } } // step 2 - remove drones from oversaturated gas if (oversaturatedGases) { foreach (var gas in Geysers) { if (gas.Unit.IdealHarvesters < gas.Unit.AssignedHarvesters) { List <Agent> workersToRemove = new List <Agent>(); for (int i = 0; i < gas.Unit.AssignedHarvesters - gas.Unit.IdealHarvesters; i++) { Agent worker = Workers .Where(w => w.Unit.Orders.Count() > 0) .Where(w => w.Unit.Orders[0].TargetUnitTag == gas.Unit.Tag).FirstOrDefault(); worker.Busy = false; workersToRemove.Add(worker); } ulong mineralTag = GetUnits(Units.MineralFields) .Where(m => DistanceBetweenSq(m.Pos, gas.Unit.Pos) < 100) .FirstOrDefault().Tag; var action = new ActionRawUnitCommand { AbilityId = (int)Abilities.SMART, TargetUnitTag = mineralTag, }; action.UnitTags.AddRange(workersToRemove.Select(w => w.Unit.Tag)); VBot.Bot.AddAction(action); return; } } } // step 3 - remove drones if over ideal drone count if (workersOnGas > VBot.Bot.Build.IdealGasWorkers) { int workersToRemoveCount = workersOnGas - VBot.Bot.Build.IdealGasWorkers; List <Agent> workersToRemove = new List <Agent>(); ulong mineralTag = 0; while (workersToRemoveCount > 0) { workersToRemoveCount--; foreach (Agent gas in Geysers) { if (gas.Unit.AssignedHarvesters == 0) { continue; } Agent worker = Workers .Where(w => w.Unit.Orders.Count() > 0) .Where(w => w.Unit.Orders[0].TargetUnitTag == gas.Unit.Tag).FirstOrDefault(); if (worker == null) { return; } workersToRemove.Add(worker); mineralTag = GetUnits(Units.MineralFields) .Where(m => DistanceBetweenSq(m.Pos, gas.Unit.Pos) < 100) .FirstOrDefault().Tag; } } ActionRawUnitCommand action = new ActionRawUnitCommand { AbilityId = (int)Abilities.SMART, TargetUnitTag = mineralTag, }; action.UnitTags.AddRange(workersToRemove.Select(w => w.Unit.Tag)); VBot.Bot.AddAction(action); } // step 4 - move idle works to mineral patches if (VBot.Bot.Observation.Observation.PlayerCommon.IdleWorkerCount > 0) { var idleWorkers = GetAgents(Units.Workers).Where(a => a.Unit.Orders.Count == 0); Agent desiredRc = null; foreach (Agent rc in resourceCenters) { if (rc.Unit.AssignedHarvesters < rc.Unit.IdealHarvesters) { desiredRc = rc; break; } } if (desiredRc == null) { desiredRc = resourceCenters[0]; } var mineralPatch = GetAgentNear(mineralPatches, Sc2Util.To2D(desiredRc.Unit.Pos)); ActionRawUnitCommand command = new ActionRawUnitCommand(); command.UnitTags.Add(idleWorkers.Select(w => w.Unit.Tag)); command.AbilityId = (int)Abilities.SMART; command.TargetUnitTag = mineralPatch.Unit.Tag; VBot.Bot.AddAction(command); } // step 5 - transfer workers around minerals Agent fromRC = null; Agent toRC = null; foreach (Agent rc in resourceCenters) { if (rc.Unit.AssignedHarvesters == rc.Unit.IdealHarvesters) { continue; } if (rc.Unit.AssignedHarvesters > rc.Unit.IdealHarvesters) { fromRC = rc; } else { toRC = rc; } } if (fromRC != null && toRC != null) { Agent workerToTransfer = Workers .Where(w => w.Unit.Orders.Count > 0 && Abilities.MiningMinerals.Contains(w.Unit.Orders[0].AbilityId) && DistanceBetweenSq(w.Unit.Pos, fromRC.Unit.Pos) < 100) .FirstOrDefault(); Agent mineralPatch = GetAgentNear(mineralPatches, toRC.Unit.Tag); ActionRawUnitCommand action = new ActionRawUnitCommand(); action.UnitTags.Add(workerToTransfer.Unit.Tag); action.TargetUnitTag = mineralPatch.Unit.Tag; action.AbilityId = (int)Abilities.SMART; VBot.Bot.AddAction(action); } }