예제 #1
0
        private void expand(MctsNode node)
        {
            // If there are no more moves, stop it
            var availableMoves = getAvailableMoves(node.Board, node.Board.NextPlayer);

            if (availableMoves == null || availableMoves.Count() == 0)
            {
                return;
            }

            int i = 0;

            foreach (var move in availableMoves)
            {
                var newBoard = (CheckerBoard)node.Board.Clone();
                newBoard.MakeMove(move, node.Board.NextPlayer);

                var childNode = new MctsNode(move, newBoard);
                childNode.Visits++;
                childNode.Name += node.Name + $"-{i++}";
                node.Children.Add(childNode);
            }

            node.IsExpanded = true;
        }
예제 #2
0
        private bool runRandomSimulation(MctsNode node, Player invokingPlayer)
        {
            var board = (CheckerBoard)node.Board.Clone();
            int turns = 0;

            while (board.GetGameStatus() == GameStatuses.Running && turns < MAX_DEPTH)
            {
                var availableMoves = getAvailableMoves(board, board.NextPlayer);
                if (availableMoves != null && availableMoves.Count() > 0)
                {
                    var randomMove = listHelper.Random(availableMoves);
                    board.MakeMove(randomMove, board.NextPlayer);
                }

                turns++;
            }

            if (board.GetGameStatus() != GameStatuses.Running && board.NextPlayer == invokingPlayer)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #3
0
        private double ucb(MctsNode child, MctsNode parent)
        {
            var result = child.Wins / (double)child.Visits + balanceConstant * Math.Sqrt(2 * Math.Log(parent.Visits) / child.Visits);

            //Debug.WriteLine($"UCT for {child.Name}: CV={child.Visits}; CW={child.Wins}; PV={parent.Visits}; R={result}");
            return(result);
        }
예제 #4
0
        private bool runSimulationWithDfs(MctsNode node, Player invokingPlayer)
        {
            var board = (CheckerBoard)node.Board.Clone();
            int turns = 0;

            while (board.GetGameStatus() == GameStatuses.Running && turns < MAX_TURNS)
            {
                var dfs  = new DfsAI(3, listHelper);
                var move = dfs.GetMove(board, board.NextPlayer);
                board.MakeMove(move, board.NextPlayer);

                /*var availableMoves = getAvailableMoves(board, board.NextPlayer);
                 * if (availableMoves != null && availableMoves.Count() > 0)
                 * {
                 *  var randomMove = listHelper.Random(availableMoves);
                 *  board.MakeMove(randomMove, board.NextPlayer);
                 * }*/

                turns++;
            }

            if (board.GetGameStatus() != GameStatuses.Running && board.NextPlayer == invokingPlayer)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #5
0
        private double runRandomSimulation(MctsNode node, Player invokingPlayer)
        {
            var board = (CheckerBoard)node.Board.Clone();
            int turns = 0;

            while (board.GetGameStatus() == GameStatuses.Running && turns < MAX_TURNS)
            {
                var availableMoves = getAvailableMoves(board, board.NextPlayer);
                if (availableMoves != null && availableMoves.Count() > 0)
                {
                    var randomMove = listHelper.Random(availableMoves);
                    board.MakeMove(randomMove, board.NextPlayer);
                }

                turns++;
            }

            if (board.GetGameStatus() != GameStatuses.Running && board.NextPlayer == invokingPlayer)
            {
                //Debug.WriteLine($"Finished in turns {turns}");
                var res = (MAX_TURNS - turns) / ((double)MAX_TURNS / 2d);
                return(res);
            }
            else
            {
                return(-1d);
            }
        }
예제 #6
0
        private MctsNode getFinalBestChild(MctsNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (node.Children == null)
            {
                throw new ArgumentNullException("node.Children");
            }
            if (node.Children.Count() == 0)
            {
                throw new ArgumentException("Node must have at least one child.", "node.Children");
            }

            //Debug.WriteLine($"Get best child of {node.Name}");

            /*var orderedNodes = node.Children.OrderByDescending(c => ucb(c, node)).ThenBy(o => randomService.NextDouble());
             * var bestNode = orderedNodes.First();
             * return bestNode;*/

            var orderedNodes = node.Children.OrderByDescending(c => c.Reward / c.Visits).ThenBy(o => randomService.NextDouble());
            var bestNode     = orderedNodes.First();

            return(bestNode);
        }
예제 #7
0
        private MctsNode getBestChild(MctsNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (node.Children == null)
            {
                throw new ArgumentNullException("node.Children");
            }
            if (node.Children.Count() == 0)
            {
                throw new ArgumentException("Node must have at least one child.", "node.Children");
            }

            //Debug.WriteLine($"Get best child of {node.Name}");

            var orderedNodes = node.Children.OrderByDescending(c => ucb(c, node)).ThenBy(o => randomService.NextDouble());
            var bestNode     = orderedNodes.First();

            return(bestNode);

            //var randChild = listHelper.Random(node.Children);
            // return randChild;
        }
예제 #8
0
        public Move GetMove(CheckerBoard currentBoard, Player invokingPlayer)
        {
            var root = new MctsNode(null, currentBoard);

            root.Name = "0";
            MctsNode currentNode  = root;
            var      visitedNodes = new List <MctsNode>();

            var executionStopwatch = new Stopwatch();

            executionStopwatch.Start();

            var iterations = 0;

            while (executionStopwatch.Elapsed <= MAX_DURATION)//(++iterations <= 1000) //
            {
                iterations++;

                visitedNodes.Add(currentNode);
                currentNode.Visits++;

                // If current node is expanded, it will find best child, and go one leven down
                if (currentNode.IsExpanded)
                {
                    // Find best child
                    var bestChild = getBestChild(currentNode);
                    currentNode = bestChild;
                }
                else
                {
                    // If node is not expanded, it expands it, and runs simulation from random child
                    expand(currentNode);

                    var isWin = false;
                    if (currentNode.Children.Count() > 0)
                    {
                        var bestChild = getBestChild(currentNode);
                        visitedNodes.Add(bestChild);
                        bestChild.Visits++;

                        // Run random simulation from this point
                        isWin = runRandomSimulation(bestChild, invokingPlayer);
                    }

                    // Backpropagate results
                    backpropageate(visitedNodes, isWin);

                    // Reset path to start from root
                    currentNode = root;
                    visitedNodes.Clear();
                }
            }

            // Save tree
            //TreeJsonSaver.Save("mcts", root);

            Console.WriteLine($"MCTS iteratiosn: {iterations}");

            // Find best
            var best = getBestChild(root);

            return(best.Move);
        }