public MCTSAgent() { _root = new MCTSNode(null, CheckerColor.Red); }
// For GC public void RemoveParent() { _parent = null; }
public void Traverse() { if (_result != MoveResult.Continue) { ColorResult cr; switch (_result) { case MoveResult.Win: cr = (PrevMover == CheckerColor.Red ? ColorResult.RedWins : ColorResult.YellowWins); break; case MoveResult.Tie: cr = ColorResult.Tie; break; default: // loss or invalid cr = (PrevMover == CheckerColor.Red ? ColorResult.YellowWins : ColorResult.RedWins); break; } Backpropagate(cr); return; } // Choose byte[] choices = MCTSAgent.Byte42; byte choicesCount = 0; float bestUCT = 0; for (byte i = 0; i < 7; i++) { // Expand if (_nodes[i] == null) { choicesCount = 0; for (byte j = i; j < 7; j++) { if (_nodes[j] == null) { choices[choicesCount] = j; choicesCount++; } } byte choice = choices[MCTSAgent.Rand.Next(choicesCount)]; _nodes[choice] = new MCTSNode(_moveList, NextNextMover, this, choice); _nodes[choice].Traverse(); return; } // Traverse if expanded float iScore = _nextMover == CheckerColor.Red ? _nodes[i]._redScore : _nodes[i]._visits - _nodes[i]._redScore; float UCT = iScore / _nodes[i]._visits + C * (float)Math.Sqrt(Math.Log(_visits) / _nodes[i]._visits); if (Math.Abs(UCT - bestUCT) < 0.0000001f) { choices[choicesCount] = i; choicesCount++; } else if (UCT > bestUCT) { choices[0] = i; choicesCount = 1; bestUCT = UCT; } } // Traverse chosen byte choose = choices[MCTSAgent.Rand.Next(choicesCount)]; _nodes[choose].Traverse(); }