パーソナルブログメモリ

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

100局の棋譜解析

2019-02-22 | python入門(すぐさまマスター)
AlphaZeroの棋風が玉の中央嗜好と見かけたので
対局の解析何かできないかなと考えて作ってみました。

1)対局時の玉の位置一手指ごとに盤上にいた場所をカウントしています。


2)どの駒を一番動かしているか(成りの時はなったあとの駒をカウント)


3)解析ではないのですが駒に色をつけると共感覚感が味わえるかなとつけてみました。盤の把握が格段にあがっているような気がします。

AlphaZeroの棋譜3 共感覚編


動かし方はこちらを前回の記事と同じです。
観賞用将棋盤の作成(AlphaZeroの棋譜をみる)

作成環境
Ubuntu 18.04
Python 3.6.8

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ファイルだと読めないものもあると思います

<考察と雑感>
個人的な話ですが、敵の玉の攻略の難易度 中央玉の金開き>美濃囲い>穴熊>居玉だったりします。
(注 穴熊は速攻で角切って組ませないように指してます)
なんとなく、それと通じるような…AlphaZeroの5八玉に一番いるようです。

一時期コンピュータ将棋は入玉に弱いといわれていましたが、
人間がプログラムしにくいのかなと思ってました。
機械学習だとその編を苦にしないのか後手AlphaZeroの入玉が多いようです。
後手elmoがまったく入玉させてもらえていません。
先手で入玉は左上がお薦めのようです。

#####↓作成したプログラム

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    "
komaCol=["","","","#0A0","#55F","#F00","#0F0","#FA5","#DDD","#F00","#F00","#F00","#F00","","#AFA","#FCC",""]


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,komaColSw
    sx=220
    sy=120
    if komaColSw==1:
        col=komaCol[kn]
        if col!="":
            cv.create_rectangle(x*40+sx-19, y*40+sy-19, x*40+sx+19, y*40+sy+19, fill = col)
    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,sName,gName
    #ファイル読み込み
    with open(fileName) as f:
        bLine=""
        win=""
        boardInit()
        tb=0
        col=["","red","green"]
        for line in f:
            if kaisekiSw==0:
                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

            if kaisekiSw==1:
                #解析処理
                continue#対局の表示はしない

            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,komaMoveCount,sName,kaisekiSw
    #駒
    kn=int(koma3.find(s[5:7])/3)
    #先手後手
    tb=2
    sx=0
    sy=0
    if s[0]=="+":tb=1
    #移動解析1
    elmoSw=1
    if tb==1 and sName!="elmo":elmoSw=0
    if tb==2 and sName=="elmo":elmoSw=0
    komaMoveCount[elmoSw][kn]+=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

    if kaisekiSw==1:
        countBoard()
    return sx,sy

def countBoard():
    global board,boardCount,sName
    senteNo=0
    goteNo=3
    if sName=="elmo":
        senteNo=2
        goteNo=1
    for x in range(9):
        for y in range(9):
            kn=board[y][x]
            if kn!=0:
                point=x+y*9
                if kn>0:
                    boardCount[senteNo][kn][point]+=1
                else:
                    boardCount[goteNo][-kn][point]+=1


def writeBoardCount(no,kName):
    kn=int(koma3.find(kName)/3)
    print("***************************************************")
    print(["zero先手","zero後手","elmo先手","elmo後手"][no],koma2[kn])
    if kn==0:return
    for y in range(9):
        l=""
        for x in range(9):
            l+=("      "+str(boardCount[no][kn][x+y*9]))[-5:]
        print(l)


#構想 csaファイル100個を順次読み込んで表示していく

#変更構想 100局でいろいろな分析してみる
#駒によって背景色を変えてみる
#どの駒がよく動くか
#王様がだいたいどの位置にいるか
#zero elmoともに分析して解析結果をなにかしら図示してみる
komaMoveCount=[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]#zero:0 elmo:1
#各駒の位置を足していく
boardCount=[]

for i in range(4):#0:zero先手 1:zero後手 2:elmo先手 3:elmo後手
    b=[]
    for j in range(16):#koma
        b+=[[0 for i in range(81)]]#9x9 x+y*9
    boardCount+=[b]
#print(boardCount)

#パラメータ
#ランダム再生
randomSw=0
#一手の待ち時間
waitTime=0.1
#駒の追加カラー
komaColSw=1
#解析スイッチ(1の時は盤面表示をしない)
kaisekiSw=1

if kaisekiSw==1:
    randomSw=0
    writeText(100,100,"解析中")
    cv.place(x=0, y=0)
    tk.update()

sName=""
gName=""

if kaisekiSw!=1:time.sleep(3)
#メインループ
for i in range(1,101):
#for i in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,51,52,53,54,55,56,57,58,59,60,61,62,63,64]:
    #ファイル読み込み
    if kaisekiSw!=1:time.sleep(1)
    if randomSw==1:i=random.randint(1,100)
    decode("./"+str(i)+".csa")
    if kaisekiSw!=1:print(i)

#koma3="   FU KY KE GI KI KA HI OU TO NY NK NG    UM RY    "
for i in range(16):
    kName=koma3[i*3:i*3+2]
    if kName=="  ":continue
    for n in range(4):
        writeBoardCount(n,kName)

print("-"*75)
#koma2=["","歩","香","桂","銀","金","角","飛","玉","と","今","企","全","","馬","竜",""]
for n,name in enumerate(["zero","elmo"]):
    l1=name
    l2="    "
    for i in range(16):
        if koma2[i]!="":
            l1+="   "+koma2[i]
            l2+=("   "+str(komaMoveCount[n][i]))[-5:]
    print(l1)
    print(l2)


#####↑作成したプログラム


プログラムは全部の駒表示しています。歩、桂、金だとこんな感じです

歩の場合2八歩が多いのが気になります。受けの妙手があるのかも


自陣一段目に桂馬を打つ手が多いです。


コンピュータ7八金(3ニ金)が大好きです

最新の画像もっと見る

コメントを投稿

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