protected override void SearchTree(Node node, int depth)
        {
            // If the root hasn't been searched yet, manually expand it.
            if (!node.Searched)
            {
                MoveState state = new MoveState();
                node.Searched = true;
                HashKey hashKey = current.HashKey;
                bool result = IsTerminal(ref state, node) || !FindChildren(node);
                current.HashKey = hashKey;
            }

            int lastNodeCount = nodes.Visited;
            Search(node);
            if (verbose)
            {
                string searching = foundSolution ? "Post-searching" : "Searching";
                string info = String.Format("{0} to depth {1},\r\n", searching, depth);
                info += String.Format("Examined {0:#,##0} new nodes ({1:#,##0} total)...",
                    nodes.Visited - lastNodeCount, nodes.Visited);
                info += String.Format("\r\nNodes allocated {0:#,##0}\r\n", nodes.Allocated);
                SetInfo(info);
            }
        }
        private void Search(Node node)
        {
            // Check for cancel.
            if (cancelInfo.Cancel)
            {
                return;
            }

            MoveState state = new MoveState();
            state.PrepareToMove(node, ref current);

            int score = Node.MaxScore;
            Node previous = node;
            for (Node child = node.Child; !Node.IsEmpty(child); child = child.Sibling)
            {
                if (child.Terminal)
                {
                    // Another node displaced this node from the transposition table.
                    RemoveDescendants(child);
                    RemoveScore(child);
                    node.Remove(previous, child);
                    nodes.Release(child);
                    continue;
                }

                if (child.Score > scoreLimit)
                {
                    if (child.Score < score)
                    {
                        score = child.Score;
                    }
                    previous = child;
                    continue;
                }

                state.DoMove(child, ref current);

                if (child.Searched)
                {
                    Search(child);
                    if (!child.HasChildren)
                    {
                        node.Remove(previous, child);
                        RemoveScore(child);
                        if (child.InTable)
                        {
                            child.Dormant = true;
                        }
                        else
                        {
                            nodes.Release(child);
                        }
                        goto removed;
                    }
                }
                else
                {
                    // Remove the unsearched score.
#if false
                    int oldScore = child.Score;
#endif
                    RemoveScore(child);

                    // Search the child node.
                    child.Searched = true;

                    if (level.IsComplete)
                    {
                        child.Complete = true;
                        CollectSolution(child);
                        node.Remove(previous, child);
                        child.Dormant = true;
                        RemoveScore(child);
                        goto removed;
                    }

                    if (IsTerminal(ref state, child) || !FindChildren(child))
                    {
                        node.Remove(previous, child);
                        if (child.InTable)
                        {
                            // Node had no children so it is effectively deadlocked.
                            transpositionTable[current.HashKey] = Node.Empty;
                        }
                        RemoveScore(child);
                        nodes.Release(child);
                        goto removed;
                    }

#if false
                    // XXX: This works but doesn't seem to help.
                    if (child.Score == oldScore)
                    {
                        Search(child);
                        if (!child.HasChildren)
                        {
                            node.Remove(nodes, previous, child);
                            RemoveScore(child);
                            if (child.InTable)
                            {
                                child.Dormant = true;
                            }
                            else
                            {
                                child.Release(nodes);
                            }
                            goto removed;
                        }
                    }
#endif
                }

                if (child.Score < score)
                {
                    score = child.Score;
                }

                previous = child;

            removed:

                state.UndoMove(ref current);
            }
            SetScore(node, score);

            state.FinishMoving(ref current);
        }
        protected override void SearchTree(Node node, int depth)
        {
            // If the root hasn't been searched yet, manually expand it.
            if (!node.Searched)
            {
                MoveState state = new MoveState();
                node.Searched = true;
                HashKey hashKey = current.HashKey;
                bool result = IsTerminal(ref state, node) || !FindChildren(node);
                current.HashKey = hashKey;
            }

            if (foundSolution && !optimizeMoves/* && !optimizePushes */)
            {
                return;
            }

            // Check for cancel.
            string info = null;
            int lastNodeCount = nodes.Visited;
            while (!cancelInfo.Cancel)
            {
                if (root.Score == Node.MaxScore)
                {
                    return;
                }

                CalculateScoreLimit();
                if (scoreTotal == 0)
                {
                    break;
                }

                if (verbose)
                {
                    string searching = foundSolution ? "Post-searching" : "Searching";
                    info = String.Format("{0} with root score {1} and score limit {2},\r\n", searching, root.Score, scoreLimit);
                }
                int n = nodes.Visited;
                Search(node);
                if (verbose)
                {
                    info += String.Format("Examined {0:#,##0} new nodes ({1:#,##0} total)...",
                        nodes.Visited - lastNodeCount, nodes.Visited);
                    info += String.Format("\r\nNodes allocated {0:#,##0}\r\n", nodes.Allocated);
                    info += String.Format("Best lower bound: {0}, best level:\r\n{1}", bestLowerBound, bestLevel.AsText);
                    SetInfo(info);
                }
                if (nodes.Visited > n)
                {
                    break;
                }
            }
        }
        private void PrintTreeWithLevels(Node node, Level level, PathFinder pathFinder)
        {
            Print(node);
            HashKey hashKey = GetPrintHashKey(level, pathFinder);
            if (transpositionTable.ContainsKey(hashKey))
            {
                Node other = transpositionTable[hashKey];
                Log.DebugPrint("table node: {0}", Node.IsEmpty(other) ? -1 : other.ID);
            }
            else
            {
                Log.DebugPrint("not in table");
            }
            Print(level);

            MoveState state = new MoveState();
            state.PrepareToMove(node, ref current);

            foreach (Node child in node.Children)
            {
                state.DoMove(child, ref current);

                PrintTreeWithLevels(child, level, pathFinder);

                state.UndoMove(ref current);
            }

            state.FinishMoving(ref current);
        }
        private void Search(Node node)
        {
            // Check for cancel.
            if (cancelInfo.Cancel)
            {
                return;
            }

            MoveState state = new MoveState();
            state.PrepareToMove(node, ref current);

            Node previous = node;
            for (Node child = node.Child; !Node.IsEmpty(child); child = child.Sibling)
            {
                if (child.Terminal)
                {
                    // Another node displaced this node from the transposition table.
                    RemoveDescendants(child);
                    node.Remove(previous, child);
                    nodes.Release(child);
                    continue;
                }

                state.DoMove(child, ref current);

                if (child.Searched)
                {
                    Search(child);
                    if (!child.HasChildren)
                    {
                        node.Remove(previous, child);
                        if (child.InTable)
                        {
                            child.Dormant = true;
                        }
                        else
                        {
                            nodes.Release(child);
                        }
                        goto removed;
                    }
                }
                else
                {
                    // Search the child node.
                    child.Searched = true;

                    if (level.IsComplete)
                    {
                        child.Complete = true;
                        CollectSolution(child);
                        node.Remove(previous, child);
                        child.Dormant = true;
                        goto removed;
                    }

                    if (IsTerminal(ref state, child) || !FindChildren(child))
                    {
                        node.Remove(previous, child);
                        if (child.InTable)
                        {
                            // Node had no children so it is effectively deadlocked.
                            transpositionTable[current.HashKey] = Node.Empty;
                        }
                        nodes.Release(child);
                        goto removed;
                    }
                }

                previous = child;

            removed:

                state.UndoMove(ref current);
            }

            state.FinishMoving(ref current);
        }
