Come posso convertire le mosse di un possibile pezzo in una mossa effettiva in una bitboard?

Jan 09 2021

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

2 AryanParekh Jan 09 2021 at 19:28

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 Frome 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 16bit. 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 Fromquadrato - D4. Ora tutto ciò che dobbiamo fare è in qualche modo ottenere il Toquadrato 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 knightAttacksrimane 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.