From 4361f34949429f36068fbe0ecb1a7ea1f6f97129 Mon Sep 17 00:00:00 2001 From: Cab Date: Sat, 10 Feb 2024 10:09:19 +0300 Subject: [PATCH] disable pawn check if no promotion available --- src/position.cpp | 38 ++++++++++++++++++++++++++++++++++++-- src/position.h | 2 ++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 50516883f..77a3f83dd 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -530,6 +530,7 @@ Position& Position::set(const Variant* v, const string& fenStr, bool isChess960, chess960 = isChess960 || v->chess960; tsumeMode = Options["TsumeMode"]; thisThread = th; + updatePawnCheckZone(); set_state(st); assert(pos_is_ok()); @@ -936,7 +937,7 @@ Bitboard Position::attackers_to(Square s, Bitboard occupied, Color c, Bitboard j // Use a faster version for variants with moderate rule variations if (var->fastAttacks) { - return (pawn_attacks_bb(~c, s) & pieces(c, PAWN)) + return (pawn_attacks_bb(~c, s) & pieces(c, PAWN) & ~pawnCannotCheckZone[c]) | (attacks_bb(s) & pieces(c, KNIGHT, ARCHBISHOP, CHANCELLOR)) | (attacks_bb< ROOK>(s, occupied) & pieces(c, ROOK, QUEEN, CHANCELLOR)) | (attacks_bb(s, occupied) & pieces(c, BISHOP, QUEEN, ARCHBISHOP)) @@ -2111,11 +2112,12 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { k ^= Zobrist::wall[gating_square(m)]; } + updatePawnCheckZone(); // Update the key with the final value st->key = k; // Calculate checkers bitboard (if move gives check) st->checkersBB = givesCheck ? attackers_to(square(them), us) & pieces(us) : Bitboard(0); - assert(givesCheck == bool(st->checkersBB)); + assert(givesCheck == bool(st->checkersBB) || givesCheck && var->prisonPawnPromotion); sideToMove = ~sideToMove; @@ -2954,6 +2956,13 @@ bool Position::is_immediate_game_end(Value& result, int ply) const { return true; } } + if (var->prisonPawnPromotion && + (pawn_attacks_bb(~sideToMove, square(~sideToMove)) + & pieces(sideToMove, PAWN) + & ~pawnCannotCheckZone[sideToMove]) ){ + result = mate_in(ply); + return true; + } return false; } @@ -3252,6 +3261,31 @@ void Position::flip() { assert(pos_is_ok()); } +void Position::updatePawnCheckZone() { + if (!var->prisonPawnPromotion) { + pawnCannotCheckZone[WHITE] = Bitboard(0); + pawnCannotCheckZone[BLACK] = Bitboard(0); + return; + } + for (Color color : { BLACK, WHITE }) { + if (count(~color) == 0) { + pawnCannotCheckZone[color] = Bitboard(0); + } else { + bool canPromotion = false; + for (PieceSet prom = promotion_piece_types(color) & rescueFor(PAWN); prom; ) { + PieceType pt = pop_lsb(prom); + if (count_in_prison(~color, pt) > 0) { + canPromotion = true; + break; + } + } + Bitboard pz = promotion_zone(color); + pawnCannotCheckZone[color] = canPromotion + ? Bitboard(0) + : color == WHITE ? shift(SOUTH, pz) : shift(NORTH, pz); + } + } +} /// Position::pos_is_ok() performs some consistency checks for the /// position object and raises an asserts if something wrong is detected. diff --git a/src/position.h b/src/position.h index 792d26afd..dd32a0c22 100644 --- a/src/position.h +++ b/src/position.h @@ -372,12 +372,14 @@ class Position { bool chess960; int pieceCountInHand[COLOR_NB][PIECE_TYPE_NB]; int pieceCountInPrison[COLOR_NB][PIECE_TYPE_NB]; + Bitboard pawnCannotCheckZone[COLOR_NB]; int virtualPieces; Bitboard promotedPieces; void add_to_hand(Piece pc); int add_to_prison(Piece pc); void remove_from_hand(Piece pc); int remove_from_prison(Piece pc); + void updatePawnCheckZone(); void drop_piece(Piece pc_hand, Piece pc_drop, Square s, PieceType exchange); void undrop_piece(Piece pc_hand, Square s, PieceType exchange); Bitboard find_drop_region(Direction dir, Square s, Bitboard occupied) const;