LCOV - code coverage report
Current view: top level - Source - attack.hpp (source / functions) Coverage Total Hit
Test: coverage Lines: 100.0 % 11 11
Test Date: 2026-03-02 16:42:41 Functions: 100.0 % 8 8

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include "bitboardTools.hpp"
       4              : #include "definition.hpp"
       5              : 
       6              : #ifdef __BMI2__
       7              : #include <immintrin.h>
       8              : #endif
       9              : 
      10              : namespace BBTools {
      11              : 
      12              : /*!
      13              :  * Two bitboard attack generation tools can be used here (controlled by WITH_MAGIC define from config.hpp):
      14              :  * - hyperbola quintessence (https://www.chessprogramming.org/Hyperbola_Quintessence)
      15              :  * - or magic (https://www.chessprogramming.org/Magic_Bitboards) with BMI2 extension if available
      16              :  */
      17              : 
      18              : // mask variable is filled with many usefull pre-computed bitboard information
      19              : // many of then will be usefull during evaluation and move generation
      20              : // note that between to not include start and end square
      21              : struct Mask {
      22              :     BitBoard bbsquare {emptyBitBoard};
      23              :     BitBoard kingZone {emptyBitBoard};
      24              :     BitBoard knight {emptyBitBoard};
      25              :     BitBoard king {emptyBitBoard};
      26              :     BitBoard diagonal {emptyBitBoard};
      27              :     BitBoard antidiagonal {emptyBitBoard};
      28              :     BitBoard file {emptyBitBoard};
      29              :     colored<BitBoard> pawnAttack {{emptyBitBoard, emptyBitBoard}};
      30              :     colored<BitBoard> push {{emptyBitBoard, emptyBitBoard}};
      31              :     colored<BitBoard> dpush {{emptyBitBoard, emptyBitBoard}};
      32              : #if !defined(WITH_SMALL_MEMORY)
      33              :     BitBoard enpassant {emptyBitBoard};
      34              :     colored<BitBoard> frontSpan {{emptyBitBoard, emptyBitBoard}};
      35              :     colored<BitBoard> rearSpan {{emptyBitBoard, emptyBitBoard}};
      36              :     colored<BitBoard> passerSpan {{emptyBitBoard, emptyBitBoard}};
      37              :     colored<BitBoard> attackFrontSpan {{emptyBitBoard, emptyBitBoard}};
      38              :     array1d<BitBoard, NbSquare> between {emptyBitBoard};
      39              : #endif
      40              : };
      41              : 
      42              : extern array1d<Mask,NbSquare> mask;
      43              : void initMask();
      44              : 
      45              : constexpr auto SquareToBitboardTable(const Square k) { return BBTools::mask[k].bbsquare;}
      46              : 
      47              : #ifndef WITH_MAGIC
      48              : 
      49              : /*!
      50              :  * This HQ BB implementation is comming from Dumb/Amoeba by Richard Delorme (a.k.a Abulmo)
      51              :  * after a discussion on talkchess about a small BB implementation
      52              :  * http://talkchess.com/forum3/viewtopic.php?f=7&t=68741&p=777898#p777682
      53              :  */
      54              : 
      55              : [[nodiscard]] BitBoard attack            (const BitBoard occupancy, const Square x, const BitBoard m);
      56              : [[nodiscard]] BitBoard rankAttack        (const BitBoard occupancy, const Square x);
      57              : [[nodiscard]] BitBoard fileAttack        (const BitBoard occupancy, const Square x);
      58              : [[nodiscard]] BitBoard diagonalAttack    (const BitBoard occupancy, const Square x);
      59              : [[nodiscard]] BitBoard antidiagonalAttack(const BitBoard occupancy, const Square x);
      60              : 
      61              : // Next functions define the user API for piece move
      62              : template < Piece > [[nodiscard]] FORCE_FINLINE BitBoard coverage      (const Square x, const BitBoard occupancy = 0, const Color c = Co_White) { assert(false); return emptyBitBoard; }
      63              : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wp>(const Square x, const BitBoard          , const Color c) { assert(isValidSquare(x)); return mask[x].pawnAttack[c]; }
      64              : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wn>(const Square x, const BitBoard          , const Color  ) { assert(isValidSquare(x)); return mask[x].knight; }
      65              : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wb>(const Square x, const BitBoard occupancy, const Color  ) { assert(isValidSquare(x)); return diagonalAttack(occupancy, x) | antidiagonalAttack(occupancy, x); }
      66              : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wr>(const Square x, const BitBoard occupancy, const Color  ) { assert(isValidSquare(x)); return fileAttack    (occupancy, x) | rankAttack        (occupancy, x); }
      67              : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wq>(const Square x, const BitBoard occupancy, const Color  ) { assert(isValidSquare(x)); return diagonalAttack(occupancy, x) | antidiagonalAttack(occupancy, x) | fileAttack(occupancy, x) | rankAttack(occupancy, x); }
      68              : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wk>(const Square x, const BitBoard          , const Color  ) { assert(isValidSquare(x)); return mask[x].king; }
      69              : 
      70              : // Attack function is just coverage interseted with a target bitboard
      71              : template<Piece pp>
      72              : [[nodiscard]] FORCE_FINLINE BitBoard attack(const Square x, const BitBoard target, const BitBoard occupancy = 0, const Color c = Co_White) {
      73              :    return coverage<pp>(x, occupancy, c) & target;
      74              : }
      75              : 
      76              : #else // MAGIC
      77              : 
      78              : namespace MagicBB {
      79              : 
      80              : /*!
      81              :  * This compact magic BB implementation is very near the one used
      82              :  * in RubiChess and Stockfish
      83              :  * It is not really much faster than HQ BB, maybe around +10%
      84              :  */
      85              : 
      86              : inline constexpr size_t BISHOP_INDEX_BITS = 9;
      87              : inline constexpr size_t ROOK_INDEX_BITS = 12;
      88              : 
      89              : struct SMagic {
      90              :   BitBoard mask {emptyBitBoard};
      91              :   BitBoard magic {emptyBitBoard};
      92              : };
      93              : 
      94              : extern array1d<SMagic, NbSquare> bishopMagic;
      95              : extern array1d<SMagic, NbSquare> rookMagic;
      96              : 
      97              : extern array2d<BitBoard, NbSquare, 1 << BISHOP_INDEX_BITS> bishopAttacks;
      98              : extern array2d<BitBoard, NbSquare, 1 << ROOK_INDEX_BITS> rookAttacks;
      99              : 
     100              : #if defined(__BMI2__) && !defined(__znver1) && !defined(__znver2) && !defined(__bdver4) && defined(ENV64BIT)
     101              : inline auto MAGICBISHOPINDEX(const BitBoard m, const Square x) { return _pext_u64(m, MagicBB::bishopMagic[x].mask);}
     102              : inline auto MAGICROOKINDEX(const BitBoard m, const Square x)    { return _pext_u64(m, MagicBB::rookMagic[x].mask);}
     103              : #else
     104     43396428 : inline auto MAGICBISHOPINDEX(const BitBoard m, const Square x) { return static_cast<int>(((m & MagicBB::bishopMagic[x].mask) * MagicBB::bishopMagic[x].magic) >> (NbSquare - BISHOP_INDEX_BITS));}
     105     95032626 : inline auto MAGICROOKINDEX(const BitBoard m, const Square x)   { return static_cast<int>(((m & MagicBB::rookMagic[x].mask) * MagicBB::rookMagic[x].magic) >> (NbSquare - ROOK_INDEX_BITS));}
     106              : #endif
     107              : 
     108    193009060 : inline auto MAGICBISHOPATTACKS(const BitBoard m, const Square x) { return MagicBB::bishopAttacks[x][MAGICBISHOPINDEX(m, x)];}
     109    222992238 : inline auto MAGICROOKATTACKS(const BitBoard m, const Square x)   { return MagicBB::rookAttacks  [x][MAGICROOKINDEX(m, x)];}
     110              : 
     111              : void initMagic();
     112              : 
     113              : } // namespace MagicBB
     114              : 
     115              : // Next functions define the user API for piece move
     116              : template < Piece > [[nodiscard]] FORCE_FINLINE BitBoard coverage      (const Square  , const BitBoard          , const Color  ) { assert(false); return emptyBitBoard; }
     117    270825320 : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wp>(const Square s, const BitBoard          , const Color c) { assert(isValidSquare(s)); return mask[s].pawnAttack[c]; }
     118    169236630 : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wn>(const Square s, const BitBoard          , const Color  ) { assert(isValidSquare(s)); return mask[s].knight; }
     119     19607804 : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wb>(const Square s, const BitBoard occupancy, const Color  ) { assert(isValidSquare(s)); return MagicBB::MAGICBISHOPATTACKS(occupancy, s); }
     120     62030389 : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wr>(const Square s, const BitBoard occupancy, const Color  ) { assert(isValidSquare(s)); return MagicBB::MAGICROOKATTACKS  (occupancy, s); }
     121     14394866 : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wq>(const Square s, const BitBoard occupancy, const Color  ) { assert(isValidSquare(s)); return MagicBB::MAGICBISHOPATTACKS(occupancy, s) | MagicBB::MAGICROOKATTACKS(occupancy, s); }
     122    229491438 : template <       > [[nodiscard]] FORCE_FINLINE BitBoard coverage<P_wk>(const Square s, const BitBoard          , const Color  ) { assert(isValidSquare(s)); return mask[s].king; }
     123              : 
     124              : // Attack function is just coverage interseted with a target bitboard
     125              : template<Piece pp>
     126              : [[nodiscard]] FORCE_FINLINE BitBoard attack(const Square s,
     127              :                                             const BitBoard target,
     128              :                                             const BitBoard occupancy = 0,
     129              :                                             const Color c = Co_White) { // color is only important/needed for pawns
     130    248177225 :    return target ? target & coverage<pp>(s, occupancy, c) : emptyBitBoard;
     131              : }
     132              : 
     133              : #endif // MAGIC
     134              : 
     135              : BitBoard between(const Square sq1, const Square sq2);
     136              : 
     137              : // Those are convenient function pointers for coverage and attack
     138              : constexpr BitBoard (*const pfCoverage[])(const Square, const BitBoard, const Color) = {&BBTools::coverage<P_wp>, &BBTools::coverage<P_wn>,
     139              :                                                                                        &BBTools::coverage<P_wb>, &BBTools::coverage<P_wr>,
     140              :                                                                                        &BBTools::coverage<P_wq>, &BBTools::coverage<P_wk>};
     141              : //constexpr BitBoard(*const pfAttack[])  (const Square, const BitBoard, const BitBoard, const Color) = { &BBTools::attack<P_wp>,   &BBTools::attack<P_wn>,   &BBTools::attack<P_wb>,   &BBTools::attack<P_wr>,   &BBTools::attack<P_wq>,   &BBTools::attack<P_wk>   };
     142              : 
     143              : // Convenient function to check is a square is under attack or not
     144              : [[nodiscard]] bool isAttackedBB(const Position &p, const Square s, const Color c);
     145              : 
     146              : // Convenient function to return the bitboard of all attacker of a specific square
     147              : [[nodiscard]] BitBoard allAttackedBB(const Position &p, const Square s, const Color c);
     148              : [[nodiscard]] BitBoard allAttackedBB(const Position &p, const Square s);
     149              : 
     150              : } // namespace BBTools
     151              : 
     152              : // Those are wrapper functions around isAttackedBB
     153              : [[nodiscard]] bool isAttacked(const Position &p, const Square s);
     154              : [[nodiscard]] bool isAttacked(const Position &p, BitBoard bb);
     155              : [[nodiscard]] bool isPosInCheck(const Position& p);
        

Generated by: LCOV version 2.0-1