Exemple #1
0
        /// <summary>
        /// Extracts the current piece from the board.
        /// The piece is only searched in the original orientation and x coordinate, must therefore be untouched.
        /// </summary>
        /// <param name="screenshot">The screenshot to extract the piece from.</param>
        /// <param name="maxFallingDistance">Expected maximal falling distance.</param>
        /// <returns>The piece and it's probability.</returns>
        public ProbabilisticResult <Piece> ExtractSpawnedPieceFuzzy(IScreenshot screenshot, int maxFallingDistance)
        {
            if (screenshot == null)
            {
                throw new ArgumentNullException(nameof(screenshot));
            }
            if (maxFallingDistance < 0)
            {
                throw new ArgumentException("maxFallingDistance must be positive");
            }

            double bestProbability = 0;
            Piece  expectedPiece   = null;

            for (int yDelta = 0; yDelta <= maxFallingDistance; yDelta++)
            {
                foreach (var tetromino in Tetriminos.All)
                {
                    var piece       = new Piece(tetromino, 0, 0, -yDelta);
                    var probability = _matcher.GetProbabilityCurrentPiece(screenshot, piece);
                    if (probability > bestProbability)
                    {
                        bestProbability = probability;
                        expectedPiece   = piece;
                    }
                }
            }

            return(new ProbabilisticResult <Piece>(expectedPiece, bestProbability));
        }
Exemple #2
0
        /// <summary>
        /// Extracts the next piece visible on the screenshot.
        /// </summary>
        /// <param name="screenshot">The screenshot to extract the piece from.</param>
        /// <returns>The next Tetrimino.</returns>
        public ProbabilisticResult <Tetrimino> ExtractNextPieceFuzzy(IScreenshot screenshot)
        {
            // relevant tiles on the screen: x : 14 - 17, y : 13 - 16

            double    bestProbability = double.NegativeInfinity;
            Tetrimino?bestTetrimino   = null;

            foreach (var tetrimino in Tetriminos.All)
            {
                //var piece = new Piece(tetromino, 0, TetrisConstants.NextPieceTemplateTileCoordinates.X, TetrisConstants.NextPieceTemplateTileCoordinates.Y);
                //var probability = _matcher.GetProbabilityCurrentPiece(screenshot, piece);
                var probability = _matcher.GetProbabilityNextPiece(screenshot, tetrimino);
                if (probability > bestProbability)
                {
                    bestProbability = probability;
                    bestTetrimino   = tetrimino;
                }
            }

            if (!bestTetrimino.HasValue)
            {
                throw new Exception("No possible value for tetrimino found!");
            }
            return(new ProbabilisticResult <Tetrimino>(bestTetrimino.Value, bestProbability));
        }
Exemple #3
0
        public double GetProbability(IScreenshot screenshot, Piece expected)
        {
            int errors = 0;

            for (int x = -1; x < 3; x++)
            {
                for (int y = -1; y < 3; y++)
                {
                    var coordinates     = Coordinates.PieceToTile(expected.X + x, expected.Y + y);
                    var isBlockReal     = expected.Shape.IsSquareOccupied(x, y);
                    var isBlockExpected = IsTileBlock(screenshot, coordinates.X, coordinates.Y);

                    if (isBlockReal != isBlockExpected)
                    {
                        errors++;
                    }
                }
            }

            if (errors > 0 && expected.Tetrimino == Tetrimino.I && expected.Y == 0 && expected.Orientation == 1)
            {
                // TODO: remove this ugly hack
                // subtract one because the I piece is not completly visible in upright position
                errors--;
            }

            double normalizedError = errors / 16.0;

            return(1 - normalizedError);
        }
Exemple #4
0
        /// <summary>
        /// Extracts the current piece from the board.
        /// </summary>
        /// <param name="screenshot">The screenshot to extract the piece from.</param>
        /// <param name="piece">The piece to search.</param>
        /// <param name="maxFallingDistance">Expected maximal falling distance.</param>
        /// <returns>The piece and it's probability.</returns>
        public ProbabilisticResult <Piece> ExtractKnownPieceFuzzy(IScreenshot screenshot, Piece piece, int maxFallingDistance)
        {
            if (screenshot == null)
            {
                throw new ArgumentNullException(nameof(screenshot));
            }
            if (maxFallingDistance < 0)
            {
                throw new ArgumentException("maxFallingDistance must be positive");
            }

            double bestProbability = 0;
            Piece  expectedPiece   = null;
            Piece  testPiece       = new Piece(piece);

            for (int yDelta = 0; yDelta <= maxFallingDistance; yDelta++)
            {
                var probability = _matcher.GetProbabilityCurrentPiece(screenshot, testPiece);

                if (probability > bestProbability)
                {
                    bestProbability = probability;
                    expectedPiece   = new Piece(testPiece);
                }

                testPiece.Fall();
            }

            return(new ProbabilisticResult <Piece>(expectedPiece, bestProbability));
        }
Exemple #5
0
 public bool IsGameOverSingleplayer(IScreenshot screenshot)
 {
     return(IsMatch(screenshot,
                    _gameoverSingleplayerReferenceImage,
                    _roiBoard,
                    _thresholdGameoverSingleplayer));
 }
Exemple #6
0
        /// <summary>
        /// Extracts the next piece visible on the screenshot.
        /// Throws an exception, if the next piece is not visible on the screenshot.
        /// </summary>
        /// <param name="screenshot">The screenshot to extract the piece from.</param>
        /// <returns>The next Tetrimino.</returns>
        public Tetrimino ExtractNextPiece(IScreenshot screenshot)
        {
            // relevant tiles on the screen: x : 14 - 17, y : 13 - 16

            ushort mask = 0;

            for (int x = 0; x < 4; x++)
            {
                for (int y = 0; y < 4; y++)
                {
                    byte mean = screenshot.GetTileMean(TetrisConstants.NextPieceTileOrigin.X + x, TetrisConstants.NextPieceTileOrigin.Y + y);
                    if (IsBlock(mean))
                    {
                        int index = 4 * (2 - y) + (x);
                        mask |= (ushort)(1 << index);
                    }
                }
            }

            var nextPiece = Piece.FromMask(mask);

            if (nextPiece?.Tetrimino == null)
            {
                throw new ApplicationException("Next piece not visible on the screenshot");
            }

            return(nextPiece.Tetrimino);
        }
Exemple #7
0
        public Board Update(IScreenshot screenshot, Board board, Piece piece)
        {
            var newBoard = new Board();
            var headInBoardCoordinates = piece.Shape.Head
                                         .Select(h => Coordinates.PieceToBoard(piece.X + h.X, piece.Y + h.Y))
                                         .ToList();

            for (int x = 0; x < board.Width; x++)
            {
                for (int y = 0; y < GameBoyConstants.ScreenHeight / GameBoyConstants.TileSize; y++)
                {
                    if (headInBoardCoordinates.Any(h => h.X == x && h.Y <= y))
                    {
                        break;
                    }

                    if (_matcher.GetProbabilityBoardBlock(screenshot, x, y) >= _thresholdBlock)
                    {
                        newBoard.Occupy(x, y);
                    }
                }
            }

            return(newBoard);
        }
Exemple #8
0
 public bool IsStart(IScreenshot screenshot)
 {
     return(IsMatch(screenshot,
                    _startMultiplayerReferenceImage,
                    _roiBoard,
                    _thresholdStartMultiplayer));
 }
Exemple #9
0
 public bool IsGameOverMultiplayer(IScreenshot screenshot)
 {
     return(IsMatch(screenshot,
                    _gameoverMultiplayerReferenceImage,
                    _roiMultiplayerGameover,
                    _thresholdGameoverMultiplayer));
 }
Exemple #10
0
        // Searches the piece only in the spawning area on top of the board and a specifiec number of tiles below
        // Searches only pieces with the orientation 0
        // returns null, if the piece was not found in the spawning area or the specifiec number of tiles below
        public Piece ExtractSpawnedPiece(IScreenshot screenshot, int searchHeight)
        {
            if (searchHeight < 0)
            {
                throw new ArgumentException("searchHeight must be positive.");
            }

            for (int yDelta = 0; yDelta <= searchHeight; yDelta++)
            {
                ushort mask = 0;
                for (int x = 0; x < 4; x++)
                {
                    for (int y = 0; y < 3; y++)
                    {
                        if (IsTileBlock(screenshot, TetrisConstants.CurrentTileOrigin.X + x, TetrisConstants.CurrentTileOrigin.Y + y + yDelta))
                        {
                            int index = 4 * (2 - y) + (x);
                            mask |= (ushort)(1 << index);
                        }
                    }
                }
                var piece = Piece.FromMask(mask);
                if (piece != null)
                {
                    piece.Fall(yDelta);
                    return(piece);
                }
            }

            // not found
            return(null);
        }
 public Piece ExtractCurrentPiece(IScreenshot screenshot, Tetrimino?tetrimino, int maxFallDistance)
 {
     if (tetrimino.HasValue)
     {
         return(ExtractCurrentPieceKnown(screenshot, tetrimino.Value, maxFallDistance));
     }
     return(ExtractCurrentPieceUnknown(screenshot, maxFallDistance));
 }
        public int Update(IScreenshot screenshot)
        {
            string sql = @"UPDATE Screenshots 
                           SET Url = @Url, CreatedAt = @CreatedAt, UpdatedAt = @UpdatedAt 
                           WHERE Url = @Url";

            return db.Execute(sql, screenshot);
        }
