public void CreateNatural(List <uint> types) { BoolGrid pathable = Tyr.Bot.MapAnalyzer.Pathable; BoolGrid unPathable = pathable.Invert(); Point2D naturalExit = Tyr.Bot.BaseManager.NaturalDefensePos; BoolGrid naturalWalls = unPathable.GetConnected(new Point2D() { X = 0, Y = 0 }).Crop((int)naturalExit.X - 12, (int)naturalExit.Y - 12, (int)naturalExit.X + 12, (int)naturalExit.Y + 12); List <BoolGrid> sides = naturalWalls.GetGroups(); Dictionary <BoolGrid, int> counts = new Dictionary <BoolGrid, int>(); foreach (BoolGrid side in sides) { counts.Add(side, side.Count()); } sides.Sort((BoolGrid a, BoolGrid b) => counts[b] - counts[a]); List <Point2D> building1Positions = Placable(sides[0], Tyr.Bot.MapAnalyzer.Placement, BuildingType.LookUp[types[0]].Size, false); List <Point2D> building2Positions = Placable(sides[1], Tyr.Bot.MapAnalyzer.Placement, BuildingType.LookUp[types[3]].Size, false); int naturalHeight = Tyr.Bot.MapAnalyzer.MapHeight((int)Tyr.Bot.BaseManager.Natural.BaseLocation.Pos.X, (int)Tyr.Bot.BaseManager.Natural.BaseLocation.Pos.Y); building1Positions = building1Positions.FindAll((p) => Tyr.Bot.MapAnalyzer.MapHeight((int)p.X, (int)p.Y) == naturalHeight); building2Positions = building2Positions.FindAll((p) => Tyr.Bot.MapAnalyzer.MapHeight((int)p.X, (int)p.Y) == naturalHeight); FindWall(types, building1Positions, building2Positions, Tyr.Bot.MapAnalyzer.Placement, false); //DrawResult(unPathable, naturalWalls, building1Positions, building2Positions); }
public BoolGrid Invert() { BoolGrid result = Clone(); result.inverted = true; return(result); }
private BoolGrid Placable(BoolGrid around, BoolGrid shrunkenStart) { ArrayBoolGrid result = new ArrayBoolGrid(around.Width(), around.Height()); for (int x = 0; x < around.Width(); x++) { for (int y = 0; y < around.Height(); y++) { if (around[x, y]) { for (int i = -2; i <= 2; i++) { if (shrunkenStart[x + i, y - 2]) { result[x + i, y - 2] = true; } if (shrunkenStart[x + i, y + 2]) { result[x + i, y + 2] = true; } if (shrunkenStart[x + 2, y + i]) { result[x + 2, y + i] = true; } if (shrunkenStart[x - 2, y + i]) { result[x - 2, y + i] = true; } } } } } return(result); }
private void check(BoolGrid pathingData, int[,] distances, Queue <Point2D> q, Point2D pos, int width, int height, int newVal) { if (check(pathingData, pos, width, height) && distances[(int)pos.X, (int)pos.Y] == 1000000000) { q.Enqueue(pos); distances[(int)pos.X, (int)pos.Y] = newVal; } }
private bool CheckRect(BoolGrid grid, Point2D pos, Point2D size) { return(CheckRect(grid, pos.X - size.X / 2f + 0.5f, pos.Y - size.Y / 2f + 0.5f, pos.X + size.X / 2f - 0.5f, pos.Y + size.Y / 2f - 0.5f)); }
private bool CheckRect(BoolGrid grid, float minX, float minY, float maxX, float maxY) { for (float x = minX; x < maxX + 0.1f; x++) { for (float y = minY; y < maxY + 0.1f; y++) { if (!grid[(int)x, (int)y]) { return(false); } } } return(true); }
public BoolGrid GetAdjacent(BoolGrid other) { ArrayBoolGrid result = new ArrayBoolGrid(Width(), Height()); for (int x = 0; x < Width(); x++) { for (int y = 0; y < Height(); y++) { result[x, y] = this[x, y] && (other[x + 1, y] || other[x - 1, y] || other[x, y + 1] || other[x, y - 1]); } } return(result); }
public BoolGrid GetAnd(BoolGrid other) { ArrayBoolGrid result = new ArrayBoolGrid(Width(), Height()); for (int x = 0; x < Width(); x++) { for (int y = 0; y < Height(); y++) { result[x, y] = this[x, y] && other[x, y]; } } return(result); }
private void GetPlacableAround(BoolGrid startArea, Point2D pos, Point2D size1, Point2D size2, ICollection <Point2D> result) { float xOffset = (size1.X + size2.X) / 2f; float yOffset = (size1.Y + size2.Y) / 2f; for (float i = -xOffset; i < 0.1f + xOffset; i++) { Point2D checkPos = new Point2D() { X = pos.X + i, Y = pos.Y - yOffset }; if (CheckRect(startArea, checkPos, size2)) { result.Add(checkPos); } checkPos = new Point2D() { X = pos.X + i, Y = pos.Y + yOffset }; if (CheckRect(startArea, checkPos, size2)) { result.Add(checkPos); } } for (float i = -yOffset; i < 0.1f + yOffset; i++) { Point2D checkPos = new Point2D() { X = pos.X + xOffset, Y = pos.Y + i }; if (CheckRect(startArea, checkPos, size2)) { result.Add(checkPos); } checkPos = new Point2D() { X = pos.X - xOffset, Y = pos.Y + i }; if (CheckRect(startArea, checkPos, size2)) { result.Add(checkPos); } } }
public BoolGrid GetConnected(BoolGrid connectedTo, int steps) { ArrayBoolGrid result = new ArrayBoolGrid(Width(), Height()); Queue <Point2D> q1 = new Queue <Point2D>(); for (int x = 0; x < Width(); x++) { for (int y = 0; y < Height(); y++) { if (connectedTo[x, y]) { q1.Enqueue(SC2Util.Point(x, y)); } } } Queue <Point2D> q2 = new Queue <Point2D>(); for (int i = 0; i < steps; i++) { while (q1.Count > 0) { Point2D cur = q1.Dequeue(); if (cur.X < 0 || cur.Y < 0 || cur.X >= Width() || cur.Y >= Height()) { continue; } if (Get(cur) && !result[cur]) { result[cur] = true; q2.Enqueue(SC2Util.Point(cur.X + 1, cur.Y)); q2.Enqueue(SC2Util.Point(cur.X - 1, cur.Y)); q2.Enqueue(SC2Util.Point(cur.X, cur.Y + 1)); q2.Enqueue(SC2Util.Point(cur.X, cur.Y - 1)); } } q1 = q2; q2 = new Queue <Point2D>(); } return(result); }
public int[,] Distances(BoolGrid start) { int width = Tyr.Bot.GameInfo.StartRaw.MapSize.X; int height = Tyr.Bot.GameInfo.StartRaw.MapSize.Y; ImageData pathingData = Tyr.Bot.GameInfo.StartRaw.PathingGrid; int[,] distances = new int[width, height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { distances[x, y] = 1000000000; } } Queue <Point2D> q = new Queue <Point2D>(); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (start[x, y]) { distances[x, y] = 0; q.Enqueue(SC2Util.Point(x, y)); } } } while (q.Count > 0) { Point2D cur = q.Dequeue(); check(pathingData, distances, q, SC2Util.Point(cur.X + 1, cur.Y), width, height, distances[(int)cur.X, (int)cur.Y] + 1); check(pathingData, distances, q, SC2Util.Point(cur.X - 1, cur.Y), width, height, distances[(int)cur.X, (int)cur.Y] + 1); check(pathingData, distances, q, SC2Util.Point(cur.X, cur.Y + 1), width, height, distances[(int)cur.X, (int)cur.Y] + 1); check(pathingData, distances, q, SC2Util.Point(cur.X, cur.Y - 1), width, height, distances[(int)cur.X, (int)cur.Y] + 1); } return(distances); }
private bool CheckPlacement(List <uint> types, Point2D start, Point2D end, BoolGrid placable, int i, bool full) { int spaceBetween = full ? 5 : 4; if (CheckPlacement(types, start, end, SC2Util.Point(end.X + i, end.Y + spaceBetween), placable, full)) { return(true); } if (CheckPlacement(types, start, end, SC2Util.Point(end.X + i, end.Y - spaceBetween), placable, full)) { return(true); } if (CheckPlacement(types, start, end, SC2Util.Point(end.X + spaceBetween, end.Y + i), placable, full)) { return(true); } if (CheckPlacement(types, start, end, SC2Util.Point(end.X - spaceBetween, end.Y + i), placable, full)) { return(true); } return(false); }
private void DrawRamp(BoolGrid startArea, BoolGrid chokes, BoolGrid ramps) { if (!Tyr.Debug) { return; } int width = Tyr.Bot.GameInfo.StartRaw.PathingGrid.Size.X; int height = Tyr.Bot.GameInfo.StartRaw.PathingGrid.Size.Y; System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (ramps[x, y]) { bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.Blue); } else if (chokes[x, y]) { bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.Orange); } else if (startArea[x, y]) { bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.Black); } else { bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.White); } } } bmp.Save(Directory.GetCurrentDirectory() + "/data/Ramp.png"); }
private List <Point2D> Placable(BoolGrid around, BoolGrid startArea, Point2D size) { Point2D size1x1 = new Point2D() { X = 1, Y = 1 }; List <Point2D> result = new List <Point2D>(); for (int x = 0; x < around.Width(); x++) { for (int y = 0; y < around.Height(); y++) { if (around[x, y]) { GetPlacableAround(startArea, new Point2D() { X = x, Y = y }, size1x1, size, result); } } } return(result); }
private bool check(BoolGrid pathingData, Point2D pos, int width, int height) { if (pos.X < 0 || pos.X >= width || pos.Y < 0 || pos.Y >= height) { return(false); } if (pathingData[pos]) { return(true); } foreach (Point2D p in Tyr.Bot.GameInfo.StartRaw.StartLocations) { if (SC2Util.DistanceGrid(pos, p) <= 3) { return(true); } } if (SC2Util.DistanceGrid(pos, StartLocation) <= 3) { return(true); } return(false); }
private void DrawPathing(BoolGrid pathable, BoolGrid placememt) { if (!Tyr.Debug) { return; } int width = Tyr.Bot.GameInfo.StartRaw.PathingGrid.Size.X; int height = Tyr.Bot.GameInfo.StartRaw.PathingGrid.Size.Y; System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (pathable[x, y] && placememt[x, y]) { bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.Purple); } else if (pathable[x, y]) { bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.Blue); } else if (placememt[x, y]) { bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.Red); } else { bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.Black); } } } bmp.Save(Directory.GetCurrentDirectory() + "/data/Pathing.png"); }
private bool CheckPlacement(List <uint> types, Point2D start, Point2D end, Point2D middle, BoolGrid placable, bool full) { if (full) { return(CheckPlacementFull(types, start, end, middle, placable)); } else { return(CheckPlacement(types, start, end, middle, placable)); } }
private void FindWall(List <uint> types, List <Point2D> startPositions, List <Point2D> endPositions, BoolGrid placable, bool full) { foreach (Point2D start in startPositions) { foreach (Point2D end in endPositions) { if (Math.Abs(start.X - end.X) > 7 || Math.Abs(start.Y - end.Y) > 7) { continue; } for (int i = -1; i <= 1; i++) { if (CheckPlacement(types, start, end, placable, i, full)) { return; } } } } foreach (Point2D start in startPositions) { foreach (Point2D end in endPositions) { if (Math.Abs(start.X - end.X) > 7 || Math.Abs(start.Y - end.Y) > 7) { continue; } if (CheckPlacement(types, start, end, placable, -2, full)) { return; } if (CheckPlacement(types, start, end, placable, 2, full)) { return; } } } }
public void Analyze(Tyr tyr) { // Determine the start location. foreach (Unit unit in tyr.Observation.Observation.RawData.Units) { if (unit.Owner == tyr.PlayerId && UnitTypes.ResourceCenters.Contains(unit.UnitType)) { StartLocation = unit.Pos; } } List <MineralField> mineralFields = new List <MineralField>(); foreach (Unit mineralField in tyr.Observation.Observation.RawData.Units) { if (UnitTypes.MineralFields.Contains(mineralField.UnitType)) { mineralFields.Add(new MineralField() { Pos = mineralField.Pos, Tag = mineralField.Tag }); } } 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.DistanceGrid(mineralFieldA.Pos, closeMineralField.Pos) <= 5) { mineralSetIds.Add(closeMineralField.Tag, currentSet); baseLocation.MineralFields.Add(closeMineralField); } } } currentSet++; } List <Gas> gasses = new List <Gas>(); foreach (Unit unit in tyr.Observation.Observation.RawData.Units) { if (UnitTypes.GasGeysers.Contains(unit.UnitType)) { gasses.Add(new Gas() { Pos = unit.Pos, Tag = unit.Tag }); } } foreach (BaseLocation loc in BaseLocations) { 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; } for (int i = 0; i < gasses.Count; i++) { if (SC2Util.DistanceGrid(loc.Pos, gasses[i].Pos) <= 24) { loc.Gasses.Add(gasses[i]); gasses[i] = gasses[gasses.Count - 1]; gasses.RemoveAt(gasses.Count - 1); i--; } } float closestDist = 1000000; for (int i = 0; i < 20; i++) { for (int j = 0; j == 0 || j < i; j++) { float maxDist; Point2D newPos; newPos = SC2Util.Point(loc.Pos.X + i - j, loc.Pos.Y + j); maxDist = checkPosition(newPos, loc); if (maxDist < closestDist) { loc.Pos = newPos; closestDist = maxDist; } newPos = SC2Util.Point(loc.Pos.X + i - j, loc.Pos.Y - j); maxDist = checkPosition(newPos, loc); if (maxDist < closestDist) { loc.Pos = newPos; closestDist = maxDist; } newPos = SC2Util.Point(loc.Pos.X - i + j, loc.Pos.Y + j); maxDist = checkPosition(newPos, loc); if (maxDist < closestDist) { loc.Pos = newPos; closestDist = maxDist; } newPos = SC2Util.Point(loc.Pos.X - i + j, loc.Pos.Y - j); maxDist = checkPosition(newPos, loc); if (maxDist < closestDist) { loc.Pos = newPos; closestDist = maxDist; } } } if (closestDist >= 999999) { System.Console.WriteLine("Unable to find proper base placement: " + loc.Pos); } } if (tyr.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)) { System.Console.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)) { System.Console.WriteLine("Incorrect base location, fixing: " + loc.Pos); loc.Pos = SC2Util.Point(34.5f, 63.5f); } } } Stopwatch stopWatch = Stopwatch.StartNew(); int width = Tyr.Bot.GameInfo.StartRaw.MapSize.X; int height = Tyr.Bot.GameInfo.StartRaw.MapSize.Y; Placement = new ImageBoolGrid(tyr.GameInfo.StartRaw.PlacementGrid); StartArea = Placement.GetConnected(SC2Util.To2D(StartLocation)); ArrayBoolGrid startLocations = new ArrayBoolGrid(Placement.Width(), Placement.Height()); foreach (Point2D startLoc in Tyr.Bot.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 = new ImageBoolGrid(Tyr.Bot.GameInfo.StartRaw.PathingGrid).GetAnd(startLocations.Invert()); BoolGrid pathable = unPathable.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); } } } } BoolGrid ramp = chokes.GetConnected(mainRamp); BoolGrid pathingWithoutRamp = pathable.GetAnd(ramp.Invert()); MainAndPocketArea = pathingWithoutRamp.GetConnected(SC2Util.To2D(StartLocation)); if (Tyr.Bot.MyRace == Race.Protoss) { DetermineWall(ramp, unPathable); } WallDistances = Distances(unPathable); stopWatch.Stop(); System.Console.WriteLine("Total time to find wall: " + stopWatch.ElapsedMilliseconds); /* * System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height); * for (int x = 0; x < width; x++) * for (int y = 0; y < height; y++) * { * if (WallDistances[x, y] == 0) * bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.Red); * else if (WallDistances[x, y] >= 25) * bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.Green); * else * bmp.SetPixel(x, height - 1 - y, System.Drawing.Color.FromArgb(WallDistances[x, y] * 10, WallDistances[x, y] * 10, WallDistances[x, y] * 10)); * } * foreach (BaseLocation loc in BaseLocations) * for (int dx = -2; dx <= 2; dx++) * for (int dy = -2; dy <= 2; dy++) * bmp.SetPixel((int)loc.Pos.X + dx, height - 1 - (int)loc.Pos.Y - dy, System.Drawing.Color.Blue); * * foreach (Unit unit in tyr.Observation.Observation.RawData.Units) * { * if (UnitTypes.GasGeysers.Contains(unit.UnitType)) * for (int dx = -1; dx <= 1; dx++) * for (int dy = -1; dy <= 1; dy++) * bmp.SetPixel((int)unit.Pos.X + dx, height - 1 - (int)unit.Pos.Y - dy, System.Drawing.Color.Cyan); * if (UnitTypes.MineralFields.Contains(unit.UnitType)) * for (int dx = 0; dx <= 1; dx++) * bmp.SetPixel((int)(unit.Pos.X - 0.5f) + dx, height - 1 - (int)(unit.Pos.Y - 0.5f), System.Drawing.Color.Cyan); * } * bmp.Save(@"C:\Users\Simon\Desktop\WallDistances.png"); */ }
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); } } } } }
private bool CheckPlacement(List <uint> types, Point2D start, Point2D end, Point2D middle, BoolGrid placable) { if (!CheckRect(placable, middle.X - 1, middle.Y - 1, middle.X + 1, middle.Y + 1)) { return(false); } if (Math.Abs(start.X - middle.X) == 3) { if (Math.Abs(start.Y - middle.Y) >= 3) { return(false); } } else if (Math.Abs(start.Y - middle.Y) == 3) { if (Math.Abs(start.X - middle.X) >= 3) { return(false); } } else { return(false); } Point2D zealotPos = SC2Util.Point(end.X, end.Y); zealotPos = SC2Util.TowardCardinal(zealotPos, middle, 2); zealotPos = SC2Util.TowardCardinal(zealotPos, Tyr.Bot.BaseManager.Natural.BaseLocation.Pos, 0.5f); /* * if (end.X - middle.X == 4) * zealotPos.X -= 2; * else if (end.X - middle.X == -4) * zealotPos.X += 2; * else if (end.Y - middle.Y == 4) * zealotPos.Y -= 2; * else * zealotPos.Y += 2; */ Point2D[] pylonPositions = new Point2D[2]; Point2D natural = Tyr.Bot.BaseManager.Natural.BaseLocation.Pos; if (Math.Abs(natural.X - middle.X) >= Math.Abs(natural.Y - middle.Y)) { if (natural.X > middle.X) { pylonPositions[0] = SC2Util.Point(middle.X + 2.5f, middle.Y + 0.5f); pylonPositions[1] = SC2Util.Point(middle.X + 2.5f, middle.Y - 0.5f); } else { pylonPositions[0] = SC2Util.Point(middle.X - 2.5f, middle.Y + 0.5f); pylonPositions[1] = SC2Util.Point(middle.X - 2.5f, middle.Y - 0.5f); } /* * if (natural.Y > middle.Y) * { * pylonPositions[2] = SC2Util.Point(middle.X + 0.5f, middle.Y + 2.5f); * pylonPositions[3] = SC2Util.Point(middle.X - 0.5f, middle.Y + 2.5f); * } * else * { * pylonPositions[2] = SC2Util.Point(middle.X + 0.5f, middle.Y - 2.5f); * pylonPositions[3] = SC2Util.Point(middle.X - 0.5f, middle.Y - 2.5f); * } */ } else { if (natural.Y > middle.Y) { pylonPositions[0] = SC2Util.Point(middle.X + 0.5f, middle.Y + 2.5f); pylonPositions[1] = SC2Util.Point(middle.X - 0.5f, middle.Y + 2.5f); } else { pylonPositions[0] = SC2Util.Point(middle.X + 0.5f, middle.Y - 2.5f); pylonPositions[1] = SC2Util.Point(middle.X - 0.5f, middle.Y - 2.5f); } /* * if (natural.X > middle.X) * { * pylonPositions[2] = SC2Util.Point(middle.X + 2.5f, middle.Y + 0.5f); * pylonPositions[3] = SC2Util.Point(middle.X + 2.5f, middle.Y - 0.5f); * } * else * { * pylonPositions[2] = SC2Util.Point(middle.X - 2.5f, middle.Y + 0.5f); * pylonPositions[3] = SC2Util.Point(middle.X - 2.5f, middle.Y - 0.5f); * } */ } Point2D pylonPos = null; foreach (Point2D pos in pylonPositions) { if (ProtossBuildingPlacement.IsBuildingInPowerField(start, SC2Util.Point(3, 3), pos) && ProtossBuildingPlacement.IsBuildingInPowerField(end, SC2Util.Point(3, 3), pos) && Tyr.Bot.buildingPlacer.CheckDistanceClose(pos, UnitTypes.PYLON, start, types[0]) && Tyr.Bot.buildingPlacer.CheckDistanceClose(pos, UnitTypes.PYLON, end, types[3])) { pylonPos = pos; } } if (pylonPos == null) { return(false); } Wall = new List <WallBuilding>(); Wall.Add(new WallBuilding() { Pos = start, Type = types[0] }); Wall.Add(new WallBuilding() { Pos = middle, Type = types[1] }); Wall.Add(new WallBuilding() { Pos = zealotPos, Type = types[2] }); Wall.Add(new WallBuilding() { Pos = end, Type = types[3] }); Wall.Add(new WallBuilding() { Pos = pylonPos, Type = UnitTypes.PYLON }); return(true); }
private bool CheckPlacementFull(List <uint> types, Point2D start, Point2D end, Point2D middle, BoolGrid placable) { if (!CheckRect(placable, middle.X - 1, middle.Y - 1, middle.X + 1, middle.Y + 1)) { return(false); } if (Math.Abs(start.X - middle.X) == 3) { if (Math.Abs(start.Y - middle.Y) >= 3) { return(false); } } else if (Math.Abs(start.Y - middle.Y) == 3) { if (Math.Abs(start.X - middle.X) >= 3) { return(false); } } else { return(false); } Point2D pylonPos = SC2Util.Point(end.X, end.Y); pylonPos = SC2Util.TowardCardinal(pylonPos, middle, 2.5f); Wall = new List <WallBuilding>(); Wall.Add(new WallBuilding() { Pos = start, Type = types[0] }); Wall.Add(new WallBuilding() { Pos = middle, Type = types[1] }); Wall.Add(new WallBuilding() { Pos = pylonPos, Type = types[2] }); Wall.Add(new WallBuilding() { Pos = end, Type = types[3] }); return(true); }
public void Create(List <uint> types) { foreach (uint type in types) { Wall.Add(new WallBuilding() { Type = type }); } BoolGrid unPathable = Tyr.Bot.MapAnalyzer.UnPathable; BoolGrid ramp = Tyr.Bot.MapAnalyzer.Ramp; BoolGrid rampAdjacent = unPathable.GetAdjacent(ramp); BoolGrid rampSides = unPathable.GetConnected(rampAdjacent, 5); List <BoolGrid> sides = rampSides.GetGroups(); List <Point2D> building1Positions = Placable(sides[0], Tyr.Bot.MapAnalyzer.StartArea, BuildingType.LookUp[types[0]].Size); List <Point2D> building2Positions = Placable(sides[1], Tyr.Bot.MapAnalyzer.StartArea, BuildingType.LookUp[types[2]].Size); float wallScore = 1000; foreach (Point2D p1 in building1Positions) { foreach (Point2D p2 in building2Positions) { if (System.Math.Abs(p1.X - p2.X) < 0.1f + (BuildingType.LookUp[types[0]].Size.X + BuildingType.LookUp[types[2]].Size.X) / 2f && System.Math.Abs(p1.Y - p2.Y) < 0.1f + (BuildingType.LookUp[types[0]].Size.Y + BuildingType.LookUp[types[2]].Size.Y) / 2f) { continue; } float newScore = SC2Util.DistanceGrid(p1, p2); if (newScore >= wallScore) { continue; } Wall[0].Pos = p1; Wall[2].Pos = p2; wallScore = newScore; } } HashSet <Point2D> around1 = new HashSet <Point2D>(); GetPlacableAround(Tyr.Bot.MapAnalyzer.StartArea, Wall[0].Pos, Wall[0].Size, Wall[1].Size, around1); HashSet <Point2D> around2 = new HashSet <Point2D>(); GetPlacableAround(Tyr.Bot.MapAnalyzer.StartArea, Wall[2].Pos, Wall[2].Size, Wall[1].Size, around2); around1.IntersectWith(around2); foreach (Point2D pos in around1) { Wall[1].Pos = new Point2D() { X = pos.X + 0.5f, Y = pos.Y + 0.5f }; break; } }
public void Analyze(Tyr tyr) { // Determine the start location. foreach (Unit unit in tyr.Observation.Observation.RawData.Units) { if (unit.Owner == tyr.PlayerId && UnitTypes.ResourceCenters.Contains(unit.UnitType)) { StartLocation = unit.Pos; } } List <MineralField> mineralFields = new List <MineralField>(); foreach (Unit mineralField in tyr.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 tyr.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 (tyr.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 = Tyr.Bot.GameInfo.StartRaw.MapSize.X; int height = Tyr.Bot.GameInfo.StartRaw.MapSize.Y; Placement = new ImageBoolGrid(tyr.GameInfo.StartRaw.PlacementGrid); StartArea = Placement.GetConnected(SC2Util.To2D(StartLocation)); ArrayBoolGrid startLocations = new ArrayBoolGrid(Placement.Width(), Placement.Height()); foreach (Point2D startLoc in Tyr.Bot.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 (Tyr.Bot.OldMapData) { unPathable = new ImageBoolGrid(Tyr.Bot.GameInfo.StartRaw.PathingGrid).GetAnd(startLocations.Invert()); Pathable = unPathable.Invert(); } else { Pathable = new ImageBoolGrid(Tyr.Bot.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 (Tyr.Bot.MyRace == Race.Protoss) { DetermineWall(Ramp, unPathable); } WallDistances = Distances(unPathable); stopWatch.Stop(); DebugUtil.WriteLine("Total time to find wall: " + stopWatch.ElapsedMilliseconds); }
public Point2D GetEnemyRamp() { if (EnemyRamp != null) { return(EnemyRamp); } if (Tyr.Bot.TargetManager.PotentialEnemyStartLocations.Count != 1) { return(null); } int width = Tyr.Bot.GameInfo.StartRaw.MapSize.X; int height = Tyr.Bot.GameInfo.StartRaw.MapSize.Y; Point2D start = Tyr.Bot.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); }