diff --git a/src/makemove.c b/src/makemove.c index 389b748f..16188f09 100644 --- a/src/makemove.c +++ b/src/makemove.c @@ -194,7 +194,7 @@ 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)); @@ -279,16 +279,10 @@ 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->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 9014f832..066014a6 100644 --- a/src/move.c +++ b/src/move.c @@ -71,6 +71,37 @@ bool MoveIsPseudoLegal(const Position *pos, const Move move) { return BB(to) & AttackBB(pieceTypeOn(from), from, pieceBB(ALL)); } +// Checks whether a move is legal +// (assumes the move is pseudo-legal in the current position) +bool MoveIsLegal(const Position *pos, const Move move) { + + Color color = sideToMove; + Square from = fromSq(move); + Square to = toSq(move); + + Square kingSq = PieceTypeOf(pieceOn(from)) == KING ? to : (Square)Lsb(colorPieceBB(color, KING)); + + Bitboard occ = (pieceBB(ALL) ^ BB(from)) | BB(to); + Bitboard exclude = BB(to); + + if (moveIsEnPas(move)) + occ ^= BB(to ^ 8), + exclude ^= BB(to ^ 8); + + Bitboard bishops = colorBB(!color) & (pieceBB(BISHOP) | pieceBB(QUEEN)); + Bitboard rooks = colorBB(!color) & (pieceBB(ROOK) | pieceBB(QUEEN)); + + Bitboard kingAttackers = + ( (PawnAttackBB(color, kingSq) & colorPieceBB(!color, PAWN)) + | (AttackBB(KING, kingSq, occ) & colorPieceBB(!color, KING)) + | (AttackBB(KNIGHT, kingSq, occ) & colorPieceBB(!color, KNIGHT)) + | (AttackBB(BISHOP, kingSq, occ) & bishops) + | (AttackBB(ROOK, kingSq, occ) & rooks)); + + // If any non-excluded piece is attacking the king, the move is illegal + return !(kingAttackers & ~exclude); +} + // Translates a move to a string char *MoveToStr(const Move move) { diff --git a/src/move.h b/src/move.h index f78e322d..58c23561 100644 --- a/src/move.h +++ b/src/move.h @@ -92,6 +92,7 @@ INLINE bool CastleLegal(const Position *pos, Square to) { } 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); bool NotInSearchMoves(Move searchmoves[], Move move); diff --git a/src/movegen.c b/src/movegen.c index f90b74c5..568712eb 100644 --- a/src/movegen.c +++ b/src/movegen.c @@ -174,21 +174,19 @@ void GenAllMoves(const Position *pos, MoveList *list) { GenQuietMoves(pos, list); } -void GenLegalMoves(Position *pos, MoveList *list) { +void GenLegalMoves(const Position *pos, MoveList *list) { MoveList allMoves; allMoves.count = allMoves.next = 0; GenAllMoves(pos, &allMoves); for (int i = 0; i < allMoves.count; ++i) { Move move = allMoves.moves[i].move; - if (!MakeMove(pos, move)) continue; + if (!MoveIsLegal(pos, move)) continue; list->moves[list->count++].move = move; - TakeMove(pos); } - pos->nodes = 0; } -int LegalMoveCount(Position *pos) { +int LegalMoveCount(const Position *pos) { MoveList list; list.count = list.next = 0; GenLegalMoves(pos, &list); diff --git a/src/movegen.h b/src/movegen.h index 31303d8b..21df2cfb 100644 --- a/src/movegen.h +++ b/src/movegen.h @@ -37,5 +37,5 @@ typedef struct { void GenNoisyMoves(const Position *pos, MoveList *list); void GenQuietMoves(const Position *pos, MoveList *list); void GenAllMoves(const Position *pos, MoveList *list); -void GenLegalMoves(Position *pos, MoveList *list); -int LegalMoveCount(Position *pos); +void GenLegalMoves(const Position *pos, MoveList *list); +int LegalMoveCount(const Position *pos); diff --git a/src/search.c b/src/search.c index 4cba415e..b8b7008a 100644 --- a/src/search.c +++ b/src/search.c @@ -202,7 +202,8 @@ static int Quiescence(Thread *thread, Stack *ss, int alpha, int beta) { ss->contCorr = &thread->contCorrHistory[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); @@ -405,7 +406,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->move = move; ss->continuation = &thread->continuation[inCheck][moveIsCapture(move)][piece(move)][toSq(move)]; @@ -474,7 +476,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 5d9bd7bf..601bf062 100644 --- a/src/tests.c +++ b/src/tests.c @@ -161,7 +161,8 @@ 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; + if (!MoveIsLegal(pos, list.moves[i].move)) continue; + MakeMove(pos, list.moves[i].move); leafnodes += RecursivePerft(pos, depth - 1); TakeMove(pos); }