private List <Point> GetPerkAims()
        {
            var aims = FullBoard.GetPerks()
                       .Where(x => !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT) &&
                              FullBoard.GetPathFromHero(x, PrevFullBoard)?.Length < 4)
                       .ToList();

            return(aims);
        }
        private List <Point> GetGoldAims()
        {
            var notAfk = FullBoard.GetOtherHeroes().Where(x => !PrevFullBoard.GetOtherHeroes().Contains(x)).ToList();
            var aims   = FullBoard.GetGold()
                         .Where(x => x.GetLengthTo(FullBoard.GetMe()) < Constants.GoldRadius * 2 &&
                                !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT) &&
                                FullBoard.GetPathFromHero(x, PrevFullBoard)?.Length < Constants.GoldRadius &&
                                notAfk.All(othetHero => FullBoard.GetPath(othetHero, x, PrevFullBoard)?.Length >= FullBoard.GetPathFromHero(x, PrevFullBoard)?.Length))
                         .ToList();

            return(aims);
        }
        private List <Point> GetTheNearestToHero(IEnumerable <Point> aims)
        {
            AimPath bestPath = null;

            foreach (var aim in aims)
            {
                var path = FullBoard.GetPathFromHero(aim, PrevFullBoard);
                if (path != null && path.Path.Count > 1)
                {
                    if (bestPath == null || path.Length < bestPath.Length)
                    {
                        bestPath = path;
                    }
                }
            }
            return(bestPath?.Path);
        }
        private (List <Point>, Direction)? GetTheNearestToExit(IEnumerable <Point> aims)
        {
            var aimPathes = new Dictionary <Point, AimPath>();

            foreach (var point in aims)
            {
                var path = FullBoard.GetPathFromHero(point, PrevFullBoard);
                if (path != null && path.Path.Count > 1)
                {
                    aimPathes[point] = path;
                }
            }
            foreach (var item in aimPathes.OrderBy(x => GetLenghtToExit(FullBoard, x.Key) * 2 + x.Value.Length))
            {
                var aim  = item.Key;
                var path = item.Value;

                if (!FullBoard.IsHeroBarrierAt(aim.ShiftLeft()) && !FullBoard.IsAt(aim.ShiftLeft(), Element.START) && !FullBoard.IsInDanger(aim.ShiftLeft(), PrevFullBoard) &&
                    GetLenghtToExit(FullBoard, aim.ShiftLeft()) > GetLenghtToExit(FullBoard, aim) &&
                    !FullBoard.IsHeroBarrierAt(aim.ShiftLeft().ShiftLeft()) &&
                    FullBoard.GetPathFromHero(aim.ShiftLeft().ShiftLeft(), PrevFullBoard) != null)
                {
                    path = FullBoard.GetPathFromHero(aim.ShiftLeft(), PrevFullBoard);
                    if (path != null)
                    {
                        return(path.Path, Direction.Left);
                    }
                }

                if (!FullBoard.IsHeroBarrierAt(aim.ShiftRight()) && !FullBoard.IsAt(aim.ShiftRight(), Element.START) && !FullBoard.IsInDanger(aim.ShiftRight(), PrevFullBoard) &&
                    GetLenghtToExit(FullBoard, aim.ShiftRight()) > GetLenghtToExit(FullBoard, aim) &&
                    !FullBoard.IsHeroBarrierAt(aim.ShiftRight().ShiftRight()) &&
                    FullBoard.GetPathFromHero(aim.ShiftRight().ShiftRight(), PrevFullBoard) != null)
                {
                    path = FullBoard.GetPathFromHero(aim.ShiftRight(), PrevFullBoard);
                    if (path != null)
                    {
                        return(path.Path, Direction.Right);
                    }
                }

                if (!FullBoard.IsHeroBarrierAt(aim.ShiftTop()) && !FullBoard.IsAt(aim.ShiftTop(), Element.START) && !FullBoard.IsInDanger(aim.ShiftTop(), PrevFullBoard) &&
                    GetLenghtToExit(FullBoard, aim.ShiftTop()) > GetLenghtToExit(FullBoard, aim) &&
                    !FullBoard.IsHeroBarrierAt(aim.ShiftTop().ShiftTop()) &&
                    FullBoard.GetPathFromHero(aim.ShiftTop().ShiftTop(), PrevFullBoard) != null)
                {
                    path = FullBoard.GetPathFromHero(aim.ShiftTop(), PrevFullBoard);
                    if (path != null)
                    {
                        return(path.Path, Direction.Up);
                    }
                }

                if (!FullBoard.IsHeroBarrierAt(aim.ShiftBottom()) && !FullBoard.IsAt(aim.ShiftBottom(), Element.START) && !FullBoard.IsInDanger(aim.ShiftBottom(), PrevFullBoard) &&
                    GetLenghtToExit(FullBoard, aim.ShiftBottom()) > GetLenghtToExit(FullBoard, aim) &&
                    !FullBoard.IsHeroBarrierAt(aim.ShiftBottom().ShiftBottom()) &&
                    FullBoard.GetPathFromHero(aim.ShiftBottom().ShiftBottom(), PrevFullBoard) != null)
                {
                    path = FullBoard.GetPathFromHero(aim.ShiftBottom(), PrevFullBoard);
                    if (path != null)
                    {
                        return(path.Path, Direction.Down);
                    }
                }
            }
            return(null);
        }