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))
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
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
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
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()
def __init__(self, record_list): super(PositionPairDataset, self).__init__() self.record_list = record_list self.board = cshogi.Board()