beginner programmer here, trying to make an app that detects blunders and wanting to learn more about the chess.engine library.
I assume that using the analyse function is a discrete, self-contained process that doesn't rely on cache or memory of previous calls from the engine or anything like that.
If this is the case, why do I get multiple different evaluations when calling analyse multiple times in a script:
import chess
import chess.engine
import os
# Loads board and engine
board = chess.Board("3r3k/pp5p/n1p2rp1/2P2p1n/1P2p3/PBNqP2P/5PP1/R2RB1K1 w - - 0 26")
engine = chess.engine.SimpleEngine.popen_uci(os.getcwd()+'/static/'+'stockfish')
#Sets engine depth constant
engine_depth = 10
# I'm assuming this is how to find the best move - arbitrary as I could have chosen any move in board.legal_moves
best_move = engine.play(board, chess.engine.Limit(depth=engine_depth)).move
# I'm assuming this is how to evaluate the score after a specific move from this position
info = engine.analyse(board, chess.engine.Limit(depth=engine_depth), root_moves=[best_move])
print(info["score"])
# Repeating the analysis call and printing the score 3 more times
info = engine.analyse(board, chess.engine.Limit(depth=engine_depth), root_moves=[best_move])
print(info["score"])
info = engine.analyse(board, chess.engine.Limit(depth=engine_depth), root_moves=[best_move])
print(info["score"])
info = engine.analyse(board, chess.engine.Limit(depth=engine_depth), root_moves=[best_move])
print(info["score"])
engine.quit()
Output:
PovScore(Cp(-21), WHITE)
PovScore(Cp(+2), WHITE)
PovScore(Cp(+19), WHITE)
PovScore(Cp(+63), WHITE)
It occurs for various engine depths above a certain level, but not when depth is low, e.g. up to 3.
It occurs with time as the limit instead of depth.
It occurs with multiple different starting positions.
It occurs with multiple different moves.
It occurs even if I have engine.quit()
and engine = chess.engine.SimpleEngine.popen_uci(os.getcwd()+'/static/'+'stockfish')
in between each call.
The analysis function can't have a random element because when I run the whole script again I get exactly the same scores. It's just that when it's called for the same position more than once in the same script, it gives a different score each time, as if it's using some kind of cache or it's looking even deeper each time.
So where am I going wrong in my understanding of how this works?
EDIT:
If I remove the root_moves
argument (just to simplify things) and then replace:
print(info["score"])
with:
for k, v in info.items():
print(k, v)
I get the following outputs:
string NNUE evaluation using nn-82215d0fd0df.nnue enabled
depth 10
seldepth 13
multipv 1
score PovScore(Cp(+25), WHITE)
nodes 4396
nps 439600
tbhits 0
time 0.01
pv [Move.from_uci('d1d3'), Move.from_uci('e4d3'), Move.from_uci('a1d1'), Move.from_uci('a6c7'), Move.from_uci('c3a4'), Move.from_uci('f6f8'), Move.from_uci('a4b2'), Move.from_uci('h5f6'), Move.from_uci('b2d3'), Move.from_uci('d8d7')]
string NNUE evaluation using nn-82215d0fd0df.nnue enabled
depth 10
seldepth 15
multipv 1
score PovScore(Cp(+55), WHITE)
nodes 4072
nps 290857
tbhits 0
time 0.014
pv [Move.from_uci('d1d3'), Move.from_uci('e4d3'), Move.from_uci('a1d1'), Move.from_uci('a6c7'), Move.from_uci('c3a4'), Move.from_uci('c7b5'), Move.from_uci('a4b2'), Move.from_uci('b5a3'), Move.from_uci('b2d3'), Move.from_uci('a3b5')]
string NNUE evaluation using nn-82215d0fd0df.nnue enabled
depth 10
seldepth 16
multipv 1
score PovScore(Cp(+26), WHITE)
nodes 4514
nps 282125
tbhits 0
time 0.016
pv [Move.from_uci('d1d3'), Move.from_uci('e4d3'), Move.from_uci('a1d1'), Move.from_uci('a6c7'), Move.from_uci('c3a4'), Move.from_uci('c7b5'), Move.from_uci('a4b2'), Move.from_uci('h8g7'), Move.from_uci('b2d3'), Move.from_uci('f6f8')]
string NNUE evaluation using nn-82215d0fd0df.nnue enabled
depth 10
seldepth 12
multipv 1
score PovScore(Cp(+164), WHITE)
nodes 2018
nps 252250
tbhits 0
time 0.008
pv [Move.from_uci('d1d3'), Move.from_uci('d8d3'), Move.from_uci('b3c4'), Move.from_uci('d3d8'), Move.from_uci('c3e2'), Move.from_uci('h8g7'), Move.from_uci('e1c3')]
So it looks like I'm getting different 'seldepths' each time. What is seldepth exactly? I can't find enough info about it in the documentation.