将棋プログラム「Sunfish」 -2ページ目

将棋プログラム「Sunfish」

主に将棋プログラム「Sunfish」の開発について書いています。

第25回世界コンピュータ将棋選手権に申し込みました。

今作っているバージョンはやっとこさ
CSAプロトコルで対局ができるようになったところで、
このままだと1次予選落ちしそうです。
それにアピール文に書くことがありません。

しかし、出ないとまただらだらとした生活を送ってしまいそうで、
勢いだけで申し込みを済ませました。

最新版を常にgithubにpushしながら開発しています。

github
https://github.com/sunfish-shogi/sunfish3

floodgate
http://wdoor.c.u-tokyo.ac.jp/shogi/view/show-player.cgi?event=LATEST&filter=floodgate&show_self_play=1&user=Sunfish3

ところで、毎回1人で出ているのですが
なかなか作業時間的にもモチベーション的にもつらく
誰か一緒に出てくれる人を探しています。

今からでも、3月くらいまでは出場者の情報を
変更できたような気がします。多分。

僕よりだいぶプログラミング得意でかつ将棋が好きで、
時間を持て余している学生とか居たら連絡ください。

合法手生成を実装したので速度の計測を行いました。

ただし、王手放置、打ち歩詰めの判定がまだ入っていません。


使用した局面は「指し手生成祭り」と同じです。
(マシンはWCSC2011出場時のラップトップ、Ubuntu、g++ 4.6.3、O2最適化)
結果は約 85万局面/sec でこれに pin とか打ち歩詰め判定が入ることを考えるとかなり遅いでしょうか。

ソースコード
https://github.com/sunfish-shogi/sunfish3

これから何回か Bonanza 6.0 の bitboard の実装について書いていきます。
今更読んでもらう必要の無い内容も多くなると思いますが、
自分の勉強もかねてまとめていきます。
間違いがあれば指摘をお願いします。

盤面の座標

まず、盤面のマス目の番号の振り方を見ます。
init.c を見ると
isquare = irank*nfile + ifile;
とあります。
irankは0~8がそれぞれ1段目~9段目、
ifileは0~8がそれぞれ9筋~1筋を指しています。
ifileが左から始まるのは csa.c などから分かります。
つまり盤面のマス目は
isquare = 0 : irank = 0, ifile = 0 : 9一
isquare = 1 : irank = 0, ifile = 1 : 8一
isquare = 2 : irank = 0, ifile = 2 : 7一
 :
isquare = 9 : irank = 1, ifile = 0 : 9二
isquare = 10 : irank = 1, ifile = 1 : 8二
 :
と左上から始まって右へ、そして次の段へ折り返しています。
また、列挙体で各マス目の番号は
enum { A9 = 0, B9, C9, D9, E9, F9, G9, H9, I9,
...
とあるので、筋は右からA, B, ..., I、
段は上から1, 2, ..., 9 としているようです。

bitとマス目の対応

次にbitboardです。Bonanza では次のように 32bit x 3 で表現しています。
typedef struct { unsigned int p[3]; } bitboard_t;
先ほどのマス目の番号との対応はini.c内の次の関数で分かります。
static bitboard_t
bb_set_mask( int sq )
{
  bitboard_t bb;
 
  BBIni(bb);
  if      ( sq > 53 ) { bb.p[2] = 1U << ( 80 - sq ); }
  else if ( sq > 26 ) { bb.p[1] = 1U << ( 53 - sq ); }
  else                { bb.p[0] = 1U << ( 26 - sq ); }
 
  return bb;
}
54以上(9七, 8七, ..., 1九) => bb.p[2]
26以上(9四, 8四, ..., 1六) => bb.p[1]
25以下(9一, 8一, ..., 1三) => bb.p[0]
という対応になっています。
3段(27マス)で区切って管理しているようです。

盤面の表現

盤面はposi_t構造体で表現されます。
shogi.hにはposi_tの各メンバに対応する以下のマクロ定義が書かれています。
BB_BOCCUPY     全ての駒
BB_BTGOLD      金、と金、成香、成桂、成銀
BB_B_HDK       馬、竜、玉
BB_B_BH        角、馬
BB_B_RD        飛、竜
BB_BPAWN_ATK   歩の効き先
BB_BPAWN       歩
BB_BLANCE      香
BB_BKNIGHT     桂
BB_BSILVER     銀
BB_BGOLD       金
BB_BBISHOP     角
BB_BROOK       飛
BB_BKING       玉
BB_BPRO_PAWN   と金
BB_BPRO_LANCE  成香
BB_BPRO_KNIGHT 成桂
BB_BPRO_SILVER 成銀
BB_BHORSE      馬
BB_BDRAGON     竜

BB_W~         後手の駒

OCCUPIED_FILE  90度回転
OCCUPIED_DIAG1 右下がり45度
OCCUPIED_DIAG2 右上がり45度
BOARD 各マスの駒を表す配列
BB_B~が先手、BB_W~が後手の駒を表します。

OCCUPYは歩、香、...、竜まで全てです。

FILEは90度回転して縦方向が連続するように、
DIAG1, DIAG2は斜めが連続するように
並び順が置き換えられたものです。
(ini.cのaini_rl90, aini_rl45, aini_rr45に従って座標変換)
まだ該当個所をきちんと読んでいませんが、
FILE, DIAG1, DIAG2は飛び駒の効きの計算に使うと思われます。
(つまり、magic bitboard なら不要?)

BOARDはbitboardでない場合でも使うのと同様の
添字がマス目、値が駒番号の配列のようです。
取られた駒の種類を取得するときに使うのでしょうか。

長くなってしまうのでここまでで一旦終わりたいと思います。


WCSC2013が終わってからプライベートではほぼ何の開発もしていませんでした。
仕事でプログラミングをしているせいか、学生の頃と比べると自由な時間をプログラミングに使おうという気になれません。

仕事は仕事でわりとやりたいことをやらせてもらっていて、それはとても良いと思っています。
ただ、子供の頃から憧れていたものはコンピュータ将棋とか円周率の計算とかで、お金になるかとか自分に才能があるかとかは別として取り組んでいないと寂しい気持ちになります。

少しまずいなと思って、年が明けた辺りからは時間を見つけて少しずつ開発を進めるようにしています。

まずは Sunfish を再度作りなおすことにしました。

https://github.com/sunfish-shogi/sunfish3

WCSC2015, 16 あたりの出場を目標に開発を進めたいと思います。
次の5月に関しては何の準備もできていないので諦めることにしました。
将棋関係の友達からは、次も前回と同じので出ればいいじゃないかと言われます。
でも、何も改良できていないプログラムで参加するのは、プレゼン資料を使いまわしてごまかすみたいに気分が良くないものです。
それに、大会で自分が将棋を指すのではなくても、これはこれで結構疲れるんです。

あと、電王戦についてはあまり関心が無くて、今後予選に出場することも考えていません。
Sunfish の次のバージョンがすごく強くなって、かつ電王戦の内容が大きく変わったら考えなおすかもしれません。

今年はブログをそれなりの頻度で更新していきたいと思っています。
今は Bonanza のソースを読んで bitboard を勉強しているので、わかったことなどをまとめていきたいです。