diff --git a/src/attacks.c b/src/attacks.c index 58409d23..2c242435 100644 --- a/src/attacks.c +++ b/src/attacks.c @@ -345,8 +345,7 @@ BitBoard SetPieceLayoutOccupancy(int idx, int bits, BitBoard attacks) { BitBoard occupany = 0; for (int i = 0; i < bits; i++) { - int sq = LSB(attacks); - PopLSB(attacks); + int sq = PopLSB(&attacks); if (idx & (1 << i)) occupany |= (1ULL << sq); diff --git a/src/bits.h b/src/bits.h index abbd60b5..e0622ce6 100644 --- a/src/bits.h +++ b/src/bits.h @@ -49,7 +49,6 @@ #define PopBit(bb, sq) ((bb) &= ~Bit(sq)) #define FlipBit(bb, sq) ((bb) ^= Bit(sq)) #define FlipBits(bb, sq1, sq2) ((bb) ^= Bit(sq1) ^ Bit(sq2)) -#define PopLSB(bb) ((bb) &= (bb) -1) #define LSB(bb) (__builtin_ctzll(bb)) #define MSB(bb) (63 ^ __builtin_clzll(bb)) @@ -82,9 +81,9 @@ INLINE uint8_t PawnFiles(BitBoard pawns) { return (uint8_t) ((pawns | (pawns >> 32)) & 0xFF); } -INLINE int popAndGetLsb(BitBoard* bb) { +INLINE int PopLSB(BitBoard* bb) { int sq = LSB(*bb); - PopLSB(*bb); + *bb &= *bb - 1; return sq; } diff --git a/src/board.c b/src/board.c index 468e88f6..b4e3cc89 100644 --- a/src/board.c +++ b/src/board.c @@ -153,7 +153,11 @@ void ParseFen(char* fen, Board* board) { sscanf(fen, " %d %d", &board->fmr, &board->moveNo); - SetOccupancies(board); + OccBB(WHITE) = OccBB(BLACK) = OccBB(BOTH) = 0; + for (int i = WHITE_PAWN; i <= BLACK_KING; i++) + OccBB(i & 1) |= board->pieces[i]; + OccBB(BOTH) = OccBB(WHITE) | OccBB(BLACK); + SetSpecialPieces(board); board->zobrist = Zobrist(board); @@ -245,56 +249,28 @@ inline int IsOCB(Board* board) { BitCount((PieceBB(BISHOP, WHITE) | PieceBB(BISHOP, BLACK)) & DARK_SQS) == 1; } -// Reset general piece locations on the board -inline void SetOccupancies(Board* board) { - OccBB(WHITE) = 0; - OccBB(BLACK) = 0; - OccBB(BOTH) = 0; - - for (int i = WHITE_PAWN; i <= BLACK_KING; i++) - OccBB(i & 1) |= board->pieces[i]; - OccBB(BOTH) = OccBB(WHITE) | OccBB(BLACK); -} - // Special pieces are those giving check, and those that are pinned // these must be recalculated every move for faster move legality purposes inline void SetSpecialPieces(Board* board) { - int kingSq = LSB(PieceBB(KING, board->stm)); - - // Reset pinned pieces - board->pinned = 0; - // checked can be initialized easily with non-blockable checks - board->checkers = (GetKnightAttacks(kingSq) & PieceBB(KNIGHT, board->xstm)) | - (GetPawnAttacks(kingSq, board->stm) & PieceBB(PAWN, board->xstm)); - - // for each side - for (int kingColor = WHITE; kingColor <= BLACK; kingColor++) { - int enemyColor = 1 - kingColor; - kingSq = LSB(PieceBB(KING, kingColor)); - - // get full rook/bishop rays from the king that intersect that piece type of - // the enemy - BitBoard enemyPiece = ((PieceBB(BISHOP, enemyColor) | PieceBB(QUEEN, enemyColor)) & GetBishopAttacks(kingSq, 0)) | - ((PieceBB(ROOK, enemyColor) | PieceBB(QUEEN, enemyColor)) & GetRookAttacks(kingSq, 0)); - - while (enemyPiece) { - int sq = LSB(enemyPiece); + const int stm = board->stm; + const int xstm = board->xstm; - // is something in the way - BitBoard blockers = BetweenSquares(kingSq, sq) & OccBB(BOTH); + int kingSq = LSB(PieceBB(KING, stm)); - if (!blockers) - // no? then its check - board->checkers |= (enemyPiece & -enemyPiece); - else if (BitCount(blockers) == 1) - // just 1? then its pinned - board->pinned |= (blockers & OccBB(kingColor)); + board->pinned = 0; + board->checkers = (GetKnightAttacks(kingSq) & PieceBB(KNIGHT, xstm)) | // knight and + (GetPawnAttacks(kingSq, stm) & PieceBB(PAWN, xstm)); // pawns are easy - // TODO: Similar logic can be applied for discoveries, but apply for self - // pieces + BitBoard sliders = ((PieceBB(BISHOP, xstm) | PieceBB(QUEEN, xstm)) & GetBishopAttacks(kingSq, 0)) | + ((PieceBB(ROOK, xstm) | PieceBB(QUEEN, xstm)) & GetRookAttacks(kingSq, 0)); + while (sliders) { + int sq = PopLSB(&sliders); - PopLSB(enemyPiece); - } + BitBoard blockers = BetweenSquares(kingSq, sq) & OccBB(BOTH); + if (!blockers) + SetBit(board->checkers, sq); + else if (BitCount(blockers) == 1) + board->pinned |= (blockers & OccBB(stm)); } } @@ -320,8 +296,12 @@ void MakeMoveUpdate(Move move, Board* board, int update) { board->fmr++; FlipBits(board->pieces[piece], from, to); + FlipBits(OccBB(board->stm), from, to); + FlipBits(OccBB(BOTH), from, to); + board->squares[from] = NO_PIECE; board->squares[to] = piece; + board->zobrist ^= ZOBRIST_PIECES[piece][from] ^ ZOBRIST_PIECES[piece][to]; if (IsCas(move)) { @@ -330,6 +310,8 @@ void MakeMoveUpdate(Move move, Board* board, int update) { int rook = Piece(ROOK, board->stm); FlipBits(PieceBB(ROOK, board->stm), rookFrom, rookTo); + FlipBits(OccBB(board->stm), rookFrom, rookTo); + FlipBits(OccBB(BOTH), rookFrom, rookTo); // chess960 can have the king going where the rook started // do this check to prevent accidental wipe outs @@ -344,7 +326,11 @@ void MakeMoveUpdate(Move move, Board* board, int update) { board->squares[capSq] = NO_PIECE; FlipBit(board->pieces[captured], capSq); + FlipBit(OccBB(board->xstm), capSq); + FlipBit(OccBB(BOTH), capSq); + board->zobrist ^= ZOBRIST_PIECES[captured][capSq]; + board->piecesCounts -= PieceCount(captured); board->phase -= PHASE_VALUES[PieceType(captured)]; board->fmr = 0; @@ -384,8 +370,6 @@ void MakeMoveUpdate(Move move, Board* board, int update) { board->fmr = 0; } - SetOccupancies(board); - int stm = board->stm; board->histPly++; @@ -446,9 +430,11 @@ void UndoMove(Move move, Board* board) { } FlipBits(board->pieces[piece], to, from); + FlipBits(OccBB(board->stm), to, from); + FlipBits(OccBB(BOTH), to, from); + board->squares[from] = piece; board->squares[to] = NO_PIECE; - board->squares[to] = NO_PIECE; if (IsCas(move)) { int rookFrom = board->cr[CASTLING_ROOK[to]]; @@ -456,6 +442,8 @@ void UndoMove(Move move, Board* board) { int rook = Piece(ROOK, board->stm); FlipBits(PieceBB(ROOK, board->stm), rookTo, rookFrom); + FlipBits(OccBB(board->stm), rookTo, rookFrom); + FlipBits(OccBB(BOTH), rookTo, rookFrom); if (from != rookTo) board->squares[rookTo] = NO_PIECE; @@ -465,12 +453,14 @@ void UndoMove(Move move, Board* board) { int captured = board->history[board->histPly].capture; FlipBit(board->pieces[captured], capSq); + FlipBit(OccBB(board->xstm), capSq); + FlipBit(OccBB(BOTH), capSq); + board->squares[capSq] = captured; + board->piecesCounts += PieceCount(captured); board->phase += PHASE_VALUES[PieceType(captured)]; } - - SetOccupancies(board); } void MakeNullMove(Board* board) { @@ -496,6 +486,8 @@ void MakeNullMove(Board* board) { // Prefetch the hash entry for this board position TTPrefetch(board->zobrist); + + SetSpecialPieces(board); } void UndoNullMove(Board* board) { @@ -707,7 +699,7 @@ int IsLegal(Move move, Board* board) { if (AttacksToSquare(board, i, OccBB(BOTH)) & OccBB(board->xstm)) return 0; - return !CHESS_960 || !GetBit(board->pinned, To(move)); + return 1; } if (PieceType(Moving(move)) == KING) diff --git a/src/board.h b/src/board.h index 51ffefcd..6d3d42c9 100644 --- a/src/board.h +++ b/src/board.h @@ -37,18 +37,14 @@ #define MDistance(a, b) (abs(Rank(a) - Rank(b)) + abs(File(a) - File(b))) #define PieceCount(pc) (1ull << (pc * 4)) -extern const int8_t PSQT[64]; extern const uint16_t KING_BUCKETS[64]; -extern const uint64_t PIECE_COUNT_IDX[]; - void ClearBoard(Board* board); void ParseFen(char* fen, Board* board); void BoardToFen(char* fen, Board* board); void PrintBoard(Board* board); void SetSpecialPieces(Board* board); -void SetOccupancies(Board* board); int DoesMoveCheck(Move move, Board* board); @@ -58,7 +54,6 @@ int IsMaterialDraw(Board* board); int IsFiftyMoveRule(Board* board); int HasNonPawn(Board* board); -int IsOCB(Board* board); void MakeNullMove(Board* board); void UndoNullMove(Board* board); diff --git a/src/eval.c b/src/eval.c index 93386d76..d09dc992 100644 --- a/src/eval.c +++ b/src/eval.c @@ -55,7 +55,7 @@ void Threats(Threat* threats, Board* board, int stm) { BitBoard knights = PieceBB(KNIGHT, stm); while (knights) { - BitBoard atx = GetKnightAttacks(popAndGetLsb(&knights)); + BitBoard atx = GetKnightAttacks(PopLSB(&knights)); threats->sqs |= atx; threats->pcs |= opponentPieces & atx; @@ -63,7 +63,7 @@ void Threats(Threat* threats, Board* board, int stm) { BitBoard bishops = PieceBB(BISHOP, stm); while (bishops) { - BitBoard atx = GetBishopAttacks(popAndGetLsb(&bishops), OccBB(BOTH)); + BitBoard atx = GetBishopAttacks(PopLSB(&bishops), OccBB(BOTH)); threats->sqs |= atx; threats->pcs |= opponentPieces & atx; @@ -74,7 +74,7 @@ void Threats(Threat* threats, Board* board, int stm) { BitBoard rooks = PieceBB(ROOK, stm); while (rooks) { - BitBoard atx = GetRookAttacks(popAndGetLsb(&rooks), OccBB(BOTH)); + BitBoard atx = GetRookAttacks(PopLSB(&rooks), OccBB(BOTH)); threats->sqs |= atx; threats->pcs |= opponentPieces & atx; @@ -82,7 +82,7 @@ void Threats(Threat* threats, Board* board, int stm) { BitBoard queens = PieceBB(QUEEN, stm); while (queens) - threats->sqs |= GetQueenAttacks(popAndGetLsb(&queens), OccBB(BOTH)); + threats->sqs |= GetQueenAttacks(PopLSB(&queens), OccBB(BOTH)); threats->sqs |= GetKingAttacks(LSB(PieceBB(KING, stm))); } diff --git a/src/history.c b/src/history.c index c4073bc9..c76653d7 100644 --- a/src/history.c +++ b/src/history.c @@ -99,19 +99,3 @@ void UpdateHistories(Board* board, AddHistoryHeuristic(&TH(piece, to, captured), -inc); } } - -int GetQuietHistory(SearchStack* ss, ThreadData* thread, Move move, int stm, BitBoard threats) { - int history = HH(stm, move, threats); - history += (*(ss - 1)->ch)[Moving(move)][To(move)]; - history += (*(ss - 2)->ch)[Moving(move)][To(move)]; - - return history; -} - -int GetCaptureHistory(ThreadData* thread, Board* board, Move m) { - int piece = PieceType(Moving(m)); - int to = To(m); - int captured = IsEP(m) ? PAWN : PieceType(board->squares[to]); - - return TH(piece, to, captured); -} \ No newline at end of file diff --git a/src/history.h b/src/history.h index fa084e33..ad32dab4 100644 --- a/src/history.h +++ b/src/history.h @@ -18,11 +18,24 @@ #define HISTORY_H #include "bits.h" +#include "board.h" +#include "move.h" #include "types.h" +#include "util.h" #define HH(stm, m, threats) (thread->hh[stm][!GetBit(threats, From(m))][!GetBit(threats, To(m))][FromTo(m)]) #define TH(p, e, c) (thread->caph[p][e][c]) +INLINE int GetQuietHistory(SearchStack* ss, ThreadData* thread, Move move, int stm, BitBoard threats) { + return (int) HH(stm, move, threats) + // + (int) (*(ss - 1)->ch)[Moving(move)][To(move)] + // + (int) (*(ss - 2)->ch)[Moving(move)][To(move)]; +} + +INLINE int GetCaptureHistory(ThreadData* thread, Board* board, Move move) { + return TH(PieceType(Moving(move)), To(move), IsEP(move) ? PAWN : PieceType(board->squares[To(move)])); +} + void UpdateHistories(Board* board, SearchStack* ss, ThreadData* thread, @@ -34,7 +47,5 @@ void UpdateHistories(Board* board, Move captures[], int nC, BitBoard threats); -int GetQuietHistory(SearchStack* ss, ThreadData* thread, Move move, int stm, BitBoard threats); -int GetCaptureHistory(ThreadData* thread, Board* board, Move move); #endif \ No newline at end of file diff --git a/src/movegen.h b/src/movegen.h index 10177872..657de113 100644 --- a/src/movegen.h +++ b/src/movegen.h @@ -79,12 +79,12 @@ INLINE ScoredMove* AddPawnMoves(ScoredMove* moves, BitBoard opts, Board* board, targets &= opts, dpTargets &= opts; while (targets) { - int to = popAndGetLsb(&targets); + int to = PopLSB(&targets); moves = AddMove(moves, to - PawnDir(stm), to, Piece(PAWN, stm), NO_PROMO, QUIET); } while (dpTargets) { - int to = popAndGetLsb(&dpTargets); + int to = PopLSB(&dpTargets); moves = AddMove(moves, to - PawnDir(stm) - PawnDir(stm), to, Piece(PAWN, stm), NO_PROMO, DP); } } else { @@ -94,12 +94,12 @@ INLINE ScoredMove* AddPawnMoves(ScoredMove* moves, BitBoard opts, Board* board, BitBoard wTargets = ShiftPawnCapW(valid, stm) & OccBB(xstm) & opts; while (eTargets) { - int to = popAndGetLsb(&eTargets); + int to = PopLSB(&eTargets); moves = AddMove(moves, to - (PawnDir(stm) + E), to, Piece(PAWN, stm), NO_PROMO, CAPTURE); } while (wTargets) { - int to = popAndGetLsb(&wTargets); + int to = PopLSB(&wTargets); moves = AddMove(moves, to - (PawnDir(stm) + W), to, Piece(PAWN, stm), NO_PROMO, CAPTURE); } @@ -107,7 +107,7 @@ INLINE ScoredMove* AddPawnMoves(ScoredMove* moves, BitBoard opts, Board* board, BitBoard movers = GetPawnAttacks(board->epSquare, xstm) & valid; while (movers) { - int from = popAndGetLsb(&movers); + int from = PopLSB(&movers); moves = AddMove(moves, from, board->epSquare, Piece(PAWN, stm), NO_PROMO, EP); } } @@ -120,17 +120,17 @@ INLINE ScoredMove* AddPawnMoves(ScoredMove* moves, BitBoard opts, Board* board, BitBoard wTargets = ShiftPawnCapW(valid, stm) & OccBB(xstm) & opts; while (sTargets) { - int to = popAndGetLsb(&sTargets); + int to = PopLSB(&sTargets); moves = AddPromotions(moves, to - PawnDir(stm), to, Piece(PAWN, stm), QUIET, stm, type); } while (eTargets) { - int to = popAndGetLsb(&eTargets); + int to = PopLSB(&eTargets); moves = AddPromotions(moves, to - (PawnDir(stm) + E), to, Piece(PAWN, stm), CAPTURE, stm, type); } while (wTargets) { - int to = popAndGetLsb(&wTargets); + int to = PopLSB(&wTargets); moves = AddPromotions(moves, to - (PawnDir(stm) + W), to, Piece(PAWN, stm), CAPTURE, stm, type); } @@ -147,13 +147,13 @@ INLINE ScoredMove* AddPieceMoves(ScoredMove* moves, BitBoard movers = PieceBB(piece, stm); while (movers) { - int from = popAndGetLsb(&movers); + int from = PopLSB(&movers); BitBoard valid = GetPieceAttacks(from, OccBB(BOTH), piece) & opts; BitBoard targets = type == QUIET ? (valid & ~OccBB(BOTH)) : (valid & OccBB(xstm)); while (targets) { - int to = popAndGetLsb(&targets); + int to = PopLSB(&targets); moves = AddMove(moves, from, to, Piece(piece, stm), NO_PROMO, type == QUIET ? QUIET : CAPTURE); } } diff --git a/src/nn.c b/src/nn.c index eff7a2c1..a40f68cb 100644 --- a/src/nn.c +++ b/src/nn.c @@ -103,12 +103,12 @@ void RefreshAccumulator(Accumulator* dest, Board* board, const int perspective) BitBoard add = curr & ~prev; while (rem) { - int sq = popAndGetLsb(&rem); + int sq = PopLSB(&rem); ApplyFeature(state->values, state->values, FeatureIdx(pc, sq, kingSq, perspective), SUB); } while (add) { - int sq = popAndGetLsb(&add); + int sq = PopLSB(&add); ApplyFeature(state->values, state->values, FeatureIdx(pc, sq, kingSq, perspective), ADD); } @@ -128,7 +128,7 @@ void ResetAccumulator(Accumulator* dest, Board* board, const int perspective) { BitBoard occ = OccBB(BOTH); while (occ) { - int sq = popAndGetLsb(&occ); + int sq = PopLSB(&occ); int pc = board->squares[sq]; int feature = FeatureIdx(pc, sq, kingSq, perspective); diff --git a/src/perft.c b/src/perft.c index 2f05e402..0fadc25a 100644 --- a/src/perft.c +++ b/src/perft.c @@ -61,7 +61,7 @@ void PerftTest(int depth, Board* board) { uint64_t nodes = Perft(depth - 1, board); UndoMove(move, board); - printf("%-5s: %" PRIu64 "\n", MoveToStr(move, board), nodes); + printf("%5s: %" PRIu64 "\n", MoveToStr(move, board), nodes); total += nodes; } diff --git a/src/pyrrhic/tbconfig.h b/src/pyrrhic/tbconfig.h index 77abdbcd..c5842d0e 100644 --- a/src/pyrrhic/tbconfig.h +++ b/src/pyrrhic/tbconfig.h @@ -45,7 +45,7 @@ #define PYRRHIC_POPCOUNT(x) (BitCount(x)) #define PYRRHIC_LSB(x) (LSB(x)) -#define PYRRHIC_POPLSB(x) (popAndGetLsb(x)) +#define PYRRHIC_POPLSB(x) (PopLSB(x)) #define PYRRHIC_PAWN_ATTACKS(sq, c) (GetPawnAttacks(sq, c)) #define PYRRHIC_KNIGHT_ATTACKS(sq) (GetKnightAttacks(sq)) diff --git a/src/zobrist.c b/src/zobrist.c index cc357cfe..168e2fda 100644 --- a/src/zobrist.c +++ b/src/zobrist.c @@ -43,9 +43,11 @@ void InitZobristKeys() { uint64_t Zobrist(Board* board) { uint64_t hash = 0ULL; - for (int piece = WHITE_PAWN; piece <= BLACK_KING; piece++) - for (BitBoard pieces = board->pieces[piece]; pieces; PopLSB(pieces)) - hash ^= ZOBRIST_PIECES[piece][LSB(pieces)]; + for (int piece = WHITE_PAWN; piece <= BLACK_KING; piece++) { + BitBoard pcs = board->pieces[piece]; + while (pcs) + hash ^= ZOBRIST_PIECES[piece][PopLSB(&pcs)]; + } if (board->epSquare) hash ^= ZOBRIST_EP_KEYS[board->epSquare];