From 1af0f0dca862465b43751a04b5177a05502ccfd3 Mon Sep 17 00:00:00 2001 From: Terje Date: Tue, 24 Oct 2023 01:24:05 +0200 Subject: [PATCH] Bench: 18586766 --- src/bitboard.c | 5 ++++- src/bitboard.h | 5 +++++ src/board.c | 24 ++++++++++++++++++++++++ src/board.h | 3 +++ src/makemove.c | 13 +++++++------ src/makemove.h | 2 +- src/move.c | 24 ++++++++++++++++++++++++ src/move.h | 3 ++- src/search.c | 9 ++++++--- src/tests.c | 4 +++- src/threads.c | 5 ++--- 11 files changed, 81 insertions(+), 16 deletions(-) diff --git a/src/bitboard.c b/src/bitboard.c index aa82f7b9..5e5d55d8 100644 --- a/src/bitboard.c +++ b/src/bitboard.c @@ -28,6 +28,7 @@ const Bitboard RankBB[RANK_NB] = { rank1BB, rank2BB, rank3BB, rank4BB, rank5BB, rank6BB, rank7BB, rank8BB }; +Bitboard LineBB[64][64]; Bitboard BetweenBB[64][64]; static Bitboard BishopAttacks[5248]; @@ -132,8 +133,10 @@ CONSTR(2) InitBitboards() { for (Square sq1 = A1; sq1 <= H8; sq1++) for (Square sq2 = A1; sq2 <= H8; sq2++) for (PieceType pt = BISHOP; pt <= ROOK; pt++) - if (AttackBB(pt, sq1, BB(sq2)) & BB(sq2)) + if (AttackBB(pt, sq1, BB(sq2)) & BB(sq2)) { + LineBB[sq1][sq2] = (AttackBB(pt, sq1, 0) & AttackBB(pt, sq2, 0)) | BB(sq1) | BB(sq2); BetweenBB[sq1][sq2] = AttackBB(pt, sq1, BB(sq2)) & AttackBB(pt, sq2, BB(sq1)); + } for (Square sq = A1; sq <= H8; ++sq) { diff --git a/src/bitboard.h b/src/bitboard.h index 78bf8f32..44e926f4 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -107,6 +107,7 @@ enum { extern const Bitboard FileBB[FILE_NB]; extern const Bitboard RankBB[RANK_NB]; +extern Bitboard LineBB[64][64]; extern Bitboard BetweenBB[64][64]; extern Magic BishopTable[64]; @@ -177,6 +178,10 @@ INLINE bool Single(Bitboard bb) { return bb && !Multiple(bb); } +INLINE bool Aligned(Square sq1, Square sq2, Square sq3) { + return LineBB[sq1][sq2] & BB(sq3); +} + INLINE int PieceCount(const Position *pos, Piece piece) { return PopCount(colorPieceBB(ColorOf(piece), PieceTypeOf(piece))); } diff --git a/src/board.c b/src/board.c index c7cfe313..1629092a 100644 --- a/src/board.c +++ b/src/board.c @@ -186,6 +186,24 @@ static void InitCastlingRight(Position *pos, Color color, int file) { RookSquare[cr] = rFrom; } +Bitboard Blockers(const Position *pos, Bitboard sliders, Square sq) { + + Bitboard blockers = 0; + + Bitboard snipers = ( (AttackBB( ROOK, sq, 0) & (pieceBB(QUEEN) | pieceBB( ROOK))) + | (AttackBB(BISHOP, sq, 0) & (pieceBB(QUEEN) | pieceBB(BISHOP)))) & sliders; + + while (snipers) { + Square sniperSq = PopLsb(&snipers); + Bitboard piecesBetween = BetweenBB[sq][sniperSq] & pieceBB(ALL); + + if (Single(piecesBetween)) + blockers |= piecesBetween; + } + + return blockers; +} + // Parse FEN and set up the position as described void ParseFen(const char *fen, Position *pos) { @@ -236,6 +254,8 @@ void ParseFen(const char *fen, Position *pos) { pos->gameMoves = atoi(strtok(NULL, " ")); // Final initializations + pos->blockers[WHITE] = Blockers(pos, colorBB(BLACK), kingSq(WHITE)); + pos->blockers[BLACK] = Blockers(pos, colorBB(WHITE), kingSq(BLACK)); pos->checkers = Checkers(pos); pos->key = GenPosKey(pos); pos->materialKey = GenMaterialKey(pos); @@ -523,6 +543,10 @@ bool PositionOk(const Position *pos) { assert(pos->castlingRights >= 0 && pos->castlingRights <= 15); + assert(pos->blockers[WHITE] == Blockers(pos, colorBB(BLACK), kingSq(WHITE))); + assert(pos->blockers[BLACK] == Blockers(pos, colorBB(WHITE), kingSq(BLACK))); + assert(pos->checkers == Checkers(pos)); + assert(GenPosKey(pos) == pos->key); assert(GenMaterialKey(pos) == pos->materialKey); assert(GenPawnKey(pos) == pos->pawnKey); diff --git a/src/board.h b/src/board.h index d7ed9b2c..8f5856e8 100644 --- a/src/board.h +++ b/src/board.h @@ -24,6 +24,7 @@ typedef struct { Key key; Key materialKey; + Bitboard blockers[COLOR_NB]; Bitboard checkers; Move move; Square epSquare; @@ -35,6 +36,7 @@ typedef struct Position { uint8_t board[64]; Bitboard pieceBB[7]; Bitboard colorBB[COLOR_NB]; + Bitboard blockers[COLOR_NB]; Bitboard checkers; int nonPawnCount[COLOR_NB]; @@ -77,6 +79,7 @@ extern Bitboard CastlePath[16]; extern Square RookSquare[16]; +Bitboard Blockers(const Position *pos, Bitboard sliders, Square sq); void ParseFen(const char *fen, Position *pos); Key KeyAfter(const Position *pos, Move move); bool SEE(const Position *pos, const Move move, const int threshold); diff --git a/src/makemove.c b/src/makemove.c index fe4dc393..bf55d1e8 100644 --- a/src/makemove.c +++ b/src/makemove.c @@ -185,6 +185,8 @@ void TakeMove(Position *pos) { // Get various info from history pos->key = history(0).key; pos->materialKey = history(0).materialKey; + pos->blockers[WHITE] = history(0).blockers[WHITE]; + pos->blockers[BLACK] = history(0).blockers[BLACK]; pos->checkers = history(0).checkers; pos->epSquare = history(0).epSquare; pos->rule50 = history(0).rule50; @@ -194,13 +196,15 @@ void TakeMove(Position *pos) { } // Make a move - take it back and return false if move was illegal -bool MakeMove(Position *pos, const Move move) { +void MakeMove(Position *pos, const Move move) { TTPrefetch(KeyAfter(pos, move)); // Save position history(0).key = pos->key; history(0).materialKey = pos->materialKey; + history(0).blockers[WHITE] = pos->blockers[WHITE]; + history(0).blockers[BLACK] = pos->blockers[BLACK]; history(0).checkers = pos->checkers; history(0).move = move; history(0).epSquare = pos->epSquare; @@ -279,16 +283,13 @@ bool MakeMove(Position *pos, const Move move) { sideToMove ^= 1; HASH_SIDE; - // If own king is attacked after the move, take it back immediately - if (KingAttacked(pos, sideToMove^1)) - return TakeMove(pos), false; + pos->blockers[WHITE] = Blockers(pos, colorBB(BLACK), kingSq(WHITE)); + pos->blockers[BLACK] = Blockers(pos, colorBB(WHITE), kingSq(BLACK)); pos->checkers = Checkers(pos); pos->nodes++; assert(PositionOk(pos)); - - return true; } // Pass the turn without moving diff --git a/src/makemove.h b/src/makemove.h index e2e0cd27..6adb78da 100644 --- a/src/makemove.h +++ b/src/makemove.h @@ -22,7 +22,7 @@ #include "types.h" -bool MakeMove(Position *pos, Move move); +void MakeMove(Position *pos, Move move); void TakeMove(Position *pos); void MakeNullMove(Position *pos); void TakeNullMove(Position *pos); diff --git a/src/move.c b/src/move.c index 5f7f4ea5..a2e9d591 100644 --- a/src/move.c +++ b/src/move.c @@ -71,6 +71,30 @@ bool MoveIsPseudoLegal(const Position *pos, const Move move) { return BB(to) & AttackBB(pieceTypeOn(from), from, pieceBB(ALL)); } +// Checks whether a move is legal (assuming it is pseudo-legal in this position) +bool MoveIsLegal(const Position *pos, const Move move) { + + const Color color = sideToMove; + const Square from = fromSq(move); + const Square to = toSq(move); + + if (moveIsEnPas(move)) { + Bitboard occupied = pieceBB(ALL) ^ BB(from) ^ BB(to) ^ BB(to ^ 8); + Bitboard rooks = colorPieceBB(!color, ROOK) | colorPieceBB(!color, QUEEN); + Bitboard bishops = colorPieceBB(!color, BISHOP) | colorPieceBB(!color, QUEEN); + return !(AttackBB( ROOK, kingSq(color), occupied) & rooks) + && !(AttackBB(BISHOP, kingSq(color), occupied) & bishops); + } + + if (moveIsCastle(move)) + return true; + + if (PieceTypeOf(piece(move)) == KING) + return !(Attackers(pos, to, pieceBB(ALL) ^ BB(from)) & colorBB(!color)); + + return !(pos->blockers[color] & BB(from)) || Aligned(from, to, kingSq(color)); +} + // Translates a move to a string char *MoveToStr(const Move move) { diff --git a/src/move.h b/src/move.h index 8ed00006..1095ec13 100644 --- a/src/move.h +++ b/src/move.h @@ -88,9 +88,10 @@ INLINE bool CastleLegal(const Position *pos, Square to) { if (SqAttacked(pos, PopLsb(&kingPath), !color)) return false; - return !chess960 || !(Attackers(pos, to, pieceBB(ALL) ^ BB(RookSquare[castle])) & colorBB(!color)); + return !chess960 || !(pos->blockers[color] & BB(RookSquare[castle])); } bool MoveIsPseudoLegal(const Position *pos, Move move); +bool MoveIsLegal(const Position *pos, const Move move); char *MoveToStr(Move move); Move ParseMove(const char *ptrChar, const Position *pos); diff --git a/src/search.c b/src/search.c index c1856158..1e10fbeb 100644 --- a/src/search.c +++ b/src/search.c @@ -162,7 +162,8 @@ static int Quiescence(Thread *thread, Stack *ss, int alpha, const int beta) { ss->continuation = &thread->continuation[inCheck][moveIsCapture(move)][piece(move)][toSq(move)]; // Recursively search the positions after making the moves, skipping illegal ones - if (!MakeMove(pos, move)) continue; + if (!MoveIsLegal(pos, move)) continue; + MakeMove(pos, move); int score = -Quiescence(thread, ss+1, -beta, -alpha); TakeMove(pos); @@ -361,7 +362,8 @@ static int AlphaBeta(Thread *thread, Stack *ss, int alpha, int beta, Depth depth if (mp.stage > NOISY_GOOD) break; - if (!MakeMove(pos, move)) continue; + if (!MoveIsLegal(pos, move)) continue; + MakeMove(pos, move); ss->continuation = &thread->continuation[inCheck][moveIsCapture(move)][piece(move)][toSq(move)]; @@ -426,7 +428,8 @@ static int AlphaBeta(Thread *thread, Stack *ss, int alpha, int beta, Depth depth } // Make the move, skipping to the next if illegal - if (!MakeMove(pos, move)) continue; + if (!MoveIsLegal(pos, move)) continue; + MakeMove(pos, move); moveCount++; diff --git a/src/tests.c b/src/tests.c index f05318bf..642b31ae 100644 --- a/src/tests.c +++ b/src/tests.c @@ -166,7 +166,9 @@ static uint64_t RecursivePerft(Position *pos, const Depth depth) { GenAllMoves(pos, &list); for (int i = 0; i < list.count; i++) { - if (!MakeMove(pos, list.moves[i].move)) continue; + Move move = list.moves[i].move; + if (!MoveIsLegal(pos, move)) continue; + MakeMove(pos, move); leafnodes += RecursivePerft(pos, depth - 1); TakeMove(pos); } diff --git a/src/threads.c b/src/threads.c index f6b00a96..54d67ba9 100644 --- a/src/threads.c +++ b/src/threads.c @@ -21,7 +21,7 @@ #include #include -#include "makemove.h" +#include "move.h" #include "movegen.h" #include "threads.h" @@ -108,9 +108,8 @@ void PrepareSearch(Position *pos, Move searchmoves[]) { for (int i = 0; i < list.count; ++i) { Move move = list.moves[list.next++].move; if (NotInSearchMoves(searchmoves, move)) continue; - if (!MakeMove(pos, move)) continue; + if (!MoveIsLegal(pos, move)) continue; ++rootMoveCount; - TakeMove(pos); } pos->nodes = 0;