class Engine: def __init__(self, skill_level): parameters = { "Write Debug Log": "false", "Contempt": 0, "Min Split Depth": 0, "Threads": 1, "Ponder": "false", "Hash": 16, "MultiPV": 1, "Skill Level": skill_level, "Move Overhead": 30, "Minimum Thinking Time": 20, "Slow Mover": 80, "UCI_Chess960": "false", } self.engine = Stockfish("resources/stockfish.exe", parameters=parameters) self.engine.set_depth(ENGINE_DEPTH) def set_position(self, fen): self.engine.set_fen_position(fen) def get_move(self, time): return self.engine.get_best_move_time(time)
class Moves: def __init__(self): self.best_move = '' self.stockfish = Stockfish( "stockfish_14_linux_x64_avx2/stockfish_14_x64_avx2") self.positions2 = "" self.pos_temp = 0 self.curr_position = (Fen().start_position_list()).copy() def current_position(self): return self.curr_position def change_position(self, position): start_pos = position[0:2].lower() stop_pos = position[2:4].lower() for key, value in self.curr_position.items(): if key == start_pos: moved_obj = value self.curr_position[start_pos] = None self.curr_position[stop_pos] = moved_obj return self.curr_position def curr_fen(self): self.positions2 = '' for ix, value in enumerate(self.curr_position.values()): # import ipdb # ipdb.set_trace() if ix % 8 == 0 and ix != 0: if self.pos_temp > 0: self.positions2 += str(self.pos_temp) self.positions2 += "/" self.pos_temp = 0 if not value: self.pos_temp += 1 else: if self.pos_temp > 0: self.positions2 += str(self.pos_temp) self.pos_temp = 0 self.positions2 += value print(self.positions2) return self.positions2 + ' b KQkq - 0 1' def stock_best(self): self.stockfish.set_fen_position(self.curr_fen()) self.best_move = self.stockfish.get_best_move_time(10) return self.best_move
class StockfishPlayer: def __init__(self, game, level): self.game = game self.engine = Stockfish('engines/stockfish', parameters={ "Threads": 4, "Skill Level": level }) def play(self, board): fen = board.fen() self.engine.set_fen_position(fen) move_uci = chess.Move.from_uci(self.engine.get_best_move_time(100)) if move_uci not in list(board.legal_moves): log.error("Wrong move chosen by Stockfish! Check code") move_uci = random.choice(list(board.legal_moves)) action = move_uci.from_square * 64 + move_uci.to_square return action
def get_from_to_move(maxtrix, image): move = input("Чей ход?[w/b]: ").lower() board = chess.Board(Detector.mat_to_fen(matrix, move)) fen = board.fen() stockfish = Stockfish( "./Engines/stockfish_13_win_x64/stockfish_13_win_x64.exe", parameters={ "Threads": os.cpu_count(), "Minimum Thinking Time": 30 }) stockfish.set_fen_position(fen) best_move = stockfish.get_best_move_time(1000) print("best move", best_move) x1, y1, x2, y2 = Detector.get_from_to(best_move, move) # print(x1, y1, x2, y2) cv2.rectangle(image, (x1, y1), (x1 + 100, y1 + 100), (0, 0, 255), 2) cv2.rectangle(image, (x2, y2), (x2 + 100, y2 + 100), (255, 0, 0), 2)
def main(player1="Player 1", player2="Player 2", mode="STANDARD", bot_bool=False, bot_difficulty=6): # resetting the variables in the .json file# json_file = open(r'components\constants.json', 'r') json_content = json.load(json_file) json_content["round_int"] = 0 json_file.close() json_file = open(r'components\constants.json', 'w') json_file.writelines(json.dumps(json_content)) json_file.close() Pieces.white_is_checked = False Pieces.black_is_checked = False Pieces.checking_piece = None #initiating pygame# pygame.init() player1 = "Spieler 1" if player1 == "" else player1 player2 = "Spieler 2" if player2 == "" else player2 #Constants# BLACK = (0, 0, 0) GREY = (50, 50, 50) WHITE = (255, 255, 255) BG_COLOR_1 = (0, 152, 163) BG_COLOR_2 = (2, 112, 120) #reading the constants from the json file# json_file = open(os.getcwd() + r"\components\constants.json", "r") json_content = json.load(json_file) round_int = json_content["round_int"] tile_size = json_content["tile_size"] anchor_point_s = (json_content["anchor_point_s_x"] * tile_size, json_content["anchor_point_s_y"] * tile_size) anchor_point_h = (json_content["anchor_point_h_x"] * tile_size, json_content["anchor_point_h_y"] * tile_size) anchor_point_hud = (json_content["anchor_point_hud_x"] * tile_size, json_content["anchor_point_hud_y"] * tile_size) json_file.close() #setting up the variables for a new and fresh game# screen_size = (11 * tile_size, 11 * tile_size) font = pygame.font.SysFont("DejaVu Sans", int(tile_size * 0.2)) font_titles = pygame.font.SysFont("DejaVu Sans", int(tile_size * 0.25)) go = True timer = Clock(time=5) #creating the surfaces# screen = pygame.display.set_mode(screen_size, 0, 0) s = pygame.Surface((8 * tile_size, 8 * tile_size)) hud = pygame.Surface((10.25 * tile_size, 2 * tile_size)) p1 = pygame.Surface((3 * tile_size, 1.5 * tile_size)) p2 = pygame.Surface((3 * tile_size, 1.5 * tile_size)) h = Hud((2 * tile_size, 8 * tile_size)) screen.fill(BG_COLOR_1) hud.fill(BG_COLOR_2) h.fill(BG_COLOR_2) h.print(pos=(0.6 * tile_size, 20), label='Spielhistorie', font=font) #window caption# pygame.display.set_caption("Chess") #creating a clock for the ingame ticks# clock = pygame.time.Clock() #creating the board on the subsurface# board = Board(master=s, width=8, height=8, tile_size=tile_size, color_a=(245, 216, 188), color_b=(176, 142, 109), color_t1=(240, 230, 221), color_t2=(201, 181, 163), anchor_point=anchor_point_s) #loading the images for the pieces# images = { "white_pawn_img": pygame.image.load(r'assets/white_pawn.png'), "white_rook_img": pygame.image.load(r'assets/white_rook.png'), "white_knight_img": pygame.image.load(r'assets/white_knight.png'), "white_bishop_img": pygame.image.load(r'assets/white_bishop.png'), "white_queen_img": pygame.image.load(r'assets/white_queen.png'), "white_king_img": pygame.image.load(r'assets/white_king.png'), "black_pawn_img": pygame.image.load(r'assets/black_pawn.png'), "black_rook_img": pygame.image.load(r'assets/black_rook.png'), "black_knight_img": pygame.image.load(r'assets/black_knight.png'), "black_bishop_img": pygame.image.load(r'assets/black_bishop.png'), "black_queen_img": pygame.image.load(r'assets/black_queen.png'), "black_king_img": pygame.image.load(r'assets/black_king.png') } #loading the icons for the buttons# quit_icon = pygame.image.load(r'assets/quit.png') takeback_icon = pygame.image.load(r'assets/takeback.png') resign_icon = pygame.image.load(r'assets/resign_flag.png') test_icon = pygame.image.load(r'assets/lightbulb.png') #creating the board build_board(mode, s, images) #creating the chessbot based on .json parameters bot = Stockfish(b'components\stockfish_20011801_x64.exe') bot.set_skill_level(bot_difficulty) quit_button = Button(x=8.5 * tile_size, y=0.4 * tile_size, w=int(0.6 * tile_size), h=int(0.6 * tile_size), color_b=BLACK, color_in=GREY, color_t=WHITE, command=quit, icon=quit_icon, imaginary_x=anchor_point_hud[0], imaginary_y=anchor_point_hud[1]) resign_button = Button(x=9.2 * tile_size, y=0.4 * tile_size, w=int(0.6 * tile_size), h=int(0.6 * tile_size), color_b=BLACK, color_in=GREY, color_t=WHITE, command=lambda: [decideWhoLost(round_int)], icon=resign_icon, imaginary_x=anchor_point_hud[0], imaginary_y=anchor_point_hud[1]) test_zone_button = Testmode_Button( x=9.2 * tile_size, y=0.4 * tile_size + 0.74 * tile_size, w=int(0.6 * tile_size), h=int(0.6 * tile_size), color_b=BLACK, color_in=GREY, color_t=WHITE, command1=lambda: [ Board.change_testmode(), #Pieces.change_ignore_me_standard(), Pieces.crop_move_done(), Pieces.kill_board(), build_board(mode, s, images), Pieces.build_from_list(screen=s), Pieces.set_round(Pieces.round_safe) ], command2=lambda: [ Board.change_testmode(), #Pieces.change_ignore_me_standard(), Pieces.safe_round() ], icon=test_icon, imaginary_x=anchor_point_hud[0], imaginary_y=anchor_point_hud[1], deaf=False) if bot_bool: command = lambda: [ takeback(board, s, takeback_button), takeback(board, s, takeback_button) ] else: command = lambda: [takeback(board, s, takeback_button)] takeback_button = Button(x=8.5 * tile_size, y=0.4 * tile_size + 0.74 * tile_size, w=int(0.6 * tile_size), h=int(0.6 * tile_size), color_b=BLACK, color_in=GREY, color_t=WHITE, command=command, icon=takeback_icon, imaginary_x=anchor_point_hud[0], imaginary_y=anchor_point_hud[1]) start_sound = mixer.Sound("assets/sounds/board-start.mp3") start_sound.play() #the mainloop# while go: #setting the framerate# clock.tick(60) #refreshing the round counter# json_file = open(os.getcwd() + r"\components\constants.json", "r") json_content = json.load(json_file) round_int = json_content["round_int"] json_file.close() #drawing the board# # if not Board.game_over: board.draw_board() #updating the bot with the new game state# bot.set_fen_position(Pieces.give_FEN()) #detecting, if the game is over, or not if not Board.game_over: Pieces.detectingCheck() Board.game_over = Pieces.detectGameOver(round_int=round_int) #end the game if the game is over# if Board.game_over or Board.resign_w or Board.resign_b: if Pieces.white_is_checked or Board.resign_w: board.end_screen('BLACK', s) elif Pieces.black_is_checked or Board.resign_b: board.end_screen('WHITE', s) else: board.end_screen('STALEMATE', s) takeback_button.active = False resign_button.active = False test_zone_button.active = False #checking if a pawn is promotable# for pawn in Pieces.all_pieces_list: if 'Pawn-B' in pawn.name and pawn.y == 7 * tile_size or 'Pawn-W' in pawn.name and pawn.y == 0 * tile_size: pawn.promotion() Pieces.detectingCheck() #highlighting the checked king# if Pieces.white_is_checked: for king in Pieces.all_pieces_list: if isinstance(king, Kings) and king.farbe == WHITE: board.check(king_pos=(king.x, king.y)) #highlighting the checked king# elif Pieces.black_is_checked: for king in Pieces.all_pieces_list: if isinstance(king, Kings) and king.farbe == BLACK: board.check(king_pos=(king.x, king.y)) #drawing all the pieces# # if not Board.game_over: for pieces in Pieces.all_pieces_list: pieces.draw(screen) #updating the mainsurface# pygame.display.update() #clearing the Subsurfaces# p1.fill(BG_COLOR_1) p2.fill(BG_COLOR_1) hud.fill(BG_COLOR_2) #refresh the time of the timers# timer.refreshTime() #creating the labels to be printed on the subsurfaces# Player_1_label = font_titles.render(player1, 1, BLACK) Player_2_label = font_titles.render(player2, 1, BLACK) timer_label = font_titles.render(timer.getTime(), 1, BLACK) #printing the labes on the subsurfaces# p1.blit(Player_1_label, (p1.get_width() / 2 - Player_1_label.get_width() / 2, 0)) p2.blit(Player_2_label, (p2.get_width() / 2 - Player_2_label.get_width() / 2, 0)) #creating the history h.fill(BG_COLOR_2) h.print((0.31 * tile_size, 20), 'Spielhistorie', font) for i in range(len(Pieces.moves_done)): fac_50 = 5 / 7 * tile_size fac_20 = 2 / 7 * tile_size h.print(pos=((i % 2) * fac_50 + fac_20, (i // 2) * fac_20 + 2 * fac_20), label=Pieces.moves_done[i], font=font) #showing the taken pieces# Pieces.taken_pieces.sort(key=lambda x: x.value, reverse=False) white_loss = [[], []] black_loss = [[], []] for piece in Pieces.taken_pieces: if piece.farbe == (0, 0, 0): if len(black_loss[0]) < 8: black_loss[0].append(piece) else: black_loss[1].append(piece) elif piece.farbe == WHITE: if len(white_loss[0]) < 8: white_loss[0].append(piece) else: white_loss[1].append(piece) for line in black_loss: for piece in line: p1.blit( pygame.transform.scale(piece.image, (tile_size // 3, tile_size // 3)), ((line.index(piece) * 11 / 32 + 6 / 40) * tile_size, (black_loss.index(line) + 1) * 0.5 * tile_size)) for line in white_loss: for piece in line: p2.blit( pygame.transform.scale(piece.image, (tile_size // 3, tile_size // 3)), ((line.index(piece) * 11 / 32 + 6 / 40) * tile_size, (white_loss.index(line) + 1) * 0.5 * tile_size)) value_white = 0 value_black = 0 for piece in Pieces.taken_pieces: if piece.farbe == (0, 0, 0): value_black += piece.value elif piece.farbe == WHITE: value_white += piece.value label = font.render('+' + str(abs(int(value_white - value_black))), True, BLACK) if int(value_white - value_black) > 0: if len(white_loss[0]) < 8: p2.blit(label, ((len(white_loss[0]) * 11 / 32 + 6 / 40) * tile_size, 0.55 * tile_size)) else: p2.blit(label, ((len(white_loss[1]) * 11 / 32 + 6 / 40) * tile_size, 1.05 * tile_size)) elif int(value_white - value_black) < 0: if len(black_loss[0]) < 8: p1.blit(label, ((len(black_loss[0]) * 11 / 32 + 6 / 40) * tile_size, 0.55 * tile_size)) else: p1.blit(label, ((len(black_loss[1]) * 11 / 32 + 6 / 40) * tile_size, 1.05 * tile_size)) #updating the hud# if round_int % 2 == 0: pygame.draw.rect(hud, BLACK, [ 0.45 * tile_size, 0.2 * tile_size, 3.1 * tile_size, 1.6 * tile_size ]) elif round_int % 2 == 1: pygame.draw.rect(hud, BLACK, [ 4.45 * tile_size, 0.2 * tile_size, 3.1 * tile_size, 1.6 * tile_size ]) hud.blit(p1, (0.5 * tile_size, 0.25 * tile_size)) hud.blit(p2, (4.5 * tile_size, 0.25 * tile_size)) hud.blit(timer_label, (3.65 * tile_size, 0.75 * tile_size)) #creating the buttons on the hud resign_button.draw(screen=hud) quit_button.draw(screen=hud) takeback_button.draw(screen=hud) test_zone_button.draw(screen=hud) items = [quit_button, resign_button, takeback_button, test_zone_button] #bliting the subsurfaces on the mainsurface screen.blit(s, anchor_point_s) screen.blit(h, anchor_point_h) screen.blit(hud, anchor_point_hud) #bot moves# if round_int % 2 == 1 and bot_bool and not Board.game_over and not Board.test_mode: opt_move = bot.get_best_move_time(random.randint(400, 1200)) for piece in Pieces.all_pieces_list: if piece.farbe == BLACK: move = piece.move_from_pos( move=opt_move, board=board, screen=screen, takeback_button=takeback_button, ignore_me=Pieces.ignore_me_standard) if move != None: break #checking for events# else: for event in pygame.event.get(): for item in items: item.processEvent(event) #closing the screen by clicking the X# if event.type == pygame.QUIT: go = False #Keyboard-Inputs# if event.type == pygame.KEYDOWN: #kill window if ESC is pressed# if event.key == pygame.K_ESCAPE: Pieces.white_is_checked = False Pieces.black_is_checked = False Pieces.checking_piece = None json_file = open(r'components\constants.json', 'r') json_content = json.load(json_file) json_content["round_int"] = 0 json_file.close() json_file = open(r'components\constants.json', 'w') json_file.writelines(json.dumps(json_content)) json_file.close() quit() #(TEMP) my information key (arrow down) to get certain information# if event.key == pygame.K_DOWN: print(Pieces.give_FEN()) #print([x.name for x in Pieces.all_pieces_list]) # for king in Pieces.all_pieces_list: # if "King-W" in king.name: # print(list(king.is_castle_legal())) #left mouse click# elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: #getting the mouseposition and than correcting it by the relative position of the subsurface# mouse_pos = pygame.mouse.get_pos() mouse_pos = (mouse_pos[0] - anchor_point_s[0], mouse_pos[1] - anchor_point_s[1]) #checking if a Piece stands on the clicked tile# if not Board.game_over: for piece in Pieces.all_pieces_list: if mouse_pos[0] >= piece.x and mouse_pos[ 1] >= piece.y: if mouse_pos[ 0] < piece.x + tile_size and mouse_pos[ 1] < piece.y + tile_size: #if the clicked piece is one of the team that currently is to move...# with_bool = round_int % 2 == 0 and piece.farbe == ( 255, 255, 255) without_bool = round_int % 2 == 1 and piece.farbe == ( 0, 0, 0) if with_bool or without_bool: #...wait for the second mouse input# move_ = piece.move( board=board, screen=screen, takeback_button=takeback_button, ignore_me=Pieces.ignore_me_standard ) move_ = move_[1][2:3] + move_[2] + str( move_[0][2:]) #check if the white kiung is checked# Pieces.detectingCheck() #resetting class variables# Pieces.white_is_checked = False Pieces.black_is_checked = False Pieces.checking_piece = None #resetting the variables in the .json file# json_file = open(r'components\constants.json', 'r') json_content = json.load(json_file) json_content["round_int"] = 0 json_file.close() json_file = open(r'components\constants.json', 'w') json_file.writelines(json.dumps(json_content)) json_file.close()
class SampleStockfish: """ Stockfish player class. """ def __init__(self, side, board, max_time_per_move, time_control): """ Initialize player class to implement Stockfish. side: str Either 'white' or 'black' for the side that the player is expected to play board: Board (default: chess.Board()) Initial board configuration (the default is just the normal board). max_time_per_move: float (default: None) Max. thinking time (in sec) to be passed to the players. time_control: 2-tuple of floats (default: None) The time control, formatted as (x, y) where the time control is x minutes with a y second increment. This argument is distinct from max_time_per_move. """ self.name = 'Stockfish' self.side = side self.board = board self.max_time_per_move = max_time_per_move self.time_control = time_control # Manage time control if self.time_control is not None and self.max_time_per_move is not None: self.time_left = np.min([60 * self.time_control[0], self.max_time_per_move]) elif self.time_control is not None: self.time_left = 60 * self.time_control[0] elif self.max_time_per_move is not None: self.time_left = self.max_time_per_move else: self.time_left = None # Start Stockfish from stockfish import Stockfish self.stockfish = Stockfish('./stockfish-11-win/Windows/stockfish_20011801_x64_modern.exe') def make_move(self): """ Method to make a move. Returns the move in UCI. """ self.stockfish.set_fen_position(self.board.fen()) if self.time_left is not None: move = self.stockfish.get_best_move_time(0.8 * self.time_left * 1000) else: # If no time controls, make this 30 s move = self.stockfish.get_best_move_time(30 * 1000) self.board.push(chess.Move.from_uci(move)) return move def receive_move(self, move, time_left=None): """ Method to update board with move from the other side. move: str Move that opponent made time_left: float (default: None) Time remaining, if None, there is no global time control """ self.board.push(chess.Move.from_uci(move)) self.time_left = time_left return def request_draw(self): """ Method to request a draw. Return True if want to request a draw, False if not. """ return False def respond_draw(self): """ Method to respond to a draw request. Return True if accept draw, False if not. """ return False def receive_trash_talk(self, trash_talk): """ Method to receive trash talk. """ return def solicit_trash_talk(self): """ Method to solicit trash talk. Return a string to solicit trash talk. If no trash talk, return none. """ return None
def stockfish_move(position, to_play): stockfish = Stockfish("/usr/games/stockfish") fen_line = position + " " + to_play + " KQkq - 0 0" stockfish.set_fen_position(fen_line) return stockfish.get_best_move_time(1000)
class Chess_bot: def __init__(self): self.stockfish = Stockfish("./stockfish") self.knn_clf = joblib.load("train/model.pkl") #The board size. Should be 320 because thats what the model has been trained on self.board_size = 320 self.checking = False self.bot_turn = True def find_color(self, img): tiles = self.get_tiles(img) #White if pawn at a2 is white else black self.white = self.knn_clf.predict([tiles[48]])[0] == 'P' self.board = chess.Board() #Set last board positions as a black board black_start = cv2.imread("black_board.png", cv2.IMREAD_GRAYSCALE) self.last_positions = self.knn_clf.predict( self.get_tiles(black_start)).reshape(8, 8) self.last_img = img return self.white def get_tiles(self, img): #Resize the image of the board board_img = cv2.resize(img, (self.board_size, self.board_size)) tile_size = self.board_size // 8 #initialize tiles array with 8 rows and columns tiles = list() for y in range(0, self.board_size, tile_size): for x in range(0, self.board_size, tile_size): tiles.append(board_img[y:y + tile_size, x:x + tile_size].flatten()) return np.array(tiles) def turn(self, img, bot_move=False): """Return True if it's bot turn to make a move else False""" #If the new predicted board is different ==> new move is being made, wait till completion. if not np.array_equal(self.last_img, img): self.checking = True self.last_img = img return False elif self.checking: #If images are equal and move has been made self.checking = False #Get new board layout tiles = self.get_tiles(img) board_pred = self.knn_clf.predict(tiles).reshape(8, 8) if np.array_equal(board_pred, self.last_positions): return False if not self.move(board_pred): self.last_positions = board_pred return False self.last_positions = board_pred print(self.board) return True else: return False def white_move(self, img): tiles = self.get_tiles(img) board_pred = self.knn_clf.predict(tiles).reshape(8, 8) if not np.array_equal(self.last_positions, board_pred): if not self.move(board_pred): return False self.last_positions = board_pred return True def move(self, new_pos): from_moves = [] to_moves = [] vals = {0: "a", 1: "b", 2: "c", 3: "d", 4: "e", 5: "f", 6: "g", 7: "h"} #Black and white have opposite coordinates Y_mod = 8 if self.white else -1 X_mod = 7 if not self.white else 0 for y in range(8): for x in range(8): if new_pos[y, x] != self.last_positions[y, x]: pos = f"{vals[abs(x-X_mod)]}{abs(Y_mod-y)}" from_moves.append(pos) if new_pos[y,x] == '1' \ else to_moves.append(pos) if len(to_moves) > 1 and len(to_moves) < 3: try: self.board.push_san("O-O") except ValueError: self.board.push_san("O-O-O") return True for from_move in from_moves: for to_move in to_moves: move = chess.Move.from_uci(f"{from_move}{to_move}") if move in self.board.legal_moves: self.board.push(move) return True print("Can't find any legal move") return False def execute_bestMove(self, borders): if not self.bot_turn: self.bot_turn = True return self.stockfish.set_fen_position(self.board.fen()) #Get the best move from current position on a time constraint #Change it if you want the bot to play faster best_move = self.stockfish.get_best_move_time(750) print( f"Best move {'for opponent' if not self.bot_turn else ''} is: {best_move}" ) #Stop the program if its checkmate if best_move == None: print("We won!!") return True #Get best_move start position [X,Y] from_pos = self.get_pos(best_move[:2], borders) #Get best_move end position [X,Y] to_pos = self.get_pos(best_move[2:], borders) #Drag the piece using the positions pyautogui.moveTo(from_pos[0], from_pos[1], 0.01) pyautogui.dragTo( from_pos[0], from_pos[1] + 1, button="left", duration=0.01 ) #This small click is used to get the focus back on the browser window pyautogui.dragTo(to_pos[0], to_pos[1], button=f"{'left' if self.bot_turn else 'right'}", duration=0.3) pyautogui.moveTo(2, 2, 0.01) self.bot_turn = not self.bot_turn def get_pos(self, tile, borders): """Get the position from the uci format position""" tile_size = (borders["maxX"] - borders["minX"]) // 8 vals = {"a": 0, "b": 1, "c": 2, "d": 3, "e": 4, "f": 5, "g": 6, "h": 7} #Black and white have opposite coordinates Y_mod = -8 if self.white else -1 X_mod = 7 if not self.white else 0 x, y = abs(X_mod - vals[tile[0]]), abs(Y_mod + int(tile[1])) Xpos = x * tile_size + tile_size // 2 + borders['minX'] Ypos = y * tile_size + tile_size // 2 + borders['minY'] return [Xpos, Ypos]
color = input("What color do you want to be? ") moves = [] order = [] while True: if color == 'white' or color == 'w': order = ["Human player", "Stockfish"] s = Ser('b') print('Starting game...') break elif color == 'black' or color == 'b': order = ["Stockfish", "Human player"] s = Ser('w') print('Starting game...') first_move = stockfish.get_best_move_time(thinking) print(f'White moves: {board.san(chess.Move.from_uci(first_move))}') board.push_uci(first_move) moves.append(first_move) break else: print('Please enter white (w) or black (b)') color = input("What color do you want to be? ") try: while True: resign = False human_move = input("Your move: ") while True: try: