Example #1
0
        void OutputUCIInfo(MCTSManager manager, MCTSNode searchRootNode, bool isFinalInfo = false)
        {
            BestMoveInfo best = searchRootNode.BestMoveInfo(false);

            if (numPV == 1)
            {
                UCIWriteLine(UCIInfo.UCIInfoString(manager, searchRootNode, best?.BestMoveNode,
                                                   showWDL: showWDL, scoreAsQ: scoreAsQ));
            }
            else
            {
                // Send top move
                UCIWriteLine(UCIInfo.UCIInfoString(manager, searchRootNode, best.BestMoveNode, 1,
                                                   showWDL: showWDL, useParentN: !perPVCounters, scoreAsQ: scoreAsQ));

                // Send other moves visited
                MCTSNode[] sortedN      = searchRootNode.ChildrenSorted(s => - (float)s.N);
                int        multiPVIndex = 2;
                for (int i = 0; i < sortedN.Length && i < numPV; i++)
                {
                    if (!object.ReferenceEquals(sortedN[i], best.BestMoveNode))
                    {
                        UCIWriteLine(UCIInfo.UCIInfoString(manager, searchRootNode, sortedN[i], multiPVIndex,
                                                           showWDL: showWDL, useParentN: !perPVCounters, scoreAsQ: scoreAsQ));
                        multiPVIndex++;
                    }
                }

                // Finally show moves that had no visits
                float  elapsedTimeSeconds = (float)(DateTime.Now - manager.StartTimeThisSearch).TotalSeconds;
                string timeStr            = $"{ elapsedTimeSeconds * 1000.0f:F0}";
                for (int i = multiPVIndex - 1; i < searchRootNode.NumPolicyMoves; i++)
                {
                    (MCTSNode node, EncodedMove move, FP16 p)info = searchRootNode.ChildAtIndexInfo(i);
                    if (info.node == null)
                    {
                        bool        isWhite = searchRootNode.Annotation.Pos.MiscInfo.SideToMove == SideType.White;
                        EncodedMove moveCorrectPerspective = isWhite ? info.move : info.move.Flipped;
                        string      str = $"info depth 0 seldepth 0 time { timeStr } nodes 1 score cp 0 tbhits 0 "
                                          + $"multipv {multiPVIndex} pv {moveCorrectPerspective.AlgebraicStr} ";
                        UCIWriteLine(str);
                        multiPVIndex++;
                    }
                }
            }
            if (verboseMoveStats && (logLiveStats || isFinalInfo))
            {
                OutputVerboseMoveStats(CeresEngine.Search.SearchRootNode);
            }
        }
Example #2
0
        public static List <LC0VerboseMoveStat> BuildStats(MCTSNode searchRootNode)
        {
            List <LC0VerboseMoveStat> stats = new List <LC0VerboseMoveStat>();

            BestMoveInfo best = searchRootNode.BestMoveInfo(false);

            // First process policy moves not yet expanded
            // starting from last one (lowest probability).
            for (int i = searchRootNode.NumPolicyMoves - 1; i >= 0; i--)
            {
                (MCTSNode node, EncodedMove move, FP16 p)info = searchRootNode.ChildAtIndexInfo(i);
                if (info.node == null)
                {
                    LC0VerboseMoveStat stat = BuildStatNotExpanded(searchRootNode, i);
                    stats.Add(stat);
                }
            }

            // Now process moves expanded in order of visit count.
            MCTSNode[] sortedN = searchRootNode.ChildrenSorted(s => (float)s.N + 0.0001f * s.P);
            foreach (MCTSNode node in sortedN)
            {
                if (!object.ReferenceEquals(node, best.BestMoveNode))
                {
                    stats.Add(BuildStatExpanded(node, false));
                }
            }

            // Save the best move for last.
            stats.Add(BuildStatExpanded(best.BestMoveNode, false));

            // Finally, output the search root node.
            stats.Add(BuildStatExpanded(searchRootNode, true));

            return(stats);
        }
Example #3
0
        private BestMoveInfo FindBestMoveImpl(IGameState gameState, GamePlayer currentPlayer, Int32 depth)
        {
            IGameMove[] moves = _gameLogic.GetPossibleMoves(gameState, currentPlayer);

            if (moves.Length <= 0)
            {
                //// there are no more possible moves to analyse, so return current state evaluation

                return(new BestMoveInfo
                {
                    MoveRate = _stateEvaluator.Evaluate(gameState, currentPlayer)
                });
            }

            Int32[] rates = new Int32[moves.Length];

            //Parallel.For(0, moves.Length, q =>

            for (Int32 q = 0; q < moves.Length; q++)
            {
                IGameMove nextMove = moves[q];

                IGameState newState = _gameLogic.MakeMove(nextMove, gameState);

                Int32 stateRate = _stateEvaluator.Evaluate(newState, currentPlayer);

                if (stateRate != 0 /* */)
                {
                    rates[q] = AdjustStateRate(depth, stateRate);
                }
                else
                {
                    if (depth > 0)
                    {
                        BestMoveInfo bestMoveInfo = FindBestMoveImpl(newState, OtherPlayer(currentPlayer), depth - 1);

                        bestMoveInfo.Move = nextMove;

                        rates[q] = bestMoveInfo.MoveRate;
                    }
                    else
                    {
                        stateRate = _moveEvaluator.Evaluate(gameState, nextMove, newState);

                        rates[q] = AdjustStateRate(depth, stateRate);
                    }
                }
            }
            //);

            Int32 index = -1;
            Int32 rate  = 0;

            List <Int32> equalRate = new List <Int32>(rates.Length);

            if (currentPlayer == GamePlayer.PlayerMax)
            {
                for (Int32 q = 0; q < rates.Length; q++)
                {
                    Int32 currentRate = rates[q];

                    if (index == -1 || currentRate > rate)
                    {
                        index = q;
                        rate  = currentRate;

                        equalRate.Clear();

                        equalRate.Add(q);
                    }
                    else
                    {
                        if (currentRate == rate)
                        {
                            equalRate.Add(q);
                        }
                    }
                }
            }
            else if (currentPlayer == GamePlayer.PlayerMin)
            {
                for (Int32 q = 0; q < rates.Length; q++)
                {
                    Int32 currentRate = rates[q];

                    if (index == -1 || currentRate < rate)
                    {
                        index = q;
                        rate  = currentRate;

                        equalRate.Clear();

                        equalRate.Add(q);
                    }
                    else
                    {
                        if (currentRate == rate)
                        {
                            equalRate.Add(q);
                        }
                    }
                }
            }
            else
            {
                throw new NotSupportedException(currentPlayer.ToString());
            }

            if (equalRate.Count > 1)
            {
                index = equalRate[Environment.TickCount % equalRate.Count];
            }

            return(new BestMoveInfo
            {
                Move = moves[index],
                MoveRate = rates[index]
            });
        }
Example #4
0
        public IGameMove FindBestMove(IGameState gameState, GamePlayer player)
        {
            BestMoveInfo bestMoveInfo = FindBestMoveImpl(gameState, player, _depth);

            return(bestMoveInfo.Move);
        }