
import java.math.BigInteger;


public class Perft 
{

    static Boolean OutOfBounds(int move) {

        if (move < 0) {
            return true;
        }
        if (move > 63) {
            return true;
        }
        return false;
    }

    static void PrintMoveNoNL(int starting, int target_square, int tag) { //starting

        // Print starting
        if (OutOfBounds(starting)) {
            System.out.printf("%d", starting);
        } else {
            System.out.printf("%c%c", GenConst.SQ_CHAR_X[starting], GenConst.SQ_CHAR_Y[starting]);
        }

        // Print target
        if (OutOfBounds(target_square)) {
            System.out.printf("%d", target_square);
        } else {
            System.out.printf("%c%c", GenConst.SQ_CHAR_X[target_square], GenConst.SQ_CHAR_Y[target_square]);
        }

        // Print promotion tag
        switch (tag) {
            case GenConst.TAG_BCaptureKnightPromotion:
            case GenConst.TAG_BKnightPromotion:
            case GenConst.TAG_WKnightPromotion:
            case GenConst.TAG_WCaptureKnightPromotion:
                System.out.printf("n");
                break;
            case GenConst.TAG_BCaptureRookPromotion:
            case GenConst.TAG_BRookPromotion:
            case GenConst.TAG_WRookPromotion:
            case GenConst.TAG_WCaptureRookPromotion:
                System.out.printf("r");
                break;
            case GenConst.TAG_BCaptureBishopPromotion:
            case GenConst.TAG_BBishopPromotion:
            case GenConst.TAG_WBishopPromotion:
            case GenConst.TAG_WCaptureBishopPromotion:
                System.out.printf("b");
                break;
            case GenConst.TAG_BCaptureQueenPromotion:
            case GenConst.TAG_BQueenPromotion:
            case GenConst.TAG_WQueenPromotion:
            case GenConst.TAG_WCaptureQueenPromotion:
                System.out.printf("q");
                break;
            default:
                break;
        }
    }

    static final int MOVE_STARTING = 0;
    static final int MOVE_TARGET = 1;
    static final int MOVE_PIECE = 2;
    static final int MOVE_TAG = 3;
    static final int NO_SQUARE = 64;

    static final int WKS_CASTLE_RIGHTS = 0;
    static final int WQS_CASTLE_RIGHTS = 1;
    static final int BKS_CASTLE_RIGHTS = 2;
    static final int BQS_CASTLE_RIGHTS = 3;

    static final int PINNED_SQUARE_INDEX = 0;
    static final int PINNING_PIECE_INDEX = 1;

    static final BigInteger WKS_EMPTY_BITBOARD = new BigInteger("6917529027641081856");
    static final BigInteger WQS_EMPTY_BITBOARD = new BigInteger("1008806316530991104");
    static final BigInteger BKS_EMPTY_BITBOARD = new BigInteger("96");
    static final BigInteger BQS_EMPTY_BITBOARD = new BigInteger("14");

    static final BigInteger RANK_1_BITBOARD = new BigInteger( "18374686479671623680");
    static final BigInteger RANK_2_BITBOARD =new BigInteger( "71776119061217280");
    static final BigInteger RANK_3_BITBOARD =new BigInteger( "280375465082880");
    static final BigInteger RANK_4_BITBOARD =new BigInteger( "1095216660480");
    static final BigInteger RANK_5_BITBOARD =new BigInteger( "4278190080");
    static final BigInteger RANK_6_BITBOARD =new BigInteger( "16711680");
    static final BigInteger RANK_7_BITBOARD =new BigInteger( "65280");
    static final BigInteger RANK_8_BITBOARD =new BigInteger( "255");

    static final BigInteger MAX_ULONG = new BigInteger("18446744073709551615");

    static final BigInteger MAGIC = new BigInteger("285870213051386505");

    static final int[] DEBRUIJN64 =
    {
        0, 47,  1, 56, 48, 27,  2, 60,
        57, 49, 41, 37, 28, 16,  3, 61,
        54, 58, 35, 52, 50, 42, 21, 44,
        38, 32, 29, 23, 17, 11,  4, 62,
        46, 55, 26, 59, 40, 36, 15, 53,
        34, 51, 20, 43, 31, 22, 10, 45,
        25, 39, 14, 33, 19, 30,  9, 24,
        13, 18,  8, 12,  7,  6,  5, 63
    };

    static int BitScanForward(BigInteger bitboard) {

        for (int i = 0; i < 64; i++) {
            if (bitboard.testBit(i)) {
                return i;
            }
        }
        throw new AssertionError("Bitscanforward: bit not found");
        //BigInteger xorResult = bitboard.xor(bitboard.subtract(BigInteger.ONE));
        //BigInteger multiplied = xorResult.multiply(MAGIC);
        //int index = multiplied.shiftRight(58).intValue();
        //return DEBRUIJN64[index];
    }

    static boolean isNotZero(BigInteger bitboard) {
        return bitboard.signum() != 0;
    }

    static boolean isZero(BigInteger bitboard) {
        return bitboard.signum() == 0;
    }

    static BigInteger removeBit(BigInteger bitboard) {
        return bitboard.and(bitboard.subtract(BigInteger.ONE));
    }

    static void printMoveInfo(int startingSquare, int targetSquare, int tag, int piece) 
    {
        Pr.println("\n    Move Info:");
        Pr.print("     Starting Square: ");
        Pr.printInt(startingSquare);
        Pr.print(" ");
        Pr.printSquareLn(startingSquare);
        Pr.print("     Target Square: ");
        Pr.printInt(targetSquare);
        Pr.print(" ");
        Pr.printSquareLn(targetSquare);
        Pr.print("     Tag: ");
        Pr.printIntLn(tag);
        Pr.print("     Piece: ");
        Pr.printIntLn(piece);
    }


