public int RootAlphaBeta(int alpha, int beta, Board board, int depth) { Stopwatch s = new Stopwatch(); s.Start(); Board bCopy = board; int[] moves = bCopy.GetInterestingMoves(); if (moves.Length == 0) { return((board.width * board.width) / 2); } int bestId = 0; int color = board.blackTurn ? 1 : -1; string deb = ""; for (int i = 0; i < moves.Length; i++) { bCopy = new Board(board); bCopy.ChangeSquare(moves[i]); bCopy.EndTurn(); int score = -AlphaBeta(-beta, -alpha, bCopy, depth - 1, color); if (score > alpha) { alpha = score; bestId = i; deb += "Move: " + moves[i].ToString() + " has value " + score.ToString() + ".\n "; } } s.Stop(); deb += "\n\n Execution took " + s.ElapsedMilliseconds.ToString() + " miliseconds."; board.DebugWrite(deb); return(moves[bestId]); }
public int MonteCarloSearch(Board rootState, double searchTimer) { //Check if we can find a winning move in one move string deb = ""; if (true) { int winCheck = GetHighestValueMove(rootState, 1); if (winCheck == (rootState.width * rootState.width) / 2) { return((rootState.width * rootState.width) / 2); } Board copy = new Board(rootState); copy.ChangeSquare(winCheck); int value = rootState.blackTurn ? EvaluateBoard(copy) : -EvaluateBoard(copy); deb += "Highest 1 ply value move is: " + winCheck.ToString() + ", value " + value.ToString() + ".\n "; if (value > 9999) { rootState.DebugWrite(deb); return(winCheck); } } Node root = new Node(rootState.lastSquare, null, rootState, 1); Stopwatch s = new Stopwatch(); s.Start(); while (s.Elapsed.Seconds < searchTimer) { Node node = root; Board state = new Board(rootState); //Select while (node.untriedMoves.Count == 0 && node.nodes.Count != 0) { node = NodeSelection(node); state.ChangeSquare(node.move); state.EndTurn(); } //Expand if (node.untriedMoves.Count != 0) { int move = node.GetRandomMove(); state.ChangeSquare(move); state.EndTurn(); node = node.AddChild(move, state); } //Rollout int lastMove = node.move; while (EvaluateBoard(state) == 0) { //int move = RootAlphaBeta(int.MinValue, int.MaxValue, state, 2); int move = GetHighestValueMove(state, 1); state.ChangeSquare(move); state.EndTurn(); lastMove = move; } //Backpropagate int result = state.CheckWin(lastMove); while (node != null) { node.games++; if (result == -1) { node.wins += 0.4; } else if ((result == 1 && rootState.blackTurn) || (result == 2 && !rootState.blackTurn)) { node.wins += 1; } else { node.wins += 0; } node = node.parent; } } int bestI = 0; double bestValue = double.MinValue; for (int i = 0; i < root.nodes.Count; i++) { double val = root.nodes[i].games * (root.nodes[i].wins / root.nodes[i].games); if (val > bestValue) { deb += "Move: " + root.nodes[i].move.ToString() + " has Wins " + root.nodes[i].wins.ToString("0.0") + ", games " + root.nodes[i].games.ToString() + ", = " + (root.nodes[i].wins / root.nodes[i].games).ToString("0.000") + ".\n "; bestI = i; bestValue = val; } } rootState.DebugWrite(deb); //rootState.DebugWrite("Done finding move from " + root.nodes.Count.ToString() + " available."); return(root.nodes[bestI].move); }
public int MultiThreadedRAlphaBeta(Board board, int depth, int maxThreadNum) { Stopwatch s = new Stopwatch(); s.Start(); Queue <int> moves; if (depth > 4) { moves = new Queue <int>(FindMoves(board, 3)); } else { moves = new Queue <int>(board.GetInterestingMoves()); } //Queue<int> moves = new Queue<int>(board.GetInterestingMoves()); int moveNum = moves.Count; if (moves.Count == 0) { return((board.width * board.width) / 2); } else if (moves.Count == 1) { board.DebugWrite("Execution took " + s.ElapsedMilliseconds.ToString() + " miliseconds for " + moveNum + " move. (defmoves) = " + board.GetInterestingMoves().Length); return(moves.Dequeue()); } int bestMove = 0; int alpha = int.MinValue; int color = board.blackTurn ? 1 : -1; string deb = ""; int threadNum = 4; if (moves.Count <= 4) { threadNum = moves.Count; } else if (moves.Count >= 32) { threadNum = maxThreadNum - 2 > 4 ? maxThreadNum - 2 : 4; } else { for (int i = maxThreadNum; i >= 4; i--) { if (moves.Count % i == 0) { threadNum = i; break; } } } Thread[] threads = new Thread[threadNum]; results.Clear(); for (int i = 0; i < threadNum; i++) { int[] threadMoves; if (moves.Count > moveNum / threadNum) { threadMoves = new int[moveNum / threadNum]; } else { threadMoves = new int[moves.Count]; } for (int j = 0; j < threadMoves.Length; j++) { threadMoves[j] = moves.Dequeue(); } threads[i] = new Thread(() => { AlphaBetaFromMoves(board, depth, threadMoves); }); threads[i].Start(); } for (int i = 0; i < threadNum; i++) { threads[i].Join(); } for (int i = 0; i < threadNum; i++) { deb += "Move: " + results[i].Key.ToString() + " has value " + results[i].Value.ToString() + ".\n "; if (results[i].Value > alpha && results[i].Key != -1) { bestMove = results[i].Key; alpha = results[i].Value; } } s.Stop(); deb += "\n\n Execution took " + s.ElapsedMilliseconds.ToString() + " miliseconds for " + moveNum + " moves. (defmoves) = " + board.GetInterestingMoves().Length; //deb += "\n\n After last move FindNewMoves found " + FindNewMoves(board, board.lastMove).Length + " new moves."; board.DebugWrite(deb); return(bestMove); }