Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

レイアウト

Square は筋を先に、段を後に並べた 0 始まりの番号を使う。

したがって Square::raw() = file * 9 + rank であり、同じ筋の 9 マスは連続する。

bit 0..8      : 1 筋の 1..9 段
bit 9..17     : 2 筋の 1..9 段
...
bit 72..80    : 9 筋の 1..9 段

この順序では file_mask は各 9 ビットの連続範囲になり、rank_mask は 9 ビット間隔の集合になる。

二つの u64

Bitboard は 81 ビットを一つの Rust の u128 フィールドには置かない。

内部配列の p[0] は bit 0..62 を、p[1] は bit 63..80 を保持する。

Bitboard::ALL はこの二つの有効範囲だけを 1 にし、コンストラクタも同じ範囲を強制する。

p[0] : bit 62 ........................................ bit 0
p[1] : bit 17 ........................................ bit 0
       = 盤面の bit 80 ............................... bit 63

packed_bitsp[1] を 63 ビット左へずらして連続した盤面ビット列を復元する。

raw_bitsp[1] を 64 ビット左へずらす内部用の値であり、二ワードのレーン境界を保つ。

二つの表現は同じ盤面集合を扱うが、bit 63 以降の位置が異なるため、相互に混ぜて保存・比較してはならない。

境界と変換

from_packed_bits は入力の bit 81 以上を捨て、連続表現から p を構築する。

from_parts も各ワードをマスクするため、外部から渡す二ワード値に盤外ビットがあっても Bitboard には残らない。

反対に from_raw_bits_unmasked は crate 内の二ワード演算と飛び利き計算が使う内部変換である。

これは中間計算で盤外ビットを保持できるようにするためであり、公開データの構築手段ではない。

整列

型は 16 バイト整列される。

x86_64 で SSE2 が有効なら、論理演算は二ワードを 128 ビットのレジスタとして読み書きする。

整列は型の ABI とレイアウトを安定させるが、実装は unaligned load/store intrinsic を用いるため、呼び出し側が別途ポインタ整列を管理する契約ではない。

幾何学との対応

座標番号は筋ごとに連続するため、縦方向の利きは 9 ビットの連続範囲として取り出せる。

横方向と斜め方向は連続したビット列ではないが、事前生成した方向レイを使うことで同じ集合演算へ持ち込める。

同じ筋:  bit 36, 37, 38, 39, 40, 41, 42, 43, 44
同じ段:  bit  4, 13, 22, 31, 40, 49, 58, 67, 76

この違いが、香の筋方向で小さな FILE_ATTACKS 表を使い、角と飛の他方向でレイ抽出を使う理由である。

マス番号の増減だけで方角を判断せず、FileRank の関係または生成済みテーブルを使う。

端のマスで番号の算術を続けると、隣の筋・段へ回り込む誤りを作りやすい。

表示と向き

Debug 表示は段と筋を反転した順で盤面を出力するため、ビット番号の昇順とは見た目の走査順が一致しない。

一方、BitIter は raw index の昇順、すなわち pop_lsb の順でマスを返す。

表示、棋譜座標、内部ビット順を混同しないことが、反転とテーブル生成の検証で特に重要になる。