0

初学者程序员在这里,尝试制作一个检测错误的应用程序,并希望了解有关 chess.engine 库的更多信息。

我假设使用分析函数是一个离散的、自包含的过程,它不依赖于引擎先前调用的缓存或内存或类似的东西。

如果是这种情况,为什么在脚本中多次调用分析时会得到多个不同的评估:

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()

输出:

PovScore(Cp(-21), WHITE)
PovScore(Cp(+2), WHITE)
PovScore(Cp(+19), WHITE)
PovScore(Cp(+63), WHITE)

它发生在一定水平以上的各种发动机深度,但在深度较低时不会发生,例如高达 3。
它以时间而不是深度作为限制发生。
它发生在多个不同的起始位置。
它发生在多个不同的动作中。
即使我在每次通话之间都有engine.quit(),也会发生这种情况。engine = chess.engine.SimpleEngine.popen_uci(os.getcwd()+'/static/'+'stockfish')

分析函数不能有随机元素,因为当我再次运行整个脚本时,我得到完全相同的分数。只是当它在同一个脚本中多次调用同一个位置时,它每次都会给出不同的分数,好像它正在使用某种缓存或者每次它看起来更深。

那么我对它的工作原理的理解哪里出错了?

编辑:

如果我删除root_moves参数(只是为了简化事情)然后替换:

print(info["score"])

和:

for k, v in info.items():
    print(k, v)

我得到以下输出:

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')]

所以看起来我每次都得到不同的“seldepths”。什么是seldepth?我在文档中找不到足够的信息。

4

1 回答 1

1

Stockfish 对于具有节点深度限制、状态和选项相等的单线程分析是确定性的。

引擎状态主要是哈希表(以及可能加载的 Syzygy 表库)。因此,您的第二次分析将利用第一次运行的哈希表。第三次运行将重用第二次运行的哈希表结果,依此类推。

通常重用哈希表结果是可取的并且可以提高强度,但是有一种方法可以重置引擎状态,清除哈希表。

在 UCI 协议中,这是通过发送提示来完成的:

ucinewgame

在 python-chess 中,这是通过使用game密钥自动管理的。

engine.analyse(..., game="key1")
engine.analyse(..., game="key1")
engine.analyse(..., game="key2")  # will clear previous state
engine.play(..., game="key2")
engine.analyse(..., game="key1")  # will clear previous state

键可以是任何东西,特别object()是不等于任何其他对象,因此总是会清除哈希表。


import chess
import chess.engine

board = chess.Board("3r3k/pp5p/n1p2rp1/2P2p1n/1P2p3/PBNqP2P/5PP1/R2RB1K1 w - - 0 26")
engine = chess.engine.SimpleEngine.popen_uci("stockfish")
engine_depth = 10

best_move = engine.play(board, chess.engine.Limit(depth=engine_depth), game=object()).move

info = engine.analyse(board, chess.engine.Limit(depth=engine_depth), game=object(), root_moves=[best_move])
print(info["score"])

info = engine.analyse(board, chess.engine.Limit(depth=engine_depth), game=object(), root_moves=[best_move])
print(info["score"])

info = engine.analyse(board, chess.engine.Limit(depth=engine_depth), game=object(), root_moves=[best_move])
print(info["score"])

info = engine.analyse(board, chess.engine.Limit(depth=engine_depth), game=object(), root_moves=[best_move])
print(info["score"])

engine.quit()
PovScore(Cp(+35), WHITE)
PovScore(Cp(+35), WHITE)
PovScore(Cp(+35), WHITE)
PovScore(Cp(+35), WHITE)
于 2021-02-17T22:52:25.270 回答