Exemple #13
0
 public ScreenshotCreatedEventArgs(IScreenshot screenshot)
 {
     if (screenshot == null)
     {
         throw new ArgumentNullException("screenshot");
     }
     Screenshot = screenshot;
 }
Exemple #14
0
        public void Store(IScreenshot screenshot)
        {
            var name = Guid.NewGuid() + ".jpg";

            File.WriteAllBytes(Path.Combine(_path, name), screenshot.Content);

            RaiseScreenshotStored(new ScreenshotStoredEventArgs(name));
        }
Exemple #15
0
        public void NotRecognizeNextPiece(string imageKey, IScreenshot screenshot)
        {
            var result = _pieceExtractor.ExtractNextPieceFuzzy(screenshot);

            Assert.True(result.IsRejected(_probabilityThreshold));
            Assert.GreaterOrEqual(result.Probability, 0.0);
            Assert.Less(result.Probability, _probabilityThreshold);
        }
Exemple #16
0
        static IPlatformScreenshot AsPlatform(this IScreenshot screenshot)
        {
            if (screenshot is not IPlatformScreenshot platform)
            {
                throw new PlatformNotSupportedException("This implementation of IScreenshot does not implement IPlatformScreenshot.");
            }

            return(platform);
        }
Exemple #17
0
        // This is needed from rendering transparent background as black
        private Bitmap DrawImageOnWhiteBackground(IScreenshot screenshot, int width, int height)
        {
            Bitmap   blank = new Bitmap(width, height);
            Graphics g     = Graphics.FromImage(blank);

            g.Clear(Color.White);
            g.DrawImage(screenshot.Image, 0, 0, width, height);
            return(new Bitmap(blank));
        }
        private Piece ExtractCurrentPieceKnown(IScreenshot screenshot, Tetrimino tetrimino, int maxFallDistance)
        {
            var foundPiece = _tetrisExtractor.ExtractSpawnedPiece(screenshot, maxFallDistance);

            if (foundPiece != null && foundPiece.Tetrimino == tetrimino && foundPiece.IsUntouched)
            {
                return(foundPiece);
            }
            return(null);
        }
Exemple #19
0
        public string UploadScreenshotToAmazonS3RecordTransaction()
        {
            //Upload screenshot to Amazon S3
            screenshot = upload.AmazonS3();

            //Insert screenshot into the Screenshots table
            repository.Add(screenshot);

            return screenshot.Url;
        }
Exemple #20
0
        /*
         * private bool IsMatch(IScreenshot screenshot, Mat reference, double threshold)
         * {
         *  var result = new Mat();
         *
         *  CvInvoke.AbsDiff(screenshot.Image, reference, result);
         *  var mean = CvInvoke.Mean(result);
         *
         *  return mean.V0 <= threshold * 255;
         * }
         */

        private bool IsMatch(IScreenshot screenshot, Mat reference, Rectangle roi, double threshold)
        {
            var result        = new Mat();
            var screenshotRoi = new Mat(screenshot.Image, roi);
            var referenceRoi  = new Mat(reference, roi);

            CvInvoke.AbsDiff(screenshotRoi, referenceRoi, result);
            var mean = CvInvoke.Mean(result);

            return(mean.V0 <= threshold * 255);
        }
Exemple #21
0
        public GameState Extract(IScreenshot screenshot, GameState currentGameState)
        {
            //var board = ExtractBoard();
            var board        = new Board();
            var currentPiece = ExtractSpawnedPieceOrigin(screenshot);
            var nextPiece    = ExtractNextPiece(screenshot);

            var gameState = new GameState(board, currentPiece, nextPiece);

            return(gameState);
        }
        public void RecognizeNextPiece(string imageKey, IScreenshot screenshot, Tetrimino nextPieceExpected)
        {
            _nextPiece++;

            var tetromino = _extractor.ExtractNextPiece(screenshot);

            Assert.NotNull(tetromino);
            Assert.AreEqual(nextPieceExpected, tetromino);

            _nextPieceRecognized++;
        }
        public Tetrimino?ExtractNextPiece(IScreenshot screenshot)
        {
            var result = _pieceExtractor.ExtractNextPieceFuzzy(screenshot);

            if (result.IsAccepted(_thresholdNextPiece))
            {
                return(result.Result);
            }

            return(null);
        }
 public ScreenCapture(int width, int height)
 {
     //win8/win10
     if (Environment.OSVersion.Version >= new Version(6, 2))
     {
         _screenshot = new DXGIScreenshot();
     }
     else
     {
         _screenshot = new GDIScreenshot(width, height);
     }
 }
        public void RecognizeUnknownSpawnedPiece(string imageKey, IScreenshot screenshot, Piece currentPieceExpected)
        {
            _unknownSpawnedPiece++;

            var searchHeight = currentPieceExpected.FallHeight;
            var piece        = _extractor.ExtractSpawnedPiece(screenshot, searchHeight);

            Assert.NotNull(piece);
            Assert.AreEqual(currentPieceExpected, piece);

            _unknownSpawnedPieceRecognized++;
        }
        public void NotRecognizeUnknownSpawnedPiece(string imageKey, IScreenshot screenshot)
        {
            _unknownSpawnedPiece++;

            // TODO: make tests with higher search distance!
            var searchHeight = 3;
            var piece        = _extractor.ExtractSpawnedPiece(screenshot, searchHeight);

            Assert.Null(piece);

            _unknownSpawnedPieceRecognized++;
        }
