Пример #1
0
 def load(self, path):
     pgn = open(path)
     offsets = []
     for offset, headers in chess.pgn.scan_headers(pgn):
         offsets.append(offset)
     for offset in offsets:
         pgn.seek(offset)
         game = chess.pgn.read_game(pgn)
         exporter = chess.pgn.StringExporter()
         pgn_string = game.accept(exporter)
         game_headers = self._get_headers_columns(game.headers)
         game_id = [x for x in (Game.insert(pgn=pgn_string, **game_headers).returning(Game.id)).execute()][0][0]
         node = game
         while not node.is_end():
             next_node = node.variations[0]
             fen = node.board().fen()
             hash_key = hashlib.md5(fen.encode()).hexdigest()
             position_result = (Position.select().where(Position.hash == hash_key).execute())
             if not position_result:
                 position_id = [x for x in (Position.insert(hash=hash_key).returning(Position.id)).execute()][0][0]
             else:
                 position_id = position_result[0].id
             PositionGame.insert(position_id=position_id, game_id=game_id).execute()
             node = next_node
     pgn.close()
Пример #2
0
 def get_games_from_file(self, filename):
     pgn = open(filename, errors='ignore')
     games = []
     for offset in chess.pgn.scan_offsets(pgn):
         pgn.seek(offset)
         games.append(chess.pgn.read_game(pgn))
     return games
Пример #3
0
def load_generic_text(directory):
    '''Generator that yields text raw from the directory.'''
    files = find_files(directory)
    for filename in files:
        text = ""
        k = 0
        pgn = open(filename)
        for offset, headers in chess.pgn.scan_headers(pgn):
            pgn.seek(offset)
            game = chess.pgn.read_game(pgn)
            node = game
            nm = 1
            while not node.is_end():
                board_fen = replace_tags(node.board().fen())
                next_node = node.variation(0)
                label_san = node.board().san(next_node.move)
                text += board_fen + ":" + label_san + "\n"
                nm += 1
                node = next_node
            if k % 1000 == 0 and k > 1:
                print("Saving file: " + filename + "-" + str(k) + ".txt")
                y = []
                for index, item in enumerate(text):
                    y.append(text[index])
                y = np.array(y)
                np.savetxt(filename + "-" + str(k) + ".txt",
                           y.reshape(1, y.shape[0]),
                           delimiter="",
                           newline="\n",
                           fmt="%s")
                text = ""
            k += 1
        pgn.close()
        yield filename
Пример #4
0
def load_generic_text(directory):
    '''Generator that yields text raw from the directory.'''
    files = find_files(directory)
    text = " "
    for filename in files:
        k = 0
        pgn = open(filename)
        for offset, headers in chess.pgn.scan_headers(pgn):
            pgn.seek(offset)
            game = chess.pgn.read_game(pgn)
            node = game
            while not node.is_end():
                next_node = node.variation(0)
                label_san = node.board().san(next_node.move)
                if " " + label_san + " " not in text:
                    text += label_san + " "
                node = next_node
            if k % 100 == 0 and k > 1:
                print ("Labeling file: " + filename + ", step: " + str(k))
            k += 1
        pgn.close()
    y = []
    for index, item in enumerate(text):
        y.append(text[index])
    y = np.array(y)
    np.savetxt("labels.txt", y.reshape(1, y.shape[0]), delimiter="", newline="\n", fmt="%s")
Пример #5
0
def parser(file, elo=400, draws=False, time_control=True):
    pgn = open(file)
    games = []
    results = []
    offsets = []
    counter = 0
    while True:
        offset = pgn.tell()
        headers = chess.pgn.read_headers(pgn)
        if headers is None:
            break

        if headers.get("Result") not in ["1-0", "0-1", "1/2-1/2"]:
            continue

        if not draws:
            if headers.get("Result") == "1/2-1/2":
                continue

        elo_white = headers.get("WhiteElo")
        elo_black = headers.get("BlackElo")

        if elo_white is None or not elo_white.isnumeric():
            elo_white = 0
        if elo_black is None or not elo_black.isnumeric():
            elo_black = 0

        time_control = headers.get("TimeControl")

        if time_control:
            if not time_control[0:4].isnumeric():
                if not time_control[0:3].isnumeric():
                    continue

                if int(time_control[0:3]) < 180:
                    continue

        if int(elo_black) >= elo or int(elo_white) >= elo:
            offsets.append(offset)
            result = headers.get("Result")
            if result == "1-0":
                results.append("white")
            elif result == "0-1":
                results.append("black")
            else:
                print(result)
                results.append("draw")
            counter += 1
        if counter > 50000:
            break

    for offset in offsets:
        pgn.seek(offset)
        games.append(chess.pgn.read_game(pgn))

    return games, results
