CUI操作ベースのチェス
ライブラリのおかげでCUI操作ベースのチェスを作るのは非常に簡単です。
ライブラリ
必要なライブラリはchess
です。Google Colabではデフォルトで入っていないのでGoogle Colabをお使いの方はインストールしてください。
!pip install chess
必要なライブラリをインポートします。
import chess
import chess.svg
from IPython.display import SVG, display
ただし、SVG形式での表示ではなくCUI表示でいいという方は、
import chess
だけで大丈夫です。
メイン関数
メイン関数はこのようになります。ライブラリを活用することでかなりシンプルなコードになりました。is_game_over()
はそのまま、ゲームオーバーかどうかを判定するメソッドです。ゲームおーばになるまでwhile
でループを回しています。
def main():
board = chess.Board()
while not board.is_game_over():
print_board(board)
move_str = input("手を入力してください (例: e2e4): ")
try:
move = chess.Move.from_uci(move_str)
if move in board.legal_moves:
board.push(move)
else:
print("不正な手です")
except Exception as e:
print("入力エラー:", e)
print_board(board)
print("ゲーム終了:", board.result())
表示メソッド
表示メソッドはこのようになります。
def print_board(board):
svg = chess.svg.board(board=board, size=500)
display(SVG(data=svg))
完全にCUIベースで操作したい場合は
def print_board(board):
print(board)
としてください。この場合の盤面の出力は、
のようになります。
全体
全体のコードは下のようになります。
import chess
import chess.svg
from IPython.display import SVG, display
def print_board(board):
svg = chess.svg.board(board=board, size=500)
display(SVG(data=svg))
def main():
board = chess.Board()
while not board.is_game_over():
print_board(board)
move_str = input("手を入力してください (例: e2e4): ")
try:
move = chess.Move.from_uci(move_str)
if move in board.legal_moves:
board.push(move)
else:
print("不正な手です")
except Exception as e:
print("入力エラー:", e)
print_board(board)
print("ゲーム終了:", board.result())
if __name__ == "__main__":
main()
StockFishを使う
基本的な使い方
チェスの最強エンジンと言えばStockFishです。StockFishをGoogleColabで使うには、chess.engine
をインポートします。
import chess.engine
エンジンを起動するには、
engine = chess.engine.SimpleEngine.popen_uci("/usr/games/stockfish")
のように書きます[1]。
そして、現状の盤面の状態bord
と思考時間制約think_time
を渡して次の手をStockFishから取得するには、
def get_stockfish_move(board, engine, think_time = 0.3):
result = engine.play(board, chess.engine.Limit(time=think_time))
return result.move
と書きます。
StockFish vs ランダムプレイヤー
チェスにあまり慣れていない人にとってCUI操作ベースでゲーム終了まで実験するだけでもかなりの労力だと思います。
そこで、試しに、合法手の中からランダムに手を選ぶプレイヤーを定義してStockFishと戦わせてみましょう。全体のコードは次のようになります。
import chess
import chess.engine
import random
# --- 関数定義 ---
# ランダムな合法手を選ぶ
def get_random_legal_move(board):
legal_moves = list(board.legal_moves)
return random.choice(legal_moves)
# Stockfishの最善手を取得する
def get_stockfish_move(board, engine, think_time = 0.3):
result = engine.play(board, chess.engine.Limit(time=think_time))
return result.move
# 対戦のメインループ
def stockfish_vs_random(engine):
board = chess.Board()
move_count = 0
while not board.is_game_over():
if board.turn == chess.WHITE:
move = get_random_legal_move(board)
print(f"ランダムプレイヤーの手: {move}")
else:
# print("Stockfish が思考中...")
move = get_stockfish_move(board, engine)
print(f"Stockfish の手: {move}")
board.push(move)
move_count += 1
print("\n=== ゲーム終了 ===")
#print(board)
print("結果:", board.result())
print(f"総手数: {move_count}手")
# main関数
def main():
# Stockfishエンジンを起動
engine = chess.engine.SimpleEngine.popen_uci("/usr/games/stockfish")
# 対戦開始
stockfish_vs_random(engine)
# エンジン終了
engine.quit()
# 実行
if __name__ == "__main__":
main()
試合の運びは次のようになりました。
ランダムプレイヤーの手: a2a3
Stockfish の手: e7e5
ランダムプレイヤーの手: h2h4
Stockfish の手: d7d5
ランダムプレイヤーの手: e2e4
Stockfish の手: d5e4
ランダムプレイヤーの手: d1h5
Stockfish の手: f8d6
ランダムプレイヤーの手: h5g5
Stockfish の手: g8f6
ランダムプレイヤーの手: f1b5
Stockfish の手: c7c6
ランダムプレイヤーの手: c2c3
Stockfish の手: c6b5
ランダムプレイヤーの手: c3c4
Stockfish の手: e8g8
ランダムプレイヤーの手: g5g7
Stockfish の手: g8g7
ランダムプレイヤーの手: c4c5
Stockfish の手: d6c5
ランダムプレイヤーの手: g1e2
Stockfish の手: f6g4
ランダムプレイヤーの手: d2d3
Stockfish の手: c5f2
ランダムプレイヤーの手: e1d2
Stockfish の手: d8d3
=== ゲーム終了 ===
結果: 0-1
総手数: 26手
26手で黒番のStockFishが勝利です。コードを少しいじれば、ソフト同士の対戦なども簡単に行うことができます。
現代の強力なチェスソフト(StockFishやKomodoなど)同士の試合は高い確率で引き分けになります。
特定の乱数要素を加えた上で膨大な試合数を課し、統計データを取るのも面白いかも知れません。
pygameを使う
pygameを使えば、マウス操作が可能なデスクトップアプリにすることもできます。こちらのGitHubリポジトリにて作成したものを公開しています。
デスクトップ版でStockFishを使うときはStockFishのGitHubからエンジンをダウンロードしてローカルで動かすようにすることをお勧めします。