If I were a Professor of Computer Science

Discussion of chess software programming and technical issues.

Moderator: Ras

Mike Sherwin
Posts: 965
Joined: Fri Aug 21, 2020 1:25 am
Location: Planet Earth, Sol system
Full name: Michael J Sherwin

Re: If I were a Professor of Computer Science

Post by Mike Sherwin »

Seems I made a mistake for the rooks. Here are the corrected versions.

Code: Select all

u64 RookAttacks(sq, occ) {
    u64 vBlockers = occ & vFileMask[sq];
    u64 hBlockers = occ & hRankMask[sq]; 
    u64 vIndex = (vBlockers >> (sq & 7) * MAIN_DIAGONAL) >> 57;
    u64 hIndex = hBlockers >> ((sq >> 3) + 1);
    return vSuperSet[sq][vIndex] & hSuperSet[sq][hIndex];

Code: Select all

u64 BishopAttacks(sq, occ) {
    u64 dBlockers = occ & diagonalMask[sq];
    u64 aBlockers = occ & antidiagMask[sq]; 
    u64 dIndex = (dBlockers * 0x0202020202020202) >> 58;
    u64 aIndex = (aBlockers * 0x0202020202020202) >> 58;
    return dSuperSet[sq][dIndex] & aSuperSet[sq][aIndex];
}
Mike Sherwin
Posts: 965
Joined: Fri Aug 21, 2020 1:25 am
Location: Planet Earth, Sol system
Full name: Michael J Sherwin

Re: If I were a Professor of Computer Science

Post by Mike Sherwin »

This was a rough day. Initializing complicated data structures is I think the hardest part of programming. And I'm sure the way I did it made it even harder. I was only able to initialize the vSuperset[sq][vIndex] array. It did test good in the debugger. :D I got the variable names a little bit confused but I'll correct those tomorrow.

Code: Select all

for (vocc = 0; vocc < 64; vocc++) { // should be vIndex
	  vSuperset[sq][vocc] = 0;
	  occ = (vocc << 1) | 0x81; // " " vocc
	  set = 0; // " " occ
	  for (s08 i = 0; i < 8; i++) {
		if (((1 << i) & occ)) set |= 1ull << ((i << 3) << x);
	  }
	  for (ts = sq + 8; (ts >> 3) <= RANK8; ts += 8) {
		if (!(set & 1ull << ts)) {
		  vSuperset[sq][vocc] |= 1ull << ts;
		}
		else {
		  vSuperset[sq][vocc] |= 1ull << ts;
		  break;
		}
	  } 
	  for (ts = sq - 8; (ts >> 3) >= RANK1; ts -= 8) {
		if (!(set & 1ull << ts)) {
		  vSuperset[sq][vocc] |= 1ull << ts;
		}
		else {
		  vSuperset[sq][vocc] |= 1ull << ts;
		  break;
		}
	  } 
	}
This code takes a vIndex and rotates it to the aFile then << (sq & 7) x. After the vertical occ is in place two for loops search from sq looking for blockers while or-ing bits into vSuperset[sq][vIndex]. I could not find out how to do a reverse kindergarten rotation. The CPW is not very strong on initializing tables. :(
Mike Sherwin
Posts: 965
Joined: Fri Aug 21, 2020 1:25 am
Location: Planet Earth, Sol system
Full name: Michael J Sherwin

Re: If I were a Professor of Computer Science

Post by Mike Sherwin »

Mike Sherwin wrote: Wed Jan 04, 2023 9:43 am This was a rough day. Initializing complicated data structures is I think the hardest part of programming. And I'm sure the way I did it made it even harder. I was only able to initialize the vSuperset[sq][vIndex] array. It did test good in the debugger. :D I got the variable names a little bit confused but I'll correct those tomorrow.

Code: Select all

for (vocc = 0; vocc < 64; vocc++) { // should be vIndex
	  vSuperset[sq][vocc] = 0;
	  occ = (vocc << 1) | 0x81; // " " vocc
	  set = 0; // " " occ
	  for (s08 i = 0; i < 8; i++) {
		if (((1 << i) & occ)) set |= 1ull << ((i << 3) << x);
	  }
	  for (ts = sq + 8; (ts >> 3) <= RANK8; ts += 8) {
		if (!(set & 1ull << ts)) {
		  vSuperset[sq][vocc] |= 1ull << ts;
		}
		else {
		  vSuperset[sq][vocc] |= 1ull << ts;
		  break;
		}
	  } 
	  for (ts = sq - 8; (ts >> 3) >= RANK1; ts -= 8) {
		if (!(set & 1ull << ts)) {
		  vSuperset[sq][vocc] |= 1ull << ts;
		}
		else {
		  vSuperset[sq][vocc] |= 1ull << ts;
		  break;
		}
	  } 
	}
This code takes a vIndex and rotates it to the aFile then << (sq & 7) x. After the vertical occ is in place two for loops search from sq looking for blockers while or-ing bits into vSuperset[sq][vIndex]. I could not find out how to do a reverse kindergarten rotation. The CPW is not very strong on initializing tables. :(
I renamed some variables so the code can be more easily understood. And a couple of bugs were fixed. All four corners and e4 were tested. It worked perfectly for those squares. I hope it is bug free now.

Code: Select all

	for (vIndex = 0; vIndex < 64; vIndex++) {
	  vSuperset[sq][vIndex] = 0;
	  vocc = vIndex << 1;
	  blockers = 0;
	  for (s08 i = 0; i < 8; i++) {
		if (((1 << i) & vocc)) blockers |= ((1ull << (i << 3)) << x);
	  }
	  blockers |= (0x0100000000000001ull << x);
	  for (ts = sq + 8; (ts >> 3) <= RANK8; ts += 8) {
		if (!(blockers & 1ull << ts)) {
		  vSuperset[sq][vIndex] |= 1ull << ts;
		}
		else {
		  vSuperset[sq][vIndex] |= 1ull << ts;
		  break;
		}
	  } 
	  for (ts = sq - 8; (ts >> 3) >= RANK1; ts -= 8) {
		if (!(blockers & 1ull << ts)) {
		  vSuperset[sq][vIndex] |= 1ull << ts;
		}
		else {
		  vSuperset[sq][vIndex] |= 1ull << ts;
		  break;
		}
	  } 
	}
Mike Sherwin
Posts: 965
Joined: Fri Aug 21, 2020 1:25 am
Location: Planet Earth, Sol system
Full name: Michael J Sherwin

Re: If I were a Professor of Computer Science

Post by Mike Sherwin »

Here is the initialization for the rank attacks. Tonight I realized that supersets are not required in this version of the move generator. The final return would the be, return vPartialSet[sq][vIndex] | hPartialSet[sq][hIndex];
And I'll have to change the name of the move generator to Kindergarten Split Index Partial Set Yielding bitboards, SIPSY bitboards. :lol:

Code: Select all

// horizontal indexes
	  for (hIndex = 0; hIndex < 64; hIndex++) {
		hSuperset[sq][hIndex] = 0;
		hocc = (hIndex << 1) ;
		blockers = ((u64)(hocc | 0x81) << (y * 8));
		for (ts = sq + 1; ts <= y * 8 + 7; ts++) {
		  if (!(blockers & 1ull << ts)) {
			hSuperset[sq][hIndex] |= 1ull << ts;
		  }
		  else {
			hSuperset[sq][hIndex] |= 1ull << ts;
			break;
		  }
		}
		for (ts = sq - 1; ts >= y * 8; ts--) {
		  if (!(blockers & 1ull << ts)) {
			hSuperset[sq][hIndex] |= 1ull << ts;
		  }
		  else {
			hSuperset[sq][hIndex] |= 1ull << ts;
			break;
		  }
		}
	  }
I just looked and I see that Gerd Isenberg has not posted since March 2022. Does anyone know if Gerd is okay?
Mike Sherwin
Posts: 965
Joined: Fri Aug 21, 2020 1:25 am
Location: Planet Earth, Sol system
Full name: Michael J Sherwin

Re: If I were a Professor of Computer Science

Post by Mike Sherwin »

It took me two whole days working every waking hour to write the code to initialize the diagonal look up tables. I had to change my thinking to get it right. The anti diagonal is exactly similar except it has +- 7 instead of +-9. Also to be consistent I'm going to rewrite the rank and file tables. It is really quite different now. The index as blockers were being placed (or I was trying to anyway) into u64 blockers;. That was totally not necessary! Just, if (docc & (1 << (ts & 7))) break;, was easy enough! And it took hours and hours to realize that the test in the for loops cannot be done first. That means I should have used a do loop. But now that they are done I kind of like it the way it is. And now that the battle of initialization has been won my new move generator code should be done by tomorrow! :D

Code: Select all

	// diagonal indexes
	for (dIndex = 0; dIndex < 64; dIndex++) {
	  dSubset[sq][dIndex] = 0;
	  docc = dIndex << 1;
	  if ((sq & 7) != FILEh && (sq >> 3) != RANK8) {
		for (ts = sq + 9; ; ts += 9) {
		  dSubset[sq][dIndex] |= (1ull << ts);
		  if (docc & (1 << (ts & 7))) break;
		  if ((ts & 7) == FILEh || (ts >> 3) == RANK8) break;
		}
	  }
	  if ((sq & 7) != FILEa && (sq >> 3) != RANK1) {
		for (ts = sq - 9; ; ts -= 9) {
		  dSubset[sq][dIndex] |= (1ull << ts);
		  if (docc & (1 << (ts & 7))) break;
		  if ((ts & 7) == FILEa || (ts >> 3) == RANK1) break;
		}
	  }
	}

Code: Select all

	// anti diagonal indexes
	for (aIndex = 0; aIndex < 64; aIndex++) {
	  aSubset[sq][aIndex] = 0;
	  aocc = aIndex << 1;
	  if ((sq & 7) != FILEh && (sq >> 3) != RANK8) {
		for (ts = sq + 7; ; ts += 7) {
		  aSubset[sq][aIndex] |= (1ull << ts);
		  if (aocc & (1 << (ts & 7))) break;
		  if ((ts & 7) == FILEh || (ts >> 3) == RANK8) break;
		}
	  }
	  if ((sq & 7) != FILEa && (sq >> 3) != RANK1) {
		for (ts = sq - 7; ; ts -= 7) {
		  aSubset[sq][aIndex] |= (1ull << ts);
		  if (aocc & (1 << (ts & 7))) break;
		  if ((ts & 7) == FILEa || (ts >> 3) == RANK1) break;
		}
	  }
	}
Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: If I were a Professor of Computer Science

Post by Henk »

What does the score of a move mean?

I think you will generate a lot of new move structures because score will change often or not.
So why store a score in a move?
Henk
Posts: 7251
Joined: Mon May 27, 2013 10:31 am

Re: If I were a Professor of Computer Science

Post by Henk »

O wait you probably update the score per move.
Mike Sherwin
Posts: 965
Joined: Fri Aug 21, 2020 1:25 am
Location: Planet Earth, Sol system
Full name: Michael J Sherwin

Re: If I were a Professor of Computer Science

Post by Mike Sherwin »

Henk wrote: Wed Jan 11, 2023 10:05 pm O wait you probably update the score per move.
When the move list is created the moves are scored by their PSQTs for move ordering. And for performing a shallow search on the remaining moves. If depth > 3 play a move then call search with depth 1 to give each move a score.
Mike Sherwin
Posts: 965
Joined: Fri Aug 21, 2020 1:25 am
Location: Planet Earth, Sol system
Full name: Michael J Sherwin

Re: If I were a Professor of Computer Science

Post by Mike Sherwin »

I took a break for a couple days because nothing ever works the first time and I was too stressed after completing the initialization to deal with any more stress right away. Today I risked it and put the new bishop move generator in Bricabrac as it is already a working engine that passes all perft test. And it worked first time! :shock: Unbelievable, :lol: Here is all the applicable code as it is in Bricabrac.

Code: Select all

u64 vMask[64];
u64 hMask[64];
u64 dMask[64];
u64 aMask[64];

u64 vSubset[64][64];
u64 hSubset[64][64];
u64 dSubset[64][64];
u64 aSubset[64][64];

// for each square

    // diagonals
    for (ts = sq + 9, dx = x + 1, dy = y + 1; dx < FILEh && dy < RANK8; dMask[sq] |= 1ull << ts, ts += 9, dx++, dy++);
    for (ts = sq - 9, dx = x - 1, dy = y - 1; dx > FILEa && dy > RANK1; dMask[sq] |= 1ull << ts, ts -= 9, dx--, dy--);

    // anti diagonals
    for (ts = sq + 7, dx = x - 1, dy = y + 1; dx > FILEa && dy < RANK8; aMask[sq] |= 1ull << ts, ts += 7, dx++, dy++);
    for (ts = sq - 7, dx = x + 1, dy = y - 1; dx < FILEh && dy > RANK1; aMask[sq] |= 1ull << ts, ts -= 7, dx--, dy--);

	// diagonal indexes
	for (index = 0; index < 64; index++) {
	  dSubset[sq][index] = 0;
	  occ = index << 1;
	  if ((sq & 7) != FILEh && (sq >> 3) != RANK8) {
		for (ts = sq + 9; ; ts += 9) {
		  dSubset[sq][index] |= (1ull << ts);
		  if (occ & (1 << (ts & 7))) break;
		  if ((ts & 7) == FILEh || (ts >> 3) == RANK8) break;
		}
	  }
	  if ((sq & 7) != FILEa && (sq >> 3) != RANK1) {
		for (ts = sq - 9; ; ts -= 9) {
		  dSubset[sq][index] |= (1ull << ts);
		  if (occ & (1 << (ts & 7))) break;
		  if ((ts & 7) == FILEa || (ts >> 3) == RANK1) break;
		}
	  }
	}

	// anti diagonal indexes
	for (index = 0; index < 64; index++) {
	  aSubset[sq][index] = 0;
	  occ = index << 1;
	  if ((sq & 7) != FILEh && (sq >> 3) != RANK8) {
		for (ts = sq + 7; ; ts += 7) {
		  aSubset[sq][index] |= (1ull << ts);
		  if (occ & (1 << (ts & 7))) break;
		  if ((ts & 7) == FILEh || (ts >> 3) == RANK8) break;
		}
	  }
	  if ((sq & 7) != FILEa && (sq >> 3) != RANK1) {
		for (ts = sq - 7; ; ts -= 7) {
		  aSubset[sq][index] |= (1ull << ts);
		  if (occ & (1 << (ts & 7))) break;
		  if ((ts & 7) == FILEa || (ts >> 3) == RANK1) break;
		}
	  }
	  
// the bishop attack getter
    case WB:
    case BB:
      dBlockers = aPieces & dMask[fs];
      aBlockers = aPieces & aMask[fs];
      dIndex = ((dBlockers * 0x0202020202020202ull) >> 58) & 63;
      aIndex = ((aBlockers * 0x0202020202020202ull) >> 58) & 63;
      bb = (dSubset[fs][dIndex] | aSubset[fs][aIndex]) & notme;
      break;

The rook should follow shortly.
dangi12012
Posts: 1062
Joined: Tue Apr 28, 2020 10:03 pm
Full name: Daniel Infuehr

Re: If I were a Professor of Computer Science

Post by dangi12012 »

Any updates on this topic ? I am looking very much forward to a new original movegenerator! :o
Worlds-fastest-Bitboard-Chess-Movegenerator
Daniel Inführ - Software Developer