Exemple #27
0
        public void RecognizeNextPiece(string imageKey, IScreenshot screenshot, Tetrimino nextPieceExpected)
        {
            _nextPiece++;

            var result = _pieceExtractor.ExtractNextPieceFuzzy(screenshot);

            Assert.True(result.IsAccepted(_probabilityThreshold));
            Assert.AreEqual(nextPieceExpected, result.Result);
            Assert.GreaterOrEqual(result.Probability, _probabilityThreshold);
            Assert.LessOrEqual(result.Probability, 1.0);

            _nextPieceRecognized++;
        }
Exemple #28
0
        public void NotRecognizeUnknownSpawnedPiece(string imageKey, IScreenshot screenshot)
        {
            _unknownSpawnedPiece++;

            // TODO: make tests with higher search distance!
            var maxFallingDistance = 3;
            var result             = _pieceExtractor.ExtractSpawnedPieceFuzzy(screenshot, maxFallingDistance);

            Assert.True(result.IsRejected(_probabilityThreshold));
            Assert.GreaterOrEqual(result.Probability, 0.0);
            Assert.Less(result.Probability, _probabilityThreshold);

            _unknownSpawnedPieceRecognized++;
        }
Exemple #29
0
        private int GetAddedLines(IScreenshot screenshot, Board board, double threshold)
        {
            int numLines = 0;

            for (; numLines < 4; numLines++)
            {
                var probability = GetHorizonRaisedProbability(screenshot, board, numLines);
                if (probability < threshold)
                {
                    break;
                }
            }
            return(numLines);
        }
Exemple #30
0
        private double GetHorizonRaisedProbability(IScreenshot screenshot, Board board, int height = 0)
        {
            double probabilitySum = 0.0;

            foreach (var block in board.GetHorizon(height))
            {
                if (block.Y < board.Height)
                {
                    probabilitySum += _matcher.GetProbabilityBoardBlock(screenshot, block.X, block.Y);
                }
            }

            return(probabilitySum / board.Width);
        }
Exemple #31
0
        // x and y are in board coordinates
        private byte GetTileBlockMean(IScreenshot screenshot, int x, int y)
        {
            // TODO: make relative to board size?
            // ignore walls
            if (x < 2 || x > 11)
            {
                return(255);
            }
            if (y < 0 || y > 17)
            {
                return(255);
            }

            return(screenshot.GetTileMean(x, y));
        }
Exemple #32
0
        public Upload()
        {
            config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap() { ExeConfigFilename = "App.config" }, ConfigurationUserLevel.None);

            string AWSAccessKey = config.AppSettings.Settings["AWSAccessKey"].Value;
            string AWSSecretKey = config.AppSettings.Settings["AWSSecretKey"].Value;
            s3Client = new AmazonS3Client(AWSAccessKey, AWSSecretKey, RegionEndpoint.USEast1);
            s3RegionEndpoint = RegionEndpoint.USEast1;

            FilePath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            FileName = config.AppSettings.Settings["FileName"].Value;
            BucketName = config.AppSettings.Settings["BucketName"].Value;

            screenshot = new Screenshot();
        }
Exemple #33
0
        public void PieceMatchingNextPiecePositives(string imageKey, IScreenshot screenshot, Tetrimino nextPieceExpected)
        {
            _nextPiecesTotal++;
            var probabilityNextPiece = _matcher.GetProbabilityNextPiece(screenshot, nextPieceExpected);

            _logger.Info($"PieceMatchingNextPiecePositives: {probabilityNextPiece * 100.0:F}");

            var nextPieceFound = probabilityNextPiece >= _probabilityThreshold;

            if (nextPieceFound)
            {
                _nextPiecesRecognized++;
            }
            Assert.True(nextPieceFound);
        }
        public int Add(IScreenshot screenshot)
        {
            string sql = "INSERT INTO Screenshots (Url, CreatedAt, UpdatedAt) VALUES (@Url, @CreatedAt, @UpdatedAt);";

            return db.Execute(sql, screenshot);
        }