#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; }