The following explanation is based on how it's done in Fruit, and there are similar implementations in Crafty and Stockfish (and probably many many other engines as well).
The scaling looks like this:
eval = ((opening * (256 - phase)) + (endgame * phase)) / 256
Where opening is the evaluation of the position with middle game in mind (e.g. keep kings protected behind their pawn covers) and endgame is the evaluation with endgame in mind (e.g. activate the kings). Both these evaluations are done in parallel when evaluating a position.
The phase is evaluated like this (code specifics left out):
PawnPhase = 0
KnightPhase = 1
BishopPhase = 1
RookPhase = 2
QueenPhase = 4
TotalPhase = PawnPhase*16 + KnightPhase*4 +
BishopPhase*4 + RookPhase*4 + QueenPhase*2
phase = TotalPhase
phase -= wp * PawnPhase // Number of white pawns
phase -= wn * Knight // White knights
...
phase -= br * RookPhase
phase -= bq * QueenPhase
phase = (phase * 256 + (TotalPhase / 2)) / TotalPhase
Example
White and black each has NNBR and the evaluation for opening is +100 and endgame is +300
According to the above numbers we then get:
phase = (14 * 256 + (24 / 2)) / 24 = 149
## Where 14 is 24-1-1-1-2-1-1-1-2 (TotalPhase - phases of all pieces)
eval = ((100 * (256 - 149)) + (300 * 149)) / 256 = 216 tapered eval
Chess programming wiki - Tapered Eval
-
Quite ingenious. Funny how the decision on game phase in current version of Mediocre is extremely close to this (without interpolating on it of course), I wonder if I stole that from Fruit way back when I implemented it. :)
No comments:
Post a Comment