behind |= shift<Down>(behind);
behind |= shift<Down+Down>(behind);
+ if (pawnsOnly)
+ {
+ safe = behind & ~attackedBy[Them][ALL_PIECES];
+ behind = 0;
+ }
+
int bonus = popcount(safe) + popcount(behind & safe);
- int weight = pos.count<ALL_PIECES>(Us)
- - (16 - pos.count<PAWN>()) / 4;
-
+ int weight = pos.count<ALL_PIECES>(Us) - 1;
Score score = make_score(bonus * weight * weight / 16, 0);
if (T)
Bitboard ourPawns = b & pos.pieces(Us);
Bitboard theirPawns = b & pos.pieces(Them);
- Value safety = (shift<Down>(theirPawns) & BlockSquares & ksq) ? Value(374) : Value(5);
+ Value bonus[] = { (shift<Down>(theirPawns) & BlockSquares & ksq) ? Value(374) : Value(5),
+ VALUE_ZERO };
- File center = clamp(file_of(ksq), FILE_B, FILE_G);
+ File center = clamp(file_of(ksq), FILE_B, File(pos.max_file() - 1));
for (File f = File(center - 1); f <= File(center + 1); ++f)
{
b = ourPawns & file_bb(f);
- Rank ourRank = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1;
+ Rank ourRank = b ? relative_rank(Us, backmost_sq(Us, b), pos.max_rank()) : RANK_1;
b = theirPawns & file_bb(f);
- Rank theirRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1;
+ Rank theirRank = b ? relative_rank(Us, frontmost_sq(Them, b), pos.max_rank()) : RANK_1;
- int d = std::min(f, ~f);
- bonus[MG] += ShelterStrength[d][ourRank];
+ int d = std::min(std::min(f, File(pos.max_file() - f)), FILE_D);
- // higher weight for pawns on second rank and missing shelter in drop variants
- safety += ShelterStrength[d][ourRank] * (1 + (pos.captures_to_hand() && ourRank <= RANK_2));
- safety -= (ourRank && (ourRank == theirRank - 1)) ? 66 * (theirRank == RANK_3)
- : UnblockedStorm[d][theirRank];
++ bonus[MG] += ShelterStrength[d][ourRank] * (1 + (pos.captures_to_hand() && ourRank <= RANK_2));
+
+ if (ourRank && (ourRank == theirRank - 1))
+ bonus[MG] -= 82 * (theirRank == RANK_3), bonus[EG] -= 82 * (theirRank == RANK_3);
+ else
+ bonus[MG] -= UnblockedStorm[d][theirRank];
}
- return safety;
+ if (bonus[MG] > mg_value(shelter))
+ shelter = make_score(bonus[MG], bonus[EG]);
}
// If we can castle use the bonus after the castling if it is bigger
if (pos.can_castle(Us | KING_SIDE))
- evaluate_shelter<Us>(pos, relative_square(Us, SQ_G1), shelter);
+ {
+ Square s = make_square(pos.castling_kingside_file(), Us == WHITE ? RANK_1 : pos.max_rank());
- bonus = std::max(bonus, evaluate_shelter<Us>(pos, s));
++ evaluate_shelter<Us>(pos, s, shelter);
+ }
if (pos.can_castle(Us | QUEEN_SIDE))
- evaluate_shelter<Us>(pos, relative_square(Us, SQ_C1), shelter);
+ {
+ Square s = make_square(pos.castling_queenside_file(), Us == WHITE ? RANK_1 : pos.max_rank());
- bonus = std::max(bonus, evaluate_shelter<Us>(pos, s));
++ evaluate_shelter<Us>(pos, s, shelter);
+ }
- return make_score(bonus, -16 * minPawnDist);
+ return shelter - make_score(VALUE_ZERO, 16 * minPawnDist);
}
// Explicit template instantiation
// Step 16. Reduced depth search (LMR). If the move fails high it will be
// re-searched at full depth.
if ( depth >= 3 * ONE_PLY
- && moveCount > 1
- && (!(captureOrPromotion || (pos.must_capture() && MoveList<CAPTURES>(pos).size())) || moveCountPruning))
+ && moveCount > 1 + 3 * rootNode
- && ( !captureOrPromotion
++ && ( !(captureOrPromotion || (pos.must_capture() && MoveList<CAPTURES>(pos).size()))
+ || moveCountPruning
+ || ss->staticEval + PieceValue[EG][pos.captured_piece()] <= alpha))
{
- Depth r = reduction<PvNode>(improving, depth, moveCount);
+ Depth r = reduction(improving, depth, moveCount);
// Decrease reduction if position is or has been on the PV
if (ttPv)
// Decrease reduction if opponent's move count is high (~10 Elo)
if ((ss-1)->moveCount > 15)
r -= ONE_PLY;
+ // Decrease reduction if move has been singularly extended
+ r -= singularExtensionLMRmultiplier * ONE_PLY;
- if (!captureOrPromotion)
+ if (!captureOrPromotion && !(pos.must_capture() && MoveList<CAPTURES>(pos).size()))
{
// Increase reduction if ttMove is a capture (~0 Elo)
if (ttCapture)
struct TTEntry {
- Move move() const { return (Move )move16; }
+ Move move() const { return (Move )move32; }
Value value() const { return (Value)value16; }
Value eval() const { return (Value)eval16; }
- Depth depth() const { return (Depth)(depth8 * int(ONE_PLY)); }
+ Depth depth() const { return (Depth)(depth8 * int(ONE_PLY)) + DEPTH_NONE; }
bool is_pv() const { return (bool)(genBound8 & 0x4); }
Bound bound() const { return (Bound)(genBound8 & 0x3); }
void save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev);
#endif
typedef uint64_t Key;
+#ifdef LARGEBOARDS
+#if defined(__GNUC__) && defined(IS_64BIT)
+typedef unsigned __int128 Bitboard;
+#else
+struct Bitboard {
+ uint64_t b64[2];
+
+ constexpr Bitboard() : b64 {0, 0} {}
+ constexpr Bitboard(uint64_t i) : b64 {0, i} {}
+ constexpr Bitboard(uint64_t hi, uint64_t lo) : b64 {hi, lo} {};
+
+ constexpr operator bool() const {
+ return b64[0] || b64[1];
+ }
+
+ constexpr operator long long unsigned () const {
+ return b64[1];
+ }
+
+ constexpr operator unsigned() const {
+ return b64[1];
+ }
+
+ constexpr Bitboard operator << (const unsigned int bits) const {
+ return Bitboard( bits >= 64 ? b64[1] << (bits - 64)
+ : bits == 0 ? b64[0]
+ : ((b64[0] << bits) | (b64[1] >> (64 - bits))),
+ bits >= 64 ? 0 : b64[1] << bits);
+ }
+
+ constexpr Bitboard operator >> (const unsigned int bits) const {
+ return Bitboard(bits >= 64 ? 0 : b64[0] >> bits,
+ bits >= 64 ? b64[0] >> (bits - 64)
+ : bits == 0 ? b64[1]
+ : ((b64[1] >> bits) | (b64[0] << (64 - bits))));
+ }
+
+ constexpr Bitboard operator << (const int bits) const {
+ return *this << unsigned(bits);
+ }
+
+ constexpr Bitboard operator >> (const int bits) const {
+ return *this >> unsigned(bits);
+ }
+
+ constexpr bool operator == (const Bitboard y) const {
+ return (b64[0] == y.b64[0]) && (b64[1] == y.b64[1]);
+ }
+
+ constexpr bool operator != (const Bitboard y) const {
+ return !(*this == y);
+ }
+
+ inline Bitboard& operator |=(const Bitboard x) {
+ b64[0] |= x.b64[0];
+ b64[1] |= x.b64[1];
+ return *this;
+ }
+ inline Bitboard& operator &=(const Bitboard x) {
+ b64[0] &= x.b64[0];
+ b64[1] &= x.b64[1];
+ return *this;
+ }
+ inline Bitboard& operator ^=(const Bitboard x) {
+ b64[0] ^= x.b64[0];
+ b64[1] ^= x.b64[1];
+ return *this;
+ }
+
+ constexpr Bitboard operator ~ () const {
+ return Bitboard(~b64[0], ~b64[1]);
+ }
+
+ constexpr Bitboard operator | (const Bitboard x) const {
+ return Bitboard(b64[0] | x.b64[0], b64[1] | x.b64[1]);
+ }
+
+ constexpr Bitboard operator & (const Bitboard x) const {
+ return Bitboard(b64[0] & x.b64[0], b64[1] & x.b64[1]);
+ }
+
+ constexpr Bitboard operator ^ (const Bitboard x) const {
+ return Bitboard(b64[0] ^ x.b64[0], b64[1] ^ x.b64[1]);
+ }
+
+ constexpr Bitboard operator - (const Bitboard x) const {
+ return Bitboard(b64[0] - x.b64[0] - (b64[1] < x.b64[1]), b64[1] - x.b64[1]);
+ }
+
+ constexpr Bitboard operator - (const int x) const {
+ return *this - Bitboard(x);
+ }
+
+ inline Bitboard operator * (const Bitboard x) const {
+ uint64_t a_lo = (uint32_t)b64[1];
+ uint64_t a_hi = b64[1] >> 32;
+ uint64_t b_lo = (uint32_t)x.b64[1];
+ uint64_t b_hi = x.b64[1] >> 32;
+
+ uint64_t t1 = (a_hi * b_lo) + ((a_lo * b_lo) >> 32);
+ uint64_t t2 = (a_lo * b_hi) + (t1 & 0xFFFFFFFF);
+
+ return Bitboard(b64[0] * x.b64[1] + b64[1] * x.b64[0] + (a_hi * b_hi) + (t1 >> 32) + (t2 >> 32),
+ (t2 << 32) + (a_lo * b_lo & 0xFFFFFFFF));
+ }
+};
+#endif
+constexpr int SQUARE_BITS = 7;
+#else
typedef uint64_t Bitboard;
+constexpr int SQUARE_BITS = 6;
+#endif
-constexpr int MAX_MOVES = 256;
+constexpr int MAX_MOVES = 512;
- constexpr int MAX_PLY = 128;
+ constexpr int MAX_PLY = 246;
/// A move needs 16 bits to be stored
///