2020-10-22 18:00:00

V-C級月組5局目 十六夜桜花 VS 凪なぎさ (四間飛車 VS 四間飛車 相振り飛車) 感想

はいどうも、頭痛系VTuberの凪なぎさです(´-﹏-`;) V-C級月組5局目 十六夜桜花 VS 凪なぎさの感想について記載します。 戦型としては四間飛車 VS 四間飛車の相振り飛車の戦いとなりました。 本リーグの私の最終対局です。

結果から言ってしまうと本対局では私の勝利でリーグ成績としては2勝1敗という成績となりました。

目次

V名人戦って?

Vtuberの、Vtuberによる、Vtuberのため棋戦、それがV名人戦 簡単に説明すると、将棋がさせるVtuberの将棋棋戦です。 棋力帯に応じて現在はA級、B級、C級と3つのクラスにクラス分けされています。

大まかな棋力帯としては下記のような感じです。

  • A級: 2段以上
  • B級: 2級 〜 2段
  • C級: 2級以下

最上位のリーグの優勝者がV名人への挑戦権を得て番勝負を行います。

詳しくは公式の規定を参照ください。 V名人戦 規定(2020.08.29).pdf - Google ドライブ

現在(2020年10月22日時点)では第二期V名人戦が開幕しています。

公式サイトもあるので参照ください。 V名人戦公式サイト

参加者一覧や、各参加者のYoutubeチャンネルなどは過去記事にて私のブログでもまとめています。 第2期V名人戦が開幕、参加者とその組分けは? | なぎなぎブログ

中継配信 アーカイブ

本対局の様子はこちらのアーカイブから確認いただけます。

本局の棋譜

81dojoを使って対局をしています。 棋譜はこちらから参照してください。

棋譜再生 (NagisaNagi 対 izaiza_izayoi) / 81道場 Webシステム

感想とポイント

対局についての感想や、対局時に考えていたことについて書いていきます。 ちなみにこの手のほうが良いなどは上げればきりがないので、ここでは言及しません。 あくまで対局中に考えていたこと、思っていたことと、流れが変わった場面等を記載していきます。

対局前

対局の日はあまり体調が良くなく、ちょっと頭痛がしてました。 なのであまり読まなくていいような戦型にしたいという気持ちがありました。

戦型

戦型は四間飛車 対 四間飛車 の相振り飛車の形になりました。

最近は居飛車ばかり指しているのですが、割と序盤から考えることが多かったり気をつけなきゃいけないことが多かったりすると思うので、今回は四間飛車を選びました。 四間飛車選んだ理由は、四間飛車ならほとんどの場合で特に考えずに組めるからです。

相手がノーマル四間飛車やってくることほぼ確定であれば46銀左急戦とかも慣れている(得意戦法も46銀左でエントリーしてた)ので選択肢としてはあったのですが、対戦相手の十六夜桜花さんは振り飛車党というのはわかっていましたが、ノーマル四間飛車、ノーマル三間飛車をせずに、早石田とかだと私は慣れてない展開になって頭痛が痛くなってしまいそうな展開も考えられたので居飛車を避けました。 あとは、1局目、2局目も居飛車だったので、ちょっと振ってみてもいいかなていう気持ちもありました

序盤

四間飛車で美濃囲うところまではとにかく何も考えずに組めたのは作戦通りです。 相振りなのに端歩付きこしちゃったのは居飛車で対抗系のときは端受けてこないときはいつも付きこすようにしてるのでその癖が出てしまって想定外でしたが(゜゜)

あといつも相振り飛車のときは、この四間飛車の手筋で2筋に回るのやってるんですが、今回相手の銀上がりが早かったのでできなかったですね。

本当はこういう展開にしたかったですね。

別に本局の展開も悪くはないと思いますが、慣れてない感じになってしまったかもしれません。

中盤

銀を打たされてやや指しにくい感じに

中盤と言えるのかわからないですが、駒がぶつかって銀交換となった場面

このあたりやり取りは、こっちだけ先に銀を打たないといけなくなってしまってちょっと悪いかなと思っていました。

65歩突くと角交換になるので、角と銀を両方持ち駒になると相手の指し手の選択肢も増えそうで怖かったので、なかなかこの後65歩と突くこともできませんでした。 なので飛車引かれたあとに、65銀と出たのですが疑問手だったみたいです。 65銀は形悪いですが、1歩得ですし、56銀と戻ればまぁ良いかなと思っていました。

このあとの展開として、感想戦でも少し触れていましたが、先手の私の65銀に対して後手側は24歩から23飛車と2筋に回る展開をされるとこちらが厳しそうでした。

うまく咎められた55銀

55銀打ちと駒をぶつけてきた局面

この瞬間相手の角が浮いているので,65歩や55銀(同銀) 同歩 65歩という手がぱっと浮かびました。

このあたりすぐ浮かぶようになったのは成長を感じますね。

すぐに65歩つくのは、56銀取られたときに角は抜けますが、56銀の位置が嫌だったりなにか技がかかるといけないと思い、55銀 同歩 65歩の手順としました。 そのほうが局面はシンプルだと思うので。頭痛のときはシンプルに!

終盤

この局面で良い必至をかける手がありましたが、ちょっと自信がなくてさせませんでした。

ちなみにここで71角成と切ってしまうのが必至となります。

28銀としたりしても 同馬 同玉 74桂 71玉 82金 といった形で詰みます

ただ対局中はちゃんと読みきれず、詰みそこねてここで逆転されるのも怖いので、本局では11銀と香車を取って今回は安全勝ちを狙いに行きました。

この後は狙い通り安全を維持してなんとか勝つことができました。

全体を通して

ソフトでの解析結果を置いておきます。

序盤で疑問手2つでしたが、悪手はなかったので良かったかなと思います。

あと、今回は時間を序盤の方で使い切らなかったのは良かったかもしれません。

いつものなら序盤で時間を使い切ってしまうのですが、四間飛車という割と考えなくても組みやすい戦法の選択や、 頭痛なのであまり深く読まずシンプルにわかりやすく進めていくという意識があって、その結果割とうまく時間も使えてた気がします。

これがなぎなぎ流頭痛戦法です( ・´ー・`)

