Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@mizar
Last active May 31, 2022 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mizar/a6874e89405afe6532d512a9a4e53ae1 to your computer and use it in GitHub Desktop.
Save mizar/a6874e89405afe6532d512a9a4e53ae1 to your computer and use it in GitHub Desktop.
将棋AI:USIエンジン:ランダムプレイヤー
* text=auto
*.bat text eol=crlf
*.cmd text eol=crlf
*.sh text eol=lf
@echo off
py randomplayer.py
#!/bin/python3
from cshogi import Board, move_to_usi
from random import choice
# ## 参考文献:
# - 将棋所:USIプロトコルとは http://shogidokoro.starfree.jp/usi.html
# - cshogi: 高速なPythonの将棋ライブラリ https://github.com/TadaoYamaoka/cshogi
# - 参考書籍: 強い将棋ソフトの創りかた https://book.mynavi.jp/ec/products/detail/id=126887
# - USIエンジン状態遷移図(抄) https://gist.github.com/mizar/299fc1e78e17f694761e51714d9f562c
# - 強い将棋AIエンジンの例 (長時間の探索など): [python-dlshogi2](https://github.com/TadaoYamaoka/python-dlshogi2)
# - 少し強い将棋AIエンジンの例 (現局面のみ推論): [ポリシープレイヤー](https://gist.github.com/mizar/3335181fb6a88d40fcbe3d1b463e9d8d)
# - 参考動画: 【プログラミングミリしら勢向け】将棋AIを作って動かそう!【コラボ配信】 https://youtu.be/BOfnFbwyjFU (自分の手番で投了する将棋AIエンジン)
# License: GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
# 平手初期局面のSFEN文字列
SFEN_HIRATE = "lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1"
# 局面情報
board = Board()
# 先読みモード
ponder = False
while True:
# コマンド入力行全体
cmdline = input()
# 空白文字区切りに分割
cmds = cmdline.split()
# 先頭コマンド節取り出し
cmd0 = cmds.pop(0)
# USI応答
if cmd0 == "usi":
print("id name RandomPlayer")
print("usiok")
continue
# 初期化
if cmd0 == "isready":
board.set_sfen(SFEN_HIRATE)
ponder = False
print("readyok")
continue
# 局面設定
if cmd0 == "position":
# 次のコマンド節
cmd1 = cmds.pop(0)
# 初期局面が平手の場合
if cmd1 == "startpos":
board.set_sfen(SFEN_HIRATE)
# 初期局面が任意の場合
if cmd1 == "sfen":
board.set_sfen(' '.join(cmds[0:4]))
del cmds[0:4]
# 指し手文字列の処理
while len(cmds) > 0:
move = cmds.pop(0)
if move == "moves":
continue
board.push_usi(move)
continue
# 探索
# 今回は長時間の探索処理を省いているので、以下のコマンドが入力された時に指し手を決定して出力する。
# - 「先読み以外の探索開始(go ponder ではない go)」
# - 「先読みした相手の指し手が当たり(go ponder 中の ponderhit)」
# - 「先読みした相手の指し手が外れ(go ponder 中の stop)」
if cmd0 == "go" or (ponder and (cmd0 == "ponderhit" or cmd0 == "stop")):
# 先読み探索はしない
if "ponder" in cmds:
ponder = True
continue
else:
ponder = False
# 合法手の一覧
legalmoves = list(board.legal_moves)
# 合法手が無ければ投了
if len(legalmoves) == 0:
print("bestmove resign")
continue
# 指し手を乱択
bestmoveusi = move_to_usi(choice(legalmoves))
# 指し手を進める
board.push_usi(bestmoveusi)
# 相手の指し手を乱択
ponder_legalmoves = list(board.legal_moves)
pondermoveusi = None
if len(ponder_legalmoves) > 0:
pondermoveusi = move_to_usi(choice(ponder_legalmoves))
# 指し手を戻す
board.pop()
# 指し手を出力
if pondermoveusi is not None:
print("bestmove " + bestmoveusi + " ponder " + pondermoveusi)
else:
print("bestmove " + bestmoveusi)
continue
# 対局終了:先読み状態のみ解消する
if cmd0 == "gameover":
ponder = False
# エンジン終了:ここではループの外に出るだけ
if cmd0 == "quit":
break
# デバッグ用:局面情報の出力
if cmd0 == "d":
print(board)
print(board.sfen())
# どれにも引っかからない場合は無視してループに戻る
continue
# ループを抜けたら終了
exit
pip install -r requirements.txt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment