Pythonプログラミングで

チェスを作る

Stage 6 勝敗を判定する

6-2 チェックの数を数える

お次はチェックの判定です。

まあ判定と呼ぶくらいですからチェックの有無を True / False でリターンするメソッドかけば事足りますよ。でもダブルチェックとかトリプルチェックという表し方がチェスの棋譜にはありまして、それを見据えて何ヶ所でチェックされているかをリターンする機能が欲しいなと。

UNAVAILABLE

なんでめんどくせーことすんだよ

プログラミングはいつもユーザー第一ですから。

UNAVAILABLE

じゃあターミナルで棋譜使ってチェスなんてやらせるなよ

それはごもっともだ。

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

で、checkcounter メソッドです。

                        
    def checkcounter(self, checkee, logger=None):
        ### LOGGER SETTING
        logger = logger or self.logger
        
        ### SEARCHING FOR CHECKEE'S KING
        TO = self.king_place(checkee)
        try:
            toFILE = TO[FILE]
            toRANK = TO[RANK]
        except:
            logger.info('THERE IS NO KING ON THE BOARD')
            return False

        # COUNTING UP CHECKS
        count = 0
        # searching all the squares, count up the checking pieces
        for frFILE in range(SIZE):
            for frRANK in range(SIZE):
                # pawn might capture the king by promoting, so do not forget promote=Q or something
                if fundam.PosNeg(self.board[frFILE][frRANK]) == -checkee and self.motionjudge(frFILE, frRANK, toFILE, toRANK, Q):
                    logger.info('CHECK: {}, {} -> {}, {}'.format(frFILE, frRANK, toFILE, toRANK))
                    count += 1
        # if checkee is not checked, return 0
        return count
                        
                    

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

中身を見ていきましょう。

                        
    def checkcounter(self, checkee, logger=None):
                        
                    

引数の checkee は

チェックを受けている

プレーヤー番号です。間違えないでください。しっかりわかるようにあえてこの名前をつけたんですから。それなりに英語をやった人ならわかるでしょ?

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

中に入ったらまずはロガーを設定して、

                        
    def checkcounter(self, checkee, logger=None):
        ### LOGGER SETTING
        logger = logger or self.logger
                        
                    

6-1 で作った king_place で checkee のキングを探します。そもそもキングがいなければ相手はチェックのしようがないので、キングがいなければ別処理。

                        
        ### SEARCHING FOR CHECKEE'S KING
        TO = self.king_place(checkee)
        try:
            toFILE = TO[FILE]
            toRANK = TO[RANK]
        except:
            logger.info('THERE IS NO KING ON THE BOARD')
            return False
                        
                    

もしキングがいない (king_place が EMPTY つまり 0) なら、TO の型は list ではなく int になりますから、try 文の中でわざとエラーを起こして except へ入り False をリターンする仕組みになっています。

UNAVAILABLE

エラー起きなかったらそのまま TO にキングの位置が入るんやな

そうです。

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

その後チェックの個数を記録する count という変数を用意します。

                        
        # COUNTING UP CHECKS
        count = 0
        # searching all the squares, count up the checking pieces
        for frFILE in range(SIZE):
            for frRANK in range(SIZE):
                        
                    

for 文によって盤面上すべての相手の駒の座標を frFILE, frRANK の中に入れ

                        
        # COUNTING UP CHECKS
        count = 0
        # searching all squares for opponent's piece to reach KING
        for frFILE in range(SIZE):
            for frRANK in range(SIZE):
                # pawn might capture the king by promoting, so do not forget promote=Q or something
                if fundam.PosNeg(self.board[frFILE][frRANK]) == -checkee and self.motionjudge(frFILE, frRANK, toFILE, toRANK, Q):
                        
                    

駒が checkee にとって相手のものだったら

                        
        for frFILE in range(SIZE):
            for frRANK in range(SIZE):
            # pawn might capture the king by promoting, so do not forget promote=Q or something
            if fundam.PosNeg(self.board[frFILE][frRANK]) == -checkee and self.motionjudge(frFILE, frRANK, toFILE, toRANK, Q):
                logger.info('CHECK: {}, {} -> {}, {}'.format(frFILE, frRANK, toFILE, toRANK))
                count += 1
                        
                    

motionjudge を実行してみます。

                        
        for frFILE in range(SIZE):
            for frRANK in range(SIZE):
            # pawn might capture the king by promoting, so do not forget promote=Q or something
            if fundam.PosNeg(self.board[frFILE][frRANK]) == -checkee and self.motionjudge(frFILE, frRANK, toFILE, toRANK, Q):
                logger.info('CHECK: {}, {} -> {}, {}'.format(frFILE, frRANK, toFILE, toRANK))
                count += 1
                        
                    

もし motionjudge が True をリターンすれば「キングのいるマスに行ける」つまりチェックしていることになりますから、チェックの数を数えてくれてる count の値を増やしてあげましょう。この時ロガーも一緒に出してあげると親切ですね。

                        
            # pawn might capture the king by promoting, so do not forget promote=Q or something
            if fundam.PosNeg(self.board[frFILE][frRANK]) == -checkee and self.motionjudge(frFILE, frRANK, toFILE, toRANK, Q):
                logger.info('CHECK: {}, {} -> {}, {}'.format(frFILE, frRANK, toFILE, toRANK))
                count += 1
                        
                    

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

ループを抜けたら count をリターンします。

                        
        # if checkee is not checked, return 0
        return count
                        
                    

つまりチェックされている回数が返されます。もしチェックされていなければ

リターンは 0

です。False ではないことに注意してください。

NEXT 6-3 チェックメイト・ステイルメイトを判定する