I'm putting together a simple chess position evaluation function. This being the first time for me building a chess engine, I am feeling very tentative with putting in just any evaluation function. The one shown on this Chess Programming Wiki page looks like a good candidate. However this has an ellipsis at the end which makes me unsure of whether it will be a good one to use?
Once the whole engine is in place and functional, I intend to come back to the evaluation function and make a real attempt to sorting it out properly. But for now I need some sort of function which is good enough to play against an average amateur.
An evaluation function, also known as a heuristic evaluation function or static evaluation function, is a function used by game-playing programs to estimate the value or goodness of a position in the minimax and related algorithms.
An evaluation function is used to heuristically determine the relative value of a positions used in general case when no specialized evaluation or tablebase evaluation is available. In Stockfish it is never applied for positions where king of either side is in check.
The most basic component of an evaluation function is material, obviously. This should be perfectly straightforward, but on its own does not lead to interesting play. The engine has no sense of position at all, and simply reacts to tactical lines. But we will start here:
value = white_material - black_material // calculate delta material
Next we introduce some positional awareness through piece-square tables. For example, this is a such a predefined table for pawns:
pawn_table = {
0, 0, 0, 0, 0, 0, 0, 0,
75, 75, 75, 75, 75, 75, 75, 75,
25, 25, 29, 29, 29, 29, 25, 25,
4, 8, 12, 21, 21, 12, 8, 4,
0, 4, 8, 17, 17, 8, 4, 0,
4, -4, -8, 4, 4, -8, -4, 4,
4, 8, 8,-17,-17, 8, 8, 4,
0, 0, 0, 0, 0, 0, 0, 0
}
Note that this assumes the common centipawn (value of pawn is ~100) value system. For each white pawn we encounter, we index into the table with the pawn's square and add the corresponding value.
for each p in white pawns
value += pawn_table[square(p)]
Note that we can use use a simple calculation to reflect the table when indexing for black pieces. Alternatively you can define separate tables.
For simple evaluation this will work very well and your engine will probably already be playing common openings. However, it's not too hard to make some simple improvements. For example, you can create tables for the opening and the endgame, and interpolate between them using some sort of phase calculation. This is especially effective for kings, where their place shifts from the corners to the middle of the board as the game progresses.
Thus our evaluation function may look something like:
evaluate(position, colour) {
phase = total_pieces / 32 // this is just an example
opening_value += ... // sum of evaluation terms
endgame_value += ...
final_value = phase * opening_value + (1 - phase) * endgame_value
return final_value * sign(colour) // adjust for caller's perspective
}
This type of evaluation, along with quiescence search, should be enough to annihilate most amateurs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With