< 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        {
 173085924            int ply = _searchDepth - depth;
 173085925            bool isPvNode = beta - alpha > 1;
 173085926            Nodes++;
 27
 173085928            if (boardState.IsDraw())
 029                return 0;
 30
 173085931            (bool hasValue, int ttScore, Move ttBest) = TranspositionTable.GetEntry(boardState.BoardHash, alpha, beta, d
 173085932            if (hasValue)
 33            {
 34                // TODO: This doesn't seem right - revisit TT impl
 7467935                boardState.BestMove = ttBest;
 7467936                return TranspositionTable.RetrieveScore(ttScore, ply);
 37            }
 38
 165618039            if (depth <= 0)
 115342440                return Quiescence.Search(boardState, alpha, beta, cancellationToken);
 41
 50275642            if (CanPruneNullMove(isPvNode, boardState, allowNullMove, depth))
 43            {
 10617144                boardState.MakeNullMove();
 10617145                int score = -Search(boardState, depth - 1 - 2, -beta, -beta + 1, false, cancellationToken);
 10617146                boardState.UndoNullMove();
 10617147                if (score >= beta)
 7694948                    return beta; // TODO : Store in TT
 49            }
 50
 51            int originalAlpha = alpha;
 42580752            bool foundPv = false;
 42580753            TranspositionEntryType entryType = TranspositionEntryType.Alpha;
 54
 42580755            boardState.GenerateMoves();
 42580756            PopulateMoveScores(boardState, ply);
 57
 42580758            int numberOfLegalMoves = 0;
 42580759            List<Move> moves = boardState.Moves;
 380831460            for(int i = 0; i < moves.Count; ++i)
 61            {
 185563162                MoveOrdering.SortNextBestMove(moves, i);
 185563163                Move move = moves[i];
 185563164                if (cancellationToken.IsCancellationRequested)
 65                    break;
 185562766                boardState.MakeMove(move);
 185562767                if (boardState.IsInCheck(boardState.SideToMove.Other()))
 68                {
 23188869                    boardState.UnmakeMove(move);
 23188870                    continue;
 71                }
 72
 162373973                int score = SearchDeeper(boardState, depth, alpha, beta, cancellationToken, foundPv, allowNullMove);
 74
 162373975                numberOfLegalMoves++;
 76
 162373977                boardState.UnmakeMove(move);
 162373978                if (score >= beta)
 79                {
 37727780                    return BetaCutoff(beta, move, ply, boardState, depth);
 81                }
 124646282                if (score > alpha)
 83                {
 202484                    AlphaUpdate(score, move, boardState, depth, out alpha, out foundPv, out entryType);
 85                }
 86            }
 87
 4853088            if (numberOfLegalMoves == 0)
 89            {
 7890                if (boardState.IsInCheck(boardState.SideToMove))
 7891                    return -Constants.MaxCentipawnEval + ply;
 092                return 0;
 93            }
 94
 4845295            TranspositionTable.SubmitEntry(boardState.BoardHash, TranspositionTable.AdjustScore(alpha, ply), depth, boar
 96
 4845297            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;
 1623739104            if (foundPv)
 105            {
 24992106                score = PrincipalVariationSearch(boardState, depth, alpha, beta, allowNullMove, cancellationToken);
 107            }
 108            else
 109            {
 1598747110                score = -Search(boardState, depth - 1, -beta, -alpha, allowNullMove, cancellationToken);
 111            }
 1623739112            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        {
 2499212            int score = -Search(boardState, depth - 1, -alpha - 1, -alpha, allowNullMove, cancellationToken);
 2499213            if (score > alpha && score < beta)
 90614                score = -Search(boardState, depth - 1, -beta, -alpha, allowNullMove, cancellationToken);
 2499215            return score;
 16        }
 17
 18        private static void AlphaUpdate(int score, Move move, BoardState boardState, int depth, out int alpha, out bool 
 19        {
 202420            entryType = TranspositionEntryType.Exact;
 202421            if (!move.IsCapture())
 115722                MoveOrdering.AddHistoryMove(boardState.GetPieceOn(move.Source), move, depth);
 202423            alpha = score;
 202424            boardState.BestMove = move;
 202425            foundPv = true;
 202426        }
 27
 28        private static int BetaCutoff(int beta, Move move, int ply, BoardState boardState, int depth)
 29        {
 37727730            TranspositionTable.SubmitEntry(boardState.BoardHash, TranspositionTable.AdjustScore(beta, ply), depth, move,
 37727731                TranspositionEntryType.Beta);
 37727732            if (!move.IsCapture())
 6825633                MoveOrdering.AddKillerMove(move, ply);
 37727734            return beta;
 35        }
 36
 37        private static void PopulateMoveScores(BoardState boardState, int ply)
 38        {
 39            // Move hashMove = TranspositionTable.GetHashMove(boardState.BoardHash);
 2980576040            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                // {
 1447707349                MoveOrdering.PopulateMoveScore(move, boardState, ply);
 50                // }
 51            }
 42580752        }
 53
 54        private static bool CanPruneNullMove(bool isPvNode, BoardState boardState, bool allowNullMove, int depth)
 55        {
 50275656            return allowNullMove && !isPvNode && !boardState.IsInCheck(boardState.SideToMove) && depth >= 2  &&
 50275657                   boardState.Phase > GamePhase.OnlyPawns;
 58        }
 59    }
 60}