From 9a287fe6480f1dec4459c5ce948317292fc93511 Mon Sep 17 00:00:00 2001 From: luk3k Date: Thu, 25 Jan 2024 11:29:29 +0100 Subject: [PATCH] added probabilistic stockfish simulation to engine --- engine.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ main.py | 16 ++++++++++++++++ requirements.txt | 3 ++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/engine.py b/engine.py index db50503..0051260 100644 --- a/engine.py +++ b/engine.py @@ -1,6 +1,9 @@ import chess import chess.engine import random +import eval +import numpy as np +from stockfish import Stockfish def pick_move(board: chess.Board) -> chess.Move | None: @@ -32,3 +35,46 @@ def simulate_game(board: chess.Board, move: chess.Move, depth: int): board.push(r.move) engine.quit() + + +def simulate_stockfish_prob(board: chess.Board, move: chess.Move, games: int = 10, depth: int = 10) -> (float, float): + """ + Simulate a game using + :param board: chess board + :param move: chosen move + :param games: number of games that should be simulated after playing the move + :param depth: simulation depth per game + :return: + """ + board.push(move) + copied_board = board.copy() + scores = [] + + stockfish = Stockfish("./stockfish/stockfish-ubuntu-x86-64-avx2", depth=2, parameters={"Threads": 8, "Hash": 2048}) + stockfish.set_elo_rating(1200) + stockfish.set_fen_position(board.fen()) + + def reset_game(): + nonlocal scores, copied_board, board + score = eval.score_stockfish(copied_board).white().score(mate_score=100_000) + scores.append(score) + copied_board = board.copy() + stockfish.set_fen_position(board.fen()) + + for _ in range(games): + for d in range(depth): + if copied_board.is_game_over() or d == depth - 1: + reset_game() + break + + if d == depth - 1: + reset_game() + + top_moves = stockfish.get_top_moves(3) + chosen_move = random.choice(top_moves)['Move'] + stockfish.make_moves_from_current_position([chosen_move]) + copied_board.push(chess.Move.from_uci(chosen_move)) + + print(scores) + # TODO: return distribution here? + return np.array(scores).mean(), np.array(scores).std() diff --git a/main.py b/main.py index e3b501d..5171f16 100644 --- a/main.py +++ b/main.py @@ -29,6 +29,21 @@ def test_stockfish(): analyze_results(sorted_moves) +def test_stockfish_prob(): + fools_mate = "rnbqkbnr/pppp1ppp/4p3/8/5PP1/8/PPPPP2P/RNBQKBNR b KQkq f3 0 2" + board = chess.Board(fools_mate) + moves = {} + untried_moves = list(board.legal_moves) + for move in untried_moves: + mean, std = engine.simulate_stockfish_prob(board, move, 10, 4) + moves[move] = (mean, std) + board = chess.Board(fools_mate) + + sorted_moves = dict(sorted(moves.items(), key=lambda x: x[0].uci())) + for m, s in sorted_moves.items(): + print(f"move '{m.uci()}' (prob_stockfish): mean={s[0]}, std={s[1]}") + + def analyze_results(moves: dict): for m, b in moves.items(): manual_score = eval.score_manual(b) @@ -39,6 +54,7 @@ def analyze_results(moves: dict): def main(): test_mcts() test_stockfish() + test_stockfish_prob() if __name__ == '__main__': diff --git a/requirements.txt b/requirements.txt index 68b140b..b83defa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ chess==1.10.0 -numpy==1.26.3 \ No newline at end of file +numpy==1.26.3 +stockfish==3.28.0 \ No newline at end of file