Example #1
0
        /// <summary>
        /// Recursively searches a tree node and gives the evaluation for this node assuming best play for each player
        /// </summary>
        /// <param name="node">Current node</param>
        /// <returns>Evaluation (pos: white advantage)</returns>
        private double RecursiveEvaluateNode(TreeNode node)
        {
            InterlockedEngineStats.Increment_NodesVisited();

            // End of recursion
            if (node.Children is null)
            {
                return(Evaluation.GetEvaluation(node.Board));
            }

            // Assume that the enemy (child node) will make a best move for him
            double enemySign     = GetSign(!node.Board.IsWhiteToMove);
            double bestEnemyMove = enemySign * WORST_SCORE;

            foreach (var childNode in node.Children)
            {
                double enemyScore = RecursiveEvaluateNode(childNode);
                if ((enemySign * enemyScore) > (enemySign * bestEnemyMove))
                {
                    bestEnemyMove = enemyScore;
                }
            }

            return(bestEnemyMove);
        }
Example #2
0
        /// <summary>
        /// Recursively searches a tree node and gives the evaluation for this node assuming best play for each player
        /// </summary>
        /// <param name="node">Current node</param>
        /// <returns>Evaluation (pos: white advantage)</returns>
        private double RecursiveEvaluateNode(TreeNode node, TextWriter tw, int depth)
        {
            InterlockedEngineStats.Increment_NodesVisited();

            // End of recursion
            if (node.Children.Count == 0)
            {
                double eval = Evaluation.GetEvaluation(node.Board);

                for (int i = 0; i < depth; i++)
                {
                    tw.Write('\t');
                }
                tw.Write(node.Board.IsWhiteToMove ? "w: " : "b: ");
                tw.WriteLine(UCINotation.SerializeMove(node.Move) + " -> " + eval);

                return(eval);
            }

            // Assume that the enemy (child node) will make a best move for him
            double enemySign     = GetSign(!node.Board.IsWhiteToMove);
            double bestEnemyMove = enemySign * WORST_SCORE;

            foreach (var childNode in node.Children)
            {
                double enemyScore = RecursiveEvaluateNode(childNode, tw, depth + 1);
                if ((enemySign * enemyScore) > (enemySign * bestEnemyMove))
                {
                    bestEnemyMove = enemyScore;
                }
            }

            for (int i = 0; i < depth; i++)
            {
                tw.Write('\t');
            }
            tw.Write(node.Board.IsWhiteToMove ? "w: " : "b: ");
            tw.WriteLine(UCINotation.SerializeMove(node.Move) + " -> " + bestEnemyMove);

            return(bestEnemyMove);
        }
Example #3
0
        public Move ReactToMove(IEnumerable <Move> moves)
        {
            // Make a move within the next 3 seconds
            cancellationTokenSource = new CancellationTokenSource();
            cancellationTokenSource.CancelAfter(5000);

            var initialBoard = new Board(moves);

            // Reset stats
            InterlockedEngineStats.Reset();

            // Start with the first tree layer
            ConcurrentBag <TreeNode> lastTreeLayer = new ConcurrentBag <TreeNode>(initialBoard.GetLegalMoves().Select(x => new TreeNode()
            {
                Board      = new Board(moves.Append(x)), // This is far from optimal, but ok since this is only done in init phase
                Children   = null,
                Evaluation = double.NaN,
                Parent     = null,
                Move       = x
            }));

            // Start building a tree
            List <TreeNode> gameTree = new List <TreeNode>(lastTreeLayer);
            int             depth    = 0;

            do
            {
                var newTreeLayer = new ConcurrentBag <TreeNode>();

                Parallel.ForEach(lastTreeLayer, (parentNode, state) =>
                {
                    parentNode.Children = new List <TreeNode>();
                    foreach (var possibleMove in parentNode.Board.GetLegalMoves())
                    {
                        // make a copy and change it
                        Board branchBoardAfterMove = (Board)(parentNode.Board.Clone());
                        branchBoardAfterMove.Mutate(possibleMove);

                        TreeNode childNode = new TreeNode()
                        {
                            Board      = branchBoardAfterMove,
                            Children   = null,
                            Evaluation = double.NaN,
                            Parent     = parentNode,
                            IsComplete = false,
                            Move       = possibleMove
                        };

                        newTreeLayer.Add(childNode);
                        parentNode.Children.Add(childNode);
                    }

                    parentNode.IsComplete = true;


                    if (cancellationTokenSource.IsCancellationRequested)
                    {
                        state.Stop();
                    }
                });

                if (cancellationTokenSource.IsCancellationRequested)
                {
                    break;
                }

                InterlockedEngineStats.Update_MaxDepth(++depth);

                // swap
                lastTreeLayer = newTreeLayer;

                if (depth >= MaxDepth)
                {
                    break;
                }
            } while (!cancellationTokenSource.IsCancellationRequested);


            // Traverse tree
            StreamWriter sw = new StreamWriter("test.txt");

            double bestScore = Sign(WORST_SCORE);
            Move   bestMove  = gameTree.First().Move;

            foreach (var candidate in gameTree)
            {
                double deepEvaluation = RecursiveEvaluateNode(candidate);
                if (Sign(deepEvaluation) > Sign(bestScore))
                {
                    bestScore = deepEvaluation;
                    bestMove  = candidate.Move;
                }
            }

            // turn file upside down
            sw.Flush();
            sw.Close();
            File.WriteAllLines("test.txt", File.ReadAllLines("test.txt").Reverse());


            InterlockedEngineStats.Set_Evaluation(bestScore);

            return(bestMove);
        }