public int Search(Color playerToMove, int maxPly, int depth, int alpha, int beta)
        {
            ZobristHash lZobristHash = Board.ZobristHash.Clone();

            lZobristHash.Mark(playerToMove);

            if (depth > 1)
            {
                TranspositionTable.Node lNode = TranspositionTable.Retrieve(lZobristHash);

                if ((lNode.Flag != TranspositionTable.NodeType.Unknown) && ((maxPly - depth) <= lNode.Height))
                {
                    switch (lNode.Flag)
                    {
                    case TranspositionTable.NodeType.Exact:
                    {
                        SearchComplete = false;
                        TranspositionTableHits++;
                        return(lNode.Value);
                    }

                    case TranspositionTable.NodeType.LowerBound:
                    {
                        alpha = (alpha > lNode.Value) ? alpha : lNode.Value;
                        break;
                    }

                    case TranspositionTable.NodeType.UpperBound:
                    {
                        beta = (beta < lNode.Value) ? beta : lNode.Value;
                        break;
                    }
                    }

                    if (alpha >= beta)
                    {
                        return(lNode.Value);
                    }
                }
            }

            if ((depth == maxPly) || ((depth != 0) && (SearchInterface.IsGameOver())))
            {
                if (depth == maxPly)
                {
                    SearchComplete = false;
                }

                NodesEvaluated++;
                int lEval = SearchInterface.Evaluate(playerToMove);

                TranspositionTable.Record(maxPly - depth, lEval, TranspositionTable.NodeType.Exact, lZobristHash);

                return(lEval);
            }

            PrincipalVariation.SetPVLength(depth);

            MoveList lMoves = SearchInterface.GetMoveList(playerToMove, SearchOptions.IncludeEndGameMoves);

            SearchInterface.PruneMoveList(lMoves);

            SearchInterface.PrioritizeMoves(lMoves, playerToMove);

            if ((SearchOptions.UsePatterns) && (lMoves.Count != 0))
            {
                PatternMap lPatternMap = SearchOptions.PatternDetector.FindPatterns(Board, playerToMove, lMoves.AllMoves);
                lPatternMap.UpdateMoveList(lMoves);
            }

            if (lMoves.Count == 0)
            {
                lMoves.Add(CoordinateSystem.PASS);
            }

            if ((lMoves.Count == 1) && (lMoves[0] == CoordinateSystem.PASS) && (Board.LastMove == CoordinateSystem.PASS))
            {
                PrincipalVariation.UpdatePV(depth, CoordinateSystem.PASS);

                int lEval = SearchInterface.Evaluate(playerToMove);
                TranspositionTable.Record(maxPly - depth, lEval, TranspositionTable.NodeType.Exact, lZobristHash);
                return(lEval);
            }

            // follow the principle variation
            if (FollowPV)
            {
                FollowPV = false;

                int lPVMove = PrincipalVariation.GetMove(depth);

                if (lPVMove != PrincipalVariation.NO_VALUE)
                {
                    if (lMoves.Contains(lPVMove))
                    {
                        lMoves.SetValue(lPVMove, Int32.MaxValue);
                        FollowPV = true;
                    }
                }
            }

            SearchInterface.SortMoveList(lMoves);

            if (UpdateStatusFlag)
            {
                UpdateStatus();
            }

            if (StopThinkingFlag)
            {
                Stop();
            }

            int lSuperKoCount = 0;

            TranspositionTable.NodeType lFlag = TranspositionTable.NodeType.UpperBound;

            foreach (int lMove in lMoves)
            {
                NodesSearched++;

                bool lPlayed = Board.PlayStone(lMove, playerToMove, true);

                if (!lPlayed)
                {
                    throw new ApplicationException("SearchMethodAB_ID_TT_PVS.cs: You hit a bug!");
                }

                if ((CheckSuperKo) && (Board.IsSuperKo()))
                {
                    lSuperKoCount++;
                    Board.Undo();
                }
                else
                {
                    int lScore = -Search(playerToMove.Opposite, maxPly, depth + 1, -beta, -alpha);
                    Board.Undo();

                    if (lScore > alpha)
                    {
                        if (lScore >= beta)
                        {
                            TranspositionTable.Record(maxPly - depth, alpha, TranspositionTable.NodeType.LowerBound, lZobristHash);
                            return(lScore);
                        }

                        alpha = lScore;
                        lFlag = TranspositionTable.NodeType.Exact;
                        PrincipalVariation.UpdatePV(depth, lMove);
                    }
                }
            }

            if (lSuperKoCount == lMoves.Count)
            {
                return(SearchInterface.Evaluate(playerToMove));
            }

            TranspositionTable.Record(maxPly - depth, alpha, lFlag, lZobristHash);

            return(alpha);
        }
