// does alpha-beta search on the null window [beta-1, beta] using a transposition table. // the score returned is from the active player's perspective. private int NullWindowSearch(MutState state, int beta, int depth) { Debug.Assert(depth >= 0 && depth <= Depth); Debug.Assert(_nodesRemaining > 0); int alpha = beta - 1; // null window search _nodesRemaining--; _nodesSearched++; // note: it's pretty expensive to check for mate/stalemate since it involves trying to enumerate the current state's successors. // as a result, we don't bother checking for those conditions and returning the correct value when depth == 0. if (depth == 0) { return(Quiesce(state, alpha, beta, depth: 0)); } // Check for cancellation if (Canceled) { _pvt.SetNoPv(depth); return(state.Heuristic); } // TT lookup TtEntry tte; Move storedPvMove = default; if (TtLookup(state, alpha, beta, depth, out var ttRef, out int bound)) { return(bound); }
// note: Heuristic is calculated from the active player's viewpoint public static int Heuristic(MutState state) { int result = 0; for (var bb = state.Occupied; !bb.IsZero; bb = bb.ClearNext()) { var location = bb.NextLocation(); var piece = state.Board[location].Piece; var(kind, side) = (piece.Kind, piece.Side); int pieceValue = PieceScore(kind); int pieceSquareValue = PsqScore(piece, location); if (side == state.ActiveSide) { result += pieceValue; result += pieceSquareValue; } else { result -= pieceValue; result -= pieceSquareValue; } } return(result); }
public static int OfTerminal(MutState state) { // this assert is pretty costly //Debug.Assert(state.ToImmutable().IsTerminal); bool isStalemate = !state.IsCheck; if (isStalemate) { return(0); } return(MinScore); }
private int RunMtdf(MutState root, CancellationToken ct, out ImmutableArray <Move> pv) { _tt = (ITranspositionTable <TtEntry>)Tt; _ct = ct; _nodesSearched = 0; _nodesRemaining = MaxNodes; _pvt = new PvTable(Depth); _kt = new KillerTable(Depth); int guess = FirstGuess; var(lowerBound, upperBound) = (Evaluation.MinScore, Evaluation.MaxScore); do { int beta = guess == lowerBound ? (guess + 1) : guess; Log.Debug("Starting null-window search for state {0} with beta={1}", root, beta); guess = NullWindowSearch(root, beta, Depth); Log.Debug("Null-window search for state {0} with beta={1} returned {2}", root, beta, guess); if (guess < beta) // the real value is <= guess { upperBound = guess; } else // beta-cutoff: the real value is >= guess { lowerBound = guess; } // EXPERIMENTAL: trying binary search guess = (int)(((long)lowerBound + (long)upperBound) / 2); }while (lowerBound < upperBound && _nodesRemaining > 0); pv = _pvt.GetTopPv().ToImmutableArray(); return(guess); }