dylhunn / dragontoothmg

A fast Go chess library. Legal move generation, move/board types, apply/unapply, FEN parsing, Zobrist hashing.
https://dylhunn.github.io/dragontoothmg/
GNU General Public License v3.0
47 stars 7 forks source link

Move and Board need convenience methods to avoid using bitboard internals directly. #1

Open DeybisMelendez opened 2 years ago

DeybisMelendez commented 2 years ago

I don't really understand how bitboards work, so I have no idea how to know which piece I'm moving or which player it belongs to.

I would really appreciate a little explanation or adding a method that allows you to obtain this information directly.

dylhunn commented 2 years ago

You should be able to use Move.To() and Move.From() methods to check which squares are being used. API is defined here.

The best explanation of bitboards I know of is here on the Chess Programming Wiki.

You might consider adding some helper methods on Move or Board to make this easier -- e.g. a convenience method that takes a square ID and tells you what piece code is present.

DeybisMelendez commented 2 years ago

Move.From() returns uint8, what operation should I do to get the Piece?

DeybisMelendez commented 2 years ago

I wrote this:

import chess "github.com/dylhunn/dragontoothmg"
func GetPiece(move chess.Move, board *chess.Board) {
    squareMask := uint64(1) << move.From()
    Piece := chess.Nothing
    if board.Wtomove {
        if board.White.Knights&squareMask != 0 {
            Piece = chess.Knight
        } else if board.White.Pawns&squareMask != 0 {
            Piece = chess.Pawn
        } /// etc...
    } else { // etc...
    fmt.Println(Piece)
}

Is this correct?

dylhunn commented 2 years ago

@DeybisMelendez

Move.From() returns uint8, what operation should I do to get the Piece?

In order to save space in the Move type, it doesn't actually contain the piece kind -- you need the Board for that. From the code:

// Data stored inside, from LSB
// 6 bits: destination square
// 6 bits: source square
// 3 bits: promotion

So you need to check all the bitboards for pieces at that square. What you're doing above looks right!

Be aware that using your helper method will incur a small performance penalty, since you're checking all 10 bitboards. However, each check is still O(1) constant time, so it's not that bad.

Feel free to send me a PR if you'd like to add this to the library.