パーソナルブログメモリ

a = [1, 1]
for _ in "*" * 999: a += [sum(a[-2:])]
print(a)

観賞用将棋盤の作成(AlphaZeroの棋譜をみる)

2019-02-19 | python入門(すぐさまマスター)
AlphaZeroの棋譜2


作成環境
Ubuntu 18.04
Python 3.6.8

AlphaZeroの対局100局の観賞用に作成しました。
deepmind社のこちらのページから
棋譜ダウンロードのページ
100 AlphaZero-Stockfish games, starting from 2016 TCEC world championship opening positions (.zip file).
をダウンロード

解凍したフォルダに下のプログラムを t.py というファイル名でおいて
解凍したフォルダを端末から開いて python3 t.py で実行です。
(Ubuntu環境で作成しているので他の環境だとpathの指定方法とかfontを変更しないと動かないかもしれません)

csaファイルはダウンロードしたものから解析しているので一般的なcsaファイルだと読めないものもあると思います



<プログラムの簡単な解説>

python3に標準ライブラリとして取り込まれたtkinterを画面処理に使用しています。

データ構造はボードを2次元配列9x11としていて9行までが盤面10行目が先手の持ち駒(数)11行目が後手になってます。
board[9]=[0,1,2,3,4,5,6,7,0]だと先手は歩1 香2 桂3 銀4 金5 角6 飛7の持ち駒をもっていることに
koma2が駒の番号に対応する駒の字になります。
後手の盤面の駒はマイナス表示になっています。
(このプログラムを解析される方はいないと思いますが、わけわからないと思うので少しでも手がかりを残しておきます)

表示される駒で成り駒の漢字は一部当て字です。成香が今、成桂が企、成銀が全としています。(設計で一番悩んだ所です)

パラメータの変更
#ランダム再生
randomSw 1以外だと1から100まで順に再生します。ランダムにすると同じファイルを連続で再生ということもあります。
#一手の待ち時間
waitTime 1手表示ごと待つ時間です。単位は秒です0.1とかも入れられます。


import tkinter
import time
import random

tk = tkinter.Tk()
tk.title("shogi 100")
tk.geometry("800x600+100+100")
tk.update()

cv = tkinter.Canvas(tk, width = 800, height = 600)
f12=("Helvetica", 12, "bold")
f20=("Helvetica", 20, "bold")
f25=("Helvetica", 25, "bold")

koma2=["","歩","香","桂","銀","金","角","飛","玉","と","今","企","全","","馬","竜",""]
koma3="   FU KY KE GI KI KA HI OU TO NY NK NG    UM RY    "

bd=["234585432","070000060","111111111","060000070","234585432"]

board=[]

def boardInit():
    global board,bd
    board=[]
    for y in range(3):
        l=[]
        for x in range(9):
            l+=[int(bd[y][x])*-1]
        board+=[l]
    for y in range(3):
        board+=[[0,0,0,0,0,0,0,0,0]]
    for y in range(2,5):
        l=[]
        for x in range(9):
            l+=[int(bd[y][x])]
        board+=[l]
    for y in range(2):
        board+=[[0,0,0,0,0,0,0,0,0]]

def writeText(x,y,s):
    global f20
    cv.create_text(x, y, text=s, font=f20)

def writeKoma(x,y,kn,tb,count=0):#tb 1:sente 2:gote
    global f25
    sx=220
    sy=120
    cv.create_text(x*40+sx, y*40+sy, text=koma2[kn], font=f25,angle=[0,0,180][tb])
    if count>1:cv.create_text(x*40+sx+25, y*40+sy+5,text=str(count),font=f25,angle=0)

def writeBoard(b,sName,gName,win,filename):
    writeText(400,30,filename)
    writeText(120,60,gName)
    writeText(630,500,sName)
    writeText(400,570,win)
    for y in range(9):
        for x in range(9):
            n=b[y][x]
            if n!=0:
                if n>0:
                     writeKoma(x,y,n,1)
                else:
                     writeKoma(x,y,-n,2)
    for x in range(1,8):
        if b[9][x]>0:
            writeKoma(10,9-x,x,1,b[9][x])
        if b[10][x]>0:
            writeKoma(-2,x-1,x,1,b[10][x])

# csa
# FU KI KA GI UM OU KE TO HI KY NK RY NG NY
# +先手 -後手
#V2.2
#N+elmo
#N-AlphaZero
#PI
#+
#+7776FU
#-4132KI
#%TORYO

def decode(fileName):
    global waitTime,cv
    #ファイル読み込み
    with open(fileName) as f:
        bLine=""
        sName=""
        gName=""
        win=""
        boardInit()
        tb=0
        col=["","red","green"]
        for line in f:
            cv = tkinter.Canvas(tk, width = 800, height = 600)
            line=line.replace(chr(10),"").replace(chr(13),"")
            sx,sy=-1,-1
            if line=="+":pass
            elif line[0]=="+":
                sx,sy=move(line)
                tb=1
            elif line[0]=="-":
                sx,sy=move(line)
                tb=2
            elif line[:2]=="N+":
                sName=line[2:]
                continue
            elif line[:2]=="N-":
                gName=line[2:]
                continue
            elif line=="%TORYO":
                win="後手"+gName+"勝ち"
                if bLine[0]=="+":win="先手"+sName+"勝ち"
            else:
                continue
            bLine=line
            cv.create_rectangle(0, 0, 800, 600, fill = 'gray')
            cv.create_rectangle(200, 100, 560, 460, fill = 'yellow')
            cv.create_rectangle(100, 100, 180, 380, fill = 'yellow')
            cv.create_rectangle(580, 180, 660, 460, fill = 'yellow')
            for i in range(8):
                cv.create_line(240+40*i, 100, 240+40*i, 460)
                cv.create_line(200, 140+40*i, 560, 140+40*i)
            if sx>-1:
                cv.create_rectangle(200+sx*40, 100+sy*40, 240+sx*40, 140+sy*40, fill = col[tb])
            writeBoard(board,sName,gName,win,fileName[2:])
            cv.place(x=0, y=0)
            tk.update()
            time.sleep(waitTime)
    del f

def move(s):
    global board,koma3
    #駒
    kn=int(koma3.find(s[5:7])/3)
    #先手後手
    tb=2
    sx=0
    sy=0
    if s[0]=="+":tb=1
    #持ち駒処理
    if s[1:3]=="00":
        board[tb+8][kn]-=1
        sx=9-int(s[3])
        sy=int(s[4])-1
        if tb==2:kn*=-1
        board[sy][sx]=kn
    else:
        #移動処理
        mx=9-int(s[1])
        my=int(s[2])-1
        sx=9-int(s[3])
        sy=int(s[4])-1
        if board[sy][sx]!=0:#駒取判定
            tk=abs(board[sy][sx])%8
            board[tb+8][tk]+=1
        if tb==2:kn*=-1
        board[my][mx]=0
        board[sy][sx]=kn
    return sx,sy

#構想 csaファイル100個を順次読み込んで表示していく
#パラメータ
#ランダム再生
randomSw=1
#一手の待ち時間
waitTime=1

time.sleep(3)
#メインループ
for i in range(1,101):
    #ファイル読み込み
    time.sleep(1)
    if randomSw==1:i=random.randint(1,100)
    decode("./"+str(i)+".csa")

最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。