public static Point GetClosestEnemyPosition(BattleNetClient client, out List <Movement> movements, int maxTurnsToCalculate)
        {
            var enemyPosition = PointUtility.CreateNegativePoint();

            movements = new List <Movement>();

            List <List <Point> >    checkedPoints      = new List <List <Point> >(new [] { new List <Point>(new [] { client.GetPlayerTank() }) });
            List <List <Movement> > movementsInProcess = new List <List <Movement> >(new [] { new List <Movement>(new [] { Movement.Stop }) });
            List <Point>            currentRangePoints = new List <Point>(new[] { client.GetPlayerTank() });

            for (int count = 0; count < maxTurnsToCalculate && enemyPosition.IsNegativePoint(); count++)
            {
                enemyPosition = GetClosestEnemyPosition(client,
                                                        checkedPoints, movementsInProcess,
                                                        currentRangePoints,
                                                        out movements);
            }

            if (movements.Any())
            {
                movements.RemoveAt(0);
                return(enemyPosition);
            }
            else
            {
                return(PointUtility.CreateNegativePoint());
            }
        }
        private static Point GetClosestEnemyPosition(BattleNetClient client, List <List <Point> > checkedPoints,
                                                     List <List <Movement> > movements, List <Point> currentRangePoints, out List <Movement> road)
        {
            if (client.IsAnyOfEnemyAt(currentRangePoints))
            {
                for (int index = 0; index < currentRangePoints.Count; index++)
                {
                    if (client.IsEnemyAt(currentRangePoints[index]))
                    {
                        road = new List <Movement>(movements[index]);
                        return(currentRangePoints[index]);
                    }
                }
            }

            var iterationMap      = MapUtility.IterationMap;
            var nextRangePoints   = new List <Point>();
            var nextMovements     = new List <List <Movement> >();
            var nextCheckedPoints = new List <List <Point> >();

            for (int index = 0; index < movements.Count; index++)
            {
                foreach (var iteration in iterationMap)
                {
                    var nextPosition = iteration.Value(currentRangePoints[index]);
                    var movement     = iteration.Key.ToMovement();

                    if (checkedPoints[index].Exists(x => x.X == nextPosition.X && x.Y == nextPosition.Y))
                    {
                        continue;
                    }

                    if (client.IsOutOf(nextPosition) || client.IsObstacleAt(nextPosition))
                    {
                        continue;
                    }

                    nextRangePoints.Add(nextPosition);

                    var move = new List <Movement>(movements[index]);
                    move.Add(iteration.Key.ToMovement());
                    nextMovements.Add(move);

                    var nextChecked = new List <Point>(checkedPoints[index]);
                    nextChecked.Add(currentRangePoints[index]);
                    nextCheckedPoints.Add(nextChecked);
                }
            }

            checkedPoints.Clear();
            checkedPoints.AddRange(nextCheckedPoints);
            movements.Clear();
            movements.AddRange(nextMovements);
            currentRangePoints.Clear();
            currentRangePoints.AddRange(nextRangePoints);
            road = new List <Movement>();
            return(PointUtility.CreateNegativePoint());
        }
        private static Point GetClosestPosition(BattleNetClient client, Point position, Func <Point, bool> successCheck,
                                                List <Point> checkedPoints, List <Movement> movements)
        {
            if (checkedPoints.Exists(x => x.X == position.X && x.Y == position.Y))
            {
                return(PointUtility.CreateNegativePoint());//skip checking.
            }

            if (client.IsOutOf(position) || client.IsObstacleAt(position))
            {
                return(PointUtility.CreateNegativePoint());
            }

            var iterationMap = MapUtility.IterationMap;

            var topPosition    = iterationMap[Direction.Up](position);
            var bottomPosition = iterationMap[Direction.Down](position);
            var leftPosition   = iterationMap[Direction.Left](position);
            var rightPosition  = iterationMap[Direction.Right](position);

            checkedPoints.Add(position);

            if (successCheck(position))
            {
                return(position);
            }

            var topChildMovements    = new List <Movement>(movements);
            var bottomChildMovements = new List <Movement>(movements);
            var rightChildMovements  = new List <Movement>(movements);
            var leftChildMovements   = new List <Movement>(movements);

            var topEnemyPosition    = GetClosestPosition(client, topPosition, successCheck, new List <Point>(checkedPoints), topChildMovements);
            var bottomEnemyPosition = GetClosestPosition(client, bottomPosition, successCheck, new List <Point>(checkedPoints), bottomChildMovements);
            var leftEnemyPosition   = GetClosestPosition(client, leftPosition, successCheck, new List <Point>(checkedPoints), leftChildMovements);
            var rightEnemyPosition  = GetClosestPosition(client, rightPosition, successCheck, new List <Point>(checkedPoints), rightChildMovements);

            var topMovements    = topChildMovements.Count;
            var bottomMovements = bottomChildMovements.Count;
            var leftMovements   = leftChildMovements.Count;
            var rightMovements  = rightChildMovements.Count;

            if (topMovements < bottomMovements &&
                topMovements < leftMovements &&
                topMovements < rightMovements)
            {
                movements.Add(Movement.Up);
                movements.AddRange(topChildMovements);
                return(topEnemyPosition);
            }

            if (bottomMovements < topMovements &&
                bottomMovements < leftMovements &&
                bottomMovements < rightMovements)
            {
                movements.Add(Movement.Down);
                movements.AddRange(bottomChildMovements);
                return(bottomEnemyPosition);
            }

            if (leftMovements < topMovements &&
                leftMovements < bottomMovements &&
                leftMovements < rightMovements)
            {
                movements.Add(Movement.Left);
                movements.AddRange(leftChildMovements);
                return(leftEnemyPosition);
            }

            if (rightMovements < topMovements &&
                rightMovements < bottomMovements &&
                rightMovements < leftMovements)
            {
                movements.Add(Movement.Right);
                movements.AddRange(rightChildMovements);
                return(rightEnemyPosition);
            }

            return(PointUtility.CreateNegativePoint());
        }