Pythonプログラミングで

チェスを作る

Stage 10 記録からゲームを進める

10-1 記録ファイルを読み込む

これ以降は board.py ファイル Board クラスの tracefile メソッドにコーディングします。

                        
    def tracefile(self, destination_turn, destination_player, isrecwrite=True, logger=None):
        ### LOGGER SETTING
        logger = logger or self.logger
        

        # in case back to the first
        if destination_turn == 1 and destination_player == WHITE:
            local_board = Board()
            return local_board


        # preparing (initializing) the sub file; all the local moves are recorded on the sub file
        open(SUBRECADDRESS, 'w').close()
        # reading the main file
        f = open(MAINRECADDRESS, 'r')
        line = f.read()
        f.close()
        # deleting first and last spaces
        line = line.strip()
        logger.info('line is "{}"'.format(line))

        # local Board
        local_board = Board()
        

        # DETECTING EACH LETTER IN LINE
        for letter in line:
            # when you come to the end of a sentence
            if letter in [' ', '\t', '\n', ',', '.']:
                logger.info('local_board.s is {}'.format(local_board.s))
                motion = local_board.s_analyze()
                # normal motion
                if type(motion) is list:
                    local_board.move(*motion)
                    local_board.record(SUBRECADDRESS)  # all the local moves are recorded on the sub file
                    # parameter manipulations
                    if local_board.player == BLACK:
                        local_board.turn += 1
                    local_board.player *= -1
                    # reaching destination
                    if local_board.turn == destination_turn and local_board.player == destination_player:
                        logger.info('trace succeeded')
                        if isrecwrite:
                            # copying the file
                            f = open(MAINRECADDRESS, 'w')
                            g = open(SUBRECADDRESS, 'r')
                            f.write(g.read())
                            f.close()
                            g.close()
                        return local_board
                # game set
                elif type(motion) is int:
                    print('GAME SET')
                    if isrecwrite:
                        # copying the record
                        f = open(MAINRECADDRESS, 'w')
                        g = open(SUBRECADDRESS, 'r')
                        f.write(g.read())
                        f.close()
                        g.close()
                    return motion
                # initializing local_board.s
                local_board.s = ''
            # the sentence does not end yet
            else:
                local_board.s = ''.join([local_board.s, letter])
                logger.debug('local_board.s = {}'.format(local_board.s))

        # last one local_board.s; the same as in the for loop
        logger.info('local_board.s is {}'.format(local_board.s))
        motion = local_board.s_analyze()
        if type(motion) is list:
            local_board.move(*motion)
            local_board.record(SUBRECADDRESS)
            if local_board.player == BLACK:
                local_board.turn += 1
            local_board.player *= -1
            # reaching destination
            if local_board.turn == destination_turn and local_board.player == destination_player:
                logger.info('trace succeeded')
                if isrecwrite:
                    f = open(MAINRECADDRESS, 'w')
                    g = open(SUBRECADDRESS, 'r')
                    f.write(g.read())
                    f.close()
                    g.close()
                return local_board
        elif type(motion) is int:
            if isrecwrite:
                f = open(MAINRECADDRESS, 'w')
                g = open(SUBRECADDRESS, 'r')
                f.write(g.read())
                f.close()
                g.close()
            return motion

        # reaching here, you cannot trace
        logger.warning('FAILED TO BACK')
        return self
                        
                    
UNAVAILABLE

ウッソ......だろ......

こいつを全 4 回に分けてご説明します。

~~~~~~~~~~~~~~~

指定のターン・プレーヤーの手番の直前までゲームを進める機能です。例えばこういう記録がついていたとして

1	a4          c5          
2	g3          Qa5         
3	e4          Qa6                                 
                    

第 2 ターンの黒まで戻ると指定すると Qa5 を実行する

まで戻ります。つまり盤面はこう。

UNAVAILABLE
UNAVAILABLE

Qa5 の前だから、まだ Qa5 してないんだな。

その通りです。

~~~~~~~~~~~~~~~

まずは引数を見ていきましょう。

                        
    def tracefile(self, destination_turn, destination_player, isrecwrite=True, logger=None):
                        
                    
destination_turnゴールとなる指定ターン
destination_playerゴールとなる指定プレーヤー
isrecwrite記録を書き換えるか

先ほどの例で言えば、destination_turn=2, destination_player=BLACK で第 2 ターン黒が Qa5 とする

まで戻ってくれます。

中身に入ります。最初はやっぱりロガーを設定します。

                        
    def tracefile(self, destination_turn, destination_player, isrecwrite=True, logger=None):
        ### LOGGER SETTING
        logger = logger or self.logger
                        
                    

ここは Board クラスの中身ですから、ロガーは指定のない限りクラスのロガーを使うのがいいでしょう。

~~~~~~~~~~~~~~~

ここから先ではメソッド内で local_board という Board の影武者インスタンスを作成し、これをいじります。

UNAVAILABLE

何回かやったな

ええ、6-3 なんかで。

コードに戻りましょう。まず第 1 ターンで白が駒を動かす直前で操作を止める場合、まだ駒は初期配置ですから、local_board を初期設定してすぐにリターンしてください。

                        
        # in case back to the first
        if destination_turn == 1 and destination_player == WHITE:
            local_board = Board()
            return local_board
                        
                    
UNAVAILABLE

別に場合わけなんてせんでええやろ

なんで場合わけが必要なのかはもうちょい先になるまでわかりませんよ。

~~~~~~~~~~~~~~~

そのほか駒の動きを要する場合は、まず SUBRECADDRESS を書き込みモード 'w' で開いた後すぐに閉じて初期化、真っ白にします。

                        
        # preparing (initializing) the sub file; all the local moves are recorded on the sub file
        open(SUBRECADDRESS, 'w').close()
                        
                    

次いで MAINRECADDRESS の中身をすべて line に読み取ってしまいます。同時に両端にある空白文字と改行文字を strip メソッドですべて消します。

                        
        # reading the main file
        f = open(MAINRECADDRESS, 'r')
        # deleting first and last spaces
        line = f.read()
        f.close()
        # deleting first and last spaces
        line = line.strip()
        logger.info('line is "{}"'.format(line))
                        
                    

~~~~~~~~~~~~~~~

line には棋譜として意味のある文だけでなく、例えばターン番号を表す数字が入っているなど、無視しなければいけない文があります。例えばこんな感じ。

1\ta4          c5          \n2\tg3          Qa5         

UNAVAILABLE

タブ文字とか改行が余分に入ってんのか

無視すべき文を無視し、拾うべき文を拾う。これが tracefile に求められる機能です。

それでは local_board を宣言して一文一文に目を向けていきましょう。

                        
        # local Board
        local_board = Board()
                        
                    

NEXT 10-2 棋譜の内容を解読する