/// 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.
+/// number of steps for a king in x to reach y.
-template<typename T> inline int distance(T x, T y) { return std::abs(x - y); }
+template<typename T1 = Square> inline int distance(Square x, Square y);
+template<> inline int distance<File>(Square x, Square y) { return std::abs(file_of(x) - file_of(y)); }
+template<> inline int distance<Rank>(Square x, Square y) { return std::abs(rank_of(x) - rank_of(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)); }
-
template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
return v < lo ? lo : v > hi ? hi : v;
}
Square ksq = pos.square<KING>(weakSide);
Square psq1 = pos.squares<PAWN>(strongSide)[0];
Square psq2 = pos.squares<PAWN>(strongSide)[1];
- Rank r1 = rank_of(psq1);
- Rank r2 = rank_of(psq2);
Square blockSq1, blockSq2;
if (relative_rank(strongSide, psq1) > relative_rank(strongSide, psq2))
&& opposite_colors(ksq, wbsq)
&& ( bbsq == blockSq2
|| (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(weakSide, BISHOP))
- || distance(r1, r2) >= 2))
+ || distance<Rank>(psq1, psq2) >= 2))
return SCALE_FACTOR_DRAW;
else if ( ksq == blockSq2
// bishop, bigger when the center files are blocked with pawns.
Bitboard blocked = pos.pieces(Us, PAWN) & shift<Down>(pos.pieces());
- score -= BishopPawns * pe->pawns_on_same_color_squares(Us, s)
+ score -= BishopPawns * pos.pawns_on_same_color_squares(Us, s)
* (1 + popcount(blocked & CenterFiles));
// Bonus for bishop on a long diagonal which can "see" both center squares
score += RookOnPawn * popcount(pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]);
// Bonus for rook on an open or semi-open file
- if (pe->semiopen_file(Us, file_of(s)))
- score += RookOnFile[bool(pe->semiopen_file(Them, file_of(s)))];
+ if (pos.semiopen_file(Us, file_of(s)))
+ score += RookOnFile[bool(pos.semiopen_file(Them, file_of(s)))];
// Penalty when trapped by the king, even more if the king cannot castle
else if (mob <= 3)
int bonus = popcount(safe) + popcount(behind & safe);
int weight = pos.count<ALL_PIECES>(Us)
- - 2 * popcount(pe->semiopenFiles[WHITE] & pe->semiopenFiles[BLACK]);
+ - (16 - pos.count<PAWN>()) / 4;
Score score = make_score(bonus * weight * weight / 16, 0);
if (T == Best)
std::swap(*cur, *std::max_element(cur, endMoves));
- move = *cur++;
+ if (*cur != ttMove && filter())
+ return *cur++;
- if (move != ttMove && filter())
- return move;
+ cur++;
}
- return move = MOVE_NONE;
+ return MOVE_NONE;
}
/// MovePicker::next_move() is the most important method of the MovePicker class. It
case GOOD_CAPTURE:
if (select<Best>([&](){
- return pos.see_ge(move, Value(-55 * (cur-1)->value / 1024)) ?
+ return pos.see_ge(*cur, Value(-55 * cur->value / 1024)) ?
// Move losing capture to endBadCaptures to be tried later
- true : (*endBadCaptures++ = move, false); }))
- return move;
+ true : (*endBadCaptures++ = *cur, false); }))
+ return *(cur - 1);
// Prepare the pointers to loop over the refutations array
cur = std::begin(refutations);
/* fallthrough */
case REFUTATION:
- if (select<Next>([&](){ return move != MOVE_NONE
- && !pos.capture(move)
- && pos.pseudo_legal(move); }))
- return move;
+ if (select<Next>([&](){ return *cur != MOVE_NONE
+ && !pos.capture(*cur)
+ && pos.pseudo_legal(*cur); }))
+ return *(cur - 1);
++stage;
/* fallthrough */
case QUIET:
if ( !skipQuiets
- && select<Next>([&](){return move != refutations[0]
- && move != refutations[1]
- && move != refutations[2];}))
- return move;
+ && select<Next>([&](){return *cur != refutations[0].move
+ && *cur != refutations[1].move
+ && *cur != refutations[2].move;}))
+ return *(cur - 1);
// Prepare the pointers to loop over the bad captures
cur = moves;
return select<Best>([](){ return true; });
case PROBCUT:
- return select<Best>([&](){ return pos.see_ge(move, threshold); });
+ return select<Best>([&](){ return pos.see_ge(*cur, threshold); });
case QCAPTURE:
if (select<Best>([&](){ return depth > DEPTH_QS_RECAPTURES
- || to_sq(move) == recaptureSquare; }))
- return move;
+ || to_sq(*cur) == recaptureSquare; }))
+ return *(cur - 1);
// If we did not find any move and we do not try checks, we have finished
if (depth != DEPTH_QS_CHECKS)
Move ttMove;
ExtMove refutations[3], *cur, *endMoves, *endBadCaptures;
int stage;
- Move move;
Square recaptureSquare;
Value threshold;
Depth depth;
constexpr Score Isolated = S( 5, 15);
// Connected pawn bonus
- constexpr int Connected[RANK_NB] = { 0, 13, 24, 18, 65, 100, 175, 330 };
+ constexpr int Connected[RANK_NB] = { 0, 13, 17, 24, 59, 96, 171 };
// Strength of pawn shelter for our king by [distance from edge][rank].
// RANK_1 = 0 is used for files where we have no pawn, or pawn is behind our king.
Bitboard theirPawns = pos.pieces(Them, PAWN);
e->passedPawns[Us] = e->pawnAttacksSpan[Us] = e->weakUnopposed[Us] = 0;
- e->semiopenFiles[Us] = 0xFF;
e->kingSquares[Us] = SQ_NONE;
e->pawnAttacks[Us] = pawn_attacks_bb<Us>(ourPawns);
- e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares);
- e->pawnsOnSquares[Us][WHITE] = pos.count<PAWN>(Us) - e->pawnsOnSquares[Us][BLACK];
// Loop through all pawns of the current color and score each pawn
while ((s = *pl++) != SQ_NONE)
assert(pos.piece_on(s) == make_piece(Us, PAWN));
File f = file_of(s);
+ Rank r = relative_rank(Us, s);
- e->semiopenFiles[Us] &= ~(1 << f);
e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s);
// Flag the pawn
&& popcount(phalanx) >= popcount(leverPush))
e->passedPawns[Us] |= s;
- else if ( stoppers == square_bb(s + Up)
- && relative_rank(Us, s) >= RANK_5)
+ else if (stoppers == square_bb(s + Up) && r >= RANK_5)
{
b = shift<Up>(support) & ~theirPawns;
while (b)
// Score this pawn
if (support | phalanx)
{
- int r = relative_rank(Us, s);
- int v = phalanx ? Connected[r] + Connected[r + 1] : 2 * Connected[r];
+ int v = (phalanx ? 3 : 2) * Connected[r];
v = 17 * popcount(support) + (v >> (opposed + 1));
score += make_score(v, v * (r - 2) / 4);
}
e->key = key;
e->scores[WHITE] = evaluate<WHITE>(pos, e);
e->scores[BLACK] = evaluate<BLACK>(pos, e);
- e->passedCount= popcount(e->passedPawns[WHITE] | e->passedPawns[BLACK]);
return e;
}
Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
Bitboard pawn_attacks_span(Color c) const { return pawnAttacksSpan[c]; }
int weak_unopposed(Color c) const { return weakUnopposed[c]; }
- int passed_count() const { return passedCount; }
-
- int semiopen_file(Color c, File f) const {
- return semiopenFiles[c] & (1 << f);
- }
-
- int pawns_on_same_color_squares(Color c, Square s) const {
- return pawnsOnSquares[c][bool(DarkSquares & s)];
- }
+ int passed_count() const { return popcount(passedPawns[WHITE] | passedPawns[BLACK]); };
template<Color Us>
Score king_safety(const Position& pos) {
Score kingSafety[COLOR_NB];
int weakUnopposed[COLOR_NB];
int castlingRights[COLOR_NB];
- int semiopenFiles[COLOR_NB];
int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares]
- int passedCount;
};
typedef HashTable<Entry, 16384> Table;
template<PieceType Pt> int count() const;
template<PieceType Pt> const Square* squares(Color c) const;
template<PieceType Pt> Square square(Color c) const;
+ int semiopen_file(Color c, File f) const;
// Castling
int castling_rights(Color c) const;
// Piece specific
bool pawn_passed(Color c, Square s) const;
bool opposite_bishops() const;
+ int pawns_on_same_color_squares(Color c, Square s) const;
// Doing and undoing moves
void do_move(Move m, StateInfo& newSt);
return st->epSquare;
}
+inline int Position::semiopen_file(Color c, File f) const {
+ return !(pieces(c, PAWN) & file_bb(f));
+}
+
inline bool Position::can_castle(CastlingRight cr) const {
return st->castlingRights & cr;
}
&& relative_rank(sideToMove, from_sq(m)) > RANK_4;
}
+inline int Position::pawns_on_same_color_squares(Color c, Square s) const {
+ return popcount(pieces(c, PAWN) & ((DarkSquares & s) ? DarkSquares : ~DarkSquares));
+}
+
inline Key Position::key() const {
return st->key;
}
if (!pos.capture_or_promotion(ttMove))
update_quiet_stats(pos, ss, ttMove, nullptr, 0, stat_bonus(depth));
- // Extra penalty for a quiet TT or main killer move in previous ply when it gets refuted
- if ( ((ss-1)->moveCount == 1 || (ss-1)->currentMove == (ss-1)->killers[0])
- && !pos.captured_piece())
+ // Extra penalty for early quiet moves of the previous ply
+ if ((ss-1)->moveCount <= 2 && !pos.captured_piece())
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, -stat_bonus(depth + ONE_PLY));
}
// Penalty for a quiet ttMove that fails low
Thread* thisThread = pos.this_thread();
(ss+1)->ply = ss->ply + 1;
- ss->currentMove = bestMove = MOVE_NONE;
- ss->continuationHistory = &thisThread->continuationHistory[NO_PIECE][0];
+ bestMove = MOVE_NONE;
inCheck = pos.checkers();
moveCount = 0;