private static void MCRollout(Node leaf) { Con4Board board = leaf.state; int player = leaf.playerToMove; int value = 0; BoardState bs = leaf.bs; while (true) { //BoardState bs = board.EvaluateBoard(); //checkEqualityOfEval(board, bs); if (bs != BoardState.ongoing) { value = BoardStateToValue(bs); break; } else { List <int> possMoves = board.GetPossibleMoves(); board = board.SimulateMove(player, possMoves[rnd.Next(possMoves.Count)]); simulations++; bs = Evaluate.EvaluateBoard(board); evaluations++; player *= -1; } } Backpropagate(leaf, value); }
private static void HandleLeafNode(Node leaf) { if (leaf.totalVisits == 0) { MCRollout(leaf); } else { // EXPAND Con4Board board = leaf.state; //BoardState bs = board.EvaluateBoard(); //checkEqualityOfEval(board, bs); //BoardState bs = Evaluate.EvaluateBoard(board); BoardState bs = leaf.bs; //evaluations++; if (bs != BoardState.ongoing) // Terminal node, do not expand, just backprop { Backpropagate(leaf, BoardStateToValue(bs)); } else // Not terminal, expand { List <int> possMoves = board.GetPossibleMoves(); foreach (int move in possMoves) { leaf.children.Add(new Node(leaf, board.SimulateMove(leaf.playerToMove, move), leaf.playerToMove * -1, move)); simulations++; } Node firstChild = leaf.children[0]; MCRollout(firstChild); } } }
public static int FindMove(Con4Board board, long searchTimeMs) { simulations = 0; evaluations = 0; if (root == null) { // New tree root = new Node(null, board, 1, -1); List <int> possMoves = board.GetPossibleMoves(); foreach (int move in possMoves) { root.children.Add(new Node(root, board.SimulateMove(root.playerToMove, move), root.playerToMove * -1, move)); simulations++; } } else { // Continue from last tree // Set root to child which matches opponents move foreach (Node node in root.children) { if (node.state.Equals(board)) { root = node; root.parent = null; // Let GC remove rest of tree Console.WriteLine("Found root, continuing where we left off!"); break; } } } stopwatch.Restart(); while (stopwatch.ElapsedMilliseconds < searchTimeMs) { //stopwatch.Restart(); for (int i = 0; i < 100; i++) { MCTSIteration(); } //stopwatch.Stop(); //Console.WriteLine(stopwatch.ElapsedMilliseconds); //searchTimeMs -= stopwatch.ElapsedMilliseconds; } List <Node> children = root.children; int bestMove = children[0].previousMove; double bestValue = children[0].totalValue; Node nextRoot = children[0]; // To continue on same tree next move Console.Write("Move values {m, v}: "); Console.Write("{" + children[0].previousMove + ", " + children[0].totalValue + "} "); for (int i = 1; i < children.Count; i++) { Node child = children[i]; double totVal = child.totalValue; Console.Write("{" + child.previousMove + ", " + totVal + "}"); if (totVal > bestValue) { bestValue = totVal; bestMove = child.previousMove; nextRoot = child; } } Console.WriteLine(" => Playing move: " + bestMove); Console.WriteLine("Simulations: " + simulations + ", Evaluations: " + evaluations); root = nextRoot; return(bestMove); }