SebLague / Chess-Challenge

Create your own tiny chess bot!
https://www.youtube.com/watch?v=Ne40a5LkK6A
MIT License
1.78k stars 1.06k forks source link

BitboardHelper attack methods returning 0s for knights/pawns #329

Closed biscuitderg closed 1 year ago

biscuitderg commented 1 year ago

I am trying to evaluate controlled space on the board based on how many squares the bot's pieces are able to attack, but pawns/knights are giving unexpected values when using BitboardHelper.GetPawnAttacks() and BitboardHelper.GetKnightAttacks()

Here is what I'm currently running to view attacked squares while attempting to debug:

public class MyBot : IChessBot
{
    public Dictionary<Square, ulong> GetAttackBitboards(Board board, bool bot_is_white = true)
    {
        int mod = 6;
        Dictionary<Square, ulong> AttackBitboards = new Dictionary<Square, ulong> { };
        PieceList[] all_pieces = board.GetAllPieceLists();
        PieceList current_list;
        ulong my_pieces = board.BlackPiecesBitboard;
        ulong current_bitboard;
        if (bot_is_white)
        {
            mod = 0;
        }
        for (int i = mod; i < 6 + mod; i++)
        {
            current_list = all_pieces[i];
            foreach (Piece p in current_list)
            {
                if (i - mod == 0) //Pawn
                {
                    current_bitboard = BitboardHelper.GetPawnAttacks(p.Square, bot_is_white) & ~my_pieces; //ignoring squares currently occupied by the bots pieces here
                }
                if (i - mod == 1) //Knight
                {
                    current_bitboard = BitboardHelper.GetKnightAttacks(p.Square) & ~my_pieces; // expecting to see starting move squares for knights here, getting 0
                }
                if (i - mod == 5) //King
                {
                    current_bitboard = BitboardHelper.GetKingAttacks(p.Square) & ~my_pieces; // this appears to be working
                }
                else //Others
                {
                    current_bitboard = BitboardHelper.GetSliderAttacks(p.PieceType, p.Square, board) & ~my_pieces;// this also appears to be working
                }
                AttackBitboards[p.Square] = current_bitboard;
            }
        }
        return AttackBitboards;
    }

    public Move Think(Board board, Timer timer)
    {
        Move[] moves = board.GetLegalMoves();

        Console.WriteLine("All Black Pieces");
        Console.WriteLine(Convert.ToString((long)board.BlackPiecesBitboard, toBase: 2)); //returns expected value in starting position

        Dictionary<Square, ulong> AttackBitboards = GetAttackBitboards(board, board.IsWhiteToMove);

        foreach (KeyValuePair<Square, ulong> entry in AttackBitboards)
        {
            Console.WriteLine(board.GetPiece(entry.Key));
            Console.WriteLine("Attacking Squares");
            Console.WriteLine(Convert.ToString((long)entry.Value, toBase: 2)); //prints 0 to console for all pawns/knights
        }
        return moves[0];
    }
}

image

Even after moving a pawn up to where it could be attacked by a black pawn (thinking maybe there had to be an enemy piece on the square), it is still showing all 0s for pawns. I have ensured that isWhite = False when calling the GetPawnAttacks or GetKnightAttacks methods. Even when & ~my_pieces is removed within GetAttackBitboards(), knights and pawns are still returning 0 when nonzero values are expected.

SebLague commented 1 year ago

Hi, I don't have time to look into your code right now unfortunately, but just wanted to mention that I've recently added a function called VisualizeBitboard in the BitboardHelper class which may help with debugging bitboard issues. I've also verified that the GetKnightAttacks and GetPawnAttacks are working as expected.

biscuitderg commented 1 year ago

Thanks, I will check that out and see

biscuitderg commented 1 year ago

@SebLague Ok, I've dug in a bit further. I overlooked my conditionals and I was overwriting the pawn/knight values due to that final if/else. Closing this out, my bad lol