public UltimateTicTacToeMove TakeTurn(UltimateTicTacToeBoard ticTacToeBoard) { _taunt("Planning My Move..."); GameTree currentTree = _gameTree?.GetNode(ticTacToeBoard); Debug.WriteLine($"There were {_gameTree?.GetNodeCount()} nodes in the tree prior to this move."); //Taunt the player if they played well! if (_gameTree?.Children != null && _gameTree.Children.Count != 0) { var lowScore = _gameTree.Children.Min(node => node.Score); var highScore = _gameTree.Children.Max(node => node.Score); var bestMove = Player == Player.O ? highScore : lowScore; var worstMove = Player == Player.X ? highScore : lowScore; var bestPlayedMoves = _gameTree.Children.Where(child => child.Score == bestMove); var worstPlayedMoves = _gameTree.Children.Where(child => child.Score == worstMove); var playedMoves = bestPlayedMoves as IList <GameTree> ?? bestPlayedMoves.ToList(); if (playedMoves.Contains(currentTree) && playedMoves.Count == 1 && Math.Abs(bestMove - worstMove) > 250) { _taunt("Nice Move Kiddums!"); Thread.Sleep(timeout: new TimeSpan(0, 0, 5)); } else if (worstPlayedMoves.Contains(currentTree) && Math.Abs(bestMove - worstMove) > 250) { _taunt("What are you thinking?"); Thread.Sleep(timeout: new TimeSpan(0, 0, 5)); } } _gameTree = currentTree ?? new GameTree(data: ticTacToeBoard.Clone()); Debug.WriteLine($"Tree Triming reduced it to {_gameTree.GetNodeCount()} nodes."); Debug.WriteLine($"Memory Used {GC.GetTotalMemory(false)}"); GC.Collect(); GC.WaitForPendingFinalizers(); Debug.WriteLine($"Memory Used {GC.GetTotalMemory(false)}"); PopulateTree(); Debug.WriteLine($"Memory Used {GC.GetTotalMemory(false)}"); Debug.WriteLine($"Tree population increased it to {_gameTree.GetNodeCount()} nodes at a depth of {_gameTree.GetTreeDepth()}."); var move = MinMax(); return(move); }
private void PopulateTree() { var startAdd = DateTime.UtcNow; bool continueAddingNodes = true; while (continueAddingNodes && _gameTree.GetNodeCount() < 100000 && _gameTree.GetTreeDepth() < 30) { var nodesAdded = AddDepthToGameTree(); var runtime = DateTime.UtcNow.Subtract(startAdd); if (runtime.TotalSeconds >= 5 || (_gameTree.GetTreeDepth() >= 15 && nodesAdded <= 10)) { //diminishing returns, we're 10+ moves deep and adding less than 10 scenarios each round continueAddingNodes = false; } } }