Interesuje mnie programowanie silnika szachowego i używanie tablic bitowych do reprezentowania stanu gry. Wiem, że są kilka silników szachowych typu open source, które używają bitboardów, ale nie jest łatwo spojrzeć na kod i zrozumieć, co się dzieje. Szukam dobrego materiału referencyjnego na temat tego, jak przedstawić cały stan w bitboardach.
Wyraźne wyjaśnienie, jak utrzymać stan gry za pomocą tablic bitowych, a zwłaszcza jak wygenerować listę prawidłowych ruchów z dowolnej tablicy bitowej lub dostarczenie dobrych odniesień do takiego wyjaśnienia, przyniesie zielony znacznik wyboru.
Komentarze
- 1. OP nie wykazuje żadnej znajomości tematu. Oznacza to, że PO nie próbował poważnie się kształcić. 2. Tu chodzi o programowanie, a nie o szachy.
- @TonyEnnis Dlaczego musisz zachowywać się tak niegrzecznie w stosunku do innych ludzi ??, okaż mu trochę szacunku i pokaż mu, co powinna poprawić, zamiast być tak kwaśnym
- Podawanie faktów nie jest niegrzeczne ani kwaśne, @AryanParekh
- @Tonny Ennis. Wyobraź sobie, że jesteś początkującym, nowym i po prostu zadawałeś pytanie w nadziei, że ' uzyskasz dobrą odpowiedź. I wtedy zobaczysz taki komentarz. Czy inne osoby przeszły ponownie, aby odpowiedzieć na jego pytania? A może czujesz się zbyt wysoko, aby to rozważyć.
Odpowiedź
Najlepsze źródło informacji o programowaniu silnika szachowego to Wiki programowania szachowego , która ma dużą sekcję na tablicach bitowych . Jest tam wszystko, czego potrzebujesz do stworzenia silnika opartego na tablicy bitowej, chociaż jest on raczej rozproszony i czasami napisany przez ludzi, dla których angielski jest drugim językiem.
Komentarze
- Te 2 linki są teraz nieprawidłowe.
- Nadal działają dla mnie w momencie pisania tego komentarza.
Odpowiedź
Jakiego języka programowania chcesz używać?
Aby zaimplementować tablicę bitową w C #, użyj System.UInt64 . Może przechowywać 64 bity, po 1 na każdy kwadrat szachownicy. Ten typ wartości nadaje się do wielu szybkich operacji bitowych.
To jest dobry samouczek bitboardowy .
Oto kilka przykładów z mojego własnego silnika szachowego C #. Jak widać z kodu, zapakowanie twojego korzystaj z tablic bitowych, ale zazwyczaj są one bardzo szybkie, szczególnie do oceny pozycji.
Przykład 1 – definicja tablicy bitowej:
internal UInt64 WhiteKing; internal UInt64 WhiteQueens; internal UInt64 WhiteRooks; internal UInt64 WhiteBishops; internal UInt64 WhiteKnights; internal UInt64 WhitePawns; internal UInt64 WhitePieces;
Przykład 2 – Inicjalizacja tablicy bitowej:
// Initialise piece bitboards using square contents. private void InitPieceBitboards() { this.WhiteKing = 0; this.WhiteQueens = 0; this.WhiteRooks = 0; this.WhiteBishops = 0; this.WhiteKnights = 0; this.WhitePawns = 0; for (Int16 i = 0; i < 64; i++) { if (this.Squares[i] == Constants.WHITE_KING) { this.WhiteKing = this.WhiteKing | Constants.BITSET[i]; } if (this.Squares[i] == Constants.WHITE_QUEEN) { this.WhiteQueens = this.WhiteQueens | Constants.BITSET[i]; } if (this.Squares[i] == Constants.WHITE_ROOK) { this.WhiteRooks = this.WhiteRooks | Constants.BITSET[i]; } if (this.Squares[i] == Constants.WHITE_BISHOP) { this.WhiteBishops = this.WhiteBishops | Constants.BITSET[i]; } if (this.Squares[i] == Constants.WHITE_KNIGHT) { this.WhiteKnights = this.WhiteKnights | Constants.BITSET[i]; } if (this.Squares[i] == Constants.WHITE_PAWN) { this.WhitePawns = this.WhitePawns | Constants.BITSET[i]; } this.WhitePieces = this.WhiteKing | this.WhiteQueens | this.WhiteRooks | this.WhiteBishops | this.WhiteKnights | this.WhitePawns; this.BlackPieces = this.BlackKing | this.BlackQueens | this.BlackRooks | this.BlackBishops | this.BlackKnights | this.BlackPawns; this.SquaresOccupied = this.WhitePieces | this.BlackPieces; } }
Przykład 3 – Generowanie przeniesienia:
// We can"t capture one of our own pieces. eligibleSquares = ~this.WhitePieces; // Generate moves for white knights. remainingKnights = this.WhiteKnights; // Generate the moves for each knight... while (remainingKnights != 0) { squareFrom = BitOps.BitScanForward(remainingKnights); generatedMoves = Constants.ATTACKS_KNIGHT[squareFrom] & eligibleSquares; while (generatedMoves != 0) { squareTo = BitOps.BitScanForward(generatedMoves); moveList.Add(new Move(squareFrom, squareTo, Constants.WHITE_KNIGHT, this.Squares[squareTo], Constants.EMPTY)); generatedMoves ^= Constants.BITSET[squareTo]; } // Finished with this knight - move on to the next one. remainingKnights ^= Constants.BITSET[squareFrom]; }
Przykład 4 – Oblicz wynik materiałowy:
// Material score from scratch, in centipawns from White"s perspective. internal static Int32 ScoreMaterial(Board position) { return BitOps.BitCountWegner(position.WhitePawns) * Constants.VALUE_PAWN + BitOps.BitCountWegner(position.WhiteKnights) * Constants.VALUE_KNIGHT + BitOps.BitCountWegner(position.WhiteBishops) * Constants.VALUE_BISHOP + BitOps.BitCountWegner(position.WhiteRooks) * Constants.VALUE_ROOK + BitOps.BitCountWegner(position.WhiteQueens) * Constants.VALUE_QUEEN - BitOps.BitCountWegner(position.BlackPawns) * Constants.VALUE_PAWN - BitOps.BitCountWegner(position.BlackKnights) * Constants.VALUE_KNIGHT - BitOps.BitCountWegner(position.BlackBishops) * Constants.VALUE_BISHOP - BitOps.BitCountWegner(position.BlackRooks) * Constants.VALUE_ROOK - BitOps.BitCountWegner(position.BlackQueens) * Constants.VALUE_QUEEN; }
Przykład 5 – Obliczanie ruchliwości elementu:
// Calculate mobility score for white knights. remainingPieces = position.WhiteKnights; while (remainingPieces != 0) { squareFrom = BitOps.BitScanForward(remainingPieces); mobilityKnight += BitOps.BitCountWegner(Constants.ATTACKS_KNIGHT[squareFrom] & unoccupiedSquares); remainingPieces ^= Constants.BITSET[squareFrom]; }
Komentarze
- czy możesz podać definicję moveList?