Come posso convertire le mosse di un possibile pezzo in una mossa effettiva in una bitboard?
Se ho un bitboard (ad esempio per le caselle dei cavalieri può spostarsi) in questo modo:
00000000
00000000
00000000
00000000
00000000
01000000
00100000
N0000000
Come posso "convertirlo" in una mossa o "applicare" quella mossa?
Risposte
In realtà ci sono due domande nel tuo post
Come convertire gli attacchi in Bitboard in un elenco di mosse?
Come rappresentare quelle mosse?
- Come rappresentare quelle mosse?
Questa domanda è stata discussa qui e qui a fondo. Ma per fornire un contesto ai lettori di questo post, un modo molto semplice per farlo può essere usare una classe / struttura per rappresentare una mossa
- Da (dov'era il pezzo in movimento)
- A (dove sarà il pezzo in movimento)
- Flag mossa speciale (se la mossa era una mossa speciale, ad esempio enpassant, casting, promozione)
- Pezzo promosso (se la mossa era una mossa di promozione, a quale pezzo è stata promossa)
Puoi anche avere attributi extra come pezzo catturato, tipo di castello, ecc. Ma queste informazioni possono anche essere dedotte usando i quadrati From
e To
.
Quindi, considerando quanto sopra, possiamo rappresentare la mossa come segue
struct Move {
char from;
char to;
char spMoveFlag;
char promotedPiece;
};
Tuttavia, molti motori scacchistici, incluso il mio, usano un altro metodo che può comprimere la mossa in solo 16
bit. Leggi di più a riguardo qui .
Una volta che sappiamo cos'è una mossa, possiamo rispondere alla domanda successiva
- Come convertire gli attacchi in Bitboard in un elenco di mosse?
Consideriamo che abbiamo un cavaliere sulla casella d4 . Abbiamo anche una funzione che restituisce gli attacchi di un cavaliere dato il quadrato.
. . . . . . . .
. . . . . . . .
. . 1 . 1 . . .
. 1 . . . 1 . .
. . . n . . . . = knightattacks(SQ_D4)
. 1 . . . 1 . .
. . 1 . 1 . . .
. . . . . . . .
Quindi memorizziamo questo all'interno di una variabile knightAttacks
uint64_t knightAttacks = getKnightAttacksBB(SQ_D4);
Se noti attentamente, abbiamo già 1 dei 4 attributi di cui abbiamo bisogno per rappresentare la mossa, che è il From
quadrato - D4
. Ora tutto ciò che dobbiamo fare è in qualche modo ottenere il To
quadrato per completare questo dato che un cavaliere non può eseguire alcun tipo di mosse speciali.
Un metodo molto comune è quello di far scoppiare il bit meno significativo fino a quando non knightAttacks
rimane nulla, ad es 0
.
0000011100001000
^
Least significant bit (lsb)
Puoi seguire il link che ti ho fornito per sapere come puoi eseguire questa operazione, o c'è la possibilità che il tuo compilatore possa già fornirtelo.
Hai semplicemente bisogno di creare una funzione che cancella il lsb di una bitboard e restituisce il suo indice. Chiamiamolo poplsb()
.
Complessivamente, il tuo codice può assomigliare a questo
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
}
Questo funziona perché ogni volta che si apre lsb, un po 'viene cancellato fino a quando il numero è == 0. Questo è il momento in cui il ciclo si interrompe e si ha una lista di mosse perfettamente buona. La stessa idea si applica a qualsiasi tipo di mossa che hai creato utilizzando Bitboard.