Add untested FP
This commit is contained in:
parent
9b049cdcec
commit
fdf71bbfce
|
@ -51,6 +51,11 @@ const
|
|||
# Constants to configure FP
|
||||
# (Futility pruning)
|
||||
|
||||
# Limit after which FP is disabled
|
||||
FP_DEPTH_LIMIT = 1
|
||||
# Advantage threshold
|
||||
FP_EVAL_MARGIN = 125
|
||||
|
||||
NUM_KILLERS* = 2
|
||||
MAX_DEPTH* = 255
|
||||
# Constants used during move ordering
|
||||
|
@ -158,7 +163,7 @@ func isTactical(self: Move): bool {.inline.} =
|
|||
func isQuiet(self: Move): bool {.inline.} =
|
||||
## Returns whether the given move is
|
||||
## a quiet
|
||||
return not self.isCapture() and not self.isEnPassant()
|
||||
return not self.isCapture() and not self.isEnPassant() and not self.isPromotion()
|
||||
|
||||
|
||||
proc getEstimatedMoveScore(self: SearchManager, move: Move, ply: int): int =
|
||||
|
@ -376,6 +381,7 @@ proc search(self: var SearchManager, depth, ply: int, alpha, beta: Score, isPV:
|
|||
if depth <= 0:
|
||||
# Quiescent search gain: 264.8 +/- 71.6
|
||||
return self.qsearch(0, alpha, beta)
|
||||
let staticEval = self.board.position.evaluate()
|
||||
if ply > 0:
|
||||
# Probe the transposition table to see if we can cause an early cutoff
|
||||
let query = self.transpositionTable[].get(self.board.position.zobristKey, depth.uint8)
|
||||
|
@ -389,7 +395,6 @@ proc search(self: var SearchManager, depth, ply: int, alpha, beta: Score, isPV:
|
|||
of UpperBound:
|
||||
if query.entry.score <= alpha:
|
||||
return query.entry.score
|
||||
let staticEval = self.board.position.evaluate()
|
||||
if not isPV and not self.board.inCheck() and depth <= RFP_DEPTH_LIMIT and staticEval - RFP_EVAL_THRESHOLD * depth >= beta:
|
||||
## Reverse futility pruning: if the side to move has a significant advantage
|
||||
## in the current position and is not in check, return the position's static
|
||||
|
@ -463,6 +468,14 @@ proc search(self: var SearchManager, depth, ply: int, alpha, beta: Score, isPV:
|
|||
for i, move in moves:
|
||||
if ply == 0 and self.searchMoves.len() > 0 and move notin self.searchMoves:
|
||||
continue
|
||||
when defined(FP):
|
||||
if not isPV and depth <= FP_DEPTH_LIMIT and staticEval + FP_EVAL_MARGIN * depth < alpha and bestScore > mateScore() - MAX_DEPTH:
|
||||
# Futility pruning: If a move cannot meaningfully improve alpha, prune it from the
|
||||
# tree. Much like RFP, this is an unsound optimization (and a riskier one at that,
|
||||
# apparently), so our depth limit and evaluation margins are very conservative
|
||||
# compared to RFP. Also, we need to make sure the best score is not a mate score, or
|
||||
# we'd risk pruning moves that evade checkmate
|
||||
continue
|
||||
self.board.doMove(move)
|
||||
let
|
||||
extension = self.getSearchExtension(move)
|
||||
|
@ -508,12 +521,12 @@ proc search(self: var SearchManager, depth, ply: int, alpha, beta: Score, isPV:
|
|||
bestScore = max(score, bestScore)
|
||||
if score >= beta:
|
||||
if move.isQuiet():
|
||||
# History heuristic: keep track of moves that caused a beta cutoff and order
|
||||
# History heuristic: keep track of quiets that caused a beta cutoff and order
|
||||
# them early in subsequent searches, as they might be really good later. A
|
||||
# quadratic bonus wrt. depth is usually the value that is used (though some
|
||||
# engines, namely Stockfish, use a linear bonus. Maybe we can investigate this)
|
||||
self.storeHistoryScore(sideToMove, move, score, depth * depth)
|
||||
# Killer move heuristic: store moves that caused a beta cutoff according to the distance from
|
||||
# Killer move heuristic: store quiets that caused a beta cutoff according to the distance from
|
||||
# root that they occurred at, as they might be good refutations for future moves from the opponent.
|
||||
# Elo gains: 33.5 +/- 19.3
|
||||
self.storeKillerMove(ply, move)
|
||||
|
|
Loading…
Reference in New Issue