Pythonプログラミングで

チェスを作る

Stage 3 盤面のクラスの基本機能を作る

3-1 コンストラクタを作る

このステージでは board.py ファイルを使っていきます。お手元にご用意ください。

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

ファイルの頭で様々インポートを済ませたら、まずはロガー local_logger を宣言します。名前は __name__ つまりこのモジュール(ファイル)に合わせます。

                        
local_logger = setLogger(__name__)
                        
                    

それではクラスに入りましょう。コンストラクタをコーディングしますよ。

                        
    def __init__(self, *, board=[], target=[OVERSIZE, OVERSIZE], castl_k=[WHITE, BLACK], castl_q=[WHITE, BLACK], player=WHITE, turn=1, s='', logger=local_logger):
        ### BORAD COPYING (NOTE: when copying any list, you have to use copy.deepcopy)
        if len(board) == SIZE:
            self.board = copy.deepcopy(board)
        ### BOARD INITIALIZING
        else:
            # [0][0] is white's R, [0][1] is white's P, ...
            self.board = [
                [R, P, 0, 0, 0, 0, -P, -R],
                [N, P, 0, 0, 0, 0, -P, -N],
                [B, P, 0, 0, 0, 0, -P, -B],
                [Q, P, 0, 0, 0, 0, -P, -Q],
                [K, P, 0, 0, 0, 0, -P, -K],
                [B, P, 0, 0, 0, 0, -P, -B],
                [N, P, 0, 0, 0, 0, -P, -N],
                [R, P, 0, 0, 0, 0, -P, -R]
            ]
        self.ep_target = copy.deepcopy(target) # for en passan
        self.castl_k = copy.deepcopy(castl_k)   # for castling
        self.castl_q = copy.deepcopy(castl_q)   # for castling
        self.turn = turn  # starts from 1
        self.player = player
        self.s = s  # for motion analyzing and recording
        self.logger = logger
                        
                    

引数はざっとこんな感じです。

board盤面
targetアンパッサンで使用
castl_kキャスリングで使用
castl_qキャスリングで使用
player手番のプレーヤー
sプレーヤーが入力した棋譜
turn手番のターン数
loggerクラスで使うロガー

board はすでにある盤面を継続したいときに使います。代入するのは board[file][rank] の形をとるような board リストです。「この board を使いなさい」というときに使ってください。特に入力がなければ駒は初期配置にセッティングされます。

UNAVAILABLE

このボード使えって、そんなことある?

具体的には盤面を複製する場合を考えています。例えば

UNAVAILABLE

実際に駒動かしてみてどうなるかみてみたいけど、今の盤面は残しておきたい

とか。

UNAVAILABLE

よくわからんわ

後々ありがたいくらいにわかりますよ。

                        
def __init__(self, *, board=[], target=[OVERSIZE, OVERSIZE], castl_k=[WHITE, BLACK], castl_q=[WHITE, BLACK], player=WHITE, turn=1, s='', logger=local_logger):
                        
                    

target はアンパッサンで、castl_k/castl_q はキャスリングで使いますので、今はこの通りにコーディングしてください。ちゃんとあとのステージで解説します。

                        
def __init__(self, *, board=[], target=[OVERSIZE, OVERSIZE], castl_k=[WHITE, BLACK], castl_q=[WHITE, BLACK], player=WHITE, turn=1, s='', logger=local_logger):
                        
                    

player は現在手番のプレーヤー、turn は手数を表します。

                        
def __init__(self, *, board=[], target=[OVERSIZE, OVERSIZE], castl_k=[WHITE, BLACK], castl_q=[WHITE, BLACK], player=WHITE, turn=1, s='', logger=local_logger):
                        
                    

s はプレーヤーが入力した駒の動きを棋譜の形で入れます。

                        
def __init__(self, *, board=[], target=[OVERSIZE, OVERSIZE], castl_k=[WHITE, BLACK], castl_q=[WHITE, BLACK], player=WHITE, turn=1, s='', logger=local_logger):
                        
                    

ロガー logger は local_logger をデフォルトにとります。

UNAVAILABLE

要は盤面の情報全部突っ込めってことやろ

その通りです。

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

中身に入りましょう。まずは盤面を設定します。すでにある盤面を使うかどうかは、引数のリストの要素の数が 2-2 で設定した SIZE と同じかどうかで判断できますね。ちゃんとした盤面を表していれば len(board) って file の数と同じはずですから。

                        
        ### BOARD COPYING (NOTE: when copying any list, you have to use copy.deepcopy)
        if len(board) == SIZE:
            self.board = copy.deepcopy(board)
                        
                    

また、リストの盤面をメソッドに引き込むときは特に注意が必要ですよ。下手に代入なんかしないでください。

board はリスト型ですが、リスト型ってミュータブルですので、board に突っ込まれたリストをそのまま使ってこのクラスで中身をいじってしまうと、入力元のクラス外のリストまで影響を受けてしまいますよ。

UNAVAILABLE

ああ、そういうことね。理解したわ

わからなければ上のリンクから飛んで備忘録を見るか、他所で丁寧な説明を受けてきてくださいな。な?

ということですでにある盤面を引き込むときは copy モジュールの copy.deepcopy メソッドを使います。

                        
        # NOTE: when copying any list, you have to use copy.deepcopy
        if len(board) == SIZE:
            self.board = copy.deepcopy(board)
                        
                    

代入しないときは初期配置にしてください。

                        
        ### BOARD INITIALIZING
        else:
            # [0][0] is white's R, [0][1] is white's P, ...
            self.board = [
                [R, P, 0, 0, 0, 0, -P, -R],
                [N, P, 0, 0, 0, 0, -P, -N],
                [B, P, 0, 0, 0, 0, -P, -B],
                [Q, P, 0, 0, 0, 0, -P, -Q],
                [K, P, 0, 0, 0, 0, -P, -K],
                [B, P, 0, 0, 0, 0, -P, -B],
                [N, P, 0, 0, 0, 0, -P, -N],
                [R, P, 0, 0, 0, 0, -P, -R]
            ]
                        
                    

board の外側のインデックスfile を、内側が rank を表しますから、[0, 0] (=[1 - 1, 1 - 1]) は 白のルークを、[0, 1] (=[1 - 1, 2 - 1]) は白のポーンを入れるんですよ。黒の駒にはマイナスを付け忘れないこと。

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

target や castl_k, castl_q は今はコードをコピペしてください。実際使うときにならないと、説明があんまりよくわからないので。

                        
        self.ep_target = copy.deepcopy(target) # for en passan
        self.castl_k = copy.deepcopy(castl_k)   # for castling
                        
                    

turn や player, s, logger といったイミュータブルのものは何の心配もせずとも代入しちゃって結構です。

                        
        self.turn = turn  # starts from 1
        self.player = player
        self.s = s  # for motion analyzing and recording
        self.logger = logger
                        
                    

これでコンストラクタは終わりました。お疲れ様です。

NEXT 3-2 盤面を表示する