将棋の初手(電竜戦さくらパイルール2023編)

将棋の初手は26歩か76歩がほとんどです。

以前、将棋俱楽部24の二番絞りを調査する際にも確認しました。

二番絞り@将棋倶楽部24の戦型分析 - 48's diary

 

ところが、近年将棋は先手有利と分かってきているのですがなんとか公平な大会運営ができないかということでパイルールを採用した実験的イベントが準備されています。

電竜戦さくらパイルール2023、参加者募集中 | コンピュータ将棋協会blog

Google Forms: Sign-in

 

このパイルールでは仮の先手が26歩や76歩と指すと仮の後手に先手を取られ損をすることは明白です。といっても86歩を指すとそのまま先手を指さなければなった際に大変な目にあいます。

 

ということで、仮の先手はなるべくどちらを取っても良いように中立的な手を指すのが良さそうです。

そこで、二番絞りで将棋の初手30種類を指した局面を評価してみました。

実行プログラムは以下のものです。(go_scoreに関してはcshogi本家にもプルリク送ってあります)

 

# パイルール事前評価用スクリプト
import cshogi
from cshogi.usi import Engine

def go_score(self, ponder=False, btime=None, wtime=None, byoyomi=None, binc=None, winc=None, nodes=None, listener=None):
    if self.debug: listener = print
    cmd = 'go'
    if ponder:
        cmd += ' ponder'
    else:
        if btime is not None:
            cmd += ' btime ' + str(btime)
        if wtime is not None:
            cmd += ' wtime ' + str(wtime)
        if byoyomi is not None:
            cmd += ' byoyomi ' + str(byoyomi)
        else:
            if binc is not None:
                cmd += ' binc ' + str(binc)
            if winc is not None:
                cmd += ' winc ' + str(winc)
        if nodes is not None:
            cmd += ' nodes ' + str(nodes)
    if listener:
        listener(cmd)
    self.proc.stdin.write(cmd.encode('ascii') + b'\n')
    self.proc.stdin.flush()
    score = {} # 読み筋毎に評価値を残す
    while True:
        self.proc.stdout.flush()
        line = self.proc.stdout.readline()
        if line == '':
            raise EOFError()
        line = line.strip().decode('ascii')
        if listener:
            listener(line)
        l = line.split()
        if 'cp' in l and 'pv' in l: # 読み筋毎に評価値を残す。詰みの場合は無視
            score[l[l.index('pv')+1]] = l[l.index('cp')+1]
        if line[:8] == 'bestmove':
            items = line[9:].split(' ')
            if len(items) == 3 and items[1] == 'ponder':
                return items[0], items[2], score[items[0]]
            else:
                return items[0], None, score[items[0]]
               
Engine.go_score = go_score

# engine = Engine('/content/LesserkaiSrc/Lesserkai/Lesserkai')
engine = Engine("nibanshibori.exe", debug=False)
engine.setoption("DNN_Batch_Size", 32)
engine.setoption("DNN_Model", "nibanshibori.onnx")
engine.isready()

board = cshogi.Board()

for move in board.legal_moves:
    board.push(move)
    engine.position(sfen='sfen '+board.sfen())
    # a,b,c = engine.go_score(nodes=10000)
    a,b,c = engine.go_score(byoyomi=10000)
    print(cshogi.move_to_usi(move),c)
    board.pop()


 

実行結果は以下になります。

 

> py .\pie.py
1g1f -73
2g2f -206
3g3f 171
4g4f 205
5g5f 192
6g6f -44
7g7f -198
8g8f 812
9g9f -41
1i1h 507
9i9h 327
3i3h 4
3i4h 19
7i6h 47
7i7h 224
2h1h 341
2h3h 307
2h4h 328
2h5h 269
2h6h 211
2h7h 190
4i3h 267
4i4h 180
4i5h 14
6i5h 322
6i6h 205
6i7h -51
5i4h 300
5i5h 80
5i6h -22

 

ということで結論としてもっとも公平(0に近い)のが38銀でした。次点は58金右ですね。

これによって仮の先手のときは38銀とすることにします。

仮の後手は上記の評価値がマイナスのとき後手不利ということで先手を取るほうが良い、評価値がプラスなら後手有利なので後手を取るほうが良いということです。

 

具体的に戦型や対戦勝率を確認したり定跡を準備したりなどもう少し深く対策した方がよい気もしますが、あまり時間もないのでこれでエントリーしてみようと思います。

---

追記:

もちろんですが初手38銀の棋譜に興味のない人が多いと思います。

個人的には先手後手でハンデ戦として持ち時間差くらいが適当かと考えていますが、プロ棋士でもそれを30分とするか1時間とするかそれぞれイメージが異なるようですね。

マチュアではほぼ差がないようなので気にしなくていいと思います。