Пример #1
0
        /// <summary>
        /// Scans the board bitmap for Vitae marbles (there is no highlight button for Mors and Vitae).
        /// </summary>
        /// <param name="boardBmp">Bitmap of the game board.</param>
        /// <param name="potentialPoints">Points with board coordinates to look for on the board.</param>
        private List <Point> ScanBoardForVitae(Bitmap boardBmp, IEnumerable <Point> potentialPoints)
        {
            var highlightedPoints = new List <Point>();

            // Browse the board
            foreach (var point in potentialPoints)
            {
                if (!SigmarCoordinateHelper.IsValidBoardCoordinate(point.X, point.Y))
                {
                    // Invalid coordinate. Don't bother.
                    continue;
                }

                // Get the rectangle on the image matching the marble to recognize at the current board position
                var targetRectangle = SigmarCoordinateHelper.GetMarbleRectangle(point.X, point.Y);

                // Get some pixel in the center of the first pixel row and try to approximate it as the highlight color
                var arrowPixel  = boardBmp.GetPixel(targetRectangle.Left + 26, targetRectangle.Top + 26);
                var marblePixel = boardBmp.GetPixel(targetRectangle.Left + 26, targetRectangle.Top + 41);
                if (arrowPixel.GetBrightness() > marblePixel.GetBrightness())
                {
                    highlightedPoints.Add(point);
                }
            }

            return(highlightedPoints);
        }
Пример #2
0
        /// <summary>
        /// Scans the board bitmap for highlighted marbles and returns their positions.
        /// </summary>
        /// <param name="boardBmp">Bitmap of the game board.</param>
        private List <Point> ScanBoardForHighlightedMarbles(Bitmap boardBmp)
        {
            var highlightedPoints = new List <Point>();

            // Browse the board
            for (int boardX = 0; boardX < SigmarCoordinateHelper.BoardSize; boardX++)
            {
                for (int boardY = 0; boardY < SigmarCoordinateHelper.BoardSize; boardY++)
                {
                    if (!SigmarCoordinateHelper.IsValidBoardCoordinate(boardX, boardY))
                    {
                        // Invalid coordinate. Don't bother.
                        continue;
                    }

                    // Get the rectangle on the image matching the marble to recognize at the current board position
                    var targetRectangle = SigmarCoordinateHelper.GetMarbleRectangle(boardX, boardY);

                    // Get some pixels around the marble and figure out if they are bright enough to be highlights
                    var targetColorBottom = boardBmp.GetPixel(targetRectangle.X + targetRectangle.Width / 2, targetRectangle.Bottom - 2);
                    var targetColorTop    = boardBmp.GetPixel(targetRectangle.X + targetRectangle.Width / 2 - 8, targetRectangle.Top);
                    if (targetColorBottom.GetBrightness() > 0.85f || targetColorTop.GetBrightness() > 0.85f)
                    {
                        highlightedPoints.Add(new Point(boardX, boardY));
                    }
                }
            }

            return(highlightedPoints);
        }
Пример #3
0
        /// <summary>
        /// Plays the given solution.
        /// </summary>
        /// <param name="solution">Sequence of plays to solve the board.</param>
        private void PlaySolution(List <Play> solution)
        {
            var inputService = new InputService(Program.OpusMagnumProcessName);

            foreach (var play in solution)
            {
                // Click the first tile
                Point windowFirstTilePoint = SigmarCoordinateHelper.GetWindowCoordinateOfTileCenterOnBoard(play.FirstTile);
                inputService.SendMouseLeftButtonClick(windowFirstTilePoint.X, windowFirstTilePoint.Y);

                Thread.Sleep(50); // Leave the game some time to react.

                // Click the second tile
                Point windowSecondTilePoint = SigmarCoordinateHelper.GetWindowCoordinateOfTileCenterOnBoard(play.SecondTile);
                inputService.SendMouseLeftButtonClick(windowSecondTilePoint.X, windowSecondTilePoint.Y);

                Thread.Sleep(50); // Leave the game some time to react.
            }
        }
Пример #4
0
        /// <summary>
        /// Browses the board and returns marbles that are considered playable: they have at least 3 empty tiles around them,
        /// and for metals, they are the first remaining in the sequence.
        /// </summary>
        /// <param name="board">Board to browse.</param>
        private IEnumerable <Marble> GetPlayableMarbles(Board board)
        {
            var firstMetalTileInSequence = board.GetFirstMetalRemainingInSequence();

            for (int x = 0; x < board.Tiles.GetLength(0); x++)
            {
                for (int y = 0; y < board.Tiles.GetLength(1); y++)
                {
                    var tile = board.Tiles[x, y];
                    if (tile == Tile.Empty)
                    {
                        continue;
                    }

                    if (tile >= Tile.Lead && tile <= Tile.Gold && tile != firstMetalTileInSequence)
                    {
                        // We are on a metal tile that cannot be played yet because there is another metal coming before it in the sequence.
                        continue;
                    }

                    // We are looking for 3 contiguous neighbors that are free
                    int lastFreeContiguousNeighbors = 0;
                    int?firstFreeSequence           = null;
                    foreach (var neighbor in GetNeighbors(new Point(x, y)))
                    {
                        // A neighbor is considered free if it's out of the board or if it's an empty tile
                        if (!SigmarCoordinateHelper.IsValidBoardCoordinate(neighbor.X, neighbor.Y) ||
                            board.Tiles[neighbor.X, neighbor.Y] == Tile.Empty)
                        {
                            // This neighbor is free. Increment the sequence.
                            lastFreeContiguousNeighbors++;

                            // If we already found 3 contiguous neighbors, we're good. Stop searching.
                            if (lastFreeContiguousNeighbors == 3)
                            {
                                break;
                            }
                        }
                        else
                        {
                            // This neighbor isn't free.
                            // We have to reset the sequence of contiguous free neighbors.
                            // We just keep the first sequence in memory so that it can be added to the last sequence.
                            if (firstFreeSequence == null)
                            {
                                firstFreeSequence = lastFreeContiguousNeighbors;
                            }
                            lastFreeContiguousNeighbors = 0;
                        }
                    }

                    // We have finished browsing the neighbors in a clockwise fashion (so that every last one is contiguous from the previous one).
                    // To determine if the spot at (x,y) is free, we have to check if there are 3 contiguous free neighbors.
                    // We sum the last free contiguous neighbors number with the first free sequence, so that our starting point doesn't impact the result.
                    // I hope that makes sense.
                    if (lastFreeContiguousNeighbors + firstFreeSequence.GetValueOrDefault() >= 3)
                    {
                        // The tile at (x,y) is free. So we return it.
                        yield return(new Marble(x, y, tile));
                    }
                }
            }
        }