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(); }