Code: Select all
/*******************************************************************/
/*
The rotated bitboard attacks with special line mapping
as part of the board structure.
(c) 2006 Harald Lüßen
*/
/*******************************************************************/
#include "bb_ifdef.h"
#include "bb_basics.h"
#include "bb_bitboard.h"
#include "bb_board.h"
#include "bb_main.h"
#if USE_ROTATED_BITBOARDS_LINES()
/*******************************************************************/
/*
directions and shifts
+-----+-----+-----+
|<<= 9|<<= 8|<<= 7|
+-----+-----+-----+
|<<= 1| |>>= 1|
+-----+-----+-----+
|>>= 7|>>= 8|>>= 9|
+-----+-----+-----+
We use this mapping of the normal board squares to bitboard bits
+-------------------------+
| 63 62 61 60 59 58 57 56 | 8
| 55 54 53 52 51 50 49 48 | 7
| 47 46 45 44 43 42 41 40 | 6
| 39 38 37 36 35 35 33 32 | 5
| 31 30 29 28 27 26 25 24 | 4
| 23 22 21 20 19 18 17 16 | 3
| 15 14 13 12 11 10 9 8 | 2
| 7 6 5 4 3 2 1 0 | 1
+-------------------------+
a b c d e f g h
*/
/*******************************************************************/
// pieces at begin of game in rotated bitboards
const Bitboard begin_all_rl90= C64(0xc3c3c3c3c3c3c3c3);
const Bitboard begin_all_rl45= C64(0x870f1e3c78f0e1c3);
const Bitboard begin_all_rr45= C64(0xc3e1f0783c1e0f87);
/*******************************************************************/
// Bit numbers of the normal board in the rotated board
const byte normal_to_rl90[64] =
{
0, 8, 16, 24, 32, 40, 48, 56,
1, 9, 17, 25, 33, 41, 49, 57,
2, 10, 18, 26, 34, 42, 50, 58,
3, 11, 19, 27, 35, 43, 51, 59,
4, 12, 20, 28, 36, 44, 52, 60,
5, 13, 21, 29, 37, 45, 53, 61,
6, 14, 22, 30, 38, 46, 54, 62,
7, 15, 23, 31, 39, 47, 55, 63,
};
// Bit numbers of the normal board in the rotated board
// The squares are in the same line as in the normal board.
const byte normal_to_rl45[64] =
{
0, 57, 50, 43, 36, 29, 22, 15,
8, 1, 58, 51, 44, 37, 30, 23,
16, 9, 2, 59, 52, 45, 38, 31,
24, 17, 10, 3, 60, 53, 46, 39,
32, 25, 18, 11, 4, 61, 54, 47,
40, 33, 26, 19, 12, 5, 62, 55,
48, 41, 34, 27, 20, 13, 6, 63,
56, 49, 42, 35, 28, 21, 14, 7,
};
// Bit numbers of the normal board in the rotated board
// The squares are in the same line as in the normal board.
const byte normal_to_rr45[64] =
{
0, 9, 18, 27, 36, 45, 54, 63,
8, 17, 26, 35, 44, 53, 62, 7,
16, 25, 34, 43, 52, 61, 6, 15,
24, 33, 42, 51, 60, 5, 14, 23,
32, 41, 50, 59, 4, 13, 22, 31,
40, 49, 58, 3, 12, 21, 30, 39,
48, 57, 2, 11, 20, 29, 38, 47,
56, 1, 10, 19, 28, 37, 46, 55,
};
// Shift values of the rotated bitboard for attacks and move generation.
// Shift the rotated bitboard this number of bits to find the row in the low bits.
// The index is the square number on the normal board.
const byte shift_of_rl90[64] =
{
0, 8, 16, 24, 32, 40, 48, 56,
0, 8, 16, 24, 32, 40, 48, 56,
0, 8, 16, 24, 32, 40, 48, 56,
0, 8, 16, 24, 32, 40, 48, 56,
0, 8, 16, 24, 32, 40, 48, 56,
0, 8, 16, 24, 32, 40, 48, 56,
0, 8, 16, 24, 32, 40, 48, 56,
0, 8, 16, 24, 32, 40, 48, 56,
};
// Shift values of the rotated bitboard for attacks and move generation.
// Shift the rotated bitboard this number of bits to find the row in the low bits.
// The index is the square number on the normal board.
const byte shift_of_rl45[64] =
{
0, 56, 48, 40, 32, 24, 16, 8,
8, 0, 56, 48, 40, 32, 24, 16,
16, 8, 0, 56, 48, 40, 32, 24,
24, 16, 8, 0, 56, 48, 40, 32,
32, 24, 16, 8, 0, 56, 48, 40,
40, 32, 24, 16, 8, 0, 56, 48,
48, 40, 32, 24, 16, 8, 0, 56,
56, 48, 40, 32, 24, 16, 8, 0,
};
// Shift values of the rotated bitboard for attacks and move generation.
// Shift the rotated bitboard this number of bits to find the row in the low bits.
// The index is the square number on the normal board.
const byte shift_of_rr45[64] =
{
0, 8, 16, 24, 32, 40, 48, 56,
8, 16, 24, 32, 40, 48, 56, 0,
16, 24, 32, 40, 48, 56, 0, 8,
24, 32, 40, 48, 56, 0, 8, 16,
32, 40, 48, 56, 0, 8, 16, 24,
40, 48, 56, 0, 8, 16, 24, 32,
48, 56, 0, 8, 16, 24, 32, 40,
56, 0, 8, 16, 24, 32, 40, 48,
};
// Mask values of the rotated bitboard for attacks and move generation.
// Mask the low bits of a shifted diagonal/row/line with bits in the correct length.
// The index is the square number on the normal board.
const byte mask_of_rl45[64] =
{
0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80,
0x7f, 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0,
0x3f, 0x7f, 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0,
0x1f, 0x3f, 0x7f, 0xff, 0xfe, 0xfc, 0xf8, 0xf0,
0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0xfe, 0xfc, 0xf8,
0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0xfe, 0xfc,
0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0xfe,
0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
};
// Mask values of the rotated bitboard for attacks and move generation.
// Mask the low bits of a shifted diagonal/row/line with bits in the correct length.
// The index is the square number on the normal board.
const byte mask_of_rr45[64] =
{
0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0xfe,
0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0xfe, 0xfc,
0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0xfe, 0xfc, 0xf8,
0x1f, 0x3f, 0x7f, 0xff, 0xfe, 0xfc, 0xf8, 0xf0,
0x3f, 0x7f, 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0,
0x7f, 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0,
0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80,
};
/*******************************************************************/
/**
Put the scattered bits of an sliding attack pattern
back to the original bitboard.
*/
Bitboard slider_rl90_to_bitboard[256];
/**
Put the scattered bits of an sliding attack pattern
back to the original bitboard.
*/
Bitboard slider_rl45_to_bitboard[8][256];
/**
Put the scattered bits of an sliding attack pattern
back to the original bitboard.
*/
Bitboard slider_rr45_to_bitboard[8][256];
/*******************************************************************/
/**
Set the rotated bitboards of all pieces
*/
void Board::set_all_rotated_bitboards()
{
Bitboard pieces = wpieces_ | bpieces_;
all_rl90_ = 0;
all_rl45_ = 0;
all_rr45_ = 0;
int sq;
for ( sq = 0; sq < 64; ++sq )
{
if ( pieces.test_bit( sq ) )
{
all_rl90_.set_bit( normal_to_rl90[sq] );
all_rl45_.set_bit( normal_to_rl45[sq] );
all_rr45_.set_bit( normal_to_rr45[sq] );
}
}
}
/*******************************************************************/
/**
Prepare the slider attacks back transformation table.
Put the scattered bits of an sliding attack pattern
back to the original bitboard.
*/
void Board::init_slider_attacks_index()
{
// Bitboard slider_rl90_to_bitboard[256];
int slider;
Bitboard result = 0;
for ( slider = 0; slider < 128; ++slider )
{
result = slider;
result *= C64(0x0002040810204081); // projection northeast
result &= C64(0x0101010101010101); // line_h;
slider_rl90_to_bitboard[slider] = result;
slider_rl90_to_bitboard[slider + 128] = result + (C64(1) << 56);
//logf << "slider_rl90_to_bitboard " << slider << endl;
//logf << slider_rl90_to_bitboard[slider].txt8lines() << endl;
//logf << "slider_rl90_to_bitboard " << slider + 128<< endl;
//logf << slider_rl90_to_bitboard[slider + 128].txt8lines() << endl;
}
for ( slider = 0; slider < 256; ++slider )
{
// Bitboard slider_rl45_to_bitboard[8][256];
result = slider;
result *= C64(0x0101010101010101); // projection north
result &= C64(0x8040201008040201); // diagonal A8..H1
for ( int index = 0; index < 8; ++index )
{
slider_rl45_to_bitboard[index][slider] = (result << (8 * index ))
| (result >> (8 * (8 - index)));
//logf << "slider_rl45_to_bitboard " << index << " " << slider << endl;
//logf << slider_rl45_to_bitboard[index][slider].txt8lines() << endl;
}
// Bitboard slider_rr45_to_bitboard[8][256];
result = slider;
result *= C64(0x0101010101010101); // projection north
result &= C64(0x0102040810204080); // diagonal A1..H8
for ( int index = 0; index < 8; ++index )
{
slider_rr45_to_bitboard[index][slider] = (result << (8 * (1 + index)))
| (result >> (8 * (7 - index)));
//logf << "slider_rr45_to_bitboard " << index << " " << slider << endl;
//logf << slider_rr45_to_bitboard[index][slider].txt8lines() << endl;
}
}
}
/*******************************************************************/
/**
Get a bitboard with all positions set to 1 which can be attacked
from a bishop, rook or queen on the square moving in the direction.
*/
Bitboard Board::direction_attacks( byte square, byte dir ) const
{
Bitboard result;
Bitboard occ;
byte shift;
byte pos;
byte pattern;
byte att;
// 4 3 2
// 5 0 1
// 6 7 8
switch ( dir )
{
case 1:
// normal bitboard
occ = wpieces_ | bpieces_;
shift = square & 0x38;
occ >>= (shift + 1);
pattern = occ;
pos = square & 7;
att = slider_attacks[pattern & 0x3f][pos];
att &= (1 << pos) - 1;
result = att;
result <<= shift;
break;
case 5:
// normal bitboard
occ = wpieces_ | bpieces_;
shift = square & 0x38;
occ >>= (shift + 1);
pattern = occ;
pos = square & 7;
att = slider_attacks[pattern & 0x3f][pos];
att &= ~((1 << pos) - 1);
result = att;
result <<= shift;
break;
case 7:
// rotated rl90 bitboard
occ = all_rl90_;
shift = shift_of_rl90[square];
occ >>= (shift + 1);
pattern = occ;
pos = square >> 3;
att = slider_attacks[pattern & 0x3f][pos];
att &= (1 << pos) - 1;
result = slider_rl90_to_bitboard[att];
result <<= (square & 7);
break;
case 3:
// rotated rl90 bitboard
occ = all_rl90_;
shift = shift_of_rl90[square];
occ >>= (shift + 1);
pattern = occ;
pos = square >> 3;
att = slider_attacks[pattern & 0x3f][pos];
att &= ~((1 << pos) - 1);
result = slider_rl90_to_bitboard[att];
result <<= (square & 7);
break;
case 8:
// rotated rl45 bitboard
occ = all_rl45_;
shift = shift_of_rl45[square];
occ >>= (shift + 1);
pattern = occ;
pos = square & 7;
att = slider_attacks[pattern & 0x3f][pos];
att &= mask_of_rl45[square];
att &= (1 << pos) - 1;
result = slider_rl45_to_bitboard[normal_to_rl45[square] >> 3][att];
break;
case 4:
// rotated rl45 bitboard
occ = all_rl45_;
shift = shift_of_rl45[square];
occ >>= (shift + 1);
pattern = occ;
pos = square & 7;
att = slider_attacks[pattern & 0x3f][pos];
att &= mask_of_rl45[square];
att &= ~((1 << pos) - 1);
result = slider_rl45_to_bitboard[normal_to_rl45[square] >> 3][att];
break;
case 2:
// rotated rr45 bitboard
occ = all_rr45_;
shift = shift_of_rr45[square];
occ >>= (shift + 1);
pattern = occ;
pos = square & 7;
att = slider_attacks[pattern & 0x3f][pos];
att &= mask_of_rr45[square];
att &= (1 << pos) - 1;
result = slider_rr45_to_bitboard[normal_to_rr45[square] >> 3][att];
break;
case 6:
// rotated rr45 bitboard
occ = all_rr45_;
shift = shift_of_rr45[square];
occ >>= (shift + 1);
pattern = occ;
pos = square & 7;
att = slider_attacks[pattern & 0x3f][pos];
att &= mask_of_rr45[square];
att &= ~((1 << pos) - 1);
result = slider_rr45_to_bitboard[normal_to_rr45[square] >> 3][att];
break;
default:
result = 0;
break;
}
return result;
}
/*******************************************************************/
/**
Get a bitboard with all positions set to 1 which can be attacked
from a rook or queen on the square.
*/
Bitboard Board::orthogonal_attacks( byte square ) const
{
Bitboard result;
// normal bitboard
Bitboard occ = wpieces_ | bpieces_;
byte shift = square & 0x38;
occ >>= (shift + 1);
byte pattern = occ;
byte att = slider_attacks[pattern & 0x3f][square & 7];
result = att;
result <<= shift;
// rotated rl90 bitboard
occ = all_rl90_;
shift = shift_of_rl90[square];
occ >>= (shift + 1);
pattern = occ;
att = slider_attacks[pattern & 0x3f][square >> 3];
occ = slider_rl90_to_bitboard[att];
occ <<= square & 7;
result |= occ;
return result;
}
/*******************************************************************/
/**
Get a bitboard with all positions set to 1 which can be attacked
from a bishop or queen on the square.
*/
Bitboard Board::diagonal_attacks( byte square ) const
{
Bitboard result;
// rotated rl45 bitboard
Bitboard occ = all_rl45_;
byte shift = shift_of_rl45[square];
occ >>= (shift + 1);
byte pattern = occ;
byte att = slider_attacks[pattern & 0x3f][square & 7];
att &= mask_of_rl45[square];
result = slider_rl45_to_bitboard[normal_to_rl45[square] >> 3][att];
// rotated rr45 bitboard
occ = all_rr45_;
shift = shift_of_rr45[square];
occ >>= (shift + 1);
pattern = occ;
att = slider_attacks[pattern & 0x3f][square & 7];
att &= mask_of_rr45[square];
occ = slider_rr45_to_bitboard[normal_to_rr45[square] >> 3][att];
result |= occ;
return result;
}
/*******************************************************************/
#endif // USE_ROTATED_BITBOARDS_LINES()