def get_planes_from_game(game, mate_in_one=False): """ Returns all plane descriptions of a given game and their corresponding target values: - the game outcome (-1, 0, 1) - the next move which will be played in each position :param game: Game handle which is a python-chess object (e.g. mv_hist_len = 8 means that the current position and the 7 previous positions are exported) :param mate_in_one: Decide weather only to export the position before the last mate-in-one move (this option is for evaluation and DEBUG purposes) :return: x - the position description of all moves in the game y_value - the target values of the scene description. Here the game outcome. returns -1 if the current player lost, +1 if the current player won, 0 for draw y_policy - the policy vector one-hot encoded indicating the next move the player current player chose in this position """ fen_dic = { } # A dictionary which maps the fen description to its number of occurrences x = [] y_value = [] y_policy = [] board = game.board() # get the initial board state # update the y value accordingly if board.turn == chess.WHITE: y_init = 1 else: y_init = -1 if game.headers["Result"] == "0-1": y_init *= -1 elif game.headers["Result"] == "1/2-1/2": y_init = 0 all_moves = [] # Extract all moves first and save them into a list for move in game.main_line(): all_moves.append(move) # Iterate through all moves (except the last one) and play them on a board. # you don't want to push the last move on the board because you had no movement policy to learn from in this case # The moves get pushed at the end of the for-loop and is only used in the next loop. # Therefore we can iterate over 'all' moves for i, move in enumerate(all_moves): board_occ = 0 # by default the positions hasn't occurred before fen = board.fen() # remove the halfmove counter & move counter from this fen to make repetitions possible fen = fen[:fen.find(" ") + 2] # save the board state to the fen dictionary if fen in list(fen_dic.keys()): fen_dic[fen] += 1 board_occ = fen_dic[fen] else: fen_dic[fen] = 1 # create a new entry # we insert the move i (and not i+1), because the start is the empty board position next_move = all_moves[i] # check if you need to export a mate_in_one_scenario if not mate_in_one or i == len(all_moves) - 1: # receive the board and the evaluation of the current position in plane representation # We don't want to store float values because the integer datatype is cheaper, # that's why normalize is set to false x_cur = board_to_planes(board, board_occ, normalize=False) # add the evaluation of 1 position to the list x.append(x_cur) y_value.append(y_init) # add the next move defined in policy vector notation to the policy list # the network always sees the board as if he's the white player, that's the move is mirrored fro black y_policy.append( move_to_policy(next_move, is_white_to_move=board.turn)) y_init *= -1 # flip the y_init value after each move board.push(move) # push the next move on the board # check if there has been any moves if x and y_value and y_policy: x = np.stack(x, axis=0) y_value = np.stack(y_value, axis=0) y_policy = np.stack(y_policy, axis=0) else: print("game.headers:") print(game.headers) raise Exception("The given pgn file's mainline is empty!") return x, y_value, y_policy
def get_state_planes(self): return board_to_planes(self.board, board_occ=self._board_occ, normalize=True)
def get_state_planes(self): """Transform the current board state to a plane""" return board_to_planes(self.board, board_occ=self._board_occ, normalize=True)