mirror of
https://github.com/OMGeeky/hcsalmon1-Chess-Engine-Test.git
synced 2026-02-23 15:49:51 +01:00
Update Algorithm explanation.txt
This commit is contained in:
@@ -202,11 +202,12 @@ will be stored.
|
|||||||
}
|
}
|
||||||
|
|
||||||
For pins it's a bit more complicated. We first need INBETWEEN_BITBOARDS.
|
For pins it's a bit more complicated. We first need INBETWEEN_BITBOARDS.
|
||||||
This is a multi dimensional array that simple has all of this bits inbetween every square combination.
|
This is a multi dimensional array that simply has all of this bits inbetween every square combination.
|
||||||
|
It also includes the last square.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
INBETWEEN_BITBOARD[E1][E8] =
|
INBETWEEN_BITBOARD[E1][E8] =
|
||||||
0 0 0 0 0 0 0 0
|
0 0 0 0 1 0 0 0
|
||||||
0 0 0 0 1 0 0 0
|
0 0 0 0 1 0 0 0
|
||||||
0 0 0 0 1 0 0 0
|
0 0 0 0 1 0 0 0
|
||||||
0 0 0 0 1 0 0 0
|
0 0 0 0 1 0 0 0
|
||||||
@@ -215,15 +216,17 @@ Example:
|
|||||||
0 0 0 0 1 0 0 0
|
0 0 0 0 1 0 0 0
|
||||||
0 0 0 0 0 0 0 0
|
0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
INBETWEEN_BITBOARD[E1][E8] =
|
INBETWEEN_BITBOARD[B7][G2] =
|
||||||
0 0 0 0 0 0 0 0
|
0 0 0 0 0 0 0 0
|
||||||
0 0 0 0 1 0 0 0
|
|
||||||
0 0 0 0 1 0 0 0
|
|
||||||
0 0 0 0 1 0 0 0
|
|
||||||
0 0 0 0 1 0 0 0
|
|
||||||
0 0 0 0 1 0 0 0
|
|
||||||
0 0 0 0 1 0 0 0
|
|
||||||
0 0 0 0 0 0 0 0
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 1 0 0 0 0 0
|
||||||
|
0 0 0 1 0 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 0 1 0 0
|
||||||
|
0 0 0 0 0 0 1 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
We use these for pins and check for rooks, queens and bishops.
|
||||||
|
|
||||||
int pinArray[8][2] =
|
int pinArray[8][2] =
|
||||||
{
|
{
|
||||||
@@ -247,31 +250,223 @@ We create a pin array. The first index is the square being pinned. The second in
|
|||||||
while (temp_bitboard != 0) //if there is a black bishop there
|
while (temp_bitboard != 0) //if there is a black bishop there
|
||||||
{
|
{
|
||||||
const int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); //find the square
|
const int piece_square = (DEBRUIJN64[MAGIC * (temp_bitboard ^ (temp_bitboard - 1)) >> 58]); //find the square
|
||||||
temp_pin_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL;
|
temp_pin_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square] & WHITE_OCCUPANCIES_LOCAL;
|
||||||
|
//for the squares inbetween, is there a white piece there
|
||||||
|
|
||||||
if (temp_pin_bitboard == 0)
|
if (temp_pin_bitboard == 0) //if there is no white piece, the bishop is attacking the king
|
||||||
{
|
{
|
||||||
if (check_bitboard == 0)
|
if (check_bitboard == 0)
|
||||||
{
|
{
|
||||||
check_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square];
|
check_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][piece_square]; //add the check
|
||||||
}
|
}
|
||||||
whiteKingCheckCount++;
|
whiteKingCheckCount++;
|
||||||
}
|
}
|
||||||
else
|
else //if there is a white piece inbetween, there is a potential pin
|
||||||
{
|
{
|
||||||
const int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]);
|
const int pinned_square = (DEBRUIJN64[MAGIC * (temp_pin_bitboard ^ (temp_pin_bitboard - 1)) >> 58]); //get the square
|
||||||
temp_pin_bitboard &= temp_pin_bitboard - 1;
|
temp_pin_bitboard &= temp_pin_bitboard - 1; //remove one bit from bitboard
|
||||||
|
|
||||||
if (temp_pin_bitboard == 0)
|
if (temp_pin_bitboard == 0) //if the bitboard is not empty then that piece was pinned.
|
||||||
{
|
{
|
||||||
pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square;
|
pinArray[pinNumber][PINNED_SQUARE_INDEX] = pinned_square; //add the pinned square
|
||||||
pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square;
|
pinArray[pinNumber][PINNING_PIECE_INDEX] = piece_square; //add the pinning piece
|
||||||
pinNumber++;
|
pinNumber++; //increase the pin number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
temp_bitboard &= temp_bitboard - 1; //remove the bit to stop infinitive loop
|
temp_bitboard &= temp_bitboard - 1; //remove the bit to stop infinitive loop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
We do the same for queen and rook.
|
||||||
|
We then check if a piece is pinned like so:
|
||||||
|
|
||||||
|
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; //set it max, so allows all moves first
|
||||||
|
if (pinNumber != 0) //if there is a pin somewhere
|
||||||
|
{
|
||||||
|
for (int i = 0; i < pinNumber; i++) //loop through them
|
||||||
|
{
|
||||||
|
if (pinArray[i][PINNED_SQUARE_INDEX] == starting_square) //if this piece is pinned
|
||||||
|
{
|
||||||
|
temp_pin_bitboard = INBETWEEN_BITBOARDS[whiteKingPosition][pinArray[i][PINNING_PIECE_INDEX]];
|
||||||
|
//set the temp_pin_bitboard to the bits in between the king and pinning piece
|
||||||
|
//This means the knight can only move
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_attack = ((KNIGHT_ATTACKS[starting_square] & BLACK_OCCUPANCIES_LOCAL) & check_bitboard) & temp_pin_bitboard;
|
||||||
|
//Then you AND the attacks with the check and pins
|
||||||
|
|
||||||
|
//add moves if temp_attack isn't zero etc...
|
||||||
|
while (temp_attack != 0) ...
|
||||||
|
|
||||||
|
Let's say in this position:
|
||||||
|
|
||||||
|
__ __ __ __ BK __ __ __
|
||||||
|
__ __ __ __ BR __ __ __
|
||||||
|
__ __ __ __ __ __ __ __
|
||||||
|
__ __ __ __ __ __ __ __
|
||||||
|
__ __ __ __ __ __ __ __
|
||||||
|
__ __ __ __ __ __ __ __
|
||||||
|
__ __ __ __ WR __ __ __
|
||||||
|
__ __ __ __ WK __ __ __
|
||||||
|
|
||||||
|
Here both rooks are pinning each other.
|
||||||
|
The white rook bitboard looks like this:
|
||||||
|
|
||||||
|
tempBitboard = bitboard_array[WR];
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
The rook moves will look like this:
|
||||||
|
|
||||||
|
rook_attacks = GetRookAttackFast(rook_square, COMBINED_OCCUPANCIES);
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
1 1 1 1 0 1 1 1
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
|
||||||
|
We AND this with empty squares to get non capture moves:
|
||||||
|
|
||||||
|
EMPTY_OCCUPANCIES:
|
||||||
|
1 1 1 1 0 1 1 1
|
||||||
|
1 1 1 1 0 1 1 1
|
||||||
|
1 1 1 1 1 1 1 1
|
||||||
|
1 1 1 1 1 1 1 1
|
||||||
|
1 1 1 1 1 1 1 1
|
||||||
|
1 1 1 1 1 1 1 1
|
||||||
|
1 1 1 1 0 1 1 1
|
||||||
|
1 1 1 1 0 1 1 1
|
||||||
|
|
||||||
|
unsigned long long non_capture_moves = EMPTY_OCCUPANCIES & rook_attacks;
|
||||||
|
non_capture_moves:
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
1 1 1 1 0 1 1 1
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
We get the capture moves by ANDing the attacks with black occupancies:
|
||||||
|
|
||||||
|
BLACK_OCCUPANCIES:
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
unsigned long long capture_moves = BLACK_OCCUPANCIES & rook_attacks;
|
||||||
|
capture_moves:
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
The pin bitboard will look like this:
|
||||||
|
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
We then AND that with captures and non captures. So if there is a pin, only these squares are valid.
|
||||||
|
Similar with check:
|
||||||
|
|
||||||
|
__ __ __ __ BK __ __ __
|
||||||
|
__ __ __ __ BR __ __ __
|
||||||
|
__ __ __ __ __ __ __ __
|
||||||
|
__ __ __ __ __ __ __ __
|
||||||
|
__ __ __ __ __ __ __ __
|
||||||
|
__ __ __ __ __ __ __ __
|
||||||
|
WR __ __ __ __ __ __ __
|
||||||
|
__ __ __ __ WK __ __ __
|
||||||
|
|
||||||
|
The check bitboard here:
|
||||||
|
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
The white rook attacks:
|
||||||
|
|
||||||
|
1 0 0 0 0 0 0 0
|
||||||
|
1 0 0 0 0 0 0 0
|
||||||
|
1 0 0 0 0 0 0 0
|
||||||
|
1 0 0 0 0 0 0 0
|
||||||
|
1 0 0 0 0 0 0 0
|
||||||
|
1 0 0 0 0 0 0 0
|
||||||
|
0 1 1 1 1 1 1 1
|
||||||
|
1 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
AND then together:
|
||||||
|
|
||||||
|
unsigned long long valid_rook_moves = checkBitboard & rook_attacks;
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
0 0 0 0 1 0 0 0
|
||||||
|
0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
Only these moves are valid.
|
||||||
|
|
||||||
|
The lazy and slow way to do pins and check:
|
||||||
|
|
||||||
|
for (int i = 0; i < move_count; ++i) {
|
||||||
|
|
||||||
|
MakeMove(move_list[i]);
|
||||||
|
if (isWhiteToMove)
|
||||||
|
{
|
||||||
|
if (is_attacked_by_black(white_king_position, COMBINED_OCCUPANCIES) == true) {
|
||||||
|
UnmakeMove(move_list[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (is_attacked_by_white(black_king_position, COMBINED_OCCUPANCIES) == true) {
|
||||||
|
UnmakeMove(move_list[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
__Finding Pieces__
|
__Finding Pieces__
|
||||||
|
|
||||||
I didn't write BitscanForward. It uses the DEBRUJN method to get "the least significant bit".
|
I didn't write BitscanForward. It uses the DEBRUJN method to get "the least significant bit".
|
||||||
|
|||||||
Reference in New Issue
Block a user