public BaseLocation GetEnemyThird() { if (Bot.Main.TargetManager.PotentialEnemyStartLocations.Count != 1) { return(null); } float dist = 1000000000; BaseLocation enemyNatural = GetEnemyNatural(); BaseLocation enemyThird = null; foreach (BaseLocation loc in Bot.Main.MapAnalyzer.BaseLocations) { float distanceToMain = SC2Util.DistanceSq(Bot.Main.TargetManager.PotentialEnemyStartLocations[0], loc.Pos); if (distanceToMain <= 4) { continue; } if (SC2Util.DistanceSq(enemyNatural.Pos, loc.Pos) <= 2 * 2) { continue; } if (distanceToMain < dist) { dist = distanceToMain; enemyThird = loc; } } return(enemyThird); }
public BaseLocation GetEnemyNatural() { if (Bot.Main.TargetManager.PotentialEnemyStartLocations.Count != 1) { return(null); } int[,] distances = Distances(Bot.Main.TargetManager.PotentialEnemyStartLocations[0]); int dist = 1000000000; BaseLocation enemyNatural = null; foreach (BaseLocation loc in Bot.Main.MapAnalyzer.BaseLocations) { int distanceToMain = distances[(int)loc.Pos.X, (int)loc.Pos.Y]; if (distanceToMain <= 5) { continue; } if (distanceToMain < dist) { dist = distanceToMain; enemyNatural = loc; } } return(enemyNatural); }
private float checkPosition(Point2D pos, BaseLocation loc) { foreach (MineralField mineralField in loc.MineralFields) { if (SC2Util.DistanceGrid(mineralField.Pos, pos) <= 10 && System.Math.Abs(mineralField.Pos.X - pos.X) <= 5.5 && System.Math.Abs(mineralField.Pos.Y - pos.Y) <= 5.5) { return(100000000); } } foreach (Gas gas in loc.Gasses) { if (SC2Util.DistanceGrid(gas.Pos, pos) <= 11 && System.Math.Abs(gas.Pos.X - pos.X) <= 6.1 && System.Math.Abs(gas.Pos.Y - pos.Y) <= 6.1) { return(100000000); } if (SC2Util.DistanceSq(gas.Pos, pos) >= 11 * 11) { return(100000000); } } // Check if a resource center can actually be built here. for (float x = -2.5f; x < 2.5f + 0.1f; x++) { for (float y = -2.5f; y < 2.5f + 0.1f; y++) { if (!SC2Util.GetTilePlacable((int)System.Math.Round(pos.X + x), (int)System.Math.Round(pos.Y + y))) { return(100000000); } } } float maxDist = 0; foreach (MineralField mineralField in loc.MineralFields) { maxDist += SC2Util.DistanceSq(mineralField.Pos, pos); } foreach (Gas gas in loc.Gasses) { maxDist += SC2Util.DistanceSq(gas.Pos, pos); } return(maxDist); }
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); }
private void DetermineFinalLocation(BaseLocation loc, List <Gas> gasses) { for (int i = 0; i < gasses.Count; i++) { foreach (MineralField field in loc.MineralFields) { if (SC2Util.DistanceSq(field.Pos, gasses[i].Pos) <= 8 * 8) { loc.Gasses.Add(gasses[i]); gasses[i] = gasses[gasses.Count - 1]; gasses.RemoveAt(gasses.Count - 1); i--; break; } } } if (loc.Gasses.Count == 1) { for (int i = 0; i < gasses.Count; i++) { if (SC2Util.DistanceSq(loc.Gasses[0].Pos, gasses[i].Pos) <= 8 * 8) { loc.Gasses.Add(gasses[i]); gasses[i] = gasses[gasses.Count - 1]; gasses.RemoveAt(gasses.Count - 1); i--; break; } } } float x = 0; float y = 0; foreach (MineralField field in loc.MineralFields) { x += (int)field.Pos.X; y += (int)field.Pos.Y; } x /= loc.MineralFields.Count; y /= loc.MineralFields.Count; // Round to nearest half position. Nexii are 5x5 and therefore always centered in the middle of a tile. x = (int)(x) + 0.5f; y = (int)(y) + 0.5f; // Temporary position, we still need a proper position. loc.Pos = SC2Util.Point(x, y); MineralField closest = null; float distance = 10000; foreach (MineralField field in loc.MineralFields) { if (SC2Util.DistanceGrid(field.Pos, loc.Pos) < distance) { distance = SC2Util.DistanceGrid(field.Pos, loc.Pos); closest = field; } } // Move the estimated base position slightly away from the closest mineral. // This ensures that the base location will not end up on the far side of the minerals. if (closest.Pos.X < loc.Pos.X) { loc.Pos.X += 2; } else if (closest.Pos.X > loc.Pos.X) { loc.Pos.X -= 2; } if (closest.Pos.Y < loc.Pos.Y) { loc.Pos.Y += 2; } else if (closest.Pos.Y > loc.Pos.Y) { loc.Pos.Y -= 2; } bool test = SC2Util.DistanceSq(loc.Pos, new Point2D() { X = 127.5f, Y = 77.5f }) <= 10 * 10; float closestDist = 1000000; Point2D approxPos = loc.Pos; for (int i = 0; i < 20; i++) { for (int j = 0; j == 0 || j < i; j++) { float maxDist; Point2D newPos; newPos = SC2Util.Point(approxPos.X + i - j, approxPos.Y + j); maxDist = checkPosition(newPos, loc); if (maxDist < closestDist) { loc.Pos = newPos; closestDist = maxDist; } newPos = SC2Util.Point(approxPos.X + i - j, approxPos.Y - j); maxDist = checkPosition(newPos, loc); if (maxDist < closestDist) { loc.Pos = newPos; closestDist = maxDist; } newPos = SC2Util.Point(approxPos.X - i + j, approxPos.Y + j); maxDist = checkPosition(newPos, loc); if (maxDist < closestDist) { loc.Pos = newPos; closestDist = maxDist; } newPos = SC2Util.Point(approxPos.X - i + j, approxPos.Y - j); maxDist = checkPosition(newPos, loc); if (maxDist < closestDist) { loc.Pos = newPos; closestDist = maxDist; } } } if (loc.Gasses.Count != 2) { FileUtil.Debug("Wrong number of gasses, found: " + loc.Gasses.Count); } if (closestDist >= 999999) { DebugUtil.WriteLine("Unable to find proper base placement: " + loc.Pos); } }