Files
Coding with Tom 8850bfa3c4 Update main.c
Removed unnecessary if statements and made move_list 50 elements
2025-01-20 16:46:38 +00:00

4987 lines
204 KiB
C

#include <stdio.h>
#include <time.h>
#include <string.h> // For strlen
#include <stdlib.h>
#include "Constants.h"
unsigned long long* bitboardArray[12];
unsigned long long* occupancies[3];
int* ep;
int* castleRights[4];
int* isWhite;
unsigned long long bitboard_array_global[12];
unsigned long long occupancies_global[3];
int ep_global;
int castle_rights_global[4];
int is_white_global;
const int TRUE = 0;
const int FALSE = 1;
const int WHITE_TO_PLAY = 0;
const int BLACK_TO_PLAY = 1;
inline int BitscanForward(const unsigned long long tempBitboard);
const unsigned long long MAGIC = 0x03f79d71b4cb0a89;
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
};
inline int BitscanForward(const unsigned long long tempBitboard)
{
return (DEBRUIJN64[MAGIC * (tempBitboard ^ (tempBitboard - 1)) >> 58]);
}
#pragma region Fen constants
//fens
const char* FEN_STARTING_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
const char* FEN_STARTING_POSITION_BLACK = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR b KQkq - 0 1";
const char* FEN_STARTING_POSITION_ONLY_PAWNS = "4k3/pppppppp/8/8/8/8/PPPPPPPP/4K3 w KQkq - 0 1";
const char* FEN_STARTING_POSITION_EP_E4 = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq e4 0 1";
const char* FEN_STARTING_POSITION_ONLY_KNIGHTS = "1n2k1n1/8/8/8/8/8/8/1N2K1N1 w - - 0 1";
const char* FEN_STARTING_POSITION_ONLY_KNIGHTS_BLACK = "1n2k1n1/8/8/8/8/8/8/1N2K1N1 b - - 0 1";
const char* FEN_TEST_KNIGHT_CAPTURES = "4k1n1/8/8/8/8/2n5/8/1N2K1N1 b - - 0 1";
const char* FEN_TEST_ONLY_KINGS = "8/8/3k4/8/3K4/8/8/8 w - - 0 1";
const char* FEN_TEST_ONLY_KNIGHTS = "8/8/3k4/8/3K4/8/8/8 w - - 0 1";
const char* FEN_TRICKY_WHITE = "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - ";
const char* FEN_TRICKY_BLACK = "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R b KQkq - ";
const char* FEN_TEST_EP = "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - ";
const char* FEN_SCHOLARS_MATE = "r1bqkb1r/pppp1ppp/2n2n2/4p2Q/2B1P3/8/PPPP1PPP/RNB1K1NR w KQkq - 4 4";
const char* FEN_FRIED_LIVER_BLACK = "r1bqkb1r/pppp1ppp/2n2n2/4p1N1/2B1P3/8/PPPP1PPP/RNBQK2R b KQkq - 5 4";
const char* FEN_FRIED_LIVER_WHITE = "r1bqkb1r/ppp2ppp/2np1n2/4p1N1/2B1P3/8/PPPP1PPP/RNBQK2R w KQkq - 0 5";
const char* FEN_KNIGHT_FORK = "rn1qk2r/pp3ppp/2p1pn2/6N1/8/1PP3P1/P4PBP/R2Q1RK1 w - - 0 1";
const char* FEN_MATE_0_TEST = "r1bqkb1r/pppp1Qpp/2n2n2/4p3/2B1P3/8/PPPP1PPP/RNB1K1NR b KQkq - 0 1";
const char* FEN_MATE_4_TEST = "r7/q6p/2k1p3/2N1Q3/1ppP4/P2b4/1P4PP/K2R4 b - - 0 1";
const char* FEN_BONGCLOUD = "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPPKPPP/RNBQ1BNR b kq - 1 2";
const char* FEN_PERPETUAL = "6k1/5pp1/6p1/8/8/3Q3P/5PP1/6K1 w - - 0 1";
const char* FEN_MATE_3 = "r4rk1/ppp1q1p1/2n2pP1/8/8/2N5/PPP1BQ2/2KR3R w - - 0 1";
const char* FEN_BLACK_DOUBLE_CHECK = "4k3/8/8/8/4N3/8/8/4R1K1 w - - 0 1";
#pragma endregion
#pragma region Constants
const int PINNED_SQUARE_INDEX = 0;
const int PINNING_PIECE_INDEX = 1;
//LSB
//equation: startingSquare = (DEBRUIJN64[MAGIC * (tempBitboard ^ (tempBitboard - 1)) >> 58]);
const unsigned long long MAX_ULONG = 18446744073709551615;
const int MOVE_STARTING = 0;
const int MOVE_TARGET = 1;
const int MOVE_PIECE = 2;
const int MOVE_TAG = 3;
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 char BLACK_PAWN_CHAR = 'p'; const char BLACK_KNIGHT_CHAR = 'n'; const char BLACK_BISHOP_CHAR = 'b'; const char BLACK_ROOK_CHAR = 'r'; const char BLACK_QUEEN_CHAR = 'q'; const char BLACK_KING_CHAR = 'k';
const char WHITE_PAWN_CHAR = 'P'; const char WHITE_KNIGHT_CHAR = 'N'; const char WHITE_BISHOP_CHAR = 'B'; const char WHITE_ROOK_CHAR = 'R'; const char WHITE_QUEEN_CHAR = 'Q'; const char WHITE_KING_CHAR = 'K'; const char DUCK_CHAR = 'D';
const char BRACKET_CHAR = '/'; const char SPACE_CHAR = ' '; const char DASH_CHAR = '-'; const char W_SIDE_CHAR = 'w'; const char B_SIDE_CHAR = 'b'; const char CAPITAL_K_CHAR = 'K'; const char CAPITAL_Q_CHAR = 'Q'; const char SMALL_K_CHAR = 'k'; const char SMALL_Q_CHAR = 'q';
const int BITBOARD_COUNT = 12;
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 unsigned long long RANK_1_BITBOARD = 18374686479671623680ULL;
const unsigned long long RANK_2_BITBOARD = 71776119061217280ULL;
const unsigned long long RANK_3_BITBOARD = 280375465082880ULL;
const unsigned long long RANK_4_BITBOARD = 1095216660480ULL;
const unsigned long long RANK_5_BITBOARD = 4278190080ULL;
const unsigned long long RANK_6_BITBOARD = 16711680ULL;
const unsigned long long RANK_7_BITBOARD = 65280ULL;
const unsigned long long RANK_8_BITBOARD = 255ULL;
const unsigned long long FILE_A_BITBOARD = 72340172838076673ULL;
const unsigned long long FILE_B_BITBOARD = 144680345676153346ULL;
const unsigned long long FILE_C_BITBOARD = 289360691352306692ULL;
const unsigned long long FILE_D_BITBOARD = 578721382704613384ULL;
const unsigned long long FILE_E_BITBOARD = 1157442765409226768ULL;
const unsigned long long FILE_F_BITBOARD = 2314885530818453536ULL;
const unsigned long long FILE_G_BITBOARD = 4629771061636907072ULL;
const unsigned long long FILE_H_BITBOARD = 9259542123273814144ULL;
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];
}
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];
}
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 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 int PROMOTION_START = TAG_BKnightPromotion;
const int PROMOTION_END_INCLUSIVE = TAG_WCaptureRookPromotion;
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 WKS_EMPTY_BITBOARD = 6917529027641081856ULL;
const unsigned long long WQS_EMPTY_BITBOARD = 1008806316530991104ULL;
const unsigned long long BKS_EMPTY_BITBOARD = 96ULL;
const unsigned long long BQS_EMPTY_BITBOARD = 14ULL;
const int COMBINED_OCCUPANCIES = 0;
const int WHITE_OCCUPANCIES = 1;
const int BLACK_OCCUPANCIES = 2;
typedef struct {
unsigned long long pieceArray[12];
int isWhite;
int ep;
int castleRights[4];
} Board;
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;
const char PIECE_COLOURS[12] = { 'W','W','W','W','W','W','b','b','b','b','b','b' };
const char PIECE_CHARS[12] = { 'P','N','B','R','Q','K','p','n','b','r','q','k' };
#pragma endregion
void CopyGlobalBoardGlobal()
{
for (size_t i = 0; i < 12; ++i)
{
bitboard_array_global[i] = *bitboardArray[i];
}
for (size_t i = 0; i < 3; ++i)
{
occupancies_global[i] = *occupancies[i];
}
for (size_t i = 0; i < 4; ++i)
{
castle_rights_global[i] = *castleRights[i];
}
ep_global = *ep;
is_white_global = *isWhite;
}
void CopyGlobalBoardStruct(Board* board)
{
for (size_t i = 0; i < 12; ++i)
{
board->pieceArray[i] = *bitboardArray[i];
}
for (size_t i = 0; i < 4; ++i)
{
board->castleRights[i] = *castleRights[i];
}
board->ep = *ep;
board->isWhite = *isWhite;
}
void ResetBoardGlobal()
{
*castleRights[0] = FALSE;
*castleRights[1] = FALSE;
*castleRights[2] = FALSE;
*castleRights[3] = FALSE;
for (size_t i = 0; i < BITBOARD_COUNT; i++)
{
*bitboardArray[i] = 0;
}
for (size_t i = 0; i < 3; i++)
{
*occupancies[i] = 0;
}
*isWhite = TRUE;
*ep = NO_SQUARE;
}
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];
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;
}
}
*occupancies[WHITE_OCCUPANCIES] = *bitboardArray[WP] | *bitboardArray[WN] | *bitboardArray[WB] | *bitboardArray[WR] | *bitboardArray[WQ] | *bitboardArray[WK];
*occupancies[BLACK_OCCUPANCIES] = *bitboardArray[BP] | *bitboardArray[BN] | *bitboardArray[BB] | *bitboardArray[BR] | *bitboardArray[BQ] | *bitboardArray[BK];
*occupancies[COMBINED_OCCUPANCIES] = *occupancies[WHITE_OCCUPANCIES] | *occupancies[BLACK_OCCUPANCIES];
}
void CreateBoard()
{
for (size_t i = 0; i < 12; ++i)
{
bitboardArray[i] = (unsigned long long*)malloc(sizeof(unsigned long long));
}
for (size_t i = 0; i < 3; ++i)
{
occupancies[i] = (unsigned long long*)malloc(sizeof(unsigned long long));
}
ep = (int*)malloc(sizeof(int));
isWhite = (int*)malloc(sizeof(int));
for (size_t i = 0; i < 4; ++i)
{
castleRights[i] = (int*)malloc(sizeof(int));
}
}
int 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;
}
int 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;
}
int OutOfBounds(const int move)
{
if (move < 0)
{
return TRUE;
}
if (move > 63)
{
return TRUE;
}
return FALSE;
}
void PrintMoveNoNL(const int move[])
{ //starting
if (OutOfBounds(move[MOVE_STARTING]) == TRUE)
{
printf("%d", move[MOVE_STARTING]);
}
else
{
printf("%c", SQ_CHAR_X[move[MOVE_STARTING]]);
printf("%c", SQ_CHAR_Y[move[MOVE_STARTING]]);
}
//target
if (OutOfBounds(move[MOVE_TARGET]) == TRUE)
{
printf("%d", move[MOVE_TARGET]);
}
else
{
printf("%c", SQ_CHAR_X[move[MOVE_TARGET]]);
printf("%c", SQ_CHAR_Y[move[MOVE_TARGET]]);
}
int tag = move[MOVE_TAG];
if (tag == TAG_BCaptureKnightPromotion || tag == TAG_BKnightPromotion || tag == TAG_WKnightPromotion || tag == TAG_WCaptureKnightPromotion)
{
printf("n");
}
else if (tag == TAG_BCaptureRookPromotion || tag == TAG_BRookPromotion || tag == TAG_WRookPromotion || tag == TAG_WCaptureRookPromotion)
{
printf("r");
}
else if (tag == TAG_BCaptureBishopPromotion || tag == TAG_BBishopPromotion || tag == TAG_WBishopPromotion || tag == TAG_WCaptureBishopPromotion)
{
printf("b");
}
else if (tag == TAG_BCaptureQueenPromotion || tag == TAG_BQueenPromotion || tag == TAG_WQueenPromotion || tag == TAG_WCaptureQueenPromotion)
{
printf("q");
}
}
unsigned long long PerftInlineStruct(Board *board, 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 = board->pieceArray[0] | board->pieceArray[1] | board->pieceArray[2] | board->pieceArray[3] | board->pieceArray[4] | board->pieceArray[5];
const unsigned long long BLACK_OCCUPANCIES_LOCAL = board->pieceArray[6] | board->pieceArray[7] | board->pieceArray[8] | board->pieceArray[9] | board->pieceArray[10] | board->pieceArray[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 (board->isWhite == TRUE)
{
int whiteKingCheckCount = 0;
const int whiteKingPosition = (DEBRUIJN64[MAGIC * (board->pieceArray[WK] ^ (board->pieceArray[WK] - 1)) >> 58]);
#pragma region pins and check
//pawns
temp_bitboard = board->pieceArray[BP] & WHITE_PAWN_ATTACKS[whiteKingPosition];
if (temp_bitboard != 0)
{
const int pawn_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]);
check_bitboard |= SQUARE_BBS[pawn_square];
whiteKingCheckCount++;
}
//knights
temp_bitboard = board->pieceArray[BN] & KNIGHT_ATTACKS[whiteKingPosition];
if (temp_bitboard != 0)
{
const int knight_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]);
check_bitboard |= SQUARE_BBS[knight_square];
whiteKingCheckCount++;
}
//bishops
const unsigned long long bishopAttacksChecks = GetBishopAttacksFast(whiteKingPosition, BLACK_OCCUPANCIES_LOCAL);
temp_bitboard = board->pieceArray[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)
{
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 = board->pieceArray[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)
{
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 = board->pieceArray[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)
{
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 = board->pieceArray[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)
{
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 & (~board->pieceArray[WK]);
temp_attack = KING_ATTACKS[whiteKingPosition];
temp_empty = temp_attack & EMPTY_OCCUPANCIES;
while (temp_empty != 0)
{
target_square = (DEBRUIJN64[MAGIC * (temp_empty ^ (temp_empty - 1)) >> 58]);
temp_empty &= temp_empty - 1;
if ((board->pieceArray[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[BN] & KNIGHT_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[BK] & KING_ATTACKS[target_square]) != 0)
{
continue;
}
unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing);
if ((board->pieceArray[BB] & bishopAttacks) != 0)
{
continue;
}
if ((board->pieceArray[BQ] & bishopAttacks) != 0)
{
continue;
}
unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing);
if ((board->pieceArray[BR] & rookAttacks) != 0)
{
continue;
}
if ((board->pieceArray[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 = (DEBRUIJN64[MAGIC * (temp_captures ^ (temp_captures - 1)) >> 58]);
temp_captures &= temp_captures - 1;
if ((board->pieceArray[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[BN] & KNIGHT_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[BK] & KING_ATTACKS[target_square]) != 0)
{
continue;
}
const unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing);
if ((board->pieceArray[BB] & bishopAttacks) != 0)
{
continue;
}
if ((board->pieceArray[BQ] & bishopAttacks) != 0)
{
continue;
}
const unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing);
if ((board->pieceArray[BR] & rookAttacks) != 0)
{
continue;
}
if ((board->pieceArray[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 & (~board->pieceArray[WK]);
temp_attack = KING_ATTACKS[whiteKingPosition];
temp_empty = temp_attack & EMPTY_OCCUPANCIES;
while (temp_empty != 0)
{
target_square = (DEBRUIJN64[MAGIC * (temp_empty ^ (temp_empty - 1)) >> 58]);
temp_empty &= temp_empty - 1;
if ((board->pieceArray[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[BN] & KNIGHT_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[BK] & KING_ATTACKS[target_square]) != 0)
{
continue;
}
unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing);
if ((board->pieceArray[BB] & bishopAttacks) != 0)
{
continue;
}
if ((board->pieceArray[BQ] & bishopAttacks) != 0)
{
continue;
}
unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing);
if ((board->pieceArray[BR] & rookAttacks) != 0)
{
continue;
}
if ((board->pieceArray[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 = (DEBRUIJN64[MAGIC * (temp_captures ^ (temp_captures - 1)) >> 58]);
temp_captures &= temp_captures - 1;
if ((board->pieceArray[BP] & WHITE_PAWN_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[BN] & KNIGHT_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[BK] & KING_ATTACKS[target_square]) != 0)
{
continue;
}
unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupanciesWithoutWhiteKing);
if ((board->pieceArray[BB] & bishopAttacks) != 0)
{
continue;
}
if ((board->pieceArray[BQ] & bishopAttacks) != 0)
{
continue;
}
unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupanciesWithoutWhiteKing);
if ((board->pieceArray[BR] & rookAttacks) != 0)
{
continue;
}
if ((board->pieceArray[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 (board->castleRights[WKS_CASTLE_RIGHTS] == TRUE)
{
if (whiteKingPosition == E1) //king on e1
{
if ((WKS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty
{
if ((board->pieceArray[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 (board->castleRights[WQS_CASTLE_RIGHTS] == TRUE)
{
if (whiteKingPosition == E1) //king on e1
{
if ((WQS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty
{
if ((board->pieceArray[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 = board->pieceArray[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 = board->pieceArray[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 (board->ep != NO_SQUARE)
{
if ((((WHITE_PAWN_ATTACKS[starting_square] & SQUARE_BBS[board->ep]) & check_bitboard) & temp_pin_bitboard) != 0)
{
if ((board->pieceArray[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] = board->ep;
move_list[move_count][MOVE_TAG] = TAG_WHITEEP;
move_list[move_count][MOVE_PIECE] = WP;
move_count++;
}
else if ((board->pieceArray[BR] & RANK_5_BITBOARD) == 0 && (board->pieceArray[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] = board->ep;
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[board->ep + 8];
const unsigned long long rookAttacksFromKing = GetRookAttacksFast(whiteKingPosition, occupancyWithoutEPPawns);
if ((rookAttacksFromKing & board->pieceArray[BR]) == 0)
{
if ((rookAttacksFromKing & board->pieceArray[BQ]) == 0)
{
move_list[move_count][MOVE_STARTING] = starting_square;
move_list[move_count][MOVE_TARGET] = board->ep;
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 = board->pieceArray[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 = board->pieceArray[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 = board->pieceArray[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 * (board->pieceArray[BK] ^ (board->pieceArray[BK] - 1)) >> 58]);
#pragma region pins and check
//pawns
temp_bitboard = board->pieceArray[WP] & BLACK_PAWN_ATTACKS[blackKingPosition];
if (temp_bitboard != 0)
{
const int pawn_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]);
check_bitboard |= SQUARE_BBS[pawn_square];
blackKingCheckCount++;
}
//knights
temp_bitboard = board->pieceArray[WN] & KNIGHT_ATTACKS[blackKingPosition];
if (temp_bitboard != 0)
{
const int knight_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]);
check_bitboard = SQUARE_BBS[knight_square];
blackKingCheckCount++;
}
//bishops
const unsigned long long bishopAttacksChecks = GetBishopAttacksFast(blackKingPosition, WHITE_OCCUPANCIES_LOCAL);
temp_bitboard = board->pieceArray[WB] & bishopAttacksChecks;
while (temp_bitboard != 0)
{
const 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)
{
check_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
blackKingCheckCount++;
}
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 = board->pieceArray[WQ] & bishopAttacksChecks;
while (temp_bitboard != 0)
{
const 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)
{
check_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
blackKingCheckCount++;
}
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(blackKingPosition, WHITE_OCCUPANCIES_LOCAL);
temp_bitboard = board->pieceArray[WR] & rook_attacks;
while (temp_bitboard != 0)
{
const 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)
{
check_bitboard = INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
blackKingCheckCount++;
}
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 = board->pieceArray[WQ] & rook_attacks;
while (temp_bitboard != 0)
{
const 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)
{
check_bitboard |= INBETWEEN_BITBOARDS[blackKingPosition][piece_square];
blackKingCheckCount++;
}
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 (blackKingCheckCount > 1)
{
#pragma region Black king
const unsigned long long occupancyWithoutBlackKing = COMBINED_OCCUPANCIES_LOCAL & (~board->pieceArray[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 ((board->pieceArray[WP] & BLACK_PAWN_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[WN] & KNIGHT_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[WK] & KING_ATTACKS[target_square]) != 0)
{
continue;
}
unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing);
if ((board->pieceArray[WB] & bishopAttacks) != 0)
{
continue;
}
if ((board->pieceArray[WQ] & bishopAttacks) != 0)
{
continue;
}
unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing);
if ((board->pieceArray[WR] & rookAttacks) != 0)
{
continue;
}
if ((board->pieceArray[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 ((board->pieceArray[WP] & WHITE_PAWN_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[WN] & KNIGHT_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[WK] & KING_ATTACKS[target_square]) != 0)
{
continue;
}
unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing);
if ((board->pieceArray[WB] & bishopAttacks) != 0)
{
continue;
}
if ((board->pieceArray[WQ] & bishopAttacks) != 0)
{
continue;
}
unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing);
if ((board->pieceArray[WR] & rookAttacks) != 0)
{
continue;
}
if ((board->pieceArray[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 = board->pieceArray[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 (board->ep != NO_SQUARE)
{
if ((((BLACK_PAWN_ATTACKS[starting_square] & SQUARE_BBS[board->ep]) & check_bitboard) & temp_pin_bitboard) != 0)
{
if ((board->pieceArray[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] = board->ep;
move_list[move_count][MOVE_TAG] = TAG_BLACKEP;
move_list[move_count][MOVE_PIECE] = BP;
move_count++;
}
else if ((board->pieceArray[WR] & RANK_4_BITBOARD) == 0 && (board->pieceArray[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] = board->ep;
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[board->ep - 8];
unsigned long long rookAttacksFromKing = GetRookAttacksFast(blackKingPosition, occupancyWithoutEPPawns);
if ((rookAttacksFromKing & board->pieceArray[WR]) == 0)
{
if ((rookAttacksFromKing & board->pieceArray[WQ]) == 0)
{
move_list[move_count][MOVE_STARTING] = starting_square;
move_list[move_count][MOVE_TARGET] = board->ep;
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 = board->pieceArray[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 = board->pieceArray[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 = board->pieceArray[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 = board->pieceArray[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 ((board->pieceArray[WP] & BLACK_PAWN_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[WN] & KNIGHT_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[WK] & KING_ATTACKS[target_square]) != 0)
{
continue;
}
const unsigned long long occupancyWithoutBlackKing = COMBINED_OCCUPANCIES_LOCAL & (~board->pieceArray[BK]);
const unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing);
if ((board->pieceArray[WB] & bishopAttacks) != 0)
{
continue;
}
if ((board->pieceArray[WQ] & bishopAttacks) != 0)
{
continue;
}
const unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing);
if ((board->pieceArray[WR] & rookAttacks) != 0)
{
continue;
}
if ((board->pieceArray[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 ((board->pieceArray[WP] & BLACK_PAWN_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[WN] & KNIGHT_ATTACKS[target_square]) != 0)
{
continue;
}
if ((board->pieceArray[WK] & KING_ATTACKS[target_square]) != 0)
{
continue;
}
const unsigned long long occupancyWithoutBlackKing = COMBINED_OCCUPANCIES_LOCAL & (~board->pieceArray[BK]);
const unsigned long long bishopAttacks = GetBishopAttacksFast(target_square, occupancyWithoutBlackKing);
if ((board->pieceArray[WB] & bishopAttacks) != 0)
{
continue;
}
if ((board->pieceArray[WQ] & bishopAttacks) != 0)
{
continue;
}
const unsigned long long rookAttacks = GetRookAttacksFast(target_square, occupancyWithoutBlackKing);
if ((board->pieceArray[WR] & rookAttacks) != 0)
{
continue;
}
if ((board->pieceArray[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 (board->castleRights[BKS_CASTLE_RIGHTS] == TRUE)
{
if (blackKingPosition == E8) //king on e1
{
if ((BKS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty
{
if ((board->pieceArray[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 (board->castleRights[BQS_CASTLE_RIGHTS] == TRUE)
{
if (blackKingPosition == E8) //king on e1
{
if ((BQS_EMPTY_BITBOARD & COMBINED_OCCUPANCIES_LOCAL) == 0) //f1 and g1 empty
{
if ((board->pieceArray[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 = board->ep;
int copy_castle[4];
copy_castle[0] = board->castleRights[0];
copy_castle[1] = board->castleRights[1];
copy_castle[2] = board->castleRights[2];
copy_castle[3] = board->castleRights[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
if (board->isWhite == TRUE) {
board->isWhite = FALSE;
} else {
board->isWhite = TRUE;
}
switch (tag)
{
case 0: //none
case 26: //check
board->pieceArray[piece] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
break;
case 1: //capture
case 27: //check cap
board->pieceArray[piece] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
if (piece >= WP && piece <= WK)
{
for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
}
else //is black
{
for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
}
board->ep = NO_SQUARE;
break;
case 2: //white ep
//move piece
board->pieceArray[WP] |= SQUARE_BBS[targetSquare];
board->pieceArray[WP] &= ~SQUARE_BBS[startingSquare];
//remove
board->pieceArray[BP] &= ~SQUARE_BBS[targetSquare + 8];
board->ep = NO_SQUARE;
break;
case 3: //black ep
//move piece
board->pieceArray[BP] |= SQUARE_BBS[targetSquare];
board->pieceArray[BP] &= ~SQUARE_BBS[startingSquare];
//remove white pawn square up
board->pieceArray[WP] &= ~SQUARE_BBS[targetSquare - 8];
board->ep = NO_SQUARE;
break;
#pragma region Castling
case 4: //WKS
//white king
board->pieceArray[WK] |= SQUARE_BBS[G1];
board->pieceArray[WK] &= ~SQUARE_BBS[E1];
//white rook
board->pieceArray[WR] |= SQUARE_BBS[F1];
board->pieceArray[WR] &= ~SQUARE_BBS[H1];
board->castleRights[WKS_CASTLE_RIGHTS] = FALSE;
board->castleRights[WQS_CASTLE_RIGHTS] = FALSE;
board->ep = NO_SQUARE;
break;
case 5: //WQS
//white king
board->pieceArray[WK] |= SQUARE_BBS[C1];
board->pieceArray[WK] &= ~SQUARE_BBS[E1];
//white rook
board->pieceArray[WR] |= SQUARE_BBS[D1];
board->pieceArray[WR] &= ~SQUARE_BBS[A1];
board->castleRights[WKS_CASTLE_RIGHTS] = FALSE;
board->castleRights[WQS_CASTLE_RIGHTS] = FALSE;
board->ep = NO_SQUARE;
break;
case 6: //BKS
//white king
board->pieceArray[BK] |= SQUARE_BBS[G8];
board->pieceArray[BK] &= ~SQUARE_BBS[E8];
//white rook
board->pieceArray[BR] |= SQUARE_BBS[F8];
board->pieceArray[BR] &= ~SQUARE_BBS[H8];
board->castleRights[BKS_CASTLE_RIGHTS] = FALSE;
board->castleRights[BQS_CASTLE_RIGHTS] = FALSE;
board->ep = NO_SQUARE;
break;
case 7: //BQS
//white king
board->pieceArray[BK] |= SQUARE_BBS[C8];
board->pieceArray[BK] &= ~SQUARE_BBS[E8];
//white rook
board->pieceArray[BR] |= SQUARE_BBS[D8];
board->pieceArray[BR] &= ~SQUARE_BBS[A8];
board->castleRights[BKS_CASTLE_RIGHTS] = FALSE;
board->castleRights[BQS_CASTLE_RIGHTS] = FALSE;
board->ep = NO_SQUARE;
break;
#pragma endregion
#pragma region Promotion makemove
case 8: //BNPr
board->pieceArray[BN] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
break;
case 9: //BBPr
board->pieceArray[BB] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
break;
case 10: //BQPr
board->pieceArray[BQ] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
break;
case 11: //BRPr
board->pieceArray[BR] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
break;
case 12: //WNPr
board->pieceArray[WN] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
break;
case 13: //WBPr
board->pieceArray[WB] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
break;
case 14: //WQPr
board->pieceArray[WQ] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
break;
case 15: //WRPr
board->pieceArray[WR] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
break;
case 16: //BNPrCAP
board->pieceArray[BN] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
break;
case 17: //BBPrCAP
board->pieceArray[BB] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
break;
case 18: //BQPrCAP
board->pieceArray[BQ] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
break;
case 19: //BRPrCAP
board->pieceArray[BR] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
for (size_t i = WHITE_START_INDEX; i <= WHITE_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
break;
case 20: //WNPrCAP
board->pieceArray[WN] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
break;
case 21: //WBPrCAP
board->pieceArray[WB] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
break;
case 22: //WQPrCAP
board->pieceArray[WQ] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
break;
case 23: //WRPrCAP
board->pieceArray[WR] |= SQUARE_BBS[targetSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[startingSquare];
board->ep = NO_SQUARE;
for (size_t i = BLACK_START_INDEX; i <= BLACK_END_INDEX; ++i)
{
if ((board->pieceArray[i] & SQUARE_BBS[targetSquare]) != 0)
{
captureIndex = i;
break;
}
}
board->pieceArray[captureIndex] &= ~SQUARE_BBS[targetSquare];
break;
#pragma endregion
case 24: //WDouble
board->pieceArray[WP] |= SQUARE_BBS[targetSquare];
board->pieceArray[WP] &= ~SQUARE_BBS[startingSquare];
board->ep = targetSquare + 8;
break;
case 25: //BDouble
board->pieceArray[BP] |= SQUARE_BBS[targetSquare];
board->pieceArray[BP] &= ~SQUARE_BBS[startingSquare];
board->ep = targetSquare - 8;
break;
}
if (piece == WK)
{
board->castleRights[WKS_CASTLE_RIGHTS] = FALSE;
board->castleRights[WQS_CASTLE_RIGHTS] = FALSE;
}
else if (piece == BK)
{
board->castleRights[BKS_CASTLE_RIGHTS] = FALSE;
board->castleRights[BQS_CASTLE_RIGHTS] = FALSE;
}
else if (piece == WR)
{
if (board->castleRights[WKS_CASTLE_RIGHTS] == TRUE)
{
if ((board->pieceArray[WR] & SQUARE_BBS[H1]) == 0)
{
board->castleRights[WKS_CASTLE_RIGHTS] = FALSE;
}
}
if (board->castleRights[WQS_CASTLE_RIGHTS] == TRUE)
{
if ((board->pieceArray[WR] & SQUARE_BBS[A1]) == 0)
{
board->castleRights[WQS_CASTLE_RIGHTS] = FALSE;
}
}
}
else if (piece == BR)
{
if (board->castleRights[BKS_CASTLE_RIGHTS] == TRUE)
{
if ((board->pieceArray[BR] & SQUARE_BBS[H8]) == 0)
{
board->castleRights[BKS_CASTLE_RIGHTS] = FALSE;
}
}
if (board->castleRights[BQS_CASTLE_RIGHTS] == TRUE)
{
if ((board->pieceArray[BR] & SQUARE_BBS[A8]) == 0)
{
board->castleRights[BQS_CASTLE_RIGHTS] = FALSE;
}
}
}
#pragma endregion
priorNodes = nodes;
nodes += PerftInlineStruct(board, depth - 1, ply + 1);
#pragma region Unmakemove
if (board->isWhite == TRUE) {
board->isWhite = FALSE;
}
else {
board->isWhite = TRUE;
}
switch (tag)
{
case 0: //none
case 26: //check
board->pieceArray[piece] |= SQUARE_BBS[startingSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[targetSquare];
break;
case 1: //capture
case 27: //check cap
board->pieceArray[piece] |= SQUARE_BBS[startingSquare];
board->pieceArray[piece] &= ~SQUARE_BBS[targetSquare];
if (piece >= WP && piece <= WK)
{
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
}
else //is black
{
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
}
break;
case 2: //white ep
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WP] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[BP] |= SQUARE_BBS[targetSquare + 8];
break;
case 3: //black ep
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BP] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[WP] |= SQUARE_BBS[targetSquare - 8];
break;
case 4: //WKS
//white king
board->pieceArray[WK] |= SQUARE_BBS[E1];
board->pieceArray[WK] &= ~SQUARE_BBS[G1];
//white rook
board->pieceArray[WR] |= SQUARE_BBS[H1];
board->pieceArray[WR] &= ~SQUARE_BBS[F1];
break;
case 5: //WQS
//white king
board->pieceArray[WK] |= SQUARE_BBS[E1];
board->pieceArray[WK] &= ~SQUARE_BBS[C1];
//white rook
board->pieceArray[WR] |= SQUARE_BBS[A1];
board->pieceArray[WR] &= ~SQUARE_BBS[D1];
break;
case 6: //BKS
//white king
board->pieceArray[BK] |= SQUARE_BBS[E8];
board->pieceArray[BK] &= ~SQUARE_BBS[G8];
//white rook
board->pieceArray[BR] |= SQUARE_BBS[H8];
board->pieceArray[BR] &= ~SQUARE_BBS[F8];
break;
case 7: //BQS
//white king
board->pieceArray[BK] |= SQUARE_BBS[E8];
board->pieceArray[BK] &= ~SQUARE_BBS[C8];
//white rook
board->pieceArray[BR] |= SQUARE_BBS[A8];
board->pieceArray[BR] &= ~SQUARE_BBS[D8];
break;
#pragma region Promotion Unmakemove
case 8: //BNPr
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BN] &= ~SQUARE_BBS[targetSquare];
break;
case 9: //BBPr
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BB] &= ~SQUARE_BBS[targetSquare];
break;
case 10: //BQPr
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BQ] &= ~SQUARE_BBS[targetSquare];
break;
case 11: //BRPr
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BR] &= ~SQUARE_BBS[targetSquare];
break;
case 12: //WNPr
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WN] &= ~SQUARE_BBS[targetSquare];
break;
case 13: //WBPr
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WB] &= ~SQUARE_BBS[targetSquare];
break;
case 14: //WQPr
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WQ] &= ~SQUARE_BBS[targetSquare];
break;
case 15: //WRPr
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WR] &= ~SQUARE_BBS[targetSquare];
break;
case 16: //BNPrCAP
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BN] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 17: //BBPrCAP
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BB] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 18: //BQPrCAP
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BQ] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 19: //BRPrCAP
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BR] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 20: //WNPrCAP
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WN] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 21: //WBPrCAP
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WB] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 22: //WQPrCAP
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WQ] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 23: //WRPrCAP
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WR] &= ~SQUARE_BBS[targetSquare];
board->pieceArray[captureIndex] |= SQUARE_BBS[targetSquare];
break;
#pragma endregion
case 24: //WDouble
board->pieceArray[WP] |= SQUARE_BBS[startingSquare];
board->pieceArray[WP] &= ~SQUARE_BBS[targetSquare];
break;
case 25: //BDouble
board->pieceArray[BP] |= SQUARE_BBS[startingSquare];
board->pieceArray[BP] &= ~SQUARE_BBS[targetSquare];
break;
}
board->castleRights[0] = copy_castle[0];
board->castleRights[1] = copy_castle[1];
board->castleRights[2] = copy_castle[2];
board->castleRights[3] = copy_castle[3];
board->ep = 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 RunPerftInlineStruct(const int depth)
{
Board board;
CopyGlobalBoardStruct(&board);
clock_t start_time = clock(); // Get the initial time
unsigned long long nodes = PerftInlineStruct(&board, 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);
}
unsigned long long PerftInlineGlobalOcc(const int depth, const int ply)
{
//if (depth == 0)
//{
// return 1;
//}
int move_list[50][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 = (DEBRUIJN64[MAGIC * (bitboard_array_global[WK] ^ (bitboard_array_global[WK] - 1)) >> 58]);
#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]);
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]);
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)
{
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)
{
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)
{
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)
{
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 = (DEBRUIJN64[MAGIC * (temp_empty ^ (temp_empty - 1)) >> 58]);
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 = (DEBRUIJN64[MAGIC * (temp_captures ^ (temp_captures - 1)) >> 58]);
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 = (DEBRUIJN64[MAGIC * (temp_empty ^ (temp_empty - 1)) >> 58]);
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 = (DEBRUIJN64[MAGIC * (temp_captures ^ (temp_captures - 1)) >> 58]);
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]);
check_bitboard = SQUARE_BBS[pawn_square];
blackKingCheckCount++;
}
//knights
temp_bitboard = bitboard_array_global[WN] & KNIGHT_ATTACKS[blackKingPosition];
if (temp_bitboard != 0)
{
const int knight_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]);
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)
{
const 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
{
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[WQ] & bishopAttacksChecks;
while (temp_bitboard != 0)
{
const 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
{
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(blackKingPosition, WHITE_OCCUPANCIES_LOCAL);
temp_bitboard = bitboard_array_global[WR] & rook_attacks;
while (temp_bitboard != 0)
{
const 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
{
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[WQ] & rook_attacks;
while (temp_bitboard != 0)
{
const 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
{
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 (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;
const int copy_castle[4] =
{
castle_rights_global[0],
castle_rights_global[1],
castle_rights_global[2],
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
if (is_white_global == TRUE) {
is_white_global = FALSE;
} else {
is_white_global = TRUE;
}
switch (tag)
{
case 0: //none
case 26: //check
bitboard_array_global[piece] |= SQUARE_BBS[targetSquare];
bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare];
ep_global = NO_SQUARE;
break;
case 1: //capture
case 27: //check cap
bitboard_array_global[piece] |= SQUARE_BBS[targetSquare];
bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare];
if (piece >= WP && piece <= WK)
{
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 2: //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 3: //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 4: //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 5: //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 6: //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 7: //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 8: //BNPr
bitboard_array_global[BN] |= SQUARE_BBS[targetSquare];
bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare];
ep_global = NO_SQUARE;
break;
case 9: //BBPr
bitboard_array_global[BB] |= SQUARE_BBS[targetSquare];
bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare];
ep_global = NO_SQUARE;
break;
case 10: //BQPr
bitboard_array_global[BQ] |= SQUARE_BBS[targetSquare];
bitboard_array_global[piece] &= ~SQUARE_BBS[startingSquare];
ep_global = NO_SQUARE;
break;
case 11: //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 += PerftInlineGlobalOcc(depth - 1, ply + 1);
#pragma region Unmakemove
if (is_white_global == TRUE) {
is_white_global = FALSE;
}
else {
is_white_global = TRUE;
}
switch (tag)
{
case 0: //none
case 26: //check
bitboard_array_global[piece] |= SQUARE_BBS[startingSquare];
bitboard_array_global[piece] &= ~SQUARE_BBS[targetSquare];
break;
case 1: //capture
case 27: //check cap
bitboard_array_global[piece] |= SQUARE_BBS[startingSquare];
bitboard_array_global[piece] &= ~SQUARE_BBS[targetSquare];
if (piece >= WP && piece <= WK)
{
bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare];
}
else //is black
{
bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare];
}
break;
case 2: //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 3: //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 4: //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 5: //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 6: //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 7: //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 8: //BNPr
bitboard_array_global[BP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[BN] &= ~SQUARE_BBS[targetSquare];
break;
case 9: //BBPr
bitboard_array_global[BP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[BB] &= ~SQUARE_BBS[targetSquare];
break;
case 10: //BQPr
bitboard_array_global[BP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[BQ] &= ~SQUARE_BBS[targetSquare];
break;
case 11: //BRPr
bitboard_array_global[BP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[BR] &= ~SQUARE_BBS[targetSquare];
break;
case 12: //WNPr
bitboard_array_global[WP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[WN] &= ~SQUARE_BBS[targetSquare];
break;
case 13: //WBPr
bitboard_array_global[WP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[WB] &= ~SQUARE_BBS[targetSquare];
break;
case 14: //WQPr
bitboard_array_global[WP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[WQ] &= ~SQUARE_BBS[targetSquare];
break;
case 15: //WRPr
bitboard_array_global[WP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[WR] &= ~SQUARE_BBS[targetSquare];
break;
case 16: //BNPrCAP
bitboard_array_global[BP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[BN] &= ~SQUARE_BBS[targetSquare];
bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 17: //BBPrCAP
bitboard_array_global[BP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[BB] &= ~SQUARE_BBS[targetSquare];
bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 18: //BQPrCAP
bitboard_array_global[BP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[BQ] &= ~SQUARE_BBS[targetSquare];
bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 19: //BRPrCAP
bitboard_array_global[BP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[BR] &= ~SQUARE_BBS[targetSquare];
bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 20: //WNPrCAP
bitboard_array_global[WP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[WN] &= ~SQUARE_BBS[targetSquare];
bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 21: //WBPrCAP
bitboard_array_global[WP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[WB] &= ~SQUARE_BBS[targetSquare];
bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 22: //WQPrCAP
bitboard_array_global[WP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[WQ] &= ~SQUARE_BBS[targetSquare];
bitboard_array_global[captureIndex] |= SQUARE_BBS[targetSquare];
break;
case 23: //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 24: //WDouble
bitboard_array_global[WP] |= SQUARE_BBS[startingSquare];
bitboard_array_global[WP] &= ~SQUARE_BBS[targetSquare];
break;
case 25: //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 RunPerftInlineGlobalOcc(const int depth)
{
CopyGlobalBoardGlobal();
clock_t start_time = clock(); // Get the initial time
unsigned long long nodes = PerftInlineGlobalOcc(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();
ParseFenGlobal(FEN_STARTING_POSITION, 0);
RunPerftInlineGlobalOcc(6);
//RunPerftInlineStruct(6);
return 0;
}