private static async Task FindNonEmptyView(WordSearcherGameClient wsGameClient)
        {
            if (wsGameClient.State.SeesAnything)
            {
                Logger.Log.Info("Already have a non-empty view, no search is required.");
                return;
            }

            Logger.Log.Info("Looking for a non-empty view for width and height estimation...");
            var linesChecked = 0;

            while (true)
            {
                var searchRange    = 50 + linesChecked / 5 * 20;
                var foundSomething =
                    await MoveUntilSeeAnything(wsGameClient, linesChecked % 2 == 0?Direction.Right : Direction.Left,
                                               searchRange);

                if (foundSomething)
                {
                    break;
                }

                Logger.Log.Info(
                    $"Found nothing in range {searchRange} on line, going {Constants.VisibleFieldHeight} lower... (current Y:{wsGameClient.State.Y})");
                linesChecked++;
                await wsGameClient.MoveAsync(Direction.Down, Constants.VisibleFieldHeight);
            }

            Logger.Log.Info("Non-empty view found.");
        }
 private async Task <int> MoveToSeeLetterTop(int letterY)
 {
     if (letterY != 0)
     {
         await wsGameClient.MoveAsync(0, letterY);
     }
     return(0);
 }
        public async Task <bool[, ]> ScanMapAsync()
        {
            Logger.Log.Info("Scanning...");
            var mapWriter = new MapWriter(wsGameClient, mapWidth, mapHeight);

            var linesRemain = mapHeight;

            mapWriter.UpdateMap();
            Logger.Log.Debug("Scan progress: 0%");
            while (true)
            {
                for (var i = 0; i < mapWidth - Constants.VisibleFieldWidth; i++)
                {
                    await wsGameClient.MoveAsync(Direction.Right);

                    if (i % Constants.VisibleFieldWidth == 0)
                    {
                        mapWriter.UpdateMap();
                    }
                }

                mapWriter.UpdateMap();
                linesRemain -= Constants.VisibleFieldHeight;
                if (linesRemain <= 0)
                {
                    break;
                }
                await wsGameClient.MoveAsync(Direction.Down, Math.Min(linesRemain, Constants.VisibleFieldHeight));

                mapWriter.UpdateMap();
                Logger.Log.Debug($"Scan progress: {(int) (100 - (float) linesRemain / mapHeight * 100)}%");
            }

            Logger.Log.Debug("Scan progress: 100%");
            Logger.Log.Info("Scan complete.");

            return(mapWriter.Map);
        }
        private static async Task <bool> MoveUntilSeeAnything(WordSearcherGameClient wsGameClient, Direction direction,
                                                              int maxMoves = -1)
        {
            while (!wsGameClient.State.SeesAnything && maxMoves != 0)
            {
                await wsGameClient.MoveAsync(direction);

                if (maxMoves > 0)
                {
                    maxMoves--;
                }
            }

            return(wsGameClient.State.SeesAnything);
        }