protected virtual void PrepareToSolve() { // Give some feedback because calculating deadlocks can take some time. SetInfo("Preparing to solve level..."); // Start the clock. startSnapshot = TimeSnapshot.Now; // Put solver in a sane state in case there are any exceptions. solutions.Clear(); // Validate parameter combinations. ValidateParameters(); // Avoid recalculating as much as possible if the level hasn't changed. if (!precalculatedLevel) { PrecalculateLevel(); // Check for cancellation during pre-calculation. if (cancelInfo.Cancel) { return; } precalculatedLevel = true; } // Avoid reallocating these big data structures for multiple solver runs. if (!allocated) { nodes = new NodeCollection(initialCapacity, validate); transpositionTable = new TranspositionTable(nodes, initialCapacity); current.Parents = new Node[maxParents]; allocated = true; } else { nodes.Clear(); transpositionTable.Clear(); } // However, the positions of the occupants might have changed. // This gives a performance boost when calculating deadlocks. level.CopyOccupantsFrom(originalLevel); CheckLevel(); // The push map depends on the actual starting box positions. // This could be avoided if we didn't use the no-box map. CalculatePushMap(); // Initialize solver variables. current.ParentIndex = 0; level.Validate = validate; transpositionTable.Validate = validate; foundSolution = false; moveLimit = int.MaxValue; pushLimit = int.MaxValue; duplicates = 0; boxStart = 0; // Prime the "current" values. current.Initialize(level, pathFinder); // Create the root of the search tree. root = new Node(nodes, current.SokobanRow, current.SokobanColumn, Direction.None, 0, 0); // Record the clock. donePreparingSnapshot = TimeSnapshot.Now; }
public bool Solve() { PrepareToSolve(); // Check for cancel. if (cancelInfo.Cancel) { SetError("Solver canceled."); return false; } if (!verbose) { SetInfo("Verbose information not enabled."); } error = ""; int depth = 0; while (true) { if (foundSolution && !collectSolutions) { break; } if (Finished()) { break; } int lastNodeCount = nodes.Visited; SearchTree(root, ++depth); if (cancelInfo.Cancel) { SetError("Solver canceled."); break; } if (nodes.Count >= maximumNodes) { SetError("Maximum nodes exceeded."); break; } if (nodes.Visited == lastNodeCount) { if (solutions.Count == 0) { SetError("All positions examined lead to dead ends."); } break; } } stopSnapshot = TimeSnapshot.Now; SortSolutions(); // Populate information property. if (verbose) { SetFinalInfo(depth); } if (validate) { SolverValidator validator = new SolverValidator(this, nodes, root, transpositionTable); validator.CheckDataStructures(); } return foundSolution; }