py-stockfish / stockfish

Integrates the Stockfish chess engine with Python (Official fork)
https://py-stockfish.github.io/stockfish/
MIT License
29 stars 8 forks source link

Stockfish crashes on running function get_best_move() [BUG] #49

Closed nIKiTaaaaaaa-coder closed 1 year ago

nIKiTaaaaaaa-coder commented 1 year ago

I am working on a small chess project and I wanted to add AI. I chose stockfish. When I try to run stockfish.get_best_move(), it outputs this:

Traceback (most recent call last):
  File "/Users/nsegrenev/Documents/Python Projects/console_ches.py", line 594, in <module>
    move = stockfish.get_best_move()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/stockfish/models.py", line 338, in get_best_move
    return self._get_best_move_from_sf_popen_process()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/stockfish/models.py", line 358, in _get_best_move_from_sf_popen_process
    text = self._read_line()
           ^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/stockfish/models.py", line 160, in _read_line
    raise StockfishException("The Stockfish process has crashed")
stockfish.models.StockfishException: The Stockfish process has crashed

Here is my system stats

nsegrenev@MacBook-Air-Nikita stockfish % uname -a
Darwin MacBook-Air-Nikita.local 22.5.0 Darwin Kernel Version 22.5.0: Mon Apr 24 20:52:43 PDT 2023; root:xnu-8796.121.2~5/RELEASE_ARM64_T8112 arm64

What can I do?

kieferro commented 1 year ago

Could you try to start stockfish via the command line and input this:

setoption name Debug Log File value setoption name Contempt value 0 setoption name Min Split Depth value 0 setoption name Ponder value false setoption name MultiPV value 1 setoption name Skill Level value 20 setoption name Move Overhead value 10 setoption name Minimum Thinking Time value 20 setoption name Slow Mover value 100 setoption name UCI_Chess960 value false setoption name UCI_LimitStrength value false setoption name UCI_Elo value 1350 setoption name Threads value 1 setoption name Hash value 16 position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 setoption name UCI_ShowWDL value true ucinewgame go depth 15

Also, it would still be helpful to know if you set any special parameters (like depth) or if you just used the default parameters.

nIKiTaaaaaaa-coder commented 1 year ago

Here:


