Beispiel #1
0
        public List <AgentCommand> CreateOnlyFirstSolutionCommand(HighlevelMove move, State currentState, int agentIndex)
        {
            var box = move.MoveThis;

            // Make all blockages into "fake" walls
            foreach (Entity e in currentState.Entities)
            {
                Level.AddWall(e.Pos);
            }

            Level.RemoveWall(box.Pos);
            Level.RemoveWall(move.ToHere);

            List <AgentCommand> result = new List <AgentCommand>();

            if (move.UsingThisAgent.HasValue)
            {
                int boxIndex = Array.IndexOf(Boxes, move.MoveThis);
                Level.RemoveWall(move.UsingThisAgent.Value.Pos);
                result = CreateSolutionCommands(move, move.ToHere, agentIndex, boxIndex);
            }
            else
            {
                var agentToPos = RunAStar(move.MoveThis.Pos, move.ToHere);
                MoveToLocation(agentToPos, result, agentIndex);
            }

            Level.ResetWalls();
            return(result);
        }
Beispiel #2
0
        private static void VerifyCommands(Level level, HighlevelMove move, List <AgentCommand> expectedCommands)
        {
            List <AgentCommands> agentCommands = new LessNaiveSolver(level, level, new List <HighlevelMove>()
            {
                move
            }).Solve();
            List <AgentCommand> actualCommands = agentCommands.First().Commands;

            CollectionAssert.AreEqual(expectedCommands, actualCommands);
        }
Beispiel #3
0
        private static void VerifyMoveAgentToGoalCreator(string levelString, List <AgentCommand> expectedCommands)
        {
            Level level        = TestTools.StringToLevel(levelString);
            Level clearedLevel = TestTools.StringToLevel(levelString.Replace('G', ' '));

            Entity agent = level.InitialState.Entities.Single(x => x.Type == '0');
            Entity goal  = level.InitialState.Entities.Single(x => x.Type == 'G');

            HighlevelMove move = new HighlevelMove(clearedLevel.InitialState, agent, goal.Pos, null, null);

            VerifyCommands(clearedLevel, move, expectedCommands);
        }
Beispiel #4
0
        private static void VerifyMoveBoxToGoalCreator(string levelString, List <AgentCommand> expectedCommands)
        {
            Level level        = TestTools.StringToLevel(levelString);
            Level clearedLevel = TestTools.StringToLevel(levelString.Replace('G', ' ').Replace('F', ' '));

            Entity agent         = level.InitialState.Entities.Single(x => x.Type == '0');
            Entity box           = level.InitialState.Entities.Single(x => x.Type == 'B');
            Entity goal          = level.InitialState.Entities.Single(x => x.Type == 'G');
            Point  agentFinalPos = level.InitialState.Entities.Single(x => x.Type == 'F').Pos;

            HighlevelMove move = new HighlevelMove(clearedLevel.InitialState, box, goal.Pos, agent, agentFinalPos);

            VerifyCommands(clearedLevel, move, expectedCommands);
        }
Beispiel #5
0
        private void FindDistantTurningPoint(
            HighlevelMove plan,
            ref Point agentNextToBox,
            Point agentEndPos,
            ref Point?turnPoint,
            ref Point turnIntoPoint,
            Point boxPos,
            Point goalPos,
            List <AgentCommand> commands,
            int agentIndex,
            int boxIndex,
            ref List <Point> boxToAgentEnd,
            ref bool startPull,
            ref bool endPull,
            ref int count,
            ref int skipFirst
            )
        {
            turnPoint = plan.UTurnPos.Value;

            // Find spot beside turning point.
            foreach (Point dirDelta in Direction.NONE.DirectionDeltas())
            {
                Point dirP = turnPoint.Value + dirDelta;
                if (!Level.IsWall(dirP) && dirP != agentNextToBox)
                {
                    turnIntoPoint = turnPoint.Value + dirDelta;
                    break;
                }
            }

            // Reach turning point.
            var pathToTurnIntoPoint = RunAStar(boxPos, turnIntoPoint);

            // If A* doesn't go through selected turn(into) points
            //if (pathToTurnIntoPoint[pathToTurnIntoPoint.Count - 2] != turnPoint)
            //{
            //    List<Point> blocks = new List<Point>();
            //    while (pathToTurnIntoPoint[pathToTurnIntoPoint.Count - 2] != turnPoint)
            //    {
            //        Point p = pathToTurnIntoPoint[pathToTurnIntoPoint.Count - 2];
            //        Level.AddWall(p);
            //        blocks.Add(p);
            //        pathToTurnIntoPoint = RunAStar(boxPos, turnIntoPoint);
            //    }
            //    foreach (Point p in blocks)
            //        Level.RemoveWall(p);
            //}



            startPull = !pathToTurnIntoPoint.Contains(agentNextToBox);

            if (startPull)
            {
                //if (!pathToTurnIntoPoint.Contains(agentNextToBox))
                PushOnPath(pathToTurnIntoPoint, agentNextToBox, commands, agentIndex, boxIndex);
                Agents[agentIndex] = Agents[agentIndex].Move(turnPoint.Value);
                boxToAgentEnd      = RunAStar(turnIntoPoint, agentEndPos);
            }
            else
            {
                // SARegExAZ is an excellent example... of a mess.
                PullOnPath(pathToTurnIntoPoint, commands, agentIndex, boxIndex);
                Agents[agentIndex] = Agents[agentIndex].Move(turnIntoPoint);
                boxToAgentEnd      = RunAStar(turnPoint.Value, agentEndPos);
            }

            agentNextToBox = Agents[agentIndex].Pos; // Agent is always next to box.
            endPull        = boxToAgentEnd.Contains(goalPos);
            startPull      = !endPull;

            count     = 0;
            skipFirst = startPull ? 1 : 0;
            foreach (var pos in boxToAgentEnd.Skip(skipFirst))
            {
                count++;
                if (!IsCorridor(pos))
                {
                    turnPoint = pos;
                    break;
                }
            }
            count += skipFirst;
        }
