コード例 #1
0
 public TranspositionEntry(
     ulong hash,
     int depth,
     double score,
     int ancient,
     TranspositionEntryType nodeType,
     ColoredBitBoard move)
 {
     Hash     = hash;
     Depth    = depth;
     Score    = score;
     Ancient  = ancient;
     NodeType = nodeType;
     Move     = move;
 }
コード例 #2
0
 private void StoreEvaluation(int score, TranspositionEntryType type)
 {
     if (!transpositions.ContainsKey(board.positionKey))
     {
         transpositions.Add(board.positionKey, new TranspositionEntry {
             Score = score, Type = type
         });
     }
     else if (type == TranspositionEntryType.Exact) //We have a better evaluation
     {
         transpositions[board.positionKey] = new TranspositionEntry {
             Score = score, Type = type
         };
     }
 }
コード例 #3
0
        private int DeepEval(int depth, int alpha, int beta, bool nullMoveAllowed, Move[] pv, IDictionary <Move, int> orderedTopLevelMoves = null)
        {
            searchInfo.Nodes++;

            if (transpositions.ContainsKey(board.positionKey))
            {
                searchInfo.Transpositions++;
                var score = LookupEvaluation(alpha, beta);

                if (score != LookupFailed)
                {
                    return(score);
                }
            }

            generator.Setup();
            var moves = generator.GetMoves(false);

            if (!moves.Any())
            {
                //When in Check: Checkmate:
                if (generator.InCheck)
                {
                    //Compute checkmate score:
                    var currentDepth = board.states.Count; //TODO add ply variable to board
                    return(-CHECKMATE + currentDepth);
                }
                else //Stalemate
                {
                    return(DRAW);
                }
            }
            else if (board.states.Any(s => s.positionKey == board.positionKey))
            {
                //Repetition
                return(DRAW);
            }

            //TODO Add 50 moves rule

            if (depth == 0)
            {
                return(QuiesceneSearch(alpha, beta));
            }

            if (depth == 1)
            {
                //Futility pruning
                var currentEval = Evaluation.Evaluate(board);
                if (currentEval + Evaluation.BishopValue < alpha)
                {
                    searchInfo.FutilityPrunes++;
                    //Prune this node, i.e. go directly to QuiesceneSearch
                    return(QuiesceneSearch(alpha, beta));
                }
            }

            if (nullMoveAllowed && !generator.InCheck && depth >= 1 + R)
            {
                searchInfo.NullMoves++;
                //Null move pruning
                var npv = new Move[depth]; //irellevant here
                board.SubmitNullMove();
                int eval = -DeepEval(depth - 1 - R, -beta, -beta + 1, false, npv);
                board.UndoNullMove();
                if (eval >= beta)
                {
                    searchInfo.NullMovesSuccess++;
                    return(eval);
                }
            }

            TranspositionEntryType ttType = TranspositionEntryType.UpperBound;
            int movenumber = 1;

            bool searchPV = true;

            foreach (var move in moves.OrderByDescending(m => MoveImportance(m, depth, orderedTopLevelMoves)))
            {
                if (depth == searchInfo.Depth) //Upper level
                {
                    Console.WriteLine($"info currmove {move.ToAlgebraicNotation()} currmovenumber {movenumber++} depth {depth}");
                }

                var npv = new Move[depth - 1];
                board.SubmitMove(move);

                int eval;
                if (searchPV)
                {
                    eval = -DeepEval(depth - 1, -beta, -alpha, true, npv);
                }
                else
                {
                    searchInfo.Scouts++;
                    //Scout zw search
                    eval = -ZWSerach(depth - 1, -alpha);
                    if (eval > alpha)
                    {
                        eval = -DeepEval(depth - 1, -beta, -alpha, true, npv); // re-search
                    }
                    else
                    {
                        searchInfo.ScoutRemovals++;
                    }
                }

                board.UndoMove();

                if (depth == searchInfo.Depth)
                {
                    searchInfo.TopLevelMoveOrder.Add(move, eval);
                }

                if (eval >= beta)
                {
                    searchInfo.BetaCutoffs++;
                    //transposition is an upper bound
                    StoreEvaluation(eval, TranspositionEntryType.LowerBound);
                    if (move.CapturedPiece == Piece.NONE)
                    {
                        KillerMoves[board.Ply][2] = KillerMoves[board.Ply][1];
                        KillerMoves[board.Ply][1] = KillerMoves[board.Ply][0];
                        KillerMoves[board.Ply][0] = move;
                    }
                    return(beta);
                }
                else if (eval > alpha)
                {
                    alpha    = eval;
                    searchPV = false;
                    pv[0]    = move;
                    Array.Copy(npv, 0, pv, 1, npv.Length);
                    ttType = TranspositionEntryType.Exact;
                }
            }

            StoreEvaluation(alpha, ttType);

            return(alpha);
        }