Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: For Dr. Robert Hyatt

Author: Ed Trice

Date: 05:24:55 12/31/03

Go up one level in this thread



>Hello again Ed!
>
>I thought your program was already blazingly fast. What happened to your claims
>that your 80-bit bitboard program was faster than any array based program on
>32-bit hardware?
>
>If I recall correctly, your program generates 140 million moves per second on
>your Pentium III 2 GHz (nice overclocking job BTW). It seems like Dr. Hyatt
>should be the one asking you for tips, since your program apparently blows his
>out of the water (along with every other PC chess program ever written). Do tell
>us your secrets Ed!

At one point in time, someone contacted me and was asking questions that
indicated that they had a good bit of knowledge about chess programming. That
individual was also asking me questions, for reasons I do not fully understand.

At that point in time I had a crude bitboard move generator in place for Gothic
Chess. It was not hooked up to an alpha-beta procedure, nor any type of
evaluation function. Even with these caveats in place, the individual persisted
in asking me performance-related questions.

The only way I could test the engine was to call the move generator in a for
loop and time it. Again, this would be like detaching Crafty from the rest of
its engine, then seeing how quickly it could generate moves.

My numbers were of the order of magnitude you mentioned, but I do not have the
exact figures.

As for "secrets", there really are none. Just overloading the operators in C++.

Examples:

typedef struct
{
	unsigned short b2;
	unsigned long long b1;
}
BITBOARD; // 80 bits composed of a 64 and a 16

int operator == (BITBOARD x, BITBOARD y)
{
	if(x.b1 == y.b1 && x.b2 == y.b2)
		return 1;
	return 0;
}


void operator |= (BITBOARD &x, BITBOARD y)    // bit OR bitboard x with bitboard
y, change the orginal
											// this redefines the |= bitwise operator
{
	x.b1 |= y.b1;
	x.b2 |= y.b2;
}


BITBOARD operator | (BITBOARD x, BITBOARD y)    // bit OR bitboard x with
bitboard y, return the result
											// this redefines the | bitwise operator
{
	x.b1 |= y.b1;
	x.b2 |= y.b2;

	return x;
}


BITBOARD operator ^ (BITBOARD x, BITBOARD y)    // bit XOR bitboard x with
bitboard y, return the result
											// this redefines the ^ bitwise operator
{
	x.b1 ^= y.b1;
	x.b2 ^= y.b2;

	return x;
}


void operator ^= (BITBOARD &x, BITBOARD y)    // bit XOR bitboard x with
bitboard y, change the original
											// this redefines the ^= bitwise operator
{
	x.b1 ^= y.b1;
	x.b2 ^= y.b2;
}


void operator &= (BITBOARD &x, BITBOARD y)    // bit AND bitboard x with
bitboard y, change the original
											// this redefines the &= bitwise operator
{
	x.b1 &= y.b1;
	x.b2 &= y.b2;
}


BITBOARD operator & (BITBOARD x, BITBOARD y)    // bit AND bitboard x with
bitboard y and return the result
											// this redefines the & bitwise operator
{
	x.b1 &= y.b1;
	x.b2 &= y.b2;

	return x;
}


BITBOARD operator ~ (BITBOARD x)    // invert the bits of a bitboard
{
	x.b1 = ~x.b1;
	x.b2 = ~x.b2;

	return x;
}


void operator <<= (BITBOARD &x, int shiftDistance)    // shift 80-bit x left
"shiftDistance" bits
													// change the original by reference variable
{
	if(shiftDistance < 16)
	{
		x.b1 <<= shiftDistance;
		if(x.b2)
		{
			x.b1 |= (x.b2 >> (16-shiftDistance)); // extract the top bits from the 16 and
OR them with the 64
			x.b2 <<= shiftDistance;
		}
	}
	else
	{
		x.b1 <<= 16; // shift 16
		if(x.b2)
		{
			x.b1 |= x.b2; // tack on the 16 bits of the 16
			x.b2 = 0; // we shifted all the bits off the end of the 16
		}
		x.b1 <<= (shiftDistance - 16); // shift the 64 the rest of the way
	}
}

