ฉันจะแปลงการเคลื่อนไหวของชิ้นส่วนที่เป็นไปได้ให้เป็นการเคลื่อนไหวจริงในบิตบอร์ดได้อย่างไร
ถ้าฉันมีบิตบอร์ด (เช่นอัศวินสี่เหลี่ยมเขาสามารถย้ายไปได้) เช่นนี้:
00000000
00000000
00000000
00000000
00000000
01000000
00100000
N0000000
ฉันจะ "แปลง" เป็นการย้ายหรือ "ใช้" การย้ายนั้นได้อย่างไร
คำตอบ
มีคำถามสองข้อในโพสต์ของคุณ
จะแปลงการโจมตีใน Bitboards เป็นรายการการเคลื่อนไหวได้อย่างไร?
จะแสดงถึงการเคลื่อนไหวเหล่านั้นได้อย่างไร?
- จะแสดงถึงการเคลื่อนไหวเหล่านั้นได้อย่างไร?
คำถามนี้ได้รับการกล่าวถึงที่นี่และที่นี่อย่างละเอียด แต่เพื่อให้บริบทบางอย่างแก่ผู้อ่านโพสต์นี้วิธีง่ายๆในการทำเช่นนี้คือการใช้คลาส / โครงสร้างเพื่อแสดงการเคลื่อนไหว
- จาก (ชิ้นส่วนที่เคลื่อนที่ได้)
- ถึง (ชิ้นส่วนที่เคลื่อนที่จะอยู่ที่ไหน)
- Special Move Flag (ไม่ว่าการเคลื่อนไหวนั้นจะเป็นการเคลื่อนไหวพิเศษเช่น enpassant การคัดเลือกนักแสดงการเลื่อนตำแหน่ง)
- ชิ้นส่วนที่ได้รับการเลื่อนขั้น (หากการเคลื่อนไหวเป็นการเลื่อนขั้นเลื่อนตำแหน่งชิ้นส่วนใดที่ส่งเสริม)
คุณยังสามารถมีคุณสมบัติพิเศษเช่นชิ้นส่วนที่จับได้ประเภทของปราสาทเป็นต้น แต่ข้อมูลนั้นสามารถอนุมานได้โดยใช้From
และTo
กำลังสอง
ดังนั้นเมื่อพิจารณาจากข้างต้นเราสามารถแสดงการย้ายได้ดังนี้
struct Move {
char from;
char to;
char spMoveFlag;
char promotedPiece;
};
อย่างไรก็ตามเครื่องมือหมากรุกจำนวนมากรวมถึงของฉันใช้วิธีอื่นที่สามารถบีบอัดการเคลื่อนไหวให้เป็น16
บิตได้ อ่านข้อมูลเพิ่มเติมเกี่ยวกับที่นี่
เมื่อเรารู้ว่าการเคลื่อนไหวคืออะไรเราสามารถตอบคำถามต่อไปได้
- จะแปลงการโจมตีใน Bitboards เป็นรายการการเคลื่อนไหวได้อย่างไร?
ลองพิจารณาว่าเรามีอัศวินในตารางd4 นอกจากนี้เรายังมีฟังก์ชั่นที่ส่งกลับการโจมตีของอัศวินที่ได้รับจากจัตุรัส
. . . . . . . .
. . . . . . . .
. . 1 . 1 . . .
. 1 . . . 1 . .
. . . n . . . . = knightattacks(SQ_D4)
. 1 . . . 1 . .
. . 1 . 1 . . .
. . . . . . . .
ลองเก็บสิ่งนี้ไว้ในตัวแปร knightAttacks
uint64_t knightAttacks = getKnightAttacksBB(SQ_D4);
ถ้าคุณสังเกตเห็นอย่างรอบคอบเรามีอยู่แล้ว 1 ของคุณลักษณะ 4 เราต้องเป็นตัวแทนของการย้ายซึ่งเป็นFrom
ตาราง D4
- ตอนนี้สิ่งที่เราต้องทำก็คือทำให้สTo
แควร์เสร็จสมบูรณ์เนื่องจากอัศวินไม่สามารถเคลื่อนไหวพิเศษใด ๆ ได้
วิธีการทั่วไปคือการแสดงบิตที่มีนัยสำคัญน้อยที่สุดจนกว่าคุณknightAttacks
จะไม่เหลืออะไร0
เลย
0000011100001000
^
Least significant bit (lsb)
คุณสามารถไปตามลิงค์ที่ฉันให้ไว้เพื่อทราบว่าคุณสามารถดำเนินการนี้ได้อย่างไรหรือมีโอกาสที่คอมไพเลอร์ของคุณอาจให้ข้อมูลแก่คุณอยู่แล้ว
คุณต้องสร้างฟังก์ชันที่ล้าง lsb ของ bitboard และส่งกลับดัชนี ขอเรียกว่า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 นั่นคือเวลาที่ลูปหยุดลงและคุณมีรายการการเคลื่อนไหวที่ดีอย่างสมบูรณ์แบบ แนวคิดเดียวกันนี้ใช้กับการเคลื่อนไหวทุกประเภทที่คุณสร้างขึ้นโดยใช้ Bitboards