private List <Point> GetZombieAims()
        {
            var target = FullBoard.GetZombies().Where(x => x.GetLengthTo(FullBoard.GetMe()) <= 5).ToList();
            var aims   = new List <Point>();

            aims.AddRange(target.Select(x => x.ShiftLeft().ShiftLeft()).Where(x => !FullBoard.IsHeroBarrierAt(x) && !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT)));
            aims.AddRange(target.Select(x => x.ShiftRight().ShiftRight()).Where(x => !FullBoard.IsHeroBarrierAt(x) && !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT)));
            aims.AddRange(target.Select(x => x.ShiftLeft().ShiftLeft()).Where(x => !FullBoard.IsHeroBarrierAt(x) && !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT)));
            aims.AddRange(target.Select(x => x.ShiftRight().ShiftRight()).Where(x => !FullBoard.IsHeroBarrierAt(x) && !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT)));
            return(aims);
        }
        private List <Point> GetFarmAims()
        {
            var target = new List <Point>();

            target.AddRange(FullBoard.GetOtherHeroes().Where(x => FullBoard.GetStarts().Any(start => start.GetLengthTo(x) < 2)).ToList());
            target.AddRange(FullBoard.GetStarts());
            var aims = new List <Point>();

            aims.AddRange(target.Select(x => x.ShiftLeft()).Where(x => !FullBoard.IsHeroBarrierAt(x) && !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT)));
            aims.AddRange(target.Select(x => x.ShiftRight()).Where(x => !FullBoard.IsHeroBarrierAt(x) && !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT)));
            aims.AddRange(target.Select(x => x.ShiftTop()).Where(x => !FullBoard.IsHeroBarrierAt(x) && !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT)));
            aims.AddRange(target.Select(x => x.ShiftBottom()).Where(x => !FullBoard.IsHeroBarrierAt(x) && !FullBoard.IsInDanger(x, PrevFullBoard) && !FullBoard.IsAt(x, Element.LASER_DOWN, Element.LASER_LEFT, Element.LASER_UP, Element.LASER_RIGHT)));
            return(aims);
        }
        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);
        }