Como posso converter movimentos de peças possíveis em um movimento real em um bitboard?
Se eu tiver um bitboard (por exemplo, para quadrados de cavaleiros, ele pode se mover) como este:
00000000
00000000
00000000
00000000
00000000
01000000
00100000
N0000000
Como posso "convertê-lo" em um movimento ou "aplicar" esse movimento?
Respostas
Na verdade, existem duas perguntas em sua postagem
Como converter ataques em bitboards em uma lista de movimentos?
Como representar esses movimentos?
- Como representar esses movimentos?
Esta questão foi discutida aqui e aqui completamente. Mas para fornecer algum contexto aos leitores deste post, uma maneira muito simples de fazer isso pode ser usar uma classe / estrutura para representar um movimento
- De (onde estava a peça móvel)
- Para (onde a peça em movimento estará)
- Sinalizador de movimento especial (se o movimento foi um movimento especial, ou seja, enpassant, casting, promoção)
- Peça promovida (se o movimento foi um movimento de promoção, para qual peça foi promovido)
Você também pode ter atributos extras, como peça capturada, tipo de castelo, etc. Mas essa informação também pode ser deduzida usando os quadrados From
e To
.
Portanto, considerando o acima, podemos representar o movimento da seguinte forma
struct Move {
char from;
char to;
char spMoveFlag;
char promotedPiece;
};
No entanto, muitos mecanismos de xadrez, incluindo o meu, usam outro método que pode compactar o movimento em apenas 16
pedaços. Leia mais sobre isso aqui .
Depois de saber o que é um movimento, podemos responder à próxima pergunta
- Como converter ataques em bitboards em uma lista de movimentos?
Vamos considerar que temos um cavalo na casa d4 . Também temos uma função que retorna os ataques de um cavaleiro dado o quadrado.
. . . . . . . .
. . . . . . . .
. . 1 . 1 . . .
. 1 . . . 1 . .
. . . n . . . . = knightattacks(SQ_D4)
. 1 . . . 1 . .
. . 1 . 1 . . .
. . . . . . . .
Então, vamos armazenar isso dentro de uma variável knightAttacks
uint64_t knightAttacks = getKnightAttacksBB(SQ_D4);
Se você observar com atenção, já temos 1 dos 4 atributos de que precisamos para representar o lance, que é o From
quadrado - D4
. Agora, tudo o que precisamos fazer é de alguma forma obter o To
quadrado para completar isso, já que um cavalo não pode realizar nenhum tipo de movimento especial.
Um método muito comum é estalar o bit menos significativo até que você knightAttacks
fique sem nada, ou seja 0
.
0000011100001000
^
Least significant bit (lsb)
Você pode seguir o link que forneci para saber como você pode fazer isso, ou há uma chance de que seu compilador já pode fornecer isso a você.
Você simplesmente precisa criar uma função que limpe o lsb de um bitboard e retorne seu índice. Vamos chamá-lo poplsb()
.
Ao todo, seu código pode ter a seguinte aparência
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
}
Isso funciona porque cada vez que você estala o lsb, um bit é limpo até que o número seja == 0. É quando o loop para e você tem uma lista de movimentos perfeitamente boa. A mesma ideia se aplica a qualquer tipo de movimento que você criou usando Bitboards.