stegemma wrote: Just to have a reference, in Satana i get perft 6 in:
without test for check at last leave: <4 seconds
with test for check at last leave: >12 seconds
In Nightmare the move generator is very bulky, I don't like to use macros and I want to avoid as many templates as possible.
I generate captures/promotions and quiet moves separately because I do staged move generation.
For pawns I do:
Code: Select all
// pawn moves for white excluding promotions
bbfrom = 0xffffffffff00 & pos->bitboards[White].pawns;
bbto = ~pos->occupied & (bbfrom << 8);
bdt2 = 0xff000000 & ~pos->occupied & (bbto << 8);
while (bbto) {
to = LSB(bbto);
(moves++)->Store(to - 8, to, QuietMove | PawnMove);
bbto &= bbto - 1;
}
while (bdt2) {
to = LSB(bdt2);
(moves++)->Store(to - 16, to, QuietMove | PawnMove | PawnMove2, to - 8);
bdt2 &= bdt2 - 1;
}
if (White == stm) { // white pawn captures and promotions
// right direction
// promotion with capture
bbfrom = 0x7f000000000000 & pos->bitboards[White].pawns;
if (bbto & bbfrom << 9) {
(moves++)->Store(to - 9, to, Promotion | Capture | PawnMove, WhitePiece | Queen);
(moves++)->Store(to - 9, to, Promotion | Capture | PawnMove, WhitePiece | Rook);
(moves++)->Store(to - 9, to, Promotion | Capture | PawnMove, WhitePiece | Knight);
(moves++)->Store(to - 9, to, Promotion | Capture | PawnMove, WhitePiece | Bishop);
}
// capture with pawn
bbfrom = 0x7f7f7f7f7f00 & pos->bitboards[White].pawns;
if (bbto & bbfrom << 9)
(moves++)->Store(to - 9, to, Capture | PawnMove);
// enpassant capture
if (bbep & bbto << 8 & bbfrom << 9)
(moves++)->Store(to - 1, to + 8, Capture | Enpassant | PawnMove, to);
// left direction
// promotion with capture
bbfrom = 0xfe000000000000 & pos->bitboards[White].pawns;
if (bbto & bbfrom << 7) {
(moves++)->Store(to - 7, to, Promotion | Capture | PawnMove, WhitePiece | Queen);
(moves++)->Store(to - 7, to, Promotion | Capture | PawnMove, WhitePiece | Rook);
(moves++)->Store(to - 7, to, Promotion | Capture | PawnMove, WhitePiece | Knight);
(moves++)->Store(to - 7, to, Promotion | Capture | PawnMove, WhitePiece | Bishop);
}
// capture with pawn
bbfrom = 0xfefefefefe00 & pos->bitboards[White].pawns;
if (bbto & bbfrom << 7)
(moves++)->Store(to - 7, to, Capture | PawnMove);
// enpassant capture
if (bbep & bbto << 8 & bbfrom << 7)
(moves++)->Store(to + 1, to + 8, Capture | Enpassant | PawnMove, to);
} // end white
This is with checking for legality and fully updated hash keys etc.
The speed is not very important anyway because move generation only takes about 5% of the total time spent in the program.
Normally I avoid promotions to bishops and in quiescence I only promote to queens.