可能なピースの動きをビットボードの実際の動きに変換するにはどうすればよいですか?

Jan 09 2021

私がこのようなビットボードを持っている場合(たとえば、彼が移動できるナイトスクエアの場合):

00000000
00000000
00000000
00000000
00000000
01000000
00100000
N0000000

どうすればそれを移動に「変換」したり、その移動を「適用」したりできますか?

回答

2 AryanParekh Jan 09 2021 at 19:28

あなたの投稿には実際には2つの質問があります

  • ビットボードの攻撃を移動のリストに変換するにはどうすればよいですか?

  • それらの動きをどのように表現するのですか?


  • それらの動きをどのように表現するのですか?

この質問はこことここで徹底的に議論されました。しかし、この投稿の読者にコンテキストを提供するために、これを行う非常に簡単な方法は、クラス/構造体を使用して移動を表すことです。

  • から(可動部分があった場所)
  • To(可動部分がある場所)
  • 特別な移動フラグ(移動が特別な移動であったかどうか、つまり、アンパッサン、キャスティング、プロモーション)
  • プロモートピース(移動がプロモーション移動の場合、どのピースにプロモートしましたか)

キャプチャされたピース、城のタイプなどの追加の属性を持つこともできます。ただし、その情報は、FromおよびTo正方形を使用して推測することもできます。

したがって、上記を考慮すると、次のように動きを表すことができます

struct Move {
    char from; 
    char to;   
    char spMoveFlag;
    char promotedPiece;
};

しかし、私のものを含む多くのチェスエンジンは、動きをほんの少しに圧縮できる別の方法を使用してい16ます。詳しくはこちらをご覧ください。

動きが何であるかがわかったら、次の質問に答えることができます


  • ビットボードの攻撃を移動のリストに変換するにはどうすればよいですか?

正方形d4に騎士がいるとしましょう。正方形を与えられた騎士の攻撃を返す機能もあります。

. . . . . . . . 
. . . . . . . . 
. . 1 . 1 . . . 
. 1 . . . 1 . . 
. . . n . . . .   =  knightattacks(SQ_D4)
. 1 . . . 1 . . 
. . 1 . 1 . . . 
. . . . . . . . 

それでは、これを変数内に格納しましょう knightAttacks

uint64_t knightAttacks = getKnightAttacksBB(SQ_D4);

注意深く気づいたら、移動を表すために必要な4つの属性のうちの1つ、つまりFrom正方形がすでにありますD4To騎士はどんな種類の特別な動きも実行できないので、今私たちがする必要があるのは、どういうわけかこれを完了するために正方形を手に入れることです。

非常に一般的な方法は、最下位ビットをポップすることです。knightAttacksすなわち何も残されています0

0000011100001000 
            ^
            Least significant bit (lsb)

私が提供したリンクをたどって、これを実行する方法を知ることができます。または、コンパイラーがすでに提供している可能性があります。

ビットボードのlsbをクリアし、そのインデックスを返す関数を作成する必要があります。それを呼びましょうpoplsb()

全体として、コードは次のようになります

int from = SQ_D4;
uint16_t knightAttacks = getknightAttacks(from);

while (knightAttacks)  {
     int to = poplsb(knightAttacks);
     MyMoveList.Add( NewMove(from, to, 0, 0) ); // The last two 0's denote that there is no special move
}

これが機能するのは、lsbをポップするたびに、数値が== 0になるまでビットがクリアされるためです。ループが停止し、完全に適切な移動リストが得られるときです。同じ考え方が、ビットボードを使用して作成したあらゆる種類の動きに当てはまります。