limiting stockfish evaluation time

572 views Asked by At

I am trying to get the evaluations for a series of fen positions using the Python stockfish library. When the solution is mate in x, my code runs quickly. When the solution is x centipawns it runs for a very long time. How do I get stockfish to limit the amount of time it has to think about the evaluation? Here's my code:

fish = Stockfish()
evals = []
fen = 'r1bqk2r/pp1pbppp/2n1pn2/2p5/2B1N3/4PN2/PPPP1PPP/R1BQ1RK1 b kq - 1 1'
fish.set_fen_position(fen)
fish.get_evaluation()
2

There are 2 answers

0
ferdy On

I looked at the code and getting the score using time is not supported at the moment.

I created a function where you can control the time limit. The function will return score in cp and mate as well as the bestmove.

Code

from stockfish import Stockfish


VALUE_MATE = 32000


def mate_to_value(mate: int) -> int:
    """
    Convert mate number to value.
    """
    if mate > 0:
        v = VALUE_MATE - 2*mate + 1
    else:
        v = -VALUE_MATE - 2*mate

    return v


def my_get_evaluation(fish: Stockfish, fen: str, timems: int):
    """
    Evaluate the fen with fish at a given timems.
    Returns a dict of score {'cp': '49', 'mate': None} and move.
    """
    score = {}
    bestmove = '0000'

    fish.set_fen_position(fen)
    fish.get_best_move_time(timems)

    search_info = fish.info
    bestmove = search_info.split(' pv ')[1].split()[0]

    if 'score cp ' in search_info:
        score_cp = search_info.split('score cp ')[1].split()[0]
        score.update({'cp': int(score_cp), 'mate': None})
    elif 'score mate ' in search_info:
        score_mate = search_info.split('score mate ')[1].split()[0]
        score_cp = mate_to_value(int(score_mate))
        score.update({'cp': int(score_cp), 'mate': int(score_mate)})

    return score, bestmove

Sample application

def myprocess():
    evals = []
    only_score_cp = []
    bestmoves = []

    timems = 5000
    fens = [
        'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
        '1k6/7Q/2K5/8/8/8/8/8 w - - 0 1',
        '1k6/7Q/1K6/8/8/8/8/8 b - - 0 1'
    ]
    fish = Stockfish(r'F:\Chess\Engines\stockfish\sf14\sf14.exe')

    for fen in fens:
        score, bm = my_get_evaluation(fish, fen, timems)
        evals.append(score)
        bestmoves.append(bm)
        only_score_cp.append(score['cp'])

    for e in evals:
        print(e)
    print()

    for bm in bestmoves:
        print(bm)
    print()

    for s in only_score_cp:
        print(s)
    print()

    for f, m, e in zip(fens, bestmoves, evals):
        print(f'fen: {f}, move: {m}, score: {e}')


# Start
myprocess()

Output

{'cp': 49, 'mate': None}
{'cp': 31999, 'mate': 1}
{'cp': -31998, 'mate': -1}

e2e4
h7b7
b8c8

49
31999
-31998

fen: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1, move: e2e4, score: {'cp': 49, 'mate': None}
fen: 1k6/7Q/2K5/8/8/8/8/8 w - - 0 1, move: h7b7, score: {'cp': 31999, 'mate': 1}
fen: 1k6/7Q/1K6/8/8/8/8/8 b - - 0 1, move: b8c8, score: {'cp': -31998, 'mate': -1}
0
LittleCoder On

You can use the python-chesslibrary ($ pip instep python-chess) and simply do that :

import chess
import chess.engine
engine = chess.engine.SimpleEngine.popen_uci("your/stockfish/path/here.exe")
fen = 'r1bqk2r/pp1pbppp/2n1pn2/2p5/2B1N3/4PN2/PPPP1PPP/R1BQ1RK1 b kq - 1 1'
board = chess.Board(fen)
evaluation = chess.engine.Limit(time=1))['score']
print(evaluation)