def test_input_features(self):
        aoba_kifu = r'../../data/aoba/arch000032000000.csa'

        board = cshogi.Board()
        for i, kifu in enumerate(CSA.Parser.parse_file(aoba_kifu)):
            if i >= 2048:
                break
            board.reset()

            n = len(kifu.moves)
            hcpes = np.empty(n, dtype=cshogi.HuffmanCodedPosAndEval)
            hcpes['gameResult'] = kifu.win

            feature1a = np.empty((n, FEATURES1_NUM, 9, 9), dtype=np.float32)
            feature2a = np.empty((n, FEATURES2_NUM, 9, 9), dtype=np.float32)
            for j, move in enumerate(kifu.moves):
                board.push(move)
                board.to_hcp(hcpes[j]['hcp'])

                # featureコマンドを作って
                # やねうら王が作った特徴量をファイルに書き出すようにした
                self.engine.position(sfen=board.sfen())
                self.engine.proc.stdin.write('feature'.encode('ascii') + b'\n')
                self.engine.proc.stdin.flush()
                while True:
                    self.engine.proc.stdout.flush()
                    line = self.engine.proc.stdout.readline()
                    if line == '':
                        raise EOFError()
                    break
                file_name = line.strip().decode('shift-jis')
                tmp = np.fromfile(str(self.exe_dir / file_name),
                                  dtype=np.float32)
                tmp = np.reshape(tmp, (FEATURES1_NUM + FEATURES2_NUM, 9, 9))
                feature1a[j] = tmp[:FEATURES1_NUM]
                feature2a[j] = tmp[FEATURES1_NUM:]

            # 学習で使っている特徴量を作成
            feature1b = np.empty((n, FEATURES1_NUM, 9, 9), dtype=np.float32)
            feature2b = np.empty((n, FEATURES2_NUM, 9, 9), dtype=np.float32)
            results = np.empty(n, dtype=np.int32)
            cppshogi.hcpe_decode_with_result(hcpes, feature1b, feature2b,
                                             results)

            self.assertTrue(np.all(feature1a == feature1b))
            self.assertTrue(np.all(feature2a == feature2b))
Example #2
0
def read_kifu_cython(kifu_list):
    positions = []
    parser = cshogi.Parser()
    for filepath in kifu_list:
        parser.parse_csa_file(filepath)
        board = cshogi.Board()
        for move, score in zip(parser.moves, parser.scores):
            hcpe = np.empty(1, dtype=cshogi.HuffmanCodedPosAndEval)
            # hcp
            board.to_hcp(hcpe[0]['hcp'])
            # eval
            hcpe[0]['eval'] = score
            # move
            hcpe[0]['bestMove16'] = cshogi.move16(move)
            # result
            hcpe[0]['gameResult'] = parser.win

            positions.append(hcpe)
            board.push(move)
    return positions
Example #3
0
    def generator():
        data_list = []
        with h5py.File(path, 'r') as f:
            for key1, value1 in f.items():
                for key2, value2 in value1.items():
                    for key3 in value2.keys():
                        data_list.append((key1, key2, key3))

            board = cshogi.Board()
            while True:
                # positive dataの系列
                anchor, positive = get_positive_data(data_list=data_list,
                                                     f=f, board=board)
                # negativeの配列
                negative_list = get_negative_data(
                    data_list=data_list, f=f, board=board,
                    n_data=n_negative_data
                )

                yield anchor, positive, negative_list
Example #4
0
    def test_random(self):
        batch_size = 100
        feature1 = np.empty((batch_size, FEATURES1_NUM, 9, 9),
                            dtype=np.float32)
        feature2 = np.empty((batch_size, FEATURES2_NUM, 9, 9),
                            dtype=np.float32)
        move = np.empty(batch_size, dtype=np.int32)
        result = np.empty(batch_size, dtype=np.float32)
        value = np.empty(batch_size, dtype=np.float32)
        mask = np.empty((batch_size, MAX_MOVE_LABEL_NUM * 9 * 9),
                        dtype=np.float32)

        cppshogi.hcpe_decode_with_mask(
            self.data[:batch_size], feature1, feature2, move, result,
            value, mask
        )

        board = cshogi.Board()
        for i in range(batch_size):
            board.set_hcp(self.data[i:i + 1])

            # 駒を数える
            count = np.zeros(7, dtype=np.int32)
            for p in board.pieces:
                # 手番の情報を消す
                q = p & 0x7
                if p == 0 or q == cshogi.KING:
                    continue
                if (p >> 4) == board.turn:
                    count[self.order[q]] += 1
                else:
                    count[self.order[q]] -= 1
            count += np.asarray(board.pieces_in_hand[board.turn])
            count -= np.asarray(board.pieces_in_hand[1 - board.turn])

            x2 = feature2[i, -7:]
            for j in range(7):
                # 全部値が同じ
                self.assertTrue(np.all(x2[j] == count[j]))
 def __init__(self):
     self.board = cshogi.Board()