BITBOARD operator << (BITBOARD x, int shiftDistance)// shift 80-bit x left
"shiftDistance" bits
{													// return the shifted result; leave original unchanged
	if(shiftDistance < 16)
	{
		x.b1 <<= shiftDistance;
		if(x.b2)
		{
			x.b1 |= (x.b2 >> (16-shiftDistance)); // extract the top bits from the 16 and
OR them with the 64
			x.b2 <<= shiftDistance;
		}
	}
	else
	{
		x.b1 <<= 16; // shift 16
		if(x.b2)
		{
			x.b1 |= x.b2; // tack on the 16 bits of the 16
			x.b2 = 0; // we shifted all the bits off the end of the 16
		}
		x.b1 <<= (shiftDistance - 16); // shift the 64 the rest of the way
	}

	return x;
}

BITBOARD operator >> (BITBOARD x, int shiftDistance)    // shift 80-bit x right
"shiftDistance" bits
													// return the shifted result; leave original unchanged
{
	if(x.b2)
	{
		if(shiftDistance < 16)
			x.b2 >>= shiftDistance; // top of board, bits shift off the right and are
lost, nothing to carry
		else
			x.b2 = 0;
	}
	if(shiftDistance <= 16)
		x.b2 |= (x.b1 << (16-shiftDistance));
	else
		x.b2 |= (x.b1 >> (shiftDistance - 16));

	if(shiftDistance < 64)
		x.b1 >>= shiftDistance; // now we can shift b1 since we extracted the bits we
need
	else
		x.b1 = 0;
	return x;
}

void operator >>= (BITBOARD &x, int shiftDistance)    // shift 80-bit x right
"shiftDistance" bits
														// change the original with a reference variable
{
	if(x.b2)
	{
		if(shiftDistance < 16)
			x.b2 >>= shiftDistance; // top of board, bits shift off the right and are
lost, nothing to carry
		else
			x.b2 = 0;
	}
	if(shiftDistance <= 16)
		x.b2 |= (x.b1 << (16-shiftDistance));
	else
		x.b2 |= (x.b1 >> (shiftDistance - 16));

	if(shiftDistance < 64)
		x.b1 >>= shiftDistance; // now we can shift b1 since we extracted the bits we
need
	else
		x.b1 = 0;
}



With this structure in place, I am able to execute bitwise operations on an
80-bit structure.

But the rotated bitboard technique helps a great deal. For this I need 80-square
rotation bitboards like the ones below:

int init_r90[80] = { 70, 60, 50, 40, 30, 20, 10, 0,
                     71, 61, 51, 41, 31, 21, 11, 1,
                     72, 62, 52, 42, 32, 22, 12, 2,
                     73, 63, 53, 43, 33, 23, 13, 3,
                     74, 64, 54, 44, 34, 24, 14, 4,
                     75, 65, 55, 45, 35, 25, 15, 5,
                     76, 66, 56, 46, 36, 26, 16, 6,
                     77, 67, 57, 47, 37, 27, 17, 7,
                     78, 68, 58, 48, 38, 28, 18, 8,
                     79, 69, 59, 49, 39, 29, 19, 9 };

int init_l90[80] = { 7, 15, 23, 31, 39, 47, 55, 63, 71, 79,
                     6, 14, 22, 30, 38, 46, 54, 62, 70, 78,
                     5, 13, 21, 29, 37, 45, 53, 61, 69, 77,
                     4, 12, 20, 28, 36, 44, 52, 60, 68, 76,
                     3, 11, 19, 27, 35, 43, 51, 59, 67, 75,
                     2, 10, 18, 26, 34, 42, 50, 58, 66, 74,
                     1,  9, 17, 25, 33, 41, 49, 57, 65, 73,
                     0,  8, 16, 24, 32, 40, 48, 56, 64, 72, };

