Bagaimana cara mengubah gerakan potongan yang mungkin menjadi gerakan aktual di bitboard?
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
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 From
dan 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 16
bit. 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 From
persegi - D4
. Sekarang yang perlu kita lakukan hanyalah membuat To
kotak 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 knightAttacks
tidak 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.