nsegrenev@MacBook-Air-Nikita stockfish % stockfish
Stockfish 16 by the Stockfish developers (see AUTHORS file)
setoption name Debug Log File value
setoption name Contempt value 0
No such option: Contempt
setoption name Min Split Depth value 0
No such option: Min Split Depth
setoption name Ponder value false
setoption name MultiPV value 1
setoption name Skill Level value 20
setoption name Move Overhead value 10
setoption name Minimum Thinking Time value 20
No such option: Minimum Thinking Time
setoption name Slow Mover value 100
setoption name UCI_Chess960 value false
setoption name UCI_LimitStrength value false
setoption name UCI_Elo value 1350
setoption name Threads value 1
setoption name Hash value 16
position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
setoption name UCI_ShowWDL value true
ucinewgame
go depth 15
info string NNUE evaluation using nn-5af11540bbfe.nnue enabled
info depth 1 seldepth 1 multipv 1 score cp 2 wdl 9 984 7 nodes 20 nps 10000 hashfull 0 tbhits 0 time 2 pv g1f3
info depth 2 seldepth 2 multipv 1 score cp 2 wdl 9 984 7 nodes 40 nps 20000 hashfull 0 tbhits 0 time 2 pv g1f3
info depth 3 seldepth 2 multipv 1 score cp 16 wdl 18 979 3 nodes 70 nps 35000 hashfull 0 tbhits 0 time 2 pv c2c3
info depth 4 seldepth 2 multipv 1 score cp 29 wdl 35 963 2 nodes 101 nps 50500 hashfull 0 tbhits 0 time 2 pv e2e4
info depth 5 seldepth 3 multipv 1 score cp 42 wdl 68 931 1 nodes 131 nps 65500 hashfull 0 tbhits 0 time 2 pv e2e4 g8f6
info depth 6 seldepth 4 multipv 1 score cp 59 wdl 143 857 0 nodes 489 nps 122250 hashfull 0 tbhits 0 time 4 pv g1f3 d7d5 d2d4
info depth 7 seldepth 6 multipv 1 score cp 31 wdl 38 960 2 nodes 1560 nps 156000 hashfull 1 tbhits 0 time 10 pv e2e4 d7d5 e4d5 d8d5 g1f3
info depth 8 seldepth 6 multipv 1 score cp 40 wdl 60 939 1 nodes 2105 nps 175416 hashfull 1 tbhits 0 time 12 pv e2e4 d7d5 e4d5 d8d5
info depth 9 seldepth 8 multipv 1 score cp 48 wdl 87 912 1 nodes 4500 nps 204545 hashfull 1 tbhits 0 time 22 pv e2e4 e7e5 g1f3 g8f6 f3e5 f6e4 d2d4 b8c6
info depth 10 seldepth 10 multipv 1 score cp 50 wdl 96 903 1 nodes 7548 nps 235875 hashfull 2 tbhits 0 time 32 pv e2e4 e7e5 g1f3 g8f6 b1c3 d7d6 d2d4
info depth 11 seldepth 12 multipv 1 score cp 44 wdl 74 925 1 nodes 13058 nps 277829 hashfull 3 tbhits 0 time 47 pv e2e4 e7e5 g1f3 g8f6 b1c3 d7d6 d2d4 e5d4 d1d4 b8c6 d4d3 f8e7
info depth 12 seldepth 16 multipv 1 score cp 40 wdl 59 940 1 nodes 35836 nps 347922 hashfull 15 tbhits 0 time 103 pv e2e4 e7e5 g1f3 g8f6 d2d4 f6e4 f3e5 e4f6 f1c4 d7d5
info depth 13 seldepth 18 multipv 1 score cp 43 wdl 69 930 1 nodes 59384 nps 368844 hashfull 26 tbhits 0 time 161 pv e2e4 e7e5 g1f3 g8f6 d2d4 f6e4 f3e5 d7d5 f1d3 f8b4 c2c3 b4d6
info depth 14 seldepth 19 multipv 1 score cp 48 wdl 87 912 1 nodes 73942 nps 377255 hashfull 30 tbhits 0 time 196 pv e2e4 e7e5 g1f3 g8f6 d2d4 f6e4 f1d3 d7d5 f3e5 f8b4 b1d2 e8g8 e1g1 b4d2 c1d2
info depth 15 seldepth 19 multipv 1 score cp 33 wdl 43 956 1 nodes 173344 nps 391295 hashfull 69 tbhits 0 time 443 pv e2e4 c7c5 b1c3 b8c6 g1f3 e7e5 f1c4 f8e7 d2d3 d7d6 e1g1 h7h6 h2h3 g8f6 f3h2 e8g8 f2f4 e5f4 c1f4
bestmove e2e4 ponder c7c5```
kieferro commented 1 year ago

Okay, thanks, that all looks fine to me.

I see that you are using Stockfish 16. That could possibly be related to the problem because we haven't tested much with it yet. Could you maybe try your code with another version of Stockfish as well?

And does the crash happen consistently or only some of the time?

nIKiTaaaaaaa-coder commented 1 year ago

how to install older version?

nIKiTaaaaaaa-coder commented 1 year ago

I see only versions for linux on the official dropbox

kieferro commented 1 year ago

I see only versions for linux on the official dropbox

Yes that's right, sorry. I wasn't aware that there don't seem to be any older versions for Mac. There is also not by chance the possibility to install older versions of packages via brew?

nIKiTaaaaaaa-coder commented 1 year ago

I tried, but I couldn't find. I thought, that linux versions might work too, since Mac OS is some sort of linux too. But they didn't. I tried install ing older versions via brew, but I couldn't get it working. Is there a way to work with stockfish 16, since it is the last stable version?

kieferro commented 1 year ago

Is there a way to work with stockfish 16, since it is the last stable version?

Just so there is no misunderstanding: The wrapper should actually work with all (except maybe the very old) Stockfish versions. So you do not have to downgrade to another version to use it. It would just have been handy to track down the source of the problem. But it really looks like that's not easily possible with homebrew.

I have installed stockfish via homebrew on an Ubuntu installation and had no problems with using the wrapper with it. Could you please share the exact code that lead to the error message?

nIKiTaaaaaaa-coder commented 1 year ago

It's big and messy, but here:

import re
import time
import datetime
from stockfish import Stockfish

COLOR_MODE = True
if COLOR_MODE:
    BOLD_TEXT = "\u001b[1;97m"
    BLACK_BOLD_TEXT = "\u001b[1;30m"
    DARK_GREY_BG = "\u001b[48;5;236m"
    LIGHT_GREY_BG = "\u001b[48;5;246m"
    CLEAR = "\u001b[0m"
else:
    BOLD_TEXT = ""
    BLACK_BOLD_TEXT = ""
    DARK_GREY_BG = ""
    LIGHT_GREY_BG = ""
    CLEAR = ""

KING_W = f"{BOLD_TEXT}♚"
QUEEN_W = f"{BOLD_TEXT}♛"
ROOK_W = f"{BOLD_TEXT}♜"
BISHOP_W = f"{BOLD_TEXT}♝"
KNIGHT_W = f"{BOLD_TEXT}♞"
PAWN_W = f"{BOLD_TEXT}♟"
KING_B = f"{BLACK_BOLD_TEXT}♚"
QUEEN_B = f"{BLACK_BOLD_TEXT}♛"
ROOK_B = f"{BLACK_BOLD_TEXT}♜"
BISHOP_B = f"{BLACK_BOLD_TEXT}♝"
KNIGHT_B = f"{BLACK_BOLD_TEXT}♞"
PAWN_B = f"{BLACK_BOLD_TEXT}♟"

WHITE_FIGURES = [ROOK_W, KNIGHT_W, BISHOP_W, KING_W, QUEEN_W, BISHOP_W, KNIGHT_W, ROOK_W, PAWN_W]
BLACK_FIGURES = [ROOK_B, KNIGHT_B, BISHOP_B, KING_B, QUEEN_B, BISHOP_B, KNIGHT_B, ROOK_B, PAWN_B]
FIGURES = [WHITE_FIGURES, BLACK_FIGURES]

BOARD = [[ROOK_B, KNIGHT_B, BISHOP_B, KING_B, QUEEN_B, BISHOP_B, KNIGHT_B, ROOK_B], [PAWN_B for i in range(8)], list(" "*8), list(" "*8), list(" "*8), list(" "*8), [PAWN_W for i in range(8)], [ROOK_W, KNIGHT_W, BISHOP_W, QUEEN_W, KING_W, BISHOP_W, KNIGHT_W, ROOK_W]]
EATEN = [[], []]

KING_B_MOVED = False
KING_W_MOVED = False
ROOK_W_1_MOVED = False
ROOK_W_2_MOVED = False
ROOK_B_1_MOVED = False
ROOK_B_2_MOVED = False

def print_board(cross = []):
    print(f"{BOLD_TEXT} A B C D E F G H{CLEAR}")
    for y in range(8):
        print(f"{BOLD_TEXT}{y+1}{CLEAR}", end="")
        for x in range(8):
            cross_or_space = " "
            if [x, y] in cross:
                cross_or_space = f"{BOLD_TEXT}X"
            if (x+y%2)%2 == 1:
                print(f"{DARK_GREY_BG}"+BOARD[y][x]+cross_or_space+f"{CLEAR}", end="")
            else:
                print(f"{LIGHT_GREY_BG}"+BOARD[y][x]+cross_or_space+f"{CLEAR}", end="")
        if TIMER:
            if y == 3:
                print(f"{BOLD_TEXT}    {datetime.timedelta(seconds=int(black_time_left))}{CLEAR}", end="")
            elif y==4:
                print(f"{BOLD_TEXT}    {datetime.timedelta(seconds=int(white_time_left))}{CLEAR}", end="")
        print()
def check_win():
    global black_time_left, white_time_left

    if TIMER:
        if black_time_left <= 0:
            return True, "white", "win by time"
        elif white_time_left <= 0:
            return True, "black", "win by time"

    # Check for check
    to_cross_all = []
    for y in range(8):
        for x in range(8):
            where_can_move = []
            cp = -1
            if BOARD[y][x] in WHITE_FIGURES:
                cp = 0
            elif BOARD[y][x] in BLACK_FIGURES:
                cp = 1
            fig_type = None
            if cp >= 0:
                fig_type = ["rook", "knight", "bishop", "king", "queen", "bishop", "knight", "rook", "pawn"][FIGURES[cp].index(BOARD[y][x])]
            if BOARD[y][x] == 0:
                if BOARD[y][x] in WHITE_FIGURES:
                    if y == 6:
                        if BOARD[y-2][x] == " ":
                            where_can_move.append([x, y-2, cp])
                    if BOARD[y-1][x] == " ":
                        where_can_move.append([x, y-1, cp])
                    if x-1 >= 0 and BOARD[y-1][x-1] in FIGURES[(current_player+1)%2]:
                        where_can_move.append([x-1, y-1, cp])
                    if x+1 < 8 and BOARD[y-1][x+1] in FIGURES[(current_player+1)%2]:
                        where_can_move.append([x+1, y-1, cp])
                else:
                    if y == 1:
                        if BOARD[y+2][x] == " ":
                            where_can_move.append([x, y+2, cp])
                    if BOARD[y+1][x] == " ":
                        where_can_move.append([x, y+1, cp])
                    if x-1 >= 0 and BOARD[y+1][x-1] in FIGURES[(current_player+1)%2]:
                        where_can_move.append([x-1, y+1, cp])
                    if x+1 < 8 and BOARD[y+1][x+1] in FIGURES[(current_player+1)%2]:
                        where_can_move.append([x+1, y+1, cp])
            elif fig_type == "king":
                where_can_move.append([x, y+1, cp])
                where_can_move.append([x, y-1, cp])
                where_can_move.append([x+1, y, cp])
                where_can_move.append([x-1, y, cp])
                where_can_move.append([x+1, y+1, cp])
                where_can_move.append([x-1, y+1, cp])
                where_can_move.append([x+1, y-1, cp])
                where_can_move.append([x-1, y-1, cp])
            elif fig_type == "rook":
                # print(123455432123456)
                # print(y+1, 8)
                for i in range(y+1, 8):
                    # print([x, i])
                    where_can_move.append([x, i, cp])
                    if BOARD[i][x] != " ":
                        break
                for i in range(x+1, 8):
                    # print([i, y])
                    where_can_move.append([i, y, cp])
                    if BOARD[y][i] != " ":
                        break
                for i in range(y-1, -1, -1):
                    # print([x, i])
                    where_can_move.append([x, i, cp])
                    if BOARD[i][x] != " ":
                        break
                for i in range(x-1, -1, -1):
                    # print([i, y])
                    where_can_move.append([i, y, cp])
                    if BOARD[y][i] != " ":
                        break
            elif fig_type == "bishop":
                i, j = x+1, y+1
                while i < 8 and j < 8:
                    where_can_move.append([i, j, cp])
                    if BOARD[j][i] != " ":
                        break
                    i+=1
                    j+=1
                i, j = x-1, y-1
                while i >= 0 and j >= 0:
                    where_can_move.append([i, j, cp])
                    if BOARD[j][i] != " ":
                        break
                    i-=1
                    j-=1
                i, j = x-1, y+1
                while i >= 0 and j < 8:
                    where_can_move.append([i, j, cp])
                    if BOARD[j][i] != " ":
                        break
                    i-=1
                    j+=1
                i, j = x+1, y-1
                while i < 8 and j >= 0:
                    where_can_move.append([i, j, cp])
                    if BOARD[j][i] != " ":
                        break
                    i+=1
                    j-=1
            elif fig_type == "queen":
                for i in range(y+1, 8):
                    where_can_move.append([x, i, cp])
                    if BOARD[i][x] != " ":
                        break
                for i in range(x+1, 8):
                    where_can_move.append([i, y, cp])
                    if BOARD[y][i] != " ":
                        break
                for i in range(y-1, -1, -1):
                    where_can_move.append([x, i, cp])
                    if BOARD[i][x] != " ":
                        break
                for i in range(x-1, -1, -1):
                    where_can_move.append([i, y, cp])
                    if BOARD[y][i] != " ":
                        break
                i, j = x+1, y+1
                while i < 8 and j < 8:
                    where_can_move.append([i, j, cp])
                    if BOARD[j][i] != " ":
                        break
                    i+=1
                    j+=1
                i, j = x-1, y-1
                while i >= 0 and j >= 0:
                    where_can_move.append([i, j, cp])
                    if BOARD[j][i] != " ":
                        break
                    i-=1
                    j-=1
                i, j = x-1, y+1
                while i >= 0 and j < 8:
                    where_can_move.append([i, j, cp])
                    if BOARD[j][i] != " ":
                        break
                    i-=1
                    j+=1
                i, j = x+1, y-1
                while i < 8 and j >= 0:
                    where_can_move.append([i, j, cp])
                    if BOARD[j][i] != " ":
                        break
                    i+=1
                    j-=1
            elif fig_type == "knight":
                where_can_move.append([x-1, y-2, cp])
                where_can_move.append([x+1, y-2, cp])
                where_can_move.append([x+2, y-1, cp])
                where_can_move.append([x-2, y-1, cp])
                where_can_move.append([x-2, y+1, cp])
                where_can_move.append([x+2, y+1, cp])
                where_can_move.append([x-1, y+2, cp])
                where_can_move.append([x+1, y+2, cp])
    for x_, y_, cp in where_can_move:
        print(x_, y_)
        if x_ >= 0 and x_ < 8 and y_ >= 0 and y_ < 8 and (BOARD[y_][x_] not in [*FIGURES[cp], FIGURES[(cp+1)%2][3]]):
            to_cross_all.append([x_, y_])
    for x, y in list(set(tuple(map(tuple, to_cross_all)))):
        if BOARD[y][x] == KING_B:
            print(f"{BOLD_TEXT}Black's king is under check!{CLEAR}")
        elif BOARD[y][x] == KING_W:
            print(f"{BOLD_TEXT}White's king is under check!{CLEAR}")

    # Check for checkmate
    test_moves = []
    x, y = -1, -1
    for y_ in range(8):
        for x_ in range(8):
            if BOARD[y_][x_] == KING_W:
                x, y = x_, y_
        if x+y != -2:
            break
    test_moves.append([x, y+1])
    test_moves.append([x, y-1])
    test_moves.append([x+1, y])
    test_moves.append([x-1, y])
    test_moves.append([x+1, y+1])
    test_moves.append([x-1, y+1])
    test_moves.append([x+1, y-1])
    test_moves.append([x-1, y-1])
    if len(test_moves) == 0:
        return True, "white", "checkmate"

    test_moves = []
    x, y = -1, -1
    for y_ in range(8):
        for x_ in range(8):
            if BOARD[y_][x_] == KING_B:
                x, y = x_, y_
        if x+y != -2:
            break
    test_moves.append([x, y+1])
    test_moves.append([x, y-1])
    test_moves.append([x+1, y])
    test_moves.append([x-1, y])
    test_moves.append([x+1, y+1])
    test_moves.append([x-1, y+1])
    test_moves.append([x+1, y-1])
    test_moves.append([x-1, y-1])
    if len(test_moves) == 0:
        return True, "black", "checkmate"

    #Check for draw
    figs_left = []
    for y in range(8):
        for x in range(8):
            if BOARD[y][x] != " ":
                fig = [None, None, None]
                if BOARD[y][x] in FIGURES[0]:
                    fig[0] = "0"
                    fig[1] = ["rook", "knight", "bishop", "king", "queen", "bishop", "knight", "rook", "pawn"][FIGURES[0].index(BOARD[y][x])]
                    fig[2] = str((x+y%2)%2)
                elif BOARD[y][x] in FIGURES[1]:
                    fig[0] = "1"
                    fig[1] = ["rook", "knight", "bishop", "king", "queen", "bishop", "knight", "rook", "pawn"][FIGURES[1].index(BOARD[y][x])]
                    fig[2] = str((x+y%2)%2)
                figs_left.append(fig)

    figs_str = " ".join([" ".join(f) for f in sorted(figs_left)])
    # print(1, figs_str)
    if len(to_cross_all) == 0:
        return True, "draw", "stalemate"
    elif re.search(r"^0 king \d 1 king \d$", figs_str):
        return True, "draw", "dead position (king against king)"
    elif re.search(r"^\d bishop \d 0 king \d 1 king \d$", figs_str):
        return True, "draw", "dead position (king against king and bishop)"
    elif re.search(r"^0 king \d \d knight \d 1 king \d$", figs_str):
        return True, "draw", "dead position (king against king and knight)"
    elif re.search(r"^(0 bishop 1 0 king \d 1 bishop 1 1 king \d)||(0 bishop 0 0 king \d 1 bishop 0 1 king \d)$", figs_str).group(0):
        return True, "draw", "dead position (king and bishop against king and bishop, with both bishops on squares of the same color)"
    return False, None, None

def generate_fen(en_passant="-"):
    global current_player, halfmoves, fullmoves, KING_B_MOVED, KING_W_MOVED, ROOK_W_1_MOVED, ROOK_W_2_MOVED, ROOK_B_1_MOVED, ROOK_B_2_MOVED
    fen = ""

    for i in range(len(BOARD)):
        counter = 0
        for j in range(len(BOARD[i])):
            if BOARD[i][j] == " ":
                counter+=1
            else:
                if counter!=1:
                    fen+=str(counter)
                    counter=0
                fen += "RNBKQBNRPrnbkqbnrp"[(WHITE_FIGURES+BLACK_FIGURES).index(BOARD[i][j])]
        if counter!=1:
            fen+=str(counter)
        fen+="/"
    fen = fen[:-1]
    fen += " "+"wb"[current_player]+" "
    flag=False
    if not KING_W_MOVED and not ROOK_W_2_MOVED and BOARD[0][1]==" " and BOARD[0][2]==" " and BOARD[0][3]==" ":
        fen+="K"
        flag=True
    if not KING_W_MOVED and not ROOK_W_2_MOVED and BOARD[0][5]==" " and BOARD[0][6]==" ":
        fen+="Q"
        flag=True
    if not KING_B_MOVED and not ROOK_B_1_MOVED and BOARD[7][1]==" " and BOARD[7][2]==" " and BOARD[7][3]==" ":
        fen+="k"
        flag=True
    if not KING_B_MOVED and not ROOK_B_2_MOVED and BOARD[0][5]==" " and BOARD[0][6]==" ":
        fen+="q"
        flag=True
    if not flag:
        fen+="-"
    fen+=f" {en_passant} {halfmoves} {fullmoves}"

current_player = 0
DEPTH = 18
THREADS = 1
draw_by_player = False
win, winner, win_type = False, None, None
TIMER = input("Want to turn on timer? (y for yes, and anything else for no) > ")=="y"
PAWN_REVIVE = input("Want make pawns revive figures on edge? (y for yes, and anything else for no) > ")=="y"
ENABLE_AI = True
if ENABLE_AI:
    stockfish = Stockfish(path="/Users/nsegrenev/homebrew/Cellar/stockfish/16/bin/stockfish", depth=DEPTH, parameters={"Threads": THREADS, "Minimum Thinking Time": (30 if TIMER else 0)})
    stockfish.set_fen_position("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
black_time_left, white_time_left = 3600, 3600
halfmoves=0
fullmoves=1
en_passant="-"

while True:
    move_from, move_to = "", ""
    castling=None
    start = time.time()
    # Print stuff
    print(f"{BOLD_TEXT}{['White', 'Black'][current_player]} move!{CLEAR}")
    print_board()
    # Choose figure
    if (ENABLE_AI and current_player == 0) or (not ENABLE_AI):
        while True:
            fig = input("Choose what figure to move (coordinates, for example A1, B2, C3) > ")
            if fig == "DRAW":
                draw_by_player = True
                break
            elif fig == "0-0":
                castling="short"
                break
            elif fig=="0-0-0":
                castling="long"
                break
            try:
                x, y = list("ABCDEFGH").index(fig[0].upper()), int(fig[1])-1
                if BOARD[y][x] == " ":
                    print("There is no figure. Please try again.")
                elif BOARD[y][x] not in FIGURES[current_player]:
                    print("This is not your figure. Please try again.")
            except IndexError:
                print("Invalid input. Please try again.")
            except ValueError:
                print("Invalid input. Please try again.")
            else:
                if BOARD[y][x] in FIGURES[current_player]:
                    break
        if draw_by_player:
            break
        if not castling:
            move_from = fig.lower()
            # Print all possible moves
            fig_type = ["rook", "knight", "bishop", "king", "queen", "bishop", "knight", "rook", "pawn"][FIGURES[current_player].index(BOARD[y][x])]
            # print(f"You've chosen {fig_type}")
            where_can_move = []
            if fig_type == "pawn":
                if current_player == 0:
                    if y == 6:
                        if BOARD[y-2][x] == " ":
                            where_can_move.append([x, y-2])
                    if BOARD[y-1][x] == " ":
                        where_can_move.append([x, y-1])
                    if x-1 >= 0 and BOARD[y-1][x-1] in FIGURES[(current_player+1)%2]:
                        where_can_move.append([x-1, y-1])
                    if x+1 < 8 and BOARD[y-1][x+1] in FIGURES[(current_player+1)%2]:
                        where_can_move.append([x+1, y-1])
                else:
                    if y == 1:
                        if BOARD[y+2][x] == " ":
                            where_can_move.append([x, y+2])
                    if BOARD[y+1][x] == " ":
                        where_can_move.append([x, y+1])
                    if x-1 >= 0 and BOARD[y+1][x-1] in FIGURES[(current_player+1)%2]:
                        where_can_move.append([x-1, y+1])
                    if x+1 < 8 and BOARD[y+1][x+1] in FIGURES[(current_player+1)%2]:
                        where_can_move.append([x+1, y+1])
            elif fig_type == "king":
                if current_player == 0:
                    KING_W_MOVED = True
                else:
                    KING_B_MOVED = False
                where_can_move.append([x, y+1])
                where_can_move.append([x, y-1])
                where_can_move.append([x+1, y])
                where_can_move.append([x-1, y])
                where_can_move.append([x+1, y+1])
                where_can_move.append([x-1, y+1])
                where_can_move.append([x+1, y-1])
                where_can_move.append([x-1, y-1])
            elif fig_type == "rook":
                if current_player == 0:
                    if (x, y) == ():pass
                # print(123455432123456)
                # print(y+1, 8)
                if (x, y) == (0, 0):
                    ROOK_W_1_MOVED = True
                elif (x, y) == (7, 0):
                    ROOK_W_2_MOVED = True
                elif (x, y) == (0, 7):
                    ROOK_B_1_MOVED = True
                elif (x, y) == (7, 7):
                    ROOK_B_2_MOVED = True
                for i in range(y+1, 8):
                    # print([x, i])
                    where_can_move.append([x, i])
                    if BOARD[i][x] != " ":
                        break
                for i in range(x+1, 8):
                    # print([i, y])
                    where_can_move.append([i, y])
                    if BOARD[y][i] != " ":
                        break
                for i in range(y-1, -1, -1):
                    # print([x, i])
                    where_can_move.append([x, i])
                    if BOARD[i][x] != " ":
                        break
                for i in range(x-1, -1, -1):
                    # print([i, y])
                    where_can_move.append([i, y])
                    if BOARD[y][i] != " ":
                        break
            elif fig_type == "bishop":
                i, j = x+1, y+1
                while i < 8 and j < 8:
                    where_can_move.append([i, j])
                    if BOARD[j][i] != " ":
                        break
                    i+=1
                    j+=1
                i, j = x-1, y-1
                while i >= 0 and j >= 0:
                    where_can_move.append([i, j])
                    if BOARD[j][i] != " ":
                        break
                    i-=1
                    j-=1
                i, j = x-1, y+1
                while i >= 0 and j < 8:
                    where_can_move.append([i, j])
                    if BOARD[j][i] != " ":
                        break
                    i-=1
                    j+=1
                i, j = x+1, y-1
                while i < 8 and j >= 0:
                    where_can_move.append([i, j])
                    if BOARD[j][i] != " ":
                        break
                    i+=1
                    j-=1
            elif fig_type == "queen":
                for i in range(y+1, 8):
                    where_can_move.append([x, i])
                    if BOARD[i][x] != " ":
                        break
                for i in range(x+1, 8):
                    where_can_move.append([i, y])
                    if BOARD[y][i] != " ":
                        break
                for i in range(y-1, -1, -1):
                    where_can_move.append([x, i])
                    if BOARD[i][x] != " ":
                        break
                for i in range(x-1, -1, -1):
                    where_can_move.append([i, y])
                    if BOARD[y][i] != " ":
                        break
                i, j = x+1, y+1
                while i < 8 and j < 8:
                    where_can_move.append([i, j])
                    if BOARD[j][i] != " ":
                        break
                    i+=1
                    j+=1
                i, j = x-1, y-1
                while i >= 0 and j >= 0:
                    where_can_move.append([i, j])
                    if BOARD[j][i] != " ":
                        break
                    i-=1
                    j-=1
                i, j = x-1, y+1
                while i >= 0 and j < 8:
                    where_can_move.append([i, j])
                    if BOARD[j][i] != " ":
                        break
                    i-=1
                    j+=1
                i, j = x+1, y-1
                while i < 8 and j >= 0:
                    where_can_move.append([i, j])
                    if BOARD[j][i] != " ":
                        break
                    i+=1
                    j-=1
            elif fig_type == "knight":
                where_can_move.append([x-1, y-2])
                where_can_move.append([x+1, y-2])
                where_can_move.append([x+2, y-1])
                where_can_move.append([x-2, y-1])
                where_can_move.append([x-2, y+1])
                where_can_move.append([x+2, y+1])
                where_can_move.append([x-1, y+2])
                where_can_move.append([x+1, y+2])
            to_cross = []
            # print(where_can_move)
            for x_, y_ in where_can_move:
                if x_ >= 0 and x_ < 8 and y_ >= 0 and y_ < 8 and (BOARD[y_][x_] not in [*FIGURES[current_player], FIGURES[(current_player+1)%2][3]]):
                    to_cross.append([x_, y_])
            if len(to_cross) == 0:
                print("Can't move figure. Please try again.")
                continue
            print_board(to_cross)
            x_old, y_old = x, y
            while True:
                to_move = input("Choose where to move (coordinates, for example A1, B2, C3) > ")
                if to_move == "DRAW":
                    draw_by_player = True
                    break
                try:
                    x, y = list("ABCDEFGH").index(to_move[0].upper()), int(to_move[1])-1
                    if [x, y] not in to_cross:
                        print("Can't move here. Please try again")
                except IndexError:
                    print("Invalid input. Please try again.")
                except ValueError:
                    print("Invalid input. Please try again.")
                else:
                    if [x, y] in to_cross:
                        break
            move_to = to_move.lower()
            if draw_by_player:
                break
            if fig_type == "pawn" and PAWN_REVIVE:
                if (y == 0 and current_player == 0) or (y == 7 and current_player == 1):
                    eaten_not_pawn = [f for f in EATEN[current_player] if f not in [PAWN_W, PAWN_B]]
                    print(" ".join(eaten_not_pawn))
                    print(" ".join([str(i) for i in range(1, len(eaten_not_pawn)+1)]))
                    while True:
                        f = input("Your pawn has reached the opposite edge. Choose what figure to revive (number) > ")
                        if f == "DRAW":
                            draw_by_player = True
                            break
                        try:
                            f = int(f) - 1
                            if f>=0 and f<len(eaten_not_pawn):
                                BOARD[y_old][x_old] = eaten_not_pawn[f]
                                break
                        except ValueError:
                            print("Invalid input. Please try again.")
                        except IndexError:
                            print("Invalid input. Please try again.")
            if draw_by_player:
                break
            halfmoves+=1
            if fig_type == "pawn":
                halfmoves=0
                if abs(y_old-y) == 2:
                    if y_old>y:
                        en_passant="abcdefgh"[x]+str(y_old-1)
                    else:
                        en_passant="abcdefgh"[x]+str(y_old+1)
            if BOARD[y][x] != " ":
                EATEN[(current_player+1)%2].append(BOARD[y][x])
                halfmoves = 0
            BOARD[y_old][x_old], BOARD[y][x] = " ", BOARD[y_old][x_old]
        else:
            if castling == "short":
                if current_player == 0:
                    if not KING_W_MOVED and not ROOK_W_2_MOVED and BOARD[0][5]==" " and BOARD[0][6]==" ":
                        pass #DONT FORGET TO MAKE CASTLING
                else:
                    if not KING_B_MOVED and not ROOK_B_2_MOVED and BOARD[0][5]==" " and BOARD[0][6]==" ":
                        pass #DONT FORGET TO MAKE CASTLING
            elif castling == "long":
                if current_player == 1:
                    if not KING_W_MOVED and not ROOK_W_2_MOVED and BOARD[0][1]==" " and BOARD[0][2]==" " and BOARD[0][3]==" ":
                        pass #DONT FORGET TO MAKE CASTLING
                else:
                    if not KING_B_MOVED and not ROOK_B_1_MOVED and BOARD[7][1]==" " and BOARD[7][2]==" " and BOARD[7][3]==" ":
                        pass #DONT FORGET TO MAKE CASTLING

        # if ENABLE_AI:
            # stockfish.make_moves_from_current_position([move_from+move_to])
    else:
        stockfish.set_fen_position(generate_fen(en_passant))
        if TIMER:
            move = stockfish.get_best_move(wtime=white_time_left*1000, btime=black_time_left*1000)
        else:
            move = stockfish.get_best_move()
        f, t = move[:2], move[2:]
        x1, y1 = list("ABCDEFGH").index(f[0].upper()), int(f[1])-1
        x2, y2 = list("ABCDEFGH").index(t[0].upper()), int(t[1])-1
        if BOARD[y1][x1] in WHITE_FIGURES:
            print("WHITE")
        else:
            print("BLACK")
    # Check for win
    win, winner, win_type = check_win()
    if win:
        break
    elapsed = time.time()-start
    if current_player==0:
        white_time_left -= elapsed
    else:
        black_time_left -= elapsed
        fullmoves += 1
    halfmoves += 1
    # Switch player
    current_player += 1
    current_player %= 2

if winner == "black":
    print(f"{BOLD_TEXT}Black win! {win_type.capitalize()}!{CLEAR}")
elif winner == "white":
    print(f"{BOLD_TEXT}White win! {win_type.capitalize()}!{CLEAR}")
elif draw_by_player:
    print(f"{BOLD_TEXT}Draw! Aborted by player!{CLEAR}")
else:
    print(f"{BOLD_TEXT}Draw!  {win_type.capitalize()}!{CLEAR}")
nIKiTaaaaaaa-coder commented 1 year ago

To be exact, stockfish is used in lines 627-639 and 348-350

kieferro commented 1 year ago

Thanks. I can reproduce the problem on my ubuntu setup when I input y, y, H7, H5. That makes it way easier to investigate the issue.

kieferro commented 1 year ago

Your code has a bug: The generate_fen function returns nothing. Therefore the FEN is set to None and this causes the engine to crash.

nIKiTaaaaaaa-coder commented 1 year ago

Sorry, my bad.