int diag_sq[80] = {                0,
                                 1,  0,
                               2,  1,  0,
                             3,  2,  1,  0,
                           4,  3,  2,  1,  0,
                         5,  4,  3,  2,  1,  0,
                       6,  5,  4,  3,  2,  1,  0,
                     7,  6,  5,  4,  3,  2,  1,  0,
                       7,  6,  5,  4,  3,  2,  1,  0,
                         7,  6,  5,  4,  3,  2,  1,  0,
                           6,  5,  4,  3,  2,  1,  0,
                             5,  4,  3,  2,  1,  0,
                               4,  3,  2,  1,  0,
                                 3,  2,  1,  0,
                                   2,  1,  0,
                                     1,  0,
                                       0 };

int bias_rl45[80] = {
					               0,
                                 1,  1,
                               3,  3,  3,
                             6,  6,  6,  6,
                          10, 10, 10, 10, 10,
                        15, 15, 15, 15, 15, 15,
                      21, 21, 21, 21, 21, 21, 21,
                    28, 28, 28, 28, 28, 28, 28, 28,
                      36, 36, 36, 36, 36, 36, 36, 36,
                        44, 44, 44, 44, 44, 44, 44, 44,
                          52, 52, 52, 52, 52, 52, 52,
                            59, 59, 59, 59, 59, 59,
                              65, 65, 65, 65, 65,
                                70, 70, 70, 70,
                                  74, 74, 74,
                                    77, 77,
                                      79 };


int init_l45[80] = {               0,
                                 2,  5,
                               9, 14,  20,
                             27, 35, 43,  51,
                            1,  4,  8,  13, 19,
                          26, 34, 42, 50, 58,  3,
                         7, 12, 18, 25, 33, 41, 49,
                       57, 64, 6, 11, 17, 24, 32,  40,
                         48, 56, 63, 69, 10, 16, 23, 31,
                           39, 47, 55, 62, 68, 73, 15, 22,
                             30, 38, 46, 54, 61, 67, 72,
                               76, 21, 29, 37, 45, 53,
                                 60, 66, 71, 75, 78,
                                   28, 36, 44, 52,
                                     59, 65, 70,
                                       74, 77,
                                         79 };


int init_ul45[80] = {               0,
                                  10, 1,
                               20,  11, 2,
                             30, 21, 12,  3,
                           40, 31, 22, 13,  4,
                         50, 41, 32, 23, 14,  5,
                       60, 51, 42, 33, 24, 15,  6,
                     70, 61, 52, 43, 34, 25, 16,  7,
                       71, 62, 53, 44, 35, 26, 17,  8,
                         72, 63, 54, 45, 36, 27, 18,  9,
                           73, 64, 55, 46, 37, 28, 19,
                             74, 65, 56, 47, 38, 29,
                               75, 66, 57, 48, 39,
                                 76, 67, 58, 49,
                                   77, 68, 59,
                              		 78, 69,
                                 	   79 };



int init_ur45[80] = {             	 	9, // 0
									  8,   19, // 2
								    7,  18,  29, // 5
                                  6, 17,  28,  39, // 9
                                5, 16, 27,  38,  49, // 14
                              4, 15, 26, 37,  48,  59, // 20
                            3, 14, 25, 36, 47,  58,  69, // 27
                          2, 13, 24, 35, 46, 57,   68,  79, // 35
                        1, 12, 23, 34, 45,  56,  67,  78, // 43
                      0,  11, 22, 33, 44, 55, 66, 77, // 51
                        10, 21, 32, 43, 54, 65, 76, // 58
                         20, 31, 42, 53, 64, 75, // 64
                           30, 41, 52, 63, 74, // 69
                             40, 51, 62, 73, // 73
                               50, 61, 72, // 76
                                 60, 71, // 78
                                   70
                                   };



