ここでは、MarcのMoveGeneratorの中でのデータ表現について分析してみる。盤上の桝位置を示す値、駒コードについては、Marcのソース chess_square_defs.vhd の中で定義されている。桝位置はカラム/ローが3ビットづつ("000"~"111")の計6ビット、駒コードは3ビットで具体的には次の様な表現になっている[*1]
--
"000":Empty (空桝)
"001":Pawn
"010":King
"100":Knight
"101":Bishop
"110":Rook
"111":Queen
--
更に色(手番)は "1" をWhite、"0" をBlackとし、色+駒コードの合計4ビットで駒種を表現している。これとは別に、更に2つの内部表現がある。1つは「駒の利き表現(6ビット)」で、もう一つはアービトレーション用「優先度(3ビット)」だ[*2]。どちらも駒種コードからデコード生成され、内部的に処理し易いように変換しているだけのことなので複雑に考える必要はない。


これを将棋へ適用する場合、余程酷いコード設計でない限りは神経質になる必要はないと考える。必要があれば、処理の内容に応じて内部でコード変換を掛けて用いれば良いだけの話だ。とはいえ無駄なデコードが頻繁に入るようではリソース的にも速度的にも厳しくなるので、なるべく(ソフト処理でもハード処理でも)合理的な将棋用のコードをここで考えてみることにする。
--
(bit0~3の4ビット)
"0000":歩 "1000":と
"0001":香 "1001":成香
"0010":桂 "1010":成桂
"0011":銀 "1011":成銀
"0100":金 "1100":<未使用>
"0101":角 "1101":馬
"0110":飛 "1110":竜
"0111":玉 "1111":<仮想合駒>
--
上記は現謎電で使用している駒コードで、4ビットで構成される。これがベストだとは言えないかもしれないが、ソフト/ハード共用で使うコードとしては、それほど悪くはないと考えている。また、これとは別に手番等を示す為に2ビットが頭に付加される。
--
(bit4~5の2ビット)
"00":空桝
"01":先手(下手)駒
"10":後手(上手)駒
"11":<移動不可:OB領域>
--
この中の "11" については内部的なコードで盤外検出用に使っているものである。ソフト探索の場合に意味があるだけで、ハード探索では決して使用されない[*3]。なお、指手の生成順の制御は、アービタに送り込む「駒の優先度」、即ち駒の価値で決められることになるわけだが、その場合は4ビット駒コードから4つのLUTを使い1つのロジックレベルで変換が可能であるし、利き表現については元々将棋は駒種が多く、左右対称ではあっても「前後の対称性」が低いので、チェスの様には単純化出来ないものと考えている。


余談だが、ソフトでのデータ表現の場合、「ビット位置」が極めて重要な意味を持つ場合があるが、ハードでは基本的にON/OFFの表現であって、それを纏めて「2進数値」として捉えるだけでなく、「ベクトル」や「1ビットデータの配列」として扱う。結局配線次第でビット位置を自在に入れ替えたり削ったり割り込んだり出来るので、ソフトより更に「柔軟にデータ処理ができる」ことを知っておく必要があり、それがハードを巧く使うコツにもなる。

-- 続く --


[*1] なにやら妙なコード体系に見えるが、これはこれで相当合理的な割り当て方である。

[*2] 詳しくは、Marcのソース chess_square.vhd と論文 MBThesis.pdf "An FPGA Move Generator for the Game of Chess"の4-3(前者)と4-4(後者)を参照のこと。
[*3] そもそもハード探索の場合、盤外に相当する「桝」が存在しない。