public bool ReceiveTurn(Move m) { if (Root.Children != null) { foreach (UCTNode child in Root.Children) { if (child.Position.Equals(m)) { Console.WriteLine("UCTTurbo-{0} had {1} nodes, lost {2} nodes and now has {3} nodes", _player == 1?"Black":"White", Root.MeasureTree(), Root.MeasureTree() - child.MeasureTree(), child.MeasureTree()); Root = child; Root.Parent.Children = null; child.Parent = null; if (child.Children == null) { child.CreateChildren(); } return(true); } } } Board newBoard = Root.BoardState.Clone(); if (newBoard.PlaceStone(m) == false) { throw new ArgumentException("invalid turn"); } Console.WriteLine("UCTTurbo-{0} had {1} nodes, lost {1} nodes and now has {2} nodes", _player == 1 ? "Black" : "White", Root.MeasureTree(), 1); Root.Children = null; //break the link for garbage collection UCTNode newRoot = new UCTNode(null, new Move(m), newBoard); newRoot.CreateChildren(); Root = newRoot; return(true); }
public MonteCarloUCT(byte player, bool randomSims, bool resetTreeEachTurn) { if (player != 1 && player != 2) throw new ArgumentOutOfRangeException("player"); Root = new UCTNode(null, new Move(-5, -5), new Board()); Root.CreateChildren(); _player = player; _randomUCT = randomSims; _resetTreeEachTurn = resetTreeEachTurn; _sims = GameParameters.UCTSimulations; }
public MonteCarloUCT(byte player, bool randomSims, bool resetTreeEachTurn) { if (player != 1 && player != 2) { throw new ArgumentOutOfRangeException("player"); } Root = new UCTNode(null, new Move(-5, -5), new Board()); Root.CreateChildren(); _player = player; _randomUCT = randomSims; _resetTreeEachTurn = resetTreeEachTurn; _sims = GameParameters.UCTSimulations; }
private int PlaySimulation(UCTNode n) { if (_boardClone == null) { _boardClone = new Board(); } int randomWinner = 0; if (n.IsSolved == true) //should always be false (only for single thread! - can be true for multiple threads) { int solvedCurrentPlayerWins = n.SolvedWinner == _player ? 1 : 0; n.Update(solvedCurrentPlayerWins); //update node (Node-wins are associated with moves in the Nodes) return(n.SolvedWinner); } if (n.Children == null && n.Visits < GameParameters.UCTExpansion && n.IsSolved == false) { if (_boardClone == null) { _boardClone = new Board(); } randomWinner = PlayMoreOrLessRandomGame(n); } else { if (n.HasChildren == false) { n.CreateChildren(); } UCTNode next = UCTSelect(n); // select a move if (next == null) //only happens in finished positions and solved nodes - we can start backpropagating ideal result { n.IsSolved = true; if (n.Children.Count == 0) //this is a terminal position - there can be no nodes after it { n.SolvedWinner = n.BoardState.DetermineWinner(); } else //this is a non-terminal position for which all possible subsequent moves have been checked { if (n.BoardState.ActivePlayer == _player) //if, for this node, it's this player's turn, then we take the best result { foreach (UCTNode child in n.Children) { if (child.IsSolved == false) { throw new ImpossibleException("solved node's child is not solved", "PlaySimulation"); } if (child.SolvedWinner == _player) //if we find a choice that leads to sure win for current player, we immediately take it { n.SolvedWinner = _player; n.Update(1); return(1); } //if we don't find a node that leads to current player's victory n.SolvedWinner = 3 - _player; n.Update(0); return(0); } } else //if it's enemy's turn on this node, then we take the worst result { foreach (UCTNode child in n.Children) { if (child.IsSolved == false) { throw new ImpossibleException("solved node's child is not solved", "PlaySimulation"); } if (child.SolvedWinner != _player) //if we find a choice that leads to sure win for enemy, we immediately take it { n.SolvedWinner = 3 - _player; n.Update(0); return(0); } //if we don't find a node that leads to enemy's victory, we assume that this is our winning node n.SolvedWinner = _player; n.Update(1); return(1); } } } } else { randomWinner = PlaySimulation(next); } } int currentPlayerWins = randomWinner == _player ? 1 : 0; n.Update(currentPlayerWins); //update node (Node-wins are associated with moves in the Nodes) return(randomWinner); }
private int PlaySimulation(UCTNode n) { if (_boardClone == null) _boardClone = new Board(); int randomWinner = 0; if (n.IsSolved == true) //should always be false (only for single thread! - can be true for multiple threads) { int solvedCurrentPlayerWins = n.SolvedWinner == _player ? 1 : 0; n.Update(solvedCurrentPlayerWins); //update node (Node-wins are associated with moves in the Nodes) return n.SolvedWinner; } if (n.Children == null && n.Visits < GameParameters.UCTExpansion && n.IsSolved == false) { if (_boardClone == null) _boardClone = new Board(); randomWinner = PlayMoreOrLessRandomGame(n); } else { if (n.HasChildren == false) n.CreateChildren(); UCTNode next = UCTSelect(n); // select a move if (next == null) //only happens in finished positions and solved nodes - we can start backpropagating ideal result { n.IsSolved = true; if (n.Children.Count == 0) //this is a terminal position - there can be no nodes after it { n.SolvedWinner = n.BoardState.DetermineWinner(); } else //this is a non-terminal position for which all possible subsequent moves have been checked { if (n.BoardState.ActivePlayer == _player) //if, for this node, it's this player's turn, then we take the best result { foreach (UCTNode child in n.Children) { if (child.IsSolved == false) throw new ImpossibleException("solved node's child is not solved", "PlaySimulation"); if (child.SolvedWinner == _player) //if we find a choice that leads to sure win for current player, we immediately take it { n.SolvedWinner = _player; n.Update(1); return 1; } //if we don't find a node that leads to current player's victory n.SolvedWinner = 3 - _player; n.Update(0); return 0; } } else //if it's enemy's turn on this node, then we take the worst result { foreach (UCTNode child in n.Children) { if (child.IsSolved == false) throw new ImpossibleException("solved node's child is not solved", "PlaySimulation"); if (child.SolvedWinner != _player) //if we find a choice that leads to sure win for enemy, we immediately take it { n.SolvedWinner = 3 - _player; n.Update(0); return 0; } //if we don't find a node that leads to enemy's victory, we assume that this is our winning node n.SolvedWinner = _player; n.Update(1); return 1; } } } } else { randomWinner = PlaySimulation(next); } } int currentPlayerWins = randomWinner == _player ? 1 : 0; n.Update(currentPlayerWins); //update node (Node-wins are associated with moves in the Nodes) return randomWinner; }
public bool ReceiveTurn(Move m) { if (Root.Children != null) { foreach (UCTNode child in Root.Children) { if (child.Position.Equals(m)) { Console.WriteLine("UCTTurbo-{0} had {1} nodes, lost {2} nodes and now has {3} nodes", _player==1?"Black":"White", Root.MeasureTree(), Root.MeasureTree()-child.MeasureTree(), child.MeasureTree()); Root = child; Root.Parent.Children = null; child.Parent = null; if (child.Children == null) child.CreateChildren(); return true; } } } Board newBoard = Root.BoardState.Clone(); if (newBoard.PlaceStone(m) == false) throw new ArgumentException("invalid turn"); Console.WriteLine("UCTTurbo-{0} had {1} nodes, lost {1} nodes and now has {2} nodes", _player == 1 ? "Black" : "White", Root.MeasureTree(), 1); Root.Children = null; //break the link for garbage collection UCTNode newRoot = new UCTNode(null, new Move(m), newBoard); newRoot.CreateChildren(); Root = newRoot; return true; }