Stage 10 記録からゲームを進める
10-4 棋譜からゲームを再現する機能を実装する
次は readmode.py へ行ってもらいます。
#! /usr/bin/env python3
# readmode.py
# programmed by Saito-Saito-Saito
# explained on https://Saito-Saito-Saito.github.io/chess
# last updated: 16 August 2020
import sys
from config import *
import board
local_logger = setLogger(__name__)
def readmode(turnmode=False, reverse=False, logger=None):
### LOGGER SETTING
logger = logger or local_logger
# initializing the board
main_board = board.Board()
main_board.print()
print('ENTER TO START')
input()
while True:
### DISPLAYING TURN NO. AND PLAYER
if main_board.player == WHITE:
print('\n{}\tWHITE'.format(main_board.turn), end='\t')
new_board = main_board.tracefile(main_board.turn, BLACK, False)
elif main_board.player == BLACK:
print('\n{}\tBLACK'.format(main_board.turn), end='\t')
new_board = main_board.tracefile(main_board.turn + 1, WHITE, False)
else:
logger.error('UNEXPECTED VALUE of PLAYER in readmode')
print('SYSTEM ERROR')
sys.exit('SYSTEM ERROR')
### DISPLAYING THE RESULT
if type(new_board) is int:
if new_board == EMPTY:
print('1/2-1/2\n\nDRAW')
return
elif new_board == WHITE:
print('1-0\n\nWHITE WINS')
return
elif new_board == BLACK:
print('0-1\n\nBLACK WINS')
return
else:
logger.error('UNEXPECTED VALUE of new_board in readmode')
print('SYSTEM ERROR')
sys.exit('SYSTEM ERROR')
# moving a piece
else:
main_board = new_board
print(main_board.s)
main_board.print(turnmode=turnmode, reverse=reverse)
### EXIT CODE
print('ENTER TO NEXT / X TO QUIT ', end='')
if input() in ['X', 'x']:
print('QUITTED')
return
if __name__=="__main__":
readmode()
sys, config, board をインポートして、local_logger を設定します。もちろん config.py の中身は config. を付けなくてもいいようにしてください。
import sys
from config import *
import board
local_logger = setLogger(__name__)
では readmode 関数へ入りましょう。
まずはいつも通り引数の確認です。
def readmode(turnmode=False, reverse=False, logger=None):
### LOGGER SETTING
logger = logger or local_logger
turnmode や reverse は Board クラスの print インスタンスに入れる引数です。
なんで reverse を一緒に使うんだ?
詳しくは後述しますけれども、tracefile メソッドが指定のターン・プレイヤーの手番
直前
までしか再現しないことに原因がありますね。
~~~~~~~~~~~~~~~
main_board インスタンスを宣言して盤面を初期化したら、まずは読み取りモードを使うユーザーに心の準備をする時間をあげます。それが "ENTER TO START" の部分。
# initializing the board
main_board = board.Board()
main_board.print()
print('ENTER TO START')
input()
これあったほうがいいですよ。
え?なんでもう駒動いてんの??
ってなりますから。
while ループに入ります。
while True:
~~~~~~~~~~~~~~~
ループの最初では「第何ターンのどちらの番か」を明記してあげます。
### DISPLAYING TURN NO. & PLAYER
if main_board.player == WHITE:
print('\n{}\tWHITE'.format(main_board.turn), end='\t')
new_board = main_board.tracefile(main_board.turn, BLACK, False)
elif main_board.player == BLACK:
print('\n{}\tBLACK'.format(main_board.turn), end='\t')
new_board = main_board.tracefile(main_board.turn + 1, WHITE, False)
else:
logger.error('UNEXPECTED VALUE of PLAYER in readmode')
print('SYSTEM ERROR')
sys.exit('SYSTEM ERROR')
また new_board には手番が終わった後の状況を tracefile を使って代入します。
### DISPLAYING TURN NO. & PLAYER
if main_board.player == WHITE:
print('\n{}\tWHITE'.format(main_board.turn), end='\t')
new_board = main_board.tracefile(main_board.turn, BLACK, False)
elif main_board.player == BLACK:
print('\n{}\tBLACK'.format(main_board.turn), end='\t')
new_board = main_board.tracefile(main_board.turn + 1, WHITE, False)
else:
logger.error('UNEXPECTED VALUE of PLAYER in readmode')
print('SYSTEM ERROR')
sys.exit('SYSTEM ERROR')
でもターン番号とかプレーヤーの値とかおかしくねえか?
あくまで「プレーヤーの手番が終わった後の盤面」を代入する点に注意してください。tracefile は
destination の直前の状態にする
メソッドですよ。
白が手番を終えたところまで tracefile で遡りたければ、引数は main_board.turn, BLACK ですし、黒が終えたところまで遡りたければ引数は main_board.turn + 1, WHITE です。しっかり確認してください。
~~~~~~~~~~~~~~~
プレーヤーまで表示し終わったら new_board の型によって場合分けします。
new_board が int 型なら WHITE/BLACK/EMPTY のいずれかがリターンされていて、勝敗がついています。勝者に応じて "1-0", "0-1" などと、ユーザーに勝敗を見せましょう。
if type(new_board) is int:
if new_board == EMPTY:
print('1/2-1/2\n\nDRAW')
return
elif new_board == WHITE:
print('1-0\n\nWHITE WINS')
return
elif new_board == BLACK:
print('0-1\n\nBLACK WINS')
return
else:
logger.error('UNEXPECTED VALUE of new_board in readmode')
print('SYSTEM ERROR')
sys.exit('SYSTEM ERROR')
それ以外では駒を動かしている場合です。new_board を main_board に突っ込んでください。
# moving a piece
else:
main_board = new_board
print(main_board.s)
main_board.print(turnmode=turnmode, reverse=reverse)
そして print もお忘れなく。特に turnmode が True のときは reverse も True にとなるように引数を調整した方がいいかと思われます。
もしこれを逆にしてしまうと、main_board.player と盤面の向きが逆転してしまいますから。
~~~~~~~~~~~~~~~
これで 1 手です。エンターキーで次に進めるようにします。ユーザーが
ちょいとトイレ行ってくるわ
とかいろんな理由をつけて途中退室することも考えられますので、終了コード "X" を用意してあげます。
### EXIT CODE
print('ENTER TO NEXT / X TO QUIT ', end='')
if input() in ['X', 'x']:
print('QUITTED')
return