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