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()
