예제 #1
0
        public IEnumerable <AStarState> GetJumpsIntoFills(AStarState botState)
        {
            var currentWeight = botState.Weight;

            foreach (var adjacent in botState.EndPosition.GetAdjacents())
            {
                if (!Matrix.Contains(adjacent) || Matrix.IsVoid(adjacent))
                {
                    continue;
                }
                var weight = currentWeight + GetInFillWeight();

                if (!GroundedChecker.CanRemove(new[] { adjacent, botState.DestroyedCell }.Where(c => c != null).ToHashSet()))
                {
                    continue;
                }

                yield return(new AStarState
                {
                    Move1 = adjacent - botState.EndPosition,
                    StartPosition = botState.EndPosition,
                    EndPosition = adjacent,
                    DestroyedCell = adjacent,
                    LastDestroyedCell = botState.DestroyedCell,
                    Weight = weight,
                    Dad = botState,
                    MaxPotentialWeight = weight + GetPotentialOptimalWeight(adjacent, botState.Straight),
                    Straight = botState.Straight
                });
            }
        }
예제 #2
0
        public IEnumerable <AStarState> GetSJumps(AStarState botState)
        {
            var botPosition   = botState.EndPosition;
            var currentWeight = botState.Weight;

            foreach (var vector in new Vector(0, 0, 0).GetAdjacents())
            {
                for (int i = 1; i <= 15; i++)
                {
                    if (botState.DestroyedCell != null && i > 1)
                    {
                        break;
                    }

                    var move     = vector * i;
                    var position = botPosition + move;
                    if (!Matrix.Contains(position) || Matrix.IsFull(position) || IsForbiddenArea(position) || position == BotPosition)
                    {
                        break;
                    }
                    var weight = currentWeight + GetSMoveWeight(i);
                    yield return(new AStarState
                    {
                        LastDestroyedCell = botState.DestroyedCell,
                        Move1 = move,
                        Dad = botState,
                        StartPosition = botState.EndPosition,
                        EndPosition = position,
                        Weight = weight,
                        MaxPotentialWeight = weight + GetPotentialOptimalWeight(position, botState.Straight),
                        Straight = botState.Straight
                    });
                }
            }
        }
예제 #3
0
        public bool FindPath(out List <Vector> movePositions, out List <ICommand> commands, out int iterationsCount)
        {
            var priorityQueue = new PriorityQueue <AStarState>();
            var startState    = new AStarState
            {
                DestroyedCell = Model.IsFull(BotPosition) ? BotPosition : null,
                EndPosition   = BotPosition,
                Straight      = true
            };
            var endState = new AStarState
            {
                StartPosition = End,
                EndPosition   = End,
                Straight      = false,
                DestroyedCell = Matrix.IsFull(End) ? End : null
            };

            priorityQueue.Enqueue(0, startState);
            priorityQueue.Enqueue(0, endState);
            MinStates[Tuple.Create(startState.EndPosition, false)] = startState;
            MinStates[Tuple.Create(endState.EndPosition, false)]   = endState;

            bool       isEnd     = false;
            AStarState result    = null;
            AStarState endResult = null;

            iterationsCount = 0;
            var bestWeight = long.MaxValue;

            while (!priorityQueue.Empty)
            {
                var state = priorityQueue.Dequeue();
                if (MinStates.TryGetValue(Tuple.Create(state.EndPosition, state.DestroyedCell != null), out var minState) && minState.Weight < state.Weight)
                {
                    continue;
                }

                foreach (var newState in GetSJumps(state).Concat(GetLJumps(state)).Concat(GetJumpsIntoFills(state)))
                {
                    if (MinStates.TryGetValue(Tuple.Create(newState.EndPosition, newState.DestroyedCell != null), out var oldState) && oldState.Weight <= newState.Weight && newState.Straight == oldState.Straight)
                    {
                        continue;
                    }

                    if (oldState != null && newState.Straight != oldState.Straight)
                    {
                        if (newState.Straight)
                        {
                            result    = newState;
                            endResult = oldState;
                        }
                        else
                        {
                            result    = oldState;
                            endResult = newState;
                        }

                        if (newState.DestroyedCell == null)
                        {
                            isEnd = true;
                            break;
                        }
                    }

                    MinStates[Tuple.Create(newState.EndPosition, newState.DestroyedCell != null)] = newState;
                    priorityQueue.Enqueue(-newState.MaxPotentialWeight + (newState.Straight
                                                                      ? (End - newState.EndPosition).Euclidlen
                                                                      : (BotPosition - newState.EndPosition).Euclidlen) / Matrix.R / 3, newState);
                    iterationsCount++;
                }

                if (isEnd)
                {
                    break;
                }
            }

            if (!isEnd)
            {
                movePositions = null;
                commands      = null;
                return(false);
            }

            var states = result.GetStates().Reverse().Concat(endResult.GetStates()).ToList();

            commands      = states.SelectMany(state => state.GetCommands()).ToList();
            movePositions = states.SelectMany(state => state.Straight ? state.GetUsedVectors() : state.GetUsedVectors().Reverse()).ToList();

            return(true);
        }
예제 #4
0
        public IEnumerable <AStarState> GetLJumps(AStarState botState)
        {
            var ss = new[] { -1, 1, -2, 2, -3, 3, -4, 4, -5, 5 };

            if (botState.DestroyedCell != null)
            {
                yield break;
            }

            var botPosition   = botState.EndPosition;
            var currentWeight = botState.Weight;

            var moveVectors = new[]
            {
                new Vector(1, 0, 0),
                new Vector(0, 1, 0),
                new Vector(0, 0, 1)
            };

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    bool bannedNX = false;
                    bool bannedPX = false;

                    foreach (var x in ss)
                    {
                        var move1 = moveVectors[i] * x;
                        if (x < 0 && bannedNX || x > 0 && bannedPX)
                        {
                            continue;
                        }
                        if (!Matrix.Contains(botPosition + move1) || Matrix.IsFull(botPosition + move1) ||
                            IsForbiddenArea(botPosition + move1) || botPosition + move1 == BotPosition)
                        {
                            if (x < 0)
                            {
                                bannedNX = true;
                            }
                            else
                            {
                                bannedPX = true;
                            }
                            continue;
                        }

                        bool bannedNY = false;
                        bool bannedPY = false;

                        foreach (var y in ss)
                        {
                            var move2 = moveVectors[j] * y;
                            if (y < 0 && bannedNY || y > 0 && bannedPY)
                            {
                                continue;
                            }
                            if (!Matrix.Contains(botPosition + move1 + move2) || Matrix.IsFull(botPosition + move1 + move2) ||
                                IsForbiddenArea(botPosition + move1 + move2) || botPosition + move1 + move2 == BotPosition)
                            {
                                if (y < 0)
                                {
                                    bannedNY = true;
                                }
                                else
                                {
                                    bannedPY = true;
                                }
                                continue;
                            }

                            var position = botPosition + move1 + move2;
                            var weight   = currentWeight + GetLMoveWeight(x, y);
                            var state    = new AStarState
                            {
                                Move1              = move1,
                                Move2              = move2,
                                Dad                = botState,
                                StartPosition      = botState.EndPosition,
                                EndPosition        = position,
                                Weight             = weight,
                                MaxPotentialWeight = weight + GetPotentialOptimalWeight(position, botState.Straight),
                                Straight           = botState.Straight
                            };

                            yield return(state);
                        }
                    }
                }
            }
        }