public SearchResult(int node, Move move, TimeSpan time) { VisitedNode = node; BestMove = move; Elapse = time; }
private int Negamax(int depth, int alpha, int beta, int color, bool debug, bool allowNull) { Stopwatch sw = null; if (depth == MaxDepth) { sw = new Stopwatch(); sw.Start(); } if (depth <= 0) { int score = Evaluate(color, debug, depth = 0); return(score); } //Null move if (allowNull) { int nullTurn = -color; int nullValue = -Negamax(depth - 1 - 2, -beta, -beta + 1, nullTurn, debug, false); if (nullValue >= beta) { return(nullValue); //Cut off } } List <Move> possibleMoves = null; possibleMoves = (debug) ? DebugLegalMoves() : examinedBoard.LegalMovesForPlayer(color); if (possibleMoves.Count == 0) { int score = Evaluate(color, debug, depth); return(score); } int bestValue = Int32.MinValue; Move bestMove = null; OrderMove(possibleMoves, depth); foreach (Move eleMove in possibleMoves) { visitedNode++; examinedBoard.MakeMove(eleMove); //Print information //Console.Write("\n" + new string('\t', MaxDepth - depth) + eleMove.ToString()); int value = -Negamax(depth - 1, -beta, -alpha, -color, debug, nullPruning); examinedBoard.UndoMove(eleMove); //save hisEval if (depth == MaxDepth) { hisEval[eleMove.ToString()] = value; } // We found a new max, also keep track of move if (value > bestValue) { bestValue = value; bestMove = eleMove; } // If our max is greater than our lower bound, update our lower bound if (value > alpha) { alpha = value; } // Alpha-beta pruning if (alpha >= beta) { //Console.Write(new string('\t', MaxDepth - depth) + "Cut off"); //Save killer move if (eleMove.Capture == '.') { searchKiller[MaxDepth - depth, 1] = searchKiller[MaxDepth - depth, 0]; searchKiller[MaxDepth - depth, 0] = eleMove; } //save history SaveHistoryHeuristic(eleMove, depth); break; } } if (depth == MaxDepth) { sw.Stop(); Result = new SearchResult(visitedNode, bestMove, sw.Elapsed); } return(bestValue); }
private MNResult AlphaBeta(int depth, int beta, int alpha, Move move, bool player, bool debug = false) { //BLACK is max player bool isMaxPlayer = (player == BLACK) ? true : false; if (depth == 0) { return(EvaluateNode(move, player, debug)); } List <Move> possibleMoves = null; if (!debug) { possibleMoves = examinedBoard.PossibleMoves(player); } else { Console.Write("How many moves are there:"); int count = Convert.ToInt32(Console.ReadLine()); possibleMoves = new List <Move>(); for (int i = 0; i < count; i++) { Move debugMove = new Move(1, 4, 3, 4, this.examinedBoard); possibleMoves.Add(debugMove); } } if (possibleMoves.Count == 0) { return(EvaluateNode(move, player, debug)); } //sort later foreach (Move eleMove in possibleMoves) { examinedBoard.MakeMove(eleMove); bool nextPlayer = !player; MNResult result = AlphaBeta(depth - 1, beta, alpha, eleMove, nextPlayer, debug); int value = result.Value; examinedBoard.UndoMove(eleMove); //BLACK is Max Player if (isMaxPlayer) { if (value > alpha) //Max Nodes can only make restriction on the lower bound { alpha = value; if (depth == MaxDepth) { move = result.Move; } } } else { if (value < beta) { beta = value; if (depth == MaxDepth) { move = result.Move; } } } if (alpha >= beta) //pruning { if (isMaxPlayer) { return(new MNResult(move, alpha)); } else { return(new MNResult(move, beta)); } } } // Travel all child node, no prunning if (isMaxPlayer) { //value of node is alpha value return(new MNResult(move, alpha)); } else { //value of min node is beta value return(new MNResult(move, beta)); } }