Exemple #1
0
        /// <summary>
        /// Analyzes a specified position until a specified limit is exhausted.
        ///
        /// TODO: This method is highly redundant (and inferior to?) the next method AnalyzePositionFromFENAndMoves, delete it.
        /// </summary>
        /// <param name="fenOrFENAndMoves">a FEN</param>
        /// <param name="nodes"></param>
        /// <returns></returns>
        public UCISearchInfo AnalyzePositionFromFEN(string fenAndMovesString, SearchLimit searchLimit)
        {
            List <LC0VerboseMoveStat> moves = new List <LC0VerboseMoveStat>();

            Runner.EvalPositionPrepare();

            UCISearchInfo searchInfo;

            if (searchLimit.Type == SearchLimitType.SecondsPerMove)
            {
                searchInfo = Runner.EvalPositionToMovetime(fenAndMovesString, (int)(searchLimit.Value * 1000.0f));
            }
            else if (searchLimit.Type == SearchLimitType.NodesPerMove)
            {
                searchInfo = Runner.EvalPositionToNodes(fenAndMovesString, (int)searchLimit.Value);
            }
            else
            {
                throw new Exception("Unknown search limit " + searchLimit.Type);
            }

            double elapsed = searchInfo.EngineReportedSearchTime / 1000.0f;

            // no more, we now assume  win_percentages is requested     LeelaVerboseMoveStats ret = new LeelaVerboseMoveStats(positionEnd, searchInfo.BestMove, elapsed, searchInfo.Nodes, LZPositionEvalLogistic.CentipawnToLogistic2018(searchInfo.Score));
            float scoreConverted    = 2.0f * (((float)searchInfo.ScoreCentipawns / 10_000f) - 0.5f);
            PositionWithHistory pwh = PositionWithHistory.FromFENAndMovesUCI(fenAndMovesString);
            LC0VerboseMoveStats ret = new LC0VerboseMoveStats(pwh.FinalPosition, searchInfo.BestMove, elapsed, searchInfo.Nodes, scoreConverted, searchInfo);

            foreach (string info in searchInfo.Infos)
            {
                if (info.Contains("P:"))
                {
                    moves.Add(new LC0VerboseMoveStat(ret, info));
                }
            }

            ret.SetMoves(moves);

            // TODO: Someday perhaps make LeelaVerboseMoveStats a subclass of UCISearchInfo so this is more elegant
            UCISearchInfo uciInfo = new UCISearchInfo(null, ret.BestMove, null);

            uciInfo.Nodes = ret.NumNodes;
            uciInfo.EngineReportedSearchTime = (int)(1000.0f * ret.ElapsedTime);
            uciInfo.ExtraInfo = ret;
            uciInfo.BestMove  = ret.BestMove;

            return(uciInfo);
        }
Exemple #2
0
        protected override GameEngineSearchResult DoSearch(PositionWithHistory curPositionAndMoves,
                                                           SearchLimit searchLimit,
                                                           List <GameMoveStat> gameMoveHistory, ProgressCallback callback,
                                                           bool verbose)
        {
            DoSearchPrepare();

            bool weAreWhite = curPositionAndMoves.FinalPosition.MiscInfo.SideToMove == SideType.White;

            UCISearchInfo gameInfo;

            switch (searchLimit.Type)
            {
            case SearchLimitType.SecondsPerMove:
                gameInfo = UCIRunner.EvalPositionToMovetime(curPositionAndMoves.FENAndMovesString, (int)(searchLimit.Value * 1000));
                break;

            case SearchLimitType.NodesPerMove:
                gameInfo = UCIRunner.EvalPositionToNodes(curPositionAndMoves.FENAndMovesString, (int)(searchLimit.Value));
                break;

            case SearchLimitType.NodesForAllMoves:
                using (new TimingBlock(new TimingStats(), TimingBlock.LoggingType.None))
                {
                    gameInfo = UCIRunner.EvalPositionRemainingNodes(curPositionAndMoves.FENAndMovesString,
                                                                    weAreWhite,
                                                                    searchLimit.MaxMovesToGo,
                                                                    (int)(searchLimit.Value),
                                                                    (int)(searchLimit.ValueIncrement));
                }

                break;

            case SearchLimitType.SecondsForAllMoves:
                using (new TimingBlock(new TimingStats(), TimingBlock.LoggingType.None))
                {
                    gameInfo = UCIRunner.EvalPositionRemainingTime(curPositionAndMoves.FENAndMovesString,
                                                                   weAreWhite,
                                                                   searchLimit.MaxMovesToGo,
                                                                   (int)(searchLimit.Value * 1000),
                                                                   (int)(searchLimit.ValueIncrement * 1000));
                }

                break;

            default:
                throw new NotSupportedException($"Unsupported MoveType {searchLimit.Type}");
            }

            float q = EncodedEvalLogistic.CentipawnToLogistic(gameInfo.ScoreCentipawns);

            return(new GameEngineSearchResult(gameInfo.BestMove, q, gameInfo.ScoreCentipawns, float.NaN, searchLimit, default, 0, (int)gameInfo.Nodes, gameInfo.Depth));