Пример #1
0
        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);
        }
Пример #2
0
        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");
             */
        }
Пример #3
0
        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);
            }
        }