예제 #1
0
        public BoolGrid Shrink()
        {
            ArrayBoolGrid result = new ArrayBoolGrid(Width(), Height());

            for (int x = 1; x < Width() - 1; x++)
            {
                for (int y = 1; y < Height() - 1; y++)
                {
                    bool success = true;
                    for (int dx = -1; dx <= 1 && success; dx++)
                    {
                        for (int dy = -1; dy <= 1 && success; dy++)
                        {
                            success = this[x + dx, y + dy];
                        }
                    }
                    if (success)
                    {
                        result[x, y] = true;
                    }
                }
            }

            return(result);
        }
예제 #2
0
        public BoolGrid GetConnected(Point2D point, ArrayBoolGrid encountered)
        {
            ArrayBoolGrid result = new ArrayBoolGrid(Width(), Height());

            Queue <Point2D> q = new Queue <Point2D>();

            q.Enqueue(point);
            while (q.Count > 0)
            {
                Point2D cur = q.Dequeue();
                if (cur.X < 0 || cur.Y < 0 || cur.X >= Width() || cur.Y >= Height())
                {
                    continue;
                }
                if (Get(cur) && !encountered[cur])
                {
                    result[cur]      = true;
                    encountered[cur] = true;
                    q.Enqueue(SC2Util.Point(cur.X + 1, cur.Y));
                    q.Enqueue(SC2Util.Point(cur.X - 1, cur.Y));
                    q.Enqueue(SC2Util.Point(cur.X, cur.Y + 1));
                    q.Enqueue(SC2Util.Point(cur.X, cur.Y - 1));
                }
            }
            return(result);
        }
예제 #3
0
        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);
        }
예제 #4
0
        public override BoolGrid Clone()
        {
            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];
                }
            }
            return(result);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        public List <BoolGrid> GetGroups()
        {
            List <BoolGrid> groups      = new List <BoolGrid>();
            ArrayBoolGrid   encountered = new ArrayBoolGrid(Width(), Height());

            for (int x = 0; x < Width(); x++)
            {
                for (int y = 0; y < Height(); y++)
                {
                    if (this[x, y] && !encountered[x, y])
                    {
                        groups.Add(GetConnected(SC2Util.Point(x, y), encountered));
                    }
                }
            }

            return(groups);
        }
예제 #8
0
        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);
        }
예제 #9
0
        public BoolGrid Crop(int startX, int startY, int endX, int endY)
        {
            ArrayBoolGrid result = new ArrayBoolGrid(Width(), Height());

            for (int x = 0; x < Width(); x++)
            {
                for (int y = 0; y < Height(); y++)
                {
                    if (x < startX || x >= endX || y < startY || y >= endY)
                    {
                        result[x, y] = false;
                    }
                    else
                    {
                        result[x, y] = this[x, y];
                    }
                }
            }
            return(result);
        }
예제 #10
0
        public BoolGrid FindMainAndNaturalArea(WallInCreator wall)
        {
            ArrayBoolGrid pathable = new ArrayBoolGrid(Pathable);

            foreach (WallBuilding building in wall.Wall)
            {
                for (float dx = building.Pos.X - building.Size.X / 2f; dx <= building.Pos.X + building.Size.X / 2f; dx++)
                {
                    for (float dy = building.Pos.Y - building.Size.Y / 2f; dy <= building.Pos.Y + building.Size.Y / 2f; dy++)
                    {
                        pathable[(int)dx, (int)dy] = false;
                    }
                }
            }

            BoolGrid result = pathable.GetConnected(SC2Util.To2D(StartLocation));

            //DrawGrid(result, "MainAndNatural.png");
            return(result);
        }
예제 #11
0
        public BoolGrid Grow()
        {
            ArrayBoolGrid result = new ArrayBoolGrid(Width(), Height());

            for (int x = 1; x < Width() - 1; x++)
            {
                for (int y = 1; y < Height() - 1; y++)
                {
                    bool success = false;
                    for (int dx = -1; dx <= 1 && !success; dx++)
                    {
                        for (int dy = -1; dy <= 1 && !success; dy++)
                        {
                            success = this[x + dx, y + dy];
                        }
                    }
                    result[x, y] = success;
                }
            }

            return(result);
        }
예제 #12
0
        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);
        }