Bagaimana cara mengubah gerakan potongan yang mungkin menjadi gerakan aktual di bitboard?

Jan 09 2021

Jika saya memiliki bitboard (misalnya untuk kotak ksatria dia bisa pindah ke) seperti ini:

00000000
00000000
00000000
00000000
00000000
01000000
00100000
N0000000

Bagaimana saya bisa "mengubahnya" menjadi gerakan atau "menerapkan" langkah itu?

Jawaban

2 AryanParekh Jan 09 2021 at 19:28

Sebenarnya ada dua pertanyaan di postingan Anda

  • Bagaimana cara mengubah Serangan di Bitboards menjadi daftar gerakan?

  • Bagaimana cara merepresentasikan gerakan itu?


  • Bagaimana cara merepresentasikan gerakan itu?

Pertanyaan ini telah dibahas di sini dan di sini secara menyeluruh. Tetapi untuk memberikan beberapa konteks kepada pembaca posting ini, cara yang sangat sederhana untuk melakukannya adalah dengan menggunakan class / struct untuk mewakili suatu gerakan.

  • Dari (tempat potongan yang bergerak itu)
  • Ke (di mana bidak yang bergerak itu berada)
  • Bendera Pindah Khusus (apakah gerakan itu merupakan gerakan khusus, yaitu enpassant, casting, promotion)
  • Bidak yang Dipromosikan (jika kepindahan itu adalah jurus promosi, bidak apa yang dipromosikannya)

Anda juga dapat memiliki atribut tambahan seperti bidak yang ditangkap, jenis kastil, dll. Tetapi informasi itu juga dapat disimpulkan menggunakan kotak Fromdan To.

Jadi dengan memperhatikan hal di atas, kita dapat merepresentasikan pergerakan tersebut sebagai berikut

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

Namun, banyak mesin catur, termasuk milik saya, menggunakan metode lain yang dapat memampatkan langkah menjadi hanya 16bit. Baca lebih lanjut tentang itu di sini .

Begitu kita tahu apa itu gerakan, kita bisa menjawab pertanyaan berikutnya


  • Bagaimana cara mengubah Serangan di Bitboards menjadi daftar gerakan?

Mari kita pertimbangkan bahwa kita memiliki seorang ksatria di alun-alun d4 . Kami juga memiliki fungsi yang mengembalikan serangan seorang ksatria yang diberi kotak.

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

Jadi mari simpan ini di dalam variabel knightAttacks

uint64_t knightAttacks = getKnightAttacksBB(SQ_D4);

Jika Anda perhatikan dengan seksama, kami sudah memiliki 1 dari 4 atribut yang kami butuhkan untuk mewakili gerakan, yaitu Frompersegi - D4. Sekarang yang perlu kita lakukan hanyalah membuat Tokotak untuk menyelesaikan ini karena seorang kesatria tidak dapat melakukan gerakan khusus apa pun.

Metode yang sangat umum adalah dengan mengeluarkan bit yang paling tidak signifikan sampai Anda knightAttackstidak memiliki apa-apa yaitu 0.

0000011100001000 
            ^
            Least significant bit (lsb)

Anda dapat mengikuti tautan yang saya berikan untuk mengetahui bagaimana Anda dapat melakukan ini, atau ada kemungkinan kompilator Anda mungkin sudah menyediakannya untuk Anda.

Anda hanya perlu membuat fungsi yang menghapus lsb dari bitboard dan mengembalikan indeksnya. Sebut saja poplsb().

Secara keseluruhan, kode Anda akan terlihat seperti ini

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
}

Ini berfungsi karena setiap kali Anda meletuskan lsb, sedikit dihapus hingga jumlahnya == 0. Saat itulah loop berhenti dan Anda memiliki daftar gerakan yang sangat bagus. Ide yang sama berlaku untuk semua jenis gerakan yang Anda buat menggunakan Bitboards.