along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "movepick.h"
+
+#include <algorithm>
#include <cassert>
+#include <iterator>
+#include <utility>
#include "bitboard.h"
-#include "movepick.h"
+#include "position.h"
namespace Stockfish {
} // namespace
-/// Constructors of the MovePicker class. As arguments we pass information
-/// to help it to return the (presumably) good moves first, to decide which
+/// Constructors of the MovePicker class. As arguments, we pass information
+/// to help it return the (presumably) good moves first, to decide which
/// moves to return (in the quiescence search, for instance, we only want to
-/// search captures, promotions, and some checks) and how important good move
-/// ordering is at the current node.
+/// search captures, promotions, and some checks) and how important a good
+/// move ordering is at the current node.
/// MovePicker constructor for the main search
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh,
stage = (pos.checkers() ? EVASION_TT : MAIN_TT) +
!(ttm && pos.pseudo_legal(ttm));
- threatenedPieces = 0;
}
/// MovePicker constructor for quiescence search
stage = PROBCUT_TT + !(ttm && pos.capture_stage(ttm)
&& pos.pseudo_legal(ttm)
- && pos.see_ge(ttm, occupied, threshold));
+ && pos.see_ge(ttm, threshold));
}
/// MovePicker::score() assigns a numerical value to each move in a list, used
static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
- [[maybe_unused]] Bitboard threatenedByPawn, threatenedByMinor, threatenedByRook;
+ [[maybe_unused]] Bitboard threatenedByPawn, threatenedByMinor, threatenedByRook, threatenedPieces;
if constexpr (Type == QUIETS)
{
Color us = pos.side_to_move();
for (auto& m : *this)
if constexpr (Type == CAPTURES)
- m.value = (7 * int(PieceValue[MG][pos.piece_on(to_sq(m))])
- + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))]) / 16;
+ m.value = (7 * int(PieceValue[pos.piece_on(to_sq(m))])
+ + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))]) / 16;
else if constexpr (Type == QUIETS)
- m.value = 2 * (*mainHistory)[pos.side_to_move()][from_to(m)]
- + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
- + (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)]
- + (threatenedPieces & from_sq(m) ?
- (type_of(pos.moved_piece(m)) == QUEEN && !(to_sq(m) & threatenedByRook) ? 50000
- : type_of(pos.moved_piece(m)) == ROOK && !(to_sq(m) & threatenedByMinor) ? 25000
- : !(to_sq(m) & threatenedByPawn) ? 15000
- : 0)
- : 0)
- + bool(pos.check_squares(type_of(pos.moved_piece(m))) & to_sq(m)) * 16384;
+ {
+ Piece pc = pos.moved_piece(m);
+ PieceType pt = type_of(pos.moved_piece(m));
+ Square from = from_sq(m);
+ Square to = to_sq(m);
+
+ // histories
+ m.value = 2 * (*mainHistory)[pos.side_to_move()][from_to(m)];
+ m.value += 2 * (*continuationHistory[0])[pc][to];
+ m.value += (*continuationHistory[1])[pc][to];
+ m.value += (*continuationHistory[2])[pc][to] / 4;
+ m.value += (*continuationHistory[3])[pc][to];
+ m.value += (*continuationHistory[5])[pc][to];
+
+ // bonus for checks
+ m.value += bool(pos.check_squares(pt) & to) * 16384;
+
+ // bonus for escaping from capture
+ m.value += threatenedPieces & from ?
+ (pt == QUEEN && !(to & threatenedByRook) ? 50000
+ : pt == ROOK && !(to & threatenedByMinor) ? 25000
+ : !(to & threatenedByPawn) ? 15000
+ : 0 )
+ : 0 ;
+
+ // malus for putting piece en prise
+ m.value -= !(threatenedPieces & from) ?
+ (pt == QUEEN ? bool(to & threatenedByRook) * 50000
+ + bool(to & threatenedByMinor) * 10000
+ + bool(to & threatenedByPawn) * 20000
+ : pt == ROOK ? bool(to & threatenedByMinor) * 25000
+ + bool(to & threatenedByPawn) * 10000
+ : pt != PAWN ? bool(to & threatenedByPawn) * 15000
+ : 0 )
+ : 0 ;
+ }
+
else // Type == EVASIONS
{
if (pos.capture_stage(m))
- m.value = PieceValue[MG][pos.piece_on(to_sq(m))]
+ m.value = PieceValue[pos.piece_on(to_sq(m))]
- Value(type_of(pos.moved_piece(m)))
+ (1 << 28);
else
case GOOD_CAPTURE:
if (select<Next>([&](){
- return pos.see_ge(*cur, occupied, Value(-cur->value)) ?
+ return pos.see_ge(*cur, Value(-cur->value)) ?
// Move losing capture to endBadCaptures to be tried later
true : (*endBadCaptures++ = *cur, false); }))
return *(cur - 1);
return select<Best>([](){ return true; });
case PROBCUT:
- return select<Next>([&](){ return pos.see_ge(*cur, occupied, threshold); });
+ return select<Next>([&](){ return pos.see_ge(*cur, threshold); });
case QCAPTURE:
if (select<Next>([&](){ return depth > DEPTH_QS_RECAPTURES