private void FindDeadlockedSets(int size, int minimumAdjacent)
        {
            // If only estimating, calculate the estimate;
            if (estimate)
            {
                int nonAdjacent = (int)Math.Pow(freeCoordinates.Length, size - minimumAdjacent);
                int adjacent = (int)Math.Pow(8, minimumAdjacent);
                AddEstimate("solved", size, nonAdjacent + adjacent);
                return;
            }

            // Create a subset level with the boxes placed anywhere and no sokoban.
            subsetLevel = LevelUtils.GetSubsetLevel(level, false, size);

            // Create a frozen deadlock finder for the subset level.
            DeadlockFinder frozenFinder = new FrozenDeadlockFinder(subsetLevel, simpleDeadlockMap);

            // Create the deadlock solver.
            SubsetSolver subsetSolver = new ForewardsSubsetSolver(subsetLevel);
            subsetSolver.CancelInfo = cancelInfo;
            subsetSolver.PrepareToSolve();

            // Iterate over all unique sized sets of free inside coordinates.
            foreach (Coordinate2D[] coords in CoordinateUtils.GetAdjacentCoordinateSets(freeCoordinates, size, minimumAdjacent, false))
            {
                // Check for cancel.
                if (cancelInfo.Cancel)
                {
                    return;
                }

                // Bump the actual count.
                ++actualCount;

                // Move the boxes into postion.
                subsetLevel.MoveBoxes(coords);

                // Skip sets that are already complete.
                if (subsetLevel.IsComplete)
                {
                    continue;
                }

                // Don't bother trying to solve deadlocks that
                // the frozen deadlock finder can find.
                if (frozenFinder.IsDeadlocked())
                {
                    // But do add the deadlock if there is
                    // no unconditional proper subset that
                    // is deadlocked.
                    if (!IsAnyProperSubsetDeadlocked(true, coords))
                    {
                        AddDeadlock(coords);
                    }
                    continue;
                }

                // If any subset is deadlocked then skip this set.
                if (IsAnyProperSubsetDeadlocked(coords))
                {
                    continue;
                }

            #if DEBUG
                // Verify minimum adjacency.
                if (minimumAdjacent > 0 && CountAdjacent(false, coords) < minimumAdjacent)
                {
                    throw new Exception("set enumerator violated adjacency");
                }
            #endif

                if (IsPositionSolvable(subsetSolver, coords))
                {
                    // Skip a priori solvable levels.
                    continue;
                }

                // Try to solve the level.
                subsetSolver.Solve();

                // If not solved add the deadlocked set.
                if (subsetSolver.SolvedNone)
                {
                    // This is an unconditional deadlock set.
                    AddDeadlock(coords);
                }
                else if (!subsetSolver.SolvedAll)
                {
                    // This deadlock depends on the sokoban.
                    AddDeadlock(subsetSolver.SokobanMap, coords);
                }
            }

            // Finish adding deadlocks.
            PromoteDeadlocks();
        }
        protected void FindFrozenDeadlockedSets(int size)
        {
            // Create a subset level with the boxes placed anywhere and no sokoban.
            Level deadlockLevel = LevelUtils.GetSubsetLevel(level, false, size);

            // Create a frozen deadlock finder for the subset level.
            DeadlockFinder frozenFinder = new FrozenDeadlockFinder(deadlockLevel, simpleDeadlockMap);

            // Iterate over all unique sets of adjacent free inside coordinates
            // of the specified size consisting only of squares added in
            // alternating perpendicular directions.
            foreach (Coordinate2D[] coords in CoordinateUtils.GetAlternatingAxisSets(freeCoordinates, size))
            {
                // Check for cancel.
                if (cancelInfo.Cancel)
                {
                    return;
                }

                // Move the boxes into position.
                deadlockLevel.MoveBoxes(coords);

                // Check whether the set is a frozen deadlock.
                if (frozenFinder.IsDeadlocked() && !IsDeadlocked(true, deadlockLevel))
                {
                    // Add the deadlock.
                    AddDeadlock(coords);
                }
            }

            // Finish adding deadlocks.
            PromoteDeadlocks();
        }