diff --git a/chess_move_generator.cpp b/chess_move_generator.cpp new file mode 100644 index 0000000..f2cf42e --- /dev/null +++ b/chess_move_generator.cpp @@ -0,0 +1,2706 @@ + +#include +#include "constants.h" + +#pragma region General constants + +const int MOVE_STARTING = 0; +const int MOVE_TARGET = 1; +const int MOVE_PIECE = 2; +const int MOVE_TAG = 3; + +const char* FEN_STARTING_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; + +const unsigned long long WKS_EMPTY_BITBOARD = 6917529027641081856; +const unsigned long long WQS_EMPTY_BITBOARD = 1008806316530991104; +const unsigned long long BKS_EMPTY_BITBOARD = 96; +const unsigned long long BQS_EMPTY_BITBOARD = 14; + +const unsigned long long MAX_ULONG = 18446744073709551615; + +const char SQ_CHAR_Y[65] = +{ + '8','8','8','8','8','8','8','8', + '7','7','7','7','7','7','7','7', + '6','6','6','6','6','6','6','6', + '5','5','5','5','5','5','5','5', + '4','4','4','4','4','4','4','4', + '3','3','3','3','3','3','3','3', + '2','2','2','2','2','2','2','2', + '1','1','1','1','1','1','1','1','A' +}; + +const char SQ_CHAR_X[65] = +{ + 'a','b','c','d','e','f','g','h', + 'a','b','c','d','e','f','g','h', + 'a','b','c','d','e','f','g','h', + 'a','b','c','d','e','f','g','h', + 'a','b','c','d','e','f','g','h', + 'a','b','c','d','e','f','g','h', + 'a','b','c','d','e','f','g','h', + 'a','b','c','d','e','f','g','h','N' +}; + +const int WKS_CASTLE_RIGHTS = 0, WQS_CASTLE_RIGHTS = 1, BKS_CASTLE_RIGHTS = 2, BQS_CASTLE_RIGHTS = 3; +const int WP = 0, WN = 1, WB = 2, WR = 3, WQ = 4, WK = 5, +BP = 6, BN = 7, BB = 8, BR = 9, BQ = 10, BK = 11; + +const int A8 = 0, B8 = 1, C8 = 2, D8 = 3, E8 = 4, F8 = 5, G8 = 6, H8 = 7, +A7 = 8, B7 = 9, C7 = 10, D7 = 11, E7 = 12, F7 = 13, G7 = 14, H7 = 15, +A6 = 16, B6 = 17, C6 = 18, D6 = 19, E6 = 20, F6 = 21, G6 = 22, H6 = 23, +A5 = 24, B5 = 25, C5 = 26, D5 = 27, E5 = 28, F5 = 29, G5 = 30, H5 = 31, +A4 = 32, B4 = 33, C4 = 34, D4 = 35, E4 = 36, F4 = 37, G4 = 38, H4 = 39, +A3 = 40, B3 = 41, C3 = 42, D3 = 43, E3 = 44, F3 = 45, G3 = 46, H3 = 47, +A2 = 48, B2 = 49, C2 = 50, D2 = 51, E2 = 52, F2 = 53, G2 = 54, H2 = 55, +A1 = 56, B1 = 57, C1 = 58, D1 = 59, E1 = 60, F1 = 61, G1 = 62, H1 = 63, NO_SQUARE = 64; + +const unsigned long long RANK_1_BITBOARD = 18374686479671623680; +const unsigned long long RANK_2_BITBOARD = 71776119061217280; +const unsigned long long RANK_3_BITBOARD = 280375465082880; +const unsigned long long RANK_4_BITBOARD = 1095216660480; +const unsigned long long RANK_5_BITBOARD = 4278190080; +const unsigned long long RANK_6_BITBOARD = 16711680; +const unsigned long long RANK_7_BITBOARD = 65280; +const unsigned long long RANK_8_BITBOARD = 255; + +const int WHITE_START_INDEX = WP; +const int WHITE_END_INDEX = WK; +const int BLACK_START_INDEX = BP; +const int BLACK_END_INDEX = BK; + +const int PINNED_SQUARE_INDEX = 0; +const int PINNING_PIECE_INDEX = 1; + +const int TAG_NONE = 0, TAG_CAPTURE = 1, TAG_WHITEEP = 2, TAG_BLACKEP = 3, TAG_WCASTLEKS = 4, TAG_WCASTLEQS = 5, TAG_BCASTLEKS = 6, TAG_BCASTLEQS = 7, +TAG_BKnightPromotion = 8, TAG_BBishopPromotion = 9, TAG_BQueenPromotion = 10, TAG_BRookPromotion = 11, +TAG_WKnightPromotion = 12, TAG_WBishopPromotion = 13, TAG_WQueenPromotion = 14, TAG_WRookPromotion = 15, +TAG_BCaptureKnightPromotion = 16, TAG_BCaptureBishopPromotion = 17, TAG_BCaptureQueenPromotion = 18, TAG_BCaptureRookPromotion = 19, +TAG_WCaptureKnightPromotion = 20, TAG_WCaptureBishopPromotion = 21, TAG_WCaptureQueenPromotion = 22, TAG_WCaptureRookPromotion = 23, +TAG_DoublePawnWhite = 24, TAG_DoublePawnBlack = 25, TAG_CHECK = 26, TAG_CHECK_CAPTURE = 27; + +const unsigned long long MAGIC = 285870213051386505; + +const int DEBRUIJN64[64] = +{ + 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 +}; + +#pragma endregion + +//equation: startingSquare = (DEBRUIJN64[MAGIC * (tempBitboard ^ (tempBitboard - 1)) >> 58]); + +inline bool PieceIsWhite(const int piece) +{ + if (piece >= WP) + { + if (piece <= WK) + { + return true; + } + } + return false; +} + +inline int BitscanForward(const unsigned long long tempBitboard) +{ + return (DEBRUIJN64[MAGIC * (tempBitboard ^ (tempBitboard - 1)) >> 58]); +} + +inline unsigned long long GetRookAttacksFast(const int startingSquare, unsigned long long occupancy) +{ + occupancy &= ROOK_MASKS[startingSquare]; + occupancy *= ROOK_MAGIC_NUMBERS[startingSquare]; + occupancy >>= 64 - ROOK_REL_BITS[startingSquare]; + return ROOK_ATTACKS[startingSquare][occupancy]; +} + +inline unsigned long long GetBishopAttacksFast(const int startingSquare, unsigned long long occupancy) +{ + occupancy &= BISHOP_MASKS[startingSquare]; + occupancy *= BISHOP_MAGIC_NUMBERS[startingSquare]; + occupancy >>= 64 - BISHOP_REL_BITS[startingSquare]; + return BISHOP_ATTACKS[startingSquare][occupancy]; +} + + +unsigned long long* bitboardArray[12]; +int* ep; +bool* castleRights[4]; +bool* isWhite; + +unsigned long long bitboard_array_global[12]; +int ep_global; +bool castle_rights_global[4]; +bool is_white_global; + + +inline bool Is_Square_Attacked_By_Black_Global(const int square, const unsigned long long occupancy) +{ + if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[square]) != 0) + { + return true; + } + if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[square]) != 0) + { + return true; + } + if ((bitboard_array_global[BK] & KING_ATTACKS[square]) != 0) + { + return true; + } + unsigned long long bishopAttacks = GetBishopAttacksFast(square, occupancy); + if ((bitboard_array_global[BB] & bishopAttacks) != 0) + { + return true; + } + if ((bitboard_array_global[BQ] & bishopAttacks) != 0) + { + return true; + } + unsigned long long rookAttacks = GetRookAttacksFast(square, occupancy); + if ((bitboard_array_global[BR] & rookAttacks) != 0) + { + return true; + } + if ((bitboard_array_global[BQ] & rookAttacks) != 0) + { + return true; + } + return false; +} + +inline bool Is_Square_Attacked_By_White_Global(const int square, const unsigned long long occupancy) +{ + if ((bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[square]) != 0) + { + return true; + } + if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[square]) != 0) + { + return true; + } + if ((bitboard_array_global[WK] & KING_ATTACKS[square]) != 0) + { + return true; + } + unsigned long long bishopAttacks = GetBishopAttacksFast(square, occupancy); + if ((bitboard_array_global[WB] & bishopAttacks) != 0) + { + return true; + } + if ((bitboard_array_global[WQ] & bishopAttacks) != 0) + { + return true; + } + unsigned long long rookAttacks = GetRookAttacksFast(square, occupancy); + if ((bitboard_array_global[WR] & rookAttacks) != 0) + { + return true; + } + if ((bitboard_array_global[WQ] & rookAttacks) != 0) + { + return true; + } + return false; +} + + +void CreateBoard() +{ + for (size_t i = 0; i < 12; ++i) + { + bitboardArray[i] = new unsigned long long; + } + ep = new int; + isWhite = new bool; + for (size_t i = 0; i < 4; ++i) + { + castleRights[i] = new bool; + } +} + + +void CopyGlobalBoardGlobal() +{ + for (size_t i = 0; i < 12; ++i) + { + bitboard_array_global[i] = *bitboardArray[i]; + } + for (size_t i = 0; i < 4; ++i) + { + castle_rights_global[i] = *castleRights[i]; + } + ep_global = *ep; + is_white_global = *isWhite; +} + + +void ResetBoardGlobal() +{ + *castleRights[0] = false; + *castleRights[1] = false; + *castleRights[2] = false; + *castleRights[3] = false; + + for (size_t i = 0; i < 12; i++) + { + *bitboardArray[i] = 0; + } + *isWhite = true; + *ep = NO_SQUARE; +} + +const int PIECE_PHASE = 0; const int SIDE_PHASE = 1; const int CASTLE_PHASE = 2; const int EP_PHASE = 3; const int FIFTY_MOVE_PHASE = 4; const int MOVE_COUNT_PHASE = 5; + +void ParseFenGlobal(const char input[], const size_t startingIndex) +{ + ResetBoardGlobal(); + + const size_t inputLength = strlen(input); + if (startingIndex >= inputLength) + { + return; + } + if (startingIndex < 0) + { + return; + } + + int currentPhase = PIECE_PHASE; + int bracketCount = 0; + int squareCount = 0; + int epX = -1; + int epY = -1; + + for (size_t characterIndex = startingIndex; characterIndex < inputLength; characterIndex++) + { + const char characterInFen = input[characterIndex]; + //printf("index: %d ", characterIndex); + //printf("currentPhase: %d", currentPhase); + //printf(" char: %c\n", characterInFen); + //printf(" bracketcount %d", bracketCount); + //printf(" squarecount: %d\n", squareCount); + switch (currentPhase) + { + case 0: + + if (bracketCount == 7 && characterInFen == ' ') + { + //printf(" next phase brackcount = 7, char is empty\n"); + currentPhase++; + } + else + { + if (bracketCount > 7) + { + bracketCount = 0; + } + + if (squareCount > 7) + { + squareCount = 0; + } + + int square = (bracketCount * 8) + squareCount; + + switch (characterInFen) + { + + case 'B': + //printf(" W bishop found %d\n", square); + *bitboardArray[WB] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'R': + //printf(" WR found\n"); + *bitboardArray[WR] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'P': + //printf(" add white pawn %d\n", square); + *bitboardArray[WP] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'Q': + //printf(" WQ found\n"); + *bitboardArray[WQ] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'K': + //printf(" WK\n"); + *bitboardArray[WK] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'N': + //printf(" WN found\n"); + *bitboardArray[WN] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'b': + //printf(" BB found\n"); + *bitboardArray[BB] |= SQUARE_BBS[square]; + squareCount++; + break; + + case 'p': + //printf(" BP sq: %d\n", square); + *bitboardArray[BP] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'q': + //printf(" BQ sq: %d\n", square); + *bitboardArray[BQ] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'r': + //printf(" BR sq: %d\n", square); + *bitboardArray[BR] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'n': + //printf(" BN sq: %d\n", square); + *bitboardArray[BN] |= SQUARE_BBS[square]; + squareCount++; + break; + case 'k': + //printf(" BK sq: %d\n", square); + *bitboardArray[BK] |= SQUARE_BBS[square]; + squareCount++; + break; + + case '/': + //printf(" forward bracket slash\n", square); + squareCount = 0; + bracketCount++; + break; + case '1': + //printf(" 1 found\n"); + squareCount += 1; + break; + case '2': + //printf(" 2 found\n"); + squareCount += 2; + break; + case '3': + //printf(" 3 found\n"); + squareCount += 3; + break; + case '4': + //printf(" 4 found\n"); + squareCount += 4; + break; + case '5': + //printf(" 5 found\n"); + squareCount += 5; + break; + case '6': + //printf(" 6 found\n"); + squareCount += 6; + break; + case '7': + //printf(" 7 found\n"); + squareCount += 7; + break; + case '8': + //printf(" 8 found\n"); + squareCount += 8; + break; + } + } + break; + case 1: + if (characterInFen == 'w') + { + *isWhite = true; + } + else if (characterInFen == 'b') + { + *isWhite = false; + } + else if (characterInFen == ' ') + { + currentPhase++; + } + break; + case 2: + switch (characterInFen) + { + case 'K': + *castleRights[0] = true; + break; + case 'Q': + *castleRights[1] = true; + break; + case 'k': + *castleRights[2] = true; + break; + case 'q': + *castleRights[3] = true; + break; + case '-': + + break; + case ' ': + currentPhase++; + break; + } + break; + case 3: + if (characterInFen == ' ') + { + if (epX != -1) + { + if (epY != -1) + { + *ep = (epY * 8) + epX; + } + } + currentPhase++; + } + else + { + switch (characterInFen) + { + case 'a': + epX = 0; + break; + case 'b': + epX = 1; + break; + case 'c': + epX = 2; + break; + case 'd': + epX = 3; + break; + case 'e': + epX = 4; + break; + case 'f': + epX = 5; + break; + case 'g': + epX = 6; + break; + case 'h': + epX = 7; + break; + case '1': + epY = 7; + break; + case '2': + epY = 6; + break; + case '3': + epY = 5; + break; + case '4': + epY = 4; + break; + case '5': + epY = 3; + break; + case '6': + epY = 2; + break; + case '7': + epY = 1; + break; + case '8': + epY = 0; + break; + } + } + break; + case 4: + break; + case 5: + break; + } + } +} + + +unsigned long long PerftInlineGlobal(const int depth, const int ply) +{ + //if (depth == 0) + //{ + // return 1; + //} + + int move_list[250][4]; + int move_count = 0; + + //Move generating variables + const unsigned long long WHITE_OCCUPANCIES_LOCAL = bitboard_array_global[0] | bitboard_array_global[1] | bitboard_array_global[2] | bitboard_array_global[3] | bitboard_array_global[4] | bitboard_array_global[5]; + const unsigned long long BLACK_OCCUPANCIES_LOCAL = bitboard_array_global[6] | bitboard_array_global[7] | bitboard_array_global[8] | bitboard_array_global[9] | bitboard_array_global[10] | bitboard_array_global[11]; + const unsigned long long COMBINED_OCCUPANCIES_LOCAL = WHITE_OCCUPANCIES_LOCAL | BLACK_OCCUPANCIES_LOCAL; + const unsigned long long EMPTY_OCCUPANCIES = ~COMBINED_OCCUPANCIES_LOCAL; + unsigned long long temp_bitboard, check_bitboard = 0ULL, temp_pin_bitboard, temp_attack, temp_empty, temp_captures; + int starting_square = NO_SQUARE, target_square = NO_SQUARE; + + int pinArray[8][2] = + { + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + }; + + int pinNumber = 0; + +#pragma region Generate Moves + + if (is_white_global == true) + { + int whiteKingCheckCount = 0; + const int whiteKingPosition = BitscanForward(bitboard_array_global[WK]); + +#pragma region pins and check + + //pawns + temp_bitboard = bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[whiteKingPosition]; + if (temp_bitboard != 0) + { + const int pawn_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + + if (check_bitboard == 0) + { + check_bitboard = 1ULL << pawn_square; + } + + whiteKingCheckCount++; + } + + //knights + temp_bitboard = bitboard_array_global[BN] & KNIGHT_ATTACKS[whiteKingPosition]; + if (temp_bitboard != 0) + { + const int knight_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + + if (check_bitboard == 0) + { + check_bitboard = SQUARE_BBS[knight_square]; + } + + whiteKingCheckCount++; + } + + //bishops + const unsigned long long bishopAttacksChecks = GetBishopAttacksFast(whiteKingPosition, BLACK_OCCUPANCIES_LOCAL); + temp_bitboard = bitboard_array_global[BB] & bishopAttacksChecks; + while (temp_bitboard != 0) + { + const int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_pin_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL; + + if (temp_pin_bitboard == 0) + { + if (check_bitboard == 0) + { + check_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square]; + } + whiteKingCheckCount++; + } + else + { + const int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); + temp_pin_bitboard &= temp_pin_bitboard - 1; + + if (temp_pin_bitboard == 0) + { + pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; + pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; + pinNumber++; + } + } + temp_bitboard &= temp_bitboard - 1; + } + + //queen + temp_bitboard = bitboard_array_global[BQ] & bishopAttacksChecks; + while (temp_bitboard != 0) + { + const int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_pin_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL; + + if (temp_pin_bitboard == 0) + { + if (check_bitboard == 0) + { + check_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square]; + } + whiteKingCheckCount++; + } + else + { + const int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); + temp_pin_bitboard &= temp_pin_bitboard - 1; + + if (temp_pin_bitboard == 0) + { + pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; + pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; + pinNumber++; + } + } + temp_bitboard &= temp_bitboard - 1; + } + + //rook + const unsigned long long rook_attacks = GetRookAttacksFast(whiteKingPosition, BLACK_OCCUPANCIES_LOCAL); + temp_bitboard = bitboard_array_global[BR] & rook_attacks; + while (temp_bitboard != 0) + { + const int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_pin_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL; + + if (temp_pin_bitboard == 0) + { + if (check_bitboard == 0) + { + check_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square]; + } + whiteKingCheckCount++; + } + else + { + const int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); + temp_pin_bitboard &= temp_pin_bitboard - 1; + + if (temp_pin_bitboard == 0) + { + pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; + pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; + pinNumber++; + } + } + temp_bitboard &= temp_bitboard - 1; + } + + //queen + temp_bitboard = bitboard_array_global[BQ] & rook_attacks; + while (temp_bitboard != 0) + { + const int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_pin_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL; + + if (temp_pin_bitboard == 0) + { + if (check_bitboard == 0) + { + check_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square]; + } + whiteKingCheckCount++; + } + else + { + const int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); + temp_pin_bitboard &= temp_pin_bitboard - 1; + + if (temp_pin_bitboard == 0) + { + pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; + pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; + pinNumber++; + } + } + temp_bitboard &= temp_bitboard - 1; + } + +#pragma endregion + + if (whiteKingCheckCount > 1) + { +#pragma region White king + const unsigned long long occupanciesWithoutWhiteKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[WK]); + temp_attack = KING_ATTACKS[whiteKingPosition]; + temp_empty = temp_attack & EMPTY_OCCUPANCIES; + while (temp_empty != 0) + { + target_square = BitscanForward(temp_empty); + temp_empty &= temp_empty - 1; + + if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[BK] & KING_ATTACKS[target_square]) != 0) + { + continue; + } + unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing); + if ((bitboard_array_global[BB] & bishopAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[BQ] & bishopAttacks) != 0) + { + continue; + } + unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing); + if ((bitboard_array_global[BR] & rookAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[BQ] & rookAttacks) != 0) + { + continue; + } + + move_list[move_count][MOVE_STARTING] = whiteKingPosition; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = WK; + move_count++; + } + + //captures + temp_captures = temp_attack & BLACK_OCCUPANCIES_LOCAL; + while (temp_captures != 0) + { + target_square = BitscanForward(temp_captures); + temp_captures &= temp_captures - 1; + + if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[BK] & KING_ATTACKS[target_square]) != 0) + { + continue; + } + const unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing); + if ((bitboard_array_global[BB] & bishopAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[BQ] & bishopAttacks) != 0) + { + continue; + } + const unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing); + if ((bitboard_array_global[BR] & rookAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[BQ] & rookAttacks) != 0) + { + continue; + } + + move_list[move_count][MOVE_STARTING] = whiteKingPosition; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = WK; + move_count++; + } + +#pragma endregion + } + else + { + + if (whiteKingCheckCount == 0) + { + check_bitboard = MAX_ULONG; + } + +#pragma region White king + const unsigned long long occupanciesWithoutWhiteKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[WK]); + temp_attack = KING_ATTACKS[whiteKingPosition]; + temp_empty = temp_attack & EMPTY_OCCUPANCIES; + while (temp_empty != 0) + { + target_square = BitscanForward(temp_empty); + temp_empty &= temp_empty - 1; + + if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[BK] & KING_ATTACKS[target_square]) != 0) + { + continue; + } + unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing); + if ((bitboard_array_global[BB] & bishopAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[BQ] & bishopAttacks) != 0) + { + continue; + } + unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing); + if ((bitboard_array_global[BR] & rookAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[BQ] & rookAttacks) != 0) + { + continue; + } + + move_list[move_count][MOVE_STARTING] = whiteKingPosition; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = WK; + move_count++; + } + + //captures + temp_captures = temp_attack & BLACK_OCCUPANCIES_LOCAL; + while (temp_captures != 0) + { + target_square = BitscanForward(temp_captures); + temp_captures &= temp_captures - 1; + + if ((bitboard_array_global[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[BN] & KNIGHT_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[BK] & KING_ATTACKS[target_square]) != 0) + { + continue; + } + unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing); + if ((bitboard_array_global[BB] & bishopAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[BQ] & bishopAttacks) != 0) + { + continue; + } + unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing); + if ((bitboard_array_global[BR] & rookAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[BQ] & rookAttacks) != 0) + { + continue; + } + + move_list[move_count][MOVE_STARTING] = whiteKingPosition; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = WK; + move_count++; + } + + if (whiteKingCheckCount == 0) + { + if (castle_rights_global[WKS_CASTLE_RIGHTS] == true) + { + if (whiteKingPosition == E1) //king on e1 + { + if ((WKS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty + { + if ((bitboard_array_global[WR] & SQUARE_BBS[H1]) != 0) //rook on h1 + { + if (Is_Square_Attacked_By_Black_Global(F1, COMBINED_OCCUPANCIES_LOCAL) == false) + { + if (Is_Square_Attacked_By_Black_Global(G1, COMBINED_OCCUPANCIES_LOCAL) == false) + { + move_list[move_count][MOVE_STARTING] = E1; + move_list[move_count][MOVE_TARGET] = G1; + move_list[move_count][MOVE_TAG] = TAG_WCASTLEKS; + move_list[move_count][MOVE_PIECE] = WK; + move_count++; + } + } + } + } + } + } + if (castle_rights_global[WQS_CASTLE_RIGHTS] == true) + { + if (whiteKingPosition == E1) //king on e1 + { + if ((WQS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty + { + if ((bitboard_array_global[WR] & SQUARE_BBS[A1]) != 0) //rook on h1 + { + if (Is_Square_Attacked_By_Black_Global(C1, COMBINED_OCCUPANCIES_LOCAL) == false) + { + if (Is_Square_Attacked_By_Black_Global(D1, COMBINED_OCCUPANCIES_LOCAL) == false) + { + move_list[move_count][MOVE_STARTING] = E1; + move_list[move_count][MOVE_TARGET] = C1; + move_list[move_count][MOVE_TAG] = TAG_WCASTLEQS; + move_list[move_count][MOVE_PIECE] = WK; + move_count++; + } + } + } + } + } + } + } + +#pragma endregion + +#pragma region White knight + + temp_bitboard = bitboard_array_global[WN]; + + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_bitboard &= temp_bitboard - 1; //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 = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + + temp_attack = ((KNIGHT_ATTACKS[starting_square] & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; //gets knight captures + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = WN; + move_count++; + } + + temp_attack = ((KNIGHT_ATTACKS[starting_square] & EMPTY_OCCUPANCIES) & check_bitboard) & temp_pin_bitboard; + + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = WN; + move_count++; + } + } +#pragma endregion + +#pragma region White pawn + + temp_bitboard = bitboard_array_global[WP]; + + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_bitboard &= temp_bitboard - 1; + + 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 = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + +#pragma region Pawn forward + + if ((SQUARE_BBS[starting_square - 8] & COMBINED_OCCUPANCIES_LOCAL) == 0) //if up one square is empty + { + if (((SQUARE_BBS[starting_square - 8] & check_bitboard) & temp_pin_bitboard) != 0) + { + if ((SQUARE_BBS[starting_square] & RANK_7_BITBOARD) != 0) //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] = TAG_WQueenPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_WRookPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_WBishopPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_WKnightPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = WP; + move_count++; + } + } + + if ((SQUARE_BBS[starting_square] & RANK_2_BITBOARD) != 0) //if on rank 2 + { + if (((SQUARE_BBS[starting_square - 16] & check_bitboard) & temp_pin_bitboard) != 0) //if not pinned or + { + if (((SQUARE_BBS[starting_square - 16]) & COMBINED_OCCUPANCIES_LOCAL) == 0) //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] = TAG_DoublePawnWhite; + move_list[move_count][MOVE_PIECE] = WP; + move_count++; + } + } + } + } + +#pragma endregion + +#pragma region Pawn captures + + temp_attack = ((WHITE_PAWN_ATTACKS[starting_square] & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; //if black piece diagonal to pawn + + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + if ((SQUARE_BBS[starting_square] & RANK_7_BITBOARD) != 0) //if promotion + { + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_WCaptureQueenPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_WCaptureRookPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_WCaptureBishopPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_WCaptureKnightPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = WP; + move_count++; + } + } + + if ((SQUARE_BBS[starting_square] & RANK_5_BITBOARD) != 0) //check rank for ep + { + if (ep_global != NO_SQUARE) + { + if ((((WHITE_PAWN_ATTACKS[starting_square] & SQUARE_BBS[ep_global]) & check_bitboard) & temp_pin_bitboard) != 0) + { + if ((bitboard_array_global[WK] & RANK_5_BITBOARD) == 0) //if no king on rank 5 + { + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = ep_global; + move_list[move_count][MOVE_TAG] = TAG_WHITEEP; + move_list[move_count][MOVE_PIECE] = WP; + move_count++; + } + else if ((bitboard_array_global[BR] & RANK_5_BITBOARD) == 0 && (bitboard_array_global[BQ] & RANK_5_BITBOARD) == 0) // if no b rook or queen on rank 5 + { + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = ep_global; + move_list[move_count][MOVE_TAG] = TAG_WHITEEP; + move_list[move_count][MOVE_PIECE] = WP; + move_count++; + } + else //wk and br or bq on rank 5 + { + unsigned long long occupancyWithoutEPPawns = COMBINED_OCCUPANCIES_LOCAL & ~SQUARE_BBS[starting_square]; + occupancyWithoutEPPawns &= ~SQUARE_BBS[ep_global + 8]; + + const unsigned long long rookAttacksFromKing = GetRookAttacksFast(whiteKingPosition, occupancyWithoutEPPawns); + + if ((rookAttacksFromKing & bitboard_array_global[BR]) == 0) + { + if ((rookAttacksFromKing & bitboard_array_global[BQ]) == 0) + { + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = ep_global; + move_list[move_count][MOVE_TAG] = TAG_WHITEEP; + move_list[move_count][MOVE_PIECE] = WP; + move_count++; + } + } + } + } + } + } + +#pragma endregion + } + +#pragma endregion + +#pragma region White Rook + temp_bitboard = bitboard_array_global[WR]; + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_bitboard &= temp_bitboard - 1; + + 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 = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + + const unsigned long long rookAttacks = GetRookAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); + + temp_attack = ((rookAttacks & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = WR; + move_count++; + } + + temp_attack = ((rookAttacks & EMPTY_OCCUPANCIES) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = WR; + move_count++; + } + } +#pragma endregion + +#pragma region White bishop + temp_bitboard = bitboard_array_global[WB]; + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_bitboard &= temp_bitboard - 1; + + 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 = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + + unsigned long long bishopAttacks = GetBishopAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); + + temp_attack = ((bishopAttacks & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = WB; + move_count++; + } + + temp_attack = ((bishopAttacks & EMPTY_OCCUPANCIES) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = WB; + move_count++; + } + } +#pragma endregion + +#pragma region White Queen + temp_bitboard = bitboard_array_global[WQ]; + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_bitboard &= temp_bitboard - 1; + + 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 = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + + unsigned long long queenAttacks = GetRookAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); + queenAttacks |= GetBishopAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); + + temp_attack = ((queenAttacks & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; + + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = WQ; + move_count++; + } + + temp_attack = ((queenAttacks & EMPTY_OCCUPANCIES) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = WQ; + move_count++; + } + } +#pragma endregion + } + } + else //black move + { + int blackKingCheckCount = 0; + int blackKingPosition = (DEBRUIJN64[MAGIC * (bitboard_array_global[BK] ^ (bitboard_array_global[BK] - 1)) >> 58]); + +#pragma region pins and check + + //pawns + temp_bitboard = bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[blackKingPosition]; + if (temp_bitboard != 0) + { + const int pawn_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + + if (check_bitboard == 0) + { + check_bitboard = SQUARE_BBS[pawn_square]; + } + + blackKingCheckCount++; + } + + //knights + temp_bitboard = bitboard_array_global[WN] & KNIGHT_ATTACKS[blackKingPosition]; + if (temp_bitboard != 0) + { + int knight_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + + if (check_bitboard == 0) + { + check_bitboard = SQUARE_BBS[knight_square]; + } + + blackKingCheckCount++; + } + + //bishops + const unsigned long long bishopAttacksChecks = GetBishopAttacksFast(blackKingPosition, WHITE_OCCUPANCIES_LOCAL); + temp_bitboard = bitboard_array_global[WB] & bishopAttacksChecks; + while (temp_bitboard != 0) + { + int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_pin_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES_LOCAL; + + if (temp_pin_bitboard == 0) + { + if (check_bitboard == 0) + { + check_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square]; + } + blackKingCheckCount++; + } + else + { + int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); + temp_pin_bitboard &= temp_pin_bitboard - 1; + + if (temp_pin_bitboard == 0) + { + pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; + pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; + pinNumber++; + } + } + temp_bitboard &= temp_bitboard - 1; + } + + //queen + temp_bitboard = bitboard_array_global[WQ] & bishopAttacksChecks; + while (temp_bitboard != 0) + { + int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + + temp_pin_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES_LOCAL; + + if (temp_pin_bitboard == 0) + { + if (check_bitboard == 0) + { + check_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square]; + } + blackKingCheckCount++; + } + else + { + int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); + temp_pin_bitboard &= temp_pin_bitboard - 1; + + if (temp_pin_bitboard == 0) + { + pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; + pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; + pinNumber++; + } + } + temp_bitboard &= temp_bitboard - 1; + } + + //rook + unsigned long long rook_attacks = GetRookAttacksFast(blackKingPosition, WHITE_OCCUPANCIES_LOCAL); + temp_bitboard = bitboard_array_global[WR] & rook_attacks; + while (temp_bitboard != 0) + { + int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_pin_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES_LOCAL; + + if (temp_pin_bitboard == 0) + { + if (check_bitboard == 0) + { + check_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square]; + } + blackKingCheckCount++; + } + else + { + int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); + temp_pin_bitboard &= temp_pin_bitboard - 1; + + if (temp_pin_bitboard == 0) + { + pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; + pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; + pinNumber++; + } + } + temp_bitboard &= temp_bitboard - 1; + } + + //queen + temp_bitboard = bitboard_array_global[WQ] & rook_attacks; + while (temp_bitboard != 0) + { + int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_pin_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square] & BLACK_OCCUPANCIES_LOCAL; + + if (temp_pin_bitboard == 0) + { + if (check_bitboard == 0) + { + check_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square]; + } + blackKingCheckCount++; + } + else + { + int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); + temp_pin_bitboard &= temp_pin_bitboard - 1; + + if (temp_pin_bitboard == 0) + { + pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; + pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; + pinNumber++; + } + } + temp_bitboard &= temp_bitboard - 1; + } + +#pragma endregion + + if (blackKingCheckCount > 1) + { +#pragma region Black king + const unsigned long long occupancyWithoutBlackKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[BK]); + temp_attack = KING_ATTACKS[blackKingPosition] & WHITE_OCCUPANCIES_LOCAL; + + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + if ((bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[WK] & KING_ATTACKS[target_square]) != 0) + { + continue; + } + unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing); + if ((bitboard_array_global[WB] & bishopAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[WQ] & bishopAttacks) != 0) + { + continue; + } + unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing); + if ((bitboard_array_global[WR] & rookAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[WQ] & rookAttacks) != 0) + { + continue; + } + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = BK; + move_count++; + } + + temp_attack = KING_ATTACKS[blackKingPosition] & ~COMBINED_OCCUPANCIES_LOCAL; + + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + if ((bitboard_array_global[WP] & WHITE_PAWN_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[WK] & KING_ATTACKS[target_square]) != 0) + { + continue; + } + unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing); + if ((bitboard_array_global[WB] & bishopAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[WQ] & bishopAttacks) != 0) + { + continue; + } + unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing); + if ((bitboard_array_global[WR] & rookAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[WQ] & rookAttacks) != 0) + { + continue; + } + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = BK; + move_count++; + } +#pragma endregion + } + else + { + if (blackKingCheckCount == 0) + { + check_bitboard = MAX_ULONG; + } + +#pragma region Black pawns + + temp_bitboard = bitboard_array_global[BP]; + + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_bitboard &= temp_bitboard - 1; + + 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 = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + +#pragma region Pawn forward + + if ((SQUARE_BBS[starting_square + 8] & COMBINED_OCCUPANCIES_LOCAL) == 0) //if up one square is empty + { + if (((SQUARE_BBS[starting_square + 8] & check_bitboard) & temp_pin_bitboard) != 0) + { + if ((SQUARE_BBS[starting_square] & RANK_2_BITBOARD) != 0) //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] = TAG_BBishopPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_BKnightPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_BRookPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_BQueenPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = BP; + move_count++; + } + } + + if ((SQUARE_BBS[starting_square] & RANK_7_BITBOARD) != 0) //if on rank 2 + { + if (((SQUARE_BBS[starting_square + 16] & check_bitboard) & temp_pin_bitboard) != 0) + { + if (((SQUARE_BBS[starting_square + 16]) & COMBINED_OCCUPANCIES_LOCAL) == 0) //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] = TAG_DoublePawnBlack; + move_list[move_count][MOVE_PIECE] = BP; + move_count++; + } + } + } + } + +#pragma endregion + +#pragma region region Pawn captures + + temp_attack = ((BLACK_PAWN_ATTACKS[starting_square] & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; //if black piece diagonal to pawn + + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); //find the bit + temp_attack &= temp_attack - 1; + + if ((SQUARE_BBS[starting_square] & RANK_2_BITBOARD) != 0) //if promotion + { + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_BCaptureQueenPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_BCaptureRookPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_BCaptureKnightPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_BCaptureBishopPromotion; + move_list[move_count][MOVE_PIECE] = 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] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = BP; + move_count++; + } + } + + if ((SQUARE_BBS[starting_square] & RANK_4_BITBOARD) != 0) //check rank for ep + { + if (ep_global != NO_SQUARE) + { + if ((((BLACK_PAWN_ATTACKS[starting_square] & SQUARE_BBS[ep_global]) & check_bitboard) & temp_pin_bitboard) != 0) + { + if ((bitboard_array_global[BK] & RANK_4_BITBOARD) == 0) //if no king on rank 5 + { + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = ep_global; + move_list[move_count][MOVE_TAG] = TAG_BLACKEP; + move_list[move_count][MOVE_PIECE] = BP; + move_count++; + } + else if ((bitboard_array_global[WR] & RANK_4_BITBOARD) == 0 && (bitboard_array_global[WQ] & RANK_4_BITBOARD) == 0) // if no b rook or queen on rank 5 + { + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = ep_global; + move_list[move_count][MOVE_TAG] = TAG_BLACKEP; + move_list[move_count][MOVE_PIECE] = BP; + move_count++; + } + else //wk and br or bq on rank 5 + { + unsigned long long occupancyWithoutEPPawns = COMBINED_OCCUPANCIES_LOCAL & ~SQUARE_BBS[starting_square]; + occupancyWithoutEPPawns &= ~SQUARE_BBS[ep_global - 8]; + + unsigned long long rookAttacksFromKing = GetRookAttacksFast(blackKingPosition, occupancyWithoutEPPawns); + + if ((rookAttacksFromKing & bitboard_array_global[WR]) == 0) + { + if ((rookAttacksFromKing & bitboard_array_global[WQ]) == 0) + { + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = ep_global; + move_list[move_count][MOVE_TAG] = TAG_BLACKEP; + move_list[move_count][MOVE_PIECE] = BP; + move_count++; + } + } + } + } + } + } + +#pragma endregion + } +#pragma endregion + +#pragma region black Knight + temp_bitboard = bitboard_array_global[BN]; + + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); //looks for the startingSquare + temp_bitboard &= temp_bitboard - 1; //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 = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + + temp_attack = ((KNIGHT_ATTACKS[starting_square] & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; //gets knight captures + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = BN; + move_count++; + } + + temp_attack = ((KNIGHT_ATTACKS[starting_square] & (~COMBINED_OCCUPANCIES_LOCAL)) & check_bitboard) & temp_pin_bitboard; + + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = BN; + move_count++; + } + } +#pragma endregion + +#pragma region Black bishop + temp_bitboard = bitboard_array_global[BB]; + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_bitboard &= temp_bitboard - 1; + + 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 = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + + const unsigned long long bishopAttacks = GetBishopAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); + + temp_attack = ((bishopAttacks & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = BB; + move_count++; + } + + temp_attack = ((bishopAttacks & (~COMBINED_OCCUPANCIES_LOCAL)) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = BB; + move_count++; + } + } +#pragma endregion + +#pragma region Black Rook + temp_bitboard = bitboard_array_global[BR]; + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_bitboard &= temp_bitboard - 1; + + 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 = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + + unsigned long long rookAttacks = GetRookAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); + + temp_attack = ((rookAttacks & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = BR; + move_count++; + } + + temp_attack = ((rookAttacks & (~COMBINED_OCCUPANCIES_LOCAL)) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = BR; + move_count++; + } + } +#pragma endregion + +#pragma region Black queen + + temp_bitboard = bitboard_array_global[BQ]; + while (temp_bitboard != 0) + { + starting_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); + temp_bitboard &= temp_bitboard - 1; + + 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 = INBETWEEN_BITBOARDS[blackKingPosition][pinArray[i][PINNING_PIECE_INDEX]]; + } + } + } + + unsigned long long queenAttacks = GetRookAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); + queenAttacks |= GetBishopAttacksFast(starting_square, COMBINED_OCCUPANCIES_LOCAL); + + temp_attack = ((queenAttacks & WHITE_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard; + + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = BQ; + move_count++; + } + + temp_attack = ((queenAttacks & (~COMBINED_OCCUPANCIES_LOCAL)) & check_bitboard) & temp_pin_bitboard; + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + move_list[move_count][MOVE_STARTING] = starting_square; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = BQ; + move_count++; + } + } +#pragma endregion + +#pragma region Black King + + temp_attack = KING_ATTACKS[blackKingPosition] & WHITE_OCCUPANCIES_LOCAL; //gets knight captures + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + if ((bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[WK] & KING_ATTACKS[target_square]) != 0) + { + continue; + } + const unsigned long long occupancyWithoutBlackKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[BK]); + const unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing); + if ((bitboard_array_global[WB] & bishopAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[WQ] & bishopAttacks) != 0) + { + continue; + } + const unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing); + if ((bitboard_array_global[WR] & rookAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[WQ] & rookAttacks) != 0) + { + continue; + } + + move_list[move_count][MOVE_STARTING] = blackKingPosition; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_CAPTURE; + move_list[move_count][MOVE_PIECE] = BK; + move_count++; + } + + temp_attack = KING_ATTACKS[blackKingPosition] & (~COMBINED_OCCUPANCIES_LOCAL); //get knight moves to emtpy squares + + while (temp_attack != 0) + { + target_square = (DEBRUIJN64[MAGIC * (temp_attack ^ (temp_attack - 1)) >> 58]); + temp_attack &= temp_attack - 1; + + if ((bitboard_array_global[WP] & BLACK_PAWN_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[WN] & KNIGHT_ATTACKS[target_square]) != 0) + { + continue; + } + if ((bitboard_array_global[WK] & KING_ATTACKS[target_square]) != 0) + { + continue; + } + const unsigned long long occupancyWithoutBlackKing = COMBINED_OCCUPANCIES_LOCAL & (~bitboard_array_global[BK]); + const unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing); + if ((bitboard_array_global[WB] & bishopAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[WQ] & bishopAttacks) != 0) + { + continue; + } + const unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing); + if ((bitboard_array_global[WR] & rookAttacks) != 0) + { + continue; + } + if ((bitboard_array_global[WQ] & rookAttacks) != 0) + { + continue; + } + + move_list[move_count][MOVE_STARTING] = blackKingPosition; + move_list[move_count][MOVE_TARGET] = target_square; + move_list[move_count][MOVE_TAG] = TAG_NONE; + move_list[move_count][MOVE_PIECE] = BK; + move_count++; + } + } + if (blackKingCheckCount == 0) + { + if (castle_rights_global[BKS_CASTLE_RIGHTS] == true) + { + if (blackKingPosition == E8) //king on e1 + { + if ((BKS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty + { + if ((bitboard_array_global[BR] & SQUARE_BBS[H8]) != 0) //rook on h1 + { + if (Is_Square_Attacked_By_White_Global(F8, COMBINED_OCCUPANCIES_LOCAL) == false) + { + if (Is_Square_Attacked_By_White_Global(G8, COMBINED_OCCUPANCIES_LOCAL) == false) + { + move_list[move_count][MOVE_STARTING] = E8; + move_list[move_count][MOVE_TARGET] = G8; + move_list[move_count][MOVE_TAG] = TAG_BCASTLEKS; + move_list[move_count][MOVE_PIECE] = BK; + move_count++; + } + } + } + } + } + } + if (castle_rights_global[BQS_CASTLE_RIGHTS] == true) + { + if (blackKingPosition == E8) //king on e1 + { + if ((BQS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty + { + if ((bitboard_array_global[BR] & SQUARE_BBS[A8]) != 0) //rook on h1 + { + if (Is_Square_Attacked_By_White_Global(C8, COMBINED_OCCUPANCIES_LOCAL) == false) + { + if (Is_Square_Attacked_By_White_Global(D8, COMBINED_OCCUPANCIES_LOCAL) == false) + { + move_list[move_count][MOVE_STARTING] = E8; + move_list[move_count][MOVE_TARGET] = C8; + move_list[move_count][MOVE_TAG] = TAG_BCASTLEQS; + move_list[move_count][MOVE_PIECE] = BK; + move_count++; + } + } + } + } + } + } +#pragma endregion + } + } + +#pragma endregion + + if (depth == 1) + { + return move_count; + } + + unsigned long long nodes = 0;// , priorNodes; + int copyEp = ep_global; + bool copy_castle[4]; + copy_castle[0] = castle_rights_global[0]; + copy_castle[1] = castle_rights_global[1]; + copy_castle[2] = castle_rights_global[2]; + copy_castle[3] = castle_rights_global[3]; + + for (size_t move_index = 0; move_index < move_count; ++move_index) + { + const int startingSquare = move_list[move_index][MOVE_STARTING]; + const int targetSquare = move_list[move_index][MOVE_TARGET]; + const int piece = move_list[move_index][MOVE_PIECE]; + const int tag = move_list[move_index][MOVE_TAG]; + + int captureIndex = -1; + +#pragma region Makemove + + is_white_global = !is_white_global; + switch (tag) + { + case TAG_NONE: //none + case TAG_CHECK: //check + bitboard_array_global[piece] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + break; + case TAG_CAPTURE: //capture + case TAG_CHECK_CAPTURE: //check cap + bitboard_array_global[piece] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + if (PieceIsWhite(piece) == true) + { + for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + + } + else //is black + { + for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + } + + ep_global = NO_SQUARE; + break; + case TAG_WHITEEP: //white ep + //move piece + bitboard_array_global[WP] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[WP] &= ~SQUARE_BBS[startingSquare]; + //remove + bitboard_array_global[BP] &= ~SQUARE_BBS[targetSquare + 8]; + ep_global = NO_SQUARE; + break; + case TAG_BLACKEP: //black ep + //move piece + bitboard_array_global[BP] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[BP] &= ~SQUARE_BBS[startingSquare]; + //remove white pawn square up + bitboard_array_global[WP] &= ~SQUARE_BBS[targetSquare - 8]; + ep_global = NO_SQUARE; + break; + +#pragma region Castling + + case TAG_WCASTLEKS: //WKS + //white king + bitboard_array_global[WK] |= SQUARE_BBS[G1]; + bitboard_array_global[WK] &= ~SQUARE_BBS[E1]; + //white rook + bitboard_array_global[WR] |= SQUARE_BBS[F1]; + bitboard_array_global[WR] &= ~SQUARE_BBS[H1]; + castle_rights_global[WKS_CASTLE_RIGHTS] = false; + castle_rights_global[WQS_CASTLE_RIGHTS] = false; + ep_global = NO_SQUARE; + break; + case TAG_WCASTLEQS: //WQS + //white king + bitboard_array_global[WK] |= SQUARE_BBS[C1]; + bitboard_array_global[WK] &= ~SQUARE_BBS[E1]; + //white rook + bitboard_array_global[WR] |= SQUARE_BBS[D1]; + bitboard_array_global[WR] &= ~SQUARE_BBS[A1]; + castle_rights_global[WKS_CASTLE_RIGHTS] = false; + castle_rights_global[WQS_CASTLE_RIGHTS] = false; + ep_global = NO_SQUARE; + break; + case TAG_BCASTLEKS: //BKS + //white king + bitboard_array_global[BK] |= SQUARE_BBS[G8]; + bitboard_array_global[BK] &= ~SQUARE_BBS[E8]; + //white rook + bitboard_array_global[BR] |= SQUARE_BBS[F8]; + bitboard_array_global[BR] &= ~SQUARE_BBS[H8]; + + castle_rights_global[BKS_CASTLE_RIGHTS] = false; + castle_rights_global[BQS_CASTLE_RIGHTS] = false; + ep_global = NO_SQUARE; + break; + case TAG_BCASTLEQS: //BQS + //white king + bitboard_array_global[BK] |= SQUARE_BBS[C8]; + bitboard_array_global[BK] &= ~SQUARE_BBS[E8]; + //white rook + bitboard_array_global[BR] |= SQUARE_BBS[D8]; + bitboard_array_global[BR] &= ~SQUARE_BBS[A8]; + castle_rights_global[BKS_CASTLE_RIGHTS] = false; + castle_rights_global[BQS_CASTLE_RIGHTS] = false; + ep_global = NO_SQUARE; + break; + +#pragma endregion + +#pragma region Promotion makemove + + case TAG_BKnightPromotion: //BNPr + bitboard_array_global[BN] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + break; + case TAG_BBishopPromotion: //BBPr + bitboard_array_global[BB] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + break; + case TAG_BQueenPromotion: //BQPr + bitboard_array_global[BQ] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + break; + case TAG_BRookPromotion: //BRPr + bitboard_array_global[BR] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + break; + case 12: //WNPr + bitboard_array_global[WN] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + break; + case 13: //WBPr + bitboard_array_global[WB] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + break; + case 14: //WQPr + bitboard_array_global[WQ] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + break; + case 15: //WRPr + bitboard_array_global[WR] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + break; + case 16: //BNPrCAP + bitboard_array_global[BN] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + + break; + case 17: //BBPrCAP + bitboard_array_global[BB] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + + break; + case 18: //BQPrCAP + bitboard_array_global[BQ] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + + break; + case 19: //BRPrCAP + bitboard_array_global[BR] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + + break; + case 20: //WNPrCAP + bitboard_array_global[WN] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + + break; + case 21: //WBPrCAP + bitboard_array_global[WB] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + + break; + case 22: //WQPrCAP + bitboard_array_global[WQ] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + ep_global = NO_SQUARE; + for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + + break; + case 23: //WRPrCAP + bitboard_array_global[WR] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare]; + + ep_global = NO_SQUARE; + for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i) + { + if ((bitboard_array_global[i] & SQUARE_BBS[targetSquare]) != 0) + { + captureIndex = i; + break; + } + } + bitboard_array_global[captureIndex] &= ~SQUARE_BBS[targetSquare]; + break; + +#pragma endregion + + case 24: //WDouble + bitboard_array_global[WP] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[WP] &= ~SQUARE_BBS[startingSquare]; + ep_global = targetSquare + 8; + break; + case 25: //BDouble + bitboard_array_global[BP] |= SQUARE_BBS[targetSquare]; + bitboard_array_global[BP] &= ~SQUARE_BBS[startingSquare]; + ep_global = targetSquare - 8; + break; + } + + if (piece == WK) + { + castle_rights_global[WKS_CASTLE_RIGHTS] = false; + castle_rights_global[WQS_CASTLE_RIGHTS] = false; + } + else if (piece == BK) + { + castle_rights_global[BKS_CASTLE_RIGHTS] = false; + castle_rights_global[BQS_CASTLE_RIGHTS] = false; + } + else if (piece == WR) + { + if (castle_rights_global[WKS_CASTLE_RIGHTS] == true) + { + if ((bitboard_array_global[WR] & SQUARE_BBS[H1]) == 0) + { + castle_rights_global[WKS_CASTLE_RIGHTS] = false; + } + } + if (castle_rights_global[WQS_CASTLE_RIGHTS] == true) + { + if ((bitboard_array_global[WR] & SQUARE_BBS[A1]) == 0) + { + castle_rights_global[WQS_CASTLE_RIGHTS] = false; + } + } + } + else if (piece == BR) + { + if (castle_rights_global[BKS_CASTLE_RIGHTS] == true) + { + if ((bitboard_array_global[BR] & SQUARE_BBS[H8]) == 0) + { + castle_rights_global[BKS_CASTLE_RIGHTS] = false; + } + } + if (castle_rights_global[BQS_CASTLE_RIGHTS] == true) + { + if ((bitboard_array_global[BR] & SQUARE_BBS[A8]) == 0) + { + castle_rights_global[BQS_CASTLE_RIGHTS] = false; + } + } + } + +#pragma endregion + + //priorNodes = nodes; + nodes += PerftInlineGlobal(depth - 1, ply + 1); + +#pragma region Unmakemove + + is_white_global = !is_white_global; + switch (tag) + { + case TAG_NONE: //none + case TAG_CHECK: //check + bitboard_array_global[piece] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[targetSquare]; + + break; + case TAG_CAPTURE: //capture + case TAG_CHECK_CAPTURE: //check cap + bitboard_array_global[piece] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[piece] &= ~SQUARE_BBS[targetSquare]; + if (PieceIsWhite(piece) == true) + { + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + } + else //is black + { + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + } + + break; + case TAG_WHITEEP: //white ep + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WP] &= ~SQUARE_BBS[targetSquare]; + bitboard_array_global[BP] |= SQUARE_BBS[targetSquare + 8]; + + break; + case TAG_BLACKEP: //black ep + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BP] &= ~SQUARE_BBS[targetSquare]; + bitboard_array_global[WP] |= SQUARE_BBS[targetSquare - 8]; + + break; + case TAG_WCASTLEKS: //WKS + //white king + bitboard_array_global[WK] |= SQUARE_BBS[E1]; + bitboard_array_global[WK] &= ~SQUARE_BBS[G1]; + //white rook + bitboard_array_global[WR] |= SQUARE_BBS[H1]; + bitboard_array_global[WR] &= ~SQUARE_BBS[F1]; + break; + case TAG_WCASTLEQS: //WQS + //white king + bitboard_array_global[WK] |= SQUARE_BBS[E1]; + bitboard_array_global[WK] &= ~SQUARE_BBS[C1]; + //white rook + bitboard_array_global[WR] |= SQUARE_BBS[A1]; + bitboard_array_global[WR] &= ~SQUARE_BBS[D1]; + break; + case TAG_BCASTLEKS: //BKS + //white king + bitboard_array_global[BK] |= SQUARE_BBS[E8]; + bitboard_array_global[BK] &= ~SQUARE_BBS[G8]; + //white rook + bitboard_array_global[BR] |= SQUARE_BBS[H8]; + bitboard_array_global[BR] &= ~SQUARE_BBS[F8]; + break; + case TAG_BCASTLEQS: //BQS + //white king + bitboard_array_global[BK] |= SQUARE_BBS[E8]; + bitboard_array_global[BK] &= ~SQUARE_BBS[C8]; + //white rook + bitboard_array_global[BR] |= SQUARE_BBS[A8]; + bitboard_array_global[BR] &= ~SQUARE_BBS[D8]; + + break; + +#pragma region Promotion Unmakemove + case TAG_BKnightPromotion: //BNPr + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BN] &= ~SQUARE_BBS[targetSquare]; + break; + case TAG_BBishopPromotion: //BBPr + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BB] &= ~SQUARE_BBS[targetSquare]; + break; + case TAG_BQueenPromotion: //BQPr + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BQ] &= ~SQUARE_BBS[targetSquare]; + break; + case TAG_BRookPromotion: //BRPr + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BR] &= ~SQUARE_BBS[targetSquare]; + break; + case TAG_WKnightPromotion: //WNPr + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WN] &= ~SQUARE_BBS[targetSquare]; + break; + case TAG_WBishopPromotion: //WBPr + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WB] &= ~SQUARE_BBS[targetSquare]; + break; + case TAG_WQueenPromotion: //WQPr + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WQ] &= ~SQUARE_BBS[targetSquare]; + break; + case TAG_WRookPromotion: //WRPr + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WR] &= ~SQUARE_BBS[targetSquare]; + break; + case TAG_BCaptureKnightPromotion: //BNPrCAP + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BN] &= ~SQUARE_BBS[targetSquare]; + + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + break; + case TAG_BCaptureBishopPromotion: //BBPrCAP + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BB] &= ~SQUARE_BBS[targetSquare]; + + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + + break; + case TAG_BCaptureQueenPromotion: //BQPrCAP + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BQ] &= ~SQUARE_BBS[targetSquare]; + + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + break; + case TAG_BCaptureRookPromotion: //BRPrCAP + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BR] &= ~SQUARE_BBS[targetSquare]; + + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + break; + case TAG_WCaptureKnightPromotion: //WNPrCAP + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WN] &= ~SQUARE_BBS[targetSquare]; + + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + break; + case TAG_WCaptureBishopPromotion: //WBPrCAP + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WB] &= ~SQUARE_BBS[targetSquare]; + + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + break; + case TAG_WCaptureQueenPromotion: //WQPrCAP + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WQ] &= ~SQUARE_BBS[targetSquare]; + + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + break; + case TAG_WCaptureRookPromotion: //WRPrCAP + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WR] &= ~SQUARE_BBS[targetSquare]; + + bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare]; + break; + +#pragma endregion + + case TAG_DoublePawnWhite: //WDouble + bitboard_array_global[WP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[WP] &= ~SQUARE_BBS[targetSquare]; + break; + case TAG_DoublePawnBlack: //BDouble + bitboard_array_global[BP] |= SQUARE_BBS[startingSquare]; + bitboard_array_global[BP] &= ~SQUARE_BBS[targetSquare]; + break; + } + + castle_rights_global[0] = copy_castle[0]; + castle_rights_global[1] = copy_castle[1]; + castle_rights_global[2] = copy_castle[2]; + castle_rights_global[3] = copy_castle[3]; + ep_global = copyEp; + + //if (epGlobal != NO_SQUARE) + //{ + // std::cout << " ep: " << SQ_CHAR_X[epGlobal] << SQ_CHAR_Y[epGlobal] << '\n'; + //} + +#pragma endregion + +//if (ply == 0) +//{ + // PrintMoveNoNL(move_list[move_index]); + // printf(": %llu\n", nodes - priorNodes); +//} + } + + return nodes; +} + + +void RunPerftInlineGlobal(const int depth) +{ + CopyGlobalBoardGlobal(); + + clock_t start_time = clock(); // Get the initial time + + unsigned long long nodes = PerftInlineGlobal(depth, 0); + + clock_t end_time = clock(); + double elapsed_milliseconds = (double)(end_time - start_time) * 1000.0 / CLOCKS_PER_SEC; + printf("Nodes: %llu\n", nodes); + printf("Elapsed time: %.2f milliseconds\n", elapsed_milliseconds); +} + + +int main() +{ + CreateBoard(); + + //std::cin.get(); + ParseFenGlobal(FEN_STARTING_POSITION, 0); + RunPerftInlineGlobal(6); + + return 0; +}