Пример #6
0
    def test_scan_headers(self):
        with open("data/games/kasparov-deep-blue-1997.pgn") as pgn:
            offsets = (offset for offset, headers in chess.pgn.scan_headers(pgn)
                              if headers["Result"] == "1/2-1/2")

            first_drawn_game_offset = next(offsets)
            pgn.seek(first_drawn_game_offset)
            first_drawn_game = chess.pgn.read_game(pgn)
            self.assertEqual(first_drawn_game.headers["Site"], "03")
            self.assertEqual(first_drawn_game.variation(0).move, chess.Move.from_uci("d2d3"))
Пример #7
0
def get_games_from_file(filename):
    pgn = open(filename, errors='ignore')
    offsets = list(chess.pgn.scan_offsets(pgn))
    n = len(offsets)
    print(f"found {n} games")
    games = []
    for offset in offsets:
        pgn.seek(offset)
        games.append(chess.pgn.read_game(pgn))
    return games
Пример #8
0
 def load_game(self, index):
     if index >= 0 and index < len(self.entries):
         entry = self.entries[index]
         with open(self.filename) as pgn:
             offset = entry.pgn_offset
             pgn.seek(offset)
             game = chess.pgn.read_game(pgn)
             self.index_current_game = index
         return game
     else:
         raise ValueError("no game for supplied index in database")
Пример #9
0
def load_generic_text(directory, type_file):
    '''Generator that yields text raw from the directory.'''
    files = find_files(directory)
    print(files)
    for filename in files:
        print("Parsing file: " + filename)
        board_text = ""
        movement_text = ""
        k = 0
        pgn = open(filename)
        for offset, headers in chess.pgn.scan_headers(pgn):
            pgn.seek(offset)
            game = chess.pgn.read_game(pgn)
            node = game
            nm = 1
            while not node.is_end():
                board_fen = replace_tags(node.board().fen())
                next_node = node.variation(0)
                label_san = node.board().san(next_node.move)
                board_text += " ".join(board_fen) + "\n"
                movement_text += " ".join(label_san) + "\n"
                nm += 1
                node = next_node
            if k % 1000 == 0 and k > 1:
                print("Saving: " + filename + " " + str(k))
                print("Saving: " + filename + " " + str(k))
                y = []
                m = []
                for index, item in enumerate(board_text):
                    y.append(board_text[index])
                for index, item in enumerate(movement_text):
                    m.append(movement_text[index])
                y = np.array(y)
                m = np.array(m)
                with open(
                        "nmt/datasets/" + type_file + "/" + type_file + ".gm",
                        'a') as f_handle:
                    np.savetxt(f_handle,
                               y.reshape(1, y.shape[0]),
                               delimiter="",
                               newline="\n",
                               fmt="%s")
                with open(
                        "nmt/datasets/" + type_file + "/" + type_file + ".mv",
                        'a') as f_handle:
                    np.savetxt(f_handle,
                               m.reshape(1, m.shape[0]),
                               delimiter="",
                               newline="\n",
                               fmt="%s")
                board_text = ""
                movement_text = ""
            k += 1
        pgn.close()
Пример #10
0
def offsets_to_df(offsets, pgn):
    print('Parsing {} games.'.format(len(offsets)))

    rows = []
    with click.progressbar(offsets, label="Parsing pgn") as offsets:
        for offset in offsets:
            pgn.seek(offset)
            game = chess.pgn.read_game(pgn)
            rows.extend(game_to_rows(game))

    return pd.DataFrame(rows)
Пример #11
0
    def read_file(self, filename):
        pgn = open(filename, errors='ignore')

        futures = deque()
        for offset in chess.pgn.scan_offsets(pgn):
            pgn.seek(offset)
            game = chess.pgn.read_game(pgn)
            futures.append(self.executor.submit(get_buffer, game, self.config))

        print(f"found {len(futures)} games")
        while futures:
            yield futures.popleft()  # no more memleak
Пример #12
0
 def load_game(self, index):
     print(self.entries)
     if index >= 0 and index < len(self.entries):
         entry = self.entries[index]
         with open(self.filename) as pgn:
             offset = entry.pgn_offset
             pgn.seek(offset)
             game = chess.pgn.read_game(pgn)
             self.index_current_game = index
         return game
     else:
         raise ValueError("no game for supplied index in database")
Пример #13
0
    def test_scan_offsets(self):
        with open("data/games/kasparov-deep-blue-1997.pgn") as pgn:
            offsets = list(chess.pgn.scan_offsets(pgn))
            self.assertEqual(len(offsets), 6)

            pgn.seek(offsets[0])
            first_game = chess.pgn.read_game(pgn)
            self.assertEqual(first_game.headers["Event"], "IBM Man-Machine, New York USA")
            self.assertEqual(first_game.headers["Site"], "01")

            pgn.seek(offsets[5])
            sixth_game = chess.pgn.read_game(pgn)
            self.assertEqual(sixth_game.headers["Event"], "IBM Man-Machine, New York USA")
            self.assertEqual(sixth_game.headers["Site"], "06")
Пример #14
0
def get_games_from_file(filename: str) -> List[chess.pgn.Game]:
    """
    :param str filename: file containing the pgn game data
    :return list(pgn.Game): chess games in that file
    """
    pgn = open(filename, errors='ignore')
    offsets = list(chess.pgn.scan_offsets(pgn))
    n = len(offsets)
    print(f"found {n} games")
    games = []
    for offset in offsets:
        pgn.seek(offset)
        games.append(chess.pgn.read_game(pgn))
    return games
Пример #15
0
    def update_game(self, idx, game_tree):
        old_length = self.delete_game_for_update_at(idx)

        dos_newlines = False
        if "\r\n".encode() in open(self.filename,"rb").read():
            dos_newlines = True

        if(dos_newlines):
            game_str = (str(game_tree.root())).replace('\n','\r\n')
            game_str = (game_str + '\r\n\r\n').encode('utf-8')
        else:
            game_str = (str(game_tree.root())+"\n\n").encode('utf-8')
        length = len(game_str)

        offset = self.entries[idx].pgn_offset

        # we can't mmap an empty file
        # the file is however empty, if the current
        # game was the only one in the database
        # just append it
        current_filesize = os.stat(self.filename).st_size
        print("current fs: "+str(current_filesize))
        if current_filesize == 0:
            print("file is empty")
            self.entries = []
            self.append_game(game_tree)
        else:
            pgn = open(self.filename, 'r+')
            m=mm.mmap(pgn.fileno(),0)
            size = len(m)
            new_size = size + length
            m.flush()
            m.close()
            pgn.seek(size)
            pgn.write('A'*length)
            pgn.flush()
            m=mm.mmap(pgn.fileno(),0)
            m.move(offset+length,offset,size-offset)
            m.seek(offset)
            m.write(game_str)
            m.flush()
            m.close()
            pgn.close()

            for i in range(idx+1, len(self.entries)):
                self.entries[i].pgn_offset += (length-old_length)

        self.checksum = crc32_from_file(self.filename)
        self.entries[idx] = Entry(offset, game_tree.root().headers)
Пример #16
0
def get_games_from_file(filename):
    """

    :param str filename: file containing the pgn game data
    :return list(pgn.Game): chess games in that file
    """
    pgn = open(filename, errors='ignore')
    offsets = list(chess.pgn.scan_offsets(pgn))
    n = len(offsets)
    print(f"found {n} games")
    games = []
    for offset in offsets:
        pgn.seek(offset)
        games.append(chess.pgn.read_game(pgn))
    return games
Пример #17
0
    def update_game(self, idx, game_tree):
        old_length = self.delete_game_for_update_at(idx)

        dos_newlines = False
        if "\r\n".encode() in open(self.filename, "rb").read():
            dos_newlines = True

        if (dos_newlines):
            game_str = (str(game_tree.root())).replace('\n', '\r\n')
            game_str = (game_str + '\r\n\r\n').encode('utf-8')
        else:
            game_str = (str(game_tree.root()) + "\n\n").encode('utf-8')
        length = len(game_str)

        offset = self.entries[idx].pgn_offset

        # we can't mmap an empty file
        # the file is however empty, if the current
        # game was the only one in the database
        # just append it
        current_filesize = os.stat(self.filename).st_size
        if current_filesize == 0:
            self.entries = []
            self.append_game(game_tree)
        else:
            pgn = open(self.filename, 'r+')
            m = mm.mmap(pgn.fileno(), 0)
            size = len(m)
            new_size = size + length
            m.flush()
            m.close()
            pgn.seek(size)
            pgn.write('A' * length)
            pgn.flush()
            m = mm.mmap(pgn.fileno(), 0)
            m.move(offset + length, offset, size - offset)
            m.seek(offset)
            m.write(game_str)
            m.flush()
            m.close()
            pgn.close()

            for i in range(idx + 1, len(self.entries)):
                self.entries[i].pgn_offset += (length - old_length)

        self.checksum = crc32_from_file(self.filename)
        self.entries[idx] = Entry(offset, game_tree.root().headers)
Пример #18
0
def filter_pgn_file_for_games(
    pgn: TextIO,
    filters: Dict[str, List[Any]] = {},
    verbose_period: Optional[int] = None,
) -> Generator[chess.pgn.Game, None, None]:
    count = 0
    while True:
        offset = pgn.tell()

        headers = chess.pgn.read_headers(pgn)
        if headers is None:
            break

        for key, vals in filters.items():
            if headers.get(key) not in vals:
                break
        else:
            pgn.seek(offset)
            game = chess.pgn.read_game(pgn)
            count += 1
            if verbose_period is not None and count % verbose_period == 0:
                print(f"{count} games processed")
            yield game
Пример #19
0
def get_games_from_file(filename):
    """

	:param str filename: file containing the pgn game data
	:return list(pgn.Game): chess games in that file
	"""
    pgn = open(filename, errors='ignore')
    offsets = []
    while True:
        offset = pgn.tell()

        headers = chess.pgn.read_headers(pgn)
        if headers is None:
            break

        offsets.append(offset)
    n = len(offsets)
    print(f"found {n} games")
    games = []
    for offset in offsets:
        pgn.seek(offset)
        games.append(chess.pgn.read_game(pgn))
    return games
Пример #20
0
def gen(pgn_file_path):
    with open(pgn_file_path) as pgn:

        # Start from random position in the file
        pgn.seek(0, 2)
        pgn.seek(random.randint(0, pgn.tell()))
        chess.pgn.read_headers(pgn)

        while True:
            game = chess.pgn.read_game(pgn)

            if not game:
                pgn.seek(0)
                continue
            '''
      result_header = game.headers['Result']
      game_value_for_white = 0
      if result_header == '*':
        continue
      elif result_header == '1-0':
        game_value_for_white = 1
      elif result_header == '0-1':
        game_value_for_white = -1
      else:
        game_value_for_white = 0
      '''

            board = game.board()
            for node in game.mainline():
                board.push(node.move)
                eval = node.eval()
                if not eval:
                    break
                eval = eval.pov(not board.turn).score()
                if not eval:
                    continue
                try:
                    X = get_halfkp_indeces(board)
                except:
                    print(f'Would have crashed: {board}')
                    continue
                # y = game_value_for_white if board.turn == chess.WHITE else -game_value_for_white
                # y = eval if board.turn == chess.WHITE else -eval
                yield (X[0], X[1]), eval / 100
Пример #21
0
def read(filename, data):
    pgn = open(filename)
    cnt = 0
    while True:
        cnt += 1
        if cnt % 10000 == 0:
            print(cnt)

        offset = pgn.tell()
        headers = chess.pgn.read_headers(pgn)
        if headers is None:
            break

        point = 0
        if headers['Result'] == '1-0':
            point = 1
        if headers['Result'] == '1/2-1/2':
            point = 0.5

        date = headers['UTCDate']
        if date not in data:
            data[date] = {}
            data[date]['games'] = [1, 0]
            data[date]['traps'] = [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
                                   [0, 0]]
            """
            0: Oh no my queen, Stafford
            1: Oh no my knight, Stafford
            2: Stafford: 5.e5 Ne4 6.d4 Qh4 7.g3 Ng3
            3: Punishing natural development, Stafford
            4: Punishing capture hxg4, Stafford
            5: Englund gambit trap
            """
        else:
            data[date]['games'][0] += 1
        data[date]['games'][1] += point

        opening = headers["Opening"]
        if opening not in data[date]:
            data[date][opening] = [1, 0]
        else:
            data[date][opening][0] += 1
        data[date][opening][1] += point

        if opening == 'Englund Gambit' or opening == 'Russian Game: Stafford Gambit':
            pgn.seek(offset)
            mygame = chess.pgn.read_game(pgn)

            for i in range(10):
                if mygame.next() != None:
                    mygame = mygame.next()
            if mygame.board().fen(
            ) == 'rnbqk2r/ppp1Pppp/8/8/8/5N2/PPP1PbPP/RNBQKB1R w KQkq - 0 6':
                data[date]['traps'][5][0] += 1
                data[date]['traps'][5][1] += point
                print(date, data[date]['traps'])
            mygame = mygame.game()

            for i in range(13):
                if mygame.next() != None:
                    mygame = mygame.next()
            if mygame.board().fen(
            ) == 'r1bBk2r/ppp2ppp/2p5/2b5/4n3/3P4/PPP2PPP/RN1QKB1R b KQkq - 0 7':
                data[date]['traps'][0][0] += 1
                data[date]['traps'][0][1] += point
                print(date, data[date]['traps'])
            mygame = mygame.game()

            for i in range(12):
                if mygame.next() != None:
                    mygame = mygame.next()
            if mygame.board().fen(
            ) == 'r1bqk2r/ppp2ppp/2p5/2b1P3/4n3/3P4/PPP2PPP/RNBQKB1R w KQkq - 1 7':
                data[date]['traps'][1][0] += 1
                data[date]['traps'][1][1] += point
                print(date, data[date]['traps'])
            mygame = mygame.game()

            for i in range(14):
                if mygame.next() != None:
                    mygame = mygame.next()
            if mygame.board().fen(
            ) == 'r1b1kb1r/ppp2ppp/2p5/4P3/3P3q/6n1/PPP2P1P/RNBQKB1R w KQkq - 0 8':
                data[date]['traps'][2][0] += 1
                data[date]['traps'][2][1] += point
                print(date, data[date]['traps'])
            mygame = mygame.game()

            for i in range(16):
                if mygame.next() != None:
                    mygame = mygame.next()
            if mygame.board().fen(
            ) == 'r1b1k2r/ppp2ppp/2p5/2b5/2B1P2q/2N4P/PPPP1nP1/R1BQ1RK1 w kq - 0 9':
                data[date]['traps'][3][0] += 1
                data[date]['traps'][3][1] += point
                print(date, data[date]['traps'])
            mygame = mygame.game()

            for i in range(17):
                if mygame.next() != None:
                    mygame = mygame.next()
            if mygame.board().fen() == 'r1b1k2r/ppp2pp1/2p5/2b4p/3qP1P1/2N5/PPPPBPP1/R1BQ1RK1 b kq - 0 9' or \
                    mygame.board().fen() == 'r1b1k2r/ppp2pp1/2pq4/2b4p/4P1P1/3P4/PPP1BPP1/RNBQ1RK1 b kq - 0 9':
                data[date]['traps'][4][0] += 1
                data[date]['traps'][4][1] += point
                print(date, data[date]['traps'])

    return data
Пример #22
0
 def get_end_offset(self):
     with open(self.filename, 'r') as pgn:
         pgn.seek(0, os.SEEK_END)
         end_offset = pgn.tell()
     return end_offset
Пример #23
0
if __name__ == '__main__':
	pathPgn = './output.pgn'
	if sys.argv[1:]:
		pathPgn = sys.argv[1]
	print "opening PGN: %s" % pathPgn
	pgn = open(pathPgn)

	lineCur = 1   
	lineToOffset = {}
	while 1:
		lineToOffset[lineCur] = pgn.tell()
		if not pgn.readline():
			break;
		lineCur += 1
	pgn.seek(0)

	print lineToOffset
	sys.exit(-1)

 
	gameNum = 1
	while 1:
		game = chess.pgn.read_game(pgn)
		fen = game.headers["FEN"]
		print "offset:%d, game:%d, fen:%s" % (pgn.tell(), gameNum, fen)
	
		m = re.match(regexFen, fen)
		if not m:
			print "%s is not valid" % fen
			fix(filename)
Пример #24
0
with open("../../AepliBase.pgn") as pgn:
    offsets_gen = chess.pgn.scan_offsets(pgn)
    offsets = []
    try:
        while len(offsets) < N:
            # skip some
            for i in range(200):
                offset = next(offsets_gen)
            offsets.append(offset)
            sys.stdout.write('.')
            sys.stdout.flush()
    except:
        pass
    print(len(offsets), ' offsets found')
    for offset in offsets:
        pgn.seek(offset)
        g = chess.pgn.read_game(pgn)
        games.append(g)
        sys.stdout.write('.')
        sys.stdout.flush()
    print(len(games), ' games parsed')
with open('qanim.js', 'w') as out:
    out.write('moves=[')
    for iMoveWanted in range(depth):
        print('\n', iMoveWanted)
        piece_move_counts = [[[[[0] * S for y1 in range(S)] for x2 in range(S)]
                              for y2 in range(S)] for p in range(P)]
        for g in games:
            sys.stdout.write('.')
            sys.stdout.flush()
            moves = list(g.main_line())
Пример #25
0
    def read_game(self, idx):
        self.env.reset()
        self.black = ChessPlayer(self.config, self.model)
        self.white = ChessPlayer(self.config, self.model)
        files = find_pgn_files(self.config.resource.play_data_dir)
        if len(files) > 0:
            random.shuffle(files)
            filename = files[0]
            pgn = open(filename, errors='ignore')
            size = os.path.getsize(filename)
            pos = random.randint(0, size)
            pgn.seek(pos)

            line = pgn.readline()
            offset = 0
            # Parse game headers.
            while line:
                if line.isspace() or line.startswith("%"):
                    line = pgn.readline()
                    continue

                # Read header tags.
                tag_match = TAG_REGEX.match(line)
                if tag_match:
                    offset = pgn.tell()
                    break

                line = pgn.readline()

            pgn.seek(offset)
            game = chess.pgn.read_game(pgn)
            node = game
            result = game.headers["Result"]
            actions = []
            while not node.is_end():
                next_node = node.variation(0)
                actions.append(node.board().uci(next_node.move))
                node = next_node
            pgn.close()

            k = 0
            observation = self.env.observation
            while not self.env.done and k < len(actions):
                if self.env.board.turn == chess.BLACK:
                    action = self.black.sl_action(observation, actions[k])
                else:
                    action = self.white.sl_action(observation, actions[k])
                board, info = self.env.step(action)
                observation = board.fen()
                k += 1

            self.env.done = True
            if not self.env.board.is_game_over() and result != '1/2-1/2':
                self.env.resigned = True
            if result == '1-0':
                self.env.winner = Winner.white
            elif result == '0-1':
                self.env.winner = Winner.black
            else:
                self.env.winner = Winner.draw

            self.finish_game()
            self.save_play_data(write=idx % self.config.play_data.nb_game_in_file == 0)
            self.remove_play_data()
        return self.env
Пример #26
0
if __name__ == '__main__':
    pathPgn = './output.pgn'
    if sys.argv[1:]:
        pathPgn = sys.argv[1]
    print "opening PGN: %s" % pathPgn
    pgn = open(pathPgn)

    lineCur = 1
    lineToOffset = {}
    while 1:
        lineToOffset[lineCur] = pgn.tell()
        if not pgn.readline():
            break
        lineCur += 1
    pgn.seek(0)

    print lineToOffset
    sys.exit(-1)

    gameNum = 1
    while 1:
        game = chess.pgn.read_game(pgn)
        fen = game.headers["FEN"]
        print "offset:%d, game:%d, fen:%s" % (pgn.tell(), gameNum, fen)

        m = re.match(regexFen, fen)
        if not m:
            print "%s is not valid" % fen
            fix(filename)
Пример #27
0
 def get_end_offset(self):
     with open(self.filename,'r') as pgn:
         pgn.seek(0,os.SEEK_END)
         end_offset = pgn.tell()
     print("determined end offset: "+str(end_offset))
     return end_offset
Пример #28
0
    def state_action_sl(self, loop=True, featurized=False, board="both"):
        """
        Returns (state, action) tuple from white's perspective - flips black's perspective to match
        - state: np.array [12 pieces x 64 squares]
            - piece order:  wp wn wb wr wq wk bp bn bb br bq bk
            - square order: a1 b1 c1 ... h8
        - action: [np.array [1 x 64 squares], np.array [1 x 64 squares]] representing [from_board, to_board]
        """
        from_board = False
        to_board = False
        if board == "both":
            from_board = True
            to_board = True
        elif board == "from":
            from_board = True
        elif board == "to":
            to_board = True
        elif board == "full":
            pass

        idx_batch = 0
        with open(self.filename) as pgn:
            S = []
            A_from = []
            A_to = []
            A_combined = []
            while True:
                game = chess.pgn.read_game(pgn)
                if game is None:
                    if not loop:
                        break
                    print("\n******************************************")
                    print("********** LOOPING OVER DATASET **********")
                    print("******************************************\n")
                    pgn.seek(0)
                    continue

                num_moves = int(game.headers["PlyCount"])
                board = game.board()
                node = game.root()

                if num_moves <= 4:
                    continue

                # Make sure game was played all the way through
                last_node = game.root()
                while last_node.variations:
                    last_node = last_node.variations[0]
                if "forfeit" in last_node.comment:
                    continue

                black_turn = False
                while node.variations:
                    # Play white
                    s = state_from_board(board,
                                         featurized=featurized,
                                         black=black_turn)
                    move = node.variations[0].move
                    a_from, a_to = action_from_move(move, black=black_turn)
                    board.push(move)
                    black_turn = not black_turn

                    node = node.variations[0]

                    S.append(s)
                    A_from.append(a_from)
                    A_to.append(a_to)
                    if not (from_board or to_board):
                        a_combined = np.outer(a_from, a_to).flatten()
                        A_combined.append(a_combined)
                    idx_batch += 1

                    if idx_batch >= BATCH_SIZE and len(S) >= POOL_SIZE:
                        # Shuffle moves in game
                        idx = list(np.random.permutation(len(S)))
                        S_shuffle = [S[i] for i in idx]
                        A_from_shuffle = [A_from[i] for i in idx]
                        A_to_shuffle = [A_to[i] for i in idx]
                        S = S_shuffle[BATCH_SIZE:]
                        A_from = A_from_shuffle[BATCH_SIZE:]
                        A_to = A_to_shuffle[BATCH_SIZE:]
                        if not not A_combined:
                            A_combined_shuffle = [A_combined[i] for i in idx]
                            A_combined = A_combined_shuffle[BATCH_SIZE:]
                        idx_batch = 0
                        if from_board and to_board:
                            yield (np.array(S_shuffle[:BATCH_SIZE]), \
                                   [np.array(A_from_shuffle[:BATCH_SIZE]), \
                                    np.array(A_to_shuffle[:BATCH_SIZE])])
                        elif from_board:
                            yield (np.array(S_shuffle[:BATCH_SIZE]), \
                                   np.array(A_from_shuffle[:BATCH_SIZE]))
                        elif to_board:
                            yield ([np.array(S_shuffle[:BATCH_SIZE]), \
                                    np.array(A_from_shuffle[:BATCH_SIZE]).reshape(BATCH_SIZE,1,NUM_ROWS,NUM_COLS)], \
                                   np.array(A_to_shuffle[:BATCH_SIZE]))
                        else:
                            yield (np.array(S_shuffle[:BATCH_SIZE]), \
                                   np.array(A_combined_shuffle[:BATCH_SIZE]))
Пример #29
0
    def black_state_action_sl(self, loop=True, featurized=False):
        """
        Returns (state, action) tuple from black's perspective
        - state: np.array [12 pieces x 64 squares]
            - piece order:  wp wn wb wr wq wk bp bn bb br bq bk
            - square order: a1 b1 c1 ... h8
        - action: [np.array [1 x 64 squares], np.array [1 x 64 squares]] representing [from_board, to_board]
        """
        BATCH_SIZE = 32
        idx_batch = 0
        with open(self.filename) as pgn:
            S = []
            A_from = []
            A_to = []
            while True:
                game = chess.pgn.read_game(pgn)
                if game is None:
                    if not loop:
                        break
                    print("\n******************************************")
                    print("********** LOOPING OVER DATASET **********")
                    print("******************************************\n")
                    pgn.seek(0)
                    continue

                num_moves = int(game.headers["PlyCount"])
                board = game.board()
                node = game.root()

                if num_moves <= 5:
                    continue

                # Make sure game was played all the way through
                last_node = game.root()
                while last_node.variations:
                    last_node = last_node.variations[0]
                if "forfeit" in last_node.comment:
                    continue

                # Play white
                move = node.variations[0].move
                board.push(move)
                node = node.variations[0]

                while node.variations:
                    s = state_from_board(board, featurized=featurized)
                    move = node.variations[0].move
                    a_from, a_to = action_from_move(move)

                    # Play black
                    board.push(move)

                    # Play white
                    node = node.variations[0]
                    if node.variations:
                        move = node.variations[0].move
                        board.push(move)

                        if node.variations:
                            node = node.variations[0]

                    S.append(s)
                    A_from.append(a_from)
                    A_to.append(a_to)
                    idx_batch += 1

                    if idx_batch == BATCH_SIZE:
                        # Shuffle moves in game
                        idx = list(np.random.permutation(len(S)))
                        S_shuffle = [S[i] for i in idx]
                        A_from_shuffle = [A_from[i] for i in idx]
                        A_to_shuffle = [A_to[i] for i in idx]
                        S = []
                        A_from = []
                        A_to = []
                        idx_batch = 0
                        yield np.array(S_shuffle), [
                            np.array(A_from_shuffle),
                            np.array(A_to_shuffle)
                        ]
Пример #30
0
    def state_value(self, loop=True, featurized=False, board='both'):
        """
        Returns (state, action) tuple from white's perspective - flips black's perspective to match
        - state: np.array [12 pieces x 64 squares]
            - piece order:  wp wn wb wr wq wk bp bn bb br bq bk
            - square order: a1 b1 c1 ... h8
        - action: [np.array [1 x 64 squares], np.array [1 x 64 squares]] representing [from_board, to_board]
        """
        idx_batch = 0
        with open(self.filename) as pgn:
            S = []
            R = []
            while True:
                game = chess.pgn.read_game(pgn)
                if game is None:
                    if not loop:
                        break
                    print("\n******************************************")
                    print("********** LOOPING OVER DATASET **********")
                    print("******************************************\n")
                    pgn.seek(0)
                    continue

                num_moves = int(game.headers["PlyCount"])
                board = game.board()
                node = game.root()

                if num_moves <= 4:
                    continue

                # Make sure game was played all the way through
                last_node = game.root()
                while last_node.variations:
                    last_node = last_node.variations[0]
                if "forfeit" in last_node.comment:
                    continue

                z = 0
                white_score = game.headers["Result"].split("-")[0].split("/")
                if len(white_score) == 1:
                    z = 2 * int(white_score[0]) - 1

                black_turn = False
                while node.variations:
                    # Play white
                    s = state_from_board(board,
                                         featurized=featurized,
                                         black=black_turn)
                    move = node.variations[0].move
                    r = z if not black_turn else -z
                    board.push(move)
                    black_turn = not black_turn

                    node = node.variations[0]

                    S.append(s)
                    R.append(r)
                    idx_batch += 1

                    if idx_batch >= BATCH_SIZE and len(S) >= POOL_SIZE:
                        # Shuffle moves in game
                        idx = list(np.random.permutation(len(S)))
                        S_shuffle = [S[i] for i in idx]
                        R_shuffle = [R[i] for i in idx]
                        S = S_shuffle[BATCH_SIZE:]
                        R = R_shuffle[BATCH_SIZE:]
                        idx_batch = 0
                        yield np.array(S_shuffle[:BATCH_SIZE]), np.array(
                            R_shuffle[:BATCH_SIZE])
Пример #31
0
    def random_black_state(self):
        """
        Returns (state, reward) tuple at black's turn from white's perspective
        - state: np.array [12 pieces x 8 rows x 8 cols]
            - piece order:  wp wn wb wr wq wk bp bn bb br bq bk
            - row order: a b c ... h
            - col order: 1 2 3 ... 8
        - reward: GAMMA^moves_remaining * {-1, 0, 1} (lose, draw, win)
        """
        with open(self.filename) as pgn:
            while True:
                game = chess.pgn.read_game(pgn)
                if game is None:
                    if not self.loop:
                        break
                    pgn.seek(0)
                    self.num_games = self.idx_game
                    self.idx_game = 0
                    continue

                num_moves = int(game.headers["PlyCount"])
                if num_moves < 2:
                    continue

                # Make sure game was played all the way through
                last_node = game.root()
                while last_node.variations:
                    last_node = last_node.variations[0]
                if "forfeit" in last_node.comment:
                    continue

                # Choose a random black-turn state
                # if self.test_set:
                #     if self.num_games:
                #         idx_move = self.idx_moves[self.idx_game]
                #     else:
                #         idx_move = random.randint(1, num_moves // 2) * 2 - 1
                #         self.idx_moves.append(idx_move)
                # else:
                #     idx_move = random.randint(1, num_moves // 2) * 2 - 1
                idx_move = random.randint(1, num_moves // 2) * 2 - 1
                moves_remaining = (num_moves - idx_move) // 2

                # Play moves up to idx_move
                board = game.board()
                node = game.root()
                for i in range(idx_move):
                    board.push(node.variations[0].move)
                    node = node.variations[0]

                # headers["Result"]: {"0-1", "1-0", "1/2-1/2"}
                # result: {-1, 0, 1}
                # Parse result from header
                white_score = game.headers["Result"].split("-")[0].split("/")
                if len(white_score) == 1:
                    result = 2 * int(white_score[0]) - 1
                else:
                    result = 0

                state = state_from_board(board).reshape(
                    (1, NUM_COLORS * NUM_PIECES, NUM_ROWS, NUM_COLS))
                reward = np.array([(GAMMA**moves_remaining) * result])

                self.idx_game += 1
                yield state, reward