Pythonプログラミングで

チェスを作る

Stage 8 ゲームを進行する

8-4 リザインを処理する

リザインのイベントコードの処理はこんなもん。

                        
        # resign code
        if main_board.s in ['X', 'x']:
            winner = -main_board.player
            break
                        
                    

「1-0」とかでリザインできることを知らない人のために、脱出用のコマンド X を用意してあげています。

入力している人が負けを認める形にしたいので、winner は相手です。これがもし winner を自分にできるようにしてしまうと、ゲーム始まった瞬間に

UNAVAILABLE

はい俺の勝ちー

とできてしまいますので。

break は大枠の while ループからの脱出。これでゲーム終了させます。

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

"Z" は Stage 9 でやります。

Stage 9 でやります。

UNAVAILABLE

そんな突っかかるなって

これ以外の正規の入力は s_analyze メソッドで対処できますね。対処できるように Stage 7 であんなに頑張って s_analyze をコーディングしたんですから。

では一度ここから先のコードを見てみましょう。

                        
        # motion detection
        motion = main_board.s_analyze()
        # game set (resign)
        if type(motion) is int:
            if motion == EMPTY:
                # necessary to agree to end the game
                if main_board.player == WHITE:
                    print('Do you agree, BLACK (y/n)? >>>', end=' ')
                elif main_board.player == BLACK:
                    print('Do you agree, WHITE (y/n)? >>>', end=' ')
                else:
                    logger.error('UNEXPECTED VALUE of PLAYER in the while loop')
                    print('SYSTEM ERROR')
                    sys.exit('SYSTEM ERROR')
                # when agreed
                if input() in ['y', 'Y']:
                    winner = EMPTY
                    break
                # when rejected
                else:
                    main_board.print(turnmode=turnmode, reverse=False)
                    continue
                    continue
            elif motion == WHITE == -main_board.player:
                winner = WHITE
                break
            elif motion == BLACK == -main_board.player:
                winner = BLACK
                break
            else:
                print('IVNALID INPUT')
                continue
        # invalid input (here, valid motion is conducted)
        if motion == False or main_board.move(*motion) == False:
            print('INVALID INPUT/MOTION')
            continue

        ...
                        
                    
UNAVAILABLE

相変わらずなげーな

プレーヤーによって場合わけすることが多いので、見た目よりも記述量は少なく感じると思いますよ。

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

まず s_analyze の結果を motion という変数に格納しています。

                        
        # motion detection
        motion = main_board.s_analyze()
        # game set (resign)
        if type(motion) is int:
            ...
                        
                    

s_analyze の返り値の型はこんな感じ。

駒を動かすlist[frFILE, frRANK, toFILE, toRANK, promote]
勝敗int白勝ち (1-0)WHITE (== 1)
黒勝ち (0-1)BLACK (== -1)
引き分け (1/2 - 1/2)EMPTY (== 0)
エラーboolFalse

したがって、motion からもリザインを判断できるようにしなければいけません。

UNAVAILABLE

おいおい、1-0 ってちゃんと書いたのにゲーム終わんねーぞクソが

とか言われないようにね。

表の通り、motion が int 型であればリザインですから、

                        
        if type(motion) is int:
                        
                    

として判断します。

if の中身はイベントコードで "X" を入力した時と大体変わらないんですが、引き分けの時はしっかり相手の許可をとりましょう。

UNAVAILABLE

ちょっとこの感じ負ける気しかしないから引き分けにしとくわ

って乱発されたらたまったもんじゃないでしょう。だから必ず相手に同意するか聞いてください。

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

では相手が同意するかお伺いをたてる機能を実装します。

                        
            if motion == EMPTY:
                # necessary to agree to end the game
                if main_board.player == WHITE:
                    print('Do you agree, BLACK (y/n)? >>>', end=' ')
                elif main_board.player == BLACK:
                    print('Do you agree, WHITE (y/n)? >>>', end=' ')
                else:
                    logger.error('UNEXPECTED VALUE of PLAYER in the while loop')
                    print('SYSTEM ERROR')
                    sys.exit('SYSTEM ERROR')
                # when agreed
                if input() in ['y', 'Y']:
                    winner = EMPTY
                    break
                # when rejected
                else:
                    main_board.print(turnmode=turnmode, reverse=False)
                    continue
                        
                    

一つ一つみていきましょう。まず最初の if 分岐は「引き分けかどうか」です。引き分けでなければ相手の同意は不要でしょ?

UNAVAILABLE

ダメだ。勝手に負けるのは許さん

って、漫画とかならよくありそうですが現実ではあまり機会がないでしょう。

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

その次は実際に相手プレーヤーにお伺いする文言です。「引き分けしたいって言ってますけど、よろしいですか?」ということ。

                        
                # necessary to agree to end the game
                if main_board.player == WHITE:
                    print('Do you agree, BLACK (y/n)? >>>', end=' ')
                elif main_board.player == BLACK:
                    print('Do you agree, WHITE (y/n)? >>>', end=' ')
                else:
                    logger.error('UNEXPECTED VALUE of PLAYER in the while loop')
                    print('SYSTEM ERROR')
                    sys.exit('SYSTEM ERROR')
                        
                    

もし答えが yes なら引き分けとしますので、winner を EMPTY にして全体を回してる while ループから脱出します。8-2 からずっと回してるやつ。

                        
                # when agreed
                if input() in ['y', 'Y']:
                    winner = EMPTY
                    break
                        
                    

それ以外ではもちろんゲームを終わらせるわけにはいきませんから、8-4 のヘルプの後のように盤面を再表示して while 先頭に戻ります。

                        
                # when rejected
                else:
                    main_board.print(turnmode=turnmode, reverse=False)
                    continue
                        
                    

ここまでで引き分けのリザインの実装は完了です。

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

負けを認める場合のコードも実装しますよ。てかそもそもこっちが本題。

                        
            elif motion == WHITE == -main_board.player:
                winner = WHITE
                break
            elif motion == BLACK == -main_board.player:
                winner = BLACK
                break
                        
                    

motion が WHITE であれば黒が負けを認めていますので、winner は WHITE, 逆も然りです。またリザインは必ず

自分が負けを認める

形でないといけませんから、motion が WHITE のときは player が BLACK か、逆なら逆かもみてあげる必要があります。

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

最後に motion が int でありながら、ここまでどこにも引っかかってこなかった可哀想な子たちをどうにかしてあげます。

                        
            else:
                print('IVNALID INPUT')
                continue
                        
                    

以上でリザインの処理は終了です。お疲れ様でした。

NEXT 8-6 盤上で駒を動かす