1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-30 08:43:09 +00:00
BadFish/src/bitboard.h
Vizvezdenec 9dc6d270fc Introduce concept of double pawn protection.
Exclude doubly protected by pawns squares when calculating attackers on
king ring. Idea of this patch is not to count attackers if they attack
only squares that are protected by two pawns.

STC
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 70040 W: 15476 L: 15002 D: 39562
http://tests.stockfishchess.org/tests/view/5c0354860ebc5902bcee1106

LTC
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 16530 W: 2795 L: 2607 D: 11128
http://tests.stockfishchess.org/tests/view/5c0385080ebc5902bcee14b5

This is third king safety patch in recent times so we probably need
retuning of king safety parameters.

Bench: 3057978
2018-12-02 20:18:51 +01:00

394 lines
11 KiB
C++

/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BITBOARD_H_INCLUDED
#define BITBOARD_H_INCLUDED
#include <string>
#include "types.h"
namespace Bitbases {
void init();
bool probe(Square wksq, Square wpsq, Square bksq, Color us);
}
namespace Bitboards {
void init();
const std::string pretty(Bitboard b);
}
constexpr Bitboard AllSquares = ~Bitboard(0);
constexpr Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
constexpr Bitboard FileABB = 0x0101010101010101ULL;
constexpr Bitboard FileBBB = FileABB << 1;
constexpr Bitboard FileCBB = FileABB << 2;
constexpr Bitboard FileDBB = FileABB << 3;
constexpr Bitboard FileEBB = FileABB << 4;
constexpr Bitboard FileFBB = FileABB << 5;
constexpr Bitboard FileGBB = FileABB << 6;
constexpr Bitboard FileHBB = FileABB << 7;
constexpr Bitboard Rank1BB = 0xFF;
constexpr Bitboard Rank2BB = Rank1BB << (8 * 1);
constexpr Bitboard Rank3BB = Rank1BB << (8 * 2);
constexpr Bitboard Rank4BB = Rank1BB << (8 * 3);
constexpr Bitboard Rank5BB = Rank1BB << (8 * 4);
constexpr Bitboard Rank6BB = Rank1BB << (8 * 5);
constexpr Bitboard Rank7BB = Rank1BB << (8 * 6);
constexpr Bitboard Rank8BB = Rank1BB << (8 * 7);
extern int SquareDistance[SQUARE_NB][SQUARE_NB];
extern Bitboard SquareBB[SQUARE_NB];
extern Bitboard FileBB[FILE_NB];
extern Bitboard RankBB[RANK_NB];
extern Bitboard AdjacentFilesBB[FILE_NB];
extern Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
extern Bitboard DistanceRingBB[SQUARE_NB][8];
extern Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB];
extern Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
extern Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
/// Magic holds all magic bitboards relevant data for a single square
struct Magic {
Bitboard mask;
Bitboard magic;
Bitboard* attacks;
unsigned shift;
// Compute the attack's index using the 'magic bitboards' approach
unsigned index(Bitboard occupied) const {
if (HasPext)
return unsigned(pext(occupied, mask));
if (Is64Bit)
return unsigned(((occupied & mask) * magic) >> shift);
unsigned lo = unsigned(occupied) & unsigned(mask);
unsigned hi = unsigned(occupied >> 32) & unsigned(mask >> 32);
return (lo * unsigned(magic) ^ hi * unsigned(magic >> 32)) >> shift;
}
};
extern Magic RookMagics[SQUARE_NB];
extern Magic BishopMagics[SQUARE_NB];
/// Overloads of bitwise operators between a Bitboard and a Square for testing
/// whether a given bit is set in a bitboard, and for setting and clearing bits.
inline Bitboard operator&(Bitboard b, Square s) {
assert(s >= SQ_A1 && s <= SQ_H8);
return b & SquareBB[s];
}
inline Bitboard operator|(Bitboard b, Square s) {
assert(s >= SQ_A1 && s <= SQ_H8);
return b | SquareBB[s];
}
inline Bitboard operator^(Bitboard b, Square s) {
assert(s >= SQ_A1 && s <= SQ_H8);
return b ^ SquareBB[s];
}
inline Bitboard& operator|=(Bitboard& b, Square s) {
assert(s >= SQ_A1 && s <= SQ_H8);
return b |= SquareBB[s];
}
inline Bitboard& operator^=(Bitboard& b, Square s) {
assert(s >= SQ_A1 && s <= SQ_H8);
return b ^= SquareBB[s];
}
constexpr bool more_than_one(Bitboard b) {
return b & (b - 1);
}
/// rank_bb() and file_bb() return a bitboard representing all the squares on
/// the given file or rank.
inline Bitboard rank_bb(Rank r) {
return RankBB[r];
}
inline Bitboard rank_bb(Square s) {
return RankBB[rank_of(s)];
}
inline Bitboard file_bb(File f) {
return FileBB[f];
}
inline Bitboard file_bb(Square s) {
return FileBB[file_of(s)];
}
/// shift() moves a bitboard one step along direction D (mainly for pawns)
template<Direction D>
constexpr Bitboard shift(Bitboard b) {
return D == NORTH ? b << 8 : D == SOUTH ? b >> 8
: D == EAST ? (b & ~FileHBB) << 1 : D == WEST ? (b & ~FileABB) >> 1
: D == NORTH_EAST ? (b & ~FileHBB) << 9 : D == NORTH_WEST ? (b & ~FileABB) << 7
: D == SOUTH_EAST ? (b & ~FileHBB) >> 7 : D == SOUTH_WEST ? (b & ~FileABB) >> 9
: 0;
}
/// pawn_attacks_bb() returns the pawn attacks for the given color from the
/// squares in the given bitboard.
template<Color C>
constexpr Bitboard pawn_attacks_bb(Bitboard b) {
return C == WHITE ? shift<NORTH_WEST>(b) | shift<NORTH_EAST>(b)
: shift<SOUTH_WEST>(b) | shift<SOUTH_EAST>(b);
}
/// double_pawn_attacks_bb() returns the pawn attacks for the given color
/// from the squares in the given bitboard.
template<Color C>
constexpr Bitboard double_pawn_attacks_bb(Bitboard b) {
return C == WHITE ? shift<NORTH_WEST>(b) & shift<NORTH_EAST>(b)
: shift<SOUTH_WEST>(b) & shift<SOUTH_EAST>(b);
}
/// adjacent_files_bb() returns a bitboard representing all the squares on the
/// adjacent files of the given one.
inline Bitboard adjacent_files_bb(File f) {
return AdjacentFilesBB[f];
}
/// between_bb() returns a bitboard representing all the squares between the two
/// given ones. For instance, between_bb(SQ_C4, SQ_F7) returns a bitboard with
/// the bits for square d5 and e6 set. If s1 and s2 are not on the same rank, file
/// or diagonal, 0 is returned.
inline Bitboard between_bb(Square s1, Square s2) {
return BetweenBB[s1][s2];
}
/// forward_ranks_bb() returns a bitboard representing the squares on all the ranks
/// in front of the given one, from the point of view of the given color. For instance,
/// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2.
inline Bitboard forward_ranks_bb(Color c, Square s) {
return ForwardRanksBB[c][rank_of(s)];
}
/// forward_file_bb() returns a bitboard representing all the squares along the line
/// in front of the given one, from the point of view of the given color:
/// ForwardFileBB[c][s] = forward_ranks_bb(c, s) & file_bb(s)
inline Bitboard forward_file_bb(Color c, Square s) {
return ForwardFileBB[c][s];
}
/// pawn_attack_span() returns a bitboard representing all the squares that can be
/// attacked by a pawn of the given color when it moves along its file, starting
/// from the given square:
/// PawnAttackSpan[c][s] = forward_ranks_bb(c, s) & adjacent_files_bb(file_of(s));
inline Bitboard pawn_attack_span(Color c, Square s) {
return PawnAttackSpan[c][s];
}
/// passed_pawn_mask() returns a bitboard mask which can be used to test if a
/// pawn of the given color and on the given square is a passed pawn:
/// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_file_bb(c, s)
inline Bitboard passed_pawn_mask(Color c, Square s) {
return PassedPawnMask[c][s];
}
/// aligned() returns true if the squares s1, s2 and s3 are aligned either on a
/// straight or on a diagonal line.
inline bool aligned(Square s1, Square s2, Square s3) {
return LineBB[s1][s2] & s3;
}
/// distance() functions return the distance between x and y, defined as the
/// number of steps for a king in x to reach y. Works with squares, ranks, files.
template<typename T> inline int distance(T x, T y) { return x < y ? y - x : x - y; }
template<> inline int distance<Square>(Square x, Square y) { return SquareDistance[x][y]; }
template<typename T1, typename T2> inline int distance(T2 x, T2 y);
template<> inline int distance<File>(Square x, Square y) { return distance(file_of(x), file_of(y)); }
template<> inline int distance<Rank>(Square x, Square y) { return distance(rank_of(x), rank_of(y)); }
/// attacks_bb() returns a bitboard representing all the squares attacked by a
/// piece of type Pt (bishop or rook) placed on 's'.
template<PieceType Pt>
inline Bitboard attacks_bb(Square s, Bitboard occupied) {
const Magic& m = Pt == ROOK ? RookMagics[s] : BishopMagics[s];
return m.attacks[m.index(occupied)];
}
inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) {
assert(pt != PAWN);
switch (pt)
{
case BISHOP: return attacks_bb<BISHOP>(s, occupied);
case ROOK : return attacks_bb< ROOK>(s, occupied);
case QUEEN : return attacks_bb<BISHOP>(s, occupied) | attacks_bb<ROOK>(s, occupied);
default : return PseudoAttacks[pt][s];
}
}
/// popcount() counts the number of non-zero bits in a bitboard
inline int popcount(Bitboard b) {
#ifndef USE_POPCNT
extern uint8_t PopCnt16[1 << 16];
union { Bitboard bb; uint16_t u[4]; } v = { b };
return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
return (int)_mm_popcnt_u64(b);
#else // Assumed gcc or compatible compiler
return __builtin_popcountll(b);
#endif
}
/// lsb() and msb() return the least/most significant bit in a non-zero bitboard
#if defined(__GNUC__) // GCC, Clang, ICC
inline Square lsb(Bitboard b) {
assert(b);
return Square(__builtin_ctzll(b));
}
inline Square msb(Bitboard b) {
assert(b);
return Square(63 ^ __builtin_clzll(b));
}
#elif defined(_MSC_VER) // MSVC
#ifdef _WIN64 // MSVC, WIN64
inline Square lsb(Bitboard b) {
assert(b);
unsigned long idx;
_BitScanForward64(&idx, b);
return (Square) idx;
}
inline Square msb(Bitboard b) {
assert(b);
unsigned long idx;
_BitScanReverse64(&idx, b);
return (Square) idx;
}
#else // MSVC, WIN32
inline Square lsb(Bitboard b) {
assert(b);
unsigned long idx;
if (b & 0xffffffff) {
_BitScanForward(&idx, int32_t(b));
return Square(idx);
} else {
_BitScanForward(&idx, int32_t(b >> 32));
return Square(idx + 32);
}
}
inline Square msb(Bitboard b) {
assert(b);
unsigned long idx;
if (b >> 32) {
_BitScanReverse(&idx, int32_t(b >> 32));
return Square(idx + 32);
} else {
_BitScanReverse(&idx, int32_t(b));
return Square(idx);
}
}
#endif
#else // Compiler is neither GCC nor MSVC compatible
#error "Compiler not supported."
#endif
/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard
inline Square pop_lsb(Bitboard* b) {
const Square s = lsb(*b);
*b &= *b - 1;
return s;
}
/// frontmost_sq() and backmost_sq() return the square corresponding to the
/// most/least advanced bit relative to the given color.
inline Square frontmost_sq(Color c, Bitboard b) { return c == WHITE ? msb(b) : lsb(b); }
inline Square backmost_sq(Color c, Bitboard b) { return c == WHITE ? lsb(b) : msb(b); }
#endif // #ifndef BITBOARD_H_INCLUDED