Exemple #6
0
        protected bool IsTerminalWithoutMoves(ref MoveState state, Node node)
        {
            // Update current hash key for node.
#if USE_INCREMENTAL_PATH_FINDER
            state.Find(ref current);
#else
            pathFinder.Find(current.SokobanRow, current.SokobanColumn);
#endif
#if USE_INCREMENTAL_HASH_KEY
            Coordinate2D proxySokobanCoord = pathFinder.GetFirstAccessibleCoordinate();
            current.HashKey ^= HashKey.GetSokobanHashKey(proxySokobanCoord.Row, proxySokobanCoord.Column);
#else
            current.HashKey = GetSlowHashKey();
#endif
#if DEBUG
            ValidateHashKey(node);
#endif

            // Look up the current hash key in the transposition table.
            Node other;
            if (transpositionTable.TryGetValue(current.HashKey, out other))
            {
                duplicates++;

                // Choose which node to pursue.
                if (Node.IsEmpty(other) || other.Pushes <= node.Pushes)
                {
                    // The other node is deadlocked or as good as this one.
                    return true;
                }

                // This node is better than the other one, which is not deadlocked.
                transpositionTable[current.HashKey] = node;
                node.InTable = true;
                other.InTable = false;
                if (other.Dormant)
                {
                    nodes.Release(other);
                }
                else
                {
                    other.Terminal = true;
                }
#if DEBUG
                ValidateNotDeadlocked();
#endif
                return false;
            }

            if (deadlockFinder.IsDeadlocked(current.SokobanRow, current.SokobanColumn))
            {
                transpositionTable.Add(current.HashKey, Node.Empty);
                return true;
            }

            transpositionTable.Add(current.HashKey, node);
            node.InTable = true;
            return false;
        }