int init_r45[80] = {				    44, // 0
									  36, 28, // 2
								    21, 15, 10, // 5
                                   6,  3,  1, 0, // 9
                                52, 45, 37, 29, 22, // 14
                              16, 11,  7,  4,  2, 59, // 20
                            53, 46, 38, 30, 23, 17, 12, // 27
                           8,  5, 65, 60, 54, 47, 39, 31, // 35
                        24, 18, 13,  9, 70, 66, 61, 55, // 43
                      48, 40, 32, 25, 19, 14, 74, 71, // 51
                        67, 62, 56, 49, 41, 33, 26, // 58
                         20, 77, 75, 72, 68, 63, // 64
                           57, 50, 42, 34, 27, // 69
                             79, 78, 76, 73, // 73
                               69, 64, 58, // 76
                                 51, 43, // 78
                                   35
                                   };


int diagonal_length[80] = {         1,
                                  2,  2,
                                3,  3,  3,
                              4,  4,  4,  4,
                            5,  5,  5,  5,  5,
                          6,  6,  6,  6,  6,  6,
                        7,  7,  7,  7,  7,  7,  7,
                      8,  8,  8,  8,  8,  8,  8,  8,
                        8,  8,  8,  8,  8,  8,  8,  8,
                     	  8,  8,  8,  8,  8,  8,  8,  8,
	                   		7,  7,  7,  7,  7,  7,  7,
	                     	  6,  6,  6,  6,  6,  6,
	                       		5,  5,  5,  5,  5,
	                         	  4,  4,  4,  4,
	                            	3,  3,  3,
	                              	  2,  2,
	                                	1 };


And now I can initialize all of the attack data, like this:

void InitBishopAttacks(void)
{
    int square, pcs, attacks;
    int rsq, tsq, i, sq;
    int mask;



  //initialize the rotated attack board that is based on one that is
 // rotated left 45 degrees (which lines up the (a8-j1) diagonal
 // horizontally.

    for (square=0;square<80;square++)
    {
      for (i=0;i<256;i++)
      {
        bishop_attacks_rl45[square*256+i]=BitBoard_0;
        bishop_mobility_rl45[square][i]=0;
      }
      for (pcs=0;pcs<(1<<diagonal_length[init_l45[square]]);pcs++)
      {
        rsq=init_l45[square];
        tsq=diag_sq[rsq];
        attacks=InitializeFindAttacks(tsq,pcs,diagonal_length[rsq])<<
                          (8-diagonal_length[rsq]);
        while (attacks)
        {
          sq=first_one_8bit[attacks];
          bishop_attacks_rl45[square*256+pcs]=
            bishop_attacks_rl45[square*256+pcs] |
               SetMask(init_ul45[sq+bias_rl45[rsq]]);
          attacks=attacks&(~(1<<(7-sq)));
        }
      }
      mask=(1<<diagonal_length[init_l45[square]])-1;
      for (pcs=0;pcs<256;pcs++)
      {
        if ((pcs&mask) != pcs)
          bishop_attacks_rl45[square*256+pcs]=
            bishop_attacks_rl45[square*256+(pcs&mask)];
        bishop_mobility_rl45[square][pcs]=
          PopCnt(bishop_attacks_rl45[square*256+pcs]);
      }
    }


  //initialize the rotated attack board that is based on one that is
 // rotated right 45 degrees (which lines up the (a1-j8) diagonal
 // horizontally,

    for (square=0;square<80;square++)
    {
      for (i=0;i<256;i++)
      {
        bishop_attacks_rr45[square*256+i]=BitBoard_0;
        bishop_mobility_rr45[square][i]=0;
      }
      for (pcs=0;pcs<(1<<diagonal_length[init_r45[square]]);pcs++)
      {
        rsq=init_r45[square];
        tsq=diag_sq[rsq];
        attacks=InitializeFindAttacks(tsq,pcs,diagonal_length[rsq]) <<
(8-diagonal_length[rsq]);
        while (attacks)
        {
          sq=first_one_8bit[attacks];
          bishop_attacks_rr45[square*256+pcs] |=
SetMask(init_ur45[sq+bias_rl45[rsq]]);
          attacks=attacks&(~(1<<(7-sq)));
        }
      }
      mask=(1<<diagonal_length[init_r45[square]])-1;
      for (pcs=0;pcs<256;pcs++)
      {
        if ((pcs&mask) != pcs)
          bishop_attacks_rr45[square*256+pcs]=
            bishop_attacks_rr45[square*256+(pcs&mask)];
        bishop_mobility_rr45[square][pcs]=
          PopCnt(bishop_attacks_rr45[square*256+pcs]);
      }
    }

}

