< Summary

Line coverage
97%
Covered lines: 72
Uncovered lines: 2
Coverable lines: 74
Total lines: 175
Line coverage: 97.2%
Branch coverage
95%
Covered branches: 42
Total branches: 44
Branch coverage: 95.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: Search(...)100%11100%
File 1: Search(...)91.66%242495.45%
File 1: SearchDeeper(...)100%22100%
File 2: PrincipalVariationSearch(...)100%44100%
File 2: AlphaUpdate(...)100%22100%
File 2: BetaCutoff(...)100%22100%
File 2: PopulateMoveScores(...)100%22100%
File 2: CanPruneNullMove(...)100%88100%

File(s)

/home/runner/work/rudim/rudim/Rudim/Search/Negamax.cs

#LineLine coverage
 1using Rudim.Board;
 2using Rudim.Common;
 3using System.Collections.Generic;
 4using System.Threading;
 5
 6namespace Rudim.Search
 7{
 8    public static partial class Negamax
 9    {
 10        public static int Nodes;
 11        private static int _searchDepth;
 12
 13        public static int Search(BoardState boardState, int depth, CancellationToken cancellationToken)
 14        {
 4315            _searchDepth = depth;
 4316            Nodes = 0;
 4317            Quiescence.ResetNodes();
 4318            int score = Search(boardState, depth, int.MinValue + 1, int.MaxValue - 1, true, cancellationToken);
 4319            return score;
 20        }
 21
 22        private static int Search(BoardState boardState, int depth, int alpha, int beta, bool allowNullMove,Cancellation
 23        {
 184916124            int ply = _searchDepth - depth;
 184916125            bool isPvNode = beta - alpha > 1;
 184916126            Nodes++;
 27
 184916128            if (boardState.IsDraw())
 029                return 0;
 30
 184916131            (bool hasValue, int ttScore, Move ttBest) = TranspositionTable.GetEntry(boardState.BoardHash, alpha, beta, d
 184916132            if (hasValue)
 33            {
 34                // TODO: This doesn't seem right - revisit TT impl
 7939835                boardState.BestMove = ttBest;
 7939836                return TranspositionTable.RetrieveScore(ttScore, ply);
 37            }
 38
 176976339            if (depth <= 0)
 124124540                return Quiescence.Search(boardState, alpha, beta, cancellationToken);
 41
 52851842            if (CanPruneNullMove(isPvNode, boardState, allowNullMove, depth))
 43            {
 12043844                boardState.MakeNullMove();
 12043845                int score = -Search(boardState, depth - 1 - 2, -beta, -beta + 1, false, cancellationToken);
 12043846                boardState.UndoNullMove();
 12043847                if (score >= beta)
 8743948                    return beta; // TODO : Store in TT
 49            }
 50
 51            int originalAlpha = alpha;
 44107952            bool foundPv = false;
 44107953            TranspositionEntryType entryType = TranspositionEntryType.Alpha;
 54
 44107955            boardState.GenerateMoves();
 44107956            PopulateMoveScores(boardState, ply);
 57
 44107958            int numberOfLegalMoves = 0;
 44107959            List<Move> moves = boardState.Moves;
 407984260            for(int i = 0; i < moves.Count; ++i)
 61            {
 198721262                MoveOrdering.SortNextBestMove(moves, i);
 198721263                Move move = moves[i];
 198721264                if (cancellationToken.IsCancellationRequested)
 65                    break;
 198720866                boardState.MakeMove(move);
 198720867                if (boardState.IsInCheck(boardState.SideToMove.Other()))
 68                {
 25939269                    boardState.UnmakeMove(move);
 25939270                    continue;
 71                }
 72
 172781673                int score = SearchDeeper(boardState, depth, alpha, beta, cancellationToken, foundPv, allowNullMove);
 74
 172781675                numberOfLegalMoves++;
 76
 172781677                boardState.UnmakeMove(move);
 172781678                if (score >= beta)
 79                {
 38836680                    return BetaCutoff(beta, move, ply, boardState, depth);
 81                }
 133945082                if (score > alpha)
 83                {
 197084                    AlphaUpdate(score, move, boardState, depth, out alpha, out foundPv, out entryType);
 85                }
 86            }
 87
 5271388            if (numberOfLegalMoves == 0)
 89            {
 10390                if (boardState.IsInCheck(boardState.SideToMove))
 10391                    return -Constants.MaxCentipawnEval + ply;
 092                return 0;
 93            }
 94
 5261095            TranspositionTable.SubmitEntry(boardState.BoardHash, TranspositionTable.AdjustScore(alpha, ply), depth, boar
 96
 5261097            return alpha;
 98        }
 99
 100        private static int SearchDeeper(BoardState boardState, int depth, int alpha, int beta,
 101            CancellationToken cancellationToken, bool foundPv, bool allowNullMove)
 102        {
 103            int score;
 1727816104            if (foundPv)
 105            {
 25570106                score = PrincipalVariationSearch(boardState, depth, alpha, beta, allowNullMove, cancellationToken);
 107            }
 108            else
 109            {
 1702246110                score = -Search(boardState, depth - 1, -beta, -alpha, allowNullMove, cancellationToken);
 111            }
 1727816112            return score;
 113        }
 114    }
 115}

/home/runner/work/rudim/rudim/Rudim/Search/Negamax.Helpers.cs

#LineLine coverage
 1using Rudim.Board;
 2using Rudim.Common;
 3using System.Threading;
 4
 5namespace Rudim.Search
 6{
 7    public static partial class Negamax
 8    {
 9        private static int PrincipalVariationSearch(BoardState boardState, int depth, int alpha, int beta,
 10            bool allowNullMove, CancellationToken cancellationToken)
 11        {
 2557012            int score = -Search(boardState, depth - 1, -alpha - 1, -alpha, allowNullMove, cancellationToken);
 2557013            if (score > alpha && score < beta)
 86414                score = -Search(boardState, depth - 1, -beta, -alpha, allowNullMove, cancellationToken);
 2557015            return score;
 16        }
 17
 18        private static void AlphaUpdate(int score, Move move, BoardState boardState, int depth, out int alpha, out bool 
 19        {
 197020            entryType = TranspositionEntryType.Exact;
 197021            if (!move.IsCapture())
 112022                MoveOrdering.AddHistoryMove(boardState.GetPieceOn(move.Source), move, depth);
 197023            alpha = score;
 197024            boardState.BestMove = move;
 197025            foundPv = true;
 197026        }
 27
 28        private static int BetaCutoff(int beta, Move move, int ply, BoardState boardState, int depth)
 29        {
 38836630            TranspositionTable.SubmitEntry(boardState.BoardHash, TranspositionTable.AdjustScore(beta, ply), depth, move,
 38836631                TranspositionEntryType.Beta);
 38836632            if (!move.IsCapture())
 7146433                MoveOrdering.AddKillerMove(move, ply);
 38836634            return beta;
 35        }
 36
 37        private static void PopulateMoveScores(BoardState boardState, int ply)
 38        {
 39            // Move hashMove = TranspositionTable.GetHashMove(boardState.BoardHash);
 3063428840            foreach (Move move in boardState.Moves)
 41            {
 42                // TODO: Revisit Hash Move once TT impl is more clear, this doesn't seem to be gaining as much ELO
 43                // if (move == hashMove)
 44                // {
 45                //     MoveOrdering.PopulateHashMove(move);
 46                // }
 47                // else
 48                // {
 1487606549                MoveOrdering.PopulateMoveScore(move, boardState, ply);
 50                // }
 51            }
 44107952        }
 53
 54        private static bool CanPruneNullMove(bool isPvNode, BoardState boardState, bool allowNullMove, int depth)
 55        {
 52851856            return allowNullMove && !isPvNode && !boardState.IsInCheck(boardState.SideToMove) && depth >= 2  &&
 52851857                   boardState.Phase > GamePhase.OnlyPawns;
 58        }
 59    }
 60}