簡體   English   中英

如何在蟒蛇國際象棋中獲得白色的獲勝機會

[英]How to get the winning chances of white in python-chess

所以我開始創建一個多人國際象棋游戲。 現在,因為它是一個圖形用戶界面,所以我在左邊有棋盤,在右邊有一個分析區。

現在,我希望我的分析區域顯示用戶的獲勝機會。

假設有一個正方形塊,里面有兩個矩形。 現在,它們都代表 50-50 的機會。 每次移動后,我想用當前的機會更新它。 那么我怎樣才能得到一個呢?

我可以返回一個Cp類,但它顯示了機會的准確性(我猜)。

如果有人玩過 chess.com,我想你會明白我想得到什么 :D

(1) 您可以為支持 wdl 信息的引擎嘗試此操作。

"""
* Install python
* Install python-chess
    pip install chess
"""


import chess
import chess.engine


def analyze(engine_file, threads, hash_mb, fen, movetime_sec, max_depth):
    """
    Analyze position fen with the engine_file and stream the winning chances of both sides.
    The engine should support the wdl info.
    """
    engine = chess.engine.SimpleEngine.popen_uci(engine_file)

    # Set threads and hash engine options.
    engine.configure({'Threads': threads})
    engine.configure({'Hash': hash_mb})

    limit = chess.engine.Limit(time=movetime_sec, depth=max_depth)
    board = chess.Board(fen, chess960=False)
    stm = board.turn  # stm is Side To Move

    # Get engine analysis info while it is analyzing the position.
    with engine.analysis(board, limit=limit) as analysis:
        for info in analysis:
            eng_score = info.get("score")

            if eng_score is not None:
                wdl = eng_score.wdl()  # win/draw/loss info point of view is stm
                wins, draws, losses = wdl[0], wdl[1], wdl[2]

                score = wins + draws/2
                total = wins + draws + losses

                score_rate = score / total
                win_rate = wins / total
                draw_rate = draws / total
                loss_rate = losses / total
                
                white_winning_chances = win_rate if stm==chess.WHITE else loss_rate
                black_winning_chances = win_rate if stm==chess.BLACK else loss_rate

                white_score_rate = score_rate if stm==chess.WHITE else 1 - score_rate
                black_score_rate = score_rate if stm==chess.BLACK else 1 - score_rate

                # Show info.
                print(f'white_winning_chances: {100 * white_winning_chances:0.2f}%, white_score_rate: {100 * white_score_rate:0.2f}%, white_draw_rate: {100 * draw_rate:0.2f}%')
                print(f'black_winning_chances: {100 * black_winning_chances:0.2f}%, black_score_rate: {100 * black_score_rate:0.2f}%, black_draw_rate: {100 * draw_rate:0.2f}%')

    engine.quit()


def main():
    engine_file = 'F:/Chess/Engines/stockfish/sf14/sf14.exe'
    fen = 'rnbqkb1r/1p2pppp/p2p1n2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 0 6'  # sicilian opening
    movetime_sec = 5
    max_depth = 24
    threads = 1
    hash_mb = 64
    
    analyze(engine_file, threads, hash_mb, fen, movetime_sec, max_depth)


if __name__ == "__main__":
    main()

輸出:

...

white_winning_chances: 18.20%, white_score_rate: 57.25%, white_draw_rate: 78.10%
black_winning_chances: 3.70%, black_score_rate: 42.75%, black_draw_rate: 78.10%
white_winning_chances: 20.60%, white_score_rate: 58.70%, white_draw_rate: 76.20%
black_winning_chances: 3.20%, black_score_rate: 41.30%, black_draw_rate: 76.20%
white_winning_chances: 19.10%, white_score_rate: 57.80%, white_draw_rate: 77.40%
black_winning_chances: 3.50%, black_score_rate: 42.20%, black_draw_rate: 77.40%
white_winning_chances: 19.10%, white_score_rate: 57.80%, white_draw_rate: 77.40%
black_winning_chances: 3.50%, black_score_rate: 42.20%, black_draw_rate: 77.40%

(2) 對於不支持wdl的引擎或者你想用分數來計算它的獲勝概率。

import chess
import chess.engine


MATE_SCORE = 32000


def winning_probability(cp):
    """
    Use a sigmoid or logistic function to map the engine score cp into [0 to 1] winning probability.
    Technically winning probability is like score rate because the game of chess has draw results.
    So winning probability is like (num_wins + num_draw/2)/total_games.

    cp is a score in centipawn unit.

    Ref: https://www.chessprogramming.org/Pawn_Advantage,_Win_Percentage,_and_Elo
    """
    # K is a factor to scale the winning probability, if K is low the winning probability is high.
    # Stronger engine generally has a lower K value that is if stronger engine has an advantage of
    # 75 centipawn, while a weaker engine has an advantage of 75 centipawn too, it is the stronger
    # engine that has a higher chance to win the game.
    K = 4  

    p = cp/100  # convert centipawn to pawn unit

    return 1 / (1 + 10 ** (-p/K))


def analyze(engine_file, threads, hash_mb, fen, movetime_sec, max_depth):
    """
    Analyze position fen with the engine_file and stream the score and rate.
    """
    engine = chess.engine.SimpleEngine.popen_uci(engine_file)

    # Set threads and hash engine options.
    engine.configure({'Threads': threads})
    engine.configure({'Hash': hash_mb})

    limit = chess.engine.Limit(time=movetime_sec, depth=max_depth)
    board = chess.Board(fen, chess960=False)

    # Get engine analysis info while it is analyzing the position.
    with engine.analysis(board, limit=limit) as analysis:
        for info in analysis:
            eng_score = info.get("score")

            if eng_score is not None:
                score = eng_score.relative.score(mate_score=MATE_SCORE)  # score is in centipawn with side POV(Point Of View)
                print(f'score: {score}, side to move score rate: {100 * winning_probability(score):0.2f}%')

    engine.quit()


def main():
    engine_file = 'F:/Chess/Engines/stockfish/sf14/sf14.exe'
    fen = 'rnbqkb1r/1p2pppp/p2p1n2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 0 6'  # sicilian opening
    movetime_sec = 5
    max_depth = 24
    threads = 1
    hash_mb = 64
    
    analyze(engine_file, threads, hash_mb, fen, movetime_sec, max_depth)


if __name__ == "__main__":
    main()

輸出:

score: 41, side to move score rate: 55.87%
score: 45, side to move score rate: 56.44%
score: 53, side to move score rate: 57.57%
score: 48, side to move score rate: 56.86%
score: 48, side to move score rate: 56.86%

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM