/// <summary> /// Performs the tree search. /// </summary> /// <param name="rootState"></param> /// <param name="maxIterations"></param> /// <param name="randomizeState"></param> /// <returns></returns> internal static TreeNode Search(PlayingState rootState, int maxIterations = int.MaxValue, bool randomizeState = true) { var rootNode = new TreeNode(); HandRandomizer randomizer = null; if ((randomizeState) && (rootState.NeedRandomize())) { randomizer = new HandRandomizer(rootState); } for (var i = 0; i < maxIterations; i++) { var node = rootNode; // 1. Determinize. var state = rootState.CloneAndRandomize(randomizer); // 2. Select. var validMoves = state.GetValidMoves(); while ((validMoves != 0) && (node.GetUntriedMoves(validMoves) == 0)) // The node is fully expanded and non-terminal. { node = node.UcbSelectChild(validMoves); state.DoMove(node.Move); validMoves = state.GetValidMoves(); } // 3. Expand. var untriedMoves = node.GetUntriedMoves(validMoves); if (untriedMoves != 0) { var randomMove = GetRandomMove(untriedMoves, state); var activeIndex = state.ActiveIndex; state.DoMove(randomMove); node = node.AddChild(randomMove, activeIndex); } // 4. Simulate. validMoves = state.GetValidMoves(); while (validMoves != 0) { var randomMove = GetRandomMove(validMoves, state); state.DoMove(randomMove); validMoves = state.GetValidMoves(); } // 5. Backpropagate. while (node != null) { node.UpdateStatistics(state); node = node.Parent; } } return(rootNode.GetBestChild()); }
/// <summary> /// Performs the tree search. /// </summary> /// <param name="rootState"></param> /// <param name="maxIterations"></param> /// <param name="randomizeState"></param> /// <returns></returns> internal static TreeNode Search(PlayingState rootState, int maxIterations = int.MaxValue, bool randomizeState = true) { var rootNode = new TreeNode(); HandRandomizer randomizer = null; if ((randomizeState) && (rootState.NeedRandomize())) randomizer = new HandRandomizer(rootState); for (var i = 0; i < maxIterations; i++) { var node = rootNode; // 1. Determinize. var state = rootState.CloneAndRandomize(randomizer); // 2. Select. var validMoves = state.GetValidMoves(); while ((validMoves != 0) && (node.GetUntriedMoves(validMoves) == 0)) // The node is fully expanded and non-terminal. { node = node.UcbSelectChild(validMoves); state.DoMove(node.Move); validMoves = state.GetValidMoves(); } // 3. Expand. var untriedMoves = node.GetUntriedMoves(validMoves); if (untriedMoves != 0) { var randomMove = GetRandomMove(untriedMoves, state); var activeIndex = state.ActiveIndex; state.DoMove(randomMove); node = node.AddChild(randomMove, activeIndex); } // 4. Simulate. validMoves = state.GetValidMoves(); while (validMoves != 0) { var randomMove = GetRandomMove(validMoves, state); state.DoMove(randomMove); validMoves = state.GetValidMoves(); } // 5. Backpropagate. while (node != null) { node.UpdateStatistics(state); node = node.Parent; } } return rootNode.GetBestChild(); }
/// <summary> /// Returns a clone of the state replacing closed (not visible) hands with random card distributions. /// </summary> /// <param name="randomizer">Null to clone without randomizing.</param> /// <returns></returns> internal PlayingState CloneAndRandomize(HandRandomizer randomizer) { PlayingState clone = Clone(); if (randomizer != null) randomizer.Randomize(); return clone; }
/// <summary> /// Returns a clone of the state replacing closed (not visible) hands with random card distributions. /// </summary> /// <param name="randomizer">Null to clone without randomizing.</param> /// <returns></returns> internal PlayingState CloneAndRandomize(HandRandomizer randomizer) { PlayingState clone = Clone(); if (randomizer != null) { randomizer.Randomize(); } return(clone); }