Exemple #1
0
 public static int SolutionChanges(Level level, MoveList solution)
 {
     if (solution == null)
     {
         return -1;
     }
     Level tempLevel = new Level(level);
     int changes = 0;
     int lastBoxIndex = -1;
     foreach (OperationDirectionPair pair in solution)
     {
         if (pair.Operation == Operation.Push)
         {
             int boxIndex = tempLevel.BoxIndex(tempLevel.SokobanCoordinate + pair.Direction);
             if (boxIndex != lastBoxIndex)
             {
                 changes++;
                 lastBoxIndex = boxIndex;
             }
         }
         tempLevel.Move(pair);
     }
     return changes;
 }
Exemple #2
0
        public static MoveList ShortenToFirstPush(Level level, MoveList moveList)
        {
            // Perform and count initial moves.
            int initialMoves = 0;
            foreach (OperationDirectionPair pair in moveList)
            {
                if (pair.Operation == Operation.Push)
                {
                    break;
                }
                level.Move(pair);
                initialMoves++;
            }

            // Make a copy of the move list and shorten it.
            MoveList finalMoveList = new MoveList(moveList);
            finalMoveList.RemoveRange(0, initialMoves);

            return finalMoveList;
        }
Exemple #3
0
 public static int MinimumBoxMoves(Level level, MoveList solution)
 {
     if (solution == null)
     {
         return -1;
     }
     int boxes = level.Boxes;
     if (boxes == 0)
     {
         return 0;
     }
     int[] boxMoves = new int[boxes];
     Level tempLevel = new Level(level);
     foreach (OperationDirectionPair pair in solution)
     {
         if (pair.Operation == Operation.Push)
         {
             boxMoves[tempLevel.BoxIndex(tempLevel.SokobanCoordinate + pair.Direction)]++;
         }
         tempLevel.Move(pair);
     }
     int min = int.MaxValue;
     foreach (int moves in boxMoves)
     {
         min = Math.Min(min, moves);
     }
     return min;
 }
Exemple #4
0
 public static bool IsSolutionCompatible(Level level, MoveList solution)
 {
     Level tempLevel = new Level(level);
     foreach (OperationDirectionPair pair in solution)
     {
         if (!tempLevel.Move(pair.Operation, pair.Direction))
         {
             if (pair.Operation != Operation.Move || !tempLevel.Move(Operation.Push, pair.Direction))
             {
                 return false;
             }
         }
     }
     return true;
 }
Exemple #5
0
        public static Array2D<int> GetTraversalMap(Level level, MoveList solution)
        {
            // Create a traversal map counting the number of times
            // each square is occupied during the course of the solution,
            // initialized to zero.
            Array2D<int> traversalMap = new Array2D<int>(level.Height, level.Width);
            Level tempLevel = new Level(level);

            // Count the starting positions as one traversal.
            traversalMap[tempLevel.SokobanCoordinate]++;
            foreach (Coordinate2D coord in tempLevel.BoxCoordinates)
            {
                traversalMap[coord]++;
            }

            // Count all sokoban positions and box movements in the solution.
            foreach (OperationDirectionPair pair in solution)
            {
                if (pair.Operation == Operation.Push)
                {
                    traversalMap[tempLevel.SokobanCoordinate + 2 * pair.Direction]++;
                }
                tempLevel.Move(pair);
                traversalMap[tempLevel.SokobanCoordinate]++;
            }

            return traversalMap;
        }
Exemple #6
0
        protected void CollectSolution(Node leaf)
        {
            foundSolution = true;

            // Don't bother if we're not collection solutions.
            if (!collectSolutions)
            {
                return;
            }

            // Prepare to construct the solution.
            MoveList solution = new MoveList();
            Level tempLevel = new Level(originalLevel);
            tempLevel.Validate = validate;
            PathFinder tempFinder = PathFinder.CreateInstance(tempLevel, true);

            // Iterate over the nodes from the root to the leaf.
            int previousPushes = 0;
#if false
            List<Node> nodeList = FindParents(root, leaf);
#else
            List<Node> nodeList = new List<Node>();
            for (int i = 0; i < current.ParentIndex; i++)
            {
                nodeList.Add(current.Parents[i]);
            }
            nodeList.Add(leaf);
#endif
            foreach (Node node in nodeList)
            {
                // Check whether we need to move the sokoban.
                if (node.Coordinate != tempLevel.SokobanCoordinate)
                {
                    // Move the sokoban to the box.
                    solution.AddRange(tempFinder.FindAndGetPath(node.Coordinate));
                    tempLevel.MoveSokoban(node.Coordinate);
                }

                // Check whether we need to push a box.
                int consecutivePushes = node.Pushes - previousPushes;
                if (consecutivePushes != 0)
                {
                    // Push the box one or more times.
                    OperationDirectionPair push = new OperationDirectionPair(Levels.Operation.Push, node.Direction);
                    for (int j = 0; j < consecutivePushes; j++)
                    {
                        solution.Add(push);
                        tempLevel.Move(push);
                    }
                    previousPushes = node.Pushes;
                }
            }

            // Validate the solution.
            if (!tempLevel.IsComplete)
            {
                throw Abort("constructed move list does not solve level");
            }
            if (optimizeMoves && solution.Count != leaf.Moves)
            {
                throw Abort("constructed move list does not match leaf tree in moves");
            }
            if (LevelUtils.SolutionPushes(solution) != leaf.Pushes)
            {
                throw Abort("constructed move list does not match leaf tree in pushes");
            }

            // Add the solution.
            solutions.Add(solution);

            int moves = solution.Count;
            int pushes = LevelUtils.SolutionPushes(solution);
            moveLimit = Math.Min(moveLimit, moves);
            pushLimit = Math.Min(pushLimit, pushes);

#if DEBUG
            if (verbose)
            {
                Log.DebugPrint("                            found solution: {0}/{1}", moves, pushes);
            }
#endif
        }