Code: Select all
// In GenAllMoves(Thread* t, sMove* m);
case WKC:
mft = ((u64)((board[h1] == WRC) && !(occ & owcs) && !AtkByBlack(t, awcs))) * WCS;
m += (mft == WCS);
mft = ((u64)((board[a1] == WRC) && !(occ & owcl) && !AtkByBlack(t, awcl))) * WCL;
m += (mft == WCL);
[[fallthrough]];
case WK:
atk |= bb = kingMoves[fs] & notme;
break;
Code: Select all
static bool AtkByBlack(Thread* t, u64 b) {
u64 atk = 0;
u64 occ = sides[WHITE] | sides[BLACK];
while (b) {
s32 sq = std::countr_zero(b);
b ^= 1ull << sq;
atk |= (wPawnCaptures[sq] & pawns[BLACK]);
atk |= (knightMoves[sq] & knights[BLACK]);
atk |= (kingMoves[sq] & kings[BLACK]);
atk |= (dSubset[sq][(((occ & dMask[sq]) * file_b2_b7) >> 58)] & (bishops[BLACK] | queens[BLACK]));
atk |= (aSubset[sq][(((occ & aMask[sq]) * file_b2_b7) >> 58)] & (bishops[BLACK] | queens[BLACK]));
atk |= (hSubset[sq][(occ >> hShift[sq]) & 63] & (rooks[BLACK] | queens[BLACK]));
atk |= (vSubset[sq][((((occ >> (sq & 7)) & file_a2_a7) * diag_c2_h7) >> 58)] & (rooks[BLACK] | queens[BLACK]));
}
return (atk != 0);
}
Code: Select all
// 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 & (1ull << (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 & (1ull << (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) != FILEa && (sq >> 3) != RANK8) {
for (ts = sq + 7; ; ts += 7) {
aSubset[sq][index] |= (1ull << ts);
if (occ & (1ull << (ts & 7))) break;
if ((ts & 7) == FILEa || (ts >> 3) == RANK8) break;
}
}
if ((sq & 7) != FILEh && (sq >> 3) != RANK1) {
for (ts = sq - 7; ; ts -= 7) {
aSubset[sq][index] |= (1ull << ts);
if (occ & (1ull << (ts & 7))) break;
if ((ts & 7) == FILEh || (ts >> 3) == RANK1) break;
}
}
}
// vertical indexes
for (index = 0; index < 64; index++) {
vSubset[sq][index] = 0;
uint64_t blockers = 0;
for (int i = 0; i <= 5; i++) {
if (index & (1ull << i)) {
blockers |= (1ull << (((5 - i) << 3) + 8));
}
}
if ((sq >> 3) != RANK8) {
for (ts = sq + 8; ; ts += 8) {
vSubset[sq][index] |= (1ull << ts);
if (blockers & (1ull << (ts - (ts & 7)))) break;
if ((ts >> 3) == RANK8) break;
}
}
if ((sq >> 3) != RANK1) {
for (ts = sq - 8; ; ts -= 8) {
vSubset[sq][index] |= (1ull << ts);
if (blockers & (1ull << (ts - (ts & 7)))) break;
if ((ts >> 3) == RANK1) break;
}
}
}
// horizontal indexes
for (index = 0; index < 64; index++) {
hSubset[sq][index] = 0;
occ = index << 1;
if ((sq & 7) != FILEh) {
for (ts = sq + 1; ; ts += 1) {
hSubset[sq][index] |= (1ull << ts);
if (occ & (1ull << (ts & 7))) break;
if ((ts & 7) == FILEh) break;
}
}
if ((sq & 7) != FILEa) {
for (ts = sq - 1; ; ts -= 1) {
hSubset[sq][index] |= (1ull << ts);
if (occ & (1ull << (ts & 7))) break;
if ((ts & 7) == FILEa) break;
}
}
}
// horizontal shift
hShift[sq] = (sq & 56) + 1;
}
Code: Select all
enum {
WP2, WP3, WP4, WP5, WP6, WP7, WN, WB, WRC, WR, WQ, WKC, WK,
ES,
BP7, BP6, BP5, BP4, BP3, BP2, BN, BB, BRC, BR, BQ, BKC, BK,
WPQ, WPN, WPR, WPB, WCS, WCL,
BPQ, BPN, BPR, BPB, BCS, BCL
};
Code: Select all
case WP5:
sq = mts - ((epbit[sly] == (1ull << mts)) << 3);
mtt = board[sq];
board[mfs] = ES;
board[sq] = ES;
board[mts] = WP6;
pawns[WHITE] ^= (1ull << mfs | 1ull << mts);
sides[WHITE] ^= (1ull << mfs | 1ull << mts);
*types[mtt] ^= (u64)(mtt != ES) << sq;
sides[BLACK] ^= (u64)(mtt != ES) << sq;
mat[BLACK] -= value[mtt];
pos[WHITE] += (wptbl[mts] - wptbl[mfs]);
pos[BLACK] -= tbls[mtt][sq];
break;
These are just a few highlights of Protozoa. Right now I can only make moves verified by the move generator. My last working engine is Bricabrac. It searched approximately 11,000,000 positions a second using a single thread on a Ryzen 9 3950x at 4.2 GHz. This engine will be substantially faster!

One other design feature that is different from Bricabrac is that it will be able to play more than one game at a time. I'm also developing a GUI where one can setup as many positions as there are available threads and analyze all at the same time. Analysis will incorporate a combination of real time reinforcement learning and full width search.
When I get Protozoa to the point it can play a game in a chess gui I will provide a link to the engine.