My new almost bb engine does not use bbs to generate moves. It uses them for other things though. Each piece in the SOA has a bb stack. When a move is made the board is scanned to determine which pieces bb has been invalidated. The complete bb for pawns, knights and the kings. The rays for the sliders. I'll just explain the sliders. I set a bit for each invalidated ray. On needing moves for an invalidated ray that bb is pushed onto the piece bb stack. Then the ray is removed by a ray zero mask. The new ray generated by classic bb ray generation is ored in. Popcount is used on the new ray to get the number of moves. That number is saved in the first element of a ray move array. Example, unsigned char rayNE[64][8]. The rest of the elements contain actual to_squares in the direction of the array. For move generation a for_loop is used. For capture only generation only the last ts is checked. So move generation is done by precomputed move list and the bbs are used for evaluation, move from tt verification and other things. And no bb is generated until needed. It seems imho to be the best of all worlds.
Sample code.
Code: Select all
void InitBBGen() {
s32 i, j, s;
for (i = 0; i < 40; i++) {
t->top[i] = 0;
t->inv[i] = 0;
for (j = 0; j < 200; j++)
t->bbStack[i][j] = 0;
}
for (s = 0; s <= H8; s++) {
i = t->brd[s];
j = t->typ[i];
switch (j) {
case NONE:
break;
case WP:
t->inv[i] = 0b00000000;
WPBBG(t,s,&t->bbStack[i][t->top[i]]);
break;
case WN:
t->inv[i] = 0b00000000;
WNBBG(t,s,&t->bbStack[i][t->top[i]]);
break;
case WB:
t->inv[i] = 0b00001111;
WSBBG(t,s,&t->inv[i], &t->bbStack[i][t->top[i]]);
break;
case WR:
t->inv[i] = 0b11110000;
WSBBG(t,s,&t->inv[i], &t->bbStack[i][t->top[i]]);
break;
case WQ:
t->inv[i] = 0b11111111;
WSBBG(t,s,&t->inv[i], &t->bbStack[i][t->top[i]]);
break;
case WK:
t->inv[i] = 0b00000000;
WKBBG(t,s,&t->bbStack[i][t->top[i]]);
break;
case WCKS: case WCQS: case WTER:
break;
case BP:
t->inv[i] = 0b00000000;
BPBBG(t,s,&t->bbStack[i][t->top[i]]);
break;
case BN:
t->inv[i] = 0b00000000;
BNMMG(t,s,&t->bbStack[i][t->top[i]]);
break;
case BB:
t->inv[i] = 0b00001111;
BSBBG(t,s,&t->inv[i], &t->bbStack[i][t->top[i]]);
break;
case BR:
t->inv[i] = 0b11110000;
BSMMG(t,s,&t->inv[i], &t->bbStack[i][t->top[i]]);
break;
case BQ:
t->inv[i] = 0b11111111;
BSBBG(t,s,&t->inv[i], &t->bbStack[i][t->top[i]]);
break;
case BK:
t->inv[i] = 0b00000000;
BKBBG(t,s,&t->bbStack[i][t->top[i]]);
break;
}
}
}
// White Pawn bb Generator
void WPBBG(threadS *t, s32 fs, u64 *bb) {
s32 row = fs >> 3;
switch (row) {
case 0:
break;
case 1:
*bb = ((sqWPc[fs] & t->bPieces) | (sqWPm[fs] & below[FirstBit64(sqWPm[fs] & t->aPieces)]));
break;
case 2:
case 3:
*bb = ((sqWPc[fs] & t->bPieces) | (sqWPm[fs] & t->nPieces));
break;
case 4:
*bb = ((sqWPc[fs] & t->bPieces | t->esq) | (sqWPm[fs] & t->nPieces));
break;
case 5: case 6:
*bb = ((sqWPc[fs] & t->bPieces) | (sqWPm[fs] & t->nPieces));
break;
}
}
// White Knight bb Generator
void WNBBG(threadS *t, s32 fs, u64 *bb) {
*bb = (sqrKN[fs] & ~t->wPieces);
}
// White King bb Generator
void WKBBG(threadS *t, s32 fs, u64 *bb) {
*bb = (sqrKG[fs] & ~t->wPieces);
}
// White Slider bb Generator
void WSBBG(threadS *t, s32 fs, u32 *inv, u64 *bb) {
s32 i;
do {
i = FirstBit32(*inv);
*inv ^= (1 << i);
switch (i) {
case NW:
*bb &= andNW[fs];
*bb |= (rayNW[fs] & belowInc[FirstBit64(rayNW[fs] & t->aPieces)]);
break;
case NE:
*bb &= andNE[fs];
*bb |= (rayNE[fs] & belowInc[FirstBit64(rayNE[fs] & t->aPieces)]);
break;
case SW:
*bb &= andSW[fs];
*bb |= (raySW[fs] & aboveInc[LastBit64(raySW[fs] & t->aPieces)]);
break;
case SE:
*bb &= andSE[fs];
*bb |= (raySE[fs] & aboveInc[LastBit64(raySE[fs] & t->aPieces)]);
break;
case NN:
*bb &= andNN[fs];
*bb |= (rayNN[fs] & belowInc[FirstBit64(rayNN[fs] & t->aPieces)]);
break;
case EE:
*bb &= andEE[fs];
*bb |= (rayEE[fs] & belowInc[FirstBit64(rayEE[fs] & t->aPieces)]);
break;
case SS:
*bb &= andSS[fs];
*bb |= (raySS[fs] & aboveInc[LastBit64(raySS[fs] & t->aPieces)]);
break;
case WW:
*bb &= andWW[fs];
*bb |= (rayWW[fs] & aboveInc[LastBit64(rayWW[fs] & t->aPieces)]);
break;
}
} while (*inv);
*bb &= ~t->wPieces;
}