Not to forget our friend the Knight...


void InitKnightAttacks(void)
{
	int i;
	BITBOARD temp = {0, 0x8000000000000000}; // left-most bit of 80 is set
	// shift this bit on this bit board right and OR to make 80 knight attack maps
	// ranks are numbered from 0 to 7 starting at A1
	// files are numbered 0 to 9 starting at A1

	for(i=0; i<80; i++) // i is square number from 0 to 79, left to right, bottom
to top, A1 to J8
	{
		knight_attacks[i].b1=0;
		knight_attacks[i].b2=0;

		if(File(i)<9 && Rank(i)<6) // we can move right 1 up 2 (+21)
			knight_attacks[i] |= ( temp>>(i+21) );
		if(File(i)<8 && Rank(i)<7) // we can move right 2 up 1 (+12)
			knight_attacks[i] |= ( temp>>(i+12) );

		if(File(i)<9 && Rank(i)>1) // we can move right 1 down 2 (-19)
			knight_attacks[i] |= ( temp>>(i-19) );
		if(File(i)<8 && Rank(i)>0) // we can move right 2 down 1 (-8)
			knight_attacks[i] |= ( temp>>(i-8) );

		if(File(i)>0 && Rank(i)>1) // we can move left 1 down 2 (-21)
			knight_attacks[i] |= ( temp>>(i-21) );
		if(File(i)>1 && Rank(i)>0) // we can move left 2 down 1 (-12)
			knight_attacks[i] |= ( temp>>(i-12) );

		if(File(i)>0 && Rank(i)<6) // we can move left 1 up 2 (+19)
			knight_attacks[i] |= ( temp>>(i+19) );
		if(File(i)>1 && Rank(i)<7) // we can move left 2 up 1 (+8)
			knight_attacks[i] |= ( temp>>(i+8) );
	}
}


And the pawn...

void InitializePawnAttacks(void)
{

  int i, j, sq;

  static const int bishopsq[4]={-11,-9,9,11};

  for(i=0;i<80;i++)
  {
    w_pawn_attacks[i]=BitBoard_0;
    if (i < 70)
      for(j=2;j<4;j++)
      {
        sq=i+bishopsq[j];
        if((abs(Rank(sq)-Rank(i))==1) &&
           (abs(File(sq) - File(i))==1) &&
              (sq < 80) && (sq > -1))
          w_pawn_attacks[i] |= mask_1>>sq;
      }
    b_pawn_attacks[i]=BitBoard_0;
    if (i > 9)
      for(j=0;j<2;j++)
      {
        sq=i+bishopsq[j];
        if((abs(Rank(sq)-Rank(i))==1) &&
           (abs(File(sq)-File(i))==1) &&
              (sq < 80) && (sq > -1))
          b_pawn_attacks[i] |= mask_1>>sq;
      }
  }
}

But now I have to do some additional housekeeping for the wider board for pawn
masks...

