Miacis for Android開発日記

 深層強化学習を用いた将棋ソフト『Miacis』を開発しており、PyTorchのライブラリを眺めていたらAndroidで動かせるなーということに気づいたので作ってみました。

 アプリのリンク

 ソースコードのリンク

 Androidアプリというか、一般にGUI付きのアプリを開発する事自体が初めてだったので、記録を残した方が面白いかなと思って開発当初からの日記をつけていました。途中から書くのが面倒になってかなり雑になってしまったが、お蔵入りにする意味もなさそうなので公開。

3月15日

 開発環境はUbuntu20.04。目標は「将棋アプリを作り、Miacisと対局できるようにする」

 以下の記事を参考にした。

 まずはAndroid Studioをインストールするところから。公式ページに従ってやるととりあえず起動はできた。

 手元のAndroidをUSBケーブルで繋いでも認識しない問題が発生。まずそもそもadb serverが見つからないとかいう話だったので開発パソコンにインストール。

sudo apt install adb

 あとはAndroid側で開発者モードをオンにする作業を行う。「設定>システム>端末情報>ビルド番号」を連打して、開発者向けオプションを有効にし、「設定>システム>開発者向けオプション>USBデバッグ」をONに変える。

 それでも見つからなかったけど、Android本体とパソコンを繋ぐケーブルを別のものに替えたら認識した。ひょっとしてこういうケーブルって充電しかできないものと情報のやり取りまでちゃんとできるものの区別がある? そういうことすら知らないレベルです。

 とりあえずコードもなにも変えないまま最初のHello World!が手元のデバイスで表示された。

3月16日

 とりあえず公式チュートリアルを読んでいくことにする。

 アクティビティやエントリポイントとかいう概念がイマイチ掴みきれない。アプリ、プロジェクト、モジュールあたりの用語もどれがどういう感じのものを指すのか。まぁこのあたりはやっていくうちにわかってくるだろう。

 チュートリアル通りに進めて、テキストボックスとボタンを表示させた。

 Android StudioGUIでテキストボックスなどの配置をいじると自動的にxmlが更新されて適切に配置してくれるということらしい。すごいもんだ。そもそもxmlがなんなのか正確には理解していないが、なんかそういう書式の決まったファイルなんだろうという程度。

 画面遷移と画面上部のメニューによる「もとの画面に戻る」まで実現するところでチュートリアルが終わった。意外と短く、まだなんもわからない感じはする。まぁなんかxmlファイルと上手く連携しつつ中身だけプログラムで受け渡しながらやっていくという感じなのだろうな。

 流石にこれだけではどうしようもないのでなんかそれっぽいやつに進む。

 Unit1の3つ目までやった。なんだかわかるようなわからないような感じ。

3月17日

 Unit1の4つ目を終わらせて、サイコロが振れるようになった。

 Unit2からチュートリアルに日本語訳がないようだ。英語、つらい。

3月18日

 Unit2-2まで終わらせた。

 色を変えるとかテーマを変えるとか、アイコンを設定するとか、スクロールバーを追加するとか。適切に動作を示したアイコンを追加するとか、そういう振る舞いができる気がしない。難しい。

 あとTalkBackの項目が何度探しても見つからなくてそこは検証できなかった。検索してもそんな症状なさそうだし、よくわからない。

3月19日

 Unit2-3まで終わらせた。

 List系は特になんてことはないけど、RecyclerViewの細かいところは理解が及ばないところもあった。

3月21日

 Collection型は大丈夫、だと言いたいところだが、Setの順番が違う可能性があるって、内部的にこれはどういうふうに保持しているんだろう。挿入とか削除の計算量が示されないのであとで調べておかなきゃ。

 とうとう画面遷移がまともに始まった。Activityが画面単位というのはわかるが、IntentやらContextやらがよくわからない。というか画面遷移的なコードはAdapter部分に書くのか。そのあたりの役割分担もまだ馴染んでいない。

 なにがなんやらさっぱりわからなかった。

 Activity lifecycleは、考え自体はわかるが実際に自分でアプリを作って適切に設定するのは大変そう。注意力コンテストか?

3月22日

 Unit3-2、フラグメントについて。なんもわからん。指示に従うことすらまともにできないレベルで何もわからない。さらにナビゲーショングラフとかいうものまで出てきた。意味不明。

 これを英語で読んでいくのは不可能と判断したのでとりあえず断念。

 基本を学ぶのにも飽きてきたので自分が作りたいものをやっていくフェーズにとりあえず移行してみる。

 まずは以下の記事を参考に、根本的にNNモデルをアプリ内で動かせるかどうかの検証。

 とりあえずメインから2つのActivityに遷移できるような状態を作成し、そのうち片方で特定の画像に対して学習済みResNetを用いて推論する機能を実装。

f:id:tokumini:20210322154809p:plainf:id:tokumini:20210322154811p:plain

 バージョンの違いで少し手間取ったけど上手くできた。

 Miacisで実際に学習したモデルを使った推論もできた。ここができたということはかなり完成できる可能性が高まったように思う。

 将棋盤部分を作っていく。たとえば以下のようなものを参考にした。

 素材には以下のフリー素材を使った。

 ガチャガチャやってこんな感じ。

 ImageViewを81マス分用意して、そのマスに置かれている駒を表示させる。駒がマスギリギリの大きさで詰まっていてやや違和感はあるんだけど、そこを直すのは微妙に面倒なような。僕の頭が悪いだけでなんか簡単なやり方があるか?

 あとこれ見ていて気がついたけど駒台を作らなくてはいけないんだな。上下に適当に置いておけば良いか。レイアウト的に入らないものがスマートフォンがあったりしたらどうしましょ。

3月23日

 PositionMoveクラスなどをC++からKotlinへ移植していく。結構記法が違うので面倒が多い。

 とりあえず初期局面を設定して描画することはできた。

 合法判定は入れていないが、駒を動かすこともできた。

 しかしここからの合法性判定が難しい。やっぱり合法手を全て生成してその中に入っているかどうかで判定するのが楽な気がするので合法手生成からやりたいが、Bitboardがおそらく使えないのでどうするか。PEXTは無理なんじゃないかな。Rotated Bitboardなら作れるかもしれないが、元のMiacisがそういう仕組みじゃないので勉強するところから始めないといけない。

 多少遅くていいから配列から上手く生成する手段を考えたい。ピンされた駒が動いて自殺手になるのが大変ではあるんだよな。

 とりあえず特定のマスに利きがあるかどうかを求める関数を作ればなんとかなるか。というわけで実装して、二歩とかはまだ詰めてないけど合法手生成を入れた。

3月24日

 駒台を追加して持ち駒を表示できるようにした。

 基本的には合法手しか指せないし、かなり将棋盤っぽくはなってきたが、まだ成るか成らないかを選べない。これ結構面倒かもしれないな。

 ぴよ将棋のこれとかどうやってるんだろう。

 ダイアログか、言葉がわからないと検索もできないので大変だったけど、多分これはダイアログで実現するものだろう。

 えー、でもモーダルダイアログというものじゃないとダイアログを表示している間に勝手に処理が進んでしまう。これどうすれば良いんだろう。Androidではモーダルダイアログなんてないよって言ってる記事ばかりだ。ビジーループでも待てないし、どういうこと? ダイアログなんてそこの入力をもとに動作を切り替えたいから使うんじゃないの? なんでそれができないの?

 関数として切り出してコールバックで呼び出せば良いのか。それでできたが、なんだかなー。

 選択中の駒を強調表示する(背景色を変える)機能を入れた。

 かなり将棋アプリらしくなってきた。しかしまだ思考部分も全然書いてないし対局設定とかも全然設定できる感じではないので先は長い。

3月25日

  • こっちが指したら相手も一手指す仕組みを導入して、対局ができるようになった。
  • ホーム画面にボタンを追加して以下の4モードで起動できるように変更
    • 検討モード
    • 先手として対局
    • 後手として対局
    • 手番をランダムに決めて対局
  • 指し手生成のバグを修正

3月26日

  • Policyを5手分表示するように修正
  • Valueを棒グラフで表示する参考

 KotlinのRange checkは計算量大丈夫なんだろうか。多分大丈夫なんだろうけど、確信が持てるまでは変えたくない。

3月29日

 後手で指す場合は盤面を180°回転させて表示したいわけだけど、これが難しい。なんか妙にバグる。脳みそがバグる。自動補完された変数名が想定と違うものになっていたことに気づかずずっとよくわからない現象に悩まされていた。

 打ち歩詰めの判定を入れ忘れていたことを思い出して、これ合法手生成に入れるの難しいんだよなーって思ってたんだけど、打ち歩詰めになる手は生成してしまって、局面の勝敗判定のところでやってしまうのでいいか。

 対局成績を保存したいのでデータの保存などについて調べる。参考

3月30日

  • 入玉模様のときにバグることが発覚。王手判定で玉への利きを検証するときに、玉から桂馬の利きを生やそうとして盤外へ飛び抜けていた。
  • 宣言勝ちを実装
  • 動かしたときに自動的に思考を走らせる自動検討モードを実装
  • モード切替時などにポップアップを追加 参考
  • 対局成績の記録を追加。アップデート入れたときにファイル内容がどうなるかとか知らないので簡単に消し飛んでしまいそうなところはあるなぁ 参考

 いや、小さいデータの保存はSharedPreferencesを使う方が良いのかもしれない 。修正した。

  • Chainという機能があることを知ったのでちょっと使ってみた 参考
  • Kotlinでクラス変数を作る方法が調べてもよくわからなかったんだけど、companion objectを使えば良かったんだなということに気づいて修正

3月31日

 アイコンを決める(きふわらべ氏が以前描いたものを利用させていただくことに)。そう言えば去年なんか全員分描いてもらっていたんじゃなかったっけと過去ツイートを掘り出したら超カワイイMiacisが出てきて即利用許可をお願いしに行った。快諾してもらい感謝感謝。

  • 投了を追加
  • その他諸々の細かい変更
  • リリース 参考
  • com.exampleは使えないって、まぁそれはそうなんだろうけど、どう命名したら良いのかよくわからないな。適当
  • 適当に画像とか作って、とりあえずリリース完了。審査待ち

4月1日

  • 自動検討モードの切り替えをトグルスイッチで行うように変更
  • 思考部分をCoroutineで実装して別スレッドへ 参考
    • 並列化については結構苦労していろいろ調べたけど、結局公式ページをなんとか読解していくので多分実現できた。自動翻訳なのか知らないけど読みにくい……
    • Dispatcherというのがよくわからないけど、なんかDefaultで良いっぽい 参考

4月2日

  • SFENの入力で文字列の合法性を判定する機能を追加
  • 対局設定のActivityを追加
  • バージョンを上げてリリースし直した。審査まだかなー

4月4日

 評価値グラフを追加

4月5日

  • 自動検討モードのオン/オフを記憶する仕組みを導入したらめちゃくちゃバグりまくった
    • 最初からオンになっていると、起動直後に検討が何回か入って、排他制御が甘いので盤面が壊れて落ちるという現象っぽい。排他制御、本質的に難しい
    • 盤面のコピー機能を追加してなんとかした。まだ落ちるタイミングはあるようだけど

4月7日

 とうとうリリースされた。審査に1週間くらいかかったな……。途中でバージョン2とか3を次々投入したのがダメだったんだろうとは思うが、開発途中だと毎日更新くらいしたくなりそうな気がする(気が短いので完成を待つということができない)。

 とりあえず開発日記としてはここまで了