private void DetermineWall(BoolGrid ramp, BoolGrid unPathable) { BoolGrid rampAdjacent = unPathable.GetAdjacent(ramp); BoolGrid rampSides = unPathable.GetConnected(rampAdjacent, 5); List <BoolGrid> sides = rampSides.GetGroups(); BoolGrid shrunkenStart = StartArea.Shrink(); List <Point2D> building1Positions = Placable(sides[0], shrunkenStart).ToList(); List <Point2D> building2Positions = Placable(sides[1], shrunkenStart).ToList(); float wallScore = 1000; foreach (Point2D p1 in building1Positions) { foreach (Point2D p2 in building2Positions) { if (System.Math.Abs(p1.X - p2.X) < 3 && System.Math.Abs(p1.Y - p2.Y) < 3) { continue; } float newScore = SC2Util.DistanceGrid(p1, p2); if (newScore >= wallScore) { continue; } for (float i = -2.5f; i < 3; i++) { if (CheckPylon(SC2Util.Point(p1.X + 2.5f, p1.Y + i), p1, p2)) { wallScore = newScore; building1 = p1; building2 = p2; building3 = SC2Util.Point(p1.X + 2.5f, p1.Y + i); } if (CheckPylon(SC2Util.Point(p1.X - 2.5f, p1.Y + i), p1, p2)) { wallScore = newScore; building1 = p1; building2 = p2; building3 = SC2Util.Point(p1.X - 2.5f, p1.Y + i); } if (CheckPylon(SC2Util.Point(p1.X + i, p1.Y + 2.5f), p1, p2)) { wallScore = newScore; building1 = p1; building2 = p2; building3 = SC2Util.Point(p1.X + i, p1.Y + 2.5f); } if (CheckPylon(SC2Util.Point(p1.X + i, p1.Y - 2.5f), p1, p2)) { wallScore = newScore; building1 = p1; building2 = p2; building3 = SC2Util.Point(p1.X + i, p1.Y - 2.5f); } } } } }
public Point2D GetEnemyRamp() { if (EnemyRamp != null) { return(EnemyRamp); } if (Bot.Main.TargetManager.PotentialEnemyStartLocations.Count != 1) { return(null); } int width = Bot.Main.GameInfo.StartRaw.MapSize.X; int height = Bot.Main.GameInfo.StartRaw.MapSize.Y; Point2D start = Bot.Main.TargetManager.PotentialEnemyStartLocations[0]; BoolGrid enemyStartArea = Placement.GetConnected(start); BoolGrid chokes = Placement.Invert().GetAnd(Pathable); BoolGrid mainExits = chokes.GetAdjacent(enemyStartArea); int[,] startDistances = Distances(SC2Util.To2D(StartLocation)); int dist = 1000; Point2D mainRamp = null; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (mainExits[x, y]) { int newDist = startDistances[x, y]; FileUtil.Debug("Ramp distance: " + newDist); if (newDist < dist) { dist = newDist; mainRamp = SC2Util.Point(x, y); } } } } BoolGrid enemyRamp = chokes.GetConnected(mainRamp); float totalX = 0; float totalY = 0; float count = 0; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (enemyRamp[x, y]) { totalX += x; totalY += y; count++; } } } EnemyRamp = new Point2D() { X = totalX / count, Y = totalY / count }; return(EnemyRamp); }
public void Analyze(Bot bot) { // Determine the start location. foreach (Unit unit in bot.Observation.Observation.RawData.Units) { if (unit.Owner == bot.PlayerId && UnitTypes.ResourceCenters.Contains(unit.UnitType)) { StartLocation = unit.Pos; } } List <MineralField> mineralFields = new List <MineralField>(); foreach (Unit mineralField in bot.Observation.Observation.RawData.Units) { if (UnitTypes.MineralFields.Contains(mineralField.UnitType)) { mineralFields.Add(new MineralField() { Pos = mineralField.Pos, Tag = mineralField.Tag }); } } // The Units provided in our observation are not guaranteed to be in the same order every game. // To ensure the base finding algorithm finds the same base location every time we sort the mineral fields by position. mineralFields.Sort((a, b) => (int)(2 * (a.Pos.X + a.Pos.Y * 10000 - b.Pos.X - b.Pos.Y * 10000))); Dictionary <ulong, int> mineralSetIds = new Dictionary <ulong, int>(); List <List <MineralField> > mineralSets = new List <List <MineralField> >(); int currentSet = 0; foreach (MineralField mineralField in mineralFields) { if (mineralSetIds.ContainsKey(mineralField.Tag)) { continue; } BaseLocation baseLocation = new BaseLocation(); BaseLocations.Add(baseLocation); mineralSetIds.Add(mineralField.Tag, currentSet); baseLocation.MineralFields.Add(mineralField); for (int i = 0; i < baseLocation.MineralFields.Count; i++) { MineralField mineralFieldA = baseLocation.MineralFields[i]; foreach (MineralField closeMineralField in mineralFields) { if (mineralSetIds.ContainsKey(closeMineralField.Tag)) { continue; } if (SC2Util.DistanceSq(mineralFieldA.Pos, closeMineralField.Pos) <= 4 * 4) { mineralSetIds.Add(closeMineralField.Tag, currentSet); baseLocation.MineralFields.Add(closeMineralField); } } } currentSet++; } List <Gas> gasses = new List <Gas>(); foreach (Unit unit in bot.Observation.Observation.RawData.Units) { if (UnitTypes.GasGeysers.Contains(unit.UnitType)) { gasses.Add(new Gas() { Pos = unit.Pos, Tag = unit.Tag }); } } // The Units provided in our observation are not guaranteed to be in the same order every game. // To ensure the base finding algorithm finds the same base location every time we sort the gasses by position. gasses.Sort((a, b) => (int)(2 * (a.Pos.X + a.Pos.Y * 10000 - b.Pos.X - b.Pos.Y * 10000))); foreach (BaseLocation loc in BaseLocations) { DetermineFinalLocation(loc, gasses); } if (bot.GameInfo.MapName.Contains("Blueshift")) { foreach (BaseLocation loc in BaseLocations) { if (SC2Util.DistanceSq(loc.Pos, SC2Util.Point(141.5f, 112.5f)) <= 5 * 5 && (loc.Pos.X != 141.5 || loc.Pos.Y != 112.5)) { DebugUtil.WriteLine("Incorrect base location, fixing: " + loc.Pos); loc.Pos = SC2Util.Point(141.5f, 112.5f); } else if (SC2Util.DistanceSq(loc.Pos, SC2Util.Point(34.5f, 63.5f)) <= 5 * 5 && (loc.Pos.X != 34.5 || loc.Pos.Y != 63.5)) { DebugUtil.WriteLine("Incorrect base location, fixing: " + loc.Pos); loc.Pos = SC2Util.Point(34.5f, 63.5f); } } } Stopwatch stopWatch = Stopwatch.StartNew(); int width = Bot.Main.GameInfo.StartRaw.MapSize.X; int height = Bot.Main.GameInfo.StartRaw.MapSize.Y; Placement = new ImageBoolGrid(bot.GameInfo.StartRaw.PlacementGrid); StartArea = Placement.GetConnected(SC2Util.To2D(StartLocation)); ArrayBoolGrid startLocations = new ArrayBoolGrid(Placement.Width(), Placement.Height()); foreach (Point2D startLoc in Bot.Main.GameInfo.StartRaw.StartLocations) { for (int x = -2; x <= 2; x++) { for (int y = -2; y <= 2; y++) { startLocations[(int)startLoc.X + x, (int)startLoc.Y + y] = true; } } } for (int x = -2; x <= 2; x++) { for (int y = -2; y <= 2; y++) { startLocations[(int)StartLocation.X + x, (int)StartLocation.Y + y] = true; } } BoolGrid unPathable; if (Bot.Main.OldMapData) { unPathable = new ImageBoolGrid(Bot.Main.GameInfo.StartRaw.PathingGrid).GetAnd(startLocations.Invert()); Pathable = unPathable.Invert(); } else { Pathable = new ImageBoolGrid(Bot.Main.GameInfo.StartRaw.PathingGrid).GetOr(startLocations); unPathable = Pathable.Invert(); } BoolGrid chokes = Placement.Invert().GetAnd(Pathable); BoolGrid mainExits = chokes.GetAdjacent(StartArea); enemyDistances = EnemyDistances; int dist = 1000; Point2D mainRamp = null; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (mainExits[x, y]) { int newDist = enemyDistances[x, y]; if (newDist < dist) { dist = newDist; mainRamp = SC2Util.Point(x, y); } } } } Ramp = chokes.GetConnected(mainRamp); BoolGrid pathingWithoutRamp = Pathable.GetAnd(Ramp.Invert()); MainAndPocketArea = pathingWithoutRamp.GetConnected(SC2Util.To2D(StartLocation)); if (Bot.Main.MyRace == Race.Protoss) { DetermineWall(Ramp, unPathable); } WallDistances = Distances(unPathable); stopWatch.Stop(); DebugUtil.WriteLine("Total time to find wall: " + stopWatch.ElapsedMilliseconds); }