Increase number of tunables (bench 5459982)

This commit is contained in:
2026-02-25 23:07:31 +01:00
parent 591e3e4177
commit b4e20caf1b
4 changed files with 293 additions and 127 deletions

View File

@@ -438,20 +438,20 @@ proc updateHistories(self: SearchManager, sideToMove: PieceColor, move: Move, pi
let startAttacked = self.board.position.threats.contains(move.startSquare)
let targetAttacked = self.board.position.threats.contains(move.targetSquare)
if move.isQuiet():
var bonus = (if good: self.parameters.moveBonuses.conthist.good else: -self.parameters.moveBonuses.conthist.bad) * depth
if ply > 0 and not self.board.positions[^2].fromNull:
let prevPiece = self.stack[ply - 1].piece
let bonus = (if good: self.parameters.moveBonuses.conthist.ply1.good else: -self.parameters.moveBonuses.conthist.ply1.bad) * depth
self.histories.continuationHistory[sideToMove][piece.kind][move.targetSquare][prevPiece.color][prevPiece.kind][self.stack[ply - 1].move.targetSquare] += (bonus - abs(bonus) * self.conthistScore(sideToMove, piece, move.targetSquare, ply, 1) div HISTORY_SCORE_CAP).int16
if ply > 1 and not self.board.positions[^3].fromNull:
let prevPiece = self.stack[ply - 2].piece
let bonus = (if good: self.parameters.moveBonuses.conthist.ply2.good else: -self.parameters.moveBonuses.conthist.ply2.bad) * depth
self.histories.continuationHistory[sideToMove][piece.kind][move.targetSquare][prevPiece.color][prevPiece.kind][self.stack[ply - 2].move.targetSquare] += (bonus - abs(bonus) * self.conthistScore(sideToMove, piece, move.targetSquare, ply, 2) div HISTORY_SCORE_CAP).int16
if ply > 3 and not self.board.positions[^5].fromNull:
let prevPiece = self.stack[ply - 4].piece
let bonus = (if good: self.parameters.moveBonuses.conthist.ply4.good else: -self.parameters.moveBonuses.conthist.ply4.bad) * depth
self.histories.continuationHistory[sideToMove][piece.kind][move.targetSquare][prevPiece.color][prevPiece.kind][self.stack[ply - 4].move.targetSquare] += (bonus - abs(bonus) * self.conthistScore(sideToMove, piece, move.targetSquare, ply, 4) div HISTORY_SCORE_CAP).int16
bonus = (if good: self.parameters.moveBonuses.quiet.good else: -self.parameters.moveBonuses.quiet.bad) * depth
let bonus = (if good: self.parameters.moveBonuses.quiet.good else: -self.parameters.moveBonuses.quiet.bad) * depth
self.histories.quietHistory[sideToMove][move.startSquare][move.targetSquare][startAttacked][targetAttacked] += int16(bonus - abs(bonus) * self.historyScore(sideToMove, move) div HISTORY_SCORE_CAP)
elif move.isCapture():
@@ -483,7 +483,7 @@ proc scoreMove(self: SearchManager, hashMove: Move, move: Move, ply: int): Score
# Good/bad tacticals
if move.isTactical():
let winning = self.parameters.see(self.board.position, move, 0)
let winning = self.parameters.see(self.board.position, move, 0, SeeOrdering)
if move.isCapture():
result.data += self.historyScore(sideToMove, move)
# Prioritize attacking our opponent's
@@ -839,7 +839,7 @@ proc qsearch(self: var SearchManager, root: static bool, ply: int, alpha, beta:
elif scoredMove.stage() == BadNoisy:
false
else:
self.parameters.see(self.board.position, move, 0)
self.parameters.see(self.board.position, move, 0, SeePruning)
# Skip known bad captures
if not winning:
continue
@@ -849,7 +849,7 @@ proc qsearch(self: var SearchManager, root: static bool, ply: int, alpha, beta:
# Qsearch futility pruning: similar to FP in regular search, but we skip moves
# that gain no material on top of not improving alpha (given a margin)
if not recapture and not self.stack[ply].inCheck and staticEval + self.parameters.qsearchFpEvalMargin <= alpha and not self.parameters.see(self.board.position, move, 1):
if not recapture and not self.stack[ply].inCheck and staticEval + self.parameters.qsearchFpEvalMargin <= alpha and not self.parameters.see(self.board.position, move, 1, SeePruning):
continue
let kingSq = self.board.position.kingSquare(self.board.sideToMove)
self.stack[ply].move = move
@@ -1056,7 +1056,9 @@ proc search(self: var SearchManager, depth, ply: int, alpha, beta: Score, isPV,
# Reverse futility pruning: if the static eval suggests a fail high is likely,
# cut off the node
let margin = (self.parameters.rfpMargins.base * depth) - self.parameters.rfpMargins.improving * improving.int
let rfpBase = if hashMove.isQuiet(): self.parameters.rfpMargins.base.quiet else: self.parameters.rfpMargins.base.noisy
let rfpImproving = if hashMove.isQuiet(): self.parameters.rfpMargins.improving.quiet else: self.parameters.rfpMargins.improving.noisy
let margin = (rfpBase * depth) - rfpImproving * improving.int
if ttAdjustedEval - margin >= beta:
# Instead of returning the static eval, we do something known as "fail mid"
@@ -1097,7 +1099,8 @@ proc search(self: var SearchManager, depth, ply: int, alpha, beta: Score, isPV,
NMP_DEPTH_REDUCTION = 3
NMP_EVAL_DEPTH_MAX_REDUCTION = 3
var reduction = NMP_BASE_REDUCTION + depth div NMP_DEPTH_REDUCTION
reduction += min((staticEval - beta) div self.parameters.nmpEvalDivisor, NMP_EVAL_DEPTH_MAX_REDUCTION)
let nmpDivisor = if hashMove.isQuiet(): self.parameters.nmpEvalDivisor.quiet else: self.parameters.nmpEvalDivisor.noisy
reduction += min((staticEval - beta) div nmpDivisor, NMP_EVAL_DEPTH_MAX_REDUCTION)
let score = -self.search(depth - reduction, ply + 1, -beta - 1, -beta, isPV=false, root=false, cutNode=not cutNode)
self.board.unmakeMove()
if self.shouldStop():
@@ -1178,7 +1181,7 @@ proc search(self: var SearchManager, depth, ply: int, alpha, beta: Score, isPV,
if lmrDepth <= SEE_PRUNING_MAX_DEPTH and (move.isQuiet() or move.isCapture() or move.isEnPassant()):
# SEE pruning: prune moves with a bad enough SEE score
let margin = -depth * (if move.isQuiet(): self.parameters.seePruningMargin.quiet else: self.parameters.seePruningMargin.capture)
if not self.parameters.see(self.board.position, move, margin):
if not self.parameters.see(self.board.position, move, margin, SeePruning):
inc(seenMoves)
continue
var singular = 0
@@ -1213,7 +1216,9 @@ proc search(self: var SearchManager, depth, ply: int, alpha, beta: Score, isPV,
# Multiple extensions. Hash move is increasingly singular: explore it
# even deeper
for margin in [self.parameters.doubleExtMargin, self.parameters.tripleExtMargin]:
let doubleExtMargin = if hashMove.isQuiet(): self.parameters.doubleExtMargin.quiet else: self.parameters.doubleExtMargin.noisy
let tripleExtMargin = if hashMove.isQuiet(): self.parameters.tripleExtMargin.quiet else: self.parameters.tripleExtMargin.noisy
for margin in [doubleExtMargin, tripleExtMargin]:
if singularScore <= newAlpha - margin:
inc(singular)
elif newBeta >= beta:
@@ -1314,7 +1319,8 @@ proc search(self: var SearchManager, depth, ply: int, alpha, beta: Score, isPV,
let prevMove = self.stack[ply - 1].move
self.histories.counterMoves[prevMove.startSquare][prevMove.targetSquare] = move
let histDepth = depth + (bestScore - beta > self.parameters.historyDepthEvalThreshold).int
let historyEvalThreshold = if move.isQuiet(): self.parameters.historyDepthEvalThreshold.quiet else: self.parameters.historyDepthEvalThreshold.noisy
let histDepth = depth + (bestScore - beta > historyEvalThreshold).int
# If the best move we found is a tactical move, we don't want to punish quiets,
# because they still might be good (just not as good wrt the best move).
# Very important to note that move == bestMove here!
@@ -1420,16 +1426,18 @@ proc aspirationSearch(self: var SearchManager, depth: int, score: Score): Score
# Reset the reduction whenever we fail low to ensure
# we don't miss good stuff that seems bad at first
reduction = 0
# Try again with larger window
delta = Score(delta * self.parameters.aspWindowWideningFactor.failLow div 128)
elif score >= beta:
beta = min(SCORE_INF, score + delta)
# Whenever we fail high, reduce the search depth as we
# expect the score to be good for our opponent anyway
reduction += 1
# Try again with larger window
delta = Score(delta * self.parameters.aspWindowWideningFactor.failHigh div 128)
else:
# Value was within the alpha-beta bounds, we're done
break
# Try again with larger window
delta += delta
if delta >= Score(self.parameters.aspWindowMaxSize):
# Window got too wide, give up and search with the full range
# of alpha-beta values

View File

@@ -206,7 +206,9 @@ proc scale(self: var SearchLimit, limiter: SearchLimiter, params: SearchParamete
totalNodes = limiter.searchStats.nodeCount.load(moRelaxed)
bestMoveNodes = limiter.searchStats.spentNodes[move.startSquare][move.targetSquare].load(moRelaxed)
bestMoveFrac = bestMoveNodes.float / totalNodes.float
scaleFactor = params.nodeTmBaseOffset - bestMoveFrac * params.nodeTmScaleFactor
baseOffset = if move.isQuiet(): params.nodeTmBaseOffset.quiet else: params.nodeTmBaseOffset.noisy
factor = if move.isQuiet(): params.nodeTmScaleFactor.quiet else: params.nodeTmScaleFactor.noisy
scaleFactor = baseOffset - bestMoveFrac * factor
self.lowerBound = min(self.upperBound, (self.origLowerBound.float * scaleFactor).uint64)

View File

@@ -18,17 +18,22 @@ import heimdall/[pieces, board, position]
import heimdall/util/tunables
func gain(parameters: SearchParameters, position: Position, move: Move): int =
type
SeeContext* = enum
SeeOrdering, SeePruning
func gain(weights: array[Pawn..Empty, int], position: Position, move: Move): int =
## Returns how much a single move gains in terms
## of static material value
if move.isCastling():
return 0
if move.isEnPassant():
return parameters.staticPieceScore(Pawn)
return weights[Pawn]
result = parameters.staticPieceScore(position.on(move.targetSquare))
result = weights[position.on(move.targetSquare).kind]
if move.isPromotion():
result += parameters.staticPieceScore(move.flag().promotionToPiece()) - parameters.staticPieceScore(Pawn)
result += weights[move.flag().promotionToPiece()] - weights[Pawn]
func popLeastValuable(position: Position, occupancy: var Bitboard, attackers: Bitboard, stm: PieceColor): PieceKind =
@@ -44,7 +49,7 @@ func popLeastValuable(position: Position, occupancy: var Bitboard, attackers: Bi
return Empty
proc see*(parameters: SearchParameters, position: Position, move: Move, threshold: int): bool =
proc see*(parameters: SearchParameters, position: Position, move: Move, threshold: int, context: SeeContext): bool =
## Statically evaluates a sequence of exchanges
## starting from the given one and returns whether
## the exchange can beat the given threshold.
@@ -54,12 +59,18 @@ proc see*(parameters: SearchParameters, position: Position, move: Move, threshol
# Yoinked from Stormphrax
var score = gain(parameters, position, move) - threshold
let weights = case context:
of SeeOrdering: parameters.seeWeights.ordering
of SeePruning:
if move.isQuiet(): parameters.seeWeights.pruneQuiet
else: parameters.seeWeights.pruneNoisy
var score = gain(weights, position, move) - threshold
if score < 0:
return false
var next = if move.isPromotion(): move.flag().promotionToPiece() else: position.on(move.startSquare).kind
score -= parameters.staticPieceScore(next)
score -= weights[next]
if score >= 0:
return true
@@ -92,7 +103,7 @@ proc see*(parameters: SearchParameters, position: Position, move: Move, threshol
attackers = attackers and occupancy
score = -score - 1 - parameters.staticPieceScore(next)
score = -score - 1 - weights[next]
stm = stm.opposite()
if score >= 0:
@@ -103,4 +114,4 @@ proc see*(parameters: SearchParameters, position: Position, move: Move, threshol
# We beat the threshold, hooray!
break
return position.sideToMove != stm
return position.sideToMove != stm

View File

@@ -34,10 +34,10 @@ type
SearchParameters* = ref object
# NMP: Reduce search depth by min((staticEval - beta) / divisor, maxValue)
nmpEvalDivisor*: int
nmpEvalDivisor*: tuple[quiet, noisy: int]
# RFP: Prune only when staticEval - (depth * base - improving_margin * improving) >= beta
rfpMargins*: tuple[base, improving: int]
rfpMargins*: tuple[base, improving: tuple[quiet, noisy: int]]
# FP: Prune only when (staticEval + offset) + margin * (depth + improving) <= alpha
fpEvalMargin*: int
@@ -55,6 +55,9 @@ type
# of alpha beta values once the window
# size gets to this value
aspWindowMaxSize*: int
# Delta widening divisors (delta = delta * 128 / divisor)
# for fail low (score <= alpha) and fail high (score >= beta)
aspWindowWideningFactor*: tuple[failLow, failHigh: int]
# Only prune quiet/capture moves whose SEE score
# is < this value times depth
@@ -62,7 +65,7 @@ type
# Good/bad moves get their bonus/malus * depth in their
# respective history tables
moveBonuses*: tuple[quiet, capture, conthist: tuple[good, bad: int]]
moveBonuses*: tuple[quiet, capture: tuple[good, bad: int], conthist: tuple[ply1, ply2, ply4: tuple[good, bad: int]]]
# Time management
@@ -72,15 +75,15 @@ type
# These are tuned as integers and then divided by 1000
# when loading them in
nodeTmBaseOffset*: float
nodeTmScaleFactor*: float
nodeTmBaseOffset*: tuple[quiet, noisy: float]
nodeTmScaleFactor*: tuple[quiet, noisy: float]
# Eval margin for qsearch futility pruning
qsearchFpEvalMargin*: int
# Score margins for multiple extensions
doubleExtMargin*: int
tripleExtMargin*: int
doubleExtMargin*: tuple[quiet, noisy: int]
tripleExtMargin*: tuple[quiet, noisy: int]
# Material scaling parameters
materialScalingOffset*: int
@@ -88,10 +91,10 @@ type
# Eval threshold for increasing depth
# for move history updates
historyDepthEvalThreshold*: int
historyDepthEvalThreshold*: tuple[quiet, noisy: int]
# Tunable piece weights
seeWeights*: array[Pawn..Empty, int]
# Tunable piece weights for SEE (split by context)
seeWeights*: tuple[ordering, pruneQuiet, pruneNoisy: array[Pawn..Empty, int]]
materialWeights*: array[Pawn..Empty, int]
# LMR table parameters (tuned as integers, divided by 1000)
@@ -121,41 +124,63 @@ NonPawnCorrHistWeightScale, 254
AspWindowMaxSize, 980
NonPawnCorrHistEvalScale, 470
MaterialKnightWeight, 465
DoubleExtMargin, 15
SEEQueenWeight, 1257
NodeTMBaseOffset, 2861
DoubleExtMarginQuiet, 15
DoubleExtMarginNoisy, 15
SEEOrdQueenWeight, 1257
SEEPruneQuietQueenWeight, 1257
SEEPruneNoisyQueenWeight, 1257
NodeTMBaseOffsetQuiet, 2861
NodeTMBaseOffsetNoisy, 2861
SEEPruningQuietMargin, 79
SEEPruningCaptureMargin, 124
NMPEvalDivisor, 243
RFPImprovingMargin, 135
HistoryDepthEvalThreshold, 53
NMPEvalDivisorQuiet, 243
NMPEvalDivisorNoisy, 243
RFPImprovingMarginQuiet, 135
RFPImprovingMarginNoisy, 135
HistoryDepthEvalThresholdQuiet, 53
HistoryDepthEvalThresholdNoisy, 53
BadQuietMalus, 280
ContHistMalus, 280
SEEKnightWeight, 465
ContHistMalusPly1, 280
ContHistMalusPly2, 280
ContHistMalusPly4, 280
SEEOrdKnightWeight, 465
SEEPruneQuietKnightWeight, 465
SEEPruneNoisyKnightWeight, 465
NonPawnCorrHistMinValue, -12428
RFPBaseMargin, 168
RFPBaseMarginQuiet, 168
RFPBaseMarginNoisy, 168
HistoryLMRQuietDivisor, 10901
MajorCorrHistMaxValue, 12028
PawnCorrHistWeightScale, 255
SEEPawnWeight, 99
SEERookWeight, 691
SEEOrdPawnWeight, 99
SEEPruneQuietPawnWeight, 99
SEEPruneNoisyPawnWeight, 99
SEEOrdRookWeight, 691
SEEPruneQuietRookWeight, 691
SEEPruneNoisyRookWeight, 691
MinorCorrHistWeightScale, 260
AspWindowInitialSize, 19
MinorCorrHistMinValue, -12442
QSearchFPEvalMargin, 211
MajorCorrHistMinValue, -12308
TripleExtMargin, 50
TripleExtMarginQuiet, 50
TripleExtMarginNoisy, 50
MaterialRookWeight, 647
HistoryLMRNoisyDivisor, 13902
GoodCaptureBonus, 45
NodeTMScaleFactor, 1634
NodeTMScaleFactorQuiet, 1634
NodeTMScaleFactorNoisy, 1634
MatScalingOffset, 26283
GoodQuietBonus, 261
ContHistBonus, 261
ContHistBonusPly1, 261
ContHistBonusPly2, 261
ContHistBonusPly4, 261
MajorCorrHistWeightScale, 257
PawnCorrHistMinValue, -12060
PawnCorrHistMaxValue, 12461
SEEBishopWeight, 485
SEEOrdBishopWeight, 485
SEEPruneQuietBishopWeight, 485
SEEPruneNoisyBishopWeight, 485
FPBaseOffset, 5
BadCaptureMalus, 113
FPEvalMargin, 98
@@ -177,8 +202,10 @@ template addTunableParameter(name: string, min, max, default: int, quantized = f
proc initTunableParameters: Table[string, TunableParameter] =
## Adds all our tunable parameters to the global
## parameter list
addTunableParameter("RFPBaseMargin", 1, 200, 100)
addTunableParameter("RFPImprovingMargin", 1, 200, 100)
addTunableParameter("RFPBaseMarginQuiet", 1, 200, 100)
addTunableParameter("RFPBaseMarginNoisy", 1, 200, 100)
addTunableParameter("RFPImprovingMarginQuiet", 1, 200, 100)
addTunableParameter("RFPImprovingMarginNoisy", 1, 200, 100)
addTunableParameter("FPEvalMargin", 1, 500, 250)
addTunableParameter("FPBaseOffset", 0, 200, 1)
# Value asspulled by cj, btw
@@ -186,32 +213,54 @@ proc initTunableParameters: Table[string, TunableParameter] =
addTunableParameter("HistoryLMRNoisyDivisor", 6144, 24576, 12288, true)
addTunableParameter("AspWindowInitialSize", 1, 60, 30)
addTunableParameter("AspWindowMaxSize", 1, 2000, 1000)
addTunableParameter("AspWindowWideningFailLow", 128, 384, 256)
addTunableParameter("AspWindowWideningFailHigh", 128, 384, 256)
addTunableParameter("SEEPruningQuietMargin", 1, 160, 80)
addTunableParameter("SEEPruningCaptureMargin", 1, 320, 160)
addTunableParameter("GoodQuietBonus", 1, 340, 170)
addTunableParameter("BadQuietMalus", 1, 900, 450)
addTunableParameter("GoodCaptureBonus", 1, 90, 45)
addTunableParameter("BadCaptureMalus", 1, 224, 112)
addTunableParameter("ContHistBonus", 1, 340, 170)
addTunableParameter("ContHistMalus", 1, 900, 450)
addTunableParameter("ContHistBonusPly1", 1, 340, 170)
addTunableParameter("ContHistMalusPly1", 1, 900, 450)
addTunableParameter("ContHistBonusPly2", 1, 340, 170)
addTunableParameter("ContHistMalusPly2", 1, 900, 450)
addTunableParameter("ContHistBonusPly4", 1, 340, 170)
addTunableParameter("ContHistMalusPly4", 1, 900, 450)
# Values yoinked from Stormphrax :3
addTunableParameter("NodeTMBaseOffset", 1000, 3000, 2630)
addTunableParameter("NodeTMScaleFactor", 1000, 2500, 1700)
addTunableParameter("NodeTMBaseOffsetQuiet", 1000, 3000, 2630)
addTunableParameter("NodeTMBaseOffsetNoisy", 1000, 3000, 2630)
addTunableParameter("NodeTMScaleFactorQuiet", 1000, 2500, 1700)
addTunableParameter("NodeTMScaleFactorNoisy", 1000, 2500, 1700)
addTunableParameter("QSearchFPEvalMargin", 100, 400, 200)
# We copying sf on this one
addTunableParameter("DoubleExtMargin", 0, 80, 40)
addTunableParameter("TripleExtMargin", 50, 200, 100)
addTunableParameter("DoubleExtMarginQuiet", 0, 80, 40)
addTunableParameter("DoubleExtMarginNoisy", 0, 80, 40)
addTunableParameter("TripleExtMarginQuiet", 50, 200, 100)
addTunableParameter("TripleExtMarginNoisy", 50, 200, 100)
addTunableParameter("MatScalingOffset", 13250, 53000, 26500)
addTunableParameter("MatScalingDivisor", 16384, 65536, 32768)
addTunableParameter("NMPEvalDivisor", 120, 350, 245)
addTunableParameter("HistoryDepthEvalThreshold", 25, 100, 50)
addTunableParameter("NMPEvalDivisorQuiet", 120, 350, 245)
addTunableParameter("NMPEvalDivisorNoisy", 120, 350, 245)
addTunableParameter("HistoryDepthEvalThresholdQuiet", 25, 100, 50)
addTunableParameter("HistoryDepthEvalThresholdNoisy", 25, 100, 50)
addTunableParameter("SEEPawnWeight", 50, 200, 100)
addTunableParameter("SEEKnightWeight", 225, 900, 450)
addTunableParameter("SEEBishopWeight", 225, 900, 450)
addTunableParameter("SEERookWeight", 325, 1300, 650)
addTunableParameter("SEEQueenWeight", 625, 2500, 1250)
addTunableParameter("SEEOrdPawnWeight", 50, 200, 100)
addTunableParameter("SEEOrdKnightWeight", 225, 900, 450)
addTunableParameter("SEEOrdBishopWeight", 225, 900, 450)
addTunableParameter("SEEOrdRookWeight", 325, 1300, 650)
addTunableParameter("SEEOrdQueenWeight", 625, 2500, 1250)
addTunableParameter("SEEPruneQuietPawnWeight", 50, 200, 100)
addTunableParameter("SEEPruneQuietKnightWeight", 225, 900, 450)
addTunableParameter("SEEPruneQuietBishopWeight", 225, 900, 450)
addTunableParameter("SEEPruneQuietRookWeight", 325, 1300, 650)
addTunableParameter("SEEPruneQuietQueenWeight", 625, 2500, 1250)
addTunableParameter("SEEPruneNoisyPawnWeight", 50, 200, 100)
addTunableParameter("SEEPruneNoisyKnightWeight", 225, 900, 450)
addTunableParameter("SEEPruneNoisyBishopWeight", 225, 900, 450)
addTunableParameter("SEEPruneNoisyRookWeight", 325, 1300, 650)
addTunableParameter("SEEPruneNoisyQueenWeight", 625, 2500, 1250)
addTunableParameter("MaterialPawnWeight", 50, 200, 100)
addTunableParameter("MaterialKnightWeight", 225, 900, 450)
addTunableParameter("MaterialBishopWeight", 225, 900, 450)
@@ -274,10 +323,14 @@ proc setParameter*(self: SearchParameters, name: string, value: int) =
# This is ugly, but short of macro shenanigans it's
# the best we can do
case name:
of "RFPBaseMargin":
self.rfpMargins.base = value
of "RFPImprovingMargin":
self.rfpMargins.improving = value
of "RFPBaseMarginQuiet":
self.rfpMargins.base.quiet = value
of "RFPBaseMarginNoisy":
self.rfpMargins.base.noisy = value
of "RFPImprovingMarginQuiet":
self.rfpMargins.improving.quiet = value
of "RFPImprovingMarginNoisy":
self.rfpMargins.improving.noisy = value
of "FPEvalMargin":
self.fpEvalMargin = value
of "FPBaseOffset":
@@ -290,6 +343,10 @@ proc setParameter*(self: SearchParameters, name: string, value: int) =
self.aspWindowInitialSize = value
of "AspWindowMaxSize":
self.aspWindowMaxSize = value
of "AspWindowWideningFailLow":
self.aspWindowWideningFactor.failLow = value
of "AspWindowWideningFailHigh":
self.aspWindowWideningFactor.failHigh = value
of "SEEPruningQuietMargin":
self.seePruningMargin.quiet = value
of "SEEPruningCaptureMargin":
@@ -298,42 +355,82 @@ proc setParameter*(self: SearchParameters, name: string, value: int) =
self.moveBonuses.quiet.good = value
of "BadQuietMalus":
self.moveBonuses.quiet.bad = value
of "ContHistBonus":
self.moveBonuses.conthist.good = value
of "ContHistMalus":
self.moveBonuses.conthist.bad = value
of "ContHistBonusPly1":
self.moveBonuses.conthist.ply1.good = value
of "ContHistMalusPly1":
self.moveBonuses.conthist.ply1.bad = value
of "ContHistBonusPly2":
self.moveBonuses.conthist.ply2.good = value
of "ContHistMalusPly2":
self.moveBonuses.conthist.ply2.bad = value
of "ContHistBonusPly4":
self.moveBonuses.conthist.ply4.good = value
of "ContHistMalusPly4":
self.moveBonuses.conthist.ply4.bad = value
of "GoodCaptureBonus":
self.moveBonuses.capture.good = value
of "BadCaptureMalus":
self.moveBonuses.capture.bad = value
of "NodeTMBaseOffset":
self.nodeTmBaseOffset = value / 1000
of "NodeTMScaleFactor":
self.nodeTmScaleFactor = value / 1000
of "NodeTMBaseOffsetQuiet":
self.nodeTmBaseOffset.quiet = value / 1000
of "NodeTMBaseOffsetNoisy":
self.nodeTmBaseOffset.noisy = value / 1000
of "NodeTMScaleFactorQuiet":
self.nodeTmScaleFactor.quiet = value / 1000
of "NodeTMScaleFactorNoisy":
self.nodeTmScaleFactor.noisy = value / 1000
of "QSearchFPEvalMargin":
self.qsearchFpEvalMargin = value
of "DoubleExtMargin":
self.doubleExtMargin = value
of "DoubleExtMarginQuiet":
self.doubleExtMargin.quiet = value
of "DoubleExtMarginNoisy":
self.doubleExtMargin.noisy = value
of "MatScalingDivisor":
self.materialScalingDivisor = value
of "MatScalingOffset":
self.materialScalingOffset = value
of "NMPEvalDivisor":
self.nmpEvalDivisor = value
of "TripleExtMargin":
self.tripleExtMargin = value
of "HistoryDepthEvalThreshold":
self.historyDepthEvalThreshold = value
of "SEEPawnWeight":
self.seeWeights[Pawn] = value
of "SEEKnightWeight":
self.seeWeights[Knight] = value
of "SEEBishopWeight":
self.seeWeights[Bishop] = value
of "SEERookWeight":
self.seeWeights[Rook] = value
of "SEEQueenWeight":
self.seeWeights[Queen] = value
of "NMPEvalDivisorQuiet":
self.nmpEvalDivisor.quiet = value
of "NMPEvalDivisorNoisy":
self.nmpEvalDivisor.noisy = value
of "TripleExtMarginQuiet":
self.tripleExtMargin.quiet = value
of "TripleExtMarginNoisy":
self.tripleExtMargin.noisy = value
of "HistoryDepthEvalThresholdQuiet":
self.historyDepthEvalThreshold.quiet = value
of "HistoryDepthEvalThresholdNoisy":
self.historyDepthEvalThreshold.noisy = value
of "SEEOrdPawnWeight":
self.seeWeights.ordering[Pawn] = value
of "SEEOrdKnightWeight":
self.seeWeights.ordering[Knight] = value
of "SEEOrdBishopWeight":
self.seeWeights.ordering[Bishop] = value
of "SEEOrdRookWeight":
self.seeWeights.ordering[Rook] = value
of "SEEOrdQueenWeight":
self.seeWeights.ordering[Queen] = value
of "SEEPruneQuietPawnWeight":
self.seeWeights.pruneQuiet[Pawn] = value
of "SEEPruneQuietKnightWeight":
self.seeWeights.pruneQuiet[Knight] = value
of "SEEPruneQuietBishopWeight":
self.seeWeights.pruneQuiet[Bishop] = value
of "SEEPruneQuietRookWeight":
self.seeWeights.pruneQuiet[Rook] = value
of "SEEPruneQuietQueenWeight":
self.seeWeights.pruneQuiet[Queen] = value
of "SEEPruneNoisyPawnWeight":
self.seeWeights.pruneNoisy[Pawn] = value
of "SEEPruneNoisyKnightWeight":
self.seeWeights.pruneNoisy[Knight] = value
of "SEEPruneNoisyBishopWeight":
self.seeWeights.pruneNoisy[Bishop] = value
of "SEEPruneNoisyRookWeight":
self.seeWeights.pruneNoisy[Rook] = value
of "SEEPruneNoisyQueenWeight":
self.seeWeights.pruneNoisy[Queen] = value
of "MaterialPawnWeight":
self.materialWeights[Pawn] = value
of "MaterialKnightWeight":
@@ -407,10 +504,14 @@ proc getParameter*(self: SearchParameters, name: string): int =
# This is ugly, but short of macro shenanigans it's
# the best we can do
case name:
of "RFPBaseMargin":
self.rfpMargins.base
of "RFPImprovingMargin":
self.rfpMargins.improving
of "RFPBaseMarginQuiet":
self.rfpMargins.base.quiet
of "RFPBaseMarginNoisy":
self.rfpMargins.base.noisy
of "RFPImprovingMarginQuiet":
self.rfpMargins.improving.quiet
of "RFPImprovingMarginNoisy":
self.rfpMargins.improving.noisy
of "FPEvalMargin":
self.fpEvalMargin
of "FPBaseOffset":
@@ -423,6 +524,10 @@ proc getParameter*(self: SearchParameters, name: string): int =
self.aspWindowInitialSize
of "AspWindowMaxSize":
self.aspWindowMaxSize
of "AspWindowWideningFailLow":
self.aspWindowWideningFactor.failLow
of "AspWindowWideningFailHigh":
self.aspWindowWideningFactor.failHigh
of "SEEPruningQuietMargin":
self.seePruningMargin.quiet
of "SEEPruningCaptureMargin":
@@ -431,42 +536,82 @@ proc getParameter*(self: SearchParameters, name: string): int =
self.moveBonuses.quiet.good
of "BadQuietMalus":
self.moveBonuses.quiet.bad
of "ContHistBonus":
self.moveBonuses.conthist.good
of "ContHistMalus":
self.moveBonuses.conthist.bad
of "ContHistBonusPly1":
self.moveBonuses.conthist.ply1.good
of "ContHistMalusPly1":
self.moveBonuses.conthist.ply1.bad
of "ContHistBonusPly2":
self.moveBonuses.conthist.ply2.good
of "ContHistMalusPly2":
self.moveBonuses.conthist.ply2.bad
of "ContHistBonusPly4":
self.moveBonuses.conthist.ply4.good
of "ContHistMalusPly4":
self.moveBonuses.conthist.ply4.bad
of "GoodCaptureBonus":
self.moveBonuses.capture.good
of "BadCaptureMalus":
self.moveBonuses.capture.bad
of "NodeTMBaseOffset":
int(self.nodeTmBaseOffset * 1000)
of "NodeTMScaleFactor":
int(self.nodeTmScaleFactor * 1000)
of "NodeTMBaseOffsetQuiet":
int(self.nodeTmBaseOffset.quiet * 1000)
of "NodeTMBaseOffsetNoisy":
int(self.nodeTmBaseOffset.noisy * 1000)
of "NodeTMScaleFactorQuiet":
int(self.nodeTmScaleFactor.quiet * 1000)
of "NodeTMScaleFactorNoisy":
int(self.nodeTmScaleFactor.noisy * 1000)
of "QSearchFPEvalMargin":
self.qsearchFpEvalMargin
of "DoubleExtMargin":
self.doubleExtMargin
of "DoubleExtMarginQuiet":
self.doubleExtMargin.quiet
of "DoubleExtMarginNoisy":
self.doubleExtMargin.noisy
of "MatScalingDivisor":
self.materialScalingDivisor
of "MatScalingOffset":
self.materialScalingOffset
of "NMPEvalDivisor":
self.nmpEvalDivisor
of "TripleExtMargin":
self.tripleExtMargin
of "HistoryDepthEvalThreshold":
self.historyDepthEvalThreshold
of "SEEPawnWeight":
self.seeWeights[Pawn]
of "SEEKnightWeight":
self.seeWeights[Knight]
of "SEEBishopWeight":
self.seeWeights[Bishop]
of "SEERookWeight":
self.seeWeights[Rook]
of "SEEQueenWeight":
self.seeWeights[Queen]
of "NMPEvalDivisorQuiet":
self.nmpEvalDivisor.quiet
of "NMPEvalDivisorNoisy":
self.nmpEvalDivisor.noisy
of "TripleExtMarginQuiet":
self.tripleExtMargin.quiet
of "TripleExtMarginNoisy":
self.tripleExtMargin.noisy
of "HistoryDepthEvalThresholdQuiet":
self.historyDepthEvalThreshold.quiet
of "HistoryDepthEvalThresholdNoisy":
self.historyDepthEvalThreshold.noisy
of "SEEOrdPawnWeight":
self.seeWeights.ordering[Pawn]
of "SEEOrdKnightWeight":
self.seeWeights.ordering[Knight]
of "SEEOrdBishopWeight":
self.seeWeights.ordering[Bishop]
of "SEEOrdRookWeight":
self.seeWeights.ordering[Rook]
of "SEEOrdQueenWeight":
self.seeWeights.ordering[Queen]
of "SEEPruneQuietPawnWeight":
self.seeWeights.pruneQuiet[Pawn]
of "SEEPruneQuietKnightWeight":
self.seeWeights.pruneQuiet[Knight]
of "SEEPruneQuietBishopWeight":
self.seeWeights.pruneQuiet[Bishop]
of "SEEPruneQuietRookWeight":
self.seeWeights.pruneQuiet[Rook]
of "SEEPruneQuietQueenWeight":
self.seeWeights.pruneQuiet[Queen]
of "SEEPruneNoisyPawnWeight":
self.seeWeights.pruneNoisy[Pawn]
of "SEEPruneNoisyKnightWeight":
self.seeWeights.pruneNoisy[Knight]
of "SEEPruneNoisyBishopWeight":
self.seeWeights.pruneNoisy[Bishop]
of "SEEPruneNoisyRookWeight":
self.seeWeights.pruneNoisy[Rook]
of "SEEPruneNoisyQueenWeight":
self.seeWeights.pruneNoisy[Queen]
of "MaterialPawnWeight":
self.materialWeights[Pawn]
of "MaterialKnightWeight":
@@ -561,12 +706,12 @@ proc getSPSAInput*(parameters: SearchParameters): string =
func staticPieceScore*(parameters: SearchParameters, kind: PieceKind): int {.inline.} =
## Returns a static score for the given piece
## type to be used inside SEE
parameters.seeWeights[kind]
## type using SEE ordering weights (used for MVV)
parameters.seeWeights.ordering[kind]
func staticPieceScore*(parameters: SearchParameters, piece: Piece): int {.inline.} =
## Returns a static score for the given piece
## to be used inside SEE
## using SEE ordering weights (used for MVV)
parameters.staticPieceScore(piece.kind)
func materialPieceScore*(parameters: SearchParameters, kind: PieceKind): int {.inline.} =