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 を使いなさい」というときに使ってください。特に入力がなければ駒は初期配置にセッティングされます。
このボード使えって、そんなことある?
具体的には盤面を複製する場合を考えています。例えば
実際に駒動かしてみてどうなるかみてみたいけど、今の盤面は残しておきたい
とか。
よくわからんわ
後々ありがたいくらいにわかりますよ。
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 をデフォルトにとります。
要は盤面の情報全部突っ込めってことやろ
その通りです。
~~~~~~~~~~~~~~~
中身に入りましょう。まずは盤面を設定します。すでにある盤面を使うかどうかは、引数のリストの要素の数が 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 に突っ込まれたリストをそのまま使ってこのクラスで中身をいじってしまうと、入力元のクラス外のリストまで影響を受けてしまいますよ。
ああ、そういうことね。理解したわ
わからなければ上のリンクから飛んで備忘録を見るか、他所で丁寧な説明を受けてきてくださいな。な?
ということですでにある盤面を引き込むときは 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
これでコンストラクタは終わりました。お疲れ様です。