public UctNode UCTSelect(UctNode UctNode) { UctNode res = null; UctNode next = UctNode.Child; double best_uct = 0; while (next != null) { // for all children double uctvalue; if (next.Visits > 0) { double winrate = next.GetWinRate(); double uct = UCTK * Math.Sqrt(Math.Log(UctNode.Visits) / next.Visits); uctvalue = winrate + uct; } else { // Always play a random unexplored move first uctvalue = 10000 + 1000 * _random.NextDouble(); } if (uctvalue > best_uct) { // get max uctvalue of all children best_uct = uctvalue; res = next; } next = next.Sibling; } return res; }
public UctNode GetBestChild(UctNode root) { UctNode Child = root.Child; UctNode best_child = null; int best_visits = -1; while (Child != null) { // for all children if (Child.Visits > best_visits) { best_child = Child; best_visits = Child.Visits; } Child = Child.Sibling; } return best_child; }
// return 0=lose 1=win for current player to move private int PlaySimulation(Field field, UctNode n) { int randomresult = 0; if (n.Child == null && n.Visits < 10) { // 10 simulations until chilren are expanded (saves memory) randomresult = PlayRandomGame(field); } else { if (n.Child == null) CreateChildren(field, n); UctNode next = UCTSelect(n); // select a move if (next == null) { /* ERROR */ } field.MakeMove(next.Pos); int res = PlaySimulation(field, next); randomresult = 1 - res; } n.Update(1 - randomresult); //update UctNode (UctNode-wins are associated with moves in the Nodes) return randomresult; }
// generate a move, using the uct algorithm private int UCTSearch(int numsim) { root = new UctNode(0); //init uct tree CreateChildren(Field, root); Field clone; for (int i = 0; i < numsim; i++) { clone = Field.Clone(); PlaySimulation(clone, root); } UctNode n = GetBestChild(root); return n.Pos; }
// expand children in UctNode private void CreateChildren(Field field, UctNode parent) { UctNode last = parent; for (int i = 1; i <= field.Width; i++) for (int j = 1; j <= field.Height; j++) { var pos = Field.GetPosition(i, j); if (field[pos].IsPuttingAllowed()) { UctNode UctNode = new UctNode(pos); if (last == parent) last.Child = UctNode; else last.Sibling = UctNode; last = UctNode; } } }