    static int makeMove(int piece, int tag, int startingSquare, int targetSquare)
    {
        Pr.println("___make move____  piece: " + piece + " tag: " + tag + " startingSquare: " + startingSquare + " targetSquare: " + targetSquare);
        assert piece >= GenConst.WP && piece <= GenConst.BK : "invalid piece: " + piece;
        assert startingSquare >= 0 && startingSquare < 64 : "invalid starting square: " + startingSquare;
        assert targetSquare >= 0 && targetSquare < 64 : "invalid target square: " + targetSquare;

       // printMoveInfo(startingSquare, targetSquare, tag, piece);

        int captureIndex = -1;
        Board.is_white_global = !Board.is_white_global;
        switch (tag)
        {
        case GenConst.TAG_NONE: //none
        case GenConst.TAG_CHECK: //check
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_CAPTURE: //capture
        case GenConst.TAG_CHECK_CAPTURE: //check cap
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            if (piece >= GenConst.WP && piece <= GenConst.WK)
            {
                for (int i = GenConst.BP; i <= GenConst.BK; ++i)
                {
                    if (targetSquare == 47) {
                        Pr.println("   board array: " + Board.bitboard_array_global[i]);
                    }

                    if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                    {
                        captureIndex = i;
                        break;
                    }
                }
                assert captureIndex >= 0 && captureIndex <= 11 : "invalid capture index, capture";
                if (captureIndex < 0 || captureIndex > 11)
                {
                    Pr.println("Invalid capture index: " + captureIndex);
                }
                Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            }
            else //is black
            {
                for (int i = GenConst.WP; i <= GenConst.WK; ++i)
                {
                    if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                    {
                        captureIndex = i;
                        break;
                    }
                }
                assert captureIndex >= 0 && captureIndex <= 11 : "invalid capture index, capture";
                Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            }

            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_WHITEEP: //white ep
            //move piece
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[targetSquare + 8].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BLACKEP: //black ep
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[targetSquare - 8].not());
            Board.ep = NO_SQUARE;
            break;

        case GenConst.TAG_WCASTLEKS: //WKS
            //white king
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].or(MoveConstants.SQUARE_BBS[GenConst.G1]);
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].and(MoveConstants.SQUARE_BBS[GenConst.E1].not());
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[GenConst.F1]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.H1].not());

            Board.castle_rights_global[WKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[WQS_CASTLE_RIGHTS] = false;
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_WCASTLEQS: //WQS
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].or(MoveConstants.SQUARE_BBS[GenConst.C1]);
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].and(MoveConstants.SQUARE_BBS[GenConst.E1].not());
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[GenConst.D1]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.A1].not());

            Board.castle_rights_global[WKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[WQS_CASTLE_RIGHTS] = false;
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BCASTLEKS: //BKS
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].or(MoveConstants.SQUARE_BBS[GenConst.G8]);
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].and(MoveConstants.SQUARE_BBS[GenConst.E8].not());
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[GenConst.F8]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.H8].not());

            Board.castle_rights_global[BKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[BQS_CASTLE_RIGHTS] = false;
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BCASTLEQS: //BQS
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].or(MoveConstants.SQUARE_BBS[GenConst.C8]);
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].and(MoveConstants.SQUARE_BBS[GenConst.E8].not());
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[GenConst.D8]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.A8].not());

            Board.castle_rights_global[BKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[BQS_CASTLE_RIGHTS] = false;
            Board.ep = NO_SQUARE;
            break;

        case GenConst.TAG_BKnightPromotion: //BNPr
            Board.bitboard_array_global[GenConst.BN] =Board.bitboard_array_global[GenConst.BN].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BBishopPromotion: //BBPr
            Board.bitboard_array_global[GenConst.BB] =Board.bitboard_array_global[GenConst.BB].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BQueenPromotion: //BQPr
            Board.bitboard_array_global[GenConst.BQ] =Board.bitboard_array_global[GenConst.BQ].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BRookPromotion: //BRPr
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 12: //WNPr
            Board.bitboard_array_global[GenConst.WN] =Board.bitboard_array_global[GenConst.WN].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 13: //WBPr
            Board.bitboard_array_global[GenConst.WB] =Board.bitboard_array_global[GenConst.WB].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 14: //WQPr
            Board.bitboard_array_global[GenConst.WQ] =Board.bitboard_array_global[GenConst.WQ].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 15: //WRPr
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 16: //BNPrCAP
            Board.bitboard_array_global[GenConst.BN] =Board.bitboard_array_global[GenConst.BN].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.WP; i <= GenConst.WK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());

            break;
        case 17: //BBPrCAP
            Board.bitboard_array_global[GenConst.BB] =Board.bitboard_array_global[GenConst.BB].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.WP; i <= GenConst.WK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 18: //BQPrCAP
            Board.bitboard_array_global[GenConst.BQ] =Board.bitboard_array_global[GenConst.BQ].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.WP; i <= GenConst.WK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 19: //BRPrCAP
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.WP; i <= GenConst.WK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 20: //WNPrCAP
            Board.bitboard_array_global[GenConst.WN] =Board.bitboard_array_global[GenConst.WN].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.BP; i <= GenConst.BK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());

            break;
        case 21: //WBPrCAP
            Board.bitboard_array_global[GenConst.WB] =Board.bitboard_array_global[GenConst.WB].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.BP; i <= GenConst.BK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());

            break;
        case 22: //WQPrCAP
            Board.bitboard_array_global[GenConst.WQ] =Board.bitboard_array_global[GenConst.WQ].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.BP; i <= GenConst.BK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());

            break;
        case 23: //WRPrCAP
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());

            Board.ep = NO_SQUARE;
            for (int i = GenConst.BP; i <= GenConst.BK; i++)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 24: //WDouble
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = targetSquare + 8;
            break;
        case 25: //BDouble
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = targetSquare - 8;
            break;
        }

        if (piece == GenConst.WK)
        {
            Board.castle_rights_global[WKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[WQS_CASTLE_RIGHTS] = false;
        }
        else if (piece == GenConst.BK)
        {
            Board.castle_rights_global[BKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[BQS_CASTLE_RIGHTS] = false;
        }
        else if (piece == GenConst.WR)
        {
            if (Board.castle_rights_global[WKS_CASTLE_RIGHTS] == true)
            {
                if (isZero((Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.H1]))))
                {
                    Board.castle_rights_global[WKS_CASTLE_RIGHTS] = false;
                }
            }
            if (Board.castle_rights_global[WQS_CASTLE_RIGHTS] == true)
            {
                if (isZero((Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.A1]))))
                {
                    Board.castle_rights_global[WQS_CASTLE_RIGHTS] = false;
                }
            }
        }
        else if (piece == GenConst.BR)
        {
            if (Board.castle_rights_global[BKS_CASTLE_RIGHTS] == true)
            {
                if (isZero((Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.H8]))))
                {
                    Board.castle_rights_global[BKS_CASTLE_RIGHTS] = false;
                }
            }
            if (Board.castle_rights_global[BQS_CASTLE_RIGHTS] == true)
            {
                if (isZero((Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.A8]))))
                {
                    Board.castle_rights_global[BQS_CASTLE_RIGHTS] = false;
                }
            }
        }
        return captureIndex;
    }

    static void unmakeMove(int piece, int tag, int startingSquare, int targetSquare, int captureIndex)
    {
        Pr.println("___unmake move____  piece: " + piece + " tag: " + tag + " startingSquare: " + startingSquare + " targetSquare: " + targetSquare + " captureIndex: " + captureIndex);
        Board.is_white_global = !Board.is_white_global;
        switch (tag)
        {
        case GenConst.TAG_NONE: //none
        case GenConst.TAG_CHECK: //check
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case GenConst.TAG_CAPTURE: //capture
        case GenConst.TAG_CHECK_CAPTURE: //check cap
            assert captureIndex != -1 : "invalid capture index";
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Pr.println("bp capture before: " + Board.bitboard_array_global[GenConst.BP]);
            Board.bitboard_array_global[captureIndex] = Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Pr.println("bp capture after: " + Board.bitboard_array_global[GenConst.BP]);
            break;
        case GenConst.TAG_WHITEEP: //white ep
            //move piece
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[targetSquare + 8]);
            break;
        case GenConst.TAG_BLACKEP: //black ep
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[targetSquare - 8]);
            break;

        case GenConst.TAG_WCASTLEKS: //WKS
            //white king
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].or(MoveConstants.SQUARE_BBS[GenConst.E1]);
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].and(MoveConstants.SQUARE_BBS[GenConst.G1].not());
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[GenConst.H1]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.F1].not());
            break;
        case GenConst.TAG_WCASTLEQS: //WQS
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].or(MoveConstants.SQUARE_BBS[GenConst.E1]);
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].and(MoveConstants.SQUARE_BBS[GenConst.C1].not());
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[GenConst.A1]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.D1].not());
            break;
        case GenConst.TAG_BCASTLEKS: //BKS
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].or(MoveConstants.SQUARE_BBS[GenConst.E8]);
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].and(MoveConstants.SQUARE_BBS[GenConst.G8].not());
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[GenConst.H8]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.F8].not());
            break;
        case GenConst.TAG_BCASTLEQS: //BQS
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].or(MoveConstants.SQUARE_BBS[GenConst.E8]);
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].and(MoveConstants.SQUARE_BBS[GenConst.C8].not());
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[GenConst.A8]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.D8].not());
            break;

        case GenConst.TAG_BKnightPromotion: //BNPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BN] =Board.bitboard_array_global[GenConst.BN].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case GenConst.TAG_BBishopPromotion: //BBPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BB] =Board.bitboard_array_global[GenConst.BB].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case GenConst.TAG_BQueenPromotion: //BQPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BQ] =Board.bitboard_array_global[GenConst.BQ].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case GenConst.TAG_BRookPromotion: //BRPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 12: //WNPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WN] =Board.bitboard_array_global[GenConst.WN].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 13: //WBPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WB] =Board.bitboard_array_global[GenConst.WB].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 14: //WQPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WQ] =Board.bitboard_array_global[GenConst.WQ].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 15: //WRPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 16: //BNPrCAP
            assert captureIndex != -1 : "invalid capture index";
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BN] =Board.bitboard_array_global[GenConst.BN].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 17: //BBPrCAP
            assert captureIndex != -1 : "invalid capture index";
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BB] =Board.bitboard_array_global[GenConst.BB].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 18: //BQPrCAP
            assert captureIndex != -1 : "invalid capture index";
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BQ] =Board.bitboard_array_global[GenConst.BQ].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 19: //BRPrCAP
            assert captureIndex != -1 : "invalid capture index";
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 20: //WNPrCAP
            assert captureIndex != -1 : "invalid capture index";
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WN] =Board.bitboard_array_global[GenConst.WN].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 21: //WBPrCAP
            assert captureIndex != -1 : "invalid capture index";
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WB] =Board.bitboard_array_global[GenConst.WB].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 22: //WQPrCAP
            assert captureIndex != -1 : "invalid capture index";
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WQ] =Board.bitboard_array_global[GenConst.WQ].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 23: //WRPrCAP
            assert captureIndex != -1 : "invalid capture index";
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 24: //WDouble

            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 25: //BDouble
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            break;
        }


    }

    static int getMoves(int[][] move_list)
    {
        Pr.println(" getMoves:");

        int move_count = 0;

        //#region Moves

        //Move generating variables
        BigInteger WHITE_OCCUPANCIES = Board.bitboard_array_global[0]
        .or(Board.bitboard_array_global[1])
        .or(Board.bitboard_array_global[2])
        .or(Board.bitboard_array_global[3])
        .or(Board.bitboard_array_global[4])
        .or(Board.bitboard_array_global[5]); 
        BigInteger BLACK_OCCUPANCIES = Board.bitboard_array_global[6]
        .or(Board.bitboard_array_global[7])
        .or(Board.bitboard_array_global[8])
        .or(Board.bitboard_array_global[9])
        .or(Board.bitboard_array_global[10])
        .or(Board.bitboard_array_global[11]);
        BigInteger COMBINED_OCCUPANCIES = WHITE_OCCUPANCIES.or(BLACK_OCCUPANCIES);
        BigInteger EMPTY_OCCUPANCIES = COMBINED_OCCUPANCIES.not(); 
        BigInteger temp_bitboard, temp_pin_bitboard, temp_attack, temp_empty, temp_captures;
        BigInteger check_bitboard = new BigInteger("0");
        int starting_square = NO_SQUARE, target_square = NO_SQUARE;

        int[][] pinArray =
        {
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
        };

        int pinNumber = 0;

        Pr.println(" -variables declared");

    if (Board.is_white_global == true)
    {
        Pr.println(" white to play");

        int whiteKingCheckCount = 0;
        int whiteKingPosition = BitScanForward(Board.bitboard_array_global[GenConst.WK]);

        Pr.print("  white king position: ");
        Pr.printSquareLn(whiteKingPosition);

        //#region White checks and pins

        //pawns
        temp_bitboard = Board.bitboard_array_global[GenConst.BP].and(MoveConstants.WHITE_PAWN_ATTACKS[whiteKingPosition]);
        if (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int pawn_square = BitScanForward(temp_bitboard); 

                if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    check_bitboard = MoveConstants.SQUARE_BBS[pawn_square];
                }
            
            whiteKingCheckCount++;
        }

        //knights
        temp_bitboard = Board.bitboard_array_global[GenConst.BN].and(MoveConstants.KNIGHT_ATTACKS[whiteKingPosition]);
        if (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int knight_square = BitScanForward(temp_bitboard);

            if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                check_bitboard = MoveConstants.SQUARE_BBS[knight_square];
            }
            
            whiteKingCheckCount++;
        }

        //bishops
        BigInteger bishopAttacksChecks = MoveUtils.GetBishopMovesSeparate(BLACK_OCCUPANCIES, whiteKingPosition);
        temp_bitboard = Board.bitboard_array_global[GenConst.BB].and(bishopAttacksChecks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
                }
                whiteKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //queen
        temp_bitboard = Board.bitboard_array_global[GenConst.BQ].and(bishopAttacksChecks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 

            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
                }
                whiteKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //rook
        BigInteger rook_attacks = MoveUtils.GetRookMovesSeparate(BLACK_OCCUPANCIES, whiteKingPosition); 
        temp_bitboard = Board.bitboard_array_global[GenConst.BR].and(rook_attacks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
                }
                whiteKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //queen
        temp_bitboard = Board.bitboard_array_global[GenConst.BQ].and(rook_attacks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
                }
                whiteKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        Pr.println("  -pins and checks complete: ");
        Pr.print("  white king check count: ");
        Pr.printIntLn(whiteKingCheckCount);
        Pr.print("  pin count: ");
        Pr.printIntLn(pinNumber);
        Pr.println("  _____________");

        //#endregion

        BigInteger occupanciesWithoutWhiteKing = COMBINED_OCCUPANCIES.and(Board.bitboard_array_global[GenConst.WK].not());
        int wKingMoveCount = 0;


        temp_attack = MoveConstants.KING_ATTACKS[whiteKingPosition];
        temp_empty = temp_attack.and(EMPTY_OCCUPANCIES);
        while (temp_empty.signum() != 0) // Using BigInteger's signum() to check if it's not 0
        {
            target_square = BitScanForward(temp_empty);
            temp_empty = temp_empty.and(temp_empty.subtract(BigInteger.ONE)); // Using BigInteger's subtract and and
        
            if (Board.bitboard_array_global[GenConst.BP].and(MoveConstants.WHITE_PAWN_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BN].and(MoveConstants.KNIGHT_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BK].and(MoveConstants.KING_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(occupanciesWithoutWhiteKing, target_square);
            if (Board.bitboard_array_global[GenConst.BB].and(bishopAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BQ].and(bishopAttacks).signum() != 0) {
                continue;
            }
            BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(occupanciesWithoutWhiteKing, target_square); 
            if (Board.bitboard_array_global[GenConst.BR].and(rookAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BQ].and(rookAttacks).signum() != 0) {
                continue;
            }
        
            move_list[move_count][MOVE_STARTING] = whiteKingPosition;
            move_list[move_count][MOVE_TARGET] = target_square;
            move_list[move_count][MOVE_TAG] = GenConst.TAG_NONE;
            move_list[move_count][MOVE_PIECE] = GenConst.WK;
            move_count++;
            wKingMoveCount++;
        }

        //captures
        temp_captures = temp_attack.and(BLACK_OCCUPANCIES);
        while (temp_captures.signum() != 0) // Using BigInteger's signum() to check if it's not 0
        {
            target_square = BitScanForward(temp_captures);
            temp_captures = temp_captures.and(temp_captures.subtract(BigInteger.ONE)); // Using BigInteger's subtract and and
        
            if (Board.bitboard_array_global[GenConst.BP].and(MoveConstants.WHITE_PAWN_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BN].and(MoveConstants.KNIGHT_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BK].and(MoveConstants.KING_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(occupanciesWithoutWhiteKing, target_square);
            if (Board.bitboard_array_global[GenConst.BB].and(bishopAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BQ].and(bishopAttacks).signum() != 0) {
                continue;
            }
            BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(occupanciesWithoutWhiteKing, target_square); 
            if (Board.bitboard_array_global[GenConst.BR].and(rookAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BQ].and(rookAttacks).signum() != 0) {
                continue;
            }
        
            move_list[move_count][MOVE_STARTING] = whiteKingPosition;
            move_list[move_count][MOVE_TARGET] = target_square;
            move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
            move_list[move_count][MOVE_PIECE] = GenConst.WK;
            move_count++;
            wKingMoveCount++;
        }

        Pr.print("  white king move count: ");
        Pr.printIntLn(wKingMoveCount);
        Pr.println("  _____________");

        if (whiteKingCheckCount < 2)
        {

            if (whiteKingCheckCount == 0)
            {
                check_bitboard = MAX_ULONG;
            }

            //#region White castling

            if (whiteKingCheckCount == 0)
            {
                if (Board.castle_rights_global[WKS_CASTLE_RIGHTS] == true)
                {
                    if (whiteKingPosition == GenConst.E1) //king on e1
                    {
                        if (isNotZero(WKS_EMPTY_BITBOARD.and(COMBINED_OCCUPANCIES)) == false) //f1 and g1 empty
                        {
                            if (isNotZero(Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.H1])) == false) //rook on h1
                            {
                                if (MoveUtils.Is_Square_Attacked_By_Black_Global(GenConst.F1, COMBINED_OCCUPANCIES) == false)
                                {
                                    if (MoveUtils.Is_Square_Attacked_By_Black_Global(GenConst.G1, COMBINED_OCCUPANCIES) == false)
                                    {
                                        move_list[move_count][MOVE_STARTING] = GenConst.E1;
                                        move_list[move_count][MOVE_TARGET] = GenConst.G1;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCASTLEKS;
                                        move_list[move_count][MOVE_PIECE] = GenConst.WK;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }
                if (Board.castle_rights_global[WQS_CASTLE_RIGHTS] == true)
                {
                    if (whiteKingPosition == GenConst.E1) //king on e1
                    {
                        if (isNotZero(WQS_EMPTY_BITBOARD.and(COMBINED_OCCUPANCIES)) == false) //f1 and g1 empty
                        {
                            if ((isNotZero(Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.A1]))) == true) //rook on h1
                            {
                                if (MoveUtils.Is_Square_Attacked_By_Black_Global(GenConst.C1, COMBINED_OCCUPANCIES) == false)
                                {
                                    if (MoveUtils.Is_Square_Attacked_By_Black_Global(GenConst.D1, COMBINED_OCCUPANCIES) == false)
                                    {
                                        move_list[move_count][MOVE_STARTING] = GenConst.E1;
                                        move_list[move_count][MOVE_TARGET] = GenConst.C1;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCASTLEQS;
                                        move_list[move_count][MOVE_PIECE] = GenConst.WK;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //#endregion

            //#region White knight moves

            Pr.println("  -white knight moves: ");
            temp_bitboard = Board.bitboard_array_global[GenConst.WN];
            Pr.print("    white knight bitboard: ");
            Pr.printBigIntegerLn(temp_bitboard);
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE)); //removes the knight from that square to not infinitely loop

                Pr.println("\n   knight on square: " + starting_square);

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                temp_attack = ((MoveConstants.KNIGHT_ATTACKS[starting_square].and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard))); //gets knight captures
                Pr.println("   knight captures: " + temp_attack);

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);
                    
                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WN;
                    move_count++;
                }

                temp_attack = ((MoveConstants.KNIGHT_ATTACKS[starting_square].and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                Pr.println("   knight regular moves: " + temp_attack);

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WN;
                    move_count++;
                }
            }

            //#endregion

            //#region White pawn moves
            Pr.println("  _____________");
            Pr.println("  movecount: " + move_count);
            temp_bitboard = Board.bitboard_array_global[GenConst.WP];
            Pr.println("  -white pawn moves: ");

            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard); 
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                Pr.println("\n   pawn on square: " + starting_square);

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                //#region pawn forward

                if (isZero(MoveConstants.SQUARE_BBS[starting_square - 8].and(COMBINED_OCCUPANCIES)) == true) //if up one square is empty
                {
                    if (isNotZero(MoveConstants.SQUARE_BBS[starting_square - 8].and(check_bitboard).and(temp_pin_bitboard)) == true) //if not pinned or check
                    {
                        if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_7_BITBOARD))) //if promotion
                        {
                            Pr.println("   pawn promotion forward!");
                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_WQueenPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_WRookPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_WBishopPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_WBishopPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;

                        }
                        else
                        {
                            Pr.println("   pawn forward one");
                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;
                        }
                    }

                    if ((isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_2_BITBOARD))) == true) //if on rank 2
                    {
                        if (isNotZero(MoveConstants.SQUARE_BBS[starting_square - 16].and(check_bitboard).and(temp_pin_bitboard)) == true) //if not pinned or 
                        {
                            if (isZero(MoveConstants.SQUARE_BBS[starting_square - 16].and(COMBINED_OCCUPANCIES)) == true) //if up two squares and one square are empty
                            {
                                Pr.println("   pawn forward two");
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = starting_square - 16;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_DoublePawnWhite;
                                move_list[move_count][MOVE_PIECE] = GenConst.WP;
                                move_count++;
                            }
                        }
                    }
                }

                //#endregion
                //#region pawn attacks

                temp_attack = ((MoveConstants.WHITE_PAWN_ATTACKS[starting_square].and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard))); //if black piece diagonal to pawn
                Pr.println("   pawn attacks: " + temp_attack);

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_7_BITBOARD)) == true) //if promotion
                    {
                        Pr.println("   pawn promotion attack!");
                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCaptureQueenPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCaptureRookPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCaptureBishopPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCaptureKnightPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;
                    }
                    else
                    {
                        Pr.println("   add pawn attack move " + starting_square + " to " + target_square);
                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;
                    }
                }

                if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_5_BITBOARD))) 
                { // check rank for ep
                    if (Board.ep != NO_SQUARE) 
                    {
                        if (isNotZero(MoveConstants.WHITE_PAWN_ATTACKS[starting_square]
                                .and(MoveConstants.SQUARE_BBS[Board.ep])
                                .and(check_bitboard)
                                .and(temp_pin_bitboard))) {
                            if (isZero(Board.bitboard_array_global[GenConst.WK].and(RANK_5_BITBOARD))) { // if no king on rank 5
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = Board.ep;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_WHITEEP;
                                move_list[move_count][MOVE_PIECE] = GenConst.WP;
                                move_count++;
                            } else if (isZero(Board.bitboard_array_global[GenConst.BR].and(RANK_5_BITBOARD)) &&
                                       isZero(Board.bitboard_array_global[GenConst.BQ].and(RANK_5_BITBOARD))) { // if no b rook or queen on rank 5
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = Board.ep;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_WHITEEP;
                                move_list[move_count][MOVE_PIECE] = GenConst.WP;
                                move_count++;
                            } else { // wk and br or bq on rank 5
                                BigInteger occupancyWithoutEPPawns = COMBINED_OCCUPANCIES.and(MoveConstants.SQUARE_BBS[starting_square].not());
                                occupancyWithoutEPPawns = occupancyWithoutEPPawns.and(MoveConstants.SQUARE_BBS[Board.ep + 8].not());
                
                                BigInteger rookAttacksFromKing = MoveUtils.GetRookMovesSeparate(occupancyWithoutEPPawns, whiteKingPosition);
                
                                if (isZero(rookAttacksFromKing.and(Board.bitboard_array_global[GenConst.BR]))) 
                                {
                                    if (isZero(rookAttacksFromKing.and(Board.bitboard_array_global[GenConst.BQ]))) 
                                    {
                                        move_list[move_count][MOVE_STARTING] = starting_square;
                                        move_list[move_count][MOVE_TARGET] = Board.ep;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WHITEEP;
                                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }

                //#endregion
            }

            //#endregion

            Pr.println("  -after pawns");

            //#region White rook moves

            temp_bitboard = Board.bitboard_array_global[GenConst.WR];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(COMBINED_OCCUPANCIES, starting_square);

                temp_attack = ((rookAttacks.and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WR;
                    move_count++;
                }

                temp_attack = ((rookAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WR;
                    move_count++;
                }
            }

            //#endregion

            Pr.println("  -after rooks");

            //#region White bishop moves

            //Pr.println("\nwhite bishop");
            temp_bitboard = Board.bitboard_array_global[GenConst.WB];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                //Pr.println("get bishop attacks");
                BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(COMBINED_OCCUPANCIES, starting_square);
                //Pr.println("bishop attacks");
                //Pr.printBigIntegerLn(bishopAttacks);

                temp_attack = ((bishopAttacks.and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WB;
                    move_count++;
                }

                temp_attack = ((bishopAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WB;
                    move_count++;
                }
            }

            //#endregion

            Pr.println("  -after bishop");

            //#region White queen moves

            Pr.println("______________");
            Pr.println("   white queen:");
            temp_bitboard = Board.bitboard_array_global[GenConst.WQ];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                Pr.println("\n   queen on square: " + starting_square);

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger queenAttacks = MoveUtils.GetRookMovesSeparate(COMBINED_OCCUPANCIES, starting_square);
                Pr.println("\n   queen attacks rook: " + queenAttacks);
                queenAttacks = queenAttacks.or(MoveUtils.GetBishopMovesSeparate(COMBINED_OCCUPANCIES, starting_square));
                Pr.println("\n   queen attacks combined: " + queenAttacks);

                temp_attack = ((queenAttacks.and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                Pr.println("\n   queen attacks captures: " + temp_attack);

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WQ;
                    move_count++;
                    Pr.println("   add queen attack capture " + starting_square + " to " + target_square);
                }

                temp_attack = ((queenAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                Pr.println("\n   queen regular moves: " + temp_attack);
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WQ;
                    move_count++;
                    Pr.println("   add queen move " + starting_square + " to " + target_square);
                }
            }

            //#endregion
        
            Pr.println("  -after queen");
        }
    }
    else //black move
    {
        int blackKingCheckCount = 0;
        int blackKingPosition = BitScanForward(Board.bitboard_array_global[GenConst.BK]);

       // Pr.print("  black king position: ");
       // Pr.printIntLn(blackKingPosition);

        //#region black checks and pins

        //pawns
        temp_bitboard = Board.bitboard_array_global[GenConst.WP].and(MoveConstants.BLACK_PAWN_ATTACKS[blackKingPosition]);
        if (temp_bitboard.compareTo(BigInteger.ZERO) != 0) //if there is pawn attacking king
        {
            int pawn_square = BitScanForward(temp_bitboard); 

            if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                check_bitboard = MoveConstants.SQUARE_BBS[pawn_square];
            }
            
            blackKingCheckCount++;
        }

        //knights
        temp_bitboard = Board.bitboard_array_global[GenConst.WN].and(MoveConstants.KNIGHT_ATTACKS[blackKingPosition]);
        if (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int knight_square = BitScanForward(temp_bitboard);

            if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                check_bitboard = MoveConstants.SQUARE_BBS[knight_square];
            }
            
            blackKingCheckCount++;
        }

        //bishops
        BigInteger bishopAttacksChecks = MoveUtils.GetBishopMovesSeparate(WHITE_OCCUPANCIES, blackKingPosition);
        temp_bitboard = Board.bitboard_array_global[GenConst.WB].and(bishopAttacksChecks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square].and(BLACK_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
                }
                blackKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //queen
        temp_bitboard = Board.bitboard_array_global[GenConst.WQ].and(bishopAttacksChecks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 

            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square].and(BLACK_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
                }
                blackKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //rook
        BigInteger rook_attacks = MoveUtils.GetRookMovesSeparate(WHITE_OCCUPANCIES, blackKingPosition); 
        temp_bitboard = Board.bitboard_array_global[GenConst.WR].and(rook_attacks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square].and(BLACK_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
                }
                blackKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //queen
        temp_bitboard = Board.bitboard_array_global[GenConst.WQ].and(rook_attacks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
                }
                blackKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //#endregion

        BigInteger occupanciesWithoutWhiteKing = COMBINED_OCCUPANCIES.and(Board.bitboard_array_global[GenConst.WK].not());

        temp_attack = MoveConstants.KING_ATTACKS[blackKingPosition];
        temp_empty = temp_attack.and(EMPTY_OCCUPANCIES);

        while (temp_empty.signum() != 0) // Using BigInteger's signum() to check if it's not 0
        {
            target_square = BitScanForward(temp_empty);
            temp_empty = temp_empty.and(temp_empty.subtract(BigInteger.ONE)); // Using BigInteger's subtract and and
        
            if (Board.bitboard_array_global[GenConst.WP].and(MoveConstants.BLACK_PAWN_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WN].and(MoveConstants.KNIGHT_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WK].and(MoveConstants.KING_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(occupanciesWithoutWhiteKing, target_square);
            if (Board.bitboard_array_global[GenConst.WB].and(bishopAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WQ].and(bishopAttacks).signum() != 0) {
                continue;
            }
            BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(occupanciesWithoutWhiteKing, target_square); 
            if (Board.bitboard_array_global[GenConst.WR].and(rookAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WQ].and(rookAttacks).signum() != 0) {
                continue;
            }
        
            move_list[move_count][MOVE_STARTING] = blackKingPosition;
            move_list[move_count][MOVE_TARGET] = target_square;
            move_list[move_count][MOVE_TAG] = GenConst.TAG_NONE;
            move_list[move_count][MOVE_PIECE] = GenConst.BK;
            move_count++;
        }

        //captures
        temp_captures = temp_attack.and(WHITE_OCCUPANCIES);

        while (temp_captures.signum() != 0) // Using BigInteger's signum() to check if it's not 0
        {
            target_square = BitScanForward(temp_captures);
            temp_captures = temp_captures.and(temp_captures.subtract(BigInteger.ONE)); // Using BigInteger's subtract and and
        
            if (Board.bitboard_array_global[GenConst.WP].and(MoveConstants.BLACK_PAWN_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WN].and(MoveConstants.KNIGHT_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WK].and(MoveConstants.KING_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(occupanciesWithoutWhiteKing, target_square);
            if (Board.bitboard_array_global[GenConst.WB].and(bishopAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WQ].and(bishopAttacks).signum() != 0) {
                continue;
            }
            BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(occupanciesWithoutWhiteKing, target_square); 
            if (Board.bitboard_array_global[GenConst.WR].and(rookAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WQ].and(rookAttacks).signum() != 0) {
                continue;
            }
        
            move_list[move_count][MOVE_STARTING] = blackKingPosition;
            move_list[move_count][MOVE_TARGET] = target_square;
            move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
            move_list[move_count][MOVE_PIECE] = GenConst.BK;
            move_count++;
        }

        if (blackKingCheckCount < 2)
        {

            if (blackKingCheckCount == 0)
            {
                check_bitboard = MAX_ULONG;
            }

            //#region Black castling

            if (blackKingCheckCount == 0)
            {
                if (Board.castle_rights_global[BKS_CASTLE_RIGHTS] == true)
                {
                    if (blackKingPosition == GenConst.E8) //king on e1
                    {
                        if (isNotZero(BKS_EMPTY_BITBOARD.and(COMBINED_OCCUPANCIES)) == false) //f1 and g1 empty
                        {
                            if (isNotZero(Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.H8])) == false) //rook on h8
                            {
                                if (MoveUtils.Is_Square_Attacked_By_White_Global(GenConst.F8, COMBINED_OCCUPANCIES) == false)
                                {
                                    if (MoveUtils.Is_Square_Attacked_By_White_Global(GenConst.G8, COMBINED_OCCUPANCIES) == false)
                                    {
                                        move_list[move_count][MOVE_STARTING] = GenConst.E8;
                                        move_list[move_count][MOVE_TARGET] = GenConst.G8;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCASTLEKS;
                                        move_list[move_count][MOVE_PIECE] = GenConst.BK;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }
                if (Board.castle_rights_global[BQS_CASTLE_RIGHTS] == true)
                {
                    if (blackKingPosition == GenConst.E8) //king on e1
                    {
                        if (isNotZero(BQS_EMPTY_BITBOARD.and(COMBINED_OCCUPANCIES)) == false) //f1 and g1 empty
                        {
                            if ((isNotZero(Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.A8]))) == true) //rook on h1
                            {
                                if (MoveUtils.Is_Square_Attacked_By_White_Global(GenConst.C8, COMBINED_OCCUPANCIES) == false)
                                {
                                    if (MoveUtils.Is_Square_Attacked_By_White_Global(GenConst.D8, COMBINED_OCCUPANCIES) == false)
                                    {
                                        move_list[move_count][MOVE_STARTING] = GenConst.E8;
                                        move_list[move_count][MOVE_TARGET] = GenConst.C8;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCASTLEQS;
                                        move_list[move_count][MOVE_PIECE] = GenConst.BK;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //#endregion

            //#region Black knight moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BN];

            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE)); //removes the knight from that square to not infinitely loop

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                temp_attack = ((MoveConstants.KNIGHT_ATTACKS[starting_square].and(WHITE_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard))); //gets knight captures
                
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);
                    
                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BN;
                    move_count++;
                }

                temp_attack = ((MoveConstants.KNIGHT_ATTACKS[starting_square].and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BN;
                    move_count++;
                }
            }

            //#endregion

            //#region Black pawn moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BP];

            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard); 
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                //#region pawn forward

                if (isZero(MoveConstants.SQUARE_BBS[starting_square + 8].and(COMBINED_OCCUPANCIES)) == true) //if up one square is empty
                {
                    if (isNotZero(MoveConstants.SQUARE_BBS[starting_square + 8].and(check_bitboard).and(temp_pin_bitboard)) == true) //if not pinned or check
                    {
                        if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_2_BITBOARD))) //if promotion
                        {
                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_BQueenPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_BRookPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_BBishopPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_BBishopPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;

                        }
                        else
                        {
                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;
                        }
                    }

                    if ((isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_7_BITBOARD))) == true) //if on rank 7
                    {
                        if (isNotZero(MoveConstants.SQUARE_BBS[starting_square + 16].and(check_bitboard).and(temp_pin_bitboard)) == true) //if not pinned or 
                        {
                            if (isZero(MoveConstants.SQUARE_BBS[starting_square + 16].and(COMBINED_OCCUPANCIES)) == true) //if up two squares and one square are empty
                            {
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = starting_square + 16;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_DoublePawnBlack;
                                move_list[move_count][MOVE_PIECE] = GenConst.BP;
                                move_count++;
                            }
                        }
                    }
                }

                //#endregion
                //#region pawn attacks

                temp_attack = ((MoveConstants.BLACK_PAWN_ATTACKS[starting_square].and(WHITE_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard))); //if black piece diagonal to pawn

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_2_BITBOARD)) == true) //if promotion
                    {
                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCaptureQueenPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCaptureRookPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCaptureBishopPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCaptureKnightPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;
                    }
                    else
                    {
                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;
                    }
                }

                if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_4_BITBOARD))) 
                { // check rank for ep
                    if (Board.ep != NO_SQUARE) 
                    {
                        if (isNotZero(MoveConstants.BLACK_PAWN_ATTACKS[starting_square]
                                .and(MoveConstants.SQUARE_BBS[Board.ep])
                                .and(check_bitboard)
                                .and(temp_pin_bitboard))) {
                            if (isZero(Board.bitboard_array_global[GenConst.WK].and(RANK_4_BITBOARD))) { // if no king on rank 5
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = Board.ep;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_BLACKEP;
                                move_list[move_count][MOVE_PIECE] = GenConst.BP;
                                move_count++;
                            } else if (isZero(Board.bitboard_array_global[GenConst.WR].and(RANK_4_BITBOARD)) &&
                                       isZero(Board.bitboard_array_global[GenConst.WQ].and(RANK_4_BITBOARD))) { // if no b rook or queen on rank 5
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = Board.ep;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_BLACKEP;
                                move_list[move_count][MOVE_PIECE] = GenConst.BP;
                                move_count++;
                            } else { // wk and br or bq on rank 5
                                BigInteger occupancyWithoutEPPawns = COMBINED_OCCUPANCIES.and(MoveConstants.SQUARE_BBS[starting_square].not());
                                occupancyWithoutEPPawns = occupancyWithoutEPPawns.and(MoveConstants.SQUARE_BBS[Board.ep - 8].not());
                
                                BigInteger rookAttacksFromKing = MoveUtils.GetRookMovesSeparate(occupancyWithoutEPPawns, blackKingPosition);
                
                                if (isZero(rookAttacksFromKing.and(Board.bitboard_array_global[GenConst.WR]))) 
                                {
                                    if (isZero(rookAttacksFromKing.and(Board.bitboard_array_global[GenConst.WQ]))) 
                                    {
                                        move_list[move_count][MOVE_STARTING] = starting_square;
                                        move_list[move_count][MOVE_TARGET] = Board.ep;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BLACKEP;
                                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }

                //#endregion
            }

            //#endregion

            //#region Black rook moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BR];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

             //   Pr.print("   rook square: ");
               // Pr.printIntLn(starting_square);

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(COMBINED_OCCUPANCIES, starting_square);

               // Pr.print("rook attacks:");
               // Pr.printBigIntegerLn(rookAttacks);

                temp_attack = ((rookAttacks.and(WHITE_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));

              //  Pr.print("against white:");
              //  Pr.printBigIntegerLn(temp_attack);

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BR;
                    move_count++;
                }

                temp_attack = ((rookAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
              //  Pr.print("against empty:");
              //  Pr.printBigIntegerLn(temp_attack);

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BR;
                    move_count++;
                }
            }

            //#endregion

            //#region Black bishop moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BB];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(COMBINED_OCCUPANCIES, starting_square);

                temp_attack = ((bishopAttacks.and(WHITE_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BB;
                    move_count++;
                }

                temp_attack = ((bishopAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BB;
                    move_count++;
                }
            }

            //#endregion

            //#region Black queen moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BQ];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger queenAttacks = MoveUtils.GetRookMovesSeparate(COMBINED_OCCUPANCIES, starting_square);
                queenAttacks = queenAttacks.or(MoveUtils.GetBishopMovesSeparate(COMBINED_OCCUPANCIES, starting_square));

                temp_attack = ((queenAttacks.and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));


                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BQ;
                    move_count++;
                }

                temp_attack = ((queenAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BQ;
                    move_count++;
                }
            }

            //#endregion
        }
    }

    //#endregion
        Pr.println("-generated moves, count: " + move_count);
        return move_count;
    }


    static int PerftInlineDebug(int depth, int ply)
    {
        if (depth == 0)
        {
            return 1;
        }

        BigInteger[] bitboard_array_copy = new BigInteger[12];

        for (int i = 0; i < 12; i++)
        {
            bitboard_array_copy[i] = Board.bitboard_array_global[i];
        }

        int[][] move_list = new int[250][4];
        int move_count = getMoves(move_list);

      //  Pr.print("Move count: ");
      //  Pr.printIntLn(move_count);

    //if (depth == 1)
    //{
        //return move_count;
    //}

    int nodes = 0;
    int priorNodes;
    int copyEp = Board.ep;
    
    boolean[] copy_castle = {
        Board.castle_rights_global[0],
        Board.castle_rights_global[1],
        Board.castle_rights_global[2],
        Board.castle_rights_global[3],
    };

    Pr.println("  -Looping through moves");
    for (int move_index = 0; move_index < move_count; move_index++)
    {
        int startingSquare = move_list[move_index][MOVE_STARTING];
        int targetSquare = move_list[move_index][MOVE_TARGET];
        int piece = move_list[move_index][MOVE_PIECE];
        int tag = move_list[move_index][MOVE_TAG];

        int captureIndex = makeMove(piece, tag, startingSquare, targetSquare);

        priorNodes = nodes;
        nodes += PerftInlineDebug(depth - 1, ply + 1);

        unmakeMove(piece, tag, startingSquare, targetSquare, captureIndex);

        Board.castle_rights_global[0] = copy_castle[0];
        Board.castle_rights_global[1] = copy_castle[1];
        Board.castle_rights_global[2] = copy_castle[2];
        Board.castle_rights_global[3] = copy_castle[3];
        Board.ep = copyEp;

        for (int i = 0; i < 12; i++)
        {
            Pr.println("i: " + i + " bitboard: " + Board.bitboard_array_global[i]);
            assert Board.bitboard_array_global[i] == bitboard_array_copy[i] : "Bitboards are not the same!";
        }

        if (ply == 0)
        {
            //Pr.printInt(startingSquare);
            //Pr.printInt(targetSquare);
            //Pr.printInt(tag);
            PrintMoveNoNL(startingSquare, targetSquare, tag);
            System.out.printf(": %d\n", nodes - priorNodes);
        }
    }

        return nodes;
    }



    static int PerftInlineGlobal(int depth, int ply)
    {
        if (depth == 0)
        {
            return 1;
        }

        int[][] move_list = new int[250][4];
        int move_count = 0;

        //Move generating variables
        BigInteger WHITE_OCCUPANCIES = Board.bitboard_array_global[0]
        .or(Board.bitboard_array_global[1])
        .or(Board.bitboard_array_global[2])
        .or(Board.bitboard_array_global[3])
        .or(Board.bitboard_array_global[4])
        .or(Board.bitboard_array_global[5]); 
        BigInteger BLACK_OCCUPANCIES = Board.bitboard_array_global[6]
        .or(Board.bitboard_array_global[7])
        .or(Board.bitboard_array_global[8])
        .or(Board.bitboard_array_global[9])
        .or(Board.bitboard_array_global[10])
        .or(Board.bitboard_array_global[11]);
        BigInteger COMBINED_OCCUPANCIES = WHITE_OCCUPANCIES.or(BLACK_OCCUPANCIES);
        BigInteger EMPTY_OCCUPANCIES = COMBINED_OCCUPANCIES.not(); 
        BigInteger temp_bitboard, temp_pin_bitboard, temp_attack, temp_empty, temp_captures;
        BigInteger check_bitboard = new BigInteger("0");
        int starting_square = NO_SQUARE, target_square = NO_SQUARE;

        int[][] pinArray =
        {
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
            { -1, -1 },
        };

        int pinNumber = 0;

    if (Board.is_white_global == true)
    {
        int whiteKingCheckCount = 0;
        int whiteKingPosition = BitScanForward(Board.bitboard_array_global[GenConst.WK]);

        //#region White checks and pins

        //pawns
        temp_bitboard = Board.bitboard_array_global[GenConst.BP].and(MoveConstants.WHITE_PAWN_ATTACKS[whiteKingPosition]);
        if (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int pawn_square = BitScanForward(temp_bitboard); 

                if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    check_bitboard = MoveConstants.SQUARE_BBS[pawn_square];
                }
            
            whiteKingCheckCount++;
        }

        //knights
        temp_bitboard = Board.bitboard_array_global[GenConst.BN].and(MoveConstants.KNIGHT_ATTACKS[whiteKingPosition]);
        if (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int knight_square = BitScanForward(temp_bitboard);

            if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                check_bitboard = MoveConstants.SQUARE_BBS[knight_square];
            }
            
            whiteKingCheckCount++;
        }

        //bishops
        BigInteger bishopAttacksChecks = MoveUtils.GetBishopMovesSeparate(BLACK_OCCUPANCIES, whiteKingPosition);
        temp_bitboard = Board.bitboard_array_global[GenConst.BB].and(bishopAttacksChecks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
                }
                whiteKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //queen
        temp_bitboard = Board.bitboard_array_global[GenConst.BQ].and(bishopAttacksChecks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 

            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
                }
                whiteKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //rook
        BigInteger rook_attacks = MoveUtils.GetRookMovesSeparate(BLACK_OCCUPANCIES, whiteKingPosition); 
        temp_bitboard = Board.bitboard_array_global[GenConst.BR].and(rook_attacks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
                }
                whiteKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //queen
        temp_bitboard = Board.bitboard_array_global[GenConst.BQ].and(rook_attacks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
                }
                whiteKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //#endregion

        BigInteger occupanciesWithoutWhiteKing = COMBINED_OCCUPANCIES.and(Board.bitboard_array_global[GenConst.WK].not());

        temp_attack = MoveConstants.KING_ATTACKS[whiteKingPosition];
        temp_empty = temp_attack.and(EMPTY_OCCUPANCIES);
        while (temp_empty.signum() != 0) // Using BigInteger's signum() to check if it's not 0
        {
            target_square = BitScanForward(temp_empty);
            temp_empty = temp_empty.and(temp_empty.subtract(BigInteger.ONE)); // Using BigInteger's subtract and and
        
            if (Board.bitboard_array_global[GenConst.BP].and(MoveConstants.WHITE_PAWN_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BN].and(MoveConstants.KNIGHT_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BK].and(MoveConstants.KING_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(occupanciesWithoutWhiteKing, target_square);
            if (Board.bitboard_array_global[GenConst.BB].and(bishopAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BQ].and(bishopAttacks).signum() != 0) {
                continue;
            }
            BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(occupanciesWithoutWhiteKing, target_square); 
            if (Board.bitboard_array_global[GenConst.BR].and(rookAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BQ].and(rookAttacks).signum() != 0) {
                continue;
            }
        
            move_list[move_count][MOVE_STARTING] = whiteKingPosition;
            move_list[move_count][MOVE_TARGET] = target_square;
            move_list[move_count][MOVE_TAG] = GenConst.TAG_NONE;
            move_list[move_count][MOVE_PIECE] = GenConst.WK;
            move_count++;
        }

        //captures
        temp_captures = temp_attack.and(BLACK_OCCUPANCIES);
        while (temp_captures.signum() != 0) // Using BigInteger's signum() to check if it's not 0
        {
            target_square = BitScanForward(temp_captures);
            temp_captures = temp_captures.and(temp_captures.subtract(BigInteger.ONE)); // Using BigInteger's subtract and and
        
            if (Board.bitboard_array_global[GenConst.BP].and(MoveConstants.WHITE_PAWN_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BN].and(MoveConstants.KNIGHT_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BK].and(MoveConstants.KING_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(occupanciesWithoutWhiteKing, target_square);
            if (Board.bitboard_array_global[GenConst.BB].and(bishopAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BQ].and(bishopAttacks).signum() != 0) {
                continue;
            }
            BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(occupanciesWithoutWhiteKing, target_square); 
            if (Board.bitboard_array_global[GenConst.BR].and(rookAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.BQ].and(rookAttacks).signum() != 0) {
                continue;
            }
        
            move_list[move_count][MOVE_STARTING] = whiteKingPosition;
            move_list[move_count][MOVE_TARGET] = target_square;
            move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
            move_list[move_count][MOVE_PIECE] = GenConst.WK;
            move_count++;
        }

        if (whiteKingCheckCount < 2)
        {

            if (whiteKingCheckCount == 0)
            {
                check_bitboard = MAX_ULONG;
            }

            //#region White castling

            if (whiteKingCheckCount == 0)
            {
                if (Board.castle_rights_global[WKS_CASTLE_RIGHTS] == true)
                {
                    if (whiteKingPosition == GenConst.E1) //king on e1
                    {
                        if (isNotZero(WKS_EMPTY_BITBOARD.and(COMBINED_OCCUPANCIES)) == false) //f1 and g1 empty
                        {
                            if (isNotZero(Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.H1])) == false) //rook on h1
                            {
                                if (MoveUtils.Is_Square_Attacked_By_Black_Global(GenConst.F1, COMBINED_OCCUPANCIES) == false)
                                {
                                    if (MoveUtils.Is_Square_Attacked_By_Black_Global(GenConst.G1, COMBINED_OCCUPANCIES) == false)
                                    {
                                        move_list[move_count][MOVE_STARTING] = GenConst.E1;
                                        move_list[move_count][MOVE_TARGET] = GenConst.G1;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCASTLEKS;
                                        move_list[move_count][MOVE_PIECE] = GenConst.WK;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }
                if (Board.castle_rights_global[WQS_CASTLE_RIGHTS] == true)
                {
                    if (whiteKingPosition == GenConst.E1) //king on e1
                    {
                        if (isNotZero(WQS_EMPTY_BITBOARD.and(COMBINED_OCCUPANCIES)) == false) //f1 and g1 empty
                        {
                            if ((isNotZero(Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.A1]))) == true) //rook on h1
                            {
                                if (MoveUtils.Is_Square_Attacked_By_Black_Global(GenConst.C1, COMBINED_OCCUPANCIES) == false)
                                {
                                    if (MoveUtils.Is_Square_Attacked_By_Black_Global(GenConst.D1, COMBINED_OCCUPANCIES) == false)
                                    {
                                        move_list[move_count][MOVE_STARTING] = GenConst.E1;
                                        move_list[move_count][MOVE_TARGET] = GenConst.C1;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCASTLEQS;
                                        move_list[move_count][MOVE_PIECE] = GenConst.WK;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //#endregion

            //#region White knight moves

            temp_bitboard = Board.bitboard_array_global[GenConst.WN];

            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE)); //removes the knight from that square to not infinitely loop

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                temp_attack = ((MoveConstants.KNIGHT_ATTACKS[starting_square].and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard))); //gets knight captures
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);
                    
                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WN;
                    move_count++;
                }

                temp_attack = ((MoveConstants.KNIGHT_ATTACKS[starting_square].and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WN;
                    move_count++;
                }
            }

            //#endregion

            //#region White pawn moves

            temp_bitboard = Board.bitboard_array_global[GenConst.WP];

            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard); 
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                //#region pawn forward

                if (isZero(MoveConstants.SQUARE_BBS[starting_square - 8].and(COMBINED_OCCUPANCIES)) == true) //if up one square is empty
                {
                    if (isNotZero(MoveConstants.SQUARE_BBS[starting_square - 8].and(check_bitboard).and(temp_pin_bitboard)) == true) //if not pinned or check
                    {
                        if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_7_BITBOARD))) //if promotion
                        {
                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_WQueenPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_WRookPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_WBishopPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_WBishopPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;

                        }
                        else
                        {
                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square - 8;
                            move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                            move_list[move_count][MOVE_PIECE] = GenConst.WP;
                            move_count++;
                        }
                    }

                    if ((isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_2_BITBOARD))) == true) //if on rank 2
                    {
                        if (isNotZero(MoveConstants.SQUARE_BBS[starting_square - 16].and(check_bitboard).and(temp_pin_bitboard)) == true) //if not pinned or 
                        {
                            if (isZero(MoveConstants.SQUARE_BBS[starting_square - 16].and(COMBINED_OCCUPANCIES)) == true) //if up two squares and one square are empty
                            {
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = starting_square - 16;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_DoublePawnWhite;
                                move_list[move_count][MOVE_PIECE] = GenConst.WP;
                                move_count++;
                            }
                        }
                    }
                }

                //#endregion
                //#region pawn attacks

                temp_attack = ((MoveConstants.WHITE_PAWN_ATTACKS[starting_square].and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard))); //if black piece diagonal to pawn

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_7_BITBOARD)) == true) //if promotion
                    {
                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCaptureQueenPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCaptureRookPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCaptureBishopPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WCaptureKnightPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;
                    }
                    else
                    {
                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                        move_count++;
                    }
                }

                if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_5_BITBOARD))) 
                { // check rank for ep
                    if (Board.ep != NO_SQUARE) 
                    {
                        if (isNotZero(MoveConstants.WHITE_PAWN_ATTACKS[starting_square]
                                .and(MoveConstants.SQUARE_BBS[Board.ep])
                                .and(check_bitboard)
                                .and(temp_pin_bitboard))) {
                            if (isZero(Board.bitboard_array_global[GenConst.WK].and(RANK_5_BITBOARD))) { // if no king on rank 5
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = Board.ep;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_WHITEEP;
                                move_list[move_count][MOVE_PIECE] = GenConst.WP;
                                move_count++;
                            } else if (isZero(Board.bitboard_array_global[GenConst.BR].and(RANK_5_BITBOARD)) &&
                                       isZero(Board.bitboard_array_global[GenConst.BQ].and(RANK_5_BITBOARD))) { // if no b rook or queen on rank 5
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = Board.ep;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_WHITEEP;
                                move_list[move_count][MOVE_PIECE] = GenConst.WP;
                                move_count++;
                            } else { // wk and br or bq on rank 5
                                BigInteger occupancyWithoutEPPawns = COMBINED_OCCUPANCIES.and(MoveConstants.SQUARE_BBS[starting_square].not());
                                occupancyWithoutEPPawns = occupancyWithoutEPPawns.and(MoveConstants.SQUARE_BBS[Board.ep + 8].not());
                
                                BigInteger rookAttacksFromKing = MoveUtils.GetRookMovesSeparate(occupancyWithoutEPPawns, whiteKingPosition);
                
                                if (isZero(rookAttacksFromKing.and(Board.bitboard_array_global[GenConst.BR]))) 
                                {
                                    if (isZero(rookAttacksFromKing.and(Board.bitboard_array_global[GenConst.BQ]))) 
                                    {
                                        move_list[move_count][MOVE_STARTING] = starting_square;
                                        move_list[move_count][MOVE_TARGET] = Board.ep;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_WHITEEP;
                                        move_list[move_count][MOVE_PIECE] = GenConst.WP;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }

                //#endregion
            }

            //#endregion

            //#region White rook moves

            temp_bitboard = Board.bitboard_array_global[GenConst.WR];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(COMBINED_OCCUPANCIES, starting_square);

                temp_attack = ((rookAttacks.and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WR;
                    move_count++;
                }

                temp_attack = ((rookAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WR;
                    move_count++;
                }
            }

            //#endregion

            //#region White bishop moves

            //Pr.println("\nwhite bishop");
            temp_bitboard = Board.bitboard_array_global[GenConst.WB];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                //Pr.println("get bishop attacks");
                BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(COMBINED_OCCUPANCIES, starting_square);
                //Pr.println("bishop attacks");
                //Pr.printBigIntegerLn(bishopAttacks);

                temp_attack = ((bishopAttacks.and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WB;
                    move_count++;
                }

                temp_attack = ((bishopAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WB;
                    move_count++;
                }
            }

            //#endregion

            //#region White queen moves

            temp_bitboard = Board.bitboard_array_global[GenConst.WQ];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger queenAttacks = MoveUtils.GetRookMovesSeparate(COMBINED_OCCUPANCIES, starting_square);
                queenAttacks = queenAttacks.and(MoveUtils.GetBishopMovesSeparate(COMBINED_OCCUPANCIES, starting_square));

                temp_attack = ((queenAttacks.and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WQ;
                    move_count++;
                }

                temp_attack = ((queenAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.WQ;
                    move_count++;
                }
            }

            //#endregion
        }
    }
    else //black move
    {
        int blackKingCheckCount = 0;
        int blackKingPosition = BitScanForward(Board.bitboard_array_global[GenConst.BK]);

        //#region black checks and pins

        //pawns
        temp_bitboard = Board.bitboard_array_global[GenConst.WP].and(MoveConstants.BLACK_PAWN_ATTACKS[blackKingPosition]);
        if (temp_bitboard.compareTo(BigInteger.ZERO) != 0) //if there is pawn attacking king
        {
            int pawn_square = BitScanForward(temp_bitboard); 

            if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                check_bitboard = MoveConstants.SQUARE_BBS[pawn_square];
            }
            
            blackKingCheckCount++;
        }

        //knights
        temp_bitboard = Board.bitboard_array_global[GenConst.WN].and(MoveConstants.KNIGHT_ATTACKS[blackKingPosition]);
        if (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int knight_square = BitScanForward(temp_bitboard);

            if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                check_bitboard = MoveConstants.SQUARE_BBS[knight_square];
            }
            
            blackKingCheckCount++;
        }

        //bishops
        BigInteger bishopAttacksChecks = MoveUtils.GetBishopMovesSeparate(WHITE_OCCUPANCIES, blackKingPosition);
        temp_bitboard = Board.bitboard_array_global[GenConst.WB].and(bishopAttacksChecks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0) 
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square].and(BLACK_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0) 
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
                }
                blackKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0) 
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //queen
        temp_bitboard = Board.bitboard_array_global[GenConst.WQ].and(bishopAttacksChecks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 

            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square].and(BLACK_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
                }
                blackKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //rook
        BigInteger rook_attacks = MoveUtils.GetRookMovesSeparate(WHITE_OCCUPANCIES, blackKingPosition); 
        temp_bitboard = Board.bitboard_array_global[GenConst.WR].and(rook_attacks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square].and(BLACK_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
                }
                blackKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //queen
        temp_bitboard = Board.bitboard_array_global[GenConst.WQ].and(rook_attacks);
        while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
        {
            int piece_square = BitScanForward(temp_bitboard); 
            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square].and(WHITE_OCCUPANCIES);

            if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                if (check_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    check_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
                }
                blackKingCheckCount++;
            }
            else
            {
                int pinned_square = BitScanForward(temp_pin_bitboard); 
                temp_pin_bitboard = temp_pin_bitboard.and(temp_pin_bitboard.subtract(BigInteger.ONE));

                if (temp_pin_bitboard.compareTo(BigInteger.ZERO) != 0)
                {
                    pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
                    pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
                    pinNumber++;
                }
            }
            temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));
        }

        //#endregion

        BigInteger occupanciesWithoutWhiteKing = COMBINED_OCCUPANCIES.and(Board.bitboard_array_global[GenConst.WK].not());

        temp_attack = MoveConstants.KING_ATTACKS[blackKingPosition];
        temp_empty = temp_attack.and(EMPTY_OCCUPANCIES);
        while (temp_empty.signum() != 0) // Using BigInteger's signum() to check if it's not 0
        {
            target_square = BitScanForward(temp_empty);
            temp_empty = temp_empty.and(temp_empty.subtract(BigInteger.ONE)); // Using BigInteger's subtract and and
        
            if (Board.bitboard_array_global[GenConst.WP].and(MoveConstants.BLACK_PAWN_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WN].and(MoveConstants.KNIGHT_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WK].and(MoveConstants.KING_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(occupanciesWithoutWhiteKing, target_square);
            if (Board.bitboard_array_global[GenConst.WB].and(bishopAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WQ].and(bishopAttacks).signum() != 0) {
                continue;
            }
            BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(occupanciesWithoutWhiteKing, target_square); 
            if (Board.bitboard_array_global[GenConst.WR].and(rookAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WQ].and(rookAttacks).signum() != 0) {
                continue;
            }
        
            move_list[move_count][MOVE_STARTING] = blackKingPosition;
            move_list[move_count][MOVE_TARGET] = target_square;
            move_list[move_count][MOVE_TAG] = GenConst.TAG_NONE;
            move_list[move_count][MOVE_PIECE] = GenConst.BK;
            move_count++;
        }

        //captures
        temp_captures = temp_attack.and(BLACK_OCCUPANCIES);
        while (temp_captures.signum() != 0) // Using BigInteger's signum() to check if it's not 0
        {
            target_square = BitScanForward(temp_captures);
            temp_captures = temp_captures.and(temp_captures.subtract(BigInteger.ONE)); // Using BigInteger's subtract and and
        
            if (Board.bitboard_array_global[GenConst.WP].and(MoveConstants.BLACK_PAWN_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WN].and(MoveConstants.KNIGHT_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WK].and(MoveConstants.KING_ATTACKS[target_square]).signum() != 0) {
                continue;
            }
            BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(occupanciesWithoutWhiteKing, target_square);
            if (Board.bitboard_array_global[GenConst.WB].and(bishopAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WQ].and(bishopAttacks).signum() != 0) {
                continue;
            }
            BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(occupanciesWithoutWhiteKing, target_square); 
            if (Board.bitboard_array_global[GenConst.WR].and(rookAttacks).signum() != 0) {
                continue;
            }
            if (Board.bitboard_array_global[GenConst.WQ].and(rookAttacks).signum() != 0) {
                continue;
            }
        
            move_list[move_count][MOVE_STARTING] = blackKingPosition;
            move_list[move_count][MOVE_TARGET] = target_square;
            move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
            move_list[move_count][MOVE_PIECE] = GenConst.BK;
            move_count++;
        }

        if (blackKingCheckCount < 2)
        {

            if (blackKingCheckCount == 0)
            {
                check_bitboard = MAX_ULONG;
            }

            //#region Black castling

            if (blackKingCheckCount == 0)
            {
                if (Board.castle_rights_global[BKS_CASTLE_RIGHTS] == true)
                {
                    if (blackKingPosition == GenConst.E8) //king on e1
                    {
                        if (isNotZero(BKS_EMPTY_BITBOARD.and(COMBINED_OCCUPANCIES)) == false) //f1 and g1 empty
                        {
                            if (isNotZero(Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.H8])) == false) //rook on h8
                            {
                                if (MoveUtils.Is_Square_Attacked_By_White_Global(GenConst.F8, COMBINED_OCCUPANCIES) == false)
                                {
                                    if (MoveUtils.Is_Square_Attacked_By_White_Global(GenConst.G8, COMBINED_OCCUPANCIES) == false)
                                    {
                                        move_list[move_count][MOVE_STARTING] = GenConst.E8;
                                        move_list[move_count][MOVE_TARGET] = GenConst.G8;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCASTLEKS;
                                        move_list[move_count][MOVE_PIECE] = GenConst.BK;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }
                if (Board.castle_rights_global[BQS_CASTLE_RIGHTS] == true)
                {
                    if (blackKingPosition == GenConst.E8) //king on e1
                    {
                        if (isNotZero(BQS_EMPTY_BITBOARD.and(COMBINED_OCCUPANCIES)) == false) //f1 and g1 empty
                        {
                            if ((isNotZero(Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.A8]))) == true) //rook on h1
                            {
                                if (MoveUtils.Is_Square_Attacked_By_White_Global(GenConst.C8, COMBINED_OCCUPANCIES) == false)
                                {
                                    if (MoveUtils.Is_Square_Attacked_By_White_Global(GenConst.D8, COMBINED_OCCUPANCIES) == false)
                                    {
                                        move_list[move_count][MOVE_STARTING] = GenConst.E8;
                                        move_list[move_count][MOVE_TARGET] = GenConst.C8;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCASTLEQS;
                                        move_list[move_count][MOVE_PIECE] = GenConst.BK;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //#endregion

            //#region Black knight moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BN];

            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE)); //removes the knight from that square to not infinitely loop

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                temp_attack = ((MoveConstants.KNIGHT_ATTACKS[starting_square].and(WHITE_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard))); //gets knight captures
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);
                    
                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BN;
                    move_count++;
                }

                temp_attack = ((MoveConstants.KNIGHT_ATTACKS[starting_square].and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BN;
                    move_count++;
                }
            }

            //#endregion

            //#region Black pawn moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BP];

            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard); 
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                //#region pawn forward

                if (isZero(MoveConstants.SQUARE_BBS[starting_square + 8].and(COMBINED_OCCUPANCIES)) == true) //if up one square is empty
                {
                    if (isNotZero(MoveConstants.SQUARE_BBS[starting_square + 8].and(check_bitboard).and(temp_pin_bitboard)) == true) //if not pinned or check
                    {
                        if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_2_BITBOARD))) //if promotion
                        {
                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_BQueenPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_BRookPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_BBishopPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;

                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] = GenConst.TAG_BBishopPromotion;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;

                        }
                        else
                        {
                            move_list[move_count][MOVE_STARTING] = starting_square;
                            move_list[move_count][MOVE_TARGET] = starting_square + 8;
                            move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                            move_list[move_count][MOVE_PIECE] = GenConst.BP;
                            move_count++;
                        }
                    }

                    if ((isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_7_BITBOARD))) == true) //if on rank 7
                    {
                        if (isNotZero(MoveConstants.SQUARE_BBS[starting_square + 16].and(check_bitboard).and(temp_pin_bitboard)) == true) //if not pinned or 
                        {
                            if (isZero(MoveConstants.SQUARE_BBS[starting_square + 16].and(COMBINED_OCCUPANCIES)) == true) //if up two squares and one square are empty
                            {
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = starting_square - 16;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_DoublePawnBlack;
                                move_list[move_count][MOVE_PIECE] = GenConst.BP;
                                move_count++;
                            }
                        }
                    }
                }

                //#endregion
                //#region pawn attacks

                temp_attack = ((MoveConstants.BLACK_PAWN_ATTACKS[starting_square].and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard))); //if black piece diagonal to pawn

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_2_BITBOARD)) == true) //if promotion
                    {
                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCaptureQueenPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCaptureRookPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCaptureBishopPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;

                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BCaptureKnightPromotion;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;
                    }
                    else
                    {
                        move_list[move_count][MOVE_STARTING] = starting_square;
                        move_list[move_count][MOVE_TARGET] = target_square;
                        move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                        move_count++;
                    }
                }

                if (isNotZero(MoveConstants.SQUARE_BBS[starting_square].and(RANK_4_BITBOARD))) 
                { // check rank for ep
                    if (Board.ep != NO_SQUARE) 
                    {
                        if (isNotZero(MoveConstants.BLACK_PAWN_ATTACKS[starting_square]
                                .and(MoveConstants.SQUARE_BBS[Board.ep])
                                .and(check_bitboard)
                                .and(temp_pin_bitboard))) {
                            if (isZero(Board.bitboard_array_global[GenConst.WK].and(RANK_5_BITBOARD))) { // if no king on rank 5
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = Board.ep;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_BLACKEP;
                                move_list[move_count][MOVE_PIECE] = GenConst.BP;
                                move_count++;
                            } else if (isZero(Board.bitboard_array_global[GenConst.WR].and(RANK_5_BITBOARD)) &&
                                       isZero(Board.bitboard_array_global[GenConst.WQ].and(RANK_5_BITBOARD))) { // if no b rook or queen on rank 5
                                move_list[move_count][MOVE_STARTING] = starting_square;
                                move_list[move_count][MOVE_TARGET] = Board.ep;
                                move_list[move_count][MOVE_TAG] = GenConst.TAG_BLACKEP;
                                move_list[move_count][MOVE_PIECE] = GenConst.BP;
                                move_count++;
                            } else { // wk and br or bq on rank 5
                                BigInteger occupancyWithoutEPPawns = COMBINED_OCCUPANCIES.and(MoveConstants.SQUARE_BBS[starting_square].not());
                                occupancyWithoutEPPawns = occupancyWithoutEPPawns.and(MoveConstants.SQUARE_BBS[Board.ep - 8].not());
                
                                BigInteger rookAttacksFromKing = MoveUtils.GetRookMovesSeparate(occupancyWithoutEPPawns, blackKingPosition);
                
                                if (isZero(rookAttacksFromKing.and(Board.bitboard_array_global[GenConst.WR]))) 
                                {
                                    if (isZero(rookAttacksFromKing.and(Board.bitboard_array_global[GenConst.WQ]))) 
                                    {
                                        move_list[move_count][MOVE_STARTING] = starting_square;
                                        move_list[move_count][MOVE_TARGET] = Board.ep;
                                        move_list[move_count][MOVE_TAG] = GenConst.TAG_BLACKEP;
                                        move_list[move_count][MOVE_PIECE] = GenConst.BP;
                                        move_count++;
                                    }
                                }
                            }
                        }
                    }
                }

                //#endregion
            }

            //#endregion

            //#region Black rook moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BR];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger rookAttacks = MoveUtils.GetRookMovesSeparate(COMBINED_OCCUPANCIES, starting_square);

                temp_attack = ((rookAttacks.and(WHITE_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BR;
                    move_count++;
                }

                temp_attack = ((rookAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BR;
                    move_count++;
                }
            }

            //#endregion

            //#region Black bishop moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BB];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger bishopAttacks = MoveUtils.GetBishopMovesSeparate(COMBINED_OCCUPANCIES, starting_square);

                temp_attack = ((bishopAttacks.and(WHITE_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BB;
                    move_count++;
                }

                temp_attack = ((bishopAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BB;
                    move_count++;
                }
            }

            //#endregion

            //#region Black queen moves

            temp_bitboard = Board.bitboard_array_global[GenConst.BQ];
            while (temp_bitboard.compareTo(BigInteger.ZERO) != 0)
            {
                starting_square = BitScanForward(temp_bitboard);
                temp_bitboard = temp_bitboard.and(temp_bitboard.subtract(BigInteger.ONE));

                temp_pin_bitboard = MAX_ULONG;
                if (pinNumber != 0)
                {
                    for (int i = 0; i < pinNumber; i++)
                    {
                        if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square)
                        {
                            temp_pin_bitboard = Inb.INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
                        }
                    }
                }

                BigInteger queenAttacks = MoveUtils.GetRookMovesSeparate(COMBINED_OCCUPANCIES, starting_square);
                queenAttacks = queenAttacks.and(MoveUtils.GetBishopMovesSeparate(COMBINED_OCCUPANCIES, starting_square));

                temp_attack = ((queenAttacks.and(BLACK_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));

                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] = GenConst.TAG_CAPTURE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BQ;
                    move_count++;
                }

                temp_attack = ((queenAttacks.and(EMPTY_OCCUPANCIES).and(check_bitboard).and(temp_pin_bitboard)));
                while (isNotZero(temp_attack))
                {
                    target_square = BitScanForward(temp_attack);
                    temp_attack = removeBit(temp_attack);

                    move_list[move_count][MOVE_STARTING] = starting_square;
                    move_list[move_count][MOVE_TARGET] = target_square;
                    move_list[move_count][MOVE_TAG] =  GenConst.TAG_NONE;
                    move_list[move_count][MOVE_PIECE] = GenConst.BQ;
                    move_count++;
                }
            }

            //#endregion
        }
    }

    //if (depth == 1)
    //{
        //return move_count;
    //}

    int nodes = 0;
    int priorNodes;
    int copyEp = Board.ep;
    
    boolean[] copy_castle = {
        Board.castle_rights_global[0],
        Board.castle_rights_global[1],
        Board.castle_rights_global[2],
        Board.castle_rights_global[3],
    };

    for (int move_index = 0; move_index < move_count; move_index++)
    {
        int startingSquare = move_list[move_index][MOVE_STARTING];
        int targetSquare = move_list[move_index][MOVE_TARGET];
        int piece = move_list[move_index][MOVE_PIECE];
        int tag = move_list[move_index][MOVE_TAG];

        int captureIndex = -1;

        Board.is_white_global = !Board.is_white_global;
        switch (tag)
        {
        case GenConst.TAG_NONE: //none
        case GenConst.TAG_CHECK: //check
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_CAPTURE: //capture
        case GenConst.TAG_CHECK_CAPTURE: //check cap
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            if (piece >= GenConst.WP && piece <= GenConst.WK)
            {
                for (int i = GenConst.BP; i <= GenConst.WP; ++i)
                {
                    if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                    {
                        captureIndex = i;
                        break;
                    }
                }
                Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            }
            else //is black
            {
                for (int i = GenConst.WP; i <= GenConst.WK; ++i)
                {
                    if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                    {
                        captureIndex = i;
                        break;
                    }
                }
                Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            }

            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_WHITEEP: //white ep
            //move piece
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[targetSquare + 8].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BLACKEP: //black ep
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[targetSquare - 8].not());
            Board.ep = NO_SQUARE;
            break;

        case GenConst.TAG_WCASTLEKS: //WKS
            //white king
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].or(MoveConstants.SQUARE_BBS[GenConst.G1]);
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].and(MoveConstants.SQUARE_BBS[GenConst.E1].not());
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[GenConst.F1]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.H1].not());

            Board.castle_rights_global[WKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[WQS_CASTLE_RIGHTS] = false;
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_WCASTLEQS: //WQS
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].or(MoveConstants.SQUARE_BBS[GenConst.C1]);
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].and(MoveConstants.SQUARE_BBS[GenConst.E1].not());
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[GenConst.D1]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.A1].not());

            Board.castle_rights_global[WKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[WQS_CASTLE_RIGHTS] = false;
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BCASTLEKS: //BKS
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].or(MoveConstants.SQUARE_BBS[GenConst.G8]);
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].and(MoveConstants.SQUARE_BBS[GenConst.E8].not());
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[GenConst.F8]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.H8].not());

            Board.castle_rights_global[BKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[BQS_CASTLE_RIGHTS] = false;
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BCASTLEQS: //BQS
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].or(MoveConstants.SQUARE_BBS[GenConst.C8]);
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].and(MoveConstants.SQUARE_BBS[GenConst.E8].not());
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[GenConst.D8]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.A8].not());

            Board.castle_rights_global[BKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[BQS_CASTLE_RIGHTS] = false;
            Board.ep = NO_SQUARE;
            break;

        case GenConst.TAG_BKnightPromotion: //BNPr
            Board.bitboard_array_global[GenConst.BN] =Board.bitboard_array_global[GenConst.BN].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BBishopPromotion: //BBPr
            Board.bitboard_array_global[GenConst.BB] =Board.bitboard_array_global[GenConst.BB].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BQueenPromotion: //BQPr
            Board.bitboard_array_global[GenConst.BQ] =Board.bitboard_array_global[GenConst.BQ].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BRookPromotion: //BRPr
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 12: //WNPr
            Board.bitboard_array_global[GenConst.WN] =Board.bitboard_array_global[GenConst.WN].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 13: //WBPr
            Board.bitboard_array_global[GenConst.WB] =Board.bitboard_array_global[GenConst.WB].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 14: //WQPr
            Board.bitboard_array_global[GenConst.WQ] =Board.bitboard_array_global[GenConst.WQ].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 15: //WRPr
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 16: //BNPrCAP
            Board.bitboard_array_global[GenConst.BN] =Board.bitboard_array_global[GenConst.BN].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.WP; i <= GenConst.WK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());

            break;
        case 17: //BBPrCAP
            Board.bitboard_array_global[GenConst.BB] =Board.bitboard_array_global[GenConst.BB].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.WP; i <= GenConst.WK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 18: //BQPrCAP
            Board.bitboard_array_global[GenConst.BQ] =Board.bitboard_array_global[GenConst.BQ].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.WP; i <= GenConst.WK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 19: //BRPrCAP
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.WP; i <= GenConst.WK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 20: //WNPrCAP
            Board.bitboard_array_global[GenConst.WN] =Board.bitboard_array_global[GenConst.WN].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.BP; i <= GenConst.BK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());

            break;
        case 21: //WBPrCAP
            Board.bitboard_array_global[GenConst.WB] =Board.bitboard_array_global[GenConst.WB].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.BP; i <= GenConst.BK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());

            break;
        case 22: //WQPrCAP
            Board.bitboard_array_global[GenConst.WQ] =Board.bitboard_array_global[GenConst.WQ].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = NO_SQUARE;
            for (int i = GenConst.BP; i <= GenConst.BK; ++i)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());

            break;
        case 23: //WRPrCAP
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[startingSquare].not());

            Board.ep = NO_SQUARE;
            for (int i = GenConst.BP; i <= GenConst.BK; i++)
            {
                if (isNotZero((Board.bitboard_array_global[i].and(MoveConstants.SQUARE_BBS[targetSquare]))))
                {
                    captureIndex = i;
                    break;
                }
            }
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 24: //WDouble
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = targetSquare + 8;
            break;
        case 25: //BDouble
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            Board.ep = targetSquare - 8;
            break;
        }

        if (piece == GenConst.WK)
        {
            Board.castle_rights_global[WKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[WQS_CASTLE_RIGHTS] = false;
        }
        else if (piece == GenConst.BK)
        {
            Board.castle_rights_global[BKS_CASTLE_RIGHTS] = false;
            Board.castle_rights_global[BQS_CASTLE_RIGHTS] = false;
        }
        else if (piece == GenConst.WR)
        {
            if (Board.castle_rights_global[WKS_CASTLE_RIGHTS] == true)
            {
                if (isZero((Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.H1]))))
                {
                    Board.castle_rights_global[WKS_CASTLE_RIGHTS] = false;
                }
            }
            if (Board.castle_rights_global[WQS_CASTLE_RIGHTS] == true)
            {
                if (isZero((Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.A1]))))
                {
                    Board.castle_rights_global[WQS_CASTLE_RIGHTS] = false;
                }
            }
        }
        else if (piece == GenConst.BR)
        {
            if (Board.castle_rights_global[BKS_CASTLE_RIGHTS] == true)
            {
                if (isZero((Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.H8]))))
                {
                    Board.castle_rights_global[BKS_CASTLE_RIGHTS] = false;
                }
            }
            if (Board.castle_rights_global[BQS_CASTLE_RIGHTS] == true)
            {
                if (isZero((Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.A8]))))
                {
                    Board.castle_rights_global[BQS_CASTLE_RIGHTS] = false;
                }
            }
        }

        priorNodes = nodes;
        nodes += PerftInlineGlobal(depth - 1, ply + 1);

        Board.is_white_global = !Board.is_white_global;
        switch (tag)
        {
        case GenConst.TAG_NONE: //none
        case GenConst.TAG_CHECK: //check
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case GenConst.TAG_CAPTURE: //capture
        case GenConst.TAG_CHECK_CAPTURE: //check cap
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] = Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[startingSquare]);
            break;
        case GenConst.TAG_WHITEEP: //white ep
            //move piece
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[targetSquare + 8]);
            break;
        case GenConst.TAG_BLACKEP: //black ep
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[targetSquare - 8]);
            break;

        case GenConst.TAG_WCASTLEKS: //WKS
            //white king
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].or(MoveConstants.SQUARE_BBS[GenConst.E1]);
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].and(MoveConstants.SQUARE_BBS[GenConst.G1].not());
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[GenConst.H1]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.F1].not());
            break;
        case GenConst.TAG_WCASTLEQS: //WQS
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].or(MoveConstants.SQUARE_BBS[GenConst.E1]);
            Board.bitboard_array_global[GenConst.WK] =Board.bitboard_array_global[GenConst.WK].and(MoveConstants.SQUARE_BBS[GenConst.C1].not());
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].or(MoveConstants.SQUARE_BBS[GenConst.A1]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[GenConst.D1].not());
            break;
        case GenConst.TAG_BCASTLEKS: //BKS
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].or(MoveConstants.SQUARE_BBS[GenConst.E8]);
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].and(MoveConstants.SQUARE_BBS[GenConst.G8].not());
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[GenConst.H8]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.F8].not());
            break;
        case GenConst.TAG_BCASTLEQS: //BQS
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].or(MoveConstants.SQUARE_BBS[GenConst.E8]);
            Board.bitboard_array_global[GenConst.BK] =Board.bitboard_array_global[GenConst.BK].and(MoveConstants.SQUARE_BBS[GenConst.C8].not());
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].or(MoveConstants.SQUARE_BBS[GenConst.A8]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[GenConst.D8].not());
            break;

        case GenConst.TAG_BKnightPromotion: //BNPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BN] =Board.bitboard_array_global[GenConst.BN].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case GenConst.TAG_BBishopPromotion: //BBPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BB] =Board.bitboard_array_global[GenConst.BB].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case GenConst.TAG_BQueenPromotion: //BQPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BQ] =Board.bitboard_array_global[GenConst.BQ].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case GenConst.TAG_BRookPromotion: //BRPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.ep = NO_SQUARE;
            break;
        case 12: //WNPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WN] =Board.bitboard_array_global[GenConst.WN].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 13: //WBPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WB] =Board.bitboard_array_global[GenConst.WB].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 14: //WQPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WQ] =Board.bitboard_array_global[GenConst.WQ].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 15: //WRPr
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 16: //BNPrCAP
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BN] =Board.bitboard_array_global[GenConst.BN].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 17: //BBPrCAP
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BB] =Board.bitboard_array_global[GenConst.BB].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 18: //BQPrCAP
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BQ] =Board.bitboard_array_global[GenConst.BQ].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 19: //BRPrCAP
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.BR] =Board.bitboard_array_global[GenConst.BR].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 20: //WNPrCAP
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WN] =Board.bitboard_array_global[GenConst.WN].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 21: //WBPrCAP
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WB] =Board.bitboard_array_global[GenConst.WB].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 22: //WQPrCAP
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WQ] =Board.bitboard_array_global[GenConst.WQ].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 23: //WRPrCAP
            Board.bitboard_array_global[piece] =Board.bitboard_array_global[piece].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WR] =Board.bitboard_array_global[GenConst.WR].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            Board.bitboard_array_global[captureIndex] =Board.bitboard_array_global[captureIndex].or(MoveConstants.SQUARE_BBS[targetSquare]);
            break;
        case 24: //WDouble
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].or(MoveConstants.SQUARE_BBS[startingSquare]);
            Board.bitboard_array_global[GenConst.WP] =Board.bitboard_array_global[GenConst.WP].and(MoveConstants.SQUARE_BBS[targetSquare].not());
            break;
        case 25: //BDouble
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].or(MoveConstants.SQUARE_BBS[targetSquare]);
            Board.bitboard_array_global[GenConst.BP] =Board.bitboard_array_global[GenConst.BP].and(MoveConstants.SQUARE_BBS[startingSquare].not());
            break;
        }

        Board.castle_rights_global[0] = copy_castle[0];
        Board.castle_rights_global[1] = copy_castle[1];
        Board.castle_rights_global[2] = copy_castle[2];
        Board.castle_rights_global[3] = copy_castle[3];
        Board.ep = copyEp;

        //if (epGlobal != NO_SQUARE)
        //{
        //    std::cout << "   ep: " << SQ_CHAR_X[epGlobal] << SQ_CHAR_Y[epGlobal] << '\n';
        //}



        if (ply == 0)
        {
            //Pr.printInt(startingSquare);
            //Pr.printInt(targetSquare);
            //Pr.printInt(tag);
            PrintMoveNoNL(startingSquare, targetSquare, tag);
            System.out.printf(": %d\n", nodes - priorNodes);
        }
    }

        return nodes;
    }

    public static void RunPerftInlineGlobalOcc(int depth)
    {
        long startTime = System.currentTimeMillis();
        
        int nodes = PerftInlineDebug(depth, 0);

        long endTime = System.currentTimeMillis();

        long elapsedTime = endTime - startTime;

        String nodeString = String.format("Nodes: %d\n", nodes);
        String timeString = String.format("Time taken: %d ms\n", elapsedTime);
        
        Pr.print(nodeString);
        Pr.print(timeString);
    }
}
