< 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        {
 184042324            int ply = _searchDepth - depth;
 184042325            bool isPvNode = beta - alpha > 1;
 184042326            Nodes++;
 27
 184042328            if (boardState.IsDraw())
 029                return 0;
 30
 184042331            (bool hasValue, int ttScore, Move ttBest) = TranspositionTable.GetEntry(boardState.BoardHash, alpha, beta, d
 184042332            if (hasValue)
 33            {
 34                // TODO: This doesn't seem right - revisit TT impl
 7759735                boardState.BestMove = ttBest;
 7759736                return TranspositionTable.RetrieveScore(ttScore, ply);
 37            }
 38
 176282639            if (depth <= 0)
 123818740                return Quiescence.Search(boardState, alpha, beta, cancellationToken);
 41
 52463942            if (CanPruneNullMove(isPvNode, boardState, allowNullMove, depth))
 43            {
 12043644                boardState.MakeNullMove();
 12043645                int score = -Search(boardState, depth - 1 - 2, -beta, -beta + 1, false, cancellationToken);
 12043646                boardState.UndoNullMove();
 12043647                if (score >= beta)
 8743748                    return beta; // TODO : Store in TT
 49            }
 50
 51            int originalAlpha = alpha;
 43720252            bool foundPv = false;
 43720253            TranspositionEntryType entryType = TranspositionEntryType.Alpha;
 54
 43720255            boardState.GenerateMoves();
 43720256            PopulateMoveScores(boardState, ply);
 57
 43720258            int numberOfLegalMoves = 0;
 43720259            List<Move> moves = boardState.Moves;
 405935060            for(int i = 0; i < moves.Count; ++i)
 61            {
 197729662                MoveOrdering.SortNextBestMove(moves, i);
 197729663                Move move = moves[i];
 197729664                if (cancellationToken.IsCancellationRequested)
 65                    break;
 197729266                boardState.MakeMove(move);
 197729267                if (boardState.IsInCheck(boardState.SideToMove.Other()))
 68                {
 25821269                    boardState.UnmakeMove(move);
 25821270                    continue;
 71                }
 72
 171908073                int score = SearchDeeper(boardState, depth, alpha, beta, cancellationToken, foundPv, allowNullMove);
 74
 171908075                numberOfLegalMoves++;
 76
 171908077                boardState.UnmakeMove(move);
 171908078                if (score >= beta)
 79                {
 38481980                    return BetaCutoff(beta, move, ply, boardState, depth);
 81                }
 133426182                if (score > alpha)
 83                {
 197084                    AlphaUpdate(score, move, boardState, depth, out alpha, out foundPv, out entryType);
 85                }
 86            }
 87
 5238388            if (numberOfLegalMoves == 0)
 89            {
 10390                if (boardState.IsInCheck(boardState.SideToMove))
 10391                    return -Constants.MaxCentipawnEval + ply;
 092                return 0;
 93            }
 94
 5228095            TranspositionTable.SubmitEntry(boardState.BoardHash, TranspositionTable.AdjustScore(alpha, ply), depth, boar
 96
 5228097            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;
 1719080104            if (foundPv)
 105            {
 25568106                score = PrincipalVariationSearch(boardState, depth, alpha, beta, allowNullMove, cancellationToken);
 107            }
 108            else
 109            {
 1693512110                score = -Search(boardState, depth - 1, -beta, -alpha, allowNullMove, cancellationToken);
 111            }
 1719080112            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        {
 2556812            int score = -Search(boardState, depth - 1, -alpha - 1, -alpha, allowNullMove, cancellationToken);
 2556813            if (score > alpha && score < beta)
 86414                score = -Search(boardState, depth - 1, -beta, -alpha, allowNullMove, cancellationToken);
 2556815            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        {
 38481930            TranspositionTable.SubmitEntry(boardState.BoardHash, TranspositionTable.AdjustScore(beta, ply), depth, move,
 38481931                TranspositionEntryType.Beta);
 38481932            if (!move.IsCapture())
 6955633                MoveOrdering.AddKillerMove(move, ply);
 38481934            return beta;
 35        }
 36
 37        private static void PopulateMoveScores(BoardState boardState, int ply)
 38        {
 39            // Move hashMove = TranspositionTable.GetHashMove(boardState.BoardHash);
 3041371440            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                // {
 1476965549                MoveOrdering.PopulateMoveScore(move, boardState, ply);
 50                // }
 51            }
 43720252        }
 53
 54        private static bool CanPruneNullMove(bool isPvNode, BoardState boardState, bool allowNullMove, int depth)
 55        {
 52463956            return allowNullMove && !isPvNode && !boardState.IsInCheck(boardState.SideToMove) && depth >= 2  &&
 52463957                   boardState.Phase > GamePhase.OnlyPawns;
 58        }
 59    }
 60}