Exemple #7
0
        protected bool IsTerminalWithMoves(ref MoveState state, Node node)
        {
            // Update current hash key for node.
#if USE_INCREMENTAL_HASH_KEY
            current.HashKey ^= HashKey.GetSokobanHashKey(current.SokobanRow, current.SokobanColumn);
#else
            current.HashKey = GetSlowHashKey();
#endif
#if DEBUG
            ValidateHashKey(node);
#endif

            // Look up the current hash key in the transposition table.
            Node other;
            if (transpositionTable.TryGetValue(current.HashKey, out other))
            {
                duplicates++;

                // Choose which node to pursue.
                if (optimizePushes)
                {
                    if (Node.IsEmpty(other) || other.Pushes < node.Pushes ||
                        other.Pushes == node.Pushes && other.Moves <= node.Moves)
                    {
                        // The other node is deadlocked or as good as than this one.
                        return true;
                    }
                }
                else
                {
                    if (Node.IsEmpty(other) || other.Moves <= node.Moves)
                    {
                        // The other node is deadlocked or as good as than this one.
                        return true;
                    }
                }

                // This node is better than the other one, which is not deadlocked.
                transpositionTable[current.HashKey] = node;
                node.InTable = true;
                other.InTable = false;
                if (other.Dormant)
                {
                    nodes.Release(other);
                }
                else
                {
                    other.Terminal = true;
                }

                // This is no longer a duplicate and not deadlocked, so run the finder.
#if USE_INCREMENTAL_PATH_FINDER
                state.Find(ref current);
#else
                pathFinder.Find(current.SokobanRow, current.SokobanColumn);
#endif
#if DEBUG
                ValidateNotDeadlocked();
#endif
                return false;
            }

            if (deadlockFinder.IsDeadlocked(current.SokobanRow, current.SokobanColumn))
            {
                transpositionTable.Add(current.HashKey, Node.Empty);
                return true;
            }

            // This is a brand new position, so record it.
            transpositionTable.Add(current.HashKey, node);
            node.InTable = true;

            // This is not a duplicate and not deadlocked, so run the finder.
#if USE_INCREMENTAL_PATH_FINDER
            state.Find(ref current);
#else
            pathFinder.Find(current.SokobanRow, current.SokobanColumn);
#endif
            return false;
        }
Exemple #8
0
        protected bool IsTerminal(ref MoveState state, Node node)
        {
            // This method performs four tasks:
            // - computes the hash key for the node
            // - determines whether this node is a duplicate of another in the transposition table
            // - determines whether this node is deadlocked
            // - determines which squares are accessible from this node
            // The optimal order of the tasks depends on the situation for maximum efficiency.

            return optimizeMoves ? IsTerminalWithMoves(ref state, node) : IsTerminalWithoutMoves(ref state, node);
        }