void InitializePawnMasks(void)
{
  int i;
  BITBOARD m1,m2;

  //  initialize isolated pawn masks, which are nothing more than 1's on
  //  the files adjacent to the pawn file.

  for (i=0;i<80;i++)
  {
    if (!File(i)) mask_pawn_isolated[i]=file_mask[File(i)+1];
    else if (File(i) == 9) mask_pawn_isolated[i]=file_mask[File(i)-1];
    else mask_pawn_isolated[i]=file_mask[File(i)-1] | file_mask[File(i)+1];
  }

/*
  masks to determine if a pawn is protected by another pawn or not.
  also masks to detect "duos" (pawns side-by-side only).
*/
  for (i=10;i<70;i++)
  {
    if (File(i)>0 && File(i)<9)
    {
      mask_pawn_duo[i]=SetMask(i-1) | SetMask(i+1);
      mask_pawn_protected_w[i]=SetMask(i-1) | SetMask(i+1);
      if (i > 19) mask_pawn_protected_w[i]|=SetMask(i-9) | SetMask(i-11);
      mask_pawn_protected_b[i]=SetMask(i-1) | SetMask(i+1);
      if (i < 60) mask_pawn_protected_b[i]|=SetMask(i+9) | SetMask(i+11);
    }
    else if (File(i) == 0)
    {
      mask_pawn_duo[i]=SetMask(i+1);
      mask_pawn_protected_w[i]=SetMask(i+1);
      if (i > 19) mask_pawn_protected_w[i]|=SetMask(i-9);
      mask_pawn_protected_b[i]=SetMask(i+1);
      if (i < 60) mask_pawn_protected_b[i]|=SetMask(i+11);
    }
    else if (File(i) == 9)
    {
      mask_pawn_duo[i]=SetMask(i-1);
      mask_pawn_protected_w[i]=SetMask(i-1);
      if (i > 19) mask_pawn_protected_w[i]|=SetMask(i-11);
      mask_pawn_protected_b[i]=SetMask(i-1);
      if (i < 60) mask_pawn_protected_b[i]|=SetMask(i+9);
    }
  }

  //  initialize passed pawn masks, which are nothing more than 1's on
  //  the pawn's file and the adjacent files, but only on ranks that are
  //  in "front" of the pawn.

  for (i=0;i<80;i++)
  {
    if (!File(i))
    {
      mask_pawn_passed_w[i]=plus10dir[i] | plus10dir[i+1];
      mask_pawn_passed_b[i]=minus10dir[i] | minus10dir[i+1];
    }
    else if (File(i) == 9)
    {
      mask_pawn_passed_w[i]=plus10dir[i-1] | plus10dir[i];
      mask_pawn_passed_b[i]=minus10dir[i-1] | minus10dir[i];
    }
    else
    {
      mask_pawn_passed_w[i]=plus10dir[i-1] | plus10dir[i] | plus10dir[i+1];
      mask_pawn_passed_b[i]=minus10dir[i-1] | minus10dir[i] | minus10dir[i+1];
    }
  }

  //  these masks are used to determine if the other side has any pawns
  //  that can attack [square].

  for (i=10;i<70;i++)
  {
    if (!File(i))
    {
      mask_no_pawn_attacks_w[i]=minus10dir[i+1];
      mask_no_pawn_attacks_b[i]=plus10dir[i+1];
    }
    else if (File(i) == 9)
    {
      mask_no_pawn_attacks_w[i]=minus10dir[i-1];
      mask_no_pawn_attacks_b[i]=plus10dir[i-1];
    }
    else
    {
      mask_no_pawn_attacks_w[i]=minus10dir[i-1] | minus10dir[i+1];
      mask_no_pawn_attacks_b[i]=plus10dir[i+1] | plus10dir[i-1];
    }
  }

  //  enpassant pawns are on either file adjacent to the current file, and
  //  on the same rank.

  for (i=0;i<80;i++) mask_eptest[i]=BitBoard_0;
  for (i=31;i<39;i++) mask_eptest[i]=SetMask(i-1) | SetMask(i+1);
  for (i=41;i<49;i++) mask_eptest[i]=SetMask(i-1) | SetMask(i+1);
  mask_eptest[A4]=SetMask(B4);
  mask_eptest[J4]=SetMask(I4);
  mask_eptest[A5]=SetMask(B5);
  mask_eptest[J5]=SetMask(I5);


  not_rook_pawns=file_mask[FILEB] | file_mask[FILEC] |
                 file_mask[FILED] | file_mask[FILEE] |
                 file_mask[FILEF] | file_mask[FILEG] |
                 file_mask[FILEH] | file_mask[FILEI];
}