Beispiel #6
0
        public List <AgentCommand> CreateSolutionCommands(HighlevelMove plan, Point goalPos, int agentIndex, int boxIndex)
        {
            List <AgentCommand> commands = new List <AgentCommand>();

            var          agent       = plan.UsingThisAgent.Value;
            var          agentEndPos = plan.AgentFinalPos.Value;
            var          box         = plan.MoveThis;
            List <Point> agentToBox  = null;

            // Avoids stupid square problems.
            if (Point.ManhattenDistance(box.Pos, goalPos) == 1)
            {
                if (IsStraightCorridor(goalPos) || IsStraightCorridor(box.Pos))
                {
                    // Do nothing
                }
                else if (box.Pos == agentEndPos)
                {
                    // Force agent's pathfinding to box to avoid the goal.
                    Level.AddWall(goalPos);
                }
                else if (Point.ManhattenDistance(agentEndPos, goalPos) == 1)
                { // Force agent's position next to box onto the goal.
                    Level.AddWall(box.Pos);
                    agentToBox = RunAStar(agent.Pos, goalPos);
                    agentToBox.Add(box.Pos);
                }
            }

            if (agentToBox == null)
            {
                agentToBox = RunAStar(agent.Pos, box.Pos);
            }

            Level.RemoveWall(goalPos);
            Level.RemoveWall(box.Pos);

            //Remove box location from the path as the path should end next to the box
            agentToBox.RemoveAt(agentToBox.Count - 1);
            MoveToLocation(agentToBox, commands, agentIndex);
            Point agentNextToBox = agentToBox[agentToBox.Count - 1];

            var boxToAgentEnd = RunAStar(box.Pos, agentEndPos);

            if (boxToAgentEnd.Count == 3 && agentNextToBox == goalPos && boxToAgentEnd[1] != goalPos)
            {
                boxToAgentEnd[1] = goalPos; // If pathfinding dun goofed, then force agent to pull through goal position when it OBVIOUSLY should.
            }
            bool startPull = boxToAgentEnd.Contains(agentNextToBox);
            bool endPull   = boxToAgentEnd.Contains(goalPos);

            if (agentNextToBox == goalPos) // If agent blocks goal position
            {
                startPull = true;          // Forces agent to locate distant U-turn location, pull at U-turn, and push to goal.
            }
            List <Point> firstPart  = null;
            List <Point> secondPart = null;

            if (startPull != endPull)
            {
                Point?turnPoint     = null;
                Point turnIntoPoint = new Point();

                //Find somewhere to turn around
                int count     = 0;
                int skipFirst = startPull ? 1 : 0;
                foreach (var pos in boxToAgentEnd.Skip(skipFirst))
                {
                    count++;
                    if (!IsCorridor(pos))
                    {
                        turnPoint = pos;
                        break;
                    }
                }
                count += skipFirst;


                // If we failed to find a turn point on the route
                if (!turnPoint.HasValue)
                {
                    FindDistantTurningPoint(plan, ref agentNextToBox, agentEndPos, ref turnPoint, ref turnIntoPoint, box.Pos, goalPos, commands, agentIndex, boxIndex, ref boxToAgentEnd, ref startPull, ref endPull, ref count, ref skipFirst);
                }

                turnIntoPoint = FindSpaceToTurn(boxToAgentEnd, turnPoint.Value, goalPos, agentNextToBox);

                firstPart = new List <Point>();
                firstPart.AddRange(boxToAgentEnd.Take(count));
                firstPart.Add(turnIntoPoint);

                secondPart = new List <Point>();
                secondPart.Add(turnIntoPoint);
                secondPart.AddRange(boxToAgentEnd.Skip(count - 1));
                if (!endPull)
                {
                    secondPart.Add(goalPos);
                }
                if (startPull && !endPull)
                {
                    secondPart.RemoveAt(0);
                }
            }
            else
            {
                firstPart = new List <Point>();
                firstPart.AddRange(boxToAgentEnd);
                if (!startPull)
                {
                    firstPart.Add(goalPos);
                }
            }

            Point?firstPartAgentEndPos = null;

            if (startPull)
            {
                PullOnPath(firstPart, commands, agentIndex, boxIndex);
                if (secondPart != null)
                {
                    firstPartAgentEndPos = firstPart.Last();
                }
            }
            else
            {
                PushOnPath(firstPart, agentNextToBox, commands, agentIndex, boxIndex);
                if (secondPart != null)
                {
                    firstPartAgentEndPos = firstPart[firstPart.Count - 2];
                }
            }

            if (secondPart != null)
            {
                if (endPull)
                {
                    PullOnPath(secondPart, commands, agentIndex, boxIndex);
                }
                else
                {
                    PushOnPath(secondPart, firstPartAgentEndPos.Value, commands, agentIndex, boxIndex);
                }
            }

            return(commands);
        }