さいごに

対局者の十六夜桜花さん、中継、聞き手のすず白ラパニスさん、世良祭さん、見に来てくれた皆様ありがとうございました。

本体局でV名人戦の私の対局は全て終わり、成績としては2勝1敗となりました。

V名人戦自体はまだまだ続いているのでこれからは観戦モードで楽しんでいこうと思います。

2020-10-22 08:00:00

将棋ソフト開発 Week1 ~ 将棋のコア部分を作る ~

プログラミングの勉強がてらに、将棋ソフト開発をしています。0週目は作るプログラムを方針を作成しましたが、1週目が終わり進捗報告と、やったこと、これから取り組むことについて記載していきたいと思います。 1週目ではリポジトリやパッケージ構成の準備と将棋のコア部分である各駒や盤の実装や、ルールの実装を取り組みました。

目次

進捗報告

一旦ランダムに動くところまで作りました。将棋のプレイを管理するクラスはまだ書いてないのでテストコードで無理やり実装して動かしているだけです。

ちょろっと書いてあるプログラム自体は色々この後いじってるので、後述の解説?とは違うところがあります。

1週目でやったこと

  • 将棋のコア部分の作成
    • パッケージ、リポジトリ構成決め
    • 駒の作成
    • 盤の作成
    • 移動のルールの作成

駒や盤といってもプログラム的に作成してるだけなので、実際に目に見えるものは作っていません。 一応Debugようにコンソール上で表示するようにはしました。

方針の変更

若干方針を変更しまして、拡張性の高いプログラムを作ると言っていましたが、一旦汎用的なものではなく普通の9x9の将棋をわかりやすく作ることにします。 あまりに汎用的なものを作るともはやボードゲームエンジンになってしまうので、ソレは非常に作るのは大変です。まずは動くものを作ることを優先!

パッケージ、リポジトリ構成決め

gradleのマルチプロジェクトにします。 ちなみに言語はJavaを使って書き始めてしまいました。今覚えばKotlinにしておけばよかったと思ってます。 時間があればKotlinで書き直すかもしれません。