And the rook...

void InitRookAttacks(void) // this generates 102,400 attack boards for table
lookup!
{
    int square, pcs, attacks;
    int rsq, tsq;
    int mask, i, sq;

/*
  initialize the attack board that is based on the
  normal gchess board
*/
    for (square=0; square<80; square++) // 80 squares
    {
      for (i=0; i<1024; i++) // 1024 possible bit combinations in a rank, 8
ranks with 10 squares
      {
        rook_attacks_r0[square*1024+i] = BitBoard_0; // initialize the bitboard
to 0
        rook_mobility_r0[square][i]=0;
      }
      for (pcs=0; pcs<1024; pcs++)
      {
        attacks=InitializeFindAttacks(9-File(square),pcs,10); // (int square,
int pieces, int length)
        while (attacks)
        {
          sq=first_one_10bit[attacks]; // get the leftmost attack bit number
          rook_attacks_r0[square*1024+pcs] |= SetMask((Rank(square)*10)+sq); //
set that bit in the attack board
          																 // on the appropriate rank
          attacks &= (~(1<<(9-sq))); // delete the bit in the attacks map
      	}
        rook_mobility_r0[square][pcs]=PopCnt(rook_attacks_r0[square*1024+pcs]);
// mobility is the number of squares we can move to
      }
    }

/*
  initialize the rotated attack board that is based on one that
  rotated left 90 degrees (which lines up a file horizontally,
  rather than its normal vertical orientation.)
*/
    for (square=0;square<80;square++)
    {
      for (i=0;i<256;i++) // there are now 10 ranks with 8 squares
      {
        rook_attacks_rl90[square*256+i] = BitBoard_0;
        rook_mobility_rl90[square][i]=0;
      }
      for (pcs=0;pcs<256;pcs++)
      {
        attacks=InitializeFindAttacks(Rank(square),pcs,8); // rank of the square
is now the square number, moving vertically
        while (attacks)
        {
          sq=first_one_8bit[attacks];
          rook_attacks_rl90[square*256+pcs] |=
SetMask(init_r90[(File(square)*8)+sq]);
          attacks &= (~(1<<(7-sq)));
        }

rook_mobility_rl90[square][pcs]=PopCnt(rook_attacks_rl90[square*256+pcs]);
      }
    }
}

Of course I have to change the crafty "FirstOne" and "LastOne" operators...

int FirstOne(BITBOARD arg1) // returns lowest bit number 0-79
{
	if(arg1.b1) // the 64-bit part
	{
	    if (arg1.b1>>48)
	      return (first_one[arg1.b1>>48]);
	    if ((arg1.b1>>32)&65535LL)
	      return (first_one[(arg1.b1>>32)&65535LL]+16);
	    if ((arg1.b1>>16)&65535LL)
	      return (first_one[(arg1.b1>>16)&65535LL]+32);
	    return (first_one[arg1.b1&65535LL]+48);
   	}
   	return (first_one[arg1.b2]+64); // the 16-bit part
}

int LastOne(BITBOARD arg1) // returns higest bit number 0-79
{
	if(arg1.b2) // the 16-bit part
		return (last_one[arg1.b2]+64);
    if (arg1.b1&65535)
      return (last_one[arg1.b1&65535LL]+48);
    if ((arg1.b1>>16)&65535LL)
      return (last_one[(arg1.b1>>16)&65535LL]+32);
    if ((arg1.b1>>32)&65535LL)
      return (last_one[(arg1.b1>>32)&65535LL]+16);
    return (last_one[arg1.b1>>48]);
}

Well, that is essentially it in a nutshell. So you see, there are no secrets,
just a lot of bits being manipulated.



This page took 0.01 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.