def play_game_from_file(pgn_path): game = Game() with open(pgn_path) as game_file: pgn = chess.pgn.read_game(game_file) for move in pgn.mainline_moves(): game.apply(move.uci()) children = {} for idx in range(game.NUM_ACTIONS): child = Node(None) child.visit_count = 1 if idx == game.get_num_turn() - 1 else 0 children[idx] = child root = Node(None) root.children = children game.store_search_statistics(root) return game
def play(location, option): model: tf.keras.Model = tf.keras.models.load_model(location) minimax = Minimax(model) logo.show() print('\n\n') side = None while side not in ['W', 'B']: side = input('Play as:\nWhite (W) | Black (B) | Random (R) > ') if side == 'R': side = 'W' if np.random.uniform() < 0.5 else 'B' side = side == 'W' szr = serializer.Serializer(None) if option == 'P': pgn = chess.pgn.read_game(io.StringIO(input('Paste PGN:\n> '))) for move in pgn.mainline_moves(): szr.board.push(move) while not szr.board.is_game_over(): logo.show() print('\n\n') display_board(szr.board, side) score = model.predict(np.expand_dims(szr.serialize(), 0)) print(f'ch0ss evaluation: {score}') if szr.board.turn == side: uci = None while not szr.board.is_legal(uci): if uci is not None: print('Illegal move') try: uci = chess.Move.from_uci(input('Type your move:\n > ')) except ValueError: print('Invalid move') uci = None if szr.board.is_legal(uci): szr.board.push(uci) else: print('Illegal move.') else: print('ch0ss is thinking...') move = minimax.search(szr.board, 3, side) szr.board.push(move[1])
def process_game(args): #print("Process Game") game_number = args['game_number'] progress_queue = args['progress_queue'] db_lock = args['db_lock'] gid = args['gid'] pgn = args['pgn'] moves = list(pgn.mainline_moves()) # Get the game DB object and the PGN moves with db_lock: game_obj, _ = Game.get_or_create(id=gid) white, _ = Player.get_or_create(username=pgn.headers['White'].lower()) black, _ = Player.get_or_create(username=pgn.headers['Black'].lower()) GamePlayer.get_or_create(game=game_obj, color='w', defaults={'player':white}) GamePlayer.get_or_create(game=game_obj, color='b', defaults={'player':black}) # Set up the engine engine_config = load_engine_config() engine = init_engine(engine_config) # Set up the board board = pgn.board() for m in moves: board.push(m) # Process each move in the game in reverse order moves_processed = 0 for played_move in reversed(moves): board.pop() moves_processed += 1 color = 'w' if board.turn == chess.WHITE else 'b' # Skip already-processed moves try: with db_lock: move = Move.get(game=game_obj, color=color, number=board.fullmove_number) continue except DoesNotExist: pass progress_queue.put([game_number, gid, moves_processed, len(moves)]) while True: try: # Run the engine for the top 5 moves info = engine.analyse(board, chess.engine.Limit(nodes=engine_config['nodes']), multipv=5, options=engine_config['options']) # Get the engine results pvs = {i+1: info['pv'][0] for (i, info) in enumerate(info)} evals = {i+1: score_to_cp(info['score']) for (i, info) in enumerate(info)} played_index = None for i, move in pvs.items(): if move == played_move: played_index = i if not played_index: # The played move was not in the top 5, so we need to analyze it separately board.push(played_move) if board.is_checkmate(): played_eval = 29999 if board.turn == chess.BLACK else -29999 else: one_move_info = engine.analyse(board, chess.engine.Limit(nodes=engine_config['nodes']), multipv=1, options=engine_config['options']) played_eval = -score_to_cp(one_move_info[0]['score']) board.pop() else: # The played move was in the top 5, so we can copy the corresponding eval to save time played_eval = evals[played_index] # Store the evaluations in the DB with db_lock: move = Move.create(game=game_obj, color=color, number=board.fullmove_number, \ pv1_eval=evals.get(1), pv2_eval=evals.get(2), pv3_eval=evals.get(3), \ pv4_eval=evals.get(4), pv5_eval=evals.get(5), \ played_rank=played_index, played_eval=played_eval, \ nodes=info[0].get('nodes'), masterdb_matches=masterdb_matches(board, move)) break except TypeError: # If we get a bad engine output, score_to_cp will throw a TypeError. We can just retry continue with db_lock: game_obj.is_analyzed = True game_obj.save() engine.quit()
def test_game_white_checkmate(self): with open(WHITE_CHECKMATE_PGN_PATH) as game_file: pgn = chess.pgn.read_game(game_file) game = Game() for move in pgn.mainline_moves(): game.apply(move.uci()) children = {} for idx in range(game.NUM_ACTIONS): child = Node(None) child.visit_count = 1 if idx == game.get_num_turn( ) - 1 else 0 children[idx] = child root = Node(None) root.children = children game.store_search_statistics(root) # ========= CHECK ENDING ============== self.assertTrue(game.terminal()) self.assertEqual(game.terminal_value(0), 1) self.assertEqual(game.terminal_value(1), -1) self.assertEqual(game.to_play(), int(not game.board.turn)) # ========= CHECK TARGET ============== terminal_value, pi_t = game.make_target(0) self.assertEqual(terminal_value, 1) self.assertEqual(pi_t[0], 1) terminal_value, pi_t = game.make_target(5) self.assertEqual(terminal_value, -1) self.assertEqual(pi_t[5], 1) terminal_value, pi_t = game.make_target(23) self.assertEqual(terminal_value, -1) self.assertEqual(pi_t[23], 1) terminal_value, pi_t = game.make_target(44) self.assertEqual(terminal_value, 1) self.assertEqual(pi_t[44], 1) # ========= CHECK IMAGE ============== state_index = 5 # black to play planes = game.make_image(state_index) self.assertEqual(planes.shape, (119, 8, 8)) # check current board positioning expected_num_pieces = [1, 1, 2, 2, 2, 8, 1, 1, 2, 2, 2, 8] self.assert_correct_num_pieces(planes[0:14, :, :], expected_num_pieces) expected_positions = [[(7, 4)], [(7, 3)], [(7, 0), (7, 7)], [(7, 5), (7, 2)], [(5, 2), (7, 6)], None, [(0, 4)], [(0, 3)], [(0, 0), (0, 7)], [(3, 2), (0, 2)], [(0, 1), (2, 5)], None] self.assert_correct_pieces(planes[0:14, :, :], expected_positions) # check current board - 2 positioning expected_num_pieces = [1, 1, 2, 2, 2, 8, 1, 1, 2, 2, 2, 8] self.assert_correct_num_pieces(planes[28:42, :, :], expected_num_pieces) expected_positions = [[(7, 4)], [(7, 3)], [(7, 0), (7, 7)], [(7, 5), (7, 2)], [(7, 1), (7, 6)], None, [(0, 4)], [(0, 3)], [(0, 0), (0, 7)], [(0, 5), (0, 2)], [(0, 1), (2, 5)], None] self.assert_correct_pieces(planes[28:42, :, :], expected_positions) # check last two boards are empty self.assertTrue((planes[84:112, :, :] == np.zeros( (28, 8, 8))).all()) # check auxiliaries self.assertEqual(planes[112, :, :][0][0], 1) self.assertEqual(planes[113, :, :][0][0], 3) self.assertEqual(planes[114, :, :][0][0], 3) self.assertEqual(planes[115, :, :][0][0], 1) self.assertEqual(planes[116, :, :][0][0], 1) self.assertEqual(planes[117, :, :][0][0], 1) self.assertEqual(planes[118, :, :][0][0], 1) state_index = 44 # white to play planes = game.make_image(state_index) self.assertEqual(planes.shape, (119, 8, 8)) # check current board positioning expected_num_pieces = [1, 0, 1, 2, 0, 6, 1, 1, 2, 2, 1, 4] self.assert_correct_num_pieces(planes[0:14, :, :], expected_num_pieces) expected_positions = [[(7, 6)], None, [(7, 3)], [(5, 0), (3, 5)], None, None, [(0, 4)], [(5, 5)], [(0, 1), (0, 6)], [(1, 1), (2, 1)], [(1, 4)], None] self.assert_correct_pieces(planes[0:14, :, :], expected_positions) # check current board - 2 positioning expected_num_pieces = [1, 0, 1, 2, 0, 6, 1, 1, 2, 2, 1, 4] self.assert_correct_num_pieces(planes[28:42, :, :], expected_num_pieces) expected_positions = [[(7, 6)], None, [(7, 3)], [(5, 0), (5, 3)], None, None, [(1, 3)], [(5, 5)], [(0, 1), (0, 6)], [(1, 1), (2, 1)], [(1, 4)], None] self.assert_correct_pieces(planes[28:42, :, :], expected_positions) # check auxiliaries self.assertEqual(planes[112, :, :][0][0], 0) self.assertEqual(planes[113, :, :][0][0], 23) self.assertEqual(planes[114, :, :][0][0], 2) self.assertEqual(planes[115, :, :][0][0], 0) self.assertEqual(planes[116, :, :][0][0], 0) self.assertEqual(planes[117, :, :][0][0], 0) self.assertEqual(planes[118, :, :][0][0], 0)
def test_game_draw_threefold(self): with open(DRAW_THREE_FOLD_PGN_PATH) as game_file: pgn = chess.pgn.read_game(game_file) game = Game() for move in pgn.mainline_moves(): game.apply(move.uci()) children = {} for idx in range(game.NUM_ACTIONS): child = Node(None) child.visit_count = 1 if idx == game.get_num_turn( ) - 1 else 0 children[idx] = child root = Node(None) root.children = children game.store_search_statistics(root) self.assertTrue(game.terminal()) self.assertEqual(game.terminal_value(0), 0) self.assertEqual(game.terminal_value(1), 0) self.assertEqual(game.to_play(), int(not game.board.turn)) # ========= CHECK TARGET ============== terminal_value, pi_t = game.make_target(0) self.assertEqual(terminal_value, 0) self.assertEqual(pi_t[0], 1) terminal_value, pi_t = game.make_target(10) self.assertEqual(terminal_value, 0) self.assertEqual(pi_t[10], 1) terminal_value, pi_t = game.make_target(11) self.assertEqual(terminal_value, 0) self.assertEqual(pi_t[11], 1) terminal_value, pi_t = game.make_target(12) self.assertEqual(terminal_value, 0) self.assertEqual(pi_t[12], 1) # ========= CHECK IMAGE ============== state_index = 67 # black to play planes = game.make_image(state_index) self.assertEqual(planes.shape, (119, 8, 8)) # check current board positioning expected_num_pieces = [1, 1, 1, 0, 0, 5, 1, 1, 1, 0, 0, 5] self.assert_correct_num_pieces(planes[0:14, :, :], expected_num_pieces) expected_positions = [[(6, 7)], [(5, 5)], [(4, 3)], None, None, None, [(0, 7)], [(1, 4)], [(3, 5)], None, None, None] self.assert_correct_pieces(planes[0:14, :, :], expected_positions) self.assertEqual(planes[12, :, :][0][0], 1) # board repeated once self.assertEqual(planes[13, :, :][0][0], 1) # board repeated twice # # check current board - 2 positioning expected_num_pieces = [1, 1, 1, 0, 0, 5, 1, 1, 1, 0, 0, 5] self.assert_correct_num_pieces(planes[28:42, :, :], expected_num_pieces) expected_positions = [[(6, 7)], [(5, 5)], [(4, 4)], None, None, None, [(0, 7)], [(2, 3)], [(3, 5)], None, None, None] self.assert_correct_pieces(planes[28:42, :, :], expected_positions) # check auxiliaries self.assertEqual(planes[112, :, :][0][0], 1) self.assertEqual(planes[113, :, :][0][0], 34) self.assertEqual(planes[114, :, :][0][0], 10) self.assertEqual(planes[115, :, :][0][0], 0) self.assertEqual(planes[116, :, :][0][0], 0) self.assertEqual(planes[117, :, :][0][0], 0) self.assertEqual(planes[118, :, :][0][0], 0) state_index = 4 # white to play planes = game.make_image(state_index) self.assertEqual(planes.shape, (119, 8, 8)) # check current board positioning expected_num_pieces = [1, 1, 2, 2, 2, 8, 1, 1, 2, 2, 2, 8] self.assert_correct_num_pieces(planes[0:14, :, :], expected_num_pieces) expected_positions = [[(7, 4)], [(7, 3)], [(7, 0), (7, 7)], [(7, 5), (7, 2)], [(7, 1), (7, 6)], [(6, 0), (6, 1), (6, 2), (4, 3), (4, 4), (6, 5), (6, 6), (6, 7)], [(0, 4)], [(0, 3)], [(0, 0), (0, 7)], [(0, 2), (0, 5)], [(0, 1), (0, 6)], [(1, 0), (1, 1), (1, 2), (3, 3), (2, 4), (1, 5), (1, 6), (1, 7)]] self.assert_correct_pieces(planes[0:14, :, :], expected_positions) expected_num_pieces = [1, 1, 2, 2, 2, 8, 1, 1, 2, 2, 2, 8] self.assert_correct_num_pieces(planes[28:42, :, :], expected_num_pieces) expected_positions = [[(7, 4)], [(7, 3)], [(7, 0), (7, 7)], [(7, 5), (7, 2)], [(7, 1), (7, 6)], [(6, 0), (6, 1), (6, 2), (6, 3), (4, 4), (6, 5), (6, 6), (6, 7)], [(0, 4)], [(0, 3)], [(0, 0), (0, 7)], [(0, 2), (0, 5)], [(0, 1), (0, 6)], [(1, 0), (1, 1), (1, 2), (1, 3), (2, 4), (1, 5), (1, 6), (1, 7)]] self.assert_correct_pieces(planes[28:42, :, :], expected_positions) # check last two boards are empty self.assertTrue((planes[84:112, :, :] == np.zeros( (28, 8, 8))).all()) # check auxiliaries self.assertEqual(planes[112, :, :][0][0], 0) self.assertEqual(planes[113, :, :][0][0], 3) self.assertEqual(planes[114, :, :][0][0], 0) self.assertEqual(planes[115, :, :][0][0], 1) self.assertEqual(planes[116, :, :][0][0], 1) self.assertEqual(planes[117, :, :][0][0], 1) self.assertEqual(planes[118, :, :][0][0], 1)
def test_game_draw_stalemate(self): with open(DRAW_STALEMATE_PGN_PATH) as game_file: pgn = chess.pgn.read_game(game_file) game = Game() for move in pgn.mainline_moves(): game.apply(move.uci()) children = {} for idx in range(game.NUM_ACTIONS): child = Node(None) child.visit_count = 1 if idx == game.get_num_turn( ) - 1 else 0 children[idx] = child root = Node(None) root.children = children game.store_search_statistics(root) self.assertTrue(game.terminal()) self.assertEqual(game.terminal_value(0), 0) self.assertEqual(game.terminal_value(1), 0) self.assertEqual(game.to_play(), int(not game.board.turn)) # ========= CHECK TARGET ============== terminal_value, pi_t = game.make_target(0) self.assertEqual(terminal_value, 0) self.assertEqual(pi_t[0], 1) terminal_value, pi_t = game.make_target(9) self.assertEqual(terminal_value, 0) self.assertEqual(pi_t[9], 1) terminal_value, pi_t = game.make_target(21) self.assertEqual(terminal_value, 0) self.assertEqual(pi_t[21], 1) terminal_value, pi_t = game.make_target(36) self.assertEqual(terminal_value, 0) self.assertEqual(pi_t[36], 1) # ========= CHECK IMAGE ============== state_index = 106 # white to play planes = game.make_image(state_index) self.assertEqual(len(game.legal_actions()), 0) self.assertEqual(planes.shape, (119, 8, 8)) # check current board positioning expected_num_pieces = [1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 2] self.assert_correct_num_pieces(planes[0:14, :, :], expected_num_pieces) expected_positions = [[(7, 7)], None, None, None, None, [(6, 7)], [(0, 6)], None, None, [(1, 0)], None, [(4, 5), (5, 7)]] self.assert_correct_pieces(planes[0:14, :, :], expected_positions) # check current board - 2 positioning expected_num_pieces = [1, 0, 0, 0, 0, 2, 1, 0, 0, 1, 0, 2] self.assert_correct_num_pieces(planes[28:42, :, :], expected_num_pieces) expected_positions = [[(7, 7)], None, None, None, None, [(2, 0), (6, 7)], [(0, 6)], None, None, [(0, 1)], None, [(4, 5), (5, 7)]] self.assert_correct_pieces(planes[28:42, :, :], expected_positions) # check auxiliaries self.assertEqual(planes[112, :, :][0][0], 0) self.assertEqual(planes[113, :, :][0][0], 54) self.assertEqual(planes[114, :, :][0][0], 0) self.assertEqual(planes[115, :, :][0][0], 0) self.assertEqual(planes[116, :, :][0][0], 0) self.assertEqual(planes[117, :, :][0][0], 0) self.assertEqual(planes[118, :, :][0][0], 0) state_index = 75 # black to play planes = game.make_image(state_index) self.assertEqual(planes.shape, (119, 8, 8)) # check current board positioning expected_num_pieces = [1, 0, 2, 1, 0, 2, 1, 1, 0, 1, 0, 4] self.assert_correct_num_pieces(planes[0:14, :, :], expected_num_pieces) expected_positions = [[(5, 6)], None, [(4, 2), (7, 2)], [(3, 3)], None, [(2, 7), (5, 5)], [(0, 6)], [(0, 1)], None, [(4, 5)], None, [(3, 0), (1, 5), (2, 6), (1, 7)]] self.assert_correct_pieces(planes[0:14, :, :], expected_positions) # check current board - 2 positioning expected_num_pieces = [1, 0, 2, 1, 0, 3, 1, 1, 0, 1, 0, 4] self.assert_correct_num_pieces(planes[28:42, :, :], expected_num_pieces) expected_positions = [[(5, 6)], None, [(4, 2), (7, 7)], [(3, 3)], None, [(2, 7), (4, 5), (5, 5)], [(0, 6)], [(0, 1)], None, [(1, 2)], None, [(3, 0), (1, 5), (2, 6), (1, 7)]] self.assert_correct_pieces(planes[28:42, :, :], expected_positions) # check auxiliaries self.assertEqual(planes[112, :, :][0][0], 1) self.assertEqual(planes[113, :, :][0][0], 38) self.assertEqual(planes[114, :, :][0][0], 0) self.assertEqual(planes[115, :, :][0][0], 0) self.assertEqual(planes[116, :, :][0][0], 0) self.assertEqual(planes[117, :, :][0][0], 0) self.assertEqual(planes[118, :, :][0][0], 0)