3つのプロジェクトを包含していて、それぞれ役割毎に別リポジトリにしています。

  • shogi-presentation-cli
    • プレゼンテーション層
    • 末尾にcliとしているのは一旦コマンドラインでの入出力を作成するため.
    • 今後cliではなくWebAPIのインタフェースなども作る可能性もあるが、このプレゼンテーション層のみ変更すればよいです。
  • shogi-application // アプリケーション(ユースケース)層
  • shogi-core // ドメイン層

この分け方はクリーンアーキテクチャ(Clean Architecture)やオニオンアーキテクチャを意識した分け方にしています。

画像はClean Coder Blog より引用

今の所インフラ層はないですが、今後作るアプリケーションで棋譜保存が必要になるとか、外部との通信が発生するとかとなれば作ればよいです。

現状作るものでcliのアプリを想定して下記のような構成を予定しています。

.
|-- gradle
|   `-- wrapper
|-- shogi-application // submoduleで別リポジトリ, アプリケーション層のコードを格納する
|   |-- gradle
|   |   `-- wrapper
|   `-- src
|       |-- main // アプリケーション層の実装コード
|       |   |-- java
|       |   |   `-- com
|       |   |       `-- naginagisa
|       |   |           `-- shogi
|       |   |               `-- application
|       |   |                   |-- manager
|       |   |                   `-- service
|       |   `-- resources
|       `-- test // アプリケーション層のテストコード
|           `-- java
|               `-- com
|                   `-- naginagisa
|                       `-- shogi
|                           `-- shogiapplication
|-- shogi-core  // submoduleで別リポジトリ, ドメイン層のコードを格納する
|   |-- gradle
|   |   `-- wrapper
|   `-- src // ドメイン層の実装コード
|       |-- main
|       |   `-- java
|       |       `-- com
|       |           `-- naginagisa
|       |               `-- shogi
|       |                   `-- core
|       |                       `-- domain
|       |                           |-- model // ドメインモデル
|       |                           `-- service // ドメインサービス 必要ない場合もある
|       `-- test // テストコード
|           `-- java
|               `-- com
|                   `-- naginagisa
|                       `-- shogi
|                           `-- core
|                               `-- domain 
|                                   |-- model
|                                   `-- service
`-- shogi-presentation-cli // submoduleで別リポジトリ, プレゼンテーション層のコードを格納する
    |-- gradle
    |   `-- wrapper
    `-- src
        |-- main // プレゼンテーション層の実装コード
        |   |-- java
        |   |   `-- com
        |   |       `-- naginagisa
        |   |           `-- shogi
        |   |               `-- shogipresentationcli
        |   |                   |-- presenter
        |   |                   `-- controller
        |   `-- resources
        `-- test // プレゼンテーション層のテストコード
            `-- java
                `-- com
                    `-- naginagisa
                        `-- shogi
                            `-- shogipresentationcli

一旦仮おきで、細かくはもっと分けるかもしれませんし、若干の構成変更はするかもしれません。 ただこの層で分けた、マルチプロジェクトの構成は変わらない予定です。

week1で今作ってるのはshogi-core(ドメイン層)の部分です。 submoduleにしてあるので、実際にはshogi-coreのリポジトリ単体で開発をしていけます。

駒の作成

本プログラムは高速なものを作るつもりは一切ないので、bitboardとかは使いません。コンピュータ将棋は勉強したてであまり良くわかっていませんし。 余談ですが、相当速度は犠牲にしているので、探索や学習で性能が出なくて使い物になないかだけが不安です。

domain.model.piece以下に駒関連のクラスを生成します。

pieceType側(enum)に全てロジック持つこともできそうですが、クラスで分けたほうが素直そうなので今回はクラスで分けてます。

各駒クラスはイミュータブルなものとしています。スレッドセーフになりますし、意図していないところで変更の影響を受けないようにするためです。 毎回オブジェクトを生成するのはコストではありますが、 将棋は81マスで、先手後手と駒の種類があるとして1つのコマあたりたかだか 81*2 で162のオブジェクトの生成で済みます。この程度であれば事前に生成しておく、もしくはキャッシュしておくなどすればそれほどコストはかからないかと思います。

pieceTypeはこんな感じ。 javaの場合はenumの中に振る舞いをかけてしまうのでそっちに各駒のルールなどのロジックを書いてもよいですね。

public enum PieceType {
    FU,
    KYO,
    KEIMA,
    GIN,
    KIN,
    KAKU,
    HISYA,
    TOKIN,
    NARI_KYO,
    NARI_KEI,
    NARI_GIN,
    UMA,
    RYU,
    GYOKU
}

今はクラス内で自分自身が動ける箇所を求めるメソッドを持っています(legalMoveList). 中でさらにメソッドに分けたりはしていますがやっていることは下記のことです

  • 自分の持つ効き(Effect)方向に探索して動ける箇所(Position)を取得
  • 歩は1段目(後手の場合は9段目)には存在できないなどのルール上での動ける箇所(動けない箇所)の取得

最終的に動けるマスは、これらで求めたPositionの集合の積集合や差集合などの集合演算で求めています。 ルールとかも別クラスに切り出したいですが一旦ベタ書きです Effectも将棋はたまたま効きと駒の動きが一緒ではありますが、本来動きと効きは別物だとも考えられるので分けておきたくもあります。チェスとかだと実際に効きと動きが違う駒もありますしね。 とはいえそういう変則将棋をもし作るとなったときに考えれば良いので、一旦効きと移動箇所は一緒のものにしておきます。

効きに関しては次のように定義しています。 enumですが、Javaの場合は振る舞いを持てるので盤上の他の駒を考慮しない効きのPositionのリストを返すpositionListというメソッドをつけています。

各駒クラスの、legalMoveListの実装で1つ気になっているのは王手放置などの反則手を含めるかどうか。 ここでピンや、王手放置などの手を省くもしくは、後述の盤(Board)側で省くのも良いのですが、探索時に次の局面を作ってその局面が合法な局面かどうかを判断するほうが簡単そうな気がします。 っというわけで一旦ここは反則手ありの手を生成するようにしています。 その場合メソッド名は要検討ではありますが.

盤の作成

盤関連のクラス図は次のようにしています

BoardもImmutableにしたいですが、盤には駒を追加していったりするので、一発で生成するのは引数が多くなってしまったり、例えば駒を追加するときに生成側で駒のコレクションを生成したりと大変になってしまいます。 なのでBuilderクラスを用意して生成することにしています。

マス目の表現

Squareはマス目を表します。将棋盤であれば9x9の配列で表しています。 この二次元配列も別クラスに切り分けたほうがよさそうですが一旦、このままで。後々リファクタリングするかも。

持ち駒の表現

CapturedPiecesは持ち駒を表します。 単純Mapで歩が○枚、金が▲枚みたいな感じで持っているだけですね。 持ち駒は打つことができるので、uchiteListメソッドで打つ指し手のリストを返すように実装しています。

ボード上でのすべての指して

すべての指してはlegalMoveListで求めます。 やっていることは、各コマのlegalMoveListメソッドの返り値と、持ち駒のuchiteListをすべてマージしています。

    public List<Move> legalMoveList() {
        List<Move> legalMoveList = new ArrayList<>();
        legalMoveList.addAll(pieceSet(teban).stream().flatMap(p-> p.legalMoveList(this).stream()).collect(Collectors.toList()));
        legalMoveList.addAll(currentCapturedPieces().uchiteList(this));

        return legalMoveList;
    }

pieceSetメソッドは書いてないですが、現在の手番の駒をすべて取得するようなメソッドです。 各駒クラスや、持ち駒クラスにそれぞれの領域での手の生成は任せているので、簡潔にかけます。

moveメソッド

指し手(Move)を作用させた後の盤を返します。 Move自体の説明は後述の指し手の表現を参照してください。 つまり1手指した後の局面を作るメソッドです。

指し手の表現

一旦こうしています。※ダメな実装です

from: 移動元の位置、 to: 移動先の位置, isPut: 駒打ちかどうか putPieceType: 打つ駒の種類 isPromotion: 成るかどうか

駒を打つときはfromはnullになって、 isPutフラグで駒打ちかどうか判断できる。 一見なんとかなりそうですが、 さすがにこのクラスはいろいろ問題点が多いので流石に後で直します。

問題点

  • 呼び出し側でisPutフラグを見て判断しないといけない
  • 駒を打つときはfromがnullになっていることを意識しないといけない。 Optionalなどでチェックを強制できるがあまりよいとは思えない

解決策 駒の移動のアクションと、駒を打つアクションを一緒くたにしてるのが問題な気がします。

といわけで、例えばですが指し手インタフェースを作って、それを実装した駒打ちクラス、駒移動クラスなどと言った形で各アクションごとの実装クラスを分けたほうが良さそうです。

week2で直しておきたい。

やったことのまとめ

全体のクラス図としてはこんな感じになります。 細かい関係の線は複雑になるのであえて省いています。

だいぶ部品は揃ってきたかなーという感じです。

これから取り組むこと

これからweek2で取り組むことについて

  • week1で残した課題の解消
  • 最低限のusiプロトコルの実装

先に探索部分を作ろうかとも思いましたが、さすがにコンソール画面上で将棋動かしているだけではつまらないですし、自分で対局しようにも、コマンド打ちながらというのも大変なので先にUSIプロトコルの実装をすることにしました。

USI(Universal Shogi Interface)プロトコルとは、将棋GUIソフトと思考エンジンが通信をするために、Tord Romstad氏によって考案された通信プロトコルです。USIの原案は、以下で読むことができます。

将棋所:USIプロトコルとは より引用

要は、USIプロトコルを実装すれば、自分で作った将棋ソフトも、将棋所や将棋GUIでエンジンとして登録できるようになるということです。 将棋GUIや将棋所が使えれば、マウスなどGUI操作で自分のソフトを試すことができるのでテストプレイが非常にやりやすく成りますね。

というわけでこちらを優先してweek2は取り組もうと思います。

2020-10-15 01:00:00

将棋ソフト開発 Week0 ~ 将棋アプリ開発始めます ~

コンピュータ将棋の勉強をしていると以前振り返りの記事で書きましたが、理論だけではなく実際に作ってみたいなぁと思いました。 とはいえ勉強していたのはAIの部分でしたので、今回はゼロから将棋アプリを作って行こうと思います。

目次

目的

今回強い将棋ソフトを作ることは目的としません。

今の将棋ソフトがもう強すぎるため、強いソフトを作って自分の将棋の勉強のために使うとかそういうのもあんまりモチベーションにならないので。 また強いソフトを作るための機械学習とかやり始めたら、計算リソースとかも必要なので。

というわけで今回何を目的にするかというと、主に下記を目的とします。

  • プログラミングの勉強
  • 拡張性の高い将棋アプリの作成
    • 変則将棋などもやることがあるので、自分で作れたら便利なため

プログラミングの勉強

今回はプログラミングの勉強を一つの目的として行うため将棋アプリをゼロからスクラッチで作ります。 スクラッチというのは、yaneuraouなど既存のOSSの将棋ソフトがあったりしますが、そういったものは使わずに自分でゼロから開発していきます。

拡張性の高い将棋アプリの作成

将棋系Vtuberとしても活動をしていますが、その中で仲間内でこんな変則将棋やってみたい、といったアイデアが出てくることがあります。 そういった企画をやりやすくするために、拡張性の高い将棋アプリケーションを作ることを目的とします。

方針

UI面の要件はまだ未定です。 まずは将棋のコアとなる部分を作成します。 確認のために最低限自分で対局できるくらいのusiは実装するかもしれません。

UIは未定ですが、コア部分さえ作成すれば、あとからアプリに組み込むこともできますし、サーバで動作させて通信によりブラウザで動作させることも可能なためです。

コア部分の作成には一般的に将棋に必要な機能の他に、AIの思考ルーチンも含めます。

コア部分で作るもの

  • 盤面の表現
  • 合法手生成
  • CPU指して生成

作らないもの

  • 棋譜保存

さいごに

将棋などのボードゲームを作るのは初めてで、うまくできるかわかりませんがとりあえず動くものは作れるようにまではしたいと思います。 進捗に関しては毎週報告できればなーと思います。