import cshogi
import numpy as np
from cshogi import move_drop_hand_piece, move_from, move_is_drop, move_is_promotion, move_to

from src.features.common import get_seq_from_board
from src.utils.shogi import (DOWN, DOWN_LEFT, DOWN_RIGHT, LEFT, MOVE_DIRECTION,
                             MOVE_DIRECTION_PROMOTED, RIGHT, UP, UP2_LEFT,
                             UP2_RIGHT, UP_LEFT, UP_RIGHT)

board = cshogi.Board()


def get_move_label(move, color):
    if not move_is_drop(move):
        from_sq = move_from(move)
        to_sq = move_to(move)
        if color == cshogi.WHITE:
            to_sq = 80 - to_sq
            from_sq = 80 - from_sq

        # file: 筋, rank: 段
        from_file, from_rank = divmod(from_sq, 9)
        to_file, to_rank = divmod(to_sq, 9)
        dir_file = to_file - from_file
        dir_rank = to_rank - from_rank
        if dir_rank < 0 and dir_file == 0:
            move_direction = UP
        elif dir_rank == -2 and dir_file == -1:
            move_direction = UP2_RIGHT
        elif dir_rank == -2 and dir_file == 1:
            move_direction = UP2_LEFT
Example #7
0
def main():
    win_count = 0
    draw_count = 0

    # 初期局面読み込み
    init_positions = []
    if args.initial_positions is not None:
        with open(args.initial_positions) as f:
            for line in f:
                init_positions.append(line.strip()[15:].split(' '))

    for n in range(args.games):
        if __debug__: logging.debug('game {} start'.format(n))

        # 先後入れ替え
        if n % 2 == 0:
            command1 = args.command1
            command2 = args.command2
        else:
            command1 = args.command2
            command2 = args.command1

        # USIエンジン起動
        procs = [
            subprocess.Popen([command1],
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             cwd=os.path.dirname(command1)),
            subprocess.Popen([command2],
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             cwd=os.path.dirname(command2))
        ]

        names = []
        for i, p in enumerate(procs):
            if __debug__: logging.debug('pid = {}'.format(p.pid))
            p.stdin.write(b'setoption name USI_Ponder value false\n')
            for name, value in options_list[(n + i) % 2].items():
                if __debug__:
                    logging.debug('usi option {} {}'.format(name, value))
                p.stdin.write('setoption name {} value {}\n'.format(
                    name, value).encode('ascii'))

            p.stdin.write(b'usi\n')
            p.stdin.flush()

            while True:
                p.stdout.flush()
                line = p.stdout.readline()
                if line[:7] == b'id name':
                    names.append(line.strip()[8:].decode('ascii'))
                    if __debug__: logging.debug('name = {}'.format(names[-1]))
                elif line.strip() == b'usiok':
                    break

            p.stdin.write(b'isready\n')
            p.stdin.flush()

            while True:
                p.stdout.flush()
                line = p.stdout.readline()
                if line.strip() == b'readyok':
                    break

        # 棋譜ファイル初期化
        starttime = datetime.now()
        if args.kifu_dir is not None:
            kifu_path = os.path.join(
                args.kifu_dir,
                starttime.strftime('%Y%m%d_%H%M%S_') + names[0] + 'vs' +
                names[1] + '.kif')
            kifu = KIF.Exporter(kifu_path)

            kifu.header(names, starttime)

        # 初期局面
        board = cshogi.Board()
        if args.initial_positions is not None:
            if n % 2 == 0:
                init_position = random.choice(init_positions)
            for move_usi in init_position:
                move = board.move_from_usi(move_usi)
                if args.kifu_dir is not None: kifu.move(move)
                if __debug__:
                    logging.debug('{:>3} {}'.format(board.move_number,
                                                    move_usi))
                board.push(move)

        # 新規ゲーム
        for p in procs:
            p.stdin.write(b'usinewgame\n')
            p.stdin.flush()

        # 対局
        is_game_over = False
        sec_sum = [0.0, 0.0]
        position = 'position startpos moves'
        repetition_hash = defaultdict(int)
        while not is_game_over:
            for i, p in enumerate(procs):
                if __debug__:
                    engine_id = 'engine1' if (n + i) % 2 == 0 else 'engine2'
                info = None

                # 持将棋
                if board.move_number > args.max_turn:
                    is_game_over = True
                    break

                # position
                line = position
                if __debug__: logging.debug('[{}] {}'.format(engine_id, line))
                p.stdin.write(line.encode('ascii') + b'\n')
                p.stdin.flush()

                # go
                line = 'go btime 0 wtime 0 byoyomi ' + str(args.byoyomi)
                p.stdin.write(line.encode('ascii') + b'\n')
                p.stdin.flush()
                time_start = time.time()

                is_resign = False
                is_nyugyoku = False
                while True:
                    p.stdout.flush()
                    line = p.stdout.readline().strip().decode('ascii')
                    if __debug__:
                        logging.debug('[{}] {}'.format(engine_id, line))
                    if line[:8] == 'bestmove':
                        sec = time.time() - time_start
                        sec_sum[i] += sec
                        move_usi = line[9:].split(' ', 1)[0]
                        if args.kifu_dir is not None:
                            kifu.move(board.move_from_usi(move_usi), sec,
                                      sec_sum[i])
                            if info is not None:
                                kifu.info(info)
                        # 詰みの場合、強制的に投了
                        if info is not None:
                            mate_p = info.find('mate ')
                            if mate_p > 0:
                                is_resign = True
                                if info[mate_p + 5] != '-':
                                    board.push_usi(move_usi)
                                break
                        if move_usi == 'resign':
                            # 投了
                            is_resign = True
                        elif move_usi == 'win':
                            # 入玉勝ち宣言
                            is_nyugyoku = True
                        else:
                            board.push_usi(move_usi)
                            position += ' ' + move_usi
                            repetition_hash[board.zobrist_hash()] += 1
                        break
                    elif line[:4] == 'info' and line.find('score ') > 0:
                        info = line

                # 終局判定
                repetition = board.is_draw()
                if repetition in [
                        cshogi.REPETITION_DRAW, cshogi.REPETITION_WIN,
                        cshogi.REPETITION_LOSE
                ] and repetition_hash[board.zobrist_hash()] == 4:
                    break
                repetition = cshogi.NOT_REPETITION
                if is_resign or is_nyugyoku or board.is_game_over():
                    is_game_over = True
                    break

        # 棋譜に結果出力
        if repetition == REPETITION_DRAW:
            win = 2
            if args.kifu_dir is not None:
                kifu.end('sennichite', 0.0, sec_sum[i])
        elif repetition == REPETITION_WIN:
            win = cshogi.BLACK if board.turn == cshogi.WHITE else cshogi.WHITE
            if args.kifu_dir is not None:
                kifu.end('illegal_win', 0.0, sec_sum[i])
        elif repetition == REPETITION_LOSE:
            win = cshogi.WHITE if board.turn == cshogi.WHITE else cshogi.BLACK
            if args.kifu_dir is not None:
                kifu.end('illegal_lose', 0.0, sec_sum[i])
        elif not board.is_game_over() and board.move_number > args.max_turn:
            win = 2
            if args.kifu_dir is not None:
                kifu.end('draw', 0.0, sec_sum[i])
        elif is_nyugyoku:
            win = board.turn
            if args.kifu_dir is not None:
                kifu.end('win', sec, sec_sum[i])
        else:
            win = cshogi.BLACK if board.turn == cshogi.WHITE else cshogi.WHITE
            if args.kifu_dir is not None:
                if is_resign:
                    kifu.end('resign', sec, sec_sum[i])
                else:
                    kifu.end('resign', 0.0, sec_sum[i])
        if args.kifu_dir is not None:
            kifu.close()

        # 勝敗カウント
        if n % 2 == 0 and win == shogi.BLACK or n % 2 == 1 and win == shogi.WHITE:
            win_count += 1
        elif win == 2:
            draw_count += 1

        if n + 1 == draw_count:
            win_rate = 0.0
        else:
            win_rate = win_count / (n + 1 - draw_count)

        logging.info(
            'game {} result : win = {}, win count = {}, draw count = {}, win rate = {:.1f}%'
            .format(n, win, win_count, draw_count, win_rate * 100))

        # USIエンジン終了
        for p in procs:
            p.stdin.write(b'quit\n')
            p.stdin.flush()
            p.wait()
Example #8
0
 def __init__(self, record_list):
     super(PositionPairDataset, self).__init__()
     self.record_list = record_list
     self.board = cshogi.Board()