Ejemplo n.º 2
0
        public int Search(Color playerToMove, int maxPly, int depth, int alpha, int beta)
        {
            if ((depth == maxPly) || ((depth != 0) && (SearchInterface.IsGameOver())))
            {
                if (depth == maxPly)
                {
                    SearchComplete = false;
                }

                NodesEvaluated++;
                return(SearchInterface.Evaluate(playerToMove));
            }

            PrincipalVariation.SetPVLength(depth);

            MoveList lMoves = SearchInterface.GetMoveList(playerToMove, SearchOptions.IncludeEndGameMoves);

            SearchInterface.PruneMoveList(lMoves);

            SearchInterface.PrioritizeMoves(lMoves, playerToMove);

            if ((SearchOptions.UsePatterns) && (lMoves.Count != 0))
            {
                PatternMap lPatternMap = SearchOptions.PatternDetector.FindPatterns(Board, playerToMove, MoveList.Randomize(lMoves.AllMoves, SearchOptions.Permutations, depth));
                lPatternMap.UpdateMoveList(lMoves);
            }

            if (lMoves.Count == 0)
            {
                lMoves.Add(CoordinateSystem.PASS);
            }

            if ((lMoves.Count == 1) && (lMoves[0] == CoordinateSystem.PASS) && (Board.LastMove == CoordinateSystem.PASS))
            {
                PrincipalVariation.UpdatePV(depth, CoordinateSystem.PASS);
                NodesEvaluated++;
                return(SearchInterface.Evaluate(playerToMove));
            }

            // follow the principle variation
            if (FollowPV)
            {
                FollowPV = false;

                int lPVMove = PrincipalVariation.GetMove(depth);

                if (lPVMove != PrincipalVariation.NO_VALUE)
                {
                    if (lMoves.Contains(lPVMove))
                    {
                        lMoves.SetValue(lPVMove, Int32.MaxValue);
                        FollowPV = true;
                    }
                }
            }

            SearchInterface.SortMoveList(lMoves);

            if (UpdateStatusFlag)
            {
                UpdateStatus();
            }

            if (StopThinkingFlag)
            {
                Stop();
            }

            int lSuperKoCount = 0;

            foreach (int lMove in lMoves)
            {
                NodesSearched++;

                bool lPlayed = Board.PlayStone(lMove, playerToMove, true);

                if (!lPlayed)
                {
                    throw new ApplicationException("SearchMethodAB_ID_PVS.cs: You hit a bug!");
                }

                if ((CheckSuperKo) && (Board.IsSuperKo()))
                {
                    lSuperKoCount++;
                    Board.Undo();
                }
                else
                {
                    int lScore = -Search(playerToMove.Opposite, maxPly, depth + 1, -beta, -alpha);
                    Board.Undo();

                    if (lScore > alpha)
                    {
                        if (lScore >= beta)
                        {
                            return(lScore);
                        }

                        alpha = lScore;
                        PrincipalVariation.UpdatePV(depth, lMove);
                    }
                }
            }

            if (lSuperKoCount == lMoves.Count)
            {
                return(SearchInterface.Evaluate(playerToMove));
            }

            return(alpha);
        }