Comment puis-je convertir les mouvements d'une pièce possible en un mouvement réel dans un bitboard?

Jan 09 2021

Si j'ai un bitboard (par exemple pour les carrés de chevalier vers lesquels il peut se déplacer) comme ceci:

00000000
00000000
00000000
00000000
00000000
01000000
00100000
N0000000

Comment puis-je le «convertir» en mouvement ou «appliquer» ce mouvement?

Réponses

2 AryanParekh Jan 09 2021 at 19:28

Il y a en fait deux questions dans votre message

  • Comment convertir les attaques dans Bitboards en une liste de mouvements?

  • Comment représenter ces mouvements?


  • Comment représenter ces mouvements?

Cette question a été discutée ici et ici à fond. Mais pour fournir un contexte aux lecteurs de cet article, un moyen très simple de le faire peut être d'utiliser une classe / structure pour représenter un mouvement

  • D' où était la pièce en mouvement
  • À (où sera la pièce en mouvement)
  • Drapeau de mouvement spécial (si le mouvement était un mouvement spécial, c'est-à-dire passant, lancer, promotion)
  • Pièce promue (si le mouvement était un mouvement de promotion, quelle pièce a-t-il promu)

Vous pouvez également avoir des attributs supplémentaires tels que la pièce capturée, le type de château, etc. Mais ces informations peuvent également être déduites en utilisant les cases Fromet To.

Donc, compte tenu de ce qui précède, nous pouvons représenter le mouvement comme suit

struct Move {
    char from; 
    char to;   
    char spMoveFlag;
    char promotedPiece;
};

Cependant, beaucoup de moteurs d'échecs, y compris le mien, utilisent une autre méthode qui peut compresser le mouvement en quelques 16bits. En savoir plus à ce sujet ici .

Une fois que nous savons ce qu'est un déménagement, nous pouvons répondre à la question suivante


  • Comment convertir les attaques dans Bitboards en une liste de mouvements?

Considérons que nous avons un chevalier sur la case d4 . Nous avons également une fonction qui renvoie les attaques d'un chevalier étant donné le carré.

. . . . . . . . 
. . . . . . . . 
. . 1 . 1 . . . 
. 1 . . . 1 . . 
. . . n . . . .   =  knightattacks(SQ_D4)
. 1 . . . 1 . . 
. . 1 . 1 . . . 
. . . . . . . . 

Alors stockons ceci dans une variable knightAttacks

uint64_t knightAttacks = getKnightAttacksBB(SQ_D4);

Si vous remarquez attentivement, nous avons déjà 1 des 4 attributs dont nous avons besoin pour représenter le mouvement, qui est le Fromcarré - D4. Maintenant, tout ce que nous avons à faire est d'obtenir d'une manière ou d'une autre la Tocase pour compléter cela, car un chevalier ne peut effectuer aucun type de mouvements spéciaux.

Une méthode très courante consiste à faire sauter le bit le moins significatif jusqu'à ce que vous knightAttacksne soyez plus rien, c'est-à-dire 0.

0000011100001000 
            ^
            Least significant bit (lsb)

Vous pouvez suivre le lien que j'ai fourni pour savoir comment vous pouvez effectuer cela, ou il y a une chance que votre compilateur vous le fournisse déjà.

Vous devez simplement créer une fonction qui efface le lsb d'un bitboard et renvoie son index. Appelons ça poplsb().

Au total, votre code peut ressembler à ceci

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
}

Cela fonctionne parce que chaque fois que vous sautez le lsb, un peu est effacé jusqu'à ce que le nombre soit == 0. C'est à ce moment que la boucle s'arrête et que vous avez une liste de mouvements parfaitement bonne. La même idée s'applique à tout type de mouvements que vous avez créés à l'aide de Bitboards.